main UI window
@@ -0,0 +1,125 @@
|
||||
./idea/
|
||||
/.vscode/
|
||||
/speckle_qgis_dialog_base.ui.autosave
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Jetbrains stuff:
|
||||
.idea
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
|
||||
# other
|
||||
scratch.py
|
||||
settings.json
|
||||
**/.DS_Store
|
||||
zip_build
|
||||
.qt_for_python
|
||||
speckle-sharp-ci-tools*
|
||||
zip-build*
|
||||
|
||||
/typings/*
|
||||
*.csv
|
||||
*.json
|
||||
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 345 B |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 400 B |
@@ -0,0 +1,710 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
/***************************************************************************
|
||||
SpeckleQGISDialog
|
||||
A QGIS plugin
|
||||
SpeckleQGIS Description
|
||||
Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
|
||||
-------------------
|
||||
begin : 2021-08-04
|
||||
git sha : $Format:%H$
|
||||
copyright : (C) 2021 by Speckle Systems
|
||||
email : alan@speckle.systems
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
"""
|
||||
|
||||
import inspect
|
||||
import os
|
||||
import threading
|
||||
from plugin_utils.helpers import splitTextIntoLines
|
||||
from speckle.automation.mapping_send import MappingSendDialog
|
||||
from speckle.converter.layers import getAllLayers, getLayers
|
||||
from speckle.DataStorage import DataStorage
|
||||
from ui.LogWidget import LogWidget
|
||||
from ui.logger import logToUser
|
||||
#from speckle_qgis import SpeckleQGIS
|
||||
import ui.speckle_qgis_dialog
|
||||
from qgis.core import Qgis, QgsProject,QgsVectorLayer, QgsRasterLayer, QgsIconUtils
|
||||
from specklepy.logging.exceptions import (SpeckleException, GraphQLException)
|
||||
from qgis.PyQt import QtWidgets, uic
|
||||
from qgis.PyQt import QtGui
|
||||
from qgis.PyQt.QtGui import QIcon, QPixmap
|
||||
from qgis.PyQt.QtWidgets import QCheckBox, QListWidgetItem, QAction, QDockWidget, QVBoxLayout, QHBoxLayout, QWidget, QLabel
|
||||
from qgis.PyQt import QtCore
|
||||
from qgis.PyQt.QtCore import pyqtSignal, Qt
|
||||
from speckle.logging import logger
|
||||
from specklepy.api.credentials import get_local_accounts
|
||||
|
||||
from specklepy.api.wrapper import StreamWrapper
|
||||
from specklepy.api.client import SpeckleClient
|
||||
from specklepy.logging import metrics
|
||||
|
||||
from ui.validation import tryGetStream
|
||||
|
||||
# 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.dirname(__file__), "main_dialog_qDockwidget.ui")
|
||||
)
|
||||
|
||||
COLOR_HIGHLIGHT = (210,210,210)
|
||||
|
||||
SPECKLE_COLOR = (59,130,246)
|
||||
SPECKLE_COLOR_LIGHT = (69,140,255)
|
||||
ICON_LOGO = os.path.dirname(os.path.abspath(__file__)) + "/icons/logo-slab-white@0.5x.png"
|
||||
|
||||
ICON_SEARCH = os.path.dirname(os.path.abspath(__file__)) + "/icons/magnify.png"
|
||||
|
||||
ICON_DELETE = os.path.dirname(os.path.abspath(__file__)) + "/icons/delete.png"
|
||||
ICON_DELETE_BLUE = os.path.dirname(os.path.abspath(__file__)) + "/icons/delete-blue.png"
|
||||
|
||||
ICON_SEND = os.path.dirname(os.path.abspath(__file__)) + "/icons/cube-send.png"
|
||||
ICON_RECEIVE = os.path.dirname(os.path.abspath(__file__)) + "/icons/cube-receive.png"
|
||||
|
||||
ICON_SEND_BLACK = os.path.dirname(os.path.abspath(__file__)) + "/icons/cube-send-black.png"
|
||||
ICON_RECEIVE_BLACK = os.path.dirname(os.path.abspath(__file__)) + "/icons/cube-receive-black.png"
|
||||
|
||||
ICON_SEND_BLUE = os.path.dirname(os.path.abspath(__file__)) + "/icons/cube-send-blue.png"
|
||||
ICON_RECEIVE_BLUE = os.path.dirname(os.path.abspath(__file__)) + "/icons/cube-receive-blue.png"
|
||||
|
||||
COLOR = f"color: rgb{str(SPECKLE_COLOR)};"
|
||||
BACKGR_COLOR = f"background-color: rgb{str(SPECKLE_COLOR)};"
|
||||
BACKGR_COLOR_LIGHT = f"background-color: rgb{str(SPECKLE_COLOR_LIGHT)};"
|
||||
|
||||
class MainDialog(QtWidgets.QDockWidget, FORM_CLASS):
|
||||
|
||||
closingPlugin = pyqtSignal()
|
||||
streamList: QtWidgets.QComboBox
|
||||
sendModeButton: QtWidgets.QPushButton
|
||||
receiveModeButton: QtWidgets.QPushButton
|
||||
streamBranchDropdown: QtWidgets.QComboBox
|
||||
layerSendModeDropdown: QtWidgets.QComboBox
|
||||
commitDropdown: QtWidgets.QComboBox
|
||||
layersWidget: QtWidgets.QListWidget
|
||||
saveLayerSelection: QtWidgets.QPushButton
|
||||
runButton: QtWidgets.QPushButton
|
||||
setMapping: QtWidgets.QPushButton
|
||||
experimental: QCheckBox
|
||||
msgLog: LogWidget = None
|
||||
dataStorage: DataStorage = None
|
||||
mappingSendDialog = None
|
||||
|
||||
def __init__(self, parent=None):
|
||||
"""Constructor."""
|
||||
super(MainDialog, self).__init__(parent)
|
||||
# Set up the user interface from Designer through FORM_CLASS.
|
||||
# After self.setupUi() you can access any designer object by doing
|
||||
# self.<objectname>, and you can use autoconnect slots - see
|
||||
# http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
|
||||
# #widgets-and-dialogs-with-auto-connect
|
||||
self.setupUi(self)
|
||||
|
||||
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.saveLayerSelection.setFlat(True)
|
||||
self.reloadButton.setFlat(True)
|
||||
self.closeButton.setFlat(True)
|
||||
|
||||
# https://stackoverflow.com/questions/67585501/pyqt-how-to-use-hover-in-button-stylesheet
|
||||
#color = f"color: rgb{str(SPECKLE_COLOR)};"
|
||||
#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_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.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.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.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.setGeometry(0, 0, 150, 30)
|
||||
self.runButton.setMaximumWidth(200)
|
||||
self.runButton.setIcon(QIcon(ICON_SEND))
|
||||
|
||||
# insert checkbox
|
||||
l = self.verticalLayout
|
||||
#l_item = None
|
||||
|
||||
#for i in reversed(range(self.verticalLayout.count())):
|
||||
# l_item = self.verticalLayout.itemAt(i).widget()
|
||||
|
||||
# add row with "experimental" checkbox
|
||||
box = QWidget()
|
||||
box.layout = QHBoxLayout(box)
|
||||
btn = QtWidgets.QCheckBox("Send/receive in the background (experimental!)")
|
||||
btn.setStyleSheet("QPushButton {color: black; border: 0px;padding: 0px;height: 40px;text-align: left;}")
|
||||
box.layout.addWidget(btn)
|
||||
box.layout.setContentsMargins(65, 0, 0, 0)
|
||||
self.formLayout.insertRow(10,box)
|
||||
self.experimental = btn
|
||||
|
||||
|
||||
def runSetup(self, plugin):
|
||||
|
||||
self.addDataStorage(plugin)
|
||||
self.addLabel(plugin)
|
||||
self.addProps(plugin)
|
||||
self.createMappingDialog()
|
||||
|
||||
def addProps(self, plugin):
|
||||
|
||||
# add widgets that will only show on event trigger
|
||||
logWidget = LogWidget(parent=self)
|
||||
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
|
||||
|
||||
# add row with "experimental" checkbox
|
||||
box = QWidget()
|
||||
box.layout = QHBoxLayout(box)
|
||||
btn = QtWidgets.QPushButton("Apply transformations on Send")
|
||||
btn.setFlat(True)
|
||||
btn.setStyleSheet("QPushButton {text-align: right;} QPushButton:hover { " + f"{COLOR}" + " }")
|
||||
box.layout.addWidget(btn)
|
||||
box.layout.setContentsMargins(65, 0, 0, 0)
|
||||
self.formLayout.insertRow(9,box)
|
||||
self.setMapping = btn
|
||||
|
||||
def addDataStorage(self, plugin):
|
||||
self.dataStorage = plugin.dataStorage
|
||||
self.dataStorage.project = plugin.qgis_project
|
||||
root = self.dataStorage.project.layerTreeRoot()
|
||||
self.dataStorage.all_layers = getAllLayers(root)
|
||||
|
||||
def createMappingDialog(self):
|
||||
root = self.dataStorage.project.layerTreeRoot()
|
||||
self.dataStorage.all_layers = getAllLayers(root)
|
||||
|
||||
if self.mappingSendDialog is None:
|
||||
self.mappingSendDialog = MappingSendDialog(None)
|
||||
self.mappingSendDialog.dataStorage = self.dataStorage
|
||||
|
||||
self.mappingSendDialog.runSetup()
|
||||
|
||||
def showMappingDialog(self):
|
||||
# updata DataStorage
|
||||
self.mappingSendDialog.show()
|
||||
|
||||
def addLabel(self, plugin):
|
||||
try:
|
||||
exitIcon = QPixmap(ICON_LOGO)
|
||||
#scaledExitIcon = exitIcon.scaled(QtCore.QSize(100, 31))
|
||||
exitActIcon = QIcon(exitIcon)
|
||||
|
||||
# create a label
|
||||
text_label = QtWidgets.QPushButton(" for QGIS")
|
||||
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(QtCore.QSize(300, 93))
|
||||
text_label.setMinimumSize(QtCore.QSize(100, 40))
|
||||
text_label.setMaximumWidth(200)
|
||||
|
||||
version = ""
|
||||
try:
|
||||
if isinstance(plugin.version, str): version = str(plugin.version)
|
||||
except: pass
|
||||
|
||||
|
||||
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.setTitleBarWidget(widget) # for dockwidget
|
||||
#self.gridLayoutTitleBar.addWidget(widget) # fro QMainWindow
|
||||
|
||||
except Exception as e:
|
||||
logToUser(e)
|
||||
|
||||
def resizeEvent(self, event):
|
||||
try:
|
||||
#print("resize")
|
||||
QtWidgets.QDockWidget.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())
|
||||
except Exception as e:
|
||||
#logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
def clearDropdown(self):
|
||||
try:
|
||||
#self.streamIdField.clear()
|
||||
self.streamBranchDropdown.clear()
|
||||
self.commitDropdown.clear()
|
||||
#self.layerSendModeDropdown.clear()
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
def reloadDialogUI(self, plugin):
|
||||
try:
|
||||
|
||||
#logToUser("long errror something something msg1", level=2, plugin= plugin)
|
||||
|
||||
self.clearDropdown()
|
||||
self.populateUI(plugin)
|
||||
self.enableElements(plugin)
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
|
||||
def run(self, plugin):
|
||||
try:
|
||||
# Setup events on first load only!
|
||||
self.setupOnFirstLoad(plugin)
|
||||
# Connect streams section events
|
||||
self.completeStreamSection(plugin)
|
||||
# Populate the UI dropdowns
|
||||
self.populateUI(plugin)
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
def closeEvent(self, event):
|
||||
try:
|
||||
self.closingPlugin.emit()
|
||||
event.accept()
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
def addMsg(self, text:str, level:int, url:str, blue:bool):
|
||||
#t_name = threading.current_thread().getName()
|
||||
#print(t_name)
|
||||
self.msgLog.addButton(text, level, url, blue)
|
||||
|
||||
def setupOnFirstLoad(self, plugin):
|
||||
try:
|
||||
self.runButton.clicked.connect(plugin.onRunButtonClicked)
|
||||
|
||||
self.msgLog.sendMessage.connect(self.addMsg)
|
||||
self.setMapping.clicked.connect(self.showMappingDialog)
|
||||
|
||||
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.sendModeButton.clicked.connect(lambda: self.setSendMode(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.closingPlugin.connect(plugin.onClosePlugin)
|
||||
return
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
def refreshClicked(self, plugin):
|
||||
try:
|
||||
try:
|
||||
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 )
|
||||
|
||||
plugin.reloadUI()
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
def closeClicked(self, plugin):
|
||||
try:
|
||||
try:
|
||||
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 )
|
||||
|
||||
plugin.onClosePlugin()
|
||||
except Exception as e:
|
||||
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;")
|
||||
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.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)
|
||||
self.commitDropdown.setEnabled(False)
|
||||
self.messageInput.setEnabled(True)
|
||||
self.layerSendModeDropdown.setEnabled(True)
|
||||
self.setMapping.setEnabled(True)
|
||||
|
||||
self.runBtnStatusChanged(plugin)
|
||||
return
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
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;")
|
||||
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.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.commitDropdown.setEnabled(True)
|
||||
self.layersWidget.setEnabled(False)
|
||||
self.messageInput.setEnabled(False)
|
||||
self.saveLayerSelection.setEnabled(False)
|
||||
self.layerSendModeDropdown.setEnabled(False)
|
||||
self.setMapping.setEnabled(False)
|
||||
|
||||
self.runBtnStatusChanged(plugin)
|
||||
return
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
def completeStreamSection(self, plugin):
|
||||
try:
|
||||
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
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
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(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
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 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:
|
||||
if self.layerSendModeDropdown.currentIndex() == 0 or runMode == 1: # by manual selection OR receive mode
|
||||
#self.current_layers = []
|
||||
#self.dataStorage.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
|
||||
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(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
def populateLayerDropdown(self, plugin, bySelection: bool = True):
|
||||
|
||||
try:
|
||||
if not self: return
|
||||
from ui.project_vars import set_project_layer_selection
|
||||
|
||||
self.layersWidget.clear()
|
||||
nameDisplay = []
|
||||
project = plugin.qgis_project
|
||||
|
||||
if bySelection is False: # read from project data
|
||||
|
||||
all_layers_ids = [l.id() for l in project.mapLayers().values()]
|
||||
for layer_tuple in plugin.dataStorage.current_layers:
|
||||
if layer_tuple[1].id() in all_layers_ids:
|
||||
listItem = self.fillLayerList(layer_tuple[1])
|
||||
self.layersWidget.addItem(listItem)
|
||||
|
||||
else: # read selected layers
|
||||
# Fetch selected layers
|
||||
|
||||
#plugin.current_layers = []
|
||||
self.dataStorage.current_layers.clear()
|
||||
layers = getLayers(plugin, bySelection) # List[QgsLayerTreeNode]
|
||||
for i, layer in enumerate(layers):
|
||||
#plugin.current_layers.append((layer.name(), layer))
|
||||
self.dataStorage.current_layers.append((layer.name(), layer))
|
||||
listItem = self.fillLayerList(layer)
|
||||
self.layersWidget.addItem(listItem)
|
||||
|
||||
set_project_layer_selection(plugin)
|
||||
|
||||
self.layersWidget.setIconSize(QtCore.QSize(20, 20))
|
||||
self.runBtnStatusChanged(plugin)
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
def fillLayerList(self, layer):
|
||||
try:
|
||||
icon_xxl = os.path.dirname(os.path.abspath(__file__)) + "/size-xxl.png"
|
||||
listItem = QListWidgetItem(layer.name())
|
||||
|
||||
if isinstance(layer, QgsRasterLayer) and layer.width()*layer.height() > 1000000:
|
||||
listItem.setIcon(QIcon(icon_xxl))
|
||||
|
||||
elif isinstance(layer, QgsVectorLayer) and layer.featureCount() > 20000:
|
||||
listItem.setIcon(QIcon(icon_xxl))
|
||||
|
||||
else:
|
||||
icon = QgsIconUtils().iconForLayer(layer)
|
||||
listItem.setIcon(icon)
|
||||
|
||||
return listItem
|
||||
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
|
||||
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(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
def enableElements(self, plugin):
|
||||
try:
|
||||
self.sendModeButton.setEnabled(plugin.is_setup)
|
||||
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.streamBranchDropdown.setEnabled(plugin.is_setup)
|
||||
self.layerSendModeDropdown.setEnabled(plugin.is_setup)
|
||||
self.commitDropdown.setEnabled(False)
|
||||
self.show()
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
def populateProjectStreams(self, plugin):
|
||||
try:
|
||||
from ui.project_vars import set_project_streams
|
||||
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(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
def onActiveStreamChanged(self, plugin):
|
||||
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)):
|
||||
self.populateProjectStreams(plugin)
|
||||
plugin.onStreamCreateClicked()
|
||||
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
|
||||
|
||||
self.populateActiveStreamBranchDropdown(plugin)
|
||||
self.populateActiveCommitDropdown(plugin)
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
def populateLayerSendModeDropdown(self):
|
||||
if not self: return
|
||||
try:
|
||||
self.layerSendModeDropdown.clear()
|
||||
self.layerSendModeDropdown.addItems(
|
||||
["Send selected layers", "Send saved layers"]
|
||||
)
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
def populateActiveStreamBranchDropdown(self, plugin):
|
||||
if not self: return
|
||||
try:
|
||||
if plugin.active_stream is None: return
|
||||
self.streamBranchDropdown.clear()
|
||||
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:
|
||||
return
|
||||
self.streamBranchDropdown.addItems(
|
||||
[f"{branch.name}" for branch in plugin.active_stream[1].branches.items]
|
||||
)
|
||||
self.streamBranchDropdown.addItems(["Create New Branch"])
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
def populateActiveCommitDropdown(self, plugin):
|
||||
if not self: return
|
||||
try:
|
||||
self.commitDropdown.clear()
|
||||
if plugin.active_stream is None: return
|
||||
branchName = self.streamBranchDropdown.currentText()
|
||||
if branchName == "": return
|
||||
if branchName == "Create New Branch":
|
||||
self.streamBranchDropdown.setCurrentText("main")
|
||||
plugin.onBranchCreateClicked()
|
||||
return
|
||||
branch = None
|
||||
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
|
||||
break
|
||||
print(branch)
|
||||
self.commitDropdown.addItems(
|
||||
[f"{commit.id}"+ " | " + f"{commit.message}" for commit in branch.commits.items]
|
||||
)
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
print(str(e) + "::" + str(inspect.stack()[0][3]))
|
||||
return
|
||||
|
||||
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(e, level = 2, func = inspect.stack()[0][3], plugin=self)
|
||||
return
|
||||
|
||||
@@ -0,0 +1,647 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
from typing import List
|
||||
#from speckle.converter.layers import getLayers
|
||||
|
||||
#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 import QtCore
|
||||
from PyQt5.QtCore import pyqtSignal, Qt, QSize, QEvent
|
||||
from PyQt5 import QtGui, uic
|
||||
|
||||
from specklepy.api.credentials import get_local_accounts
|
||||
|
||||
import importlib
|
||||
|
||||
from specklepy.api.wrapper import StreamWrapper
|
||||
from specklepy.api.client import SpeckleClient
|
||||
from specklepy.logging import metrics
|
||||
|
||||
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")
|
||||
|
||||
|
||||
# This loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer
|
||||
|
||||
COLOR_HIGHLIGHT = (210,210,210)
|
||||
|
||||
SPECKLE_COLOR = (59,130,246)
|
||||
SPECKLE_COLOR_LIGHT = (69,140,255)
|
||||
ICON_LOGO = os.path.dirname(os.path.abspath(__file__)) + "/logo-slab-white@0.5x.png"
|
||||
|
||||
ICON_SEARCH = os.path.dirname(os.path.abspath(__file__)) + "/magnify.png"
|
||||
|
||||
ICON_DELETE = os.path.dirname(os.path.abspath(__file__)) + "/delete.png"
|
||||
ICON_DELETE_BLUE = os.path.dirname(os.path.abspath(__file__)) + "/delete-blue.png"
|
||||
|
||||
ICON_SEND = os.path.dirname(os.path.abspath(__file__)) + "/cube-send.png"
|
||||
ICON_RECEIVE = os.path.dirname(os.path.abspath(__file__)) + "/cube-receive.png"
|
||||
|
||||
ICON_SEND_BLACK = os.path.dirname(os.path.abspath(__file__)) + "/cube-send-black.png"
|
||||
ICON_RECEIVE_BLACK = os.path.dirname(os.path.abspath(__file__)) + "/cube-receive-black.png"
|
||||
|
||||
ICON_SEND_BLUE = os.path.dirname(os.path.abspath(__file__)) + "/cube-send-blue.png"
|
||||
ICON_RECEIVE_BLUE = os.path.dirname(os.path.abspath(__file__)) + "/cube-receive-blue.png"
|
||||
|
||||
COLOR = f"color: rgb{str(SPECKLE_COLOR)};"
|
||||
BACKGR_COLOR = f"background-color: rgb{str(SPECKLE_COLOR)};"
|
||||
BACKGR_COLOR_LIGHT = f"background-color: rgb{str(SPECKLE_COLOR_LIGHT)};"
|
||||
|
||||
ui_class = os.path.dirname(os.path.abspath(__file__)) + "/speckle_qgis_dialog_base.ui"
|
||||
print(os.path.dirname(__file__))
|
||||
|
||||
class SpeckleGISDialog(QMainWindow):
|
||||
|
||||
closingPlugin = pyqtSignal()
|
||||
streamList: QtWidgets.QComboBox
|
||||
sendModeButton: QtWidgets.QPushButton
|
||||
receiveModeButton: QtWidgets.QPushButton
|
||||
streamBranchDropdown: QtWidgets.QComboBox
|
||||
layerSendModeDropdown: QtWidgets.QComboBox
|
||||
commitDropdown: QtWidgets.QComboBox
|
||||
layersWidget: QtWidgets.QListWidget
|
||||
saveLayerSelection: QtWidgets.QPushButton
|
||||
runButton: QtWidgets.QPushButton
|
||||
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)
|
||||
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.saveLayerSelection.setFlat(True)
|
||||
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_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_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.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.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.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.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
|
||||
|
||||
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):
|
||||
|
||||
try:
|
||||
exitIcon = QPixmap(ICON_LOGO)
|
||||
exitActIcon = QIcon(exitIcon)
|
||||
|
||||
# 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.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
|
||||
|
||||
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;"
|
||||
)
|
||||
|
||||
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
|
||||
except Exception as e:
|
||||
logToUser(e)
|
||||
|
||||
def resizeEvent(self, event):
|
||||
try:
|
||||
#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())
|
||||
except Exception as e:
|
||||
#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)
|
||||
|
||||
def reloadDialogUI(self, plugin):
|
||||
try:
|
||||
self.clearDropdown()
|
||||
self.populateUI(plugin)
|
||||
self.enableElements(plugin)
|
||||
except Exception as e:
|
||||
logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self)
|
||||
|
||||
|
||||
|
||||
def run(self, plugin):
|
||||
try:
|
||||
print("dockwidget run")
|
||||
# Setup events on first load only!
|
||||
self.setupOnFirstLoad(plugin)
|
||||
# Connect streams section events
|
||||
self.completeStreamSection(plugin)
|
||||
# Populate the UI dropdowns
|
||||
self.populateUI(plugin)
|
||||
print("dockwidget run end")
|
||||
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.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.receiveModeButton.clicked.connect(lambda: self.setReceiveMode(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)
|
||||
|
||||
def refreshClicked(self, plugin):
|
||||
try:
|
||||
try:
|
||||
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 )
|
||||
|
||||
plugin.reloadUI()
|
||||
except Exception as e:
|
||||
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)})
|
||||
except Exception as e:
|
||||
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)
|
||||
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;")
|
||||
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.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)
|
||||
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)
|
||||
|
||||
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;")
|
||||
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.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.commitDropdown.setEnabled(True)
|
||||
self.layersWidget.setEnabled(False)
|
||||
self.messageInput.setEnabled(False)
|
||||
self.saveLayerSelection.setEnabled(False)
|
||||
self.layerSendModeDropdown.setEnabled(False)
|
||||
|
||||
self.runBtnStatusChanged(plugin)
|
||||
return
|
||||
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)
|
||||
|
||||
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
|
||||
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):
|
||||
try:
|
||||
print("Send mode changed")
|
||||
|
||||
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
|
||||
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)
|
||||
|
||||
|
||||
def populateLayerDropdown(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.ui.project_vars import set_project_layer_selection
|
||||
|
||||
try:
|
||||
self.layersWidget.clear()
|
||||
nameDisplay = []
|
||||
project = plugin.gis_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:
|
||||
if layer_tuple[1].dataSource in all_layers_ids:
|
||||
listItem = self.fillLayerList(layer_tuple[1])
|
||||
self.layersWidget.addItem(listItem)
|
||||
|
||||
else: # read selected layers
|
||||
# Fetch selected layers
|
||||
print("populate layers from selection")
|
||||
|
||||
plugin.current_layers = []
|
||||
layers = getLayers(plugin, bySelection) # 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")
|
||||
|
||||
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)
|
||||
|
||||
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_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)
|
||||
|
||||
if layer.isRasterLayer: # and layer.width()*layer.height() > 1000000:
|
||||
listItem.setIcon(QIcon(ICON_RASTER))
|
||||
|
||||
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:
|
||||
listItem.setIcon(QIcon(ICON_XXL))
|
||||
#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)
|
||||
|
||||
def enableElements(self, plugin):
|
||||
try:
|
||||
self.sendModeButton.setEnabled(plugin.is_setup)
|
||||
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.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)
|
||||
|
||||
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:
|
||||
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)
|
||||
|
||||
|
||||
def onActiveStreamChanged(self, plugin):
|
||||
|
||||
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)):
|
||||
self.populateProjectStreams(plugin)
|
||||
plugin.onStreamCreateClicked()
|
||||
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
|
||||
|
||||
self.populateActiveStreamBranchDropdown(plugin)
|
||||
self.populateActiveCommitDropdown(plugin)
|
||||
except Exception as e:
|
||||
logToUser(str(e), level=2, func = inspect.stack()[0][3], plugin=self)
|
||||
|
||||
def populateLayerSendModeDropdown(self):
|
||||
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)
|
||||
|
||||
def populateActiveStreamBranchDropdown(self, plugin):
|
||||
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)
|
||||
return
|
||||
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 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
|
||||
try:
|
||||
self.commitDropdown.clear()
|
||||
if plugin.active_stream is None: return
|
||||
branchName = self.streamBranchDropdown.currentText()
|
||||
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)
|
||||
return
|
||||
elif plugin.active_stream[1]:
|
||||
for b in plugin.active_stream[1].branches.items:
|
||||
if b.name == branchName:
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,312 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SpeckleQGISDialogBase</class>
|
||||
<widget class="QDockWidget" name="SpeckleQGISDialogBase">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>575</width>
|
||||
<height>651</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="leftMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
|
||||
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="streamListButtons">
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="streamListLabel">
|
||||
<property name="text">
|
||||
<string>Stream</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="streamListButtons" stretch="20,1">
|
||||
<item>
|
||||
<widget class="QComboBox" name="streamList"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="streams_add_button">
|
||||
<property name="text">
|
||||
<string> </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="streams_remove_button">
|
||||
<property name="text">
|
||||
<string> </string>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>10</width>
|
||||
<height>10</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
|
||||
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="streamBranchLabel">
|
||||
<property name="text">
|
||||
<string>Branch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="streamBranchDropdown"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="commitLabel">
|
||||
<property name="text">
|
||||
<string>Commit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="commitDropdown"/>
|
||||
</item>
|
||||
|
||||
<item row="4" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
|
||||
<item row="5" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="sendModeButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Send</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="receiveModeButton">
|
||||
<property name="text">
|
||||
<string>Receive</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="layerSendModeDropdown"/>
|
||||
</item>
|
||||
|
||||
|
||||
|
||||
<item row="7" column="1">
|
||||
<widget class="QListWidget" name="layersWidget">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="resizeMode">
|
||||
<enum>QListView::Fixed</enum>
|
||||
</property>
|
||||
<property name="viewMode">
|
||||
<enum>QListView::ListMode</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
|
||||
<item row="8" 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="saveLayerSelection">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save current layer selection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="messageLabel">
|
||||
<property name="text">
|
||||
<string>Message</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QLineEdit" name="messageInput">
|
||||
<property name="placeholderText">
|
||||
<string>Sent XXX objects from QGIS</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
|
||||
|
||||
<item row="10" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<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="runButton">
|
||||
<property name="text">
|
||||
<string> SEND</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
|
||||
</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">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
|
||||
<item>
|
||||
<widget class="QPushButton" name="reloadButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Refresh</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="closeButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
|
||||
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,316 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SpeckleQArcGISDialog</class>
|
||||
<widget class="QMainWindow" name="SpeckleQArcGISDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayoutTitleBar">
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="leftMargin">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
|
||||
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="streamListButtons">
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="streamListLabel">
|
||||
<property name="text">
|
||||
<string>Stream</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="streamListButtons" stretch="20,1">
|
||||
<item>
|
||||
<widget class="QComboBox" name="streamList"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="streams_add_button">
|
||||
<property name="text">
|
||||
<string> </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="streams_remove_button">
|
||||
<property name="text">
|
||||
<string> </string>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>10</width>
|
||||
<height>10</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
|
||||
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="streamBranchLabel">
|
||||
<property name="text">
|
||||
<string>Branch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="streamBranchDropdown"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="commitLabel">
|
||||
<property name="text">
|
||||
<string>Commit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="commitDropdown"/>
|
||||
</item>
|
||||
|
||||
<item row="4" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
|
||||
<item row="5" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="sendModeButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Send</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="receiveModeButton">
|
||||
<property name="text">
|
||||
<string>Receive</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="layerSendModeDropdown"/>
|
||||
</item>
|
||||
|
||||
|
||||
|
||||
<item row="7" column="1">
|
||||
<widget class="QListWidget" name="layersWidget">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="resizeMode">
|
||||
<enum>QListView::Fixed</enum>
|
||||
</property>
|
||||
<property name="viewMode">
|
||||
<enum>QListView::ListMode</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
|
||||
<item row="8" 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="saveLayerSelection">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Set visible layers as selection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="messageLabel">
|
||||
<property name="text">
|
||||
<string>Message</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QLineEdit" name="messageInput">
|
||||
<property name="placeholderText">
|
||||
<string>Sent XXX objects from ArcGIS</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
|
||||
|
||||
<item row="10" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<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="runButton">
|
||||
<property name="text">
|
||||
<string> SEND</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
|
||||
</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">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
|
||||
<item>
|
||||
<widget class="QPushButton" name="reloadButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Refresh</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="closeButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
|
||||
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||