class OWMPR(OWWidget): name = 'ModelMap Projection Rank' description = 'Ranking projections by estimating projection quality' icon = "icons/ModelMap.svg" inputs = [('Data', Table, 'set_data', Default)] outputs = [('Features', AttributeList)] want_main_area = False settingsHandler = DomainContextHandler() variable_changed = Signal() def __init__(self): super().__init__() self.data = None self.progress = None self.infoa = gui.widgetLabel(self.controlArea, "No data loaded.") self.projectionTable = QTableView() self.controlArea.layout().addWidget(self.projectionTable) self.projectionTable.setSelectionBehavior(QTableView.SelectRows) self.projectionTable.setSelectionMode(QTableView.SingleSelection) self.projectionTable.setSortingEnabled(True) self.projectionTableModel = QStandardItemModel(self) self.projectionTableModel.setHorizontalHeaderLabels(["P-Index", "", ""]) self.projectionTable.setModel(self.projectionTableModel) self.projectionTable.setColumnWidth(0, 90) self.projectionTable.sortByColumn(0, Qt.DescendingOrder) self.projectionTable.selectionModel().selectionChanged.connect(self.on_selection_changed) gui.button(self.controlArea, self, "Rank Projections", callback=self.rank, default=True) self.resize(370, 600) def set_data(self, data): self.data = data self.infoa.setText("Data set: {}".format(data.name) if self.data else "No data loaded.") def rank(self): if self.progress: return disc = Orange.preprocess.discretize.EqualWidth(n=10) ndomain = Orange.data.Domain( [disc(self.data, attr) if type(attr) == Orange.data.variable.ContinuousVariable else attr for attr in self.data.domain.attributes], self.data.domain.class_vars) t = self.data.from_table(ndomain, self.data) attrs = t.domain.attributes tables = {} l = 0 self.progress = gui.ProgressBar(self, len(attrs) * (len(attrs) - 1) / 2) for i in range(len(attrs)): for j in range(i): ct = np.array(contingency.get_contingency(t, attrs[j], attrs[i])) pindex, _, _ = p_index(ct) tables[i, j] = ct item = QStandardItem() item.setData(float(pindex), Qt.DisplayRole) self.projectionTableModel.setItem(l, 0, item) item = QStandardItem() item.setData(attrs[i].name, Qt.DisplayRole) self.projectionTableModel.setItem(l, 1, item) item = QStandardItem() item.setData(attrs[j].name, Qt.DisplayRole) self.projectionTableModel.setItem(l, 2, item) self.progress.advance() l += 1 self.progress.finish() self.progress = None def on_selection_changed(self, selected, deselected): """Called when the ranks view selection changes.""" a1 = selected.indexes()[1].data().replace('D_', '') a2 = selected.indexes()[2].data().replace('D_', '') d = self.data.domain self.send("Features", AttributeList([d[a1], d[a2]]))
class I4CheckWindow(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.setup_model() self.tableview = QTableView() self.tableview.setSelectionMode(QAbstractItemView.NoSelection) self.tableview.setEditTriggers(QAbstractItemView.DoubleClicked) self.cbdelegate = CheckBoxDelegate() self.tableview.setItemDelegate(self.cbdelegate) self.tableview.setAutoScroll(False) self.tableview.setModel(self.model) self.tableview.sortByColumn(0, Qt.AscendingOrder) self.adjust_headers() #self.model.setHeaderData(0, Qt.Horizontal, u"") #self.model.setHeaderData(1, Qt.Horizontal, u"Title") self.radio_all = QRadioButton("All") self.radio_all.setChecked(True) self.radio_need = QRadioButton("Need") self.connect(self.radio_all, SIGNAL("toggled(bool)"), self.set_show_all) label = QLabel("DB:") label.setFixedWidth(40) label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.db_combo = QComboBox() self.populate_db_combo() self.connect( self.db_combo, SIGNAL("currentIndexChanged(int)"), self.db_index_changed) self.new_button = QPushButton("New") self.connect(self.new_button, SIGNAL("clicked()"), self.new_item) self.box = QVBoxLayout(self) self.box.addWidget(self.tableview) self.button_box = QHBoxLayout() self.button_box.setSpacing(0) self.button_box.addWidget(self.new_button) self.button_box.addWidget(self.radio_all) self.button_box.addWidget(self.radio_need) self.button_box.addWidget(label) self.button_box.addWidget(self.db_combo) self.box.addLayout(self.button_box) # self.setStyleSheet(""" # QComboBox { # font-size: 16px; # } # """) self.dwim_after_load() def dwim_after_load(self): if self.model.need_anything(): self.radio_need.setChecked(True) return self.radio_all.setChecked(True) if self.model.model.rowCount() == 0: edit_index = self.model.new() self.tableview.setCurrentIndex(edit_index) self.tableview.scrollTo(edit_index) self.tableview.edit(edit_index) def adjust_headers(self): log.debug("adjust_sizes()") self.tableview.horizontalHeader().setResizeMode(0, QHeaderView.Stretch) self.tableview.setColumnWidth(0, 1) self.tableview.verticalHeader().setDefaultSectionSize(ITEM_HEIGHT) self.tableview.verticalHeader().hide() self.tableview.horizontalHeader().hide() def setup_model(self): self.model = CheckListModel() def new_item(self): index = self.model.new() self.tableview.setCurrentIndex(index) self.tableview.resizeRowToContents(index.row()) self.tableview.scrollTo(index) self.tableview.edit(index) def set_show_all(self, show_all): if self.model.show_all == show_all: return self.model.set_show_all(show_all) self.tableview.resizeRowsToContents() def save(self): self.model.save() def checkout(self): if QMessageBox.question( self, "Checkout", "Are you sure you want to check out?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == \ QMessageBox.Yes: self.model.checkout() def reset_items(self): if QMessageBox.question( self, "Checkout", "Are you sure you want to reset the list?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == \ QMessageBox.Yes: self.model.reset_items() self.radio_all.setChecked(True) def delete_database(self): if QMessageBox.question( self, "Delete database", "Are you sure you want to delete the current database?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == \ QMessageBox.Yes: self.model.delete_database() self.populate_db_combo() self.dwim_after_load() _loading_db_combo = False def populate_db_combo(self): self._loading_db_combo = True try: self.db_combo.clear() for db_name in self.model.databases: self.db_combo.addItem(re.sub("\\.org$", "", db_name), db_name) self.db_combo.addItem("New database...", "") self.db_combo.setCurrentIndex( self.model.databases.index(self.model.current_db)) finally: self._loading_db_combo = False def db_index_changed(self, index): if self._loading_db_combo: return db_name = str(self.db_combo.itemData(index).toPyObject()) if db_name == self.model.current_db: return self.model.save() if db_name: self.model.load(db_name) self.dwim_after_load() return db_name, ok = QInputDialog.getText( self, "New Database", "Enter database name") if ok: if not re.match(r"^[\w-]+$", db_name): QMessageBox.critical( self, "Error", "Database name must contain only the following chars: " "A-Z a-z 0-9 _ -") ok = False elif db_name in self.model.databases: QMessageBox.critical( self, "Error", "Database '%s' already exists" % db_name) ok = False if not ok: self.db_combo.setCurrentIndex( self.model.databases.index(self.model.current_db)) return db_name = str(db_name) + ".org" self.model.load(db_name) self.populate_db_combo() self.dwim_after_load()
class VizRank(OWWidget): name = "Rank projections (Scatter Plot)" def __init__(self, parent_widget): super().__init__() self.parent_widget = parent_widget self.want_control_area = False self.running = False self.progress = None self.k = 10 self.projectionTable = QTableView() self.mainArea.layout().addWidget(self.projectionTable) self.projectionTable.setSelectionBehavior(QTableView.SelectRows) self.projectionTable.setSelectionMode(QTableView.SingleSelection) self.projectionTable.setSortingEnabled(True) self.projectionTableModel = QStandardItemModel(self) self.projectionTable.setModel(self.projectionTableModel) self.projectionTable.selectionModel().selectionChanged.connect( self.on_selection_changed) self.button = gui.button(self.mainArea, self, "Start evaluation", callback=self.toggle, default=True) self.resize(380, 512) self._initialize() def _initialize(self): self.running = False self.projectionTableModel.clear() self.projectionTableModel.setHorizontalHeaderLabels( ["Score", "Feature 1", "Feature 2"]) self.projectionTable.setColumnWidth(0, 60) self.projectionTable.setColumnWidth(1, 120) self.projectionTable.setColumnWidth(2, 120) self.button.setText("Start evaluation") self.button.setEnabled(False) self.pause = False self.data = None self.attrs = [] self.scores = [] self.i, self.j = 0, 0 if self.progress: self.progress.finish() self.progress = None self.information(0) if self.parent_widget.data: if not self.parent_widget.data.domain.class_var: self.information( 0, "Data with a class variable is required.") return if len(self.parent_widget.data.domain.attributes) < 2: self.information( 0, 'At least 2 unique features are needed.') return self.button.setEnabled(True) def on_selection_changed(self, selected, deselected): """Called when the ranks view selection changes.""" a1 = selected.indexes()[1].data() a2 = selected.indexes()[2].data() self.parent_widget.update_attr(attributes=(a1, a2)) def toggle(self): self.running ^= 1 if self.running: self.button.setText("Pause") self.run() else: self.button.setText("Continue") self.button.setEnabled(False) def run(self): graph = self.parent_widget.graph y_full = self.parent_widget.data.Y norm = 1 / (len(y_full) * self.k) if not self.attrs: self.attrs = self.score_heuristic() if not self.progress: self.progress = gui.ProgressBar( self, len(self.attrs) * (len(self.attrs) - 1) / 2) for i in range(self.i, len(self.attrs)): ind1 = graph.attribute_name_index[self.attrs[i]] for j in range(self.j, i): if not self.running: self.i, self.j = i, j if not self.projectionTable.selectedIndexes(): self.projectionTable.selectRow(0) self.button.setEnabled(True) return ind2 = graph.attribute_name_index[self.attrs[j]] X = graph.scaled_data[[ind1, ind2], :] valid = graph.get_valid_list([ind1, ind2]) X = X[:, valid].T y = y_full[valid] knn = NearestNeighbors(n_neighbors=self.k).fit(X) ind = knn.kneighbors(return_distance=False) score = norm * np.sum(y[ind] == y.reshape(-1, 1)) pos = bisect_left(self.scores, score) self.projectionTableModel.insertRow( len(self.scores) - pos, [QStandardItem("{:.4f}".format(score)), QStandardItem(self.attrs[j]), QStandardItem(self.attrs[i])]) self.scores.insert(pos, score) self.progress.advance() self.j = 0 self.progress.finish() if not self.projectionTable.selectedIndexes(): self.projectionTable.selectRow(0) self.button.setText("Finished") self.button.setEnabled(False) def score_heuristic(self): X = self.parent_widget.graph.scaled_data.T Y = self.parent_widget.data.Y dom = Orange.data.Domain([ContinuousVariable(str(i)) for i in range(X.shape[1])], self.parent_widget.data.domain.class_vars) data = Orange.data.Table(dom, X, Y) weights = ReliefF(n_iterations=100, k_nearest=self.k)(data) attrs = sorted( zip(weights, (x.name for x in self.parent_widget.data.domain.attributes) ), reverse=True) return [a for _, a in attrs]
class FreezeTableWidget(QTableView): def __init__(self, parent=None): QTableView.__init__(self, parent) self.freezeNum = 0 self.inited = False self.frozenTableView = QTableView(self) def columnCountChanged (self, old, new): log('columnCountChanged', old, new) def setSetting(self, setting): if self.inited and setting is not None: if 'freezeNum' in setting: self.setFreezeNum(setting['freezeNum']) if 'hideColumns' in setting: for col in range(self.model().columnCount()): if col in setting['hideColumns']: self.hideColumn(col) else: self.showColumn(col) if 'hideRows' in setting: for row in range(self.model().rowCount()): if row in setting['hideRows']: self.hideRow(row) else: self.showRow(row) def setFreezeNum(self, num): self.resizeColumnsToContents() for col in range(num): self.frozenTableView.setColumnHidden(col, False) if not self.isColumnHidden(col): width = self.columnWidth(col) # log('width:', col, width) if width != 0: self.frozenTableView.setColumnWidth(col, width) # self.setColumnHidden(col, False) for col in range(num, self.model().columnCount()): if not self.frozenTableView.isColumnHidden(col): # self.resizeColumnToContents(col) width = self.frozenTableView.columnWidth(col) self.frozenTableView.setColumnHidden(col, True) if width != 0: self.setColumnWidth(col, width) else: self.frozenTableView.setColumnHidden(col, True) #self.viewport().update() self.freezeNum = num #self.frozenTableView.viewport().stackUnder(self) #self.raise_() #self.viewport().stackUnder(self.frozenTableView); self.updateFrozenTableGeometry() # self.resizeColumnsToContents() def myInit(self, model, freezeNum): self.inited = True self.frozenTableView.setSortingEnabled(True) self.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers); self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) self.setSortingEnabled(True) self.setModel(model) self.setAlternatingRowColors(True) self.freezeNum = freezeNum self.frozenTableView.setModel(self.model()); self.frozenTableView.setFocusPolicy(QtCore.Qt.NoFocus); self.frozenTableView.verticalHeader().hide(); #self.frozenTableView.horizontalHeader().setResizeMode(QtGui.QHeaderView.Fixed); self.viewport().stackUnder(self.frozenTableView); self.frozenTableView.setStyleSheet("QTableView { border: none;" "background-color: #8EDE21;" "selection-background-color: #999}"); self.frozenTableView.setSelectionModel(self.selectionModel()) self.frozenTableView.setSelectionMode(self.selectionMode()) self.frozenTableView.setSelectionBehavior(self.selectionBehavior()) for col in range(self.freezeNum, self.model().columnCount()): self.frozenTableView.setColumnHidden(col, True) for i in range(self.freezeNum): self.frozenTableView.setColumnWidth(self.freezeNum, self.columnWidth(self.freezeNum) ) self.frozenTableView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff); self.frozenTableView.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff); self.frozenTableView.show(); self.setHorizontalScrollMode(self.ScrollPerItem); self.setVerticalScrollMode(self.ScrollPerItem); self.frozenTableView.setVerticalScrollMode(self.ScrollPerItem) self.connect(self.frozenTableView.horizontalHeader(), QtCore.SIGNAL("sortIndicatorChanged (int,Qt::SortOrder)"), self.fSortIndicatorChanged) self.connect(self.horizontalHeader(), QtCore.SIGNAL("sortIndicatorChanged (int,Qt::SortOrder)"), self.sortIndicatorChanged) self.connect(self.horizontalHeader(), QtCore.SIGNAL("sectionResized(int,int,int)"), self.updateSectionWidth) self.connect(self.verticalHeader(), QtCore.SIGNAL("sectionResized(int,int,int)"), self.updateSectionHeight) self.connect(self.frozenTableView.horizontalHeader(), QtCore.SIGNAL("sectionResized(int,int,int)"), self.updateColumn) self.connect(self.frozenTableView.verticalHeader(), QtCore.SIGNAL("sectionResized(int,int,int)"), self.updateRow) self.connect(self.frozenTableView.verticalScrollBar(), QtCore.SIGNAL("valueChanged(int)"), self.verticalScrollBar().setValue) self.connect(self.verticalScrollBar(), QtCore.SIGNAL("valueChanged(int)"), self.frozenTableView.verticalScrollBar().setValue) self.resizeColumnsToContents() self.updateFrozenTableGeometry(); def fSortIndicatorChanged(self, index, sortOrder): if index < self.freezeNum: self.frozenTableView.horizontalHeader().setSortIndicatorShown(True) self.horizontalHeader().setSortIndicatorShown(False) def sortIndicatorChanged(self, index, sortOrder): if index >= self.freezeNum: self.frozenTableView.horizontalHeader().setSortIndicatorShown(False) self.horizontalHeader().setSortIndicatorShown(True) def updateColumn(self, logicalIndex, a, newSize): self.setColumnWidth(logicalIndex,newSize); self.updateFrozenTableGeometry() def updateRow(self, logicalIndex, a, newSize): self.setRowHeight(logicalIndex, newSize) def updateSectionWidth(self, logicalIndex, a, newSize): #if logicalIndex==0 or logicalIndex == 1: self.frozenTableView.setColumnWidth(logicalIndex,newSize); self.updateFrozenTableGeometry() def updateSectionHeight(self, logicalIndex, a, newSize): self.frozenTableView.setRowHeight(logicalIndex, newSize); self.updateFrozenTableGeometry() def resizeEvent(self, event): pass QTableView.resizeEvent(self, event); self.updateFrozenTableGeometry() def moveCursor(self, cursorAction, modifiers): pass current = QTableView.moveCursor(self, cursorAction, modifiers); if cursorAction == self.MoveLeft and current.column()>0 \ and self.visualRect(current).topLeft().x() < self.frozenTableView.columnWidth(0): newValue = self.horizontalScrollBar().value() + self.visualRect(current).topLeft().x() - self.frozenTableView.columnWidth(0) self.horizontalScrollBar().setValue(newValue) return current # def scrollTo(self, index, hint): # pass # #if(index.column()>0): # print 'here' #QTableView.scrollTo(self, index, hint) def updateFrozenTableGeometry(self): width = 0 for i in range(self.freezeNum): width += self.columnWidth(i) self.frozenTableView.setGeometry(self.verticalHeader().sizeHint().width()+self.frameWidth(), \ self.frameWidth(), width, self.viewport().height()+self.horizontalHeader().height())
class LayerSelectionPage(QFrame): #TODO. Filtering, (visible) row selection, multi selection colparams = ((0,65,'Name'), (1,235,'Title'), (2,350,'Keywords')) XFER_BW = 40 def __init__(self, parent=None): super(LayerSelectionPage, self).__init__(parent) self.parent = parent #convenience link self.confconn_link = self.parent.parent.confconn #flag top prevent read read action on keyword delete. New logic makes this redundant #self.keywordbypass = False QToolTip.setFont(QFont('SansSerif', 10)) #label filterlabel = QLabel('Filter') availablelabel = QLabel('Available Layers') selectionlabel = QLabel('Layer Selections') keywordlabel = QLabel('Keyword') explainlabel = QLabel("Edit Group assignments using this dialog or to simply initialise the Layer-Config just click 'Finish'") #selection buttons chooseallbutton = QPushButton('>>') chooseallbutton.setFixedWidth(self.XFER_BW) chooseallbutton.clicked.connect(self.doChooseAllClickAction) choosebutton = QPushButton('>') choosebutton.setFixedWidth(self.XFER_BW) choosebutton.clicked.connect(self.doChooseClickAction) rejectbutton = QPushButton('<') rejectbutton.setFixedWidth(self.XFER_BW) rejectbutton.clicked.connect(self.doRejectClickAction) rejectallbutton = QPushButton('<<') rejectallbutton.setFixedWidth(self.XFER_BW) rejectallbutton.clicked.connect(self.doRejectAllClickAction) #operation buttons finishbutton = QPushButton('Finish') finishbutton.setToolTip('Finish and Close layer selection dialog') finishbutton.clicked.connect(self.parent.close) resetbutton = QPushButton('Reset') resetbutton.font() resetbutton.setToolTip('Read Layer from LDS GetCapabilities request. Overwrites current Layer Config') resetbutton.clicked.connect(self.doResetClickAction) self.available_sfpm = LDSSFPAvailableModel(self) self.selection_sfpm = LDSSFPSelectionModel(self) self.available_sfpm.setSourceModel(self.parent.available_model) self.selection_sfpm.setSourceModel(self.parent.selection_model) #textedits filteredit = QLineEdit('') filteredit.setToolTip('Filter Available-Layers pane (filter operates across Name and Title fields and accepts Regex expressions)') filteredit.textChanged.connect(self.available_sfpm.setActiveFilter) self.keywordcombo = QComboBox() self.keywordcombo.setToolTip('Select or Add a unique identifier to be saved in layer config (keyword)') self.keywordcombo.addItems(list(self.confconn_link.assigned)) self.keywordcombo.setEditable(True) self.keywordcombo.activated.connect(self.doKeyComboChangeAction) lgindex = self.confconn_link.getLayerGroupIndex(self.confconn_link.lgval,col=1) lgentry = self.confconn_link.lglist[lgindex] if LU.assessNone(lgindex) else None #keywordedit = self.keywordcombo.lineEdit().text().toUtf8().data().decode('utf8')# for writing #if no entry or layer indicated then blank self.keywordcombo.lineEdit().setText('' if lgentry is None or lgentry[0]==LORG.LAYER else lgentry[1])#self.confconn_link.lgval)#TODO. group only #header headmodel = QStandardItemModel() headmodel.setHorizontalHeaderLabels([i[2] for i in self.colparams][:self.parent.available_model.columnCount()]) headview1 = QHeaderView(Qt.Horizontal) headview1.setModel(headmodel) headview1.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) headview2 = QHeaderView(Qt.Horizontal) headview2.setModel(headmodel) headview2.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) #table self.available = QTableView() self.available.setSelectionBehavior(QAbstractItemView.SelectRows) self.available.setSelectionMode(QAbstractItemView.MultiSelection) self.selection = QTableView() self.selection.setSelectionBehavior(QAbstractItemView.SelectRows) self.selection.setSelectionMode(QAbstractItemView.MultiSelection) #interesting, must set model after selection attributes but before headers else row selections/headers don't work properly self.available.setModel(self.available_sfpm) self.selection.setModel(self.selection_sfpm) self.available.setSortingEnabled(True) self.available.setHorizontalHeader(headview1) self.selection.setSortingEnabled(True) self.selection.setHorizontalHeader(headview2) for cp in self.colparams: self.available.setColumnWidth(cp[0],cp[1]) self.selection.setColumnWidth(cp[0],cp[1]) self.available.verticalHeader().setVisible(False) self.available.horizontalHeader().setVisible(True) self.selection.verticalHeader().setVisible(False) self.selection.horizontalHeader().setVisible(True) #layout vbox00 = QVBoxLayout() vbox00.addWidget(availablelabel) vbox00.addWidget(self.available) vbox01 = QVBoxLayout() vbox01.addWidget(chooseallbutton) vbox01.addWidget(choosebutton) vbox01.addWidget(rejectbutton) vbox01.addWidget(rejectallbutton) vbox02 = QVBoxLayout() vbox02.addWidget(selectionlabel) vbox02.addWidget(self.selection) vbox10 = QVBoxLayout() vbox10.addWidget(filterlabel) vbox10.addWidget(filteredit) hbox12 = QHBoxLayout() hbox12.addWidget(keywordlabel) hbox12.addStretch(1) #hbox12.addWidget(inspbutton) #hbox12.addWidget(addbutton) #hbox12.addWidget(delbutton) vbox12 = QVBoxLayout() vbox12.addLayout(hbox12) vbox12.addWidget(self.keywordcombo) #00|01|02 #10|11|12 grid0 = QGridLayout() grid0.addLayout(vbox00,1,0) grid0.addLayout(vbox01,1,1) grid0.addLayout(vbox02,1,2) grid0.addLayout(vbox10,0,0) grid0.addLayout(vbox12,0,2) hbox2 = QHBoxLayout() hbox2.addWidget(resetbutton) hbox2.addStretch(1) hbox2.addWidget(explainlabel) hbox2.addWidget(finishbutton) #gbox1.setLayout(hbox2) vbox3 = QVBoxLayout() vbox3.addLayout(grid0) #vbox3.addLayout(hbox3) #vbox3.addWidget(line0) vbox3.addLayout(hbox2) self.setLayout(vbox3) def doChooseAllClickAction(self): '''Moves the lot to Selected''' #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data()) ktext = LU.recode(LQ.readWidgetText(self.keywordcombo.lineEdit().text())) if not self.checkKeyword(ktext): return #------------------------------ self.parent.signalModels(self.parent.STEP.PRE) #self.parent.selection_model.mdata += self.parent.available_model.mdata self.parent.selection_model.initData(self.confconn_link.complete) self.parent.available_model.initData([]) self.parent.signalModels(self.parent.STEP.POST) #------------------------------ self.parent.writeKeysToLayerConfig(ktext) #self.confconn_link.setupAssignedLayerList() if self.keywordcombo.findText(ktext) == -1: self.keywordcombo.addItem(ktext) def doChooseClickAction(self): '''Takes available selected and moves to selection''' #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data()) ktext = LU.recode(LQ.readWidgetText(self.keywordcombo.lineEdit().text())) #ktext = str(self.keywordcombo.lineEdit().text()) if not self.checkKeyword(ktext): return #------------------------------ select = self.available.selectionModel() if select.hasSelection(): self.transferSelectedRows(select.selectedRows(),self.available_sfpm,self.selection_sfpm) #------------------------------ self.parent.writeKeysToLayerConfig(ktext) #self.confconn_link.assigned = self.confconn_link.setupAssignedLayerList() # -1 to indicate no index since 0,1,... are valid if self.keywordcombo.findText(ktext) == -1: self.keywordcombo.addItem(ktext) else: ldslog.warn('L2R > Transfer action without selection') #TRACE# #pdb.set_trace() self.available.clearSelection() def transferSelectedRows(self,indices,from_model,to_model): tlist = [] for proxymodelindex in indices: transfer = from_model.getData(proxymodelindex) tlist.append((proxymodelindex,transfer),) to_model.addData([t[1] for t in tlist]) from_model.delData([t[0] for t in tlist]) return tlist def doRejectClickAction(self): '''Takes available selected and moves to selection''' #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data()) ktext = LU.recode(LQ.readWidgetText(self.keywordcombo.lineEdit().text())) if not self.checkKeyword(ktext): return #------------------------------ select = self.selection.selectionModel() if select.hasSelection(): tlist = self.transferSelectedRows(select.selectedRows(),self.selection_sfpm,self.available_sfpm) #------------------------------ kindex = self.keywordcombo.findText(ktext) remainder = self.parent.deleteKeysFromLayerConfig([ll[1][0] for ll in tlist],ktext) if remainder > 0 and kindex == -1: #items+newkey -> add self.parent.writeKeysToLayerConfig(ktext) self.keywordcombo.addItem(ktext) elif remainder == 0 and kindex > -1: #empty+oldkey -> del self.keywordcombo.removeItem(kindex) self.keywordcombo.clearEditText() else: ldslog.warn('R2L < Transfer action without selection') #TRACE# #pdb.set_trace() self.selection.clearSelection() def doRejectAllClickAction(self): #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data()) ktext = LU.recode(LQ.readWidgetText(self.keywordcombo.lineEdit().text())) if not self.checkKeyword(ktext): return #------------------------------ self.parent.deleteKeysFromLayerConfig([ll[0] for ll in self.parent.selection_model.mdata],ktext) #------------------------------ self.parent.signalModels(self.parent.STEP.PRE) #self.parent.available_model.mdata += self.parent.selection_model.mdata self.parent.available_model.initData(self.confconn_link.complete) self.parent.selection_model.initData([]) self.parent.signalModels(self.parent.STEP.POST) #------------------------------ #self.confconn_link.setupAssignedLayerList() #self.keywordbypass = True self.keywordcombo.removeItem(self.keywordcombo.findText(ktext)) self.keywordcombo.clearEditText() def doKeyComboChangeAction(self): '''Reset the available pane and if there is anything in the keyword box use this to init the selection pane''' #HACK #if self.keywordbypass: # self.keywordbypass = False # return #------------------------------ #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data()) ktext = LU.recode(LQ.readWidgetText(self.keywordcombo.lineEdit().text())) #------------------------------ av_sl = self.parent.splitData(ktext,self.confconn_link.complete) #av_sl = self.parent.splitData(ktext,self.confconn_link.complete) self.parent.signalModels(self.parent.STEP.PRE) self.parent.available_model.initData(av_sl[0]) self.parent.selection_model.initData(av_sl[1]) self.parent.signalModels(self.parent.STEP.POST) def doResetClickAction(self): '''Dumps the LC and rebuilds from a fresh read of the caps doc''' #int warning (QWidget parent, QString title, QString text, QString button0Text, QString button1Text = QString(), QString button2Text = QString(), int defaultButtonNumber = 0, int escapeButtonNumber = -1) ans = QMessageBox.warning(self, "Reset","This action will overwrite your Layer Configuration using the current LDS settings (potentially adding new or removing layers). Continue?","Continue","Cancel") if ans: #Cancel ldslog.warn('Cancelling Reset operation') return #Continue ldslog.warn('Reset Layer Config') self.parent.resetLayers() self.keywordcombo.clear() def checkKeyword(self,ktext): '''Checks keyword isn't null and isn't part of the LDS supplied keywords''' if LU.assessNone(ktext) is None: QMessageBox.about(self, "Keyword Required","Please enter a Keyword to assign Layer(s) to") return False if ktext in self.confconn_link.reserved: QMessageBox.about(self, "Reserved Keyword","'{}' is a reserved keyword, please select again".format(ktext)) return False return True
class VizRank(OWWidget): name = "Rank projections (Scatter Plot)" want_control_area = False def __init__(self, parent_widget): super().__init__() self.parent_widget = parent_widget self.running = False self.progress = None self.k = 10 self.projectionTable = QTableView() self.mainArea.layout().addWidget(self.projectionTable) self.projectionTable.setSelectionBehavior(QTableView.SelectRows) self.projectionTable.setSelectionMode(QTableView.SingleSelection) self.projectionTable.setSortingEnabled(True) self.projectionTableModel = QStandardItemModel(self) self.projectionTable.setModel(self.projectionTableModel) self.projectionTable.selectionModel().selectionChanged.connect( self.on_selection_changed) self.button = gui.button(self.mainArea, self, "Start evaluation", callback=self.toggle, default=True) self.resize(380, 512) self._initialize() def _initialize(self): self.running = False self.projectionTableModel.clear() self.projectionTableModel.setHorizontalHeaderLabels( ["Score", "Feature 1", "Feature 2"]) self.projectionTable.setColumnWidth(0, 60) self.projectionTable.setColumnWidth(1, 120) self.projectionTable.setColumnWidth(2, 120) self.button.setText("Start evaluation") self.button.setEnabled(False) self.pause = False self.data = None self.attrs = [] self.scores = [] self.i, self.j = 0, 0 if self.progress: self.progress.finish() self.progress = None self.information(0) if self.parent_widget.data: if not self.parent_widget.data.domain.class_var: self.information( 0, "Data with a class variable is required.") return if len(self.parent_widget.data.domain.attributes) < 2: self.information( 0, 'At least 2 unique features are needed.') return if len(self.parent_widget.data) < 2: self.information( 0, 'At least 2 instances are needed.') return self.button.setEnabled(True) def on_selection_changed(self, selected, deselected): """Called when the ranks view selection changes.""" a1 = selected.indexes()[1].data() a2 = selected.indexes()[2].data() self.parent_widget.update_attr(attributes=(a1, a2)) def toggle(self): self.running ^= 1 if self.running: self.button.setText("Pause") self.run() else: self.button.setText("Continue") self.button.setEnabled(False) def run(self): graph = self.parent_widget.graph y_full = self.parent_widget.data.Y if not self.attrs: self.attrs = self.score_heuristic() if not self.progress: self.progress = gui.ProgressBar( self, len(self.attrs) * (len(self.attrs) - 1) / 2) for i in range(self.i, len(self.attrs)): ind1 = graph.attribute_name_index[self.attrs[i]] for j in range(self.j, i): if not self.running: self.i, self.j = i, j if not self.projectionTable.selectedIndexes(): self.projectionTable.selectRow(0) self.button.setEnabled(True) return ind2 = graph.attribute_name_index[self.attrs[j]] X = graph.scaled_data[[ind1, ind2], :] valid = graph.get_valid_list([ind1, ind2]) X = X[:, valid].T if X.shape[0] < self.k: self.progress.advance() continue y = y_full[valid] n_neighbors = min(self.k, len(X) - 1) knn = NearestNeighbors(n_neighbors=n_neighbors).fit(X) ind = knn.kneighbors(return_distance=False) if self.parent_widget.data.domain.has_discrete_class: score = np.sum(y[ind] == y.reshape(-1, 1)) / ( len(y_full) * n_neighbors) else: score = r2_score(y, np.mean(y[ind], axis=1)) * ( len(y) / len(y_full)) pos = bisect_left(self.scores, score) self.projectionTableModel.insertRow( len(self.scores) - pos, [QStandardItem("{:.4f}".format(score)), QStandardItem(self.attrs[j]), QStandardItem(self.attrs[i])]) self.scores.insert(pos, score) self.progress.advance() self.j = 0 self.progress.finish() if not self.projectionTable.selectedIndexes(): self.projectionTable.selectRow(0) self.button.setText("Finished") self.button.setEnabled(False) def score_heuristic(self): X = self.parent_widget.graph.scaled_data.T Y = self.parent_widget.data.Y dom = Domain([ContinuousVariable(str(i)) for i in range(X.shape[1])], self.parent_widget.data.domain.class_vars) data = Table(dom, X, Y) relief = ReliefF if isinstance(dom.class_var, DiscreteVariable) else RReliefF weights = relief(n_iterations=100, k_nearest=self.k)(data) attrs = sorted(zip(weights, (x.name for x in self.parent_widget.data.domain.attributes)), reverse=True) return [a for _, a in attrs]
class LayerSelectionPage(QFrame): #TODO. Filtering, (visible) row selection, multi selection colparams = ((0, 65, 'Name'), (1, 235, 'Title'), (2, 350, 'Keywords')) XFER_BW = 40 def __init__(self, parent=None): super(LayerSelectionPage, self).__init__(parent) self.parent = parent #convenience link self.confconn_link = self.parent.parent.confconn #flag top prevent read read action on keyword delete. New logic makes this redundant #self.keywordbypass = False QToolTip.setFont(QFont('SansSerif', 10)) #label filterlabel = QLabel('Filter') availablelabel = QLabel('Available Layers') selectionlabel = QLabel('Layer Selections') keywordlabel = QLabel('Keyword') explainlabel = QLabel( "Edit Group assignments using this dialog or to simply initialise the Layer-Config just click 'Finish'" ) #selection buttons chooseallbutton = QPushButton('>>') chooseallbutton.setFixedWidth(self.XFER_BW) chooseallbutton.clicked.connect(self.doChooseAllClickAction) choosebutton = QPushButton('>') choosebutton.setFixedWidth(self.XFER_BW) choosebutton.clicked.connect(self.doChooseClickAction) rejectbutton = QPushButton('<') rejectbutton.setFixedWidth(self.XFER_BW) rejectbutton.clicked.connect(self.doRejectClickAction) rejectallbutton = QPushButton('<<') rejectallbutton.setFixedWidth(self.XFER_BW) rejectallbutton.clicked.connect(self.doRejectAllClickAction) #operation buttons finishbutton = QPushButton('Finish') finishbutton.setToolTip('Finish and Close layer selection dialog') finishbutton.clicked.connect(self.parent.close) resetbutton = QPushButton('Reset') resetbutton.font() resetbutton.setToolTip( 'Read Layer from LDS GetCapabilities request. Overwrites current Layer Config' ) resetbutton.clicked.connect(self.doResetClickAction) self.available_sfpm = LDSSFPAvailableModel(self) self.selection_sfpm = LDSSFPSelectionModel(self) self.available_sfpm.setSourceModel(self.parent.available_model) self.selection_sfpm.setSourceModel(self.parent.selection_model) #textedits filteredit = QLineEdit('') filteredit.setToolTip( 'Filter Available-Layers pane (filter operates across Name and Title fields and accepts Regex expressions)' ) filteredit.textChanged.connect(self.available_sfpm.setActiveFilter) self.keywordcombo = QComboBox() self.keywordcombo.setToolTip( 'Select or Add a unique identifier to be saved in layer config (keyword)' ) self.keywordcombo.addItems(list(self.confconn_link.assigned)) self.keywordcombo.setEditable(True) self.keywordcombo.activated.connect(self.doKeyComboChangeAction) lgindex = self.confconn_link.getLayerGroupIndex( self.confconn_link.lgval, col=1) lgentry = self.confconn_link.lglist[lgindex] if LU.assessNone( lgindex) else None #keywordedit = self.keywordcombo.lineEdit().text().toUtf8().data().decode('utf8')# for writing #if no entry or layer indicated then blank self.keywordcombo.lineEdit().setText( '' if lgentry is None or lgentry[0] == LORG.LAYER else lgentry[1]) #self.confconn_link.lgval)#TODO. group only #header headmodel = QStandardItemModel() headmodel.setHorizontalHeaderLabels([ i[2] for i in self.colparams ][:self.parent.available_model.columnCount()]) headview1 = QHeaderView(Qt.Horizontal) headview1.setModel(headmodel) headview1.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) headview2 = QHeaderView(Qt.Horizontal) headview2.setModel(headmodel) headview2.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) #table self.available = QTableView() self.available.setSelectionBehavior(QAbstractItemView.SelectRows) self.available.setSelectionMode(QAbstractItemView.MultiSelection) self.selection = QTableView() self.selection.setSelectionBehavior(QAbstractItemView.SelectRows) self.selection.setSelectionMode(QAbstractItemView.MultiSelection) #interesting, must set model after selection attributes but before headers else row selections/headers don't work properly self.available.setModel(self.available_sfpm) self.selection.setModel(self.selection_sfpm) self.available.setSortingEnabled(True) self.available.setHorizontalHeader(headview1) self.selection.setSortingEnabled(True) self.selection.setHorizontalHeader(headview2) for cp in self.colparams: self.available.setColumnWidth(cp[0], cp[1]) self.selection.setColumnWidth(cp[0], cp[1]) self.available.verticalHeader().setVisible(False) self.available.horizontalHeader().setVisible(True) self.selection.verticalHeader().setVisible(False) self.selection.horizontalHeader().setVisible(True) #layout vbox00 = QVBoxLayout() vbox00.addWidget(availablelabel) vbox00.addWidget(self.available) vbox01 = QVBoxLayout() vbox01.addWidget(chooseallbutton) vbox01.addWidget(choosebutton) vbox01.addWidget(rejectbutton) vbox01.addWidget(rejectallbutton) vbox02 = QVBoxLayout() vbox02.addWidget(selectionlabel) vbox02.addWidget(self.selection) vbox10 = QVBoxLayout() vbox10.addWidget(filterlabel) vbox10.addWidget(filteredit) hbox12 = QHBoxLayout() hbox12.addWidget(keywordlabel) hbox12.addStretch(1) #hbox12.addWidget(inspbutton) #hbox12.addWidget(addbutton) #hbox12.addWidget(delbutton) vbox12 = QVBoxLayout() vbox12.addLayout(hbox12) vbox12.addWidget(self.keywordcombo) #00|01|02 #10|11|12 grid0 = QGridLayout() grid0.addLayout(vbox00, 1, 0) grid0.addLayout(vbox01, 1, 1) grid0.addLayout(vbox02, 1, 2) grid0.addLayout(vbox10, 0, 0) grid0.addLayout(vbox12, 0, 2) hbox2 = QHBoxLayout() hbox2.addWidget(resetbutton) hbox2.addStretch(1) hbox2.addWidget(explainlabel) hbox2.addWidget(finishbutton) #gbox1.setLayout(hbox2) vbox3 = QVBoxLayout() vbox3.addLayout(grid0) #vbox3.addLayout(hbox3) #vbox3.addWidget(line0) vbox3.addLayout(hbox2) self.setLayout(vbox3) def doChooseAllClickAction(self): '''Moves the lot to Selected''' #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data()) ktext = LU.recode( LQ.readWidgetText(self.keywordcombo.lineEdit().text())) if not self.checkKeyword(ktext): return #------------------------------ self.parent.signalModels(self.parent.STEP.PRE) #self.parent.selection_model.mdata += self.parent.available_model.mdata self.parent.selection_model.initData(self.confconn_link.complete) self.parent.available_model.initData([]) self.parent.signalModels(self.parent.STEP.POST) #------------------------------ self.parent.writeKeysToLayerConfig(ktext) #self.confconn_link.setupAssignedLayerList() if self.keywordcombo.findText(ktext) == -1: self.keywordcombo.addItem(ktext) def doChooseClickAction(self): '''Takes available selected and moves to selection''' #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data()) ktext = LU.recode( LQ.readWidgetText(self.keywordcombo.lineEdit().text())) #ktext = str(self.keywordcombo.lineEdit().text()) if not self.checkKeyword(ktext): return #------------------------------ select = self.available.selectionModel() if select.hasSelection(): self.transferSelectedRows(select.selectedRows(), self.available_sfpm, self.selection_sfpm) #------------------------------ self.parent.writeKeysToLayerConfig(ktext) #self.confconn_link.assigned = self.confconn_link.setupAssignedLayerList() # -1 to indicate no index since 0,1,... are valid if self.keywordcombo.findText(ktext) == -1: self.keywordcombo.addItem(ktext) else: ldslog.warn('L2R > Transfer action without selection') #TRACE# #pdb.set_trace() self.available.clearSelection() def transferSelectedRows(self, indices, from_model, to_model): tlist = [] for proxymodelindex in indices: transfer = from_model.getData(proxymodelindex) tlist.append((proxymodelindex, transfer), ) to_model.addData([t[1] for t in tlist]) from_model.delData([t[0] for t in tlist]) return tlist def doRejectClickAction(self): '''Takes available selected and moves to selection''' #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data()) ktext = LU.recode( LQ.readWidgetText(self.keywordcombo.lineEdit().text())) if not self.checkKeyword(ktext): return #------------------------------ select = self.selection.selectionModel() if select.hasSelection(): tlist = self.transferSelectedRows(select.selectedRows(), self.selection_sfpm, self.available_sfpm) #------------------------------ kindex = self.keywordcombo.findText(ktext) remainder = self.parent.deleteKeysFromLayerConfig( [ll[1][0] for ll in tlist], ktext) if remainder > 0 and kindex == -1: #items+newkey -> add self.parent.writeKeysToLayerConfig(ktext) self.keywordcombo.addItem(ktext) elif remainder == 0 and kindex > -1: #empty+oldkey -> del self.keywordcombo.removeItem(kindex) self.keywordcombo.clearEditText() else: ldslog.warn('R2L < Transfer action without selection') #TRACE# #pdb.set_trace() self.selection.clearSelection() def doRejectAllClickAction(self): #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data()) ktext = LU.recode( LQ.readWidgetText(self.keywordcombo.lineEdit().text())) if not self.checkKeyword(ktext): return #------------------------------ self.parent.deleteKeysFromLayerConfig( [ll[0] for ll in self.parent.selection_model.mdata], ktext) #------------------------------ self.parent.signalModels(self.parent.STEP.PRE) #self.parent.available_model.mdata += self.parent.selection_model.mdata self.parent.available_model.initData(self.confconn_link.complete) self.parent.selection_model.initData([]) self.parent.signalModels(self.parent.STEP.POST) #------------------------------ #self.confconn_link.setupAssignedLayerList() #self.keywordbypass = True self.keywordcombo.removeItem(self.keywordcombo.findText(ktext)) self.keywordcombo.clearEditText() def doKeyComboChangeAction(self): '''Reset the available pane and if there is anything in the keyword box use this to init the selection pane''' #HACK #if self.keywordbypass: # self.keywordbypass = False # return #------------------------------ #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data()) ktext = LU.recode( LQ.readWidgetText(self.keywordcombo.lineEdit().text())) #------------------------------ av_sl = self.parent.splitData(ktext, self.confconn_link.complete) #av_sl = self.parent.splitData(ktext,self.confconn_link.complete) self.parent.signalModels(self.parent.STEP.PRE) self.parent.available_model.initData(av_sl[0]) self.parent.selection_model.initData(av_sl[1]) self.parent.signalModels(self.parent.STEP.POST) def doResetClickAction(self): '''Dumps the LC and rebuilds from a fresh read of the caps doc''' #int warning (QWidget parent, QString title, QString text, QString button0Text, QString button1Text = QString(), QString button2Text = QString(), int defaultButtonNumber = 0, int escapeButtonNumber = -1) ans = QMessageBox.warning( self, "Reset", "This action will overwrite your Layer Configuration using the current LDS settings (potentially adding new or removing layers). Continue?", "Continue", "Cancel") if ans: #Cancel ldslog.warn('Cancelling Reset operation') return #Continue ldslog.warn('Reset Layer Config') self.parent.resetLayers() self.keywordcombo.clear() def checkKeyword(self, ktext): '''Checks keyword isn't null and isn't part of the LDS supplied keywords''' if LU.assessNone(ktext) is None: QMessageBox.about(self, "Keyword Required", "Please enter a Keyword to assign Layer(s) to") return False if ktext in self.confconn_link.reserved: QMessageBox.about( self, "Reserved Keyword", "'{}' is a reserved keyword, please select again".format( ktext)) return False return True
class FreezeTableWidget(QTableView): def __init__(self, parent=None): QTableView.__init__(self, parent) self.freezeNum = 0 self.inited = False self.frozenTableView = QTableView(self) def columnCountChanged(self, old, new): log('columnCountChanged', old, new) def setSetting(self, setting): if self.inited and setting is not None: if 'freezeNum' in setting: self.setFreezeNum(setting['freezeNum']) if 'hideColumns' in setting: for col in range(self.model().columnCount()): if col in setting['hideColumns']: self.hideColumn(col) else: self.showColumn(col) if 'hideRows' in setting: for row in range(self.model().rowCount()): if row in setting['hideRows']: self.hideRow(row) else: self.showRow(row) def setFreezeNum(self, num): self.resizeColumnsToContents() for col in range(num): self.frozenTableView.setColumnHidden(col, False) if not self.isColumnHidden(col): width = self.columnWidth(col) # log('width:', col, width) if width != 0: self.frozenTableView.setColumnWidth(col, width) # self.setColumnHidden(col, False) for col in range(num, self.model().columnCount()): if not self.frozenTableView.isColumnHidden(col): # self.resizeColumnToContents(col) width = self.frozenTableView.columnWidth(col) self.frozenTableView.setColumnHidden(col, True) if width != 0: self.setColumnWidth(col, width) else: self.frozenTableView.setColumnHidden(col, True) #self.viewport().update() self.freezeNum = num #self.frozenTableView.viewport().stackUnder(self) #self.raise_() #self.viewport().stackUnder(self.frozenTableView); self.updateFrozenTableGeometry() # self.resizeColumnsToContents() def myInit(self, model, freezeNum): self.inited = True self.frozenTableView.setSortingEnabled(True) self.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) self.setSortingEnabled(True) self.setModel(model) self.setAlternatingRowColors(True) self.freezeNum = freezeNum self.frozenTableView.setModel(self.model()) self.frozenTableView.setFocusPolicy(QtCore.Qt.NoFocus) self.frozenTableView.verticalHeader().hide() #self.frozenTableView.horizontalHeader().setResizeMode(QtGui.QHeaderView.Fixed); self.viewport().stackUnder(self.frozenTableView) self.frozenTableView.setStyleSheet("QTableView { border: none;" "background-color: #8EDE21;" "selection-background-color: #999}") self.frozenTableView.setSelectionModel(self.selectionModel()) self.frozenTableView.setSelectionMode(self.selectionMode()) self.frozenTableView.setSelectionBehavior(self.selectionBehavior()) for col in range(self.freezeNum, self.model().columnCount()): self.frozenTableView.setColumnHidden(col, True) for i in range(self.freezeNum): self.frozenTableView.setColumnWidth( self.freezeNum, self.columnWidth(self.freezeNum)) self.frozenTableView.setHorizontalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) self.frozenTableView.setVerticalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) self.frozenTableView.show() self.setHorizontalScrollMode(self.ScrollPerItem) self.setVerticalScrollMode(self.ScrollPerItem) self.frozenTableView.setVerticalScrollMode(self.ScrollPerItem) self.connect(self.frozenTableView.horizontalHeader(), QtCore.SIGNAL("sortIndicatorChanged (int,Qt::SortOrder)"), self.fSortIndicatorChanged) self.connect(self.horizontalHeader(), QtCore.SIGNAL("sortIndicatorChanged (int,Qt::SortOrder)"), self.sortIndicatorChanged) self.connect(self.horizontalHeader(), QtCore.SIGNAL("sectionResized(int,int,int)"), self.updateSectionWidth) self.connect(self.verticalHeader(), QtCore.SIGNAL("sectionResized(int,int,int)"), self.updateSectionHeight) self.connect(self.frozenTableView.horizontalHeader(), QtCore.SIGNAL("sectionResized(int,int,int)"), self.updateColumn) self.connect(self.frozenTableView.verticalHeader(), QtCore.SIGNAL("sectionResized(int,int,int)"), self.updateRow) self.connect(self.frozenTableView.verticalScrollBar(), QtCore.SIGNAL("valueChanged(int)"), self.verticalScrollBar().setValue) self.connect(self.verticalScrollBar(), QtCore.SIGNAL("valueChanged(int)"), self.frozenTableView.verticalScrollBar().setValue) self.resizeColumnsToContents() self.updateFrozenTableGeometry() def fSortIndicatorChanged(self, index, sortOrder): if index < self.freezeNum: self.frozenTableView.horizontalHeader().setSortIndicatorShown(True) self.horizontalHeader().setSortIndicatorShown(False) def sortIndicatorChanged(self, index, sortOrder): if index >= self.freezeNum: self.frozenTableView.horizontalHeader().setSortIndicatorShown( False) self.horizontalHeader().setSortIndicatorShown(True) def updateColumn(self, logicalIndex, a, newSize): self.setColumnWidth(logicalIndex, newSize) self.updateFrozenTableGeometry() def updateRow(self, logicalIndex, a, newSize): self.setRowHeight(logicalIndex, newSize) def updateSectionWidth(self, logicalIndex, a, newSize): #if logicalIndex==0 or logicalIndex == 1: self.frozenTableView.setColumnWidth(logicalIndex, newSize) self.updateFrozenTableGeometry() def updateSectionHeight(self, logicalIndex, a, newSize): self.frozenTableView.setRowHeight(logicalIndex, newSize) self.updateFrozenTableGeometry() def resizeEvent(self, event): pass QTableView.resizeEvent(self, event) self.updateFrozenTableGeometry() def moveCursor(self, cursorAction, modifiers): pass current = QTableView.moveCursor(self, cursorAction, modifiers) if cursorAction == self.MoveLeft and current.column()>0 \ and self.visualRect(current).topLeft().x() < self.frozenTableView.columnWidth(0): newValue = self.horizontalScrollBar().value() + self.visualRect( current).topLeft().x() - self.frozenTableView.columnWidth(0) self.horizontalScrollBar().setValue(newValue) return current # def scrollTo(self, index, hint): # pass # #if(index.column()>0): # print 'here' #QTableView.scrollTo(self, index, hint) def updateFrozenTableGeometry(self): width = 0 for i in range(self.freezeNum): width += self.columnWidth(i) self.frozenTableView.setGeometry(self.verticalHeader().sizeHint().width()+self.frameWidth(), \ self.frameWidth(), width, self.viewport().height()+self.horizontalHeader().height())
class OWMPR(OWWidget): name = 'ModelMap Projection Rank' description = 'Ranking projections by estimating projection quality' icon = "icons/ModelMap.svg" inputs = [('Data', Table, 'set_data', Default)] outputs = [('Features', AttributeList)] want_main_area = False settingsHandler = DomainContextHandler() variable_changed = Signal() def __init__(self): super().__init__() self.data = None self.progress = None self.infoa = gui.widgetLabel(self.controlArea, "No data loaded.") self.projectionTable = QTableView() self.controlArea.layout().addWidget(self.projectionTable) self.projectionTable.setSelectionBehavior(QTableView.SelectRows) self.projectionTable.setSelectionMode(QTableView.SingleSelection) self.projectionTable.setSortingEnabled(True) self.projectionTableModel = QStandardItemModel(self) self.projectionTableModel.setHorizontalHeaderLabels( ["P-Index", "", ""]) self.projectionTable.setModel(self.projectionTableModel) self.projectionTable.setColumnWidth(0, 90) self.projectionTable.sortByColumn(0, Qt.DescendingOrder) self.projectionTable.selectionModel().selectionChanged.connect( self.on_selection_changed) gui.button(self.controlArea, self, "Rank Projections", callback=self.rank, default=True) self.resize(370, 600) def set_data(self, data): self.data = data self.infoa.setText("Data set: {}".format(data.name) if self. data else "No data loaded.") def rank(self): if self.progress: return disc = Orange.feature.discretization.EqualWidth(n=10) ndomain = Orange.data.Domain([ disc(self.data, attr) if type(attr) == Orange.data.variable.ContinuousVariable else attr for attr in self.data.domain.attributes ], self.data.domain.class_vars) t = self.data.from_table(ndomain, self.data) attrs = t.domain.attributes tables = {} l = 0 self.progress = gui.ProgressBar(self, len(attrs) * (len(attrs) - 1) / 2) for i in range(len(attrs)): for j in range(i): ct = np.array( contingency.get_contingency(t, attrs[j], attrs[i])) pindex, _, _ = p_index(ct) tables[i, j] = ct item = QStandardItem() item.setData(float(pindex), Qt.DisplayRole) self.projectionTableModel.setItem(l, 0, item) item = QStandardItem() item.setData(attrs[i].name, Qt.DisplayRole) self.projectionTableModel.setItem(l, 1, item) item = QStandardItem() item.setData(attrs[j].name, Qt.DisplayRole) self.projectionTableModel.setItem(l, 2, item) self.progress.advance() l += 1 self.progress.finish() self.progress = None def on_selection_changed(self, selected, deselected): """Called when the ranks view selection changes.""" a1 = selected.indexes()[1].data().replace('D_', '') a2 = selected.indexes()[2].data().replace('D_', '') d = self.data.domain self.send("Features", AttributeList([d[a1], d[a2]]))
class DictValueDialog(QtHelper.EnhancedQDialog, Logger.ClassLogger): """ Dict dialog """ def __init__(self, parent, testParams, variables, advancedMode=False ): """ Operator to fill parameter description @param dataArgs: @type dataArgs: @param parent: @type parent: """ super(DictValueDialog, self).__init__(parent) self.advancedMode = advancedMode self.testParams = testParams self.variables = variables self.createDialog() self.createConnections() self.createActions() def createDialog (self): """ Create qt dialog """ self.buttonBox = QDialogButtonBox(self) self.buttonBox.setStyleSheet( """QDialogButtonBox { dialogbuttonbox-buttons-have-icons: 1; dialog-ok-icon: url(:/ok.png); dialog-cancel-icon: url(:/test-close-black.png); }""") self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) mainLayout = QVBoxLayout() self.dictTable = QTableView(self) self.model = DictTableModel(self, advancedMode=self.advancedMode) self.dictTable.setModel(self.model) self.dictTable.setFrameShape(QFrame.StyledPanel) self.dictTable.setShowGrid(True) self.dictTable.setGridStyle (Qt.DotLine) self.dictTable.setSelectionMode(QAbstractItemView.ExtendedSelection) self.dictTable.setSelectionBehavior(QAbstractItemView.SelectRows) self.dictTable.setContextMenuPolicy(Qt.CustomContextMenu) self.dictTable.verticalHeader().setVisible(False) self.dictTable.horizontalHeader().setHighlightSections(False) self.dictTable.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel) self.dictTable.horizontalHeader().setStretchLastSection(True) self.dictTable.setColumnWidth(COL_KEY, 200) # delegate item on advanced mode if self.advancedMode: self.dictTable.setItemDelegateForColumn( COL_KEY, ItemComboDelegate(self, COL_KEY) ) self.dictTable.setItemDelegateForColumn( COL_VALUE, ItemComboDelegate(self, COL_VALUE) ) mainLayout.addWidget(self.dictTable) mainLayout.addWidget(self.buttonBox) self.setLayout(mainLayout) self.setWindowTitle(self.tr("Dict configuration")) self.setMinimumWidth(500) self.center() def getInputs(self): """ Get test inputs """ return self.testParams.parameters.table().model.getData() def getOutputs(self): """ Get test outputs """ return self.testParams.parametersOutput.table().model.getData() def createConnections (self): """ Create qt connections """ self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.dictTable.customContextMenuRequested.connect(self.onPopupMenu) def getValue(self): """ Return value """ return self.model.getData() def createActions (self): """ Actions defined: * add * del """ self.addAction = QtHelper.createAction(self, self.tr("&Add"), self.addKey, icon = QIcon(":/test-parameter-add.png"), tip = self.tr('Add a new key') ) self.delAction = QtHelper.createAction(self, self.tr("&Delete"), self.delKey, icon = QIcon(":/test-parameter-del.png"), tip = self.tr('Delete the selected key') ) self.delAllAction = QtHelper.createAction(self, self.tr("&Delete All"), self.delKeys, icon = QIcon(":/test-parameter-del.png"), tip = self.tr('Delete the selected key') ) def addKey(self): """ Add key """ self.delAllAction.setEnabled(True) index = self.dictTable.currentIndex() if not index.isValid(): row = self.model.rowCount() else: row = index.row() data = self.model.getData() if self.advancedMode: tpl = { 'key': { 'operator': '', 'value': '', 'type': '' }, 'value': { 'operator': '', 'value': '', 'type': '' } } else: tpl = { 'key': 'my key', 'value': 'my value' } # add data to model data.insert(row + 1, tpl) self.model.reset() def clear (self): """ clear contents """ self.model.setDataModel( [] ) def delKey(self): """ Delete key """ # get selected proxy indexes indexes = self.dictTable.selectedIndexes() if not indexes: return if indexes: answer = QMessageBox.question(self, self.tr("Remove"), self.tr("Do you want to remove selected key?"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: self.removeValues(indexes) def removeValues(self, indexes): """ Remove values from data @param indexes: @type indexes: """ if not indexes: return # extract name, name are unique datas = self.model.getData() allNames = [] # remove duplicate index cleanIndexes = {} for index in indexes: if index.row() not in cleanIndexes: cleanIndexes[index.row()] = index #for cleanIndex in cleanIndexes.keys(): for cleanIndex in list(cleanIndexes.keys()): # for python3 support allNames.append( datas[cleanIndex]['key'] ) self.trace('Key to remove: %s' % allNames) for paramName in allNames: self.removeValue( paramName=paramName ) def removeValue(self, paramName): """ Remove one parameter according to the name passed on argument """ datas = self.model.getData() i = None for i in xrange(len(datas)): if datas[i]['key'] == paramName: break if i is not None: param = datas.pop( i ) del param self.model.reset() def delKeys(self): """ Clear all keys """ reply = QMessageBox.question(self, self.tr("Clear all keys"), self.tr("Are you sure ?"), QMessageBox.Yes | QMessageBox.No ) if reply == QMessageBox.Yes: data = self.model.getData() try: for i in xrange(len(data)): data.pop() except Exception as e: pass self.model.reset() self.delAllAction.setEnabled(False) def onPopupMenu(self, pos): """ Display menu on right click @param pos: @type pos: """ self.menu = QMenu(self.dictTable) index = self.dictTable.currentIndex() indexes = self.dictTable.selectedIndexes() if not indexes: self.menu.addAction( self.delAction ) self.menu.addAction( self.addAction ) self.menu.addSeparator() self.menu.addAction( self.delAllAction ) self.menu.addSeparator() else: self.menu.addAction( self.delAction ) self.menu.addAction( self.addAction ) self.menu.addSeparator() self.menu.addAction( self.delAllAction ) self.menu.addSeparator() self.menu.popup( self.mapToGlobal(pos) ) def loadData(self, data): """ Load data """ if isinstance(data, dict): data = [data] self.model.setDataModel( data )
class LogDialog(QDialogWithDpi): """LogDialog for the Freeseer project. It is the dialog window for the log. There is an instance for every FreeseerApp. It has a LogHandler which calls LogDialog's message() method when a new log message is received. The call to message() causes a call to add_entry() which adds the information to a new row in the table. """ def __init__(self, parent=None): super(LogDialog, self).__init__(parent) self.resize(800, 500) self.app = QApplication.instance() icon = QIcon() icon.addPixmap(QPixmap(_fromUtf8(":/freeseer/logo.png")), QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) layout = QVBoxLayout() self.setLayout(layout) self.level = 0 self.handler = LogHandler() self.table_model = QStandardItemModel(0, 5) header_names = ["Date", "Level", "Module", "Message", "LevelNo"] date_column = header_names.index("Date") level_column = header_names.index("Level") module_column = header_names.index("Module") self.level_num_column = header_names.index("LevelNo") self.table_model.setHorizontalHeaderLabels(header_names) self.table_view = QTableView() self.table_view.setModel(self.table_model) self.table_view.horizontalHeader().setStretchLastSection(True) self.table_view.setColumnWidth(date_column, self.set_width_with_dpi(125)) self.table_view.setColumnWidth(level_column, self.set_width_with_dpi(60)) self.table_view.setColumnWidth(module_column, self.set_width_with_dpi(250)) self.table_view.setColumnHidden(self.level_num_column, True) self.table_view.setShowGrid(False) self.table_view.horizontalHeader().setClickable(False) self.table_view.verticalHeader().hide() self.table_view.setStyleSheet("""Qtable_view::item { border-bottom: 1px solid lightgrey; selection-background-color: white; selection-color: black; }""") top_panel = QHBoxLayout() self.log_levels = ["Debug", "Info", "Warning", "Error"] self.level_colors = ["#3E4C85", "#269629", "#B0AB21", "#B32020"] self.levels_label = QLabel("Filter Level: ") self.levels_label.setStyleSheet("QLabel { font-weight: bold }") self.current_level_label = QLabel(self.log_levels[0]) self.current_level_label.setStyleSheet("QLabel {{ color: {} }}".format( self.level_colors[0])) self.clear_button = QPushButton("Clear Log") self.levels_slider = QSlider(Qt.Horizontal) self.levels_slider.setStyleSheet(""" QSlider::handle:horizontal { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #FFFFFF, stop:1 #E3E3E3); border: 1px solid #707070; width: 10px; margin-top: -4px; margin-bottom: -4px; border-radius: 4px; } QSlider::handle:horizontal:hover { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #DEDEDE, stop:1 #C9C9C9); border: 1px solid #4F4F4F; border-radius: 4px; } QSlider::sub-page:horizontal { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #BFBFBF, stop: 1 #9E9E9E); background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, stop: 0 #9E9E9E, stop: 1 #858585); border: 1px solid #777; height: 10px; border-radius: 4px; } QSlider::add-page:horizontal { background: #fff; border: 1px solid #707070; height: 10px; border-radius: 4px; }""") self.levels_slider.setRange(0, len(self.log_levels) - 1) self.levels_slider.setTickPosition(QSlider.TicksBelow) self.levels_slider.setTickInterval(1) top_panel.addSpacerItem(self.qspacer_item_with_dpi(10, 0)) top_panel.addWidget(self.levels_label, 3) top_panel.addWidget(self.current_level_label, 2) top_panel.addWidget(self.levels_slider, 8) top_panel.addSpacerItem(self.qspacer_item_with_dpi(25, 0)) top_panel.addWidget(self.clear_button, 10) layout.addLayout(top_panel) layout.addWidget(self.table_view) self.connect(self.clear_button, SIGNAL('clicked()'), functools.partial(self.table_model.setRowCount, 0)) self.connect(self.levels_slider, SIGNAL('valueChanged(int)'), self.slider_set_level) self.setWindowTitle("Log") self.handler.add_listener(self) def __del__(self): self.handler.remove_listener(self) def retranslate(self): self.setWindowTitle(self.app.translate("LogDialog", "Log")) self.clear_button.setText(self.app.translate("LogDialog", "Clear Log")) self.levels_label.setText("{}: ".format( self.app.translate("LogDialog", "Filter Level"))) def message(self, message): """Passes the log fields to add_entry() It is called by LogHandler when a log message is received""" self.add_entry(message["time"], message["level"], message["full_module_name"], message["message"], str(message["levelno"])) def add_entry(self, date, level, module, message, levelno): """Adds the given fields to a new row in the log table It is called by message() when a log message is received""" items = [ QStandardItem(date), QStandardItem(level), QStandardItem(module), QStandardItem(message), QStandardItem(levelno) ] for item in items: item.setEditable(False) self.table_model.appendRow(items) def slider_set_level(self, level): self.current_level_label.setText(self.log_levels[level]) self.current_level_label.setStyleSheet("QLabel {{ color: {} }}".format( self.level_colors[level])) self.set_level(level + 1) def set_level(self, level): """Sets the current level of the LogDialog. Level is based on the selection made in the levels_combo_box. It hides all messages with a lower level.""" self.level = level * 10 for i in range(self.table_model.rowCount()): if int(str(self.table_model.item( i, self.level_num_column).text())) < self.level: self.table_view.setRowHidden(i, True) else: self.table_view.setRowHidden(i, False)
class FreezeTableWidget(QTableView): def __init__(self, table_data, headers, parent=None, *args): """ Creates two QTableViews one of which is a frozen table while the other one can scroll behind it. :param table_data: The data that goes into the tables :type table_data: List :param headers: The header data of the tables. :type headers: List :param parent: The parent of the QTableView :type parent: QWidget :param args: :type args: """ QTableView.__init__(self, parent) # set the table model self.table_model = BaseSTDMTableModel(table_data, headers, parent) # set the proxy model proxy_model = QSortFilterProxyModel(self) proxy_model.setSourceModel(self.table_model) # Assign a data model for TableView self.setModel(self.table_model) # frozen_table_view - first column self.frozen_table_view = QTableView(self) # Set the model for the widget, fixed column self.frozen_table_view.setModel(self.table_model) # Hide row headers self.frozen_table_view.verticalHeader().hide() # Widget does not accept focus self.frozen_table_view.setFocusPolicy(Qt.StrongFocus | Qt.TabFocus | Qt.ClickFocus) # The user can not resize columns self.frozen_table_view.horizontalHeader().\ setResizeMode(QHeaderView.Fixed) self.frozen_table_view.setObjectName('frozen_table') self.setSelectionMode(QAbstractItemView.NoSelection) self.set_style() # Remove the scroll bar self.frozen_table_view.setHorizontalScrollBarPolicy( Qt.ScrollBarAlwaysOff) self.frozen_table_view.setVerticalScrollBarPolicy( Qt.ScrollBarAlwaysOff) # Puts more widgets to the foreground self.viewport().stackUnder(self.frozen_table_view) # # Log in to edit mode - even with one click # Set the properties of the column headings hh = self.horizontalHeader() # Text alignment centered hh.setDefaultAlignment(Qt.AlignCenter) self.set_column_width() # Set properties header lines vh = self.verticalHeader() vh.setDefaultSectionSize(25) # height lines # text alignment centered vh.setDefaultAlignment(Qt.AlignCenter) vh.setVisible(True) # Height of rows - as in the main widget self.frozen_table_view.verticalHeader().\ setDefaultSectionSize( vh.defaultSectionSize() ) # Show frozen table view self.frozen_table_view.show() # Set the size of him like the main self.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel) self.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) self.frozen_table_view.setVerticalScrollMode( QAbstractItemView.ScrollPerPixel) ## select the first column (STR Type) self.frozen_table_view.selectColumn(0) self.frozen_table_view.setEditTriggers( QAbstractItemView.AllEditTriggers) self.set_size() self.signals() def set_size(self): """ Sets the size and size policy of the tables. :return: :rtype: """ size_policy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(0) size_policy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(size_policy) self.setMinimumSize(QSize(55, 75)) self.setMaximumSize(QSize(5550, 5555)) self.SelectionMode(QAbstractItemView.SelectColumns) # set column width to fit contents self.frozen_table_view.resizeColumnsToContents() # set row height self.frozen_table_view.resizeRowsToContents() def signals(self): """ Connects signals of the tables. """ # Connect the headers and scrollbars of # both tableviews together self.horizontalHeader().sectionResized.connect( self.update_section_width) self.verticalHeader().sectionResized.connect( self.update_section_height) self.frozen_table_view.verticalScrollBar().valueChanged.connect( self.verticalScrollBar().setValue) self.verticalScrollBar().valueChanged.connect( self.frozen_table_view.verticalScrollBar().setValue) def set_column_width(self): """ Sets the column width of the frozen QTableView. """ # Set the width of columns columns_count = self.table_model.columnCount(self) for col in range(columns_count): if col == 0: # Set the size self.horizontalHeader().resizeSection(col, 60) # Fix width self.horizontalHeader().setResizeMode(col, QHeaderView.Fixed) # Width of a fixed column - as in the main widget self.frozen_table_view.setColumnWidth(col, self.columnWidth(col)) elif col == 1: self.horizontalHeader().resizeSection(col, 150) self.horizontalHeader().setResizeMode(col, QHeaderView.Fixed) self.frozen_table_view.setColumnWidth(col, self.columnWidth(col)) else: self.horizontalHeader().resizeSection(col, 150) # Hide unnecessary columns in the # widget fixed columns self.frozen_table_view.setColumnHidden(col, True) def set_style(self): """ Sets the style of the frozen table. """ # Style frozentable view self.frozen_table_view.setStyleSheet(''' #frozen_table{ border-top:none; } ''') self.shadow = QGraphicsDropShadowEffect(self) self.shadow.setBlurRadius(5) self.shadow.setOffset(2) self.shadow.setYOffset(0) self.frozen_table_view.setGraphicsEffect(self.shadow) def add_widgets(self, spatial_unit, insert_row): """ Adds widget into the frozen table. :param str_type_id: The STR type id of the tenure type combobox :type str_type_id: Integer :param insert_row: The row number the widgets to be added. :type insert_row: Integer """ delegate = STRTypeDelegate(spatial_unit) # Set delegate to add combobox under # social tenure type column self.frozen_table_view.setItemDelegate(delegate) self.frozen_table_view.setItemDelegateForColumn(0, delegate) index = self.frozen_table_view.model().index(insert_row, 0, QModelIndex()) self.frozen_table_view.model().setData(index, '', Qt.EditRole) self.frozen_table_view.openPersistentEditor( self.frozen_table_view.model().index(insert_row, 0)) self.frozen_table_view.openPersistentEditor( self.frozen_table_view.model().index(insert_row, 1)) def update_section_width(self, logicalIndex, oldSize, newSize): """ Updates frozen table column width and geometry. :param logicalIndex: The section's logical number :type logicalIndex: Integer :param oldSize: The old size of the section :type oldSize: Integer :param newSize: The new size of the section :type newSize: Integer """ if logicalIndex == 0 or logicalIndex == 1: self.frozen_table_view.setColumnWidth(logicalIndex, newSize) self.update_frozen_table_geometry() def update_section_height(self, logicalIndex, oldSize, newSize): """ Updates frozen table column height. :param logicalIndex: The section's logical number :type logicalIndex: Integer :param oldSize: The old size of the section :type oldSize: Integer :param newSize: The new size of the section :type newSize: Integer """ self.frozen_table_view.setRowHeight(logicalIndex, newSize) def resizeEvent(self, event): """ Handles the resize event of the frozen table view. It updates the frozen table view geometry on resize of table. :param event: The event :type event: QEvent """ QTableView.resizeEvent(self, event) try: self.update_frozen_table_geometry() except Exception as log: LOGGER.debug(str(log)) def scrollTo(self, index, hint): """ Scrolls the view if necessary to ensure that the item at index is visible. The view will try to position the item according to the given hint. :param index: The scroll index :type index: QModelIndex :param hint: The scroll hint :type hint: Integer """ if index.column() > 1: QTableView.scrollTo(self, index, hint) def update_frozen_table_geometry(self): """ Updates the frozen table view geometry. """ if self.verticalHeader().isVisible(): self.frozen_table_view.setGeometry( self.verticalHeader().width() + self.frameWidth(), self.frameWidth(), self.columnWidth(0) + self.columnWidth(1), self.viewport().height() + self.horizontalHeader().height()) else: self.frozen_table_view.setGeometry( self.frameWidth(), self.frameWidth(), self.columnWidth(0) + self.columnWidth(1), self.viewport().height() + self.horizontalHeader().height()) def move_cursor(self, cursor_action, modifiers): """ Override function for correct left to scroll the keyboard. Returns a QModelIndex object pointing to the next object in the table view, based on the given cursorAction and keyboard modifiers specified by modifiers. :param cursor_action: The cursor action :type cursor_action: Integer :param modifiers: Qt.KeyboardModifier value. :type modifiers: Object :return: The current cursor position. :rtype: QModelIndex """ current = QTableView.move_cursor(self, cursor_action, modifiers) if cursor_action == self.MoveLeft and current.column() > 1 and \ self.visualRect(current).topLeft().x() < \ (self.frozen_table_view.columnWidth(0) + self.frozen_table_view.columnWidth(1)): new_value = self.horizontalScrollBar().value() + \ self.visualRect(current).topLeft().x() - \ (self.frozen_table_view.columnWidth(0) + self.frozen_table_view.columnWidth(1)) self.horizontalScrollBar().setValue(new_value) return current
class QgsAttributeTableDialog(QDialog): ''' classdocs ''' def __init__(self, parent, vectorlayer): QDialog.__init__(self, parent) # self.w = QDialog(self) self.baseLayer = vectorlayer self.canChangeAttributes = self.validate( QgsVectorDataProvider.ChangeAttributeValues) self.canDeleteFeatures = self.validate( QgsVectorDataProvider.DeleteFeatures) self.canAddAttributes = self.validate( QgsVectorDataProvider.AddAttributes) self.canDeleteAttributes = self.validate( QgsVectorDataProvider.DeleteAttributes) self.canAddFeatures = self.validate(QgsVectorDataProvider.AddFeatures) gridLayout = QGridLayout(self) self.setLayout(gridLayout) self.setWindowTitle("Attribute Table") self.setFixedSize(QSize(800, 600)) editorToolbar = QToolBar() editorToolbar.setFixedSize(QSize(768, 48)) self.actionToggleEditing = QAction(QIcon("Resource\\edit.png"), "ToggleEditing", self) self.actionToggleEditing.triggered.connect(self.toggleEditing) if (self.canChangeAttributes or self.canDeleteFeatures or self.canAddAttributes or self.canDeleteAttributes or self.canAddFeatures) and (not self.baseLayer.isReadOnly()): self.actionToggleEditing.setEnabled(True) else: self.actionToggleEditing.setEnabled(False) self.actionToggleEditing.setCheckable(True) editorToolbar.addAction(self.actionToggleEditing) self.actionSave = QAction(QIcon("Resource\\filesave.png"), "Save Edits", self) self.actionSave.triggered.connect(self.saveEditing) self.actionSave.setCheckable(False) self.actionSave.setEnabled(False) editorToolbar.addAction(self.actionSave) self.actiondeleteRows = QAction( QIcon("Resource\\mActionDeleteSelected.png"), "Delete selected features", self) self.actiondeleteRows.triggered.connect(self.deleteRows) self.actiondeleteRows.setCheckable(False) self.actiondeleteRows.setEnabled(False) editorToolbar.addAction(self.actiondeleteRows) self.actionUnselectAll = QAction( QIcon("Resource\\mActionDeselectAll.png"), "Unselect All", self) self.actionUnselectAll.triggered.connect(self.unselectAll) self.actionUnselectAll.setCheckable(False) self.actionUnselectAll.setEnabled(True) editorToolbar.addAction(self.actionUnselectAll) self.actionSelectedToZoom = QAction( QIcon("Resource\\mActionZoomToSelected.png"), "Zoom map to the selected rows", self) self.actionSelectedToZoom.triggered.connect(self.selectedToZoom) self.actionSelectedToZoom.setCheckable(False) self.actionSelectedToZoom.setEnabled(True) editorToolbar.addAction(self.actionSelectedToZoom) gridLayout.addWidget(editorToolbar, 0, 0, 1, 1) self.model = QStandardItemModel() # self.model.itemChanged.connect(self.attributeChanged) self.attributeTable = QTableView(self) self.attributeTable.setModel(self.model) self.attributeTable.setColumnWidth(0, 200) self.attributeTable.setColumnWidth(1, 160) self.attributeTable.clicked.connect(self.tableSelectionChanged) self.attributeTable.setSortingEnabled(True) self.changeItemList = [] self.selectRows = [] self.isSave = True self.initTable() gridLayout.addWidget(self.attributeTable, 1, 0, 1, 1) # self.attributeTable.selectionChanged.connect(self.selectFeature) def tableSelectionChanged(self): idxList = self.attributeTable.selectedIndexes() if idxList != None and len(idxList) > 0: self.baseLayer.removeSelection() fidList = [] for idx in idxList: fid = int(self.model.item(idx.row()).text()) fidList.append(fid) self.baseLayer.setSelectedFeatures(fidList) def toggleEditing(self): if self.baseLayer != None: if not self.actionToggleEditing.isChecked(): if self.isSave: self.baseLayer.commitChanges() self.actionSave.setEnabled(False) self.actiondeleteRows.setEnabled(False) self.model.itemChanged.disconnect(self.attributeChanged) self.toggleEditingTable(False) else: button = QMessageBox.warning( self, "Stop Editing", "Do you want to save the changes to layer?", QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel) if (button == QMessageBox.Cancel): self.actionToggleEditing.setChecked(True) elif button == QMessageBox.Save: self.saveEditing() self.baseLayer.commitChanges() self.actionSave.setEnabled(False) self.actiondeleteRows.setEnabled(False) self.model.itemChanged.disconnect( self.attributeChanged) self.toggleEditingTable(False) else: self.initTable() self.baseLayer.commitChanges() self.actionSave.setEnabled(False) self.actiondeleteRows.setEnabled(False) self.model.itemChanged.disconnect( self.attributeChanged) self.toggleEditingTable(False) # self.isEditable = False else: self.actionSave.setEnabled(True) self.actiondeleteRows.setEnabled(True) self.baseLayer.startEditing() self.toggleEditingTable(True) self.model.itemChanged.connect(self.attributeChanged) # self.isEditable = True def toggleEditingTable(self, isEditable): columnCount = self.model.columnCount() rowCount = self.model.rowCount() col = 0 while col < columnCount: row = 0 while row < rowCount: self.model.item(row, col).setEditable(isEditable) row += 1 col += 1 def attributeChanged(self, standardItem): self.isSave = False # if not self.isDelete: self.changeItemList.append(standardItem) # featureId = standardItem.row() # self.baseLayer.changeAttributeValue(featureId, # standardItem.column(), standardItem.text()) def saveEditing(self): self.isSave = True if len(self.changeItemList) > 0: for standardItem in self.changeItemList: featureId = standardItem.row() self.baseLayer.changeAttributeValue(featureId, standardItem.column(), standardItem.text()) self.changeItemList = [] if len(self.selectRows) > 0: for id in self.selectRows: self.baseLayer.deleteFeature(id) self.selectRows = [] def initTable(self): self.model.clear() # header = QHeaderView(Qt.Horizontal) # headerModel = QStandardItemModel() layer = self.baseLayer fields = layer.pendingFields() headersList = ["fid"] for field in fields: headersList.append(field.name()) self.model.setHorizontalHeaderLabels(headersList) # headerModel.setHorizontalHeaderLabels(headersList) # header.setModel(headerModel) # self.attributeTable.setHorizontalHeader(header) if len(layer.selectedFeatures()) > 0: features = layer.selectedFeatures() else: features = layer.getFeatures() for feature in features: record = [QStandardItem(str(feature.id()))] for field in feature.fields(): name = field.name() attribute = feature.attribute(name).toString() stdItemValue = QStandardItem(attribute) stdItemValue.setEditable(False) record.append(stdItemValue) self.model.appendRow(record) def deleteRows(self): if len(self.attributeTable.selectedIndexes()) > 0: self.isSave = False selectedIndexs = self.attributeTable.selectedIndexes() k = -1 self.selectRows = [] for index in selectedIndexs: if k != index.row(): k = index.row() self.selectRows.append(k) for row in self.selectRows: self.model.takeRow(row) def unselectAll(self): if len(self.attributeTable.selectedIndexes()) > 0: self.attributeTable.clearSelection() def selectedToZoom(self): if len(self.attributeTable.selectedIndexes()) > 0: self.baseLayer.removeSelection() selectedIndexs = self.attributeTable.selectedIndexes() k = -1 self.selectRows = [] for index in selectedIndexs: if k != index.row(): k = index.row() self.selectRows.append(k) self.baseLayer.setSelectedFeatures(self.selectRows) # for row in self.selectRows: # self.model.takeRow(row) define._canvas.zoomToSelected(self.baseLayer) def validate(self, condition): if self.baseLayer.dataProvider().capabilities() & condition: return True else: return False
class LogDialog(QDialog): """LogDialog for the Freeseer project. It is the dialog window for the log. There is an instance for every FreeseerApp. It has a LogHandler which calls LogDialog's message() method when a new log message is received. The call to message() causes a call to add_entry() which adds the information to a new row in the table. """ def __init__(self, parent=None): super(LogDialog, self).__init__(parent) self.resize(800, 500) self.app = QApplication.instance() icon = QIcon() icon.addPixmap(QPixmap(_fromUtf8(":/freeseer/logo.png")), QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) layout = QVBoxLayout() self.setLayout(layout) self.level = 0 self.handler = LogHandler() self.table_model = QStandardItemModel(0, 5) header_names = ["Date", "Level", "Module", "Message", "LevelNo"] date_column = header_names.index("Date") level_column = header_names.index("Level") module_column = header_names.index("Module") self.level_num_column = header_names.index("LevelNo") self.table_model.setHorizontalHeaderLabels(header_names) self.table_view = QTableView() self.table_view.setModel(self.table_model) self.table_view.horizontalHeader().setStretchLastSection(True) self.table_view.setColumnWidth(date_column, 125) self.table_view.setColumnWidth(level_column, 60) self.table_view.setColumnWidth(module_column, 250) self.table_view.setColumnHidden(self.level_num_column, True) self.table_view.setShowGrid(False) self.table_view.horizontalHeader().setClickable(False) self.table_view.verticalHeader().hide() self.table_view.setStyleSheet("""Qtable_view::item { border-bottom: 1px solid lightgrey; selection-background-color: white; selection-color: black; }""") top_panel = QHBoxLayout() self.log_levels = ["Debug", "Info", "Warning", "Error"] self.level_colors = ["#3E4C85", "#269629", "#B0AB21", "#B32020"] self.levels_label = QLabel("Filter Level: ") self.levels_label.setStyleSheet("QLabel { font-weight: bold }") self.current_level_label = QLabel(self.log_levels[0]) self.current_level_label.setStyleSheet("QLabel {{ color: {} }}".format(self.level_colors[0])) self.clear_button = QPushButton("Clear Log") self.levels_slider = QSlider(Qt.Horizontal) self.levels_slider.setStyleSheet(""" QSlider::handle:horizontal { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #FFFFFF, stop:1 #E3E3E3); border: 1px solid #707070; width: 10px; margin-top: -4px; margin-bottom: -4px; border-radius: 4px; } QSlider::handle:horizontal:hover { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #DEDEDE, stop:1 #C9C9C9); border: 1px solid #4F4F4F; border-radius: 4px; } QSlider::sub-page:horizontal { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #BFBFBF, stop: 1 #9E9E9E); background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, stop: 0 #9E9E9E, stop: 1 #858585); border: 1px solid #777; height: 10px; border-radius: 4px; } QSlider::add-page:horizontal { background: #fff; border: 1px solid #707070; height: 10px; border-radius: 4px; }""") self.levels_slider.setRange(0, len(self.log_levels) - 1) self.levels_slider.setTickPosition(QSlider.TicksBelow) self.levels_slider.setTickInterval(1) top_panel.addSpacerItem(QSpacerItem(10, 0)) top_panel.addWidget(self.levels_label, 3) top_panel.addWidget(self.current_level_label, 2) top_panel.addWidget(self.levels_slider, 8) top_panel.addSpacerItem(QSpacerItem(25, 0)) top_panel.addWidget(self.clear_button, 10) layout.addLayout(top_panel) layout.addWidget(self.table_view) self.connect(self.clear_button, SIGNAL('clicked()'), functools.partial(self.table_model.setRowCount, 0)) self.connect(self.levels_slider, SIGNAL('valueChanged(int)'), self.slider_set_level) self.setWindowTitle("Log") self.handler.add_listener(self) def __del__(self): self.handler.remove_listener(self) def retranslate(self): self.setWindowTitle(self.app.translate("LogDialog", "Log")) self.clear_button.setText(self.app.translate("LogDialog", "Clear Log")) self.levels_label.setText("{}: ".format(self.app.translate("LogDialog", "Filter Level"))) def message(self, message): """Passes the log fields to add_entry() It is called by LogHandler when a log message is received""" self.add_entry(message["time"], message["level"], message["full_module_name"], message["message"], str(message["levelno"])) def add_entry(self, date, level, module, message, levelno): """Adds the given fields to a new row in the log table It is called by message() when a log message is received""" items = [QStandardItem(date), QStandardItem(level), QStandardItem(module), QStandardItem(message), QStandardItem(levelno)] for item in items: item.setEditable(False) self.table_model.appendRow(items) def slider_set_level(self, level): self.current_level_label.setText(self.log_levels[level]) self.current_level_label.setStyleSheet("QLabel {{ color: {} }}".format(self.level_colors[level])) self.set_level(level + 1) def set_level(self, level): """Sets the current level of the LogDialog. Level is based on the selection made in the levels_combo_box. It hides all messages with a lower level.""" self.level = level * 10 for i in range(self.table_model.rowCount()): if int(str(self.table_model.item(i, self.level_num_column).text())) < self.level: self.table_view.setRowHidden(i, True) else: self.table_view.setRowHidden(i, False)
class FreezeTableWidget(QTableView): def __init__( self, table_data, headers, parent = None, *args ): """ Creates two QTableViews one of which is a frozen table while the other one can scroll behind it. :param table_data: The data that goes into the tables :type table_data: List :param headers: The header data of the tables. :type headers: List :param parent: The parent of the QTableView :type parent: QWidget :param args: :type args: """ QTableView.__init__(self, parent) # set the table model self.table_model = BaseSTDMTableModel( table_data, headers, parent ) # set the proxy model proxy_model = QSortFilterProxyModel(self) proxy_model.setSourceModel(self.table_model) # Assign a data model for TableView self.setModel(self.table_model) # frozen_table_view - first column self.frozen_table_view = QTableView(self) # Set the model for the widget, fixed column self.frozen_table_view.setModel(self.table_model) # Hide row headers self.frozen_table_view.verticalHeader().hide() # Widget does not accept focus self.frozen_table_view.setFocusPolicy( Qt.StrongFocus|Qt.TabFocus|Qt.ClickFocus ) # The user can not resize columns self.frozen_table_view.horizontalHeader().\ setResizeMode(QHeaderView.Fixed) self.frozen_table_view.setObjectName('frozen_table') self.setSelectionMode(QAbstractItemView.NoSelection) # Remove the scroll bar self.frozen_table_view.setHorizontalScrollBarPolicy( Qt.ScrollBarAlwaysOff ) self.frozen_table_view.setVerticalScrollBarPolicy( Qt.ScrollBarAlwaysOff ) # Puts more widgets to the foreground self.viewport().stackUnder(self.frozen_table_view) # # Log in to edit mode - even with one click # Set the properties of the column headings hh = self.horizontalHeader() # Text alignment centered hh.setDefaultAlignment(Qt.AlignCenter) self.set_column_width() # Set properties header lines vh = self.verticalHeader() vh.setDefaultSectionSize(25) # height lines # text alignment centered vh.setDefaultAlignment(Qt.AlignCenter) vh.setVisible(True) # Height of rows - as in the main widget self.frozen_table_view.verticalHeader().\ setDefaultSectionSize( vh.defaultSectionSize() ) # Show frozen table view self.frozen_table_view.show() # Set the size of him like the main self.setHorizontalScrollMode( QAbstractItemView.ScrollPerPixel ) self.setVerticalScrollMode( QAbstractItemView.ScrollPerPixel ) self.frozen_table_view.setVerticalScrollMode( QAbstractItemView.ScrollPerPixel ) ## select the first column (STR Type) self.frozen_table_view.selectColumn(0) self.frozen_table_view.setEditTriggers( QAbstractItemView.AllEditTriggers ) self.set_size() self.signals() def set_size(self): """ Sets the size and size policy of the tables. :return: :rtype: """ size_policy = QSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed ) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(0) size_policy.setHeightForWidth( self.sizePolicy().hasHeightForWidth() ) self.setSizePolicy(size_policy) self.setMinimumSize(QSize(55, 75)) self.setMaximumSize(QSize(5550, 5555)) self.SelectionMode( QAbstractItemView.SelectColumns ) # set column width to fit contents self.frozen_table_view.resizeColumnsToContents() # set row height self.frozen_table_view.resizeRowsToContents() def signals(self): """ Connects signals of the tables. """ # Connect the headers and scrollbars of # both tableviews together self.horizontalHeader().sectionResized.connect( self.update_section_width ) self.verticalHeader().sectionResized.connect( self.update_section_height ) self.frozen_table_view.verticalScrollBar().valueChanged.connect( self.verticalScrollBar().setValue ) self.verticalScrollBar().valueChanged.connect( self.frozen_table_view.verticalScrollBar().setValue ) def set_column_width(self): """ Sets the column width of the frozen QTableView. """ # Set the width of columns columns_count = self.table_model.columnCount(self) for col in range(columns_count): if col == 0: # Set the size self.horizontalHeader().resizeSection( col, 60 ) # Fix width self.horizontalHeader().setResizeMode( col, QHeaderView.Fixed ) # Width of a fixed column - as in the main widget self.frozen_table_view.setColumnWidth( col, self.columnWidth(col) ) elif col == 1: self.horizontalHeader().resizeSection( col, 150 ) self.horizontalHeader().setResizeMode( col, QHeaderView.Fixed ) self.frozen_table_view.setColumnWidth( col, self.columnWidth(col) ) else: self.horizontalHeader().resizeSection( col, 150 ) # Hide unnecessary columns in the # widget fixed columns self.frozen_table_view.setColumnHidden( col, True ) def add_widgets(self, spatial_unit, insert_row): """ Adds widget into the frozen table. :param str_type_id: The STR type id of the tenure type combobox :type str_type_id: Integer :param insert_row: The row number the widgets to be added. :type insert_row: Integer """ delegate = STRTypeDelegate(spatial_unit) # Set delegate to add combobox under # social tenure type column self.frozen_table_view.setItemDelegate( delegate ) self.frozen_table_view.setItemDelegateForColumn( 0, delegate ) index = self.frozen_table_view.model().index( insert_row, 0, QModelIndex() ) self.frozen_table_view.model().setData( index, '', Qt.EditRole ) self.frozen_table_view.openPersistentEditor( self.frozen_table_view.model().index(insert_row, 0) ) self.frozen_table_view.openPersistentEditor( self.frozen_table_view.model().index(insert_row, 1) ) def update_section_width( self, logicalIndex, oldSize, newSize ): """ Updates frozen table column width and geometry. :param logicalIndex: The section's logical number :type logicalIndex: Integer :param oldSize: The old size of the section :type oldSize: Integer :param newSize: The new size of the section :type newSize: Integer """ if logicalIndex==0 or logicalIndex==1: self.frozen_table_view.setColumnWidth( logicalIndex, newSize ) self.update_frozen_table_geometry() def update_section_height( self, logicalIndex, oldSize, newSize ): """ Updates frozen table column height. :param logicalIndex: The section's logical number :type logicalIndex: Integer :param oldSize: The old size of the section :type oldSize: Integer :param newSize: The new size of the section :type newSize: Integer """ self.frozen_table_view.setRowHeight( logicalIndex, newSize ) def resizeEvent(self, event): """ Handles the resize event of the frozen table view. It updates the frozen table view geometry on resize of table. :param event: The event :type event: QEvent """ QTableView.resizeEvent(self, event) try: self.update_frozen_table_geometry() except Exception as log: LOGGER.debug(str(log)) def scrollTo(self, index, hint): """ Scrolls the view if necessary to ensure that the item at index is visible. The view will try to position the item according to the given hint. :param index: The scroll index :type index: QModelIndex :param hint: The scroll hint :type hint: Integer """ if index.column() > 1: QTableView.scrollTo(self, index, hint) def update_frozen_table_geometry(self): """ Updates the frozen table view geometry. """ if self.verticalHeader().isVisible(): self.frozen_table_view.setGeometry( self.verticalHeader().width() + self.frameWidth(), self.frameWidth(), self.columnWidth(0) + self.columnWidth(1), self.viewport().height() + self.horizontalHeader().height() ) else: self.frozen_table_view.setGeometry( self.frameWidth(), self.frameWidth(), self.columnWidth(0) + self.columnWidth(1), self.viewport().height() + self.horizontalHeader().height() ) def move_cursor(self, cursor_action, modifiers): """ Override function for correct left to scroll the keyboard. Returns a QModelIndex object pointing to the next object in the table view, based on the given cursorAction and keyboard modifiers specified by modifiers. :param cursor_action: The cursor action :type cursor_action: Integer :param modifiers: Qt.KeyboardModifier value. :type modifiers: Object :return: The current cursor position. :rtype: QModelIndex """ current = QTableView.move_cursor( self, cursor_action, modifiers ) if cursor_action == self.MoveLeft and current.column() > 1 and \ self.visualRect(current).topLeft().x() < \ (self.frozen_table_view.columnWidth(0) + self.frozen_table_view.columnWidth(1)): new_value = self.horizontalScrollBar().value() + \ self.visualRect(current).topLeft().x() - \ (self.frozen_table_view.columnWidth(0) + self.frozen_table_view.columnWidth(1)) self.horizontalScrollBar().setValue(new_value) return current
class CANMonitor(QMainWindow): def __init__(self, app, test, parent): QMainWindow.__init__(self, parent) self.app = app self.lcdDict=dict() self.logBuffer=deque("", 1000) self.logBuffer2=dict() self.logBufferInit=dict() self.logEntryCount=1 self.maxLogEntryCount=65353 self.tableUpdateCouter=0 self.logFile=None self.test=test self.logFileName="/tmp/candash.log" self.connectCANEnable=True self.connectGPSEnable=True self.replayMode=False self.canIdList=[0x621, 0x353, 0x351, 0x635, 0x271, 0x371, 0x623, 0x571, 0x3e5, 0x591, 0x5d1] self.updateGPSThread=None self.config=Config("candash.cfg") self.log=Log(False) font = self.font() font.setPointSize(14) self.setFont(font) self.ampelGruen=QIcon("images/ampel-gruen.png") self.ampelRot=QIcon("images/ampel-rot.png") self.ampelGelb=QIcon("images/ampel-gelb.png") self.lastCANState=canStoppedState self.lastGPSState=gpsStoppedState self.canDecoder=CANDecoder(self) self.initUI(parent) def clearAllLCD(self): for lcdList in self.lcdDict.values(): for lcd in lcdList: if lcd.mode()==QLCDNumber.Bin: lcd.display("00000000") else: lcd.display(0) self.rpmGauge.setValue(0) self.velGauge.setValue(0) def createLCD(self, mode): lcd = QLCDNumber(self) lcd.setMode(mode) lcd.setMinimumHeight(50) lcd.setMinimumWidth(160) lcd.setDigitCount(8) if mode==QLCDNumber.Bin: lcd.display("00000000") else: lcd.display(0) lcd.setSegmentStyle(QLCDNumber.Flat) lcd.setAutoFillBackground(True) palette = lcd.palette() palette.setColor(QPalette.Normal, QPalette.Foreground, Qt.blue) palette.setColor(QPalette.Normal, QPalette.Background, Qt.lightGray) lcd.setPalette(palette); return lcd def addLCD(self, lcd, canId, subItem): if not hex(canId)+":"+subItem in self.lcdDict.keys(): lcdItemList=list() lcdItemList.append(lcd) self.lcdDict[hex(canId)+":"+subItem]=lcdItemList else: self.lcdDict[hex(canId)+":"+subItem].append(lcd) def createCANIdValueEntry(self, vbox, canId, subId, mode): lcd = self.createLCD(mode) self.addLCD(lcd, canId, subId) vbox.addWidget(lcd) def createCANIdEntry(self, form, canId, subId, label, mode): # hbox = QHBoxLayout() lbl = QLabel(self) lbl.setMinimumHeight(50) font = lbl.font() font.setPointSize(14) lbl.setFont(font) if label!=None: lbl.setText(label) # hbox.addWidget(lbl) lcd = self.createLCD(mode) # hbox.addWidget(lcd) form.addRow(lbl, lcd) self.addLCD(lcd, canId, subId) # vbox.addLayout(hbox) def createCANIdEntrySingleLine(self, form, canId, subIdList, label, mode): # hbox = QHBoxLayout() lbl = QLabel(self) lbl.setMinimumHeight(50) font = lbl.font() font.setPointSize(14) lbl.setFont(font) if label!=None: lbl.setText(label) # hbox.addWidget(lbl) hbox2=QHBoxLayout(); for i in range(len(subIdList)): subId=subIdList[i] lcd = self.createLCD(mode) hbox2.addWidget(lcd) self.addLCD(lcd, canId, subId) form.addRow(lbl, hbox2) # hbox.addLayout(hbox2) # vbox.addLayout(hbox) def createLogView(self, vbox): self.logView=QTableView(self) vbox.addWidget(self.logView) self.logViewModel=CANLogViewTableModel(self.logBuffer, self.canIdList, self) self.logView.setModel(self.logViewModel) header=QHeaderView(Qt.Horizontal, self.logView) header.setStretchLastSection(True) header.setResizeMode(NUMBER_COL, QHeaderView.Fixed) header.setResizeMode(TIME_COL, QHeaderView.Fixed) header.setResizeMode(ID_COL, QHeaderView.Fixed) self.logView.setHorizontalHeader(header) self.logView.setColumnWidth(NUMBER_COL, 80) self.logView.setColumnWidth(TIME_COL, 150) self.logView.setColumnWidth(ID_COL, 80) self.logView.setColumnWidth(SIZE_COL, 50) def createLogView2(self, vbox): self.logView2=QTableView(self) vbox.addWidget(self.logView2) self.logViewModel2=CANLogViewTableModel2(self.canIdList, self) self.logView2.setModel(self.logViewModel2) # self.logView2.setSortingEnabled(True) header=QHeaderView(Qt.Horizontal, self.logView2) # header.setStretchLastSection(True) # header.setClickable(True) header.setResizeMode(0, QHeaderView.Fixed) header.setResizeMode(1, QHeaderView.Fixed) self.logView2.setHorizontalHeader(header) self.logView2.setColumnWidth(0, 80) self.logView2.setColumnWidth(1, 50) for i in range(2, 10): self.logView2.setColumnWidth(i, 60) def initUI(self, parent): # exitAction = QAction(QIcon(), 'Exit', self) # exitAction.setShortcut('Ctrl+Q') # exitAction.setStatusTip('Exit application') # exitAction.triggered.connectToCAN(self.close) self.statusbar=self.statusBar() self.progress=QProgressBar() self.statusbar.addPermanentWidget(self.progress) # menubar = self.menuBar() # fileMenu = menubar.addMenu('&File') # fileMenu.addAction(exitAction) # toolbar = self.addToolBar('Exit') ## toolbar.addAction(exitAction) # # self.connectedIcon=QIcon("images/network-connect.png") # self.disconnectIcon=QIcon("images/network-disconnect.png") # self.connectAction = QAction(self.disconnectIcon , 'Connect', self) # self.connectAction.triggered.connect(self._connect1) # self.connectAction.setCheckable(True) # # toolbar.addAction(self.connectAction) # # self.gpsIcon=QIcon("images/icon_gps.gif") # self.reconnectGPSAction = QAction(self.gpsIcon, 'Reconnect GPS', self) # self.reconnectGPSAction.triggered.connect(self._reconnectGPS) # toolbar.addAction(self.reconnectGPSAction) mainWidget=QWidget(self) # mainWidget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) mainWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setCentralWidget(mainWidget) top=QVBoxLayout(mainWidget) self.tabs = MyTabWidget(self) top.addWidget(self.tabs) mainTab = QWidget(self) miscTab = QWidget(self) misc2Tab=QWidget(self) canLogTab=QWidget(self) dashTab=QWidget(self) gpsTab=QWidget(self) osmTab=QWidget(self) debugLogTab=QWidget(self) mainTabLayout = QFormLayout(mainTab) miscTabLayout = QFormLayout(miscTab) misc2TabLayout = QFormLayout(misc2Tab) canLogTabLayout = QVBoxLayout(canLogTab) dashTabLayout = QHBoxLayout(dashTab) gpsTabLayout=QHBoxLayout(gpsTab) osmTabLayout=QVBoxLayout(osmTab) debugLogTabLayout=QVBoxLayout(debugLogTab) self.tabs.addTab(dashTab, "Dash") self.tabs.addTab(mainTab, "Main") self.tabs.addTab(miscTab, "Misc 1") self.tabs.addTab(misc2Tab, "Misc 2") self.tabs.addTab(canLogTab, "CAN") self.tabs.addTab(gpsTab, "GPS") self.tabs.addTab(osmTab, "OSM") self.tabs.addTab(debugLogTab, "Log") self.tabs.setCurrentIndex(0) self.debugLogWidget=DebugLogWidget(self) debugLogTabLayout.setAlignment(Qt.AlignLeft|Qt.AlignTop) self.debugLogWidget.addToWidget(debugLogTabLayout) # self.debugLogWidget.addLine("test") self.createCANIdEntry(mainTabLayout, 0x353, "0", "Drehzahl", QLCDNumber.Dec) # self.createCANIdEntry(mainTabLayout, 0x353, "1", "Öltemperatur", QLCDNumber.Dec) self.createCANIdEntry(mainTabLayout, 0x353, "1", "Kuehlwasser Temperatur", QLCDNumber.Dec) self.createCANIdEntry(mainTabLayout, 0x351, "0", "Geschwindigkeit", QLCDNumber.Dec) self.createCANIdEntry(mainTabLayout, 0x351, "1", "Außentemperatur", QLCDNumber.Dec) self.createCANIdEntry(miscTabLayout, 0x635, "0", "Licht, Klemme 58d", QLCDNumber.Dec) self.createCANIdEntry(miscTabLayout, 0x271, "0", "Zuendung", QLCDNumber.Dec) self.createCANIdEntrySingleLine(miscTabLayout, 0x371, ["0", "1"], "Tuerstatus", QLCDNumber.Bin) self.createCANIdEntry(miscTabLayout, 0x371, "2", "Blinker, Retoursgang", QLCDNumber.Bin) self.createCANIdEntrySingleLine(mainTabLayout, 0x623, ["0", "1", "2"], "Uhrzeit (Stunden)", QLCDNumber.Dec) self.createCANIdEntry(mainTabLayout, 0x571, "0", "Batteriespannung", QLCDNumber.Dec) self.createCANIdEntry(misc2TabLayout, 0x3e5, "0", "Zuheizer 1", QLCDNumber.Bin) self.createCANIdEntry(misc2TabLayout, 0x3e5, "1", "Zuheizer 2", QLCDNumber.Bin) self.createCANIdEntry(misc2TabLayout, 0x3e5, "2", "Zuheizer 3", QLCDNumber.Bin) self.createCANIdEntry(misc2TabLayout, 0x3e5, "3", "Zuheizer 4", QLCDNumber.Bin) self.createCANIdEntry(misc2TabLayout, 0x3e5, "4", "Zuheizer 5", QLCDNumber.Bin) self.createCANIdEntry(miscTabLayout, 0x3e5, "5", "Zuheizer", QLCDNumber.Dec) self.createCANIdEntry(miscTabLayout, 0x591, "0", "ZV", QLCDNumber.Dec) self.createCANIdEntry(miscTabLayout, 0x5d1, "0", "Scheibenwischer", QLCDNumber.Dec) self.createCANIdEntrySingleLine(mainTabLayout, 0x351, ["2", "3"], "Wegstreckenimpuls", QLCDNumber.Dec) self.createCANIdEntrySingleLine(misc2TabLayout, 0x621, ["0"], "0x621", QLCDNumber.Bin) self.createCANIdEntrySingleLine(misc2TabLayout, 0x621, ["1", "2"], "0x621", QLCDNumber.Dec) logTabs = MyTabWidget(self) canLogTabLayout.addWidget(logTabs) logTabWidget1=QWidget() logTabWidget2=QWidget() logTabs.addTab(logTabWidget1, "Time") logTabs.addTab(logTabWidget2, "Change") logTab1Layout = QVBoxLayout(logTabWidget1) self.createLogView(logTab1Layout) self.logViewFilerBox1=CANFilterBox(False, self) self.logViewFilerBox1.addFilterBox(logTab1Layout) self.logViewTableBox1=CANLogTableBox(self.logViewModel, self.logBuffer, None, self) self.logViewTableBox1.addTableBox(logTab1Layout) logTab2Layout = QVBoxLayout(logTabWidget2) self.createLogView2(logTab2Layout) self.logViewFilterBox2=CANFilterBox(True, self) self.logViewFilterBox2.addFilterBox(logTab2Layout) self.logViewTableBox2=CANLogTableBox(self.logViewModel2, self.logBuffer2, self.logBufferInit, self) self.logViewTableBox2.addTableBox(logTab2Layout) logButtonBox = QHBoxLayout() canLogTabLayout.addLayout(logButtonBox) self.logFileButton=QCheckBox("Log to File", self) self.logFileButton.setToolTip('Enable file logging') self.logFileButton.resize(self.logFileButton.sizeHint()) self.logFileButton.setDisabled(self.replayMode==True) self.logFileButton.clicked.connect(self._enableLogFile) logButtonBox.addWidget(self.logFileButton) self.clearLogButton = QPushButton('Clear Log', self) self.clearLogButton.resize(self.clearLogButton.sizeHint()) self.clearLogButton.setDisabled(not self.logFileAvailable() or self.replayMode==True) self.clearLogButton.clicked.connect(self._clearLogFile) logButtonBox.addWidget(self.clearLogButton) self.replayButton = QPushButton('Replay Log', self) self.replayButton.resize(self.replayButton.sizeHint()) self.replayButton.setDisabled(not self.logFileAvailable() or self.connectCANEnable==True) self.replayButton.clicked.connect(self._startReplayMode) logButtonBox.addWidget(self.replayButton) self.stopReplayButton = QPushButton('Stop Replay', self) self.stopReplayButton.resize(self.stopReplayButton.sizeHint()) self.stopReplayButton.setDisabled(self.replayMode==False) self.stopReplayButton.clicked.connect(self._stopReplayMode) logButtonBox.addWidget(self.stopReplayButton) velBox = QVBoxLayout() dashTabLayout.addLayout(velBox) dashTabLayout.setAlignment(Qt.AlignCenter|Qt.AlignBottom) self.velGauge=QtPngDialGauge(self, "tacho3", "tacho31.png") self.velGauge.setMinimum(20) self.velGauge.setMaximum(220) self.velGauge.setStartAngle(135) self.velGauge.setValue(0) # self.velGauge.setMaximumSize(400, 400) velBox.addWidget(self.velGauge) self.createCANIdValueEntry(velBox, 0x351, "0", QLCDNumber.Dec) valuesBox = QVBoxLayout() valuesBox.setAlignment(Qt.AlignCenter|Qt.AlignBottom) dashTabLayout.addLayout(valuesBox) self.createCANIdValueEntry(valuesBox, 0x353, "1", QLCDNumber.Dec) self.createCANIdValueEntry(valuesBox, 0x351, "1", QLCDNumber.Dec) self.createCANIdValueEntry(valuesBox, 0x571, "0", QLCDNumber.Dec) rpmBox = QVBoxLayout() dashTabLayout.addLayout(rpmBox) # rpmBox.setAlignment(Qt.AlignCenter|Qt.AlignHCenter) self.rpmGauge=QtPngDialGauge(self, "rpm", "rpm1.png") self.rpmGauge.setMinimum(0) self.rpmGauge.setMaximum(8000) self.rpmGauge.setStartAngle(125) self.rpmGauge.setValue(2500) # self.rpmGauge.setMaximumSize(400, 400) rpmBox.addWidget(self.rpmGauge) self.createCANIdValueEntry(rpmBox, 0x353, "0", QLCDNumber.Dec) self.gpsBox=GPSMonitor(self) gpsTabLayout.setAlignment(Qt.AlignLeft|Qt.AlignTop) self.gpsBox.loadConfig(self.config) self.gpsBox.addToWidget(gpsTabLayout) self.osmWidget=OSMWidget(self) osmTabLayout.setAlignment(Qt.AlignLeft|Qt.AlignTop) self.osmWidget.addToWidget(osmTabLayout) self.osmWidget.loadConfig(self.config) self.osmWidget.initWorkers() self.connect(self.osmWidget.mapWidgetQt, SIGNAL("updateStatus(QString)"), self.updateStatusBarLabel) self.connect(self.osmWidget.downloadThread, SIGNAL("updateStatus(QString)"), self.updateStatusBarLabel) self.connect(self.osmWidget, SIGNAL("updateStatus(QString)"), self.updateStatusBarLabel) self.connect(self.osmWidget, SIGNAL("startProgress()"), self.startProgress) self.connect(self.osmWidget, SIGNAL("stopProgress()"), self.stopProgress) self.osmWidget.initHome() connectBox=QHBoxLayout() top.addLayout(connectBox) section="connect" self.connectCANButton = QCheckBox('CAN Connect', self) self.connectCANButton.clicked.connect(self._connectCAN) self.connectCANEnable=self.config.getSection(section).getboolean("CANconnect", False) self.connectCANButton.setChecked(self.connectCANEnable) self.connectCANButton.setIcon(self.ampelRot) connectBox.addWidget(self.connectCANButton) self.connectGPSButton = QCheckBox('GPS Connect', self) self.connectGPSButton.clicked.connect(self._connectGPS) self.connectGPSEnable=self.config.getSection(section).getboolean("GPSconnect", False) self.connectGPSButton.setChecked(self.connectGPSEnable) self.connectGPSButton.setIcon(self.ampelRot) connectBox.addWidget(self.connectGPSButton) self.setGeometry(0, 0, 900, 600) self.setWindowTitle("candash") self.show() self.updateCANThread = CANSocketWorker(self) self.connect(self.updateCANThread, SIGNAL("updateStatus(QString)"), self.updateStatusBarLabel) self.connect(self.updateCANThread, SIGNAL("updateCANThreadState(QString)"), self.updateCANThreadState) self.connect(self.updateCANThread, SIGNAL("clearAllLCD()"), self.clearAllLCD) self.connect(self.updateCANThread, SIGNAL("connectCANFailed()"), self.connectCANFailed) self.connect(self.updateCANThread, SIGNAL("replayModeDone()"), self.replayModeDone) self.connect(self.updateCANThread, SIGNAL("processCANData(PyQt_PyObject)"), self.canDecoder.scan_can_frame) self._connectCAN() self.updateGPSThread=getGPSUpdateThread(self) if self.updateGPSThread!=None: self.connect(self.updateGPSThread, SIGNAL("updateStatus(QString)"), self.updateStatusBarLabel) self.connect(self.updateGPSThread, SIGNAL("updateGPSThreadState(QString)"), self.updateGPSThreadState) self.connect(self.updateGPSThread, SIGNAL("connectGPSFailed()"), self.connectGPSFailed) self.connect(self.updateGPSThread, SIGNAL("updateGPSDisplay(PyQt_PyObject)"), self.updateGPSDisplay) self._connectGPS() #def mousePressEvent(self, event): # print("CANMonitor mousePressEvent") # self.tabs.mousePressEvent(event) def getWidget(self, canId, subId): try: return self.lcdDict[hex(canId)+":"+subId] except KeyError: return list() def setValueDashDisplayRPM(self, value): if value!=self.rpmGauge.value(): self.rpmGauge.setValue(value) def setValueDashDisplayVel(self, value): if value!=self.velGauge.value(): self.velGauge.setValue(value) def displayIntValue(self, canId, subId, value, formatString): lcdList=self.getWidget(canId, subId) for lcdItem in lcdList: if lcdItem.intValue()!=int(value): lcdItem.display(formatString % value) def displayBinValue(self, canId, subId, value, formatString): lcdList=self.getWidget(canId, subId) for lcdItem in lcdList: if lcdItem.intValue()!=int(value): lcdItem.display(formatString % value) def displayFloatValue(self, canId, subId, value, formatString): lcdList=self.getWidget(canId, subId) for lcdItem in lcdList: if lcdItem.value()!=value: lcdItem.display(formatString % value) def addToLogView(self, line): tableEntry=[self.logEntryCount, self.createTimeStamp()] tableEntry.extend(line[0:]) if self.logFile!=None: self.addToLogFile(tableEntry) if self.logViewTableBox1.update==True: canId=line[0] if not self.logViewFilerBox1.matchFilter(canId, line, None): return self.logBuffer.appendleft(tableEntry) self.logEntryCount=self.logEntryCount+1 if self.logEntryCount==self.maxLogEntryCount: self.logEntryCount=1 self.tableUpdateCouter=self.tableUpdateCouter+1 if self.tableUpdateCouter==10: self.logViewModel.update(self.logBuffer, None) self.tableUpdateCouter=0 def addToLogView2(self, line): if self.logViewTableBox2.update==True: canId=line[0] if not canId in self.logBufferInit.keys(): self.logBufferInit[canId]=line if not self.logViewFilterBox2.matchFilter(canId, line, self.logBufferInit[canId]): try: del self.logBuffer2[canId] except KeyError: None else: self.logBuffer2[canId]=line self.logViewModel2.update(list(self.logBuffer2.values()), self.logBufferInit) def createTimeStamp(self): stamp=datetime.fromtimestamp(time.time()) return "".join(["%02d:%02d:%02d.%06d"%(stamp.hour, stamp.minute, stamp.second, stamp.microsecond)]) def dumpLogLine(self, line): logLine="%s %s %s"% (line[1], hex(line[2]), line[3]) dataLine="".join(["0x%02X " % x for x in line[4]]) return logLine+" "+dataLine def addToLogFile(self, line): if self.logFile!=None: self.logFile.write(self.dumpLogLine(line)+"\n") def setupLogFile(self, filePath): if self.logFile==None: self.logFile=open(filePath,"a") self.logFile.write("# Log started: "+time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime())+"\n") self.logFile.write("# -------------------------------------------------------\n") def closeLogFile(self): if self.logFile!=None: self.logFile.write("# Log stoped: "+time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime())+"\n") self.logFile.write("# -------------------------------------------------------\n") self.logFile.close() self.logFile=None def logFileAvailable(self): try: open(self.logFileName, "r") return True except IOError: return False def readLogFile(self): try: logFileEntries=list() readLogFile=open(self.logFileName, "r") while True: line=readLogFile.readline() if not line: break if line[0]=="#": continue lineParts=line.split(" ") strippedLen=len(lineParts)-1 neededLineParts=lineParts[1:strippedLen] addLen=8-len(neededLineParts[2:]) for _ in range(addLen): neededLineParts.append("%s" % "0x00") logFileEntries.append(struct.pack("IIBBBBBBBB", int(neededLineParts[0], 16), int(neededLineParts[1], 10), int(neededLineParts[2], 16), int(neededLineParts[3], 16),int(neededLineParts[4], 16),int(neededLineParts[5], 16),int(neededLineParts[6], 16), int(neededLineParts[7], 16), int(neededLineParts[8], 16), int(neededLineParts[9], 16))) return logFileEntries except IOError: return list() @pyqtSlot() def _enableFilter(self): self.filter=self.filterButton.isChecked() self.filterEdit.setDisabled(self.filter==False) self.applyFilterButton.setDisabled(self.filter==False) self.filterAll.setDisabled(self.filter==False) self.filterKnown.setDisabled(self.filter==False) self.filterUnknown.setDisabled(self.filter==False) self.filterRingIdsButton.setDisabled(self.filter==False) @pyqtSlot() def _applyFilter(self): if self.filter==True: self.filterValue=self.filterEdit.text() else: self.filterValue="" @pyqtSlot() def _cleanup(self): self.osmWidget._cleanup() self.gpsBox._cleanup() if self.updateCANThread.isRunning(): self.updateCANThread.stop() if self.updateGPSThread.isRunning(): self.updateGPSThread.stop() self.closeLogFile() section="connect" self.config.removeSection(section) self.config.addSection(section) self.config.getSection(section)["canConnect"]=str(self.connectCANEnable) self.config.getSection(section)["gpsConnect"]=str(self.connectGPSEnable) self.osmWidget.saveConfig(self.config) self.gpsBox.saveConfig(self.config) self.config.writeConfig() self.log.writeLogtoFile() @pyqtSlot() def _enableLogFile(self): if self.logFileButton.isChecked()==True: if self.logFile==None: self.setupLogFile(self.logFileName) else: self.closeLogFile() self.replayButton.setDisabled(not self.logFileAvailable() or self.connectCANEnable==True) self.clearLogButton.setDisabled(not self.logFileAvailable() or self.replayMode==True) @pyqtSlot() def _startReplayMode(self): self.closeLogFile() self.logFileButton.setChecked(False) self.replayButton.setDisabled(True) self.replayMode=True self.stopReplayButton.setDisabled(self.replayMode==False) self.logFileButton.setDisabled(self.replayMode==True) self.clearLogButton.setDisabled(not self.logFileAvailable() or self.replayMode==True) replayLines=self.readLogFile() self.logViewTableBox1._clearTable() self.logViewTableBox2._clearTable() self.updateCANThread.setup(self.app, self, self.test, True, replayLines) @pyqtSlot() def _stopReplayMode(self): self.updateCANThread.stop() self.replayModeDone() def replayModeDone(self): self.replayMode=False self.stopReplayButton.setDisabled(self.replayMode==False) self.replayButton.setDisabled(not self.logFileAvailable() or self.connectCANEnable==True) self.logFileButton.setDisabled(self.replayMode==True) self.clearLogButton.setDisabled(not self.logFileAvailable() or self.replayMode==True) @pyqtSlot() def _clearLogFile(self): if self.logFileAvailable(): self.closeLogFile() os.remove(self.logFileName) self.logFile=None self._enableLogFile() @pyqtSlot() def _connectCAN(self): self.connectCANEnable=self.connectCANButton.isChecked() if self.replayMode==True: self._stopReplayMode() if self.connectCANEnable==True: # self.connectCANButton.setDisabled(True) self.logViewTableBox1._clearTable() self.logViewTableBox2._clearTable() self.updateCANThread.setup(self.app, self.connectCANEnable, self.test, False, None) else: if self.updateCANThread.isRunning(): # self.connectCANButton.setDisabled(True) self.updateCANThread.stop() self.replayButton.setDisabled(not self.logFileAvailable() or self.connectCANEnable==True) self.connectCANButton.setChecked(self.connectCANEnable==True) @pyqtSlot() def _connectGPS(self): self.connectGPSEnable=self.connectGPSButton.isChecked() if self.connectGPSEnable==True: # self.connectGPSButton.setDisabled(True) self.updateGPSThread.setup(self.connectGPSEnable) else: if self.updateGPSThread.isRunning(): # self.connectGPSButton.setDisabled(True) self.updateGPSThread.stop() self.connectGPSButton.setChecked(self.connectGPSEnable==True) @pyqtSlot() def _enableFilterRingIds(self): self.filterRingIds=self.filterRingIdsButton.isChecked() def connectCANEnabled(self): return self.connectCANEnable def connectCANFailed(self): self.connectCANEnable=False self.connectCANButton.setChecked(False) # self.connectCANButton.setDisabled(False) self.connectCANButton.setIcon(self.ampelRot) def updateStatusBarLabel(self, text): self.statusbar.showMessage(text) logLine=self.log.addLineToLog(text) self.debugLogWidget.addLineToLog(logLine) def stopProgress(self): self.progress.setMinimum(0) self.progress.setMaximum(1) self.progress.reset() def startProgress(self): self.progress.setMinimum(0) self.progress.setMaximum(0) # def connectCANSuccessful(self): # self.connectCANEnable=True ## self.connectCANButton.setChecked(True) ## self.connectCANButton.setDisabled(False) # self.connectCANButton.setIcon(self.ampelGruen) # def stopCANSuccesful(self): # self.connectCANButton.setDisabled(False) # self.connectCANButton.setIcon(self.ampelRot) def canIdIsInKnownList(self, canId): return canId in self.canIdList def updateGPSDisplay(self, gpsData): self.gpsBox.update(gpsData) def showError(self, title, text): msgBox=QMessageBox(QMessageBox.Warning, title, text, QMessageBox.Ok, self) font = self.font() font.setPointSize(14) msgBox.setFont(font) msgBox.exec() def connectGPSFailed(self): self.connectGPSButton.setChecked(False) self.connectGPSEnable=False # self.connectGPSButton.setDisabled(False) self.connectGPSButton.setIcon(self.ampelRot) self.showError("GPS Error", "Error connecing to GPS") # def connectGPSSuccesful(self): ## self.connectGPSButton.setChecked(True) # self.connectGPSEnable=True ## self.connectGPSButton.setDisabled(False) # self.connectGPSButton.setIcon(self.ampelGruen) def connectGPSEnabled(self): return self.connectGPSEnable # def stopGPSSuccesful(self): # self.connectGPSButton.setDisabled(False) # self.connectGPSButton.setIcon(self.ampelRot) def updateCANThreadState(self, state): if state!=self.lastCANState: if state==canIdleState: self.connectCANButton.setIcon(self.ampelGelb) elif state==canRunState: self.connectCANButton.setIcon(self.ampelGruen) elif state==canStoppedState: self.connectCANButton.setIcon(self.ampelRot) self.connectCANEnable=False self.lastCANState=state def updateGPSThreadState(self, state): if state!=self.lastGPSState: if state==gpsRunState: self.connectGPSButton.setIcon(self.ampelGruen) elif state==gpsStoppedState: self.connectGPSButton.setIcon(self.ampelRot) self.connectGPSnable=False self.lastGPSState=state def hasOSMWidget(self): return self.osmWidget!=None