From d2451a41d87983643a85863890591b698aa8bbc3 Mon Sep 17 00:00:00 2001 From: KatKatKateryna Date: Thu, 7 Dec 2023 01:56:21 +0800 Subject: [PATCH 01/17] create utils, import logger from UI repo --- qt_ui/DataStorage.py | 2 +- qt_ui/LogWidget.py | 2 +- qt_ui/dockwidget_main.py | 4 +- qt_ui/utils/__init__.py | 0 qt_ui/{ => utils}/global_resources.py | 0 qt_ui/{ => utils}/logger.py | 0 qt_ui/widget_add_stream.py | 2 +- qt_ui/widget_create_branch.py | 2 +- qt_ui/widget_create_stream.py | 2 +- qt_ui/widget_custom_crs.py | 100 ++++++++++++++----------- qt_ui/widget_report.py | 104 +++++++++++++++----------- 11 files changed, 125 insertions(+), 93 deletions(-) create mode 100644 qt_ui/utils/__init__.py rename qt_ui/{ => utils}/global_resources.py (100%) rename qt_ui/{ => utils}/logger.py (100%) diff --git a/qt_ui/DataStorage.py b/qt_ui/DataStorage.py index 7cb4ae0..3250a80 100644 --- a/qt_ui/DataStorage.py +++ b/qt_ui/DataStorage.py @@ -3,7 +3,7 @@ import inspect from typing import List, Optional, Tuple, Union, Any import webbrowser -from speckle.utils.panel_logging import logToUser +from specklepy_qt_ui.qt_ui.utils.logger import logToUser from specklepy.core.api.credentials import get_local_accounts diff --git a/qt_ui/LogWidget.py b/qt_ui/LogWidget.py index 5dac87a..1914bb5 100644 --- a/qt_ui/LogWidget.py +++ b/qt_ui/LogWidget.py @@ -9,7 +9,7 @@ import webbrowser from specklepy.logging import metrics from specklepy.core.api.credentials import Account -from specklepy_qt_ui.qt_ui.global_resources import ( +from specklepy_qt_ui.qt_ui.utils.global_resources import ( BACKGR_COLOR, BACKGR_COLOR_LIGHT, BACKGR_COLOR_GREY, diff --git a/qt_ui/dockwidget_main.py b/qt_ui/dockwidget_main.py index a010b5a..241ff63 100644 --- a/qt_ui/dockwidget_main.py +++ b/qt_ui/dockwidget_main.py @@ -6,10 +6,10 @@ import os from specklepy_qt_ui.qt_ui.widget_transforms import MappingSendDialog from specklepy_qt_ui.qt_ui.LogWidget import LogWidget -from specklepy_qt_ui.qt_ui.logger import logToUser +from specklepy_qt_ui.qt_ui.utils.logger import logToUser from specklepy_qt_ui.qt_ui.utils import constructCommitURL from specklepy_qt_ui.qt_ui.DataStorage import DataStorage -from specklepy_qt_ui.qt_ui.global_resources import ( +from specklepy_qt_ui.qt_ui.utils.global_resources import ( COLOR_HIGHLIGHT, SPECKLE_COLOR, SPECKLE_COLOR_LIGHT, diff --git a/qt_ui/utils/__init__.py b/qt_ui/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/qt_ui/global_resources.py b/qt_ui/utils/global_resources.py similarity index 100% rename from qt_ui/global_resources.py rename to qt_ui/utils/global_resources.py diff --git a/qt_ui/logger.py b/qt_ui/utils/logger.py similarity index 100% rename from qt_ui/logger.py rename to qt_ui/utils/logger.py diff --git a/qt_ui/widget_add_stream.py b/qt_ui/widget_add_stream.py index 3ea1e6f..0933c47 100644 --- a/qt_ui/widget_add_stream.py +++ b/qt_ui/widget_add_stream.py @@ -4,7 +4,7 @@ from typing import List, Union import urllib.parse from specklepy_qt_ui.qt_ui.DataStorage import DataStorage -from specklepy_qt_ui.qt_ui.logger import logToUser +from specklepy_qt_ui.qt_ui.utils.logger import logToUser from PyQt5 import QtWidgets, uic, QtCore from PyQt5.QtCore import pyqtSignal diff --git a/qt_ui/widget_create_branch.py b/qt_ui/widget_create_branch.py index df8697f..e39eea0 100644 --- a/qt_ui/widget_create_branch.py +++ b/qt_ui/widget_create_branch.py @@ -1,7 +1,7 @@ import inspect import os from typing import List, Tuple, Union -from specklepy_qt_ui.qt_ui.logger import logToUser +from specklepy_qt_ui.qt_ui.utils.logger import logToUser from PyQt5 import QtWidgets, uic, QtCore from PyQt5.QtCore import pyqtSignal diff --git a/qt_ui/widget_create_stream.py b/qt_ui/widget_create_stream.py index e925d38..edc4da6 100644 --- a/qt_ui/widget_create_stream.py +++ b/qt_ui/widget_create_stream.py @@ -1,7 +1,7 @@ import inspect import os from typing import List, Tuple, Union -from specklepy_qt_ui.qt_ui.logger import logToUser +from specklepy_qt_ui.qt_ui.utils.logger import logToUser from PyQt5 import QtWidgets, uic, QtCore from PyQt5.QtCore import pyqtSignal diff --git a/qt_ui/widget_custom_crs.py b/qt_ui/widget_custom_crs.py index 85aa728..11b3f86 100644 --- a/qt_ui/widget_custom_crs.py +++ b/qt_ui/widget_custom_crs.py @@ -2,79 +2,83 @@ import inspect import os from typing import List, Tuple, Union from specklepy_qt_ui.qt_ui.DataStorage import DataStorage -from specklepy_qt_ui.qt_ui.logger import logToUser +from specklepy_qt_ui.qt_ui.utils.logger import logToUser from PyQt5 import QtWidgets, uic, QtCore -from PyQt5.QtWidgets import QCheckBox, QListWidgetItem, QHBoxLayout, QWidget +from PyQt5.QtWidgets import QCheckBox, QListWidgetItem, QHBoxLayout, QWidget from PyQt5.QtCore import pyqtSignal from specklepy.core.api.client import SpeckleClient -from specklepy_qt_ui.qt_ui.global_resources import COLOR +from specklepy_qt_ui.qt_ui.utils.global_resources import COLOR # This loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer FORM_CLASS, _ = uic.loadUiType( - os.path.join(os.path.join(os.path.dirname(__file__), "ui", "custom_crs.ui") ) + os.path.join(os.path.join(os.path.dirname(__file__), "ui", "custom_crs.ui")) ) -class CustomCRSDialog(QtWidgets.QWidget, FORM_CLASS): +class CustomCRSDialog(QtWidgets.QWidget, FORM_CLASS): name_field: QtWidgets.QLineEdit = None description_field: QtWidgets.QLineEdit = None dialog_button_box: QtWidgets.QDialogButtonBox = None saveSurveyPoint: QtWidgets.QPushButton = None speckle_client: Union[SpeckleClient, None] = None - dataStorage: DataStorage = None + dataStorage: DataStorage = None - #Events - #handleCRSCreate = pyqtSignal(str,str) + # Events + # handleCRSCreate = pyqtSignal(str,str) def __init__(self, parent=None): - - super(CustomCRSDialog,self).__init__(parent, QtCore.Qt.WindowStaysOnTopHint) + super(CustomCRSDialog, self).__init__(parent, QtCore.Qt.WindowStaysOnTopHint) self.setupUi(self) - self.setWindowTitle("Set project center on Send/Receive") - - #self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Close).clicked.connect(self.onCancelClicked) - self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Cancel).setText("More Info") + self.setWindowTitle("Set project center on Send/Receive") + + # self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Close).clicked.connect(self.onCancelClicked) + self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Cancel).setText( + "More Info" + ) self.modeDropdown.currentIndexChanged.connect(self.onModeChanged) - + def onModeChanged(self): try: - if not self: return + if not self: + return index = self.modeDropdown.currentIndex() - if index == 1: # custom crs + if index == 1: # custom crs self.surveyPointLat.show() self.surveyPointLon.show() self.degreeSignX.show() self.degreeSignY.show() self.label_survey.show() - + self.offsetX.hide() self.offsetY.hide() self.label_offsets.hide() self.offsetXDegreeSign.hide() self.offsetYDegreeSign.hide() - self.description.setText("Use this option when you don't have to use a specific CRS.\ + self.description.setText( + "Use this option when you don't have to use a specific CRS.\ \n\nThis will change your Project CRS to a new custom CRS.\ - \n\nHint: right-click on the canvas -> Copy Coordinate -> EPSG:4326. ") + \n\nHint: right-click on the canvas -> Copy Coordinate -> EPSG:4326. " + ) - elif index == 0: # offsets + elif index == 0: # offsets self.surveyPointLat.hide() self.surveyPointLon.hide() self.degreeSignX.hide() self.degreeSignY.hide() self.label_survey.hide() - + self.offsetX.show() self.offsetY.show() self.label_offsets.show() - #if self.dataStorage.currentOriginalUnits == 'degrees': + # if self.dataStorage.currentOriginalUnits == 'degrees': self.offsetXDegreeSign.show() self.offsetYDegreeSign.show() - + units = self.dataStorage.currentOriginalUnits - if units == 'degrees': + if units == "degrees": self.offsetXDegreeSign.setText("°") self.offsetYDegreeSign.setText("°") elif units is not None: @@ -83,49 +87,56 @@ class CustomCRSDialog(QtWidgets.QWidget, FORM_CLASS): else: self.offsetXDegreeSign.hide() self.offsetYDegreeSign.hide() - + text = f"Use this option when your project requires a use of a specific CRS. \ \n\nThis will only affect Speckle data properties, not your Project CRS.\ \n\nHint: your current project CRS is '{self.dataStorage.currentCRS.authid()}' and using units '{self.dataStorage.currentOriginalUnits}'." - if units == 'degrees': + if units == "degrees": text += "\nThis CRS is not recommended if data was sent or needs to be \ \nreceived in a non-GIS application." - + self.description.setText(text) - + self.populateSurveyPoint() self.populateOffsets() self.populateRotation() except Exception as e: - logToUser(e, level = 2, func = inspect.stack()[0][3]) + logToUser(e, level=2, func=inspect.stack()[0][3]) return - + def populateModeDropdown(self): - if not self: return + if not self: + return try: self.modeDropdown.clear() self.modeDropdown.addItems( - ["Add offsets / rotation to the current Project CRS", "Create custom CRS"] + [ + "Add offsets / rotation to the current Project CRS", + "Create custom CRS", + ] ) except Exception as e: - logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self) + logToUser(e, level=2, func=inspect.stack()[0][3], plugin=self) return - + def populateSurveyPoint(self): if not self: return try: self.surveyPointLat.clear() self.surveyPointLon.clear() - if self.dataStorage.custom_lat is not None and self.dataStorage.custom_lon is not None: + if ( + self.dataStorage.custom_lat is not None + and self.dataStorage.custom_lon is not None + ): self.surveyPointLat.setText(str(self.dataStorage.custom_lat)) self.surveyPointLon.setText(str(self.dataStorage.custom_lon)) except Exception as e: - logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self) + logToUser(e, level=2, func=inspect.stack()[0][3], plugin=self) return - + def populateRotation(self): if not self: return @@ -134,19 +145,22 @@ class CustomCRSDialog(QtWidgets.QWidget, FORM_CLASS): if self.dataStorage.crs_rotation is not None: self.rotation.setText(str(self.dataStorage.crs_rotation)) except Exception as e: - logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self) + logToUser(e, level=2, func=inspect.stack()[0][3], plugin=self) return def populateOffsets(self): try: self.offsetX.clear() self.offsetY.clear() - if self.dataStorage.crs_offset_x is not None and self.dataStorage.crs_offset_y is not None: + if ( + self.dataStorage.crs_offset_x is not None + and self.dataStorage.crs_offset_y is not None + ): self.offsetX.setText(str(self.dataStorage.crs_offset_x)) self.offsetY.setText(str(self.dataStorage.crs_offset_y)) - + except Exception as e: - logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self) + logToUser(e, level=2, func=inspect.stack()[0][3], plugin=self) return def onOkClicked(self): @@ -154,5 +168,5 @@ class CustomCRSDialog(QtWidgets.QWidget, FORM_CLASS): try: self.close() except Exception as e: - logToUser(e, level = 2, func = inspect.stack()[0][3]) + logToUser(e, level=2, func=inspect.stack()[0][3]) return diff --git a/qt_ui/widget_report.py b/qt_ui/widget_report.py index e18901a..e193dbc 100644 --- a/qt_ui/widget_report.py +++ b/qt_ui/widget_report.py @@ -2,69 +2,73 @@ import inspect import os from typing import List, Tuple, Union from specklepy_qt_ui.qt_ui.DataStorage import DataStorage -#from specklepy_qt_ui.qt_ui.logger import logToUser + +# from specklepy_qt_ui.qt_ui.utils.logger import logToUser from PyQt5 import QtWidgets, uic, QtCore -from PyQt5.QtWidgets import QCheckBox, QListWidgetItem, QHBoxLayout, QWidget +from PyQt5.QtWidgets import QCheckBox, QListWidgetItem, QHBoxLayout, QWidget from PyQt5.QtCore import pyqtSignal from specklepy.core.api.client import SpeckleClient -from specklepy_qt_ui.qt_ui.global_resources import COLOR +from specklepy_qt_ui.qt_ui.utils.global_resources import COLOR # This loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer FORM_CLASS, _ = uic.loadUiType( - os.path.join(os.path.join(os.path.dirname(__file__), "ui", "report.ui") ) + os.path.join(os.path.join(os.path.dirname(__file__), "ui", "report.ui")) ) -class ReportDialog(QtWidgets.QWidget, FORM_CLASS): +class ReportDialog(QtWidgets.QWidget, FORM_CLASS): report_label: QtWidgets.QLabel = None report_text: QtWidgets.QTextEdit = None dataStorage: DataStorage = None def __init__(self, parent=None): - - super(ReportDialog,self).__init__(parent, QtCore.Qt.WindowStaysOnTopHint) + super(ReportDialog, self).__init__(parent, QtCore.Qt.WindowStaysOnTopHint) self.setupUi(self) self.runAllSetup() - + def runAllSetup(self): - self.setWindowTitle("Report (Speckle)") + self.setWindowTitle("Report (Speckle)") self.setMinimumWidth(500) self.setMinimumHeight(600) self.report_label.setWordWrap(True) - self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).clicked.connect(self.onOkClicked) + self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).clicked.connect( + self.onOkClicked + ) return - #self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Cancel).setText("More Info") - + # self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Cancel).setText("More Info") + def assembleReport(self): try: - if self.dataStorage is None: return + if self.dataStorage is None: + return reportList = self.dataStorage.latestActionReport - if reportList is None: return + if reportList is None: + return operation = "" total_layers = 0 total_objects = 0 text = "" sending = True - - # details + + # details last_report = "" last_report += "Details:" + "\n" for item in reportList: line = "✅ " - try: # if sending + try: # if sending line += f'{item["feature_id"]}: {item["obj_type"]}' operation = f"Sent at {self.dataStorage.latestActionTime}" - except: # if receiving + except: # if receiving sending = False line += f'{item["speckle_id"]}: {item["obj_type"]}' operation = f"Received at {self.dataStorage.latestActionTime}" - - # edit based on the type + + # edit based on the type if "Layer" in item["obj_type"]: total_layers += 1 if item["errors"] != "": @@ -75,61 +79,75 @@ class ReportDialog(QtWidgets.QWidget, FORM_CLASS): if item["errors"] != "": line += f', errors: {item["errors"]}' line = "❌ " + line[1:] - else: total_objects += 1 + else: + total_objects += 1 line = "__ " + line last_report += line + "\n" text += f"Operation: {operation}\n" text += f"Total: {total_layers} layer{'' if str(total_layers).endswith('1') else 's'}, {total_objects} feature{'' if str(total_objects).endswith('1') else 's'}\n\n" - if sending is False: + if sending is False: try: text += f"Host application: {self.dataStorage.latestHostApp}\n\n" - except: pass + except: + pass # layers and transformations (if applicable) text += "Layers and transformations (if applicable):" + "\n" for i, layer in enumerate(self.dataStorage.latestActionLayers): - #print(self.dataStorage.latestActionLayers) - name = layer #if isinstance(layer, str) else layer.name() - try: + # print(self.dataStorage.latestActionLayers) + name = layer # if isinstance(layer, str) else layer.name() + try: transformExists = 0 for item in self.dataStorage.savedTransforms: - layer_name = item.split(" -> ")[0].split(" (\'")[0] + layer_name = item.split(" -> ")[0].split(" ('")[0] transform_name = item.split(" -> ")[1] if layer_name == name: - text += f"{i+1}. {layer_name} -> '{transform_name}'" + "\n" + text += ( + f"{i+1}. {layer_name} -> '{transform_name}'" + "\n" + ) transformExists += 1 - break - if transformExists==0: + break + if transformExists == 0: text += f"{i+1}. {name} \n" - except Exception as e: print(e) - text += "\n" + except Exception as e: + print(e) + text += "\n" # add info about the offsets text += "Project CRS: " + self.dataStorage.project.crs().authid() + "\n" units = self.dataStorage.latestActionUnits - text += "Project CRS units: " + units + f"{' (not supported, treated as Meters)' if 'degrees' in units else ''}" + "\n" - text += "Project CRS WKT: \n" + self.dataStorage.project.crs().toWkt() + "\n\n" - text += f"CRS offsets: x={self.dataStorage.crs_offset_x}, y={self.dataStorage.crs_offset_y}" + "\n" - text += f"CRS rotation: {self.dataStorage.crs_rotation}°" + "\n\n" + text += ( + "Project CRS units: " + + units + + f"{' (not supported, treated as Meters)' if 'degrees' in units else ''}" + + "\n" + ) + text += ( + "Project CRS WKT: \n" + self.dataStorage.project.crs().toWkt() + "\n\n" + ) + text += ( + f"CRS offsets: x={self.dataStorage.crs_offset_x}, y={self.dataStorage.crs_offset_y}" + + "\n" + ) + text += f"CRS rotation: {self.dataStorage.crs_rotation}°" + "\n\n" text += last_report - return operation, total_layers, total_objects, text + return operation, total_layers, total_objects, text except Exception as e: print(e) - return + return - def applyReport(self): + def applyReport(self): result = self.assembleReport() if result is None: print("no report generated") - return + return operation, total_layers, total_objects, report = result - #self.report_label.setText(f"Operation: {operation}\nTotal: {total_layers} layer{'' if str(total_layers).endswith('1') else 's'}, {total_objects} feature{'' if str(total_objects).endswith('1') else 's'}") + # self.report_label.setText(f"Operation: {operation}\nTotal: {total_layers} layer{'' if str(total_layers).endswith('1') else 's'}, {total_objects} feature{'' if str(total_objects).endswith('1') else 's'}") self.report_text.setText(report) - + def onOkClicked(self): self.close() - \ No newline at end of file From 937ff8a8783cb0365c75dc0e573b1915583580cb Mon Sep 17 00:00:00 2001 From: KatKatKateryna Date: Thu, 7 Dec 2023 02:09:55 +0800 Subject: [PATCH 02/17] backup import from 'speckle' submodule --- qt_ui/DataStorage.py | 6 +- qt_ui/LogWidget.py | 41 ++++++++---- qt_ui/dockwidget_main.py | 96 +++++++++++++++++++--------- qt_ui/mainWindow.py | 18 ++++-- qt_ui/utils/logger.py | 6 +- qt_ui/widget_add_stream.py | 12 ++-- qt_ui/widget_create_branch.py | 6 +- qt_ui/widget_create_stream.py | 6 +- qt_ui/widget_custom_crs.py | 12 +++- qt_ui/widget_dependencies_upgrade.py | 6 +- qt_ui/widget_report.py | 9 ++- qt_ui/widget_transforms.py | 6 +- 12 files changed, 160 insertions(+), 64 deletions(-) diff --git a/qt_ui/DataStorage.py b/qt_ui/DataStorage.py index 3250a80..5615f0d 100644 --- a/qt_ui/DataStorage.py +++ b/qt_ui/DataStorage.py @@ -3,7 +3,11 @@ import inspect from typing import List, Optional, Tuple, Union, Any import webbrowser -from specklepy_qt_ui.qt_ui.utils.logger import logToUser +try: + from specklepy_qt_ui.qt_ui.utils.logger import logToUser +except ModuleNotFoundError: + from speckle.specklepy_qt_ui.qt_ui.utils.logger import logToUser + from specklepy.core.api.credentials import get_local_accounts diff --git a/qt_ui/LogWidget.py b/qt_ui/LogWidget.py index 1914bb5..895fe9f 100644 --- a/qt_ui/LogWidget.py +++ b/qt_ui/LogWidget.py @@ -9,19 +9,34 @@ import webbrowser from specklepy.logging import metrics from specklepy.core.api.credentials import Account -from specklepy_qt_ui.qt_ui.utils.global_resources import ( - BACKGR_COLOR, - BACKGR_COLOR_LIGHT, - BACKGR_COLOR_GREY, - BACKGR_COLOR_TRANSPARENT, - BACKGR_COLOR_HIGHLIGHT, - NEW_GREY, - NEW_GREY_HIGHLIGHT, - BACKGR_ERROR_COLOR, - BACKGR_ERROR_COLOR_LIGHT, -) -from specklepy_qt_ui.qt_ui.widget_dependencies_upgrade import DependenciesUpgradeDialog -from specklepy_qt_ui.qt_ui.widget_report import ReportDialog +try: + from specklepy_qt_ui.qt_ui.utils.global_resources import ( + BACKGR_COLOR, + BACKGR_COLOR_LIGHT, + BACKGR_COLOR_GREY, + BACKGR_COLOR_TRANSPARENT, + BACKGR_COLOR_HIGHLIGHT, + NEW_GREY, + NEW_GREY_HIGHLIGHT, + BACKGR_ERROR_COLOR, + BACKGR_ERROR_COLOR_LIGHT, + ) + from specklepy_qt_ui.qt_ui.widget_dependencies_upgrade import DependenciesUpgradeDialog + from specklepy_qt_ui.qt_ui.widget_report import ReportDialog +except ModuleNotFoundError: + from speckle.specklepy_qt_ui.qt_ui.utils.global_resources import ( + BACKGR_COLOR, + BACKGR_COLOR_LIGHT, + BACKGR_COLOR_GREY, + BACKGR_COLOR_TRANSPARENT, + BACKGR_COLOR_HIGHLIGHT, + NEW_GREY, + NEW_GREY_HIGHLIGHT, + BACKGR_ERROR_COLOR, + BACKGR_ERROR_COLOR_LIGHT, + ) + from speckle.specklepy_qt_ui.qt_ui.widget_dependencies_upgrade import DependenciesUpgradeDialog + from speckle.specklepy_qt_ui.qt_ui.widget_report import ReportDialog class LogWidget(QWidget): diff --git a/qt_ui/dockwidget_main.py b/qt_ui/dockwidget_main.py index 241ff63..a8d8037 100644 --- a/qt_ui/dockwidget_main.py +++ b/qt_ui/dockwidget_main.py @@ -4,37 +4,71 @@ from copy import copy import inspect import os -from specklepy_qt_ui.qt_ui.widget_transforms import MappingSendDialog -from specklepy_qt_ui.qt_ui.LogWidget import LogWidget -from specklepy_qt_ui.qt_ui.utils.logger import logToUser -from specklepy_qt_ui.qt_ui.utils import constructCommitURL -from specklepy_qt_ui.qt_ui.DataStorage import DataStorage -from specklepy_qt_ui.qt_ui.utils.global_resources import ( - COLOR_HIGHLIGHT, - SPECKLE_COLOR, - SPECKLE_COLOR_LIGHT, - ICON_OPEN_WEB, - ICON_REPORT, - ICON_LOGO, - ICON_SEARCH, - ICON_DELETE, - ICON_DELETE_BLUE, - ICON_SEND, - ICON_RECEIVE, - ICON_SEND_BLACK, - ICON_RECEIVE_BLACK, - ICON_SEND_BLUE, - ICON_RECEIVE_BLUE, - COLOR, - BACKGR_COLOR, - BACKGR_COLOR_LIGHT, - ICON_XXL, - ICON_RASTER, - ICON_POLYGON, - ICON_LINE, - ICON_POINT, - ICON_GENERIC, -) +try: + from specklepy_qt_ui.qt_ui.widget_transforms import MappingSendDialog + from specklepy_qt_ui.qt_ui.LogWidget import LogWidget + from specklepy_qt_ui.qt_ui.utils.logger import logToUser + from specklepy_qt_ui.qt_ui.utils import constructCommitURL + from specklepy_qt_ui.qt_ui.DataStorage import DataStorage + from specklepy_qt_ui.qt_ui.utils.global_resources import ( + COLOR_HIGHLIGHT, + SPECKLE_COLOR, + SPECKLE_COLOR_LIGHT, + ICON_OPEN_WEB, + ICON_REPORT, + ICON_LOGO, + ICON_SEARCH, + ICON_DELETE, + ICON_DELETE_BLUE, + ICON_SEND, + ICON_RECEIVE, + ICON_SEND_BLACK, + ICON_RECEIVE_BLACK, + ICON_SEND_BLUE, + ICON_RECEIVE_BLUE, + COLOR, + BACKGR_COLOR, + BACKGR_COLOR_LIGHT, + ICON_XXL, + ICON_RASTER, + ICON_POLYGON, + ICON_LINE, + ICON_POINT, + ICON_GENERIC, + ) +except ModuleNotFoundError: + from speckle.specklepy_qt_ui.qt_ui.widget_transforms import MappingSendDialog + from speckle.specklepy_qt_ui.qt_ui.LogWidget import LogWidget + from speckle.specklepy_qt_ui.qt_ui.utils.logger import logToUser + from speckle.specklepy_qt_ui.qt_ui.utils import constructCommitURL + from speckle.specklepy_qt_ui.qt_ui.DataStorage import DataStorage + from speckle.specklepy_qt_ui.qt_ui.utils.global_resources import ( + COLOR_HIGHLIGHT, + SPECKLE_COLOR, + SPECKLE_COLOR_LIGHT, + ICON_OPEN_WEB, + ICON_REPORT, + ICON_LOGO, + ICON_SEARCH, + ICON_DELETE, + ICON_DELETE_BLUE, + ICON_SEND, + ICON_RECEIVE, + ICON_SEND_BLACK, + ICON_RECEIVE_BLACK, + ICON_SEND_BLUE, + ICON_RECEIVE_BLUE, + COLOR, + BACKGR_COLOR, + BACKGR_COLOR_LIGHT, + ICON_XXL, + ICON_RASTER, + ICON_POLYGON, + ICON_LINE, + ICON_POINT, + ICON_GENERIC, + ) + from specklepy.logging.exceptions import SpeckleException, GraphQLException from specklepy.logging import metrics diff --git a/qt_ui/mainWindow.py b/qt_ui/mainWindow.py index 966a76f..195fb2b 100644 --- a/qt_ui/mainWindow.py +++ b/qt_ui/mainWindow.py @@ -50,14 +50,24 @@ except: # This loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer -from specklepy_qt_ui.qt_ui.global_resources import ( +try: + from specklepy_qt_ui.qt_ui.global_resources import ( COLOR_HIGHLIGHT, SPECKLE_COLOR, SPECKLE_COLOR_LIGHT, ICON_LOGO, ICON_SEARCH, ICON_DELETE, ICON_DELETE_BLUE, ICON_SEND, ICON_RECEIVE, ICON_SEND_BLACK, ICON_RECEIVE_BLACK, ICON_SEND_BLUE, ICON_RECEIVE_BLUE, COLOR, BACKGR_COLOR, BACKGR_COLOR_LIGHT, -) + ) +except ModuleNotFoundError: + from speckle.specklepy_qt_ui.qt_ui.global_resources import ( + COLOR_HIGHLIGHT, + SPECKLE_COLOR, SPECKLE_COLOR_LIGHT, + ICON_LOGO, ICON_SEARCH, ICON_DELETE, ICON_DELETE_BLUE, + ICON_SEND, ICON_RECEIVE, ICON_SEND_BLACK, ICON_RECEIVE_BLACK, + ICON_SEND_BLUE, ICON_RECEIVE_BLUE, + COLOR, BACKGR_COLOR, BACKGR_COLOR_LIGHT, + ) ui_class = uic.loadUiType( os.path.join(os.path.dirname(__file__), os.path.join("ui", "mainWindow.ui") ) @@ -416,7 +426,7 @@ class SpeckleGISDialog(QMainWindow): try: from speckle.ui.project_vars import set_project_layer_selection except: - from speckle_toolbox.esri.toolboxes.speckle.ui.project_vars import set_project_layer_selection + from speckle_toolbox.esri.toolboxes.speckle.speckle.ui.project_vars import set_project_layer_selection try: self.layersWidget.clear() @@ -518,7 +528,7 @@ class SpeckleGISDialog(QMainWindow): try: from speckle.ui.project_vars import set_project_streams except: - from speckle_toolbox.esri.toolboxes.speckle.ui.project_vars import set_project_streams + from speckle_toolbox.esri.toolboxes.speckle.speckle.ui.project_vars import set_project_streams try: if not self: return diff --git a/qt_ui/utils/logger.py b/qt_ui/utils/logger.py index 92a42c9..751e743 100644 --- a/qt_ui/utils/logger.py +++ b/qt_ui/utils/logger.py @@ -1,8 +1,10 @@ from PyQt5.QtWidgets import QMessageBox from PyQt5 import QtCore -from specklepy_qt_ui.qt_ui.utils import splitTextIntoLines - +try: + from specklepy_qt_ui.qt_ui.utils import splitTextIntoLines +except ModuleNotFoundError: + from speckle.specklepy_qt_ui.qt_ui.utils import splitTextIntoLines def logToUser( msg: str, func=None, level: int = 2, plugin=None, url="", blue=False, report=False diff --git a/qt_ui/widget_add_stream.py b/qt_ui/widget_add_stream.py index 0933c47..21804d1 100644 --- a/qt_ui/widget_add_stream.py +++ b/qt_ui/widget_add_stream.py @@ -2,9 +2,14 @@ import inspect import os from typing import List, Union import urllib.parse - -from specklepy_qt_ui.qt_ui.DataStorage import DataStorage -from specklepy_qt_ui.qt_ui.utils.logger import logToUser +try: + from specklepy_qt_ui.qt_ui.DataStorage import DataStorage + from specklepy_qt_ui.qt_ui.utils.logger import logToUser + from specklepy_qt_ui.qt_ui.utils import constructCommitURLfromServerCommit +except ModuleNotFoundError: + from speckle.specklepy_qt_ui.qt_ui.DataStorage import DataStorage + from speckle.specklepy_qt_ui.qt_ui.utils.logger import logToUser + from speckle.specklepy_qt_ui.qt_ui.utils import constructCommitURLfromServerCommit from PyQt5 import QtWidgets, uic, QtCore from PyQt5.QtCore import pyqtSignal @@ -16,7 +21,6 @@ from specklepy.core.api.credentials import get_local_accounts # , StreamWrapper from specklepy.core.api.wrapper import StreamWrapper from specklepy.logging import metrics -from specklepy_qt_ui.qt_ui.utils import constructCommitURLfromServerCommit # This loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer FORM_CLASS, _ = uic.loadUiType( diff --git a/qt_ui/widget_create_branch.py b/qt_ui/widget_create_branch.py index e39eea0..687387a 100644 --- a/qt_ui/widget_create_branch.py +++ b/qt_ui/widget_create_branch.py @@ -1,7 +1,11 @@ import inspect import os from typing import List, Tuple, Union -from specklepy_qt_ui.qt_ui.utils.logger import logToUser + +try: + from specklepy_qt_ui.qt_ui.utils.logger import logToUser +except ModuleNotFoundError: + from speckle.specklepy_qt_ui.qt_ui.utils.logger import logToUser from PyQt5 import QtWidgets, uic, QtCore from PyQt5.QtCore import pyqtSignal diff --git a/qt_ui/widget_create_stream.py b/qt_ui/widget_create_stream.py index edc4da6..66bc48b 100644 --- a/qt_ui/widget_create_stream.py +++ b/qt_ui/widget_create_stream.py @@ -1,7 +1,11 @@ import inspect import os from typing import List, Tuple, Union -from specklepy_qt_ui.qt_ui.utils.logger import logToUser + +try: + from specklepy_qt_ui.qt_ui.utils.logger import logToUser +except ModuleNotFoundError: + from speckle.specklepy_qt_ui.qt_ui.utils.logger import logToUser from PyQt5 import QtWidgets, uic, QtCore from PyQt5.QtCore import pyqtSignal diff --git a/qt_ui/widget_custom_crs.py b/qt_ui/widget_custom_crs.py index 11b3f86..8f27434 100644 --- a/qt_ui/widget_custom_crs.py +++ b/qt_ui/widget_custom_crs.py @@ -1,8 +1,15 @@ import inspect import os from typing import List, Tuple, Union -from specklepy_qt_ui.qt_ui.DataStorage import DataStorage -from specklepy_qt_ui.qt_ui.utils.logger import logToUser + +try: + from specklepy_qt_ui.qt_ui.DataStorage import DataStorage + from specklepy_qt_ui.qt_ui.utils.logger import logToUser + from specklepy_qt_ui.qt_ui.utils.global_resources import COLOR +except ModuleNotFoundError: + from speckle.specklepy_qt_ui.qt_ui.DataStorage import DataStorage + from speckle.specklepy_qt_ui.qt_ui.utils.logger import logToUser + from speckle.specklepy_qt_ui.qt_ui.utils.global_resources import COLOR from PyQt5 import QtWidgets, uic, QtCore from PyQt5.QtWidgets import QCheckBox, QListWidgetItem, QHBoxLayout, QWidget @@ -10,7 +17,6 @@ from PyQt5.QtCore import pyqtSignal from specklepy.core.api.client import SpeckleClient -from specklepy_qt_ui.qt_ui.utils.global_resources import COLOR # This loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer FORM_CLASS, _ = uic.loadUiType( diff --git a/qt_ui/widget_dependencies_upgrade.py b/qt_ui/widget_dependencies_upgrade.py index 2b7d895..24911cb 100644 --- a/qt_ui/widget_dependencies_upgrade.py +++ b/qt_ui/widget_dependencies_upgrade.py @@ -3,7 +3,11 @@ import urllib3 import requests import requests_toolbelt from specklepy.logging import metrics -from specklepy_qt_ui.qt_ui.DataStorage import DataStorage + +try: + from specklepy_qt_ui.qt_ui.DataStorage import DataStorage +except ModuleNotFoundError: + from speckle.specklepy_qt_ui.qt_ui.DataStorage import DataStorage from PyQt5 import QtWidgets, uic, QtCore diff --git a/qt_ui/widget_report.py b/qt_ui/widget_report.py index e193dbc..619bb0e 100644 --- a/qt_ui/widget_report.py +++ b/qt_ui/widget_report.py @@ -1,7 +1,13 @@ import inspect import os from typing import List, Tuple, Union -from specklepy_qt_ui.qt_ui.DataStorage import DataStorage + +try: + from specklepy_qt_ui.qt_ui.DataStorage import DataStorage + from specklepy_qt_ui.qt_ui.utils.global_resources import COLOR +except ModuleNotFoundError: + from speckle.specklepy_qt_ui.qt_ui.DataStorage import DataStorage + from speckle.specklepy_qt_ui.qt_ui.utils.global_resources import COLOR # from specklepy_qt_ui.qt_ui.utils.logger import logToUser @@ -11,7 +17,6 @@ from PyQt5.QtCore import pyqtSignal from specklepy.core.api.client import SpeckleClient -from specklepy_qt_ui.qt_ui.utils.global_resources import COLOR # This loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer FORM_CLASS, _ = uic.loadUiType( diff --git a/qt_ui/widget_transforms.py b/qt_ui/widget_transforms.py index d9a0fb9..2c20e7c 100644 --- a/qt_ui/widget_transforms.py +++ b/qt_ui/widget_transforms.py @@ -1,6 +1,10 @@ import os -from specklepy_qt_ui.qt_ui.DataStorage import DataStorage + +try: + from specklepy_qt_ui.qt_ui.DataStorage import DataStorage +except ModuleNotFoundError: + from speckle.specklepy_qt_ui.qt_ui.DataStorage import DataStorage from PyQt5 import QtWidgets, uic, QtCore From 2a577de45cd215ed34b5d644c3e16800e386458e Mon Sep 17 00:00:00 2001 From: KatKatKateryna Date: Thu, 7 Dec 2023 02:16:39 +0800 Subject: [PATCH 03/17] remove imports names overlap --- qt_ui/dockwidget_main.py | 4 ++-- qt_ui/utils/logger.py | 4 ++-- qt_ui/{ => utils}/utils.py | 0 qt_ui/widget_add_stream.py | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) rename qt_ui/{ => utils}/utils.py (100%) diff --git a/qt_ui/dockwidget_main.py b/qt_ui/dockwidget_main.py index a8d8037..621e127 100644 --- a/qt_ui/dockwidget_main.py +++ b/qt_ui/dockwidget_main.py @@ -8,7 +8,7 @@ try: from specklepy_qt_ui.qt_ui.widget_transforms import MappingSendDialog from specklepy_qt_ui.qt_ui.LogWidget import LogWidget from specklepy_qt_ui.qt_ui.utils.logger import logToUser - from specklepy_qt_ui.qt_ui.utils import constructCommitURL + from specklepy_qt_ui.qt_ui.utils.utils import constructCommitURL from specklepy_qt_ui.qt_ui.DataStorage import DataStorage from specklepy_qt_ui.qt_ui.utils.global_resources import ( COLOR_HIGHLIGHT, @@ -40,7 +40,7 @@ except ModuleNotFoundError: from speckle.specklepy_qt_ui.qt_ui.widget_transforms import MappingSendDialog from speckle.specklepy_qt_ui.qt_ui.LogWidget import LogWidget from speckle.specklepy_qt_ui.qt_ui.utils.logger import logToUser - from speckle.specklepy_qt_ui.qt_ui.utils import constructCommitURL + from speckle.specklepy_qt_ui.qt_ui.utils.utils import constructCommitURL from speckle.specklepy_qt_ui.qt_ui.DataStorage import DataStorage from speckle.specklepy_qt_ui.qt_ui.utils.global_resources import ( COLOR_HIGHLIGHT, diff --git a/qt_ui/utils/logger.py b/qt_ui/utils/logger.py index 751e743..134da85 100644 --- a/qt_ui/utils/logger.py +++ b/qt_ui/utils/logger.py @@ -2,9 +2,9 @@ from PyQt5.QtWidgets import QMessageBox from PyQt5 import QtCore try: - from specklepy_qt_ui.qt_ui.utils import splitTextIntoLines + from specklepy_qt_ui.qt_ui.utils.utils import splitTextIntoLines except ModuleNotFoundError: - from speckle.specklepy_qt_ui.qt_ui.utils import splitTextIntoLines + from speckle.specklepy_qt_ui.qt_ui.utils.utils import splitTextIntoLines def logToUser( msg: str, func=None, level: int = 2, plugin=None, url="", blue=False, report=False diff --git a/qt_ui/utils.py b/qt_ui/utils/utils.py similarity index 100% rename from qt_ui/utils.py rename to qt_ui/utils/utils.py diff --git a/qt_ui/widget_add_stream.py b/qt_ui/widget_add_stream.py index 21804d1..8f5425d 100644 --- a/qt_ui/widget_add_stream.py +++ b/qt_ui/widget_add_stream.py @@ -5,11 +5,11 @@ import urllib.parse try: from specklepy_qt_ui.qt_ui.DataStorage import DataStorage from specklepy_qt_ui.qt_ui.utils.logger import logToUser - from specklepy_qt_ui.qt_ui.utils import constructCommitURLfromServerCommit + from specklepy_qt_ui.qt_ui.utils.utils import constructCommitURLfromServerCommit except ModuleNotFoundError: from speckle.specklepy_qt_ui.qt_ui.DataStorage import DataStorage from speckle.specklepy_qt_ui.qt_ui.utils.logger import logToUser - from speckle.specklepy_qt_ui.qt_ui.utils import constructCommitURLfromServerCommit + from speckle.specklepy_qt_ui.qt_ui.utils.utils import constructCommitURLfromServerCommit from PyQt5 import QtWidgets, uic, QtCore from PyQt5.QtCore import pyqtSignal From 51b1de45878c0b2616d047ed2dbbdce9a747c79b Mon Sep 17 00:00:00 2001 From: KatKatKateryna Date: Thu, 7 Dec 2023 19:04:41 +0800 Subject: [PATCH 04/17] place Assets into Utils --- qt_ui/{ => utils}/assets/__init__.py | 0 qt_ui/{ => utils}/assets/chart-line.png | Bin qt_ui/{ => utils}/assets/cube-receive-black.png | Bin qt_ui/{ => utils}/assets/cube-receive-blue.png | Bin qt_ui/{ => utils}/assets/cube-receive.png | Bin qt_ui/{ => utils}/assets/cube-send-black.png | Bin qt_ui/{ => utils}/assets/cube-send-blue.png | Bin qt_ui/{ => utils}/assets/cube-send.png | Bin qt_ui/{ => utils}/assets/delete-blue.png | Bin qt_ui/{ => utils}/assets/delete.png | Bin qt_ui/{ => utils}/assets/legend_generic.png | Bin qt_ui/{ => utils}/assets/legend_line.png | Bin qt_ui/{ => utils}/assets/legend_point.png | Bin qt_ui/{ => utils}/assets/legend_polygon.png | Bin qt_ui/{ => utils}/assets/legend_raster.png | Bin qt_ui/{ => utils}/assets/logo-slab-white@0.5x.png | Bin qt_ui/{ => utils}/assets/magnify.png | Bin qt_ui/{ => utils}/assets/open-in-new.png | Bin qt_ui/{ => utils}/assets/size-xxl.png | Bin 19 files changed, 0 insertions(+), 0 deletions(-) rename qt_ui/{ => utils}/assets/__init__.py (100%) rename qt_ui/{ => utils}/assets/chart-line.png (100%) rename qt_ui/{ => utils}/assets/cube-receive-black.png (100%) rename qt_ui/{ => utils}/assets/cube-receive-blue.png (100%) rename qt_ui/{ => utils}/assets/cube-receive.png (100%) rename qt_ui/{ => utils}/assets/cube-send-black.png (100%) rename qt_ui/{ => utils}/assets/cube-send-blue.png (100%) rename qt_ui/{ => utils}/assets/cube-send.png (100%) rename qt_ui/{ => utils}/assets/delete-blue.png (100%) rename qt_ui/{ => utils}/assets/delete.png (100%) rename qt_ui/{ => utils}/assets/legend_generic.png (100%) rename qt_ui/{ => utils}/assets/legend_line.png (100%) rename qt_ui/{ => utils}/assets/legend_point.png (100%) rename qt_ui/{ => utils}/assets/legend_polygon.png (100%) rename qt_ui/{ => utils}/assets/legend_raster.png (100%) rename qt_ui/{ => utils}/assets/logo-slab-white@0.5x.png (100%) rename qt_ui/{ => utils}/assets/magnify.png (100%) rename qt_ui/{ => utils}/assets/open-in-new.png (100%) rename qt_ui/{ => utils}/assets/size-xxl.png (100%) diff --git a/qt_ui/assets/__init__.py b/qt_ui/utils/assets/__init__.py similarity index 100% rename from qt_ui/assets/__init__.py rename to qt_ui/utils/assets/__init__.py diff --git a/qt_ui/assets/chart-line.png b/qt_ui/utils/assets/chart-line.png similarity index 100% rename from qt_ui/assets/chart-line.png rename to qt_ui/utils/assets/chart-line.png diff --git a/qt_ui/assets/cube-receive-black.png b/qt_ui/utils/assets/cube-receive-black.png similarity index 100% rename from qt_ui/assets/cube-receive-black.png rename to qt_ui/utils/assets/cube-receive-black.png diff --git a/qt_ui/assets/cube-receive-blue.png b/qt_ui/utils/assets/cube-receive-blue.png similarity index 100% rename from qt_ui/assets/cube-receive-blue.png rename to qt_ui/utils/assets/cube-receive-blue.png diff --git a/qt_ui/assets/cube-receive.png b/qt_ui/utils/assets/cube-receive.png similarity index 100% rename from qt_ui/assets/cube-receive.png rename to qt_ui/utils/assets/cube-receive.png diff --git a/qt_ui/assets/cube-send-black.png b/qt_ui/utils/assets/cube-send-black.png similarity index 100% rename from qt_ui/assets/cube-send-black.png rename to qt_ui/utils/assets/cube-send-black.png diff --git a/qt_ui/assets/cube-send-blue.png b/qt_ui/utils/assets/cube-send-blue.png similarity index 100% rename from qt_ui/assets/cube-send-blue.png rename to qt_ui/utils/assets/cube-send-blue.png diff --git a/qt_ui/assets/cube-send.png b/qt_ui/utils/assets/cube-send.png similarity index 100% rename from qt_ui/assets/cube-send.png rename to qt_ui/utils/assets/cube-send.png diff --git a/qt_ui/assets/delete-blue.png b/qt_ui/utils/assets/delete-blue.png similarity index 100% rename from qt_ui/assets/delete-blue.png rename to qt_ui/utils/assets/delete-blue.png diff --git a/qt_ui/assets/delete.png b/qt_ui/utils/assets/delete.png similarity index 100% rename from qt_ui/assets/delete.png rename to qt_ui/utils/assets/delete.png diff --git a/qt_ui/assets/legend_generic.png b/qt_ui/utils/assets/legend_generic.png similarity index 100% rename from qt_ui/assets/legend_generic.png rename to qt_ui/utils/assets/legend_generic.png diff --git a/qt_ui/assets/legend_line.png b/qt_ui/utils/assets/legend_line.png similarity index 100% rename from qt_ui/assets/legend_line.png rename to qt_ui/utils/assets/legend_line.png diff --git a/qt_ui/assets/legend_point.png b/qt_ui/utils/assets/legend_point.png similarity index 100% rename from qt_ui/assets/legend_point.png rename to qt_ui/utils/assets/legend_point.png diff --git a/qt_ui/assets/legend_polygon.png b/qt_ui/utils/assets/legend_polygon.png similarity index 100% rename from qt_ui/assets/legend_polygon.png rename to qt_ui/utils/assets/legend_polygon.png diff --git a/qt_ui/assets/legend_raster.png b/qt_ui/utils/assets/legend_raster.png similarity index 100% rename from qt_ui/assets/legend_raster.png rename to qt_ui/utils/assets/legend_raster.png diff --git a/qt_ui/assets/logo-slab-white@0.5x.png b/qt_ui/utils/assets/logo-slab-white@0.5x.png similarity index 100% rename from qt_ui/assets/logo-slab-white@0.5x.png rename to qt_ui/utils/assets/logo-slab-white@0.5x.png diff --git a/qt_ui/assets/magnify.png b/qt_ui/utils/assets/magnify.png similarity index 100% rename from qt_ui/assets/magnify.png rename to qt_ui/utils/assets/magnify.png diff --git a/qt_ui/assets/open-in-new.png b/qt_ui/utils/assets/open-in-new.png similarity index 100% rename from qt_ui/assets/open-in-new.png rename to qt_ui/utils/assets/open-in-new.png diff --git a/qt_ui/assets/size-xxl.png b/qt_ui/utils/assets/size-xxl.png similarity index 100% rename from qt_ui/assets/size-xxl.png rename to qt_ui/utils/assets/size-xxl.png From 6db462df3c6a65afc255a40a28139eb2148f3806 Mon Sep 17 00:00:00 2001 From: KatKatKateryna Date: Wed, 31 Jan 2024 15:09:25 +0000 Subject: [PATCH 05/17] Revert "Change terminology to FE2" This reverts commit 876068a39a445f3fdcee1c0558f683c39dc09af5. --- qt_ui/ConnectorBindings.py | 126 ++++++ qt_ui/dockwidget_main.py | 12 +- qt_ui/mainWindow.py | 716 +++++++++++++--------------------- qt_ui/ui/add_stream_modal.ui | 2 +- qt_ui/ui/create_branch.ui | 2 +- qt_ui/ui/create_stream.ui | 2 +- qt_ui/ui/dockwidget_main.ui | 6 +- qt_ui/ui/mainWindow_main.ui | 6 +- qt_ui/widget_add_stream.py | 16 +- qt_ui/widget_create_branch.py | 46 +-- qt_ui/widget_create_stream.py | 2 +- 11 files changed, 446 insertions(+), 490 deletions(-) create mode 100644 qt_ui/ConnectorBindings.py diff --git a/qt_ui/ConnectorBindings.py b/qt_ui/ConnectorBindings.py new file mode 100644 index 0000000..43b2bf0 --- /dev/null +++ b/qt_ui/ConnectorBindings.py @@ -0,0 +1,126 @@ + +from typing import Dict, List + +from numpy import double +from import UpdateSavedStreams +from import UpdateSelectedStream + +using static DesktopUI2.ViewModels.MappingViewModel; + +namespace DesktopUI2; + +public delegate void UpdateSavedStreams(List streams); +public delegate void UpdateSelectedStream(); + +class ConnectorBindings(): + + def __init__(self): + self.ConnectorVersion: str == Assembly.GetAssembly(GetType()).GetNameAndVersion().Version + self.ConnectorName: str == Assembly.GetAssembly(GetType()).GetNameAndVersion().Name + #SavedStreamStates: List == new List() + + self.CanReceive: bool = True + '''Indicates if the connector can Receive and if that function has been implemented''' + self.CanPreviewSend: bool == False + '''Indicates if previewing send has been implemented''' + self.CanPreviewReceive: bool == False + '''Indicates if previewing receive has been implemented''' + self.CanOpen3DView: bool == False + '''Returns true if the method is overwritten and implemented.''' + + def UpdateSavedStreams(self, streams: List[StreamState]): + UpdateSavedStreams(streams) + + def UpdateSelectedStream(self): + UpdateSelectedStream() + + def Open3DView(self, viewCoordinates: List[double], viewName: str = ""): + '''Opens a 3D view in the host application + viewCoordinates: First three values are the camera position, second three the target. + viewName: Id or Name of the view''' + return + + def GetHostAppNameVersion(self)-> str: + '''Gets the current host application name with version.''' + return + + def GetHostAppName(self) -> str: + '''Gets the current host application name.''' + return + + def GetFileName(self) -> str: + '''Gets the current opened/focused file's name. + Make sure to check regarding unsaved/temporary files.''' + return + + def GetDocumentId(self) -> str: + '''Gets the current opened/focused file's id. + Generate one in here if the host app does not provide one.''' + return + + def GetDocumentLocation(self) -> str: + '''Gets the current opened/focused file's locations. + Make sure to check regarding unsaved/temporary files.''' + return + + def ResetDocument(self): + '''Clears the document state of selections and previews''' + return + + def GetActiveViewName(self) -> str: + '''Gets the current opened/focused file's view, if applicable.''' + return + + def GetStreamsInFile(self) -> List[StreamState]: + '''Returns the serialised clients present in the current open host file.''' + return + + def WriteStreamsToFile(self, streams: List[StreamState]): + '''Writes serialised clients to the current open host file.''' + return + + def AddNewStream(self, state: StreamState): + '''Adds a new client and persists the info to the host file''' + return + + def PersistAndUpdateStreamInFile(self, state: StreamState): + '''Persists the stream info to the host file; if maintaining a local in memory copy, make sure to update it too.''' + return + + def SendStream(self, state: StreamState, progress: ProgressViewModel) -> str: + '''Pushes a client's stream''' + return + + def PreviewSend(self, state: StreamState, progress: ProgressViewModel): + '''Previews a send operation''' + + def ReceiveStream(self, state: StreamState, progress: ProgressViewModel) -> StreamState: + '''Receives stream data from the server''' + + def PreviewReceive(self, state: StreamState, progress: ProgressViewModel) -> StreamState: + '''Previews a receive operation''' + + def GetSelectedObjects(self) -> List[str]: + '''Adds the current selection to the provided client.''' + + def GetObjectsInView(self) -> List[str]: + '''Gets a list of objects in the currently active view''' + + def SelectClientObjects(self, objs: List[str], deselect: bool = False): + '''clients should be able to select/preview/hover one way or another their associated objects''' + + def GetSelectionFilters(self) -> List[ISelectionFilter]: + '''Should return a list of filters that the application supports.''' + + def GetReceiveModes(self) -> List[ReceiveMode]: + '''Should return a list of receive modes that the application supports.''' + + def GetCustomStreamMenuItems(self) -> List[MenuItem]: + '''Return a list of custom menu items for stream cards.''' + + def GetSettings(self) -> List[ISetting]: + return + + def ImportFamilyCommand(self, Mapping: Dict[str, List[MappingValue]] ) -> Dict[str, List[MappingValue]] : + '''Imports family symbols in Revit''' + return diff --git a/qt_ui/dockwidget_main.py b/qt_ui/dockwidget_main.py index 3bc6dfa..6f6ceef 100644 --- a/qt_ui/dockwidget_main.py +++ b/qt_ui/dockwidget_main.py @@ -775,7 +775,7 @@ class SpeckleQGISDialog(QtWidgets.QDockWidget, FORM_CLASS): self.streamBranchDropdown.clear() # activates "populate commit" # print(2) if isinstance(plugin.active_stream[1], SpeckleException): - logToUser("Some Projects cannot be accessed", level=1, plugin=self) + logToUser("Some streams cannot be accessed", level=1, plugin=self) return elif ( plugin.active_stream is None @@ -791,7 +791,7 @@ class SpeckleQGISDialog(QtWidgets.QDockWidget, FORM_CLASS): [f"{branch.name}" for branch in plugin.active_stream[1].branches.items] ) # print(4) - self.streamBranchDropdown.addItems(["Create New Model"]) + self.streamBranchDropdown.addItems(["Create New Branch"]) # print(5) if keep_branch is True: plugin.active_branch = active_branch @@ -830,13 +830,13 @@ class SpeckleQGISDialog(QtWidgets.QDockWidget, FORM_CLASS): # print("________populateActiveCommitDropdown") # print(plugin.active_commit) if plugin.active_stream is None: - print("Active project is None") + print("Active stream is None") return branchName = self.streamBranchDropdown.currentText() # print(f"CURRENT BRANCH TEXT: {branchName}") if branchName == "": return - if branchName == "Create New Model": + if branchName == "Create New Branch": self.streamBranchDropdown.setCurrentText("main") plugin.onBranchCreateClicked() return @@ -846,7 +846,7 @@ class SpeckleQGISDialog(QtWidgets.QDockWidget, FORM_CLASS): # print(plugin.active_commit) self.commitDropdown.clear() if isinstance(plugin.active_stream[1], SpeckleException): - logToUser("Some Projects cannot be accessed", level=1, plugin=self) + logToUser("Some streams cannot be accessed", level=1, plugin=self) return elif plugin.active_stream[1]: for b in plugin.active_stream[1].branches.items: @@ -898,7 +898,7 @@ class SpeckleQGISDialog(QtWidgets.QDockWidget, FORM_CLASS): else: plugin.active_commit = None - self.commitDropdown.setItemText(0, "Latest version of this model") + self.commitDropdown.setItemText(0, "Latest commit from this branch") # enable or disable web view button # print("_________ENABLE OR DISABLE") # print(plugin.active_commit) diff --git a/qt_ui/mainWindow.py b/qt_ui/mainWindow.py index 2473702..966a76f 100644 --- a/qt_ui/mainWindow.py +++ b/qt_ui/mainWindow.py @@ -1,30 +1,21 @@ + import os import sys from typing import List +#from speckle.converter.layers import getLayers -# from speckle.converter.layers import getLayers +#import ui.speckle_qgis_dialog -# import ui.speckle_qgis_dialog - -from specklepy.logging.exceptions import SpeckleException, GraphQLException +from specklepy.logging.exceptions import (SpeckleException, GraphQLException) from PyQt5 import QtWidgets, uic from PyQt5 import QtGui from PyQt5.QtGui import QIcon, QPixmap -from PyQt5.QtWidgets import ( - QMainWindow, - QApplication, - QWidget, - QListWidgetItem, - QAction, - QDockWidget, - QVBoxLayout, - QHBoxLayout, - QWidget, - QLabel, -) +from PyQt5.QtWidgets import (QMainWindow, QApplication, QWidget, + QListWidgetItem, QAction, QDockWidget, QVBoxLayout, + QHBoxLayout, QWidget, QLabel) from PyQt5 import QtCore -from PyQt5.QtCore import pyqtSignal, Qt, QSize, QEvent -from PyQt5 import QtGui, uic +from PyQt5.QtCore import pyqtSignal, Qt, QSize, QEvent +from PyQt5 import QtGui, uic from specklepy.api.credentials import get_local_accounts @@ -34,59 +25,46 @@ from specklepy.api.wrapper import StreamWrapper from specklepy.api.client import SpeckleClient from specklepy.logging import metrics -import arcpy +import arcpy -import inspect +import inspect try: - # from speckle.speckle_arcgis_new import Speckle + #from speckle.speckle_arcgis_new import Speckle from speckle.converter.layers import getLayers, getAllProjLayers from speckle.ui.logger import logToUser from speckle.ui.LogWidget import LogWidget except: - # from speckle_toolbox.esri.toolboxes.speckle.speckle_arcgis_new import Speckle - from speckle_toolbox.esri.toolboxes.speckle.converter.layers import ( - getLayers, - getAllProjLayers, - ) + #from speckle_toolbox.esri.toolboxes.speckle.speckle_arcgis_new import Speckle + from speckle_toolbox.esri.toolboxes.speckle.converter.layers import getLayers, getAllProjLayers from speckle_toolbox.esri.toolboxes.speckle.ui.logger import logToUser from speckle_toolbox.esri.toolboxes.speckle.ui.LogWidget import LogWidget -# from ui.validation import tryGetStream +#from ui.validation import tryGetStream # Create module-like object -# pytPath = os.path.dirname(os.path.abspath(__file__)).replace("/speckle/ui","/Speckle.pyt") -# print(pytPath) -# pytModule = importlib.machinery.SourceFileLoader("specklePyt", pytPath ) -# specklePyt = pytModule.load_module("specklePyt") +#pytPath = os.path.dirname(os.path.abspath(__file__)).replace("/speckle/ui","/Speckle.pyt") +#print(pytPath) +#pytModule = importlib.machinery.SourceFileLoader("specklePyt", pytPath ) +#specklePyt = pytModule.load_module("specklePyt") # This loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer from specklepy_qt_ui.qt_ui.global_resources import ( - COLOR_HIGHLIGHT, - SPECKLE_COLOR, - SPECKLE_COLOR_LIGHT, - ICON_LOGO, - ICON_SEARCH, - ICON_DELETE, - ICON_DELETE_BLUE, - ICON_SEND, - ICON_RECEIVE, - ICON_SEND_BLACK, - ICON_RECEIVE_BLACK, - ICON_SEND_BLUE, - ICON_RECEIVE_BLUE, - COLOR, - BACKGR_COLOR, - BACKGR_COLOR_LIGHT, + COLOR_HIGHLIGHT, + SPECKLE_COLOR, SPECKLE_COLOR_LIGHT, + ICON_LOGO, ICON_SEARCH, ICON_DELETE, ICON_DELETE_BLUE, + ICON_SEND, ICON_RECEIVE, ICON_SEND_BLACK, ICON_RECEIVE_BLACK, + ICON_SEND_BLUE, ICON_RECEIVE_BLUE, + COLOR, BACKGR_COLOR, BACKGR_COLOR_LIGHT, ) ui_class = uic.loadUiType( - os.path.join(os.path.dirname(__file__), os.path.join("ui", "mainWindow.ui")) + os.path.join(os.path.dirname(__file__), os.path.join("ui", "mainWindow.ui") ) ) - class SpeckleGISDialog(QMainWindow): + closingPlugin = pyqtSignal() streamList: QtWidgets.QComboBox sendModeButton: QtWidgets.QPushButton @@ -100,17 +78,15 @@ class SpeckleGISDialog(QMainWindow): msgLog: LogWidget = None gridLayoutTitleBar = QtWidgets.QGridLayout - + def __init__(self): """Constructor.""" print("START MAIN WINDOW") - super(SpeckleGISDialog, self).__init__( - None - ) # , QtCore.Qt.WindowStaysOnTopHint) - uic.loadUi(ui_class, self) # Load the .ui file - # self.installEventFilter(self) - self.show() - # self.instances.append(1) + super(SpeckleGISDialog, self).__init__(None)#, QtCore.Qt.WindowStaysOnTopHint) + uic.loadUi(ui_class, self) # Load the .ui file + #self.installEventFilter(self) + self.show() + #self.instances.append(1) try: self.streamBranchDropdown.setMaxCount(100) self.commitDropdown.setMaxCount(100) @@ -122,188 +98,141 @@ class SpeckleGISDialog(QMainWindow): self.reloadButton.setFlat(True) self.closeButton.setFlat(True) - # backgr_color = f"background-color: rgb{str(SPECKLE_COLOR)};" - # backgr_color_light = f"background-color: rgb{str(SPECKLE_COLOR_LIGHT)};" + #backgr_color = f"background-color: rgb{str(SPECKLE_COLOR)};" + #backgr_color_light = f"background-color: rgb{str(SPECKLE_COLOR_LIGHT)};" backgr_image_del = f"border-image: url({ICON_DELETE_BLUE});" self.streams_add_button.setIcon(QIcon(ICON_SEARCH)) self.streams_add_button.setMaximumWidth(25) - self.streams_add_button.setStyleSheet( - "QPushButton {padding:3px;padding-left:5px;border: none; text-align: left;} QPushButton:hover { " - + f"background-color: rgb{str(COLOR_HIGHLIGHT)};" - + f"{COLOR}" - + " }" - ) + self.streams_add_button.setStyleSheet("QPushButton {padding:3px;padding-left:5px;border: none; text-align: left;} QPushButton:hover { " + f"background-color: rgb{str(COLOR_HIGHLIGHT)};" + f"{COLOR}" + " }") self.streams_remove_button.setIcon(QIcon(ICON_DELETE)) self.streams_remove_button.setMaximumWidth(25) - self.streams_remove_button.setStyleSheet( - "QPushButton {padding:3px;padding-left:5px;border: none; text-align: left; image-position:right} QPushButton:hover { " - + f"background-color: rgb{str(COLOR_HIGHLIGHT)};" - + f"{COLOR}" - + " }" - ) # + f"{backgr_image_del}" + self.streams_remove_button.setStyleSheet("QPushButton {padding:3px;padding-left:5px;border: none; text-align: left; image-position:right} QPushButton:hover { " + f"background-color: rgb{str(COLOR_HIGHLIGHT)};" + f"{COLOR}" + " }") #+ f"{backgr_image_del}" - self.saveLayerSelection.setStyleSheet( - "QPushButton {text-align: right;} QPushButton:hover { " - + f"{COLOR}" - + " }" - ) - self.saveSurveyPoint.setStyleSheet( - "QPushButton {text-align: right;} QPushButton:hover { " - + f"{COLOR}" - + " }" - ) - self.reloadButton.setStyleSheet( - "QPushButton {text-align: left;} QPushButton:hover { " - + f"{COLOR}" - + " }" - ) - self.closeButton.setStyleSheet( - "QPushButton {text-align: right;} QPushButton:hover { " - + f"{COLOR}" - + " }" - ) + self.saveLayerSelection.setStyleSheet("QPushButton {text-align: right;} QPushButton:hover { " + f"{COLOR}" + " }") + self.saveSurveyPoint.setStyleSheet("QPushButton {text-align: right;} QPushButton:hover { " + f"{COLOR}" + " }") + self.reloadButton.setStyleSheet("QPushButton {text-align: left;} QPushButton:hover { " + f"{COLOR}" + " }") + self.closeButton.setStyleSheet("QPushButton {text-align: right;} QPushButton:hover { " + f"{COLOR}" + " }") - self.sendModeButton.setStyleSheet( - "QPushButton {padding: 10px; border: 0px; " - + f"color: rgb{str(SPECKLE_COLOR)};" - + "} QPushButton:hover { " - + "}" - ) + + self.sendModeButton.setStyleSheet("QPushButton {padding: 10px; border: 0px; " + f"color: rgb{str(SPECKLE_COLOR)};"+ "} QPushButton:hover { " + "}" ) self.sendModeButton.setIcon(QIcon(ICON_SEND_BLUE)) - + self.receiveModeButton.setFlat(True) - self.receiveModeButton.setStyleSheet( - "QPushButton {padding: 10px; border: 0px;}" - + "QPushButton:hover { " - + f"background-color: rgb{str(COLOR_HIGHLIGHT)};" - + "}" - ) + self.receiveModeButton.setStyleSheet("QPushButton {padding: 10px; border: 0px;}"+ "QPushButton:hover { " + f"background-color: rgb{str(COLOR_HIGHLIGHT)};" + "}" ) self.receiveModeButton.setIcon(QIcon(ICON_RECEIVE_BLACK)) - self.runButton.setStyleSheet( - "QPushButton {color: white;border: 0px;border-radius: 17px;padding: 10px;" - + f"{BACKGR_COLOR}" - + "} QPushButton:hover { " - + f"{BACKGR_COLOR_LIGHT}" - + " }" - ) + self.runButton.setStyleSheet("QPushButton {color: white;border: 0px;border-radius: 17px;padding: 10px;"+ f"{BACKGR_COLOR}" + "} QPushButton:hover { "+ f"{BACKGR_COLOR_LIGHT}" + " }") self.runButton.setMaximumWidth(200) self.runButton.setIcon(QIcon(ICON_SEND)) - # add widgets that will only show on event trigger + # add widgets that will only show on event trigger logWidget = LogWidget(parent=self) self.layout().addWidget(logWidget) - self.msgLog = logWidget - - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + self.msgLog = logWidget + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + def addProps(self, plugin): self.msgLog.active_account = plugin.active_account self.msgLog.speckle_version = plugin.version - def addLabel(self, plugin): + def addLabel(self, plugin): + try: exitIcon = QPixmap(ICON_LOGO) exitActIcon = QIcon(exitIcon) - # create a label + # create a label text_label = QtWidgets.QPushButton(" for ArcGIS") - text_label.setStyleSheet( - "border: 0px;" - "color: white;" - f"{BACKGR_COLOR}" - "top-margin: 40 px;" - "padding: 10px;" - "padding-left: 20px;" - "font-size: 15px;" - "height: 30px;" - "text-align: left;" - ) + text_label.setStyleSheet("border: 0px;" + "color: white;" + f"{BACKGR_COLOR}" + "top-margin: 40 px;" + "padding: 10px;" + "padding-left: 20px;" + "font-size: 15px;" + "height: 30px;" + "text-align: left;" + ) text_label.setIcon(exitActIcon) text_label.setIconSize(QSize(300, 93)) text_label.setMinimumSize(QSize(100, 40)) text_label.setMaximumWidth(220) version = "" - try: - if isinstance(plugin.version, str): - version = str(plugin.version) - except: - pass + try: + if isinstance(plugin.version, str): version = str(plugin.version) + except: pass version_label = QtWidgets.QPushButton(f"{version}") - version_label.setStyleSheet( - "border: 0px;" - "color: white;" - f"{BACKGR_COLOR}" - "padding-top: 15px;" - "padding-left: 0px;" - "margin-left: 0px;" - "font-size: 10px;" - "height: 30px;" - "text-align: left;" - ) + version_label.setStyleSheet("border: 0px;" + "color: white;" + f"{BACKGR_COLOR}" + "padding-top: 15px;" + "padding-left: 0px;" + "margin-left: 0px;" + "font-size: 10px;" + "height: 30px;" + "text-align: left;" + ) widget = QWidget() widget.setStyleSheet(f"{BACKGR_COLOR}") connect_box = QHBoxLayout(widget) - connect_box.addWidget(text_label) # , alignment=Qt.AlignCenter) - connect_box.addWidget(version_label) + connect_box.addWidget(text_label) #, alignment=Qt.AlignCenter) + connect_box.addWidget(version_label) connect_box.setContentsMargins(0, 0, 0, 0) - self.gridLayoutTitleBar.addWidget(widget) # fro QMainWindow - # self.setTitleBarWidget(widget) # for QDockWidget + self.gridLayoutTitleBar.addWidget(widget) # fro QMainWindow + #self.setTitleBarWidget(widget) # for QDockWidget except Exception as e: logToUser(e) def resizeEvent(self, event): try: - # print("resize") + #print("resize") QtWidgets.QMainWindow.resizeEvent(self, event) - if self.msgLog.size().height() != 0: # visible - self.msgLog.setGeometry( - 0, - 0, - self.msgLog.parentWidget.frameSize().width(), - self.msgLog.parentWidget.frameSize().height(), - ) # .resize(self.frameSize().width(), self.frameSize().height()) + if self.msgLog.size().height() != 0: # visible + self.msgLog.setGeometry(0, 0, self.msgLog.parentWidget.frameSize().width(), self.msgLog.parentWidget.frameSize().height()) #.resize(self.frameSize().width(), self.frameSize().height()) except Exception as e: - # logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self) + #logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self) return - + def closeEvent(self, event): try: - # import threading + #import threading print("Close event") - # threads = threading.enumerate() - # print(f"Threads total: {str(len(threads))}: {str(threads)}") - - # print(self.instances) + #threads = threading.enumerate() + #print(f"Threads total: {str(len(threads))}: {str(threads)}") + #print(self.instances) + self.closingPlugin.emit() event.accept() - - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) - + + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + def clearDropdown(self): try: - # self.streamIdField.clear() + #self.streamIdField.clear() self.streamBranchDropdown.clear() self.commitDropdown.clear() - # self.layerSendModeDropdown.clear() - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + #self.layerSendModeDropdown.clear() + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) def reloadDialogUI(self, plugin): try: self.clearDropdown() - self.populateUI(plugin) + self.populateUI(plugin) self.enableElements(plugin) - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) - def run(self, plugin): + + + def run(self, plugin): try: print("dockwidget run") # Setup events on first load only! @@ -311,131 +240,102 @@ class SpeckleGISDialog(QMainWindow): # Connect streams section events self.completeStreamSection(plugin) # Populate the UI dropdowns - self.populateUI(plugin) + self.populateUI(plugin) print("dockwidget run end") - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + def setupOnFirstLoad(self, plugin): try: self.runButton.clicked.connect(plugin.onRunButtonClicked) - - self.streams_add_button.clicked.connect(plugin.onStreamAddButtonClicked) + + self.streams_add_button.clicked.connect( plugin.onStreamAddButtonClicked ) self.reloadButton.clicked.connect(lambda: self.refreshClicked(plugin)) self.closeButton.clicked.connect(lambda: self.closeClicked(plugin)) self.saveSurveyPoint.clicked.connect(plugin.set_survey_point) - self.saveLayerSelection.clicked.connect( - lambda: self.populateLayerDropdown(plugin) - ) + self.saveLayerSelection.clicked.connect(lambda: self.populateLayerDropdown(plugin)) self.sendModeButton.clicked.connect(lambda: self.setSendMode(plugin)) - self.layerSendModeDropdown.currentIndexChanged.connect( - lambda: self.layerSendModeChange(plugin) - ) + self.layerSendModeDropdown.currentIndexChanged.connect( lambda: self.layerSendModeChange(plugin) ) self.receiveModeButton.clicked.connect(lambda: self.setReceiveMode(plugin)) - self.streamBranchDropdown.currentIndexChanged.connect( - lambda: self.runBtnStatusChanged(plugin) - ) - self.commitDropdown.currentIndexChanged.connect( - lambda: self.runBtnStatusChanged(plugin) - ) + self.streamBranchDropdown.currentIndexChanged.connect( lambda: self.runBtnStatusChanged(plugin) ) + self.commitDropdown.currentIndexChanged.connect( lambda: self.runBtnStatusChanged(plugin) ) self.closingPlugin.connect(plugin.onClosePlugin) - return - - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + return + + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) def refreshClicked(self, plugin): try: try: - metrics.track( - "Connector Action", - plugin.active_account, - {"name": "Refresh", "connector_version": str(plugin.version)}, - ) + metrics.track("Connector Action", plugin.active_account, {"name": "Refresh", "connector_version": str(plugin.version)}) except Exception as e: - logToUser( - e, level=2, func=inspect.stack()[0][3], plugin=plugin.dockwidget - ) - + logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=plugin.dockwidget ) + plugin.reloadUI() except Exception as e: - logToUser(e, level=2, func=inspect.stack()[0][3], plugin=self) + logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self) return def closeClicked(self, plugin): try: try: - metrics.track( - "Connector Action", - plugin.active_account, - {"name": "Close", "connector_version": str(plugin.version)}, - ) + metrics.track("Connector Action", plugin.active_account, {"name": "Close", "connector_version": str(plugin.version)}) except Exception as e: - logToUser( - e, level=2, func=inspect.stack()[0][3], plugin=plugin.dockwidget - ) - + logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=plugin.dockwidget ) + plugin.onClosePlugin() except Exception as e: - logToUser(e, level=2, func=inspect.stack()[0][3], plugin=self) + logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self) return def setSendMode(self, plugin): try: - plugin.btnAction = 0 # send + plugin.btnAction = 0 # send color = f"color: rgb{str(SPECKLE_COLOR)};" - self.sendModeButton.setStyleSheet( - "border: 0px;" f"color: rgb{str(SPECKLE_COLOR)};" "padding: 10px;" - ) + self.sendModeButton.setStyleSheet("border: 0px;" + f"color: rgb{str(SPECKLE_COLOR)};" + "padding: 10px;") self.sendModeButton.setIcon(QIcon(ICON_SEND_BLUE)) self.sendModeButton.setFlat(False) self.receiveModeButton.setFlat(True) - self.receiveModeButton.setStyleSheet( - "QPushButton {border: 0px; color: black; padding: 10px; } QPushButton:hover { " - + f"background-color: rgb{str(COLOR_HIGHLIGHT)};" - + " };" - ) + self.receiveModeButton.setStyleSheet("QPushButton {border: 0px; color: black; padding: 10px; } QPushButton:hover { " + f"background-color: rgb{str(COLOR_HIGHLIGHT)};" + " };") self.receiveModeButton.setIcon(QIcon(ICON_RECEIVE_BLACK)) - # self.receiveModeButton.setFlat(True) + #self.receiveModeButton.setFlat(True) self.runButton.setProperty("text", " SEND") self.runButton.setIcon(QIcon(ICON_SEND)) - # enable sections only if in "saved streams" mode - if self.layerSendModeDropdown.currentIndex() == 1: - self.layersWidget.setEnabled(True) - if self.layerSendModeDropdown.currentIndex() == 1: - self.saveLayerSelection.setEnabled(True) + # enable sections only if in "saved streams" mode + if self.layerSendModeDropdown.currentIndex() == 1: self.layersWidget.setEnabled(True) + if self.layerSendModeDropdown.currentIndex() == 1: self.saveLayerSelection.setEnabled(True) self.commitDropdown.setEnabled(False) self.messageInput.setEnabled(True) self.layerSendModeDropdown.setEnabled(True) self.runBtnStatusChanged(plugin) return - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) - + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + def setReceiveMode(self, plugin): try: - plugin.btnAction = 1 # receive + plugin.btnAction = 1 # receive color = f"color: rgb{str(SPECKLE_COLOR)};" - self.receiveModeButton.setStyleSheet( - "border: 0px;" f"color: rgb{str(SPECKLE_COLOR)};" "padding: 10px;" - ) + self.receiveModeButton.setStyleSheet("border: 0px;" + f"color: rgb{str(SPECKLE_COLOR)};" + "padding: 10px;") self.sendModeButton.setIcon(QIcon(ICON_SEND_BLACK)) - self.sendModeButton.setStyleSheet( - "QPushButton {border: 0px; color: black; padding: 10px;} QPushButton:hover { " - + f"background-color: rgb{str(COLOR_HIGHLIGHT)};" - + " };" - ) + self.sendModeButton.setStyleSheet("QPushButton {border: 0px; color: black; padding: 10px;} QPushButton:hover { " + f"background-color: rgb{str(COLOR_HIGHLIGHT)};" + " };") self.receiveModeButton.setIcon(QIcon(ICON_RECEIVE_BLUE)) self.sendModeButton.setFlat(True) self.receiveModeButton.setFlat(False) - # self.sendModeButton.setFlat(True) + #self.sendModeButton.setFlat(True) self.runButton.setProperty("text", " RECEIVE") self.runButton.setIcon(QIcon(ICON_RECEIVE)) - # self.layerSendModeChange(plugin, 1) + #self.layerSendModeChange(plugin, 1) self.commitDropdown.setEnabled(True) self.layersWidget.setEnabled(False) self.messageInput.setEnabled(False) @@ -444,123 +344,105 @@ class SpeckleGISDialog(QMainWindow): self.runBtnStatusChanged(plugin) return - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) def completeStreamSection(self, plugin): - self.streams_remove_button.clicked.connect( - lambda: self.onStreamRemoveButtonClicked(plugin) - ) - self.streamList.currentIndexChanged.connect( - lambda: self.onActiveStreamChanged(plugin) - ) - self.streamBranchDropdown.currentIndexChanged.connect( - lambda: self.populateActiveCommitDropdown(plugin) - ) + self.streams_remove_button.clicked.connect( lambda: self.onStreamRemoveButtonClicked(plugin) ) + self.streamList.currentIndexChanged.connect( lambda: self.onActiveStreamChanged(plugin) ) + self.streamBranchDropdown.currentIndexChanged.connect( lambda: self.populateActiveCommitDropdown(plugin) ) return def populateUI(self, plugin): try: self.populateLayerSendModeDropdown() self.populateLayerDropdown(plugin, False) - # items = [self.layersWidget.item(x).text() for x in range(self.layersWidget.count())] + #items = [self.layersWidget.item(x).text() for x in range(self.layersWidget.count())] self.populateProjectStreams(plugin) self.populateSurveyPoint(plugin) self.runBtnStatusChanged(plugin) - self.runButton.setEnabled(False) - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) - + self.runButton.setEnabled(False) + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + def runBtnStatusChanged(self, plugin): try: commitStr = str(self.commitDropdown.currentText()) branchStr = str(self.streamBranchDropdown.currentText()) - if plugin.btnAction == 1: # on receive - if commitStr == "": + if plugin.btnAction == 1: # on receive + if commitStr == "": + self.runButton.setEnabled(False) + else: + self.runButton.setEnabled(True) + + if plugin.btnAction == 0: # on send + if branchStr == "": + self.runButton.setEnabled(False) + elif branchStr != "" and self.layerSendModeDropdown.currentIndex() == 1 and len(plugin.current_layers) == 0: # saved layers; but the list is empty self.runButton.setEnabled(False) else: self.runButton.setEnabled(True) + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + - if plugin.btnAction == 0: # on send - if branchStr == "": - self.runButton.setEnabled(False) - elif ( - branchStr != "" - and self.layerSendModeDropdown.currentIndex() == 1 - and len(plugin.current_layers) == 0 - ): # saved layers; but the list is empty - self.runButton.setEnabled(False) - else: - self.runButton.setEnabled(True) - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) - - def layerSendModeChange(self, plugin, runMode=None): + def layerSendModeChange(self, plugin, runMode = None): try: print("Send mode changed") - if ( - self.layerSendModeDropdown.currentIndex() == 0 or runMode == 1 - ): # by manual selection OR receive mode + if self.layerSendModeDropdown.currentIndex() == 0 or runMode == 1: # by manual selection OR receive mode self.current_layers = [] self.layersWidget.setEnabled(False) self.saveLayerSelection.setEnabled(False) - - elif self.layerSendModeDropdown.currentIndex() == 1 and ( - runMode == 0 or runMode is None - ): # by saved AND when Send mode + + elif self.layerSendModeDropdown.currentIndex() == 1 and (runMode == 0 or runMode is None): # by saved AND when Send mode self.layersWidget.setEnabled(True) self.saveLayerSelection.setEnabled(True) - + branchStr = str(self.streamBranchDropdown.currentText()) if self.layerSendModeDropdown.currentIndex() == 0: - if branchStr == "": - self.runButton.setEnabled(False) # by manual selection - else: - self.runButton.setEnabled(True) # by manual selection - elif self.layerSendModeDropdown.currentIndex() == 1: - self.runBtnStatusChanged(plugin) # by saved - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + if branchStr == "": self.runButton.setEnabled(False) # by manual selection + else: self.runButton.setEnabled(True) # by manual selection + elif self.layerSendModeDropdown.currentIndex() == 1: self.runBtnStatusChanged(plugin) # by saved + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + def populateLayerDropdown(self, plugin, bySelection: bool = True): print("populate layer dropdown / clicked save selection") - if not self: - return - try: + if not self: return + try: from speckle.ui.project_vars import set_project_layer_selection - except: - from speckle_toolbox.esri.toolboxes.speckle.ui.project_vars import ( - set_project_layer_selection, - ) - + except: + from speckle_toolbox.esri.toolboxes.speckle.ui.project_vars import set_project_layer_selection + try: self.layersWidget.clear() - nameDisplay = [] - project = plugin.gis_project + nameDisplay = [] + project = plugin.gis_project - if bySelection is False: # read from project data + if bySelection is False: # read from project data print("populate layers from saved data") - # print(project) - # print(project.activeMap) + #print(project) + #print(project.activeMap) all_layers_ids = [l.dataSource for l in getAllProjLayers(project)] for layer_tuple in plugin.current_layers: - if layer_tuple[1].dataSource in all_layers_ids: - listItem = self.fillLayerList(layer_tuple[1]) + if layer_tuple[1].dataSource in all_layers_ids: + listItem = self.fillLayerList(layer_tuple[1]) self.layersWidget.addItem(listItem) - else: # read selected layers + else: # read selected layers # Fetch selected layers print("populate layers from selection") - + plugin.current_layers = [] - layers = getLayers(plugin, bySelection) # List[QgsLayerTreeNode] + layers = getLayers(plugin, bySelection) # List[QgsLayerTreeNode] print(layers) for i, layer in enumerate(layers): - plugin.current_layers.append((layer.name, layer)) + plugin.current_layers.append((layer.name, layer)) listItem = self.fillLayerList(layer) self.layersWidget.addItem(listItem) print("populate layers from selection 2") @@ -569,51 +451,42 @@ class SpeckleGISDialog(QMainWindow): self.layersWidget.setIconSize(QSize(20, 20)) self.runBtnStatusChanged(plugin) - + return - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) def fillLayerList(self, layer): print("Fill layer list") - + try: ICON_XXL = os.path.dirname(os.path.abspath(__file__)) + "/size-xxl.png" - ICON_RASTER = ( - os.path.dirname(os.path.abspath(__file__)) + "/legend_raster.png" - ) - ICON_POLYGON = ( - os.path.dirname(os.path.abspath(__file__)) + "/legend_polygon.png" - ) + ICON_RASTER = os.path.dirname(os.path.abspath(__file__)) + "/legend_raster.png" + ICON_POLYGON = os.path.dirname(os.path.abspath(__file__)) + "/legend_polygon.png" ICON_LINE = os.path.dirname(os.path.abspath(__file__)) + "/legend_line.png" - ICON_POINT = ( - os.path.dirname(os.path.abspath(__file__)) + "/legend_point.png" - ) + ICON_POINT = os.path.dirname(os.path.abspath(__file__)) + "/legend_point.png" - listItem = QListWidgetItem(layer.name) - # print(listItem) + listItem = QListWidgetItem(layer.name) + #print(listItem) - if layer.isRasterLayer: # and layer.width()*layer.height() > 1000000: + if layer.isRasterLayer: # and layer.width()*layer.height() > 1000000: listItem.setIcon(QIcon(ICON_RASTER)) - - elif layer.isFeatureLayer: # and layer.featureCount() > 20000: + + elif layer.isFeatureLayer: # and layer.featureCount() > 20000: geomType = arcpy.Describe(layer.dataSource).shapeType - if geomType == "Polygon": - listItem.setIcon(QIcon(ICON_POLYGON)) - elif geomType == "Polyline": - listItem.setIcon(QIcon(ICON_LINE)) - elif geomType == "Point" or geomType == "Multipoint": - listItem.setIcon(QIcon(ICON_POINT)) - else: + if geomType == "Polygon": listItem.setIcon(QIcon(ICON_POLYGON)) + elif geomType == "Polyline": listItem.setIcon(QIcon(ICON_LINE)) + elif geomType == "Point" or geomType == "Multipoint": listItem.setIcon(QIcon(ICON_POINT)) + else: listItem.setIcon(QIcon(ICON_XXL)) - # else: + #else: # icon = QgsIconUtils().iconForLayer(layer) # listItem.setIcon(icon) - + return listItem - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) - + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + def populateSurveyPoint(self, plugin): if not self: return @@ -622,9 +495,9 @@ class SpeckleGISDialog(QMainWindow): self.surveyPointLat.setText(str(plugin.lat)) self.surveyPointLon.clear() self.surveyPointLon.setText(str(plugin.lon)) - - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) def enableElements(self, plugin): try: @@ -632,127 +505,101 @@ class SpeckleGISDialog(QMainWindow): self.receiveModeButton.setEnabled(plugin.is_setup) self.runButton.setEnabled(plugin.is_setup) self.streams_add_button.setEnabled(plugin.is_setup) - if plugin.is_setup is False: - self.streams_remove_button.setEnabled(plugin.is_setup) + if plugin.is_setup is False: self.streams_remove_button.setEnabled(plugin.is_setup) self.streamBranchDropdown.setEnabled(plugin.is_setup) self.layerSendModeDropdown.setEnabled(plugin.is_setup) self.commitDropdown.setEnabled(False) self.show() - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) def populateProjectStreams(self, plugin): - try: - from speckle.ui.project_vars import set_project_streams - except: - from speckle_toolbox.esri.toolboxes.speckle.ui.project_vars import ( - set_project_streams, - ) + try: + from speckle.ui.project_vars import set_project_streams + except: + from speckle_toolbox.esri.toolboxes.speckle.ui.project_vars import set_project_streams + try: - if not self: - return + if not self: return self.streamList.clear() - for stream in plugin.current_streams: + for stream in plugin.current_streams: self.streamList.addItems( - [ - f"Stream not accessible - {stream[0].stream_id}" - if stream[1] is None or isinstance(stream[1], SpeckleException) - else f"{stream[1].name}, {stream[1].id} | {stream[0].stream_url.split('/streams')[0]}" - ] - ) - if len(plugin.current_streams) == 0: - self.streamList.addItems([""]) - self.streamList.addItems(["Create New Project"]) + [f"Stream not accessible - {stream[0].stream_id}" if stream[1] is None or isinstance(stream[1], SpeckleException) else f"{stream[1].name}, {stream[1].id} | {stream[0].stream_url.split('/streams')[0]}"] + ) + if len(plugin.current_streams)==0: self.streamList.addItems([""]) + self.streamList.addItems(["Create New Stream"]) set_project_streams(plugin) index = self.streamList.currentIndex() - if index == -1: - self.streams_remove_button.setEnabled(False) - else: - self.streams_remove_button.setEnabled(True) + if index == -1: self.streams_remove_button.setEnabled(False) + else: self.streams_remove_button.setEnabled(True) - if len(plugin.current_streams) > 0: - plugin.active_stream = plugin.current_streams[0] - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + if len(plugin.current_streams)>0: plugin.active_stream = plugin.current_streams[0] + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + def onActiveStreamChanged(self, plugin): - if not self: - return + + if not self: return try: index = self.streamList.currentIndex() - if (len(plugin.current_streams) == 0 and index == 1) or ( - len(plugin.current_streams) > 0 and index == len(plugin.current_streams) - ): + if (len(plugin.current_streams) == 0 and index ==1) or (len(plugin.current_streams)>0 and index == len(plugin.current_streams)): self.populateProjectStreams(plugin) plugin.onStreamCreateClicked() return - if len(plugin.current_streams) == 0: - return - if index == -1: - return + if len(plugin.current_streams) == 0: return + if index == -1: return - try: - plugin.active_stream = plugin.current_streams[index] - except: - plugin.active_stream = None + try: plugin.active_stream = plugin.current_streams[index] + except: plugin.active_stream = None self.populateActiveStreamBranchDropdown(plugin) self.populateActiveCommitDropdown(plugin) - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) - + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + def populateLayerSendModeDropdown(self): - if not self: - return + if not self: return try: self.layerSendModeDropdown.clear() self.layerSendModeDropdown.addItems( ["Send visible layers", "Send saved layers"] ) - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) def populateActiveStreamBranchDropdown(self, plugin): - if not self: - return - if plugin.active_stream is None: - return + if not self: return + if plugin.active_stream is None: return try: self.streamBranchDropdown.clear() - if isinstance(plugin.active_stream[1], SpeckleException): - # logger.logToUser("Some streams cannot be accessed", Qgis.Warning) + if isinstance(plugin.active_stream[1], SpeckleException): + #logger.logToUser("Some streams cannot be accessed", Qgis.Warning) return - elif ( - plugin.active_stream is None - or plugin.active_stream[1] is None - or plugin.active_stream[1].branches is None - ): + elif plugin.active_stream is None or plugin.active_stream[1] is None or plugin.active_stream[1].branches is None: return self.streamBranchDropdown.addItems( [f"{branch.name}" for branch in plugin.active_stream[1].branches.items] ) - self.streamBranchDropdown.addItems(["Create New Model"]) - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + self.streamBranchDropdown.addItems(["Create New Branch"]) + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) def populateActiveCommitDropdown(self, plugin): - if not self: - return + if not self: return try: self.commitDropdown.clear() - if plugin.active_stream is None: - return + if plugin.active_stream is None: return branchName = self.streamBranchDropdown.currentText() - if branchName == "": - return - if branchName == "Create New Model": + if branchName == "": return + if branchName == "Create New Branch": self.streamBranchDropdown.setCurrentText("main") plugin.onBranchCreateClicked() return branch = None - if isinstance(plugin.active_stream[1], SpeckleException): - # logger.logToUser("Some streams cannot be accessed", Qgis.Warning) + if isinstance(plugin.active_stream[1], SpeckleException): + #logger.logToUser("Some streams cannot be accessed", Qgis.Warning) return elif plugin.active_stream[1]: for b in plugin.active_stream[1].branches.items: @@ -761,30 +608,25 @@ class SpeckleGISDialog(QMainWindow): break try: self.commitDropdown.addItems( - [ - f"{commit.id}" + " | " + f"{commit.message}" - for commit in branch.commits.items - ] + [f"{commit.id}"+ " | " + f"{commit.message}" for commit in branch.commits.items] ) - except: - pass - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + except: pass + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) def onStreamRemoveButtonClicked(self, plugin): try: - # from ui.project_vars import set_project_streams - if not self: - return + #from ui.project_vars import set_project_streams + if not self: return index = self.streamList.currentIndex() - if len(plugin.current_streams) > 0: - plugin.current_streams.pop(index) + if len(plugin.current_streams) > 0: plugin.current_streams.pop(index) plugin.active_stream = None self.streamBranchDropdown.clear() self.commitDropdown.clear() - # self.streamIdField.setText("") + #self.streamIdField.setText("") - # set_project_streams(plugin) + #set_project_streams(plugin) self.populateProjectStreams(plugin) - except Exception as e: - logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + except Exception as e: + logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + diff --git a/qt_ui/ui/add_stream_modal.ui b/qt_ui/ui/add_stream_modal.ui index 3159275..b50dc45 100644 --- a/qt_ui/ui/add_stream_modal.ui +++ b/qt_ui/ui/add_stream_modal.ui @@ -25,7 +25,7 @@ - Search Project by name or URL + Search Stream by name or URL diff --git a/qt_ui/ui/create_branch.ui b/qt_ui/ui/create_branch.ui index 5e5c0e9..992234f 100644 --- a/qt_ui/ui/create_branch.ui +++ b/qt_ui/ui/create_branch.ui @@ -26,7 +26,7 @@ - Model Name + Branch Name diff --git a/qt_ui/ui/create_stream.ui b/qt_ui/ui/create_stream.ui index 98c194c..b0ae678 100644 --- a/qt_ui/ui/create_stream.ui +++ b/qt_ui/ui/create_stream.ui @@ -34,7 +34,7 @@ - Project Name + Stream Name diff --git a/qt_ui/ui/dockwidget_main.ui b/qt_ui/ui/dockwidget_main.ui index ffc76df..871efc3 100644 --- a/qt_ui/ui/dockwidget_main.ui +++ b/qt_ui/ui/dockwidget_main.ui @@ -39,7 +39,7 @@ - Project + Stream @@ -77,7 +77,7 @@ - Model + Branch @@ -87,7 +87,7 @@ - Version + Commit diff --git a/qt_ui/ui/mainWindow_main.ui b/qt_ui/ui/mainWindow_main.ui index 6a75e36..e2308bb 100644 --- a/qt_ui/ui/mainWindow_main.ui +++ b/qt_ui/ui/mainWindow_main.ui @@ -43,7 +43,7 @@ - Project + Stream @@ -83,7 +83,7 @@ - Model + Branch @@ -93,7 +93,7 @@ - Version + Commit diff --git a/qt_ui/widget_add_stream.py b/qt_ui/widget_add_stream.py index 26be9b2..3ea1e6f 100644 --- a/qt_ui/widget_add_stream.py +++ b/qt_ui/widget_add_stream.py @@ -46,7 +46,7 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS): ) self.speckle_client = speckle_client self.setupUi(self) - self.setWindowTitle("Add Speckle Project") + self.setWindowTitle("Add Speckle stream") self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False) @@ -89,7 +89,7 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS): "Connector Action", self.dataStorage.active_account, { - "name": "Project Search By Name", + "name": "Stream Search By Name", "connector_version": str(self.dataStorage.plugin_version), }, ) @@ -149,7 +149,7 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS): "Connector Action", self.dataStorage.active_account, { - "name": "Project Search By URL", + "name": "Stream Search By URL", "connector_version": str(self.dataStorage.plugin_version), }, ) @@ -163,7 +163,7 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS): "Connector Action", self.dataStorage.active_account, { - "name": "Project Search By Name", + "name": "Stream Search By Name", "connector_version": str(self.dataStorage.plugin_version), }, ) @@ -191,7 +191,7 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS): self.search_results_list.clear() if isinstance(self.stream_results, SpeckleException): logToUser( - "Some Projects cannot be accessed", + "Some streams cannot be accessed", level=1, func=inspect.stack()[0][3], ) @@ -205,7 +205,7 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS): if isinstance(stream, SpeckleException): logToUser( - "Some Projects cannot be accessed", + "Some streams cannot be accessed", level=1, func=inspect.stack()[0][3], ) @@ -223,7 +223,7 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS): try: if isinstance(self.stream_results, SpeckleException): logToUser( - "Selected Project cannot be accessed: " + "Selected stream cannot be accessed: " + str(self.stream_results.message), level=1, func=inspect.stack()[0][3], @@ -261,7 +261,7 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS): self.close() except Exception as e: logToUser( - "Some Projects cannot be accessed: " + str(e), + "Some streams cannot be accessed: " + str(e), level=1, func=inspect.stack()[0][3], ) diff --git a/qt_ui/widget_create_branch.py b/qt_ui/widget_create_branch.py index a816dc3..df8697f 100644 --- a/qt_ui/widget_create_branch.py +++ b/qt_ui/widget_create_branch.py @@ -11,50 +11,39 @@ from specklepy.core.api.client import SpeckleClient # This loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer FORM_CLASS, _ = uic.loadUiType( - os.path.join(os.path.join(os.path.dirname(__file__), "ui", "create_branch.ui")) + os.path.join(os.path.join(os.path.dirname(__file__), "ui", "create_branch.ui") ) ) - class CreateBranchModalDialog(QtWidgets.QWidget, FORM_CLASS): + name_field: QtWidgets.QLineEdit = None description_field: QtWidgets.QLineEdit = None dialog_button_box: QtWidgets.QDialogButtonBox = None speckle_client: Union[SpeckleClient, None] = None - # Events - handleBranchCreate = pyqtSignal(str, str) + #Events + handleBranchCreate = pyqtSignal(str,str) def __init__(self, parent=None, speckle_client: SpeckleClient = None): - super(CreateBranchModalDialog, self).__init__( - parent, QtCore.Qt.WindowStaysOnTopHint - ) + super(CreateBranchModalDialog,self).__init__(parent,QtCore.Qt.WindowStaysOnTopHint) self.speckle_client = speckle_client self.setupUi(self) - self.setWindowTitle("Create New Model") - self.setMinimumWidth(300) + self.setWindowTitle("Create New Branch") self.name_field.textChanged.connect(self.nameCheck) - self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False) - self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).clicked.connect( - self.onOkClicked - ) - self.dialog_button_box.button( - QtWidgets.QDialogButtonBox.Cancel - ).clicked.connect(self.onCancelClicked) + self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False) + self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).clicked.connect(self.onOkClicked) + self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Cancel).clicked.connect(self.onCancelClicked) def nameCheck(self): try: if len(self.name_field.text()) >= 3: - self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled( - True - ) - else: - self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled( - False - ) + self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(True) + else: + self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False) return except Exception as e: - logToUser(e, level=2, func=inspect.stack()[0][3]) + logToUser(e, level = 2, func = inspect.stack()[0][3]) return def onOkClicked(self): @@ -64,17 +53,16 @@ class CreateBranchModalDialog(QtWidgets.QWidget, FORM_CLASS): self.handleBranchCreate.emit(name, description) self.close() except Exception as e: - logToUser(e, level=2, func=inspect.stack()[0][3]) + logToUser(e, level = 2, func = inspect.stack()[0][3]) return def onCancelClicked(self): try: self.close() except Exception as e: - logToUser(e, level=2, func=inspect.stack()[0][3]) + logToUser(e, level = 2, func = inspect.stack()[0][3]) return - - r""" + r''' def onAccountSelected(self, index): try: account = self.speckle_accounts[index] @@ -83,4 +71,4 @@ class CreateBranchModalDialog(QtWidgets.QWidget, FORM_CLASS): except Exception as e: logToUser(e, level = 2, func = inspect.stack()[0][3]) return - """ + ''' \ No newline at end of file diff --git a/qt_ui/widget_create_stream.py b/qt_ui/widget_create_stream.py index 0810e15..e925d38 100644 --- a/qt_ui/widget_create_stream.py +++ b/qt_ui/widget_create_stream.py @@ -37,7 +37,7 @@ class CreateStreamModalDialog(QtWidgets.QWidget, FORM_CLASS): ) self.speckle_client = speckle_client self.setupUi(self) - self.setWindowTitle("Create New Project") + self.setWindowTitle("Create New Stream") self.name_field.textChanged.connect(self.nameCheck) self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(True) From 97f2afedfb633a308d168a76e6ca10e3c121d4d9 Mon Sep 17 00:00:00 2001 From: KatKatKateryna Date: Tue, 6 Feb 2024 23:53:38 +0000 Subject: [PATCH 06/17] update main_window --- qt_ui/mainWindow.py | 1009 +++++++++++++++++--------- qt_ui/ui/mainWindow_main.ui | 105 +-- qt_ui/widget_dependencies_upgrade.py | 8 +- 3 files changed, 720 insertions(+), 402 deletions(-) diff --git a/qt_ui/mainWindow.py b/qt_ui/mainWindow.py index 195fb2b..110198e 100644 --- a/qt_ui/mainWindow.py +++ b/qt_ui/mainWindow.py @@ -1,21 +1,31 @@ - +from copy import copy import os import sys from typing import List -#from speckle.converter.layers import getLayers -#import ui.speckle_qgis_dialog +# from speckle.speckle.converter.layers import getLayers -from specklepy.logging.exceptions import (SpeckleException, GraphQLException) +# import ui.speckle_qgis_dialog + +from specklepy.logging.exceptions import SpeckleException, GraphQLException from PyQt5 import QtWidgets, uic from PyQt5 import QtGui -from PyQt5.QtGui import QIcon, QPixmap -from PyQt5.QtWidgets import (QMainWindow, QApplication, QWidget, - QListWidgetItem, QAction, QDockWidget, QVBoxLayout, - QHBoxLayout, QWidget, QLabel) +from PyQt5.QtGui import QIcon, QPixmap, QCursor +from PyQt5.QtWidgets import ( + QMainWindow, + QApplication, + QWidget, + QListWidgetItem, + QAction, + QDockWidget, + QVBoxLayout, + QHBoxLayout, + QWidget, + QLabel, +) from PyQt5 import QtCore -from PyQt5.QtCore import pyqtSignal, Qt, QSize, QEvent -from PyQt5 import QtGui, uic +from PyQt5.QtCore import pyqtSignal, Qt, QSize, QEvent +from PyQt5 import QtGui, uic from specklepy.api.credentials import get_local_accounts @@ -25,54 +35,53 @@ from specklepy.api.wrapper import StreamWrapper from specklepy.api.client import SpeckleClient from specklepy.logging import metrics -import arcpy +import arcpy -import inspect - -try: - #from speckle.speckle_arcgis_new import Speckle - from speckle.converter.layers import getLayers, getAllProjLayers - from speckle.ui.logger import logToUser - from speckle.ui.LogWidget import LogWidget -except: - #from speckle_toolbox.esri.toolboxes.speckle.speckle_arcgis_new import Speckle - from speckle_toolbox.esri.toolboxes.speckle.converter.layers import getLayers, getAllProjLayers - from speckle_toolbox.esri.toolboxes.speckle.ui.logger import logToUser - from speckle_toolbox.esri.toolboxes.speckle.ui.LogWidget import LogWidget - -#from ui.validation import tryGetStream - -# Create module-like object -#pytPath = os.path.dirname(os.path.abspath(__file__)).replace("/speckle/ui","/Speckle.pyt") -#print(pytPath) -#pytModule = importlib.machinery.SourceFileLoader("specklePyt", pytPath ) -#specklePyt = pytModule.load_module("specklePyt") +import inspect +# from speckle.speckle_arcgis_new import Speckle +from speckle.speckle.converter.layers import getLayers, getAllProjLayers +from speckle.speckle.utils.panel_logging import logToUser +from speckle.specklepy_qt_ui.qt_ui.LogWidget import LogWidget +from speckle.specklepy_qt_ui.qt_ui.utils.utils import constructCommitURL # This loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer -try: - from specklepy_qt_ui.qt_ui.global_resources import ( - COLOR_HIGHLIGHT, - SPECKLE_COLOR, SPECKLE_COLOR_LIGHT, - ICON_LOGO, ICON_SEARCH, ICON_DELETE, ICON_DELETE_BLUE, - ICON_SEND, ICON_RECEIVE, ICON_SEND_BLACK, ICON_RECEIVE_BLACK, - ICON_SEND_BLUE, ICON_RECEIVE_BLUE, - COLOR, BACKGR_COLOR, BACKGR_COLOR_LIGHT, - ) -except ModuleNotFoundError: - from speckle.specklepy_qt_ui.qt_ui.global_resources import ( - COLOR_HIGHLIGHT, - SPECKLE_COLOR, SPECKLE_COLOR_LIGHT, - ICON_LOGO, ICON_SEARCH, ICON_DELETE, ICON_DELETE_BLUE, - ICON_SEND, ICON_RECEIVE, ICON_SEND_BLACK, ICON_RECEIVE_BLACK, - ICON_SEND_BLUE, ICON_RECEIVE_BLUE, - COLOR, BACKGR_COLOR, BACKGR_COLOR_LIGHT, - ) -ui_class = uic.loadUiType( - os.path.join(os.path.dirname(__file__), os.path.join("ui", "mainWindow.ui") ) +from speckle.specklepy_qt_ui.qt_ui.utils.global_resources import ( + COLOR_HIGHLIGHT, + SPECKLE_COLOR, + SPECKLE_COLOR_LIGHT, + ICON_OPEN_WEB, + ICON_REPORT, + ICON_LOGO, + ICON_SEARCH, + ICON_DELETE, + ICON_DELETE_BLUE, + ICON_SEND, + ICON_RECEIVE, + ICON_SEND_BLACK, + ICON_RECEIVE_BLACK, + ICON_SEND_BLUE, + ICON_RECEIVE_BLUE, + COLOR, + BACKGR_COLOR, + BACKGR_COLOR_LIGHT, + ICON_XXL, + ICON_RASTER, + ICON_POLYGON, + ICON_LINE, + ICON_POINT, + ICON_GENERIC, ) +ui_file = uic.loadUiType( + os.path.join(os.path.dirname(__file__), os.path.join("ui", "mainWindow_main.ui")) +) +ui_file_path = os.path.join( + os.path.dirname(__file__), os.path.join("ui", "mainWindow_main.ui") +) + + class SpeckleGISDialog(QMainWindow): closingPlugin = pyqtSignal() @@ -88,161 +97,247 @@ class SpeckleGISDialog(QMainWindow): msgLog: LogWidget = None gridLayoutTitleBar = QtWidgets.QGridLayout - - def __init__(self): + + def __init__(self, parent=None): """Constructor.""" print("START MAIN WINDOW") - super(SpeckleGISDialog, self).__init__(None)#, QtCore.Qt.WindowStaysOnTopHint) - uic.loadUi(ui_class, self) # Load the .ui file - #self.installEventFilter(self) - self.show() - #self.instances.append(1) + super(SpeckleGISDialog, self).__init__( + parent + ) # , QtCore.Qt.WindowStaysOnTopHint) + uic.loadUi(ui_file_path, self) # Load the .ui file + # self.show() + self.runAllSetup() + + def runAllSetup(self): try: self.streamBranchDropdown.setMaxCount(100) self.commitDropdown.setMaxCount(100) self.streams_add_button.setFlat(True) self.streams_remove_button.setFlat(True) - self.saveSurveyPoint.setFlat(True) + self.commit_web_view.setFlat(True) + self.reportBtn.setFlat(True) + # self.saveSurveyPoint.setFlat(True) self.saveLayerSelection.setFlat(True) self.reloadButton.setFlat(True) self.closeButton.setFlat(True) + self.commit_web_view.setEnabled(False) - #backgr_color = f"background-color: rgb{str(SPECKLE_COLOR)};" - #backgr_color_light = f"background-color: rgb{str(SPECKLE_COLOR_LIGHT)};" + # https://stackoverflow.com/questions/67585501/pyqt-how-to-use-hover-in-button-stylesheet backgr_image_del = f"border-image: url({ICON_DELETE_BLUE});" self.streams_add_button.setIcon(QIcon(ICON_SEARCH)) self.streams_add_button.setMaximumWidth(25) - self.streams_add_button.setStyleSheet("QPushButton {padding:3px;padding-left:5px;border: none; text-align: left;} QPushButton:hover { " + f"background-color: rgb{str(COLOR_HIGHLIGHT)};" + f"{COLOR}" + " }") + self.streams_add_button.setStyleSheet( + "QPushButton {padding:3px;padding-left:5px;border: none; text-align: left;} QPushButton:hover { " + + f"background-color: rgba{str(COLOR_HIGHLIGHT)};" + + f"{COLOR}" + + " }" + ) + + self.commit_web_view.setIcon(QIcon(ICON_OPEN_WEB)) + self.commit_web_view.setMaximumWidth(25) + self.commit_web_view.setStyleSheet( + "QPushButton {padding:3px;padding-left:5px;border: none; text-align: left;} QPushButton:hover { " + + f"background-color: rgba{str(COLOR_HIGHLIGHT)};" + + f"{COLOR}" + + " }" + ) + + self.reportBtn.setIcon(QIcon(ICON_REPORT)) + self.reportBtn.setMaximumWidth(25) + self.reportBtn.setStyleSheet( + "QPushButton {padding:3px;padding-left:5px;border: none; text-align: left;} QPushButton:hover { " + + f"background-color: rgba{str(COLOR_HIGHLIGHT)};" + + f"{COLOR}" + + " }" + ) + self.streams_remove_button.setIcon(QIcon(ICON_DELETE)) self.streams_remove_button.setMaximumWidth(25) - self.streams_remove_button.setStyleSheet("QPushButton {padding:3px;padding-left:5px;border: none; text-align: left; image-position:right} QPushButton:hover { " + f"background-color: rgb{str(COLOR_HIGHLIGHT)};" + f"{COLOR}" + " }") #+ f"{backgr_image_del}" + self.streams_remove_button.setStyleSheet( + "QPushButton {padding:3px;padding-left:5px;border: none; text-align: left; image-position:right} QPushButton:hover { " + + f"background-color: rgba{str(COLOR_HIGHLIGHT)};" + + f"{COLOR}" + + " }" + ) # + f"{backgr_image_del}" - self.saveLayerSelection.setStyleSheet("QPushButton {text-align: right;} QPushButton:hover { " + f"{COLOR}" + " }") - self.saveSurveyPoint.setStyleSheet("QPushButton {text-align: right;} QPushButton:hover { " + f"{COLOR}" + " }") - self.reloadButton.setStyleSheet("QPushButton {text-align: left;} QPushButton:hover { " + f"{COLOR}" + " }") - self.closeButton.setStyleSheet("QPushButton {text-align: right;} QPushButton:hover { " + f"{COLOR}" + " }") + self.saveLayerSelection.setStyleSheet( + "QPushButton {text-align: right;} QPushButton:hover { " + + f"{COLOR}" + + " }" + ) + # self.saveSurveyPoint.setStyleSheet("QPushButton {text-align: right;} QPushButton:hover { " + f"{COLOR}" + " }") + self.reloadButton.setStyleSheet( + "QPushButton {text-align: left;} QPushButton:hover { " + + f"{COLOR}" + + " }" + ) + self.closeButton.setStyleSheet( + "QPushButton {text-align: right;} QPushButton:hover { " + + f"{COLOR}" + + " }" + ) - - self.sendModeButton.setStyleSheet("QPushButton {padding: 10px; border: 0px; " + f"color: rgb{str(SPECKLE_COLOR)};"+ "} QPushButton:hover { " + "}" ) + self.sendModeButton.setStyleSheet( + "QPushButton {padding: 10px; border: 0px; " + + f"color: rgba{str(SPECKLE_COLOR)};" + + "} QPushButton:hover { " + + "}" + ) self.sendModeButton.setIcon(QIcon(ICON_SEND_BLUE)) - + self.receiveModeButton.setFlat(True) - self.receiveModeButton.setStyleSheet("QPushButton {padding: 10px; border: 0px;}"+ "QPushButton:hover { " + f"background-color: rgb{str(COLOR_HIGHLIGHT)};" + "}" ) + self.receiveModeButton.setStyleSheet( + "QPushButton {padding: 10px; border: 0px;}" + + "QPushButton:hover { " + + f"background-color: rgba{str(COLOR_HIGHLIGHT)};" + + "}" + ) self.receiveModeButton.setIcon(QIcon(ICON_RECEIVE_BLACK)) - self.runButton.setStyleSheet("QPushButton {color: white;border: 0px;border-radius: 17px;padding: 10px;"+ f"{BACKGR_COLOR}" + "} QPushButton:hover { "+ f"{BACKGR_COLOR_LIGHT}" + " }") + self.runButton.setStyleSheet( + "QPushButton {color: white;border: 0px;border-radius: 17px;padding: 10px;" + + f"{BACKGR_COLOR}" + + "} QPushButton:hover { " + + f"{BACKGR_COLOR_LIGHT}" + + " }" + ) + # self.runButton.setGeometry(0, 0, 150, 30) self.runButton.setMaximumWidth(200) self.runButton.setIcon(QIcon(ICON_SEND)) - # add widgets that will only show on event trigger - logWidget = LogWidget(parent=self) - self.layout().addWidget(logWidget) - self.msgLog = logWidget + # insert checkbox + l = self.verticalLayout + + except Exception as e: + logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + + def runSetup(self, plugin): + # self.addDataStorage(plugin) + self.addLabel(plugin) + self.addProps(plugin) + # self.createMappingDialog() - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) - def addProps(self, plugin): - self.msgLog.active_account = plugin.active_account - self.msgLog.speckle_version = plugin.version + try: + # add widgets that will only show on event trigger + logWidget = LogWidget(parent=self) + logWidget.dataStorage = self.dataStorage - def addLabel(self, plugin): + self.layout().addWidget(logWidget) + self.msgLog = logWidget + self.msgLog.dockwidget = self + self.msgLog.active_account = plugin.dataStorage.active_account + self.msgLog.speckle_version = plugin.version + + self.crsSettings.setFlat(True) + self.crsSettings.setStyleSheet( + "QPushButton {text-align: right;} QPushButton:hover { " + + f"{COLOR}" + + " }" + ) + except Exception as e: + logToUser(e, level=2, plugin=self) + + def addLabel(self, plugin): try: exitIcon = QPixmap(ICON_LOGO) exitActIcon = QIcon(exitIcon) - # create a label + # create a label text_label = QtWidgets.QPushButton(" for ArcGIS") - text_label.setStyleSheet("border: 0px;" - "color: white;" - f"{BACKGR_COLOR}" - "top-margin: 40 px;" - "padding: 10px;" - "padding-left: 20px;" - "font-size: 15px;" - "height: 30px;" - "text-align: left;" - ) + text_label.setStyleSheet( + "border: 0px;" + "color: white;" + f"{BACKGR_COLOR}" + "top-margin: 40 px;" + "padding: 10px;" + "padding-left: 20px;" + "font-size: 15px;" + "height: 30px;" + "text-align: left;" + ) text_label.setIcon(exitActIcon) - text_label.setIconSize(QSize(300, 93)) - text_label.setMinimumSize(QSize(100, 40)) - text_label.setMaximumWidth(220) + text_label.setIconSize(QtCore.QSize(300, 93)) + text_label.setMinimumSize(QtCore.QSize(100, 40)) + text_label.setMaximumWidth(250) version = "" - try: - if isinstance(plugin.version, str): version = str(plugin.version) - except: pass + try: + if isinstance(plugin.version, str): + version = str(plugin.version) + except: + pass - version_label = QtWidgets.QPushButton(f"{version}") - version_label.setStyleSheet("border: 0px;" - "color: white;" - f"{BACKGR_COLOR}" - "padding-top: 15px;" - "padding-left: 0px;" - "margin-left: 0px;" - "font-size: 10px;" - "height: 30px;" - "text-align: left;" - ) + version_label = QtWidgets.QPushButton(version) + version_label.setStyleSheet( + "border: 0px;" + "color: white;" + f"{BACKGR_COLOR}" + "padding-top: 15px;" + "padding-left: 0px;" + "margin-left: 0px;" + "font-size: 10px;" + "height: 30px;" + "text-align: left;" + ) widget = QWidget() widget.setStyleSheet(f"{BACKGR_COLOR}") - connect_box = QHBoxLayout(widget) - connect_box.addWidget(text_label) #, alignment=Qt.AlignCenter) - connect_box.addWidget(version_label) - connect_box.setContentsMargins(0, 0, 0, 0) - self.gridLayoutTitleBar.addWidget(widget) # fro QMainWindow - #self.setTitleBarWidget(widget) # for QDockWidget + boxLayout = QHBoxLayout(widget) + boxLayout.addWidget(text_label) # , alignment=Qt.AlignCenter) + boxLayout.addWidget(version_label) + boxLayout.setContentsMargins(0, 0, 0, 0) + self.setWindowTitle("SpeckleArcGIS") + self.gridLayoutTitleBar.addWidget(widget) # fro QMainWindow + # self.setTitleBarWidget(widget) # for dockwidget + self.labelWidget = text_label + self.labelWidget.setCursor(QCursor(QtCore.Qt.PointingHandCursor)) + self.labelWidget.clicked.connect(self.onClickLogo) except Exception as e: logToUser(e) + def addDataStorage(self, plugin): + self.dataStorage = plugin.dataStorage + try: + self.dataStorage.project = plugin.project + except: + self.dataStorage.project = plugin.qproject + def resizeEvent(self, event): try: - #print("resize") + # print("resize") QtWidgets.QMainWindow.resizeEvent(self, event) - if self.msgLog.size().height() != 0: # visible - self.msgLog.setGeometry(0, 0, self.msgLog.parentWidget.frameSize().width(), self.msgLog.parentWidget.frameSize().height()) #.resize(self.frameSize().width(), self.frameSize().height()) + if self.msgLog.size().height() != 0: # visible + self.msgLog.setGeometry( + 0, + 0, + self.msgLog.parentWidget.frameSize().width(), + self.msgLog.parentWidget.frameSize().height(), + ) # .resize(self.frameSize().width(), self.frameSize().height()) except Exception as e: - #logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self) + # logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self) return - - def closeEvent(self, event): - try: - #import threading - print("Close event") - #threads = threading.enumerate() - #print(f"Threads total: {str(len(threads))}: {str(threads)}") - #print(self.instances) - - self.closingPlugin.emit() - event.accept() - - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) - def clearDropdown(self): try: - #self.streamIdField.clear() self.streamBranchDropdown.clear() self.commitDropdown.clear() - #self.layerSendModeDropdown.clear() - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + except Exception as e: + logToUser(e, level=2, func=inspect.stack()[0][3], plugin=self) + return def reloadDialogUI(self, plugin): try: self.clearDropdown() - self.populateUI(plugin) + self.populateUI(plugin) self.enableElements(plugin) - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + except Exception as e: + logToUser(e, level=2, func=inspect.stack()[0][3], plugin=self) + return - - - def run(self, plugin): + def run(self, plugin): try: print("dockwidget run") # Setup events on first load only! @@ -250,209 +345,336 @@ class SpeckleGISDialog(QMainWindow): # Connect streams section events self.completeStreamSection(plugin) # Populate the UI dropdowns - self.populateUI(plugin) + self.populateUI(plugin) print("dockwidget run end") - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + except Exception as e: + logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + def closeEvent(self, event): + try: + # import threading + print("Close event") + # threads = threading.enumerate() + # print(f"Threads total: {str(len(threads))}: {str(threads)}") + + # print(self.instances) + + self.closingPlugin.emit() + event.accept() + + except Exception as e: + logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + + def addMsg(self, obj: dict): + try: + self.msgLog.addButton(obj) + except Exception as e: + logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) def setupOnFirstLoad(self, plugin): try: - self.runButton.clicked.connect(plugin.onRunButtonClicked) - - self.streams_add_button.clicked.connect( plugin.onStreamAddButtonClicked ) + self.msgLog.sendMessage.connect(self.addMsg) + self.reportBtn.clicked.connect(self.msgLog.showReport) + + self.streams_add_button.clicked.connect(plugin.onStreamAddButtonClicked) + self.commit_web_view.clicked.connect( + lambda: plugin.openUrl( + constructCommitURL( + plugin.active_stream, + plugin.active_branch.id, + plugin.active_commit.id, + ) + ) + ) self.reloadButton.clicked.connect(lambda: self.refreshClicked(plugin)) self.closeButton.clicked.connect(lambda: self.closeClicked(plugin)) - self.saveSurveyPoint.clicked.connect(plugin.set_survey_point) - self.saveLayerSelection.clicked.connect(lambda: self.populateLayerDropdown(plugin)) + self.sendModeButton.clicked.connect(lambda: self.setSendMode(plugin)) - self.layerSendModeDropdown.currentIndexChanged.connect( lambda: self.layerSendModeChange(plugin) ) + self.layerSendModeDropdown.currentIndexChanged.connect( + lambda: self.layerSendModeChange(plugin) + ) self.receiveModeButton.clicked.connect(lambda: self.setReceiveMode(plugin)) - self.streamBranchDropdown.currentIndexChanged.connect( lambda: self.runBtnStatusChanged(plugin) ) - self.commitDropdown.currentIndexChanged.connect( lambda: self.runBtnStatusChanged(plugin) ) + # self.streamBranchDropdown.currentIndexChanged.connect( lambda: self.runBtnStatusChanged(plugin) ) + self.commitDropdown.currentIndexChanged.connect( + lambda: self.setActiveCommit(plugin) + ) + self.commitDropdown.currentIndexChanged.connect( + lambda: self.runBtnStatusChanged(plugin) + ) self.closingPlugin.connect(plugin.onClosePlugin) - return - - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + return + + except Exception as e: + logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + + def onClickLogo(self): + import webbrowser + + url = "https://speckle.systems/" + webbrowser.open(url, new=0, autoraise=True) + + try: + metrics.track( + "Connector Action", + self.dataStorage.active_account, + { + "name": "Logo Click", + "connector_version": str(self.dataStorage.plugin_version), + }, + ) + except Exception as e: + print(e) def refreshClicked(self, plugin): try: try: - metrics.track("Connector Action", plugin.active_account, {"name": "Refresh", "connector_version": str(plugin.version)}) + metrics.track( + "Connector Action", + plugin.dataStorage.active_account, + {"name": "Refresh", "connector_version": str(plugin.version)}, + ) except Exception as e: - logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=plugin.dockwidget ) - + logToUser( + e, level=2, func=inspect.stack()[0][3], plugin=plugin.dockwidget + ) + plugin.reloadUI() except Exception as e: - logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self) + logToUser(e, level=2, func=inspect.stack()[0][3], plugin=self) return def closeClicked(self, plugin): try: try: - metrics.track("Connector Action", plugin.active_account, {"name": "Close", "connector_version": str(plugin.version)}) + metrics.track( + "Connector Action", + plugin.dataStorage.active_account, + {"name": "Close", "connector_version": str(plugin.version)}, + ) except Exception as e: - logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=plugin.dockwidget ) - + logToUser( + e, level=2, func=inspect.stack()[0][3], plugin=plugin.dockwidget + ) + plugin.onClosePlugin() except Exception as e: - logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self) + logToUser(e, level=2, func=inspect.stack()[0][3], plugin=self) return def setSendMode(self, plugin): try: - plugin.btnAction = 0 # send - color = f"color: rgb{str(SPECKLE_COLOR)};" - self.sendModeButton.setStyleSheet("border: 0px;" - f"color: rgb{str(SPECKLE_COLOR)};" - "padding: 10px;") + plugin.btnAction = 0 # send + color = f"color: rgba{str(SPECKLE_COLOR)};" + self.sendModeButton.setStyleSheet( + "border: 0px;" f"color: rgba{str(SPECKLE_COLOR)};" "padding: 10px;" + ) self.sendModeButton.setIcon(QIcon(ICON_SEND_BLUE)) self.sendModeButton.setFlat(False) self.receiveModeButton.setFlat(True) - self.receiveModeButton.setStyleSheet("QPushButton {border: 0px; color: black; padding: 10px; } QPushButton:hover { " + f"background-color: rgb{str(COLOR_HIGHLIGHT)};" + " };") + self.receiveModeButton.setStyleSheet( + "QPushButton {border: 0px; color: black; padding: 10px; } QPushButton:hover { " + + f"background-color: rgba{str(COLOR_HIGHLIGHT)};" + + " };" + ) self.receiveModeButton.setIcon(QIcon(ICON_RECEIVE_BLACK)) - #self.receiveModeButton.setFlat(True) self.runButton.setProperty("text", " SEND") self.runButton.setIcon(QIcon(ICON_SEND)) - # enable sections only if in "saved streams" mode - if self.layerSendModeDropdown.currentIndex() == 1: self.layersWidget.setEnabled(True) - if self.layerSendModeDropdown.currentIndex() == 1: self.saveLayerSelection.setEnabled(True) + # enable sections only if in "saved streams" mode + if self.layerSendModeDropdown.currentIndex() == 1: + self.layersWidget.setEnabled(True) + self.saveLayerSelection.setEnabled(True) + self.commitLabel.setEnabled(False) self.commitDropdown.setEnabled(False) + self.messageLabel.setEnabled(True) self.messageInput.setEnabled(True) self.layerSendModeDropdown.setEnabled(True) + self.commit_web_view.setEnabled(False) self.runBtnStatusChanged(plugin) return - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) - + except Exception as e: + logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + def setReceiveMode(self, plugin): try: - plugin.btnAction = 1 # receive - color = f"color: rgb{str(SPECKLE_COLOR)};" - self.receiveModeButton.setStyleSheet("border: 0px;" - f"color: rgb{str(SPECKLE_COLOR)};" - "padding: 10px;") + plugin.btnAction = 1 # receive + color = f"color: rgba{str(SPECKLE_COLOR)};" + self.receiveModeButton.setStyleSheet( + "border: 0px;" f"color: rgba{str(SPECKLE_COLOR)};" "padding: 10px;" + ) self.sendModeButton.setIcon(QIcon(ICON_SEND_BLACK)) - self.sendModeButton.setStyleSheet("QPushButton {border: 0px; color: black; padding: 10px;} QPushButton:hover { " + f"background-color: rgb{str(COLOR_HIGHLIGHT)};" + " };") + self.sendModeButton.setStyleSheet( + "QPushButton {border: 0px; color: black; padding: 10px;} QPushButton:hover { " + + f"background-color: rgba{str(COLOR_HIGHLIGHT)};" + + " };" + ) self.receiveModeButton.setIcon(QIcon(ICON_RECEIVE_BLUE)) self.sendModeButton.setFlat(True) self.receiveModeButton.setFlat(False) - #self.sendModeButton.setFlat(True) self.runButton.setProperty("text", " RECEIVE") self.runButton.setIcon(QIcon(ICON_RECEIVE)) - #self.layerSendModeChange(plugin, 1) + self.commitLabel.setEnabled(True) self.commitDropdown.setEnabled(True) + self.layersWidget.setEnabled(False) + self.messageLabel.setEnabled(False) self.messageInput.setEnabled(False) self.saveLayerSelection.setEnabled(False) self.layerSendModeDropdown.setEnabled(False) + self.commit_web_view.setEnabled(True) self.runBtnStatusChanged(plugin) return - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + except Exception as e: + logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) def completeStreamSection(self, plugin): - self.streams_remove_button.clicked.connect( lambda: self.onStreamRemoveButtonClicked(plugin) ) - self.streamList.currentIndexChanged.connect( lambda: self.onActiveStreamChanged(plugin) ) - self.streamBranchDropdown.currentIndexChanged.connect( lambda: self.populateActiveCommitDropdown(plugin) ) return def populateUI(self, plugin): try: self.populateLayerSendModeDropdown() - self.populateLayerDropdown(plugin, False) - #items = [self.layersWidget.item(x).text() for x in range(self.layersWidget.count())] self.populateProjectStreams(plugin) - self.populateSurveyPoint(plugin) - self.runBtnStatusChanged(plugin) - self.runButton.setEnabled(False) - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) - + # self.runBtnStatusChanged(plugin) + # self.runButton.setEnabled(False) + except Exception as e: + logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + + def setActiveCommit(self, plugin): + try: + # print("__setActiveCommit") + # print(plugin.active_commit) + if plugin.active_branch is None: + if ( + plugin.active_stream is not None + and plugin.active_stream[1] is not None + ): + branchName = self.streamBranchDropdown.currentText() + for b in plugin.active_stream[1].branches.items: + if b.name == branchName: + branch = b + plugin.active_branch = b + break + + if plugin.active_branch is None: + return + # print(plugin.active_branch.name) + + current_id_text = str(self.commitDropdown.currentText()).split(" ")[0] + # print(current_id_text) + if current_id_text == "": # populate commits still in progress + return + + if len(plugin.active_branch.commits.items) > 0: + if "Latest" in current_id_text: + plugin.active_commit = plugin.active_branch.commits.items[0] + return + for c in plugin.active_branch.commits.items: + if c.id == current_id_text: + plugin.active_commit = c + return + # only if not found: + plugin.active_commit = plugin.active_branch.commits.items[0] + else: + plugin.active_commit = None + except Exception as e: + plugin.active_commit = None + print(e) + def runBtnStatusChanged(self, plugin): try: commitStr = str(self.commitDropdown.currentText()) branchStr = str(self.streamBranchDropdown.currentText()) - if plugin.btnAction == 1: # on receive - if commitStr == "": - self.runButton.setEnabled(False) - else: - self.runButton.setEnabled(True) - - if plugin.btnAction == 0: # on send - if branchStr == "": - self.runButton.setEnabled(False) - elif branchStr != "" and self.layerSendModeDropdown.currentIndex() == 1 and len(plugin.current_layers) == 0: # saved layers; but the list is empty + if commitStr == "": # populate commits still in progress + return + + if plugin.btnAction == 1: # on receive + if commitStr == "": self.runButton.setEnabled(False) else: self.runButton.setEnabled(True) - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) - - def layerSendModeChange(self, plugin, runMode = None): + if plugin.btnAction == 0: # on send + if branchStr == "": + self.runButton.setEnabled(False) + elif ( + self.layerSendModeDropdown.currentIndex() == 1 + and len(plugin.dataStorage.current_layers) == 0 + ): # saved layers; but the list is empty + self.runButton.setEnabled(False) + else: + self.runButton.setEnabled(True) + except Exception as e: + logToUser(e, level=2, func=inspect.stack()[0][3], plugin=self) + return + + def layerSendModeChange(self, plugin, runMode=None): try: print("Send mode changed") - if self.layerSendModeDropdown.currentIndex() == 0 or runMode == 1: # by manual selection OR receive mode - self.current_layers = [] + if ( + self.layerSendModeDropdown.currentIndex() == 0 or runMode == 1 + ): # by manual selection OR receive mode self.layersWidget.setEnabled(False) - self.saveLayerSelection.setEnabled(False) - - elif self.layerSendModeDropdown.currentIndex() == 1 and (runMode == 0 or runMode is None): # by saved AND when Send mode + + elif self.layerSendModeDropdown.currentIndex() == 1 and ( + runMode == 0 or runMode is None + ): # by saved AND when Send mode self.layersWidget.setEnabled(True) - self.saveLayerSelection.setEnabled(True) - + branchStr = str(self.streamBranchDropdown.currentText()) if self.layerSendModeDropdown.currentIndex() == 0: - if branchStr == "": self.runButton.setEnabled(False) # by manual selection - else: self.runButton.setEnabled(True) # by manual selection - elif self.layerSendModeDropdown.currentIndex() == 1: self.runBtnStatusChanged(plugin) # by saved - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + if branchStr == "": + self.runButton.setEnabled(False) # by manual selection + else: + self.runButton.setEnabled(True) # by manual selection + elif self.layerSendModeDropdown.currentIndex() == 1: + self.runBtnStatusChanged(plugin) # by saved + except Exception as e: + logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) - def populateLayerDropdown(self, plugin, bySelection: bool = True): + def populateSavedLayerDropdown(self, plugin, bySelection: bool = True): print("populate layer dropdown / clicked save selection") - if not self: return - try: - from speckle.ui.project_vars import set_project_layer_selection - except: - from speckle_toolbox.esri.toolboxes.speckle.speckle.ui.project_vars import set_project_layer_selection - + if not self: + return + try: + from speckle.speckle.utils.project_vars import set_project_layer_selection + except: + from speckle_toolbox.esri.toolboxes.speckle.speckle.utils.project_vars import ( + set_project_layer_selection, + ) + try: self.layersWidget.clear() - nameDisplay = [] - project = plugin.gis_project + nameDisplay = [] + project = plugin.project - if bySelection is False: # read from project data + if bySelection is False: # read from project data print("populate layers from saved data") - #print(project) - #print(project.activeMap) + # print(project) + # print(project.activeMap) all_layers_ids = [l.dataSource for l in getAllProjLayers(project)] for layer_tuple in plugin.current_layers: - if layer_tuple[1].dataSource in all_layers_ids: - listItem = self.fillLayerList(layer_tuple[1]) + if layer_tuple[1].dataSource in all_layers_ids: + listItem = self.fillLayerList(layer_tuple[1]) self.layersWidget.addItem(listItem) - else: # read selected layers + else: # read selected layers # Fetch selected layers print("populate layers from selection") - + plugin.current_layers = [] - layers = getLayers(plugin, bySelection) # List[QgsLayerTreeNode] + layers = getLayers(plugin, bySelection) # List[QgsLayerTreeNode] print(layers) for i, layer in enumerate(layers): - plugin.current_layers.append((layer.name, layer)) + plugin.current_layers.append((layer.name, layer)) listItem = self.fillLayerList(layer) self.layersWidget.addItem(listItem) print("populate layers from selection 2") @@ -461,53 +683,50 @@ class SpeckleGISDialog(QMainWindow): self.layersWidget.setIconSize(QSize(20, 20)) self.runBtnStatusChanged(plugin) - + return - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + except Exception as e: + logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) def fillLayerList(self, layer): print("Fill layer list") - + try: ICON_XXL = os.path.dirname(os.path.abspath(__file__)) + "/size-xxl.png" - ICON_RASTER = os.path.dirname(os.path.abspath(__file__)) + "/legend_raster.png" - ICON_POLYGON = os.path.dirname(os.path.abspath(__file__)) + "/legend_polygon.png" + ICON_RASTER = ( + os.path.dirname(os.path.abspath(__file__)) + "/legend_raster.png" + ) + ICON_POLYGON = ( + os.path.dirname(os.path.abspath(__file__)) + "/legend_polygon.png" + ) ICON_LINE = os.path.dirname(os.path.abspath(__file__)) + "/legend_line.png" - ICON_POINT = os.path.dirname(os.path.abspath(__file__)) + "/legend_point.png" + ICON_POINT = ( + os.path.dirname(os.path.abspath(__file__)) + "/legend_point.png" + ) - listItem = QListWidgetItem(layer.name) - #print(listItem) + listItem = QListWidgetItem(layer.name) + # print(listItem) - if layer.isRasterLayer: # and layer.width()*layer.height() > 1000000: + if layer.isRasterLayer: # and layer.width()*layer.height() > 1000000: listItem.setIcon(QIcon(ICON_RASTER)) - - elif layer.isFeatureLayer: # and layer.featureCount() > 20000: + + elif layer.isFeatureLayer: # and layer.featureCount() > 20000: geomType = arcpy.Describe(layer.dataSource).shapeType - if geomType == "Polygon": listItem.setIcon(QIcon(ICON_POLYGON)) - elif geomType == "Polyline": listItem.setIcon(QIcon(ICON_LINE)) - elif geomType == "Point" or geomType == "Multipoint": listItem.setIcon(QIcon(ICON_POINT)) - else: + if geomType == "Polygon": + listItem.setIcon(QIcon(ICON_POLYGON)) + elif geomType == "Polyline": + listItem.setIcon(QIcon(ICON_LINE)) + elif geomType == "Point" or geomType == "Multipoint": + listItem.setIcon(QIcon(ICON_POINT)) + else: listItem.setIcon(QIcon(ICON_XXL)) - #else: + # else: # icon = QgsIconUtils().iconForLayer(layer) # listItem.setIcon(icon) - + return listItem - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) - - def populateSurveyPoint(self, plugin): - if not self: - return - try: - self.surveyPointLat.clear() - self.surveyPointLat.setText(str(plugin.lat)) - self.surveyPointLon.clear() - self.surveyPointLon.setText(str(plugin.lon)) - - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + except Exception as e: + logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) def enableElements(self, plugin): try: @@ -515,128 +734,212 @@ class SpeckleGISDialog(QMainWindow): self.receiveModeButton.setEnabled(plugin.is_setup) self.runButton.setEnabled(plugin.is_setup) self.streams_add_button.setEnabled(plugin.is_setup) - if plugin.is_setup is False: self.streams_remove_button.setEnabled(plugin.is_setup) + self.commit_web_view.setEnabled(plugin.active_commit is not None) + self.reportBtn.setEnabled(False) + if plugin.is_setup is False: + self.streams_remove_button.setEnabled(plugin.is_setup) self.streamBranchDropdown.setEnabled(plugin.is_setup) self.layerSendModeDropdown.setEnabled(plugin.is_setup) + self.commitLabel.setEnabled(False) self.commitDropdown.setEnabled(False) self.show() - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + self.setSendMode(plugin) + except Exception as e: + logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) def populateProjectStreams(self, plugin): - - try: - from speckle.ui.project_vars import set_project_streams - except: - from speckle_toolbox.esri.toolboxes.speckle.speckle.ui.project_vars import set_project_streams - - try: - if not self: return - self.streamList.clear() - for stream in plugin.current_streams: - self.streamList.addItems( - [f"Stream not accessible - {stream[0].stream_id}" if stream[1] is None or isinstance(stream[1], SpeckleException) else f"{stream[1].name}, {stream[1].id} | {stream[0].stream_url.split('/streams')[0]}"] - ) - if len(plugin.current_streams)==0: self.streamList.addItems([""]) - self.streamList.addItems(["Create New Stream"]) - set_project_streams(plugin) - index = self.streamList.currentIndex() - if index == -1: self.streams_remove_button.setEnabled(False) - else: self.streams_remove_button.setEnabled(True) - - if len(plugin.current_streams)>0: plugin.active_stream = plugin.current_streams[0] - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) - + return def onActiveStreamChanged(self, plugin): - if not self: return + if not self: + return try: + if not self: + return index = self.streamList.currentIndex() - if (len(plugin.current_streams) == 0 and index ==1) or (len(plugin.current_streams)>0 and index == len(plugin.current_streams)): + if (len(plugin.current_streams) == 0 and index == 1) or ( + len(plugin.current_streams) > 0 and index == len(plugin.current_streams) + ): self.populateProjectStreams(plugin) plugin.onStreamCreateClicked() return - if len(plugin.current_streams) == 0: return - if index == -1: return + if len(plugin.current_streams) == 0: + return + if index == -1: + return - try: plugin.active_stream = plugin.current_streams[index] - except: plugin.active_stream = None + try: + plugin.active_stream = plugin.current_streams[index] + except: + plugin.active_stream = None self.populateActiveStreamBranchDropdown(plugin) self.populateActiveCommitDropdown(plugin) - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) - + except Exception as e: + logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) + def populateLayerSendModeDropdown(self): - if not self: return + if not self: + return try: self.layerSendModeDropdown.clear() self.layerSendModeDropdown.addItems( ["Send visible layers", "Send saved layers"] ) - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + except Exception as e: + logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) def populateActiveStreamBranchDropdown(self, plugin): - if not self: return - if plugin.active_stream is None: return + if not self: + return + if plugin.active_stream is None: + return try: - self.streamBranchDropdown.clear() - if isinstance(plugin.active_stream[1], SpeckleException): - #logger.logToUser("Some streams cannot be accessed", Qgis.Warning) + active_branch = copy(plugin.active_branch) + active_commit = copy(plugin.active_commit) + keep_branch = True # case of search by URL + if active_branch is None: # case of populating from Saved Streams + keep_branch = False + # print(active_branch) + + # print(1) + self.streamBranchDropdown.clear() # activates "populate commit" + # print(2) + if isinstance(plugin.active_stream[1], SpeckleException): + logToUser("Some streams cannot be accessed", level=1, plugin=self) return - elif plugin.active_stream is None or plugin.active_stream[1] is None or plugin.active_stream[1].branches is None: + elif ( + plugin.active_stream is None + or plugin.active_stream[1] is None + or plugin.active_stream[1].branches is None + ): return + # print(3) + # print(plugin.active_branch) + + # here the commit dropdown is triggered self.streamBranchDropdown.addItems( [f"{branch.name}" for branch in plugin.active_stream[1].branches.items] ) + # print(4) self.streamBranchDropdown.addItems(["Create New Branch"]) - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + # print(5) + if keep_branch is True: + plugin.active_branch = active_branch + if active_commit is not None: + plugin.active_commit = active_commit + elif len(plugin.active_branch.commits.items) > 0: + plugin.active_commit = plugin.active_branch.commits.items[0] + # else: + # plugin.active_commit = plugin.active_branch.commits.items[0] + # print(plugin.active_branch) + + # set index to current (if added from URL) + if ( + plugin.active_branch is not None + and plugin.active_branch in plugin.active_stream[1].branches.items + ): + # print("__________SET BRANCH TEXT") + # print(plugin.active_branch.name) + if keep_branch is True: + plugin.active_branch = active_branch + plugin.active_commit = active_commit + # print(plugin.active_branch.name) + self.streamBranchDropdown.setCurrentText( + plugin.active_branch.name + ) # activates "populate commit" + # print(6) + except Exception as e: + logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) def populateActiveCommitDropdown(self, plugin): - if not self: return + if not self: + return try: - self.commitDropdown.clear() - if plugin.active_stream is None: return + if plugin.active_stream is None: + print("Active stream is None") + return branchName = self.streamBranchDropdown.currentText() - if branchName == "": return - if branchName == "Create New Branch": + # print(f"CURRENT BRANCH TEXT: {branchName}") + if branchName == "": + return + if branchName == "Create New Branch": self.streamBranchDropdown.setCurrentText("main") plugin.onBranchCreateClicked() return branch = None - if isinstance(plugin.active_stream[1], SpeckleException): - #logger.logToUser("Some streams cannot be accessed", Qgis.Warning) + + # print("__clear commit dropdwn") + # print(plugin.active_commit) + self.commitDropdown.clear() + if isinstance(plugin.active_stream[1], SpeckleException): + logToUser("Some streams cannot be accessed", level=1, plugin=self) return elif plugin.active_stream[1]: for b in plugin.active_stream[1].branches.items: if b.name == branchName: branch = b + plugin.active_branch = b break - try: - self.commitDropdown.addItems( - [f"{commit.id}"+ " | " + f"{commit.message}" for commit in branch.commits.items] - ) - except: pass - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + + if len(branch.commits.items) > 0: + commits = [] + commits.append("") + # commits.append("Latest commit from this branch") + # self.commitDropdown.addItem("Latest commit from this branch") + + # commits = [] + for commit in branch.commits.items: + sourceApp = ( + str(commit.sourceApplication) + .replace(" ", "") + .split(".")[0] + .split("-")[0] + ) + commits.append( + f"{commit.id}" + + " | " + + f"{sourceApp}" + + " | " + + f"{commit.message}" + ) + self.commitDropdown.addItems(commits) + + # set index to current (if added from URL) + if ( + plugin.active_commit is not None + and plugin.active_commit in branch.commits.items + ): + # print("set index to current (if added from URL) ") + # print(plugin.active_commit) + self.commitDropdown.setCurrentText( + f"{plugin.active_commit.id}" + + " | " + + f"{plugin.active_commit.sourceApplication}" + + " | " + + f"{plugin.active_commit.message}" + ) + else: # overwrite active commit if plugin.active_commit is None: + # print("set index to 1st") + plugin.active_commit = branch.commits.items[0] + else: + plugin.active_commit = None + + self.commitDropdown.setItemText(0, "Latest commit from this branch") + # enable or disable web view button + # print("_________ENABLE OR DISABLE") + # print(plugin.active_commit) + # print(f"CURRENT TEXT2: {self.streamBranchDropdown.currentText()}") + if plugin.active_commit is not None and plugin.btnAction == 1: + self.commit_web_view.setEnabled(True) + else: + self.commit_web_view.setEnabled(False) + except Exception as e: + logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) def onStreamRemoveButtonClicked(self, plugin): - try: - #from ui.project_vars import set_project_streams - if not self: return - index = self.streamList.currentIndex() - if len(plugin.current_streams) > 0: plugin.current_streams.pop(index) - plugin.active_stream = None - self.streamBranchDropdown.clear() - self.commitDropdown.clear() - #self.streamIdField.setText("") - - #set_project_streams(plugin) - self.populateProjectStreams(plugin) - except Exception as e: - logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self) + return + def cancelOperations(self): + return diff --git a/qt_ui/ui/mainWindow_main.ui b/qt_ui/ui/mainWindow_main.ui index e2308bb..ded9114 100644 --- a/qt_ui/ui/mainWindow_main.ui +++ b/qt_ui/ui/mainWindow_main.ui @@ -1,7 +1,7 @@ - SpeckleQArcGISDialog - + SpeckleGISDialog + 0 @@ -98,9 +98,21 @@ - - + + + + + + + + + + + + + + @@ -126,6 +138,15 @@ + + + + + true + + + + @@ -178,21 +199,49 @@ true - Set visible layers as selection + Save current layer selection - + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + + + + + true + + + Set project center on Send/Receive + + + + + + + + Message - + Sent XXX objects from ArcGIS @@ -202,7 +251,7 @@ - + @@ -236,46 +285,8 @@ - - - - - Lat, Lon - - - - - - - - - 0.0 - - - - - - - 0.0 - - - - - - - - true - - - Set as a project center - - - - - - - + diff --git a/qt_ui/widget_dependencies_upgrade.py b/qt_ui/widget_dependencies_upgrade.py index 24911cb..11411e2 100644 --- a/qt_ui/widget_dependencies_upgrade.py +++ b/qt_ui/widget_dependencies_upgrade.py @@ -6,7 +6,7 @@ from specklepy.logging import metrics try: from specklepy_qt_ui.qt_ui.DataStorage import DataStorage -except ModuleNotFoundError: +except ModuleNotFoundError: from speckle.specklepy_qt_ui.qt_ui.DataStorage import DataStorage from PyQt5 import QtWidgets, uic, QtCore @@ -91,7 +91,11 @@ To do it manually, you can run 2 following commands from QGIS Plugins panel->Pyt def runSubprocess(self): import subprocess - from speckle.utils.utils import get_qgis_python_path as path + + try: + from speckle.utils.utils import get_qgis_python_path as path + except ModuleNotFoundError: + from speckle.speckle.utils.utils import get_qgis_python_path as path result1 = subprocess.run( [path(), "-m", "pip", "install", "requests==2.31.0"], From ef07bedc263b2a781cf76a6fba0cdc331d1695cd Mon Sep 17 00:00:00 2001 From: KatKatKateryna Date: Wed, 7 Feb 2024 00:26:07 +0000 Subject: [PATCH 07/17] fixes_main window --- qt_ui/mainWindow.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/qt_ui/mainWindow.py b/qt_ui/mainWindow.py index 110198e..4952c16 100644 --- a/qt_ui/mainWindow.py +++ b/qt_ui/mainWindow.py @@ -95,6 +95,16 @@ class SpeckleGISDialog(QMainWindow): saveLayerSelection: QtWidgets.QPushButton runButton: QtWidgets.QPushButton msgLog: LogWidget = None + custom_crs_modal = None + + signal_1 = pyqtSignal(object) + signal_2 = pyqtSignal(object) + signal_3 = pyqtSignal(object) + signal_4 = pyqtSignal(object) + signal_5 = pyqtSignal(object) + signal_6 = pyqtSignal(object) + signal_remove_btn_url = pyqtSignal(str) + signal_cancel_operation = pyqtSignal() gridLayoutTitleBar = QtWidgets.QGridLayout @@ -214,6 +224,7 @@ class SpeckleGISDialog(QMainWindow): def runSetup(self, plugin): # self.addDataStorage(plugin) + print("run setup") self.addLabel(plugin) self.addProps(plugin) # self.createMappingDialog() @@ -222,6 +233,7 @@ class SpeckleGISDialog(QMainWindow): try: # add widgets that will only show on event trigger logWidget = LogWidget(parent=self) + logWidget.layout.setContentsMargins(10, 60, 10, 40) logWidget.dataStorage = self.dataStorage self.layout().addWidget(logWidget) @@ -261,7 +273,7 @@ class SpeckleGISDialog(QMainWindow): text_label.setIcon(exitActIcon) text_label.setIconSize(QtCore.QSize(300, 93)) text_label.setMinimumSize(QtCore.QSize(100, 40)) - text_label.setMaximumWidth(250) + text_label.setMaximumWidth(300) version = "" try: From 04e4f43972f30d11d352098a0a23267e812a05bb Mon Sep 17 00:00:00 2001 From: KatKatKateryna Date: Wed, 7 Feb 2024 00:56:26 +0000 Subject: [PATCH 08/17] resize --- qt_ui/mainWindow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qt_ui/mainWindow.py b/qt_ui/mainWindow.py index 4952c16..0cd36f8 100644 --- a/qt_ui/mainWindow.py +++ b/qt_ui/mainWindow.py @@ -273,7 +273,7 @@ class SpeckleGISDialog(QMainWindow): text_label.setIcon(exitActIcon) text_label.setIconSize(QtCore.QSize(300, 93)) text_label.setMinimumSize(QtCore.QSize(100, 40)) - text_label.setMaximumWidth(300) + text_label.setMaximumWidth(250) version = "" try: From 5a85a97785af13e6039d2c308b060ff8e6866f1b Mon Sep 17 00:00:00 2001 From: KatKatKateryna Date: Wed, 7 Feb 2024 17:37:23 +0000 Subject: [PATCH 09/17] support other CRS data structures; saved layers in MainWindow --- qt_ui/LogWidget.py | 26 ++++++++++++--------- qt_ui/mainWindow.py | 45 +++++++++++++++---------------------- qt_ui/ui/mainWindow_main.ui | 2 +- qt_ui/widget_custom_crs.py | 15 ++++++++++--- 4 files changed, 47 insertions(+), 41 deletions(-) diff --git a/qt_ui/LogWidget.py b/qt_ui/LogWidget.py index 895fe9f..83f51a2 100644 --- a/qt_ui/LogWidget.py +++ b/qt_ui/LogWidget.py @@ -21,9 +21,11 @@ try: BACKGR_ERROR_COLOR, BACKGR_ERROR_COLOR_LIGHT, ) - from specklepy_qt_ui.qt_ui.widget_dependencies_upgrade import DependenciesUpgradeDialog + from specklepy_qt_ui.qt_ui.widget_dependencies_upgrade import ( + DependenciesUpgradeDialog, + ) from specklepy_qt_ui.qt_ui.widget_report import ReportDialog -except ModuleNotFoundError: +except ModuleNotFoundError: from speckle.specklepy_qt_ui.qt_ui.utils.global_resources import ( BACKGR_COLOR, BACKGR_COLOR_LIGHT, @@ -35,7 +37,9 @@ except ModuleNotFoundError: BACKGR_ERROR_COLOR, BACKGR_ERROR_COLOR_LIGHT, ) - from speckle.specklepy_qt_ui.qt_ui.widget_dependencies_upgrade import DependenciesUpgradeDialog + from speckle.specklepy_qt_ui.qt_ui.widget_dependencies_upgrade import ( + DependenciesUpgradeDialog, + ) from speckle.specklepy_qt_ui.qt_ui.widget_report import ReportDialog @@ -283,20 +287,22 @@ class LogWidget(QWidget): def getNextBtn(self): index = len(self.used_btns) # get the next "free" button - # print(index) - # print(self.btns) - if index >= len(self.btns): # remove first button print(self.layout.itemAt(0).widget()) self.layout.itemAt(0).widget().setParent(None) - - # self.used_btns.clear() self.createBtns() index = 0 - btn = self.btns[index] - # print(btn) + + return btn, index + + def getLastBtn(self): + index = len(self.used_btns) - 1 # get the next "free" button + btn = None + if index > 0: + btn = self.btns[index] + return btn, index def getBtnByKeyword(self, keyword: str): diff --git a/qt_ui/mainWindow.py b/qt_ui/mainWindow.py index 0cd36f8..afafcb1 100644 --- a/qt_ui/mainWindow.py +++ b/qt_ui/mainWindow.py @@ -380,6 +380,7 @@ class SpeckleGISDialog(QMainWindow): def addMsg(self, obj: dict): try: self.msgLog.addButton(obj) + # last_btn, index = self.msgLog.getLastBtn() except Exception as e: logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) @@ -665,15 +666,16 @@ class SpeckleGISDialog(QMainWindow): try: self.layersWidget.clear() nameDisplay = [] - project = plugin.project + project = plugin.dataStorage.project if bySelection is False: # read from project data print("populate layers from saved data") - # print(project) - # print(project.activeMap) - - all_layers_ids = [l.dataSource for l in getAllProjLayers(project)] - for layer_tuple in plugin.current_layers: + all_layers = getAllProjLayers(plugin) + if all_layers is None: + return + + all_layers_ids = [l.dataSource for l in all_layers] + for layer_tuple in plugin.dataStorage.saved_layers: if layer_tuple[1].dataSource in all_layers_ids: listItem = self.fillLayerList(layer_tuple[1]) self.layersWidget.addItem(listItem) @@ -682,16 +684,17 @@ class SpeckleGISDialog(QMainWindow): # Fetch selected layers print("populate layers from selection") - plugin.current_layers = [] - layers = getLayers(plugin, bySelection) # List[QgsLayerTreeNode] + plugin.dataStorage.current_layers = [] + layers = getLayers(plugin, bySelection=True) # List[QgsLayerTreeNode] print(layers) - for i, layer in enumerate(layers): - plugin.current_layers.append((layer.name, layer)) - listItem = self.fillLayerList(layer) - self.layersWidget.addItem(listItem) - print("populate layers from selection 2") - set_project_layer_selection(plugin) - print("populate layers from selection 3") + if layers is not None: + for i, layer in enumerate(layers): + plugin.dataStorage.current_layers.append((layer.name, layer)) + listItem = self.fillLayerList(layer) + self.layersWidget.addItem(listItem) + print("populate layers from selection 2") + set_project_layer_selection(plugin) + print("populate layers from selection 3") self.layersWidget.setIconSize(QSize(20, 20)) self.runBtnStatusChanged(plugin) @@ -704,18 +707,6 @@ class SpeckleGISDialog(QMainWindow): print("Fill layer list") try: - ICON_XXL = os.path.dirname(os.path.abspath(__file__)) + "/size-xxl.png" - ICON_RASTER = ( - os.path.dirname(os.path.abspath(__file__)) + "/legend_raster.png" - ) - ICON_POLYGON = ( - os.path.dirname(os.path.abspath(__file__)) + "/legend_polygon.png" - ) - ICON_LINE = os.path.dirname(os.path.abspath(__file__)) + "/legend_line.png" - ICON_POINT = ( - os.path.dirname(os.path.abspath(__file__)) + "/legend_point.png" - ) - listItem = QListWidgetItem(layer.name) # print(listItem) diff --git a/qt_ui/ui/mainWindow_main.ui b/qt_ui/ui/mainWindow_main.ui index ded9114..d4b38b2 100644 --- a/qt_ui/ui/mainWindow_main.ui +++ b/qt_ui/ui/mainWindow_main.ui @@ -199,7 +199,7 @@ true - Save current layer selection + Save visible layers as selection diff --git a/qt_ui/widget_custom_crs.py b/qt_ui/widget_custom_crs.py index 8f27434..99013ba 100644 --- a/qt_ui/widget_custom_crs.py +++ b/qt_ui/widget_custom_crs.py @@ -6,7 +6,7 @@ try: from specklepy_qt_ui.qt_ui.DataStorage import DataStorage from specklepy_qt_ui.qt_ui.utils.logger import logToUser from specklepy_qt_ui.qt_ui.utils.global_resources import COLOR -except ModuleNotFoundError: +except ModuleNotFoundError: from speckle.specklepy_qt_ui.qt_ui.DataStorage import DataStorage from speckle.specklepy_qt_ui.qt_ui.utils.logger import logToUser from speckle.specklepy_qt_ui.qt_ui.utils.global_resources import COLOR @@ -26,7 +26,7 @@ FORM_CLASS, _ = uic.loadUiType( class CustomCRSDialog(QtWidgets.QWidget, FORM_CLASS): name_field: QtWidgets.QLineEdit = None - description_field: QtWidgets.QLineEdit = None + description: QtWidgets.QLineEdit = None dialog_button_box: QtWidgets.QDialogButtonBox = None saveSurveyPoint: QtWidgets.QPushButton = None speckle_client: Union[SpeckleClient, None] = None @@ -84,6 +84,7 @@ class CustomCRSDialog(QtWidgets.QWidget, FORM_CLASS): self.offsetYDegreeSign.show() units = self.dataStorage.currentOriginalUnits + print(units) if units == "degrees": self.offsetXDegreeSign.setText("°") self.offsetYDegreeSign.setText("°") @@ -94,9 +95,17 @@ class CustomCRSDialog(QtWidgets.QWidget, FORM_CLASS): self.offsetXDegreeSign.hide() self.offsetYDegreeSign.hide() + try: + authid = self.dataStorage.currentCRS.authid() + except: + try: + authid = self.dataStorage.currentCRS.name + except: + authid = str(self.dataStorage.currentCRS) + text = f"Use this option when your project requires a use of a specific CRS. \ \n\nThis will only affect Speckle data properties, not your Project CRS.\ - \n\nHint: your current project CRS is '{self.dataStorage.currentCRS.authid()}' and using units '{self.dataStorage.currentOriginalUnits}'." + \n\nHint: your current project CRS is '{authid}' and using units '{self.dataStorage.currentOriginalUnits}'." if units == "degrees": text += "\nThis CRS is not recommended if data was sent or needs to be \ From 8d505db4fdfad8ed9dcddd2100636ab885708a10 Mon Sep 17 00:00:00 2001 From: KatKatKateryna Date: Wed, 7 Feb 2024 18:07:42 +0000 Subject: [PATCH 10/17] btn active --- qt_ui/mainWindow.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qt_ui/mainWindow.py b/qt_ui/mainWindow.py index afafcb1..8947298 100644 --- a/qt_ui/mainWindow.py +++ b/qt_ui/mainWindow.py @@ -617,7 +617,7 @@ class SpeckleGISDialog(QMainWindow): self.runButton.setEnabled(False) elif ( self.layerSendModeDropdown.currentIndex() == 1 - and len(plugin.dataStorage.current_layers) == 0 + and len(plugin.dataStorage.saved_layers) == 0 ): # saved layers; but the list is empty self.runButton.setEnabled(False) else: @@ -673,7 +673,7 @@ class SpeckleGISDialog(QMainWindow): all_layers = getAllProjLayers(plugin) if all_layers is None: return - + all_layers_ids = [l.dataSource for l in all_layers] for layer_tuple in plugin.dataStorage.saved_layers: if layer_tuple[1].dataSource in all_layers_ids: From 66f45e8147093911e97e74941c0da806e0eaee3a Mon Sep 17 00:00:00 2001 From: KatKatKateryna Date: Sat, 10 Feb 2024 19:00:28 +0000 Subject: [PATCH 11/17] arcgis support: crs format; pin window --- qt_ui/mainWindow.py | 35 ++++++++++++++++++++++++----- qt_ui/utils/assets/pin-outline.png | Bin 0 -> 3670 bytes qt_ui/utils/assets/pin.png | Bin 0 -> 3430 bytes qt_ui/utils/global_resources.py | 7 ++++++ qt_ui/widget_report.py | 23 ++++++++++++++----- 5 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 qt_ui/utils/assets/pin-outline.png create mode 100644 qt_ui/utils/assets/pin.png diff --git a/qt_ui/mainWindow.py b/qt_ui/mainWindow.py index 8947298..4ad8c55 100644 --- a/qt_ui/mainWindow.py +++ b/qt_ui/mainWindow.py @@ -57,6 +57,8 @@ from speckle.specklepy_qt_ui.qt_ui.utils.global_resources import ( ICON_SEARCH, ICON_DELETE, ICON_DELETE_BLUE, + ICON_PIN_ACTIVE, + ICON_PIN_DISABLED, ICON_SEND, ICON_RECEIVE, ICON_SEND_BLACK, @@ -84,6 +86,8 @@ ui_file_path = os.path.join( class SpeckleGISDialog(QMainWindow): + on_top: bool = True + pin_label: QtWidgets.QPushButton closingPlugin = pyqtSignal() streamList: QtWidgets.QComboBox sendModeButton: QtWidgets.QPushButton @@ -111,9 +115,7 @@ class SpeckleGISDialog(QMainWindow): def __init__(self, parent=None): """Constructor.""" print("START MAIN WINDOW") - super(SpeckleGISDialog, self).__init__( - parent - ) # , QtCore.Qt.WindowStaysOnTopHint) + super(SpeckleGISDialog, self).__init__(parent, QtCore.Qt.WindowStaysOnTopHint) uic.loadUi(ui_file_path, self) # Load the .ui file # self.show() self.runAllSetup() @@ -217,7 +219,7 @@ class SpeckleGISDialog(QMainWindow): self.runButton.setIcon(QIcon(ICON_SEND)) # insert checkbox - l = self.verticalLayout + # l = self.verticalLayout except Exception as e: logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) @@ -300,16 +302,39 @@ class SpeckleGISDialog(QMainWindow): boxLayout = QHBoxLayout(widget) boxLayout.addWidget(text_label) # , alignment=Qt.AlignCenter) boxLayout.addWidget(version_label) - boxLayout.setContentsMargins(0, 0, 0, 0) + boxLayout.setContentsMargins(0, 0, 30, 0) self.setWindowTitle("SpeckleArcGIS") self.gridLayoutTitleBar.addWidget(widget) # fro QMainWindow # self.setTitleBarWidget(widget) # for dockwidget self.labelWidget = text_label self.labelWidget.setCursor(QCursor(QtCore.Qt.PointingHandCursor)) self.labelWidget.clicked.connect(self.onClickLogo) + + pin_label = QtWidgets.QPushButton("") + pin_label.setIcon(QIcon(ICON_PIN_ACTIVE)) + pin_label.setMaximumWidth(25) + # pin_label.setFlat(True) + pin_label.setStyleSheet("QPushButton {border: none;}") + boxLayout.addWidget(pin_label) + pin_label.setCursor(QCursor(QtCore.Qt.PointingHandCursor)) + self.pin_label = pin_label + self.pin_label.clicked.connect(self.pinWindow) + except Exception as e: logToUser(e) + def pinWindow(self): + if self.on_top == True: + self.setWindowFlag(Qt.WindowType.WindowStaysOnTopHint, False) + self.pin_label.setIcon(QIcon(ICON_PIN_DISABLED)) + self.on_top = False + self.show() + else: + self.setWindowFlag(Qt.WindowType.WindowStaysOnTopHint, True) + self.pin_label.setIcon(QIcon(ICON_PIN_ACTIVE)) + self.on_top = True + self.show() + def addDataStorage(self, plugin): self.dataStorage = plugin.dataStorage try: diff --git a/qt_ui/utils/assets/pin-outline.png b/qt_ui/utils/assets/pin-outline.png new file mode 100644 index 0000000000000000000000000000000000000000..682d64a89d0194f5a0c10d86466663c564e87a45 GIT binary patch literal 3670 zcmeHIYgAKL7QP5bz%r<9p;eI>L5n;Bp&$kVVn7H8M1k_K6!N$UfxJvEB#?&J*ojW9 zLKLiu(qgbQh>;dz0ZT+%X$Li$mTC=%t%?SlK$Zl=2+R#wsiStS&X4&uYvtygv%kH+ zvmfW|vy+$*?dY(?0RR9;LQLcq0I-6mRsdo?JiNKI7Bx z8}O40xgdHA$mitqC}30p$c9$VWWtgcEP+L$gPTA$9m>I>Fo8k;fuu61&jA)HX1=8s zDQpJ3IcCl#Z4Ses)?(29b5QyVAxpBcM1~M#rbRMXAe#@f&iOHiroRlubC?`n5`45l z9BOvAr?tS&VDTI(34zM z!blPXYhnB_Z~ORReEj{A{e!Uqe(*12hIB>|z6w+lMEVm|%UMQ-!piaS*cb*M;_wP* zM6(Ax3EVcjnq4v(GbbB~oT)FCM6qNWhvM=$)O-p^o!J+rn??B?8YCd`zz8~AS{y2Z zMq|KrDMZ4ThCye8Jfy#`zn^d5vqpj((30pE1%-a%7us^ues?Ss{haHeGYWsWny}rh z48HPk??69o9`NF6`vKW-&*8z%h3YzCf*V*F11`mLB>;f8D)TGb;;bWHlc*x2jO&fS zf)9~b&Rc)9u%&s2uq?yfOBne5!T9aVdJOaJmE}#JAg>Ewf8>(mmA0U~4naPgab+VY zzVEQepCf$GIdSoH_l2b+Ydiy4)#DLZ%A3C!D>&@puGI81ae*JTTz)+zUW~;YBWi9K zMuLsUx<5~O)Tesq%Vld*Mw0EF8rw0^Co`vJ!lH^}Sy zWqXg?-c;`-u8?q!{_S89R%N{u9h%X=A zIJ$MstK+##LTlIehrXSOH`QsstQGGbj!56DXfN-_-P`xT6qiMJqz~HVH#~-4343l# zIv)TQylVNZfP*z}0DxULAu=LaSflU1xF<8;wcDuPldyG3rE_fD@rq=d+nbLtt72Tf zy6aTo=ymH~C1qcG?PtHTxFB@ZzH;KxD+>|ZZLA&0<>c>UmVADABs=Lk#?6_2aQ&9+ zA$&D%K%~Aq8QVTIS~J|nH;68^jbBnMo_Vfb_SbM(ZkHCREbJR3=3VR!@LrN|+y3Vp zD|L6JC#qUnh0AIVd3^1wtNiJDiCmIyW0So>S%T6L2qAKMSK;Ams3cFnb11^OE2`Jp zyCTk=rC2`Cr6pZ+s!@{mnoTyZQJV0MQ`t_Ye0lcfg#hvmE1-PQUmHGtH|f+ho56ux z6YyaFRN%Oybf17DHRuX}}Ot)j9uIOK<59%k zHAclmNL)tcs0*Q_=E_vGBr4)+*VxbbR_L(qtlG-aO4%Wg$yiP25yA8c*<_x%_Ns>> zta8+cpsI!hYHe|pM(ys}+jf=KB2#-bwfq!jC>%KY?dxZ-@U&`FH_>^1tVeo-IBg|7 z+N!KGeAd_Zg?N+3F5udzo%BY=R`c|=SCno$uL4ENg7Qmb@R`(9*J3RVRaNUUhHM)*jQKf!T zdSpKYn!H!G;5B=dCCRw&K3-UQjy)`sEv1XZ(GTWVhB zIPYYFa+oMktLQf~-CTtwOEnoGp1NUa=uNh2wQixpKKmGRAlF>7{Kf;N;2pPV8I#j2 zK6!H+_E*EuEBE&6wJgPJH9tz2!zaR~OkapU(04m5R|uGH4PnK*cIZP`Za%>WrkSEt zlaaGek5js#g?%^tQ|I0LyFP@e%Hl3o<%pt9#>Affsxy4sJp(FMR+jj2TDHM3vB#z6 zw1k!Qp7^o2S=^k58aXlX4KnEL*m&lH+a>46?uDgMMW5xd?WP6|N3WluG6z7j%69er z+S6yoAG`c&2rP?Uu>7j3U1W9+4i}&wx_Sl^qPM9_RwxB+B042!`lLA1WTfnFGl-|c zuXP@O^iV<;9qPF0sIMJ7w;|X?kT~_v@d>9QtAV?<)%t#At&i~Z07hYdv!^d}EcNm2 zaHjd-&@Ba7r08(LNyd(`s#$w~l-o7X%&Q0zcQKq!bX?JTP2*5;*&vFr)$YirXXUbh zrq(3oso3^J4PM&0Ze$rJu3gbOrYIW^Nkx=S%4L(b9mVOII9v1KwOV)Aie#hqeFXt~ zIm3KBdw{QuJ48j94!nvhl1aF8uZj2`Ww z|KTB7ST7TKWa91=RD0ljbl?2=>P4qU_`H(x^g@$gRh^41u4hbozSVu)o)F@JdrRk% z#J=xO2v0c${Z#FFDiH0hgYxu{3E5kx050V=9o{Sm@mtl+R9!t+5SH82B;Ok1KV=^f zMCthL+f-BYuSS}-X7$Q%*E;_n-mL?p3Fkq-?@z!1Gl+1hCi#aPVP0IoRVf~JVs!Vr_gbfbK@12OKT!g55(7hci92|- zD6FT46+=o#1%x2N#Ylw$5lojdu|{1w`fS)HVKGJuvV)1;zz)WELlO`}B~pnlSPv@< zLlPBDU+=T}jWN1nVq+0ROec}zdh;+3XL~g~E5jfDzwaXd>Pu^_?^Q?f?!+ z5QC)kAPmJxc%bhtP=tJD%!DB?be51C1Fi){F-R;EOQE{{2?^szO#uv2f;dAhLPdPk zIc3sj!z9MUx=~2vNho|;$dGJ$FkcD^Hu&&`pa@1)C(kj7hQAN>h6Ip=gI;ZriJkEF zwia|F#)hI$Xu0tqlMu_>J6Hlm^93jdulM^B!}9fZCDUA8ohif#8MJV8)RrHe;KM~w z7R80K!r6u5Om+z&yVEJI^cC(KjiN>(+6qxzg!=)i;VxqsD4ETs`}1K0k|Y?nCN4M! z+&QtDSPJ;Yn~lL3>r3bI4B2L4#S$ngjt52={i1RcC=5j-@mvY$6@!+RiS>$(=A(5< zz@SaTj}d_q44FuFAyVHpijM^iiJmSf(wlRU44wA-!5E||M`sube`rnAZekB@d31J= z-VP6R@pk-xB6Q|R(Ba}Vrq!SWY&Rb*#gq~Nz~_hJ4pjuq@R}>X?&GUlr30-0hPhWW zWB*@%DBC05y%9%{QtR{B-`F=in`L=9z2p?;p>*D>`LToz*6D>7kta6ZTMf#7v$7>a z(t#>{)3w^hh0m8Qr3!O~z39BZKGtPHqLdq9;ne}u{Xg8D7s{5=Dc=R(fAs9RyY9Q% z??Yd;U;pZ&y<6z>5KEilO0H#)MNrAc%3EzWo3>LbzerxzF07lG0XZ+ z!ZlK}YqM`w-6kCvjimBVXZ-r>%YS{J{|a`}F21B|6!=75l`dSut+9N}Q>TP|JX^bXdtohjx^Cs@cv~1}p~XL&cX$Wu zqS{Cf!4)$Lj$a;4iES(J3m&qVe=IU(2$&V&tNvp9n5-y5ezBqO)3)6MvtwmJJ9D9o_)SDy@UDm@W5a|M9l1%F7vpe5%eu#DfSPC z0l<2W;cEiq<=X+ktQMA!SBNyfw?kF@k2sTBoyyJ6dEd{4W(^lU!v0j`L%8qjD_mCO zdgyg*^Yyz`p{c8EA7hu5UnnfZp7Wi%d(q+3ibHEZ!R;H(LXawFWtkI2*?z2IxjIRy z9ZV1JSShy|KB<+d2HJ1IsM{%@Z5d^W)x)m1AM*&2wn@EItr{JzXz~y zuj`7QV=u#p**utMDi-JBXqQp>7cYjK%sVY*;$gggjpE9ZgjT*s-&tJC)=aOA1Nejy zUk}%8#vzRxD<$#Xr@iiOGnv+~QrlunzM@@XdxrWFR0QGm0f928 z=9s1e7nDgJ+eMc5QqBX)n|4o}SYtaYRmb2lY`x4j?bcANLM`kY9e>bGetnag=6zX~ zUYYPT<8e-p{KIj)H^Bc3fSB3vmCXYV9{q7M6?3np45l$(TYL~y40;h>g=X1F%KX& zoc@;~deD!rIB7KPY*tmSW`FS&@w$!z&9}Tvd6-Q&3+NgNRcs3D+qO3XUm?rXz35(4 z98zG~NFxR4TTZoaDzE5}mJH#?%W$d^#~YMfe1g8)mT<`&!wM{QtX|)oD)9MW*H6J{x3gbodO^K4$>N}H zm|RouEww*zidSqd_L33mg)B!_|IguLYC^VsQ2*d9$C*>!Dd Date: Sat, 10 Feb 2024 23:17:35 +0000 Subject: [PATCH 12/17] fix arcgis report on receive --- qt_ui/utils/utils.py | 2 ++ qt_ui/widget_report.py | 30 ++++++++++++++++-------------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/qt_ui/utils/utils.py b/qt_ui/utils/utils.py index 8cc73b6..41be9b1 100644 --- a/qt_ui/utils/utils.py +++ b/qt_ui/utils/utils.py @@ -2,6 +2,8 @@ from textwrap import wrap from typing import Union import requests +SYMBOL = "_x_x_" + def splitTextIntoLines(text: str = "", number: int = 40) -> str: msg = "" diff --git a/qt_ui/widget_report.py b/qt_ui/widget_report.py index 47aa11a..a5d0a59 100644 --- a/qt_ui/widget_report.py +++ b/qt_ui/widget_report.py @@ -5,9 +5,11 @@ from typing import List, Tuple, Union try: from specklepy_qt_ui.qt_ui.DataStorage import DataStorage from specklepy_qt_ui.qt_ui.utils.global_resources import COLOR + from specklepy_qt_ui.qt_ui.utils.utils import SYMBOL except ModuleNotFoundError: from speckle.specklepy_qt_ui.qt_ui.DataStorage import DataStorage from speckle.specklepy_qt_ui.qt_ui.utils.global_resources import COLOR + from speckle.specklepy_qt_ui.qt_ui.utils.utils import SYMBOL # from specklepy_qt_ui.qt_ui.utils.logger import logToUser @@ -51,7 +53,7 @@ class ReportDialog(QtWidgets.QWidget, FORM_CLASS): try: if self.dataStorage is None: return - reportList = self.dataStorage.latestActionReport + reportList: List[dict] = self.dataStorage.latestActionReport if reportList is None: return @@ -67,11 +69,13 @@ class ReportDialog(QtWidgets.QWidget, FORM_CLASS): for item in reportList: line = "✅ " try: # if sending - line += f'{item["feature_id"]}: {item["obj_type"]}' + some_id = item["feature_id"].replace(SYMBOL, "\\") + line += f'{some_id}: {item["obj_type"]}' operation = f"Sent at {self.dataStorage.latestActionTime}" except: # if receiving sending = False - line += f'{item["speckle_id"]}: {item["obj_type"]}' + some_id = item[list(item.keys())[0]].replace(SYMBOL, "\\") + line += f'{some_id}: {item["obj_type"]}' # f'{item["speckle_id"]}: {item["obj_type"]}' operation = f"Received at {self.dataStorage.latestActionTime}" # edit based on the type @@ -123,14 +127,12 @@ class ReportDialog(QtWidgets.QWidget, FORM_CLASS): # add info about the offsets try: - text += "Project CRS: " + self.dataStorage.project.crs().authid() + "\n" + crs = self.dataStorage.project.crs() + text += "Project CRS: " + crs.authid() + "\n" except AttributeError: + crs = self.dataStorage.project.activeMap.spatialReference CRS_KEYWORD = "Spatial Reference" - text += ( - f"Project {CRS_KEYWORD}: " - + self.dataStorage.project.activeMap.spatialReference.name - + "\n" - ) + text += f"Project {CRS_KEYWORD}: " + crs.name + "\n" units = self.dataStorage.latestActionUnits text += ( f"Project {CRS_KEYWORD} units: " @@ -138,11 +140,11 @@ class ReportDialog(QtWidgets.QWidget, FORM_CLASS): + f"{' (not supported, treated as Meters)' if 'degrees' in units else ''}" + "\n" ) - text += ( - f"Project {CRS_KEYWORD} WKT: \n" - + self.dataStorage.project.crs().toWkt() - + "\n\n" - ) + try: + text += f"Project {CRS_KEYWORD} WKT: \n" + crs.toWkt() + "\n\n" + except: + text += f"Project {CRS_KEYWORD} WKT: \n" + crs.exportToString() + "\n\n" + text += ( f"{CRS_KEYWORD} offsets: x={self.dataStorage.crs_offset_x}, y={self.dataStorage.crs_offset_y}" + "\n" From 30c3514bded8dbb42fa8a2c52d1a4368e1db777d Mon Sep 17 00:00:00 2001 From: KatKatKateryna Date: Sun, 11 Feb 2024 18:15:45 +0000 Subject: [PATCH 13/17] get layers with structure --- qt_ui/mainWindow.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/qt_ui/mainWindow.py b/qt_ui/mainWindow.py index 4ad8c55..bfcff1b 100644 --- a/qt_ui/mainWindow.py +++ b/qt_ui/mainWindow.py @@ -40,7 +40,7 @@ import arcpy import inspect # from speckle.speckle_arcgis_new import Speckle -from speckle.speckle.converter.layers import getLayers, getAllProjLayers +from speckle.speckle.converter.layers import getLayersWithStructure, getAllProjLayers from speckle.speckle.utils.panel_logging import logToUser from speckle.specklepy_qt_ui.qt_ui.LogWidget import LogWidget from speckle.specklepy_qt_ui.qt_ui.utils.utils import constructCommitURL @@ -710,16 +710,18 @@ class SpeckleGISDialog(QMainWindow): print("populate layers from selection") plugin.dataStorage.current_layers = [] - layers = getLayers(plugin, bySelection=True) # List[QgsLayerTreeNode] - print(layers) + layers, structure = getLayersWithStructure( + plugin, bySelection=True + ) # List[QgsLayerTreeNode] + #print(layers) if layers is not None: for i, layer in enumerate(layers): plugin.dataStorage.current_layers.append((layer.name, layer)) listItem = self.fillLayerList(layer) self.layersWidget.addItem(listItem) - print("populate layers from selection 2") + #print("populate layers from selection 2") set_project_layer_selection(plugin) - print("populate layers from selection 3") + #print("populate layers from selection 3") self.layersWidget.setIconSize(QSize(20, 20)) self.runBtnStatusChanged(plugin) @@ -729,7 +731,7 @@ class SpeckleGISDialog(QMainWindow): logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) def fillLayerList(self, layer): - print("Fill layer list") + #print("Fill layer list") try: listItem = QListWidgetItem(layer.name) From 0b099810e50a628e65bd2f362f2b3b22c543d22e Mon Sep 17 00:00:00 2001 From: KatKatKateryna Date: Mon, 12 Feb 2024 00:03:43 +0000 Subject: [PATCH 14/17] don't pin window on launch --- qt_ui/mainWindow.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/qt_ui/mainWindow.py b/qt_ui/mainWindow.py index bfcff1b..72c6f8b 100644 --- a/qt_ui/mainWindow.py +++ b/qt_ui/mainWindow.py @@ -86,7 +86,7 @@ ui_file_path = os.path.join( class SpeckleGISDialog(QMainWindow): - on_top: bool = True + on_top: bool = False pin_label: QtWidgets.QPushButton closingPlugin = pyqtSignal() streamList: QtWidgets.QComboBox @@ -115,7 +115,9 @@ class SpeckleGISDialog(QMainWindow): def __init__(self, parent=None): """Constructor.""" print("START MAIN WINDOW") - super(SpeckleGISDialog, self).__init__(parent, QtCore.Qt.WindowStaysOnTopHint) + super(SpeckleGISDialog, self).__init__( + parent + ) # , QtCore.Qt.WindowStaysOnTopHint) uic.loadUi(ui_file_path, self) # Load the .ui file # self.show() self.runAllSetup() @@ -311,7 +313,7 @@ class SpeckleGISDialog(QMainWindow): self.labelWidget.clicked.connect(self.onClickLogo) pin_label = QtWidgets.QPushButton("") - pin_label.setIcon(QIcon(ICON_PIN_ACTIVE)) + pin_label.setIcon(QIcon(ICON_PIN_DISABLED)) pin_label.setMaximumWidth(25) # pin_label.setFlat(True) pin_label.setStyleSheet("QPushButton {border: none;}") @@ -713,15 +715,15 @@ class SpeckleGISDialog(QMainWindow): layers, structure = getLayersWithStructure( plugin, bySelection=True ) # List[QgsLayerTreeNode] - #print(layers) + # print(layers) if layers is not None: for i, layer in enumerate(layers): plugin.dataStorage.current_layers.append((layer.name, layer)) listItem = self.fillLayerList(layer) self.layersWidget.addItem(listItem) - #print("populate layers from selection 2") + # print("populate layers from selection 2") set_project_layer_selection(plugin) - #print("populate layers from selection 3") + # print("populate layers from selection 3") self.layersWidget.setIconSize(QSize(20, 20)) self.runBtnStatusChanged(plugin) @@ -731,7 +733,7 @@ class SpeckleGISDialog(QMainWindow): logToUser(str(e), level=2, func=inspect.stack()[0][3], plugin=self) def fillLayerList(self, layer): - #print("Fill layer list") + # print("Fill layer list") try: listItem = QListWidgetItem(layer.name) From 563b54aa600be81e96e652e9e89ac9838c3486c3 Mon Sep 17 00:00:00 2001 From: KatKatKateryna Date: Mon, 12 Feb 2024 13:28:26 +0000 Subject: [PATCH 15/17] add workspace property --- qt_ui/DataStorage.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qt_ui/DataStorage.py b/qt_ui/DataStorage.py index 5615f0d..70ac8e2 100644 --- a/qt_ui/DataStorage.py +++ b/qt_ui/DataStorage.py @@ -5,7 +5,7 @@ import webbrowser try: from specklepy_qt_ui.qt_ui.utils.logger import logToUser -except ModuleNotFoundError: +except ModuleNotFoundError: from speckle.specklepy_qt_ui.qt_ui.utils.logger import logToUser from specklepy.core.api.credentials import get_local_accounts @@ -22,6 +22,7 @@ class DataStorage: currentCRS = None currentUnits = "m" currentOriginalUnits = "" + workspace = "" custom_lat: Optional[float] = None custom_lon: Optional[float] = None From 61af1d767688c1d2bf31abfd154079125915731c Mon Sep 17 00:00:00 2001 From: KatKatKateryna Date: Mon, 12 Feb 2024 20:46:53 +0000 Subject: [PATCH 16/17] typo --- qt_ui/widget_report.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/qt_ui/widget_report.py b/qt_ui/widget_report.py index a5d0a59..4a5337f 100644 --- a/qt_ui/widget_report.py +++ b/qt_ui/widget_report.py @@ -24,7 +24,6 @@ from specklepy.core.api.client import SpeckleClient FORM_CLASS, _ = uic.loadUiType( os.path.join(os.path.join(os.path.dirname(__file__), "ui", "report.ui")) ) -CRS_KEYWORD = "CRS" class ReportDialog(QtWidgets.QWidget, FORM_CLASS): @@ -129,27 +128,28 @@ class ReportDialog(QtWidgets.QWidget, FORM_CLASS): try: crs = self.dataStorage.project.crs() text += "Project CRS: " + crs.authid() + "\n" + crs_keyword = "CRS" except AttributeError: crs = self.dataStorage.project.activeMap.spatialReference - CRS_KEYWORD = "Spatial Reference" - text += f"Project {CRS_KEYWORD}: " + crs.name + "\n" + crs_keyword = "Spatial Reference" + text += f"Project {crs_keyword}: " + crs.name + "\n" units = self.dataStorage.latestActionUnits text += ( - f"Project {CRS_KEYWORD} units: " + f"Project {crs_keyword} units: " + units + f"{' (not supported, treated as Meters)' if 'degrees' in units else ''}" + "\n" ) try: - text += f"Project {CRS_KEYWORD} WKT: \n" + crs.toWkt() + "\n\n" + text += f"Project {crs_keyword} WKT: \n" + crs.toWkt() + "\n\n" except: - text += f"Project {CRS_KEYWORD} WKT: \n" + crs.exportToString() + "\n\n" + text += f"Project {crs_keyword} WKT: \n" + crs.exportToString() + "\n\n" text += ( - f"{CRS_KEYWORD} offsets: x={self.dataStorage.crs_offset_x}, y={self.dataStorage.crs_offset_y}" + f"{crs_keyword} offsets: x={self.dataStorage.crs_offset_x}, y={self.dataStorage.crs_offset_y}" + "\n" ) - text += f"{CRS_KEYWORD} rotation: {self.dataStorage.crs_rotation}°" + "\n\n" + text += f"{crs_keyword} rotation: {self.dataStorage.crs_rotation}°" + "\n\n" text += last_report From 18435bf4af55fc4ff5c88531e6689dc22d92c2d5 Mon Sep 17 00:00:00 2001 From: KatKatKateryna Date: Tue, 20 Feb 2024 00:09:12 +0000 Subject: [PATCH 17/17] add reports placeholders for regression testing --- qt_ui/DataStorage.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/qt_ui/DataStorage.py b/qt_ui/DataStorage.py index 70ac8e2..773adef 100644 --- a/qt_ui/DataStorage.py +++ b/qt_ui/DataStorage.py @@ -54,6 +54,9 @@ class DataStorage: latestActionLayers: Optional[list] = None latestActionUnits: str = "" + flat_report_receive: dict = {} + flat_report_latest: dict = {} + def __init__(self): # print("hello") # self.streamsToFollow.append(("https://speckle.xyz/streams/17b0b76d13/branches/random_tests", "", "09a0f3e41a"))