28 Commits

Author SHA1 Message Date
KatKatKateryna 9cd480fb6e terminology 2024-02-29 17:46:13 +00:00
KatKatKateryna 3b1d62c322 typo 2024-02-29 13:22:22 +00:00
KatKatKateryna 4ee673d9cd Change terminology to FE2 2024-02-29 13:19:24 +00:00
KatKatKateryna ed66a0fb2e Merge branch 'main' into 2.19 2024-02-23 14:24:19 +00:00
KatKatKateryna 18435bf4af add reports placeholders for regression testing 2024-02-20 00:09:12 +00:00
KatKatKateryna 61af1d7676 typo 2024-02-12 20:46:53 +00:00
KatKatKateryna bb081a9b52 Merge pull request #10 from specklesystems/2.18-fixes-for-arcgis
2.18 fixes for arcgis
2024-02-13 03:26:34 +08:00
KatKatKateryna 563b54aa60 add workspace property 2024-02-12 13:28:26 +00:00
KatKatKateryna 0b099810e5 don't pin window on launch 2024-02-12 00:03:43 +00:00
KatKatKateryna 30c3514bde get layers with structure 2024-02-11 18:15:45 +00:00
KatKatKateryna 97adaca60a fix arcgis report on receive 2024-02-10 23:17:35 +00:00
KatKatKateryna 66f45e8147 arcgis support: crs format; pin window 2024-02-10 19:00:28 +00:00
KatKatKateryna 8d505db4fd btn active 2024-02-07 18:07:42 +00:00
KatKatKateryna 5a85a97785 support other CRS data structures; saved layers in MainWindow 2024-02-07 17:37:23 +00:00
KatKatKateryna 04e4f43972 resize 2024-02-07 00:56:26 +00:00
KatKatKateryna ef07bedc26 fixes_main window 2024-02-07 00:26:07 +00:00
KatKatKateryna 97f2afedfb update main_window 2024-02-06 23:53:38 +00:00
KatKatKateryna ae83a21179 Merge pull request #9 from specklesystems/2.18
2.18
2024-02-06 03:20:48 +08:00
KatKatKateryna 240efef89a Merge branch 'main' into 2.18 2024-02-05 18:39:20 +00:00
KatKatKateryna 6db462df3c Revert "Change terminology to FE2"
This reverts commit 876068a39a.
2024-01-31 15:09:25 +00:00
KatKatKateryna 4600fa5167 Change terminology to FE2 2024-01-31 15:08:43 +00:00
KatKatKateryna 876068a39a Change terminology to FE2 2024-01-30 20:08:56 +00:00
KatKatKateryna d0c464d736 pack pyqt5 separately 2024-01-18 22:20:23 +00:00
KatKatKateryna ea76011ed2 fix icon's path 2024-01-13 17:16:47 +00:00
KatKatKateryna 51b1de4587 place Assets into Utils 2023-12-07 19:04:41 +08:00
KatKatKateryna 2a577de45c remove imports names overlap 2023-12-07 02:16:39 +08:00
KatKatKateryna 937ff8a878 backup import from 'speckle' submodule 2023-12-07 02:09:55 +08:00
KatKatKateryna d2451a41d8 create utils, import logger from UI repo 2023-12-07 01:56:21 +08:00
43 changed files with 1251 additions and 821 deletions
-126
View File
@@ -1,126 +0,0 @@
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<StreamState> 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<StreamState> == new List<StreamState>()
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 <see cref="Open3DView"/> 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
+9 -1
View File
@@ -3,7 +3,11 @@ import inspect
from typing import List, Optional, Tuple, Union, Any
import webbrowser
from speckle.utils.panel_logging 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
@@ -18,6 +22,7 @@ class DataStorage:
currentCRS = None
currentUnits = "m"
currentOriginalUnits = ""
workspace = ""
custom_lat: Optional[float] = None
custom_lon: Optional[float] = None
@@ -49,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"))
+41 -20
View File
@@ -9,19 +9,38 @@ import webbrowser
from specklepy.logging import metrics
from specklepy.core.api.credentials import Account
from specklepy_qt_ui.qt_ui.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):
@@ -268,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):
+75 -48
View File
@@ -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.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 (
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.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.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
@@ -346,11 +380,7 @@ class SpeckleQGISDialog(QtWidgets.QDockWidget, FORM_CLASS):
# print("setupOnFirstLoad")
self.msgLog.sendMessage.connect(self.addMsg)
self.setMapping.clicked.connect(self.showMappingDialog)
# print("before")
# print(self.reportBtn)
# print(self.msgLog)
self.reportBtn.clicked.connect(self.msgLog.showReport)
# print("after")
self.streams_add_button.clicked.connect(plugin.onStreamAddButtonClicked)
self.commit_web_view.clicked.connect(
@@ -661,9 +691,6 @@ class SpeckleQGISDialog(QtWidgets.QDockWidget, FORM_CLASS):
def fillLayerList(self, layer, layerType="generic"):
try:
icon_xxl = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", " size-xxl.png"
)
listItem = QListWidgetItem(layer.name())
try: # if QGIS
@@ -673,10 +700,10 @@ class SpeckleQGISDialog(QtWidgets.QDockWidget, FORM_CLASS):
isinstance(layer, QgsRasterLayer)
and layer.width() * layer.height() > 1000000
):
listItem.setIcon(QIcon(icon_xxl))
listItem.setIcon(QIcon(ICON_XXL))
elif isinstance(layer, QgsVectorLayer) and layer.featureCount() > 20000:
listItem.setIcon(QIcon(icon_xxl))
listItem.setIcon(QIcon(ICON_XXL))
else:
from qgis.core import QgsIconUtils
@@ -782,7 +809,7 @@ class SpeckleQGISDialog(QtWidgets.QDockWidget, FORM_CLASS):
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)
logToUser("Some Projects cannot be accessed", level=1, plugin=self)
return
elif (
plugin.active_stream is None
@@ -798,15 +825,15 @@ 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 Branch"])
self.streamBranchDropdown.addItems(["Create New Model"])
# 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:
elif len(plugin.active_branch.commits.items) > 0:
plugin.active_commit = plugin.active_branch.commits.items[0]
#else:
# else:
# plugin.active_commit = plugin.active_branch.commits.items[0]
# print(plugin.active_branch)
@@ -837,13 +864,13 @@ class SpeckleQGISDialog(QtWidgets.QDockWidget, FORM_CLASS):
# print("________populateActiveCommitDropdown")
# print(plugin.active_commit)
if plugin.active_stream is None:
print("Active stream is None")
print("Active project is None")
return
branchName = self.streamBranchDropdown.currentText()
# print(f"CURRENT BRANCH TEXT: {branchName}")
if branchName == "":
return
if branchName == "Create New Branch":
if branchName == "Create New Model":
self.streamBranchDropdown.setCurrentText("main")
plugin.onBranchCreateClicked()
return
@@ -853,7 +880,7 @@ class SpeckleQGISDialog(QtWidgets.QDockWidget, FORM_CLASS):
# print(plugin.active_commit)
self.commitDropdown.clear()
if isinstance(plugin.active_stream[1], SpeckleException):
logToUser("Some streams cannot be accessed", level=1, plugin=self)
logToUser("Some Projects cannot be accessed", level=1, plugin=self)
return
elif plugin.active_stream[1]:
for b in plugin.active_stream[1].branches.items:
@@ -905,7 +932,7 @@ class SpeckleQGISDialog(QtWidgets.QDockWidget, FORM_CLASS):
else:
plugin.active_commit = None
self.commitDropdown.setItemText(0, "Latest commit from this branch")
self.commitDropdown.setItemText(0, "Latest version of this model")
# enable or disable web view button
# print("_________ENABLE OR DISABLE")
# print(plugin.active_commit)
-47
View File
@@ -1,47 +0,0 @@
import os
# colors
COLOR_HIGHLIGHT = (210,210,210,1)
SPECKLE_COLOR = (59,130,246,1)
SPECKLE_COLOR_LIGHT = (69,140,255,1)
ICON_LOGO = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "logo-slab-white@0.5x.png")
ERROR_COLOR = (255,150,150,1)
ERROR_COLOR_LIGHT = (255,210,210,1)
COLOR = f"color: rgba{str(SPECKLE_COLOR)};"
BACKGR_COLOR_TRANSPARENT = f"background-color: rgba(0,0,0,0);"
BACKGR_COLOR_HIGHLIGHT = f"background-color: rgba{str(COLOR_HIGHLIGHT)};"
BACKGR_COLOR = f"background-color: rgba{str(SPECKLE_COLOR)};"
BACKGR_COLOR_LIGHT = f"background-color: rgba{str(SPECKLE_COLOR_LIGHT)};"
BACKGR_COLOR_GREY = f"background-color: rgba(220,220,220,1);"
BACKGR_ERROR_COLOR = f"background-color: rgba{str(ERROR_COLOR)};"
BACKGR_ERROR_COLOR_LIGHT = f"background-color: rgba{str(ERROR_COLOR_LIGHT)};"
NEW_GREY = BACKGR_COLOR_GREY.replace("1);","0.2);")
NEW_GREY_HIGHLIGHT = BACKGR_COLOR_HIGHLIGHT.replace("1);","0.3);")
# images
ICON_SEARCH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "magnify.png")
ICON_OPEN_WEB = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "open-in-new.png")
ICON_REPORT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "chart-line.png")
ICON_DELETE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "delete.png")
ICON_DELETE_BLUE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "delete-blue.png")
ICON_SEND = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "cube-send.png")
ICON_RECEIVE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "cube-receive.png")
ICON_SEND_BLACK = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "cube-send-black.png")
ICON_RECEIVE_BLACK = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "cube-receive-black.png")
ICON_SEND_BLUE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "cube-send-blue.png")
ICON_RECEIVE_BLUE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "cube-receive-blue.png")
ICON_XXL = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "/size-xxl.png")
ICON_RASTER = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "/legend_raster.png")
ICON_POLYGON = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "/legend_polygon.png")
ICON_LINE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "/legend_line.png")
ICON_POINT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "/legend_point.png")
ICON_GENERIC = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "/legend_generic.png")
+723 -379
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -25,7 +25,7 @@
<item row="1" column="0">
<widget class="QLabel" name="search_label">
<property name="text">
<string>Search Stream by name or URL</string>
<string>Search Project by name or URL</string>
</property>
</widget>
</item>
+1 -1
View File
@@ -26,7 +26,7 @@
<item row="0" column="0">
<widget class="QLabel" name="name_label">
<property name="text">
<string>Branch Name</string>
<string>Model Name</string>
</property>
</widget>
</item>
+1 -1
View File
@@ -34,7 +34,7 @@
<item row="1" column="0">
<widget class="QLabel" name="name_label">
<property name="text">
<string>Stream Name</string>
<string>Project Name</string>
</property>
</widget>
</item>
+3 -3
View File
@@ -39,7 +39,7 @@
<item row="1" column="0">
<widget class="QLabel" name="streamListLabel">
<property name="text">
<string>Stream</string>
<string>Project</string>
</property>
</widget>
</item>
@@ -77,7 +77,7 @@
<item row="2" column="0">
<widget class="QLabel" name="streamBranchLabel">
<property name="text">
<string>Branch</string>
<string>Model</string>
</property>
</widget>
</item>
@@ -87,7 +87,7 @@
<item row="3" column="0">
<widget class="QLabel" name="commitLabel">
<property name="text">
<string>Commit</string>
<string>Version</string>
</property>
</widget>
</item>
+61 -50
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SpeckleQArcGISDialog</class>
<widget class="QMainWindow" name="SpeckleQArcGISDialog">
<class>SpeckleGISDialog</class>
<widget class="QMainWindow" name="SpeckleGISDialog">
<property name="geometry">
<rect>
<x>0</x>
@@ -43,7 +43,7 @@
<item row="1" column="0">
<widget class="QLabel" name="streamListLabel">
<property name="text">
<string>Stream</string>
<string>Project</string>
</property>
</widget>
</item>
@@ -83,7 +83,7 @@
<item row="2" column="0">
<widget class="QLabel" name="streamBranchLabel">
<property name="text">
<string>Branch</string>
<string>Model</string>
</property>
</widget>
</item>
@@ -93,14 +93,26 @@
<item row="3" column="0">
<widget class="QLabel" name="commitLabel">
<property name="text">
<string>Commit</string>
<string>Version</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="commitDropdown"/>
</item>
<layout class="QHBoxLayout" name="commitListButtons" stretch="20,1">
<item>
<widget class="QComboBox" name="commitDropdown"/>
</item>
<item>
<widget class="QPushButton" name="commit_web_view">
<property name="text">
<string> </string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
</layout>
@@ -126,6 +138,15 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="reportBtn">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
@@ -178,21 +199,49 @@
<bool>true</bool>
</property>
<property name="text">
<string>Set visible layers as selection</string>
<string>Save visible layers as selection</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="9" column="0">
<item row="10" column="1">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="crsSettings">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Set project center on Send/Receive</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="11" column="0">
<widget class="QLabel" name="messageLabel">
<property name="text">
<string>Message</string>
</property>
</widget>
</item>
<item row="9" column="1">
<item row="11" column="1">
<widget class="QLineEdit" name="messageInput">
<property name="placeholderText">
<string>Sent XXX objects from ArcGIS</string>
@@ -202,7 +251,7 @@
<item row="10" column="1">
<item row="12" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
@@ -236,46 +285,8 @@
</layout>
</item>
<item row="11" column="0">
<widget class="QLabel" name="surveyPointLabel">
<property name="text">
<string>Lat, Lon</string>
</property>
</widget>
</item>
<item row="11" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="surveyPointLat">
<property name="placeholderText">
<string>0.0</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="surveyPointLon">
<property name="placeholderText">
<string>0.0</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="saveSurveyPoint">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Set as a project center</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="12" column="1">
<item row="13" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Before

