class LocalButtonsConf(OptionsDialogGroupBox): def __init__(self, name, main): self.main = main OptionsDialogGroupBox.__init__(self, name, main) self.buttonBox = QGroupBox("Pins") self.buttonBoxLayout = QVBoxLayout() self.buttonBox.setLayout(self.buttonBoxLayout) def initUI(self): vbox = QVBoxLayout() self.polBox = QCheckBox("Invert") vbox.addWidget(self.polBox) self.buttongroup = QButtonGroup() self.buttongroup.setExclusive(False) vbox.addWidget(self.buttonBox) self.setLayout(vbox) def initButtons(self, num): #delete buttons self.num = num # Remove buttons for i in range(self.buttonBoxLayout.count()): b = self.buttonBoxLayout.takeAt(0) self.buttonBoxLayout.removeItem(b) b.widget().deleteLater() for b in self.buttongroup.buttons(): self.buttongroup.removeButton(b) self.buttonBox.update() for i in range(self.num): cb = QCheckBox(str(i + 1)) self.buttongroup.addButton(cb, i) self.buttonBoxLayout.addWidget(cb) def localcb(mask): for i in range(self.num): self.buttongroup.button(i).setChecked(mask & (1 << i)) self.main.comms.serialGetAsync("local_btnmask?", localcb, int) def apply(self): mask = 0 for i in range(self.num): if (self.buttongroup.button(i).isChecked()): mask |= 1 << i self.main.comms.serialWrite("local_btnmask=" + str(mask)) self.main.comms.serialWrite("local_btnpol=" + ("1" if self.polBox.isChecked() else "0")) def readValues(self): self.main.comms.serialGetAsync("local_btnpins?", self.initButtons, int) self.main.comms.serialGetAsync("local_btnpol?", self.polBox.setChecked, int)
class AnalogInputConf(OptionsDialogGroupBox): analogbtns = QButtonGroup() axes = 0 def __init__(self, name, main): self.main = main OptionsDialogGroupBox.__init__(self, name, main) self.analogbtns.setExclusive(False) self.buttonBox = QGroupBox("Pins") self.buttonBoxLayout = QVBoxLayout() self.buttonBox.setLayout(self.buttonBoxLayout) def initUI(self): layout = QVBoxLayout() self.autorangeBox = QCheckBox("Autorange") layout.addWidget(self.autorangeBox) layout.addWidget(self.buttonBox) self.setLayout(layout) def readValues(self): self.main.comms.serialGetAsync("local_ain_num?", self.createAinButtons, int) self.main.comms.serialGetAsync("local_ain_acal?", self.autorangeBox.setChecked, int) def createAinButtons(self, axes): self.axes = axes # remove buttons for i in range(self.buttonBoxLayout.count()): b = self.buttonBoxLayout.takeAt(0) self.buttonBoxLayout.removeItem(b) b.widget().deleteLater() for b in self.analogbtns.buttons(): self.analogbtns.removeButton(b) # add buttons for i in range(axes): btn = QCheckBox(str(i + 1), self) self.analogbtns.addButton(btn, i) self.buttonBoxLayout.addWidget(btn) def f(axismask): for i in range(self.axes): self.analogbtns.button(i).setChecked(axismask & (1 << i)) self.main.comms.serialGetAsync("local_ain_mask?", f, int) def apply(self): mask = 0 for i in range(self.axes): if (self.analogbtns.button(i).isChecked()): mask |= 1 << i self.main.comms.serialWrite("local_ain_mask=" + str(mask)) self.main.comms.serialWrite("local_ain_acal=" + ( "1" if self.autorangeBox.isChecked() else "0"))
class QScrollableBox(QWidget): def __init__(self, parent): super(QScrollableBox, self).__init__(parent) mainLayout = QVBoxLayout() mainLayout.setContentsMargins(0, 0, 0, 0) self.scrollArea = QScrollArea(self) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) self.scrollArea.setSizePolicy(sizePolicy) self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.scrollArea.setWidgetResizable(True) mainLayout.addWidget(self.scrollArea) self.setLayout(mainLayout) scrollContents = QWidget() self.m_layout = QVBoxLayout() self.m_layout.setContentsMargins(0, 0, 0, 0) self.m_layout.setSizeConstraint(QLayout.SetNoConstraint) scrollContents.setLayout(self.m_layout) self.scrollArea.setWidget(scrollContents) def addWidget(self, w): if not w: return count = self.m_layout.count() if count > 1: self.m_layout.removeItem(self.m_layout.itemAt(count - 1)) self.m_layout.addWidget(w) w.show() self.m_layout.addStretch() self.scrollArea.update() def removeWidget(self, w): self.m_layout.removeWidget(w) self.scrollArea.update() def insertWidget(self, i, w): self.m_layout.insertWidget(i, w) self.scrollArea.update() def clearWidgets(self): item = self.m_layout.takeAt(0) while item != None: item.widget().deleteLater() self.m_layout.removeItem(item) del item self.scrollArea.update() def indexOf(self, w): return self.m_layout.indexOf(w)
class StateGrid(QWidget): def __init__(self, parent=None): super().__init__(parent) self.central_widget = QWidget(self) self.scroll_area = QScrollArea(self) self.vbox = QVBoxLayout(self) self.rows = [] self.new_row() self.init_grid() def new_row(self): size = len(self.vbox) hbox = QHBoxLayout(self) self.vbox.addLayout(hbox, 1) if len(self.vbox) == size: hbox = QHBoxLayout(self) self.vbox.addLayout(hbox, 1) self.rows.append(hbox) def add_number(self, number_color): number, color = number_color if len(self.rows) == 0 or len(self.rows[-1]) >= 7: self.new_row() new_number = Number(self.scroll_area, number, color) new_number.number_clicked_signal.connect(self.on_number_clicked) self.rows[-1].addWidget(new_number) def pop_number(self): item = self.rows[-1].itemAt(len(self.rows[-1]) - 1) number = item.widget() self.rows[-1].removeItem(item) number.hide() number.deleteLater() if len(self.rows[-1]) == 0: self.vbox.removeItem(self.rows[-1]) self.rows.pop() def init_grid(self): self.setFixedSize(400 * variables.SCALE, 500 * variables.SCALE) self.scroll_area.setFixedSize(400 * variables.SCALE, 500 * variables.SCALE) self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.central_widget.setLayout(self.vbox) self.scroll_area.setWidget(self.central_widget) self.scroll_area.setWidgetResizable(True) def on_number_clicked(self, number): variables.GAME_INTERFACE.click_number(number)
def layout_group(self, name: str, vlayout: QVBoxLayout, hlayouts: typing.List[QHBoxLayout], path_variables: typing.List[Variable], widgets: typing.List[QLineEdit], button_fn: typing.Callable[[Variable, str], type(None)]): """ Layout the controls in one of the groups: input precomputed, output precomputed or tiffs :param name: A display name for the label to the left of the line edit :param vlayout: The top-level QT layout :param hlayouts: A list of the subsidiary horizontal layouts per channel :param path_variables: path variables per channel :param widgets: the QLineEdit widgets per channel :param button_fn: The function to run when someone presses the widget's path-finding button. """ n_channels = self.model.n_alignment_channels.get() while len(hlayouts) > n_channels: idx = len(hlayouts) - 1 path_variables[idx].unregister_callback("apply-alignment") hlayout = hlayouts[idx] while hlayout.count() > 0: item = hlayout.itemAt(0) hlayout.removeItem(item) if isinstance(item, QWidgetItem): item.widget().close() del widgets[idx] vlayout.removeItem(hlayouts[idx]) del hlayouts[idx] while n_channels > len(hlayouts): idx = len(hlayouts) hlayout = QHBoxLayout() hlayouts.append(hlayout) vlayout.addLayout(hlayout) hlayout.addWidget(QLabel("%s #%d: " % (name.capitalize(), idx + 1))) widget = QLineEdit() hlayout.addWidget(widget) widgets.append(widget) variable = path_variables[idx] variable.bind_line_edit(widget, "apply-alignment") button = QPushButton("...") hlayout.addWidget(button) button.clicked.connect(partial(button_fn, variable=variable))
class FormPage(QWidget): statusMessage = pyqtSignal(str) def __init__(self, parent=None, **kwargs): super(FormPage, self).__init__(parent) layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) form_frame = QGroupBox(self) self.vbox = QVBoxLayout(form_frame) self.form = PropertyFormLayout(None, **kwargs) self.vbox.addLayout(self.form) self.vbox.addStretch(1) self._has_stretch = True layout.addWidget(form_frame) def _removeStretch(self): if self._has_stretch: self.vbox.removeItem(self.vbox.itemAt(self.vbox.count() - 1)) self._has_stretch = False def addStretch(self): if not self._has_stretch: self.vbox.addStretch(1) self._has_stretch = True def kind(self, k=None): return self.form.kind(k) def addProperty(self, kind, path, row, col, *args, **kwargs): self.form.addProperty(self, kind, path, row, col, *args, **kwargs) def get_property_bridge(self, path): return self.form.get_property_bridge(path) def addWidget(self, widget, *args): self._removeStretch() self.form.addWidget(widget, *args) def addLayout(self, sublayout, *args): self._removeStretch() self.form.addLayout(sublayout, *args) def status_message(self, msg, *args): self.statusMessage.emit(msg.format(*args))
class AttributeEditor(QScrollArea): def __init__(self, obj, title: str = 'Object', parent=None): super().__init__(parent) self.myObj = obj self.myTitle = title self.myDict = {title: obj} self.initUi() def initUi(self): self.myWidget = QWidget(self) self.myLayout = QVBoxLayout() self.myLayout.setContentsMargins(5, 5, 5, 5) self.myWidget.setLayout(self.myLayout) self.setWidget(self.myWidget) self.setWidgetResizable(True) def updateUi(self): while self.myLayout.count(): item = self.myLayout.takeAt(0) widget = item.widget() if widget is not None: widget.deleteLater() else: self.myLayout.removeItem(item) widget = AWFactory.createWidget(self.myDict, self.myTitle, self, self.dataChanged.emit) self.myLayout.addWidget(widget) self.myLayout.addStretch(0) dataChanged = pyqtSignal() def iterObj(self): if isinstance(self.myObj, dict): for name in self.myObj: yield (name) elif '__dict__' in dir(self.myObj): for name in vars(self.myObj): if name[0] != '_': yield (name) else: raise TypeError('Unsupported object with type ' + type(self.myObj))
class CustomizeScreen(QWidget): def __init__(self, main): super().__init__() self.main = main def initUI(self): self.setGeometry(300, 300, 400, 100) self.setWindowTitle('Customize Screen') # grid = QGridLayout() # self.setLayout(grid) self.initialized = 3 self.cancel = False self.lbl1 = QLabel('입력: ') self.lbl2 = QLabel('입력: ') self.lbl3 = QLabel('입력: ') self.lbl4 = QLabel('입력: ') self.lbl5 = QLabel('입력: ') self.lbl6 = QLabel('입력: ') self.lbl7 = QLabel('입력: ') self.lbl8 = QLabel('입력: ') self.lbl9 = QLabel('입력: ') self.lbl10 = QLabel('입력: ') self.lbl11 = QLabel('') self.lbl11.setAlignment(Qt.AlignCenter) self.LE1 = QLineEdit() self.LE2 = QLineEdit() self.LE3 = QLineEdit() self.LE4 = QLineEdit() self.LE5 = QLineEdit() self.LE6 = QLineEdit() self.LE7 = QLineEdit() self.LE8 = QLineEdit() self.LE9 = QLineEdit() self.LE10 = QLineEdit() self.delButton1 = QPushButton("Del") self.delButton2 = QPushButton("Del") self.delButton3 = QPushButton("Del") self.delButton4 = QPushButton("Del") self.delButton5 = QPushButton("Del") self.delButton6 = QPushButton("Del") self.delButton7 = QPushButton("Del") self.delButton8 = QPushButton("Del") self.delButton9 = QPushButton("Del") self.delButton10 = QPushButton("Del") self.addButton = QPushButton("Add") self.saveButton = QPushButton("Save") self.cancelButton = QPushButton("Cancel") self.hbox1 = QHBoxLayout() self.hbox2 = QHBoxLayout() self.hbox3 = QHBoxLayout() self.hbox4 = QHBoxLayout() self.hbox5 = QHBoxLayout() self.hbox6 = QHBoxLayout() self.hbox7 = QHBoxLayout() self.hbox8 = QHBoxLayout() self.hbox9 = QHBoxLayout() self.hbox10 = QHBoxLayout() self.hbox11 = QHBoxLayout() self.hbox12 = QHBoxLayout() self.hbox13 = QHBoxLayout() self.vbox1 = QVBoxLayout() self.vbox2 = QVBoxLayout() self.vbox3 = QVBoxLayout() self.hboxList = [ self.hbox1, self.hbox2, self.hbox3, self.hbox4, self.hbox5, self.hbox6, self.hbox7, self.hbox8, self.hbox9, self.hbox10 ] self.vbox1.addLayout(self.hboxList[0]) self.vbox1.addLayout(self.hboxList[1]) self.vbox1.addLayout(self.hboxList[2]) self.vbox2.addLayout(self.hbox13) self.vbox2.addLayout(self.hbox11) self.vbox2.addLayout(self.hbox12) self.vbox3.addLayout(self.vbox1) self.vbox3.addLayout(self.vbox2) self.hbox1.addWidget(self.lbl1) self.hbox1.addWidget(self.LE1) self.hbox1.addWidget(self.delButton1) self.hbox2.addWidget(self.lbl2) self.hbox2.addWidget(self.LE2) self.hbox2.addWidget(self.delButton2) self.hbox3.addWidget(self.lbl3) self.hbox3.addWidget(self.LE3) self.hbox3.addWidget(self.delButton3) self.hbox4.addWidget(self.lbl4) self.hbox4.addWidget(self.LE4) self.hbox4.addWidget(self.delButton4) self.hbox5.addWidget(self.lbl5) self.hbox5.addWidget(self.LE5) self.hbox5.addWidget(self.delButton5) self.hbox6.addWidget(self.lbl6) self.hbox6.addWidget(self.LE6) self.hbox6.addWidget(self.delButton6) self.hbox7.addWidget(self.lbl7) self.hbox7.addWidget(self.LE7) self.hbox7.addWidget(self.delButton7) self.hbox8.addWidget(self.lbl8) self.hbox8.addWidget(self.LE8) self.hbox8.addWidget(self.delButton8) self.hbox9.addWidget(self.lbl9) self.hbox9.addWidget(self.LE9) self.hbox9.addWidget(self.delButton9) self.hbox10.addWidget(self.lbl10) self.hbox10.addWidget(self.LE10) self.hbox10.addWidget(self.delButton10) self.hbox11.addWidget(self.addButton) self.hbox12.addWidget(self.saveButton) self.hbox12.addWidget(self.cancelButton) self.hbox13.addWidget(self.lbl11) self.addButton.clicked.connect(self.Click_addButton) self.saveButton.clicked.connect(self.Click_saveButton) self.cancelButton.clicked.connect(self.Click_cancelButton) self.infoDic = { 0: { 'del': self.delButton1, 'le': self.LE1, 'lbl': self.lbl1, 'hbox': self.hbox1 }, 1: { 'del': self.delButton2, 'le': self.LE2, 'lbl': self.lbl2, 'hbox': self.hbox2 }, 2: { 'del': self.delButton3, 'le': self.LE3, 'lbl': self.lbl3, 'hbox': self.hbox3 }, 3: { 'del': self.delButton4, 'le': self.LE4, 'lbl': self.lbl4, 'hbox': self.hbox4 }, 4: { 'del': self.delButton5, 'le': self.LE5, 'lbl': self.lbl5, 'hbox': self.hbox5 }, 5: { 'del': self.delButton6, 'le': self.LE6, 'lbl': self.lbl6, 'hbox': self.hbox6 }, 6: { 'del': self.delButton7, 'le': self.LE7, 'lbl': self.lbl7, 'hbox': self.hbox7 }, 7: { 'del': self.delButton8, 'le': self.LE8, 'lbl': self.lbl8, 'hbox': self.hbox8 }, 8: { 'del': self.delButton9, 'le': self.LE9, 'lbl': self.lbl9, 'hbox': self.hbox9 }, 9: { 'del': self.delButton10, 'le': self.LE10, 'lbl': self.lbl10, 'hbox': self.hbox10 } } self.starImgList = [ 'PNG/Number/one.png', 'PNG/Number/two.png', 'PNG/Number/three.png', 'PNG/Number/four.png', 'PNG/Number/five.png', 'PNG/Number/six.png', 'PNG/Number/seven.png', 'PNG/Number/eight.png', 'PNG/Number/nine.png', 'PNG/Number/ten.png' ] self.initializedList = [] self.customizeDic = {} for i in range(3): self.initializedList.append(self.infoDic[i]['hbox']) for i in range(3, 10): self.infoDic[i]['del'].hide() self.infoDic[i]['le'].hide() self.infoDic[i]['lbl'].hide() for i in range(len(self.infoDic)): self.infoDic[i]['del'].clicked.connect( lambda state, x=i: self.Click_delButton(x)) self.setLayout(self.vbox3) self.show() def Click_addButton(self): for i in range(len(self.infoDic)): if self.infoDic[i]['hbox'] not in self.initializedList: self.initializedList.append(self.infoDic[i]['hbox']) self.vbox1.addLayout(self.infoDic[i]['hbox']) self.infoDic[i]['del'].show() self.infoDic[i]['le'].show() self.infoDic[i]['lbl'].show() self.initialized += 1 break if self.initialized >= 10: self.lbl11.setText("Up to 10 can be entered.") self.addButton.hide() self.vbox2.removeItem(self.hbox11) print(self.initialized) def Click_delButton(self, x): if self.initialized > 3: self.infoDic[x]['le'].setText("") self.infoDic[x]['le'].hide() self.infoDic[x]['lbl'].hide() self.infoDic[x]['del'].hide() self.vbox1.removeItem(self.infoDic[x]['hbox']) self.initializedList.remove(self.infoDic[x]['hbox']) else: print("It has to more than 3.") self.lbl11.setText("You must enter at least three") return if self.initialized == 10: self.saveButton.hide() self.cancelButton.hide() self.vbox2.removeItem(self.hbox12) self.vbox2.addLayout(self.hbox11) self.addButton.show() self.vbox2.addLayout(self.hbox12) self.saveButton.show() self.cancelButton.show() self.initialized -= 1 print(self.initialized) def Click_saveButton(self): count = 0 for i in range(len(self.initializedList)): if (len(self.infoDic[i]['le'].text()) != 0): count += 1 if count < 3: self.lbl11.setText("You must enter at least three") else: for i in range(len(self.initializedList)): if (len(self.infoDic[i]['le'].text()) != 0): self.customizeDic[i] = { 'image': self.starImgList[i], 'text': self.infoDic[i]['le'].text() } print(self.customizeDic) self.close() self.main.customizeDic = self.customizeDic def Click_cancelButton(self): self.cancel = True self.close()
class CmdWindow(QWidget): ''' The Command window gives the user all the options to create and send a command message - Dropdown menus to select an Instance, Topic and Subcommand - Fields to enter payload values - A time stamped log showing the commands that were successfully sent ''' def __init__(self): super().__init__() self.title = "Telecommand System" self.top = 300 self.left = 300 self.width = 1000 self.height = 800 self.instance_name = GS_Model.data.instance_chooser self.topic_name = GS_Model.data.topic_chooser self.subcommand_name = GS_Model.data.subcommand_chooser self.payload_entries = [] self.payload_values = {} self.InitWindow() def InitWindow(self): ''' Initialize the Command window layout ''' self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) # Destination IP Address self.ip_label = QLabel("IP Address:") self.ip_textbox = QLineEdit("127.0.0.1") self.hbox_ip = QHBoxLayout() self.hbox_ip.addWidget(self.ip_label) self.hbox_ip.addWidget(self.ip_textbox) # Instance Menu self.instance_label = QLabel("Instance:") self.instance_menu = QComboBox(self) for instance in GS_Model.data.instance_keys: self.instance_menu.addItem(instance) self.instance_menu.currentIndexChanged.connect(self.UpdateInstance) self.hbox_instance = QHBoxLayout() self.hbox_instance.addWidget(self.instance_label) self.hbox_instance.addWidget(self.instance_menu) # Topic Menu self.topic_label = QLabel("Topic:") self.topic_menu = QComboBox(self) for topic in GS_Model.data.telecommand_topic_keys: self.topic_menu.addItem(topic) self.topic_menu.currentIndexChanged.connect(self.UpdateTopic) self.hbox_topic = QHBoxLayout() self.hbox_topic.addWidget(self.topic_label) self.hbox_topic.addWidget(self.topic_menu) # Subcommand Menu self.subcommand_label = QLabel("Subcommand:") self.subcommand_menu = QComboBox(self) for subcommand in GS_Model.data.subcommand_keys: self.subcommand_menu.addItem(subcommand) self.subcommand_menu.currentIndexChanged.connect(self.UpdateSubcommand) self.hbox_subcommand = QHBoxLayout() self.hbox_subcommand.addWidget(self.subcommand_label) self.hbox_subcommand.addWidget(self.subcommand_menu) # Payload Menu self.payload_label = QLabel("Payload:") self.vbox_payload = QVBoxLayout() self.vbox_payload.addWidget(self.payload_label) # Send Command Button self.send_cmd_button = QPushButton("Send Command") self.send_cmd_button.clicked.connect(self.SendCommand) # Command Log Display self.cmd_log_label = QLabel("Command Log:") self.cmd_log = QTextBrowser() # Save Command Log Button self.save_cmd_log = QPushButton("Save Command Log") self.save_cmd_log.clicked.connect(self.SaveCommandLog) # Overall Layout self.layout = QVBoxLayout() self.layout.addLayout(self.hbox_ip) self.layout.addLayout(self.hbox_instance) self.layout.addLayout(self.hbox_topic) self.layout.addLayout(self.hbox_subcommand) self.layout.addLayout(self.vbox_payload) self.layout.addWidget(self.send_cmd_button) self.layout.addWidget(self.cmd_log_label) self.layout.addWidget(self.cmd_log) self.layout.addWidget(self.save_cmd_log) self.setLayout(self.layout) self.show() def UpdateInstance(self): ''' This updates the instance variable when a new instance is selected in the GUI ''' self.instance_name = self.instance_menu.currentText() def UpdateTopic(self): ''' This updates the topic variable when a new topic is selected. It also updates the Subcommand dropdown and payload entries with new values (if available) ''' self.topic_name = self.topic_menu.currentText() if self.topic_name != GS_Model.data.topic_chooser: # Update the Subcommand dropdown menu GS_Model.data.UpdateSubcommands(self.topic_name) self.subcommand_menu.setCurrentIndex(0) for i in reversed(range(1, self.subcommand_menu.count())): self.subcommand_menu.removeItem(i) for subcommand in GS_Model.data.subcommand_keys: if subcommand != GS_Model.data.subcommand_chooser: self.subcommand_menu.addItem(subcommand) self.subcommand_menu.update() # Update payload layout if needed eds_id = GS_Controller.control.GetEdsIdFromTopic(self.topic_name) payload_struct = GS_Controller.control.GetPayload(eds_id) if payload_struct is not None: self.UpdatePayload(payload_struct) else: self.UpdatePayload([]) else: self.subcommand_menu.setCurrentIndex(0) for i in reversed(range(1, self.subcommand_menu.count())): self.subcommand_menu.removeItem(i) self.subcommand_menu.update() self.UpdatePayload([]) def UpdateSubcommand(self): ''' This updates the subcommand variable when a new subcommand is selected in the GUI If the new subcommand has new payload values, they are also updated ''' self.subcommand_name = self.subcommand_menu.currentText() eds_id = GS_Model.data.subcommand_dict[self.subcommand_name] if eds_id != 0: payload_struct = GS_Controller.control.GetPayload(eds_id) if payload_struct is not None: self.UpdatePayload(payload_struct) else: self.UpdatePayload([]) else: self.UpdatePayload([]) def ExtractEntries(self, payload_struct): ''' This method generates a list of all the payload entries throughout the payload structure. This list is used to update the display with all of the payload entries Inputs: payload_struct - The payload structure output from GS_Controller.GetPayloadStructure ''' if isinstance(payload_struct, dict): for item in list(payload_struct.keys()): self.ExtractEntries(payload_struct[item]) elif isinstance(payload_struct, list): for item in payload_struct: self.ExtractEntries(item) elif isinstance(payload_struct, tuple): label = QLabel("{:<30} {}".format(payload_struct[0], payload_struct[1])) if payload_struct[2] == 'entry': payloadinput = QLineEdit() elif payload_struct[2] == 'enum': payloadinput = QComboBox() for enum_label in list(payload_struct[3].keys()): payloadinput.addItem(enum_label) else: ErrorMessage("Error", "Something went wrong in the ExtractEntries function") return self.payload_entries.append((payload_struct[0], payload_struct[1], label, payloadinput)) else: ErrorMessage("Error", "Something went wrong in the ExtractEntries function") def UpdatePayload(self, payload_struct): ''' When the payload stucture changes, this method removes the old payload entries and adds new ones based on the payload_struct Inputs: payload_struct - The payload structure output from GS_Controller.GetPayloadStructure ''' # remove the current payload entires in the payload layout (each are their own hbox layouts) for i in reversed(range(1, self.vbox_payload.count())): layout_item = self.vbox_payload.itemAt(i) DeleteItemsOfLayout(layout_item.layout()) self.vbox_payload.removeItem(layout_item) self.vbox_payload.update() # add new widgets to represent the new payload entries self.payload_entries = [] self.ExtractEntries(payload_struct) for entry in self.payload_entries: hbox = QHBoxLayout() hbox.addWidget(entry[2]) hbox.addWidget(entry[3]) self.vbox_payload.addLayout(hbox) self.vbox_payload.update() def SendCommand(self): ''' This method takes the input IP Address and payload values and calls GS_Controller.control.SendCommand to send the packed message. If the command was successfully sent, the command log display will be updated with information related to the command. ''' ip_address = self.ip_textbox.text() valid_payload = True self.payload_values = {} for entry in self.payload_entries: try: value = entry[3].currentText() except AttributeError: value = entry[3].text() if not GS_Controller.ValidPayload(entry, value): ErrorMessage("Error", "Invalid input for '{}'".format(entry[0])) valid_payload = False else: self.payload_values[entry[0]] = value if valid_payload: (cmd_sent, msg, timestamp, port) = GS_Controller.control.SendCommand(ip_address, self.instance_name, self.topic_name, self.subcommand_name, self.payload_values) if cmd_sent: cmd_log_info = f"Command Sent: {timestamp}\n" cmd_log_info += "IP: {} ".format(ip_address) cmd_log_info += "Port: {}\n".format(port) cmd_log_info += "Instance: {} ".format(self.instance_name) cmd_log_info += "Topic: {} ".format(self.topic_name) if self.subcommand_name == GS_Model.data.subcommand_chooser: cmd_log_info += "Subcommand: None\n" else: cmd_log_info += "Subcommand: {}\n".format(self.subcommand_name) cmd_log_payload = '' payload_keys = list(self.payload_values.keys()) for key in payload_keys: cmd_log_payload += "{:<30}: ".format(key) cmd_log_payload += "{}\n".format(self.payload_values[key]) cmd_log_message = "Data to send: \n{}\n".format(GS_Model.HexString(msg, 8)) cmd_log_string = cmd_log_info + cmd_log_payload + cmd_log_message + '\n' self.cmd_log.append(cmd_log_string) self.cmd_log.verticalScrollBar().setValue(self.cmd_log.verticalScrollBar().maximum()) else: ErrorMessage("Error", msg) def SaveCommandLog(self): ''' This method outputs the command log to a time stamped text file. The command log is also cleared when the log file is written. ''' time_str = time.strftime("%Y-%m-%d__%H_%M_%S", time.gmtime()) if not os.path.isdir("output/"): os.mkdir("output/") filename = f"output/Command_Log_{time_str}.txt" fout = open(filename, 'w') fout.write(self.cmd_log.toPlainText()) fout.close() self.cmd_log.clear() self.cmd_log.update()
class Filter: locks = dict() def __init__(self, filter_content): self.filter_content = filter_content self.filter = dict() self.frame = QFrame() self.frame.setObjectName("Filter_frame") self.frame.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding) actual_layout = QVBoxLayout() widget_frame = QFrame() self.layout = QVBoxLayout() widget_frame.setLayout(self.layout) actual_layout.addWidget(widget_frame) actual_layout.addStretch(1) self.filter_names = [] self.frame.setLayout(actual_layout) self.frame.setHidden(True) def add_range(self, name, capitalize=False): min_input = QLineEdit() max_input = QLineEdit() min_input.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) min_input.setMaximumWidth(50) max_input.setMaximumWidth(50) if capitalize: name = name.capitalize() title = QLabel(name) dash = QLabel("-") frame = QFrame() layout = QHBoxLayout() layout.addWidget(min_input) layout.addStretch(0) layout.addWidget(dash) layout.addStretch(0) layout.addWidget(max_input) frame.setLayout(layout) # frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.layout.addWidget(title) self.layout.addWidget(frame) min_input.textChanged.connect( lambda: self.set_range_filter(name, min_input, max_input)) max_input.textChanged.connect( lambda: self.set_range_filter(name, min_input, max_input)) def set_range_filter(self, name, min_input, max_input): name = name.lower() minimum = -9001 maximum = 9001 try: minimum = int(min_input.text()) except: pass try: maximum = int(max_input.text()) except: pass if minimum == -9001 and maximum == 9001: if name in self.filter.keys(): del self.filter[name] else: self.filter[name] = [minimum, maximum] self.filter_content() def add_dropdown(self, name, options, suboptions=None, default=None, alphabetical=True): if alphabetical: options.sort() combo_box = QComboBox() combo_box.addItem("Any") combo_box.addItems(options) if suboptions is not None: sub_combo_box = QComboBox() sub_combo_box.setHidden(True) else: sub_combo_box = None label = QLabel(name) self.filter_names.append(name) self.layout.addWidget(label) self.layout.addWidget(combo_box) if suboptions is not None: self.layout.addWidget(sub_combo_box) sub_combo_box.currentIndexChanged.connect( lambda: self.set_sub_filters(name, combo_box, sub_combo_box)) combo_box.currentIndexChanged.connect(lambda: self.set_filters( name, combo_box, sub_combo_box, suboptions)) if default is not None: index = combo_box.findText(default, QtCore.Qt.MatchFixedString) if index >= 0: combo_box.setCurrentIndex(index) def set_sub_filters(self, name, combo_box, sub_combo_box): name = name.lower() main = combo_box.currentText().lower() sub = sub_combo_box.currentText().lower() if sub == "any": self.filter[name] = main + ".*" else: self.filter[name] = main + ".*(\ \(|\,\ )(" + sub + ").*" self.filter_content() def set_filters(self, name, combo_box, sub_combo_box=None, suboptions=None): main = combo_box.currentText() sub_cond = sub_combo_box is not None if sub_cond: sub = sub_combo_box.currentText() name = name.lower() if main == "Any" and name in self.filter.keys(): del self.filter[name] if sub_cond: sub_combo_box.setHidden(True) else: if sub_cond: if main in suboptions.keys(): _suboptions = [ subopt for subopt in suboptions[main] if subopt != "Any" ] # remove Any as suboption sub_combo_box.setHidden(False) sub_combo_box.clear() sub_combo_box.addItem("Any") sub_combo_box.addItems(_suboptions) else: sub_combo_box.clear() sub_combo_box.setHidden(True) self.filter[name] = main + ".*" # print(self.filter[name]) self.filter_content() def lock(self, attr, value): self.locks[attr] = value def get_frame(self): return self.frame def toggle_hidden(self): if self.frame.isHidden(): self.frame.setHidden(False) else: self.frame.setHidden(True) def evaluate_filter(self, entry): cond = True for key, arg in self.locks.items(): if not hasattr(entry, key) or getattr(entry, key) != arg: return False for key, arg in self.filter.items(): if not hasattr(entry, key): # print("Wrong filter key passed to entry in SearchableTable") return False attr = getattr(entry, key) if type(arg) is str and type( attr ) is str: # single attribute, single argument. Easy as pie p = re.compile('{}'.format(arg), re.IGNORECASE) cond = cond and (p.match(attr)) elif type( attr ) is list: # single argument, multiple attributes, eval individually for each element p = re.compile('{}'.format(arg), re.IGNORECASE) cond = cond and any([p.match(_attr) for _attr in attr]) elif type( arg ) is list: # numerical range, must be inbetween two values if attr is None or None in arg: continue attr = eval("float({})".format(attr)) cond = cond and (arg[0] <= attr <= arg[1]) return cond def clear_filters(self): for i in reversed(range(self.layout.count())): self.layout.removeItem(self.layout.itemAt(i)) self.filter = dict()
class MainWindow(QWidget): ## # \brief Initialization Function def __init__(self): super(MainWindow, self).__init__() #Default variables self.valid = False #Field to determine if the value is valid self.selectorLayout = None #Layout used for selecting a specific source self.sources = ["none", "text", "file", "database"] self.source = {"type": None} self.dests = ["console", "file"] self.dest = {"type": "console"} self.sourceValue = None self.sourceSchema = None #Determine screen settings geo = self.frameGeometry() self.width = QDesktopWidget().availableGeometry().width() self.height = QDesktopWidget().availableGeometry().height() #Define window par meters self.resize(self.width * .5, self.height * .5) self.setWindowTitle("Aqueti Schema Editor") self.show() #create Layouts in UI self.titleLayout = QHBoxLayout() self.mainLayout = QVBoxLayout() self.sourceLayout = QHBoxLayout() self.destLayout = QHBoxLayout() self.valueLayout = QVBoxLayout() self.buttonLayout = QHBoxLayout() #Create frames self.sourceFrame = QFrame() self.destFrame = QFrame() self.valueFrame = QFrame() self.sourceFrame.setFrameStyle(QFrame.Box) self.valueFrame.setFrameStyle(QFrame.Box) self.destFrame.setFrameStyle(QFrame.Box) self.sourceFrame.setLayout(self.sourceLayout) self.destFrame.setLayout(self.destLayout) self.valueFrame.setLayout(self.valueLayout) self.valueFrame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) #Create Scoll Area for valueFrame self.valueScrollArea = QScrollArea() self.valueScrollArea.updateGeometry() self.valueScrollArea.setWidget(self.valueFrame) self.valueScrollArea.setWidgetResizable(True) #Create title title = QLabel() title.setText("Aqueti Schema Editor") self.titleLayout.addWidget(title) #Add persistent source items sourceTitle = QLabel() sourceTitle.setText("Source:") self.sourceCombo = QComboBox() self.sourceCombo.addItems(self.sources) self.sourceCombo.currentTextChanged.connect( lambda: self.sourceChangeCallback()) selectSourceButton = QPushButton("Load") self.sourceLayout.addWidget(sourceTitle) self.sourceLayout.addWidget(self.sourceCombo) self.sourceMetaLayout = QHBoxLayout() self.sourceMetaLayout.setSizeConstraint(QHBoxLayout.SetMinimumSize) self.sourceLayout.addLayout(self.sourceMetaLayout) self.sourceLayout.addWidget(selectSourceButton) #Add persistent dest destTitle = QLabel() destTitle.setText("Dest:") self.destCombo = QComboBox() self.destCombo.addItems(self.dests) self.destCombo.currentTextChanged.connect( lambda: self.destChangeCallback()) selectDestButton = QPushButton("Load") self.destLayout.addWidget(destTitle) self.destLayout.addWidget(self.destCombo) self.destMetaLayout = QHBoxLayout() self.destMetaLayout.setSizeConstraint(QHBoxLayout.SetMinimumSize) self.destLayout.addLayout(self.destMetaLayout) self.destLayout.addWidget(selectDestButton) #Add Submit Button self.submitButton = QPushButton("Submit") self.submitButton.clicked.connect(lambda: self.submitCallback()) self.buttonLayout.addWidget(self.submitButton) #Add cancel Button cancelButton = QPushButton("Cancel") cancelButton.clicked.connect(lambda: self.cancelCallback()) self.buttonLayout.addWidget(cancelButton) #Add Layouts and draw self.mainLayout.addLayout(self.titleLayout) self.mainLayout.addWidget(self.sourceFrame) self.mainLayout.addWidget(self.destFrame) # self.mainLayout.addWidget( self.valueFrame ) self.mainLayout.addWidget(self.valueScrollArea) # self.mainLayout.addStretch(1) self.mainLayout.addLayout(self.buttonLayout) self.draw() ## # \brief updates the source Layout def updateSourceLayout(self): #Remove current layout information #Remove all widgets from the current layout while self.sourceMetaLayout.count(): item = self.sourceMetaLayout.takeAt(0) self.sourceMetaLayout.removeItem(item) widget = item.widget() if widget is not None: widget.deleteLater() try: item.deleteLater() except: pass #Find what our current source is and set the appropriate index index = 0 for i in range(0, self.sourceCombo.count()): if self.sourceCombo.itemText(i) == self.source["type"]: index = i self.sourceCombo.setCurrentIndex(index) #Add fields based on source type if self.source["type"] == "file": #Add filename fileLabel = QLabel() fileLabel.setText("file: ") try: name = self.source["filename"] except: name = "" self.sourceFilenameBox = QLineEdit() self.sourceFilenameBox.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) self.sourceFilenameBox.setText(name) # self.sourceFilenameBox.readOnly = True # self.sourceFilenameBox.sizeHint() # self.sourceFilenameBox.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.sourceMetaLayout.addWidget(fileLabel) self.sourceMetaLayout.addWidget(self.sourceFilenameBox) # #Add a submitSource Button # selectSourceButton = QPushButton("Load") # selectSourceButton.clicked.connect( lambda: self.sourceChangeCallback()) # self.sourceLayout.addWidget(selectSourceButton) # self.sourceLayout.addStretch(1) ## # \brief updates the destination layout # def updateDestLayout(self): #Remove current layout information #Remove all widgets from the current layout while self.destMetaLayout.count(): item = self.destMetaLayout.takeAt(0) self.destMetaLayout.removeItem(item) widget = item.widget() if widget is not None: widget.deleteLater() try: item.deleteLater() except: pass """ ############################################# # Layout to select a destination ############################################# destTitle = QLabel() destTitle.setText("Dest:") self.destCombo = QComboBox() self.destCombo.addItems(self.dests) """ #Find what our current dest is and set the appropriate index index = 0 for i in range(0, self.destCombo.count()): if self.destCombo.itemText(i) == self.dest["type"]: index = i self.destCombo.setCurrentIndex(index) self.destCombo.currentTextChanged.connect( lambda: self.destChangeCallback()) # self.destLayout.addWidget(destTitle) # self.destLayout.addWidget(self.destCombo) # self.destLayout.addStretch(1) #### # Fill in details base on dest tpye #### if self.dest["type"] == "console": pass elif self.dest["type"] == "file": fileLabel = QLabel() fileLabel.setText("file: ") try: name = self.dest["filename"] except: name = "" self.fileNameBox = QLineEdit() self.fileNameBox.setText(name) # self.destMetaLayout.addWidget(fileLabel) self.destMetaLayout.addWidget(self.fileNameBox) ## # \brief function that is called when the source is changed # def destChangeCallback(self): print("Changing dest") newType = self.destCombo.itemText(self.destCombo.currentIndex()) print("New Type: " + str(newType)) if newType != self.dest["type"]: self.dest = {} self.dest["type"] = newType if self.dest["type"] == "console": pass elif self.dest["type"] == "file": options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog destName, _ = QFileDialog.getSaveFileName( self, "QFileDialog.getSaveFileName()", "", "All Files (*);;JSON Files (*.json)", options=options) self.dest["filename"] = str(destName) else: print("Unsupported Type") self.draw() ## # \brief Update the value layout def updateValueLayout(self): #Remove all widgets from the current layout while self.valueLayout.count(): item = self.valueLayout.takeAt(0) self.valueLayout.removeItem(item) widget = item.widget() if widget is not None: widget.deleteLater() try: item.deleteLater() except: pass #If we have data, let's display it if self.sourceSchema != None: valueTitle = QLabel() valueTitle.setText("Schema") self.schemaWidget = SmartWidget().init("Schema", self.sourceValue, self.sourceSchema, showSchema=False) self.valueLayout.addWidget(self.schemaWidget.frame) #Disable the submit button if we don't have a schema if self.sourceSchema == None: self.submitButton.setEnabled(False) else: self.submitButton.setEnabled(True) self.setLayout(self.mainLayout) ## # \brief redraws all dynamic layouts def draw(self): self.updateDestLayout() self.updateSourceLayout() self.updateValueLayout() ## # \brief callback for when the source type changes # def sourceChangeCallback(self): #SDF Add popup to notify of schema loss #Clear the schema to disable the submit button self.sourceSchema = None self.source["type"] = self.sourceCombo.itemText( self.sourceCombo.currentIndex()) if self.source["type"] == "none": self.sourceSchema = {"bsonType": "object"} #If we are a file read the file contents as the value elif self.source["type"] == "file": options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog sourceName, _ = QFileDialog.getOpenFileName( self, "QFileDialog.getOpenFileName()", "", "All Files (*);;JSON Files (*.json)", options=options) self.source["filename"] = str(sourceName) print("Loading: " + str(self.source["filename"])) with open(self.source["filename"]) as json_file: self.sourceSchema = json.load(json_file) print("Loaded Schema:" + str(json.dumps(self.sourceSchema, indent=4))) self.updateSourceLayout() self.updateValueLayout() ## #\brief callback to get result from SmartWidget # # This function assumes that the schema is done. It will produce a popup # asking where and how to save the data # def submitCallback(self): schema = self.schemaWidget.getSchema() if self.dest["type"] == "console": print() print("Schema: (" + str(time.time()) + ")") print(json.dumps(schema, indent=4)) elif self.dest["type"] == "file": print("Writing to: " + str(self.dest["filename"])) with open(self.dest["filename"], 'w') as outfile: json.dump(schema, outfile, indent=4) else: print("Source type: " + str(self.dest["type"]) + " is not currently supported") self.close() #Use save pop-up to save data #self.saveWindow = SaveDataWindow(self.source, schema, self.saveCallback ) print(str(time.time()) + "- schema:") print(str(schema)) ## # \brief Function called after data is saved # def saveCallback(self, success): print("Data Result: " + str(success)) ## # \brief Cancels the change and exits # def cancelCallback(self): print("Exited. No changes were saved") sys.exit(1)
class LiveWidget(QWidget): """ """ def __init__(self): """ """ super(LiveWidget, self).__init__() self.pot_btn = QPushButton('PotPlayer播放') self.vlc_btn = QPushButton('VLC播放') self.vlc_widget = VLCWidget() self.player_widget = QWidget() self.player_layout = QVBoxLayout() self._layout = QVBoxLayout() self.set_player_widget() self.init_ui() def init_ui(self): """ :return: """ # player_layout = QVBoxLayout() self.player_layout.setContentsMargins(0, 0, 0, 0) self.player_layout.setSpacing(0) self.player_layout.addWidget(self.player_widget) main_layout = QVBoxLayout() main_layout.setContentsMargins(0, 0, 0, 0) main_layout.setSpacing(0) main_layout.addLayout(self.player_layout) self.setLayout(main_layout) self.setStyleSheet( "background-image:url(./resources/img/live_null.png); ") def clear_layout(self): """ :return: """ for i in range(self._layout.count()): print("i {0}".format(i)) self._layout.removeItem(self._layout.itemAt(i)) self._layout.setParent(None) self.player_layout.removeItem(self._layout) def set_widget_visible(self, visible): """ :return: """ if visible: # self.vlc_widget.setVisible(True) self.vlc_widget.show() else: # self.vlc_widget.setVisible(False) self.vlc_widget.hide() def set_player_widget(self, widget=False): """ :param widget: :return: """ # self.clear_layout() self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(0) self._layout.addWidget(self.vlc_widget) self.set_widget_visible(widget) self.player_widget.setLayout(self._layout)
class TableMetaWidget(MetaWidget): def __init__(self, parent=None): super().__init__(parent=parent) self.cover_label = CoverLabel(self) # these three widgets are in right layout self.title_label = QLabel(self) self.meta_label = QLabel(self) # this spacer item is used as a stretch in right layout, # it's width and height is not so important, we set them to 0 self.text_spacer = QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding) self.title_label.setTextFormat(Qt.RichText) self.meta_label.setTextFormat(Qt.RichText) self._setup_ui() self._refresh() def _setup_ui(self): self.cover_label.setMinimumWidth(150) self.cover_label.setMaximumWidth(200) self._v_layout = QVBoxLayout(self) self._h_layout = QHBoxLayout() self._right_layout = QVBoxLayout() self._right_layout.addStretch(0) self._right_layout.addWidget(self.title_label) self._right_layout.addWidget(self.meta_label) self._h_layout.addWidget(self.cover_label) self._h_layout.setAlignment(self.cover_label, Qt.AlignTop) self._h_layout.addLayout(self._right_layout) self._h_layout.setStretchFactor(self._right_layout, 2) self._h_layout.setStretchFactor(self.cover_label, 1) self._h_layout.setContentsMargins(0, 30, 0, 0) self._h_layout.setSpacing(30) self._v_layout.addLayout(self._h_layout) self._right_layout.setContentsMargins(0, 0, 0, 0) self._right_layout.setSpacing(5) # left margin is same as toolbar left margin self.layout().setContentsMargins(30, 0, 30, 0) self.layout().setSpacing(0) def add_tabbar(self, tabbar): self._right_layout.addWidget(tabbar) self._right_layout.setAlignment(self.parent().tabbar, Qt.AlignLeft) def set_cover_pixmap(self, pixmap): if pixmap is not None: self.cover_label.show() self._right_layout.addItem(self.text_spacer) self.cover_label.show_pixmap(pixmap) self.updateGeometry() def on_property_updated(self, name): if name in ('created_at', 'updated_at', 'songs_count', 'creator'): self._refresh_meta_label() elif name in ('title', 'subtitle'): self._refresh_title() elif name == 'cover': self._refresh_cover() def _refresh_meta_label(self): creator = self.creator # icon: 👤 creator_part = creator if creator else '' created_part = updated_part = songs_count_part = '' if self.updated_at: updated_part = '🕒 更新于 <code style="font-size: small">{}</code>'\ .format(self.updated_at.strftime('%Y-%m-%d')) if self.created_at: created_part = '🕛 创建于 <code style="font-size: small">{}</code>'\ .format(self.created_at.strftime('%Y-%m-%d')) if self.songs_count is not None: text = self.songs_count if self.songs_count != -1 else '未知' songs_count_part = '<code style="font-size: small">{}</code> 首æŒæ›²'\ .format(text) if creator_part or updated_part or created_part or songs_count_part: parts = [ creator_part, created_part, updated_part, songs_count_part ] valid_parts = [p for p in parts if p] content = ' • '.join(valid_parts) text = '<span>{}</span>'.format(content) # TODO: add linkActivated callback for meta_label self.meta_label.setText(text) self.meta_label.show() else: self.meta_label.hide() def _refresh_cover(self): if not self.cover: self.cover_label.hide() self._right_layout.removeItem(self.text_spacer) else: self._right_layout.addItem(self.text_spacer) self.updateGeometry() def _refresh_title(self): if self.title: self.title_label.show() self.title_label.setText('<h2>{}</h2>'.format(self.title)) else: self.title_label.hide() def _refresh(self): self._refresh_title() self._refresh_meta_label() self._refresh_cover() def sizeHint(self): super_size = super().sizeHint() if self.cover_label.isVisible(): margins = self.layout().contentsMargins() v_margin = margins.top() + margins.bottom() height = self.cover_label.sizeHint().height() + v_margin return QSize(super_size.width(), height) return super_size def resizeEvent(self, e): super().resizeEvent(e) # HELP: think about a more elegant way # Currently, right panel draw background image on meta widget # and bottom panel, when meta widget is resized, the background # image will also be scaled, so we need to repaint on bottom panel # and meta widget. However, by default, qt will only repaint # meta widget in this case, so we trigger bottom panel update manually self.parent()._app.ui.bottom_panel.update()
class ConsolePanel(QFrame): def __init__(self, master): super().__init__(master) self.cbTimestamp = QCheckBox("Timestamp", self) self.cbErrors = QCheckBox("Errors", self) self.cbInfo = QCheckBox("Info", self) self.cbOrders = QCheckBox("Orders", self) self.cbAnswers = QCheckBox("Answers", self) self.cbSensors = QCheckBox("Sensors", self) self.cbList = [self.cbTimestamp, self.cbErrors, self.cbInfo, self.cbOrders, self.cbAnswers, self.cbSensors] for cb in self.cbList: cb.setChecked(True) cb.stateChanged.connect(self.settings_changed) self.console = QTextEdit(self) self.console.setReadOnly(True) self.consoleVScrollBar = self.console.verticalScrollBar() self.font = "Consolas" self.fontSize = 9 self.fontSize_small = 7 self.timestampColor = QColor(119, 180, 177) self.textColor = QColor(197, 200, 198) self.errorColor = QColor(195, 48, 39) self.orderColor = QColor(1, 160, 228) self.answerColor = QColor(1, 162, 82) self.sensorColor = QColor(1, 160, 160) self.console.setStyleSheet(""" background-color: rgb(29, 31, 33); color: rgb(197, 200, 198); """) self.consoleText = "" self.margin = 41 # Parameter to tune to make things work self.width_needed = None grid = QGridLayout() self.cbArea = QVBoxLayout() grid.addLayout(self.cbArea, 0, 0) grid.addWidget(self.console, 1, 0, 1, 2) grid.setRowStretch(1, 1) grid.setColumnStretch(1, 1) self.setLayout(grid) self.organizeWidgets(init=True) def resizeEvent(self, event): w = self.cbArea.minimumSize().width() availableWidth = event.size().width() - self.margin if availableWidth > 30: if availableWidth <= w or (self.width_needed is not None and availableWidth > w + self.width_needed): self.organizeWidgets(False, availableWidth - 30) def organizeWidgets(self, init, availableWidth=None): if not init: for i in reversed(range(self.cbArea.count())): item = self.cbArea.itemAt(i) if isinstance(item, QLayoutItem): layout = item.layout() for j in reversed(range(layout.count())): widget = layout.itemAt(j).widget() if widget is not None: layout.removeWidget(widget) else: print("ERR") else: print("Err") self.cbArea.removeItem(item) item.deleteLater() self.width_needed = None i = 0 while i < len(self.cbList): line = QHBoxLayout() columnCount = 0 while True: if availableWidth is not None and line.minimumSize().width() >= availableWidth: if columnCount > 1: i -= 1 line.removeWidget(self.cbList[i]) overlap = line.minimumSize().width() - availableWidth if self.width_needed is None: self.width_needed = overlap else: self.width_needed = min(self.width_needed, overlap) break elif i >= len(self.cbList): break else: line.addWidget(self.cbList[i]) i +=1 columnCount += 1 self.cbArea.addLayout(line) def formatTextToConsole(self, text): textLines = text.splitlines(keepends=True) lineNb = 0 for line in textLines: lineNb += 1 sLine = line.split('_', maxsplit=2) if len(sLine) != 3: # print("Incorrect line nb", lineNb, ":", line) continue try: int(sLine[0]) except ValueError: print("Incorrect timestamp :", sLine[0]) continue if sLine[1] == INFO_CHANNEL_NAME: if not self.cbInfo.isChecked(): continue color = self.textColor elif sLine[1] == ERROR_CHANNEL_NAME: if not self.cbErrors.isChecked(): continue color = self.errorColor elif sLine[1] == TRACE_CHANNEL_NAME: if not self.cbInfo.isChecked(): continue color = self.textColor elif sLine[1] == SPY_ORDER_CHANNEL_NAME: if not self.cbOrders.isChecked(): continue color = self.orderColor elif sLine[1] == ANSWER_DESCRIPTOR: if not self.cbAnswers.isChecked(): continue color = self.answerColor elif sLine[1] == SENSOR_CHANNEL_NAME: if not self.cbSensors.isChecked(): continue color = self.sensorColor else: print("Incorrect line type :", sLine[1]) continue if self.cbTimestamp.isChecked(): self.console.setTextColor(self.timestampColor) self.console.setCurrentFont(QFont(self.font, self.fontSize_small)) self.console.insertPlainText(sLine[0] + " ") self.console.setTextColor(color) self.console.setCurrentFont(QFont(self.font, self.fontSize)) self.console.insertPlainText(sLine[2]) def setText(self, newText): self.consoleText = newText self.console.clear() self.formatTextToConsole(newText) self.consoleVScrollBar.setValue(self.consoleVScrollBar.maximum()) def appendText(self, text): self.consoleText += text self.formatTextToConsole(text) self.consoleVScrollBar.setValue(self.consoleVScrollBar.maximum()) def settings_changed(self): scrollValue = self.consoleVScrollBar.value() self.console.clear() self.formatTextToConsole(self.consoleText) self.consoleVScrollBar.setValue(scrollValue)
class EditDialog(QMainWindow): def __init__(self, mood, parent=None): super().__init__(parent) # Top level layout self.main_widget = QWidget() self.layout = QVBoxLayout() # Tracks have a separate layout self.new_tracks = [] self.track_layout = QVBoxLayout() for track in mood.playlist.playlist: url = track[0] title = track[1] self.add_track(url, title) # Add parameters self.update_box = QLineEdit(mood.label, self) self.layout.addWidget(self.update_box) #self.layout.addWidget(QLabel("Tracks:", self)) self.layout.addLayout(self.track_layout) add_button = QPushButton("+", self) add_button.setMaximumSize(22, 22) add_button.clicked.connect(self.pick_track) self.layout.addWidget(add_button) self.layout.addStretch(1) save_button = QPushButton("Save", self) save_button.clicked.connect(lambda: self.save_settings(mood)) self.layout.addWidget(save_button) self.main_widget.setLayout(self.layout) self.setCentralWidget(self.main_widget) # Set window properties self.setGeometry(400, 400, 320, 240) self.setWindowTitle('Settings') self.show() def pick_track(self): url = QFileDialog.getOpenFileName(self, 'Add Track') if url[0]: title = os.path.split(url[0])[-1] self.add_track(url[0], title) def add_track(self, url, title): idx = len(self.new_tracks) label = QLabel(title, self) label.setMinimumSize(100, 22) remove = QPushButton("-", self) remove.setMaximumSize(22, 22) mv_up = QPushButton("â–²", self) mv_up.setMaximumSize(22, 22) mv_down = QPushButton("â–¼", self) mv_down.setMaximumSize(22, 22) single_track = QHBoxLayout() single_track.addWidget(label) single_track.addWidget(remove) single_track.addWidget(mv_up) single_track.addWidget(mv_down) single_track.setSpacing(5) list_item = (url, title, single_track) remove.clicked.connect(lambda: self.remove_track(list_item)) mv_up.clicked.connect(lambda: self.up_track(list_item)) mv_down.clicked.connect(lambda: self.down_track(list_item)) self.new_tracks.append(list_item) self.track_layout.addLayout(single_track) def remove_track(self, list_item): url, title, single_track = list_item self.track_layout.removeItem(single_track) # Remove all the widgets for i in reversed(range(single_track.count())): single_track.itemAt(i).widget().setParent(None) # Delete the single track layout single_track.deleteLater() # Remove from list try: self.new_tracks.remove(list_item) except ValueError: pass def up_track(self, list_item): old_idx = self.new_tracks.index(list_item) if old_idx > 0: new_idx = old_idx - 1 self.new_tracks.remove(list_item) self.new_tracks.insert(new_idx, list_item) _, _, single_track = list_item self.track_layout.removeItem(single_track) self.track_layout.insertItem(new_idx, single_track) def down_track(self, list_item): old_idx = self.new_tracks.index(list_item) if old_idx < len(self.new_tracks) - 1: new_idx = old_idx + 1 self.new_tracks.remove(list_item) self.new_tracks.insert(new_idx, list_item) _, _, single_track = list_item self.track_layout.removeItem(single_track) self.track_layout.insertItem(new_idx, single_track) def save_settings(self, mood): # Update label new_label = self.update_box.text() if new_label != mood.label: mood.label = new_label mood.play_button.setText(mood.label) # Update playlist with new tracks mood.playlist.clear() for track in self.new_tracks: mood.playlist.add(track[0]) mood.playlist.restart()
class TopicsTab(QWidget): configChanged = pyqtSignal() def __init__(self): super(QWidget, self).__init__() self.config = None self.count = 0 self.topicRows = {} self.nameEdit = QLineEdit() self.dataTypeComboBox = QComboBox() self.fillDataTypes() self.opTypeComboBox = QComboBox() self.opTypeComboBox.addItem('sub', 'Subscribe') self.opTypeComboBox.addItem('pub', 'Publish') self.addButton = QPushButton('Add') self.addButton.clicked.connect(self.addClicked) self.mainLayout = QVBoxLayout() rowLayout = QHBoxLayout() rowLayout.addWidget(self.nameEdit) rowLayout.addWidget(self.dataTypeComboBox) rowLayout.addWidget(self.opTypeComboBox) rowLayout.addWidget(self.addButton) rowContainer = QWidget() rowContainer.setLayout(rowLayout) rowContainer.setObjectName('titleRow') self.mainLayout.addWidget(rowContainer) self.setLayout(self.mainLayout) def fillDataTypes(self): rosTypes = Interfaces.getRosMessageTypes() for type in rosTypes: concatType = type['typeDir'] + '/' + type['type'] self.dataTypeComboBox.addItem(concatType, concatType) def addTopicRow(self, name, type, opType): rowLayout = QHBoxLayout() rowLayout.addWidget(QLabel(name)) rowLayout.addWidget(QLabel(type)) rowLayout.addWidget(QLabel(opType)) removeButton = QPushButton('Remove') removeButton.clicked.connect(self.removeTopicClicked) removeButton.setObjectName(str(self.count)) rowLayout.addWidget(removeButton) rowContainer = QWidget() rowContainer.setLayout(rowLayout) rowContainer.setObjectName('row' + str(self.count)) self.mainLayout.addWidget(rowContainer) self.topicRows[self.count] = rowContainer self.count += 1 def addClicked(self): if self.config is not None: self.config.addTopic(self.count, self.nameEdit.text(), self.dataTypeComboBox.currentData(), self.opTypeComboBox.currentData()) self.addTopicRow(self.nameEdit.text(), self.dataTypeComboBox.currentData(), self.opTypeComboBox.currentData()) self.nameEdit.setText('') self.configChanged.emit() def removeTopicClicked(self): if self.config is not None: itemToRemove = None for i in range(self.mainLayout.count()): if self.mainLayout.itemAt(i).widget().objectName() == 'row' + self.sender().objectName(): itemToRemove = self.mainLayout.itemAt(i) break if itemToRemove is not None: self.mainLayout.removeItem(itemToRemove) itemToRemove.widget().setParent(None) self.mainLayout.update() self.configChanged.emit() self.config.removeTopic(int(self.sender().objectName())) del self.topicRows[int(self.sender().objectName())] def clearAllRows(self): clearList = [] for i in range(self.mainLayout.count()): item = self.mainLayout.itemAt(i) if item.widget().objectName() != 'titleRow': clearList.append(item) for item in clearList: self.mainLayout.removeItem(item) item.widget().setParent(None) self.mainLayout.update() self.count = 0 def setConfig(self, config): self.config = config self.clearAllRows() for topic in self.config.getTopics(): topic['id'] = self.count self.addTopicRow(topic['name'], topic['type'], topic['opType'])
class GUI(QWidget): # instance variable OUTPUT_PATH = folder = os.path.expanduser( '~{}Pictures{}pnu-newsletter'.format(os.path.sep, os.path.sep)) def __init__(self): super().__init__() self.init_ui() self.filenames = [] self.imgs = [] def init_ui(self): """ layout: 1. uploading: image that could be clicked 2. input_details: grid layout 3. output_details: grid layout 4. start: a button to start the image processing """ self.start_process() uploading_image = QPixmap('image/drag-drop-file.png') uploading_label = QLabel(self) uploading_label.setPixmap(uploading_image) self.input_details = QVBoxLayout() output_details = QGridLayout() path_label = QLabel('output path:') self.path = QLabel(self.OUTPUT_PATH) change_button = QPushButton('change') output_details.addWidget(path_label, 1, 0) output_details.addWidget(self.path, 1, 2) output_details.addWidget(change_button, 1, 10) self.start_button = QPushButton('Start!') self.err_message = "To start, there must be exactly 5 ads" self.error_label = QLabel(self.err_message) self.layout = QVBoxLayout() self.layout.setAlignment(Qt.AlignCenter) self.layout.addWidget(uploading_label) self.layout.addLayout(self.input_details) self.layout.addLayout(output_details) self.layout.addWidget(self.start_button) self.layout.addWidget(self.error_label) self.setLayout(self.layout) self.setAcceptDrops(True) self.setFixedWidth(700) self.show() uploading_label.mousePressEvent = self.load_image_folder change_button.clicked.connect(self.change_path) self.start_button.clicked.connect(self.start) self.start_button.setEnabled(False) return def start_process(self): self.process_id = str(uuid.uuid4()) print("new process {}".format(self.process_id)) self.setWindowTitle('PNU newsletter by reem-codes | process {}'.format( self.process_id)) self.img_process_path = 'image/proc_{}/'.format(self.process_id) self.filenames = [] self.imgs = [] return def change_path(self): self.OUTPUT_PATH = str(QFileDialog.getExistingDirectory( self, 'choose')) if self.OUTPUT_PATH: self.path.setText(self.OUTPUT_PATH) return def load_image_folder(self, event): filters = "Images (*.png *.xpm *.jpg *.jpeg *.gif)" filenames, _ = QFileDialog.getOpenFileNames(self, 'Open file', filter=filters) self.filenames.extend(filenames) self.load_image() return def load_image(self): for i in reversed(range(self.input_details.count())): layout = self.input_details.itemAt(i).layout() for j in reversed(range(layout.count())): layout.itemAt(j).widget().setParent(None) self.input_details.removeItem(layout) for x in range(len(self.filenames)): img_detail = dict() img_id = str(uuid.uuid4())[:8] f = self.filenames[x] head, filename = ntpath.split(f) fn, ext = os.path.splitext(filename) img_detail['img_id'] = img_id img_detail['ext'] = ext img_detail['path'] = os.path.abspath(self.img_process_path) img_detail['filepath'] = os.path.abspath( self.img_process_path) + '/' + img_id + ext self.imgs.append(img_detail) newpath = os.path.abspath(self.img_process_path) if not os.path.exists(newpath): os.makedirs(newpath) # shutil.copy2(f, os.path.abspath(self.img_process_path)) shutil.copy(f, img_detail['filepath']) pixmap = QPixmap(f) pixmap = pixmap.scaled(50, 50, Qt.KeepAspectRatio) label = QLabel() label.setPixmap(pixmap) filepath = QLabel(f) del_btn = QPushButton("x") del_btn.setFixedSize(25, 25) input = QHBoxLayout() input.addWidget(label) input.addWidget(filepath) input.addWidget(del_btn) del_btn.clicked.connect(partial(self.delete_img, img_id, input, f)) # self.delete_img self.input_details.addLayout(input) if len(self.filenames) is 5: self.start_button.setEnabled(True) else: self.start_button.setEnabled(False) self.error_label.setText(self.err_message) return def delete_img(self, img_id, layout, f): for i in range(len(self.imgs)): if img_id is self.imgs[i]['img_id']: x = i img_pth = self.img_process_path + img_id if os.path.exists(img_pth): os.remove(img_pth) for i in reversed(range(layout.count())): layout.itemAt(i).widget().setParent(None) self.input_details.removeItem(layout) self.filenames.remove(f) self.imgs.pop(x) if len(self.filenames) is 5: self.start_button.setEnabled(True) else: self.start_button.setEnabled(False) self.error_label.setText(self.err_message) return def dragEnterEvent(self, e): if e.mimeData().hasUrls: e.accept() else: e.ignore() return def dragMoveEvent(self, e): if e.mimeData().hasUrls: e.accept() else: e.ignore() return def dropEvent(self, e): if e.mimeData().hasUrls: e.setDropAction(Qt.CopyAction) e.accept() print(self.filenames) for url in e.mimeData().urls(): self.filenames.append(str(url.toLocalFile())) print(self.filenames) self.load_image() else: e.ignore() return def start(self): imgp.main(self.path.text(), self.imgs, self.process_id) self.error_label.setText('process {} is Done :D'.format( self.process_id)) if os.path.exists(self.img_process_path): shutil.rmtree(self.img_process_path) for i in reversed(range(self.input_details.count())): layout = self.input_details.itemAt(i).layout() for j in reversed(range(layout.count())): layout.itemAt(j).widget().setParent(None) self.input_details.removeItem(layout) self.start_process() return def keyPressEvent(self, e): if e.key() == Qt.Key_Escape: self.close() if e.key() == (Qt.Key_Enter or Qt.Key_Space): self.start() return def closeEvent(self, event): if os.path.exists(self.img_process_path): shutil.rmtree(self.img_process_path) return
class TopicsTab(QWidget): configChanged = pyqtSignal() def __init__(self): super(QWidget, self).__init__() self.config = None self.count = 0 self.topicRows = {} self.nameEdit = QLineEdit() self.dataTypeComboBox = QComboBox() self.fillDataTypes() self.opTypeComboBox = QComboBox() self.opTypeComboBox.addItem('sub', 'Subscribe') self.opTypeComboBox.addItem('pub', 'Publish') self.addButton = QPushButton('Add') self.addButton.clicked.connect(self.addClicked) self.mainLayout = QVBoxLayout() rowLayout = QHBoxLayout() rowLayout.addWidget(self.nameEdit) rowLayout.addWidget(self.dataTypeComboBox) rowLayout.addWidget(self.opTypeComboBox) rowLayout.addWidget(self.addButton) rowContainer = QWidget() rowContainer.setLayout(rowLayout) rowContainer.setObjectName('titleRow') self.mainLayout.addWidget(rowContainer) self.setLayout(self.mainLayout) def fillDataTypes(self): rosTypes = Interfaces.getRosMessageTypes() for type in rosTypes: concatType = type['typeDir'] + '/' + type['type'] self.dataTypeComboBox.addItem(concatType, concatType) def addTopicRow(self, name, type, opType): rowLayout = QHBoxLayout() rowLayout.addWidget(QLabel(name)) rowLayout.addWidget(QLabel(type)) rowLayout.addWidget(QLabel(opType)) removeButton = QPushButton('Remove') removeButton.clicked.connect(self.removeTopicClicked) removeButton.setObjectName(str(self.count)) rowLayout.addWidget(removeButton) rowContainer = QWidget() rowContainer.setLayout(rowLayout) rowContainer.setObjectName('row' + str(self.count)) self.mainLayout.addWidget(rowContainer) self.topicRows[self.count] = rowContainer self.count += 1 def addClicked(self): if self.config is not None: self.config.addTopic(self.count, self.nameEdit.text(), self.dataTypeComboBox.currentData(), self.opTypeComboBox.currentData()) self.addTopicRow(self.nameEdit.text(), self.dataTypeComboBox.currentData(), self.opTypeComboBox.currentData()) self.nameEdit.setText('') self.configChanged.emit() def removeTopicClicked(self): if self.config is not None: itemToRemove = None for i in range(self.mainLayout.count()): if self.mainLayout.itemAt(i).widget().objectName( ) == 'row' + self.sender().objectName(): itemToRemove = self.mainLayout.itemAt(i) break if itemToRemove is not None: self.mainLayout.removeItem(itemToRemove) itemToRemove.widget().setParent(None) self.mainLayout.update() self.configChanged.emit() self.config.removeTopic(int(self.sender().objectName())) del self.topicRows[int(self.sender().objectName())] def clearAllRows(self): clearList = [] for i in range(self.mainLayout.count()): item = self.mainLayout.itemAt(i) if item.widget().objectName() != 'titleRow': clearList.append(item) for item in clearList: self.mainLayout.removeItem(item) item.widget().setParent(None) self.mainLayout.update() self.count = 0 def setConfig(self, config): self.config = config self.clearAllRows() for topic in self.config.getTopics(): topic['id'] = self.count self.addTopicRow(topic['name'], topic['type'], topic['opType'])
class GUI(QWidget): def __init__(self): super().__init__() try: urlopen('http://maia.usno.navy.mil/ser7/finals2000A.all') except HTTPError as e: print("Main IERS link not working, using mirror") iers.conf.iers_auto_url = 'http://toshi.nofs.navy.mil/ser7/finals2000A.all' except URLError as e: print("Main IERS link not working, using mirror") iers.conf.iers_auto_url = 'http://toshi.nofs.navy.mil/ser7/finals2000A.all' #download_IERS_A() plt.style.use(astropy_mpl_style) irbeneLocation = EarthLocation(lat=57.5535171694 * u.deg, lon=21.8545525000 * u.deg, height=87.30 * u.m) self.irbene = Observer(location=irbeneLocation, name="Irbene", timezone="Europe/Riga") observe_time = Time(['2019-02-05 15:30:00']) self.targets = [] self.targetsDict = {} with open("config/config.csv", "r") as csvfile: next(csvfile) reader = csv.reader(csvfile, delimiter=",", quotechar="|") for row in reader: sourceName = row[0] raText = row[1] raText = insert(raText, 'h', 2) #Nolasa targets no faila un ievieto targetsDict un targets raText = insert(raText, 'm', 5) raText = insert(raText, 's', len(raText)) decText = row[2] if (decText[0] != "-"): decText = insert(decText, 'd', 2) decText = insert(decText, 'm', 5) decText = insert(decText, 's', len(decText)) else: decText = insert(decText, 'd', 3) decText = insert(decText, 'm', 6) decText = insert(decText, 's', len(decText)) ra = Angle(raText) dec = Angle(decText) targetCoord = SkyCoord(frame='icrs', ra=ra, dec=dec, obstime="J2000") target = FixedTarget(coord=targetCoord, name=sourceName) plannedObs = PlannedObs(target, int(row[4]), int(row[3]), int(row[5])) self.targets.append(plannedObs) # target / obs per_week / priority / scans per obs coords = {"ra": ra, "dec": dec} self.targetsDict[sourceName] = coords self.targets = sorted(self.targets, key=lambda x: x.priority) # sort targets by priority self.calibrators = [] self.calibratorsDict = {} with open("config/calibrators.csv", "r") as csvfile: next(csvfile) reader = csv.reader(csvfile, delimiter=";", quotechar="|") for row in reader: sourceName = row[0] raText = str(row[1]).replace(" ", "") raText = insert(raText, 'h', 2) raText = insert(raText, 'm', 5) raText = insert(raText, 's', len(raText)) decText = str(row[2]).replace(" ", "") if (decText[0] != "-"): decText = insert(decText, 'd', 3) decText = insert(decText, 'm', 6) decText = insert(decText, 's', len(decText)) else: decText = insert(decText, 'd', 3) decText = insert(decText, 'm', 6) decText = insert(decText, 's', len(decText)) #Nolasa no faila calibratorus un ievieto calibratorsDict un calibrators ra = Angle(raText) dec = Angle(decText) coords = {"ra": ra, "dec": dec} self.calibratorsDict[sourceName] = coords calibratorCoord = SkyCoord(frame='icrs', ra=ra, dec=dec, obstime="J2000") calibrator = FixedTarget(coord=calibratorCoord, name=sourceName) self.calibrators.append(calibrator) startArray, endArray, summaryArray = get_all_events() #No google calendar sanem noverosanas datumus un laikus self.dateList = QListWidget() tempCheck = True for i in range(len(startArray)): dayStart = parse(startArray[i]) dayEnd = parse(endArray[i]) daySummary = summaryArray[i] daySummary = daySummary + " " + str(dayStart.date()) + " " + str(dayStart.time()) + "-" + str(dayEnd.time()) item = QListWidgetItem(daySummary, self.dateList) item.setData(Qt.UserRole, [dayStart, dayEnd]) #Izveido listwidget item no datuma un laika un to ievieto listwidget item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setCheckState(Qt.Unchecked) if tempCheck and "maser" in daySummary: item.setCheckState(Qt.Checked) tempCheck = False self.dateList.addItem(item) config = configparser.ConfigParser() config.read('config/config.ini') self.config = config._sections['Default'] self.config['calibration'] = config['Default'].getboolean('calibration') #Nolasa config failu self.layout = QGridLayout() self.layout.setSpacing(0) self.layout.setContentsMargins(0,0,0,0) self.setLayout(self.layout) self.resize(1000, 600) self.dateBoxList = [] self.targetTimesCount = 0 self.load_ui() def load_ui(self): #Funkcija kas ielade galveno skatu self.observationList = QListWidget() self.plannedTargets = [] for target in self.targets[:10]: item = QListWidgetItem(str(target), self.observationList) #Aizpilda planotaju ar 10 targets kurus ieprieks nolasija no faila item.setData(Qt.UserRole, target) self.observationList.addItem(item) self.plannedTargets.append(target.name) self.layout.addWidget(self.observationList, 0, 0, 10, 2) self.observationList.itemSelectionChanged.connect(self.obsChanged) #Connect savieno kada UI elementa action (piemeram click) ar funkciju koda #Seit mainot izveleto elemntu listwidget izsauksies funkcija obsChanged for index in range(self.observationList.count()): item = self.observationList.item(index) self.targetLayout = QVBoxLayout() targetBox = QGroupBox() targetBox.setMaximumSize(350, 250) line = QHBoxLayout() nameLabel = QLabel("Target:") self.nameBox = QLineEdit() self.nameBox.setEnabled(False) nameLabel.setParent(targetBox) self.nameBox.setParent(targetBox) line.addWidget(nameLabel) line.addWidget(self.nameBox) self.targetLayout.addLayout(line) line = QHBoxLayout() priorityLabel = QLabel("Priority:") self.priorityBox = QLineEdit() priorityLabel.setParent(targetBox) self.priorityBox.setParent(targetBox) line.addWidget(priorityLabel) line.addWidget(self.priorityBox) self.targetLayout.addLayout(line) line = QHBoxLayout() obsLabel = QLabel("Obs per week:") self.obsBox = QLineEdit() obsLabel.setParent(targetBox) self.obsBox.setParent(targetBox) line.addWidget(obsLabel) line.addWidget(self.obsBox) self.targetLayout.addLayout(line) line = QHBoxLayout() scanLabel = QLabel("Scans per obs:") self.scanBox = QLineEdit() scanLabel.setParent(targetBox) self.scanBox.setParent(targetBox) line.addWidget(scanLabel) line.addWidget(self.scanBox) self.targetLayout.addLayout(line) line = QHBoxLayout() globalLabel = QLabel("Global time:") self.globalTimeBox = QLineEdit() line.addWidget(globalLabel) line.addWidget(self.globalTimeBox) self.targetLayout.addLayout(line) line = QHBoxLayout() specificLabel = QLabel("Specific times:") addTime = QPushButton("Add specific time") addTime.clicked.connect(self.add_time) line.addWidget(specificLabel) line.addWidget(addTime) self.targetLayout.addLayout(line) saveButton = QPushButton("Save changes") saveButton.clicked.connect(self.save_obs_changes) self.targetLayout.addWidget(saveButton) removeButton = QPushButton("Remove target") removeButton.clicked.connect(self.remove_obs) self.targetLayout.addWidget(removeButton) targetBox.setLayout(self.targetLayout) self.layout.addWidget(targetBox, 0, 2, 2, 1) self.targetComboBox = QComboBox() for key in self.targetsDict: if key not in self.plannedTargets: self.targetComboBox.addItem(key) self.layout.addWidget(self.targetComboBox, 2, 2) addButton = QPushButton("Add observation") addButton.clicked.connect(self.add_obs) self.layout.addWidget(addButton, 3, 2) nextButton = QPushButton("Schedule") nextButton.clicked.connect(self.prepare_schedule) self.layout.addWidget(nextButton, 0, 3) datesButton = QPushButton("Dates") datesButton.clicked.connect(self.edit_dates) self.layout.addWidget(datesButton, 1, 3) targetsButton = QPushButton("Targets") targetsButton.clicked.connect(self.edit_targets) self.layout.addWidget(targetsButton, 2, 3) calibratorsButton = QPushButton("Calibrators") calibratorsButton.clicked.connect(self.edit_calibrators) self.layout.addWidget(calibratorsButton, 3, 3) settingsButton = QPushButton("Settings") settingsButton.clicked.connect(self.load_settings) self.layout.addWidget(settingsButton, 4, 3) saveObsButton = QPushButton("Save observation") saveObsButton.clicked.connect(self.save_obs) self.layout.addWidget(saveObsButton, 5, 3) loadObsButton = QPushButton("Load observation") loadObsButton.clicked.connect(self.load_obs_new) self.layout.addWidget(loadObsButton, 6, 3) def add_time(self): #Pievieno combobox ar izveletajiem datumiem datesChecked = 0 for index in range(self.dateList.count()): if self.dateList.item(index).checkState() == Qt.Checked: datesChecked = datesChecked + 1 if datesChecked > self.targetTimesCount: line = QHBoxLayout() dateBox = QComboBox() for index in range(self.dateList.count()): if self.dateList.item(index).checkState() == Qt.Checked: dateBox.addItem(self.dateList.item(index).text(), self.dateList.item(index).data(Qt.UserRole)) dateBox.addItem("Remove") dateBox.currentTextChanged.connect(self.timeChanged) self.targetTimesCount+= 1 dateBox.sizePolicy().setHorizontalStretch(1) timeBox = QLineEdit() timeBox.sizePolicy().setHorizontalStretch(3) line.addWidget(dateBox) line.addWidget(timeBox) self.dateBoxList.append(line) self.targetLayout.insertLayout(self.targetLayout.count()-2, line) else: self.show_error("Date error", "Can't select more times than selected dates") def timeChanged(self, item): #Ja pie specifiskajiem laikiem izvelas remove tad iznem to if item == "Remove": for line in self.dateBoxList: if line is not None: item = line.itemAt(0) widget = item.widget() if type(widget) == type(QComboBox()): if widget.currentText() == "Remove": break self.targetTimesCount -= 1 widget.disconnect() self.deleteItemsOfLayout(line) self.targetLayout.removeItem(line) self.dateBoxList.remove(line) def obsChanged(self): #Nomainot observation nomaina visus texta laukus if len(self.observationList.selectedItems()) > 0: item = self.observationList.currentItem() plannedObs = item.data(Qt.UserRole) self.nameBox.setText(plannedObs.name) self.priorityBox.setText(str(plannedObs.priority)) self.obsBox.setText(str(plannedObs.obs_per_week)) self.scanBox.setText(str(plannedObs.scans_per_obs)) i = 0 maxi = self.targetLayout.count() while(i < maxi): layout_item = self.targetLayout.itemAt(i) if layout_item in self.dateBoxList: self.deleteItemsOfLayout(layout_item.layout()) self.targetLayout.removeItem(layout_item) self.dateBoxList.remove(layout_item) maxi = self.targetLayout.count() i = i -1 i=i+1 self.dateBoxList.clear() self.targetTimesCount = 0 if plannedObs.times: checkedDates = [] for index in range(self.dateList.count()): if self.dateList.item(index).checkState() == Qt.Checked: checkedDates.append(self.dateList.item(index).text()) print(checkedDates) for time in list(plannedObs.times): print(time) if time not in checkedDates: #Ja observation pievienots specifisks laiks datumam kurs vairs netiks izmantots to pazino lietotajam self.show_error("Date mismatch", "Date "+time+" is not checked, removing it") plannedObs.times.remove(time) for time in list(plannedObs.times): line = QHBoxLayout() dateBox = QComboBox() for index in range(self.dateList.count()): if self.dateList.item(index).checkState() == Qt.Checked: #Specific laikiem pievieno tikai datumus kas izveleti pie dates dateBox.addItem(self.dateList.item(index).text(), self.dateList.item(index).data(Qt.UserRole)) dateBox.addItem("Remove") dateBox.currentTextChanged.connect(self.timeChanged) self.targetTimesCount += 1 dateBox.sizePolicy().setHorizontalStretch(1) timeBox = QLineEdit(plannedObs.times[time]) timeBox.sizePolicy().setHorizontalStretch(3) line.addWidget(dateBox) line.addWidget(timeBox) self.dateBoxList.append(line) self.targetLayout.insertLayout(self.targetLayout.count() - 2, line) dateBox.setCurrentIndex(dateBox.findText(time)) else: self.nameBox.setText("") self.priorityBox.setText("") self.obsBox.setText("") self.scanBox.setText("") self.targetTimesCount = 0 def remove_obs(self): if len(self.observationList.selectedItems()) > 0: self.plannedTargets.remove(self.observationList.currentItem().data(Qt.UserRole).name) self.targetComboBox.addItem(self.observationList.currentItem().data(Qt.UserRole).name) self.observationList.takeItem(self.observationList.currentRow()) else: self.show_error("Observation error","Select an observation to remove it") def save_obs_changes(self): #Ja visi teksta lauki atbilst parbaudem tad saglaba datus, ja ne tad pazino lietotajam if not self.priorityBox.text().isdigit(): self.show_error("Priority error", "Priority must be from 1 to 4") elif int(self.priorityBox.text()) > 4 or int(self.priorityBox.text()) < 0: self.show_error("Priority error", "Priority must be from 1 to 4") elif not self.obsBox.text().isdigit(): self.show_error("Obs error", "Obs must be from 1 to 7") elif int(self.obsBox.text()) > 7 or int(self.obsBox.text()) < 0: self.show_error("Obs error", "Obs must be from 1 to 7") elif not self.scanBox.text().isdigit(): self.show_error("Scan error", "Scan must be from 1 to 120") elif int(self.scanBox.text()) > 120 or int(self.scanBox.text()) < 0: self.show_error("Scan error", "Scan must be from 1 to 120") elif len(self.dateBoxList) != len(set(self.dateBoxList)): self.show_error("Date error", "Make sure specified times don't use same dates") else: times = {} timeCheck = True for line in self.dateBoxList: if line.count() > 0: item = line.itemAt(0) widget = item.widget() date = widget.currentText() time = date[-17:] time = time.split('-') timeStart = time[0] timeStart = timeStart[:-3] timeEnd = time[1] timeEnd = timeEnd[:-3] time = line.itemAt(1).widget().text() timeCheck = self.time_check(time, timeStart, timeEnd) if timeCheck == False: break else: times[date] = line.itemAt(1).widget().text() if timeCheck: #Ja visas parbaudes izietas tad saglaba datus self.observationList.currentItem().data(Qt.UserRole).times = times self.observationList.currentItem().data(Qt.UserRole).priority = int(self.priorityBox.text()) self.observationList.currentItem().data(Qt.UserRole).obs_per_week = int(self.obsBox.text()) self.observationList.currentItem().data(Qt.UserRole).scans_per_obs = int(self.scanBox.text()) self.observationList.currentItem().data(Qt.UserRole).global_time = self.globalTimeBox.text() self.observationList.currentItem().setText(str(self.observationList.currentItem().data(Qt.UserRole))) else: self.show_error("Specific time error", "Make sure the specific times fit the dates selected") def add_obs(self): #Izveido jaunu observation if self.targetComboBox.count() > 0: targetName = self.targetComboBox.currentText() ra = self.targetsDict[targetName]["ra"] dec = self.targetsDict[targetName]["dec"] coord = SkyCoord(frame='icrs', ra=ra, dec=dec, obstime="J2000") target = FixedTarget(coord=coord, name=targetName) data = PlannedObs(target, 1, 1, 1) item = QListWidgetItem(str(data), self.observationList) item.setData(Qt.UserRole, data) self.observationList.addItem(item) self.plannedTargets.append(data.name) self.targetComboBox.removeItem(self.targetComboBox.currentIndex()) def edit_dates(self): #Atver dates skatu self.clear_window() self.layout.addWidget(self.dateList, 0, 0, 5, 2) backButton = QPushButton("Back to planner") self.layout.addWidget(backButton, 1, 2) backButton.clicked.connect(self.to_start) def edit_targets(self): #Atver targets skatu self.clear_window() self.targetList = QListWidget() for key in self.targetsDict: self.targetList.addItem(key) self.targetList.itemClicked.connect(self.targetChanged) self.layout.addWidget(self.targetList, 0, 0, 3, 1) targetLayout = QGridLayout() targetLayout.addWidget(QLabel("Ra:"), 0, 0) self.raBox = QLineEdit() targetLayout.addWidget(self.raBox, 0, 1) targetLayout.addWidget(QLabel("Dec:"), 1, 0) self.decBox = QLineEdit() targetLayout.addWidget(self.decBox, 1, 1) self.saveButton = QPushButton("Save changes") self.saveButton.clicked.connect(self.save_target_changes) targetLayout.addWidget(self.saveButton, 2, 0, 1, 2) targetBox = QGroupBox() targetBox.setLayout(targetLayout) self.layout.addWidget(targetBox, 0, 1) self.saveButton.setEnabled(False) addTargetLayout = QGridLayout() addTargetLayout.addWidget(QLabel("Name:"), 0, 0) self.addNameBox = QLineEdit() addTargetLayout.addWidget(self.addNameBox, 0, 1) addTargetLayout.addWidget(QLabel("Ra:"), 1, 0) self.addRaBox = QLineEdit() addTargetLayout.addWidget(self.addRaBox, 1, 1) addTargetLayout.addWidget(QLabel("Dec:"), 2, 0) self.addDecBox = QLineEdit() addTargetLayout.addWidget(self.addDecBox, 2, 1) self.addSaveButton = QPushButton("Save changes") self.addSaveButton.clicked.connect(self.add_target) addTargetLayout.addWidget(self.addSaveButton, 3, 0, 1, 2) addTargetBox = QGroupBox() addTargetBox.setLayout(addTargetLayout) self.layout.addWidget(addTargetBox, 1, 1) backButton = QPushButton("Back to planner") self.layout.addWidget(backButton, 0, 3) backButton.clicked.connect(self.to_start) def targetChanged(self, item): if not self.saveButton.isEnabled(): self.saveButton.setEnabled(True) targetName = item.text() target = self.targetsDict[targetName] self.raBox.setText(target["ra"].to_string()) self.decBox.setText(target["dec"].to_string(unit=u.degree)) def save_target_changes(self): if len(self.targetList.selectedItems()) != 1: self.show_error("Target error", "Make sure you have selected only 1 target") else: targetName = self.targetList.selectedItems()[0].text() raPattern = re.compile("[0-9]{1,2}h[0-9]{1,2}m[0-9]{1,2}(\.[0-9]{1,3})?s") decPattern = re.compile("-?[0-9]{1,2}d[0-9]{1,2}m[0-9]{1,2}(\.[0-9]{1,3})?s") ra = self.raBox.text() dec = self.decBox.text() if not raPattern.match(ra): self.show_error("Ra error", "Ra coordinates don't match pattern 00h00m00.00s") elif not decPattern.match(dec): self.show_error("Dec error", "Dec coordinates don't match pattern 00d00m00.00s") else: self.targetsDict[targetName]["ra"] = Angle(ra) self.targetsDict[targetName]["dec"] = Angle(dec) def add_target(self): #Pievieno jaunu target raPattern = re.compile("[0-9]{1,2}h[0-9]{1,2}m[0-9]{1,2}(\.[0-9]{1,3})?s") decPattern = re.compile("-?[0-9]{1,2}d[0-9]{1,2}m[0-9]{1,2}(\.[0-9]{1,3})?s") ra = self.addRaBox.text() dec = self.addDecBox.text() name = self.addNameBox.text() print(self.targetsDict.keys()) if ra == "" or dec == "" or name == "": self.show_error("Empty box", "Please fill all boxes") elif name in self.targetsDict.keys(): self.show_error("Existing target", "Target already exists, please edit it") elif not raPattern.match(ra): self.show_error("Ra error", "Ra coordinates don't match pattern 00h00m00.00s") elif not decPattern.match(dec): self.show_error("Dec error", "Dec coordinates don't match pattern 00d00m00.00s") else: self.targetsDict[name] = {} self.targetsDict[name]["ra"] = Angle(ra) self.targetsDict[name]["dec"] = Angle(dec) self.edit_targets() def edit_calibrators(self): #Atver calibrators skatu self.clear_window() self.calibratorList = QListWidget() for key in self.calibratorsDict: self.calibratorList.addItem(key) self.calibratorList.itemClicked.connect(self.calibratorChanged) self.layout.addWidget(self.calibratorList, 0, 0, 3, 1) calibratorLayout = QGridLayout() calibratorLayout.addWidget(QLabel("Ra:"), 0, 0) self.raBox = QLineEdit() calibratorLayout.addWidget(self.raBox, 0, 1) calibratorLayout.addWidget(QLabel("Dec:"), 1, 0) self.decBox = QLineEdit() calibratorLayout.addWidget(self.decBox, 1, 1) self.saveButton = QPushButton("Save changes") self.saveButton.clicked.connect(self.save_calibrator_changes) calibratorLayout.addWidget(self.saveButton, 2, 0, 1, 2) calibratorBox = QGroupBox() calibratorBox.setLayout(calibratorLayout) self.layout.addWidget(calibratorBox, 0, 1) self.saveButton.setEnabled(False) addcalibratorLayout = QGridLayout() addcalibratorLayout.addWidget(QLabel("Name:"), 0, 0) self.addNameBox = QLineEdit() addcalibratorLayout.addWidget(self.addNameBox, 0, 1) addcalibratorLayout.addWidget(QLabel("Ra:"), 1, 0) self.addRaBox = QLineEdit() addcalibratorLayout.addWidget(self.addRaBox, 1, 1) addcalibratorLayout.addWidget(QLabel("Dec:"), 2, 0) self.addDecBox = QLineEdit() addcalibratorLayout.addWidget(self.addDecBox, 2, 1) self.addSaveButton = QPushButton("Save changes") self.addSaveButton.clicked.connect(self.add_calibrator) addcalibratorLayout.addWidget(self.addSaveButton, 3, 0, 1, 2) addcalibratorBox = QGroupBox() addcalibratorBox.setLayout(addcalibratorLayout) self.layout.addWidget(addcalibratorBox, 1, 1) backButton = QPushButton("Back to planner") self.layout.addWidget(backButton, 0, 3) backButton.clicked.connect(self.to_start) def calibratorChanged(self, item): if not self.saveButton.isEnabled(): self.saveButton.setEnabled(True) calibratorName = item.text() calibrator = self.calibratorsDict[calibratorName] self.raBox.setText(calibrator["ra"].to_string()) self.decBox.setText(calibrator["dec"].to_string(unit=u.degree)) def save_calibrator_changes(self): if len(self.calibratorList.selectedItems()) != 1: self.show_error("calibrator error", "Make sure you have selected only 1 calibrator") else: calibratorName = self.calibratorList.selectedItems()[0].text() raPattern = re.compile("[0-9]{1,2}h[0-9]{1,2}m[0-9]{1,2}(\.[0-9]{1,5})?s") decPattern = re.compile("-?[0-9]{1,2}d[0-9]{1,2}m[0-9]{1,2}(\.[0-9]{1,5})?s") ra = self.raBox.text() dec = self.decBox.text() if not raPattern.match(ra): self.show_error("Ra error", "Ra coordinates don't match pattern 00h00m00.00s") elif not decPattern.match(dec): self.show_error("Dec error", "Dec coordinates don't match pattern 00d00m00.00s") else: self.calibratorsDict[calibratorName]["ra"] = Angle(ra) self.calibratorsDict[calibratorName]["dec"] = Angle(dec) def add_calibrator(self): raPattern = re.compile("[0-9]{1,2}h[0-9]{1,2}m[0-9]{1,2}(\.[0-9]{1,5})?s") decPattern = re.compile("-?[0-9]{1,2}d[0-9]{1,2}m[0-9]{1,2}(\.[0-9]{1,5})?s") ra = self.addRaBox.text() dec = self.addDecBox.text() name = self.addNameBox.text() print(self.calibratorsDict.keys()) if ra == "" or dec == "" or name == "": self.show_error("Empty box", "Please fill all boxes") elif name in self.calibratorsDict.keys(): self.show_error("Existing calibrator", "calibrator already exists, please edit it") elif not raPattern.match(ra): self.show_error("Ra error", "Ra coordinates don't match pattern 00h00m00.00s") elif not decPattern.match(dec): self.show_error("Dec error", "Dec coordinates don't match pattern 00d00m00.00s") else: self.calibratorsDict[name] = {} self.calibratorsDict[name]["ra"] = Angle(ra) self.calibratorsDict[name]["dec"] = Angle(dec) self.edit_calibrators() def load_settings(self): #Atver settings skatu self.clear_window() targetLayout = QFormLayout() targetBox = QGroupBox() targetBox.setMaximumSize(350, 250) calibLabel = QLabel("Calib every X min:") self.calibBox = QLineEdit() calibLabel.setParent(targetBox) self.calibBox.setParent(targetBox) self.calibBox.setText(self.config['maxtimewithoutcalibration']) targetLayout.addRow(calibLabel, self.calibBox) calibDurLabel = QLabel("Calib duration:") self.calibDurBox = QLineEdit() calibDurLabel.setParent(targetBox) self.calibDurBox.setParent(targetBox) self.calibDurBox.setText(self.config['calibrationlength']) targetLayout.addRow(calibDurLabel, self.calibDurBox) minAltLabel = QLabel("Min alt:") self.minAltBox = QLineEdit() minAltLabel.setParent(targetBox) self.minAltBox.setParent(targetBox) self.minAltBox.setText(self.config['minaltitude']) targetLayout.addRow(minAltLabel, self.minAltBox) maxAltLabel = QLabel("Max alt:") self.maxAltBox = QLineEdit() maxAltLabel.setParent(targetBox) self.maxAltBox.setParent(targetBox) self.maxAltBox.setText(self.config['maxaltitude']) targetLayout.addRow(maxAltLabel, self.maxAltBox) calibToggleLabel = QLabel("Calibration on/off") self.calibCheckBox = QCheckBox() calibToggleLabel.setParent(targetBox) self.calibCheckBox.setParent(targetBox) if (self.config['calibration']): self.calibCheckBox.setChecked(True) else: self.calibCheckBox.setChecked(False) targetLayout.addRow(calibToggleLabel, self.calibCheckBox) saveButton = QPushButton("Save settings") saveButton.clicked.connect(self.save_settings) targetLayout.addRow(saveButton) targetBox.setLayout(targetLayout) self.layout.addWidget(targetBox, 0, 2, 2, 1) def save_settings(self): if not (self.calibBox.text().isdigit() and int(self.calibBox.text()) > 0): self.show_error("Input error","Max time without calib must be positive number") elif not (self.calibDurBox.text().isdigit() and int(self.calibDurBox.text()) > 0): self.show_error("Input error","Calib duration must be positive number") elif not (self.minAltBox.text().isdigit() and int(self.minAltBox.text()) > 0): self.show_error("Input error","Min alt must be positive number") elif not (self.maxAltBox.text().isdigit() and int(self.maxAltBox.text()) > 0): self.show_error("Input error","Max alt must be positive number") else: self.config['maxtimewithoutcalibration'] = self.calibBox.text() self.config['calibrationlength'] = self.calibDurBox.text() self.config['minaltitude'] = self.minAltBox.text() self.config['maxaltitude'] = self.maxAltBox.text() self.config['calibration'] = self.calibCheckBox.isChecked() self.to_start() def prepare_schedule(self): #Pirms uzsak planosanu, parbauda vai ir izvelets kads datums hasDate = False for index in range(self.dateList.count()): if self.dateList.item(index).checkState() == Qt.Checked: hasDate = True break if not hasDate: self.show_error("Date error", "No dates selected for schedule") else: self.start_schedule() def start_schedule(self): #Sak planosanu items = (self.layout.itemAt(i).widget() for i in range(self.layout.count())) self.targets = [] for index in range(self.observationList.count()): item = self.observationList.item(index) target = item.data(Qt.UserRole) self.targets.append(target) #Visus obs ievieto masiva targets targ_to_color = {} color_idx = np.linspace(0, 1, len(self.targets)) for target, ci in zip(set(self.targets), color_idx): #Katram target un calibrator pieskir savu krasu if "split" not in target.name: if target.name not in targ_to_color: targ_to_color[target.name] = plt.cm.jet(ci) calib_to_color = {} color_idx = np.linspace(0, 1, len(self.calibrators)) for calibrator, ci in zip(set(self.calibrators), color_idx): if "split" not in calibrator.name: if calibrator.name not in calib_to_color: calib_to_color[calibrator.name] = plt.cm.brg(ci) self.plots_idx = 0 self.plots = [] week = {} for index in range(self.dateList.count()): if self.dateList.item(index).checkState() == Qt.Checked: #Dates ievieto dict week week[self.dateList.item(index).text()]=[self.dateList.item(index).data(Qt.UserRole)[0], self.dateList.item(index).data(Qt.UserRole)[1]] for daySummary, day in week.items(): dayStart = Time(day[0]) # convert from datetime to astropy.time dayEnd = Time(day[1]) timeDict = {} for target in self.targets: if daySummary in target.times: timeDict[target.name] = target.times[daySummary] #Pievieno specifiskos laikus dict timeDict elif target.global_time != "": timeDict[target.name] = target.global_time minalt = self.config['minaltitude'] maxalt = self.config['maxaltitude'] constraints = [AltitudeConstraint(minalt * u.deg, maxalt * u.deg)] read_out = 1 * u.second target_exp = 60 * u.second blocks = [] for target in self.targets: n = target.scans_per_obs priority = target.priority if (target.obs_per_week != 0): #Ja observation vel ir janovero tad izveido ObservingBlock b = ObservingBlock.from_exposures(target.target, priority, target_exp, n, read_out) blocks.append(b) slew_rate = 2 * u.deg / u.second transitioner = Transitioner(slew_rate, {'filter': {'default': 5 * u.second}}) if (self.config['calibration']): #Padod mainigos planotajam prior_scheduler = SequentialScheduler(constraints=constraints, observer=self.irbene, transitioner=transitioner, calibrators=self.calibrators, config=self.config, timeDict=timeDict) priority_schedule = Schedule(dayStart, dayEnd, targColor=targ_to_color, calibColor=calib_to_color, minalt=minalt, maxalt=maxalt) else: prior_scheduler = SequentialScheduler(constraints=constraints, observer=self.irbene, transitioner=transitioner, config=self.config, timeDict=timeDict) priority_schedule = Schedule(dayStart, dayEnd, targColor=targ_to_color, minalt=minalt, maxalt=maxalt) prior_scheduler(blocks, priority_schedule) observations = [] for block in priority_schedule.scheduled_blocks: if hasattr(block, 'target'): observation = Observation(block.target.name, block.start_time.datetime, (block.start_time + block.duration).datetime) observations.append(observation) dict_array = [] for observation in observations: #Saplanotos block nolasa un ieraksta faila for target in self.targets: if target.name == observation.name: print(target.name, " has been observed once") target.obs_per_week -= 1 dict_array.append({ "obs_name": observation.name, "start_time": observation.start_time.strftime("%Y-%m-%d %H:%M:%S"), "end_time": observation.end_time.strftime("%Y-%m-%d %H:%M:%S"), }) json_dict = dict() json_dict["observations"] = dict_array if not os.path.isdir("observations"): os.mkdir("observations") if not os.path.isdir("observations/"): os.mkdir("observations") with open("observations/" + day[0].strftime("%Y-%m-%d-%H-%M") + ".json", 'w') as outfile: json.dump(json_dict, outfile, indent=4) sky = Plot() #Izveido grafikus skyCheck = sky.plot_sky_schedule(priority_schedule) alt = Plot(width=6) alt.plot_altitude_schedule(priority_schedule) if skyCheck is not False: self.plots.append([sky, alt]) else: self.show_error("Empty schedule", "Schedule "+daySummary+"removing it") timeLeft = 0 for target in self.targets: timeLeft += target.obs_per_week * target.scans_per_obs print(target.name, ' observations left ', target.obs_per_week, ' scan size ', target.scans_per_obs, ' priority ', target.priority) print('Total time left to observe ', timeLeft) self.showSky = False self.showAlt = False self.showBoth = True self.show_schedule() def show_schedule(self): #Atver grafiku skatu self.clear_window() sky, alt = self.plots[self.plots_idx] if self.showSky: self.layout.addWidget(sky, 0, 0, 2, 6) elif self.showAlt: self.layout.addWidget(alt, 0, 0, 2, 6) elif self.showBoth: self.layout.addWidget(sky, 0, 0, 1, 6) self.layout.addWidget(alt, 1, 0, 1, 6) self.toolbar = NavigationToolbar(alt, alt.parent) self.layout.addWidget(self.toolbar, 2, 0, 1, 3) self.radioSky = QRadioButton("Show skychart") self.radioAlt = QRadioButton("Show altitude") self.radioBoth = QRadioButton("Show both") self.radioSky.clicked.connect(self.changeScheduleView) self.radioAlt.clicked.connect(self.changeScheduleView) self.radioBoth.clicked.connect(self.changeScheduleView) self.layout.addWidget(self.radioSky, 2, 3) self.layout.addWidget(self.radioAlt, 2, 4) self.layout.addWidget(self.radioBoth, 2, 5) nextButton = QPushButton("Next") nextButton.clicked.connect(self.next_schedule) backButton = QPushButton("Back") backButton.clicked.connect(self.back_schedule) self.layout.addWidget(backButton, 3, 0, 1, 3) self.layout.addWidget(nextButton, 3, 3, 1, 3) startButton = QPushButton("To start") startButton.clicked.connect(self.to_start) self.layout.addWidget(startButton, 4, 0, 1, 3) if self.plots_idx == 0: backButton.hide() if self.plots_idx == (len(self.plots) - 1): nextButton.hide() def next_schedule(self): self.plots_idx += 1 self.show_schedule() def changeScheduleView(self): radioText = self.sender().text() if "sky" in radioText: self.showSky = True self.showAlt = False self.showBoth = False self.show_schedule() self.radioSky.setChecked(True) elif "alt" in radioText: self.showSky = False self.showAlt = True self.showBoth = False self.show_schedule() self.radioAlt.setChecked(True) elif "both" in radioText: self.showSky = False self.showAlt = False self.showBoth = True self.show_schedule() self.radioBoth.setChecked(True) def back_schedule(self): self.plots_idx -= 1 self.show_schedule() def save_obs(self): filename = self.saveFileDialog() if filename != "Fail": obsList = [self.observationList.item(i).data(Qt.UserRole) for i in range(self.observationList.count())] json_dict = dict() for obs in obsList: json_dict[obs.target.name]={ "priority": obs.priority, "obs_per_week": obs.obs_per_week, "scans_per_obs": obs.scans_per_obs, "global_time": obs.global_time, "times": obs.times, } print(json_dict) with open(filename, 'w') as outfile: json.dump(json_dict, outfile, indent=4) def saveFileDialog(self): save = QFileDialog() save.setDefaultSuffix(".json") save.setNameFilter("JSON files (*.json)") save.setAcceptMode(QFileDialog.AcceptSave) save.setOption(QFileDialog.DontUseNativeDialog) if save.exec_() == QFileDialog.Accepted: return save.selectedFiles()[0] else: return "Fail" def load_obs(self): load = QFileDialog() load.setDefaultSuffix(".json") load.setNameFilter("JSON files (*.json)") load.setAcceptMode(QFileDialog.AcceptOpen) load.setOption(QFileDialog.DontUseNativeDialog) if load.exec_() == QFileDialog.Accepted: filename = load.selectedFiles()[0] with open(filename) as json_file: obs_dict = json.load(json_file) self.observationList.clear() for key in obs_dict: if key in self.targetsDict: targetName = key ra = self.targetsDict[targetName]["ra"] dec = self.targetsDict[targetName]["dec"] coord = SkyCoord(frame='icrs', ra=ra, dec=dec, obstime="J2000") target = FixedTarget(coord=coord, name=targetName) for date in obs_dict[key]['times']: print(date) # TODO Te pielikt date parbaudes, vai atkekset ja ir vai iznemt ja nav data = PlannedObs(target, int(obs_dict[key]['priority']), int(obs_dict[key]['obs_per_week']), int(obs_dict[key]['scans_per_obs']), obs_dict[key]['times'], obs_dict[key]['global_time']) item = QListWidgetItem(str(data), self.observationList) item.setData(Qt.UserRole, data) self.observationList.addItem(item) self.plannedTargets.append(target.name) else: self.show_error("Target error", key + " not in targets, skipping it") else: print("Something went wrong") def load_obs_new(self): load = QFileDialog() load.setDefaultSuffix(".conf") load.setNameFilter("CONF files (*.conf)") load.setAcceptMode(QFileDialog.AcceptOpen) load.setOption(QFileDialog.DontUseNativeDialog) if load.exec_() == QFileDialog.Accepted: self.observationList.clear() filename = load.selectedFiles()[0] configObs = configparser.ConfigParser() configObs.read(filename) sections = configObs.sections() for section in sections: target = section.split('_')[0] ra = configObs[section]["RA"] dec = configObs[section]["DEC"] if target not in self.targetsDict.keys(): coords = {"ra": Angle(ra), "dec": Angle(dec)} self.targetsDict[target] = coords else: if Angle(ra) != Angle(self.targetsDict[target]["ra"]) or Angle(dec) != Angle(self.targetsDict[target]["dec"]): qm = QMessageBox ret = qm.question(self,'', target+" has different coords in the load file, would you like to overwrite the current ones?\n"+ "new coords:"+str(ra)+"; "+str(dec)+"\ncurrent coords:"+str(self.targetsDict[target]["ra"])+"; "+str(self.targetsDict[target]["dec"]), qm.Yes | qm.No) if ret == qm.Yes: self.targetsDict[target]["ra"] = Angle(ra) self.targetsDict[target]["dec"] = Angle(dec) targetName = target ra = self.targetsDict[targetName]["ra"] dec = self.targetsDict[targetName]["dec"] coord = SkyCoord(frame='icrs', ra=ra, dec=dec, obstime="J2000") target = FixedTarget(coord=coord, name=targetName) data = PlannedObs(target, 1, 1, int(configObs[section]["n_scans"]), None, None) item = QListWidgetItem(str(data), self.observationList) item.setData(Qt.UserRole, data) self.observationList.addItem(item) self.plannedTargets.append(target.name) else: print("Something went wrong") def show_error(self, title, error_message): error_dialog = QMessageBox.critical(self, title, error_message) def to_start(self): self.clear_window() self.load_ui() def clear_window(self): for i in reversed(range(self.layout.count())): self.layout.itemAt(i).widget().setParent(None) def is_time_format(self, string): p = re.compile('^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$') print(string) res = bool(p.match(string)) return res def time_check(self, time, timeStart, timeEnd): if not self.is_time_format(time): return False else: time = time.split(':') timeStart = timeStart.split(':') timeEnd = timeEnd.split(':') if int(time[0]) < int(timeStart[0]) or int(time[0]) > int(timeEnd[0]): return False elif int(time[0]) > int(timeStart[0]) and int(time[0]) < int(timeEnd[0]): return True elif (int(time[0]) == int(timeStart[0]) and int(time[1]) < int(timeStart[1])) or (int(time[0]) == int(timeEnd[0]) and int(time[1]) > int(timeEnd[1])): return False elif (int(time[0]) == int(timeStart[0]) and int(time[1]) >= int(timeStart[1])) or (int(time[0]) == int(timeEnd[0]) and int(time[1]) < int(timeEnd[1])): return True def deleteItemsOfLayout(self, layout): if layout is not None: while layout.count(): item = layout.takeAt(0) widget = item.widget() if widget is not None: widget.setParent(None) else: self.deleteItemsOfLayout(item.layout())
class HtmlTranslator(QtWidgets.QMainWindow, tabs_design.Ui_MainWindow): def initTableHeader(self): # Шапка таблицы GUI.setTableHeader(self.langs, self.tableHeaderLayout) ################------------------------#################### #############**Создаем индексы переводов**################## ################------------------------#################### def indexVocabulary(self): initData = self.initDataVocabulary # Инициализация списков для дальнейшего наполнения data = {} for lang in self.langs: data[lang] = {} # Формируем необходимую структуру данных для записи в индексные файлы for key in initData: for lang in self.langs: data[lang].update({initData[key][lang]: key}) # Пишем в файл json данные формата "значение : ключ" (с учетом локализации) for lng in data: self.writeJson(self.vocabularyFileName + '_' + lng, data[lng]) ################------------------------#################### #############*****Заппись json в файл*****################## ################------------------------#################### def writeJson(self, fileName, data): with open(fileName + '.json', 'w', encoding='utf8') as f: json.dump(data, f, ensure_ascii=False, indent=4) ################------------------------#################### #############****Инициализация словаря****################## ################------------------------#################### def initVocabulary(self): layout = QGridLayout() initData = self.initDataVocabulary widget = QWidget() # Виджет в скролл области self.scrollArea.setWidget(widget) self.vocabularyLayout = QVBoxLayout(widget) # Рендер переводов for key in initData: horizontal = GUI.setRow(self, self.langs, initData[key], key, self.vocabularyLayout) # Установка обработчиков нажатия кнопок for itemInRow in range(horizontal.itemAt(0).count()): widgetType = horizontal.itemAt(0).itemAt( itemInRow).widget().property('type') if (widgetType == 'edit'): horizontal.itemAt(0).itemAt( itemInRow).widget().clicked.connect(self.editClick) if (widgetType == 'delete'): horizontal.itemAt(0).itemAt( itemInRow).widget().clicked.connect(self.deleteClick) self.vocabularyLayout.addLayout(horizontal) # Устанавливаем основной (вертикальный шаблон) в окне приложения self.vocabularyLayout.addStretch(1) def deleteClick(self): # Подтверждение удаления записи confirmDelete = QtWidgets.QMessageBox.critical( None, 'Подтверждение удаления', 'Вы действительно желаете удалить данную запись?', QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) if confirmDelete == QtWidgets.QMessageBox.Yes: # Получаем индекс горизонтального шаблона по аттрибуту кнопки (ID) horizontalRowLayoutId = self.sender().property('id') keyAttr = self.sender().property('key') horizontalRowLayout = self.vocabularyLayout.itemAt( horizontalRowLayoutId) # Шаблон сетки в горизонтальном шаблоне (QGridLayoiut в шаблоне QHLayout) innerRowGridLayout = horizontalRowLayout.itemAt( 0 ) #Немного костыль, если будет боолее одного layout-та не сработает widgetCount = innerRowGridLayout.count() # Удаляем все виджеты в шаблоне (layuot-e) for i in reversed(range(widgetCount)): innerRowGridLayout.itemAt(i).widget().setParent(None) # Удаляем шаблон сетки (QGridLayout) из горизонтального шаблона horizontalRowLayout.removeItem(horizontalRowLayout.itemAt(0)) self.vocabularyLayout.removeItem( self.vocabularyLayout.itemAt(horizontalRowLayoutId)) #Обновление аттрибутов ID у кнопок редактирования и удаления (чтобы индексы слоев GUI соответствовали индексам записей из словаря) i = 0 for horizontalRow in range( self.vocabularyLayout.count() - 1 ): # count()-1 Убираем из общего количества объектов последний добавляющий растяжение макету (self.vocabularyLayout.addStretch(1)) if (self.vocabularyLayout.itemAt(horizontalRow).itemAt(0) != None): for itemInRow in range( self.vocabularyLayout.itemAt(horizontalRow).itemAt( 0).count()): #Тип элемента GUI (если это тип удалить или редактировать (кнопки), то обновляем их ID-ки после удаления перевода) rowItemWidgetType = self.vocabularyLayout.itemAt( horizontalRow).itemAt(0).itemAt( itemInRow).widget().property('type') if (rowItemWidgetType == self.editType or rowItemWidgetType == self.deleteType): self.vocabularyLayout.itemAt(horizontalRow).itemAt( 0).itemAt(itemInRow).widget().setProperty( 'id', i) i += 1 del self.initDataVocabulary[keyAttr] with open(self.vocabularyFileName + '.json', 'w') as f: json.dump(self.initDataVocabulary, f) self.indexVocabulary() def editClick(self): self.dialog = QDialog(self) self.dialog.ui = uic.loadUi('editTranslateDialog.ui', self.dialog) translateKey = self.sender().property('key') self.renderDialog(self.initDataVocabulary[translateKey], key=translateKey, type='edit') def clickBtnAddTranslate(self, values=None): #инициализация диалогового окна и установка дизайна (пустой layout) self.dialog = QDialog(self) self.dialog.ui = uic.loadUi('addTranslateDialog.ui', self.dialog) self.renderDialog() def renderDialog(self, values=None, key=None, type='save'): layout = QVBoxLayout() # Ключ перевода (добавляем на layout метку и инпут) keyRow = QHBoxLayout() keyRow.addWidget(QLabel('Ключ', objectName='textLabel')) if key is not None: keyInput = QtWidgets.QLineEdit(key, objectName='inputField') else: keyInput = QtWidgets.QLineEdit(objectName='inputField') keyInput.setProperty('name', 'key') keyRow.addWidget(keyInput) layout.addLayout(keyRow) layout.addStretch(1) # Локализованные значения (сами переводы) for lang in self.langs: langRowHorizontal = QHBoxLayout() lng = QLabel(lang, objectName='textLabel') if values is not None: lngInput = QtWidgets.QLineEdit(values[lang], objectName='inputField') else: lngInput = QtWidgets.QLineEdit(objectName='inputField') lngInput.setProperty('name', lang) langRowHorizontal.addWidget(lng) langRowHorizontal.addWidget(lngInput) layout.addLayout(langRowHorizontal) layout.addStretch(1) layout.addStretch(1) # Кнопки взаимодействия с диалоговым окном (сохранить и отмена - закрыть диалог) buttonsRow = QHBoxLayout() saveButton = QPushButton( 'Сохранить', objectName='saveButton' if type == 'save' else 'editButton') cancelButton = QPushButton('Отмена', objectName='cancelButton') # Обработчик нажатия кнопок (отмена и сохранить) cancelButton.clicked.connect(self.cancelDialogClick) saveButton.clicked.connect(self.saveTranslateClick if type == 'save' else self.updateTranslateClick) buttonsRow.addWidget(cancelButton) buttonsRow.addWidget(saveButton) # Информационный текст infoRow = QHBoxLayout() info = QLabel( 'Внимание! При редактировании ключа будет создана новая запись в словаре!', objectName='dangerLabel') infoRow.addWidget(info) layout.addLayout(infoRow) layout.addStretch(1) layout.addLayout(buttonsRow) # Устанавливаем стили диалогового окна self.dialog.setStyleSheet(open("styles/qLineEdit.qss", "r").read()) self.dialog.setLayout(layout) # Показываем диалоговое окно self.dialog.show() # Обновляем перевод в файлы (словари) def updateTranslateClick(self): dialogData = {} # Собираем данные с формы (диалоговое окно) emptyInputError = False for dialogInput in range(self.dialog.layout().count()): if (self.dialog.layout().itemAt(dialogInput).__class__.__name__ == 'QHBoxLayout'): dialogItem = self.dialog.layout().itemAt(dialogInput) if (dialogItem.itemAt(1) is not None and dialogItem.itemAt(1).widget().property('name') != None): # Ключ name = self.dialog.layout().itemAt(dialogInput).itemAt( 1).widget().property('name') # Значение value = self.dialog.layout().itemAt(dialogInput).itemAt( 1).widget().text() # Проверяем на наличие пустых полей if (len(value) < 2): emptyInputError = True dialogData[name] = value # В случае пустоты хотя бы в одном из полей информируем пользователя if (emptyInputError): self.showMessage('Ошибка!', 'Не заполнены все поля', 'warning') else: newItem = {} langValueItem = {} # Записываем переводы в файлы локализаций for lang in self.langs: langValueItem[lang] = dialogData[lang] self.initDataVocabulary[dialogData['key']] = langValueItem self.writeJson(self.vocabularyFileName, self.initDataVocabulary) self.showMessage('Обновлено', 'Перевод успешно обновлен!', 'info') # Очищаем поля ввода в диалоговом окне for dialogInput in range(self.dialog.layout().count()): if (self.dialog.layout().itemAt(dialogInput).__class__.__name__ == 'QHBoxLayout'): dialogItem = self.dialog.layout().itemAt(dialogInput) if (dialogItem.itemAt(1) is not None and dialogItem.itemAt(1).widget().property('name') != None): self.dialog.layout().itemAt(dialogInput).itemAt( 1).widget().setText('') horizontal = GUI.setRow(self, self.langs, dialogData, dialogData['key'], self.vocabularyLayout) self.initVocabulary() self.indexVocabulary() # Сохраняем перевод в файлы (словари) def saveTranslateClick(self): dialogData = {} #Собираем данные с формы (диалоговое окно) emptyInputError = False for dialogInput in range(self.dialog.layout().count()): if (self.dialog.layout().itemAt(dialogInput).__class__.__name__ == 'QHBoxLayout'): dialogItem = self.dialog.layout().itemAt(dialogInput) if (dialogItem.itemAt(1) is not None and dialogItem.itemAt(1).widget().property('name') != None): #Ключ name = self.dialog.layout().itemAt(dialogInput).itemAt( 1).widget().property('name') #Значение value = self.dialog.layout().itemAt(dialogInput).itemAt( 1).widget().text() # Проверяем на наличие пустых полей if (len(value) < 2): emptyInputError = True dialogData[name] = value # В случае пустоты хотя бы в одном из полей информируем пользователя if (emptyInputError): self.showMessage('Ошибка!', 'Не заполнены все поля', 'warning') else: newItem = {} langValueItem = {} #Записываем переводы в файлы локализаций for lang in self.langs: langValueItem[lang] = dialogData[lang] if (self.initDataVocabulary is None or len(self.initDataVocabulary) < 1): self.initDataVocabulary = {} self.initDataVocabulary[dialogData['key']] = langValueItem self.initTableHeader() self.initVocabulary() else: self.initDataVocabulary[dialogData['key']] = langValueItem self.writeJson(self.vocabularyFileName, self.initDataVocabulary) self.showMessage('Сохранено', 'Перевод успешно добавлен!', 'info') # Очищаем поля ввода в диалоговом окне for dialogInput in range(self.dialog.layout().count()): if (self.dialog.layout().itemAt(dialogInput).__class__.__name__ == 'QHBoxLayout'): dialogItem = self.dialog.layout().itemAt(dialogInput) if (dialogItem.itemAt(1) is not None and dialogItem.itemAt(1).widget().property('name') != None): self.dialog.layout().itemAt(dialogInput).itemAt( 1).widget().setText('') horizontal = GUI.setRow(self, self.langs, dialogData, dialogData['key'], self.vocabularyLayout) self.initVocabulary() self.indexVocabulary() # Закрываем диалоговое окно def cancelDialogClick(self): self.dialog.close() def to_json(self, inputJson): try: json_object = json.load(inputJson) except ValueError as e: return None return json_object def getInputs(self): return (self.first.text(), self.second.text()) # def getFiles(self, dir = ''): # if(len(dir) > 0) : # return [f for f in listdir(dir) if isfile(join(dir, f))] # # def getDirs(self, dir=''): # return [f for f in listdir(dir) if isdir(join(dir, f))] ################------------------------#################### ########****Запускаем работу скрипта(Laravel)****################ ################------------------------#################### def clickBtnRunLaravel(self): try: Laravel.run(self.settingsLaravelRootDir, self.setting_main_lang) except FileNotFoundError as f: self.showMessage('Ошибка!', 'Не верно указан путь к файлу!', 'critical') def __init__(self): # Это здесь нужно для доступа к переменным, методам # и т.д. в файле html.py super().__init__() self.setupUi(self) # Это нужно для инициализации нашего дизайна # Информационное окно self.msg = QtWidgets.QMessageBox() #Инициализация входной и выходной строки self.input = '' self.output = '' #Загрузка настроек из файла self.load_settings() # Длина строки перевода (отоюражение в словаре) self.translateLen = 25 #Языки self.langs = self.setting_langs.split('|') self.default_lang = self.setting_main_lang #Типы кнопок (удалить, редактировать) self.editType = 'edit' self.deleteType = 'delete' #Загрузка словаря self.vocabularyFileName = 'vocabulary' self.vocabularyLayout = self.scrollArea #Загрузка данных словаря with open(self.vocabularyFileName + '.json', 'r') as inputData: self.initDataVocabulary = self.to_json(inputData) #Функции инициализации if (self.initDataVocabulary is not None and len(self.initDataVocabulary) > 0): self.indexVocabulary() self.initTableHeader() self.initVocabulary() #Обработчики нажатия кнопок self.btn_run.clicked.connect(self.click_btn_run) self.btn_save_settings.clicked.connect(self.click_btn_save_settings) self.btn_translate_file.clicked.connect(self.click_btn_translate_file) self.addTranslate.clicked.connect(self.clickBtnAddTranslate) #Laravel self.btnLaravelRoot.clicked.connect(self.clickBtnLaravelRoot) self.btnRunLaravel.clicked.connect(self.clickBtnRunLaravel) #Обработчик события изменение позиции курсора #self.main_input.cursorPositionChanged.connect(self.changeInput) def load_settings(self): # Читаем настройки из файла self.settings_path = 'settings.ini' if os.path.exists(self.settings_path): settings = configparser.ConfigParser() settings.read(self.settings_path) # GENERAL self.setting_langs = settings.get('GENERAL', 'LANGS') self.setting_main_lang = settings.get('GENERAL', 'MAIN_LANG') self.setting_file_translates = settings.get( 'MODX', 'FILE_TRANSLATES') self.setting_l_placeholder = settings.get('MODX', 'LEFT_PLACEHOLDER') self.setting_r_placeholder = settings.get('MODX', 'RIGHT_PLACEHOLDER') #LARAVEl self.settingsLeftLaravelPlaceholder = settings.get( 'LARAVEL', 'LEFT_LARAVEL_PLACEHOLDER') self.settingsRightLaravelPlaceholder = settings.get( 'LARAVEL', 'RIGHT_LARAVEL_PLACEHOLDER') self.settingsLaravelRootDir = settings.get('LARAVEL', 'ROOT_DIR') # DB self.setting_db_user = settings.get('DB', 'DB_USER') self.setting_db_name = settings.get('DB', 'DB_NAME') self.setting_db_pass = settings.get('DB', 'DB_PASS') # Установка значений настроек из файла на форму if len(self.setting_langs) > 0: langs_arr = self.setting_langs.split('|') if 'ru' in langs_arr: self.ru.setChecked(True) if 'en' in langs_arr: self.en.setChecked(True) if 'uk' in langs_arr: self.uk.setChecked(True) if 'de' in langs_arr: self.de.setChecked(True) main_lang = self.main_lang.findText(self.setting_main_lang, QtCore.Qt.MatchFixedString) if main_lang >= 0: self.main_lang.setCurrentIndex(main_lang) self.file_path.setText(self.setting_file_translates) self.l_placeholder.setText(self.setting_l_placeholder) self.r_placeholder.setText(self.setting_r_placeholder) self.db_user.setText(self.setting_db_user) self.db_name.setText(self.setting_db_name) self.db_pass.setText(self.setting_db_pass) #Laravel self.laravelRootDir.setText(self.settingsLaravelRootDir) self.leftLaravelPlaceholder.setText( self.settingsLeftLaravelPlaceholder) self.rightLaravelPlaceholder.setText( self.settingsRightLaravelPlaceholder) # def changeInput (self): # input = self.main_input # #self.input = self.main_input.toPlainText() # #str_output = self.input.replace('<div>', "[#" + str(exist_id) + "#]") # input.setText("<div></div>") # #print(self.input) ################------------------------#################### #############****Выбор файла переводов****################## ################------------------------#################### def click_btn_translate_file(self): fname, _filter = QtWidgets.QFileDialog.getOpenFileName( self, 'Выберите файл') self.file_path.setText(fname) ################------------------------#################### #######****Выбор корневой директории шаблонов****########### ################------------------------#################### def clickBtnLaravelRoot(self): dirName = QtWidgets.QFileDialog.getExistingDirectory( self, 'Выберите директорию', '/home') self.laravelRootDir.setText(dirName) ################------------------------#################### #############****Обновление настроек****#################### ################------------------------#################### def click_btn_save_settings(self): # языки для переводов langs = [] if self.ru.isChecked(): langs.append('ru') if self.en.isChecked(): langs.append('en') if self.uk.isChecked(): langs.append('uk') if self.de.isChecked(): langs.append('de') # Основной язык m_lang = self.main_lang.currentText() #База данных db_user = self.db_user.text() db_pass = self.db_pass.text() db_name = self.db_name.text() # Путь к файлу переводов file_translates = self.file_path.text() #Корневая директория шаблонов Laravel laravelRootDir = self.laravelRootDir.text() #Плейсхолдеры l_placeholder = self.l_placeholder.text() r_placeholder = self.r_placeholder.text() leftLaravelPlaceholder = self.leftLaravelPlaceholder.text() rightLaravelPlaceholder = self.rightLaravelPlaceholder.text() #Подтверждение сохранения настроек buttonReply = QtWidgets.QMessageBox.question( self, 'Изменение настроек', "Сохранить выбранные настройки?", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) if buttonReply == QtWidgets.QMessageBox.Yes: settings = configparser.ConfigParser() settings['GENERAL'] = { 'LANGS': '|'.join(langs), 'MAIN_LANG': m_lang, } settings['MODX'] = { 'FILE_TRANSLATES': file_translates, 'LEFT_PLACEHOLDER': l_placeholder, 'RIGHT_PLACEHOLDER': r_placeholder, } settings['LARAVEL'] = { 'LEFT_LARAVEL_PLACEHOLDER': leftLaravelPlaceholder, 'RIGHT_LARAVEL_PLACEHOLDER': rightLaravelPlaceholder, 'ROOT_DIR': laravelRootDir, } settings['DB'] = { 'DB_USER': db_user, 'DB_NAME': db_name, 'DB_PASS': db_pass, } with open(self.settings_path, "w") as config_file: settings.write(config_file) self.load_settings() def filter_values(self, x): if (re.findall( r'^{{.+}}$|^{!!.+!!}$|^@|^{{\s.+}}|^:{{.+}}$|^\+{{.+}}$', x)): return 0 return 1 ################------------------------#################### ############****Запускаем работу скрипта****################ ################------------------------#################### def click_btn_run(self): # Получаем все переводы из файла translate_path = Path(self.setting_file_translates) try: translate_path.owner() translate_file_content = check_output([ 'php', '-r', 'include "' + self.setting_file_translates + '"; echo json_encode($l);' ]) translate_file_content = json.loads(translate_file_content) # Введенный фрагмент self.input = self.output = self.main_input.toPlainText() soup = BeautifulSoup(self.input, 'html.parser') for script in soup(["script", "style"]): script.extract() # rip it out text = soup.get_text() # break into lines and remove leading and trailing space on each lines = (line.strip() for line in text.splitlines()) # break multi-headlines into a line each chunks = [c for c in filter(None, lines)] chunks = filter(self.filter_values, chunks) for v in chunks: print(v) sys.exit(0) # Массив с переводами которые уже есть в БД (и которые не нужно будет переводить) exist_translates = DB.check_translates(self.setting_db_name, self.setting_db_user, self.setting_db_pass, self.setting_main_lang, chunks) # Подставляем ID существующих переводов, и удаляем эти элементы из списка (chunks) if (len(exist_translates) > 0): for translate in exist_translates: self.output = self.output.replace( translate[self.setting_main_lang], str(self.setting_l_placeholder) + str(translate['lang_id']) + str(self.setting_r_placeholder)) chunks.pop(chunks.index(translate[self.setting_main_lang])) # Перебираем оставщиеся строки, требующие перевода translator = Translator() translator.session.proxies['http'] = '125.26.109.83:8141' translator.session.proxies['http'] = '98.221.88.193:64312' translator.session.proxies['http'] = '188.244.35.162:10801' translator.session.proxies['http'] = '185.162.0.110:10801' # языки langs = self.setting_langs.split('|') # Прогресс бар i = 0 self.progressBar.setMaximum(len(chunks) + 1) # Прогресс бар for item in chunks: # Прогресс бар i += 1 self.progressBar.setValue(i) # Прогресс бар translate_file_string = [] translate_dic = {} translate_dic[self.setting_main_lang] = item # строка для файла переводов translate_file_string = [] for lang in langs: new_translate = translator.translate( item, src=self.setting_main_lang, dest=lang).text translate_dic[lang] = new_translate # Пауза для гугла sleep(3) # для запроса в базу (корректировка языков) correct_lang_sql = [] # значения для записи в базу string_sql_values = [] for item in translate_dic.items(): print(item[0] + '--------' + item[1]) correct_lang_sql.append(DB.lang_field_connector(item[0])) string_sql_values.append("'" + item[1] + "'") # Строка для записи в файл переводов translate_file_string.append('"' + item[0] + '": "' + item[1] + '"') langs_sql = ','.join(correct_lang_sql) string_sql_values = ','.join(string_sql_values) # Запись в БД sql = "INSERT INTO modx_a_lang (" + langs_sql + ") VALUES (" + string_sql_values + ");" # values = (translate_dic["uk"], translate_dic["ru"], translate_dic["en"]); last_id = DB.add_translate(self.setting_db_name, self.setting_db_user, self.setting_db_pass, sql) # Запись в файл переводов translate_file_string = '{' + ','.join( translate_file_string) + '}' translate_file_string = json.loads(translate_file_string) # Добавление нового перевода в строку json переводов translate_file_content[last_id] = translate_file_string self.output = self.output.replace( translate_dic[self.setting_main_lang], "[#" + str(last_id) + "#]") self.write_to_file(translate_file_content, self.setting_file_translates) # subprocess.call(['chmod', '0777', '"' + self.setting_file_translates + '"']) self.main_input.setPlainText(self.output) # Информационное сообщение о завершении работы self.showMessage( "Перевод завершен!", "Перевод фрагмента html выполнен. Теперь вы можете его скопировать и добавить в свой шаблон!", 'info') except FileNotFoundError as f: self.showMessage('Ошибка!', 'Не верно указан путь к файлу!', 'critical') ################------------------------#################### ############**********Запись в файл*********################ ################------------------------#################### def write_to_file(self, json_string, path="D:\OSPanel\domains\shop.loc\dump.php"): f = codecs.open(path, "w+", "utf-8") f.write('<?php \n $l=[') tr_strings = [] for l_id, value in json_string.items(): single_tr = str(l_id) + "=>[" # Массив переводов одного слова(предложения) tr_langs = [] for lang, v in value.items(): tr_langs.append("'" + lang + "'=>'" + v + "'") # Массив переводов строк single_tr += ','.join(tr_langs) + "]," f.write(single_tr) f.write('];') f.close() return True #########****************************************########### #########****Показать сообщение пользователю*****########### #########****************************************########### def showMessage(self, title, message, icon): icons = { 'info': QtWidgets.QMessageBox.Information, 'warning': QtWidgets.QMessageBox.Warning, 'critical': QtWidgets.QMessageBox.Critical, } self.msg.setIcon(icons[icon]) self.msg.setWindowTitle(title) self.msg.setText(message) self.msg.exec_()
class MainWindow(QMainWindow): def __init__(self, root): super().__init__() self.scroll = QScrollArea( ) # Scroll Area which contains the widgets, set as the centralWidget self.widget = QWidget( ) # Widget that contains the collection of Vertical Box self.vbox = QVBoxLayout( ) # The Vertical Box that contains the Horizontal Boxes of labels and buttons self.root = root self.directory_text = DirText(self) self.hbox = QHBoxLayout() self.back_button = QPushButton() self.back_button.clicked.connect(lambda: self.execute_prev_string()) self.back_button.setStyleSheet("background-color: lightblue;") box_layout = QHBoxLayout() box_layout.addWidget(self.back_button) box_layout.addWidget(self.directory_text) self.back_button.setIcon(QIcon("arrow.png")) self.vbox.addLayout(box_layout) self.setStyleSheet("background-color: white;") self.current_dir = "/" self.directory_list = ["/"] self.initUI(root) def initUI(self, root): self.widget.setLayout(self.vbox) # Scroll Area Properties self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) # self.scroll.setHorizontalScrollBarPolicy() self.scroll.setWidgetResizable(True) self.scroll.setWidget(self.widget) self.setCentralWidget(self.scroll) self.setGeometry(600, 100, 1000, 900) self.setWindowTitle('Scroll Area Demonstration') self.show() return def resetQbox(self): for i in reversed(range(self.vbox.count())): if i == 0: continue if isinstance(self.vbox.itemAt(i), QHBoxLayout): for j in reversed(range(self.vbox.itemAt(i).count())): self.vbox.itemAt(i).itemAt(j).widget().setParent(None) self.vbox.removeItem(self.vbox.itemAt(i)) continue self.vbox.itemAt(i).widget().setParent(None) def addToVbox(self, item): self.vbox.addLayout(item) self.vbox.setAlignment(Qt.AlignTop) # def mousePressEvent(self, QMouseEvent): # self.resetQbox() def mouseDoubleClickEvent(self, QMouseEvent): print("xd doubble baby") def check_file_and_set(self, path): if path == "": self.directory_text.setText(self.current_dir) if path[0] == "/" and len(path) == 1: self.set_directory_interface(self.root, ["/"]) string_list = path.split("/")[1:] if self.root is not None: if path == "/": self.set_directory_interface(self.root, ["/"]) return folder = self.check_directory(self.root.file_inside, string_list) # ocupo añadir cosas aqui if folder == 1 or folder == 2: return self.set_directory_interface(folder, string_list) def check_directory(self, file_list, list_strings): file_to_return = None for name in list_strings: file_to_return = self.get_file_inside(name, file_list) if file_to_return == 1: pass elif file_to_return == 2: pass else: file_list = file_to_return.file_inside return file_to_return def get_file_inside(self, file_name, file_list): for file in file_list: if file.file_name == file_name: if file.type == "folder": return file else: return 1 return 2 def set_directory_interface(self, file, string_list): self.resetQbox() i = 0 box_layout = QHBoxLayout() for file in file.file_inside: if i % 5 == 0: box_layout = QHBoxLayout() box_layout.setAlignment(Qt.AlignLeft) self.addToVbox(box_layout) i += 1 file.reset_labels(self) box_layout.addWidget(file.label) box_layout.addWidget(file.label_data) # if i%2==0: # print("Entre") # var =QLabel() # var2 =QLabel() # box_layout.addWidget(var) # box_layout.addWidget(var2) string_text = "/" for string in string_list: string_text += string + "/" if string_text == "///": self.directory_list.append(self.current_dir) self.current_dir = "/" self.directory_text.setText("/") return self.directory_list.append(self.current_dir) self.current_dir = string_text[:len(string_text) - 1] self.directory_text.setText(string_text) def execute_prev_string(self): self.check_file_and_set(self.directory_list[len(self.directory_list) - 1]) print("Aqui") if len(self.directory_list) == 2: self.directory_list.pop(len(self.directory_list) - 1) return if len(self.directory_list) != 1: self.directory_list.pop(len(self.directory_list) - 1) self.directory_list.pop(len(self.directory_list) - 1) return
class RmsFrame(QFrame): def __init__(self, cu): super().__init__() self.cu = cu self.session = RaceSession() self.resetRMS() self.buildframe() self.driverBtn = {} self.driverObj = {} self.lapcount = {} self.totalTime = {} self.laptime = {} self.bestlaptime = {} self.fuelbar = {} self.pits = {} # QBAcolor = QByteArray() # QBAcolor.append('color') # self.animation = anim = QPropertyAnimation(self, QBAcolor, self) # anim.setDuration(250) # anim.setLoopCount(2) # anim.setStartValue(QColor(230,230, 0)) # anim.setEndValue(QColor(0, 0, 0)) # anim.setKeyValueAt(0.5, QColor(150,100,0)) def buildframe(self): self.vLayout = QVBoxLayout(self) self.hBtnLayout = QHBoxLayout() self.vLayout.addLayout(self.hBtnLayout) # Add driver to grid self.addDriverBtn = QPushButton('(A)dd Driver') self.addDriverKey = QShortcut(QKeySequence("a"), self) self.hBtnLayout.addWidget(self.addDriverBtn) self.addDriverBtn.clicked.connect(self.addDriver) self.addDriverKey.activated.connect(self.addDriver) # Assign Controller self.assignCtrlBtn = QPushButton('Assign Controller') self.hBtnLayout.addWidget(self.assignCtrlBtn) self.assignCtrlBtn.clicked.connect(self.openCtrlDialog) # Setup a race self.setupRace = QPushButton('Setup a Race') self.hBtnLayout.addWidget(self.setupRace) self.setupRace.clicked.connect(self.openRaceDlg) # Code cars self.codeBtn = QPushButton('(C)ode') self.codeKey = QShortcut(QKeySequence("c"), self) self.hBtnLayout.addWidget(self.codeBtn) self.codeBtn.clicked.connect(self.pressCode) self.codeKey.activated.connect(self.pressCode) # Start pace car self.paceBtn = QPushButton('(P)ace') self.paceKey = QShortcut(QKeySequence("p"), self) self.hBtnLayout.addWidget(self.paceBtn) self.paceBtn.clicked.connect(self.setPace) self.paceKey.activated.connect(self.setPace) # set Speed self.setSpeedBtn = QPushButton('Set (S)peed') self.setSpeedKey = QShortcut(QKeySequence("s"), self) self.hBtnLayout.addWidget(self.setSpeedBtn) self.setSpeedBtn.clicked.connect(self.setSpeed) self.setSpeedKey.activated.connect(self.setSpeed) # set Brakes self.setBrakeBtn = QPushButton('Set (B)rake') self.setBrakeKey = QShortcut(QKeySequence("b"), self) self.hBtnLayout.addWidget(self.setBrakeBtn) self.setBrakeBtn.clicked.connect(self.setBrake) self.setBrakeKey.activated.connect(self.setBrake) # Set Fuel self.setFuelBtn = QPushButton('Set (F)uel') self.setFuelKey = QShortcut(QKeySequence("f"), self) self.hBtnLayout.addWidget(self.setFuelBtn) self.setFuelBtn.clicked.connect(self.setFuel) self.setFuelKey.activated.connect(self.setFuel) # Reset CU self.resetBtn = QPushButton('(R)eset') self.resetKey = QShortcut(QKeySequence("r"), self) self.hBtnLayout.addWidget(self.resetBtn) self.resetBtn.clicked.connect(self.resetRMS) self.resetKey.activated.connect(self.resetRMS) # Start/Pause Race Enter self.startRaceBtn = QPushButton( 'Start Race or Enter changed Settings (Spacebar)') self.startRaceBtn.clicked.connect(self.racestart) self.spacekey = QShortcut(QKeySequence("Space"), self) self.spacekey.activated.connect(self.racestart) self.hStartBtnLayout = QHBoxLayout() self.hStartBtnLayout.addStretch(1) self.hStartBtnLayout.addWidget(self.startRaceBtn) self.hStartBtnLayout.setAlignment(self.startRaceBtn, Qt.AlignHCenter) self.hStartBtnLayout.addStretch(1) self.pitLaneStatus = QLabel() self.hStartBtnLayout.addWidget(QLabel('Pitlane')) self.hStartBtnLayout.addWidget(self.pitLaneStatus) self.fuelmode = QLabel() self.hStartBtnLayout.addWidget(QLabel('Fuel Mode')) self.hStartBtnLayout.addWidget(self.fuelmode) self.lapCounter = QLabel() self.hStartBtnLayout.addWidget(QLabel('Lap Counter')) self.hStartBtnLayout.addWidget(self.lapCounter) self.vLayout.addLayout(self.hStartBtnLayout) self.vLayout.setAlignment(self.hStartBtnLayout, Qt.AlignTop) # self.sepline = QFrame() # self.sepline.setFrameShape(QFrame.HLine) # self.sepline.setFrameShadow(QFrame.Sunken) # self.vLayout.addWidget(self.sepline) # self.vLayout.setAlignment(self.sepline, Qt.AlignTop) # Driver Grid self.vLayout.addLayout(self.buildGrid()) # Session Info self.racemode = QLabel('No Race Started') self.racemode.setAlignment(Qt.AlignCenter) self.racemode.setStyleSheet( "QLabel{ border-radius: 10px; background-color: grey; center; color: blue; font: 30pt}" ) self.vLayout.addWidget(self.racemode) self.vLayout.setAlignment(self.racemode, Qt.AlignBottom) def buildGrid(self): self.mainLayout = QGridLayout() self.mainLayout.setSpacing(10) self.mainLayout.setHorizontalSpacing(10) self.headerFont = QFont() self.headerFont.setPointSize(14) self.headerFont.setBold(True) self.labelArr = [ 'Pos', 'Driver', 'Total', 'Laps', 'Laptime', 'Best Lap', 'Fuel', 'Pits' ] for index, label in enumerate(self.labelArr): self.headerLabel = QLabel(label) self.headerLabel.setFont(self.headerFont) self.mainLayout.addWidget(self.headerLabel, 0, index, Qt.AlignHCenter) self.mainLayout.setColumnStretch(1, 1) self.mainLayout.setColumnStretch(2, 1) self.mainLayout.setColumnStretch(3, 2) self.mainLayout.setColumnStretch(4, 3) self.mainLayout.setColumnStretch(5, 3) self.mainLayout.setColumnStretch(6, 2) self.mainLayout.setColumnStretch(7, 1) return self.mainLayout def openCtrlDialog(self): self.ctrlDialog = CtrlDialog(self.driverArr) if self.ctrlDialog.exec_(): self.driverArr = self.ctrlDialog.newDriverArr def openRaceDlg(self): self.setupRaceDlg = RaceModeDialog() self.session.session = None self.session.type = None if self.setupRaceDlg.exec_(): for driver in self.driverArr: driver.bestLapTime = None driver.time = None driver.lapcount = 0 driver.pitcount = 0 self.session.setRace(self.setupRaceDlg.getRaceModeInfo()) self.racemode.setText(self.session.session + ' ' + str(self.session.amount) + ' ' + self.session.type) self.clearCU() self.cu.start() else: self.setupRaceDlg.close() def getColor(self): if self.mainLayout.itemAtPosition(1, 1): return self.mainLayout.itemAtPosition(1, 1).widget().palette().text() else: return None def setColor(self, color): PBwidget = self.mainLayout.itemAtPosition(1, 1).widget() palette = PBwidget.palette() palette.setColor(PBwidget.foregroundRole(), color) PBwidget.setFlat(True) PBwidget.setAutoFillBackground(True) PBwidget.setPalette(palette) color = pyqtProperty(QColor, getColor, setColor) def addDriver(self): driverRow = self.mainLayout.rowCount() if driverRow > 8: return driver = self.driverArr[driverRow - 1] self.posFont = QFont() self.posFont.setPointSize(35) self.posFont.setBold(True) self.driverPos = QLabel(str(driverRow)) self.driverPos.setStyleSheet( "QLabel{ border-radius: 10px; border-color: black; border: 5px solid black; background-color: white}" ) self.driverPos.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding) self.driverPos.setFont(self.posFont) self.mainLayout.addWidget(self.driverPos, driverRow, 0) self.driverBtn[driverRow] = driver.getNameBtn() self.driverBtn[driverRow].setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.mainLayout.addWidget(self.driverBtn[driverRow], driverRow, 1) self.driverObj[driverRow] = driver self.driverBtn[driverRow].clicked.connect(lambda: self.changeDriver( self.driverBtn[driverRow], self.driverObj[driverRow])) self.lapcount[driverRow] = driver.getLapCountLCD() self.lapcount[driverRow].setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.mainLayout.addWidget(self.lapcount[driverRow], driverRow, 3) self.totalFont = QFont() self.totalFont.setPointSize(25) self.totalFont.setBold(True) self.totalTime[driverRow] = QLabel('00:00') self.totalTime[driverRow].setStyleSheet( "QLabel{ border-radius: 10px; border-color: black; border: 5px solid black; background-color: white}" ) self.totalTime[driverRow].setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.totalTime[driverRow].setFont(self.totalFont) self.mainLayout.addWidget(self.totalTime[driverRow], driverRow, 2) self.laptime[driverRow] = driver.getLapLCD() self.laptime[driverRow].setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.mainLayout.addWidget(self.laptime[driverRow], driverRow, 4) self.bestlaptime[driverRow] = driver.getBestLapLCD() self.bestlaptime[driverRow].setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.mainLayout.addWidget(self.bestlaptime[driverRow], driverRow, 5) self.fuelbar[driverRow] = driver.getFuelBar() self.fuelbar[driverRow].setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) self.mainLayout.addWidget(self.fuelbar[driverRow], driverRow, 6) self.pits[driverRow] = driver.getPits() self.pits[driverRow].setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.mainLayout.addWidget(self.pits[driverRow], driverRow, 7) def racestart(self): self.cu.start() # self.mainLayout.itemAtPosition(1, 5).widget().setPits('Pit') # self.mainLayout.itemAtPosition(1, 5).widget().setPits('Track') def resetRMS(self): if hasattr(self, 'driverArr'): for driverObj in self.driverArr: driverObj.deleteLater() self.start = None self.driverArr = [RmsDriver(num) for num in range(1, 9)] self.clearCU() if hasattr(self, 'mainLayout'): while True: widgetToRemove = self.mainLayout.takeAt(0) if widgetToRemove == None: break widgetToRemove.widget().deleteLater() racemode = self.vLayout.takeAt(3) mainItem = self.vLayout.takeAt(2) self.vLayout.removeItem(racemode) self.vLayout.removeItem(mainItem) mainItem.deleteLater() self.vLayout.addLayout(self.buildGrid()) self.vLayout.addWidget(self.racemode) def clearCU(self): # discard remaining timer messages status = self.cu.request() while not isinstance(status, ControlUnit.Status): status = self.cu.request() self.status = status # reset cu timer self.cu.reset() def pressCode(self): print('press Code') self.cu.request(b'T8') def setFuel(self): print('set fuel') self.cu.request(b'T7') def setPace(self): print('pace car') self.cu.request(b'T1') def setSpeed(self): print('set speed') self.cu.request(b'T5') def setBrake(self): print('set brake') self.cu.request(b'T6') def changeDriver(self, driverButton, driverObj): self.driverChangeText = QInputDialog.getText( self, 'Change driver name', 'Driver Name', 0, driverButton.text().split('\n')[0]) if self.driverChangeText[1] == True: driverButton.setText(self.driverChangeText[0] + '\n' + 'Ctrl: ' + str(driverObj.CtrlNum)) driverObj.name = self.driverChangeText[0] def updateDisplay(self, binMode): if binMode != None: if binMode[2] == '1': self.fuelmode.setText('Real') elif binMode[3] == '1': self.fuelmode.setText('On') elif binMode[3] == '0': self.fuelmode.setText('Off') if binMode[1] == '1': self.pitLaneStatus.setText('Exists') else: self.pitLaneStatus.setText('Missing') if binMode[0] == '1': self.lapCounter.setText('Exists') else: self.lapCounter.setText('Missing') driversInPlay = [driver for driver in self.driverArr if driver.time] if len(driversInPlay) + 1 > self.mainLayout.rowCount(): self.addDriver() for pos, driver in enumerate(sorted(driversInPlay, key=posgetter), start=1): if pos == 1: if hasattr(self, 'leader') and self.leader != driver: print('pos change') # self.animation.start() self.leader = driver t = formattime(driver.time - self.start, True) elif driver.lapcount == self.leader.lapcount: t = '+%ss' % formattime(driver.time - self.leader.time) else: gap = self.leader.lapcount - driver.lapcount t = '+%d Lap%s' % (gap, 's' if gap != 1 else '') self.driverBtn[pos].setText(driver.name + '\n' + 'Ctrl: ' + str(driver.CtrlNum)) self.totalTime[pos].setText(t) self.lapcount[pos].display(driver.lapcount) self.laptime[pos].display(formattime(driver.lapTime)) self.bestlaptime[pos].display(formattime(driver.bestLapTime)) self.fuelbar[pos].setValue(driver.fuellevel) if driver.fuellevel > 0: self.fuelbar[pos].setStyleSheet( "QProgressBar{ color: white; background-color: black; border: 5px solid black; border-radius: 10px; text-align: center}\ QProgressBar::chunk { background: qlineargradient(x1: 1, y1: 0.5, x2: 0, y2: 0.5, stop: 0 #00AA00, stop: " + str(0.92 - (1 / (driver.fuellevel))) + " #22FF22, stop: " + str(0.921 - (1 / (driver.fuellevel))) + " #22FF22, stop: " + str(1.001 - (1 / (driver.fuellevel))) + " red, stop: 1 #550000); }") self.pits[pos].display(driver.pitcount) if hasattr(self, 'leader') and self.session.session != None: if self.session.type != None: self.racemode.setText(self.session.session + ' ' + str(self.session.amount) + ' ' + self.session.type) if self.session.type == 'Laps': if self.leader.lapcount > self.session.amount: self.racestart() self.session.saveSessionData(driversInPlay) self.clearCU() self.session.sessionOver() elif self.session.type == 'Timed': if self.leader.time - self.start > self.session.amount * 60000: self.racestart() self.session.saveSessionData(driversInPlay) self.clearCU() self.session.sessionOver() elif self.session.type == None: self.session.session = None self.showLeaderboard() def showLeaderboard(self): self.leaderBoard = LBDialog(self.session.leaderboard) self.leaderBoard.show()
class WidgetRegisterEntryList(QWidget): def __init__(self, master, cbRead, cbWrite): super().__init__(master) # Callbacks self.cb_read = cbRead self.cb_write = cbWrite # Layout self.grid = QVBoxLayout() self.grid.setSpacing(3) self.setLayout(self.grid) # Members self.entries = [] self.addresses = [] self.sizes = [] self.eeprom_size = 0 def init(self, register_map): self.entries = [] self.addresses = [] self.sizes = [] self.eeprom_size = len(register_map[1]) for i in reversed(range(self.grid.count())): item = self.grid.itemAt(i) w = item.widget() if w is not None: w.deleteLater() else: self.grid.removeItem(item) if len(register_map[1]) > 0: label_eeprom = QLabel("EEPROM Area", self) label_eeprom.setAlignment(Qt.AlignCenter) label_eeprom.setStyleSheet("QLabel { font: bold; }") self.grid.addWidget(label_eeprom) for e in register_map[1]: self._add_reg_entry(e) if len(register_map[2]) > 0: label_ram = QLabel("RAM Area", self) label_ram.setAlignment(Qt.AlignCenter) label_ram.setStyleSheet("QLabel { font: bold; }") self.grid.addWidget(label_ram) for e in register_map[2]: self._add_reg_entry(e) self.grid.addStretch(1) def read_all(self): for entry in self.entries: entry.read() def export_eeprom(self): output = [] for i in range(self.eeprom_size): output.append( (self.addresses[i], self.sizes[i], self.entries[i].get_gui_value())) return output def import_eeprom(self, value_list): i = 0 for entry in value_list: if len(entry) != 3: raise IndexError if entry[0] != self.addresses[i]: raise ValueError if entry[1] != self.sizes[i]: raise ValueError self.entries[i].set_gui_value(entry[2]) i += 1 # Wrapper to make the use of 'partial' clearer def _read(self, address, size): return self.cb_read(address, size) # Wrapper to make the use of 'partial' clearer def _write(self, address, value, size): return self.cb_write(address, size, value) def _add_reg_entry(self, reg_entry): r_cb = partial(self._read, size=reg_entry[1]) if reg_entry[3]: w_cb = partial(self._write, size=reg_entry[1]) else: w_cb = None w = WidgetRegisterEntry(self, reg_entry[0], reg_entry[4], reg_entry[5], reg_entry[2], r_cb, reg_entry[6], w_cb) self.entries.append(w) self.addresses.append(reg_entry[0]) self.sizes.append(reg_entry[1]) self.grid.addWidget(w)
class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(1000, 600) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21)) self.menubar.setObjectName("menubar") self.menu_File = QtWidgets.QMenu(self.menubar) self.menu_File.setObjectName("menu_File") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.action_Exit = QtWidgets.QAction(MainWindow) self.action_Exit.setObjectName("action_Exit") self.action_Exit.setStatusTip('Exit') self.actionOpenFile = QtWidgets.QAction(MainWindow) self.actionOpenFile.setObjectName("actionOpenFile") self.actionOpenFile.setStatusTip('Open new File') self.actionOpenDir = QtWidgets.QAction(MainWindow) self.actionOpenDir.setObjectName("actionOpenDir") self.actionOpenDir.setStatusTip('Open Directory') self.menu_File.addAction(self.actionOpenFile) self.menu_File.addAction(self.actionOpenDir) self.menu_File.addSeparator() self.menu_File.addAction(self.action_Exit) self.menubar.addAction(self.menu_File.menuAction()) self.contentsWidget = QListWidget() self.contentsWidget.setViewMode(QListView.ViewMode.IconMode) self.contentsWidget.setIconSize(QSize(140,140)) # add icon 2/6 self.contentsWidget.setMovement(QListView.Movement.Static) # add icon # self.contentsWidget.insertItem(0, 'Linked/Unlinked Bags') # add icon # self.contentsWidget.insertItem(1, 'Simulation Tools') # add icon self.contentsWidget.setMinimumWidth(160) self.contentsWidget.setMaximumWidth(160) self.contentsWidget.setSpacing(6) # add icon # self.contentsWidget.setMaximumWidth(480) self.createIcons() # add icon self.stack1 = QWidget() self.stack2 = QWidget() self.stack1UI() self.stack2UI() self.st = QStackedWidget(self.centralwidget) self.st.addWidget(self.stack1) self.st.addWidget(self.stack2) self.st.setMinimumWidth(640) self.st.setMinimumHeight(480) # print(self.size().width()) # tried to get mainwindow size hbox = QHBoxLayout(self.centralwidget) hbox.addWidget(self.contentsWidget) hbox.addWidget(self.st) # hbox.setStretch(1, 100) # need to check if this line matters 2/12 10:35 self.centralwidget.setLayout(hbox) # self.statusbar = QMainWindow.statusBar(MainWindow) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) self.contentsWidget.currentRowChanged.connect(self.display) self.actionOpenFile.triggered.connect(self.openFile) self.actionOpenDir.triggered.connect(self.openDir) self.action_Exit.triggered.connect(self.exit) # self.createBar() def createIcons(self): # add icon histIcon = QListWidgetItem(self.contentsWidget) histIcon.setIcon(QIcon("icon/hist-icon.jpg")) histIcon.setText("Bin Tracking") histIcon.setTextAlignment(Qt.AlignHCenter) histIcon.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) simuIcon = QListWidgetItem(self.contentsWidget) simuIcon.setIcon(QIcon("icon/simul-icon.png")) simuIcon.setText("Simulation") simuIcon.setTextAlignment(Qt.AlignHCenter) simuIcon.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) def createBar(self): print("in create bar") min_num, max_num = 0, 100 max_count = 0 linked_bag_list = [] try: df = self.linked['Beam Diff'].dropna() linked_bag_list = df.values.tolist() min_num = int(min(linked_bag_list)) if min_num > 0: # check if greater than 0, set to 0 min_num = 0 max_num = int(max(linked_bag_list)) except AttributeError: self.statusbar.showMessage('Data not ready') count = linked_bag_list count = [0] * (max_num + 1) # choose the largest num as length of count for num in linked_bag_list: count[int(num)] += 1 # update every number's count max_count = max(count) setBar = QBarSet('Beam Difference Occurrence') setBar.append(count) brush = QBrush(QColor(0x57B1FD)) pen = QPen(QColor(0x57B1FD)) pen.setWidth(2) setBar.setPen(pen) setBar.setBrush(brush) series = QBarSeries() series.append(setBar) chart = QChart() font = QFont() font.setPixelSize(18) chart.setTitleFont(font) chart.setTitle('Linked Bins Histogram') chart.addSeries(series) chart.setAnimationOptions(QChart.SeriesAnimations) axisX = QValueAxis() axisX.setTitleText("Attenuation Window") axisX.setRange(min_num, max_num+20) chart.setAxisX(axisX, series) axisY = QValueAxis() axisY.setTitleText("Frequency") axisY.setRange(0, max_count+20) chart.setAxisY(axisY, series) chart.legend().setVisible(True) chart.legend().setAlignment(Qt.AlignBottom) chartView = QChartView(chart) chartView.setRenderHint(QPainter.Antialiasing) # MainWindow.setCentralWidget(chartView) return chartView def createUnlinkedBar(self): max_count = 0 unlinked_bag_list = [] try: df = self.unlinked['Beam Diff'].dropna() unlinked_bag_list = df.values.tolist() except AttributeError: self.statusbar.showMessage('Data not ready') count = [0] * 4 for num in unlinked_bag_list: if -1000 <= num and num <= -51: count[0] += 1 elif -50 <= num and num <= -1: count[1] += 1 elif 151 <= num and num <= 200: count[2] += 1 elif 201 <= num: count[3] += 1 # print(count) max_count = max(count) setBar = QBarSet('Beam Difference Occurrence') setBar.append(count) series = QBarSeries() series.append(setBar) brush = QBrush(QColor(0xfdb157)) pen = QPen(QColor(0xfdb157)) pen.setWidth(2) setBar.setPen(pen) setBar.setBrush(brush) chart = QChart() font = QFont() font.setPixelSize(18) chart.setTitleFont(font) chart.setTitle('Unlinked Bins Summary') chart.addSeries(series) chart.setAnimationOptions(QChart.SeriesAnimations) labels = ['Not useful(-50 to -1000)', 'Pushed by operator(-1 to -50)', 'Slipping on belt(151 to 200)', 'Not useful 201+'] axisX = QBarCategoryAxis() axisX.append(labels) # chart.setAxisX(axisX, series) chart.addAxis(axisX, Qt.AlignBottom) # chart.ChartAreas[0].AxisX.LabelAutoFitStyle = LabelAutoFitStyle.WrodWrap series.attachAxis(axisX) axisY = QValueAxis() axisY.setRange(0, max_count+1) # chart.setAxisY(axisY, series) chart.addAxis(axisY, Qt.AlignLeft) series.attachAxis(axisY) chart.legend().setVisible(True) chart.legend().setAlignment(Qt.AlignBottom) chartView = QChartView(chart) chartView.setRenderHint(QPainter.Antialiasing) # MainWindow.setCentralWidget(chartView) return chartView def createSummaryBar(self): # self.dp.dfinal series = QPieSeries() labelfont = QFont() labelfont.setPixelSize(11) linked_bag, unlinked_bag = 0, 0 try: linked_bag = len(self.linked.index) unlinked_bag = len(self.unlinked.index) # slices.setPen(QPen(Qt.darkGreen, 2)) # slices.setBrush(QBrush(QColor(0xfdb157))) except AttributeError: self.statusbar.showMessage('Data not ready') series.append("Linked", linked_bag) series.append("Unlinked", unlinked_bag) slices = series.slices()[0] slices.setBrush(QBrush(QColor(0x57B1FD))) slices.setLabelVisible() slices.setLabel(("{0} {1:.2f}%").format("Linked", 100*slices.percentage())) slices.setLabelFont(labelfont) slices1 = series.slices()[1] slices1.setExploded() slices1.setLabelVisible() slices1.setPen(QPen(QColor(0x57B1FD), 2)) slices1.setBrush(QBrush(QColor(0xfdb157))) # slices1.setLabelPosition(QPieSlice.LabelOutside) slices1.setLabel(("{0} {1:.2f}%").format("Unlinked", 100*slices1.percentage())) slices1.setLabelFont(labelfont) # slices.setLabel(("%1%").format(100*slices.percentage(), 0, 'f', 1)) # slices.setLabelPosition(QPieSlice.LabelInsideHorizontal) chart = QChart() font = QFont() font.setPixelSize(18) chart.setTitleFont(font) chart.addSeries(series) chart.setAnimationOptions(QChart.SeriesAnimations) chart.setTitle("Total") chart.legend().hide() chartView = QChartView(chart) chartView.setRenderHint(QPainter.Antialiasing) return chartView def getCertainRangeList(self, total_time_lst): self.ready_to_plot_lst = [] self.range0To2 = [] self.range2To3 = [] self.range3To6 = [] self.range6To9 = [] self.range9To20 = [] for item in total_time_lst: if 0 < item and item <= 2: # print("in 0-3: ", item) self.ready_to_plot_lst.append(int(item)) self.range0To2.append(item) elif 2 < item and item <= 3: self.ready_to_plot_lst.append(int(item)) self.range2To3.append(item) elif 3 < item and item <= 6: # print("in 3-6: ", item) self.ready_to_plot_lst.append(int(item)) self.range3To6.append(item) elif 6 < item and item <= 9: # print("in 6-9: ", item) self.range6To9.append(item) self.ready_to_plot_lst.append(int(item)) elif 9 < item and item <= 20: self.range9To20.append(item) def onClicked(self, b): # try to add histogram radio button 2/11 12:02 # self.removeWidgets() # self.layout.addWidget(self.createBar()) if b.text() == "Histogram": print("histogram checkd!") elif b.text() == "RangeHist": print("range histogram") elif b.text() == "Pie Chart": print("pie chart") def stack1UI(self): self.flag = False self.layout = QVBoxLayout() combo = QComboBox(self.stack1) combo.addItem("Linked Bags") combo.addItem("Unlinked Bags") combo.addItem("Summary") # self.image = QtWidgets.QLabel(self.stack1) # try to do stackwidget here 2/10 10:52 # self.image.setObjectName("imageLabel") # try to do stackwidget here 2/10 10:52 # self.chartLayout = QHBoxLayout() # add chartLayout 2/13 9:16 self.layout.addWidget(combo) # self.layout.addWidget(self.image) # add stackwidget 2/10 10:52 # self.chartLayout.addWidget(self.test) self.layout.setAlignment(QtCore.Qt.AlignTop) # self.layout.addLayout(self.chartLayout) # add chartLayout 2/13 9:16 self.stack1.setLayout(self.layout) combo.activated[str].connect(self.onActivated) def stack2UI(self): self.vlayout = QVBoxLayout() hlayout = QHBoxLayout() combo1 = QComboBox(self.stack2) combo1.addItem("Distribution") combo1.addItem("Occurrence") combo1.addItem("Summary") label = QLabel() label.setText("Delay: ") self.text = QLineEdit() button = QPushButton("Go") hlayout.addWidget(combo1) hlayout.addWidget(label) hlayout.addWidget(self.text) hlayout.addWidget(button) self.slayout = QHBoxLayout() self.labelDelay = QtWidgets.QLabel(self.stack2) self.labelafterDelay = QtWidgets.QLabel(self.stack2) # try to add a paralel widget (before / after) self.labelDelay.setObjectName("result") self.labelafterDelay.setObjectName("delayResult") # try to add a paralel widget (before / after) # self.labelDelay.setText("before") # self.labelafterDelay.setText("after") # try to add a paralel widget (before / after) self.slayout.addWidget(self.labelDelay) self.slayout.addWidget(self.labelafterDelay) self.vlayout.addLayout(hlayout) self.vlayout.addLayout(self.slayout) self.stack2.setLayout(self.vlayout) button.clicked.connect(self.simulate) combo1.activated[str].connect(self.onActivated1) def afterDelayPieChart(self): series = QPieSeries() labelfont = QFont() labelfont.setPixelSize(11) total_running_after_delay, total_stopped_after_delay = 0, 0 try: total_running_after_delay = sum(self.tm.total_running_after_delay) total_stopped_after_delay = sum(self.tm.total_stopped_after_delay) # slices.setPen(QPen(Qt.darkGreen, 2)) # slices.setBrush(QBrush(QColor(0xfdb157))) except AttributeError: self.statusbar.showMessage('Data not ready') series.append("Run", total_running_after_delay) series.append("Stop", total_stopped_after_delay) # slices = QPieSlice() slices = series.slices()[0] # Run time slice slices.setBrush(QBrush(QColor(0x57B1FD))) # Blue slices.setLabelVisible() # Set label visible slices.setLabel(("{0} {1:.2f}%").format("Run time", 100*slices.percentage())) # Set percentage slices.setLabelFont(labelfont) # Set label font slices1 = series.slices()[1] # Stop time slice slices1.setExploded() # Set stop slice exploded slices1.setLabelVisible() # Set label visible slices1.setPen(QPen(QColor(0x57B1FD), 2)) # Blue slices1.setBrush(QBrush(QColor(0xA6E22E))) # Orange # slices1.setLabelPosition(QPieSlice.LabelOutside) # Set label outside slices1.setLabel(("{0} {1:.2f}%").format("Stop time", 100*slices1.percentage())) # Set percentage slices1.setLabelFont(labelfont) # Set label font chart = QChart() font = QFont() font.setPixelSize(18) chart.setTitleFont(font) chart.addSeries(series) chart.setAnimationOptions(QChart.SeriesAnimations) chart.setTitle("Total Time (after)") chart.legend().hide() chartView = QChartView(chart) chartView.setRenderHint(QPainter.Antialiasing) return chartView def afterDelay(self): # print("in after delay bar") min_num, max_num = 0, 100 max_count = 0 total_stopped_after_delay = [] count = [0] * (int(max_num) + 1) # choose the largest num as length of count try: total_stopped_after_delay = self.tm.total_stopped_after_delay max_num = max(total_stopped_after_delay) count = [0] * (int(max_num) + 1) # choose the largest num as length of count for num in total_stopped_after_delay: count[int(num)] += 1 # update every number's count max_count = max(count) except (AttributeError, ValueError): self.statusbar.showMessage('Data not ready') setBar = QBarSet('Stop Time Occurrence') setBar.append(count) brush = QBrush(QColor(0xA6E22E)) # Green pen = QPen(QColor(0xA6E22E)) # Green pen.setWidth(2) setBar.setPen(pen) setBar.setBrush(brush) series = QBarSeries() series.append(setBar) chart = QChart() font = QFont() font.setPixelSize(18) chart.setTitleFont(font) chart.setTitle('Stop time Occurrence (after)') chart.addSeries(series) chart.setAnimationOptions(QChart.SeriesAnimations) axisX = QValueAxis() axisX.setRange(min_num, max_num+20) chart.setAxisX(axisX, series) axisY = QValueAxis() axisY.setRange(0, max_count+20) chart.setAxisY(axisY, series) chart.legend().setVisible(True) chart.legend().setAlignment(Qt.AlignBottom) chartView = QChartView(chart) chartView.setRenderHint(QPainter.Antialiasing) # MainWindow.setCentralWidget(chartView) return chartView def afterDelayDistribution(self): min_num, max_num = 0, 100 max_count = 0 total_stopped_after_delay = [] count = [0] try: total_stopped_after_delay = self.tm.total_stopped_after_delay max_num = len(total_stopped_after_delay) # change max() to len(), now it's correct count = total_stopped_after_delay max_count = max(count) except (AttributeError, ValueError): self.statusbar.showMessage('Data not ready') setBar = QBarSet('stop time') setBar.append(count) brush = QBrush(QColor(0xA6E22E)) # Green pen = QPen(QColor(0xA6E22E)) # Green pen.setWidth(2) setBar.setPen(pen) setBar.setBrush(brush) series = QBarSeries() series.append(setBar) chart = QChart() font = QFont() font.setPixelSize(18) chart.setTitleFont(font) chart.setTitle('Stop time Distribution (after)') chart.addSeries(series) chart.setAnimationOptions(QChart.SeriesAnimations) axisX = QValueAxis() axisX.setRange(min_num, max_num) chart.setAxisX(axisX, series) axisY = QValueAxis() axisY.setRange(0, max_count+20) chart.setAxisY(axisY, series) chart.legend().setVisible(True) chart.legend().setAlignment(Qt.AlignBottom) chartView = QChartView(chart) chartView.setRenderHint(QPainter.Antialiasing) # MainWindow.setCentralWidget(chartView) return chartView def beforeDelayPieChart(self): series = QPieSeries() labelfont = QFont() labelfont.setPixelSize(11) total_running_time, total_stopped_time = 0, 0 try: total_running_time = sum(self.tm.total_running_time) total_stopped_time = sum(self.tm.total_stopped_time) # slices.setPen(QPen(Qt.darkGreen, 2)) # slices.setBrush(QBrush(QColor(0xfdb157))) except AttributeError: self.statusbar.showMessage('Data not ready') series.append("Run", total_running_time) series.append("Stop", total_stopped_time) slices = series.slices()[0] slices.setBrush(QBrush(QColor(0x57B1FD))) slices.setLabelVisible() slices.setLabel(("{0} {1:.2f}%").format("Run Time", 100*slices.percentage())) slices.setLabelFont(labelfont) slices1 = series.slices()[1] slices1.setExploded() slices1.setLabelVisible() slices1.setPen(QPen(QColor(0x57B1FD), 2)) slices1.setBrush(QBrush(QColor(0xfdb157))) slices1.setLabel(("{0} {1:.2f}%").format("Stop Time", 100*slices1.percentage())) slices1.setLabelFont(labelfont) chart = QChart() font = QFont() font.setPixelSize(18) chart.setTitleFont(font) chart.addSeries(series) chart.setAnimationOptions(QChart.SeriesAnimations) chart.setTitle("Total Time (before)") chart.legend().hide() chartView = QChartView(chart) chartView.setRenderHint(QPainter.Antialiasing) return chartView def beforeDelay(self): # print("in before delay bar") min_num, max_num = 0, 100 max_count = 0 total_stopped_time = [] count = [0] * (int(max_num) + 1) # choose the largest num as length of count try: total_stopped_time = self.tm.total_stopped_time max_num = max(total_stopped_time) count = [0] * (int(max_num) + 1) # choose the largest num as length of count for num in total_stopped_time: count[int(num)] += 1 # update every number's count max_count = max(count) except (AttributeError, ValueError): self.statusbar.showMessage('Data not ready') setBar = QBarSet('Stop Time Occurrence') setBar.append(count) brush = QBrush(QColor(0x57B1FD)) pen = QPen(QColor(0x57B1FD)) pen.setWidth(2) setBar.setPen(pen) setBar.setBrush(brush) series = QBarSeries() series.append(setBar) chart = QChart() font = QFont() font.setPixelSize(18) chart.setTitleFont(font) chart.setTitle('Stop time Occurrence (before)') chart.addSeries(series) chart.setAnimationOptions(QChart.SeriesAnimations) axisX = QValueAxis() axisX.setRange(min_num, max_num+20) chart.setAxisX(axisX, series) axisY = QValueAxis() axisY.setRange(0, max_count+20) chart.setAxisY(axisY, series) chart.legend().setVisible(True) chart.legend().setAlignment(Qt.AlignBottom) chartView = QChartView(chart) chartView.setRenderHint(QPainter.Antialiasing) # MainWindow.setCentralWidget(chartView) return chartView def beforeDelayDistribution(self): min_num, max_num = 0, 100 max_count = 0 total_stopped_time = [] count = [0] try: total_stopped_time = self.tm.total_stopped_time max_num = len(total_stopped_time) # change from max() to len() 2/12 11:11 count = total_stopped_time max_count = max(count) except (AttributeError, ValueError): self.statusbar.showMessage('Data not ready') setBar = QBarSet('stop time') setBar.append(count) brush = QBrush(QColor(0x57B1FD)) pen = QPen(QColor(0x57B1FD)) pen.setWidth(2) setBar.setPen(pen) setBar.setBrush(brush) series = QBarSeries() series.append(setBar) chart = QChart() font = QFont() font.setPixelSize(18) chart.setTitleFont(font) chart.setTitle('Stop time Distribution (before)') chart.addSeries(series) chart.setAnimationOptions(QChart.SeriesAnimations) axisX = QValueAxis() axisX.setRange(min_num, max_num) chart.setAxisX(axisX, series) axisY = QValueAxis() axisY.setRange(0, max_count+20) chart.setAxisY(axisY, series) chart.legend().setVisible(True) chart.legend().setAlignment(Qt.AlignBottom) chartView = QChartView(chart) chartView.setRenderHint(QPainter.Antialiasing) # MainWindow.setCentralWidget(chartView) return chartView def display(self, i): self.st.setCurrentIndex(i) # mainMenu components def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.menu_File.setTitle(_translate("MainWindow", "&File")) self.action_Exit.setText(_translate("MainWindow", "&Exit")) self.actionOpenFile.setText(_translate("MainWindow", "&Open File/Files")) self.actionOpenDir.setText(_translate("MainWindow", "&Open Folder")) def removeWidgets(self): for i in reversed(range(1,self.layout.count())): # change 2 to 3 if add another widget(radio) self.layout.itemAt(i).widget().setParent(None) def removeWidgets1(self): for i in reversed(range(1,self.slayout.count())): self.slayout.itemAt(i).widget().setParent(None) def removeWidgets2(self): for i in reversed(range(0,self.chartLayout.count())): self.chartLayout.itemAt(i).widget().setParent(None) self.layout.removeItem(self.chartLayout) def onActivated1(self, text): if text == 'Distribution': self.removeWidgets1() self.slayout.addWidget(self.beforeDelayDistribution(), QtCore.Qt.AlignCenter) self.slayout.addWidget(self.afterDelayDistribution(), QtCore.Qt.AlignCenter) elif text == 'Occurrence': self.removeWidgets1() self.slayout.addWidget(self.beforeDelay(), QtCore.Qt.AlignCenter) self.slayout.addWidget(self.afterDelay(), QtCore.Qt.AlignCenter) elif text == 'Summary': self.removeWidgets1() self.slayout.addWidget(self.beforeDelayPieChart(), QtCore.Qt.AlignCenter) self.slayout.addWidget(self.afterDelayPieChart(), QtCore.Qt.AlignCenter) # combo box items def onActivated(self, text): # print(text) if text == 'Linked Bags': if self.flag: self.removeWidgets2() else: self.removeWidgets() # self.layout.addLayout(self.chartLayout) # add chartLayout 2/13 9:16 # self.chartLayout.addWidget(self.createBar()) # self.removeWidgets2() # now it works for summary bar with label # self.layout.removeItem(self.slayout) self.layout.addWidget(self.createBar()) self.flag = False elif text == 'Unlinked Bags': if self.flag: self.removeWidgets2() else: self.removeWidgets() print("before unlinked bag",self.layout.count()) self.layout.addWidget(self.createUnlinkedBar()) print("after unlinked bag",self.layout.count()) self.flag = False elif text == 'Summary': if self.flag: self.removeWidgets2() else: self.removeWidgets() self.chartLayout = QHBoxLayout() self.summaryLabel = QtWidgets.QLabel() # self.summaryLabel.setText("tettddddddddddddddddddtt") self.setSummaryLabel() self.chartLayout.addWidget(self.createSummaryBar()) self.chartLayout.addWidget(self.summaryLabel) print("before add layout",self.layout.count()) self.layout.addLayout(self.chartLayout) print("after add layout",self.layout.count()) self.flag = True def setSummaryLabel(self): try: total = len(self.dfinal.index) # total number of scanned bags linked = len(self.linked.index) # total number of linked bags unlinked = total - linked # total number of unlinked bags co_count = len(self.cut_oversized.index) # cut or oversized bags. co_percentage = (co_count/total) * 100 # cut or oversized percentage co_unlinked_percentage = (co_count/unlinked) * 100 percentage = (unlinked/(total)) * 100 # percentage for unlinked bags slipping = len(self.slipping.index) s_percentage = (slipping/total) * 100 pushed = len(self.pushed.index) p_percentage = (pushed/total) * 100 self.summaryLabel.setText('Bin Tracking Infomation:\nTotal Bins: {0}\nTotal Linked Bins: {1}\nTotal Unlinked Bins: {2}\nPercent of Unlinked Bins: {3:.2f} % \ \nSlipping Bins: {4}\nPercent of Slipping Bins: {5:.2f} % \nPushed Bins: {6}\nPercent of Pushed Bins: {7:.2f} %\n'.format(total, linked, unlinked, \ percentage, slipping, s_percentage, pushed, p_percentage)) self.summaryLabel.setText(self.summaryLabel.text() + "\nUnlinked Bin Tracking: \nCut/oversized object: {0}\nPercentage (unlinked): {1:.2f} %\ \nPercentage (total): {2:.2f} %".format(co_count, co_unlinked_percentage, co_percentage)) self.summaryLabel.setFont(QtGui.QFont("Times", 12, QtGui.QFont.Bold)) except AttributeError: self.statusbar.showMessage("Data not processed") # not shown due to covered by top message def simulate(self): # print(self.text.text()) if bool(re.match('^[0-9]+$',self.text.text())): try: self.tm = TimeMeasure('runtime_.txt', int(self.text.text())) # change variables to global value 2/11 2:06 self.tm.getDuration() self.tm.runList("") self.tm.stopList("") self.tm.runListDelay("") self.tm.stopListDelay("") self.total_time = self.tm.org_finish_time - self.tm.org_start_time self.statusbar.showMessage("Done") except FileNotFoundError: self.statusbar.showMessage("Data not ready") # self.labelDelay.setText("Simulation Result:\n") # self.labelDelay.setText(self.labelDelay.text() + "\n---------------Before delay---------------\n\n") # self.labelDelay.setText(self.labelDelay.text() + "Run Time total: {0:d} Sum: {1:f} seconds Percentage: {2:.2f}%\n".format(len(self.tm.total_running_time), sum(self.tm.total_running_time), sum(self.tm.total_running_time)/self.total_time * 100)) # self.labelDelay.setText(self.labelDelay.text() + "Stop Time total: {0:d} Sum: {1:f} seconds Percentage: {2:.2f}%\n".format(len(self.tm.total_stopped_time), sum(self.tm.total_stopped_time), sum(self.tm.total_stopped_time)/self.total_time * 100)) # self.labelDelay.setText(self.labelDelay.text() + "Total: {0:f} seconds Percentage: {1:.2f}%\n".format(self.total_time, sum(self.tm.total_running_time)/self.total_time * 100 + sum(self.tm.total_stopped_time)/self.total_time * 100)) # # print("run:",len(tm.total_running_time), "sum:", sum(tm.total_running_time),"percentage:",sum(tm.total_running_time)/total_time * 100) # # print("stop:",len(tm.total_stopped_time), "sum:", sum(tm.total_stopped_time),"percentage:",sum(tm.total_stopped_time)/total_time * 100) # # print("total:",total_time, sum(tm.total_running_time)/total_time * 100 + sum(tm.total_stopped_time)/total_time * 100) # # print("\n---------------Add delay 2 seconds---------------\n") # self.labelDelay.setText(self.labelDelay.text() + "\n---------------Add delay 2 seconds---------------\n\n") # self.total_time_after_delay = self.tm.delay_finish_time - self.tm.delay_start_time # self.labelDelay.setText(self.labelDelay.text() + "Run time after delay: {0:d} Sum: {1:f} seconds Percentage: {2:.2f}%\n".format(len(self.tm.total_running_after_delay), sum(self.tm.total_running_after_delay), sum(self.tm.total_running_after_delay) / self.total_time_after_delay * 100)) # self.labelDelay.setText(self.labelDelay.text() + "Stop time after delay: {0:d} Sum: {1:f} seconds Percentage: {2:.2f}%\n".format(len(self.tm.total_stopped_after_delay), sum(self.tm.total_stopped_after_delay), sum(self.tm.total_stopped_after_delay) / self.total_time_after_delay * 100)) # self.labelDelay.setText(self.labelDelay.text() + "Total: {0:f} seconds Percentage: {1:.2f}%\n".format(self.total_time_after_delay, sum(self.tm.total_running_after_delay) / self.total_time_after_delay * 100 + sum(self.tm.total_stopped_after_delay) / self.total_time_after_delay * 100)) # # print("run after delay:", len(tm.total_running_after_delay), "sum:", sum(tm.total_running_after_delay), "percentage:",sum(tm.total_running_after_delay) / total_time_after_delay * 100) # # print("stop after delay:",len(tm.total_stopped_after_delay), "sum:", sum(tm.total_stopped_after_delay), "percentage:",sum(tm.total_stopped_after_delay) / total_time_after_delay * 100) # # print("total:",total_time_after_delay, sum(tm.total_running_after_delay) / total_time_after_delay * 100 + sum(tm.total_stopped_after_delay) / total_time_after_delay * 100) # self.tm.fakestopList() # self.delaylist = self.tm.getCertainRangeList(self.tm.fake_total_stopped_time) # # print("\nSummary:") # # print("Before delay XRAY_MIN / total: 100% ----> After delay XRAY_MIN / total: {0:.2f}%".format((len(tm.fake_total_stopped_time)-len(delaylist))/len(tm.fake_total_stopped_time)*100)) # # print("Before delay total time: 100% ----> After delay total time: {0:.2f}%".format(total_time_after_delay/total_time*100)) # self.labelDelay.setText(self.labelDelay.text() + "\nSummary:") # self.labelDelay.setText(self.labelDelay.text() + "Before delay total time: 100% ----> After delay total time: {0:.2f}%\n".format(self.total_time_after_delay/self.total_time*100)) # self.labelDelay.setText(self.labelDelay.text() + "Before delay XRAY_MIN / total: 100% ----> After delay XRAY_MIN / total: {0:.2f}%".format((len(self.tm.fake_total_stopped_time)-len(self.delaylist))/len(self.tm.fake_total_stopped_time)*100)) # self.labelDelay.setFont(QtGui.QFont("Times", 12, QtGui.QFont.Bold)) # self.labelDelay.setAlignment(Qt.AlignTop)#HCenter) # self.removeWidgets1() # self.slayout.addWidget(self.beforeDelayDistribution(), QtCore.Qt.AlignCenter) # self.slayout.addWidget(self.afterDelayDistribution(), QtCore.Qt.AlignCenter) # display summary label def setSummary(self): self.image.setPixmap(QtGui.QPixmap('his.png')) # display linked bags histogram def setLinkedHistogram(self): # pixmap = pixmap.tmaled(self.label.width(), self.label.height(), QtCore.Qt.KeepAspectRatio, QtCore.Qt.FastTransformation) # make image unclear self.image.setPixmap(QtGui.QPixmap('link.png')) # display unlinked bags histogram def setUnlinkedHistogram(self): self.image.setPixmap(QtGui.QPixmap('unlink.png')) # display time stopped histogram def setTimeStoppedHistogram(self): self.image.setPixmap(QtGui.QPixmap('stop_time_distribution.png')) # display time running histogram def setTimeRunningHistogram(self): self.image.setPixmap(QtGui.QPixmap('running_time_distribution')) # open file dialog def openFile(self): filenames, _ = QtWidgets.QFileDialog.getOpenFileNames(None,"QFileDialog.getOpenFileNames()", "","All Files (*);;Log Files (*.log);;") if filenames: print("inside:",filenames) print("fdsfs", filenames) illegal = False suf = 'log' # test for single .txt first, need to modify for final version if len(filenames) != 0: for f in filenames: # check all files are illegal in here suffix = f[f.rfind('.')+1:] if suffix != suf: print("Illegal selection") illegal = True print(illegal) if illegal: self.showdialog(illegal, True); else: # self.statusbar.showMessage('Processing Files...') start_time = timeit.default_timer() pp = PreProc(filenames) # pass files into PreProc class elapsed = timeit.default_timer() - start_time print("time cost preProc:", elapsed) # self.statusbar.showMessage('Analyzing datas...') start_time1 = timeit.default_timer() dp = DataProc() # pass the prepared data into DataProc class elapsed1 = timeit.default_timer() - start_time1 print("time cost dataProc:", elapsed1) self.linked = dp.linked self.unlinked = dp.unlinked self.dfinal = dp.dfinal self.cut_oversized = dp.cut_oversized self.slipping = dp.slipping self.pushed = dp.pushed self.statusbar.showMessage('Done') # if self.flag: # self.removeWidgets2() # else: # self.removeWidgets() # self.layout.addWidget(self.createBar()) # open directory dialog def openDir(self): dialog = QtWidgets.QFileDialog() dialog.setFileMode(QFileDialog.DirectoryOnly) dic_file = [] if dialog.exec_(): # == QtGui.QDialog.Accepted: dic_file = dialog.selectedFiles() print("openDir: (dic_file) ", dic_file) log_file = [] has_log = False suf = 'log' if dic_file: for f in os.listdir(dic_file[0]): suffix = f[f.rfind('.')+1:] name = f[:f.rfind('.')] print(name) if suffix == suf: has_log = True if "AnalogicStandaloneType" in name:# if match AnalogicStandaloneType*.log, append to log_file log_file += dic_file[0]+"/"+f, print(has_log, log_file) if not has_log: self.showdialog(False, has_log) if len(log_file) == 0 and has_log: self.showdialog(False, False) if len(log_file) != 0: start_time = timeit.default_timer() pp = PreProc(log_file) # pass files into PreProc class elapsed = timeit.default_timer() - start_time print("time cost preProc:", elapsed) start_time1 = timeit.default_timer() dp = DataProc() # pass the prepared data into DataProc class elapsed1 = timeit.default_timer() - start_time1 print("time cost dataProc:", elapsed1) self.linked = dp.linked self.unlinked = dp.unlinked self.dfinal = dp.dfinal self.cut_oversized = dp.cut_oversized self.slipping = dp.slipping self.pushed = dp.pushed self.statusbar.showMessage('Done') # if self.flag: # self.removeWidgets2() # else: # self.removeWidgets() # self.layout.addWidget(self.createBar()) # pop up warning window def showdialog(self, illegal_file, has_log): msg = QMessageBox() msg.setIcon(QMessageBox.Critical) if not has_log: msg.setText("No log files found.") if illegal_file: print("in illegal") msg.setText("Invalid log files detected.") msg.setWindowTitle("Something's wrong") # msg.setGeometry(200, 200, 300, 400) # need to change if need this line msg.setStandardButtons(QMessageBox.Ok) retval = msg.exec_() def exit(self): sys.exit(app.exec_())
class GUI_HyperParameters(QWidget): def __init__(self, gui_play, cur_hps=None): super().__init__() self.gui_play = gui_play self.name_inpt_dict = {} self.structured_hyperparams = {} self.substructered_items = [] self.reference_hps = hp.AgentsHyperparameters() if cur_hps is None: self.hp = hp.AgentsHyperparameters() else: self.hp = cur_hps self.initUI() def initUI(self): self.resize(800, 600) self.center() self.setWindowTitle('Icon') self.setWindowIcon(QIcon('test.png')) self.v_main = QVBoxLayout() idx = 0 for attr in dir(self.hp): attr_name = str(attr) if not callable(getattr(self.hp, attr)) and not attr.startswith("__"): idx += 1 hbox = QHBoxLayout() lab = QLabel(attr_name, self) hbox.addWidget(lab) the_attrib = getattr(self.hp, attr_name) if isinstance(the_attrib, dict): inp = QComboBox() inp.addItems(the_attrib.keys()) self.structured_hyperparams[attr_name] = (idx, the_attrib) inp.activated.connect(self.activated_combobox) hbox.addWidget(inp) elif isinstance(the_attrib, list): list_key = the_attrib[0] reference = getattr(self.reference_hps, attr_name) if isinstance(reference, dict): if list_key in reference: reference[list_key] = the_attrib[1] inp = QComboBox() inp.addItems(reference.keys()) self.structured_hyperparams[attr_name] = ( idx, reference) inp.activated.connect(self.activated_combobox) hbox.addWidget(inp) else: inp = None else: inp = None else: inp = QLineEdit(str(the_attrib), self) hbox.addWidget(inp) if inp is not None: self.name_inpt_dict[attr_name] = inp self.v_main.addLayout(hbox) self.add_sub_inputs() self.start_btn = QPushButton("start", self) self.start_btn.clicked.connect(self.train_click) self.v_main.addWidget(self.start_btn) self.setLayout(self.v_main) self.show() def add_sub_inputs(self): items_per_row = 3 for sub_struct in self.substructered_items: for i in range(self.v_main.count()): layout_item = self.v_main.itemAt(i) if isinstance( layout_item, QHBoxLayout) and layout_item.layout() == sub_struct: clear_layout(layout_item) self.v_main.removeItem(layout_item) self.substructered_items.clear() for struct_hyper_key in self.structured_hyperparams.keys(): combo_box = self.name_inpt_dict[struct_hyper_key] new_items_dict = self.structured_hyperparams[struct_hyper_key][1][ combo_box.currentText()] new_item_keys = list(new_items_dict.keys()) for i in range(0, len(new_item_keys), items_per_row): h_outer = QHBoxLayout() for j in range(items_per_row): if i + j < len(new_item_keys): cur_key = new_item_keys[i + j] hbox = QHBoxLayout() hbox.addWidget(QLabel(cur_key, self)) inp = QLineEdit(str(new_items_dict[cur_key]), self) hbox.addWidget(inp) self.name_inpt_dict[cur_key] = inp h_outer.addLayout(hbox) self.substructered_items.append(h_outer) self.v_main.insertLayout( self.structured_hyperparams[struct_hyper_key][0], h_outer) def activated_combobox(self): print("connected") self.add_sub_inputs() def closeEvent(self, event): event.accept() def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) @pyqtSlot() def train_click(self): for attr in dir(self.hp): if not callable(getattr(self.hp, attr)) and not attr.startswith("__"): attr_nam = str(attr) if isinstance(self.name_inpt_dict[attr_nam], QComboBox): combo_box = self.name_inpt_dict[attr_nam] selected_item = combo_box.currentText() items_dict = self.structured_hyperparams[attr_nam][1][ selected_item] for cur_key in items_dict.keys(): value = get_int_or_else_float_from_str( self.name_inpt_dict[cur_key].text()) if value is not None: items_dict[cur_key] = value print(items_dict) setattr(self.hp, attr_nam, (selected_item, items_dict)) print(getattr(self.hp, attr_nam)) else: value = get_int_or_else_float_from_str( self.name_inpt_dict[attr_nam].text()) if value is not None: setattr(self.hp, attr_nam, value) self.gui_play.new_handler_and_start(self.hp) self.hide()
class Main(Widget, QWidget): def __init__(self, widget_manager, info): # init Widget.__init__(self, widget_manager, info) QWidget.__init__(self) self.conf = {} self.lang = info.lang self.settings_win = None # setup window with open(os.path.join(RES, 'timer', 'style.css'), encoding='utf-8') as file: self.setStyleSheet(file.read()) # setup menu self.menu = QMenu(self) start_action = self.menu.addAction(QIcon(PLAY), self.lang['start']) start_action.triggered.connect(self._start) pause_action = self.menu.addAction(QIcon(PAUSE), self.lang['pause']) pause_action.triggered.connect(self._pause) reset_action = self.menu.addAction(QIcon(STOP), self.lang['reset']) reset_action.triggered.connect(self._reset) # all setups self.timer = QTimer(self) self.timer.timeout.connect(self._tick) self._last = 0 self.list = [] self.shows = {} self.v_box = QVBoxLayout(self) self.v_box.setContentsMargins(0, 0, 0, 0) self.v_box.setSpacing(1) self.setLayout(self.v_box) # constants self.TICK = os.path.join(RES, 'timer', 'tick.ogg') self.TACK = os.path.join(RES, 'timer', 'tack.ogg') self.ALARM = os.path.join(RES, 'timer', 'alarm.ogg') @try_except() def _add_timer(self, h=0, m=0, s=0, enabled=True): lcd = QLCDNumber(self), QLCDNumber(self), QLCDNumber(self) for i in range(3): lcd[i].display((h, m, s)[i]) lcd[i].setDigitCount(2) lcd[i].setSegmentStyle(QLCDNumber.Flat) lcd[i].setEnabled(enabled) h_box = QHBoxLayout() h_box.setContentsMargins(0, 0, 0, 0) h_box.setSpacing(0) h_box.addWidget(lcd[0]) h_box.addWidget(lcd[1]) h_box.addWidget(lcd[2]) self.v_box.addLayout(h_box) # ------ 0 ------------ 1 -------- 2 -------- 3 -------- 4 --- # (lcd, lcd, lcd), QHBoxLayout, is past, is enabled, (h, m, s) self.list.append((lcd, h_box, True, enabled, (h, m, s))) def _delete_timer(self, index): self.v_box.removeItem(self.list[index][1]) del self.list[index] self._reset() # render bug not fixed :( @try_except() def _turn_enabled(self, index, enabled): item = self.list[index] for lcd in item[0]: lcd.setEnabled(enabled) self.list[index] = item[0], item[1], item[2], enabled, item[4] @try_except() def _tick(self): ticked = False sec = math.floor(time.time() - self._last) # amplify precision if not sec: return for n in range(len(self.list)): item = self.list[n] if not item[3]: continue for i in range(int(sec)): if not item[0][2].value(): if item[0][1].value() or item[0][0].value(): item[0][2].display(59) if item[0][1].value(): item[0][1].display(item[0][1].value() - 1) else: item[0][1].display(59) item[0][0].display(item[0][0].value() - 1) else: item[0][2].display(item[0][2].value() - 1) if not item[0][2].value() and not item[0][1].value() \ and not item[0][0].value() and item[2]: self._alarm(n) self.list[n] = item[0], item[1], False, item[3], item[4] else: ticked = True if ticked: self._last += 1 # amplify precision self._sec_sound() else: self.timer.stop() @try_except() def _play(self, file, volume): # strange, big memory leak and crash player = QMediaPlayer(self) player.setMedia(QMediaContent(QUrl.fromLocalFile(file))) player.setVolume(volume) player.play() @try_except() def _sec_sound(self): if not strtobool(self.conf['seconds']): return volume = int(self.conf['seconds_volume']) if int(math.floor(time.time())) % 2 == 0: self._play(self.TICK, volume) else: self._play(self.TACK, volume) @try_except() def _alarm(self, index): if strtobool(self.conf['alarm']): self._play(self.ALARM, int(self.conf['alarm_volume'])) if strtobool(self.conf['alert']): self._show_timeout(index) if strtobool(self.conf['notify']): self.widget_manager.main_gui.main.tray.showMessage( self.lang['notify_title'], self.lang['notify_mess'].format(self.get_timer_text(index)), QSystemTrayIcon.Information, int(self.conf['notify_msec'])) @try_except() def _show_timeout(self, index): if index in self.shows: return self.shows[index] = Timeout(self, self.get_timer_text(index), index) @try_except() def _start(self, checked): self._last = time.time() self.timer.start(int(self.conf['tick_ms'])) # amplify precision @try_except() def _pause(self, checked): self.timer.stop() @try_except() def _reset(self, checked=False): self.timer.stop() for timer in self.list: self.v_box.removeItem(timer[1]) self._save_timers() self.list.clear() self._load_timers() self.layout().update() def _load_timers(self): if ('timers' not in self.conf) or self.conf['timers'] == '[]' or \ not self.conf['timers']: self._add_timer() return for data in json.loads(self.conf['timers']): self._add_timer(*data) def _save_timers(self): if not self.conf: return timers = [] for timer in self.list: timers.append((timer[4][0], timer[4][1], timer[4][2], timer[3])) self.conf['timers'] = json.dumps(timers) def _setup_conf(self): self.conf = self.widget_manager.get_config(self.info.NAME) if 'alarm' not in self.conf: self.conf['alarm'] = 'True' if 'alert' not in self.conf: self.conf['alert'] = 'True' if 'notify' not in self.conf: self.conf['notify'] = 'True' if 'notify_msec' not in self.conf: self.conf['notify_msec'] = str(10000) if 'seconds' not in self.conf: self.conf['seconds'] = 'False' if 'alarm_volume' not in self.conf: self.conf['alarm_volume'] = str(100) if 'seconds_volume' not in self.conf: self.conf['seconds_volume'] = str(100) if 'tick_ms' not in self.conf: self.conf['tick_ms'] = str(10) def place(self): self._setup_conf() self._load_timers() def boot(self): self._setup_conf() self._load_timers() def unload(self): self._save_timers() @try_except() def show_settings(self): self.settings_win = Settings(self) @try_except() def mousePressEvent(self, event): if event.button() == Qt.RightButton: self.menu.exec(event.globalPos()) @try_except() def mouseDoubleClickEvent(self, event): index = int(event.pos().y() / (self.height() / (len(self.list)))) self._turn_enabled(index, not self.list[index][3]) def get_timer_text(self, index) -> str: timer = str(self.list[index][4][0]) + ':' timer += str(self.list[index][4][1]) + ':' timer += str(self.list[index][4][2]) return timer
class HomeScreen(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("Home Screen") self.resize(550, 461) self.setStyleSheet(Hariku_Style.get_window_stylesheet()) self.centralWidget = QWidget() self.setCentralWidget(self.centralWidget) self.setupUI() def setupUI(self): self.setWindowIcon(Hariku_Style.getIcon()) self.centralwidget = QWidget(self) self.setFocus() self.gridLayout = QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.topcenter_layout = QHBoxLayout() spacerItem = QSpacerItem(25, 20, QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.topcenter_layout.addItem(spacerItem) self.monthFilter = QDateEdit(self.centralwidget) self.monthFilter.setCurrentSection(QDateTimeEdit.MonthSection) self.monthFilter.setButtonSymbols(QSpinBox.NoButtons) self.monthFilter.setDate(datetime.now()) self.monthFilter.setDisplayFormat("MMMM/yyyy") self.monthFilter.setFont(Hariku_Style.get_font(10)) self.monthFilter.setStyleSheet(Hariku_Style.get_dateedit_stylesheet()) self.monthFilter.dateChanged.connect(self.filterDiaryByMonth) self.topcenter_layout.addWidget(self.monthFilter) self.showAllBtn = QPushButton("Remove Filter", self.centralwidget) self.showAllBtn.setFont(Hariku_Style.get_font(8)) self.showAllBtn.clicked.connect(self.getDiaries) self.showAllBtn.setStyleSheet( Hariku_Style.get_moodBtn_stylesheet("rgb(38, 160, 173)", "rgb(8, 102, 112)")) self.topcenter_layout.addWidget(self.showAllBtn) spacerItem1 = QSpacerItem(25, 20, QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.topcenter_layout.addItem(spacerItem1) self.gridLayout.addLayout(self.topcenter_layout, 1, 0, 1, 1) self.bottomLayout = QHBoxLayout() spacerItem2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.bottomLayout.addItem(spacerItem2) self.createBtn = QPushButton("+ Add New Diary", self.centralwidget) self.createBtn.setFont(Hariku_Style.get_font(10)) self.createBtn.clicked.connect(self.addNewDiary) self.createBtn.setStyleSheet( Hariku_Style.get_moodBtn_stylesheet("rgb(40, 186, 130)", "rgb(207, 207, 188)")) self.bottomLayout.addWidget(self.createBtn) self.gridLayout.addLayout(self.bottomLayout, 4, 0, 1, 1) self.contentScrollArea = QScrollArea(self.centralwidget) self.contentScrollArea.setEnabled(True) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.contentScrollArea.sizePolicy().hasHeightForWidth()) self.contentScrollArea.setSizePolicy(sizePolicy) self.contentScrollArea.setStyleSheet( Hariku_Style.get_scrollarea_stylesheet()) self.contentScrollArea.setWidgetResizable(True) self.contentScrollArea.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 487, 321)) self.scrollAreaLayout = QVBoxLayout(self.scrollAreaWidgetContents) self.getDiaries() self.contentScrollArea.setWidget(self.scrollAreaWidgetContents) self.gridLayout.addWidget(self.contentScrollArea, 2, 0, 1, 1) self.judul = QLabel("\nWelcome Home:)\n", self) self.judul.setFont(Hariku_Style.get_font(18)) self.judul.setAlignment(QtCore.Qt.AlignCenter) self.gridLayout.addWidget(self.judul, 0, 0, 1, 1) self.setCentralWidget(self.centralwidget) def addNewDiary(self): dialog = DiaryScreen(self) dialog.show() self.hide() def clearScrollAreaLayout(self): # delete the diaries currently showind for i in reversed(range(self.scrollAreaLayout.count())): try: self.scrollAreaLayout.itemAt(i).widget().setParent(None) except AttributeError: self.scrollAreaLayout.removeItem( self.scrollAreaLayout.itemAt(i)) def filterDiaryByMonth(self): self.clearScrollAreaLayout() year = self.monthFilter.date().year() month = self.monthFilter.date().month() diaries = getDiaryByMonth(year, month) for i, diary in enumerate(diaries): self.diaryItem = QWidget(self.scrollAreaWidgetContents) sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) sizePolicy.setHeightForWidth( self.diaryItem.sizePolicy().hasHeightForWidth()) self.diaryItem.setSizePolicy(sizePolicy) self.diaryItem.setMinimumSize(QtCore.QSize(0, 50)) self.diaryItem.setStyleSheet( "background-color: rgba(227, 217, 163, 100%);\nborder-radius : 10px;" ) self.diaryItem.setObjectName("diaryItem") self.itemLayout = QGridLayout(self.diaryItem) self.contentDateLayout = QVBoxLayout() self.contentDateLayout.setObjectName("contentDateLayout") self.content = QLabel(self.truncateString(diary.content), self.diaryItem) self.content.setFont(Hariku_Style.get_font(10)) self.contentDateLayout.addWidget(self.content) self.date = QLabel( diary.date.strftime("%d %B %Y") + diary.time.strftime(" %I:%M %p"), self.diaryItem) self.date.setFont(Hariku_Style.get_font(8)) self.contentDateLayout.addWidget(self.date) self.itemLayout.addLayout(self.contentDateLayout, 0, 0, 1, 1) self.buttons.append(i) self.buttons[i] = [ QPushButton("⋗", self.diaryItem), QPushButton("×", self.diaryItem) ] self.buttons[i][0].clicked.connect( lambda checked, i=diary.diary_id: self.viewDiaryById(i)) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.buttons[i][0].sizePolicy().hasHeightForWidth()) self.buttons[i][0].setSizePolicy(sizePolicy) self.buttons[i][0].setFont(Hariku_Style.get_font(9)) self.buttons[i][0].setStyleSheet( Hariku_Style.get_moodBtn_stylesheet("rgb(145, 133, 63)", "rgb(235, 224, 157)")) self.itemLayout.addWidget(self.buttons[i][0], 0, 1, 1, 1) # self.deleteBtn = QPushButton("×", self.diaryItem) self.buttons[i][1].clicked.connect( lambda checked, i=diary.diary_id: self.deleteDiaryById(i)) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.buttons[i][1].sizePolicy().hasHeightForWidth()) self.buttons[i][1].setSizePolicy(sizePolicy) self.buttons[i][1].setFont(Hariku_Style.get_font(9)) self.buttons[i][1].setStyleSheet( Hariku_Style.get_moodBtn_stylesheet("rgb(145, 63, 63)", "rgb(235, 157, 157)")) self.itemLayout.addWidget(self.buttons[i][1], 0, 2, 1, 1) self.scrollAreaLayout.addWidget(self.diaryItem, alignment=QtCore.Qt.AlignTop) spacerItem2 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) self.scrollAreaLayout.addItem(spacerItem2) def getDiaries(self): diaries = getAllDiaries() self.monthFilter.setDate(datetime.now()) self.clearScrollAreaLayout() self.buttons = [] for i, diary in enumerate(diaries): self.diaryItem = QWidget(self.scrollAreaWidgetContents) sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) sizePolicy.setHeightForWidth( self.diaryItem.sizePolicy().hasHeightForWidth()) self.diaryItem.setSizePolicy(sizePolicy) self.diaryItem.setMinimumSize(QtCore.QSize(0, 50)) self.diaryItem.setStyleSheet( "background-color: rgba(227, 217, 163, 100%);\nborder-radius : 10px;" ) self.diaryItem.setObjectName("diaryItem") self.itemLayout = QGridLayout(self.diaryItem) self.contentDateLayout = QVBoxLayout() self.contentDateLayout.setObjectName("contentDateLayout") self.content = QLabel(self.truncateString(diary.content), self.diaryItem) self.content.setFont(Hariku_Style.get_font(10)) self.contentDateLayout.addWidget(self.content) self.date = QLabel( diary.date.strftime("%d %B %Y") + diary.time.strftime(" %I:%M %p"), self.diaryItem) self.date.setFont(Hariku_Style.get_font(8)) self.contentDateLayout.addWidget(self.date) self.itemLayout.addLayout(self.contentDateLayout, 0, 0, 1, 1) self.buttons.append(i) self.buttons[i] = [ QPushButton("⋗", self.diaryItem), QPushButton("×", self.diaryItem) ] self.buttons[i][0].clicked.connect( lambda checked, i=diary.diary_id: self.viewDiaryById(i)) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.buttons[i][0].sizePolicy().hasHeightForWidth()) self.buttons[i][0].setSizePolicy(sizePolicy) self.buttons[i][0].setFont(Hariku_Style.get_font(9)) self.buttons[i][0].setStyleSheet( Hariku_Style.get_moodBtn_stylesheet("rgb(145, 133, 63)", "rgb(235, 224, 157)")) self.itemLayout.addWidget(self.buttons[i][0], 0, 1, 1, 1) # self.deleteBtn = QPushButton("×", self.diaryItem) self.buttons[i][1].clicked.connect( lambda checked, i=diary.diary_id: self.deleteDiaryById(i)) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.buttons[i][1].sizePolicy().hasHeightForWidth()) self.buttons[i][1].setSizePolicy(sizePolicy) self.buttons[i][1].setFont(Hariku_Style.get_font(9)) self.buttons[i][1].setStyleSheet( Hariku_Style.get_moodBtn_stylesheet("rgb(145, 63, 63)", "rgb(235, 157, 157)")) self.itemLayout.addWidget(self.buttons[i][1], 0, 2, 1, 1) self.scrollAreaLayout.addWidget(self.diaryItem, alignment=QtCore.Qt.AlignTop) spacerItem2 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) self.scrollAreaLayout.addItem(spacerItem2) def truncateString(self, string): try: string = string.replace('\n', ' ') return string[:45] + '...' except IndexError: return string def viewDiaryById(self, id): dialog = DiaryScreen(self, edit=False, id=id) dialog.show() self.hide() def deleteDiaryById(self, id): deleteDiaryById(id) self.clearScrollAreaLayout() self.getDiaries()
class MainWindow(QMainWindow): def __init__(self): super().__init__() # Create menu bar self.CreateMenuBar() # Create the drawing canvas self.canvas = DrawCanvas() self.TransformationImage = TransformationImage(self.canvas.Draw) # Create the main window widget self.widget = QWidget() self.DrawWidget = QWidget() self.TransformationWidget = QWidget() # Create both main modes layouts self.TransformationLayout = QVBoxLayout() self.DrawLayout = QVBoxLayout() # Set default transformation mode to False self.isTransformationMode = False # Add draw modes buttons to draw layout self.DrawPalette = QHBoxLayout() self.AddModesButtons(self.DrawPalette) self.DrawLayout.addLayout(self.DrawPalette) # Add window transformations modes buttons to transformation layout self.TransformationsPalette = QHBoxLayout() self.AddTransformationsButtons(self.TransformationsPalette) self.TransformationLayout.addLayout(self.TransformationsPalette) # Add the drawing canvas to both layouts self.DrawLayout.addWidget(self.canvas) # Add window colors buttons to draw layout self.colorPalette = QHBoxLayout() self.AddColorButtons(self.colorPalette) self.DrawLayout.addLayout(self.colorPalette) # Create the main window widgets self.DrawWidget.setLayout(self.DrawLayout) self.TransformationWidget.setLayout(self.TransformationLayout) # Create centeral widget to hold our widget self.centralwidget = QWidget(self) # Insert our wigets to stackwidget self.stackedWidget = QStackedWidget(self.centralwidget) self.stackedWidget.addWidget(self.DrawWidget) self.stackedWidget.addWidget(self.TransformationWidget) # Set the window and default widget as DrawWidget self.setCentralWidget(self.centralwidget) # Set size and prevent from user change size self.setFixedSize(1300, 830) # Build colors buttons def AddColorButtons(self, palette): # for each color type make a button in this color for color in COLORS: button = QPaletteButton(color) # Connect the button to setColor function button.pressed.connect( lambda color=color: self.canvas.setColor(color)) # Add the buttun to layout widget palette.addWidget(button) # Update button text and change widht def WidhtSelected(self, width): widthNum = int(width.split(' ')[0]) self.canvas.setWidth(widthNum) self.widthBtn.setText(str(self.canvas.currentWidth) + 'px') # Create pen width menu def AddWidthMenu(self): menu = QMenu() # Get row on menu for each PEN_WIDTHS for width in PEN_WIDTHS: # Connect menu option to setWidth function menu.addAction(width, lambda width=width: self.WidhtSelected(width)) menu.addSeparator() # Return menu return menu # Build modes buttons def AddModesButtons(self, palette): # For each mode type make a button in this mode for mode in MODES: button = ModesButton(mode) if mode == 'Pen Width': button.setMenu(self.AddWidthMenu()) button.setText(str(self.canvas.currentWidth) + 'px') self.widthBtn = button elif mode == 'Transformation': # Connect Transformation button to FlipTransformationMode button.pressed.connect(self.FlipTransformationMode) elif mode == 'Undo': # Connect undo button to undo function button.pressed.connect(self.canvas.undo) elif mode == 'Export': # Connect undo button to undo function button.pressed.connect(self.ExportToText) else: # Connect the button to setMode function button.pressed.connect( lambda mode=mode: self.canvas.setMode(mode)) # Add the buttun to layout widget palette.addWidget(button) # Delete all drawing def RefrshCanvas(self): # Paint all pixels back to black self.canvas.painter.fillRect(0, 0, self.canvas.width, self.canvas.height, QColor('#000000')) # Update canvas self.canvas.update() # Set mode to Scale and call function def Scale(self, mode): self.canvas.setMode('Scale') # Refresh the canvas from drawing self.RefrshCanvas() # Call Scale function self.TransformationImage.Scaling(self.canvas.painter, mode) # Update canvas self.canvas.update() # Set mode to Move and call function def Move(self, mode): self.canvas.setMode('Move') # Refresh the canvas from drawing self.RefrshCanvas() # Call Move function if mode == 'U': x, y = 0, -20 elif mode == 'R': x, y = 20, 0 elif mode == 'L': x, y = -20, 0 elif mode == 'D': x, y = 0, 20 self.TransformationImage.Move(self.canvas.painter, x, y) self.canvas.update() # Set mode to Rotate and call function def Rotate(self, mode): self.canvas.setMode('Rotate') # Refresh the canvas from drawing self.RefrshCanvas() # Call Rotate function if mode == 'L': r = -5 elif mode == 'R': r = 5 self.TransformationImage.Rotation(self.canvas.painter, r) self.canvas.update() # Set mode to Mirror and call function def Mirror(self): self.canvas.setMode('Mirror') # Refresh the canvas from drawing self.RefrshCanvas() # Call Mirror function self.TransformationImage.Mirroring(self.canvas.painter) self.canvas.update() # Set mode to Shearing and call function def Shearing(self): self.canvas.setMode('Shearing') def AddTransformationsButtons(self, palette): # For each transformation type make a button in this mode for mode in TRANS_MODES: button = ModesButton(mode) button.setFixedWidth(50) # Connect Draw button to FlipTransformationMode if mode == 'Draw': button.pressed.connect(self.FlipTransformationMode) # Connect scale button to scale function elif mode == "+": button.pressed.connect(lambda mode=mode: self.Scale('+')) elif mode == "-": button.pressed.connect(lambda mode=mode: self.Scale('-')) # Connect move button to move function elif mode == '↑': button.pressed.connect(lambda mode=mode: self.Move('U')) elif mode == '←': button.pressed.connect(lambda mode=mode: self.Move('L')) elif mode == '→': button.pressed.connect(lambda mode=mode: self.Move('R')) elif mode == '↓': button.pressed.connect(lambda mode=mode: self.Move('D')) # Connect rotate button to rotate function '⟲', '⟳' elif mode == '⟲': button.pressed.connect(lambda mode=mode: self.Rotate('L')) elif mode == '⟳': button.pressed.connect(lambda mode=mode: self.Rotate('R')) # Connect mirror button to mirror function elif mode == 'Mirror': button.pressed.connect(self.Mirror) button.setFixedWidth(100) # Connect mirror button to mirror function elif mode == 'Shearing': button.pressed.connect(self.Shearing) button.setFixedWidth(100) elif mode == 'Load': button.pressed.connect(self.LoadFromText) button.setFixedWidth(100) # Add the buttun to layout widget palette.addWidget(button) # Flip between draw mode and transformation mode def FlipTransformationMode(self): # Flip current transformation mode self.isTransformationMode = not self.isTransformationMode # If isTransformationMode == ture , replace to TransformationWidget if self.isTransformationMode: # Add current canvas self.TransformationLayout.addWidget(self.canvas) # Set mode to scale mode self.canvas.currentMode = TRANS_MODES[0] # Clean all but image self.RefrshCanvas() self.TransformationImage.DrawFromImage( self.canvas.painter, self.TransformationImage.currentImage) # Replace widget self.stackedWidget.setCurrentIndex(1) # Else replace to DrawWidget else: # Remove color layout self.DrawLayout.removeItem(self.colorPalette) # Add current canvas self.DrawLayout.addWidget(self.canvas) # Add new color layout self.colorPalette = QHBoxLayout() self.AddColorButtons(self.colorPalette) self.DrawLayout.addLayout(self.colorPalette) # Set mode to draw pixel self.canvas.currentMode = MODES[1] # Replace widget self.stackedWidget.setCurrentIndex(0) # Create top menue bar def CreateMenuBar(self): menuBar = self.menuBar() fileMenu = menuBar.addMenu("File") # Creating save action saveAction = QAction("Save", self) # Setting save action shortcut saveAction.setShortcut(QKeySequence("Ctrl+S")) # Adding save action fileMenu.addAction(saveAction) saveAction.triggered.connect(self.SaveToImage) exportAction = QAction("Export ('txt')", self) # Setting export action shortcut exportAction.setShortcut(QKeySequence("Ctrl+E")) # Adding export action fileMenu.addAction(exportAction) exportAction.triggered.connect(self.ExportToText) loadAction = QAction("Load ('txt')", self) # Setting export action shortcut loadAction.setShortcut(QKeySequence("Ctrl+L")) # Adding export action fileMenu.addAction(loadAction) loadAction.triggered.connect(self.LoadFromText) clearAction = QAction("Clear", self) # Setting clear action shortcut clearAction.setShortcut(QKeySequence("Ctrl+C")) # Adding clear action fileMenu.addAction(clearAction) clearAction.triggered.connect(self.ClearCanvas) # Save the canvas as png def SaveToImage(self): # Select file to save to from file selection dialog filePath, _ = QFileDialog.getSaveFileName( self, "Save Image", "", "PNG(*.png);;JPEG(*.jpg *.jpeg);;All Files(*.*) ") if filePath == "": return # Get the pixmap from canvas pix = self.canvas.pixmap() # Make QImage from pixmap image = pix.toImage() # Save QImage as png image.save(filePath, 'png') # Export image to text file def ExportToText(self): # Open file selection dialog options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName, _ = QFileDialog.getOpenFileName( self, "QFileDialog.getOpenFileName()", "", options=options) # Make sure text file has selected. if not return if fileName.split('.')[-1] != 'txt': # Print error message self.ShowErrorMessage('Can\'t export to a none .txt file format') return # Open text file to write textFile = open(fileName, "w") # Init string actionString = '' # Save current transformation image to cuurentDraw self.TransformationImage.DrawFromImage( self.canvas.painter, self.TransformationImage.currentImage, True) # Create string for action in self.canvas.Draw.CurrentDraw: actionString += action # Remove last '\n' from string actionString = actionString[:-1] # Write string to selected file textFile.write(actionString) # Close selected file textFile.close() def LoadFromText(self): # Open file selection dialog options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName, _ = QFileDialog.getOpenFileName( self, "QFileDialog.getOpenFileName()", "", options=options) # Make sure text file has selected. if not return if fileName.split('.')[-1] != 'txt': # Print error message self.ShowErrorMessage('Please select an .txt file') return if not self.TransformationImage.DrawFromFile(self.canvas.painter, fileName): self.ShowErrorMessage('Text file no in the rigth format') self.canvas.update() # Clear canvas drawing def ClearCanvas(self): # paint all pixels back to black self.canvas.painter.fillRect(0, 0, self.canvas.width, self.canvas.height, QColor('#000000')) # Delete actions array self.canvas.Draw.CurrentDraw = [] # Delete current transfotmation image self.TransformationImage.currentImage = [] self.TransformationImage.originImage = [] # Update canvas self.canvas.update() # Popup error message def ShowErrorMessage(self, message): msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText(message) msg.setWindowTitle("Error") msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) retval = msg.exec_() msg.show()
class SecondForm(QWidget): def __init__(self, creator): super().__init__() self.creator = creator self.mode = True self.setWindowTitle( f'Добавляем запись в {creator.comboBox.currentText()}') self.main_layout = QVBoxLayout(self) self.number_of_inputs = len(HEADERS[creator.comboBox.currentText()]) self.hbox_layouts = [] self.labels = [] self.inputs = [] self.add_change_bttn = QPushButton(self) self.add_change_bttn.setText('Добавить') self.add_change_bttn.clicked.connect(self.add_change) self.main_layout.addWidget(self.add_change_bttn) self.result = [] self.setLayout(self.main_layout) # обработчик нажатия на клавиши "добавить и изменить" def add_change(self): con = sqlite3.connect('coefficients.sqlite') cur = con.cursor() table_name = self.creator.comboBox.currentText() self.number_of_inputs = len( HEADERS[self.creator.comboBox.currentText()]) if self.mode: request = f'INSERT INTO {table_name} (' + \ ', '.join(HEADERS[table_name]) + \ ') VALUES ( ' + \ ', '.join([i.text() for i in self.inputs]) + \ ')' cur.execute(request).fetchall() else: request = f'UPDATE {table_name} SET ' + \ ', '.join([f'{HEADERS[table_name][i]} = {self.inputs[i].text()}' for i in range(1, self.number_of_inputs)]) + ' WHERE ' + \ f'id = {self.inputs[0].text()}' + ';' cur.execute(request).fetchall() con.commit() con.close() self.creator.update_table() self.close() # функция очистки формы def clear_form(self): for i in self.labels: i.deleteLater() self.labels = [] for i in self.inputs: i.deleteLater() self.inputs = [] for i in self.hbox_layouts: self.main_layout.removeItem(i) i.deleteLater() self.hbox_layouts = [] # функция для построения формы в зависимости от изменяемой таблицы def add_widgets(self): self.number_of_inputs = len( HEADERS[self.creator.comboBox.currentText()]) for i in range(self.number_of_inputs): self.hbox_layouts.append(QHBoxLayout(self)) self.labels.append(QLabel(self)) self.labels[-1].setText( HEADERS[self.creator.comboBox.currentText()][i]) self.hbox_layouts[-1].addWidget(self.labels[-1]) self.inputs.append(QLineEdit(self)) self.hbox_layouts[-1].addWidget(self.inputs[-1]) self.main_layout.addLayout(self.hbox_layouts[-1]) if not self.mode: row = self.creator.tableWidget.currentRow() self.inputs[-1].setText( self.creator.tableWidget.item(row, i).text()) if i == 0: self.inputs[-1].setEnabled(False) if self.mode: self.setWindowTitle( f'Добавляем запись в {self.creator.comboBox.currentText()}') self.add_change_bttn.setText('Добавить') else: self.setWindowTitle( f'Изменяем запись из {self.creator.comboBox.currentText()}') self.add_change_bttn.setText('Изменить')
class Ui_MainWindow(object): widthSlot = 280 def setupUi(self, MainWindow): self.MainWindow = MainWindow MainWindow.setObjectName("MainWindow") MainWindow.setFixedSize(315, 600) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.calendarWidget = QtWidgets.QCalendarWidget(self.centralwidget) self.calendarWidget.setGeometry(QtCore.QRect(0, 370, 312, 183)) self.calendarWidget.setObjectName("calendarWidget") self.tableWidget = QtWidgets.QTableWidget(self.centralwidget) self.tableWidget.setGeometry(QtCore.QRect(0, 0, 321, 371)) font = QtGui.QFont() font.setPointSize(6) self.tableWidget.setFont(font) #self.tableWidget.setAutoScroll(False) #self.tableWidget.setAutoScrollMargin(7) self.tableWidget.setObjectName("tableWidget") self.tableWidget.setColumnCount(1) self.tableWidget.setRowCount(14) for i in range(self.tableWidget.rowCount()): item = QtWidgets.QTableWidgetItem() self.tableWidget.setVerticalHeaderItem(i, item) item = QtWidgets.QTableWidgetItem() item.setText("событие") self.tableWidget.setHorizontalHeaderItem(0, item) self.tableWidget.horizontalHeader().setDefaultSectionSize(280) self.tableWidget.horizontalHeader().setMinimumSectionSize(10) self.tableWidget.verticalHeader().setDefaultSectionSize(25) self.tableWidget.itemSelectionChanged.connect(self.show_form_add_event) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 319, 21)) self.menubar.setObjectName("menubar") self.menu = QtWidgets.QMenu(self.menubar) self.menu.setObjectName("menu") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.actionAddHand = QtWidgets.QAction(MainWindow) self.actionAddHand.setObjectName("actionAddHand") self.actionAddText = QtWidgets.QAction(MainWindow) self.actionAddText.setObjectName("actionAddText") self.actionAddHand.triggered.connect(self.show_form_add_event) self.action_3 = QtWidgets.QAction(MainWindow) self.action_3.setObjectName("action_3") self.menu.addAction(self.actionAddHand) self.menu.addAction(self.actionAddText) self.menu.addAction(self.action_3) self.menubar.addAction(self.menu.menuAction()) # фрейм для отображения событий self.panelEvents = QVBoxLayout(self) self.panelEvents.setContentsMargins(0, 0, 0, 0) self.panelEvents self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) #Frame для событий втечении дня frame = Event_Frame(self, self.tableWidget) frame.setLayout(self.panelEvents) # # # ширина слота в одину минуту self.oneMinSlot = (325 - 66) / (10 * 60) def show_form_add_event(self): time = self.tableWidget.currentRow() + 9 date = self.calendarWidget.selectedDate() print(date, time) #print(item) # передать дату и время self.form = form_add_event_UI.Ui_Dialog(date, time, self.calendar) self.form.show() def new_event(self, event): oneEventFrame = QFrame() heightSlot = event.duration * self.oneMinSlot #oneEventFrame.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)) #oneEventFrame.resize(Ui_MainWindow.widthSlot, heightSlot) oneEventFrame.setFixedHeight(heightSlot) oneEventFrame.setContentsMargins(0, 0, 0, 0) oneEventFrame.setStyleSheet("background-color: rgb(2, 116, 205); border-bottom: 1px solid rgb(128, 128, 255);") #color = QtGui.QColor(233, 10, 150) oneEventLayout = QHBoxLayout() oneEventLayout.setContentsMargins(0, 0, 0, 0) oneEventLayout.setObjectName("oneEventLayout") oneEventFrame.setLayout(oneEventLayout) oneEventLayout.setSpacing(0) labelNameEvent = QLabel() labelNameEvent.setToolTipDuration(10) labelNameEvent.setObjectName("labelNameEvent") #labelNameEvent.setText(event.time + " " + event.name) labelNameEvent.setAutoFillBackground(True) labelNameEvent.setFixedHeight(heightSlot) if event.link is not None: link = f'<a href="{event.link}">event.time + " " + event.name</a>' else: link = event.time + " " + event.name print(link) labelNameEvent.setText(link) labelNameEvent.setOpenExternalLinks(True) labelNameEvent.setStyleSheet("color: white;") sheet = "a { text-decoration: underline; color: white }" #labelNameEvent.setDefaultStyleSheet(sheet) #labelNameEvent.resize(Ui_MainWindow.widthSlot, oneEventFrame.height()) oneEventLayout.addWidget(labelNameEvent) print(event.link) if event.link is not None: labelLinkImg = QLabel(link) labelLinkImg.setOpenExternalLinks(True) labelLinkImg.setMouseTracking(False) labelLinkImg.setLayoutDirection(QtCore.Qt.RightToLeft) labelLinkImg.setText("") labelLinkImg.setPixmap(QtGui.QPixmap("linkk.png")) labelLinkImg.setCursor(QCursor(QtCore.Qt.PointingHandCursor)) #self.label_img.setOpenExternalLinks(True) #self.label_img.setObjectName("label_img") oneEventLayout.addWidget(labelLinkImg) return oneEventFrame def clearLayoutEvent(self, eventLayout): frame_temp = eventLayout.widget().findChildren(type(QLabel())) print(f"Удалить событие {frame_temp[0].text()}") frame_temp[0].deleteLater() if len(frame_temp) > 1: frame_temp[1].deleteLater() eventLayout.widget().deleteLater() def clearPanelEvents(self): print(f"Удалить {self.panelEvents.count()} слотов") while self.panelEvents.count(): child = self.panelEvents.takeAt(0) if isinstance(child, QtWidgets.QWidgetItem): self.clearLayoutEvent(child) self.panelEvents.removeItem(child) print(type(child)) def add_events(self, events): self.clearPanelEvents() print(f"Добавить {len(events)} событий") if len(events) == 0: return #9:00 - это начало таблицы времен begin_event = schedule_class.Event("", "", time="09:00", duration=0) for i in range(len(events)): self.add_space_widget(begin_event, events[i]) event_widget = self.new_event(events[i]) self.panelEvents.addWidget(event_widget) begin_event = events[i] self.panelEvents.setSpacing(0) end_event = schedule_class.Event("", "", time="22:00", duration=0) self.add_space_widget(begin_event, end_event) def add_space_widget(self, begin_event, end_event): dt = schedule_class.Event.time_interval(begin_event, end_event) heightSlotSpace = int(dt * self.oneMinSlot) spacerItem = QSpacerItem(20, heightSlotSpace) self.panelEvents.addSpacerItem(spacerItem) #print(dt, "пустота = ",heightSlotSpace) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "Личный секретарь")) item = self.tableWidget.verticalHeaderItem(0) item.setText(_translate("MainWindow", "время")) for i in range(1, self.tableWidget.rowCount()): item = self.tableWidget.verticalHeaderItem(i) item.setText(_translate("MainWindow", str(8+i)+":00")) self.menu.setTitle(_translate("MainWindow", "Добавить событие")) self.actionAddHand.setText(_translate("MainWindow", "Руками")) self.actionAddText.setText(_translate("MainWindow", "Из текста")) self.action_3.setText(_translate("MainWindow", "Из календаря"))