message.py
1 from PyQt5.QtWidgets import * 2 from PyQt5.QtCore import Qt 3 from PyQt5.QtGui import QColor 4 from qtvcp.core import Status, Info 5 import hal 6 7 # Set up logging 8 from qtvcp import logger 9 log = logger.getLogger(__name__) 10 11 # Instantiate the libraries with global reference 12 # STATUS gives us status messages from linuxcnc 13 STATUS = Status() 14 INFO = Info() 15 16 class Message: 17 def __init__(self): 18 self.OK_TYPE = 1 19 self.YN_TYPE = 0 20 self.QUESTION = QMessageBox.Question 21 self.INFO = QMessageBox.Information 22 self.WARNING = QMessageBox.Warning 23 self.CRITICAL = QMessageBox.Critical 24 self._color = QColor(0, 0, 0, 150) 25 self.focus_text =' ' 26 self.play_sounds = True 27 self.alert_sound = 'READY' 28 self.use_focus_overlay = True 29 30 def showDialog(self, message, more_info=None, details=None, display_type=1, 31 icon=QMessageBox.Information, pinname=None): 32 msg = QMessageBox() 33 msg.setWindowModality(Qt.ApplicationModal) 34 msg.setIcon(icon) 35 msg.setWindowTitle("User MessageBox") 36 msg.setTextFormat(Qt.RichText) 37 msg.setText('<b>%s</b>'% message) 38 if more_info: 39 msg.setInformativeText(more_info) 40 if details: 41 msg.setDetailedText(details) 42 if display_type == self.OK_TYPE: 43 msg.setStandardButtons(QMessageBox.Ok) 44 else: 45 msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) 46 msg.buttonClicked.connect(self.msgbtn) 47 # block on answer 48 retval = msg.exec_() 49 log.debug('value of pressed message box button: {}'.format(retval)) 50 self.dialog_return(None,retval==QMessageBox.Yes,display_type,pinname) 51 52 def msgbtn(self, i): 53 pass 54 #print "Button pressed is:",i.text() 55 56 # This is part of the user message system 57 # There is status that prints to the status bar 58 # There is Okdialog that prints a dialog that the user must acknoledge 59 # there is yes/no dialog where the user must choose between yes or no 60 # you can combine status and dialog messages so they print to the status bar 61 # and pop a dialog 62 def on_printmessage(self, pin, pinname, boldtext, text, details, type, icon): 63 if not pin.get(): return 64 if self.play_sounds: 65 STATUS.emit('play-sound',self.alert_sound) 66 if boldtext == "NONE": boldtext = '' 67 if "status" in type: 68 if boldtext: 69 statustext = boldtext 70 else: 71 statustext = text 72 if self.NOTIFY: 73 self.NOTIFY.notify(_("INFO:"),statustext) 74 if "dialog" in type or "okdialog" in type: 75 if self.use_focus_overlay: 76 STATUS.emit('focus-overlay-changed', True, self.focus_text, self._color) 77 if pin.get(): 78 self.HAL_GCOMP_[pinname + "-waiting"] = True 79 if "okdialog" in type: 80 self.showDialog(boldtext,text,details,self.OK_TYPE,icon,pinname) 81 else: 82 if pin.get(): 83 self.HAL_GCOMP_[pinname + "-response"] = 0 84 self.showDialog(boldtext,text,details,self.YN_TYPE,icon,pinname) 85 86 # search for and set up user requested message system. 87 # status displays on the statusbat and requires no acknowledge. 88 # dialog displays a Messagebox with yes or no buttons 89 # okdialog displays a Messagebox with an ok button 90 # dialogs require an answer before focus is sent back to main screen 91 def message_setup(self, hal_comp): 92 self.HAL_GCOMP_ = hal_comp 93 icon = QMessageBox.Question 94 if INFO.ZIPPED_USRMESS: 95 for bt,t,d,style,name in (INFO.ZIPPED_USRMESS): 96 if not ("status" in style) and not ("dialog" in style) and not ("okdialog" in style): 97 log.debug('invalid message type {} in INI File [DISPLAY] section'.format(C)) 98 continue 99 if not name == None: 100 # this is how we make a pin that can be connected to a callback 101 self[name] = self.HAL_GCOMP_.newpin(name, hal.HAL_BIT, hal.HAL_IO) 102 self[name].value_changed.connect(self.dummy(self[name],name,bt,t,d,style,icon)) 103 if ("dialog" in style): 104 self.HAL_GCOMP_.newpin(name+"-waiting", hal.HAL_BIT, hal.HAL_OUT) 105 if not ("ok" in style): 106 self.HAL_GCOMP_.newpin(name+"-response", hal.HAL_BIT, hal.HAL_OUT) 107 108 # a hacky way to adjust future options 109 # using it to adjust runtime options from a preference file in screenoptions (presently) 110 # 'with great power comes ....' 111 def message_option(self, option, data): 112 try: 113 self[option] = data 114 except: 115 pass 116 117 # This weird code is so we can get access to proper variables. 118 # using clicked.connect( self.on_printmessage(pin,name,bt,t,c) ) apparently doesn't easily 119 # add user data - it seems you only get the last set added 120 # found this closure technique hack on the web 121 # truely weird black magic 122 def dummy(self,pin,name,bt,t,d,c,i): 123 def calluser(): 124 self.on_printmessage(pin,name,bt,t,d,c,i) 125 return calluser 126 127 # message dialog returns a response here 128 # update any hand shaking pins 129 def dialog_return(self,widget,result,dialogtype,pinname): 130 if not dialogtype: # yes/no dialog 131 if pinname: 132 self.HAL_GCOMP_[pinname + "-response"] = result 133 if pinname: 134 self.HAL_GCOMP_[pinname + "-waiting"] = False 135 # reset the HAL IO pin so it can fire again 136 self.HAL_GCOMP_[pinname] = False 137 if self.use_focus_overlay: 138 STATUS.emit('focus-overlay-changed',False,None,None) 139 140 ############################## 141 # required class boiler code # 142 ############################## 143 144 def __getitem__(self, item): 145 return getattr(self, item) 146 def __setitem__(self, item, value): 147 return setattr(self, item, value) 148 149 if __name__ == '__main__': 150 import sys 151 from PyQt5.QtCore import * 152 m = Message() 153 app = QApplication(sys.argv) 154 w = QWidget() 155 b = QPushButton(w) 156 b.setText("Show Y/N\n message!") 157 b.move(10,0) 158 b.clicked.connect(lambda data: m.showdialog('This is a question message', 159 more_info='Pick yes or no', icon=m.QUESTION, display_type=m.YN_TYPE)) 160 161 c = QPushButton(w) 162 c.setText("Show OK\n message!") 163 c.move(10,40) 164 c.clicked.connect(lambda data: m.showdialog('This is an OK message', display_type=1)) 165 166 d = QPushButton(w) 167 d.setText("Show critical\n message!") 168 d.move(10,80) 169 d.clicked.connect(lambda data: m.showdialog('This is an Critical message', 170 details='There seems to be something wrong', icon=m.CRITICAL, display_type=1)) 171 172 w.setWindowTitle("PyQt Dialog demo") 173 w.setGeometry(300, 300, 300, 150) 174 w.show() 175 sys.exit(app.exec_())