widget for upgrading dependencies; line breaks in notifications; formatting
This commit is contained in:
+182
-99
@@ -1,4 +1,3 @@
|
||||
|
||||
import inspect
|
||||
from typing import Any, List
|
||||
|
||||
@@ -11,13 +10,21 @@ 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
|
||||
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_report import ReportDialog
|
||||
from specklepy_qt_ui.qt_ui.widget_dependencies_upgrade import DependenciesUpgradeDialog
|
||||
from specklepy_qt_ui.qt_ui.widget_report import ReportDialog
|
||||
|
||||
|
||||
class LogWidget(QWidget):
|
||||
|
||||
dataStorage = None
|
||||
msgs: List[str] = []
|
||||
used_btns: List[int] = []
|
||||
@@ -31,54 +38,54 @@ class LogWidget(QWidget):
|
||||
speckle_version: str
|
||||
dockwidget: Any = None
|
||||
reportDialog: Any = None
|
||||
|
||||
|
||||
# constructor
|
||||
def __init__(self, parent=None):
|
||||
super(LogWidget, self).__init__(parent)
|
||||
self.parentWidget = parent
|
||||
#print(self.parentWidget)
|
||||
# print(self.parentWidget)
|
||||
self.max_msg = 8
|
||||
|
||||
# create a temporary floating button
|
||||
width = 0 #parent.frameSize().width()
|
||||
height = 0 # parent.frameSize().height()
|
||||
|
||||
|
||||
# create a temporary floating button
|
||||
width = 0 # parent.frameSize().width()
|
||||
height = 0 # parent.frameSize().height()
|
||||
|
||||
self.setAttribute(QtCore.Qt.WA_StyledBackground, True)
|
||||
self.setStyleSheet("background-color: rgba(250,250,250,80);")
|
||||
|
||||
|
||||
self.layout = QVBoxLayout(self)
|
||||
self.layout.setContentsMargins(0, 60, 10, 20)
|
||||
self.layout.setAlignment(Qt.AlignBottom)
|
||||
self.layout.setAlignment(Qt.AlignBottom)
|
||||
self.setGeometry(0, 0, width, height)
|
||||
self.createBtns()
|
||||
|
||||
self.hide()
|
||||
self.hide()
|
||||
|
||||
def createBtns(self):
|
||||
# generate 100 buttons to use later
|
||||
self.btns = []
|
||||
for i in range(self.max_msg):
|
||||
button = QPushButton(f"👌 Error") # to '{streamName}' Sent , v
|
||||
#button.setStyleSheet("QPushButton {color: black; border: 0px;border-radius: 17px;padding: 20px;height: 40px;text-align: left;"+ f"{BACKGR_COLOR_GREY}" + "}")
|
||||
button = QPushButton(f"👌 Error") # to '{streamName}' Sent , v
|
||||
# button.setStyleSheet("QPushButton {color: black; border: 0px;border-radius: 17px;padding: 20px;height: 40px;text-align: left;"+ f"{BACKGR_COLOR_GREY}" + "}")
|
||||
button.clicked.connect(lambda: self.btnClicked())
|
||||
self.btns.append(button)
|
||||
|
||||
# overriding the mouseReleaseEvent method
|
||||
def mouseReleaseEvent(self, event):
|
||||
#print("Mouse Release Event")
|
||||
self.hide()
|
||||
#self.parentWidget.hideError()
|
||||
# print("Mouse Release Event")
|
||||
self.hide()
|
||||
# self.parentWidget.hideError()
|
||||
|
||||
def hide(self):
|
||||
#print("___HIDE LOG WIDGET")
|
||||
|
||||
# print("___HIDE LOG WIDGET")
|
||||
|
||||
self.setGeometry(0, 0, 0, 0)
|
||||
|
||||
# remove all buttons
|
||||
for i in reversed(range(self.layout.count())):
|
||||
#print(self.layout.itemAt(i))
|
||||
#print(self.layout.itemAt(i).widget())
|
||||
self.layout.itemAt(i).widget().setParent(None)
|
||||
for i in reversed(range(self.layout.count())):
|
||||
# print(self.layout.itemAt(i))
|
||||
# print(self.layout.itemAt(i).widget())
|
||||
self.layout.itemAt(i).widget().setParent(None)
|
||||
|
||||
self.createBtns()
|
||||
# remove list of used btns
|
||||
@@ -86,21 +93,25 @@ class LogWidget(QWidget):
|
||||
self.msgs.clear()
|
||||
|
||||
def addButton(self, obj: dict):
|
||||
#print("Add button")
|
||||
# print("Add button")
|
||||
text: str = obj["text"]
|
||||
level: int = obj["level"]
|
||||
url: str = obj["url"]
|
||||
url: str = obj["url"]
|
||||
blue: bool = obj["blue"]
|
||||
report: bool = obj["report"]
|
||||
|
||||
self.setGeometry(
|
||||
0,
|
||||
0,
|
||||
self.parentWidget.frameSize().width(),
|
||||
self.parentWidget.frameSize().height(),
|
||||
)
|
||||
|
||||
self.setGeometry(0, 0, self.parentWidget.frameSize().width(), self.parentWidget.frameSize().height())
|
||||
|
||||
# find index of the first unused button
|
||||
btn, index = self.getNextBtn()
|
||||
#print(btn)
|
||||
# print(btn)
|
||||
btn.setAccessibleName(url)
|
||||
#print(btn)
|
||||
# print(btn)
|
||||
btn.setText(text)
|
||||
self.resizeToText(btn)
|
||||
|
||||
@@ -108,45 +119,79 @@ class LogWidget(QWidget):
|
||||
boxLayout = QHBoxLayout(widget)
|
||||
|
||||
spacer = QPushButton("")
|
||||
spacer.setStyleSheet("QPushButton {padding:0px;"+ f"{BACKGR_COLOR_TRANSPARENT}" + "}")
|
||||
spacer.setStyleSheet(
|
||||
"QPushButton {padding:0px;" + f"{BACKGR_COLOR_TRANSPARENT}" + "}"
|
||||
)
|
||||
spacer.setMaximumWidth(10)
|
||||
|
||||
# add btns to widget layout
|
||||
boxLayout.addWidget(btn) #, alignment=Qt.AlignCenter)
|
||||
|
||||
# add report
|
||||
reportBtn = QPushButton(f"☑️ Report") # 📈 to '{streamName}' Sent , v
|
||||
|
||||
# add btns to widget layout
|
||||
boxLayout.addWidget(btn) # , alignment=Qt.AlignCenter)
|
||||
|
||||
# add report
|
||||
reportBtn = QPushButton(f"☑️ Report") # 📈 to '{streamName}' Sent , v
|
||||
reportBtn.clicked.connect(lambda: self.showReport())
|
||||
reportBtn.setMaximumWidth(150)
|
||||
reportBtn.setStyleSheet("QPushButton {color: white; border-radius: 17px;padding:0px;padding-left: 10px;padding-right: 10px;text-align: center;"+ f"{NEW_GREY}" + "} QPushButton:hover { "+ f"{NEW_GREY_HIGHLIGHT}" + " }")
|
||||
reportBtn.setStyleSheet(
|
||||
"QPushButton {color: white; border-radius: 17px;padding:0px;padding-left: 10px;padding-right: 10px;text-align: center;"
|
||||
+ f"{NEW_GREY}"
|
||||
+ "} QPushButton:hover { "
|
||||
+ f"{NEW_GREY_HIGHLIGHT}"
|
||||
+ " }"
|
||||
)
|
||||
|
||||
if report is True:
|
||||
# color report btn
|
||||
if report is True:
|
||||
# color report btn
|
||||
reportList = self.dataStorage.latestActionReport
|
||||
if reportList is not None:
|
||||
if reportList is not None:
|
||||
for item in reportList:
|
||||
if item["errors"] != "":
|
||||
reportBtn.setText("⚠️ Report")
|
||||
#reportBtn.setStyleSheet("QPushButton {color: white; border-radius: 17px;padding:0px;padding-left: 10px;padding-right: 10px;text-align: center;"+ f"{BACKGR_ERROR_COLOR}" + "} QPushButton:hover { "+ f"{BACKGR_ERROR_COLOR_LIGHT}" + " }")
|
||||
break
|
||||
# reportBtn.setStyleSheet("QPushButton {color: white; border-radius: 17px;padding:0px;padding-left: 10px;padding-right: 10px;text-align: center;"+ f"{BACKGR_ERROR_COLOR}" + "} QPushButton:hover { "+ f"{BACKGR_ERROR_COLOR_LIGHT}" + " }")
|
||||
break
|
||||
|
||||
boxLayout.addWidget(reportBtn)
|
||||
boxLayout.addWidget(spacer)
|
||||
|
||||
if url != "":
|
||||
widget.setStyleSheet("QWidget {border-radius: 17px;padding: 20px;height: 40px;text-align: left;"+ f"{BACKGR_COLOR}" + "} QWidget:hover { "+ f"{BACKGR_COLOR_LIGHT}" + " }")
|
||||
btn.setStyleSheet("QPushButton {color: white;border: 0px; padding:0px; padding-left: 10px;text-align: left;"+ f"{BACKGR_COLOR_TRANSPARENT}" + "}")
|
||||
else: # without url
|
||||
if blue is False:
|
||||
widget.setStyleSheet("QWidget {border-radius: 17px;padding: 20px;height: 40px;text-align: left;"+ f"{BACKGR_COLOR_GREY}" + "}")
|
||||
btn.setStyleSheet("QPushButton {color: black; border: 0px; padding:0px; padding-left: 10px;text-align: left;"+ f"{BACKGR_COLOR_TRANSPARENT}" + "}")
|
||||
else: # blue, no URL (after receive)
|
||||
widget.setStyleSheet("QWidget {border-radius: 17px;padding: 20px;height: 40px;text-align: left;"+ f"{BACKGR_COLOR}" + "}")
|
||||
btn.setStyleSheet("QPushButton {color: white;border: 0px; padding:0px; padding-left: 10px;text-align: left;"+ f"{BACKGR_COLOR_TRANSPARENT}" + "}")
|
||||
|
||||
self.reportBtn = reportBtn
|
||||
widget.setStyleSheet(
|
||||
"QWidget {border-radius: 17px;padding: 20px;height: 40px;text-align: left;"
|
||||
+ f"{BACKGR_COLOR}"
|
||||
+ "} QWidget:hover { "
|
||||
+ f"{BACKGR_COLOR_LIGHT}"
|
||||
+ " }"
|
||||
)
|
||||
btn.setStyleSheet(
|
||||
"QPushButton {color: white;border: 0px; padding:0px; padding-left: 10px;text-align: left;"
|
||||
+ f"{BACKGR_COLOR_TRANSPARENT}"
|
||||
+ "}"
|
||||
)
|
||||
else: # without url
|
||||
if blue is False:
|
||||
widget.setStyleSheet(
|
||||
"QWidget {border-radius: 17px;padding: 20px;height: 40px;text-align: left;"
|
||||
+ f"{BACKGR_COLOR_GREY}"
|
||||
+ "}"
|
||||
)
|
||||
btn.setStyleSheet(
|
||||
"QPushButton {color: black; border: 0px; padding:0px; padding-left: 10px;text-align: left;"
|
||||
+ f"{BACKGR_COLOR_TRANSPARENT}"
|
||||
+ "}"
|
||||
)
|
||||
else: # blue, no URL (after receive)
|
||||
widget.setStyleSheet(
|
||||
"QWidget {border-radius: 17px;padding: 20px;height: 40px;text-align: left;"
|
||||
+ f"{BACKGR_COLOR}"
|
||||
+ "}"
|
||||
)
|
||||
btn.setStyleSheet(
|
||||
"QPushButton {color: white;border: 0px; padding:0px; padding-left: 10px;text-align: left;"
|
||||
+ f"{BACKGR_COLOR_TRANSPARENT}"
|
||||
+ "}"
|
||||
)
|
||||
|
||||
self.layout.addWidget(widget) #, alignment=Qt.AlignCenter)
|
||||
self.reportBtn = reportBtn
|
||||
|
||||
self.layout.addWidget(widget) # , alignment=Qt.AlignCenter)
|
||||
self.msgs.append(text)
|
||||
self.used_btns.append(1)
|
||||
|
||||
@@ -156,91 +201,129 @@ class LogWidget(QWidget):
|
||||
self.reportDialog.applyReport()
|
||||
self.reportDialog.show()
|
||||
return
|
||||
|
||||
|
||||
def openURL(self, url: str = ""):
|
||||
try:
|
||||
metrics.track("Connector Action", self.dataStorage.active_account, {"name": "Open In Web", "connector_version": str(self.speckle_version)})
|
||||
metrics.track(
|
||||
"Connector Action",
|
||||
self.dataStorage.active_account,
|
||||
{"name": "Open In Web", "connector_version": str(self.speckle_version)},
|
||||
)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print(inspect.stack()[0][3])
|
||||
|
||||
print(e)
|
||||
print(inspect.stack()[0][3])
|
||||
|
||||
if url is not None and url != "":
|
||||
webbrowser.open(url, new=0, autoraise=True)
|
||||
|
||||
|
||||
def btnClicked(self, url = ""):
|
||||
def btnClicked(self, url=""):
|
||||
try:
|
||||
btn = self.sender()
|
||||
url = btn.accessibleName()
|
||||
|
||||
if url == "" or not isinstance(url, str):
|
||||
if url == "" or not isinstance(url, str):
|
||||
return
|
||||
elif isinstance(url, str):
|
||||
if url.startswith("http"):
|
||||
self.openURL(url)
|
||||
elif isinstance(url, str):
|
||||
if url.startswith("http"):
|
||||
self.openURL(url)
|
||||
elif url.startswith("dependencies"):
|
||||
try:
|
||||
metrics.track(
|
||||
"Connector Action",
|
||||
self.dataStorage.active_account,
|
||||
{
|
||||
"name": "Details on resolving dependencies",
|
||||
"connector_version": str(
|
||||
self.dataStorage.plugin_version
|
||||
),
|
||||
},
|
||||
)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.dependenciesDialog = DependenciesUpgradeDialog()
|
||||
self.dependenciesDialog.show()
|
||||
|
||||
elif url.startswith("cancel"):
|
||||
|
||||
try: metrics.track("Connector Action", self.dataStorage.active_account, {"name": "Cancel Operation", "connector_version": str(self.dataStorage.plugin_version)})
|
||||
except Exception as e: print(e)
|
||||
try:
|
||||
metrics.track(
|
||||
"Connector Action",
|
||||
self.dataStorage.active_account,
|
||||
{
|
||||
"name": "Cancel Operation",
|
||||
"connector_version": str(
|
||||
self.dataStorage.plugin_version
|
||||
),
|
||||
},
|
||||
)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.hide()
|
||||
|
||||
|
||||
self.parentWidget.cancelOperations()
|
||||
|
||||
except Exception as e:
|
||||
except Exception as e:
|
||||
print(e)
|
||||
pass #logger.logToUser(str(e), level=2, func = inspect.stack()[0][3])
|
||||
#self.hide()
|
||||
pass # logger.logToUser(str(e), level=2, func = inspect.stack()[0][3])
|
||||
# self.hide()
|
||||
|
||||
def getNextBtn(self):
|
||||
index = len(self.used_btns) # get the next "free" button
|
||||
#print(index)
|
||||
#print(self.btns)
|
||||
index = len(self.used_btns) # get the next "free" button
|
||||
# print(index)
|
||||
# print(self.btns)
|
||||
|
||||
if index >= len(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.used_btns.clear()
|
||||
self.createBtns()
|
||||
index = 0
|
||||
index = 0
|
||||
|
||||
btn = self.btns[index]
|
||||
#print(btn)
|
||||
return btn, index
|
||||
|
||||
# print(btn)
|
||||
return btn, index
|
||||
|
||||
def getBtnByKeyword(self, keyword: str):
|
||||
try:
|
||||
new_btn = None
|
||||
for btn in self.btns:
|
||||
url = btn.accessibleName()
|
||||
if keyword in url:
|
||||
new_btn = btn
|
||||
url = btn.accessibleName()
|
||||
if keyword in url:
|
||||
new_btn = btn
|
||||
break
|
||||
return new_btn
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
|
||||
def removeBtnUrl(self, keyword: str = "cancel"):
|
||||
try:
|
||||
btn = self.getBtnByKeyword(keyword)
|
||||
if btn is not None:
|
||||
btn.setAccessibleName("")
|
||||
btn.setStyleSheet("QPushButton {color: black; border: 0px; padding-left: 10px;text-align: left;"+ f"{BACKGR_COLOR_TRANSPARENT}" + "}")
|
||||
#widget.setStyleSheet("QWidget {border-radius: 17px;padding: 20px;height: 40px;text-align: left;"+ f"{BACKGR_COLOR_GREY}" + "}")
|
||||
#btn.setStyleSheet("QPushButton {color: black}")
|
||||
btn.parent().setStyleSheet("QWidget {border-radius: 17px;padding-left: 10px;height: 40px;text-align: left;"+ f"{BACKGR_COLOR_GREY}" + "}")
|
||||
|
||||
btn.setStyleSheet(
|
||||
"QPushButton {color: black; border: 0px; padding-left: 10px;text-align: left;"
|
||||
+ f"{BACKGR_COLOR_TRANSPARENT}"
|
||||
+ "}"
|
||||
)
|
||||
# widget.setStyleSheet("QWidget {border-radius: 17px;padding: 20px;height: 40px;text-align: left;"+ f"{BACKGR_COLOR_GREY}" + "}")
|
||||
# btn.setStyleSheet("QPushButton {color: black}")
|
||||
btn.parent().setStyleSheet(
|
||||
"QWidget {border-radius: 17px;padding-left: 10px;height: 40px;text-align: left;"
|
||||
+ f"{BACKGR_COLOR_GREY}"
|
||||
+ "}"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
|
||||
def resizeToText(self, btn):
|
||||
try:
|
||||
text = btn.text()
|
||||
#if len(text.split("\n"))>2:
|
||||
height = len(text.split("\n"))*25 + 20
|
||||
# if len(text.split("\n"))>2:
|
||||
height = len(text.split("\n")) * 25 + 20
|
||||
btn.setMinimumHeight(height)
|
||||
return btn
|
||||
except Exception as e:
|
||||
return btn
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return btn
|
||||
return btn
|
||||
|
||||
+75
-61
@@ -1,74 +1,88 @@
|
||||
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
from PyQt5 import QtCore
|
||||
|
||||
from specklepy_qt_ui.qt_ui.utils import splitTextIntoLines
|
||||
|
||||
def logToUser(msg: str, func=None, level: int = 2, plugin = None, url = "", blue = False, report = False):
|
||||
#print("Log to user")
|
||||
msg = str(msg)
|
||||
#if func is not None and func != "None":
|
||||
# print(msg + " " + url + "::" + str(func))
|
||||
#else:
|
||||
# print(msg + " " + url )
|
||||
|
||||
dockwidget = plugin
|
||||
try:
|
||||
if url == "" and blue is False: # only for info messages
|
||||
msg = addLevelSymbol(msg, level)
|
||||
if func is not None:
|
||||
msg += "::" + str(func)
|
||||
if dockwidget is None: return
|
||||
|
||||
new_msg = splitTextIntoLines(msg)
|
||||
dockwidget.msgLog.sendMessage.emit({"text":new_msg, "level":level, "url":url, "blue":blue, "report":report})
|
||||
|
||||
except Exception as e: print(e); return
|
||||
def logToUser(
|
||||
msg: str, func=None, level: int = 2, plugin=None, url="", blue=False, report=False
|
||||
):
|
||||
msg = str(msg)
|
||||
dockwidget = plugin
|
||||
try:
|
||||
if url == "" and blue is False: # only for info messages
|
||||
msg = addLevelSymbol(msg, level)
|
||||
if func is not None:
|
||||
msg += "::" + str(func)
|
||||
if dockwidget is None:
|
||||
return
|
||||
|
||||
new_msg = splitTextIntoLines(msg)
|
||||
dockwidget.msgLog.sendMessage.emit(
|
||||
{
|
||||
"text": new_msg,
|
||||
"level": level,
|
||||
"url": url,
|
||||
"blue": blue,
|
||||
"report": report,
|
||||
}
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return
|
||||
|
||||
|
||||
def addLevelSymbol(msg: str, level: int):
|
||||
if level == 0: msg = "🛈 " + msg
|
||||
if level == 1: msg = "⚠️ " + msg
|
||||
if level == 2: msg = "❗ " + msg
|
||||
return msg
|
||||
if level == 0:
|
||||
msg = "🛈 " + msg
|
||||
if level == 1:
|
||||
msg = "⚠️ " + msg
|
||||
if level == 2:
|
||||
msg = "❗ " + msg
|
||||
return msg
|
||||
|
||||
|
||||
def displayUserMsg(msg: str, func=None, level: int = 2):
|
||||
try:
|
||||
window = createWindow(msg, func, level)
|
||||
window.exec_()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
def displayUserMsg(msg: str, func=None, level: int = 2):
|
||||
try:
|
||||
window = createWindow(msg, func, level)
|
||||
window.exec_()
|
||||
except Exception as e: print(e)
|
||||
|
||||
def createWindow(msg_old: str, func=None, level: int = 2):
|
||||
#print("Create window")
|
||||
window = None
|
||||
try:
|
||||
# https://www.techwithtim.net/tutorials/pyqt5-tutorial/messageboxes/
|
||||
window = QMessageBox()
|
||||
msg = ""
|
||||
if len(msg_old)>80:
|
||||
for line in msg_old.split("\n"):
|
||||
line = splitTextIntoLines(line)
|
||||
msg += line + "\n"
|
||||
else:
|
||||
msg = msg_old
|
||||
|
||||
window.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint)
|
||||
if level==0:
|
||||
window.setWindowTitle("Info (Speckle)")
|
||||
window.setIcon(QMessageBox.Icon.Information)
|
||||
if level==1:
|
||||
window.setWindowTitle("Warning (Speckle)")
|
||||
window.setIcon(QMessageBox.Icon.Warning)
|
||||
elif level==2:
|
||||
window.setWindowTitle("Error (Speckle)")
|
||||
window.setIcon(QMessageBox.Icon.Critical)
|
||||
window.setFixedWidth(200)
|
||||
#window.setTextFormat(QtCore.Qt.RichText)
|
||||
# print("Create window")
|
||||
window = None
|
||||
try:
|
||||
# https://www.techwithtim.net/tutorials/pyqt5-tutorial/messageboxes/
|
||||
window = QMessageBox()
|
||||
msg = ""
|
||||
if len(msg_old) > 80:
|
||||
for line in msg_old.split("\n"):
|
||||
line = splitTextIntoLines(line)
|
||||
msg += line + "\n"
|
||||
else:
|
||||
msg = msg_old
|
||||
|
||||
if func is not None:
|
||||
window.setText(str(msg + "\n" + str(func)))
|
||||
else:
|
||||
window.setText(str(msg))
|
||||
#print(window)
|
||||
except Exception as e: print(e)
|
||||
return window
|
||||
window.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint)
|
||||
if level == 0:
|
||||
window.setWindowTitle("Info (Speckle)")
|
||||
window.setIcon(QMessageBox.Icon.Information)
|
||||
if level == 1:
|
||||
window.setWindowTitle("Warning (Speckle)")
|
||||
window.setIcon(QMessageBox.Icon.Warning)
|
||||
elif level == 2:
|
||||
window.setWindowTitle("Error (Speckle)")
|
||||
window.setIcon(QMessageBox.Icon.Critical)
|
||||
window.setFixedWidth(200)
|
||||
# window.setTextFormat(QtCore.Qt.RichText)
|
||||
|
||||
if func is not None:
|
||||
window.setText(str(msg + "\n" + str(func)))
|
||||
else:
|
||||
window.setText(str(msg))
|
||||
# print(window)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return window
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DependenciesUpgradeDialog</class>
|
||||
<widget class="QWidget" name="ReportDialog">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="search_form">
|
||||
<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="QVBoxLayout" name="verticalLayout">
|
||||
|
||||
<item row="2" >
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
|
||||
<item>
|
||||
<widget class="QLabel" name="report_label">
|
||||
<property name="text">
|
||||
<string> </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="report_widget">
|
||||
<property name="text">
|
||||
<string>Option: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
|
||||
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
|
||||
<item row="2" column="0">
|
||||
<widget class="QWidget">
|
||||
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_upgrade">
|
||||
<property name="text">
|
||||
<string>Upgrade dependencies automatically</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_cancel">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
|
||||
</layout>
|
||||
</widget>
|
||||
|
||||
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+48
-30
@@ -1,59 +1,77 @@
|
||||
|
||||
from textwrap import wrap
|
||||
|
||||
def splitTextIntoLines(text: str = "", number: int= 40) -> str:
|
||||
|
||||
#print("__splitTextIntoLines")
|
||||
#print(text)
|
||||
def splitTextIntoLines(text: str = "", number: int = 40) -> str:
|
||||
# print("__splitTextIntoLines")
|
||||
# print(text)
|
||||
msg = ""
|
||||
try:
|
||||
if len(text)>number:
|
||||
if len(text) > number:
|
||||
try:
|
||||
lines = wrap(text, number)
|
||||
for i, x in enumerate(lines):
|
||||
msg += x
|
||||
if i!= len(lines) - 1:
|
||||
for i, text_part in enumerate(text.split("\n")):
|
||||
lines = wrap(text_part, number)
|
||||
for k, x in enumerate(lines):
|
||||
msg += x
|
||||
if k != len(lines) - 1:
|
||||
msg += "\n"
|
||||
if i != len(text.split("\n")) - 1:
|
||||
msg += "\n"
|
||||
except Exception as e: print(e)
|
||||
else:
|
||||
except Exception as e:
|
||||
print(e)
|
||||
else:
|
||||
msg = text
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print(text)
|
||||
return msg
|
||||
|
||||
def constructCommitURL(streamWrapper, branch_id: str = None, commit_id: str = None) -> str:
|
||||
import requests
|
||||
|
||||
def constructCommitURL(
|
||||
streamWrapper, branch_id: str = None, commit_id: str = None
|
||||
) -> str:
|
||||
import requests
|
||||
|
||||
try:
|
||||
if isinstance(streamWrapper, tuple) or isinstance(streamWrapper, list):
|
||||
streamWrapper = streamWrapper[0]
|
||||
streamUrl = streamWrapper.stream_url.split("?")[0].split("&")[0].split("@")[0]
|
||||
r = requests.get(streamUrl)
|
||||
|
||||
url = streamUrl
|
||||
# check for frontend2
|
||||
try:
|
||||
header = r.headers['x-speckle-frontend-2']
|
||||
url = streamUrl.replace("streams", "projects") + "/models/" + branch_id + "@" + commit_id
|
||||
|
||||
url = streamUrl
|
||||
# check for frontend2
|
||||
try:
|
||||
header = r.headers["x-speckle-frontend-2"]
|
||||
url = (
|
||||
streamUrl.replace("streams", "projects")
|
||||
+ "/models/"
|
||||
+ branch_id
|
||||
+ "@"
|
||||
+ commit_id
|
||||
)
|
||||
except:
|
||||
url = streamUrl.replace("projects", "streams") + "/commits/" + commit_id
|
||||
return url
|
||||
return url
|
||||
except:
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
def constructCommitURLfromServerCommit(serverURL: str, stream_id: str) -> str:
|
||||
import requests
|
||||
import requests
|
||||
|
||||
r = requests.get(serverURL)
|
||||
|
||||
# check for frontend2
|
||||
try:
|
||||
header = r.headers['x-speckle-frontend-2']
|
||||
#url = streamUrl.replace("streams", "projects") + "/models/" + branch_id + "@" + commit_id
|
||||
url = serverURL + "/projects/" + stream_id # replace with 'projects' after it's implemented in Specklepy
|
||||
|
||||
# check for frontend2
|
||||
try:
|
||||
header = r.headers["x-speckle-frontend-2"]
|
||||
# url = streamUrl.replace("streams", "projects") + "/models/" + branch_id + "@" + commit_id
|
||||
url = (
|
||||
serverURL + "/projects/" + stream_id
|
||||
) # replace with 'projects' after it's implemented in Specklepy
|
||||
except:
|
||||
url = serverURL + "/streams/" + stream_id
|
||||
return url
|
||||
return url
|
||||
|
||||
#def removeSpecialCharacters(text: str) -> str:
|
||||
|
||||
# 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
|
||||
|
||||
+205
-93
@@ -12,7 +12,7 @@ from PyQt5.QtCore import pyqtSignal
|
||||
from specklepy.core.api.models import Stream, Branch, Commit
|
||||
from specklepy.core.api.client import SpeckleClient
|
||||
from specklepy.logging.exceptions import SpeckleException
|
||||
from specklepy.core.api.credentials import get_local_accounts #, StreamWrapper
|
||||
from specklepy.core.api.credentials import get_local_accounts # , StreamWrapper
|
||||
from specklepy.core.api.wrapper import StreamWrapper
|
||||
from specklepy.logging import metrics
|
||||
|
||||
@@ -20,11 +20,11 @@ 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(
|
||||
os.path.join(os.path.join(os.path.dirname(__file__), "ui", "add_stream_modal.ui") )
|
||||
os.path.join(os.path.join(os.path.dirname(__file__), "ui", "add_stream_modal.ui"))
|
||||
)
|
||||
|
||||
class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
|
||||
|
||||
class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
|
||||
search_button: QtWidgets.QPushButton = None
|
||||
search_text_field: QtWidgets.QLineEdit = None
|
||||
search_results_list: QtWidgets.QListWidget = None
|
||||
@@ -35,192 +35,305 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
|
||||
branch_result: Branch = None
|
||||
commit_result: Commit = None
|
||||
speckle_client: Union[SpeckleClient, None] = None
|
||||
dataStorage: DataStorage = None
|
||||
dataStorage: DataStorage = None
|
||||
|
||||
#Events
|
||||
# Events
|
||||
handleStreamAdd = pyqtSignal(object)
|
||||
|
||||
def __init__(self, parent=None, speckle_client: SpeckleClient = None):
|
||||
super(AddStreamModalDialog,self).__init__(parent,QtCore.Qt.WindowStaysOnTopHint)
|
||||
super(AddStreamModalDialog, self).__init__(
|
||||
parent, QtCore.Qt.WindowStaysOnTopHint
|
||||
)
|
||||
self.speckle_client = speckle_client
|
||||
self.setupUi(self)
|
||||
self.setWindowTitle("Add Speckle stream")
|
||||
|
||||
self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False)
|
||||
self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False)
|
||||
|
||||
def connect(self):
|
||||
self.search_button.clicked.connect(self.onSearchClicked)
|
||||
self.search_results_list.currentItemChanged.connect( self.searchResultChanged )
|
||||
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.search_results_list.currentItemChanged.connect(self.searchResultChanged)
|
||||
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.accounts_dropdown.currentIndexChanged.connect(self.onAccountSelected)
|
||||
self.populate_accounts_dropdown()
|
||||
|
||||
def searchResultChanged(self):
|
||||
try:
|
||||
index = self.search_results_list.currentIndex().row()
|
||||
if index == -1: self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False)
|
||||
else: self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(True)
|
||||
if index == -1:
|
||||
self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(
|
||||
False
|
||||
)
|
||||
else:
|
||||
self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(
|
||||
True
|
||||
)
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3])
|
||||
logToUser(e, level=2, func=inspect.stack()[0][3])
|
||||
return
|
||||
|
||||
def getAllStreams(self):
|
||||
try:
|
||||
query = ""
|
||||
sw = None
|
||||
sw = None
|
||||
results = []
|
||||
if self.speckle_client is not None:
|
||||
if self.speckle_client is not None:
|
||||
results = self.speckle_client.stream.search(query)
|
||||
try: metrics.track("Connector Action", self.dataStorage.active_account, {"name": "Stream Search By Name", "connector_version": str(self.dataStorage.plugin_version)})
|
||||
except Exception as e: logToUser(e, level = 2, func = inspect.stack()[0][3] )
|
||||
|
||||
elif self.speckle_client is None:
|
||||
logToUser(f"Account cannot be authenticated: {self.accounts_dropdown.currentText()}", level = 1, func = inspect.stack()[0][3])
|
||||
|
||||
try:
|
||||
metrics.track(
|
||||
"Connector Action",
|
||||
self.dataStorage.active_account,
|
||||
{
|
||||
"name": "Stream Search By Name",
|
||||
"connector_version": str(self.dataStorage.plugin_version),
|
||||
},
|
||||
)
|
||||
except Exception as e:
|
||||
logToUser(e, level=2, func=inspect.stack()[0][3])
|
||||
|
||||
elif self.speckle_client is None:
|
||||
logToUser(
|
||||
f"Account cannot be authenticated: {self.accounts_dropdown.currentText()}",
|
||||
level=1,
|
||||
func=inspect.stack()[0][3],
|
||||
)
|
||||
|
||||
self.stream_results = results
|
||||
self.populateResultsList()
|
||||
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3])
|
||||
logToUser(e, level=2, func=inspect.stack()[0][3])
|
||||
return
|
||||
|
||||
|
||||
def onSearchClicked(self):
|
||||
try:
|
||||
query = self.search_text_field.text()
|
||||
sw = None
|
||||
sw = None
|
||||
streams = []
|
||||
branch = None
|
||||
commit = None
|
||||
#print("_____ onSearchClicked___")
|
||||
if "http" in query and len(query.split("/")) >= 3: # URL
|
||||
# print("_____ onSearchClicked___")
|
||||
if "http" in query and len(query.split("/")) >= 3: # URL
|
||||
sw = StreamWrapper(query)
|
||||
stream = sw.get_client().stream.get(id = sw.stream_id, branch_limit = 100, commit_limit = 100)
|
||||
if isinstance(stream, Stream):
|
||||
stream = sw.get_client().stream.get(
|
||||
id=sw.stream_id, branch_limit=100, commit_limit=100
|
||||
)
|
||||
if isinstance(stream, Stream):
|
||||
streams = [stream]
|
||||
|
||||
if "/branches/" in query:
|
||||
#print("branches")
|
||||
branch_name = query.split("/branches/")[len(query.split("/branches/"))-1].split("/")[0].split("?")[0].split("&")[0].split("@")[0]
|
||||
#print(branch_name)
|
||||
#print(stream)
|
||||
#print(len(stream.branches.items))
|
||||
# print("branches")
|
||||
branch_name = (
|
||||
query.split("/branches/")[
|
||||
len(query.split("/branches/")) - 1
|
||||
]
|
||||
.split("/")[0]
|
||||
.split("?")[0]
|
||||
.split("&")[0]
|
||||
.split("@")[0]
|
||||
)
|
||||
# print(branch_name)
|
||||
# print(stream)
|
||||
# print(len(stream.branches.items))
|
||||
for br in stream.branches.items:
|
||||
name = urllib.parse.quote(br.name)
|
||||
#print(name)
|
||||
# print(name)
|
||||
if name == branch_name:
|
||||
branch = br
|
||||
break
|
||||
break
|
||||
elif "/commits/" in query:
|
||||
#print("commits")
|
||||
commit_id = query.split("/commits/")[len(query.split("/commits/"))-1].split("/")[0].split("?")[0].split("&")[0].split("@")[0]
|
||||
# print("commits")
|
||||
commit_id = (
|
||||
query.split("/commits/")[len(query.split("/commits/")) - 1]
|
||||
.split("/")[0]
|
||||
.split("?")[0]
|
||||
.split("&")[0]
|
||||
.split("@")[0]
|
||||
)
|
||||
for br in stream.branches.items:
|
||||
for com in br.commits.items:
|
||||
if com.id == commit_id:
|
||||
branch = br
|
||||
commit = com
|
||||
#print(branch)
|
||||
#print(commit)
|
||||
commit = com
|
||||
# print(branch)
|
||||
# print(commit)
|
||||
break
|
||||
elif isinstance(stream, Exception):
|
||||
print(stream)
|
||||
#if "/commits/" in query:
|
||||
# if "/commits/" in query:
|
||||
# branch_id = query.split("/commits/")[len(query.split("/commits/"))-1].split("/")[0].split("?")[0].split("&")[0].split("@")[0]
|
||||
# for com in stream.
|
||||
# if br.id == branch_id:
|
||||
# branch = br
|
||||
# break
|
||||
|
||||
try: metrics.track("Connector Action", self.dataStorage.active_account, {"name": "Stream Search By URL", "connector_version": str(self.dataStorage.plugin_version)})
|
||||
except Exception as e: logToUser(e, level = 2, func = inspect.stack()[0][3] )
|
||||
|
||||
elif self.speckle_client is not None:
|
||||
# break
|
||||
|
||||
try:
|
||||
metrics.track(
|
||||
"Connector Action",
|
||||
self.dataStorage.active_account,
|
||||
{
|
||||
"name": "Stream Search By URL",
|
||||
"connector_version": str(self.dataStorage.plugin_version),
|
||||
},
|
||||
)
|
||||
except Exception as e:
|
||||
logToUser(e, level=2, func=inspect.stack()[0][3])
|
||||
|
||||
elif self.speckle_client is not None:
|
||||
streams = self.speckle_client.stream.search(query)
|
||||
try: metrics.track("Connector Action", self.dataStorage.active_account, {"name": "Stream Search By Name", "connector_version": str(self.dataStorage.plugin_version)})
|
||||
except Exception as e: logToUser(e, level = 2, func = inspect.stack()[0][3] )
|
||||
|
||||
elif self.speckle_client is None:
|
||||
logToUser(f"Account cannot be authenticated: {self.accounts_dropdown.currentText()}", level = 1, func = inspect.stack()[0][3])
|
||||
|
||||
try:
|
||||
metrics.track(
|
||||
"Connector Action",
|
||||
self.dataStorage.active_account,
|
||||
{
|
||||
"name": "Stream Search By Name",
|
||||
"connector_version": str(self.dataStorage.plugin_version),
|
||||
},
|
||||
)
|
||||
except Exception as e:
|
||||
logToUser(e, level=2, func=inspect.stack()[0][3])
|
||||
|
||||
elif self.speckle_client is None:
|
||||
logToUser(
|
||||
f"Account cannot be authenticated: {self.accounts_dropdown.currentText()}",
|
||||
level=1,
|
||||
func=inspect.stack()[0][3],
|
||||
)
|
||||
|
||||
self.stream_results = streams
|
||||
self.branch_result = branch
|
||||
self.commit_result = commit
|
||||
self.populateResultsList(sw)
|
||||
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3])
|
||||
logToUser(e, level=2, func=inspect.stack()[0][3])
|
||||
return
|
||||
|
||||
def populateResultsList(self, sw = None):
|
||||
|
||||
def populateResultsList(self, sw=None):
|
||||
try:
|
||||
self.search_results_list.clear()
|
||||
if isinstance(self.stream_results, SpeckleException):
|
||||
logToUser("Some streams cannot be accessed", level = 1, func = inspect.stack()[0][3])
|
||||
return
|
||||
if isinstance(self.stream_results, SpeckleException):
|
||||
logToUser(
|
||||
"Some streams cannot be accessed",
|
||||
level=1,
|
||||
func=inspect.stack()[0][3],
|
||||
)
|
||||
return
|
||||
for stream in self.stream_results:
|
||||
host = ""
|
||||
if sw is not None:
|
||||
host = sw.get_account().serverInfo.url
|
||||
else:
|
||||
else:
|
||||
host = self.speckle_client.account.serverInfo.url
|
||||
|
||||
if isinstance(stream, SpeckleException):
|
||||
logToUser("Some streams cannot be accessed", level = 1, func = inspect.stack()[0][3])
|
||||
else:
|
||||
self.search_results_list.addItems([
|
||||
f"{stream.name}, {stream.id} | {host}" #for stream in self.stream_results
|
||||
])
|
||||
|
||||
if isinstance(stream, SpeckleException):
|
||||
logToUser(
|
||||
"Some streams cannot be accessed",
|
||||
level=1,
|
||||
func=inspect.stack()[0][3],
|
||||
)
|
||||
else:
|
||||
self.search_results_list.addItems(
|
||||
[
|
||||
f"{stream.name}, {stream.id} | {host}" # for stream in self.stream_results
|
||||
]
|
||||
)
|
||||
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):
|
||||
try:
|
||||
if isinstance(self.stream_results, SpeckleException):
|
||||
logToUser("Selected stream cannot be accessed: "+ str(self.stream_results.message), level = 1, func = inspect.stack()[0][3])
|
||||
logToUser(
|
||||
"Selected stream cannot be accessed: "
|
||||
+ str(self.stream_results.message),
|
||||
level=1,
|
||||
func=inspect.stack()[0][3],
|
||||
)
|
||||
return
|
||||
else:
|
||||
try:
|
||||
index = self.search_results_list.currentIndex().row()
|
||||
stream = self.stream_results[index]
|
||||
item = self.search_results_list.item(index)
|
||||
url = constructCommitURLfromServerCommit(item.text().split(" | ")[1], item.text().split(", ")[1].split(" | ")[0])
|
||||
#url = item.text().split(" | ")[1] + "/streams/" + item.text().split(", ")[1].split(" | ")[0]
|
||||
sw = StreamWrapper(url)
|
||||
|
||||
try: metrics.track("Connector Action", self.dataStorage.active_account, {"name": "Stream Add From Search", "connector_version": str(self.dataStorage.plugin_version)})
|
||||
except Exception as e: logToUser(e, level = 2, func = inspect.stack()[0][3] )
|
||||
|
||||
#acc = sw.get_account() #get_local_accounts()[self.accounts_dropdown.currentIndex()]
|
||||
self.handleStreamAdd.emit((sw, self.branch_result, self.commit_result)) #StreamWrapper(f"{acc.serverInfo.url}/streams/{stream.id}?u={acc.userInfo.id}"))
|
||||
url = constructCommitURLfromServerCommit(
|
||||
item.text().split(" | ")[1],
|
||||
item.text().split(", ")[1].split(" | ")[0],
|
||||
)
|
||||
# url = item.text().split(" | ")[1] + "/streams/" + item.text().split(", ")[1].split(" | ")[0]
|
||||
sw = StreamWrapper(url)
|
||||
|
||||
try:
|
||||
metrics.track(
|
||||
"Connector Action",
|
||||
self.dataStorage.active_account,
|
||||
{
|
||||
"name": "Stream Add From Search",
|
||||
"connector_version": str(
|
||||
self.dataStorage.plugin_version
|
||||
),
|
||||
},
|
||||
)
|
||||
except Exception as e:
|
||||
logToUser(e, level=2, func=inspect.stack()[0][3])
|
||||
|
||||
# acc = sw.get_account() #get_local_accounts()[self.accounts_dropdown.currentIndex()]
|
||||
self.handleStreamAdd.emit(
|
||||
(sw, self.branch_result, self.commit_result)
|
||||
) # StreamWrapper(f"{acc.serverInfo.url}/streams/{stream.id}?u={acc.userInfo.id}"))
|
||||
self.close()
|
||||
except Exception as e:
|
||||
logToUser("Some streams cannot be accessed: " + str(e), level = 1, func = inspect.stack()[0][3])
|
||||
return
|
||||
logToUser(
|
||||
"Some streams cannot be accessed: " + str(e),
|
||||
level=1,
|
||||
func=inspect.stack()[0][3],
|
||||
)
|
||||
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 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
|
||||
|
||||
def onAccountSelected(self, index = 0):
|
||||
def onAccountSelected(self, index=0):
|
||||
try:
|
||||
|
||||
try: metrics.track("Connector Action", self.dataStorage.active_account, {"name": "Account Select", "connector_version": str(self.dataStorage.plugin_version)})
|
||||
except Exception as e: logToUser(e, level = 2, func = inspect.stack()[0][3] )
|
||||
|
||||
try:
|
||||
metrics.track(
|
||||
"Connector Action",
|
||||
self.dataStorage.active_account,
|
||||
{
|
||||
"name": "Account Select",
|
||||
"connector_version": str(self.dataStorage.plugin_version),
|
||||
},
|
||||
)
|
||||
except Exception as e:
|
||||
logToUser(e, level=2, func=inspect.stack()[0][3])
|
||||
|
||||
account = self.speckle_accounts[index]
|
||||
self.speckle_client = SpeckleClient(account.serverInfo.url, account.serverInfo.url.startswith("https"))
|
||||
self.speckle_client.authenticate_with_token(token=account.token)
|
||||
self.speckle_client = SpeckleClient(
|
||||
account.serverInfo.url, account.serverInfo.url.startswith("https")
|
||||
)
|
||||
|
||||
try:
|
||||
self.speckle_client.authenticate_with_token(token=account.token)
|
||||
except SpeckleException as ex:
|
||||
raise Exception(f"Dependencies versioning error: {ex.message}")
|
||||
|
||||
self.getAllStreams()
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3])
|
||||
logToUser(e, level=2, func=inspect.stack()[0][3])
|
||||
return
|
||||
|
||||
def populate_accounts_dropdown(self):
|
||||
@@ -235,6 +348,5 @@ class AddStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
|
||||
]
|
||||
)
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3])
|
||||
logToUser(e, level=2, func=inspect.stack()[0][3])
|
||||
return
|
||||
|
||||
|
||||
@@ -6,15 +6,20 @@ from specklepy_qt_ui.qt_ui.logger import logToUser
|
||||
from PyQt5 import QtWidgets, uic, QtCore
|
||||
from PyQt5.QtCore import pyqtSignal
|
||||
from specklepy.core.api.client import SpeckleClient
|
||||
from specklepy.core.api.credentials import Account, get_local_accounts #, StreamWrapper
|
||||
from specklepy.core.api.credentials import (
|
||||
Account,
|
||||
get_local_accounts,
|
||||
) # , StreamWrapper
|
||||
|
||||
from specklepy.logging.exceptions import SpeckleException
|
||||
|
||||
# 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_stream.ui") )
|
||||
os.path.join(os.path.join(os.path.dirname(__file__), "ui", "create_stream.ui"))
|
||||
)
|
||||
|
||||
class CreateStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
|
||||
|
||||
class CreateStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
|
||||
name_field: QtWidgets.QLineEdit = None
|
||||
description_field: QtWidgets.QLineEdit = None
|
||||
dialog_button_box: QtWidgets.QDialogButtonBox = None
|
||||
@@ -23,31 +28,41 @@ class CreateStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
|
||||
|
||||
speckle_client: Union[SpeckleClient, None] = None
|
||||
|
||||
#Events
|
||||
# Events
|
||||
handleStreamCreate = pyqtSignal(Account, str, str, bool)
|
||||
|
||||
def __init__(self, parent=None, speckle_client: SpeckleClient = None):
|
||||
super(CreateStreamModalDialog,self).__init__(parent,QtCore.Qt.WindowStaysOnTopHint)
|
||||
super(CreateStreamModalDialog, self).__init__(
|
||||
parent, QtCore.Qt.WindowStaysOnTopHint
|
||||
)
|
||||
self.speckle_client = speckle_client
|
||||
self.setupUi(self)
|
||||
self.setWindowTitle("Create New Stream")
|
||||
|
||||
self.name_field.textChanged.connect(self.nameCheck)
|
||||
self.dialog_button_box.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(True)
|
||||
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(True)
|
||||
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.accounts_dropdown.currentIndexChanged.connect(self.onAccountSelected)
|
||||
self.populate_accounts_dropdown()
|
||||
|
||||
def nameCheck(self):
|
||||
try:
|
||||
if len(self.name_field.text()) == 0 or 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):
|
||||
@@ -56,27 +71,34 @@ class CreateStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
|
||||
name = self.name_field.text()
|
||||
description = self.description_field.text()
|
||||
public = self.public_toggle.isChecked()
|
||||
self.handleStreamCreate.emit(acc,name,description,public)
|
||||
self.handleStreamCreate.emit(acc, name, description, public)
|
||||
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.handleCancelStreamCreate.emit()
|
||||
# self.handleCancelStreamCreate.emit()
|
||||
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 onAccountSelected(self, index):
|
||||
try:
|
||||
account = self.speckle_accounts[index]
|
||||
self.speckle_client = SpeckleClient(account.serverInfo.url, account.serverInfo.url.startswith("https"))
|
||||
self.speckle_client.authenticate_with_token(token=account.token)
|
||||
self.speckle_client = SpeckleClient(
|
||||
account.serverInfo.url, account.serverInfo.url.startswith("https")
|
||||
)
|
||||
|
||||
try:
|
||||
self.speckle_client.authenticate_with_token(token=account.token)
|
||||
except SpeckleException as ex:
|
||||
raise Exception(f"Dependencies versioning error: {ex.message}")
|
||||
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3])
|
||||
logToUser(e, level=2, func=inspect.stack()[0][3])
|
||||
return
|
||||
|
||||
def populate_accounts_dropdown(self):
|
||||
@@ -91,6 +113,5 @@ class CreateStreamModalDialog(QtWidgets.QWidget, FORM_CLASS):
|
||||
]
|
||||
)
|
||||
except Exception as e:
|
||||
logToUser(e, level = 2, func = inspect.stack()[0][3])
|
||||
logToUser(e, level=2, func=inspect.stack()[0][3])
|
||||
return
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
import os
|
||||
import urllib3
|
||||
import requests
|
||||
import requests_toolbelt
|
||||
|
||||
from PyQt5 import QtWidgets, uic, QtCore
|
||||
|
||||
# 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", "dependencies.ui"))
|
||||
)
|
||||
|
||||
|
||||
class DependenciesUpgradeDialog(QtWidgets.QWidget, FORM_CLASS):
|
||||
report_label: QtWidgets.QLabel = None
|
||||
report_widget: QtWidgets.QTextEdit = None
|
||||
btn_cancel: QtWidgets.QPushButton = None
|
||||
btn_upgrade: QtWidgets.QPushButton = None
|
||||
report_text: str = ""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(DependenciesUpgradeDialog, self).__init__(
|
||||
parent, QtCore.Qt.WindowStaysOnTopHint
|
||||
)
|
||||
self.setupUi(self)
|
||||
self.runAllSetup()
|
||||
|
||||
def runAllSetup(self):
|
||||
self.setWindowTitle("Upgrade Python dependencies (Speckle)")
|
||||
self.setMinimumWidth(900)
|
||||
self.setMinimumHeight(400)
|
||||
self.report_label.setWordWrap(True)
|
||||
self.btn_cancel.clicked.connect(self.onOkClicked)
|
||||
self.btn_upgrade.clicked.connect(self.upgradeDependencies)
|
||||
self.btn_upgrade.setEnabled(True)
|
||||
self.report_text = f"""Speckle plugin requires changes in versions of some Python libraries:
|
||||
\nurllib3: from {urllib3.__version__} to 1.26.16
|
||||
requests: from {requests.__version__} to 2.31.0
|
||||
requests_toolbelt: from {requests_toolbelt.__version__} to 0.10.1
|
||||
\nYou can use the button below run the upgrade automatically.
|
||||
To do it manually, you can run 2 following commands from QGIS Plugins panel->Python Console, and then restart QGIS:
|
||||
\n\ndef upgradeDependencies():
|
||||
\timport subprocess
|
||||
\tfrom speckle.utils.utils import get_qgis_python_path as path
|
||||
\tresult = subprocess.run([path(), "-m", "pip", "install", "requests==2.31.0"],shell=True,timeout=1000,)
|
||||
\tprint(result.returncode)
|
||||
\tresult = subprocess.run([path(), "-m", "pip", "install", "urllib3==1.26.16"],shell=True,timeout=1000,)
|
||||
\tprint(result.returncode)
|
||||
\tresult = subprocess.run([path(), "-m", "pip", "install", "requests_toolbelt==0.10.1"],shell=True,timeout=1000,)
|
||||
\tprint(result.returncode)
|
||||
\nupgradeDependencies()
|
||||
\n\n"""
|
||||
self.report_widget.setText(self.report_text)
|
||||
return
|
||||
|
||||
def onOkClicked(self):
|
||||
self.close()
|
||||
|
||||
def upgradeDependencies(self):
|
||||
self.report_widget.setText("It might take a moment...")
|
||||
self.btn_upgrade.setEnabled(False)
|
||||
res1, res2, res3 = self.runSubprocess()
|
||||
|
||||
if res1.returncode == res2.returncode == res3.returncode == 0:
|
||||
self.report_widget.setText(
|
||||
"Libraries successfully upgraded. Please restart QGIS for Speckle to use the upgraded libraries."
|
||||
)
|
||||
else:
|
||||
self.report_widget.setText(
|
||||
f"Something went wrong. Here are the error logs: \n\n{res1.stdout}\n\n{res2.stdout}"
|
||||
)
|
||||
|
||||
def runSubprocess(self):
|
||||
import subprocess
|
||||
from speckle.utils.utils import get_qgis_python_path as path
|
||||
|
||||
result1 = subprocess.run(
|
||||
[path(), "-m", "pip", "install", "requests==2.31.0"],
|
||||
shell=True,
|
||||
timeout=1000,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
result2 = subprocess.run(
|
||||
[path(), "-m", "pip", "install", "urllib3==1.26.16"],
|
||||
shell=True,
|
||||
timeout=1000,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
result3 = subprocess.run(
|
||||
[path(), "-m", "pip", "install", "requests_toolbelt==0.10.1"],
|
||||
shell=True,
|
||||
timeout=1000,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
return result1, result2, result3
|
||||
Reference in New Issue
Block a user