13 Commits

Author SHA1 Message Date
bdad077350 logging levels modified; log interface for hipa added 2023-05-16 12:23:19 +02:00
051e361c9f base and guiframe 2023-05-01 09:48:14 +02:00
7cac3da421 overdue update 2023-04-05 14:17:18 +02:00
cb7a74d189 qtab composite widget update 2023-02-24 07:26:49 +01:00
9c2c5d7d37 qtab composite widget update 2023-02-23 08:33:44 +01:00
3640082b59 qtab composite widget added 2023-02-23 08:09:14 +01:00
71bcf8c7df merge 2023-02-21 14:55:46 +01:00
6994394da4 update from pyacc 2023-02-21 14:43:41 +01:00
64ce267c84 qradiobutton now excepts default value 2022-10-28 11:05:25 +02:00
cd289303a6 qradiobutton now excepts default value 2022-10-28 10:59:28 +02:00
87def4961c sendelogsls.py uses bdbase.sendelogframe.py 2022-10-24 08:12:47 +02:00
a332aecd87 v1.4.0 2022-10-06 08:26:50 +02:00
fcf37b60c8 overdue 2022-09-14 15:03:15 +02:00
5 changed files with 1792 additions and 220 deletions

145
base.py
View File

@@ -5,10 +5,11 @@ from collections import OrderedDict
from datetime import datetime from datetime import datetime
import getpass import getpass
import h5py import h5py
import logging
import inspect import inspect
import platform import platform
import re
import os import os
import re
import sys import sys
import time import time
@@ -30,6 +31,8 @@ from pyqtacc.bdbase.readjson import ReadJSON
from pyqtacc.bdbase.savehdf import QSaveHDF from pyqtacc.bdbase.savehdf import QSaveHDF
from pyqtacc.bdbase.hdf5filemenu import HDF5GroupBox from pyqtacc.bdbase.hdf5filemenu import HDF5GroupBox
from pyqtacc.bdbase.sendelog import QSendToELOG from pyqtacc.bdbase.sendelog import QSendToELOG
from pyqtacc.bdbase.screenshot import QScreenshot from pyqtacc.bdbase.screenshot import QScreenshot
from pyqtacc.bdbase.guiframe import GUIFrame from pyqtacc.bdbase.guiframe import GUIFrame
@@ -101,32 +104,53 @@ class BaseWindow(QMainWindow):
time_in_seconds=self.time_in_seconds, time_in_seconds=self.time_in_seconds,
reanalysis_time_in_seconds=self.reanalysis_time) reanalysis_time_in_seconds=self.reanalysis_time)
print("date_str", date_str, flush=True) #print("date_str", date_str, flush=True)
write_message_fired = False
for i, (nfig, name) in enumerate( for i, (nfig, name) in enumerate(
zip(self.settings.data["GUI"]["resultsSeq"], zip(self.settings.data["GUI"]["resultsSeq"],
self.settings.data["GUI"]["subResultsTabTitle"])): self.settings.data["GUI"]["subResultsTabTitle"])):
canvas = 'Canvas {0}'.format(i+1) canvas = 'Canvas {0}'.format(i+1)
name_base = name.replace(' ', '_').lower() name_base = name.replace(' ', '_').lower()
for idx in range(0, nfig): if self.all_data['Figure data'][canvas] is not None:
nfig_canvas = len(self.all_data['Figure data'][canvas])
nfig_canvas = min(nfig_canvas, nfig)
else:
nfig_canvas = nfig
for idx in range(0, nfig_canvas):
if self.all_data['Figure data'][canvas] is not None: if self.all_data['Figure data'][canvas] is not None:
name = name_base + "_{0}".format( name = name_base + "_{0}".format(
idx) if idx > 0 else name_base idx) if idx > 0 else name_base
save_dest = (folder_name + date_str + '_' + name + save_dest = (folder_name + date_str + '_' + name +
'.png') '.png')
print("idx", i, save_dest, flush=True)
if not os.path.exists(save_dest): if not os.path.exists(save_dest):
if self.all_data['Figure data'][canvas][ if self.all_data['Figure data'][canvas][
idx] is not None: idx] is not None:
self.all_data['Figure data'][canvas][ _dirname = os.path.dirname(save_dest)
idx].savefig(save_dest) if os.access(_dirname, os.W_OK):
self.all_data['Figure data'][canvas][
idx].savefig(save_dest)
elif not write_message_fired:
_mess = ("Do not have write permission " +
"for directory {0} from this " +
"host {1}. Images not saved and " +
"cannot be sent to elog").format(
_dirname, os.uname()[1])
self.parent.trigger_log_message.emit(
MsgSeverity.WARN.name, _pymodule,
_line(), _mess, {})
write_message_fired = True
attach_files.append(save_dest) attach_files.append(save_dest)
if attach_files: if attach_files:
self.parent.attach_files = attach_files self.parent.attach_files = attach_files
print("All files attached") print("All files attached", flush=True)
else: else:
print("No files to attach", flush=True) print("No files to attach", flush=True)
time.sleep(0.2) #avoid race condition time.sleep(0.2) #avoid race condition
@@ -276,12 +300,15 @@ class BaseWindow(QMainWindow):
def run(self): def run(self):
"""Run thread """Run thread
""" """
all_dict = self.analysis_procedure.measure_and_analyze( all_dict = self.analysis_procedure.measure_and_analyze(
self.input_parameters) self.input_parameters)
# Emit results # Emit results
if all_dict is not None: if all_dict:
self.trigger_thread_event.emit(all_dict) self.trigger_thread_event.emit(all_dict)
mess = "Analysis completed" mess = "Analysis completed"
self.parent.trigger_log_message.emit( self.parent.trigger_log_message.emit(
MsgSeverity.INFO.name, _pymodule, _line(), mess, {}) MsgSeverity.INFO.name, _pymodule, _line(), mess, {})
@@ -293,7 +320,7 @@ class BaseWindow(QMainWindow):
def __init__(self, parent=None, pymodule=None, appversion=None, title="", def __init__(self, parent=None, pymodule=None, appversion=None, title="",
user_mode=UserMode.OPERATION, facility=Facility.SwissFEL, user_mode=UserMode.OPERATION, facility=Facility.SwissFEL,
extended=True, has_optics=True): extended=True, has_optics=True, has_procedure=True):
super(BaseWindow, self).__init__(parent) super(BaseWindow, self).__init__(parent)
self.parent = parent self.parent = parent
@@ -307,12 +334,18 @@ class BaseWindow(QMainWindow):
self.facility = facility self.facility = facility
self.user_mode = user_mode self.user_mode = user_mode
self.appname, self.appext = self.pymodule.split(".") self.appname, self.appext = self.pymodule.split(".")
print("=============================================") print("=============================================")
print("Starting {0} at: {1}".format(self.appname, datetime.now())) print("Starting {0} at: {1}".format(self.appname, datetime.now()))
print("User: {0} Host: {1}".format(os.getlogin(), os.uname()[1])) print("User: {0} Host: {1}".format(os.getlogin(), os.uname()[1]))
print("=============================================", flush=True) print("=============================================", flush=True)
self.settings = ReadJSON(self.appname)
#Read out current_logbook
self.cafe = PyCafe.CyCafe() self.cafe = PyCafe.CyCafe()
self.cyca = PyCafe.CyCa() self.cyca = PyCafe.CyCa()
self.cafe_exception = PyCafe.CafeException self.cafe_exception = PyCafe.CafeException
@@ -332,7 +365,7 @@ class BaseWindow(QMainWindow):
self.hdf_dialog = None self.hdf_dialog = None
self.daq_analysis_completed = False self.daq_analysis_completed = False
self.hdf_save_completed = False
self.setObjectName("MainWindow") self.setObjectName("MainWindow")
self.setWindowTitle(self.appname) self.setWindowTitle(self.appname)
@@ -343,8 +376,7 @@ class BaseWindow(QMainWindow):
self.menu = self.menuBar() self.menu = self.menuBar()
self.settings = ReadJSON(self.appname)
''' '''
try: try:
dirname = self.settings.data["stdout"]["destination"] dirname = self.settings.data["stdout"]["destination"]
@@ -364,6 +396,12 @@ class BaseWindow(QMainWindow):
self.stdlog_dest = (self.settings.data["stdlog"]["destination"] + self.stdlog_dest = (self.settings.data["stdlog"]["destination"] +
self.appname + "-" + os.getlogin() + ".log") self.appname + "-" + os.getlogin() + ".log")
self.logging = logging
#self.logging.basicConfig(filename=self.stdlog_dest, level=logging.DEBUG)
self.logging.basicConfig(level=logging.NOTSET)
self.logger = self.logging.getLogger(__name__)
self.logger.info("Logging activated")
self.date_str = None self.date_str = None
self.autopost_elog = True self.autopost_elog = True
@@ -382,13 +420,16 @@ class BaseWindow(QMainWindow):
self.autopost_epics = self.settings.data["menuFlags"]["hasEpics"] self.autopost_epics = self.settings.data["menuFlags"]["hasEpics"]
except KeyError as error: except KeyError as error:
print("KeyError in base.py, init:", error) print("KeyError in base.py, init:", error)
self.autopost_epics = True self.autopost_epics = False
try: try:
self.autopost_hdf = self.settings.data["menuFlags"]["hasH5"] self.autopost_hdf = self.settings.data["menuFlags"]["hasH5"]
except KeyError as error: except KeyError as error:
print("KeyError in base.py, init:", error) print("KeyError in base.py, init:", error)
self.autopost_hdf = True self.autopost_hdf = False
self.hdf_save_completed = False if self.autopost_hdf else True
self.all_input_parameters = {} #gui self.all_input_parameters = {} #gui
self.all_input_labels = {} #gui self.all_input_labels = {} #gui
@@ -412,7 +453,8 @@ class BaseWindow(QMainWindow):
from src.analysis import AnalysisProcedure from src.analysis import AnalysisProcedure
self.analysis_procedure = AnalysisProcedure(self) self.analysis_procedure = AnalysisProcedure(self)
except ImportError as e: except ImportError as e:
print("Import Error:", e) print(("Base class without user supplied AnalysisProcedure class."
+ " mport Error:"), e)
##self.trigger_elog_entry.connect(self.receive_elog_notification) ##self.trigger_elog_entry.connect(self.receive_elog_notification)
##self.trigger_hdf_save.connect(self.save_to_hdf) ##self.trigger_hdf_save.connect(self.save_to_hdf)
@@ -463,18 +505,25 @@ class BaseWindow(QMainWindow):
if self.facility == Facility.SwissFEL: if self.facility == Facility.SwissFEL:
from pyqtacc.sf.guiheader import GUIHeader from pyqtacc.sf.guiheader import GUIHeader
from pyqtacc.bdbase.sendelog import QSendToELOG
elif self.facility == Facility.SLS: elif self.facility == Facility.SLS:
from pyqtacc.sls.guiheader import GUIHeader from pyqtacc.sls.guiheader import GUIHeader
from pyqtacc.sls.sendelogsls import QSendToELOG
elif self.facility == Facility.HIPA:
from pyqtacc.hipa.guiheader import GUIHeader
from pyqtacc.hipa.sendeloghipa import QSendToELOG
self.gui_header = GUIHeader(self, user_mode=self.user_mode, self.gui_header = GUIHeader(self, user_mode=self.user_mode,
extended=extended) extended=extended)
self.mainwindow_layout.addWidget(self.gui_header.header_wgt) self.mainwindow_layout.addWidget(self.gui_header.header_wgt)
self.gui_frame = GUIFrame(self, has_optics=self.has_optics) self.gui_frame = GUIFrame(self, has_optics=self.has_optics,
has_procedure=has_procedure)
self.show_log_message = self.gui_frame.show_log_message self.show_log_message = self.gui_frame.show_log_message
self.hdf_dock_widget = QNoDockWidget(" HDF5", self) if self.autopost_hdf:
self.init_hdf_analysis_wgt() self.hdf_dock_widget = QNoDockWidget(" HDF5", self)
self.init_hdf_analysis_wgt()
self.mainwindow_layout.addWidget(self.gui_frame.central_tab_widget) self.mainwindow_layout.addWidget(self.gui_frame.central_tab_widget)
self.mainwindow.setLayout(self.mainwindow_layout) self.mainwindow.setLayout(self.mainwindow_layout)
@@ -487,7 +536,7 @@ class BaseWindow(QMainWindow):
self.mainwindow.setMinimumWidth(SLS_CENTRAL_WIDGET_MINIMUM_WIDTH) self.mainwindow.setMinimumWidth(SLS_CENTRAL_WIDGET_MINIMUM_WIDTH)
self.setCentralWidget(self.mainwindow) self.setCentralWidget(self.mainwindow)
self.show_log_message(MsgSeverity.INFO, _pymodule, _line(), self.show_log_message(MsgSeverity.INFO.name, _pymodule, _line(),
"Application configured") "Application configured")
@@ -523,7 +572,7 @@ class BaseWindow(QMainWindow):
if self.settings.data["Parameters"][key]["flag"]: if self.settings.data["Parameters"][key]["flag"]:
self.input_parameters[key] = val self.input_parameters[key] = val
self.all_input_parameters[key] = val self.all_input_parameters[key] = val
#print("val=",val, key) #print("val=",val, key)
except KeyError as e: except KeyError as e:
@@ -569,8 +618,8 @@ class BaseWindow(QMainWindow):
if self.settings.data["Expert"][key]["flag"]: if self.settings.data["Expert"][key]["flag"]:
self.expert_parameters[key] = val self.expert_parameters[key] = val
self.all_expert_parameters[key] = val self.all_expert_parameters[key] = val
#print("val=",val, key) #print("val=",val, key)
except KeyError as e: except KeyError as e:
print("Key Error in base.py initialization:", e) print("Key Error in base.py initialization:", e)
@@ -811,7 +860,7 @@ class BaseWindow(QMainWindow):
""" """
#Close all dock widgets #Close all dock widgets
#self.removeDockWidget(self.hdf_dock_widget) #self.removeDockWidget(self.hdf_dock_widget)
self.logger.info("Closing Application")
self.save_application_settings() self.save_application_settings()
QApplication.processEvents() QApplication.processEvents()
self.cafe.monitorStopAll() self.cafe.monitorStopAll()
@@ -1147,6 +1196,7 @@ class BaseWindow(QMainWindow):
#print("filename", self.hdf_filename) #print("filename", self.hdf_filename)
def verify_send_to_elog(self): def verify_send_to_elog(self):
if self.analysis_thread is not None: if self.analysis_thread is not None:
if self.analysis_thread.isRunning(): if self.analysis_thread.isRunning():
_mess = ("Measurement in progress. " + _mess = ("Measurement in progress. " +
@@ -1180,6 +1230,9 @@ class BaseWindow(QMainWindow):
def send_to_elog(self): def send_to_elog(self):
""" Response to elog_action; normally overwritten """ Response to elog_action; normally overwritten
""" """
if not self.verify_send_to_elog():
return
'''
if self.analysis_thread is not None: if self.analysis_thread is not None:
if self.analysis_thread.isRunning(): if self.analysis_thread.isRunning():
_mess = ("Measurement in progress. " + _mess = ("Measurement in progress. " +
@@ -1188,6 +1241,7 @@ class BaseWindow(QMainWindow):
QMessageBox.Ok) QMessageBox.Ok)
return return
'''
#_elog_sf = ElogSwissFEL() #_elog_sf = ElogSwissFEL()
_logbook = None _logbook = None
@@ -1197,6 +1251,7 @@ class BaseWindow(QMainWindow):
_attach_files = [] _attach_files = []
_message = "" _message = ""
QSendToELOG(self, logbook=_logbook, categoryIdx=_category_idx, QSendToELOG(self, logbook=_logbook, categoryIdx=_category_idx,
domainIdx=_domain_idx, sectionIdx=_section_idx, domainIdx=_domain_idx, sectionIdx=_section_idx,
title=self.title, message=_message, title=self.title, message=_message,
@@ -1613,7 +1668,7 @@ class BaseWindow(QMainWindow):
@Slot() @Slot()
def start_analysis_thread(self): def start_analysis_thread(self):
if not self.analysis_procedure: if not self.analysis_procedure:
mess = "Analysis thread not configured for this application" mess = "Analysis thread not configured for this application"
self.show_log_message(MsgSeverity.ERROR, _pymodule, _line(), mess) self.show_log_message(MsgSeverity.ERROR, _pymodule, _line(), mess)
@@ -1636,17 +1691,17 @@ class BaseWindow(QMainWindow):
if not self.verify_analysis_preconditions(): if not self.verify_analysis_preconditions():
return return
self.analysis_thread = self.AnalysisThread( self.analysis_thread = self.AnalysisThread(
self, self.analysis_procedure, self.input_parameters) self, self.analysis_procedure, self.input_parameters)
self.analysis_thread.trigger_thread_event.connect( self.analysis_thread.trigger_thread_event.connect(
self.receive_analysis_results) self.receive_analysis_results)
self.analysis_thread.started.connect(self.analysis_thread_started) self.analysis_thread.started.connect(self.analysis_thread_started)
self.analysis_thread.finished.connect(self.analysis_thread_finished) self.analysis_thread.finished.connect(self.analysis_thread_finished)
#getMachineDatafor hdf
self.analysis_thread.start() self.analysis_thread.start()
QApplication.processEvents() QApplication.processEvents()
@@ -1686,17 +1741,26 @@ class BaseWindow(QMainWindow):
@Slot(dict) @Slot(dict)
def receive_analysis_results(self, all_dict): def receive_analysis_results(self, all_dict):
#print("receive analysis results", all_dict)
self.all_data = all_dict self.all_data = all_dict
self.gui_frame.canvas_update(all_dict['Figure data']) self.gui_frame.canvas_update(all_dict['Figure data'])
if self.gui_frame.results_output_wgt_dict:
#all_dict['Processed data']['Results']={}
#all_dict['Processed data']['Results']['mean'] = 123.23
#all_dict['Processed data']['Results']['SD'] = 0.23
try:
results_data = all_dict['Processed data']['Results']
self.gui_frame.send_to_results_output_wgt(results_data)
except:
pass
self.gui_frame.central_tab_widget.setCurrentIndex(1) self.gui_frame.central_tab_widget.setCurrentIndex(1)
self.gui_frame.results_tab_wgt.setCurrentIndex(0) self.gui_frame.results_tab_wgt.setCurrentIndex(0)
@Slot() @Slot()
def receive_abort_analysis(self): def receive_abort_analysis(self):
"""Instantiate action on abort """Instantiate action on abort
""" """
print("Aborting")
if self.analysis_procedure.abort: if self.analysis_procedure.abort:
return return
self.gui_frame.in_abort_procedure() self.gui_frame.in_abort_procedure()
@@ -1719,6 +1783,12 @@ class BaseWindow(QMainWindow):
message="Measurement in progress..."): message="Measurement in progress..."):
'''Receives update of message''' '''Receives update of message'''
self.progressbar.setVisible(True) self.progressbar.setVisible(True)
try:
if self.input_parameters["simulation"] :
self.progressbar_color = self.progressbar_simulation
except KeyError:
pass
if value == PROGRESS_BAR_THREAD_INIT: if value == PROGRESS_BAR_THREAD_INIT:
self.progressbar.setVisible(False) self.progressbar.setVisible(False)
self.progressbar.setFormat("") self.progressbar.setFormat("")
@@ -1738,6 +1808,8 @@ class BaseWindow(QMainWindow):
prog_val = re.findall(r'\d+', message) prog_val = re.findall(r'\d+', message)
if prog_val: if prog_val:
self.progressbar.setValue(int(prog_val[0])) self.progressbar.setValue(int(prog_val[0]))
else:
self.progressbar.setValue(int(10))
mess = "Aborting measurement procedure" mess = "Aborting measurement procedure"
self.show_log_message( self.show_log_message(
MsgSeverity.WARN.name, _pymodule, _line(), mess) MsgSeverity.WARN.name, _pymodule, _line(), mess)
@@ -1764,7 +1836,8 @@ class BaseWindow(QMainWindow):
self.progressbar.setValue(value) self.progressbar.setValue(value)
self.progressbar.setObjectName(self.progressbar_color) self.progressbar.setObjectName(self.progressbar_color)
self.daq_analysis_completed = True self.daq_analysis_completed = True
self.hdf_save_completed = False if self.autopost_hdf:
self.hdf_save_completed = False
QTimer.singleShot(2000, lambda: self.progressbar.setVisible(False)) QTimer.singleShot(2000, lambda: self.progressbar.setVisible(False))
else: else:
self.progressbar.setFormat(message) self.progressbar.setFormat(message)
@@ -1774,7 +1847,7 @@ class BaseWindow(QMainWindow):
self.progressbar.style().polish(self.progressbar) self.progressbar.style().polish(self.progressbar)
QApplication.processEvents() QApplication.processEvents()
time.sleep(0.0001) time.sleep(0.0001)
def initialize_application(self, appname=_appname, delay=None, def initialize_application(self, appname=_appname, delay=None,
facility=Facility.SwissFEL): facility=Facility.SwissFEL):
@@ -1794,6 +1867,9 @@ class BaseWindow(QMainWindow):
elif facility == Facility.SLS: elif facility == Facility.SLS:
from pyqtacc.qrc_resources.facility.sls.pyrcc5 import qrc_resources from pyqtacc.qrc_resources.facility.sls.pyrcc5 import qrc_resources
print("FACILITY SLS") print("FACILITY SLS")
elif facility == Facility.HIPA:
from pyqtacc.qrc_resources.facility.hipa.pyrcc5 import qrc_resources
print("FACILITY HIPA")
else: else:
print("Unknown Facility; assuming SLS") print("Unknown Facility; assuming SLS")
from pyqtacc.qrc_resources.facility.sls.pyrcc5 import qrc_resources from pyqtacc.qrc_resources.facility.sls.pyrcc5 import qrc_resources
@@ -1880,7 +1956,8 @@ class BaseWindow(QMainWindow):
int_seconds_remaining = int(delay - (now-start1)) int_seconds_remaining = int(delay - (now-start1))
seconds_remaining = '{:2d}'.format(int_seconds_remaining) seconds_remaining = '{:2d}'.format(int_seconds_remaining)
self.splash_progressbar.setValue(val) self.splash_progressbar.setValue(val)
self.processEvents() #self.processEvents()
self.flush()
sec_str = "s" if abs(int_seconds_remaining) != 1 else "" sec_str = "s" if abs(int_seconds_remaining) != 1 else ""
mess = """ mess = """
<br><p style='color:black; font-weight:bold; <br><p style='color:black; font-weight:bold;

View File

@@ -18,6 +18,7 @@ class Facility(IntEnum):
PSI = 0 PSI = 0
SwissFEL = 1 SwissFEL = 1
SLS = 2 SLS = 2
HIPA = 3
class MsgSeverity(IntEnum): class MsgSeverity(IntEnum):
""" For use with message logger """ For use with message logger
@@ -35,6 +36,7 @@ class UserMode(IntEnum):
OPERATION = 1 OPERATION = 1
EXPERT = 2 EXPERT = 2
SIMULATION = 3 SIMULATION = 3

File diff suppressed because it is too large Load Diff

View File

@@ -34,6 +34,7 @@ class QSendToELOG(QDialog):
attachFile=None, destination_folder=None): attachFile=None, destination_folder=None):
#super(QSendToELOG, self).__init__(parent) #super(QSendToELOG, self).__init__(parent)
super().__init__() super().__init__()
self.files_text = '' self.files_text = ''
self.fflag = False self.fflag = False
self.parent = parent self.parent = parent
@@ -43,7 +44,7 @@ class QSendToELOG(QDialog):
self.destination = destination_folder self.destination = destination_folder
self.window_title = self.parent.appname + ": " + _appname self.window_title = self.parent.appname + ": " + _appname
self.pymodule = _pymodule self.pymodule = _pymodule
self.setWindowTitle(self.window_title) self.setWindowTitle(self.window_title)
elog_books = list(self.parent.settings.data["ElogBooks"]) elog_books = list(self.parent.settings.data["ElogBooks"])
@@ -51,6 +52,7 @@ class QSendToELOG(QDialog):
self.elog_items.addItems(elog_books) self.elog_items.addItems(elog_books)
self.elog_items.currentIndexChanged.connect(self.on_elog_change) self.elog_items.currentIndexChanged.connect(self.on_elog_change)
idx = 0 idx = 0
if logbook is not None: if logbook is not None:
try: try:
idx = elog_books.index(logbook) idx = elog_books.index(logbook)
@@ -144,7 +146,7 @@ class QSendToELOG(QDialog):
self.files = [] self.files = []
self.attributes = {} self.attributes = {}
self.layout = QVBoxLayout(self) self.layout = QVBoxLayout(self)
self.layout.addLayout(logbook) self.layout.addLayout(logbook)
self.layout.addLayout(self.applicationbox) self.layout.addLayout(self.applicationbox)
@@ -187,7 +189,7 @@ class QSendToELOG(QDialog):
self.fflag = True self.fflag = True
filebox.addWidget(self.filesE) filebox.addWidget(self.filesE)
openCloseVBox = QVBoxLayout() openCloseVBox = QVBoxLayout()
self.openBtn = QPushButton('Add') self.openBtn = QPushButton('Add')
self.openBtn.setAutoDefault(False) self.openBtn.setAutoDefault(False)
@@ -216,7 +218,7 @@ class QSendToELOG(QDialog):
self.messagelbl.setStyleSheet("QLabel { color : red; }") self.messagelbl.setStyleSheet("QLabel { color : red; }")
self.layout.addWidget(self.messagelbl) self.layout.addWidget(self.messagelbl)
self.layout.addLayout(btnLayout) self.layout.addLayout(btnLayout)
self.setMinimumWidth(440) self.setMinimumWidth(440)
self.exec() self.exec()

