def getItem(self, index: QModelIndex) -> ProtocolTreeItem: if index.isValid(): item = index.internalPointer() if item: return item return self.rootItem
def data(self, index: QModelIndex, role=Qt.DisplayRole): if not index.isValid(): return None i = index.row() j = index.column() device = self.get_device_at(i) if role == Qt.DisplayRole: if j == 0: return self.backend_handler.DEVICE_NAMES[i] elif j == 1: if device.is_enabled: if device.supports_rx and device.supports_tx: device_info = "supports RX and TX" elif device.supports_rx and not device.supports_tx: device_info = "supports RX only" elif not device.supports_rx and device.supports_tx: device_info = "supports TX only" else: device_info = "" else: device_info = "disabled" return device_info elif j == 2: return "" if device.has_native_backend else "not available" elif j == 3: return "" if device.has_gnuradio_backend else "not available" elif role == Qt.CheckStateRole: if j == 0 and (device.has_native_backend or device.has_gnuradio_backend): return Qt.Checked if device.is_enabled else Qt.Unchecked elif j == 2 and device.has_native_backend: return Qt.Checked if device.selected_backend == Backends.native else Qt.Unchecked elif j == 3 and device.has_gnuradio_backend: return Qt.Checked if device.selected_backend == Backends.grc else Qt.Unchecked
def setData(self, index: QModelIndex, value: QVariant, role: int = None): if not index.isValid(): return False item = index.internalPointer() if role == Qt.CheckStateRole: childrenCount = item.childrenCount() if childrenCount: for i in range(childrenCount): self.setData(index.child(i, 0), value, role = role) else: item.selected = bool(value) self.dataChanged.emit(index, index, [Qt.CheckStateRole]) # recalculate parents p = index while True: p = p.parent() if p.isValid(): self.dataChanged.emit(p, p, [Qt.CheckStateRole]) else: break # success return True if role == Qt.EditRole: assert index.column() == TaskTreeColumn.FileName item.setNameByUser(value) self.dataChanged.emit(index, index, [Qt.DisplayRole]) return True return False
def __newFolder(self): """ Private slot to add a new bookmarks folder. """ from .BookmarkNode import BookmarkNode currentIndex = self.bookmarksTree.currentIndex() idx = QModelIndex(currentIndex) sourceIndex = self.__proxyModel.mapToSource(idx) sourceNode = self.__bookmarksModel.node(sourceIndex) row = -1 # append new folder as the last item per default if sourceNode is not None and \ sourceNode.type() != BookmarkNode.Folder: # If the selected item is not a folder, add a new folder to the # parent folder, but directly below the selected item. idx = idx.parent() row = currentIndex.row() + 1 if not idx.isValid(): # Select bookmarks menu as default. idx = self.__proxyModel.index(1, 0) idx = self.__proxyModel.mapToSource(idx) parent = self.__bookmarksModel.node(idx) node = BookmarkNode(BookmarkNode.Folder) node.title = self.tr("New Folder") self.__bookmarksManager.addBookmark(parent, node, row)
def flags(self, index: QModelIndex): if index.isValid(): if self.is_writeable: return Qt.ItemIsEnabled | Qt.ItemIsEditable | Qt.ItemIsSelectable else: return Qt.ItemIsEnabled | Qt.ItemIsSelectable else: return Qt.NoItemFlags
def parent(self, index: QtCore.QModelIndex): if not index.isValid(): return QtCore.QModelIndex() item = index.internalPointer().parent if item == self.root or item is None: return QtCore.QModelIndex() else: return self.createIndex(item.row, 0, item)
def rowCount(self, parent: QModelIndex = None, *args, **kwargs): if not self._root: return 0 if parent.isValid(): parentItem = parent.internalPointer() return parentItem.childrenCount() else: return self._root.childrenCount()
def data(self, index: QModelIndex, role=Qt.DisplayRole): if not index.isValid(): return None i, j = index.row(), index.column() try: lbl = self.display_labels[i] except IndexError: return None if not lbl or not self.message: return None if isinstance(lbl, ChecksumLabel): calculated_crc = lbl.calculate_checksum_for_message(self.message, use_decoded_bits=True) else: calculated_crc = None if role == Qt.DisplayRole: if j == 0: return lbl.name elif j == 1: return lbl.DISPLAY_FORMATS[lbl.display_format_index] elif j == 2: start, end = self.message.get_label_range(lbl, lbl.display_format_index % 3, True) if lbl.display_format_index in (0, 1, 2): try: data = self.bit_str[self.message_index][start:end] if lbl.display_format_index == 0 \ else self.hex_str[self.message_index][start:end] if lbl.display_format_index == 1 \ else self.ascii_str[self.message_index][start:end] if lbl.display_format_index == 2 \ else "" except IndexError: return None else: # decimal try: data = str(int(self.bit_str[self.message_index][start:end], 2)) except (IndexError, ValueError): return None if calculated_crc is not None: data += " (should be {0})".format(util.convert_bits_to_string(calculated_crc, lbl.display_format_index)) return data elif role == Qt.BackgroundColorRole: if isinstance(lbl, ChecksumLabel): start, end = self.message.get_label_range(lbl, 0, True) if calculated_crc == self.message.decoded_bits[start:end]: return constants.BG_COLOR_CORRECT else: return constants.BG_COLOR_WRONG else: return None
def data(self, index: QtCore.QModelIndex, role=QtCore.Qt.DisplayRole): if index.isValid(): ip = index.internalPointer() if index.column() == 0: if role == QtCore.Qt.DisplayRole: return ("*" if ip.unfinished() else "") + ip.title() elif role == QtCore.Qt.ToolTipRole: return ip.tooltip() elif role == QtCore.Qt.DecorationRole: return ip.image()
def parent(self, index: QModelIndex = None): if not index.isValid(): return QModelIndex() childItem = index.internalPointer() parentItem = childItem.parent if parentItem == self._root: return QModelIndex() else: return self.createIndex(parentItem.siblingNumber(), 0, parentItem)
def data(self, index: QModelIndex, role=Qt.DisplayRole): i = index.row() participant = self.simulator_config.active_participants[i] if not index.isValid(): return None if role == Qt.DisplayRole: return participant.name + " (" + participant.shortname + ")" elif role == Qt.CheckStateRole: return Qt.Checked if participant.simulate else Qt.Unchecked
def flags(self, index: QtCore.QModelIndex) -> QtCore.Qt.ItemFlags: flags = super().flags(index) if not index.isValid(): return flags flags |= QtCore.Qt.ItemIsDragEnabled file_item = self.item(index) if index.column() == 0: flags |= QtCore.Qt.ItemIsEditable if file_item.is_dir: flags |= QtCore.Qt.ItemIsDropEnabled return flags
def data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> Optional[str]: """Qt override.""" if index.isValid() and role == Qt.DisplayRole: obj = self.listdata[index.row()] colname = self.header_attr[index.column()] thing = getattr(obj, colname) if callable(thing): return str(thing()) else: return str(thing) return None
def flags(self, index: QModelIndex): if index.isValid(): alignment_offset = self.get_alignment_offset_at(index.row()) if index.column() < alignment_offset: return Qt.ItemIsSelectable | Qt.ItemIsEnabled if self.is_writeable: return Qt.ItemIsEnabled | Qt.ItemIsEditable | Qt.ItemIsSelectable else: return Qt.ItemIsEnabled | Qt.ItemIsSelectable else: return Qt.NoItemFlags
def tilesChanged(self, tiles): if (tiles.first().tileset() != self.mTileset): return topLeft = QModelIndex() bottomRight = QModelIndex() for tile in tiles: i = self.tileIndex(tile) if (not topLeft.isValid()): topLeft = i bottomRight = i continue if (i.row() < topLeft.row() or i.column() < topLeft.column()): topLeft = self.index(min(topLeft.row(), i.row()), min(topLeft.column(), i.column())) if (i.row() > bottomRight.row() or i.column() > bottomRight.column()): bottomRight = self.index(max(bottomRight.row(), i.row()), max(bottomRight.column(), i.column())) if (topLeft.isValid()): self.dataChanged.emit(topLeft, bottomRight)
def data(self, index: QModelIndex, role=Qt.DisplayRole): if not index.isValid(): return None i = index.row() j = index.column() if role == Qt.DisplayRole and self.display_data: if self.label_mask[i, j]: return "." return super().data(index, role)
def data(self, index: QModelIndex, role=Qt.DisplayRole): if not index.isValid(): return None i, j = index.row(), index.column() if role == Qt.DisplayRole: data_range = self.checksum_label.data_ranges[i] if j == 0: return self.message.convert_index(data_range[0], 0, self.proto_view, True)[0] + 1 elif j == 1: return self.message.convert_index(data_range[1], 0, self.proto_view, True)[0] return None
def parent(self, index: QModelIndex = None): if not index.isValid(): return QModelIndex() child_item = self.getItem(index) try: parent_item = child_item.parent() except AttributeError: return QModelIndex() if parent_item == self.rootItem or parent_item is None: return QModelIndex() return self.createIndex(parent_item.indexInParent(), 0, parent_item)
def data(self, index: QModelIndex, role = None): if not index.isValid(): return None item = index.internalPointer() if role == Qt.DisplayRole: return item.data(index.column()) elif role == Qt.CheckStateRole and index.column() == TaskTreeColumn.FileName: return item.selected elif role == Qt.DecorationRole and index.column() == TaskTreeColumn.FileName: # TODO: use with real icons from PyQt5.QtGui import QIcon return QIcon.fromTheme("xware-desktop") return None
def data(self, index: QModelIndex, role=Qt.DisplayRole): if not index.isValid(): return None if role == Qt.DisplayRole or role == Qt.EditRole: i = index.row() j = index.column() fieldtype = self.field_types[i] if j == 0: return fieldtype.caption elif j == 1: return fieldtype.function.name elif j == 2: return ProtocolLabel.DISPLAY_FORMATS[fieldtype.display_format_index]
def selection_changed(self, curr_index: QModelIndex, prev_index: QModelIndex): """ Updates the information about currently selected account. """ if not curr_index.isValid(): return None # Make sure selection is visible in the view self.selection.setCurrentIndex( curr_index, QItemSelectionModel.SelectCurrent) acc = curr_index.data(role=Qt.UserRole) # Set the type of account self.typeBox.setCurrentText(acc.type) # Set the checkboxes self.closedBox.setChecked(acc.closed) self.exBudgetBox.setChecked(acc.exbudget)
def data(self, index: QModelIndex, role=Qt.DisplayRole): if not index.isValid(): return None i = index.row() j = index.column() if role == Qt.DisplayRole and self.display_data: try: alignment_offset = self.get_alignment_offset_at(i) if j < alignment_offset: return self.ALIGNMENT_CHAR if self.proto_view == 0: return self.display_data[i][j - alignment_offset] elif self.proto_view == 1: return "{0:x}".format(self.display_data[i][j - alignment_offset]) elif self.proto_view == 2: return chr(self.display_data[i][j - alignment_offset]) except IndexError: return None elif role == Qt.TextAlignmentRole: if i in self.first_messages: return Qt.AlignHCenter + Qt.AlignBottom else: return Qt.AlignCenter elif role == Qt.BackgroundColorRole: return self.background_colors[i, j] elif role == Qt.FontRole: font = QFont() font.setBold(self.bold_fonts[i, j]) font.setItalic(self.italic_fonts[i, j]) return font elif role == Qt.TextColorRole: return self.text_colors[i, j] elif role == Qt.ToolTipRole: return self.get_tooltip(i, j) else: return None
def data(self, index: QModelIndex, role=Qt.DisplayRole): if not index.isValid(): return None if role == Qt.DisplayRole: i = index.row() j = index.column() rule = self.ruleset[i] assert isinstance(rule, Rule) if j == 0: return rule.start + 1 elif j == 1: return rule.end elif j == 2: return rule.value_type elif j == 3: return rule.operator_description elif j == 4: return rule.target_value
def data(self, index: QtCore.QModelIndex, role: int=QtCore.Qt.DisplayRole) -> QtCore.QVariant: if not index.isValid(): return QtCore.QVariant() if index.column() < 0 or index.column() >= self.columnCount: return QtCore.QVariant() if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole: return self.item(index).data[index.column()] if index.column() == 0: for case in switch(role): if case(QtWidgets.QDirModel.FileIconRole): return self.file_icon if not self.item(index).is_dir else \ self.folder_icon if case(): return QtCore.QVariant() return QtCore.QVariant()
def dropMimeData(self, mime_data: QtCore.QMimeData, drop_actions: QtCore.Qt.DropActions, row: int, column: int, index: QtCore.QModelIndex): if not index.isValid() or not drop_actions & QtCore.Qt.CopyAction: return False urls = mime_data.urls() root = mime_data.property('root') print(root) for url in urls: source_path = os.path.dirname(url.path()) filename = os.path.basename(url.path()) print(source_path) print(filename) target_path = self.filePath(index) print(target_path) if root != '': target_path += source_path[source_path.index(root):] print(target_path) self.file_downloading.emit(source_path, target_path, filename) return True
def paint(self, painter, option, index): ##option.rect.setWidth(option.rect.width() - 18) # QStyledItemDelegate.paint(self, painter, option, index) ##option.rect.setWidth(option.rect.width() + 18) itemIndex = QModelIndex() character = self.mdlCharacter.getCharacterByID(index.data()) if character: itemIndex = character.index(Character.name.value) opt = QStyleOptionViewItem(option) self.initStyleOption(opt, itemIndex) qApp.style().drawControl(QStyle.CE_ItemViewItem, opt, painter) # if index.isValid() and index.internalPointer().data(Outline.POV.value) not in ["", None]: if itemIndex.isValid() and self.mdlCharacter.data(itemIndex) not in ["", None]: opt = QStyleOptionComboBox() opt.rect = option.rect r = qApp.style().subControlRect(QStyle.CC_ComboBox, opt, QStyle.SC_ComboBoxArrow) option.rect = r qApp.style().drawPrimitive(QStyle.PE_IndicatorArrowDown, option, painter)
def setData(self, index: QModelIndex, value, role=None): if not index.isValid(): return False i, j = index.row(), index.column() device = self.get_device_at(i) if role == Qt.CheckStateRole: enabled = bool(value) if j == 0: device.is_enabled = enabled if j == 2: if enabled and device.has_native_backend: device.selected_backend = Backends.native elif not enabled and device.has_gnuradio_backend: device.selected_backend = Backends.grc elif j == 3: if enabled and device.has_gnuradio_backend: device.selected_backend = Backends.grc elif not enabled and device.has_native_backend: device.selected_backend = Backends.native self.update() device.write_settings() return True
def flags(self, index: QModelIndex): if not index.isValid(): return None j = index.column() device = self.get_device_at(index.row()) if j == 0 and not device.has_native_backend and not device.has_gnuradio_backend: return Qt.NoItemFlags if j in [1, 2, 3] and not device.is_enabled: return Qt.NoItemFlags if j == 2 and not device.has_native_backend: return Qt.NoItemFlags if j == 3 and not device.has_gnuradio_backend: return Qt.NoItemFlags flags = Qt.ItemIsEnabled if j in [0, 2, 3]: flags |= Qt.ItemIsUserCheckable return flags
def setData(self, index: QModelIndex, data_value, role=Qt.EditRole): if index.isValid() and role == Qt.EditRole: self.column_objects[index.column()].set_data( index, data_value, role) self.dataEdited.emit()
def set_data(self, index: QModelIndex, data, role=Qt.EditRole): if index.isValid() and role == Qt.EditRole: self.data_type.set_data(index.row(), data)
def data(self, index: QModelIndex, role: Qt.ItemDataRole) -> QVariant: # note: this method is performance-critical. # it is called a lot, and so must run extremely fast. assert index.isValid() col = index.column() tx_item = self.transactions.value_from_pos(index.row()) tx_hash = tx_item['txid'] conf = tx_item['confirmations'] txpos = tx_item['txpos_in_block'] or 0 height = tx_item['height'] token = self.parent.wallet.db.get_token(tx_item['token_key']) bind_addr = tx_item['bind_addr'] from_addr = tx_item['from_addr'] to_addr = tx_item['to_addr'] timestamp = tx_item['timestamp'] if timestamp is None: timestamp = float("inf") try: status, status_str = self.tx_status_cache[tx_hash] except KeyError: tx_mined_info = self.tx_mined_info_from_tx_item(tx_item) status, status_str = self.parent.wallet.get_tx_status(tx_hash, tx_mined_info) balance_str = f"{tx_item['amount']}" if to_addr == bind_addr else f"- {tx_item['amount']}" if role == Qt.UserRole: # for sorting d = { TokenHistoryColumns.STATUS: (-timestamp, conf, -status, -height, -txpos), TokenHistoryColumns.BIND_ADDRESS: bind_addr, TokenHistoryColumns.TOKEN: token.symbol, TokenHistoryColumns.AMOUNT: balance_str, } return QVariant(d[col]) if role not in (Qt.DisplayRole, Qt.EditRole): if col == TokenHistoryColumns.STATUS and role == Qt.DecorationRole: return QVariant(read_QIcon(TX_ICONS[status])) elif col == TokenHistoryColumns.STATUS and role == Qt.ToolTipRole: return QVariant(str(conf) + _(" confirmation" + ("s" if conf != 1 else ""))) elif col > TokenHistoryColumns.BIND_ADDRESS and role == Qt.TextAlignmentRole: return QVariant(Qt.AlignRight | Qt.AlignVCenter) elif col != TokenHistoryColumns.STATUS and role == Qt.FontRole: return QVariant(QFont(MONOSPACE_FONT)) elif col in (TokenHistoryColumns.TOKEN, TokenHistoryColumns.AMOUNT) \ and role == Qt.ForegroundRole and from_addr == bind_addr: red_brush = QBrush(QColor("#BC1E1E")) return QVariant(red_brush) return QVariant() if col == TokenHistoryColumns.STATUS: return QVariant(status_str) elif col == TokenHistoryColumns.BIND_ADDRESS: return QVariant(bind_addr) elif col == TokenHistoryColumns.TOKEN: return QVariant(token.symbol) elif col == TokenHistoryColumns.AMOUNT: amount = tx_item['amount'] if from_addr == bind_addr: amount = -amount v_str = self.parent.format_amount(amount, is_diff=True, whitespaces=True, num_zeros=0, decimal_point=token.decimals) return QVariant(v_str) return QVariant()
def data(self, index: QModelIndex, role: Qt.ItemDataRole) -> QVariant: # note: this method is performance-critical. # it is called a lot, and so must run extremely fast. assert index.isValid() col = index.column() tx_item = self.transactions.value_from_pos(index.row()) is_lightning = tx_item.get('lightning', False) timestamp = tx_item['timestamp'] if is_lightning: status = 0 txpos = tx_item['txpos'] if timestamp is None: status_str = 'unconfirmed' else: status_str = format_time(int(timestamp)) else: tx_hash = tx_item['txid'] conf = tx_item['confirmations'] txpos = tx_item['txpos_in_block'] or 0 height = tx_item['height'] try: status, status_str = self.tx_status_cache[tx_hash] except KeyError: tx_mined_info = self.tx_mined_info_from_tx_item(tx_item) status, status_str = self.parent.wallet.get_tx_status(tx_hash, tx_mined_info) # we sort by timestamp if timestamp is None: timestamp = float("inf") if role == Qt.UserRole: # for sorting d = { HistoryColumns.STATUS: # height breaks ties for unverified txns # txpos breaks ties for verified same block txns (-timestamp, conf, -status, -height, -txpos) if not is_lightning else (-timestamp, 0,0,0,-txpos), HistoryColumns.DESCRIPTION: tx_item['label'] if 'label' in tx_item else None, HistoryColumns.AMOUNT: (tx_item['bc_value'].value if 'bc_value' in tx_item else 0)\ + (tx_item['ln_value'].value if 'ln_value' in tx_item else 0), HistoryColumns.BALANCE: (tx_item['balance'].value if 'balance' in tx_item else 0)\ + (tx_item['balance_msat']//1000 if 'balance_msat'in tx_item else 0), HistoryColumns.FIAT_VALUE: tx_item['fiat_value'].value if 'fiat_value' in tx_item else None, HistoryColumns.FIAT_ACQ_PRICE: tx_item['acquisition_price'].value if 'acquisition_price' in tx_item else None, HistoryColumns.FIAT_CAP_GAINS: tx_item['capital_gain'].value if 'capital_gain' in tx_item else None, HistoryColumns.TXID: tx_hash if not is_lightning else None, } return QVariant(d[col]) if role not in (Qt.DisplayRole, Qt.EditRole): if col == HistoryColumns.STATUS and role == Qt.DecorationRole: icon = "lightning" if is_lightning else TX_ICONS[status] return QVariant(read_QIcon(icon)) elif col == HistoryColumns.STATUS and role == Qt.ToolTipRole: msg = 'lightning transaction' if is_lightning else str(conf) + _(" confirmation" + ("s" if conf != 1 else "")) return QVariant(msg) elif col > HistoryColumns.DESCRIPTION and role == Qt.TextAlignmentRole: return QVariant(Qt.AlignRight | Qt.AlignVCenter) elif col != HistoryColumns.STATUS and role == Qt.FontRole: monospace_font = QFont(MONOSPACE_FONT) return QVariant(monospace_font) #elif col == HistoryColumns.DESCRIPTION and role == Qt.DecorationRole and not is_lightning\ # and self.parent.wallet.invoices.paid.get(tx_hash): # return QVariant(read_QIcon("seal")) elif col in (HistoryColumns.DESCRIPTION, HistoryColumns.AMOUNT) \ and role == Qt.ForegroundRole and not is_lightning and tx_item['value'].value < 0: red_brush = QBrush(QColor("#BC1E1E")) return QVariant(red_brush) elif col == HistoryColumns.FIAT_VALUE and role == Qt.ForegroundRole \ and not tx_item.get('fiat_default') and tx_item.get('fiat_value') is not None: blue_brush = QBrush(QColor("#1E1EFF")) return QVariant(blue_brush) return QVariant() if col == HistoryColumns.STATUS: return QVariant(status_str) elif col == HistoryColumns.DESCRIPTION and 'label' in tx_item: return QVariant(tx_item['label']) elif col == HistoryColumns.AMOUNT: bc_value = tx_item['bc_value'].value if 'bc_value' in tx_item else 0 ln_value = tx_item['ln_value'].value if 'ln_value' in tx_item else 0 value = bc_value + ln_value v_str = self.parent.format_amount(value, is_diff=True, whitespaces=True) return QVariant(v_str) elif col == HistoryColumns.BALANCE: balance = tx_item['balance'].value balance_str = self.parent.format_amount(balance, whitespaces=True) return QVariant(balance_str) elif col == HistoryColumns.FIAT_VALUE and 'fiat_value' in tx_item: value_str = self.parent.fx.format_fiat(tx_item['fiat_value'].value) return QVariant(value_str) elif col == HistoryColumns.FIAT_ACQ_PRICE and \ tx_item['value'].value < 0 and 'acquisition_price' in tx_item: # fixme: should use is_mine acq = tx_item['acquisition_price'].value return QVariant(self.parent.fx.format_fiat(acq)) elif col == HistoryColumns.FIAT_CAP_GAINS and 'capital_gain' in tx_item: cg = tx_item['capital_gain'].value return QVariant(self.parent.fx.format_fiat(cg)) elif col == HistoryColumns.TXID: return QVariant(tx_hash) return QVariant()
def data(self, index: QModelIndex, role=Qt.DisplayRole): if not index.isValid(): return None i, j = index.row(), index.column() try: lbl = self.display_labels[i] except IndexError: return None if isinstance(lbl, ChecksumLabel) and self.message is not None: calculated_crc = lbl.calculate_checksum_for_message( self.message, use_decoded_bits=True) else: calculated_crc = None if role == Qt.DisplayRole: if j == 0: return lbl.name elif j == 1: return lbl.color_index elif j == 2: return lbl.DISPLAY_FORMATS[lbl.display_format_index] elif j == 3: return lbl.display_order_str elif j == 4: return self.__display_data(lbl, calculated_crc) elif role == Qt.CheckStateRole and j == 0: return lbl.show elif role == Qt.BackgroundColorRole: if isinstance( lbl, ChecksumLabel) and j == 4 and self.message is not None: start, end = self.message.get_label_range(lbl, 0, True) if calculated_crc == self.message.decoded_bits[start:end]: return settings.BG_COLOR_CORRECT else: return settings.BG_COLOR_WRONG else: return None elif role == Qt.ToolTipRole: if j == 2: return self.tr( "Choose display type for the value of the label:" "<ul>" "<li>Bit</li>" "<li>Hexadecimal (Hex)</li>" "<li>ASCII chars</li>" "<li>Decimal Number</li>" "<li>Binary Coded Decimal (BCD)</li>" "</ul>") if j == 3: return self.tr("Choose bit order for the displayed value:" "<ul>" "<li>Most Significant Bit (MSB) [Default]</li>" "<li>Least Significant Bit (LSB)</li>" "<li>Least Significant Digit (LSD)</li>" "</ul>") elif role == Qt.FontRole and j == 0: font = QFont() font.setBold(i in self.selected_label_indices) return font
def columnCount(self, parent: QModelIndex = ...) -> int: if parent.isValid(): return parent.internalPointer().column_count else: return self.root_item.column_count
def rowCount(self, parent:QModelIndex=None, *args, **kwargs): if parent.isValid(): # internal nodes child: CustomNode=parent.internalPointer() return len(child.children) return len(self._root.children) # first level nodes
def flags(self, index: QModelIndex): if not index.isValid(): return 0 item = index.internalPointer() return item.flags(index.column())
def hasChildren(self, index: QModelIndex): return not index.isValid()
def data(self, index: QModelIndex, role: Qt.ItemDataRole) -> QVariant: # note: this method is performance-critical. # it is called a lot, and so must run extremely fast. assert index.isValid() col = index.column() tx_item = self.transactions.value_from_pos(index.row()) tx_hash = tx_item['txid'] conf = tx_item['confirmations'] txpos = tx_item['txpos_in_block'] or 0 height = tx_item['height'] try: status, status_str = self.tx_status_cache[tx_hash] except KeyError: tx_mined_info = self.tx_mined_info_from_tx_item(tx_item) status, status_str = self.parent.wallet.get_tx_status( tx_hash, tx_mined_info) if role == Qt.UserRole: # for sorting d = { HistoryColumns.STATUS_ICON: # height breaks ties for unverified txns # txpos breaks ties for verified same block txns (status, conf, -height, -txpos), HistoryColumns.STATUS_TEXT: status_str, HistoryColumns.DESCRIPTION: tx_item['label'], HistoryColumns.COIN_VALUE: tx_item['value'].value, HistoryColumns.RUNNING_COIN_BALANCE: tx_item['balance'].value, HistoryColumns.FIAT_VALUE: tx_item['fiat_value'].value if 'fiat_value' in tx_item else None, HistoryColumns.FIAT_ACQ_PRICE: tx_item['acquisition_price'].value if 'acquisition_price' in tx_item else None, HistoryColumns.FIAT_CAP_GAINS: tx_item['capital_gain'].value if 'capital_gain' in tx_item else None, HistoryColumns.TXID: tx_hash, } return QVariant(d[col]) if role not in (Qt.DisplayRole, Qt.EditRole): if col == HistoryColumns.STATUS_ICON and role == Qt.DecorationRole: return QVariant(read_QIcon(TX_ICONS[status])) elif col == HistoryColumns.STATUS_ICON and role == Qt.ToolTipRole: return QVariant( str(conf) + _(" confirmation" + ("s" if conf != 1 else ""))) elif col > HistoryColumns.DESCRIPTION and role == Qt.TextAlignmentRole: return QVariant(Qt.AlignRight | Qt.AlignVCenter) elif col != HistoryColumns.STATUS_TEXT and role == Qt.FontRole: monospace_font = QFont(MONOSPACE_FONT) return QVariant(monospace_font) elif col == HistoryColumns.DESCRIPTION and role == Qt.DecorationRole \ and self.parent.wallet.invoices.paid.get(tx_hash): return QVariant(read_QIcon("seal")) elif col in (HistoryColumns.DESCRIPTION, HistoryColumns.COIN_VALUE) \ and role == Qt.ForegroundRole and tx_item['value'].value < 0: red_brush = QBrush(QColor("#BC1E1E")) return QVariant(red_brush) elif col == HistoryColumns.FIAT_VALUE and role == Qt.ForegroundRole \ and not tx_item.get('fiat_default') and tx_item.get('fiat_value') is not None: blue_brush = QBrush(QColor("#1E1EFF")) return QVariant(blue_brush) return QVariant() if col == HistoryColumns.STATUS_TEXT: return QVariant(status_str) elif col == HistoryColumns.DESCRIPTION: return QVariant(tx_item['label']) elif col == HistoryColumns.COIN_VALUE: value = tx_item['value'].value v_str = self.parent.format_amount(value, is_diff=True, whitespaces=True) return QVariant(v_str) elif col == HistoryColumns.RUNNING_COIN_BALANCE: balance = tx_item['balance'].value balance_str = self.parent.format_amount(balance, whitespaces=True) return QVariant(balance_str) elif col == HistoryColumns.FIAT_VALUE and 'fiat_value' in tx_item: value_str = self.parent.fx.format_fiat(tx_item['fiat_value'].value) return QVariant(value_str) elif col == HistoryColumns.FIAT_ACQ_PRICE and \ tx_item['value'].value < 0 and 'acquisition_price' in tx_item: # fixme: should use is_mine acq = tx_item['acquisition_price'].value return QVariant(self.parent.fx.format_fiat(acq)) elif col == HistoryColumns.FIAT_CAP_GAINS and 'capital_gain' in tx_item: cg = tx_item['capital_gain'].value return QVariant(self.parent.fx.format_fiat(cg)) elif col == HistoryColumns.TXID: return QVariant(tx_hash) return QVariant()
def get_data_for_role(self, index: QModelIndex, role: Qt.ItemDataRole) -> QVariant: # note: this method is performance-critical. # it is called a lot, and so must run extremely fast. assert index.isValid() col = index.column() window = self.model.parent tx_item = self.get_data() is_lightning = tx_item.get('lightning', False) timestamp = tx_item['timestamp'] if is_lightning: status = 0 if timestamp is None: status_str = 'unconfirmed' else: status_str = format_time(int(timestamp)) else: tx_hash = tx_item['txid'] conf = tx_item['confirmations'] try: status, status_str = self.model.tx_status_cache[tx_hash] except KeyError: tx_mined_info = self.model.tx_mined_info_from_tx_item(tx_item) status, status_str = window.wallet.get_tx_status( tx_hash, tx_mined_info) if role == Qt.UserRole: # for sorting d = { HistoryColumns.STATUS: # respect sort order of self.transactions (wallet.get_full_history) -index.row(), HistoryColumns.DESCRIPTION: tx_item['label'] if 'label' in tx_item else None, HistoryColumns.AMOUNT: (tx_item['bc_value'].value if 'bc_value' in tx_item else 0)\ + (tx_item['ln_value'].value if 'ln_value' in tx_item else 0), HistoryColumns.BALANCE: (tx_item['balance'].value if 'balance' in tx_item else 0), HistoryColumns.FIAT_VALUE: tx_item['fiat_value'].value if 'fiat_value' in tx_item else None, HistoryColumns.FIAT_ACQ_PRICE: tx_item['acquisition_price'].value if 'acquisition_price' in tx_item else None, HistoryColumns.FIAT_CAP_GAINS: tx_item['capital_gain'].value if 'capital_gain' in tx_item else None, HistoryColumns.TXID: tx_hash if not is_lightning else None, } return QVariant(d[col]) if role not in (Qt.DisplayRole, Qt.EditRole): if col == HistoryColumns.STATUS and role == Qt.DecorationRole: icon = "lightning" if is_lightning else TX_ICONS[status] return QVariant(read_QIcon(icon)) elif col == HistoryColumns.STATUS and role == Qt.ToolTipRole: if is_lightning: msg = 'lightning transaction' else: # on-chain if tx_item['height'] == TX_HEIGHT_LOCAL: # note: should we also explain double-spends? msg = _( "This transaction is only available on your local machine.\n" "The currently connected server does not know about it.\n" "You can either broadcast it now, or simply remove it." ) else: msg = str(conf) + _(" confirmation" + ("s" if conf != 1 else "")) return QVariant(msg) elif col > HistoryColumns.DESCRIPTION and role == Qt.TextAlignmentRole: return QVariant(int(Qt.AlignRight | Qt.AlignVCenter)) elif col > HistoryColumns.DESCRIPTION and role == Qt.FontRole: monospace_font = QFont(MONOSPACE_FONT) return QVariant(monospace_font) #elif col == HistoryColumns.DESCRIPTION and role == Qt.DecorationRole and not is_lightning\ # and self.parent.wallet.invoices.paid.get(tx_hash): # return QVariant(read_QIcon("seal")) elif col in (HistoryColumns.DESCRIPTION, HistoryColumns.AMOUNT) \ and role == Qt.ForegroundRole and tx_item['value'].value < 0: red_brush = QBrush(QColor("#BC1E1E")) return QVariant(red_brush) elif col == HistoryColumns.FIAT_VALUE and role == Qt.ForegroundRole \ and not tx_item.get('fiat_default') and tx_item.get('fiat_value') is not None: blue_brush = QBrush(QColor("#1E1EFF")) return QVariant(blue_brush) return QVariant() if col == HistoryColumns.STATUS: return QVariant(status_str) elif col == HistoryColumns.DESCRIPTION and 'label' in tx_item: return QVariant(tx_item['label']) elif col == HistoryColumns.AMOUNT: bc_value = tx_item['bc_value'].value if 'bc_value' in tx_item else 0 ln_value = tx_item['ln_value'].value if 'ln_value' in tx_item else 0 value = bc_value + ln_value v_str = window.format_amount(value, is_diff=True, whitespaces=True) return QVariant(v_str) elif col == HistoryColumns.BALANCE: balance = tx_item['balance'].value balance_str = window.format_amount(balance, whitespaces=True) return QVariant(balance_str) elif col == HistoryColumns.FIAT_VALUE and 'fiat_value' in tx_item: value_str = window.fx.format_fiat(tx_item['fiat_value'].value) return QVariant(value_str) elif col == HistoryColumns.FIAT_ACQ_PRICE and \ tx_item['value'].value < 0 and 'acquisition_price' in tx_item: # fixme: should use is_mine acq = tx_item['acquisition_price'].value return QVariant(window.fx.format_fiat(acq)) elif col == HistoryColumns.FIAT_CAP_GAINS and 'capital_gain' in tx_item: cg = tx_item['capital_gain'].value return QVariant(window.fx.format_fiat(cg)) elif col == HistoryColumns.TXID: return QVariant(tx_hash) if not is_lightning else QVariant('') return QVariant()
class editorWidget(QWidget, Ui_editorWidget_ui): """ `editorWidget` is a class responsible for displaying and editing one `outlineItem`. This item can be a folder or a text. It has four views (see `self.setView`) - For folders: "text", "outline" or "cork" (set in `self.folderView`) Text: displays a list of `textEditView` in a scroll area Outline: displays an outline, using an `outlineView` Cork: displays flash cards, using a `corkView` - For text: item is simply displayed in a `textEditView` All those views are contained in `editorWidget` single widget: `self.stack`. `editorWidget` are managed in `tabSplitted` (that allow to open several `outlineItem`s, either in Tabs or in split views. `tabSplitted` are in turn managed by the `mainEditor`, which is unique and gives UI buttons to manage all those views. """ toggledSpellcheck = pyqtSignal(bool) dictChanged = pyqtSignal(str) _maxTabTitleLength = 24 def __init__(self, parent): QWidget.__init__(self, parent) self.setupUi(self) self.currentIndex = QModelIndex() self.currentID = None self.txtEdits = [] self.scroll.setBackgroundRole(QPalette.Base) self.toggledSpellcheck.connect(self.txtRedacText.toggleSpellcheck, AUC) self.dictChanged.connect(self.txtRedacText.setDict, AUC) self.txtRedacText.setHighlighting(True) self.currentDict = "" self.spellcheck = True self.folderView = "cork" self.mw = mainWindow() self._tabWidget = None # set by mainEditor on creation self._model = None # Capture textEdit scrollbar, so that we can put it outside the margins. self.txtEditScrollBar = self.txtRedacText.verticalScrollBar() self.txtEditScrollBar.setParent(self) self.stack.currentChanged.connect(self.setScrollBarVisibility) # def setModel(self, model): # self._model = model # self.setView() def resizeEvent(self, event): """ textEdit's scrollBar has been reparented to self. So we need to update it's geomtry when self is resized, and put it where we want it to be. """ # Update scrollbar geometry r = self.geometry() w = 10 # Cf. style.mainEditorTabSS r.setWidth(w) r.moveRight(self.geometry().width()) self.txtEditScrollBar.setGeometry(r) QWidget.resizeEvent(self, event) def setScrollBarVisibility(self): """ Since the texteEdit scrollBar has been reparented to self, it is not hidden when stack changes. We have to do it manually. """ self.txtEditScrollBar.setVisible(self.stack.currentIndex() == 0) def setFolderView(self, v): oldV = self.folderView if v == "cork": self.folderView = "cork" elif v == "outline": self.folderView = "outline" else: self.folderView = "text" # Saving value settings.folderView = self.folderView if oldV != self.folderView and self.currentIndex: self.setCurrentModelIndex(self.currentIndex) def setCorkSizeFactor(self, v): self.corkView.itemDelegate().setCorkSizeFactor(v) self.redrawCorkItems() def redrawCorkItems(self): r = self.corkView.rootIndex() if r.isValid(): count = r.internalPointer().childCount() elif self._model: count = self._model.rootItem.childCount() else: count = 0 for c in range(count): self.corkView.itemDelegate().sizeHintChanged.emit(r.child(c, 0)) def updateTabTitle(self): """ `editorWidget` belongs to a `QTabWidget` in a `tabSplitter`. We update the tab title to reflect that of current item. """ # `self._tabWidget` is set by mainEditor when creating tab and `editorWidget`. # if `editorWidget` is ever used out of `mainEditor`, this could throw # an error. if not self._tabWidget: return if self.currentIndex.isValid(): item = self.currentIndex.internalPointer() elif self._model: item = self._model.rootItem else: return i = self._tabWidget.indexOf(self) self._tabWidget.setTabText(i, self.ellidedTitle(item.title())) self._tabWidget.setTabToolTip(i, item.title()) def ellidedTitle(self, title): if len(title) > self._maxTabTitleLength: return "{}…".format(title[:self._maxTabTitleLength]) else: return title def setView(self): # index = mainWindow().treeRedacOutline.currentIndex() # Counting the number of other selected items # sel = [] # for i in mainWindow().treeRedacOutline.selectionModel().selection().indexes(): # if i.column() != 0: continue # if i not in sel: sel.append(i) # if len(sel) != 0: # item = index.internalPointer() # else: # index = QModelIndex() # item = self.mw.mdlOutline.rootItem # self.currentIndex = index if self.currentIndex.isValid(): item = self.currentIndex.internalPointer() else: item = self.mw.mdlOutline.rootItem self.updateTabTitle() def addTitle(itm): edt = MDEditView(self, html="<h{l}>{t}</h{l}>".format(l=min( itm.level() + 1, 5), t=itm.title()), autoResize=True) edt.setFrameShape(QFrame.NoFrame) self.txtEdits.append(edt) l.addWidget(edt) def addLine(): line = QFrame(self.text) line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) l.addWidget(line) def addText(itm): edt = MDEditView(self, index=itm.index(), spellcheck=self.spellcheck, dict=settings.dict, highlighting=True, autoResize=True) edt.setFrameShape(QFrame.NoFrame) edt.setStatusTip("{}".format(itm.path())) self.toggledSpellcheck.connect(edt.toggleSpellcheck, AUC) self.dictChanged.connect(edt.setDict, AUC) # edt.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) self.txtEdits.append(edt) l.addWidget(edt) def addChildren(itm): for c in range(itm.childCount()): child = itm.child(c) if child.isFolder(): addTitle(child) addChildren(child) else: addText(child) addLine() def addSpacer(): l.addItem( QSpacerItem(10, 1000, QSizePolicy.Minimum, QSizePolicy.Expanding)) # Display multiple selected items # if len(sel) > 1 and False: # Buggy and not very useful, skip # self.stack.setCurrentIndex(1) # w = QWidget() # l = QVBoxLayout(w) # self.txtEdits = [] # for idx in sel: # sItem = idx.internalPointer() # addTitle(sItem) # if sItem.isFolder(): # addChildren(sItem) # else: # addText(sItem) # addLine() # addSpacer() # self.scroll.setWidget(w) if item and item.isFolder() and self.folderView == "text": self.stack.setCurrentIndex(1) w = QWidget() w.setObjectName("editorWidgetFolderText") l = QVBoxLayout(w) opt = settings.textEditor background = (opt["background"] if not opt["backgroundTransparent"] else "transparent") w.setStyleSheet("background: {};".format(background)) self.stack.widget(1).setStyleSheet( "background: {}".format(background)) # self.scroll.setWidgetResizable(False) self.txtEdits = [] if item != self._model.rootItem: addTitle(item) addChildren(item) addSpacer() self.scroll.setWidget(w) elif item and item.isFolder() and self.folderView == "cork": self.stack.setCurrentIndex(2) self.corkView.setModel(self._model) self.corkView.setRootIndex(self.currentIndex) try: self.corkView.selectionModel().selectionChanged.connect( mainWindow().redacMetadata.selectionChanged, AUC) self.corkView.clicked.connect( mainWindow().redacMetadata.selectionChanged, AUC) self.corkView.clicked.connect( mainWindow().mainEditor.updateTargets, AUC) except TypeError: pass elif item and item.isFolder() and self.folderView == "outline": self.stack.setCurrentIndex(3) self.outlineView.setModelCharacters(mainWindow().mdlCharacter) self.outlineView.setModelLabels(mainWindow().mdlLabels) self.outlineView.setModelStatus(mainWindow().mdlStatus) self.outlineView.setModel(self._model) self.outlineView.setRootIndex(self.currentIndex) try: self.outlineView.selectionModel().selectionChanged.connect( mainWindow().redacMetadata.selectionChanged, AUC) self.outlineView.clicked.connect( mainWindow().redacMetadata.selectionChanged, AUC) self.outlineView.clicked.connect( mainWindow().mainEditor.updateTargets, AUC) except TypeError: pass if item and item.isText(): self.txtRedacText.setCurrentModelIndex(self.currentIndex) self.stack.setCurrentIndex(0) # Single text item else: self.txtRedacText.setCurrentModelIndex(QModelIndex()) try: self._model.dataChanged.connect(self.modelDataChanged, AUC) self._model.rowsInserted.connect(self.updateIndexFromID, AUC) self._model.rowsRemoved.connect(self.updateIndexFromID, AUC) #self.mw.mdlOutline.rowsAboutToBeRemoved.connect(self.rowsAboutToBeRemoved, AUC) except TypeError: pass self.updateStatusBar() def setCurrentModelIndex(self, index=None): if index.isValid(): self.currentIndex = index self._model = index.model() self.currentID = self._model.ID(index) else: self.currentIndex = QModelIndex() self.currentID = None if self._model: self.setView() def updateIndexFromID(self): """ Index might have changed (through drag an drop), so we keep current item's ID and update index. Item might have been deleted too. """ idx = self._model.getIndexByID(self.currentID) # If we have an ID but the ID does not exist, it has been deleted if self.currentID and idx == QModelIndex(): # Item has been deleted, we open the parent instead self.setCurrentModelIndex(self.currentIndex.parent()) # FIXME: selection in self.mw.treeRedacOutline is not updated # but we cannot simply setCurrentIndex through treeRedacOutline # because this might be a tab in the background / out of focus # Also the UI of mainEditor is not updated (so the folder icons # are not display, button "up" doesn't work, etc.). # Item has been moved elif idx != self.currentIndex: # We update the index self.currentIndex = idx self.setView() def modelDataChanged(self, topLeft, bottomRight): # if self.currentID: # self.updateIndexFromID() if not self.currentIndex: return if topLeft.row() <= self.currentIndex.row() <= bottomRight.row(): self.updateStatusBar() #def rowsAboutToBeRemoved(self, parent, first, last): #if self.currentIndex: #if self.currentIndex.parent() == parent and \ #first <= self.currentIndex.row() <= last: ## Item deleted, close tab #self.mw.mainEditor.tab.removeTab(self.mw.mainEditor.tab.indexOf(self)) def updateStatusBar(self): # Update progress # if self.currentIndex and self.currentIndex.isValid(): # if self._model: mw = mainWindow() if not mw: return mw.mainEditor.updateStats() def toggleSpellcheck(self, v): self.spellcheck = v self.toggledSpellcheck.emit(v) def setDict(self, dct): self.currentDict = dct self.dictChanged.emit(dct) ############################################################################### # FUNCTIONS FOR MENU ACCESS ############################################################################### def getCurrentItemView(self): """ Returns the current item view, between txtRedacText, outlineView and corkView. If folder/text view, returns None. (Because handled differently) """ if self.stack.currentIndex() == 0: return self.txtRedacText elif self.folderView == "outline": return self.outlineView elif self.folderView == "cork": return self.corkView else: return None def copy(self): if self.getCurrentItemView(): self.getCurrentItemView().copy() def cut(self): if self.getCurrentItemView(): self.getCurrentItemView().cut() def paste(self): if self.getCurrentItemView(): self.getCurrentItemView().paste() def rename(self): if self.getCurrentItemView(): self.getCurrentItemView().rename() def duplicate(self): if self.getCurrentItemView(): self.getCurrentItemView().duplicate() def delete(self): if self.getCurrentItemView(): self.getCurrentItemView().delete() def moveUp(self): if self.getCurrentItemView(): self.getCurrentItemView().moveUp() def moveDown(self): if self.getCurrentItemView(): self.getCurrentItemView().moveDown() def splitDialog(self): """ Opens a dialog to split selected items. """ if self.getCurrentItemView() == self.txtRedacText: # Text editor if not self.currentIndex.isValid(): return sel = self.txtRedacText.textCursor().selectedText() # selectedText uses \u2029 instead of \n, no idea why. sel = sel.replace("\u2029", "\n") splitDialog(self, [self.currentIndex], mark=sel) elif self.getCurrentItemView(): # One of the views self.getCurrentItemView().splitDialog() def splitCursor(self): """ Splits items at cursor position. If there is a selection, that selection becomes the new item's title. Call context: Only works when editing a file. """ if not self.currentIndex.isValid(): return if self.getCurrentItemView() == self.txtRedacText: c = self.txtRedacText.textCursor() title = c.selectedText() # selection can be backward pos = min(c.selectionStart(), c.selectionEnd()) item = self.currentIndex.internalPointer() item.splitAt(pos, len(title)) def merge(self): """ Merges selected items together. Call context: Multiple selection, same parent. """ if self.getCurrentItemView() == self.txtRedacText: # Text editor, nothing to merge pass elif self.getCurrentItemView(): # One of the views self.getCurrentItemView().merge()
def rowCount(self, parent: QModelIndex = QModelIndex()) -> int: """Qt Model API function. Returns the number of rows/children for the given parent.""" if not parent.isValid(): return len(self.images) else: return parent.internalPointer().row_count()
def parent(self, in_index: QModelIndex=None): if in_index.isValid(): parent=in_index.internalPointer().parent if parent: return QtCore.QAbstractItemModel.createIndex(self,parent.row,0,parent) return QtCore.QModelIndex()
def columnCount(self,parent: QModelIndex=None, *args, **kwargs): if parent.isValid(): return parent.internalPointer().columnCount() return self._root.columnCount()
def columnCount(self, parent: QtCore.QModelIndex = None): """Return the number of columns""" if parent is None: parent = QtCore.QModelIndex() return 8 if not parent.isValid() else 0
def itemFromIndex(self, index): index = QModelIndex( index) # explicitly convert from QPersistentModelIndex if index.isValid(): return index.internalPointer().childAt(index.row()) return self._root
def parentFromIndex(self, index): index = QModelIndex( index) # explicitly convert from QPersistentModelIndex if index.isValid(): return index.internalPointer() return self._root
def data(self, index: QModelIndex, role=Qt.DisplayRole): if not index.isValid(): return None row = index.row() # check for special case where no backup devices are active if len(self.rows) == 0: if role == Qt.DisplayRole: return ViewRowType.header elif role == Roles.device_details: if not self.prefs.backup_files: return _("Backups are not configured"), self.removableIcon elif self.prefs.backup_device_autodetection: return _("No backup devices detected"), self.removableIcon else: return ( _("Valid backup locations not yet specified"), self.folderIcon, ) # at least one device / location is being used if row >= len(self.rows) or row < 0: return None if row not in self.rows: return None row_id = self.rows[row] path = self.row_id_to_path[row_id] if role == Qt.DisplayRole: if row_id in self.headers: return ViewRowType.header else: return ViewRowType.content else: device = self.backup_devices[path] mount = device.mount if role == Qt.ToolTipRole: return path elif role == Roles.device_details: if self.prefs.backup_device_autodetection: icon = self.removableIcon else: icon = self.folderIcon return device.display_name, icon elif role == Roles.storage: ( photos_size_to_download, videos_size_to_download, ) = self._download_size_by_backup_type( backup_type=device.backup_type) ( photos_size_to_download, videos_size_to_download, ) = adjusted_download_size( photos_size_to_download=photos_size_to_download, videos_size_to_download=videos_size_to_download, os_stat_device=device.os_stat_device, downloading_to=self._downloading_to, ) bytes_total, bytes_free = get_mount_size(mount=mount) return BackupVolumeUse( bytes_total=bytes_total, bytes_free=bytes_free, backup_type=device.backup_type, marked=self.marked, photos_size_to_download=photos_size_to_download, videos_size_to_download=videos_size_to_download, ) return None
def data(self, index: QModelIndex, role: Qt.ItemDataRole) -> QVariant: assert index.isValid() col = index.column() coin_item = index.internalPointer() address = coin_item['address'] is_frozen_addr = coin_item['is_frozen_addr'] is_frozen_coin = coin_item['is_frozen_coin'] height = coin_item['height'] outpoint = coin_item['outpoint'] out_short = coin_item['out_short'] label = coin_item['label'] balance = coin_item['balance'] ps_rounds = coin_item['ps_rounds'] is_ps_ks = coin_item['is_ps_ks'] if ps_rounds is None: ps_rounds = 'N/A' elif ps_rounds == PSCoinRounds.COLLATERAL: ps_rounds = 'Collateral' elif ps_rounds == PSCoinRounds.OTHER: ps_rounds = 'Other' else: ps_rounds = str(ps_rounds) if role == Qt.ToolTipRole: if col == UTXOColumns.ADDRESS and is_frozen_addr: return QVariant(_('Address is frozen')) elif col == UTXOColumns.OUTPOINT: if is_frozen_coin: return QVariant(f'{outpoint}\n{_("Coin is frozen")}') else: return QVariant(outpoint) elif role not in (Qt.DisplayRole, Qt.EditRole): if role == Qt.TextAlignmentRole: if col in [ UTXOColumns.AMOUNT, UTXOColumns.HEIGHT, UTXOColumns.PS_ROUNDS, UTXOColumns.KEYSTORE_TYPE ]: return QVariant(Qt.AlignRight | Qt.AlignVCenter) else: return QVariant(Qt.AlignVCenter) elif role == Qt.FontRole: return QVariant(QFont(MONOSPACE_FONT)) elif role == Qt.BackgroundRole: if col == UTXOColumns.ADDRESS and is_frozen_addr: return QVariant(ColorScheme.BLUE.as_color(True)) elif col == UTXOColumns.OUTPOINT and is_frozen_coin: return QVariant(ColorScheme.BLUE.as_color(True)) elif col == UTXOColumns.OUTPOINT: return QVariant(out_short) elif col == UTXOColumns.ADDRESS: return QVariant(address) elif col == UTXOColumns.LABEL: return QVariant(label) elif col == UTXOColumns.AMOUNT: return QVariant(balance) elif col == UTXOColumns.HEIGHT: return QVariant(height) elif col == UTXOColumns.PS_ROUNDS: return QVariant(ps_rounds) elif col == UTXOColumns.KEYSTORE_TYPE: return QVariant(_('PS Keystore') if is_ps_ks else _('Main')) else: return QVariant()
def rowCount(self, parent: QtCore.QModelIndex = None): """Return the number of rows""" if parent is None: parent = QtCore.QModelIndex() return len(self._residues) if not parent.isValid() else 0
def data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> QVariant: if not index.isValid(): return QVariant() item = index.internalPointer() # Delegate to the model instance data() method return item.data(index.column(), role)
def paint(self, painter: QtGui.QPainter, option: 'QStyleOptionViewItem', index: QtCore.QModelIndex) -> None: """ Paints the message on the screen :param painter: Controls actual painting :param option: Options for painting :param index: Index of item :return: """ if not index.isValid(): return painter.save( ) # Save current state, before altering for custom painting painter.setRenderHints(QPainter.Antialiasing) context = index.model().chat_message_contexts()[index.row()] message_text = index.data(Qt.DisplayRole) profile_pix: QPixmap = index.data(Qt.DecorationRole) # Determine message rect message_font = QApplication.font() message_fm = QFontMetrics(message_font) if context.is_sender: # Paint text with 10 pixel padding message_rect = message_fm.boundingRect( option.rect.left(), option.rect.top() + MessageItemDelegate.profile_padding / 2, option.rect.width() - MessageItemDelegate.total_pfp_width, 0, Qt.AlignRight | Qt.AlignTop | Qt.TextWordWrap, message_text) # Draw bubble rect bubble_rect = QRect( message_rect.left() - MessageItemDelegate.profile_padding / 2, message_rect.top() - MessageItemDelegate.profile_padding / 2, message_rect.width() + MessageItemDelegate.profile_padding, message_rect.height() + MessageItemDelegate.profile_padding) blue = QColor(35, 57, 93) painter.setBrush(blue) painter.setPen(blue) painter.drawRoundedRect(bubble_rect, 5, 5) painter.setPen(Qt.white) painter.setFont(message_font) painter.drawText(message_rect, Qt.AlignLeft | Qt.AlignTop | Qt.TextWordWrap, message_text) # Paint icon profile_rect = QRect( message_rect.right() + MessageItemDelegate.profile_padding, option.rect.top(), MessageItemDelegate.icon_radius, MessageItemDelegate.icon_radius) painter.drawPixmap(profile_rect, profile_pix) else: # Paint icon profile_rect = QRect(option.rect.left(), option.rect.top(), MessageItemDelegate.icon_radius, MessageItemDelegate.icon_radius) painter.drawPixmap(profile_rect, profile_pix) # Paint text with 10 pixel padding message_rect = message_fm.boundingRect( profile_rect.right() + MessageItemDelegate.profile_padding, option.rect.top() + MessageItemDelegate.profile_padding / 2, option.rect.width() - MessageItemDelegate.total_pfp_width, 0, Qt.AlignLeft | Qt.AlignTop | Qt.TextWordWrap, message_text) # Draw bubble rect bubble_rect = QRect( message_rect.left() - MessageItemDelegate.profile_padding / 2, message_rect.top() - MessageItemDelegate.profile_padding / 2, message_rect.width() + MessageItemDelegate.profile_padding, message_rect.height() + MessageItemDelegate.profile_padding) gray = QColor(105, 105, 105) painter.setBrush(gray) painter.setPen(gray) painter.drawRoundedRect(bubble_rect, 5, 5) painter.setPen(Qt.white) painter.setFont(message_font) painter.drawText(message_rect, Qt.AlignLeft | Qt.AlignTop | Qt.TextWordWrap, message_text) painter.restore() # Reset to state before changes
def flags(self, index: QModelIndex): if not index.isValid(): return Qt.ItemIsEnabled return (qc.QAbstractItemModel.flags(self, index) | Qt.ItemIsEditable | Qt.ItemNeverHasChildren)
def canDropMimeData(self, mime_data: QtCore.QMimeData, action: QtCore.Qt.DropAction, target_row: int, target_column: int, target_parent: QtCore.QModelIndex) -> bool: # Some tests if drop is possible at the given location. # Only a drop - flags non withstanding - on the ingredient column is possible if target_column != self.IngredientColumns.INGREDIENT and target_column != -1: return False # A drop on the root column if target_parent.isValid( ) and target_parent.column() != self.IngredientColumns.INGREDIENT: return False drop_on_item = target_row == -1 and target_column == -1 # Test all dragged item - if one of those fails, a drop doesn't make sense # Unfortunately we cannot rely on item's position - because the user might have dragged the items before # and position might not reflect the position inside the tree anymore. This is trade off: Either renumber # the tree's content each time a drag has occurred - and causing database load - or renumber the tree only # when the user saves the changes, making it more difficult to determine the item's status # (group, alternative..) for index in self._dragged_indices: parent_item = index.parent() # -------------------- Groups --------------------- # This is the only case where item_position can be safely used: A group can only be moved within the # root level, so even if the position doesn't reflect the model's position, it's OK to use the # information to determine if it's a group or a root level ingredient if data.IngredientListEntry.is_group( int(index.data(QtCore.Qt.UserRole))): # A group cannot be dropped on another group or item if drop_on_item: # Attempted drop on an item, no matter on which level return False else: # A move before/after target_parent's item if target_parent.isValid(): # There's a parent (i.e. a level below root) return False if index.row() == target_row: # Drag in front of itself. Makes no sense return False # A group can only be moved inside the "group window", i.e. between the tree's very first row # and before the first root-level ingredient if target_row > 0: previous_index = self.index( target_row - 1, self.IngredientColumns.INGREDIENT, QtCore.QModelIndex()) if previous_index == index: # Drag behind itself. Makes no sense return False if not data.IngredientListEntry.is_group( int(previous_index.data(QtCore.Qt.UserRole))): # No group - trying to move the group into the root level ingredients return False # -------------------- Ingredients -------------------- else: # Two case: Either a move or a drop on an item (i.e. attach it to parent) # First, drop on an item if drop_on_item: if not target_parent.isValid(): return False # Drop on a group if data.IngredientListEntry.is_group( int(target_parent.data(QtCore.Qt.UserRole))): # The item is allowed to have children, but only if it's an ingredient # (and not alternative ingredients, otherwise the level would change: and becomes or and or # becomes the ingredient. This isn't what the user really wants) if self.hasChildren(index): if self.depth( index) != self.IngredientLevels.INGREDIENT: return False if self.rowCount( index) >= data.IngredientListEntry.MAX_ENTRIES: return False if parent_item is not None and parent_item == target_parent: return False else: # Only accept items that haven't got children. Otherwise this would lead to odd results: # Ingredient B which has an alternative C (B OR C) dropped on Ingredient A would lead to: # Ingredient A OR Ingredient B AND Ingredient C, which is clearly not right. Alternatively # do some major internal rewriting if self.hasChildren(index): return False # Only a certain level can be accepted if self.depth( target_parent ) >= self.IngredientLevels.ALTERNATIVEGROUP: return False if self.rowCount( target_parent ) >= data.IngredientListEntry.MAX_ENTRIES: return False else: # Move parent_level = self.IngredientLevels.ROOT if target_parent.isValid(): parent_level = self.depth(target_parent) if self.rowCount( target_parent ) >= data.IngredientListEntry.MAX_ENTRIES: return False # The root-level ingredients have to be beneath the grouped items if parent_level == self.IngredientLevels.ROOT: number_of_root_items = self.invisibleRootItem( ).rowCount() # target_row == number_of_root_items would mean an append at the end of the list, # which would be perfectly acceptable if target_row < number_of_root_items: next_index = self.index( target_row, self.IngredientColumns.INGREDIENT, QtCore.QModelIndex()) if data.IngredientListEntry.is_group( int(next_index.data(QtCore.Qt.UserRole))): # trying to move an ingredient item before a group return False # Contrary to drop, moving an item with children is allowed.. but only if its moved on the # same level. Otherwise the tree would either increase it's depth to a invalid value or # something similar confusing like dropping an item with children on an item would occur. if self.hasChildren(index): # Since parent is always one level higher than the item if parent_level != self.depth(index) - 1: return False return super().canDropMimeData(mime_data, action, target_row, target_column, target_parent)
def _indexToItem(self, index: QModelIndex): if not index.isValid(): return self._root else: return index.internalPointer()
def rowCount(self, parent: QtCore.QModelIndex = ...) -> int: if parent.isValid(): pointer = parent.internalPointer() return pointer.rowCount() else: return self.root.rowCount()
def index(self, row: int, column: int, parent: QModelIndex): if not parent.isValid(): # parent is root if len(self.coin_items) > row: return self.createIndex(row, column, self.coin_items[row]) return QModelIndex()
def data(self, index: QModelIndex, role: int = ...): if not index.isValid(): return QVariant() node: EncounterNode = index.internalPointer() p: Entity = self.encounter.entities[node.player] h = self.headers[index.column()] if h == self.TXT_CLASS and role == Qt.DecorationRole: if node.pixmap is None: try: #print("was none") specInfo = self.resourceHandler.getSpecialization(p.elite, p.prof) p = QPixmap() p.loadFromData(specInfo[self.resourceHandler.PROFESSION_ICON]) p = p.scaled(QSize(20, 20), Qt.KeepAspectRatio, Qt.SmoothTransformation) node.pixmap = p except Exception as e: return QVariant() return node.pixmap if role == Qt.TextAlignmentRole: if h in [self.TXT_SUBSQUAD, self.TXT_CLASS, self.TXT_DEAD, self.TXT_DOWN, self.TXT_DPS, self.TXT_BOSS_DPS, self.TXT_DMG_BOSS, self.TXT_DMG_TOTAL]: return Qt.AlignCenter if role == Qt.DisplayRole: if h == self.TXT_SUBSQUAD: return p.subsquad if h == self.TXT_CHARACTER: return p.character if h == self.TXT_ACCOUNT: return p.account if h == self.TXT_BOSS_DPS: return self.encounter.getBossDps(node.player) if h == self.TXT_DPS: return self.encounter.getTotalDps(node.player) if h == self.TXT_DMG_TOTAL: return p.damage.totalOut if h == self.TXT_DMG_BOSS: return self.encounter.getBossDamage(node.player) if h == self.TXT_DOWN: return p.downed if h == self.TXT_DEAD: return p.dead return QVariant() if role == Qt.BackgroundRole: if not self.encounter.fullComplete: return QVariant() rightBound = self.headerWidths[index.column()]/self.totalWidth leftBound = 0 if index.column() > 0: leftBound = self.headerWidths[index.column() - 1]/self.totalWidth # barBound = self.encounter.getTotalDps(node.player)/self.highestRowValue if self.highestRowValue == 0: barBound = 0 else: barBound = self.data(self.createIndex(index.row(), self.sortColumn, node), Qt.DisplayRole)/self.highestRowValue profColor = QColor(*reference.CLASS_COLORS[p.prof], 60) if rightBound <= barBound: return profColor elif leftBound >= barBound: return QVariant() else: colpercent = rightBound - leftBound colwidth = 0 if index.column() > 0: colwidth = self.headerWidths[index.column()] - self.headerWidths[index.column() - 1] else: colwidth = self.headerWidths[index.column()] toFill = barBound-leftBound gradient = QLinearGradient(0, 0, colwidth, 0) gradient.setColorAt(toFill/colpercent, profColor) gradient.setColorAt((toFill/colpercent) + .000001, QColor('white')) brush = QBrush(gradient) return brush
def data(self, model_index: QModelIndex, role: int) -> QVariant: row = model_index.row() column = model_index.column() if row >= len(self._data): return None if column >= len(self._column_names): return None if model_index.isValid(): line = self._data[row] # First check the custom sort role. if role == QT_SORT_ROLE: if column == TYPE_COLUMN: if line.flags & AddressFlags.RECEIVING: return 1 elif line.flags & AddressFlags.CHANGE: return 2 return 100 elif column == STATE_COLUMN: if line.flags & AddressFlags.FROZEN: return 1 elif line.flags & AddressFlags.RETIRED: return 2 elif line.flags & AddressFlags.BEYOND_LIMIT: return 3 return 0 elif column == ADDRESS_COLUMN: return line.address.hash160() elif column == INDEX_COLUMN: return line.index elif column == LABEL_COLUMN: return self._view._wallet.labels.get(line.address.to_string(), '') elif column == USAGES_COLUMN: return len(self._view._wallet.get_address_history(line.address)) elif column in (BALANCE_COLUMN, FIAT_BALANCE_COLUMN): if column == BALANCE_COLUMN: return self._view._parent.format_amount(line.balance, whitespaces=True) elif column == FIAT_BALANCE_COLUMN: fx = app_state.fx rate = fx.exchange_rate() return fx.value_str(line.balance, rate) elif role == Qt.DecorationRole: if column == TYPE_COLUMN: if line.flags & AddressFlags.RECEIVING: return self._receive_icon elif line.flags & AddressFlags.CHANGE: return self._change_icon elif role == Qt.DisplayRole: if column == TYPE_COLUMN: pass elif column == STATE_COLUMN: if line.flags & AddressFlags.BEYOND_LIMIT: return "B" elif column == ADDRESS_COLUMN: return line.address.to_string() elif column == INDEX_COLUMN: return line.index elif column == LABEL_COLUMN: return self._view._wallet.get_address_label(line.address.to_string()) elif column == USAGES_COLUMN: return len(self._view._wallet.get_address_history(line.address)) elif column == BALANCE_COLUMN: return self._view._parent.format_amount(line.balance, whitespaces=True) elif column == FIAT_BALANCE_COLUMN: fx = app_state.fx rate = fx.exchange_rate() return fx.value_str(line.balance, rate) elif role == Qt.FontRole: if column in (ADDRESS_COLUMN, BALANCE_COLUMN, FIAT_BALANCE_COLUMN): return self._monospace_font elif role == Qt.BackgroundRole: if column == STATE_COLUMN: if line.flags & AddressFlags.FROZEN: return self._frozen_brush elif line.flags & AddressFlags.RETIRED: return self._archived_brush elif line.flags & AddressFlags.BEYOND_LIMIT: return self._beyond_limit_brush elif role == Qt.TextAlignmentRole: if column in (TYPE_COLUMN, STATE_COLUMN): return Qt.AlignCenter elif column in (BALANCE_COLUMN, FIAT_BALANCE_COLUMN, USAGES_COLUMN, INDEX_COLUMN): return Qt.AlignRight | Qt.AlignVCenter return Qt.AlignVCenter elif role == Qt.ToolTipRole: if column == TYPE_COLUMN: if line.flags & AddressFlags.RECEIVING: return _("Receiving address") elif line.flags & AddressFlags.CHANGE: return _("Change address") elif column == STATE_COLUMN: if line.flags & AddressFlags.FROZEN: return _("This is a frozen address") elif line.flags & AddressFlags.RETIRED: return _("This an address that was once in use, "+ "but is now empty and has been retired") elif line.flags & AddressFlags.BEYOND_LIMIT: return _("This address is generated from beyond the current gap limit") elif role == Qt.EditRole: if column == LABEL_COLUMN: return self._view._wallet.get_address_label(line.address.to_string())
def data(self, index: QModelIndex, role=Qt.DisplayRole): if not index.isValid(): return None i, j = index.row(), index.column() try: lbl = self.display_labels[i] except IndexError: return None if isinstance(lbl, ChecksumLabel) and self.message is not None: calculated_crc = lbl.calculate_checksum_for_message(self.message, use_decoded_bits=True) else: calculated_crc = None if role == Qt.DisplayRole: if j == 0: return lbl.name elif j == 1: return lbl.color_index elif j == 2: return lbl.DISPLAY_FORMATS[lbl.display_format_index] elif j == 3: return lbl.display_order_str elif j == 4: return self.__display_data(lbl, calculated_crc) elif role == Qt.CheckStateRole and j == 0: return lbl.show elif role == Qt.BackgroundColorRole: if isinstance(lbl, ChecksumLabel) and j == 4 and self.message is not None: start, end = self.message.get_label_range(lbl, 0, True) if calculated_crc == self.message.decoded_bits[start:end]: return constants.BG_COLOR_CORRECT else: return constants.BG_COLOR_WRONG else: return None elif role == Qt.ToolTipRole: if j == 2: return self.tr("Choose display type for the value of the label:" "<ul>" "<li>Bit</li>" "<li>Hexadecimal (Hex)</li>" "<li>ASCII chars</li>" "<li>Decimal Number</li>" "<li>Binary Coded Decimal (BCD)</li>" "</ul>") if j == 3: return self.tr("Choose bit order for the displayed value:" "<ul>" "<li>Most Significant Bit (MSB) [Default]</li>" "<li>Least Significant Bit (LSB)</li>" "<li>Least Significant Digit (LSD)</li>" "</ul>") elif role == Qt.FontRole and j == 0: font = QFont() font.setBold(i in self.selected_label_indices) return font
def flags(self, index: QModelIndex): if not index.isValid(): return Qt.ItemIsEnabled return Qt.ItemIsEnabled | Qt.ItemIsDropEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled | Qt.ItemIsEditable