def __init__(self, parent=None): super().__init__(parent) self._model = LogRecordModel() filter_model = QSortFilterProxyModel() filter_model.setSourceModel(self._model) filter_model.setFilterKeyColumn(3) self.msg_filter = QLineEdit() self.log_view = QTableView() self.log_view.setModel(filter_model) header = self.log_view.horizontalHeader() #header.setSectionResizeMode(header.Stretch) header.setStretchLastSection(True) self.status_label = QLabel() # Connect signals: self.msg_filter.textChanged.connect(filter_model.setFilterFixedString) # Make nice layout: layout = QVBoxLayout(self) layout.addWidget(self.msg_filter) layout.addWidget(self.log_view) layout.addWidget(self.status_label) # Attach udp server: self._udpServer = UdpHandler(self._model) self._model.stats_changed.connect(self.status_label.setText)
class UserAgentsDialog(QDialog, Ui_UserAgentsDialog): """ Class implementing a dialog to show all saved user agent settings. """ def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super(UserAgentsDialog, self).__init__(parent) self.setupUi(self) self.removeButton.clicked.connect( self.userAgentsTable.removeSelected) self.removeAllButton.clicked.connect( self.userAgentsTable.removeAll) self.userAgentsTable.verticalHeader().hide() self.__userAgentModel = UserAgentModel( Helpviewer.HelpWindow.HelpWindow.userAgentsManager(), self) self.__proxyModel = QSortFilterProxyModel(self) self.__proxyModel.setSourceModel(self.__userAgentModel) self.searchEdit.textChanged.connect( self.__proxyModel.setFilterFixedString) self.userAgentsTable.setModel(self.__proxyModel) fm = QFontMetrics(QFont()) height = fm.height() + fm.height() // 3 self.userAgentsTable.verticalHeader().setDefaultSectionSize(height) self.userAgentsTable.verticalHeader().setMinimumSectionSize(-1) self.userAgentsTable.resizeColumnsToContents() self.userAgentsTable.horizontalHeader().setStretchLastSection(True)
def setSourceModel(self, model): QSortFilterProxyModel.setSourceModel(self, model) self.sourceModel().dataChanged.connect(self.mapModelMaybe) self.sourceModel().rowsInserted.connect(self.mapModel) self.sourceModel().rowsRemoved.connect(self.mapModel) self.sourceModel().rowsMoved.connect(self.mapModel) self.mapModel()
def __init__(self, core, parent=None): super().__init__(parent) uic.loadUi(resource_path('data/ObjectsTab.ui'), self) self._core = core model = models.ObjectModel(self._core.inv) proxyModel = QSortFilterProxyModel() proxyModel.setSourceModel(model) self.tableView.setModel(proxyModel)
def initUI(self, db): equipment = EquipmentModel(db) self.setModel(equipment) self.setStates() self.setSelectionMode(QAbstractItemView.MultiSelection) self.setSelectionBehavior(QAbstractItemView.SelectRows) self.setSizes() proxy = QSortFilterProxyModel() self.setModel(proxy) proxy.setSourceModel(equipment)
class ZoomValuesDialog(QDialog, Ui_ZoomValuesDialog): """ Class implementing a dialog to show all saved zoom values. """ def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super(ZoomValuesDialog, self).__init__(parent) self.setupUi(self) self.removeButton.clicked.connect( self.zoomValuesTable.removeSelected) self.removeAllButton.clicked.connect(self.zoomValuesTable.removeAll) import Helpviewer.HelpWindow from .ZoomValuesModel import ZoomValuesModel self.zoomValuesTable.verticalHeader().hide() self.__zoomValuesModel = ZoomValuesModel( Helpviewer.HelpWindow.HelpWindow.zoomManager(), self) self.__proxyModel = QSortFilterProxyModel(self) self.__proxyModel.setSourceModel(self.__zoomValuesModel) self.searchEdit.textChanged.connect( self.__proxyModel.setFilterFixedString) self.zoomValuesTable.setModel(self.__proxyModel) fm = QFontMetrics(QFont()) height = fm.height() + fm.height() // 3 self.zoomValuesTable.verticalHeader().setDefaultSectionSize(height) self.zoomValuesTable.verticalHeader().setMinimumSectionSize(-1) self.__calculateHeaderSizes() def __calculateHeaderSizes(self): """ Private method to calculate the section sizes of the horizontal header. """ fm = QFontMetrics(QFont()) for section in range(self.__zoomValuesModel.columnCount()): header = self.zoomValuesTable.horizontalHeader()\ .sectionSizeHint(section) if section == 0: header = fm.width("extraveryveryverylongsitename") elif section == 1: header = fm.width("averagelongzoomvalue") buffer = fm.width("mm") header += buffer self.zoomValuesTable.horizontalHeader()\ .resizeSection(section, header) self.zoomValuesTable.horizontalHeader().setStretchLastSection(True)
class ClickToFlashWhitelistDialog(QDialog, Ui_ClickToFlashWhitelistDialog): """ Class implementing a dialog to manage the ClickToFlash whitelist. """ def __init__(self, whitelist, parent=None): """ Constructor @param whitelist list of whitelisted hosts (list of string) @param parent reference to the parent widget (QWidget) """ super(ClickToFlashWhitelistDialog, self).__init__(parent) self.setupUi(self) self.iconLabel.setPixmap(UI.PixmapCache.getPixmap("flashBlock48.png")) self.__model = QStringListModel(whitelist[:], self) self.__model.sort(0) self.__proxyModel = QSortFilterProxyModel(self) self.__proxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive) self.__proxyModel.setSourceModel(self.__model) self.whitelist.setModel(self.__proxyModel) self.searchEdit.textChanged.connect( self.__proxyModel.setFilterFixedString) self.removeButton.clicked.connect(self.whitelist.removeSelected) self.removeAllButton.clicked.connect(self.whitelist.removeAll) @pyqtSlot() def on_addButton_clicked(self): """ Private slot to add an entry to the whitelist. """ host, ok = QInputDialog.getText( self, self.tr("ClickToFlash Whitelist"), self.tr("Enter host name to add to whitelist:"), QLineEdit.Normal) if ok and host != "" and host not in self.__model.stringList(): self.__model.insertRow(self.__model.rowCount()) self.__model.setData( self.__model.index(self.__model.rowCount() - 1), host) self.__model.sort(0) def getWhitelist(self): """ Public method to get the whitelisted hosts. @return list of whitelisted hosts (list of string) """ return self.__model.stringList()
def __init__(self, parent=None): QSortFilterProxyModel.__init__(self, parent) # self.rootItem = QStandardItem() self.p1 = QStandardItem(self.tr("Main")) self.p2 = QStandardItem(self.tr("Secundary")) self.p3 = QStandardItem(self.tr("Minors")) self._cats = [ self.p1, self.p2, self.p3 ]
class E5ErrorMessageFilterDialog(QDialog, Ui_E5ErrorMessageFilterDialog): """ Class implementing a dialog to manage the list of messages to be ignored. """ def __init__(self, messageFilters, parent=None): """ Constructor @param messageFilters list of message filters to be edited (list of strings) @param parent reference to the parent widget (QWidget) """ super(E5ErrorMessageFilterDialog, self).__init__(parent) self.setupUi(self) self.__model = QStringListModel(messageFilters, self) self.__model.sort(0) self.__proxyModel = QSortFilterProxyModel(self) self.__proxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive) self.__proxyModel.setSourceModel(self.__model) self.filterList.setModel(self.__proxyModel) self.searchEdit.textChanged.connect( self.__proxyModel.setFilterFixedString) self.removeButton.clicked.connect(self.filterList.removeSelected) self.removeAllButton.clicked.connect(self.filterList.removeAll) @pyqtSlot() def on_addButton_clicked(self): """ Private slot to add an entry to the list. """ filter, ok = QInputDialog.getText( self, self.tr("Error Messages Filter"), self.tr("Enter message filter to add to the list:"), QLineEdit.Normal) if ok and filter != "" and filter not in self.__model.stringList(): self.__model.insertRow(self.__model.rowCount()) self.__model.setData( self.__model.index(self.__model.rowCount() - 1), filter) self.__model.sort(0) def getFilters(self): """ Public method to get the list of message filters. @return error message filters (list of strings) """ return self.__model.stringList()[:]
class SqlRelationalTableModel(QtSql.QSqlRelationalTableModel): def __init__(self, model, parent, db): super().__init__(parent, db) self.model = model self._proxyModel = QSortFilterProxyModel(self) self._proxyModel.setSortLocaleAware(True) self._proxyModel.setSourceModel(self) def relationModel(self, _column): return self.model def data(self, index, role=Qt.DisplayRole): if role == Qt.DecorationRole: if index.row() < 0: return None iconIndex = self.index(index.row(), self.fieldIndex('icon')) if not self.data(iconIndex) or self.data(iconIndex).isNull(): return None icon = QPixmap() icon.loadFromData(self.data(iconIndex)) return icon return super().data(index, role) def proxyModel(self): return self._proxyModel def sort(self, sort=True): if sort: self._proxyModel.sort(self.fieldIndex('value')) else: self._proxyModel.sort(-1)
def __init__(self, settings, directory, check_id_fct, annotations_path, parent=None): super().__init__(parent) # FIXME Delayed refactoring of check_id_fct and annotations_path. # Variables section. library_id = settings["libraryID"] library_type = settings["libraryType"] api_key = settings["apiKey"] self._zotero = ZoteroWrap(library_id, library_type, api_key, directory) # Widgets section. model = ZoteroTableModel(self._zotero, check_id_fct, annotations_path) model.load() proxy_model = QSortFilterProxyModel() proxy_model.setSourceModel(model) proxy_model.setDynamicSortFilter(True) proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive) proxy_model.setFilterKeyColumn(-1) # NB: All columns. self.view = QTableView(self) self.view.setModel(proxy_model) self.view.setCornerButtonEnabled(False) self.view.setEditTriggers(QAbstractItemView.NoEditTriggers) self.view.setSelectionBehavior(QAbstractItemView.SelectRows) self.view.setSelectionMode(QAbstractItemView.SingleSelection) # NB: Triggers a call to sortByColumn() which sorts by the first column. self.view.setSortingEnabled(True) self.view.setWordWrap(False) self.view.verticalHeader().hide() self.filter_edit = FilterEdit(self.view) # NB: The thread does not begin executing until start() is called. self.refresh_thread = ZoteroRefreshThread(model, self) # Layouts section. header_layout = QFormLayout() header_layout.addRow("Filter:", self.filter_edit) header_layout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) utils.configure_form_layout(header_layout) main_layout = QVBoxLayout() main_layout.addLayout(header_layout) main_layout.addWidget(self.view) self.setLayout(main_layout) # Signals section. self.filter_edit.textChanged.connect(proxy_model.setFilterFixedString) self.refresh_thread.started.connect(self.refresh_started) self.refresh_thread.finished.connect(self.refresh_finished)
class NoCacheHostsDialog(QDialog, Ui_NoCacheHostsDialog): """ Class implementing a dialog to manage the list of hosts not to be cached. """ def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super(NoCacheHostsDialog, self).__init__(parent) self.setupUi(self) self.__model = QStringListModel( Preferences.getHelp("NoCacheHosts"), self) self.__model.sort(0) self.__proxyModel = QSortFilterProxyModel(self) self.__proxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive) self.__proxyModel.setSourceModel(self.__model) self.noCacheList.setModel(self.__proxyModel) self.searchEdit.textChanged.connect( self.__proxyModel.setFilterFixedString) self.removeButton.clicked.connect(self.noCacheList.removeSelected) self.removeAllButton.clicked.connect(self.noCacheList.removeAll) @pyqtSlot() def on_addButton_clicked(self): """ Private slot to add an entry to the list. """ host, ok = QInputDialog.getText( self, self.tr("Not Cached Hosts"), self.tr("Enter host name to add to the list:"), QLineEdit.Normal) if ok and host != "" and host not in self.__model.stringList(): self.__model.insertRow(self.__model.rowCount()) self.__model.setData( self.__model.index(self.__model.rowCount() - 1), host) self.__model.sort(0) def accept(self): """ Public method to accept the dialog data. """ Preferences.setHelp("NoCacheHosts", self.__model.stringList()) super(NoCacheHostsDialog, self).accept()
def __init__(self, database, main_spectrum = None): super(ReferenceSpectraDialog, self).__init__() self.main_spectrum = main_spectrum self.ui = Ui_ReferenceSpectraDialog() self.ui.setupUi(self) self.reference_catalogues = ReferenceCatalogues(database) self.full_model = QStandardItemModel() self.catalogues_model = QStandardItemModel() self.ui.catalogue.setModel(self.catalogues_model) self.ui.catalogue.currentTextChanged.connect(lambda txt: self.populate()) for catname, cat in self.reference_catalogues.catalogues.items(): row = QStandardItem(catname) row.setData(cat) self.catalogues_model.appendRow(row) self.model = QSortFilterProxyModel() self.model.setSourceModel(self.full_model) self.model.setFilterCaseSensitivity(Qt.CaseInsensitive) self.model.setFilterKeyColumn(0) self.ui.entries.setModel(self.model) self.ui.type_filter.currentTextChanged.connect(lambda txt: self.model.setFilterWildcard("{}*".format(txt) ) ) self.ui.buttonBox.button(QDialogButtonBox.Open).setEnabled(False) self.ui.entries.selectionModel().selectionChanged.connect(lambda selected, deselected: self.ui.buttonBox.button(QDialogButtonBox.Open).setEnabled(len(selected.indexes()) > 0) ) self.accepted.connect(self.load_fits) self.populate()
def get_widget(self): if self.widget is None: self.widget = QWidget() self.ui = properties_dock_ui.Ui_PropertiesDock() self.ui.setupUi(self.widget) if self.tree_sheet is not None and self.core_part is not None: table_model = self.core_part.property_table_model # filter : self.filter = QSortFilterProxyModel(self.widget) self.filter.setFilterKeyColumn(-1) self.filter.setFilterCaseSensitivity(False) self.filter.setSourceModel(table_model) # model : self.ui.tableView.setModel(self.filter) # connect : self.ui.addPropButton.clicked.connect(self.add_property_row) self.ui.removePropButton.clicked.connect( self.remove_property_row) self.ui.filterLineEdit.textChanged.connect( self.filter.setFilterFixedString) self.ui.tableView.clicked.connect(self.set_current_row) self.widget.gui_part = self return self.widget
def __init__(self): QDialog.__init__(self) self.setupUi(self) self.settings = MySettings() SettingDialog.__init__(self, self.settings) # new declaration of ProjectFinder since changes can be cancelled self.project_finder = ProjectFinder(self) # table model self.project_search_model = ProjectSearchModel(self.project_finder) self.proxyModel = QSortFilterProxyModel(self) self.proxyModel.setSourceModel(self.project_search_model) self.projectSearchTable.setModel(self.proxyModel) header = self.projectSearchTable.horizontalHeader() header.setSectionResizeMode(QHeaderView.ResizeToContents) # open/create QuickFinder file self.createFileButton.clicked.connect(self.create_QFTS_file) self.openFileButton.clicked.connect(self.open_QFTS_file) self.read_QFTS_file() # project search self.addSearchButton.clicked.connect(self.add_project_search) self.removeSearchButton.clicked.connect(self.remove_project_search) self.editSearchButton.clicked.connect(self.edit_project_search) self.refreshButton.clicked.connect(self.refresh_project_search) self.projectSearchTable.selectionModel().selectionChanged.connect(self.enableButtons) self.enableButtons() # geomapfish self.geomapfishCrsButton.clicked.connect(self.geomapfishCrsButtonClicked)
def __init__(self, model, parent, db): super().__init__(parent, db) self.model = model self._proxyModel = QSortFilterProxyModel(self) self._proxyModel.setSortLocaleAware(True) self._proxyModel.setSourceModel(self)
def __init__(self, data, info, parent=None): """ Constructor @param data contents to be edited (string) @param info info string to show at the header (string) @param parent reference to the parent widget (QWidget) """ super(SpellingDictionaryEditDialog, self).__init__(parent) self.setupUi(self) self.infoLabel.setText(info) self.__model = QStringListModel(data.splitlines(), self) self.__model.sort(0) self.__proxyModel = QSortFilterProxyModel(self) self.__proxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive) self.__proxyModel.setDynamicSortFilter(True) self.__proxyModel.setSourceModel(self.__model) self.wordList.setModel(self.__proxyModel) self.searchEdit.textChanged.connect( self.__proxyModel.setFilterFixedString) self.removeButton.clicked.connect(self.wordList.removeSelected) self.removeAllButton.clicked.connect(self.wordList.removeAll)
def display(self, incidents, locations): self.model = IncidentModel(incidents, locations, self) self.proxy = QSortFilterProxyModel(self) self.proxy.setSourceModel(self.model) self.proxy.setFilterRole(self.model.filter_role) self.proxy.setFilterRegExp(QRegExp(self.filter.text())) self.view.setModel(self.proxy)
def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super(ZoomValuesDialog, self).__init__(parent) self.setupUi(self) self.removeButton.clicked.connect( self.zoomValuesTable.removeSelected) self.removeAllButton.clicked.connect(self.zoomValuesTable.removeAll) import Helpviewer.HelpWindow from .ZoomValuesModel import ZoomValuesModel self.zoomValuesTable.verticalHeader().hide() self.__zoomValuesModel = ZoomValuesModel( Helpviewer.HelpWindow.HelpWindow.zoomManager(), self) self.__proxyModel = QSortFilterProxyModel(self) self.__proxyModel.setSourceModel(self.__zoomValuesModel) self.searchEdit.textChanged.connect( self.__proxyModel.setFilterFixedString) self.zoomValuesTable.setModel(self.__proxyModel) fm = QFontMetrics(QFont()) height = fm.height() + fm.height() // 3 self.zoomValuesTable.verticalHeader().setDefaultSectionSize(height) self.zoomValuesTable.verticalHeader().setMinimumSectionSize(-1) self.__calculateHeaderSizes()
def lessThan(self, left, right): if left.column() == 1: # size return left.data(USER_ROLE_SIZE) < right.data(USER_ROLE_SIZE) elif left.column() == 2: # last modified return left.data(USER_ROLE_LAST_MODIFIED) < right.data(USER_ROLE_LAST_MODIFIED) return QSortFilterProxyModel.lessThan(self, left, right)
def setupUi(self): self.load_ui("typeattrquery.ui") # populate attr list self.attr_model = SEToolsListModel(self) self.attr_model.item_list = sorted(r for r in self.policy.typeattributes()) self.attrs.setModel(self.attr_model) # populate type list self.type_model = SEToolsListModel(self) self.type_model.item_list = sorted(self.policy.types()) self.types.setModel(self.type_model) # set up results self.table_results_model = TypeAttributeTableModel(self) self.sort_proxy = QSortFilterProxyModel(self) self.sort_proxy.setSourceModel(self.table_results_model) self.table_results.setModel(self.sort_proxy) self.table_results.sortByColumn(0, Qt.AscendingOrder) # setup indications of errors on level/range self.orig_palette = self.name.palette() self.error_palette = self.name.palette() self.error_palette.setColor(QPalette.Base, Qt.red) self.clear_name_error() # set up processing thread self.thread = QThread() self.worker = QueryResultsUpdater(self.query, self.table_results_model) self.worker.moveToThread(self.thread) self.worker.raw_line.connect(self.raw_results.appendPlainText) self.worker.finished.connect(self.update_complete) self.worker.finished.connect(self.thread.quit) self.thread.started.connect(self.worker.update) # create a "busy, please wait" dialog self.busy = QProgressDialog(self) self.busy.setModal(True) self.busy.setRange(0, 0) self.busy.setMinimumDuration(0) self.busy.canceled.connect(self.thread.requestInterruption) self.busy.reset() # update busy dialog from query INFO logs self.handler = LogHandlerToSignal() self.handler.message.connect(self.busy.setLabelText) logging.getLogger("setools.typeattrquery").addHandler(self.handler) # Ensure settings are consistent with the initial .ui state self.notes.setHidden(not self.notes_expander.isChecked()) # connect signals self.attrs.doubleClicked.connect(self.get_detail) self.attrs.get_detail.triggered.connect(self.get_detail) self.name.textEdited.connect(self.clear_name_error) self.name.editingFinished.connect(self.set_name) self.name_regex.toggled.connect(self.set_name_regex) self.types.selectionModel().selectionChanged.connect(self.set_types) self.invert_types.clicked.connect(self.invert_type_selection) self.buttonBox.clicked.connect(self.run)
def lessThan(self, left, right): if left.column() != 2: # position return QSortFilterProxyModel.lessThan(self, left, right) # Sort letters before digits, so that Bricklets connected to a # Master Brick are shown before Bricks stacked on the Master. # Also sort extensions after letters (i.e Bricks), so they are shown last. # Also sort slave stacks, having position 0, (i.e. from a RS485 Extension) # behind Bricks stacked on the Master. def get_sort_key(data): if len(data) == 0: # Put empty string before everything return 0 diff = ord('z') - ord('0') + 1 # Put digits after letters if data.isdigit(): # Swap 0 behind 1-9 if data == '0': diff += 9 else: diff -= 1 if 'Ext' in data: diff += 10 # Put digits of extensions after normal digits data = data[3:] return ord(data) + (diff if data.isdigit() else 0) # Compare by name if the position is the same if get_sort_key(left.data()) == get_sort_key(right.data()): return left.sibling(left.row(), 0).data() < right.sibling(right.row(), 0).data() return get_sort_key(left.data()) < get_sort_key(right.data())
def columnCount(self, parent): """ Public method to return the number of columns. @param parent index of the parent (QModelIndex) @return number of columns (integer) """ return min(1, QSortFilterProxyModel.columnCount(self, parent))
class CompletingComboBox(QComboBox): """An editable combo box that filters and autocompletes.""" def __init__(self, parent=None): super().__init__(parent) self.setEditable(True) self.filter = QSortFilterProxyModel(self) self.filter.setFilterCaseSensitivity(Qt.CaseInsensitive) self.filter.setSourceModel(self.model()) self.completer = QCompleter(self.filter, self) self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) self.setCompleter(self.completer) self.lineEdit().textEdited.connect( self.filter.setFilterFixedString) self.currentIndexChanged.connect(self._index_changed) def _index_changed(self, index): self.lineEdit().selectAll()
def setupUi(self): self.load_ui("apol/defaultquery.ui") # set up results self.table_results_model = DefaultTableModel(self) self.sort_proxy = QSortFilterProxyModel(self) self.sort_proxy.setSourceModel(self.table_results_model) self.table_results.setModel(self.sort_proxy) self.table_results.sortByColumn(1, Qt.AscendingOrder) # populate class list self.class_model = SEToolsListModel(self) self.class_model.item_list = sorted(self.policy.classes()) self.tclass.setModel(self.class_model) # these two lists have empty string as their first item # (in the .ui file): # populate default value list for i, e in enumerate(DefaultValue, start=1): self.default_value.insertItem(i, e.name, e) # populate default range value list for i, e in enumerate(DefaultRangeValue, start=1): self.default_range_value.insertItem(i, e.name, e) # set up processing thread self.thread = QThread() self.worker = QueryResultsUpdater(self.query, self.table_results_model) self.worker.moveToThread(self.thread) self.worker.raw_line.connect(self.raw_results.appendPlainText) self.worker.finished.connect(self.update_complete) self.worker.finished.connect(self.thread.quit) self.thread.started.connect(self.worker.update) # create a "busy, please wait" dialog self.busy = QProgressDialog(self) self.busy.setModal(True) self.busy.setRange(0, 0) self.busy.setMinimumDuration(0) self.busy.canceled.connect(self.thread.requestInterruption) self.busy.reset() # update busy dialog from query INFO logs self.handler = LogHandlerToSignal() self.handler.message.connect(self.busy.setLabelText) logging.getLogger("setools.defaultquery").addHandler(self.handler) # Ensure settings are consistent with the initial .ui state self.default_range_value.setEnabled(self.default_range.isChecked()) self.notes.setHidden(not self.notes_expander.isChecked()) # connect signals self.default_range.toggled.connect(self.default_range_value.setEnabled) self.clear_ruletypes.clicked.connect(self.clear_all_ruletypes) self.all_ruletypes.clicked.connect(self.set_all_ruletypes) self.tclass.selectionModel().selectionChanged.connect(self.set_tclass) self.invert_class.clicked.connect(self.invert_tclass_selection) self.buttonBox.clicked.connect(self.run)
class TagChooser(QListView): changed = Signal() def __init__(self, db): super(TagChooser,self).__init__() self.db = db self.filter = u'' self.data = QStandardItemModel() self.proxy = QSortFilterProxyModel() self.proxy.setSourceModel(self.data) self.setModel(self.proxy) self.data.itemChanged.connect(self.changed) for t in sorted(self.db.list_tags()): item = QStandardItem(t) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setCheckState(Qt.Unchecked) self.data.appendRow(item) def setTags(self, tags): for i in range(self.data.rowCount()): item = self.data.item(i) if item.text() in tags: item.setCheckState(Qt.Checked) else: item.setCheckState(Qt.Unchecked) def selectedTags(self): tags = [] for i in range(self.data.rowCount()): item = self.data.item(i) if item.checkState() == Qt.Checked: tags.append(item.text()) return tags def matchingFiles(self): tags = self.selectedTags() if not tags: return [] res = list(self.db.find_files_by_tags(tags)) res.sort() return res
def __init__(self, networkAccessManager, parent=None): """ Constructor @param networkAccessManager reference to the network access manager (QNetworkAccessManager) @param parent reference to the parent widget (QWidget) """ super(E5NetworkMonitor, self).__init__(parent) self.setupUi(self) self.setWindowFlags(Qt.Window) self.__requestHeaders = QStandardItemModel(self) self.__requestHeaders.setHorizontalHeaderLabels( [self.tr("Name"), self.tr("Value")]) self.requestHeadersList.setModel(self.__requestHeaders) self.requestHeadersList.horizontalHeader().setStretchLastSection(True) self.requestHeadersList.doubleClicked.connect(self.__showHeaderDetails) self.__replyHeaders = QStandardItemModel(self) self.__replyHeaders.setHorizontalHeaderLabels( [self.tr("Name"), self.tr("Value")]) self.responseHeadersList.setModel(self.__replyHeaders) self.responseHeadersList.horizontalHeader().setStretchLastSection(True) self.responseHeadersList.doubleClicked.connect( self.__showHeaderDetails) self.requestsList.horizontalHeader().setStretchLastSection(True) self.requestsList.verticalHeader().setMinimumSectionSize(-1) self.__proxyModel = QSortFilterProxyModel(self) self.__proxyModel.setFilterKeyColumn(-1) self.searchEdit.textChanged.connect( self.__proxyModel.setFilterFixedString) self.removeButton.clicked.connect(self.requestsList.removeSelected) self.removeAllButton.clicked.connect(self.requestsList.removeAll) self.__model = E5RequestModel(networkAccessManager, self) self.__proxyModel.setSourceModel(self.__model) self.requestsList.setModel(self.__proxyModel) self.__proxyModel.rowsInserted.connect( self.requestsList.scrollToBottom) self.requestsList.selectionModel()\ .currentChanged[QModelIndex, QModelIndex]\ .connect(self.__currentChanged) fm = self.fontMetrics() em = fm.width("m") self.requestsList.horizontalHeader().resizeSection(0, em * 5) self.requestsList.horizontalHeader().resizeSection(1, em * 20) self.requestsList.horizontalHeader().resizeSection(3, em * 5) self.requestsList.horizontalHeader().resizeSection(4, em * 15) self.__headersDlg = None
def filterAcceptsRow(self, sourceRow, sourceParent): index = self.sourceModel().index(sourceRow, 0, sourceParent) rowCount = self.sourceModel().rowCount(index) accepted = QSortFilterProxyModel.filterAcceptsRow(self, sourceRow, sourceParent) if rowCount > 0 and not accepted: for row in range(rowCount): if self.filterAcceptsRow(row, index): return True return accepted
def __init__(self, parent=None): super().__init__(parent) self.setEditable(True) self.filter = QSortFilterProxyModel(self) self.filter.setFilterCaseSensitivity(Qt.CaseInsensitive) self.filter.setSourceModel(self.model()) self.completer = QCompleter(self.filter, self) self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) self.setCompleter(self.completer) self.lineEdit().textEdited.connect( self.filter.setFilterFixedString) self.currentIndexChanged.connect(self._index_changed)
def main(): app = QGuiApplication(sys.argv) app.setApplicationName('InfiniteCopy') openDataBase() view = QQuickView() clipboardItemModel = ClipboardItemModel() clipboardItemModel.create() filterProxyModel = QSortFilterProxyModel() filterProxyModel.setSourceModel(clipboardItemModel) clipboard = Clipboard() clipboard.setFormats([ mimeText, mimeHtml, mimePng, mimeSvg ]) clipboard.changed.connect(clipboardItemModel.addItem) engine = view.engine() imageProvider = ClipboardItemModelImageProvider(clipboardItemModel) engine.addImageProvider("items", imageProvider) context = view.rootContext() context.setContextProperty('clipboardItemModel', clipboardItemModel) context.setContextProperty('clipboardItemModelFilterProxy', filterProxyModel) context.setContextProperty('clipboard', clipboard) view.setSource(QUrl.fromLocalFile('qml/MainWindow.qml')) view.setGeometry(100, 100, 400, 240) view.show() engine.quit.connect(QGuiApplication.quit) return app.exec_()
class CookiesDialog(QDialog, Ui_CookiesDialog): """ Class implementing a dialog to show all cookies. """ def __init__(self, cookieJar, parent=None): """ Constructor @param cookieJar reference to the cookie jar (CookieJar) @param parent reference to the parent widget (QWidget) """ super(CookiesDialog, self).__init__(parent) self.setupUi(self) self.addButton.setEnabled(False) self.__cookieJar = cookieJar self.removeButton.clicked.connect(self.cookiesTable.removeSelected) self.removeAllButton.clicked.connect(self.cookiesTable.removeAll) self.cookiesTable.verticalHeader().hide() model = CookieModel(cookieJar, self) self.__proxyModel = QSortFilterProxyModel(self) self.__proxyModel.setSourceModel(model) self.searchEdit.textChanged.connect( self.__proxyModel.setFilterFixedString) self.cookiesTable.setModel(self.__proxyModel) self.cookiesTable.doubleClicked.connect(self.__showCookieDetails) self.cookiesTable.selectionModel().selectionChanged.connect( self.__tableSelectionChanged) self.cookiesTable.model().modelReset.connect(self.__tableModelReset) fm = QFontMetrics(QFont()) height = fm.height() + fm.height() // 3 self.cookiesTable.verticalHeader().setDefaultSectionSize(height) self.cookiesTable.verticalHeader().setMinimumSectionSize(-1) for section in range(model.columnCount()): header = self.cookiesTable.horizontalHeader()\ .sectionSizeHint(section) if section == 0: header = fm.width("averagebiglonghost.averagedomain.info") elif section == 1: header = fm.width("_session_id") elif section == 4: header = fm.width(QDateTime.currentDateTime().toString( Qt.LocalDate)) buffer = fm.width("mm") header += buffer self.cookiesTable.horizontalHeader().resizeSection(section, header) self.cookiesTable.horizontalHeader().setStretchLastSection(True) self.cookiesTable.model().sort( self.cookiesTable.horizontalHeader().sortIndicatorSection(), Qt.AscendingOrder) self.__detailsDialog = None def __showCookieDetails(self, index): """ Private slot to show a dialog with the cookie details. @param index index of the entry to show (QModelIndex) """ if not index.isValid(): return cookiesTable = self.sender() if cookiesTable is None: return model = cookiesTable.model() row = index.row() domain = model.data(model.index(row, 0)) name = model.data(model.index(row, 1)) path = model.data(model.index(row, 2)) secure = model.data(model.index(row, 3)) expires = model.data(model.index(row, 4)).toString("yyyy-MM-dd hh:mm") value = bytes( QByteArray.fromPercentEncoding(model.data(model.index( row, 5)))).decode() if self.__detailsDialog is None: from .CookieDetailsDialog import CookieDetailsDialog self.__detailsDialog = CookieDetailsDialog(self) self.__detailsDialog.setData(domain, name, path, secure, expires, value) self.__detailsDialog.show() @pyqtSlot() def on_addButton_clicked(self): """ Private slot to add a new exception. """ selection = self.cookiesTable.selectionModel().selectedRows() if len(selection) == 0: return from .CookiesExceptionsDialog import CookiesExceptionsDialog firstSelected = selection[0] domainSelection = firstSelected.sibling(firstSelected.row(), 0) domain = self.__proxyModel.data(domainSelection, Qt.DisplayRole) dlg = CookiesExceptionsDialog(self.__cookieJar, self) dlg.setDomainName(domain) dlg.exec_() def __tableSelectionChanged(self, selected, deselected): """ Private slot to handle a change of selected items. @param selected selected indexes (QItemSelection) @param deselected deselected indexes (QItemSelection) """ self.addButton.setEnabled(len(selected.indexes()) > 0) def __tableModelReset(self): """ Private slot to handle a reset of the cookies table. """ self.addButton.setEnabled(False)
def setSourceModel(self, source_model): try: self.source_model = source_model QSortFilterProxyModel.setSourceModel(self, self.source_model) except Exception as e: logging.exception('exception occurred')
def __init__(self, parent): QSortFilterProxyModel.__init__(self, parent) self.source_model: ExtSortFilterTableModel = None
from PyQt5.QtGui import QStandardItemModel, QStandardItem from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLineEdit, QTableView app = QApplication([]) window = QWidget() # standard item model model = QStandardItemModel(5, 3) model.setHorizontalHeaderLabels(['ID', 'DATE', 'VALUE']) for row, text in enumerate(['Cell', 'Fish', 'Apple', 'Ananas', 'Mango'] * 20000): item = QStandardItem(text) model.setItem(row, 2, item) # filter proxy model filter_proxy_model = QSortFilterProxyModel() filter_proxy_model.setSourceModel(model) filter_proxy_model.setFilterKeyColumn(2) # third column # line edit for filtering layout = QVBoxLayout(window) line_edit = QLineEdit() line_edit.textChanged.connect(filter_proxy_model.setFilterRegExp) layout.addWidget(line_edit) # table view table = QTableView() table.setModel(filter_proxy_model) layout.addWidget(table) window.show()
class Services(QWidget): """ Klasa odpowiedzialna za widget usług """ def __init__(self, parent, db): super(QWidget, self).__init__(parent) self.parent = parent self.proxy = QSortFilterProxyModel(self) self.view = QTableView() self.txt_nazwa = QLineEdit() self.txt_cena = QLineEdit() self.txt_czas = QLineEdit() self.txt_opis = QTextEdit() self.btn_mod = QPushButton('Modyfikuj') self.btn_usun = QPushButton('Usuń') self.id_modify = -1 # Parametry połączenia z bazą self.model = QSqlTableModel(self, db) self.initUI() def initUI(self): """ Inicjuje UI """ self.table_init() self.btn_usun.setDisabled(True) self.btn_mod.setDisabled(True) self.txt_czas.setInputMask('99:00') # Tworzenie kontrolek lbl_wysz = QLabel("Wyszukaj zabieg:") txt_wysz = QLineEdit(self) btn_dodaj = QPushButton('Dodaj') lbl_nazwa = QLabel('Nazwa:') lbl_cena = QLabel('Cena:') lbl_czas = QLabel('Czas:') lbl_opis = QLabel('Opis:') # Tworzenie widoków centralbox = QHBoxLayout() findbox = QHBoxLayout() vbox = QVBoxLayout() groupbox = QGroupBox('Zabiegi') groupbox_layout = QVBoxLayout() button_hbox = QHBoxLayout() formbox = QFormLayout() # Metody self.view.clicked.connect(self.change) txt_wysz.textChanged.connect(self.searching) btn_dodaj.clicked.connect(self.add) self.btn_mod.clicked.connect(self.modify) self.btn_usun.clicked.connect(self.remove) # Ustawianie widoków findbox.addWidget(lbl_wysz) findbox.addWidget(txt_wysz) button_hbox.addWidget(btn_dodaj) button_hbox.addWidget(self.btn_mod) button_hbox.addWidget(self.btn_usun) formbox.addRow(lbl_nazwa, self.txt_nazwa) formbox.addRow(lbl_cena, self.txt_cena) formbox.addRow(lbl_czas, self.txt_czas) formbox.addRow(lbl_opis, self.txt_opis) groupbox_layout.addLayout(formbox) groupbox_layout.addLayout(button_hbox) groupbox.setLayout(groupbox_layout) vbox.addLayout(findbox) vbox.addWidget(groupbox) centralbox.addLayout(vbox) centralbox.addWidget(self.view) self.setLayout(centralbox) self.show() def table_init(self): """ Inicjuje wygląd tabeli """ self.model.setTable('uslugi') # query = QSqlQuery('SELECT uzytkownik_id, uzytkownik_nazwa, imie, nazwisko, pracownik FROM uzytkownik;') # self.model.setQuery(query) self.model.select() self.proxy.setSourceModel(self.model) naglowki = { 'uslugi_id': 'ID', 'nazwa': 'Nazwa', 'cena': 'Cena', "czas": 'Czas', 'Opis': 'Opis', } # Ustawianie nagłówków ilosc_kolumn = self.model.columnCount() for i in range(ilosc_kolumn): nazwa_kolumn = self.model.headerData(i, Qt.Horizontal) self.model.setHeaderData(i, Qt.Horizontal, naglowki[nazwa_kolumn]) self.view.setSizeAdjustPolicy( QAbstractScrollArea.AdjustToContentsOnFirstShow) self.view.setSortingEnabled(True) self.view.setAlternatingRowColors(True) # Wczytanie danych self.view.setModel(self.proxy) self.view.hideColumn(0) self.view.sortByColumn(1, Qt.AscendingOrder) self.view.setEditTriggers(QAbstractItemView.NoEditTriggers) def change(self): """ Metoda edytująca zaznaczone wiersze - Wstawia wartości z wierszy w odpowiednie pola """ index = (self.view.selectionModel().currentIndex()) value = index.sibling(index.row(), index.column()).data() self.id_modify = index.sibling(index.row(), 0).data() self.txt_nazwa.setText(index.sibling(index.row(), 1).data()) self.txt_cena.setText(str(index.sibling(index.row(), 2).data())) self.txt_czas.setText(index.sibling(index.row(), 3).data()) self.txt_opis.setText(index.sibling(index.row(), 4).data()) if self.id_modify >= 0 and self.txt_nazwa.text( ) and self.txt_cena.text() and self.txt_czas.text(): self.btn_mod.setEnabled(True) self.btn_usun.setEnabled(True) else: self.btn_usun.setDisabled(True) self.btn_mod.setDisabled(True) value.setText('') def if_checked(self, txt, q, val=None): """ Sprawdza poprawność wprowadzonych damych. :param val: wartości do zapytania :param q: zapytanie query MySql :param txt: komunikat """ if len(self.txt_nazwa.text()) < 3 or len( self.txt_cena.text()) < 1 or len(self.txt_czas.text()) < 2: msg = QMessageBox() msg.setIcon(QMessageBox.Warning) msg.setText(txt) msg.setWindowTitle("Popraw dane") msg.exec_() return False else: print('Trwa zmiana w bazie danych') if val: print('Połączenie') t = query_to_db(q, val) print(t) return t # = polaczenie(q, val) else: print('Transakcja') return transaction_to_db(q) def add(self): """ Dodaje nową usługę do bazy danych i odświeża widok. """ tekst = 'Nie wprowadzono wszystkich danych' # Dodanie nowego użytkownika query = 'INSERT INTO uslugi (nazwa, cena, czas, Opis) VALUES (%s, %s, %s, %s)' val = (self.txt_nazwa.text(), self.txt_cena.text().replace(',', '.'), self.txt_czas.text(), self.txt_opis.toPlainText()) if self.if_checked(tekst, query, val): msg = QMessageBox(self) msg.setIcon(QMessageBox.Information) msg.setText('Dodano nową usługę') msg.setWindowTitle("Dodano nową usługę") msg.exec_() else: msg = QMessageBox(self) msg.setIcon(QMessageBox.Warning) msg.setText('Usługa znajduje się już w bazie') msg.setWindowTitle("Błąd!") msg.exec_() # Odświeżanie widoku tabeli self.model.select() self.view.reset() def modify(self): """ Modyfikuje bazę danych """ test = 'Dane zostały błędnie zmodyfikowane.' query = 'UPDATE uslugi SET nazwa = %s, cena = %s, czas = %s, Opis = %s WHERE uslugi_id = %s;' val = (self.txt_nazwa.text(), self.txt_cena.text().replace(',', '.'), self.txt_czas.text(), self.txt_opis.toPlainText(), self.id_modify) if self.if_checked(test, query, val): msg = QMessageBox(self) msg.setIcon(QMessageBox.Information) msg.setText('Informacje o usłudze zostały pomyślnie zmodyfikowane') msg.setWindowTitle("Zmodyfikowano usługi") msg.exec_() # Odświeżanie widoku tabeli self.model.select() self.view.reset() def remove(self): """ Usuwa dane z bazy danych """ test = 'Błąd! Nie można usunąć danej usługi!' query2 = 'DELETE FROM wizyty WHERE uslugi_id = %s' query = 'DELETE FROM uslugi WHERE uslugi_id = %s' val = (self.id_modify, ) query1 = 'DELETE FROM uzytkownik_usluga WHERE uslugi_id = %s' ret = QMessageBox.question(self, 'Usuwanie usługi', "Czy na pewno chcesz usunąć daną usługę?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if ret == QMessageBox.Yes: if self.if_checked(test, [(query2, val), (query1, val), (query, val)]): msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText('Usługa została usunięta') msg.setWindowTitle("Usunięto") msg.exec_() self.txt_nazwa.setText('') self.txt_cena.setText('') self.txt_czas.setText('') self.txt_opis.setText('') # Odświeżanie widoku tabeli self.model.select() self.view.reset() @pyqtSlot(str) def searching(self, text): """ Wyszukuje po wszystkich kolumnach tabeli :param text: """ search = QRegExp(text, Qt.CaseInsensitive, QRegExp.RegExp) self.proxy.setFilterRegExp(search) # Odpowiedzialne za kolumnę, po której filtruje self.proxy.setFilterKeyColumn(1)
class PortconQueryTab(AnalysisTab): """An portcon query.""" def __init__(self, parent, policy, perm_map): super(PortconQueryTab, self).__init__(parent) self.log = logging.getLogger(__name__) self.policy = policy self.query = PortconQuery(policy) self.setupUi() def __del__(self): self.thread.quit() self.thread.wait(5000) logging.getLogger("setools.portconquery").removeHandler(self.handler) def setupUi(self): self.load_ui("apol/portconquery.ui") # set up user autocompletion user_completion_list = [str(u) for u in self.policy.users()] user_completer_model = QStringListModel(self) user_completer_model.setStringList(sorted(user_completion_list)) self.user_completion = QCompleter() self.user_completion.setModel(user_completer_model) self.user.setCompleter(self.user_completion) # set up role autocompletion role_completion_list = [str(r) for r in self.policy.roles()] role_completer_model = QStringListModel(self) role_completer_model.setStringList(sorted(role_completion_list)) self.role_completion = QCompleter() self.role_completion.setModel(role_completer_model) self.role.setCompleter(self.role_completion) # set up type autocompletion type_completion_list = [str(t) for t in self.policy.types()] type_completer_model = QStringListModel(self) type_completer_model.setStringList(sorted(type_completion_list)) self.type_completion = QCompleter() self.type_completion.setModel(type_completer_model) self.type_.setCompleter(self.type_completion) # setup indications of errors on source/target/default self.errors = set() self.orig_palette = self.type_.palette() self.error_palette = self.type_.palette() self.error_palette.setColor(QPalette.Base, Qt.red) self.clear_ports_error() self.clear_user_error() self.clear_type_error() self.clear_role_error() self.clear_range_error() # populate protocol list. This has empty string as # the first item in the .ui file: for i, e in enumerate(PortconProtocol, start=1): self.protocol.insertItem(i, e.name.upper(), e) # set up results self.table_results_model = PortconTableModel(self) self.sort_proxy = QSortFilterProxyModel(self) self.sort_proxy.setSourceModel(self.table_results_model) self.table_results.setModel(self.sort_proxy) self.table_results.sortByColumn(0, Qt.AscendingOrder) # set up processing thread self.thread = QThread() self.worker = QueryResultsUpdater(self.query, self.table_results_model) self.worker.moveToThread(self.thread) self.worker.raw_line.connect(self.raw_results.appendPlainText) self.worker.finished.connect(self.update_complete) self.worker.finished.connect(self.thread.quit) self.thread.started.connect(self.worker.update) # create a "busy, please wait" dialog self.busy = QProgressDialog(self) self.busy.setModal(True) self.busy.setRange(0, 0) self.busy.setMinimumDuration(0) self.busy.canceled.connect(self.thread.requestInterruption) self.busy.reset() # update busy dialog from query INFO logs self.handler = LogHandlerToSignal() self.handler.message.connect(self.busy.setLabelText) logging.getLogger("setools.portconquery").addHandler(self.handler) # Ensure settings are consistent with the initial .ui state self.criteria_frame.setHidden(not self.criteria_expander.isChecked()) self.notes.setHidden(not self.notes_expander.isChecked()) # Range criteria is available only if policy is MLS if not self.policy.mls: self.range_criteria.setEnabled(False) self.range_criteria.setToolTip("MLS is disabled in this policy.") self.range_.setToolTip("MLS is disabled in this policy.") self.range_exact.setToolTip("MLS is disabled in this policy.") self.range_overlap.setToolTip("MLS is disabled in this policy.") self.range_subset.setToolTip("MLS is disabled in this policy.") self.range_superset.setToolTip("MLS is disabled in this policy.") # connect signals self.buttonBox.clicked.connect(self.run) self.ports.textEdited.connect(self.clear_ports_error) self.ports.editingFinished.connect(self.set_ports) self.user.textEdited.connect(self.clear_user_error) self.user.editingFinished.connect(self.set_user) self.user_regex.toggled.connect(self.set_user_regex) self.role.textEdited.connect(self.clear_role_error) self.role.editingFinished.connect(self.set_role) self.role_regex.toggled.connect(self.set_role_regex) self.type_.textEdited.connect(self.clear_type_error) self.type_.editingFinished.connect(self.set_type) self.type_regex.toggled.connect(self.set_type_regex) self.range_.textEdited.connect(self.clear_range_error) self.range_.editingFinished.connect(self.set_range) # # Ports criteria # def clear_ports_error(self): self.clear_criteria_error(self.ports, "Match the ports.") def set_ports(self): try: pending_ports = self.ports.text() if pending_ports: try: ports = [int(i) for i in pending_ports.split("-")] except ValueError as ex: raise ValueError( "Enter a port number or range, e.g. 22 or 6000-6020" ) from ex if len(ports) == 2: self.query.ports = ports elif len(ports) == 1: self.query.ports = (ports[0], ports[0]) else: raise ValueError( "Enter a port number or range, e.g. 22 or 6000-6020") else: self.query.ports = (0, 0) except Exception as ex: self.log.error("Ports error: {0}".format(ex)) self.set_criteria_error(self.ports, ex) # # User criteria # def clear_user_error(self): self.clear_criteria_error(self.user, "Match the user of the context.") def set_user(self): try: self.query.user = self.user.text() except Exception as ex: self.log.error("Context user error: {0}".format(ex)) self.set_criteria_error(self.user, ex) def set_user_regex(self, state): self.log.debug("Setting user_regex {0}".format(state)) self.query.user_regex = state self.clear_user_error() self.set_user() # # Role criteria # def clear_role_error(self): self.clear_criteria_error(self.role, "Match the role of the context.") def set_role(self): try: self.query.role = self.role.text() except Exception as ex: self.log.error("Context role error: {0}".format(ex)) self.set_criteria_error(self.role, ex) def set_role_regex(self, state): self.log.debug("Setting role_regex {0}".format(state)) self.query.role_regex = state self.clear_role_error() self.set_role() # # Type criteria # def clear_type_error(self): self.clear_criteria_error(self.type_, "Match the type of the context.") def set_type(self): try: self.query.type_ = self.type_.text() except Exception as ex: self.log.error("Context type error: {0}".format(ex)) self.set_criteria_error(self.type_, ex) def set_type_regex(self, state): self.log.debug("Setting type_regex {0}".format(state)) self.query.type_regex = state self.clear_type_error() self.set_type() # # Range criteria # def clear_range_error(self): self.clear_criteria_error(self.range_, "Match the range of the context.") def set_range(self): try: self.query.range_ = self.range_.text() except Exception as ex: self.log.info("Context range error: " + str(ex)) self.set_criteria_error(self.range_, ex) # # Save/Load tab # def save(self): """Return a dictionary of settings.""" if self.errors: raise TabFieldError("Field(s) are in error: {0}".format(" ".join( o.objectName() for o in self.errors))) settings = {} save_checkboxes(self, settings, [ "criteria_expander", "notes_expander", "ports_exact", "ports_overlap", "ports_subset", "ports_superset", "user_regex", "role_regex", "type_regex", "range_exact", "range_overlap", "range_subset", "range_superset" ]) save_lineedits(self, settings, ["ports", "user", "role", "type_", "range_"]) save_comboboxes(self, settings, ["protocol"]) save_textedits(self, settings, ["notes"]) return settings def load(self, settings): load_checkboxes(self, settings, [ "criteria_expander", "notes_expander", "ports_exact", "ports_overlap", "ports_subset", "ports_superset", "user_regex", "role_regex", "type_regex", "range_exact", "range_overlap", "range_subset", "range_superset" ]) load_lineedits(self, settings, ["ports", "user", "role", "type_", "range_"]) load_comboboxes(self, settings, ["protocol"]) load_textedits(self, settings, ["notes"]) # # Results runner # def run(self, button): # right now there is only one button. self.query.ports_overlap = self.ports_overlap.isChecked() self.query.ports_subset = self.ports_subset.isChecked() self.query.ports_superset = self.ports_superset.isChecked() self.query.protocol = self.protocol.currentData(Qt.UserRole) self.query.range_overlap = self.range_overlap.isChecked() self.query.range_subset = self.range_subset.isChecked() self.query.range_superset = self.range_superset.isChecked() # start processing self.busy.setLabelText("Processing query...") self.busy.show() self.raw_results.clear() self.thread.start() def update_complete(self, count): self.log.info("{0} portcon statment(s) found.".format(count)) # update sizes/location of result displays if not self.busy.wasCanceled(): self.busy.setLabelText( "Resizing the result table's columns; GUI may be unresponsive") self.busy.repaint() self.table_results.resizeColumnsToContents() if not self.busy.wasCanceled(): self.busy.setLabelText( "Resizing the result table's rows; GUI may be unresponsive") self.busy.repaint() self.table_results.resizeRowsToContents() if not self.busy.wasCanceled(): self.busy.setLabelText( "Moving the raw result to top; GUI may be unresponsive") self.busy.repaint() self.raw_results.moveCursor(QTextCursor.Start) self.busy.reset()
class BreakPointViewer(QTreeView): """ Class implementing the Breakpoint viewer widget. Breakpoints will be shown with all their details. They can be modified through the context menu of this widget. @signal sourceFile(str, int) emitted to show the source of a breakpoint """ sourceFile = pyqtSignal(str, int) def __init__(self, parent=None): """ Constructor @param parent the parent (QWidget) """ super(BreakPointViewer, self).__init__(parent) self.setObjectName("BreakPointViewer") self.__model = None self.setItemsExpandable(False) self.setRootIsDecorated(False) self.setAlternatingRowColors(True) self.setSelectionMode(QAbstractItemView.ExtendedSelection) self.setSelectionBehavior(QAbstractItemView.SelectRows) self.setWindowTitle(self.tr("Breakpoints")) self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.__showContextMenu) self.doubleClicked.connect(self.__doubleClicked) self.__createPopupMenus() self.condHistory = [] self.fnHistory = [] self.fnHistory.append('') def setModel(self, model): """ Public slot to set the breakpoint model. @param model reference to the breakpoint model (BreakPointModel) """ self.__model = model self.sortingModel = QSortFilterProxyModel() self.sortingModel.setDynamicSortFilter(True) self.sortingModel.setSourceModel(self.__model) super(BreakPointViewer, self).setModel(self.sortingModel) header = self.header() header.setSortIndicator(0, Qt.AscendingOrder) header.setSortIndicatorShown(True) if qVersion() >= "5.0.0": header.setSectionsClickable(True) else: header.setClickable(True) self.setSortingEnabled(True) self.__layoutDisplay() def __layoutDisplay(self): """ Private slot to perform a layout operation. """ self.__resizeColumns() self.__resort() def __resizeColumns(self): """ Private slot to resize the view when items get added, edited or deleted. """ self.header().resizeSections(QHeaderView.ResizeToContents) self.header().setStretchLastSection(True) def __resort(self): """ Private slot to resort the tree. """ self.model().sort(self.header().sortIndicatorSection(), self.header().sortIndicatorOrder()) def __toSourceIndex(self, index): """ Private slot to convert an index to a source index. @param index index to be converted (QModelIndex) @return mapped index (QModelIndex) """ return self.sortingModel.mapToSource(index) def __fromSourceIndex(self, sindex): """ Private slot to convert a source index to an index. @param sindex source index to be converted (QModelIndex) @return mapped index (QModelIndex) """ return self.sortingModel.mapFromSource(sindex) def __setRowSelected(self, index, selected=True): """ Private slot to select a complete row. @param index index determining the row to be selected (QModelIndex) @param selected flag indicating the action (bool) """ if not index.isValid(): return if selected: flags = QItemSelectionModel.SelectionFlags( QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows) else: flags = QItemSelectionModel.SelectionFlags( QItemSelectionModel.Deselect | QItemSelectionModel.Rows) self.selectionModel().select(index, flags) def __createPopupMenus(self): """ Private method to generate the popup menus. """ self.menu = QMenu() self.menu.addAction(self.tr("Add"), self.__addBreak) self.menu.addAction(self.tr("Edit..."), self.__editBreak) self.menu.addSeparator() self.menu.addAction(self.tr("Enable"), self.__enableBreak) self.menu.addAction(self.tr("Enable all"), self.__enableAllBreaks) self.menu.addSeparator() self.menu.addAction(self.tr("Disable"), self.__disableBreak) self.menu.addAction(self.tr("Disable all"), self.__disableAllBreaks) self.menu.addSeparator() self.menu.addAction(self.tr("Delete"), self.__deleteBreak) self.menu.addAction(self.tr("Delete all"), self.__deleteAllBreaks) self.menu.addSeparator() self.menu.addAction(self.tr("Goto"), self.__showSource) self.menu.addSeparator() self.menu.addAction(self.tr("Configure..."), self.__configure) self.backMenuActions = {} self.backMenu = QMenu() self.backMenu.addAction(self.tr("Add"), self.__addBreak) self.backMenuActions["EnableAll"] = \ self.backMenu.addAction(self.tr("Enable all"), self.__enableAllBreaks) self.backMenuActions["DisableAll"] = \ self.backMenu.addAction(self.tr("Disable all"), self.__disableAllBreaks) self.backMenuActions["DeleteAll"] = \ self.backMenu.addAction(self.tr("Delete all"), self.__deleteAllBreaks) self.backMenu.aboutToShow.connect(self.__showBackMenu) self.backMenu.addSeparator() self.backMenu.addAction(self.tr("Configure..."), self.__configure) self.multiMenu = QMenu() self.multiMenu.addAction(self.tr("Add"), self.__addBreak) self.multiMenu.addSeparator() self.multiMenu.addAction(self.tr("Enable selected"), self.__enableSelectedBreaks) self.multiMenu.addAction(self.tr("Enable all"), self.__enableAllBreaks) self.multiMenu.addSeparator() self.multiMenu.addAction(self.tr("Disable selected"), self.__disableSelectedBreaks) self.multiMenu.addAction(self.tr("Disable all"), self.__disableAllBreaks) self.multiMenu.addSeparator() self.multiMenu.addAction(self.tr("Delete selected"), self.__deleteSelectedBreaks) self.multiMenu.addAction(self.tr("Delete all"), self.__deleteAllBreaks) self.multiMenu.addSeparator() self.multiMenu.addAction(self.tr("Configure..."), self.__configure) def __showContextMenu(self, coord): """ Private slot to show the context menu. @param coord the position of the mouse pointer (QPoint) """ cnt = self.__getSelectedItemsCount() if cnt <= 1: index = self.indexAt(coord) if index.isValid(): cnt = 1 self.__setRowSelected(index) coord = self.mapToGlobal(coord) if cnt > 1: self.multiMenu.popup(coord) elif cnt == 1: self.menu.popup(coord) else: self.backMenu.popup(coord) def __clearSelection(self): """ Private slot to clear the selection. """ for index in self.selectedIndexes(): self.__setRowSelected(index, False) def __addBreak(self): """ Private slot to handle the add breakpoint context menu entry. """ from .EditBreakpointDialog import EditBreakpointDialog dlg = EditBreakpointDialog((self.fnHistory[0], None), None, self.condHistory, self, modal=1, addMode=1, filenameHistory=self.fnHistory) if dlg.exec_() == QDialog.Accepted: fn, line, cond, temp, enabled, count = dlg.getAddData() if fn is not None: if fn in self.fnHistory: self.fnHistory.remove(fn) self.fnHistory.insert(0, fn) if cond: if cond in self.condHistory: self.condHistory.remove(cond) self.condHistory.insert(0, cond) self.__model.addBreakPoint(fn, line, (cond, temp, enabled, count)) self.__resizeColumns() self.__resort() def __doubleClicked(self, index): """ Private slot to handle the double clicked signal. @param index index of the entry that was double clicked (QModelIndex) """ if index.isValid(): self.__editBreakpoint(index) def __editBreak(self): """ Private slot to handle the edit breakpoint context menu entry. """ index = self.currentIndex() if index.isValid(): self.__editBreakpoint(index) def __editBreakpoint(self, index): """ Private slot to edit a breakpoint. @param index index of breakpoint to be edited (QModelIndex) """ sindex = self.__toSourceIndex(index) if sindex.isValid(): bp = self.__model.getBreakPointByIndex(sindex) if not bp: return fn, line, cond, temp, enabled, count = bp[:6] from .EditBreakpointDialog import EditBreakpointDialog dlg = EditBreakpointDialog((fn, line), (cond, temp, enabled, count), self.condHistory, self, modal=True) if dlg.exec_() == QDialog.Accepted: cond, temp, enabled, count = dlg.getData() if cond: if cond in self.condHistory: self.condHistory.remove(cond) self.condHistory.insert(0, cond) self.__model.setBreakPointByIndex(sindex, fn, line, (cond, temp, enabled, count)) self.__resizeColumns() self.__resort() def __setBpEnabled(self, index, enabled): """ Private method to set the enabled status of a breakpoint. @param index index of breakpoint to be enabled/disabled (QModelIndex) @param enabled flag indicating the enabled status to be set (boolean) """ sindex = self.__toSourceIndex(index) if sindex.isValid(): self.__model.setBreakPointEnabledByIndex(sindex, enabled) def __enableBreak(self): """ Private slot to handle the enable breakpoint context menu entry. """ index = self.currentIndex() self.__setBpEnabled(index, True) self.__resizeColumns() self.__resort() def __enableAllBreaks(self): """ Private slot to handle the enable all breakpoints context menu entry. """ index = self.model().index(0, 0) while index.isValid(): self.__setBpEnabled(index, True) index = self.indexBelow(index) self.__resizeColumns() self.__resort() def __enableSelectedBreaks(self): """ Private slot to handle the enable selected breakpoints context menu entry. """ for index in self.selectedIndexes(): if index.column() == 0: self.__setBpEnabled(index, True) self.__resizeColumns() self.__resort() def __disableBreak(self): """ Private slot to handle the disable breakpoint context menu entry. """ index = self.currentIndex() self.__setBpEnabled(index, False) self.__resizeColumns() self.__resort() def __disableAllBreaks(self): """ Private slot to handle the disable all breakpoints context menu entry. """ index = self.model().index(0, 0) while index.isValid(): self.__setBpEnabled(index, False) index = self.indexBelow(index) self.__resizeColumns() self.__resort() def __disableSelectedBreaks(self): """ Private slot to handle the disable selected breakpoints context menu entry. """ for index in self.selectedIndexes(): if index.column() == 0: self.__setBpEnabled(index, False) self.__resizeColumns() self.__resort() def __deleteBreak(self): """ Private slot to handle the delete breakpoint context menu entry. """ index = self.currentIndex() sindex = self.__toSourceIndex(index) if sindex.isValid(): self.__model.deleteBreakPointByIndex(sindex) def __deleteAllBreaks(self): """ Private slot to handle the delete all breakpoints context menu entry. """ self.__model.deleteAll() def __deleteSelectedBreaks(self): """ Private slot to handle the delete selected breakpoints context menu entry. """ idxList = [] for index in self.selectedIndexes(): sindex = self.__toSourceIndex(index) if sindex.isValid() and index.column() == 0: idxList.append(sindex) self.__model.deleteBreakPoints(idxList) def __showSource(self): """ Private slot to handle the goto context menu entry. """ index = self.currentIndex() sindex = self.__toSourceIndex(index) bp = self.__model.getBreakPointByIndex(sindex) if not bp: return fn, line = bp[:2] self.sourceFile.emit(fn, line) def highlightBreakpoint(self, fn, lineno): """ Public slot to handle the clientLine signal. @param fn filename of the breakpoint (string) @param lineno line number of the breakpoint (integer) """ sindex = self.__model.getBreakPointIndex(fn, lineno) if sindex.isValid(): return index = self.__fromSourceIndex(sindex) if index.isValid(): self.__clearSelection() self.__setRowSelected(index, True) def handleResetUI(self): """ Public slot to reset the breakpoint viewer. """ self.__clearSelection() def __showBackMenu(self): """ Private slot to handle the aboutToShow signal of the background menu. """ if self.model().rowCount() == 0: self.backMenuActions["EnableAll"].setEnabled(False) self.backMenuActions["DisableAll"].setEnabled(False) self.backMenuActions["DeleteAll"].setEnabled(False) else: self.backMenuActions["EnableAll"].setEnabled(True) self.backMenuActions["DisableAll"].setEnabled(True) self.backMenuActions["DeleteAll"].setEnabled(True) def __getSelectedItemsCount(self): """ Private method to get the count of items selected. @return count of items selected (integer) """ count = len(self.selectedIndexes()) // (self.__model.columnCount() - 1) # column count is 1 greater than selectable return count def __configure(self): """ Private method to open the configuration dialog. """ e5App().getObject("UserInterface").showPreferences( "debuggerGeneralPage")
class TERuleQueryTab(AnalysisTab): """A Type Enforcement rule query.""" def __init__(self, parent, policy, perm_map): super(TERuleQueryTab, self).__init__(parent) self.log = logging.getLogger(__name__) self.policy = policy self.query = TERuleQuery(policy) self.setupUi() def __del__(self): self.thread.quit() self.thread.wait(5000) logging.getLogger("setools.terulequery").removeHandler(self.handler) def setupUi(self): self.load_ui("apol/terulequery.ui") # set up source/target autocompletion typeattr_completion_list = [str(t) for t in self.policy.types()] typeattr_completion_list.extend( str(a) for a in self.policy.typeattributes()) typeattr_completer_model = QStringListModel(self) typeattr_completer_model.setStringList( sorted(typeattr_completion_list)) self.typeattr_completion = QCompleter() self.typeattr_completion.setModel(typeattr_completer_model) self.source.setCompleter(self.typeattr_completion) self.target.setCompleter(self.typeattr_completion) # set up default autocompletion type_completion_list = [str(t) for t in self.policy.types()] type_completer_model = QStringListModel(self) type_completer_model.setStringList(sorted(type_completion_list)) self.type_completion = QCompleter() self.type_completion.setModel(type_completer_model) self.default_type.setCompleter(self.type_completion) # setup indications of errors on source/target/default self.errors = set() self.orig_palette = self.source.palette() self.error_palette = self.source.palette() self.error_palette.setColor(QPalette.Base, Qt.red) self.clear_source_error() self.clear_target_error() self.clear_default_error() self.clear_xperm_error() # populate class list self.class_model = SEToolsListModel(self) self.class_model.item_list = sorted(self.policy.classes()) self.tclass.setModel(self.class_model) # populate perm list self.perms_model = PermListModel(self, self.policy) self.perms.setModel(self.perms_model) # populate bool list self.bool_model = SEToolsListModel(self) self.bool_model.item_list = sorted(self.policy.bools()) self.bool_criteria.setModel(self.bool_model) # set up results self.table_results_model = TERuleTableModel(self) self.sort_proxy = QSortFilterProxyModel(self) self.sort_proxy.setSourceModel(self.table_results_model) self.table_results.setModel(self.sort_proxy) self.table_results.sortByColumn(0, Qt.AscendingOrder) # set up processing thread self.thread = QThread() self.worker = QueryResultsUpdater(self.query, self.table_results_model) self.worker.moveToThread(self.thread) self.worker.raw_line.connect(self.raw_results.appendPlainText) self.worker.finished.connect(self.update_complete) self.worker.finished.connect(self.thread.quit) self.thread.started.connect(self.worker.update) # create a "busy, please wait" dialog self.busy = QProgressDialog(self) self.busy.setModal(True) self.busy.setRange(0, 0) self.busy.setMinimumDuration(0) self.busy.canceled.connect(self.thread.requestInterruption) self.busy.reset() # update busy dialog from query INFO logs self.handler = LogHandlerToSignal() self.handler.message.connect(self.busy.setLabelText) logging.getLogger("setools.terulequery").addHandler(self.handler) # Ensure settings are consistent with the initial .ui state self.set_source_regex(self.source_regex.isChecked()) self.set_target_regex(self.target_regex.isChecked()) self.set_default_regex(self.default_regex.isChecked()) self.toggle_xperm_criteria() self.criteria_frame.setHidden(not self.criteria_expander.isChecked()) self.notes.setHidden(not self.notes_expander.isChecked()) # connect signals self.buttonBox.clicked.connect(self.run) self.allowxperm.toggled.connect(self.toggle_xperm_criteria) self.auditallowxperm.toggled.connect(self.toggle_xperm_criteria) self.neverallowxperm.toggled.connect(self.toggle_xperm_criteria) self.dontauditxperm.toggled.connect(self.toggle_xperm_criteria) self.clear_ruletypes.clicked.connect(self.clear_all_ruletypes) self.all_ruletypes.clicked.connect(self.set_all_ruletypes) self.source.textEdited.connect(self.clear_source_error) self.source.editingFinished.connect(self.set_source) self.source_regex.toggled.connect(self.set_source_regex) self.target.textEdited.connect(self.clear_target_error) self.target.editingFinished.connect(self.set_target) self.target_regex.toggled.connect(self.set_target_regex) self.tclass.selectionModel().selectionChanged.connect(self.set_tclass) self.invert_class.clicked.connect(self.invert_tclass_selection) self.perms.selectionModel().selectionChanged.connect(self.set_perms) self.invert_perms.clicked.connect(self.invert_perms_selection) self.xperms.textEdited.connect(self.clear_xperm_error) self.xperms.editingFinished.connect(self.set_xperm) self.default_type.textEdited.connect(self.clear_default_error) self.default_type.editingFinished.connect(self.set_default_type) self.default_regex.toggled.connect(self.set_default_regex) self.bool_criteria.selectionModel().selectionChanged.connect( self.set_bools) # # Ruletype criteria # def _set_ruletypes(self, value): self.allow.setChecked(value) self.allowxperm.setChecked(value) self.auditallow.setChecked(value) self.auditallowxperm.setChecked(value) self.neverallow.setChecked(value) self.neverallowxperm.setChecked(value) self.dontaudit.setChecked(value) self.dontauditxperm.setChecked(value) self.type_transition.setChecked(value) self.type_member.setChecked(value) self.type_change.setChecked(value) def set_all_ruletypes(self): self._set_ruletypes(True) def clear_all_ruletypes(self): self._set_ruletypes(False) # # Source criteria # def clear_source_error(self): self.clear_criteria_error( self.source, "Match the source type/attribute of the rule.") def set_source(self): try: self.query.source = self.source.text() except Exception as ex: self.log.error("Source type/attribute error: {0}".format(ex)) self.set_criteria_error(self.source, ex) def set_source_regex(self, state): self.log.debug("Setting source_regex {0}".format(state)) self.query.source_regex = state self.clear_source_error() self.set_source() # # Target criteria # def clear_target_error(self): self.clear_criteria_error( self.target, "Match the target type/attribute of the rule.") def set_target(self): try: self.query.target = self.target.text() except Exception as ex: self.log.error("Target type/attribute error: {0}".format(ex)) self.set_criteria_error(self.target, ex) def set_target_regex(self, state): self.log.debug("Setting target_regex {0}".format(state)) self.query.target_regex = state self.clear_target_error() self.set_target() # # Class criteria # def set_tclass(self): selected_classes = [] for index in self.tclass.selectionModel().selectedIndexes(): selected_classes.append(self.class_model.data(index, Qt.UserRole)) self.query.tclass = selected_classes self.perms_model.set_classes(selected_classes) def invert_tclass_selection(self): invert_list_selection(self.tclass.selectionModel()) # # Permissions criteria # def set_perms(self): selected_perms = [] for index in self.perms.selectionModel().selectedIndexes(): selected_perms.append(self.perms_model.data(index, Qt.UserRole)) self.query.perms = selected_perms def invert_perms_selection(self): invert_list_selection(self.perms.selectionModel()) # # Extended permission criteria # def toggle_xperm_criteria(self): mode = any( (self.allowxperm.isChecked(), self.auditallowxperm.isChecked(), self.neverallowxperm.isChecked(), self.dontauditxperm.isChecked())) self.xperms.setEnabled(mode) self.xperms_equal.setEnabled(mode) def clear_xperm_error(self): self.clear_criteria_error( self.xperms, "Match the extended permissions of the rule. " "Comma-separated permissions or ranges of permissions.") def set_xperm(self): try: text = self.xperms.text() if text: self.query.xperms = xperm_str_to_tuple_ranges(text) else: self.query.xperms = None except Exception as ex: self.log.error("Extended permissions error: {0}".format(ex)) self.set_criteria_error(self.xperms, ex) # # Default criteria # def clear_default_error(self): self.clear_criteria_error(self.default_type, "Match the default type the rule.") def set_default_type(self): self.query.default_regex = self.default_regex.isChecked() try: self.query.default = self.default_type.text() except Exception as ex: self.log.error("Default type error: {0}".format(ex)) self.set_criteria_error(self.default_type, ex) def set_default_regex(self, state): self.log.debug("Setting default_regex {0}".format(state)) self.query.default_regex = state self.clear_default_error() self.set_default_type() # # Boolean criteria # def set_bools(self): selected_bools = [] for index in self.bool_criteria.selectionModel().selectedIndexes(): selected_bools.append(self.bool_model.data(index, Qt.UserRole)) self.query.boolean = selected_bools # # Save/Load tab # def save(self): """Return a dictionary of settings.""" if self.errors: raise TabFieldError("Field(s) are in error: {0}".format(" ".join( o.objectName() for o in self.errors))) settings = {} save_checkboxes(self, settings, [ "criteria_expander", "notes_expander", "allow", "allowxperm", "auditallow", "auditallowxperm", "neverallow", "neverallowxperm", "dontaudit", "dontauditxperm", "type_transition", "type_change", "type_member", "source_indirect", "source_regex", "target_indirect", "target_regex", "perms_subset", "xperms_equal", "default_regex", "bools_equal" ]) save_lineedits(self, settings, ["source", "target", "xperms", "default_type"]) save_listviews(self, settings, ["tclass", "perms", "bool_criteria"]) save_textedits(self, settings, ["notes"]) return settings def load(self, settings): load_checkboxes(self, settings, [ "allow", "allowxperm", "auditallow", "auditallowxperm", "neverallow", "neverallowxperm", "dontaudit", "dontauditxperm", "type_transition", "type_change", "type_member", "criteria_expander", "notes_expander", "source_indirect", "source_regex", "target_indirect", "target_regex", "perms_subset", "xperms_equal", "default_regex", "bools_equal" ]) load_lineedits(self, settings, ["source", "target", "xperms", "default_type"]) load_listviews(self, settings, ["tclass", "perms", "bool_criteria"]) load_textedits(self, settings, ["notes"]) # # Results runner # def run(self, button): # right now there is only one button. rule_types = [] max_results = 0 if self.allow.isChecked(): rule_types.append("allow") max_results += self.policy.allow_count if self.allowxperm.isChecked(): rule_types.append("allowxperm") max_results += self.policy.allowxperm_count if self.auditallow.isChecked(): rule_types.append("auditallow") max_results += self.policy.auditallow_count if self.auditallowxperm.isChecked(): rule_types.append("auditallowxperm") max_results += self.policy.auditallowxperm_count if self.neverallow.isChecked(): rule_types.append("neverallow") max_results += self.policy.neverallow_count if self.neverallowxperm.isChecked(): rule_types.append("neverallowxperm") max_results += self.policy.neverallowxperm_count if self.dontaudit.isChecked(): rule_types.append("dontaudit") max_results += self.policy.dontaudit_count if self.dontauditxperm.isChecked(): rule_types.append("dontauditxperm") max_results += self.policy.dontauditxperm_count if self.type_transition.isChecked(): rule_types.append("type_transition") max_results += self.policy.type_transition_count if self.type_member.isChecked(): rule_types.append("type_member") max_results += self.policy.type_member_count if self.type_change.isChecked(): rule_types.append("type_change") max_results += self.policy.type_change_count self.query.ruletype = rule_types self.query.source_indirect = self.source_indirect.isChecked() self.query.target_indirect = self.target_indirect.isChecked() self.query.perms_subset = self.perms_subset.isChecked() self.query.boolean_equal = self.bools_equal.isChecked() # if query is broad, show warning. if not any((self.query.source, self.query.target, self.query.tclass, self.query.perms, self.query.xperms, self.query.default, self.query.boolean)) \ and max_results > 1000: reply = QMessageBox.question( self, "Continue?", "This is a broad query, estimated to return {0} results. Continue?" .format(max_results), QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.No: return # start processing self.busy.setLabelText("Processing query...") self.busy.show() self.raw_results.clear() self.thread.start() def update_complete(self, count): self.log.info("{0} type enforcement rule(s) found.".format(count)) # update sizes/location of result displays if not self.busy.wasCanceled(): self.busy.setLabelText( "Resizing the result table's columns; GUI may be unresponsive") self.busy.repaint() self.table_results.resizeColumnsToContents() # If the permissions column width is too long, pull back # to a reasonable size header = self.table_results.horizontalHeader() if header.sectionSize(4) > 400: header.resizeSection(4, 400) if not self.busy.wasCanceled(): self.busy.setLabelText( "Resizing the result table's rows; GUI may be unresponsive") self.busy.repaint() self.table_results.resizeRowsToContents() if not self.busy.wasCanceled(): self.busy.setLabelText( "Moving the raw result to top; GUI may be unresponsive") self.busy.repaint() self.raw_results.moveCursor(QTextCursor.Start) self.busy.reset()
def setupUi(self): self.load_ui("apol/rbacrulequery.ui") # set up role autocompletion (source, default) role_completion_list = [str(r) for r in self.policy.roles()] role_completer_model = QStringListModel(self) role_completer_model.setStringList(sorted(role_completion_list)) self.role_completion = QCompleter() self.role_completion.setModel(role_completer_model) self.source.setCompleter(self.role_completion) self.default_role.setCompleter(self.role_completion) # set up role/type autocompletion (target) roletype_completion_list = [str(r) for r in self.policy.roles()] # roletype_completion_list.extend(str(a) for a in self.policy.roleattributes()) roletype_completion_list.extend(str(t) for t in self.policy.types()) roletype_completion_list.extend( str(a) for a in self.policy.typeattributes()) roletype_completer_model = QStringListModel(self) roletype_completer_model.setStringList( sorted(roletype_completion_list)) self.roletype_completion = QCompleter() self.roletype_completion.setModel(roletype_completer_model) self.target.setCompleter(self.roletype_completion) # setup indications of errors on source/target/default self.errors = set() self.orig_palette = self.source.palette() self.error_palette = self.source.palette() self.error_palette.setColor(QPalette.Base, Qt.red) self.clear_source_error() self.clear_target_error() self.clear_default_error() # populate class list self.class_model = SEToolsListModel(self) self.class_model.item_list = sorted(self.policy.classes()) self.tclass.setModel(self.class_model) # set up results self.table_results_model = RBACRuleTableModel(self) self.sort_proxy = QSortFilterProxyModel(self) self.sort_proxy.setSourceModel(self.table_results_model) self.table_results.setModel(self.sort_proxy) self.table_results.sortByColumn(0, Qt.AscendingOrder) # set up processing thread self.thread = QThread() self.worker = QueryResultsUpdater(self.query, self.table_results_model) self.worker.moveToThread(self.thread) self.worker.raw_line.connect(self.raw_results.appendPlainText) self.worker.finished.connect(self.update_complete) self.worker.finished.connect(self.thread.quit) self.thread.started.connect(self.worker.update) # create a "busy, please wait" dialog self.busy = QProgressDialog(self) self.busy.setModal(True) self.busy.setRange(0, 0) self.busy.setMinimumDuration(0) self.busy.canceled.connect(self.thread.requestInterruption) self.busy.reset() # update busy dialog from query INFO logs self.handler = LogHandlerToSignal() self.handler.message.connect(self.busy.setLabelText) logging.getLogger("setools.rbacrulequery").addHandler(self.handler) # Ensure settings are consistent with the initial .ui state self.set_source_regex(self.source_regex.isChecked()) self.set_target_regex(self.target_regex.isChecked()) self.set_default_regex(self.default_regex.isChecked()) self.criteria_frame.setHidden(not self.criteria_expander.isChecked()) self.notes.setHidden(not self.notes_expander.isChecked()) # connect signals self.buttonBox.clicked.connect(self.run) self.clear_ruletypes.clicked.connect(self.clear_all_ruletypes) self.all_ruletypes.clicked.connect(self.set_all_ruletypes) self.source.textEdited.connect(self.clear_source_error) self.source.editingFinished.connect(self.set_source) self.source_regex.toggled.connect(self.set_source_regex) self.target.textEdited.connect(self.clear_target_error) self.target.editingFinished.connect(self.set_target) self.target_regex.toggled.connect(self.set_target_regex) self.tclass.selectionModel().selectionChanged.connect(self.set_tclass) self.invert_class.clicked.connect(self.invert_tclass_selection) self.default_role.textEdited.connect(self.clear_default_error) self.default_role.editingFinished.connect(self.set_default_role) self.default_regex.toggled.connect(self.set_default_regex)
class CustomerDialog(QDialog): def __init__(self): super(CustomerDialog, self).__init__() self.all_customers = Customer.objects.all() self.customer_fields = ['Id', 'Name', 'CIN'] self.customers_model = QStandardItemModel(len(self.all_customers), 3) self.customers_model.setHorizontalHeaderLabels(self.customer_fields) self.customers_filter_proxy_model = QSortFilterProxyModel() self.customers_filter_proxy_model.setSourceModel(self.customers_model) self.selected_customer = "" self.ui = Ui_CustomerWidget() self.ui.setupUi(self) self.ui.lineEdit.textChanged.connect(self.customers_filter_proxy_model.setFilterRegExp) self.ui.CustomersList.setModel(self.customers_filter_proxy_model) self.populate_customers_list() def populate_customers_list(self): self.populate_customer_model() self.customers_filter_proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive) self.customers_filter_proxy_model.setFilterKeyColumn(1) self.ui.lineEdit.textChanged.connect(self.customers_filter_proxy_model.setFilterRegExp) self.ui.CustomersList.setModel(self.customers_filter_proxy_model) selection_model = self.ui.CustomersList.selectionModel() selection_model.selectionChanged.connect(self.on_customer_selectionChanged) def populate_customer_model(self): for row, customer in enumerate(self.all_customers): pid = QStandardItem(str(customer.id)) name = QStandardItem(str(customer.get_full_name())) id_number = QStandardItem(str(customer.id_number)) # code = QStandardItem(str(customer.code)) self.customers_model.setItem(row, 0, pid) self.customers_model.setItem(row, 1, name) self.customers_model.setItem(row, 2, id_number) # self.product_model.setItem(row, 3, code) @pyqtSlot('QItemSelection', 'QItemSelection') def on_customer_selectionChanged(self, selected): item = selected.indexes() if item: pid = self.selected_customer = item[0].data() self.selected_customer = Customer.objects.get(pk=pid) self.populate_customer_info(self.selected_customer) def populate_customer_info(self, customer): # GENERAL INFO self.ui.label_32.setText(customer.salutation) self.ui.label_33.setText(customer.address.__str__()) # INVOICING INFO self.ui.label_7.setText(customer.get_full_name()) # SALES INFO self.ui.label_17.setText(customer.salutation) self.ui.label_18.setText(customer.address.__str__())
class DictionaryEditorWidget(QDialog): def __init__(self, parent=None): super().__init__(parent) self.parent = parent self.pyboDict = dict() self.initPyboDict() self.tokens = [] self.resize(400, 600) self.setWindowTitle('Dictionary Editor') self.setupTable() self.initUI() def getDict(self): mergedDict = self.pyboDict.copy() # mergedDict = {'ཉམ་ཐག་པ': 'VERB'} for token in Token.objects.all(): if token.type == Token.TYPE_UPDATE: mergedDict[token.text] = token.pos else: # Dict.ACTION_DELETE del mergedDict[token.text] return mergedDict def setupTable(self): dict = self.getDict() self.model = TableModel(parent=self, header=('Text', 'Tag'), data=[[k, v] for k, v in dict.items()]) # print(self.model.bt.has_word('ནང་ཆོས་')) self.proxyModel = QSortFilterProxyModel() self.proxyModel.eventFilter = lambda: self.removeButton.setDisabled( True) self.proxyModel.setSourceModel(self.model) self.tableView = QTableView() self.tableView.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) self.tableView.setFixedHeight(500) self.tableView.setModel(self.proxyModel) def initUI(self): self.searchLabel = QLabel() self.searchLabel.setPixmap( QIcon(os.path.join(BASE_DIR, 'icons', 'searching.png')).pixmap(QSize(20, 20))) self.searchField = QLineEdit() self.searchField.textChanged.connect(self.search) hbox = QHBoxLayout() hbox.addWidget(self.searchLabel) hbox.addWidget(self.searchField) self.addButton = QPushButton() self.addButton.setFlat(True) self.addButton.setIcon( QIcon(os.path.join(BASE_DIR, 'icons', 'add.png'))) self.addButton.setIconSize(QSize(30, 30)) self.addButton.clicked.connect(self.addWord) self.removeButton = QPushButton() self.removeButton.setFlat(True) self.removeButton.setIcon( QIcon(os.path.join(BASE_DIR, "icons", "delete.png"))) self.removeButton.setIconSize(QSize(30, 30)) self.removeButton.clicked.connect(self.removeWord) hbox2 = QHBoxLayout() hbox2.addWidget(self.addButton) hbox2.addStretch() hbox2.addWidget(self.removeButton) self.fbox = QFormLayout() self.fbox.addRow(hbox) self.fbox.addRow(hbox2) self.fbox.addRow(self.tableView) self.setLayout(self.fbox) def search(self, text): self.proxyModel.setFilterKeyColumn(-1) # -1 means all cols self.proxyModel.setFilterFixedString(text) def initPyboDict(self): # import pkg_resources # resourcePkg = 'pybo' # resourcePath = '/'.join(('resources', 'lexica_bo', 'Tibetan.DICT')) # reader = pkg_resources.resource_stream(resourcePkg, resourcePath) resourcePath = os.path.join(BASE_DIR, 'resources', 'dictionaries', 'lexica_bo', 'Tibetan.DICT') reader = open(resourcePath, mode="r", encoding="utf-8", newline="") file = reader.read() for line in file.splitlines(): key, val = line.split() self.pyboDict[key] = val # file.decode() reader.close() def removeWord(self): rows = sorted( set(index.row() for index in self.tableView.selectionModel().selectedIndexes())) for row in reversed(rows): self.model.data.pop(row) self.model.saveDict() def addWord(self, text=None): if text is not None: self.model.data.insert(0, [text, '']) else: self.model.data.insert(0, ['', '']) self.model.layoutChanged.emit() def getAllTags(self): return set(self.getDict().values())
class ListWidget(QWidget): deviceSelected = pyqtSignal(TasmotaDevice) openRulesEditor = pyqtSignal() openConsole = pyqtSignal() openTelemetry = pyqtSignal() openWebUI = pyqtSignal() def __init__(self, parent, *args, **kwargs): super(ListWidget, self).__init__(*args, **kwargs) self.setWindowTitle("Devices list") self.setWindowState(Qt.WindowMaximized) self.setLayout(VLayout(margin=0, spacing=0)) self.mqtt = parent.mqtt self.env = parent.env self.device = None self.idx = None self.nam = QNetworkAccessManager() self.backup = bytes() self.settings = QSettings("{}/TDM/tdm.cfg".format(QDir.homePath()), QSettings.IniFormat) views_order = self.settings.value("views_order", []) self.views = {} self.settings.beginGroup("Views") views = self.settings.childKeys() if views and views_order: for view in views_order.split(";"): view_list = self.settings.value(view).split(";") self.views[view] = base_view + view_list else: self.views = default_views self.settings.endGroup() self.tb = Toolbar(Qt.Horizontal, 24, Qt.ToolButtonTextBesideIcon) self.tb_relays = Toolbar(Qt.Horizontal, 24, Qt.ToolButtonIconOnly) # self.tb_filter = Toolbar(Qt.Horizontal, 24, Qt.ToolButtonTextBesideIcon) self.tb_views = Toolbar(Qt.Horizontal, 24, Qt.ToolButtonTextBesideIcon) self.pwm_sliders = [] self.layout().addWidget(self.tb) self.layout().addWidget(self.tb_relays) # self.layout().addWidget(self.tb_filter) self.device_list = TableView() self.device_list.setIconSize(QSize(24, 24)) self.model = parent.device_model self.model.setupColumns(self.views["Home"]) self.sorted_device_model = QSortFilterProxyModel() self.sorted_device_model.setFilterCaseSensitivity(Qt.CaseInsensitive) self.sorted_device_model.setSourceModel(parent.device_model) self.sorted_device_model.setSortRole(Qt.InitialSortOrderRole) self.sorted_device_model.setSortLocaleAware(True) self.sorted_device_model.setFilterKeyColumn(-1) self.device_list.setModel(self.sorted_device_model) self.device_list.setupView(self.views["Home"]) self.device_list.setSortingEnabled(True) self.device_list.setWordWrap(True) self.device_list.setItemDelegate(DeviceDelegate()) self.device_list.sortByColumn(self.model.columnIndex("FriendlyName"), Qt.AscendingOrder) self.device_list.setContextMenuPolicy(Qt.CustomContextMenu) self.device_list.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) self.layout().addWidget(self.device_list) self.layout().addWidget(self.tb_views) self.device_list.clicked.connect(self.select_device) self.device_list.customContextMenuRequested.connect(self.show_list_ctx_menu) self.ctx_menu = QMenu() self.create_actions() self.create_view_buttons() # self.create_view_filter() self.device_list.doubleClicked.connect(lambda: self.openConsole.emit()) def create_actions(self): actConsole = self.tb.addAction(QIcon("GUI/icons/console.png"), "Console", self.openConsole.emit) actConsole.setShortcut("Ctrl+E") actRules = self.tb.addAction(QIcon("GUI/icons/rules.png"), "Rules", self.openRulesEditor.emit) actRules.setShortcut("Ctrl+R") actTimers = self.tb.addAction(QIcon("GUI/icons/timers.png"), "Timers", self.configureTimers) actButtons = self.tb.addAction(QIcon("GUI/icons/buttons.png"), "Buttons", self.configureButtons) actButtons.setShortcut("Ctrl+B") actSwitches = self.tb.addAction(QIcon("GUI/icons/switches.png"), "Switches", self.configureSwitches) actSwitches.setShortcut("Ctrl+S") actPower = self.tb.addAction(QIcon("GUI/icons/power.png"), "Power", self.configurePower) actPower.setShortcut("Ctrl+P") # setopts = self.tb.addAction(QIcon("GUI/icons/setoptions.png"), "SetOptions", self.configureSO) # setopts.setShortcut("Ctrl+S") self.tb.addSpacer() actTelemetry = self.tb.addAction(QIcon("GUI/icons/telemetry.png"), "Telemetry", self.openTelemetry.emit) actTelemetry.setShortcut("Ctrl+T") actWebui = self.tb.addAction(QIcon("GUI/icons/web.png"), "WebUI", self.openWebUI.emit) actWebui.setShortcut("Ctrl+U") self.ctx_menu.addActions([actRules, actTimers, actButtons, actSwitches, actPower, actTelemetry, actWebui]) self.ctx_menu.addSeparator() self.ctx_menu_cfg = QMenu("Configure") self.ctx_menu_cfg.setIcon(QIcon("GUI/icons/settings.png")) self.ctx_menu_cfg.addAction("Module", self.configureModule) self.ctx_menu_cfg.addAction("GPIO", self.configureGPIO) self.ctx_menu_cfg.addAction("Template", self.configureTemplate) # self.ctx_menu_cfg.addAction("Wifi", self.ctx_menu_teleperiod) # self.ctx_menu_cfg.addAction("Time", self.cfgTime.emit) # self.ctx_menu_cfg.addAction("MQTT", self.ctx_menu_teleperiod) # self.ctx_menu_cfg.addAction("Logging", self.ctx_menu_teleperiod) self.ctx_menu.addMenu(self.ctx_menu_cfg) self.ctx_menu.addSeparator() self.ctx_menu.addAction(QIcon("GUI/icons/refresh.png"), "Refresh", self.ctx_menu_refresh) self.ctx_menu.addSeparator() self.ctx_menu.addAction(QIcon("GUI/icons/clear.png"), "Clear retained", self.ctx_menu_clear_retained) self.ctx_menu.addAction("Clear Backlog", self.ctx_menu_clear_backlog) self.ctx_menu.addSeparator() self.ctx_menu.addAction(QIcon("GUI/icons/copy.png"), "Copy", self.ctx_menu_copy) self.ctx_menu.addSeparator() self.ctx_menu.addAction(QIcon("GUI/icons/restart.png"), "Restart", self.ctx_menu_restart) self.ctx_menu.addAction(QIcon(), "Reset", self.ctx_menu_reset) self.ctx_menu.addSeparator() self.ctx_menu.addAction(QIcon("GUI/icons/delete.png"), "Delete", self.ctx_menu_delete_device) # self.tb.addAction(QIcon(), "Multi Command", self.ctx_menu_webui) self.agAllPower = QActionGroup(self) self.agAllPower.addAction(QIcon("GUI/icons/P_ON.png"), "All ON") self.agAllPower.addAction(QIcon("GUI/icons/P_OFF.png"), "All OFF") self.agAllPower.setEnabled(False) self.agAllPower.setExclusive(False) self.agAllPower.triggered.connect(self.toggle_power_all) self.tb_relays.addActions(self.agAllPower.actions()) self.agRelays = QActionGroup(self) self.agRelays.setVisible(False) self.agRelays.setExclusive(False) for a in range(1, 9): act = QAction(QIcon("GUI/icons/P{}_OFF.png".format(a)), "") act.setShortcut("F{}".format(a)) self.agRelays.addAction(act) self.agRelays.triggered.connect(self.toggle_power) self.tb_relays.addActions(self.agRelays.actions()) self.tb_relays.addSeparator() self.actColor = self.tb_relays.addAction(QIcon("GUI/icons/color.png"), "Color", self.set_color) self.actColor.setEnabled(False) self.actChannels = self.tb_relays.addAction(QIcon("GUI/icons/sliders.png"), "Channels") self.actChannels.setEnabled(False) self.mChannels = QMenu() self.actChannels.setMenu(self.mChannels) self.tb_relays.widgetForAction(self.actChannels).setPopupMode(QToolButton.InstantPopup) def create_view_buttons(self): self.tb_views.addWidget(QLabel("View mode: ")) ag_views = QActionGroup(self) ag_views.setExclusive(True) for v in self.views.keys(): a = QAction(v) a.triggered.connect(self.change_view) a.setCheckable(True) ag_views.addAction(a) self.tb_views.addActions(ag_views.actions()) ag_views.actions()[0].setChecked(True) stretch = QWidget() stretch.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)) self.tb_views.addWidget(stretch) # actEditView = self.tb_views.addAction("Edit views...") # def create_view_filter(self): # # self.tb_filter.addWidget(QLabel("Show devices: ")) # # self.cbxLWT = QComboBox() # # self.cbxLWT.addItems(["All", "Online"d, "Offline"]) # # self.cbxLWT.currentTextChanged.connect(self.build_filter_regex) # # self.tb_filter.addWidget(self.cbxLWT) # # self.tb_filter.addWidget(QLabel(" Search: ")) # self.leSearch = QLineEdit() # self.leSearch.setClearButtonEnabled(True) # self.leSearch.textChanged.connect(self.build_filter_regex) # self.tb_filter.addWidget(self.leSearch) # # def build_filter_regex(self, txt): # query = self.leSearch.text() # # if self.cbxLWT.currentText() != "All": # # query = "{}|{}".format(self.cbxLWT.currentText(), query) # self.sorted_device_model.setFilterRegExp(query) def change_view(self, a=None): view = self.views[self.sender().text()] self.model.setupColumns(view) self.device_list.setupView(view) def ctx_menu_copy(self): if self.idx: string = dumps(self.model.data(self.idx)) if string.startswith('"') and string.endswith('"'): string = string[1:-1] QApplication.clipboard().setText(string) def ctx_menu_clear_retained(self): if self.device: relays = self.device.power() if relays and len(relays.keys()) > 0: for r in relays.keys(): self.mqtt.publish(self.device.cmnd_topic(r), retain=True) QMessageBox.information(self, "Clear retained", "Cleared retained messages.") def ctx_menu_clear_backlog(self): if self.device: self.mqtt.publish(self.device.cmnd_topic("backlog"), "") QMessageBox.information(self, "Clear Backlog", "Backlog cleared.") def ctx_menu_restart(self): if self.device: self.mqtt.publish(self.device.cmnd_topic("restart"), payload="1") for k in list(self.device.power().keys()): self.device.p.pop(k) def ctx_menu_reset(self): if self.device: reset, ok = QInputDialog.getItem(self, "Reset device and restart", "Select reset mode", resets, editable=False) if ok: self.mqtt.publish(self.device.cmnd_topic("reset"), payload=reset.split(":")[0]) for k in list(self.device.power().keys()): self.device.p.pop(k) def ctx_menu_refresh(self): if self.device: for k in list(self.device.power().keys()): self.device.p.pop(k) for c in initial_commands(): cmd, payload = c cmd = self.device.cmnd_topic(cmd) self.mqtt.publish(cmd, payload, 1) def ctx_menu_delete_device(self): if self.device: if QMessageBox.question(self, "Confirm", "Do you want to remove the following device?\n'{}' ({})" .format(self.device.p['FriendlyName1'], self.device.p['Topic'])) == QMessageBox.Yes: self.model.deleteDevice(self.idx) def ctx_menu_teleperiod(self): if self.device: teleperiod, ok = QInputDialog.getInt(self, "Set telemetry period", "Input 1 to reset to default\n[Min: 10, Max: 3600]", self.device.p['TelePeriod'], 1, 3600) if ok: if teleperiod != 1 and teleperiod < 10: teleperiod = 10 self.mqtt.publish(self.device.cmnd_topic("teleperiod"), teleperiod) def ctx_menu_config_backup(self): if self.device: self.backup = bytes() self.dl = self.nam.get(QNetworkRequest(QUrl("http://{}/dl".format(self.device.p['IPAddress'])))) self.dl.readyRead.connect(self.get_dump) self.dl.finished.connect(self.save_dump) def ctx_menu_ota_set_url(self): if self.device: url, ok = QInputDialog.getText(self, "Set OTA URL", '100 chars max. Set to "1" to reset to default.', text=self.device.p['OtaUrl']) if ok: self.mqtt.publish(self.device.cmnd_topic("otaurl"), payload=url) def ctx_menu_ota_set_upgrade(self): if self.device: if QMessageBox.question(self, "OTA Upgrade", "Are you sure to OTA upgrade from\n{}".format(self.device.p['OtaUrl']), QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes: self.mqtt.publish(self.device.cmnd_topic("upgrade"), payload="1") def show_list_ctx_menu(self, at): self.select_device(self.device_list.indexAt(at)) self.ctx_menu.popup(self.device_list.viewport().mapToGlobal(at)) def select_device(self, idx): self.idx = self.sorted_device_model.mapToSource(idx) self.device = self.model.deviceAtRow(self.idx.row()) self.deviceSelected.emit(self.device) relays = self.device.power() self.agAllPower.setEnabled(len(relays) >= 1) for i, a in enumerate(self.agRelays.actions()): a.setVisible(len(relays) > 1 and i < len(relays)) color = self.device.color().get("Color", False) has_color = bool(color) self.actColor.setEnabled(has_color and not self.device.setoption(68)) self.actChannels.setEnabled(has_color) if has_color: self.actChannels.menu().clear() max_val = 100 if self.device.setoption(15) == 0: max_val = 1023 for k, v in self.device.pwm().items(): channel = SliderAction(self, k) channel.slider.setMaximum(max_val) channel.slider.setValue(int(v)) self.mChannels.addAction(channel) channel.slider.valueChanged.connect(self.set_channel) dimmer = self.device.color().get("Dimmer") if dimmer: saDimmer = SliderAction(self, "Dimmer") saDimmer.slider.setValue(int(dimmer)) self.mChannels.addAction(saDimmer) saDimmer.slider.valueChanged.connect(self.set_channel) def toggle_power(self, action): if self.device: idx = self.agRelays.actions().index(action) relay = sorted(list(self.device.power().keys()))[idx] self.mqtt.publish(self.device.cmnd_topic(relay), "toggle") def toggle_power_all(self, action): if self.device: idx = self.agAllPower.actions().index(action) for r in sorted(self.device.power().keys()): self.mqtt.publish(self.device.cmnd_topic(r), idx ^ 1) def set_color(self): if self.device: color = self.device.color().get("Color") if color: dlg = QColorDialog() new_color = dlg.getColor(QColor("#{}".format(color))) if new_color.isValid(): new_color = new_color.name() if new_color != color: self.mqtt.publish(self.device.cmnd_topic("color"), new_color) def set_channel(self, value=0): cmd = self.sender().objectName() if self.device: self.mqtt.publish(self.device.cmnd_topic(cmd), str(value)) def configureSO(self): if self.device: dlg = SetOptionsDialog(self.device) dlg.sendCommand.connect(self.mqtt.publish) dlg.exec_() def configureModule(self): if self.device: dlg = ModuleDialog(self.device) dlg.sendCommand.connect(self.mqtt.publish) dlg.exec_() def configureGPIO(self): if self.device: dlg = GPIODialog(self.device) dlg.sendCommand.connect(self.mqtt.publish) dlg.exec_() def configureTemplate(self): if self.device: dlg = TemplateDialog(self.device) dlg.sendCommand.connect(self.mqtt.publish) dlg.exec_() def configureTimers(self): if self.device: self.mqtt.publish(self.device.cmnd_topic("timers")) timers = TimersDialog(self.device) self.mqtt.messageSignal.connect(timers.parseMessage) timers.sendCommand.connect(self.mqtt.publish) timers.exec_() def configureButtons(self): if self.device: backlog = [] buttons = ButtonsDialog(self.device) if buttons.exec_() == QDialog.Accepted: for c, cw in buttons.command_widgets.items(): current_value = self.device.p.get(c) new_value = "" if isinstance(cw.input, SpinBox): new_value = cw.input.value() if isinstance(cw.input, QComboBox): new_value = cw.input.currentIndex() if current_value != new_value: backlog.append("{} {}".format(c, new_value)) so_error = False for so, sow in buttons.setoption_widgets.items(): current_value = None try: current_value = self.device.setoption(so) except ValueError: so_error = True new_value = -1 if isinstance(sow.input, SpinBox): new_value = sow.input.value() if isinstance(sow.input, QComboBox): new_value = sow.input.currentIndex() if not so_error and current_value and current_value != new_value: backlog.append("SetOption{} {}".format(so, new_value)) if backlog: backlog.append("status 3") self.mqtt.publish(self.device.cmnd_topic("backlog"), "; ".join(backlog)) def configureSwitches(self): if self.device: backlog = [] switches = SwitchesDialog(self.device) if switches.exec_() == QDialog.Accepted: for c, cw in switches.command_widgets.items(): current_value = self.device.p.get(c) new_value = "" if isinstance(cw.input, SpinBox): new_value = cw.input.value() if isinstance(cw.input, QComboBox): new_value = cw.input.currentIndex() if current_value != new_value: backlog.append("{} {}".format(c, new_value)) so_error = False for so, sow in switches.setoption_widgets.items(): current_value = None try: current_value = self.device.setoption(so) except ValueError: so_error = True new_value = -1 if isinstance(sow.input, SpinBox): new_value = sow.input.value() if isinstance(sow.input, QComboBox): new_value = sow.input.currentIndex() if not so_error and current_value != new_value: backlog.append("SetOption{} {}".format(so, new_value)) for sw, sw_mode in enumerate(self.device.p['SwitchMode']): new_value = switches.sm.inputs[sw].currentIndex() if sw_mode != new_value: backlog.append("switchmode{} {}".format(sw+1, new_value)) if backlog: backlog.append("status") backlog.append("status 3") self.mqtt.publish(self.device.cmnd_topic("backlog"), "; ".join(backlog)) def configurePower(self): if self.device: backlog = [] power = PowerDialog(self.device) if power.exec_() == QDialog.Accepted: for c, cw in power.command_widgets.items(): current_value = self.device.p.get(c) new_value = "" if isinstance(cw.input, SpinBox): new_value = cw.input.value() if isinstance(cw.input, QComboBox): new_value = cw.input.currentIndex() if current_value != new_value: backlog.append("{} {}".format(c, new_value)) so_error = False for so, sow in power.setoption_widgets.items(): current_value = None try: current_value = self.device.setoption(so) except ValueError: so_error = True new_value = -1 if isinstance(sow.input, SpinBox): new_value = sow.input.value() if isinstance(sow.input, QComboBox): new_value = sow.input.currentIndex() if not so_error and current_value != new_value: backlog.append("SetOption{} {}".format(so, new_value)) new_interlock_value = power.ci.input.currentData() new_interlock_grps = " ".join([grp.text().replace(" ", "") for grp in power.ci.groups]).rstrip() if new_interlock_value != self.device.p.get("Interlock", "OFF"): backlog.append("interlock {}".format(new_interlock_value)) if new_interlock_grps != self.device.p.get("Groups", ""): backlog.append("interlock {}".format(new_interlock_grps)) for i, pt in enumerate(power.cpt.inputs): ptime = "PulseTime{}".format(i+1) current_ptime = self.device.p.get(ptime) if current_ptime: current_value = list(current_ptime.keys())[0] new_value = str(pt.value()) if new_value != current_value: backlog.append("{} {}".format(ptime, new_value)) if backlog: backlog.append("status") backlog.append("status 3") self.mqtt.publish(self.device.cmnd_topic("backlog"), "; ".join(backlog)) def get_dump(self): self.backup += self.dl.readAll() def save_dump(self): fname = self.dl.header(QNetworkRequest.ContentDispositionHeader) if fname: fname = fname.split('=')[1] save_file = QFileDialog.getSaveFileName(self, "Save config backup", "{}/TDM/{}".format(QDir.homePath(), fname))[0] if save_file: with open(save_file, "wb") as f: f.write(self.backup) def check_fulltopic(self, fulltopic): fulltopic += "/" if not fulltopic.endswith('/') else '' return "%prefix%" in fulltopic and "%topic%" in fulltopic def closeEvent(self, event): event.ignore()
def setupUi(self, MainWindow): self.bill_bool = 2 self.totalbill = 0 self.item_price = 0 self.stock_list = QtWidgets.QTextEdit() self.stock_list.setReadOnly(1) MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 688) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.centralwidget) self.verticalLayout_2.setObjectName("verticalLayout_2") self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout.setSizeConstraint( QtWidgets.QLayout.SetDefaultConstraint) self.verticalLayout.setObjectName("verticalLayout") self.quick_add_box = QtWidgets.QGroupBox(self.centralwidget) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.quick_add_box.sizePolicy().hasHeightForWidth()) self.quick_add_box.setSizePolicy(sizePolicy) self.quick_add_box.setObjectName("quick_add_box") self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.quick_add_box) self.verticalLayout_4.setSizeConstraint( QtWidgets.QLayout.SetDefaultConstraint) self.verticalLayout_4.setSpacing(1) self.verticalLayout_4.setObjectName("verticalLayout_4") self.verticalLayout_3 = QtWidgets.QVBoxLayout() self.verticalLayout_3.setSpacing(10) self.verticalLayout_3.setObjectName("verticalLayout_3") self.horizontalLayout_3 = QtWidgets.QHBoxLayout() self.horizontalLayout_3.setObjectName("horizontalLayout_3") self.gridLayout = QtWidgets.QGridLayout() self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize) self.gridLayout.setHorizontalSpacing(4) self.gridLayout.setVerticalSpacing(0) self.gridLayout.setObjectName("gridLayout") self.product_list = QtWidgets.QComboBox(self.quick_add_box) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(2) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.product_list.sizePolicy().hasHeightForWidth()) self.product_list.setSizePolicy(sizePolicy) self.product_list.setObjectName("product_list") self.gridLayout.addWidget(self.product_list, 1, 0, 1, 1) self.product_label = QtWidgets.QLabel(self.quick_add_box) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.product_label.sizePolicy().hasHeightForWidth()) self.product_label.setSizePolicy(sizePolicy) self.product_label.setObjectName("product_label") self.gridLayout.addWidget(self.product_label, 0, 0, 1, 1) self.buyer_list = QtWidgets.QComboBox(self.quick_add_box) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.buyer_list.sizePolicy().hasHeightForWidth()) self.buyer_list.setSizePolicy(sizePolicy) self.buyer_list.setObjectName("buyer_list") self.gridLayout.addWidget(self.buyer_list, 1, 1, 1, 1) self.buyer_label = QtWidgets.QLabel(self.quick_add_box) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.buyer_label.sizePolicy().hasHeightForWidth()) self.buyer_label.setSizePolicy(sizePolicy) self.buyer_label.setObjectName("buyer_label") self.gridLayout.addWidget(self.buyer_label, 0, 1, 1, 1) self.add_button = QtWidgets.QPushButton(self.quick_add_box) self.add_button.setObjectName("add_button") self.gridLayout.addWidget(self.add_button, 1, 3, 1, 1) self.quantity_number = QtWidgets.QSpinBox(self.quick_add_box) self.quantity_number.setObjectName("quantity_number") self.gridLayout.addWidget(self.quantity_number, 1, 2, 1, 1) self.horizontalLayout_3.addLayout(self.gridLayout) self.verticalLayout_3.addLayout(self.horizontalLayout_3) self.line = QtWidgets.QFrame(self.quick_add_box) self.line.setFrameShape(QtWidgets.QFrame.HLine) self.line.setFrameShadow(QtWidgets.QFrame.Sunken) self.line.setObjectName("line") self.verticalLayout_3.addWidget(self.line) self.horizontalLayout_4 = QtWidgets.QHBoxLayout() self.horizontalLayout_4.setObjectName("horizontalLayout_4") self.total_label = QtWidgets.QLabel(self.quick_add_box) self.total_label.setFrameShape(QtWidgets.QFrame.NoFrame) self.total_label.setObjectName("total_label") self.horizontalLayout_4.addWidget(self.total_label) spacerItem = QtWidgets.QSpacerItem( 40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_4.addItem(spacerItem) self.start_button = QtWidgets.QPushButton(self.quick_add_box) self.start_button.setText("") icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap( ":/start/ic_play_arrow_black_18dp_2x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.start_button.setIcon(icon) self.start_button.setObjectName("start_button") self.horizontalLayout_4.addWidget(self.start_button) self.stop_button = QtWidgets.QPushButton(self.quick_add_box) self.stop_button.setText("") icon1 = QtGui.QIcon() icon1.addPixmap(QtGui.QPixmap( ":/stop/ic_stop_black_18dp_2x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.stop_button.setIcon(icon1) self.stop_button.setObjectName("stop_button") self.horizontalLayout_4.addWidget(self.stop_button) self.verticalLayout_3.addLayout(self.horizontalLayout_4) self.verticalLayout_4.addLayout(self.verticalLayout_3) self.verticalLayout.addWidget(self.quick_add_box) self.verticalLayout_2.addLayout(self.verticalLayout) self.label_5 = QtWidgets.QLabel(self.centralwidget) self.label_5.setScaledContents(True) self.label_5.setObjectName("label_5") self.verticalLayout_2.addWidget(self.label_5) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") self.bill_box = QtWidgets.QGroupBox(self.centralwidget) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(2) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.bill_box.sizePolicy().hasHeightForWidth()) self.bill_box.setSizePolicy(sizePolicy) self.bill_box.setObjectName("bill_box") self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.bill_box) self.verticalLayout_8.setObjectName("verticalLayout_8") self.verticalLayout_7 = QtWidgets.QVBoxLayout() self.verticalLayout_7.setObjectName("verticalLayout_7") self.gridLayout_2 = QtWidgets.QGridLayout() self.gridLayout_2.setObjectName("gridLayout_2") self.bill_name_label = QtWidgets.QLabel(self.bill_box) self.bill_name_label.setObjectName("bill_name_label") self.gridLayout_2.addWidget(self.bill_name_label, 0, 0, 1, 1) self.bill_product_list = QtWidgets.QComboBox(self.bill_box) self.bill_product_list.setObjectName("bill_product_list") self.gridLayout_2.addWidget(self.bill_product_list, 2, 1, 1, 1) self.bill_buyer_type_label = QtWidgets.QLabel(self.bill_box) self.bill_buyer_type_label.setObjectName("bill_buyer_type_label") self.gridLayout_2.addWidget(self.bill_buyer_type_label, 1, 0, 1, 1) self.bill_buyer_list = QtWidgets.QComboBox(self.bill_box) self.bill_buyer_list.setObjectName("bill_buyer_list") self.gridLayout_2.addWidget(self.bill_buyer_list, 1, 1, 1, 1) self.bill_product_label = QtWidgets.QLabel(self.bill_box) self.bill_product_label.setObjectName("bill_product_label") self.gridLayout_2.addWidget(self.bill_product_label, 2, 0, 1, 1) self.bill_name_line = QtWidgets.QLineEdit(self.bill_box) self.bill_name_line.setObjectName("bill_name_line") self.gridLayout_2.addWidget(self.bill_name_line, 0, 1, 1, 1) self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") spacerItem1 = QtWidgets.QSpacerItem( 40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem1) self.bill_quantity_no = QtWidgets.QSpinBox(self.bill_box) self.bill_quantity_no.setObjectName("bill_quantity_no") self.horizontalLayout_2.addWidget(self.bill_quantity_no) self.bill_add_button = QtWidgets.QPushButton(self.bill_box) self.bill_add_button.setObjectName("bill_add_button") self.horizontalLayout_2.addWidget(self.bill_add_button) self.gridLayout_2.addLayout(self.horizontalLayout_2, 3, 1, 1, 1) self.verticalLayout_7.addLayout(self.gridLayout_2) self.tableView = QtWidgets.QTableView(self.bill_box) self.tableView.setObjectName("tableView") self.verticalLayout_7.addWidget(self.tableView) self.horizontalLayout_6 = QtWidgets.QHBoxLayout() self.horizontalLayout_6.setObjectName("horizontalLayout_6") self.delete_button = QtWidgets.QPushButton(self.bill_box) self.delete_button.setObjectName("delete_button") self.horizontalLayout_6.addWidget(self.delete_button) spacerItem2 = QtWidgets.QSpacerItem( 40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_6.addItem(spacerItem2) self.bill_total_label = QtWidgets.QLabel(self.bill_box) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.bill_total_label.sizePolicy().hasHeightForWidth()) self.bill_total_label.setSizePolicy(sizePolicy) self.bill_total_label.setObjectName("bill_total_label") self.horizontalLayout_6.addWidget(self.bill_total_label) self.verticalLayout_7.addLayout(self.horizontalLayout_6) self.horizontalLayout_5 = QtWidgets.QHBoxLayout() self.horizontalLayout_5.setSizeConstraint( QtWidgets.QLayout.SetDefaultConstraint) self.horizontalLayout_5.setObjectName("horizontalLayout_5") self.print_check = QtWidgets.QCheckBox(self.bill_box) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.print_check.sizePolicy().hasHeightForWidth()) self.print_check.setSizePolicy(sizePolicy) self.print_check.setLayoutDirection(QtCore.Qt.RightToLeft) self.print_check.setObjectName("print_check") self.horizontalLayout_5.addWidget(self.print_check) spacerItem3 = QtWidgets.QSpacerItem( 40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_5.addItem(spacerItem3) self.submit_button = QtWidgets.QPushButton(self.bill_box) self.submit_button.setObjectName("submit_button") self.horizontalLayout_5.addWidget(self.submit_button) self.verticalLayout_7.addLayout(self.horizontalLayout_5) self.verticalLayout_8.addLayout(self.verticalLayout_7) self.horizontalLayout.addWidget(self.bill_box) self.stock_box = QtWidgets.QGroupBox(self.centralwidget) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.stock_box.sizePolicy().hasHeightForWidth()) self.stock_box.setSizePolicy(sizePolicy) self.stock_box.setObjectName("stock_box") self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.stock_box) self.verticalLayout_6.setObjectName("verticalLayout_6") self.verticalLayout_5 = QtWidgets.QVBoxLayout() self.verticalLayout_5.setObjectName("verticalLayout_5") self.verticalLayout_6.addLayout(self.verticalLayout_5) self.horizontalLayout.addWidget(self.stock_box) self.stock_layout = QtWidgets.QHBoxLayout() self.verticalLayout_6.addWidget(self.stock_list) self.verticalLayout_2.addLayout(self.horizontalLayout) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 31)) self.menubar.setObjectName("menubar") self.menuFile = QtWidgets.QMenu(self.menubar) self.menuFile.setObjectName("menuFile") self.menuEdit = QtWidgets.QMenu(self.menubar) self.menuEdit.setObjectName("menuEdit") self.menuReports = QtWidgets.QMenu(self.menubar) self.menuReports.setObjectName("menuReports") self.menuOptionis = QtWidgets.QMenu(self.menubar) self.menuOptionis.setObjectName("menuOptionis") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.actionExit = QtWidgets.QAction(MainWindow) self.actionExit.setObjectName("actionExit") self.actionAbout = QtWidgets.QAction(MainWindow) self.actionAbout.setObjectName("actionAbout") self.actionUndo = QtWidgets.QAction(MainWindow) self.actionUndo.setObjectName("actionUndo") self.actionEdit_Products_Stock = QtWidgets.QAction(MainWindow) self.actionEdit_Products_Stock.setObjectName( "actionEdit_Products_Stock") self.actionEdit_Sales = QtWidgets.QAction(MainWindow) self.actionEdit_Sales.setObjectName("actionEdit_Sales") self.actionEdit_Buyer = QtWidgets.QAction(MainWindow) self.actionEdit_Buyer.setObjectName("actionEdit_Buyer") self.actionMonthly_Report = QtWidgets.QAction(MainWindow) self.actionMonthly_Report.setObjectName("actionMonthly_Report") self.actionWeekly_Report = QtWidgets.QAction(MainWindow) self.actionWeekly_Report.setObjectName("actionWeekly_Report") self.actionDaily_Report = QtWidgets.QAction(MainWindow) self.actionDaily_Report.setObjectName("actionDaily_Report") self.actionInventory = QtWidgets.QAction(MainWindow) self.actionInventory.setObjectName("actionInventory") self.actionClear_Old_Records = QtWidgets.QAction(MainWindow) self.actionClear_Old_Records.setObjectName("actionClear_Old_Records") # self.actionSettings = QtWidgets.QAction(MainWindow) # self.actionSettings.setObjectName("actionSettings") self.menuFile.addAction(self.actionExit) self.menuFile.addAction(self.actionAbout) self.menuEdit.addAction(self.actionUndo) self.menuEdit.addSeparator() self.menuEdit.addAction(self.actionEdit_Products_Stock) self.menuEdit.addAction(self.actionEdit_Sales) self.menuEdit.addAction(self.actionEdit_Buyer) self.menuReports.addAction(self.actionMonthly_Report) self.menuReports.addAction(self.actionWeekly_Report) self.menuReports.addAction(self.actionDaily_Report) self.menuReports.addAction(self.actionInventory) self.menuOptionis.addAction(self.actionClear_Old_Records) # self.menuOptionis.addAction(self.actionSettings) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuEdit.menuAction()) self.menubar.addAction(self.menuReports.menuAction()) self.menubar.addAction(self.menuOptionis.menuAction()) self.product_list.setEditable(1) self.buyer_list.setEditable(1) self.bill_buyer_list.setEditable(1) self.bill_product_list.setEditable(1) self.dbman.products_model.select() self.proxy_product_model = QSortFilterProxyModel() self.proxy_product_model.setSourceModel(self.dbman.products_model) self.proxy_product_model.insertRow(0) self.proxy_product_model.setFilterKeyColumn(1) self.product_list.setModel(self.proxy_product_model) self.product_list.setModelColumn( self.proxy_product_model.filterKeyColumn()) self.dbman.buyer_model.select() self.proxy_buyer_model = QSortFilterProxyModel() self.proxy_buyer_model.setSourceModel(self.dbman.buyer_model) self.proxy_buyer_model.insertRow(0) self.proxy_buyer_model.setFilterKeyColumn(0) self.buyer_list.setModel(self.proxy_buyer_model) self.buyer_list.setModelColumn( self.proxy_buyer_model.filterKeyColumn()) self.bill_product_list.setModel(self.proxy_product_model) self.bill_product_list.setModelColumn( self.proxy_product_model.filterKeyColumn()) self.bill_buyer_list.setModel(self.proxy_buyer_model) self.bill_buyer_list.setModelColumn( self.proxy_buyer_model.filterKeyColumn()) self.bill_quantity_no.setValue(1) self.start_button.clicked.connect(self.bill_start) self.stop_button.clicked.connect(self.bill_stop) self.add_button.clicked.connect(self.tally) self.bill_add_button.clicked.connect(self.bill_item) self.product_list.currentIndexChanged.connect(self.reset_tally) self.setWindowIcon(QtGui.QIcon('icon.png')) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow)
class Ui_MainWindow(object): dbman = DBMan() dbman.load_tables() dbman.clear_undo() def setupUi(self, MainWindow): self.bill_bool = 2 self.totalbill = 0 self.item_price = 0 self.stock_list = QtWidgets.QTextEdit() self.stock_list.setReadOnly(1) MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 688) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.centralwidget) self.verticalLayout_2.setObjectName("verticalLayout_2") self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout.setSizeConstraint( QtWidgets.QLayout.SetDefaultConstraint) self.verticalLayout.setObjectName("verticalLayout") self.quick_add_box = QtWidgets.QGroupBox(self.centralwidget) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.quick_add_box.sizePolicy().hasHeightForWidth()) self.quick_add_box.setSizePolicy(sizePolicy) self.quick_add_box.setObjectName("quick_add_box") self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.quick_add_box) self.verticalLayout_4.setSizeConstraint( QtWidgets.QLayout.SetDefaultConstraint) self.verticalLayout_4.setSpacing(1) self.verticalLayout_4.setObjectName("verticalLayout_4") self.verticalLayout_3 = QtWidgets.QVBoxLayout() self.verticalLayout_3.setSpacing(10) self.verticalLayout_3.setObjectName("verticalLayout_3") self.horizontalLayout_3 = QtWidgets.QHBoxLayout() self.horizontalLayout_3.setObjectName("horizontalLayout_3") self.gridLayout = QtWidgets.QGridLayout() self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize) self.gridLayout.setHorizontalSpacing(4) self.gridLayout.setVerticalSpacing(0) self.gridLayout.setObjectName("gridLayout") self.product_list = QtWidgets.QComboBox(self.quick_add_box) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(2) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.product_list.sizePolicy().hasHeightForWidth()) self.product_list.setSizePolicy(sizePolicy) self.product_list.setObjectName("product_list") self.gridLayout.addWidget(self.product_list, 1, 0, 1, 1) self.product_label = QtWidgets.QLabel(self.quick_add_box) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.product_label.sizePolicy().hasHeightForWidth()) self.product_label.setSizePolicy(sizePolicy) self.product_label.setObjectName("product_label") self.gridLayout.addWidget(self.product_label, 0, 0, 1, 1) self.buyer_list = QtWidgets.QComboBox(self.quick_add_box) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.buyer_list.sizePolicy().hasHeightForWidth()) self.buyer_list.setSizePolicy(sizePolicy) self.buyer_list.setObjectName("buyer_list") self.gridLayout.addWidget(self.buyer_list, 1, 1, 1, 1) self.buyer_label = QtWidgets.QLabel(self.quick_add_box) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.buyer_label.sizePolicy().hasHeightForWidth()) self.buyer_label.setSizePolicy(sizePolicy) self.buyer_label.setObjectName("buyer_label") self.gridLayout.addWidget(self.buyer_label, 0, 1, 1, 1) self.add_button = QtWidgets.QPushButton(self.quick_add_box) self.add_button.setObjectName("add_button") self.gridLayout.addWidget(self.add_button, 1, 3, 1, 1) self.quantity_number = QtWidgets.QSpinBox(self.quick_add_box) self.quantity_number.setObjectName("quantity_number") self.gridLayout.addWidget(self.quantity_number, 1, 2, 1, 1) self.horizontalLayout_3.addLayout(self.gridLayout) self.verticalLayout_3.addLayout(self.horizontalLayout_3) self.line = QtWidgets.QFrame(self.quick_add_box) self.line.setFrameShape(QtWidgets.QFrame.HLine) self.line.setFrameShadow(QtWidgets.QFrame.Sunken) self.line.setObjectName("line") self.verticalLayout_3.addWidget(self.line) self.horizontalLayout_4 = QtWidgets.QHBoxLayout() self.horizontalLayout_4.setObjectName("horizontalLayout_4") self.total_label = QtWidgets.QLabel(self.quick_add_box) self.total_label.setFrameShape(QtWidgets.QFrame.NoFrame) self.total_label.setObjectName("total_label") self.horizontalLayout_4.addWidget(self.total_label) spacerItem = QtWidgets.QSpacerItem( 40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_4.addItem(spacerItem) self.start_button = QtWidgets.QPushButton(self.quick_add_box) self.start_button.setText("") icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap( ":/start/ic_play_arrow_black_18dp_2x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.start_button.setIcon(icon) self.start_button.setObjectName("start_button") self.horizontalLayout_4.addWidget(self.start_button) self.stop_button = QtWidgets.QPushButton(self.quick_add_box) self.stop_button.setText("") icon1 = QtGui.QIcon() icon1.addPixmap(QtGui.QPixmap( ":/stop/ic_stop_black_18dp_2x.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.stop_button.setIcon(icon1) self.stop_button.setObjectName("stop_button") self.horizontalLayout_4.addWidget(self.stop_button) self.verticalLayout_3.addLayout(self.horizontalLayout_4) self.verticalLayout_4.addLayout(self.verticalLayout_3) self.verticalLayout.addWidget(self.quick_add_box) self.verticalLayout_2.addLayout(self.verticalLayout) self.label_5 = QtWidgets.QLabel(self.centralwidget) self.label_5.setScaledContents(True) self.label_5.setObjectName("label_5") self.verticalLayout_2.addWidget(self.label_5) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") self.bill_box = QtWidgets.QGroupBox(self.centralwidget) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(2) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.bill_box.sizePolicy().hasHeightForWidth()) self.bill_box.setSizePolicy(sizePolicy) self.bill_box.setObjectName("bill_box") self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.bill_box) self.verticalLayout_8.setObjectName("verticalLayout_8") self.verticalLayout_7 = QtWidgets.QVBoxLayout() self.verticalLayout_7.setObjectName("verticalLayout_7") self.gridLayout_2 = QtWidgets.QGridLayout() self.gridLayout_2.setObjectName("gridLayout_2") self.bill_name_label = QtWidgets.QLabel(self.bill_box) self.bill_name_label.setObjectName("bill_name_label") self.gridLayout_2.addWidget(self.bill_name_label, 0, 0, 1, 1) self.bill_product_list = QtWidgets.QComboBox(self.bill_box) self.bill_product_list.setObjectName("bill_product_list") self.gridLayout_2.addWidget(self.bill_product_list, 2, 1, 1, 1) self.bill_buyer_type_label = QtWidgets.QLabel(self.bill_box) self.bill_buyer_type_label.setObjectName("bill_buyer_type_label") self.gridLayout_2.addWidget(self.bill_buyer_type_label, 1, 0, 1, 1) self.bill_buyer_list = QtWidgets.QComboBox(self.bill_box) self.bill_buyer_list.setObjectName("bill_buyer_list") self.gridLayout_2.addWidget(self.bill_buyer_list, 1, 1, 1, 1) self.bill_product_label = QtWidgets.QLabel(self.bill_box) self.bill_product_label.setObjectName("bill_product_label") self.gridLayout_2.addWidget(self.bill_product_label, 2, 0, 1, 1) self.bill_name_line = QtWidgets.QLineEdit(self.bill_box) self.bill_name_line.setObjectName("bill_name_line") self.gridLayout_2.addWidget(self.bill_name_line, 0, 1, 1, 1) self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") spacerItem1 = QtWidgets.QSpacerItem( 40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem1) self.bill_quantity_no = QtWidgets.QSpinBox(self.bill_box) self.bill_quantity_no.setObjectName("bill_quantity_no") self.horizontalLayout_2.addWidget(self.bill_quantity_no) self.bill_add_button = QtWidgets.QPushButton(self.bill_box) self.bill_add_button.setObjectName("bill_add_button") self.horizontalLayout_2.addWidget(self.bill_add_button) self.gridLayout_2.addLayout(self.horizontalLayout_2, 3, 1, 1, 1) self.verticalLayout_7.addLayout(self.gridLayout_2) self.tableView = QtWidgets.QTableView(self.bill_box) self.tableView.setObjectName("tableView") self.verticalLayout_7.addWidget(self.tableView) self.horizontalLayout_6 = QtWidgets.QHBoxLayout() self.horizontalLayout_6.setObjectName("horizontalLayout_6") self.delete_button = QtWidgets.QPushButton(self.bill_box) self.delete_button.setObjectName("delete_button") self.horizontalLayout_6.addWidget(self.delete_button) spacerItem2 = QtWidgets.QSpacerItem( 40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_6.addItem(spacerItem2) self.bill_total_label = QtWidgets.QLabel(self.bill_box) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.bill_total_label.sizePolicy().hasHeightForWidth()) self.bill_total_label.setSizePolicy(sizePolicy) self.bill_total_label.setObjectName("bill_total_label") self.horizontalLayout_6.addWidget(self.bill_total_label) self.verticalLayout_7.addLayout(self.horizontalLayout_6) self.horizontalLayout_5 = QtWidgets.QHBoxLayout() self.horizontalLayout_5.setSizeConstraint( QtWidgets.QLayout.SetDefaultConstraint) self.horizontalLayout_5.setObjectName("horizontalLayout_5") self.print_check = QtWidgets.QCheckBox(self.bill_box) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.print_check.sizePolicy().hasHeightForWidth()) self.print_check.setSizePolicy(sizePolicy) self.print_check.setLayoutDirection(QtCore.Qt.RightToLeft) self.print_check.setObjectName("print_check") self.horizontalLayout_5.addWidget(self.print_check) spacerItem3 = QtWidgets.QSpacerItem( 40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_5.addItem(spacerItem3) self.submit_button = QtWidgets.QPushButton(self.bill_box) self.submit_button.setObjectName("submit_button") self.horizontalLayout_5.addWidget(self.submit_button) self.verticalLayout_7.addLayout(self.horizontalLayout_5) self.verticalLayout_8.addLayout(self.verticalLayout_7) self.horizontalLayout.addWidget(self.bill_box) self.stock_box = QtWidgets.QGroupBox(self.centralwidget) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.stock_box.sizePolicy().hasHeightForWidth()) self.stock_box.setSizePolicy(sizePolicy) self.stock_box.setObjectName("stock_box") self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.stock_box) self.verticalLayout_6.setObjectName("verticalLayout_6") self.verticalLayout_5 = QtWidgets.QVBoxLayout() self.verticalLayout_5.setObjectName("verticalLayout_5") self.verticalLayout_6.addLayout(self.verticalLayout_5) self.horizontalLayout.addWidget(self.stock_box) self.stock_layout = QtWidgets.QHBoxLayout() self.verticalLayout_6.addWidget(self.stock_list) self.verticalLayout_2.addLayout(self.horizontalLayout) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 31)) self.menubar.setObjectName("menubar") self.menuFile = QtWidgets.QMenu(self.menubar) self.menuFile.setObjectName("menuFile") self.menuEdit = QtWidgets.QMenu(self.menubar) self.menuEdit.setObjectName("menuEdit") self.menuReports = QtWidgets.QMenu(self.menubar) self.menuReports.setObjectName("menuReports") self.menuOptionis = QtWidgets.QMenu(self.menubar) self.menuOptionis.setObjectName("menuOptionis") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.actionExit = QtWidgets.QAction(MainWindow) self.actionExit.setObjectName("actionExit") self.actionAbout = QtWidgets.QAction(MainWindow) self.actionAbout.setObjectName("actionAbout") self.actionUndo = QtWidgets.QAction(MainWindow) self.actionUndo.setObjectName("actionUndo") self.actionEdit_Products_Stock = QtWidgets.QAction(MainWindow) self.actionEdit_Products_Stock.setObjectName( "actionEdit_Products_Stock") self.actionEdit_Sales = QtWidgets.QAction(MainWindow) self.actionEdit_Sales.setObjectName("actionEdit_Sales") self.actionEdit_Buyer = QtWidgets.QAction(MainWindow) self.actionEdit_Buyer.setObjectName("actionEdit_Buyer") self.actionMonthly_Report = QtWidgets.QAction(MainWindow) self.actionMonthly_Report.setObjectName("actionMonthly_Report") self.actionWeekly_Report = QtWidgets.QAction(MainWindow) self.actionWeekly_Report.setObjectName("actionWeekly_Report") self.actionDaily_Report = QtWidgets.QAction(MainWindow) self.actionDaily_Report.setObjectName("actionDaily_Report") self.actionInventory = QtWidgets.QAction(MainWindow) self.actionInventory.setObjectName("actionInventory") self.actionClear_Old_Records = QtWidgets.QAction(MainWindow) self.actionClear_Old_Records.setObjectName("actionClear_Old_Records") # self.actionSettings = QtWidgets.QAction(MainWindow) # self.actionSettings.setObjectName("actionSettings") self.menuFile.addAction(self.actionExit) self.menuFile.addAction(self.actionAbout) self.menuEdit.addAction(self.actionUndo) self.menuEdit.addSeparator() self.menuEdit.addAction(self.actionEdit_Products_Stock) self.menuEdit.addAction(self.actionEdit_Sales) self.menuEdit.addAction(self.actionEdit_Buyer) self.menuReports.addAction(self.actionMonthly_Report) self.menuReports.addAction(self.actionWeekly_Report) self.menuReports.addAction(self.actionDaily_Report) self.menuReports.addAction(self.actionInventory) self.menuOptionis.addAction(self.actionClear_Old_Records) # self.menuOptionis.addAction(self.actionSettings) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuEdit.menuAction()) self.menubar.addAction(self.menuReports.menuAction()) self.menubar.addAction(self.menuOptionis.menuAction()) self.product_list.setEditable(1) self.buyer_list.setEditable(1) self.bill_buyer_list.setEditable(1) self.bill_product_list.setEditable(1) self.dbman.products_model.select() self.proxy_product_model = QSortFilterProxyModel() self.proxy_product_model.setSourceModel(self.dbman.products_model) self.proxy_product_model.insertRow(0) self.proxy_product_model.setFilterKeyColumn(1) self.product_list.setModel(self.proxy_product_model) self.product_list.setModelColumn( self.proxy_product_model.filterKeyColumn()) self.dbman.buyer_model.select() self.proxy_buyer_model = QSortFilterProxyModel() self.proxy_buyer_model.setSourceModel(self.dbman.buyer_model) self.proxy_buyer_model.insertRow(0) self.proxy_buyer_model.setFilterKeyColumn(0) self.buyer_list.setModel(self.proxy_buyer_model) self.buyer_list.setModelColumn( self.proxy_buyer_model.filterKeyColumn()) self.bill_product_list.setModel(self.proxy_product_model) self.bill_product_list.setModelColumn( self.proxy_product_model.filterKeyColumn()) self.bill_buyer_list.setModel(self.proxy_buyer_model) self.bill_buyer_list.setModelColumn( self.proxy_buyer_model.filterKeyColumn()) self.bill_quantity_no.setValue(1) self.start_button.clicked.connect(self.bill_start) self.stop_button.clicked.connect(self.bill_stop) self.add_button.clicked.connect(self.tally) self.bill_add_button.clicked.connect(self.bill_item) self.product_list.currentIndexChanged.connect(self.reset_tally) self.setWindowIcon(QtGui.QIcon('icon.png')) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "IET Store Log")) self.quick_add_box.setTitle(_translate("MainWindow", "Quick Add")) self.product_label.setText(_translate("MainWindow", "Product")) self.buyer_label.setText(_translate("MainWindow", "Customer Type")) self.add_button.setText(_translate("MainWindow", "Submit")) self.total_label.setText(_translate("MainWindow", "Total : 0")) self.label_5.setText(_translate( "MainWindow", "<b> Last Added : None </b>")) self.label_5.setAlignment(QtCore.Qt.AlignCenter) self.bill_box.setTitle(_translate("MainWindow", "Bill")) self.bill_name_label.setText(_translate("MainWindow", "Customer Name")) self.bill_buyer_type_label.setText( _translate("MainWindow", "Customer Type")) self.bill_product_label.setText(_translate("MainWindow", "Product")) self.bill_add_button.setText(_translate("MainWindow", "Add")) self.delete_button.setText(_translate("MainWindow", "Delete")) self.bill_total_label.setText(_translate("MainWindow", "Total : 0")) self.print_check.setText(_translate("MainWindow", "Print")) self.submit_button.setText(_translate("MainWindow", "Submit")) self.stock_box.setTitle(_translate("MainWindow", "Lowest Stock")) self.menuFile.setTitle(_translate("MainWindow", "&File")) self.menuEdit.setTitle(_translate("MainWindow", "&Edit")) self.menuReports.setTitle(_translate("MainWindow", "&Reports")) self.menuOptionis.setTitle(_translate("MainWindow", "Opt&ions")) self.actionExit.setText(_translate("MainWindow", "Exit")) self.actionAbout.setText(_translate("MainWindow", "About")) self.actionUndo.setText(_translate("MainWindow", "Undo")) self.actionEdit_Products_Stock.setText( _translate("MainWindow", "Edit Products & Stock")) self.actionEdit_Sales.setText(_translate("MainWindow", "Edit Sales")) self.actionEdit_Buyer.setText( _translate("MainWindow", "Edit Customer Type")) self.actionMonthly_Report.setText( _translate("MainWindow", "Monthly Report")) self.actionWeekly_Report.setText( _translate("MainWindow", "Weekly Report")) self.actionDaily_Report.setText( _translate("MainWindow", "Daily Report")) self.actionInventory.setText(_translate("MainWindow", "Inventory")) self.actionClear_Old_Records.setText( _translate("MainWindow", "Clear Old Records")) # self.actionSettings.setText(_translate("MainWindow", "Settings")) self.actionExit.triggered.connect(self.close_window) self.actionAbout.triggered.connect(self.about_dialog) self.actionUndo.triggered.connect(self.undo) self.actionEdit_Products_Stock.triggered.connect( self.dialog_edit_products) self.actionEdit_Sales.triggered.connect(self.dialog_edit_sales) self.actionEdit_Buyer.triggered.connect(self.dialog_edit_buyer) self.actionMonthly_Report.triggered.connect(self.gen_month_report) self.actionWeekly_Report.triggered.connect(self.gen_weekly_report) self.actionDaily_Report.triggered.connect(self.gen_daily_report) self.actionInventory.triggered.connect(self.inventory) self.actionClear_Old_Records.triggered.connect(self.cleaner) self.delete_button.clicked.connect(self.delete) self.submit_button.clicked.connect(self.billmaker) self.stock_list.setText(self.dbman.load_low_stock()) def close_window(self): self.close() pass def bill_start(self): self.bill_bool = 0 self.totalbill = 0 self.total_label.setText("Total : " + str(self.totalbill)) def bill(self): stock = int(self.dbman.return_stock(self.product_list.currentText())) price = int(self.dbman.return_price(self.product_list.currentText())) tally = int(self.quantity_number.value()) if stock >= tally: if self.bill_bool == 0: self.totalbill = self.totalbill + (tally * price) print(self.totalbill) self.total_label.setText("Total : " + str(self.totalbill)) def bill_stop(self): self.bill_bool = 1 def reset_tally(self): self.quantity_number.setValue(1) def tally(self): if self.product_list.currentIndex() != 0: tally = self.quantity_number.value() pname = str(self.product_list.currentText()) print(pname) self.buyer_type = str(self.buyer_list.currentText()) sale = self.dbman.update_sales(pname, tally, self.buyer_type) self.bill() if sale: self.label_5.setText("<b>" + "Last Added : " + sale + "</b>") def dialog_edit_products(self): products_dialog = TableEditor('products') products_dialog.exec_() self.stock_list.setText(self.dbman.load_low_stock()) self.dbman.products_model.select() def about_dialog(self): about = """ <h2 style="text-align: center;">Created By,</h2> <h4 style="text-align: center;">Javed Hussain</h4> <h4 style="text-align: center;">Neethu KT</h4> <h4 style="text-align: center;">Shahma P</h4> <h4 style="text-align: center;">Anu Krishna</h4> <h3 style="text-align: center;"> </h3> <h3 style="text-align: center;">IT 2015 - 2019</h3> <h3 style="text-align: center;"><a href="https://github.com/trailblazer42">Github</a></h3> """ dial = warning(1, about) dial.exec_() def dialog_edit_sales(self): sales_dialog = TableEditor('salesview') sales_dialog.exec_() def dialog_edit_buyer(self): sales_dialog = TableEditor('buyer_type') sales_dialog.exec_() def gen_month_report(self): sdate = date.today().replace(day=1) edate = date.today() rep_dialog = Report(sdate, edate) rep_dialog.exec_() def gen_weekly_report(self): edate = date.today() sdate = edate - timedelta(7) rep_dialog = Report(sdate, edate) rep_dialog.exec_() def gen_daily_report(self): edate = date.today() rep_dialog = Report(edate, edate) rep_dialog.exec_() def cleaner(self): self.dbman.clean() def undo(self): self.dbman.undo_sale() def inventory(self): inv = Inventory() inv.filepick() def billmaker(self): cname = self.bill_name_line.text() buyer = self.bill_buyer_list.currentText() to_print = self.print_check.isChecked() if to_print: bill_generate = Bill(cname, buyer) self.dbman.update_bill_sales(buyer) self.dbman.bill_model.select() else: self.dbman.update_bill_sales(buyer) self.dbman.bill_model.select() self.bill_product_list.setCurrentIndex(-1) self.label_5.setText("<b>" + "Last Added: Bill for " + cname + "</b>") self.bill_name_line.clear() def bill_item(self): self.tableView.setModel(self.dbman.bill_model) self.tableView.setColumnHidden(0, True) pname = self.bill_product_list.currentText() buyer = self.bill_buyer_list.currentText() quantity = self.bill_quantity_no.value() total = self.dbman.update_bill(pname, quantity, buyer) self.bill_total_label.setText("Total : " + str(total)) self.dbman.bill_model.select() def delete(self): self.rowindexes = self.tableView.selectionModel().selectedRows(0) for rindex in (self.rowindexes): row = (rindex.data()) self.dbman.bill_delete(row) self.dbman.bill_model.select()
def edit_contact_dialog(wallet_api, contact_key=None): editing = contact_key is not None if editing: title = _("Edit Contact") else: title = _("New Contact") d = WindowModalDialog(wallet_api.wallet_window.reference(), title) vbox = QVBoxLayout(d) vbox.addWidget(QLabel(title + ':')) def _contact_insert_completion(text): if text: index = combo1.findText(text) combo1.setCurrentIndex(index) identity_line = QLineEdit() name_line = QLineEdit() combo1 = QComboBox() combo1.setFixedWidth(280) combo1.setEditable(True) # add a filter model to filter matching items contact_filter_model = QSortFilterProxyModel(combo1) contact_filter_model.setFilterCaseSensitivity(Qt.CaseInsensitive) contact_filter_model.setSourceModel(combo1.model()) contact_completer = QCompleter(contact_filter_model, combo1) contact_completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) combo1.setCompleter(contact_completer) ok_button = OkButton(d) ok_button.setEnabled(False) def _validate_form() -> None: def _set_validation_state(element, is_valid) -> None: if not is_valid: element.setStyleSheet("border: 1px solid red") else: element.setStyleSheet("") can_submit = True system_name = combo1.currentText().lower().strip() is_valid = True try: system_id = get_system_id(system_name) except ContactDataError: system_id = None is_valid = False _set_validation_state(combo1, is_valid) can_submit = can_submit and is_valid identity_text = identity_line.text().strip() if system_id is None: identity_result = IdentityCheckResult.Invalid else: identity_result = wallet_api.check_identity_valid( system_id, identity_text, skip_exists=editing) is_valid = identity_result == IdentityCheckResult.Ok _set_validation_state(identity_line, is_valid) if is_valid: identity_line.setToolTip("") elif identity_result == IdentityCheckResult.Invalid: if system_id == IdentitySystem.OnChain: identity_line.setToolTip(_("Not a valid Bitcoin address")) else: identity_line.setToolTip(_("Incorrect format")) elif identity_result == IdentityCheckResult.InUse: identity_line.setToolTip(_("Already in use")) can_submit = can_submit and is_valid name_text = name_line.text().strip() name_result = wallet_api.check_label(name_text) is_valid = (name_result == IdentityCheckResult.Ok or editing and name_result == IdentityCheckResult.InUse) _set_validation_state(name_line, is_valid) if is_valid: name_line.setToolTip("") elif name_result == IdentityCheckResult.Invalid: name_line.setToolTip(_("Name too short")) elif name_result == IdentityCheckResult.InUse: name_line.setToolTip(_("Name already in use")) can_submit = can_submit and is_valid ok_button.setEnabled(can_submit) def _contact_text_changed(text: str) -> None: _validate_form() combo1.lineEdit().textEdited.connect( contact_filter_model.setFilterFixedString) combo1.editTextChanged.connect(_contact_text_changed) identity_line.textChanged.connect(_contact_text_changed) name_line.textChanged.connect(_contact_text_changed) contact_completer.activated.connect(_contact_insert_completion) combo1.addItems(list(IDENTITY_SYSTEM_NAMES.values())) grid = QGridLayout() identity_line.setFixedWidth(280) name_line.setFixedWidth(280) grid.addWidget(QLabel(_("Identity Type")), 1, 0) grid.addWidget(combo1, 1, 1) grid.addWidget(QLabel(_("Identity")), 2, 0) grid.addWidget(identity_line, 2, 1) grid.addWidget(QLabel(_("Name")), 3, 0) grid.addWidget(name_line, 3, 1) vbox.addLayout(grid) vbox.addLayout(Buttons(CancelButton(d), ok_button)) if contact_key is None: combo1.lineEdit().setText( IDENTITY_SYSTEM_NAMES[IdentitySystem.OnChain]) identity_line.setFocus() else: entry = wallet_api.get_contact(contact_key[0]) identity = [ ci for ci in entry.identities if ci.identity_id == contact_key[1] ][0] combo1.lineEdit().setText(IDENTITY_SYSTEM_NAMES[identity.system_id]) identity_line.setText(identity.system_data) name_line.setText(entry.label) name_line.setFocus() if d.exec_(): name_text = name_line.text().strip() identity_text = identity_line.text().strip() system_id = get_system_id(combo1.currentText()) if contact_key is not None: contact = wallet_api.get_contact(contact_key[0]) identity = [ ci for ci in contact.identities if ci.identity_id == contact_key[1] ][0] if contact_key[1] != identity.identity_id: wallet_api.remove_identity(contact_key[0], contact_key[1]) wallet_api.add_identity(contact_key[0], system_id, identity_text) if contact.label != name_text: wallet_api.set_label(contact_key[0], name_text) else: wallet_api.add_contact(system_id, name_text, identity_text)
class SearchFileWidget(QWidget): language_filter_change = pyqtSignal(list) def __init__(self): QWidget.__init__(self) self._refreshing = False self.fileModel = None self.proxyFileModel = None self.videoModel = None self._state = None self.timeLastSearch = QTime.currentTime() self.ui = Ui_SearchFileWidget() self.setup_ui() def set_state(self, state): self._state = state self._state.login_status_changed.connect(self.on_login_state_changed) self._state.interface_language_changed.connect( self.on_interface_language_changed) def get_state(self): return self._state def setup_ui(self): self.ui.setupUi(self) settings = QSettings() self.ui.splitter.setSizes([600, 1000]) self.ui.splitter.setChildrenCollapsible(False) # Set up folder view lastDir = settings.value("mainwindow/workingDirectory", QDir.homePath()) log.debug('Current directory: {currentDir}'.format(currentDir=lastDir)) self.fileModel = QFileSystemModel(self) self.fileModel.setFilter(QDir.AllDirs | QDir.Dirs | QDir.Drives | QDir.NoDotAndDotDot | QDir.Readable | QDir.Executable | QDir.Writable) self.fileModel.iconProvider().setOptions( QFileIconProvider.DontUseCustomDirectoryIcons) self.fileModel.setRootPath(QDir.rootPath()) self.fileModel.directoryLoaded.connect(self.onFileModelDirectoryLoaded) self.proxyFileModel = QSortFilterProxyModel(self) self.proxyFileModel.setSortRole(Qt.DisplayRole) self.proxyFileModel.setSourceModel(self.fileModel) self.proxyFileModel.sort(0, Qt.AscendingOrder) self.proxyFileModel.setSortCaseSensitivity(Qt.CaseInsensitive) self.ui.folderView.setModel(self.proxyFileModel) self.ui.folderView.setHeaderHidden(True) self.ui.folderView.hideColumn(3) self.ui.folderView.hideColumn(2) self.ui.folderView.hideColumn(1) index = self.fileModel.index(str(lastDir)) proxyIndex = self.proxyFileModel.mapFromSource(index) self.ui.folderView.scrollTo(proxyIndex) self.ui.folderView.expanded.connect(self.onFolderViewExpanded) self.ui.folderView.clicked.connect(self.onFolderTreeClicked) self.ui.buttonFind.clicked.connect(self.onButtonFind) self.ui.buttonRefresh.clicked.connect(self.onButtonRefresh) # Set up introduction self.showInstructions() # Set up video view self.ui.filterLanguageForVideo.set_unknown_text(_('All languages')) self.ui.filterLanguageForVideo.set_selected_language( UnknownLanguage.create_generic()) self.ui.filterLanguageForVideo.selected_language_changed.connect( self.on_language_combobox_filter_change) self.videoModel = VideoModel(self) self.videoModel.connect_treeview(self.ui.videoView) self.ui.videoView.setHeaderHidden(True) self.ui.videoView.activated.connect(self.onClickVideoTreeView) self.ui.videoView.clicked.connect(self.onClickVideoTreeView) self.ui.videoView.customContextMenuRequested.connect(self.onContext) self.videoModel.dataChanged.connect(self.subtitlesCheckedChanged) self.language_filter_change.connect( self.videoModel.on_filter_languages_change) self.ui.buttonSearchSelectVideos.clicked.connect( self.onButtonSearchSelectVideos) self.ui.buttonSearchSelectFolder.clicked.connect( self.onButtonSearchSelectFolder) self.ui.buttonDownload.clicked.connect(self.onButtonDownload) self.ui.buttonPlay.clicked.connect(self.onButtonPlay) self.ui.buttonIMDB.clicked.connect(self.onViewOnlineInfo) self.ui.videoView.setContextMenuPolicy(Qt.CustomContextMenu) # Drag and Drop files to the videoView enabled self.ui.videoView.__class__.dragEnterEvent = self.dragEnterEvent self.ui.videoView.__class__.dragMoveEvent = self.dragEnterEvent self.ui.videoView.__class__.dropEvent = self.dropEvent self.ui.videoView.setAcceptDrops(1) # FIXME: ok to drop this connect? # self.ui.videoView.clicked.connect(self.onClickMovieTreeView) self.retranslate() def retranslate(self): introduction = '<p align="center"><h2>{title}</h2></p>' \ '<p><b>{tab1header}</b><br/>{tab1content}</p>' \ '<p><b>{tab2header}</b><br/>{tab2content}</p>'\ '<p><b>{tab3header}</b><br/>{tab3content}</p>'.format( title=_('How To Use {title}').format(title=PROJECT_TITLE), tab1header=_('1st Tab:'), tab2header=_('2nd Tab:'), tab3header=_('3rd Tab:'), tab1content=_('Select, from the Folder Tree on the left, the folder which contains the videos ' 'that need subtitles. {project} will then try to automatically find available ' 'subtitles.').format(project=PROJECT_TITLE), tab2content=_('If you don\'t have the videos in your machine, you can search subtitles by ' 'introducing the title/name of the video.').format(project=PROJECT_TITLE), tab3content=_('If you have found some subtitle somewhere else that is not in {project}\'s database, ' 'please upload those subtitles so next users will be able to ' 'find them more easily.').format(project=PROJECT_TITLE)) self.ui.introductionHelp.setHtml(introduction) @pyqtSlot(Language) def on_interface_language_changed(self, language): self.ui.retranslateUi(self) self.retranslate() @pyqtSlot(str) def onFileModelDirectoryLoaded(self, path): settings = QSettings() lastDir = settings.value('mainwindow/workingDirectory', QDir.homePath()) qDirLastDir = QDir(lastDir) qDirLastDir.cdUp() if qDirLastDir.path() == path: index = self.fileModel.index(lastDir) proxyIndex = self.proxyFileModel.mapFromSource(index) self.ui.folderView.scrollTo(proxyIndex) self.ui.folderView.setCurrentIndex(proxyIndex) @pyqtSlot(int, str) def on_login_state_changed(self, state, message): log.debug( 'on_login_state_changed(state={state}, message={message}'.format( state=state, message=message)) if state in (State.LOGIN_STATUS_LOGGED_OUT, State.LOGIN_STATUS_BUSY): self.ui.buttonSearchSelectFolder.setEnabled(False) self.ui.buttonSearchSelectVideos.setEnabled(False) self.ui.buttonFind.setEnabled(False) elif state == State.LOGIN_STATUS_LOGGED_IN: self.ui.buttonSearchSelectFolder.setEnabled(True) self.ui.buttonSearchSelectVideos.setEnabled(True) self.ui.buttonFind.setEnabled( self.get_current_selected_folder() is not None) else: log.warning('unknown state') @pyqtSlot(Language) def on_language_combobox_filter_change(self, language): if language.is_generic(): self.language_filter_change.emit( self.get_state().get_permanent_language_filter()) else: self.language_filter_change.emit([language]) def on_permanent_language_filter_change(self, languages): selected_language = self.ui.filterLanguageForVideo.get_selected_language( ) if selected_language.is_generic(): self.language_filter_change.emit(languages) @pyqtSlot() def subtitlesCheckedChanged(self): subs = self.videoModel.get_checked_subtitles() if subs: self.ui.buttonDownload.setEnabled(True) else: self.ui.buttonDownload.setEnabled(False) def showInstructions(self): self.ui.stackedSearchResult.setCurrentWidget(self.ui.pageIntroduction) def hideInstructions(self): self.ui.stackedSearchResult.setCurrentWidget(self.ui.pageSearchResult) @pyqtSlot(QModelIndex) def onFolderTreeClicked(self, proxyIndex): """What to do when a Folder in the tree is clicked""" if not proxyIndex.isValid(): return index = self.proxyFileModel.mapToSource(proxyIndex) settings = QSettings() folder_path = self.fileModel.filePath(index) settings.setValue('mainwindow/workingDirectory', folder_path) # self.ui.buttonFind.setEnabled(self.get_state().) def get_current_selected_folder(self): proxyIndex = self.ui.folderView.currentIndex() index = self.proxyFileModel.mapToSource(proxyIndex) folder_path = Path(self.fileModel.filePath(index)) if not folder_path: return None return folder_path def get_current_selected_item_videomodel(self): current_index = self.ui.videoView.currentIndex() return self.videoModel.getSelectedItem(current_index) @pyqtSlot() def onButtonFind(self): now = QTime.currentTime() if now < self.timeLastSearch.addMSecs(500): return folder_path = self.get_current_selected_folder() settings = QSettings() settings.setValue('mainwindow/workingDirectory', str(folder_path)) self.search_videos([folder_path]) self.timeLastSearch = QTime.currentTime() @pyqtSlot() def onButtonRefresh(self): currentPath = self.get_current_selected_folder() if not currentPath: settings = QSettings() currentPath = settings.value('mainwindow/workingDirectory', QDir.homePath()) self._refreshing = True self.ui.folderView.collapseAll() currentPath = self.get_current_selected_folder() if not currentPath: settings = QSettings() currentPath = settings.value('mainwindow/workingDirectory', QDir.homePath()) index = self.fileModel.index(str(currentPath)) self.ui.folderView.scrollTo(self.proxyFileModel.mapFromSource(index)) @pyqtSlot(QModelIndex) def onFolderViewExpanded(self, proxyIndex): if self._refreshing: expandedPath = self.fileModel.filePath( self.proxyFileModel.mapToSource(proxyIndex)) if expandedPath == QDir.rootPath(): currentPath = self.get_current_selected_folder() if not currentPath: settings = QSettings() currentPath = settings.value('mainwindow/workingDirectory', QDir.homePath()) index = self.fileModel.index(str(currentPath)) self.ui.folderView.scrollTo( self.proxyFileModel.mapFromSource(index)) self._refreshing = False @pyqtSlot() def onButtonSearchSelectFolder(self): settings = QSettings() path = settings.value('mainwindow/workingDirectory', QDir.homePath()) folder_path = QFileDialog.getExistingDirectory( self, _('Select the directory that contains your videos'), path) if folder_path: settings.setValue('mainwindow/workingDirectory', folder_path) self.search_videos([Path(folder_path)]) @pyqtSlot() def onButtonSearchSelectVideos(self): settings = QSettings() currentDir = settings.value('mainwindow/workingDirectory', QDir.homePath()) fileNames, t = QFileDialog.getOpenFileNames( self, _('Select the video(s) that need subtitles'), currentDir, get_select_videos()) if fileNames: settings.setValue('mainwindow/workingDirectory', QFileInfo(fileNames[0]).absolutePath()) self.search_videos([Path(filename) for filename in fileNames]) def search_videos(self, paths): if not self.get_state().connected(): QMessageBox.about( self, _("Error"), _('You are not connected to the server. Please reconnect first.' )) return self.ui.buttonFind.setEnabled(False) self._search_videos_raw(paths) self.ui.buttonFind.setEnabled(True) def _search_videos_raw(self, paths): # FIXME: must pass mainwindow as argument to ProgressCallbackWidget callback = ProgressCallbackWidget(self) callback.set_title_text(_("Scanning...")) callback.set_label_text(_("Scanning files")) callback.set_finished_text(_("Scanning finished")) callback.set_block(True) callback.show() try: local_videos, local_subs = scan_videopaths(paths, callback=callback, recursive=True) except OSError: callback.cancel() QMessageBox.warning(self, _('Error'), _('Some directories are not accessible.')) if callback.canceled(): return callback.finish() log.debug("Videos found: %s" % local_videos) log.debug("Subtitles found: %s" % local_subs) self.hideInstructions() QCoreApplication.processEvents() if not local_videos: QMessageBox.about(self, _("Scan Results"), _("No video has been found.")) return total = len(local_videos) # FIXME: must pass mainwindow as argument to ProgressCallbackWidget # callback = ProgressCallbackWidget(self) # callback.set_title_text(_("Asking Server...")) # callback.set_label_text(_("Searching subtitles...")) # callback.set_updated_text(_("Searching subtitles ( %d / %d )")) # callback.set_finished_text(_("Search finished")) callback.set_block(True) callback.set_range(0, total) callback.show() callback.set_range(0, 2) download_callback = callback.get_child_progress(0, 1) # videoSearchResults = self.get_state().get_OSDBServer().SearchSubtitles("", videos_piece) remote_subs = self.get_state().get_OSDBServer().search_videos( videos=local_videos, callback=download_callback) self.videoModel.set_videos(local_videos) # self.onFilterLanguageVideo(self.ui.filterLanguageForVideo.get_selected_language()) if remote_subs is None: QMessageBox.about( self, _("Error"), _("Error contacting the server. Please try again later")) callback.finish() # TODO: CHECK if our local subtitles are already in the server, otherwise suggest to upload # self.OSDBServer.CheckSubHash(sub_hashes) @pyqtSlot() def onButtonPlay(self): settings = QSettings() programPath = settings.value('options/VideoPlayerPath', '') parameters = settings.value('options/VideoPlayerParameters', '') if programPath == '': QMessageBox.about( self, _('Error'), _('No default video player has been defined in Settings.')) return selected_subtitle = self.get_current_selected_item_videomodel() if isinstance(selected_subtitle, SubtitleFileNetwork): selected_subtitle = selected_subtitle.get_subtitles()[0] if isinstance(selected_subtitle, LocalSubtitleFile): subtitle_file_path = selected_subtitle.get_filepath() elif isinstance(selected_subtitle, RemoteSubtitleFile): subtitle_file_path = QDir.temp().absoluteFilePath( 'subdownloader.tmp.srt') log.debug( 'Temporary subtitle will be downloaded into: {temp_path}'. format(temp_path=subtitle_file_path)) # FIXME: must pass mainwindow as argument to ProgressCallbackWidget callback = ProgressCallbackWidget(self) callback.set_title_text(_('Playing video + sub')) callback.set_label_text(_('Downloading files...')) callback.set_finished_text(_('Downloading finished')) callback.set_block(True) callback.set_range(0, 100) callback.show() try: subtitle_stream = selected_subtitle.download( self.get_state().get_OSDBServer(), callback=callback) except ProviderConnectionError: log.debug('Unable to download subtitle "{}"'.format( selected_subtitle.get_filename()), exc_info=sys.exc_info()) QMessageBox.about( self, _('Error'), _('Unable to download subtitle "{subtitle}"').format( subtitle=selected_subtitle.get_filename())) callback.finish() return callback.finish() write_stream(subtitle_stream, subtitle_file_path) video = selected_subtitle.get_parent().get_parent().get_parent() def windows_escape(text): return '"{text}"'.format(text=text.replace('"', '\\"')) params = [windows_escape(programPath)] for param in parameters.split(' '): param = param.format(video.get_filepath(), subtitle_file_path) if platform.system() in ('Windows', 'Microsoft'): param = windows_escape(param) params.append(param) pid = None log.info('Running this command: {params}'.format(params=params)) try: log.debug('Trying os.spawnvpe ...') pid = os.spawnvpe(os.P_NOWAIT, programPath, params, os.environ) log.debug('... SUCCESS. pid={pid}'.format(pid=pid)) except AttributeError: log.debug('... FAILED', exc_info=sys.exc_info()) except Exception as e: log.debug('... FAILED', exc_info=sys.exc_info()) if pid is None: try: log.debug('Trying os.fork ...') pid = os.fork() if not pid: log.debug('... SUCCESS. pid={pid}'.format(pid=pid)) os.execvpe(os.P_NOWAIT, programPath, params, os.environ) except: log.debug('... FAIL', exc_info=sys.exc_info()) if pid is None: QMessageBox.about(self, _('Error'), _('Unable to launch videoplayer')) @pyqtSlot(QModelIndex) def onClickVideoTreeView(self, index): data_item = self.videoModel.getSelectedItem(index) if isinstance(data_item, SubtitleFile): self.ui.buttonPlay.setEnabled(True) else: self.ui.buttonPlay.setEnabled(False) if isinstance(data_item, VideoFile): video = data_item if True: # video.getMovieInfo(): self.ui.buttonIMDB.setEnabled(True) self.ui.buttonIMDB.setIcon(QIcon(':/images/info.png')) self.ui.buttonIMDB.setText(_('Movie Info')) elif isinstance(data_item, RemoteSubtitleFile): self.ui.buttonIMDB.setEnabled(True) self.ui.buttonIMDB.setIcon( QIcon(':/images/sites/opensubtitles.png')) self.ui.buttonIMDB.setText(_('Subtitle Info')) else: self.ui.buttonIMDB.setEnabled(False) def onContext(self, point): # FIXME: code duplication with Main.onContext and/or SearchNameWidget and/or SearchFileWidget menu = QMenu('Menu', self) listview = self.ui.videoView index = listview.currentIndex() data_item = listview.model().getSelectedItem(index) if data_item is not None: if isinstance(data_item, VideoFile): video = data_item video_identities = video.get_identities() if any(video_identities.iter_imdb_identity()): online_action = QAction(QIcon(":/images/info.png"), _("View IMDb info"), self) online_action.triggered.connect(self.onViewOnlineInfo) else: online_action = QAction(QIcon(":/images/info.png"), _("Set IMDb info..."), self) online_action.triggered.connect(self.on_set_imdb_info) menu.addAction(online_action) elif isinstance(data_item, SubtitleFile): play_action = QAction(QIcon(":/images/play.png"), _("Play video + subtitle"), self) play_action.triggered.connect(self.onButtonPlay) menu.addAction(play_action) if isinstance(data_item, RemoteSubtitleFile): download_action = QAction(QIcon(":/images/download.png"), _("Download"), self) download_action.triggered.connect(self.onButtonDownload) menu.addAction(download_action) online_action = QAction( QIcon(":/images/sites/opensubtitles.png"), _("View online info"), self) online_action.triggered.connect(self.onViewOnlineInfo) menu.addAction(online_action) # Show the context menu. menu.exec_(listview.mapToGlobal(point)) def onButtonDownload(self): # We download the subtitle in the same folder than the video subs = self.videoModel.get_checked_subtitles() replace_all = False skip_all = False if not subs: QMessageBox.about(self, _("Error"), _("No subtitles selected to be downloaded")) return total_subs = len(subs) answer = None success_downloaded = 0 # FIXME: must pass mainwindow as argument to ProgressCallbackWidget callback = ProgressCallbackWidget(self) callback.set_title_text(_("Downloading...")) callback.set_label_text(_("Downloading files...")) callback.set_updated_text(_("Downloading subtitle {0} ({1}/{2})")) callback.set_finished_text( _("{0} from {1} subtitles downloaded successfully")) callback.set_block(True) callback.set_range(0, total_subs) callback.show() for i, sub in enumerate(subs): if callback.canceled(): break destinationPath = self.get_state().getDownloadPath(self, sub) if not destinationPath: break log.debug("Trying to download subtitle '%s'" % destinationPath) callback.update(i, QFileInfo(destinationPath).fileName(), i + 1, total_subs) # Check if we have write permissions, otherwise show warning window while True: # If the file and the folder don't have write access. if not QFileInfo( destinationPath).isWritable() and not QFileInfo( QFileInfo(destinationPath).absoluteDir().path() ).isWritable(): warningBox = QMessageBox( _("Error write permission"), _("%s cannot be saved.\nCheck that the folder exists and you have write-access permissions." ) % destinationPath, QMessageBox.Warning, QMessageBox.Retry | QMessageBox.Default, QMessageBox.Discard | QMessageBox.Escape, QMessageBox.NoButton, self) saveAsButton = warningBox.addButton( _("Save as..."), QMessageBox.ActionRole) answer = warningBox.exec_() if answer == QMessageBox.Retry: continue elif answer == QMessageBox.Discard: break # Let's get out from the While true # If we choose the SAVE AS elif answer == QMessageBox.NoButton: fileName, t = QFileDialog.getSaveFileName( self, _("Save subtitle as..."), destinationPath, 'All (*.*)') if fileName: destinationPath = fileName else: # If we have write access we leave the while loop. break # If we have chosen Discard subtitle button. if answer == QMessageBox.Discard: continue # Continue the next subtitle optionWhereToDownload = QSettings().value( "options/whereToDownload", "SAME_FOLDER") # Check if doesn't exists already, otherwise show fileExistsBox # dialog if QFileInfo(destinationPath).exists( ) and not replace_all and not skip_all and optionWhereToDownload != "ASK_FOLDER": # The "remote filename" below is actually not the real filename. Real name could be confusing # since we always rename downloaded sub to match movie # filename. fileExistsBox = QMessageBox( QMessageBox.Warning, _("File already exists"), _("Local: {local}\n\nRemote: {remote}\n\nHow would you like to proceed?" ).format(local=destinationPath, remote=QFileInfo(destinationPath).fileName()), QMessageBox.NoButton, self) skipButton = fileExistsBox.addButton(_("Skip"), QMessageBox.ActionRole) # skipAllButton = fileExistsBox.addButton(_("Skip all"), QMessageBox.ActionRole) replaceButton = fileExistsBox.addButton( _("Replace"), QMessageBox.ActionRole) replaceAllButton = fileExistsBox.addButton( _("Replace all"), QMessageBox.ActionRole) saveAsButton = fileExistsBox.addButton(_("Save as..."), QMessageBox.ActionRole) cancelButton = fileExistsBox.addButton(_("Cancel"), QMessageBox.ActionRole) fileExistsBox.exec_() answer = fileExistsBox.clickedButton() if answer == replaceAllButton: # Don't ask us again (for this batch of files) replace_all = True elif answer == saveAsButton: # We will find a uniqiue filename and suggest this to user. # add .<lang> to (inside) the filename. If that is not enough, start adding numbers. # There should also be a preferences setting "Autorename # files" or similar ( =never ask) FIXME suggBaseName, suggFileExt = os.path.splitext( destinationPath) fNameCtr = 0 # Counter used to generate a unique filename suggestedFileName = suggBaseName + '.' + \ sub.get_language().xxx() + suggFileExt while (os.path.exists(suggestedFileName)): fNameCtr += 1 suggestedFileName = suggBaseName + '.' + \ sub.get_language().xxx() + '-' + \ str(fNameCtr) + suggFileExt fileName, t = QFileDialog.getSaveFileName( None, _("Save subtitle as..."), suggestedFileName, 'All (*.*)') if fileName: destinationPath = fileName else: # Skip this particular file if no filename chosen continue elif answer == skipButton: continue # Skip this particular file # elif answer == skipAllButton: # count += percentage # skip_all = True # Skip all files already downloaded # continue elif answer == cancelButton: break # Break out of DL loop - cancel was pushed QCoreApplication.processEvents() # FIXME: redundant update? callback.update(i, QFileInfo(destinationPath).fileName(), i + 1, total_subs) try: if not skip_all: log.debug("Downloading subtitle '%s'" % destinationPath) download_callback = ProgressCallback() # FIXME data_stream = sub.download( provider_instance=self.get_state().get_OSDBServer(), callback=download_callback, ) write_stream(data_stream, destinationPath) except Exception as e: log.exception('Unable to Download subtitle {}'.format( sub.get_filename())) QMessageBox.about( self, _("Error"), _("Unable to download subtitle %s") % sub.get_filename()) callback.finish(success_downloaded, total_subs) def onViewOnlineInfo(self): # FIXME: code duplication with Main.onContext and/or SearchNameWidget and/or SearchFileWidget # Tab for SearchByHash TODO:replace this 0 by an ENUM value listview = self.ui.videoView index = listview.currentIndex() data_item = self.videoModel.getSelectedItem(index) if isinstance(data_item, VideoFile): video = data_item video_identities = video.get_identities() if any(video_identities.iter_imdb_identity()): imdb_identity = next(video_identities.iter_imdb_identity()) webbrowser.open(imdb_identity.get_imdb_url(), new=2, autoraise=1) elif isinstance(data_item, RemoteSubtitleFile): sub = data_item webbrowser.open(sub.get_link(), new=2, autoraise=1) @pyqtSlot() def on_set_imdb_info(self): #FIXME: DUPLICATED WITH SEARCHNAMEWIDGET QMessageBox.about(self, _("Info"), "Not implemented yet. Sorry...")
def setup_ui(self): self.ui.setupUi(self) settings = QSettings() self.ui.splitter.setSizes([600, 1000]) self.ui.splitter.setChildrenCollapsible(False) # Set up folder view lastDir = settings.value("mainwindow/workingDirectory", QDir.homePath()) log.debug('Current directory: {currentDir}'.format(currentDir=lastDir)) self.fileModel = QFileSystemModel(self) self.fileModel.setFilter(QDir.AllDirs | QDir.Dirs | QDir.Drives | QDir.NoDotAndDotDot | QDir.Readable | QDir.Executable | QDir.Writable) self.fileModel.iconProvider().setOptions( QFileIconProvider.DontUseCustomDirectoryIcons) self.fileModel.setRootPath(QDir.rootPath()) self.fileModel.directoryLoaded.connect(self.onFileModelDirectoryLoaded) self.proxyFileModel = QSortFilterProxyModel(self) self.proxyFileModel.setSortRole(Qt.DisplayRole) self.proxyFileModel.setSourceModel(self.fileModel) self.proxyFileModel.sort(0, Qt.AscendingOrder) self.proxyFileModel.setSortCaseSensitivity(Qt.CaseInsensitive) self.ui.folderView.setModel(self.proxyFileModel) self.ui.folderView.setHeaderHidden(True) self.ui.folderView.hideColumn(3) self.ui.folderView.hideColumn(2) self.ui.folderView.hideColumn(1) index = self.fileModel.index(str(lastDir)) proxyIndex = self.proxyFileModel.mapFromSource(index) self.ui.folderView.scrollTo(proxyIndex) self.ui.folderView.expanded.connect(self.onFolderViewExpanded) self.ui.folderView.clicked.connect(self.onFolderTreeClicked) self.ui.buttonFind.clicked.connect(self.onButtonFind) self.ui.buttonRefresh.clicked.connect(self.onButtonRefresh) # Set up introduction self.showInstructions() # Set up video view self.ui.filterLanguageForVideo.set_unknown_text(_('All languages')) self.ui.filterLanguageForVideo.set_selected_language( UnknownLanguage.create_generic()) self.ui.filterLanguageForVideo.selected_language_changed.connect( self.on_language_combobox_filter_change) self.videoModel = VideoModel(self) self.videoModel.connect_treeview(self.ui.videoView) self.ui.videoView.setHeaderHidden(True) self.ui.videoView.activated.connect(self.onClickVideoTreeView) self.ui.videoView.clicked.connect(self.onClickVideoTreeView) self.ui.videoView.customContextMenuRequested.connect(self.onContext) self.videoModel.dataChanged.connect(self.subtitlesCheckedChanged) self.language_filter_change.connect( self.videoModel.on_filter_languages_change) self.ui.buttonSearchSelectVideos.clicked.connect( self.onButtonSearchSelectVideos) self.ui.buttonSearchSelectFolder.clicked.connect( self.onButtonSearchSelectFolder) self.ui.buttonDownload.clicked.connect(self.onButtonDownload) self.ui.buttonPlay.clicked.connect(self.onButtonPlay) self.ui.buttonIMDB.clicked.connect(self.onViewOnlineInfo) self.ui.videoView.setContextMenuPolicy(Qt.CustomContextMenu) # Drag and Drop files to the videoView enabled self.ui.videoView.__class__.dragEnterEvent = self.dragEnterEvent self.ui.videoView.__class__.dragMoveEvent = self.dragEnterEvent self.ui.videoView.__class__.dropEvent = self.dropEvent self.ui.videoView.setAcceptDrops(1) # FIXME: ok to drop this connect? # self.ui.videoView.clicked.connect(self.onClickMovieTreeView) self.retranslate()
def __init__(self, username): QSortFilterProxyModel.__init__(self) self.username = username self.tFilt = "" self.uFilt = "" self.setDynamicSortFilter(True)
class RBACRuleQueryTab(AnalysisTab): """A RBAC rule query.""" def __init__(self, parent, policy, perm_map): super(RBACRuleQueryTab, self).__init__(parent) self.log = logging.getLogger(__name__) self.policy = policy self.query = RBACRuleQuery(policy) self.setupUi() def __del__(self): self.thread.quit() self.thread.wait(5000) logging.getLogger("setools.rbacrulequery").removeHandler(self.handler) def setupUi(self): self.load_ui("apol/rbacrulequery.ui") # set up role autocompletion (source, default) role_completion_list = [str(r) for r in self.policy.roles()] role_completer_model = QStringListModel(self) role_completer_model.setStringList(sorted(role_completion_list)) self.role_completion = QCompleter() self.role_completion.setModel(role_completer_model) self.source.setCompleter(self.role_completion) self.default_role.setCompleter(self.role_completion) # set up role/type autocompletion (target) roletype_completion_list = [str(r) for r in self.policy.roles()] # roletype_completion_list.extend(str(a) for a in self.policy.roleattributes()) roletype_completion_list.extend(str(t) for t in self.policy.types()) roletype_completion_list.extend( str(a) for a in self.policy.typeattributes()) roletype_completer_model = QStringListModel(self) roletype_completer_model.setStringList( sorted(roletype_completion_list)) self.roletype_completion = QCompleter() self.roletype_completion.setModel(roletype_completer_model) self.target.setCompleter(self.roletype_completion) # setup indications of errors on source/target/default self.errors = set() self.orig_palette = self.source.palette() self.error_palette = self.source.palette() self.error_palette.setColor(QPalette.Base, Qt.red) self.clear_source_error() self.clear_target_error() self.clear_default_error() # populate class list self.class_model = SEToolsListModel(self) self.class_model.item_list = sorted(self.policy.classes()) self.tclass.setModel(self.class_model) # set up results self.table_results_model = RBACRuleTableModel(self) self.sort_proxy = QSortFilterProxyModel(self) self.sort_proxy.setSourceModel(self.table_results_model) self.table_results.setModel(self.sort_proxy) self.table_results.sortByColumn(0, Qt.AscendingOrder) # set up processing thread self.thread = QThread() self.worker = QueryResultsUpdater(self.query, self.table_results_model) self.worker.moveToThread(self.thread) self.worker.raw_line.connect(self.raw_results.appendPlainText) self.worker.finished.connect(self.update_complete) self.worker.finished.connect(self.thread.quit) self.thread.started.connect(self.worker.update) # create a "busy, please wait" dialog self.busy = QProgressDialog(self) self.busy.setModal(True) self.busy.setRange(0, 0) self.busy.setMinimumDuration(0) self.busy.canceled.connect(self.thread.requestInterruption) self.busy.reset() # update busy dialog from query INFO logs self.handler = LogHandlerToSignal() self.handler.message.connect(self.busy.setLabelText) logging.getLogger("setools.rbacrulequery").addHandler(self.handler) # Ensure settings are consistent with the initial .ui state self.set_source_regex(self.source_regex.isChecked()) self.set_target_regex(self.target_regex.isChecked()) self.set_default_regex(self.default_regex.isChecked()) self.criteria_frame.setHidden(not self.criteria_expander.isChecked()) self.notes.setHidden(not self.notes_expander.isChecked()) # connect signals self.buttonBox.clicked.connect(self.run) self.clear_ruletypes.clicked.connect(self.clear_all_ruletypes) self.all_ruletypes.clicked.connect(self.set_all_ruletypes) self.source.textEdited.connect(self.clear_source_error) self.source.editingFinished.connect(self.set_source) self.source_regex.toggled.connect(self.set_source_regex) self.target.textEdited.connect(self.clear_target_error) self.target.editingFinished.connect(self.set_target) self.target_regex.toggled.connect(self.set_target_regex) self.tclass.selectionModel().selectionChanged.connect(self.set_tclass) self.invert_class.clicked.connect(self.invert_tclass_selection) self.default_role.textEdited.connect(self.clear_default_error) self.default_role.editingFinished.connect(self.set_default_role) self.default_regex.toggled.connect(self.set_default_regex) # # Ruletype criteria # def _set_ruletypes(self, value): self.allow.setChecked(value) self.role_transition.setChecked(value) def set_all_ruletypes(self): self._set_ruletypes(True) def clear_all_ruletypes(self): self._set_ruletypes(False) # # Source criteria # def clear_source_error(self): self.clear_criteria_error(self.source, "Match the source role of the rule.") def set_source(self): try: self.query.source = self.source.text() except Exception as ex: self.log.error("Source role error: {0}".format(ex)) self.set_criteria_error(self.source, ex) def set_source_regex(self, state): self.log.debug("Setting source_regex {0}".format(state)) self.query.source_regex = state self.clear_source_error() self.set_source() # # Target criteria # def clear_target_error(self): self.clear_criteria_error(self.target, "Match the target role/type of the rule.") def set_target(self): try: self.query.target = self.target.text() except Exception as ex: self.log.error("Target type/role error: {0}".format(ex)) self.set_criteria_error(self.target, ex) def set_target_regex(self, state): self.log.debug("Setting target_regex {0}".format(state)) self.query.target_regex = state self.clear_target_error() self.set_target() # # Class criteria # def set_tclass(self): selected_classes = [] for index in self.tclass.selectionModel().selectedIndexes(): selected_classes.append(self.class_model.data(index, Qt.UserRole)) self.query.tclass = selected_classes def invert_tclass_selection(self): invert_list_selection(self.tclass.selectionModel()) # # Default criteria # def clear_default_error(self): self.clear_criteria_error(self.default_role, "Match the default role the rule.") def set_default_role(self): self.query.default_regex = self.default_regex.isChecked() try: self.query.default = self.default_role.text() except Exception as ex: self.log.error("Default role error: {0}".format(ex)) self.set_criteria_error(self.default_role, ex) def set_default_regex(self, state): self.log.debug("Setting default_regex {0}".format(state)) self.query.default_regex = state self.clear_default_error() self.set_default_role() # # Save/Load tab # def save(self): """Return a dictionary of settings.""" if self.errors: raise TabFieldError("Field(s) are in error: {0}".format(" ".join( o.objectName() for o in self.errors))) settings = {} save_checkboxes(self, settings, [ "criteria_expander", "notes_expander", "allow", "role_transition", "source_indirect", "source_regex", "target_indirect", "target_regex", "default_regex" ]) save_lineedits(self, settings, ["source", "target", "default_role"]) save_listviews(self, settings, ["tclass"]) save_textedits(self, settings, ["notes"]) return settings def load(self, settings): load_checkboxes(self, settings, [ "criteria_expander", "notes_expander", "allow", "role_transition", "source_indirect", "source_regex", "target_indirect", "target_regex", "default_regex" ]) load_lineedits(self, settings, ["source", "target", "default_role"]) load_listviews(self, settings, ["tclass"]) load_textedits(self, settings, ["notes"]) # # Results runner # def run(self, button): # right now there is only one button. rule_types = [] for mode in [self.allow, self.role_transition]: if mode.isChecked(): rule_types.append(mode.objectName()) self.query.ruletype = rule_types self.query.source_indirect = self.source_indirect.isChecked() self.query.target_indirect = self.target_indirect.isChecked() # start processing self.busy.setLabelText("Processing query...") self.busy.show() self.raw_results.clear() self.thread.start() def update_complete(self, count): self.log.info("{0} RBAC rule(s) found.".format(count)) # update sizes/location of result displays if not self.busy.wasCanceled(): self.busy.setLabelText( "Resizing the result table's columns; GUI may be unresponsive") self.busy.repaint() self.table_results.resizeColumnsToContents() if not self.busy.wasCanceled(): self.busy.setLabelText( "Resizing the result table's rows; GUI may be unresponsive") self.busy.repaint() self.table_results.resizeRowsToContents() if not self.busy.wasCanceled(): self.busy.setLabelText( "Moving the raw result to top; GUI may be unresponsive") self.busy.repaint() self.raw_results.moveCursor(QTextCursor.Start) self.busy.reset()
def populate_table(self, table: QTableView, data=[]): model = TableModel(data) sortable_model = QSortFilterProxyModel(model) sortable_model.setSourceModel(model) table.setModel(sortable_model)
def setupUi(self): self.load_ui("netifconquery.ui") # set up user autocompletion user_completion_list = [str(u) for u in self.policy.users()] user_completer_model = QStringListModel(self) user_completer_model.setStringList(sorted(user_completion_list)) self.user_completion = QCompleter() self.user_completion.setModel(user_completer_model) self.user.setCompleter(self.user_completion) # set up role autocompletion role_completion_list = [str(r) for r in self.policy.roles()] role_completer_model = QStringListModel(self) role_completer_model.setStringList(sorted(role_completion_list)) self.role_completion = QCompleter() self.role_completion.setModel(role_completer_model) self.role.setCompleter(self.role_completion) # set up type autocompletion type_completion_list = [str(t) for t in self.policy.types()] type_completer_model = QStringListModel(self) type_completer_model.setStringList(sorted(type_completion_list)) self.type_completion = QCompleter() self.type_completion.setModel(type_completer_model) self.type_.setCompleter(self.type_completion) # setup indications of errors on source/target/default self.orig_palette = self.type_.palette() self.error_palette = self.type_.palette() self.error_palette.setColor(QPalette.Base, Qt.red) self.clear_name_error() self.clear_user_error() self.clear_type_error() self.clear_role_error() self.clear_range_error() # set up results self.table_results_model = NetifconTableModel(self) self.sort_proxy = QSortFilterProxyModel(self) self.sort_proxy.setSourceModel(self.table_results_model) self.table_results.setModel(self.sort_proxy) self.table_results.sortByColumn(0, Qt.AscendingOrder) # set up processing thread self.thread = QThread() self.worker = QueryResultsUpdater(self.query, self.table_results_model) self.worker.moveToThread(self.thread) self.worker.raw_line.connect(self.raw_results.appendPlainText) self.worker.finished.connect(self.update_complete) self.worker.finished.connect(self.thread.quit) self.thread.started.connect(self.worker.update) # create a "busy, please wait" dialog self.busy = QProgressDialog(self) self.busy.setModal(True) self.busy.setRange(0, 0) self.busy.setMinimumDuration(0) self.busy.canceled.connect(self.thread.requestInterruption) self.busy.reset() # update busy dialog from query INFO logs self.handler = LogHandlerToSignal() self.handler.message.connect(self.busy.setLabelText) logging.getLogger("setools.netifconquery").addHandler(self.handler) # Ensure settings are consistent with the initial .ui state self.set_name_regex(self.name_regex.isChecked()) self.criteria_frame.setHidden(not self.criteria_expander.isChecked()) self.notes.setHidden(not self.notes_expander.isChecked()) # Range criteria is available only if policy is MLS if not self.policy.mls: self.range_criteria.setEnabled(False) self.range_criteria.setToolTip("MLS is disabled in this policy.") self.range_.setToolTip("MLS is disabled in this policy.") self.range_exact.setToolTip("MLS is disabled in this policy.") self.range_overlap.setToolTip("MLS is disabled in this policy.") self.range_subset.setToolTip("MLS is disabled in this policy.") self.range_superset.setToolTip("MLS is disabled in this policy.") # connect signals self.buttonBox.clicked.connect(self.run) self.name.textEdited.connect(self.clear_name_error) self.name.editingFinished.connect(self.set_name) self.name_regex.toggled.connect(self.set_name_regex) self.user.textEdited.connect(self.clear_user_error) self.user.editingFinished.connect(self.set_user) self.user_regex.toggled.connect(self.set_user_regex) self.role.textEdited.connect(self.clear_role_error) self.role.editingFinished.connect(self.set_role) self.role_regex.toggled.connect(self.set_role_regex) self.type_.textEdited.connect(self.clear_type_error) self.type_.editingFinished.connect(self.set_type) self.type_regex.toggled.connect(self.set_type_regex) self.range_.textEdited.connect(self.clear_range_error) self.range_.editingFinished.connect(self.set_range)
class DwarfListView(QTreeView): """ Using QTreeView as ListView because it allows ListView+QHeaderView """ def __init__(self, parent=None, search_enabled=True): super(DwarfListView, self).__init__(parent=parent) self._search_enabled = search_enabled self._current_search = '' self._uppercase_hex = True _prefs = Prefs() self.rows_dualcolor = _prefs.get('dwarf_ui_alternaterowcolors', False) self.uppercase_hex = _prefs.get('dwarf_ui_hexstyle', 'upper').lower() == 'upper' self.setEditTriggers(self.NoEditTriggers) self.setHeaderHidden(False) self.setAutoFillBackground(True) self.setRootIsDecorated(False) # TODO: use filter self._proxy_model = QSortFilterProxyModel(self) self._proxy_model.setSourceModel(self.model()) # self.setSortingEnabled(True) def keyPressEvent(self, event): """ onkeydown """ key = event.key() mod = event.modifiers() if key == Qt.Key_F and mod & Qt.ControlModifier and self.search_enabled: # CTRL + F self._on_cm_search() else: super(DwarfListView, self).keyPressEvent(event) # ************************************************************************ # **************************** Properties ******************************** # ************************************************************************ @property def rows_dualcolor(self): """ AlternatingRowColors """ return self.alternatingRowColors() @rows_dualcolor.setter def rows_dualcolor(self, value): """ AlternatingRowColors """ if isinstance(value, bool): self.setAlternatingRowColors(value) elif isinstance(value, str): self.setAlternatingRowColors(value.lower() == 'true') @property def uppercase_hex(self): """ Addresses displayed lower/upper-case """ return self._uppercase_hex @uppercase_hex.setter def uppercase_hex(self, value): """ Addresses displayed lower/upper-case value - bool or str 'upper', 'lower' """ if isinstance(value, bool): self._uppercase_hex = value elif isinstance(value, str): self._uppercase_hex = (value == 'upper') @property def search_enabled(self): return self._search_enabled @search_enabled.setter def search_enabled(self, value): if isinstance(value, bool): self._search_enabled = value # ************************************************************************ # **************************** Functions ********************************* # ************************************************************************ def clear(self): """ Delete Entries but not Headerdata """ model = self.model() if model is not None: model.removeRows(0, model.rowCount()) def get_item(self, index): """ Returns [] with col_texts """ if self.model() is not None: item_data = [] if index < self.model().rowCount(): for i in range(self.model().columnCount()): item_text = self.model().item(index, i).text() if item_text: item_data.append(item_text) else: item_data.append('') return item_data return None def get_item_text(self, index, col): """ returns text in index, col """ if self.model() is not None: if index < self.model().rowCount(): if col < self.model().columnCount(): item = self.model().item(index, col) if isinstance(item, QStandardItem): return self.model().item(index, col).text() return None def contains_text(self, text, case_sensitive=False, stop_at_match=True, match_exactly=False): """ looks in all fields for text returns true, [[row, col]] if text exists """ if not text: return ret_val = False ret_res = [] if self.model() is not None: for i in range(self.model().rowCount()): for j in range(self.model().columnCount()): item_text = self.get_item_text(i, j) if item_text is None: continue if match_exactly: if not case_sensitive: _eval = item_text.lower() == text.lower() else: _eval = item_text == text else: if not case_sensitive: _eval = text.lower() in item_text.lower() else: _eval = item_text in text if _eval: ret_res.append([i, j]) if stop_at_match: break if ret_res: ret_val = True if ret_val: return ret_val, ret_res else: return ret_val, [] def number_of_items(self): """ returns number of rows """ if self.model() is not None: return self.model().rowCount() return None def number_of_rows(self): """ returns number of rows """ if self.model() is not None: return self.number_of_items() return None def number_of_total(self): """ returns number of all fields rows+cols """ if self.model() is not None: return self.model().rowCount() + self.model().columnCount() return None def number_of_cols(self): """ returns number of cols """ if self.model() is not None: return self.model().columnCount() return None # ************************************************************************ # **************************** Handlers ********************************** # ************************************************************************ def mouseDoubleClickEvent(self, event): # pylint: disable=invalid-name """ override doubleclickevent to prevent doublerightclicks """ if event.button() == Qt.LeftButton: super().mouseDoubleClickEvent(event) def resizeEvent(self, event): # pylint: disable=invalid-name """ override to give user control over header back """ super(DwarfListView, self).resizeEvent(event) header = self.header() resize_mode = (QHeaderView.ResizeToContents | QHeaderView.Interactive) if header: for col in range(header.count()): if header.sectionResizeMode(col) == resize_mode: header.setSectionResizeMode(col, QHeaderView.ResizeToContents) width = header.sectionSize(col) header.setSectionResizeMode(col, QHeaderView.Interactive) header.resizeSection(col, width) def _on_cm_search(self): from dwarf_debugger.ui.dialogs.dialog_input import InputDialog accept, input_ = InputDialog.input( self, hint='Search something in this list', placeholder='search...', input_content=self._current_search) if accept and not input_: # reset search self._current_search = '' for row in range(self.model().rowCount()): self.setRowHidden(row, self.model().invisibleRootItem().index(), False) elif accept and input_: # search for input self._current_search = input_ have_result, search_results = self.contains_text( input_, stop_at_match=False) if not have_result: return # hide non matching for row in range(self.model().rowCount()): item = self.model().item(row, 0) hide = True for sr in search_results: if sr[0] == row: hide = False break self.setRowHidden(row, self.model().invisibleRootItem().index(), hide)
class NetifconQueryTab(SEToolsWidget, QScrollArea): """A netifcon query.""" def __init__(self, parent, policy, perm_map): super(NetifconQueryTab, self).__init__(parent) self.log = logging.getLogger(__name__) self.policy = policy self.query = NetifconQuery(policy) self.setupUi() def __del__(self): self.thread.quit() self.thread.wait(5000) logging.getLogger("setools.netifconquery").removeHandler(self.handler) def setupUi(self): self.load_ui("netifconquery.ui") # set up user autocompletion user_completion_list = [str(u) for u in self.policy.users()] user_completer_model = QStringListModel(self) user_completer_model.setStringList(sorted(user_completion_list)) self.user_completion = QCompleter() self.user_completion.setModel(user_completer_model) self.user.setCompleter(self.user_completion) # set up role autocompletion role_completion_list = [str(r) for r in self.policy.roles()] role_completer_model = QStringListModel(self) role_completer_model.setStringList(sorted(role_completion_list)) self.role_completion = QCompleter() self.role_completion.setModel(role_completer_model) self.role.setCompleter(self.role_completion) # set up type autocompletion type_completion_list = [str(t) for t in self.policy.types()] type_completer_model = QStringListModel(self) type_completer_model.setStringList(sorted(type_completion_list)) self.type_completion = QCompleter() self.type_completion.setModel(type_completer_model) self.type_.setCompleter(self.type_completion) # setup indications of errors on source/target/default self.orig_palette = self.type_.palette() self.error_palette = self.type_.palette() self.error_palette.setColor(QPalette.Base, Qt.red) self.clear_name_error() self.clear_user_error() self.clear_type_error() self.clear_role_error() self.clear_range_error() # set up results self.table_results_model = NetifconTableModel(self) self.sort_proxy = QSortFilterProxyModel(self) self.sort_proxy.setSourceModel(self.table_results_model) self.table_results.setModel(self.sort_proxy) self.table_results.sortByColumn(0, Qt.AscendingOrder) # set up processing thread self.thread = QThread() self.worker = QueryResultsUpdater(self.query, self.table_results_model) self.worker.moveToThread(self.thread) self.worker.raw_line.connect(self.raw_results.appendPlainText) self.worker.finished.connect(self.update_complete) self.worker.finished.connect(self.thread.quit) self.thread.started.connect(self.worker.update) # create a "busy, please wait" dialog self.busy = QProgressDialog(self) self.busy.setModal(True) self.busy.setRange(0, 0) self.busy.setMinimumDuration(0) self.busy.canceled.connect(self.thread.requestInterruption) self.busy.reset() # update busy dialog from query INFO logs self.handler = LogHandlerToSignal() self.handler.message.connect(self.busy.setLabelText) logging.getLogger("setools.netifconquery").addHandler(self.handler) # Ensure settings are consistent with the initial .ui state self.set_name_regex(self.name_regex.isChecked()) self.criteria_frame.setHidden(not self.criteria_expander.isChecked()) self.notes.setHidden(not self.notes_expander.isChecked()) # Range criteria is available only if policy is MLS if not self.policy.mls: self.range_criteria.setEnabled(False) self.range_criteria.setToolTip("MLS is disabled in this policy.") self.range_.setToolTip("MLS is disabled in this policy.") self.range_exact.setToolTip("MLS is disabled in this policy.") self.range_overlap.setToolTip("MLS is disabled in this policy.") self.range_subset.setToolTip("MLS is disabled in this policy.") self.range_superset.setToolTip("MLS is disabled in this policy.") # connect signals self.buttonBox.clicked.connect(self.run) self.name.textEdited.connect(self.clear_name_error) self.name.editingFinished.connect(self.set_name) self.name_regex.toggled.connect(self.set_name_regex) self.user.textEdited.connect(self.clear_user_error) self.user.editingFinished.connect(self.set_user) self.user_regex.toggled.connect(self.set_user_regex) self.role.textEdited.connect(self.clear_role_error) self.role.editingFinished.connect(self.set_role) self.role_regex.toggled.connect(self.set_role_regex) self.type_.textEdited.connect(self.clear_type_error) self.type_.editingFinished.connect(self.set_type) self.type_regex.toggled.connect(self.set_type_regex) self.range_.textEdited.connect(self.clear_range_error) self.range_.editingFinished.connect(self.set_range) # # Name criteria # def clear_name_error(self): self.name.setToolTip("Match the device name.") self.name.setPalette(self.orig_palette) def set_name(self): try: self.query.name = self.name.text() except Exception as ex: self.log.error("Device name error: {0}".format(ex)) self.name.setToolTip("Error: " + str(ex)) self.name.setPalette(self.error_palette) def set_name_regex(self, state): self.log.debug("Setting name_regex {0}".format(state)) self.query.name_regex = state self.clear_name_error() self.set_name() # # User criteria # def clear_user_error(self): self.user.setToolTip("Match the user of the context.") self.user.setPalette(self.orig_palette) def set_user(self): try: self.query.user = self.user.text() except Exception as ex: self.log.error("Context user error: {0}".format(ex)) self.user.setToolTip("Error: " + str(ex)) self.user.setPalette(self.error_palette) def set_user_regex(self, state): self.log.debug("Setting user_regex {0}".format(state)) self.query.user_regex = state self.clear_user_error() self.set_user() # # Role criteria # def clear_role_error(self): self.role.setToolTip("Match the role of the context.") self.role.setPalette(self.orig_palette) def set_role(self): try: self.query.role = self.role.text() except Exception as ex: self.log.error("Context role error: {0}".format(ex)) self.role.setToolTip("Error: " + str(ex)) self.role.setPalette(self.error_palette) def set_role_regex(self, state): self.log.debug("Setting role_regex {0}".format(state)) self.query.role_regex = state self.clear_role_error() self.set_role() # # Type criteria # def clear_type_error(self): self.type_.setToolTip("Match the type of the context.") self.type_.setPalette(self.orig_palette) def set_type(self): try: self.query.type_ = self.type_.text() except Exception as ex: self.log.error("Context type error: {0}".format(ex)) self.type_.setToolTip("Error: " + str(ex)) self.type_.setPalette(self.error_palette) def set_type_regex(self, state): self.log.debug("Setting type_regex {0}".format(state)) self.query.type_regex = state self.clear_type_error() self.set_type() # # Range criteria # def clear_range_error(self): self.range_.setToolTip("Match the range of the context.") self.range_.setPalette(self.orig_palette) def set_range(self): try: self.query.range_ = self.range_.text() except Exception as ex: self.log.info("Context range error: " + str(ex)) self.range_.setToolTip("Error: " + str(ex)) self.range_.setPalette(self.error_palette) # # Results runner # def run(self, button): # right now there is only one button. self.query.range_overlap = self.range_overlap.isChecked() self.query.range_subset = self.range_subset.isChecked() self.query.range_superset = self.range_superset.isChecked() # start processing self.busy.setLabelText("Processing query...") self.busy.show() self.raw_results.clear() self.thread.start() def update_complete(self, count): self.log.info("{0} netifcon statment(s) found.".format(count)) # update sizes/location of result displays if not self.busy.wasCanceled(): self.busy.setLabelText( "Resizing the result table's columns; GUI may be unresponsive") self.busy.repaint() self.table_results.resizeColumnsToContents() if not self.busy.wasCanceled(): self.busy.setLabelText( "Resizing the result table's rows; GUI may be unresponsive") self.busy.repaint() self.table_results.resizeRowsToContents() if not self.busy.wasCanceled(): self.busy.setLabelText( "Moving the raw result to top; GUI may be unresponsive") self.busy.repaint() self.raw_results.moveCursor(QTextCursor.Start) self.busy.reset()
class MLSRuleQueryTab(SEToolsWidget, QScrollArea): """An MLS rule query.""" def __init__(self, parent, policy, perm_map): super(MLSRuleQueryTab, self).__init__(parent) self.log = logging.getLogger(__name__) self.policy = policy self.query = MLSRuleQuery(policy) self.setupUi() def __del__(self): self.thread.quit() self.thread.wait(5000) logging.getLogger("setools.mlsrulequery").removeHandler(self.handler) def setupUi(self): self.load_ui("mlsrulequery.ui") # set up source/target autocompletion typeattr_completion_list = [str(t) for t in self.policy.types()] typeattr_completion_list.extend( str(a) for a in self.policy.typeattributes()) typeattr_completer_model = QStringListModel(self) typeattr_completer_model.setStringList( sorted(typeattr_completion_list)) self.typeattr_completion = QCompleter() self.typeattr_completion.setModel(typeattr_completer_model) self.source.setCompleter(self.typeattr_completion) self.target.setCompleter(self.typeattr_completion) # setup indications of errors on source/target/default self.orig_palette = self.source.palette() self.error_palette = self.source.palette() self.error_palette.setColor(QPalette.Base, Qt.red) self.clear_source_error() self.clear_target_error() self.clear_default_error() # populate class list self.class_model = SEToolsListModel(self) self.class_model.item_list = sorted(self.policy.classes()) self.tclass.setModel(self.class_model) # set up results self.table_results_model = MLSRuleTableModel(self) self.sort_proxy = QSortFilterProxyModel(self) self.sort_proxy.setSourceModel(self.table_results_model) self.table_results.setModel(self.sort_proxy) self.table_results.sortByColumn(1, Qt.AscendingOrder) # set up processing thread self.thread = QThread() self.worker = QueryResultsUpdater(self.query, self.table_results_model) self.worker.moveToThread(self.thread) self.worker.raw_line.connect(self.raw_results.appendPlainText) self.worker.finished.connect(self.update_complete) self.worker.finished.connect(self.thread.quit) self.thread.started.connect(self.worker.update) # create a "busy, please wait" dialog self.busy = QProgressDialog(self) self.busy.setModal(True) self.busy.setRange(0, 0) self.busy.setMinimumDuration(0) self.busy.canceled.connect(self.thread.requestInterruption) self.busy.reset() # update busy dialog from query INFO logs self.handler = LogHandlerToSignal() self.handler.message.connect(self.busy.setLabelText) logging.getLogger("setools.mlsrulequery").addHandler(self.handler) # Ensure settings are consistent with the initial .ui state self.set_source_regex(self.source_regex.isChecked()) self.set_target_regex(self.target_regex.isChecked()) self.criteria_frame.setHidden(not self.criteria_expander.isChecked()) self.notes.setHidden(not self.notes_expander.isChecked()) # connect signals self.buttonBox.clicked.connect(self.run) self.clear_ruletypes.clicked.connect(self.clear_all_ruletypes) self.all_ruletypes.clicked.connect(self.set_all_ruletypes) self.source.textEdited.connect(self.clear_source_error) self.source.editingFinished.connect(self.set_source) self.source_regex.toggled.connect(self.set_source_regex) self.target.textEdited.connect(self.clear_target_error) self.target.editingFinished.connect(self.set_target) self.target_regex.toggled.connect(self.set_target_regex) self.tclass.selectionModel().selectionChanged.connect(self.set_tclass) self.invert_class.clicked.connect(self.invert_tclass_selection) self.default_range.textEdited.connect(self.clear_default_error) self.default_range.editingFinished.connect(self.set_default_range) # # Ruletype criteria # def _set_ruletypes(self, value): self.range_transition.setChecked(value) def set_all_ruletypes(self): self._set_ruletypes(True) def clear_all_ruletypes(self): self._set_ruletypes(False) # # Source criteria # def clear_source_error(self): self.source.setToolTip("Match the source type/attribute of the rule.") self.source.setPalette(self.orig_palette) def set_source(self): try: self.query.source = self.source.text() except Exception as ex: self.log.error("Source type/attribute error: {0}".format(ex)) self.source.setToolTip("Error: {0}".format(ex)) self.source.setPalette(self.error_palette) def set_source_regex(self, state): self.log.debug("Setting source_regex {0}".format(state)) self.query.source_regex = state self.clear_source_error() self.set_source() # # Target criteria # def clear_target_error(self): self.target.setToolTip("Match the target type/attribute of the rule.") self.target.setPalette(self.orig_palette) def set_target(self): try: self.query.target = self.target.text() except Exception as ex: self.log.error("Target type/attribute error: {0}".format(ex)) self.target.setToolTip("Error: {0}".format(ex)) self.target.setPalette(self.error_palette) def set_target_regex(self, state): self.log.debug("Setting target_regex {0}".format(state)) self.query.target_regex = state self.clear_target_error() self.set_target() # # Class criteria # def set_tclass(self): selected_classes = [] for index in self.tclass.selectionModel().selectedIndexes(): selected_classes.append(self.class_model.data(index, Qt.UserRole)) self.query.tclass = selected_classes def invert_tclass_selection(self): invert_list_selection(self.tclass.selectionModel()) # # Default criteria # def clear_default_error(self): self.default_range.setToolTip("Match the default type the rule.") self.default_range.setPalette(self.orig_palette) def set_default_range(self): try: self.query.default = self.default_range.text() except Exception as ex: self.log.error("Default range error: {0}".format(ex)) self.default_range.setToolTip("Error: {0}".format(ex)) self.default_range.setPalette(self.error_palette) # # Results runner # def run(self, button): # right now there is only one button. self.query.ruletype = ['range_transition'] self.query.source_indirect = self.source_indirect.isChecked() self.query.target_indirect = self.target_indirect.isChecked() # start processing self.busy.setLabelText("Processing query...") self.busy.show() self.raw_results.clear() self.thread.start() def update_complete(self, count): self.log.info("{0} MLS rule(s) found.".format(count)) # update sizes/location of result displays if not self.busy.wasCanceled(): self.busy.setLabelText( "Resizing the result table's columns; GUI may be unresponsive") self.busy.repaint() self.table_results.resizeColumnsToContents() if not self.busy.wasCanceled(): self.busy.setLabelText( "Resizing the result table's rows; GUI may be unresponsive") self.busy.repaint() self.table_results.resizeRowsToContents() if not self.busy.wasCanceled(): self.busy.setLabelText( "Moving the raw result to top; GUI may be unresponsive") self.busy.repaint() self.raw_results.moveCursor(QTextCursor.Start) self.busy.reset()
class CategoryQueryTab(AnalysisTab): """Category browser and query tab.""" section = AnalysisSection.Components tab_title = "MLS Categories" mlsonly = True def __init__(self, parent, policy, perm_map): super(CategoryQueryTab, self).__init__(parent) self.log = logging.getLogger(__name__) self.policy = policy self.query = CategoryQuery(policy) self.setupUi() def __del__(self): with suppress(RuntimeError): self.thread.quit() self.thread.wait(5000) logging.getLogger("setools.categoryquery").removeHandler(self.handler) def setupUi(self): self.load_ui("apol/categoryquery.ui") # populate category list self.category_model = SEToolsListModel(self) self.category_model.item_list = sorted(self.policy.categories()) self.cats.setModel(self.category_model) # set up results self.table_results_model = MLSComponentTableModel(self) self.sort_proxy = QSortFilterProxyModel(self) self.sort_proxy.setSourceModel(self.table_results_model) self.table_results.setModel(self.sort_proxy) self.table_results.sortByColumn(0, Qt.AscendingOrder) # setup indications of errors on level/range self.errors = set() self.orig_palette = self.name.palette() self.error_palette = self.name.palette() self.error_palette.setColor(QPalette.Base, Qt.red) self.clear_name_error() # set up processing thread self.thread = QThread() self.worker = QueryResultsUpdater(self.query, self.table_results_model) self.worker.moveToThread(self.thread) self.worker.raw_line.connect(self.raw_results.appendPlainText) self.worker.finished.connect(self.update_complete) self.worker.finished.connect(self.thread.quit) self.thread.started.connect(self.worker.update) # create a "busy, please wait" dialog self.busy = QProgressDialog(self) self.busy.setModal(True) self.busy.setRange(0, 0) self.busy.setMinimumDuration(0) self.busy.canceled.connect(self.thread.requestInterruption) self.busy.reset() # update busy dialog from query INFO logs self.handler = LogHandlerToSignal() self.handler.message.connect(self.busy.setLabelText) logging.getLogger("setools.categoryquery").addHandler(self.handler) # Ensure settings are consistent with the initial .ui state self.notes.setHidden(not self.notes_expander.isChecked()) # connect signals self.cats.doubleClicked.connect(self.get_detail) self.cats.get_detail.triggered.connect(self.get_detail) self.name.textEdited.connect(self.clear_name_error) self.name.editingFinished.connect(self.set_name) self.name_regex.toggled.connect(self.set_name_regex) self.buttonBox.clicked.connect(self.run) # # Category browser # def get_detail(self): # .ui is set for single item selection. index = self.cats.selectedIndexes()[0] item = self.category_model.data(index, Qt.UserRole) self.log.debug("Generating detail window for {0}".format(item)) category_detail(self, item) # # Name criteria # def clear_name_error(self): self.clear_criteria_error(self.name, "Match the category name.") def set_name(self): try: self.query.name = self.name.text() except Exception as ex: self.log.error("Category name error: {0}".format(ex)) self.set_criteria_error(self.name, ex) def set_name_regex(self, state): self.log.debug("Setting name_regex {0}".format(state)) self.query.name_regex = state self.clear_name_error() self.set_name() # # Save/Load tab # def save(self): """Return a dictionary of settings.""" if self.errors: raise TabFieldError("Field(s) are in error: {0}".format(" ".join( o.objectName() for o in self.errors))) settings = {} save_checkboxes(self, settings, ["criteria_expander", "notes_expander", "name_regex"]) save_lineedits(self, settings, ["name"]) save_textedits(self, settings, ["notes"]) return settings def load(self, settings): load_checkboxes(self, settings, ["criteria_expander", "notes_expander", "name_regex"]) load_lineedits(self, settings, ["name"]) load_textedits(self, settings, ["notes"]) # # Results runner # def run(self, button): # right now there is only one button. # start processing self.busy.setLabelText("Processing query...") self.busy.show() self.raw_results.clear() self.thread.start() def update_complete(self, count): self.log.info("{0} categories found.".format(count)) # update sizes/location of result displays if not self.busy.wasCanceled(): self.busy.setLabelText( "Resizing the result table's columns; GUI may be unresponsive") self.busy.repaint() self.table_results.resizeColumnsToContents() # If the attrs or alias column widths are too long, pull back # to a reasonable size header = self.table_results.horizontalHeader() if header.sectionSize(1) > 400: header.resizeSection(1, 400) if header.sectionSize(2) > 400: header.resizeSection(2, 400) if not self.busy.wasCanceled(): self.busy.setLabelText( "Resizing the result table's rows; GUI may be unresponsive") self.busy.repaint() self.table_results.resizeRowsToContents() if not self.busy.wasCanceled(): self.busy.setLabelText( "Moving the raw result to top; GUI may be unresponsive") self.busy.repaint() self.raw_results.moveCursor(QTextCursor.Start) self.busy.reset()
class ComboBoxAutocomplete(QComboBox): """UI dropdown element with autocomplete. Attributes: completer (QtWidgets.QCompleter): Autocomplete instance tied to the dropdown items. proxy_model (QtWidgets.QSortFilterProxyModel): Configurations of the autocomplete. """ def __init__(self, parent=None): """Creates default configurations (case insensitive) and constructs the UI element. Args: parent (App(QDialog), optional): Object corresponding to the parent UI element. """ super(ComboBoxAutocomplete, self).__init__(parent) self.setFocusPolicy(Qt.StrongFocus) self.setEditable(True) # Setup proxy model to sort and filter data passed between model and view self.proxy_model = QSortFilterProxyModel(self) self.proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive) self.proxy_model.setSourceModel(self.model()) # Setup completer self.completer = QCompleter(self.proxy_model, self) self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) self.setCompleter(self.completer) # Connect autocompletion signals self.lineEdit().textEdited.connect( self.proxy_model.setFilterFixedString) self.completer.activated.connect(self.on_completer_activated) # Override def on_completer_activated(self, text): """Callback event handler for a query in the autocomplete. Args: text (str): Query text. """ if not text: return index = self.findText(text) self.setCurrentIndex(index) self.activated[str].emit(self.itemText(index)) # Override def setModel(self, model): """Updates the configuration model. Args: model (QtWidgets.QSortFilterProxyModel): New configuration to update to. """ super(ComboBoxAutocomplete, self).setModel(model) self.proxy_model.setSourceModel(model) self.completer.setModel(self.proxy_model) # Override def setModelColumn(self, column): """Updates the column being autocompleted. Args: column (int): Column from the data used for checking suggestions. """ self.completer.setCompletionColumn(column) self.proxy_model.setFilterKeyColumn(column) super(ComboBoxAutocomplete, self).setModelColumn(column)
def __init__(self, parent, *args, **kwargs): super(ListWidget, self).__init__(*args, **kwargs) self.setWindowTitle("Devices list") self.setWindowState(Qt.WindowMaximized) self.setLayout(VLayout(margin=0, spacing=0)) self.mqtt = parent.mqtt self.env = parent.env self.device = None self.idx = None self.nam = QNetworkAccessManager() self.backup = bytes() self.settings = QSettings("{}/TDM/tdm.cfg".format(QDir.homePath()), QSettings.IniFormat) views_order = self.settings.value("views_order", []) self.views = {} self.settings.beginGroup("Views") views = self.settings.childKeys() if views and views_order: for view in views_order.split(";"): view_list = self.settings.value(view).split(";") self.views[view] = base_view + view_list else: self.views = default_views self.settings.endGroup() self.tb = Toolbar(Qt.Horizontal, 24, Qt.ToolButtonTextBesideIcon) self.tb_relays = Toolbar(Qt.Horizontal, 24, Qt.ToolButtonIconOnly) # self.tb_filter = Toolbar(Qt.Horizontal, 24, Qt.ToolButtonTextBesideIcon) self.tb_views = Toolbar(Qt.Horizontal, 24, Qt.ToolButtonTextBesideIcon) self.pwm_sliders = [] self.layout().addWidget(self.tb) self.layout().addWidget(self.tb_relays) # self.layout().addWidget(self.tb_filter) self.device_list = TableView() self.device_list.setIconSize(QSize(24, 24)) self.model = parent.device_model self.model.setupColumns(self.views["Home"]) self.sorted_device_model = QSortFilterProxyModel() self.sorted_device_model.setFilterCaseSensitivity(Qt.CaseInsensitive) self.sorted_device_model.setSourceModel(parent.device_model) self.sorted_device_model.setSortRole(Qt.InitialSortOrderRole) self.sorted_device_model.setSortLocaleAware(True) self.sorted_device_model.setFilterKeyColumn(-1) self.device_list.setModel(self.sorted_device_model) self.device_list.setupView(self.views["Home"]) self.device_list.setSortingEnabled(True) self.device_list.setWordWrap(True) self.device_list.setItemDelegate(DeviceDelegate()) self.device_list.sortByColumn(self.model.columnIndex("FriendlyName"), Qt.AscendingOrder) self.device_list.setContextMenuPolicy(Qt.CustomContextMenu) self.device_list.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) self.layout().addWidget(self.device_list) self.layout().addWidget(self.tb_views) self.device_list.clicked.connect(self.select_device) self.device_list.customContextMenuRequested.connect(self.show_list_ctx_menu) self.ctx_menu = QMenu() self.create_actions() self.create_view_buttons() # self.create_view_filter() self.device_list.doubleClicked.connect(lambda: self.openConsole.emit())
class E5NetworkMonitor(QDialog, Ui_E5NetworkMonitor): """ Class implementing a network monitor dialog. """ _monitor = None @classmethod def instance(cls, networkAccessManager): """ Class method to get a reference to our singleton. @param networkAccessManager reference to the network access manager (QNetworkAccessManager) @return reference to the network monitor singleton (E5NetworkMonitor) """ if cls._monitor is None: cls._monitor = E5NetworkMonitor(networkAccessManager) return cls._monitor @classmethod def closeMonitor(cls): """ Class method to close the monitor dialog. """ if cls._monitor is not None: cls._monitor.close() def __init__(self, networkAccessManager, parent=None): """ Constructor @param networkAccessManager reference to the network access manager (QNetworkAccessManager) @param parent reference to the parent widget (QWidget) """ super(E5NetworkMonitor, self).__init__(parent) self.setupUi(self) self.setWindowFlags(Qt.Window) self.__requestHeaders = QStandardItemModel(self) self.__requestHeaders.setHorizontalHeaderLabels( [self.tr("Name"), self.tr("Value")]) self.requestHeadersList.setModel(self.__requestHeaders) self.requestHeadersList.horizontalHeader().setStretchLastSection(True) self.requestHeadersList.doubleClicked.connect(self.__showHeaderDetails) self.__replyHeaders = QStandardItemModel(self) self.__replyHeaders.setHorizontalHeaderLabels( [self.tr("Name"), self.tr("Value")]) self.responseHeadersList.setModel(self.__replyHeaders) self.responseHeadersList.horizontalHeader().setStretchLastSection(True) self.responseHeadersList.doubleClicked.connect( self.__showHeaderDetails) self.requestsList.horizontalHeader().setStretchLastSection(True) self.requestsList.verticalHeader().setMinimumSectionSize(-1) self.__proxyModel = QSortFilterProxyModel(self) self.__proxyModel.setFilterKeyColumn(-1) self.searchEdit.textChanged.connect( self.__proxyModel.setFilterFixedString) self.removeButton.clicked.connect(self.requestsList.removeSelected) self.removeAllButton.clicked.connect(self.requestsList.removeAll) self.__model = E5RequestModel(networkAccessManager, self) self.__proxyModel.setSourceModel(self.__model) self.requestsList.setModel(self.__proxyModel) self.__proxyModel.rowsInserted.connect( self.requestsList.scrollToBottom) self.requestsList.selectionModel()\ .currentChanged[QModelIndex, QModelIndex]\ .connect(self.__currentChanged) fm = self.fontMetrics() em = fm.width("m") self.requestsList.horizontalHeader().resizeSection(0, em * 5) self.requestsList.horizontalHeader().resizeSection(1, em * 20) self.requestsList.horizontalHeader().resizeSection(3, em * 5) self.requestsList.horizontalHeader().resizeSection(4, em * 15) self.__headersDlg = None def closeEvent(self, evt): """ Protected method called upon closing the dialog. @param evt reference to the close event object (QCloseEvent) """ self.__class__._monitor = None super(E5NetworkMonitor, self).closeEvent(evt) def reject(self): """ Public slot to close the dialog with a Reject status. """ self.__class__._monitor = None super(E5NetworkMonitor, self).reject() def __currentChanged(self, current, previous): """ Private slot to handle a change of the current index. @param current new current index (QModelIndex) @param previous old current index (QModelIndex) """ self.__requestHeaders.setRowCount(0) self.__replyHeaders.setRowCount(0) if not current.isValid(): return row = self.__proxyModel.mapToSource(current).row() req = self.__model.requests[row].request for header in req.rawHeaderList(): self.__requestHeaders.insertRows(0, 1, QModelIndex()) self.__requestHeaders.setData(self.__requestHeaders.index(0, 0), str(header, "utf-8")) self.__requestHeaders.setData(self.__requestHeaders.index(0, 1), str(req.rawHeader(header), "utf-8")) self.__requestHeaders.item(0, 0).setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.__requestHeaders.item(0, 1).setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) for header in self.__model.requests[row].replyHeaders: self.__replyHeaders.insertRows(0, 1, QModelIndex()) self.__replyHeaders.setData(self.__replyHeaders.index(0, 0), header[0]) self.__replyHeaders.setData(self.__replyHeaders.index(0, 1), header[1]) self.__replyHeaders.item(0, 0).setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.__replyHeaders.item(0, 1).setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) def __showHeaderDetails(self, index): """ Private slot to show a dialog with the header details. @param index index of the entry to show (QModelIndex) """ if not index.isValid(): return headerList = self.sender() if headerList is None: return row = index.row() name = headerList.model().data(headerList.model().index(row, 0)) value = headerList.model().data(headerList.model().index(row, 1)) if self.__headersDlg is None: from .E5NetworkHeaderDetailsDialog import \ E5NetworkHeaderDetailsDialog self.__headersDlg = E5NetworkHeaderDetailsDialog(self) self.__headersDlg.setData(name, value) self.__headersDlg.show()
class MinibufferInput(QLineEdit): completion_activated = Signal(QModelIndex) FuzzyMatch = Prompt.FuzzyMatch SimpleMatch = Prompt.SimpleMatch def __init__(self, parent, window): QLineEdit.__init__(self, parent) self._completer_model = None self._popup = Popup(window, self) self.textEdited.connect(self._show_completions) self._popup.installEventFilter(self) self.installEventFilter(self) self._eat_focusout = False self._proxy_model = QSortFilterProxyModel(self) self._proxy_model.setFilterKeyColumn(-1) self._popup.setModel(self._proxy_model) self._popup.activated.connect(self._on_completion_activated) self._popup.selectionModel().currentRowChanged.connect( self._on_row_changed) self._right_italic_text = "" self._mark = False self.configure_completer({}) def configure_completer(self, opts): self._popup._max_visible_items = opts.get("max-visible-items", 10) self._match = opts.get("match", self.SimpleMatch) self._autocomplete_single = opts.get("autocomplete-single", True) self._autocomplete = opts.get("autocomplete", False) if self._autocomplete: self._autocomplete_single = False self._complete_empty = opts.get("complete-empty", False) def keymap(self): prompt = self.parent()._prompt if prompt and prompt.keymap: return prompt.keymap return KEYMAP def eventFilter(self, obj, event): etype = event.type() if etype == QEvent.FocusOut and obj == self and self._eat_focusout \ and self._popup.isVisible(): # keep the focus on the line edit return True elif etype == QEvent.MouseButtonPress: # if we've clicked in the widget (or its descendant), let it handle # the click pos = obj.mapToGlobal(event.pos()) target = QApplication.widgetAt(pos) if target and (self.isAncestorOf(target) or target == self): if not self._popup.underMouse(): self._popup.hide() target.event(event) return True if not self._popup.underMouse(): self._popup.hide() return True elif etype in (QEvent.KeyPress, QEvent.KeyRelease): # send event to the line edit self._eat_focusout = True self.event(event) self._eat_focusout = False return True return QLineEdit.eventFilter(self, obj, event) def event(self, evt): t = evt.type() if t == QEvent.KeyPress: if KEY_EATER.event_filter(self, evt): return True elif t == QEvent.Show: LOCAL_KEYMAP_SETTER.minibuffer_input_focus_changed(self, True) elif t == QEvent.Hide: LOCAL_KEYMAP_SETTER.minibuffer_input_focus_changed(self, False) return QLineEdit.event(self, evt) def set_completer_model(self, completer_model): self._proxy_model.setSourceModel(completer_model) def completer_model(self): return self._proxy_model.sourceModel() def set_match(self, type): self._match = type if self._popup.isVisible(): self._show_completions(self.text()) def _on_row_changed(self, current, old): if self._autocomplete: self.complete(hide_popup=False) def _show_completions(self, txt, force=False): force = force or self._complete_empty if self._match is not None: if self._match == self.SimpleMatch: pattern = "^" + QRegExp.escape(txt) elif self._match == self.FuzzyMatch: pattern = ".*".join(QRegExp.escape(t) for t in txt.split()) self._proxy_model.setFilterRegExp( QRegExp(pattern, Qt.CaseInsensitive)) else: self._proxy_model.setFilterRegExp(None) if self._proxy_model.rowCount() == 0: self._popup.hide() elif not txt and not force: self._popup.hide() else: self._popup.popup() def show_completions(self, filter_text=None): self._show_completions( filter_text if filter_text is not None else self.text(), True) def _on_completion_activated(self, index, hide_popup=True): if hide_popup: self._popup.hide() model = index.model() if index.column() != 0: index = model.index(index.row(), 0) self.setText(model.data(index)) self.completion_activated.emit(model.mapToSource(index)) def popup(self): return self._popup def complete(self, hide_popup=True): if not self._popup.isVisible(): return index = self._popup.selectionModel().currentIndex() if index.isValid(): self._on_completion_activated(index, hide_popup=hide_popup) elif self._autocomplete_single and self._proxy_model.rowCount() == 1: self._on_completion_activated(self._proxy_model.index(0, 0), hide_popup=hide_popup) def select_next_completion(self, forward=True): model = self._proxy_model entries = model.rowCount() if entries == 0: return selection = self._popup.selectionModel().currentIndex() if not selection.isValid(): row = 0 if forward else (entries - 1) else: row = selection.row() if forward: row = row + 1 if row >= entries: row = 0 else: row = row - 1 if row < 0: row = (entries - 1) self._popup.selectRow(row) def mark(self): return self._mark def set_mark(self, value=None): if value is None: value = not self._mark self._mark = value return self._mark def reinit(self): self.setText("") self.setEchoMode(self.Normal) self.setValidator(None) self._right_italic_text = "" def set_right_italic_text(self, text): self._right_italic_text = text self.update() def paintEvent(self, event): QLineEdit.paintEvent(self, event) if not self._right_italic_text: return painter = QPainter(self) font = painter.font() font.setItalic(True) painter.setFont(font) painter.setRenderHint(QPainter.Antialiasing, True) painter.drawText(self.rect().adjusted(0, 0, -10, 0), Qt.AlignRight, self._right_italic_text)
def __init__(self, *args, **kwargs): QSortFilterProxyModel.__init__(self, *args, **kwargs) self.filters = {} self.multi_filter_mode = MultiFilterMode.AND