def on_point_toggle(self, item: QtWidgets.QTreeWidgetItem, column: int) -> None: """ Callback for toggling point selection Adds/removes points to background removal queue Args: item (QtWidgets.QTreeWidgetItme): toggled widget item column (int): mandatory unused argument in signal """ if item.childCount() == 0: # a bit inefficient here (e.g dynamic programming could help) treepath = '' node = item while node is not None: treepath = '/' + node.text(0) + treepath node = node.parent() # remove prepended '/' treepath = treepath[1:] index = self.pointPlotSelect.findText(treepath) if index < 0 and item.checkState(0): self.pointPlotSelect.addItem(treepath) elif index >= 0 and not item.checkState(0): self.pointPlotSelect.removeItem(index) else: for child in [ item.child(index) for index in range(item.childCount()) ]: child.setCheckState(0, item.checkState(0))
def _update_checkboxes(self, item: QTreeWidgetItem, column: int): if column != 0: return new_check_state = item.checkState(0) self._set_check_state_to_tree(item, new_check_state) while True: item = item.parent() if item is None: break has_checked_children = False has_partially_checked_children = False has_unchecked_children = False for i in range(item.childCount()): state = item.child(i).checkState(0) if state == Qt.Checked: has_checked_children = True elif state == Qt.PartiallyChecked: has_partially_checked_children = True else: has_unchecked_children = True if not has_partially_checked_children and \ not has_unchecked_children: new_state = Qt.Checked elif has_checked_children or has_partially_checked_children: new_state = Qt.PartiallyChecked else: new_state = Qt.Unchecked item.setCheckState(0, new_state) self._update_selection_label()
def _update_checkboxes(self, item: QTreeWidgetItem, column: int): if column != 0: return new_check_state = item.checkState(0) self._set_check_state_to_tree(item, new_check_state) while True: item = item.parent() if item is None: break has_checked_children = False has_partially_checked_children = False has_unchecked_children = False for i in range(item.childCount()): state = item.child(i).checkState(0) if state == Qt.Checked: has_checked_children = True elif state == Qt.PartiallyChecked: has_partially_checked_children = True else: has_unchecked_children = True if not has_partially_checked_children and not has_unchecked_children: new_state = Qt.Checked elif has_checked_children or has_partially_checked_children: new_state = Qt.PartiallyChecked else: new_state = Qt.Unchecked item.setCheckState(0, new_state) self._update_selection_label()
def move_item(self, item: QTreeWidgetItem, favorite: bool): """ Move an time to or from the favorites tree. """ if favorite: tree = self.tab2.options self.settings.user_options['favorites'].remove(item.data(0, DISPLAY_NAME_SLOT)) else: tree = self.tab2.favorites self.settings.user_options['favorites'].append(item.data(0, DISPLAY_NAME_SLOT)) self.tab2.enable_favorites(bool(self.settings.user_options['favorites'])) tree.blockSignals(True) tree.addTopLevelItem(item) self.tab2.options.update_size() self.tab2.favorites.update_size() self.file_handler.save_settings(self.settings.settings_data) if item.checkState(0) == Qt.Checked: item.setExpanded(True) else: item.setExpanded(False) tree.blockSignals(False)
def parameter_updater(self, item: QTreeWidgetItem, col=None, save=True): """Handles updating the options for a parameter.""" if 'Custom' != self.tab1.profile_dropdown.currentText(): self.tab1.profile_dropdown.addItem('Custom') self.tab1.profile_dropdown.setCurrentText('Custom') self.settings.user_options['current_profile'] = '' if item.data(0, LEVEL_SLOT) == 0: if item.data(0, DATA_SLOT) in self.settings.need_parameters: result = self.alert_message('Warning!', 'This parameter needs an option!', 'There are no options!\n' 'Would you make one?', True) if result == QMessageBox.Yes: success = self.add_option(item) if not success: item.treeWidget().blockSignals(True) item.setCheckState(0, Qt.Unchecked) item.treeWidget().blockSignals(False) item.treeWidget().check_dependency(item) else: item.treeWidget().blockSignals(True) item.setCheckState(0, Qt.Unchecked) item.treeWidget().blockSignals(False) item.treeWidget().check_dependency(item) if item.checkState(0) == Qt.Checked: self.settings[item.data(0, DATA_SLOT)]['state'] = True if item.data(0, DATA_SLOT) == 'Download location': for i in range(item.childCount()): self.parameter_updater(item.child(i), save=False) else: self.settings[item.data(0, DATA_SLOT)]['state'] = False if item.data(0, DATA_SLOT) == 'Download location': self.tab2.download_lineedit.setText(path_shortener(self.local_dl_path)) self.tab2.download_lineedit.setToolTip(self.local_dl_path) elif item.data(0, LEVEL_SLOT) == 1: # Settings['Settings'][Name of setting]['active option']] = index of child self.settings[item.parent().data(0, DATA_SLOT)]['active option'] = item.data(0, INDEX_SLOT) if item.parent().data(0, DATA_SLOT) == 'Download location': if item.checkState(0) == Qt.Checked: self.tab2.download_lineedit.setText(item.data(0, DISPLAY_NAME_SLOT)) self.tab2.download_lineedit.setToolTip(item.data(0, DATA_SLOT)) if save: self.file_handler.save_settings(self.settings.settings_data)
def resizer(self, item: QTreeWidgetItem): # print('Child count', item.childCount()) if item.checkState(0): if self.height() + 15 * item.childCount() < ParameterTree.max_size: self.setFixedHeight(self.height() + 15 * item.childCount()) # print('Expanding') else: self.update_size()
def resizer(self, item: QTreeWidgetItem): """Handles resize changes when an parameters options are expanded/collapsed.""" # print('Child count', item.childCount()) if item.checkState(0): if self.height() + 15 * item.childCount() < ParameterTree.max_size: self.setFixedHeight(self.height() + 15 * item.childCount()) # print('Expanding') else: self.update_size()
def check_dependency(self, item: QTreeWidgetItem): """ Looks for mentioned dependents, and enables/disables those depending on checkstate. :param item: changed item from QTreeWidget (paramTree) :type item: QTreeWidget """ if item.data(0, 33) == 0 and item.data(0, 37): for i in item.data(0, 37): if item.checkState(0) == Qt.Unchecked: self.blockSignals(True) i.setDisabled(True) i.setExpanded(False) self.blockSignals(False) i.setCheckState(0, Qt.Unchecked) else: self.blockSignals(True) i.setDisabled(False) self.blockSignals(False)
class Demo(QWidget): def __init__(self): super(Demo, self).__init__() self.resize(500, 300) self.label = QLabel('No Click') # 1 self.tree = QTreeWidget(self) # 2 self.tree.setColumnCount(2) self.tree.setHeaderLabels(['Install Components', 'Test']) self.tree.itemClicked.connect(self.change_func) self.preview = QTreeWidgetItem(self.tree) # 3 self.preview.setText(0, 'Preview') # self.preview = QTreeWidgetItem() # self.preview.setText(0, 'Preview') # self.tree.addTopLevelItem(self.preview) self.qt5112 = QTreeWidgetItem() # 4 self.qt5112.setText(0, 'Qt 5.11.2 snapshot') self.qt5112.setCheckState(0, Qt.Unchecked) self.preview.addChild(self.qt5112) choice_list = ['macOS', 'Android x86', 'Android ARMv7', 'Sources', 'iOS'] self.item_list = [] for i, c in enumerate(choice_list): # 5 item = QTreeWidgetItem(self.qt5112) item.setText(0, c) item.setCheckState(0, Qt.Unchecked) self.item_list.append(item) self.test_item = QTreeWidgetItem(self.qt5112) # 6 self.test_item.setText(0, 'test1') self.test_item.setText(1, 'test2') self.tree.expandAll() # 7 self.h_layout = QHBoxLayout() self.h_layout.addWidget(self.tree) self.h_layout.addWidget(self.label) self.setLayout(self.h_layout) def change_func(self, item, column): self.label.setText(item.text(column)) # 8 print(item.text(column)) print(column) if item == self.qt5112: # 9 if self.qt5112.checkState(0) == Qt.Checked: [x.setCheckState(0, Qt.Checked) for x in self.item_list] else: [x.setCheckState(0, Qt.Unchecked) for x in self.item_list] else: # 10 check_count = 0 for x in self.item_list: if x.checkState(0) == Qt.Checked: check_count += 1 if check_count == 5: self.qt5112.setCheckState(0, Qt.Checked) elif 0 < check_count < 5: self.qt5112.setCheckState(0, Qt.PartiallyChecked) else: self.qt5112.setCheckState(0, Qt.Unchecked)
def expand_options(self, item: QTreeWidgetItem): """Handles if the options should show, depends on checkstate.""" if item.checkState(0) == Qt.Checked: item.setExpanded(True) else: item.setExpanded(False)
class TempReaderApp(QMainWindow, Ui_MainWindow): def __init__(self): QMainWindow.__init__(self) Ui_MainWindow.__init__(self) self.setupUi(self) self.initUI() logFile = "Logs" + os.sep + "TempReaderApp.log" logging.basicConfig( level=logging.DEBUG, format= '%(asctime)s - %(funcName)s - Line %(lineno)d - %(levelname)s: %(message)s', datefmt='%m-%d-%Y %I:%M:%S %p', filename=logFile, filemode='a') handler = RotatingFileHandler(logFile, maxBytes=5 * 1024 * 1024, backupCount=1, encoding=None, delay=0) logging.getLogger().addHandler(handler) logging.debug("Temperature app initialized") def initUI(self): font = QFont() font.setPointSize(12) self.center() self.setFixedSize(self.size()) self.setWindowFlags(QtCore.Qt.FramelessWindowHint) self.setWindowIcon(QtGui.QIcon("Icons" + os.sep + "Thermometer.png")) self.webView.setEnabled(False) self.webViewTable.setEnabled(False) self.plotTabLbl.setText("Select file to load.") self.plotTabLbl.setVisible(True) self.tableTabLbl.setText("Select file to load.") self.tableTabLbl.setVisible(True) self.loadBtn.clicked.connect(self.ProcessData) self.resetBtn.clicked.connect(self.Reset) self.createPDFBtn.clicked.connect(self.CreatePDF) self.exitBtn.clicked.connect(self.Exit) self.imageGLbl.setPixmap( QtGui.QPixmap("Icons" + os.sep + "whitegear.png")) self.imageFLbl.setPixmap(QtGui.QPixmap("Icons" + os.sep + "file.png")) self.imageCLbl.setPixmap( QtGui.QPixmap("Icons" + os.sep + "scatterplot.png")) self.browser = QTreeWidgetItem(self.treeWidget) self.browser.setFlags(self.browser.flags() | Qt.ItemIsUserCheckable) self.browser.setText(0, "Open Browser") self.browser.setCheckState(0, Qt.Unchecked) self.browser.setFont(0, font) self.sav_img = QTreeWidgetItem(self.treeWidget) self.sav_img.setFlags(self.sav_img.flags() | Qt.ItemIsUserCheckable) self.sav_img.setText(0, "Save Images") self.sav_img.setCheckState(0, Qt.Unchecked) self.sav_img.setFont(0, font) self.webViewTable.page().mainFrame().setScrollBarPolicy( Qt.Horizontal, Qt.ScrollBarAlwaysOff) self.webViewTable.page().mainFrame().setScrollBarPolicy( Qt.Vertical, Qt.ScrollBarAlwaysOff) self.webViewTable.setEnabled(False) self.treeWidget.setVerticalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) self.treeWidget.setStyleSheet(""" QTreeWidget:item:disabled { color: #A0A0A0; } """) self.tabWidget.setCurrentIndex(0) self.miniBtn.clicked.connect(self.miniScreen) def center(self): qr = self.frameGeometry() cp = QtWidgets.QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def miniScreen(self): self.setWindowState(Qt.WindowMinimized) def LoadFile(self): logging.debug("Loading temperature file") self.CleanPlot() self.fname = QFileDialog.getOpenFileName(self, 'Select file', '/home', 'Temp File (8500_RCTT.json)') self.fileEdit.setText(self.fname[0]) if not self.fname[0]: logging.warning("Temperature file selection cancelled") return None logging.info("Filename: {0}".format(self.fname[0])) return self.fname[0] def ProcessData(self): file = self.LoadFile() print("test") self.tableTabLbl.setText("Loading file, please wait.") self.tableTabLbl.setVisible(True) self.plotTabLbl.setText("Loading file, please wait.") self.plotTabLbl.setVisible(True) QApplication.processEvents() if not file: logging.debug("File not selected") return logging.debug("Processing data") days, high, low, temps, status, sn, times = self.ReadData() if not all([days, high, low, temps, status, sn, times]): logging.error( "Could not process data from temperature file, list is None") return None self.CreatePlot(days, temps, high, low, status, sn, times) def ReadData(self): logging.debug("Begin reading temperature data") temps = [] days = [] times = [] status = [] sn = [] high = [] low = [] try: with open(self.fname[0]) as file: data = json.load(file) for item in data["Readings"]: temps.append(item["AvgTemp"]) days.append("{0}-{1}-{2}".format(item["Date"][5:7], item["Date"][8:], item["Date"][0:4])) high.append(item["HighRange"]) low.append(item["LowRange"]) times.append(item["Time"]) status.append(item["Status"]) sn.append(item["SN"]) return days, high, low, temps, status, sn, times except Exception as ex: MessageBox("Error opening file {0}".format(ex)) logging.error("Exception occurred reading data: {0}".format(ex)) return None, None, None, None, None, None, None def CleanPlot(self): logging.debug("clean plots on the UI") self.webView.setVisible(False) self.webViewTable.setVisible(False) self.webView.setEnabled(False) self.webViewTable.setEnabled(False) self.plotTabLbl.setText("Select file to load.") self.plotTabLbl.setVisible(True) self.tableTabLbl.setText("Select file to load.") self.tableTabLbl.setVisible(True) def CreatePlot(self, days, temps, high, low, status, sn, times): logging.debug("Creating plot of temperature data") degree = u"\u00b0" # upper = [high[0]] * len(days) # lower = [low[0]] * len(days) self.openbrowser = True if self.browser.checkState(0) == 2 else False self.saveFiles = True if self.sav_img.checkState(0) == 2 else False # image = 'png' img_plot_filename = 'img_TempReadingsPlot.png' img_table_filename = 'img_TempReadingsTable.png' # output to static HTML file output_file("temp_plot.html") tools = ["box_select", "hover", "reset"] # create a new plot p = figure(plot_height=700, plot_width=1000, tools=tools, x_axis_label='Days', x_minor_ticks=len(days), y_axis_label='Temperature ({0}C)'.format(degree), x_axis_type="datetime", toolbar_location="right", title="All Temperature Readings") p_filtered = figure(plot_height=700, plot_width=1000, tools=tools, x_axis_label='Days', x_minor_ticks=len(days), y_axis_label='Temperature ({0}C)'.format(degree), x_axis_type="datetime", toolbar_location="right", title="Out of Limit Temperature Readings") from datetime import datetime daysF = None try: daysF = [ datetime(int(x[6:]), int(x[0:2]), int(x[3:5])) for x in days ] except Exception as ex: logging.warning( "Could not convert to date time object: {0}".format(ex)) MessageBox("Error encountered processing data: {0}".format(ex)) source = ColumnDataSource( data={ 'Day': daysF, # python datetime object as X axis 'Temp': temps, 'Day_str': days, # string of datetime for display in tooltip 'High': high, 'Low': low, 'Status': status }) # p.line(days, upper, legend="Upper Limit", line_width=3) # p.line(days, lower, legend="Lower Limit", line_width=3) filter_points = [] for i, item in enumerate(temps): if item < low[i] or item > high[i]: filter_points.append(i) view = CDSView(source=source, filters=[IndexFilter(filter_points)]) p_filtered.circle('Day', 'Temp', source=source, legend="Readings", line_width=3, hover_color="green", alpha=0.4, size=11, view=view) # p.annulus(x=days, y=temps, color="#7FC97F", # inner_radius=0.2, outer_radius=0.5) p_filtered.title.align = "center" p_filtered.title.text_color = "navy" p_filtered.title.text_font_size = "20px" p_filtered.title.text_font_style = "bold" p_filtered.xaxis[0].ticker.desired_num_ticks = len(days) p_filtered.legend.visible = False p_filtered.select_one(HoverTool).tooltips = [('Date', '@Day_str'), ('Temp', '@Temp'), ('High', '@High'), ('Low', '@Low'), ('Status', '@Status')] p.circle('Day', 'Temp', source=source, legend="Readings", line_width=3, hover_color="green", alpha=0.4, size=11) # p.annulus(x=days, y=temps, color="#7FC97F", # inner_radius=0.2, outer_radius=0.5) p.title.align = "center" p.title.text_color = "navy" p.title.text_font_size = "20px" p.title.text_font_style = "bold" p.xaxis[0].ticker.desired_num_ticks = len(days) p.legend.visible = False p.select_one(HoverTool).tooltips = [('Date', '@Day_str'), ('Temp', '@Temp'), ('High', '@High'), ('Low', '@Low'), ('Status', '@Status')] if filter_points: save(column(p, p_filtered)) else: save(column(p)) try: shutil.copy2(os.path.join('temp_plot.html'), os.path.join("Plots" + os.sep + "plot.html")) except Exception as ex: logging.warning("Could not move files: {0}".format(ex)) MessageBox("Error encountered processing data: {0}".format(ex)) self.createHTML(days, temps, high, low, times, status, sn) if self.openbrowser: import webbrowser webbrowser.open(os.path.join("Plots" + os.sep + "plot.html")) webbrowser.open(os.path.join("Plots" + os.sep + "HTMLTable.html")) if self.saveFiles: export_png(p, filename=img_plot_filename) try: shutil.move( os.path.join(img_plot_filename), os.path.join("Images" + os.sep + img_plot_filename)) except Exception as ex: logging.warning("Could not move files: {0}".format(ex)) MessageBox("Error encountered processing data: {0}".format(ex)) self.ShowPlots(r"Plots\plot.html", r"Plots\HTMLTable.html") def createHTML(self, days, temps, high, low, times, status, sn): strTable = """ <html> <head> <style> table{ width: 100%; border-collapse: collapse; font-family: Arial, serif; } th{ height: 5px; text-align: center; background-color: #003366;; color: white; border: 1px solid #008CBA; } td{ height: 5px; text-align: center; border: 1px solid #008CBA; font-size: 13px; } </style> </head> <div style=overflow - x: auto;> <table> <tr> <th>Date</th> <th>Time</th> <th>Temp</th> <th>High</th> <th>Low</th> <th>Status</th> <th>SN</th> </tr> """ endTable = "</table></div></html>" for i in range(len(days)): if temps[i] <= high[i] and temps[i] >= low[i]: strRW = "<tr><td>" + str(days[i]) + "</td><td>" + str(times[i]) + "</td><td>" + str(temps[i]) \ + "</td><td>" + str(high[i])+ "</td><td>" + str(low[i]) + "</td><td>" + str(status[i]) \ + "</td><td>" + str(sn[i]) + "</td></tr>" else: strRW = "<tr style=color:red><td>" + str(days[i]) + "</td><td>" + str(times[i]) + "</td><td>" + str(temps[i]) \ + "</td><td>" + str(high[i]) + "</td><td>" + str(low[i]) + "</td><td>" + str(status[i]) \ + "</td><td>" + str(sn[i]) + "</td></tr>" strTable = strTable + strRW strTable = strTable + endTable with open("Plots" + os.sep + "HTMLTable.html", 'w') as html: html.write(strTable) return html def ShowPlots(self, html, table): logging.debug("Showing plot") self.webView.load( QUrl(os.path.join("file:///" + os.path.abspath(html)))) self.webViewTable.load( QUrl(os.path.join("file:///" + os.path.abspath(table)))) self.webView.setEnabled(True) self.webViewTable.setEnabled(False) self.plotTabLbl.setVisible(False) self.tableTabLbl.setVisible(False) self.webViewTable.show() self.webView.show() logging.debug("End Showing plot") def CreatePDF(self): try: directory = self.directory = QFileDialog.getExistingDirectory( self, 'Select directory', os.path.dirname(os.path.realpath(__file__)), QFileDialog.ShowDirsOnly) self.pdfEdit.setText(self.directory) # TODO check if files exists plotFilename = "img_TempReadingsPlot.png" if not os.path.isfile(directory + os.sep + plotFilename): logging.warning("Files are missing") msg = MessageBox("Image files are missing.") return pdf = MyPDF() pdf.alias_nb_pages() pdf.set_display_mode(zoom='real', layout='default') pdf.add_page("L") pdf.set_font('Arial', 'B', 12) pdf.set_title("Reagent Carousel Temperature Report") pdf.set_author("Rick Roll") # pdf.text(70.0, 5.0, "Reagent Carousel Temperature Report") pdf.image(directory + os.sep + plotFilename, x=45, y=None, w=0, h=160) pdf.set_x(60) h = """ <html> <head> <table> <tr> <th width="14%">Date</th> <th width="14%">Time</th> <th width="14%">Temp</th> <th width="14%">High</th> <th width="14%">Low</th> <th width="14%">Status</th> <th width="14%">SN</th> </tr> <tr><td>09-12-2016</td><td>07:10:52 AM</td><td>8.7</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr style=color:red><td>09-13-2016</td><td>07:12:15 AM</td><td>1.2</td><td>15.0</td><td>2.0</td><td>Fail</td><td>16FMP00032</td></tr><tr><td>09-14-2016</td><td>08:08:02 AM</td><td>6.1</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>09-15-2016</td><td>08:14:23 AM</td><td>8.0</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>09-16-2016</td><td>01:43:56 PM</td><td>8.1</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>09-17-2016</td><td>01:45:04 PM</td><td>9.2</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>09-18-2016</td><td>03:17:04 PM</td><td>9.5</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>09-19-2016</td><td>03:40:05 PM</td><td>9.6</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>09-20-2016</td><td>03:40:46 PM</td><td>9.7</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>09-21-2016</td><td>03:42:26 PM</td><td>9.8</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>09-22-2016</td><td>03:43:22 PM</td><td>9.9</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>09-23-2016</td><td>03:45:20 PM</td><td>10.0</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>09-24-2016</td><td>03:47:49 PM</td><td>10.1</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>09-25-2016</td><td>03:48:26 PM</td><td>10.2</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>09-26-2016</td><td>10:13:56 AM</td><td>10.3</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>09-27-2016</td><td>11:40:18 AM</td><td>10.4</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>09-28-2016</td><td>11:41:44 AM</td><td>10.5</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>09-29-2016</td><td>11:43:48 AM</td><td>10.5</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>09-30-2016</td><td>01:45:21 PM</td><td>10.5</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr style=color:red><td>10-01-2016</td><td>02:00:36 PM</td><td>15.9</td><td>15.0</td><td>2.0</td><td>Fail</td><td>16FMP00032</td></tr><tr><td>10-02-2016</td><td>02:01:11 PM</td><td>10.6</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>10-03-2016</td><td>02:01:46 PM</td><td>10.5</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>10-04-2016</td><td>02:02:11 PM</td><td>10.6</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>10-05-2016</td><td>02:02:42 PM</td><td>10.4</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>10-06-2016</td><td>02:03:14 PM</td><td>10.5</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>10-07-2016</td><td>02:03:52 PM</td><td>10.5</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>10-08-2016</td><td>02:04:32 PM</td><td>10.6</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>10-09-2016</td><td>02:04:58 PM</td><td>13.5</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>10-10-2016</td><td>02:45:23 PM</td><td>10.6</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>10-11-2016</td><td>09:45:16 AM</td><td>11.0</td><td>15.0</td><td>2.0</td><td>Pass</td><td>16FMP00032</td></tr><tr><td>10-12-2016</td><td>09:47:09 AM</td><td>11.0</td><td>15.0</td><td>8.0</td><td>Pass</td><td>16FMP00032</td></tr></table></div></html> """ pdf.write_html(h) outputFile = "Reports" + os.sep + 'TempReadingsReport.pdf' pdf.output(outputFile, "F") pdf.close() print("open file") subprocess.Popen([outputFile], shell=True) except Exception as ex: logging.error("Error occurred while generating PDF {0}".format(ex)) errorMessage = MessageBox("Error encountered: {0}".format(ex)) errorMessage.showDialog() def Reset(self): self.CleanPlot() self.fileEdit.setText('') self.pdfEdit.setText('') self.loadBtn.setEnabled(True) def Exit(self): sys.exit(0)
def load(filename, widget): """Loads snippets from a file, displaying them in a list. The user can then choose: - overwrite builtin snippets or not - overwrite own snippets with same title or not - select and view snippets contents. """ try: d = ET.parse(filename) elements = list(d.findall('snippet')) if not elements: raise ValueError(_("No snippets found.")) except Exception as e: QMessageBox.critical( widget, app.caption(_("Error")), _("Can't read from source:\n\n{url}\n\n{error}").format( url=filename, error=e)) return dlg = widgets.dialog.Dialog(widget) dlg.setWindowModality(Qt.WindowModal) dlg.setWindowTitle(app.caption(_("dialog title", "Import Snippets"))) tree = QTreeWidget(headerHidden=True, rootIsDecorated=False) dlg.setMainWidget(tree) userguide.addButton(dlg.buttonBox(), "snippet_import_export") allnames = frozenset(snippets.names()) builtins = frozenset(builtin.builtin_snippets) titles = dict( (snippets.title(n), n) for n in allnames if n not in builtins) new = QTreeWidgetItem(tree, [_("New Snippets")]) updated = QTreeWidgetItem(tree, [_("Updated Snippets")]) unchanged = QTreeWidgetItem(tree, [_("Unchanged Snippets")]) new.setFlags(Qt.ItemIsEnabled) updated.setFlags(Qt.ItemIsEnabled) unchanged.setFlags(Qt.ItemIsEnabled) new.setExpanded(True) updated.setExpanded(True) items = [] for snip in elements: item = QTreeWidgetItem() item.body = snip.find('body').text item.title = snip.find('title').text item.shortcuts = list(e.text for e in snip.findall('shortcuts/shortcut')) title = item.title or snippets.maketitle( snippets.parse(item.body).text) item.setText(0, title) name = snip.get('id') name = name if name in builtins else None # determine if new, updated or unchanged if not name: name = titles.get(title) item.name = name if not name or name not in allnames: new.addChild(item) items.append(item) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) item.setCheckState(0, Qt.Checked) elif name: if (item.body != snippets.text(name) or title != snippets.title(name) or (item.shortcuts and item.shortcuts != [s.toString() for s in model.shortcuts(name) or ()])): updated.addChild(item) items.append(item) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) item.setCheckState(0, Qt.Checked) else: unchanged.addChild(item) item.setFlags(Qt.ItemIsEnabled) # count: for i in new, updated, unchanged: i.setText(0, i.text(0) + " ({0})".format(i.childCount())) for i in new, updated: if i.childCount(): i.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) i.setCheckState(0, Qt.Checked) def changed(item): if item in (new, updated): for i in range(item.childCount()): c = item.child(i) c.setCheckState(0, item.checkState(0)) tree.itemChanged.connect(changed) importShortcuts = QTreeWidgetItem([_("Import Keyboard Shortcuts")]) if items: tree.addTopLevelItem(importShortcuts) importShortcuts.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) importShortcuts.setCheckState(0, Qt.Checked) dlg.setMessage(_("Choose which snippets you want to import:")) else: dlg.setMessage(_("There are no new or updated snippets in the file.")) unchanged.setExpanded(True) tree.setWhatsThis( _("<p>Here the snippets from {filename} are displayed.</p>\n" "<p>If there are new or updated snippets, you can select or deselect " "them one by one, or all at once, using the checkbox of the group. " "Then click OK to import all the selected snippets.</p>\n" "<p>Existing, unchanged snippets can't be imported.</p>\n").format( filename=os.path.basename(filename))) qutil.saveDialogSize(dlg, "snippettool/import/size", QSize(400, 300)) if not dlg.exec_() or not items: return ac = model.collection() m = model.model() with qutil.busyCursor(): for i in items: if i.checkState(0) == Qt.Checked: index = m.saveSnippet(i.name, i.body, i.title) if i.shortcuts and importShortcuts.checkState(0): shortcuts = list(map(QKeySequence.fromString, i.shortcuts)) ac.setShortcuts(m.name(index), shortcuts) widget.updateColumnSizes()
def load(filename, widget): """Loads snippets from a file, displaying them in a list. The user can then choose: - overwrite builtin snippets or not - overwrite own snippets with same title or not - select and view snippets contents. """ try: d = ET.parse(filename) elements = list(d.findall('snippet')) if not elements: raise ValueError(_("No snippets found.")) except Exception as e: QMessageBox.critical(widget, app.caption(_("Error")), _("Can't read from source:\n\n{url}\n\n{error}").format( url=filename, error=e)) return dlg = widgets.dialog.Dialog(widget) dlg.setWindowModality(Qt.WindowModal) dlg.setWindowTitle(app.caption(_("dialog title", "Import Snippets"))) tree = QTreeWidget(headerHidden=True, rootIsDecorated=False) dlg.setMainWidget(tree) userguide.addButton(dlg.buttonBox(), "snippet_import_export") allnames = frozenset(snippets.names()) builtins = frozenset(builtin.builtin_snippets) titles = dict((snippets.title(n), n) for n in allnames if n not in builtins) new = QTreeWidgetItem(tree, [_("New Snippets")]) updated = QTreeWidgetItem(tree, [_("Updated Snippets")]) unchanged = QTreeWidgetItem(tree, [_("Unchanged Snippets")]) new.setFlags(Qt.ItemIsEnabled) updated.setFlags(Qt.ItemIsEnabled) unchanged.setFlags(Qt.ItemIsEnabled) new.setExpanded(True) updated.setExpanded(True) items = [] for snip in elements: item = QTreeWidgetItem() item.body = snip.find('body').text item.title = snip.find('title').text item.shortcuts = list(e.text for e in snip.findall('shortcuts/shortcut')) title = item.title or snippets.maketitle(snippets.parse(item.body).text) item.setText(0, title) name = snip.get('id') name = name if name in builtins else None # determine if new, updated or unchanged if not name: name = titles.get(title) item.name = name if not name or name not in allnames: new.addChild(item) items.append(item) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) item.setCheckState(0, Qt.Checked) elif name: if (item.body != snippets.text(name) or title != snippets.title(name) or (item.shortcuts and item.shortcuts != [s.toString() for s in model.shortcuts(name) or ()])): updated.addChild(item) items.append(item) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) item.setCheckState(0, Qt.Checked) else: unchanged.addChild(item) item.setFlags(Qt.ItemIsEnabled) # count: for i in new, updated, unchanged: i.setText(0, i.text(0) + " ({0})".format(i.childCount())) for i in new, updated: if i.childCount(): i.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) i.setCheckState(0, Qt.Checked) def changed(item): if item in (new, updated): for i in range(item.childCount()): c = item.child(i) c.setCheckState(0, item.checkState(0)) tree.itemChanged.connect(changed) importShortcuts = QTreeWidgetItem([_("Import Keyboard Shortcuts")]) if items: tree.addTopLevelItem(importShortcuts) importShortcuts.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) importShortcuts.setCheckState(0, Qt.Checked) dlg.setMessage(_("Choose which snippets you want to import:")) else: dlg.setMessage(_("There are no new or updated snippets in the file.")) unchanged.setExpanded(True) tree.setWhatsThis(_( "<p>Here the snippets from {filename} are displayed.</p>\n" "<p>If there are new or updated snippets, you can select or deselect " "them one by one, or all at once, using the checkbox of the group. " "Then click OK to import all the selected snippets.</p>\n" "<p>Existing, unchanged snippets can't be imported.</p>\n" ).format(filename=os.path.basename(filename))) qutil.saveDialogSize(dlg, "snippettool/import/size", QSize(400, 300)) if not dlg.exec_() or not items: return ac = model.collection() m = model.model() with qutil.busyCursor(): for i in items: if i.checkState(0) == Qt.Checked: index = m.saveSnippet(i.name, i.body, i.title) if i.shortcuts and importShortcuts.checkState(0): shortcuts = list(map(QKeySequence.fromString, i.shortcuts)) ac.setShortcuts(m.name(index), shortcuts) widget.updateColumnSizes()
class OptionTreeWidget(QTreeWidget): # type: ignore """A Widget to manage different user options.""" GRP_CR = "CommitReport" OPT_CR_MR = "Merge reports" OPT_CR_RORDER = "Report Order" OPT_CR_CMAP = "Commit map" OPT_CR_PT = "Play time" OPT_SCF = "Show CF graph" OPT_SDF = "Show DF graph" def __init__(self, parent) -> None: super(OptionTreeWidget, self).__init__(parent) self.headerItem().setText(0, "Options") self.headerItem().setText(1, "Value") self.header().setSectionResizeMode(0, QHeaderView.Stretch) self.header().setSectionResizeMode(1, QHeaderView.Interactive) self.header().setCascadingSectionResizes(False) self.header().setDefaultSectionSize(100) self.header().setMinimumSectionSize(26) self.header().setStretchLastSection(False) self.itemDoubleClicked.connect(self._handle_item_double_click) self.__scf = QTreeWidgetItem(self) self.__scf.setCheckState(1, Qt.Unchecked) self.__scf.setText(0, self.OPT_SCF) self.__sdf = QTreeWidgetItem(self) self.__sdf.setText(0, self.OPT_SDF) self.__sdf.setCheckState(1, Qt.Unchecked) grp = QTreeWidgetItem(self) grp.setText(0, self.GRP_CR) self.__mr = QTreeWidgetItem(grp) self.__mr.setCheckState(1, Qt.Unchecked) self.__mr.setText(0, self.OPT_CR_MR) self.__cm = QTreeWidgetItem(grp) self.__cm.setText(0, self.OPT_CR_CMAP) # Add QBox item so select order function drop_item = QTreeWidgetItem(grp) self.__combo_box = QComboBox() self.__combo_box.addItem("---") self.__combo_box.addItem("Linear History") self.setItemWidget(drop_item, 1, self.__combo_box) drop_item.setText(0, self.OPT_CR_RORDER) play_time_item = QTreeWidgetItem(grp) play_time_item.setText(0, self.OPT_CR_PT) self.__pt_lineedit = QLineEdit() valid = QIntValidator() valid.bottom = 10 valid.top = 50000 self.__pt_lineedit.setValidator(valid) self.setItemWidget(play_time_item, 1, self.__pt_lineedit) self.__pt_lineedit.insert(str(5000)) @property def merge_report_checkstate(self): """Check state of merge report option.""" return self.__mr.checkState(1) @property def show_cf_checkstate(self): """Check state of show cf plot option.""" return self.__scf.checkState(1) @property def show_df_checkstate(self): """Check state of show df plot option.""" return self.__sdf.checkState(1) @property def report_order(self): """Get current combo box selection.""" return self.__combo_box.currentText() @property def play_time(self): """Get current play time.""" return int(self.__pt_lineedit.text()) def connect_cb_cic(self, func): """Register a callback for the combo box currentIndexChanged signal.""" self.__combo_box.currentIndexChanged.connect(func) def _handle_item_double_click(self, item, col): if item is self.__cm and col == 1: path = self._get_file() self.__cm.setText(1, path) def _get_file(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog file_path, _ = QFileDialog.getOpenFileName( self, "Load CommitReport file", "", "All Files (*)", options=options ) return file_path
def update_todo(self, list_item: QtWidgets.QTreeWidgetItem): todo_item: TodoItem = list_item.data(0, QtCore.Qt.UserRole) if list_item.checkState(0) == QtCore.Qt.Checked: todo_item.complete() self.updater_thread.start()