def setData(self, model, qidx): self.model = model self.current = QPersistentModelIndex(qidx) self.model.rowsInserted.connect(self.updatePos) self.model.rowsRemoved.connect(self.updatePos) self.model.rowsInserted.connect(self.updateNavButtons) self.model.rowsRemoved.connect(self.updateNavButtons) self.model.dataChanged.connect(self._dataChanged) self.model.modelReset.connect(self.disable) self.updateImage()
def set_current_idx(self, set_current: QPersistentModelIndex): if set_current: assert isinstance(set_current, QPersistentModelIndex) assert set_current.isValid() self.selectionModel().select(QModelIndex(set_current), QItemSelectionModel.SelectCurrent)
def createEditor(self, parent, option, idx): self.opened = QPersistentModelIndex(idx) return super().createEditor(parent, option, idx)
def update_model(self, clear=True): log.info("updating effects model.") app = get_app() # Get window to check filters win = app.window _ = app._tr # Clear all items if clear: self.model_names = {} self.model.clear() # Add Headers self.model.setHorizontalHeaderLabels( [_("Thumb"), _("Name"), _("Description")]) # Get the folder path of effects effects_dir = os.path.join(info.PATH, "effects") icons_dir = os.path.join(effects_dir, "icons") # Get a JSON list of all supported effects in libopenshot raw_effects_list = json.loads(openshot.EffectInfo.Json()) # Loop through each effect for effect_info in raw_effects_list: # Get basic properties about each effect effect_name = effect_info["class_name"] title = effect_info["name"] description = effect_info["description"] # Remove any spaces from icon name icon_name = "%s.png" % effect_name.lower().replace(' ', '') icon_path = os.path.join(icons_dir, icon_name) # Determine the category of effect (audio, video, both) category = None if effect_info["has_video"] and effect_info["has_audio"]: category = "Audio & Video" elif not effect_info["has_video"] and effect_info["has_audio"]: category = "Audio" elif effect_info["has_video"] and not effect_info["has_audio"]: category = "Video" # Filter out effect (if needed) if (win.effectsFilter.text() != "" and win.effectsFilter.text().lower() not in self.app._tr(title).lower() and win.effectsFilter.text().lower() not in self.app._tr(description).lower()): continue # Check for thumbnail path (in build-in cache) thumb_path = os.path.join(info.IMAGES_PATH, "cache", icon_name) # Check built-in cache (if not found) if not os.path.exists(thumb_path): # Check user folder cache thumb_path = os.path.join(info.CACHE_PATH, icon_name) # Generate thumbnail (if needed) if not os.path.exists(thumb_path): try: # Reload this reader log.info('Generating thumbnail for %s (%s)' % (thumb_path, icon_path)) clip = openshot.Clip(icon_path) reader = clip.Reader() # Open reader reader.Open() # Save thumbnail reader.GetFrame(0).Thumbnail( thumb_path, 98, 64, os.path.join(info.IMAGES_PATH, "mask.png"), "", "#000", True, "png", 85) reader.Close() except Exception: # Handle exception log.info('Invalid effect image file: %s' % icon_path) msg = QMessageBox() msg.setText( _("{} is not a valid image file.".format(icon_path))) msg.exec_() continue row = [] # Append thumbnail col = QStandardItem() icon_pixmap = QPixmap(thumb_path) scaled_pixmap = icon_pixmap.scaled(QSize(98, 64), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) col.setIcon(QIcon(scaled_pixmap)) col.setText(self.app._tr(title)) col.setToolTip(self.app._tr(title)) col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsDragEnabled) row.append(col) # Append Name col = QStandardItem("Name") col.setData(self.app._tr(title), Qt.DisplayRole) col.setText(self.app._tr(title)) col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsDragEnabled) row.append(col) # Append Description col = QStandardItem("Description") col.setData(self.app._tr(description), Qt.DisplayRole) col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsDragEnabled) row.append(col) # Append Category col = QStandardItem("Category") col.setData(category, Qt.DisplayRole) col.setText(category) col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsDragEnabled) row.append(col) # Append Path col = QStandardItem("Effect") col.setData(effect_name, Qt.DisplayRole) col.setText(effect_name) col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsDragEnabled) row.append(col) # Append ROW to MODEL (if does not already exist in model) if effect_name not in self.model_names: self.model.appendRow(row) self.model_names[effect_name] = QPersistentModelIndex( row[1].index()) # Emit signal when model is updated self.ModelRefreshed.emit()
def update(self): self.wallet = self.parent.wallet current_address = self.current_item_user_role(col=self.Columns.LABEL) if self.show_change == 1: addr_list = self.wallet.get_receiving_addresses() elif self.show_change == 2: addr_list = self.wallet.get_change_addresses() else: addr_list = self.wallet.get_addresses() self.model().clear() self.refresh_headers() fx = self.parent.fx set_address = None for address in addr_list: num = self.wallet.get_address_history_len(address) label = self.wallet.labels.get(address, '') c, u, x = self.wallet.get_addr_balance(address) balance = c + u + x is_used_and_empty = self.wallet.is_used(address) and balance == 0 if self.show_used == 1 and (balance or is_used_and_empty): continue if self.show_used == 2 and balance == 0: continue if self.show_used == 3 and not is_used_and_empty: continue balance_text = self.parent.format_amount(balance, whitespaces=True) # create item if fx and fx.get_fiat_address_config(): rate = fx.exchange_rate() fiat_balance = fx.value_str(balance, rate) else: fiat_balance = '' labels = ['', address, label, balance_text, fiat_balance, "%d"%num] address_item = [QStandardItem(e) for e in labels] # align text and set fonts for i, item in enumerate(address_item): item.setTextAlignment(Qt.AlignVCenter) if i not in (self.Columns.TYPE, self.Columns.LABEL): item.setFont(QFont(MONOSPACE_FONT)) item.setEditable(i in self.editable_columns) address_item[self.Columns.FIAT_BALANCE].setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) # setup column 0 if self.wallet.is_change(address): address_item[self.Columns.TYPE].setText(_('change')) address_item[self.Columns.TYPE].setBackground(ColorScheme.YELLOW.as_color(True)) else: address_item[self.Columns.TYPE].setText(_('receiving')) address_item[self.Columns.TYPE].setBackground(ColorScheme.GREEN.as_color(True)) address_item[self.Columns.LABEL].setData(address, Qt.UserRole) # setup column 1 if self.wallet.is_frozen(address): address_item[self.Columns.ADDRESS].setBackground(ColorScheme.BLUE.as_color(True)) if self.wallet.is_beyond_limit(address): address_item[self.Columns.ADDRESS].setBackground(ColorScheme.RED.as_color(True)) # add item count = self.model().rowCount() self.model().insertRow(count, address_item) address_idx = self.model().index(count, self.Columns.LABEL) if address == current_address: set_address = QPersistentModelIndex(address_idx) self.set_current_idx(set_address) # show/hide columns if fx and fx.get_fiat_address_config(): self.showColumn(self.Columns.FIAT_BALANCE) else: self.hideColumn(self.Columns.FIAT_BALANCE)
class Viewer(QtMainWindow): jobAdded = Signal() jobFinished = Signal() def __init__(self, weboob, parent=None): super(Viewer, self).__init__(parent) self.ui = Ui_Viewer() self.ui.setupUi(self) self.ui.prevButton.clicked.connect(self.prev) self.ui.nextButton.clicked.connect(self.next) self.ui.firstButton.clicked.connect(self.first) self.ui.lastButton.clicked.connect(self.last) self.ui.actionZoomIn.triggered.connect(self.zoomIn) self.ui.actionZoomOut.triggered.connect(self.zoomOut) self.ui.actionFullSize.triggered.connect(self.zoomFullSize) self.ui.actionFitWindow.triggered.connect(self.zoomFit) self.ui.actionSaveImage.setShortcut(QKeySequence.Save) self.ui.actionSaveImage.triggered.connect(self.saveImage) self.ui.actionClose.setShortcut(QKeySequence.Close) self.ui.actionClose.triggered.connect(self.close) self.model = None self.current = None self.total = 0 self.zoomFactor = 1 self.zoomMode = ZOOM_FACTOR self.weboob = weboob def setData(self, model, qidx): self.model = model self.current = QPersistentModelIndex(qidx) self.model.rowsInserted.connect(self.updatePos) self.model.rowsRemoved.connect(self.updatePos) self.model.rowsInserted.connect(self.updateNavButtons) self.model.rowsRemoved.connect(self.updateNavButtons) self.model.dataChanged.connect(self._dataChanged) self.model.modelReset.connect(self.disable) self.updateImage() @Slot() def disable(self): self.setEnabled(False) def updateNavButtons(self): prev = self.current.row() > 0 self.ui.prevButton.setEnabled(prev) self.ui.firstButton.setEnabled(prev) next = self.current.row() < self.total - 1 self.ui.nextButton.setEnabled(next) self.ui.lastButton.setEnabled(next) def updatePos(self): self.total = self.model.rowCount(self.current.parent()) self.ui.posLabel.setText('%d / %d' % (self.current.row() + 1, self.total)) def updateImage(self): self.updatePos() self.updateNavButtons() obj = self.current.data(ResultModel.RoleObject) if obj.data is NotLoaded: self.model.fillObj(obj, ['data'], QModelIndex(self.current)) self.pixmap = None elif obj.data: self.pixmap = QPixmap(QImage.fromData(obj.data)) else: self.pixmap = QPixmap() self._rebuildImage() @Slot(QModelIndex) def _dataChanged(self, qidx): if qidx == self.current: obj = qidx.data(ResultModel.RoleObject) if obj.data: self.pixmap = QPixmap(QImage.fromData(obj.data)) else: self.pixmap = QPixmap() self._rebuildImage() @Slot() def next(self): new = self.current.sibling(self.current.row() + 1, 0) if not new.isValid(): return self.current = QPersistentModelIndex(new) self.updateImage() @Slot() def prev(self): if self.current.row() == 0: return self.current = QPersistentModelIndex(self.current.sibling(self.current.row() - 1, 0)) self.updateImage() @Slot() def first(self): self.current = QPersistentModelIndex(self.current.sibling(0, 0)) self.updateImage() @Slot() def last(self): self.current = QPersistentModelIndex(self.current.sibling(self.total - 1, 0)) self.updateImage() @Slot() def zoomIn(self): self.zoomFactor *= 1.25 self.zoomMode = ZOOM_FACTOR self._rebuildImage() @Slot() def zoomOut(self): self.zoomFactor *= 0.75 self.zoomMode = ZOOM_FACTOR self._rebuildImage() @Slot() def zoomFullSize(self): self.zoomFactor = 1 self.zoomMode = ZOOM_FACTOR self._rebuildImage() @Slot() def zoomFit(self): self.zoomMode = ZOOM_FIT self._rebuildImage() def resizeEvent(self, ev): super(Viewer, self).resizeEvent(ev) if self.zoomMode == ZOOM_FIT: self._rebuildImage() def _rebuildZoom(self): if self.zoomMode == ZOOM_FACTOR: new_width = int(self.pixmap.width() * self.zoomFactor) pixmap = self.pixmap.scaledToWidth(new_width, Qt.SmoothTransformation) else: new_size = self.ui.scrollArea.viewport().size() pixmap = self.pixmap.scaled(new_size, Qt.KeepAspectRatio, Qt.SmoothTransformation) self.zoomFactor = pixmap.width() / float(self.pixmap.width()) return pixmap def _rebuildImage(self): if self.pixmap is None: self.ui.view.setText('Loading...') return elif self.pixmap.isNull(): self.ui.view.setText('Image could not be loaded') return pixmap = self._rebuildZoom() self.ui.view.setPixmap(pixmap) @Slot() def saveImage(self): def ext_for_filter(s): return re.match(r'(?:[A-Z]+) \(\*\.([a-z]+)\)$', s).group(1) if not self.pixmap: return filters = ['PNG (*.png)', 'JPEG (*.jpg)', 'GIF (*.gif)'] obj = self.current.data(ResultModel.RoleObject) name = '%s.%s' % (obj.title or obj.id or u'', obj.ext or 'png') default = filters[0] for f in filters: if name.endswith(ext_for_filter(f)): default = f filters = ';;'.join(filters) target = os.path.join(self.parent().lastSaveDir, name) out, filter = QFileDialog.getSaveFileName(self, 'Save image', target, filters, default) if not out: return ext = ext_for_filter(filter) self.parent().lastSaveDir = os.path.dirname(out) if not os.path.splitext(out)[1]: out = '%s.%s' % (out, ext) if os.path.exists(out): q = self.tr('%s already exists, are you sure you want to replace it?') % out reply = QMessageBox.question(self, self.tr('Overwrite?'), q) if reply == QMessageBox.No: return self.saveImage() self.pixmap.save(out, ext.upper())
def first(self): self.current = QPersistentModelIndex(self.current.sibling(0, 0)) self.updateImage()
def next(self): new = self.current.sibling(self.current.row() + 1, 0) if not new.isValid(): return self.current = QPersistentModelIndex(new) self.updateImage()
def create_menu(self, position: QPoint): org_idx: QModelIndex = self.indexAt(position) idx = self.proxy.mapToSource(org_idx) if not idx.isValid(): # can happen e.g. before list is populated for the first time return tx_item = self.hm.transactions.value_from_pos(idx.row()) if tx_item.get('lightning') and tx_item['type'] == 'payment': menu = QMenu() menu.addAction( _("View Payment"), lambda: self.parent.show_lightning_transaction(tx_item)) cc = self.add_copy_menu(menu, idx) cc.addAction( _("Payment Hash"), lambda: self.place_text_on_clipboard(tx_item['payment_hash'], title="Payment Hash")) cc.addAction( _("Preimage"), lambda: self.place_text_on_clipboard(tx_item['preimage'], title="Preimage")) menu.exec_(self.viewport().mapToGlobal(position)) return tx_hash = tx_item['txid'] if tx_item.get('lightning'): tx = self.wallet.lnworker.lnwatcher.db.get_transaction(tx_hash) else: tx = self.wallet.db.get_transaction(tx_hash) if not tx: return tx_URL = block_explorer_URL(self.config, 'tx', tx_hash) tx_details = self.wallet.get_tx_info(tx) is_unconfirmed = tx_details.tx_mined_status.height <= 0 invoice_keys = self.wallet._get_relevant_invoice_keys_for_tx(tx) menu = QMenu() if tx_details.can_remove: menu.addAction(_("Remove"), lambda: self.remove_local_tx(tx_hash)) cc = self.add_copy_menu(menu, idx) cc.addAction( _("Transaction ID"), lambda: self.place_text_on_clipboard(tx_hash, title="TXID")) for c in self.editable_columns: if self.isColumnHidden(c): continue label = self.hm.headerData(c, Qt.Horizontal, Qt.DisplayRole) # TODO use siblingAtColumn when min Qt version is >=5.11 persistent = QPersistentModelIndex( org_idx.sibling(org_idx.row(), c)) menu.addAction(_("Edit {}").format(label), lambda p=persistent: self.edit(QModelIndex(p))) menu.addAction(_("View Transaction"), lambda: self.show_transaction(tx_item, tx)) channel_id = tx_item.get('channel_id') if channel_id: menu.addAction( _("View Channel"), lambda: self.parent.show_channel(bytes.fromhex(channel_id))) if is_unconfirmed and tx: # note: the current implementation of RBF *needs* the old tx fee if tx_details.can_bump and tx_details.fee is not None: menu.addAction(_("Increase fee"), lambda: self.parent.bump_fee_dialog(tx)) else: child_tx = self.wallet.cpfp(tx, 0) if child_tx: menu.addAction(_("Child pays for parent"), lambda: self.parent.cpfp(tx, child_tx)) if invoice_keys: menu.addAction( read_QIcon("seal"), _("View invoice"), lambda: [self.parent.show_invoice(key) for key in invoice_keys]) if tx_URL: menu.addAction(_("View on block explorer"), lambda: webopen(tx_URL)) menu.exec_(self.viewport().mapToGlobal(position))
def create_menu(self, position: QPoint): org_idx: QModelIndex = self.indexAt(position) idx = self.proxy.mapToSource(org_idx) if not idx.isValid(): # can happen e.g. before list is populated for the first time return tx_item = self.hm.transactions.value_from_pos(idx.row()) column = idx.column() if column == HistoryColumns.STATUS_ICON: column_title = _('Transaction ID') column_data = tx_item['txid'] else: column_title = self.hm.headerData(column, Qt.Horizontal, Qt.DisplayRole) column_data = self.hm.data(idx, Qt.DisplayRole).value() tx_hash = tx_item['txid'] tx = self.wallet.db.get_transaction(tx_hash) if not tx: return tx_URL = block_explorer_URL(self.config, 'tx', tx_hash) height = self.wallet.get_tx_height(tx_hash).height is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(tx) is_unconfirmed = height <= 0 pr_key = self.wallet.invoices.paid.get(tx_hash) menu = QMenu() if height == TX_HEIGHT_LOCAL: menu.addAction(_("Remove"), lambda: self.remove_local_tx(tx_hash)) amount_columns = [ HistoryColumns.COIN_VALUE, HistoryColumns.RUNNING_COIN_BALANCE, HistoryColumns.FIAT_VALUE, HistoryColumns.FIAT_ACQ_PRICE, HistoryColumns.FIAT_CAP_GAINS ] if column in amount_columns: column_data = column_data.strip() menu.addAction( _("Copy {}").format(column_title), lambda: self.parent.app.clipboard().setText(column_data)) for c in self.editable_columns: if self.isColumnHidden(c): continue label = self.hm.headerData(c, Qt.Horizontal, Qt.DisplayRole) # TODO use siblingAtColumn when min Qt version is >=5.11 persistent = QPersistentModelIndex( org_idx.sibling(org_idx.row(), c)) menu.addAction(_("Edit {}").format(label), lambda p=persistent: self.edit(QModelIndex(p))) menu.addAction(_("Details"), lambda: self.show_transaction(tx_hash)) if is_unconfirmed and tx: # note: the current implementation of RBF *needs* the old tx fee rbf = is_mine and not tx.is_final() and fee is not None if rbf: menu.addAction(_("Increase fee"), lambda: self.parent.bump_fee_dialog(tx)) else: child_tx = self.wallet.cpfp(tx, 0) if child_tx: menu.addAction(_("Child pays for parent"), lambda: self.parent.cpfp(tx, child_tx)) if pr_key: menu.addAction(read_QIcon("seal"), _("View invoice"), lambda: self.parent.show_invoice(pr_key)) if tx_URL: menu.addAction(_("View on block explorer"), lambda: webopen(tx_URL)) menu.exec_(self.viewport().mapToGlobal(position))
def myDropEvent(self, event, drop_item): """Workaround for broken QTreeWidget::dropEvent per https://bugreports.qt.io/browse/QTBUG-45320 doing reverse ordering of items on dropping. reimplementation in python from C++ For this code we need dual GPL3 license instead of pure BSD3 """ if event.source() == self and (event.dropAction() == Qt.MoveAction or self.dragDropMode() == QAbstractItemView.InternalMove): droptuple = self.dropOn(event, drop_item) if droptuple is not None: (row, col, drop_index) = droptuple # print("droptuple", droptuple[2].row()) idxs = self.selectedIndexes() indexes = [] for idx in idxs: if idx.column() == 0: indexes.append(idx) if drop_index in indexes: return # When removing items the drop location could shift new_drop_index = QPersistentModelIndex(self.model().index( row, col, drop_index)) # print("updatated drop_row", new_drop_index.row()) # Remove the items taken = [] for i in range(len(indexes) - 1, -1, -1): # print("idx", indexes[i].row(), indexes[i].column()) parent = self.itemFromIndex(indexes[i]) if parent is None or parent.parent() is None: t_item = self.takeTopLevelItem(indexes[i].row()) taken.append(t_item) else: t_item = parent.parent().takeChild(indexes[i].row()) taken.append(t_item) # end for # insert them back in at their new positions for i in range(len(indexes)): # Either at a specific point or appended if row == -1: if drop_index.isValid(): parent = self.itemFromIndex(drop_index) parent.insertChild(parent.childCount(), taken.pop()) else: self.insertTopLevelItem(self.topLevelItemCount(), taken.pop()) else: r = new_drop_index.row( ) if new_drop_index.row() >= 0 else row if drop_index.isValid(): parent = self.itemFromIndex(drop_index) parent.insertChild(min(r, parent.childCount()), taken.pop()) else: self.insertTopLevelItem( min(r, self.topLevelItemCount()), taken.pop()) # end for event.accept() # Don't want QAbstractItemView to delete it because it was "moved" we already did it event.setDropAction(Qt.CopyAction) QTreeView.dropEvent(self, event)
def update(self): if self.maybe_defer_update(): return current_address = self.current_item_user_role(col=self.Columns.LABEL) if self.show_change == AddressTypeFilter.RECEIVING: addr_list = self.wallet.get_receiving_addresses() elif self.show_change == AddressTypeFilter.CHANGE: addr_list = self.wallet.get_change_addresses() else: addr_list = self.wallet.get_addresses() self.proxy.setDynamicSortFilter(False) # temp. disable re-sorting after every change self.std_model.clear() self.refresh_headers() fx = self.parent.fx set_address = None addresses_beyond_gap_limit = self.wallet.get_all_known_addresses_beyond_gap_limit() for address in addr_list: num = self.wallet.get_address_history_len(address) label = self.wallet.labels.get(address, '') c, u, x = self.wallet.get_addr_balance(address) balance = c + u + x is_used_and_empty = self.wallet.is_used(address) and balance == 0 if self.show_used == AddressUsageStateFilter.UNUSED and (balance or is_used_and_empty): continue if self.show_used == AddressUsageStateFilter.FUNDED and balance == 0: continue if self.show_used == AddressUsageStateFilter.USED_AND_EMPTY and not is_used_and_empty: continue balance_text = self.parent.format_amount(balance, whitespaces=True) # create item if fx and fx.get_fiat_address_config(): rate = fx.exchange_rate() fiat_balance = fx.value_str(balance, rate) else: fiat_balance = '' labels = ['', address, label, balance_text, fiat_balance, "%d"%num] address_item = [QStandardItem(e) for e in labels] # align text and set fonts for i, item in enumerate(address_item): item.setTextAlignment(Qt.AlignVCenter) if i not in (self.Columns.TYPE, self.Columns.LABEL): item.setFont(QFont(MONOSPACE_FONT)) self.set_editability(address_item) address_item[self.Columns.FIAT_BALANCE].setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) # setup column 0 if self.wallet.is_change(address): address_item[self.Columns.TYPE].setText(_('change')) address_item[self.Columns.TYPE].setBackground(ColorScheme.YELLOW.as_color(True)) else: address_item[self.Columns.TYPE].setText(_('receiving')) address_item[self.Columns.TYPE].setBackground(ColorScheme.GREEN.as_color(True)) address_item[self.Columns.LABEL].setData(address, Qt.UserRole) address_path = self.wallet.get_address_index(address) address_item[self.Columns.TYPE].setData(address_path, self.ROLE_SORT_ORDER) address_path_str = self.wallet.get_address_path_str(address) if address_path_str is not None: address_item[self.Columns.TYPE].setToolTip(address_path_str) address_item[self.Columns.FIAT_BALANCE].setData(balance, self.ROLE_SORT_ORDER) # setup column 1 if self.wallet.is_frozen_address(address): address_item[self.Columns.ADDRESS].setBackground(ColorScheme.BLUE.as_color(True)) if address in addresses_beyond_gap_limit: address_item[self.Columns.ADDRESS].setBackground(ColorScheme.RED.as_color(True)) # add item count = self.std_model.rowCount() self.std_model.insertRow(count, address_item) address_idx = self.std_model.index(count, self.Columns.LABEL) if address == current_address: set_address = QPersistentModelIndex(address_idx) self.set_current_idx(set_address) # show/hide columns if fx and fx.get_fiat_address_config(): self.showColumn(self.Columns.FIAT_BALANCE) else: self.hideColumn(self.Columns.FIAT_BALANCE) self.filter() self.proxy.setDynamicSortFilter(True)
def test_model_persistent_index(model_test): ''' ☑ 🛇 read-only.ro ☑ ★ user.json ☑ ⎕ commands.json ☐ 🛇 asset:plover:assets/main.json ''' persistent_index = QPersistentModelIndex(model_test.model.index(1)) assert persistent_index.row() == 1 assert persistent_index.data(Qt.CheckStateRole) == Qt.Checked assert persistent_index.data(Qt.DecorationRole) == 'favorite' assert persistent_index.data(Qt.DisplayRole) == 'user.json' model_test.configure(classic_dictionaries_display_order=True) assert persistent_index.row() == 2 assert persistent_index.data(Qt.CheckStateRole) == Qt.Checked assert persistent_index.data(Qt.DecorationRole) == 'favorite' assert persistent_index.data(Qt.DisplayRole) == 'user.json' model_test.model.setData(persistent_index, Qt.Unchecked, Qt.CheckStateRole) assert persistent_index.row() == 2 assert persistent_index.data(Qt.CheckStateRole) == Qt.Unchecked assert persistent_index.data(Qt.DecorationRole) == 'normal' assert persistent_index.data(Qt.DisplayRole) == 'user.json'
def create_menu(self, position): from electrum_axe.wallet import Multisig_Wallet is_multisig = isinstance(self.wallet, Multisig_Wallet) can_delete = self.wallet.can_delete_address() selected = self.selectionModel().selectedRows() if not selected: return multi_select = len(selected) > 1 addr_items = [] for idx in selected: if not idx.isValid(): return addr_items.append(idx.internalPointer()) addrs = [addr_item['addr'] for addr_item in addr_items] menu = QMenu() if not multi_select: idx = self.indexAt(position) if not idx.isValid(): return col = idx.column() item = addr_items[0] if not item: return addr = item['addr'] is_ps = item['is_ps'] is_ps_ks = item['is_ps_ks'] hd = self.am.headerData addr_title = hd(AddrColumns.LABEL, None, Qt.DisplayRole) column_title = hd(col, None, Qt.DisplayRole) label_idx = idx.sibling(idx.row(), AddrColumns.LABEL) copy_text = str(self.am.data(idx, Qt.DisplayRole).value()) if col in [AddrColumns.COIN_BALANCE, AddrColumns.FIAT_BALANCE]: copy_text = copy_text.strip() menu.addAction(_("Copy {}").format(column_title), lambda: self.place_text_on_clipboard(copy_text)) menu.addAction(_('Details'), lambda: self.parent.show_address(addr)) persistent = QPersistentModelIndex(label_idx) menu.addAction(_("Edit {}").format(addr_title), lambda p=persistent: self.edit(QModelIndex(p))) if not is_ps and not is_ps_ks: menu.addAction(_("Request payment"), lambda: self.parent.receive_at(addr)) if self.wallet.can_export() or self.wallet.psman.is_ps_ks(addr): menu.addAction(_("Private key"), lambda: self.parent.show_private_key(addr)) if not is_multisig and not self.wallet.is_watching_only(): menu.addAction(_("Sign/verify message"), lambda: self.parent.sign_verify_message(addr)) menu.addAction(_("Encrypt/decrypt message"), lambda: self.parent.encrypt_message(addr)) if can_delete: menu.addAction(_("Remove from wallet"), lambda: self.parent.remove_address(addr)) addr_URL = block_explorer_URL(self.config, 'addr', addr) if addr_URL: menu.addAction(_("View on block explorer"), lambda: webopen(addr_URL)) if not is_ps: def set_frozen_state(addrs, state): self.parent.set_frozen_state_of_addresses(addrs, state) if not self.wallet.is_frozen_address(addr): menu.addAction(_("Freeze"), lambda: set_frozen_state([addr], True)) else: menu.addAction(_("Unfreeze"), lambda: set_frozen_state([addr], False)) coins = self.wallet.get_spendable_coins(addrs, config=self.config) if coins: menu.addAction(_("Spend from"), lambda: self.parent.spend_coins(coins)) run_hook('receive_menu', menu, addrs, self.wallet) menu.exec_(self.viewport().mapToGlobal(position))
def create_menu(self, position: QPoint): org_idx: QModelIndex = self.indexAt(position) idx = self.proxy.mapToSource(org_idx) if not idx.isValid(): # can happen e.g. before list is populated for the first time return tx_item = idx.internalPointer().get_data() if tx_item.get('lightning') and tx_item['type'] == 'payment': menu = QMenu() menu.addAction( _("View Payment"), lambda: self.parent.show_lightning_transaction(tx_item)) cc = self.add_copy_menu(menu, idx) cc.addAction( _("Payment Hash"), lambda: self.place_text_on_clipboard(tx_item['payment_hash'], title="Payment Hash")) cc.addAction( _("Preimage"), lambda: self.place_text_on_clipboard(tx_item['preimage'], title="Preimage")) key = tx_item['payment_hash'] log = self.wallet.lnworker.logs.get(key) if log: menu.addAction( _("View log"), lambda: self.parent.invoice_list.show_log(key, log)) menu.exec_(self.viewport().mapToGlobal(position)) return tx_hash = tx_item['txid'] if tx_item.get('lightning'): tx = self.wallet.lnworker.lnwatcher.db.get_transaction(tx_hash) else: tx = self.wallet.db.get_transaction(tx_hash) if not tx: return tx_URL = block_explorer_URL(self.config, 'tx', tx_hash) tx_details = self.wallet.get_tx_info(tx) is_unconfirmed = tx_details.tx_mined_status.height <= 0 menu = QMenu() if tx_details.can_remove: menu.addAction(_("Remove"), lambda: self.remove_local_tx(tx_hash)) cc = self.add_copy_menu(menu, idx) cc.addAction( _("Transaction ID"), lambda: self.place_text_on_clipboard(tx_hash, title="TXID")) for c in self.editable_columns: if self.isColumnHidden(c): continue label = self.hm.headerData(c, Qt.Horizontal, Qt.DisplayRole) # TODO use siblingAtColumn when min Qt version is >=5.11 persistent = QPersistentModelIndex( org_idx.sibling(org_idx.row(), c)) menu.addAction(_("Edit {}").format(label), lambda p=persistent: self.edit(QModelIndex(p))) menu.addAction(_("View Transaction"), lambda: self.show_transaction(tx_item, tx)) channel_id = tx_item.get('channel_id') if channel_id: menu.addAction( _("View Channel"), lambda: self.parent.show_channel(bytes.fromhex(channel_id))) if is_unconfirmed and tx: if tx_details.can_bump: menu.addAction(_("Increase fee"), lambda: self.parent.bump_fee_dialog(tx)) else: if tx_details.can_cpfp: menu.addAction(_("Child pays for parent"), lambda: self.parent.cpfp_dialog(tx)) if tx_details.can_dscancel: menu.addAction(_("Cancel (double-spend)"), lambda: self.parent.dscancel_dialog(tx)) invoices = self.wallet.get_relevant_invoices_for_tx(tx) if len(invoices) == 1: menu.addAction( _("View invoice"), lambda inv=invoices[0]: self.parent.show_onchain_invoice(inv)) elif len(invoices) > 1: menu_invs = menu.addMenu(_("Related invoices")) for inv in invoices: menu_invs.addAction( _("View invoice"), lambda inv=inv: self.parent.show_onchain_invoice(inv)) if tx_URL: menu.addAction(_("View on block explorer"), lambda: webopen(tx_URL)) menu.exec_(self.viewport().mapToGlobal(position))
def fillTable(self, init=False): try: if self.crs is None or self.crsLay is None: return if self.isHidden() and not init: return if self.debug: self.info.log("fillTable", "debug", self.debug) self.blockItemChange = True self.tblCoords.clear() self.tblCoords.setColumnCount(5) self.tblCoords.setHorizontalHeaderItem(0, QTableWidgetItem("X")) self.tblCoords.setHorizontalHeaderItem(1, QTableWidgetItem("Y")) self.tblCoords.setHorizontalHeaderItem(2, QTableWidgetItem("")) self.tblCoords.setHorizontalHeaderItem(3, QTableWidgetItem("Xr")) self.tblCoords.setHorizontalHeaderItem(4, QTableWidgetItem("Yr")) self.tblCoords.horizontalHeader().setSectionHidden(3, self.debug) # self.tblCoords.setColumnHidden(3, self.debug) self.tblCoords.setColumnHidden(4, self.debug) self.tblCoords.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) self.tblCoords.horizontalHeader().setSectionResizeMode( 2, QHeaderView.ResizeToContents) # QHeaderView.Fixed destCrs = self.crs self.canvas.refresh() if self.cboFeat.currentData(): feat = self.layer.getFeature(self.cboFeat.currentData()) geometry = feat.geometry() tr = QgsCoordinateTransform(self.crsLay, destCrs, self.prj) row = 0 column = 2 # btn column for v in geometry.vertices(): self.tblCoords.setRowCount(row + 1) if self.debug: self.info.log("vertex:", v.x(), v.y()) v.transform(tr) itemX = QTableWidgetItem(str(v.x())) self.tblCoords.setItem(row, 0, itemX) itemY = QTableWidgetItem(str(v.y())) self.tblCoords.setItem(row, 1, itemY) itemXr = QTableWidgetItem(str(v.x())) self.tblCoords.setItem(row, 3, itemXr) itemYr = QTableWidgetItem(str(v.y())) self.tblCoords.setItem(row, 4, itemYr) index = QPersistentModelIndex(self.tblCoords.model().index( row, column)) btn = MyButton(self.gtomain) btn.setIcon(self.icon) btn.click.connect(lambda *args, index=index: self. cellClick(index.row(), index.column())) btn.setEnabled(False) btn.setPixmap(self.icon.pixmap(24, 24)) self.tblCoords.setCellWidget(row, 2, btn) row = row + 1 if self.debug: self.info.log("vertex transformed:", v.x(), v.y()) self.reset() if geometry.type( ) == QgsWkbTypes.GeometryType.PolygonGeometry: # remove double vertex???? self.tblCoords.removeRow(self.tblCoords.rowCount() - 1) if self.isVisible(): self.setRubber() self.markedFeature = self.helper.markFeature( self.layer, feat) self.btnZoomTo.setEnabled(True) self.blockItemChange = False self.tblCoords.setCurrentCell(0, 0) else: self.reset() self.blockItemChange = False except Exception as e: self.info.err(e)
def prev(self): if self.current.row() == 0: return self.current = QPersistentModelIndex(self.current.sibling(self.current.row() - 1, 0)) self.updateImage()
def Save1VEZExcel(self, trig=1): i = 0 N = [] nm = [] lv = [] t = [] Pe1 = [] Pe2 = [] Pe = [] current_path = { 1: self.path_vez_excel, 2: self.path_ro_excel, 3: self.path_ro_word }[trig] try: fname = QFileDialog.getSaveFileName( self, 'Сохранить файл', current_path, '*.xlsx;;*.xls' if trig != 3 else '*.docx')[0] # Обрати внимание на последний элемент while self.ski.item(i): item = self.ski.item(i) if item.checkState(): modelindex = QPersistentModelIndex( self.ski.indexFromItem(item)) ind = self.d[modelindex] p = self.file_path[ind] if p != None: if self.arr[ind] == None: try: arr, st_arr = imagescan.Scan(p) except Exception: arr = None else: arr = self.arr[ind] else: arr = self.arr[ind] if arr != None and arr != []: if trig == 1: N.append(arr) nm.append(self.file_name[ind]) lv.append(self.arr_lv[ind] if self.arr_lv[ind] != self.lv_c else None) t.append(self.arr_t[ind] if self.arr_t[ind] != self.t_c else None) elif trig == 2 or trig == 3: try: pe1, pe2, pe = roo.RschRoo( arr, self.arr_lv[ind], self.arr_t[ind]) except Exception: 1 else: nm.append(self.file_name[ind]) lv.append(self.arr_lv[ind]) t.append(self.arr_t[ind]) Pe1.append(round(pe1, 2)) Pe2.append(round(pe2, 2)) Pe.append(round(pe, 2)) i += 1 if trig == 1: if fname != "": self.path_vez_excel = os.path.dirname(fname) xlsx.SaveFile1(fname, nm, N, lv, t) elif trig == 2: if fname != "": self.path_ro_excel = os.path.dirname(fname) xlsx.SaveFile2(fname, nm, Pe1, Pe2, Pe, lv, t) elif trig == 3: if fname != "": self.path_ro_word = os.path.dirname(fname) Word.Word(fname, nm, Pe, lv, t, self.NPrj.text(), self.NVL.text()) except Exception as ex: if str(ex) != "string index out of range": ems = QErrorMessage(self) ems.setWindowTitle('Возникла ошибка') ems.showMessage('Не получилось сгенерировать массив точек. ' + str(ex)) else: mes = QMessageBox.information(self, 'Генерация массива точек', 'Операция прошла успешно.', buttons=QMessageBox.Ok, defaultButton=QMessageBox.Ok)
def last(self): self.current = QPersistentModelIndex(self.current.sibling(self.total - 1, 0)) self.updateImage()
def presseditem(self, modelindex): self.adres = QPersistentModelIndex(modelindex)
def createEditor(self, parent, option, idx): self.opened = QPersistentModelIndex(idx) self.tv.is_editor_open = True return super().createEditor(parent, option, idx)
def create_menu(self, position): from electrum.wallet import Multisig_Wallet is_multisig = isinstance(self.wallet, Multisig_Wallet) can_delete = self.wallet.can_delete_address() selected = self.selected_in_column(self.Columns.ADDRESS) if not selected: return multi_select = len(selected) > 1 addrs = [self.model().itemFromIndex(item).text() for item in selected] menu = QMenu() if not multi_select: idx = self.indexAt(position) col = idx.column() item = self.model().itemFromIndex(idx) if not item: return addr = addrs[0] addr_column_title = self.model().horizontalHeaderItem( self.Columns.LABEL).text() addr_idx = idx.sibling(idx.row(), self.Columns.LABEL) column_title = self.model().horizontalHeaderItem(col).text() copy_text = self.model().itemFromIndex(idx).text() menu.addAction( _("Copy {}").format(column_title), lambda: self.place_text_on_clipboard(copy_text)) menu.addAction(_('Details'), lambda: self.parent.show_address(addr)) persistent = QPersistentModelIndex(addr_idx) menu.addAction(_("Edit {}").format(addr_column_title), lambda p=persistent: self.edit(QModelIndex(p))) menu.addAction(_("Request payment"), lambda: self.parent.receive_at(addr)) if self.wallet.can_export(): menu.addAction(_("Private key"), lambda: self.parent.show_private_key(addr)) if not is_multisig and not self.wallet.is_watching_only(): menu.addAction(_("Sign/verify message"), lambda: self.parent.sign_verify_message(addr)) menu.addAction(_("Encrypt/decrypt message"), lambda: self.parent.encrypt_message(addr)) if can_delete: menu.addAction(_("Remove from wallet"), lambda: self.parent.remove_address(addr)) addr_URL = block_explorer_URL(self.config, 'addr', addr) if addr_URL: menu.addAction(_("View on block explorer"), lambda: webbrowser.open(addr_URL)) if not self.wallet.is_frozen(addr): menu.addAction( _("Freeze"), lambda: self.parent.set_frozen_state([addr], True)) else: menu.addAction( _("Unfreeze"), lambda: self.parent.set_frozen_state([addr], False)) coins = self.wallet.get_utxos(addrs) if coins: menu.addAction(_("Spend from"), lambda: self.parent.spend_coins(coins)) run_hook('receive_menu', menu, addrs, self.wallet) menu.exec_(self.viewport().mapToGlobal(position))