324
sendelogframe.py Normal file
View File

@@ -0,0 +1,324 @@
import getpass
import inspect
import os
import time
from qtpy.QtCore import Qt
from qtpy.QtWidgets import (QComboBox, QDialog, QFileDialog, QHBoxLayout,
QLabel, QLineEdit, QPushButton, QTextEdit,
QVBoxLayout)
import elog # https://github.com/paulscherrerinstitute/py_elog
from pyqtacc.bdbase.enumkind import MsgSeverity
_version = "1.0.0"
_pymodule = os.path.basename(__file__)
_appname, _appext = _pymodule.split(".")
def _line():
"""Macro to return the current line number.
The current line number within the file is used when
reporting messages to the message logging window.
Returns:
int: Current line number.
"""
return inspect.currentframe().f_back.f_lineno
class QSendToELOGFrame(QDialog):
""" Graphical interface to elog
"""
def __init__(self, parent, logbook=None, title=None, message=None,
attachFile=None, destination_folder=None):
super().__init__()
self.files_text = ''
self.fflag = False
self.parent = parent
if destination_folder is None:
self.destination = self.parent.elog_dest + " / " + self.parent.appname
else:
self.destination = destination_folder
self.window_title = self.parent.appname + ": " + _appname
self.pymodule = _pymodule
self.setWindowTitle(self.window_title)
elog_books = list(self.parent.settings.data["ElogBooks"])
self.elog_items = QComboBox()
self.elog_items.addItems(elog_books)
self.elog_items.currentIndexChanged.connect(self.on_elog_change)
idx = 0
if logbook is not None:
try:
idx = elog_books.index(logbook)
except Exception:
mess = "Index not found for logbook {0}".format(logbook)
self.parent.show_log_message(MsgSeverity.WARN, self.pymodule,
_line(), mess)
else:
logbook = self.parent.settings.data["Elog"]["book"]
try:
idx = elog_books.index(logbook)
except Exception:
mess = "Index not found for logbook {0}".format(logbook)
self.parent.show_log_message(MsgSeverity.WARN, self.pymodule,
_line(), mess)
self.logbook = logbook
self.elog_items.setCurrentIndex(idx)
self.elog_items.currentIndexChanged.emit(idx)
self.elog_items.setObjectName("Elog")
self.title_items = QHBoxLayout()
self.title_items.addWidget(QLabel('Title: '))
self.titleline = QLineEdit()
self.titleline.setObjectName('Elog')
#self.titleline.setStatusTip('elog')
if title is None:
title = self.parent.appname
self.titleline.setText(str(title))
self.titleline.setFixedWidth(300)
self.titleline.setAlignment(Qt.AlignCenter)
self.title_items.addWidget(self.titleline)
self.applicationbox = QHBoxLayout()
self.applicationbox.addWidget(QLabel('Application:'))
self.applicationlabel = QLabel(self.parent.pymodule)
self.applicationlabel.setObjectName("Elog")
# self.applicationbox.addStretch()
self.applicationbox.addWidget(self.applicationlabel)
logbook = QHBoxLayout()
logbook.addWidget(QLabel('Logbook: '))
logbook.addWidget(self.elog_items)
authorbox = QHBoxLayout()
authorbox.addWidget(QLabel('Author: '))
self.author = QLineEdit()
self.author.setObjectName('Elog')
self.author.setFixedWidth(195)
self.author.setStatusTip('elog')
self.author.setText(getpass.getuser())
authorbox.addWidget(self.author)
self.files = []
self.attributes = {}
self.layout = QVBoxLayout(self)
self.layout.addLayout(logbook)
self.layout.addLayout(self.applicationbox)
self.layout.addLayout(authorbox)
self.layout.addLayout(self.title_items)
report = QLabel('Report: ')
self.layout.addWidget(report)
self.message = QTextEdit(message)
self.layout.addWidget(self.message)
filebox = QHBoxLayout()
qlfile = QLabel('Attach:')
qlfile.setAlignment(Qt.AlignTop)
filebox.addWidget(qlfile)
self.filesE = QTextEdit()
self.filesE.setAlignment(Qt.AlignTop)
self.filesE.setFixedHeight(80)
self.filesE.setReadOnly(True)
self.attachFile = attachFile
if self.attachFile is not None:
_attachFile = []
if isinstance(self.attachFile, str):
_attachFile.append(self.attachFile)
elif isinstance(self.attachFile, list):
_attachFile = self.attachFile
for i, file in enumerate(_attachFile):
_attach_base = os.path.basename(file)
if i > 0:
self.files_text += "\n"
self.files_text += str(_attach_base)
self.filesE.setText(self.files_text)
self.fflag = True
filebox.addWidget(self.filesE)
openCloseVBox = QVBoxLayout()
self.openBtn = QPushButton('Add')
self.openBtn.setAutoDefault(False)
self.openBtn.clicked.connect(self.openFiles)
openCloseVBox.addWidget(self.openBtn)
closeBtn = QPushButton('Clear')
closeBtn.setAutoDefault(False)
closeBtn.clicked.connect(self.clearFiles)
openCloseVBox.addWidget(closeBtn)
filebox.addLayout(openCloseVBox)
self.layout.addLayout(filebox)
btnLayout = QHBoxLayout()
self.okBtn = QPushButton('Send')
self.okBtn.setAutoDefault(False)
self.okBtn.clicked.connect(self.ok)
self.cancelBtn = QPushButton('Cancel')
self.cancelBtn.setAutoDefault(False)
self.cancelBtn.clicked.connect(self.close)
btnLayout.addWidget(self.okBtn)
btnLayout.addWidget(self.cancelBtn)
self.messagelbl = QLabel('')
self.messagelbl.setStyleSheet("QLabel { color : red; }")
self.layout.addWidget(self.messagelbl)
self.layout.addLayout(btnLayout)
self.setMinimumWidth(440)
#self.exec()
def on_elog_change(self, elog_change_val):
if "test" in self.elog_items.currentText():
_bgcolor = "QComboBox {background: plum; color : black;}"
else:
_bgcolor = "QComboBox {background: lightblue; color : black;}"
self.elog_items.setStyleSheet(_bgcolor)
def ok(self):
message = self.message.document().toPlainText()
if not message:
self.messagelbl.setText('Please enter a brief Report')
return
title = self.titleline.text()
if not title:
self.messagelbl.setText('Titel attribute is required')
return
author = self.author.text()
application = self.applicationlabel.text()
self.attributes['Autor'] = author
self.attributes['Author'] = author
self.attributes['Application'] = application
self.attributes['Titel'] = title
self.attributes['Title'] = title
self.attributes['When'] = str(time.time())
self.attributes['Wann'] = str(time.time())
if self.attachFile is not None:
_attachFile = []
if isinstance(self.attachFile, str):
_attachFile.append(self.attachFile)
elif isinstance(self.attachFile, list):
_attachFile = self.attachFile
for i in range(0, len(_attachFile)):
if "/tmp" in _attachFile[i]:
self.files.append(str(_attachFile[i]))
elif "/afs/psi.ch" in _attachFile[i]:
self.files.append(str(_attachFile[i]))
elif "/sls/bd/data/" in _attachFile[i]:
self.files.append(str(_attachFile[i]))
else:
self.files.append(self.destination + str(_attachFile[i]))
el = self.elog_items.currentText()
url = self.parent.settings.data["ElogBooks"][el]["url"]
self.logbook = elog.open(url, user='robot', password='robot')
try:
if self.files:
self.logbook.post(message, attributes=self.attributes,
attachments=self.files)
else:
self.logbook.post(message, attributes=self.attributes)
#self.trigger_elog_entry.emit(True, url, "OK")
self.receive_elog_notification(True, url, "OK")
except Exception as ex:
#self.trigger_elog_entry.emit(False, url, str(ex))
print("Exception in sendelog.py", str(ex))
self.receive_elog_notification(False, url, str(ex))
#for file in self.files:
# if os.path.exists(file):
# os.remove(file)
self.close()
def clearFiles(self):
self.attachFile = []
self.filesE.clear()
self.files = []
self.files_text = ''
self.fflag = False
def openFiles(self):
# Notethat openFiles also gets called when qDialog cacnel is clicked!
qFileDialog = QFileDialog()
extensions = ("Images (*.bmp *.eps *.gif *.jpeg *.jpg *.pdf *.png " +
"*.ps *.tiff *.xpm);;Text files (*.txt *.text);;" +
"JSON/XML files (*.json *.xml)")
flocal = qFileDialog.getOpenFileNames(
self, 'Open File', self.destination, extensions)[0]
if not flocal:
return
self.files.append(flocal[0])
if self.fflag:
self.files_text += '\n'
self.files_text += str(flocal[0].split('/')[-1])
self.fflag = True
self.filesE.setText(self.files_text)
def receive_elog_notification(self, is_accepted, logbook_url, elog_message):
'''Receive notification from ELOG, and report to log window'''
yes_no = "made" if is_accepted else "failed"
mess = "Entry into ELOG: {0} {1}".format(logbook_url, yes_no)
if is_accepted:
self.parent.show_log_message(MsgSeverity.INFO, self.pymodule,
_line(), mess)
else:
mess += ".\n" + elog_message
self.parent.show_log_message(MsgSeverity.WARN, self.pymodule,
_line(), mess)
self.parent.statusbar.showMessage(mess)
def get_logbook_specific_items(self, logbook):
'''Retrieve logbook specific options'''
#First check what is the logbook being requested?
#find layout items
layout_items = []
layout_items_optional = []
try:
layout_items = list(self.parent.settings.data[
"ElogBooks"][logbook]['Required'].keys())
except KeyError:
pass
try:
layout_items_optional = list(self.parent.settings.data[
"ElogBooks"][logbook]['Optional'].keys())
except KeyError:
pass
layout_items.extend(layout_items_optional)
return layout_items