Width:  |  Height:  |  Size: 345 B

After

Width:  |  Height:  |  Size: 345 B

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Before

Width:  |  Height:  |  Size: 400 B

After

Width:  |  Height:  |  Size: 400 B

+90
View File
@@ -0,0 +1,90 @@
import os
# colors
COLOR_HIGHLIGHT = (210, 210, 210, 1)
SPECKLE_COLOR = (59, 130, 246, 1)
SPECKLE_COLOR_LIGHT = (69, 140, 255, 1)
ICON_LOGO = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "logo-slab-white@0.5x.png"
)
ERROR_COLOR = (255, 150, 150, 1)
ERROR_COLOR_LIGHT = (255, 210, 210, 1)
COLOR = f"color: rgba{str(SPECKLE_COLOR)};"
BACKGR_COLOR_TRANSPARENT = f"background-color: rgba(0,0,0,0);"
BACKGR_COLOR_HIGHLIGHT = f"background-color: rgba{str(COLOR_HIGHLIGHT)};"
BACKGR_COLOR = f"background-color: rgba{str(SPECKLE_COLOR)};"
BACKGR_COLOR_LIGHT = f"background-color: rgba{str(SPECKLE_COLOR_LIGHT)};"
BACKGR_COLOR_GREY = f"background-color: rgba(220,220,220,1);"
BACKGR_ERROR_COLOR = f"background-color: rgba{str(ERROR_COLOR)};"
BACKGR_ERROR_COLOR_LIGHT = f"background-color: rgba{str(ERROR_COLOR_LIGHT)};"
NEW_GREY = BACKGR_COLOR_GREY.replace("1);", "0.2);")
NEW_GREY_HIGHLIGHT = BACKGR_COLOR_HIGHLIGHT.replace("1);", "0.3);")
# images
ICON_SEARCH = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "magnify.png"
)
ICON_OPEN_WEB = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "open-in-new.png"
)
ICON_REPORT = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "chart-line.png"
)
ICON_DELETE = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "delete.png"
)
ICON_DELETE_BLUE = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "delete-blue.png"
)
ICON_SEND = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "cube-send.png"
)
ICON_RECEIVE = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "cube-receive.png"
)
ICON_SEND_BLACK = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "cube-send-black.png"
)
ICON_RECEIVE_BLACK = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "cube-receive-black.png"
)
ICON_SEND_BLUE = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "cube-send-blue.png"
)
ICON_RECEIVE_BLUE = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "cube-receive-blue.png"
)
ICON_XXL = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "size-xxl.png"
)
ICON_RASTER = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "legend_raster.png"
)
ICON_POLYGON = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "legend_polygon.png"
)
ICON_LINE = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "legend_line.png"
)
ICON_POINT = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "legend_point.png"
)
ICON_GENERIC = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "legend_generic.png"
)
ICON_PIN_ACTIVE = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "pin.png"
)
ICON_PIN_DISABLED = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "assets", "pin-outline.png"
)
+7 -4
View File
@@ -1,7 +1,7 @@
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.utils import splitTextIntoLines
except ModuleNotFoundError:
from speckle.specklepy_qt_ui.qt_ui.utils.utils import splitTextIntoLines
def logToUser(
@@ -55,6 +55,9 @@ def displayUserMsg(msg: str, func=None, level: int = 2):
def createWindow(msg_old: str, func=None, level: int = 2):
# print("Create window")
from PyQt5.QtWidgets import QMessageBox
from PyQt5 import QtCore
window = None
try:
# https://www.techwithtim.net/tutorials/pyqt5-tutorial/messageboxes/
+9 -11
View File
@@ -1,10 +1,11 @@
from textwrap import wrap
from typing import Union
import requests
SYMBOL = "_x_x_"
def splitTextIntoLines(text: str = "", number: int = 40) -> str:
# print("__splitTextIntoLines")
# print(text)
msg = ""
try:
if len(text) > number:
@@ -28,8 +29,10 @@ def splitTextIntoLines(text: str = "", number: int = 40) -> str:
def constructCommitURL(
streamWrapper, branch_id: str = None, commit_id: str = None
) -> str:
streamWrapper,
branch_id: Union[str, None] = None,
commit_id: Union[str, None] = None,
) -> Union[str, None]:
import requests
try:
@@ -41,7 +44,7 @@ def constructCommitURL(
url = streamUrl
# check for frontend2
try:
header = r.headers["x-speckle-frontend-2"]
header = r.headers["x-speckle-frontend-2"] # will throw Exception in FE1
url = (
streamUrl.replace("streams", "projects")
+ "/models/"
@@ -53,7 +56,7 @@ def constructCommitURL(
url = streamUrl.replace("projects", "streams") + "/commits/" + commit_id
return url
except:
pass
return None
def constructCommitURLfromServerCommit(serverURL: str, stream_id: str) -> str:
@@ -71,8 +74,3 @@ def constructCommitURLfromServerCommit(serverURL: str, stream_id: str) -> str:
except KeyError:
url = serverURL + "/streams/" + stream_id
return url
# def removeSpecialCharacters(text: str) -> str:
# new_text = text.replace("[","_").replace("]","_").replace(" ","_").replace("-","_").replace("(","_").replace(")","_").replace(":","_").replace("\\","_").replace("/","_").replace("\"","_").replace("&","_").replace("@","_").replace("$","_").replace("%","_").replace("^","_")
# return new_text
+16 -12
View File
@@ -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.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.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.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(
@@ -46,7 +50,7 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
)
self.speckle_client = speckle_client
self.setupUi(self)
self.setWindowTitle("Add Speckle stream")
self.setWindowTitle("Add Speckle Project")
self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False)
@@ -89,7 +93,7 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
"Connector Action",
self.dataStorage.active_account,
{
"name": "Stream Search By Name",
"name": "Project Search By Name",
"connector_version": str(self.dataStorage.plugin_version),
},
)
@@ -149,7 +153,7 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
"Connector Action",
self.dataStorage.active_account,
{
"name": "Stream Search By URL",
"name": "Project Search By URL",
"connector_version": str(self.dataStorage.plugin_version),
},
)
@@ -163,7 +167,7 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
"Connector Action",
self.dataStorage.active_account,
{
"name": "Stream Search By Name",
"name": "Project Search By Name",
"connector_version": str(self.dataStorage.plugin_version),
},
)
@@ -191,7 +195,7 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
self.search_results_list.clear()
if isinstance(self.stream_results, SpeckleException):
logToUser(
"Some streams cannot be accessed",
"Some Projects cannot be accessed",
level=1,
func=inspect.stack()[0][3],
)
@@ -205,7 +209,7 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
if isinstance(stream, SpeckleException):
logToUser(
"Some streams cannot be accessed",
"Some Projects cannot be accessed",
level=1,
func=inspect.stack()[0][3],
)
@@ -223,7 +227,7 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
try:
if isinstance(self.stream_results, SpeckleException):
logToUser(
"Selected stream cannot be accessed: "
"Selected Project cannot be accessed: "
+ str(self.stream_results.message),
level=1,
func=inspect.stack()[0][3],
@@ -261,7 +265,7 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
self.close()
except Exception as e:
logToUser(
"Some streams cannot be accessed: " + str(e),
"Some Projects cannot be accessed: " + str(e),
level=1,
func=inspect.stack()[0][3],
)
+34 -18
View File
@@ -1,7 +1,11 @@
import inspect
import os
from typing import List, Tuple, Union
from specklepy_qt_ui.qt_ui.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
@@ -11,39 +15,50 @@ 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):
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 Branch")
self.setWindowTitle("Create New Model")
self.setMinimumWidth(300)
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):
@@ -53,16 +68,17 @@ 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]
@@ -71,4 +87,4 @@ class CreateBranchModalDialog(QtWidgets.QWidget, FORM_CLASS):
except Exception as e:
logToUser(e, level = 2, func = inspect.stack()[0][3])
return
'''
"""
+6 -2
View File
@@ -1,7 +1,11 @@
import inspect
import os
from typing import List, Tuple, Union
from specklepy_qt_ui.qt_ui.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
@@ -37,7 +41,7 @@ class CreateStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
)
self.speckle_client = speckle_client
self.setupUi(self)
self.setWindowTitle("Create New Stream")
self.setWindowTitle("Create New Project")
self.name_field.textChanged.connect(self.nameCheck)
self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(True)
+75 -46
View File
@@ -1,80 +1,91 @@
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
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
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
# 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
description: 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':
print(units)
if units == "degrees":
self.offsetXDegreeSign.setText("°")
self.offsetYDegreeSign.setText("°")
elif units is not None:
@@ -83,49 +94,64 @@ class CustomCRSDialog(QtWidgets.QWidget, FORM_CLASS):
else:
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':
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 +160,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 +183,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
+10 -2
View File
@@ -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
@@ -87,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"],
+84 -48
View File
@@ -1,70 +1,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
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
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
# 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
reportList = self.dataStorage.latestActionReport
if reportList is None: return
if self.dataStorage is None:
return
reportList: List[dict] = self.dataStorage.latestActionReport
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
line += f'{item["feature_id"]}: {item["obj_type"]}'
try: # if sending
some_id = item["feature_id"].replace(SYMBOL, "\\")
line += f'{some_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"]}'
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
# edit based on the type
if "Layer" in item["obj_type"]:
total_layers += 1
if item["errors"] != "":
@@ -75,61 +88,84 @@ 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"
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"
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 += (
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"
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"
)
text += f"{crs_keyword} 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()
+5 -1
View File
@@ -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