def _menuAction_copy_evaluated_buffer(self, buffer_id): mime = QMimeData() buff = self.current_state.symbolic_buffers[buffer_id][0] res = self.current_state.solver.evaluate(buff).as_bytes() res = '"' + repr(res)[2:-1] + '"' mime.setText(res) QApplication.clipboard().setMimeData(mime)
def _copy_string(self, expr): mime = QMimeData() expr_bytes = split_bv_in_list(expr, 8) res = "" for el in reversed(expr_bytes): res += chr(el.value) if el.value >= 32 and el.value <= 126 else "." mime.setText(res) QApplication.clipboard().setMimeData(mime)
def _copy_little_endian(self, expr): mime = QMimeData() expr_bytes = split_bv_in_list(expr, 8) res = 0 i = 0 for el in reversed(expr_bytes): res += el.value << i * 8 i += 1 mime.setText(hex(res)) QApplication.clipboard().setMimeData(mime)
def _copy_binary(self, expr): mime = QMimeData() expr_bytes = split_bv_in_list(expr, 8) res = "\"" for el in reversed(expr_bytes): res += "\\x{:02x}".format(el.value) res += "\"" mime.setText(res) QApplication.clipboard().setMimeData(mime)
def startDrag(self, supportedActions): dragged = self.selectedItems()[0] mimeData = QMimeData() mimeData.setText(dragged.text(0)) drag = QDrag(self) drag.setMimeData(mimeData) drag.exec_(supportedActions=supportedActions, defaultAction=Qt.MoveAction)
class DragListView(QListView): """Custom QListView class with dragging support. Attributes: parent (QWidget): The parent of this view """ def __init__(self, parent): """Initialize the view.""" super().__init__(parent=parent) self.drag_start_pos = None self.pixmap = None self.mime_data = None def mousePressEvent(self, event): """Register drag start position""" super().mousePressEvent(event) if event.button() == Qt.LeftButton: index = self.indexAt(event.pos()) if not index.isValid() or not index.model().is_index_draggable( index): self.drag_start_pos = None self.pixmap = None self.mime_data = None return self.drag_start_pos = event.pos() self.pixmap = index.data(Qt.DecorationRole).pixmap(self.iconSize()) mime_data_text = self.model().get_mime_data_text(index) self.mime_data = QMimeData() self.mime_data.setText(mime_data_text) def mouseMoveEvent(self, event): """Start dragging action if needed""" if not event.buttons() & Qt.LeftButton: return if not self.drag_start_pos: return if (event.pos() - self.drag_start_pos ).manhattanLength() < QApplication.startDragDistance(): return drag = QDrag(self) drag.setPixmap(self.pixmap) drag.setMimeData(self.mime_data) drag.setHotSpot(self.pixmap.rect().center()) drag.exec_() self.drag_start_pos = None self.pixmap = None self.mime_data = None def mouseReleaseEvent(self, event): """Forget drag start position""" super().mouseReleaseEvent(event) self.drag_start_pos = None self.pixmap = None self.mime_data = None
def mimeData(self, indexes): file_ = self._table.database.file ids = [self._ids[r] for r in list({i.row() for i in indexes})] records = [self._table.GetRow(i) for i in ids] texkeys = [r["texkey"] for r in records if r["texkey"] is not None] data_list = [file_, ids, records] data = QMimeData() data.setData(self.mimeTypes()[0], QByteArray(json.dumps(data_list).encode("utf-8"))) data.setText(", ".join(texkeys)) return data
def mousePressEvent(self, event): # call to super needed for selections super().mousePressEvent(event) if event.button() == Qt.LeftButton: drag = QDrag(self) mimeData = QMimeData() item = self.itemAt(event.pos()) if item is None: return mimeData.setText(item.data(Qt.UserRole)[0]) # should be path to file drag.setMimeData(mimeData) # set dragging pixmap drag.setPixmap(item.icon().pixmap(QSize(160, 120))) # roughly center the cursor relative to pixmap drag.setHotSpot(QPoint(60, 60)) dropAction = drag.exec_()
def mouseMoveEvent(self, event): """Start dragging action if needed""" if not event.buttons() & Qt.LeftButton: return if not self.drag_start_pos: return if (event.pos() - self.drag_start_pos ).manhattanLength() < QApplication.startDragDistance(): return drag = QDrag(self) mimeData = QMimeData() mimeData.setText(self.text) drag.setMimeData(mimeData) drag.setPixmap(self.pixmap()) drag.setHotSpot(self.pixmap().rect().center()) dropAction = drag.exec_()
def mouseMoveEvent(self, event): if event.buttons() != Qt.LeftButton: return if (event.pos() - self._dragStartPosition ).manhattanLength() < QApplication.startDragDistance(): return pixmap = QPixmap(23, 23) pixmap.fill(self._color_srgb) drag = QDrag(self) mime_data = QMimeData() text = encode_index(self.parentWidget().index) mime_data.setText(text) drag.setMimeData(mime_data) drag.setPixmap(pixmap) drop_action = drag.start(Qt.CopyAction) # | Qt.MoveAction)
def mousePressEvent(self, event): label = self.childAt(event.pos()) if not label: return hot_spot = event.pos() - label.pos() mime_data = QMimeData() mime_data.setText(label.text()) mime_data.setData("application/x-hotspot", str(hot_spot.x())) pixmap = QPixmap(label.size()) label.render(pixmap) drag = QDrag(self) drag.setMimeData(mime_data) drag.setPixmap(pixmap) drag.setHotSpot(hot_spot) dropAction = drag.exec_(Qt.CopyAction | Qt.MoveAction, Qt.CopyAction) if dropAction == Qt.MoveAction: label.close()
def mimeData(self, indexes): """ Builds a dict mapping db name to item type to a list of ids. Returns: QMimeData """ items = {self.item_from_index(ind): None for ind in indexes} # NOTE: this avoids dupes and keeps order d = {} for item in items: parent_item = item.parent_item db_row = self.db_row(parent_item) parent_type = parent_item.item_type master_key = ";;".join([str(db_row), parent_type]) d.setdefault(master_key, []).append(item.child_number()) data = json.dumps(d) mime = QMimeData() mime.setText(data) return mime
def mousePressEvent(self, event): hotSpot = event.pos() mimeData = QMimeData() mimeData.setText(self.text()) mimeData.setData('application/x-hotspot', '%d %d' % (hotSpot.x(), hotSpot.y())) pixmap = QPixmap(self.size()) self.render(pixmap) drag = QDrag(self) drag.setMimeData(mimeData) drag.setPixmap(pixmap) drag.setHotSpot(hotSpot) dropAction = drag.exec_(Qt.CopyAction | Qt.MoveAction, Qt.CopyAction) if dropAction == Qt.MoveAction: self.close() self.update()
def mousePressEvent(self, event): hotSpot = event.pos() mimeData = QMimeData() mimeData.setText(self.text()) mimeData.setData('application/x-hotspot', b'%d %d' % (hotSpot.x(), hotSpot.y())) pixmap = QPixmap(self.size()) self.render(pixmap) drag = QDrag(self) drag.setMimeData(mimeData) drag.setPixmap(pixmap) drag.setHotSpot(hotSpot) dropAction = drag.exec_(Qt.CopyAction | Qt.MoveAction, Qt.CopyAction) if dropAction == Qt.MoveAction: self.close() self.update()
class ProjectItemButtonBase(ProjectItemDragMixin, QToolButton): def __init__(self, toolbox, icon, item_type, parent=None): super().__init__(parent=parent) self.item_type = item_type self.setIcon(icon) self.setMouseTracking(True) self.drag_about_to_start.connect(self._handle_drag_about_to_start) @Slot() def _handle_drag_about_to_start(self): self.setDown(False) self.update() def mousePressEvent(self, event): """Register drag start position""" super().mousePressEvent(event) if event.button() == Qt.LeftButton: self.drag_start_pos = event.pos() self.pixmap = self.icon().pixmap(self.iconSize()) self.mime_data = QMimeData() self.mime_data.setText(self._make_mime_data_text()) def _make_mime_data_text(self): raise NotImplementedError()
def test_drop_project_item_on_design_view(self): mime_data = QMimeData() item_type = next(iter(self.toolbox.item_factories)) mime_data.setText(f"{item_type},spec") gv = self.toolbox.ui.graphicsView scene_pos = QPointF(44, 20) pos = gv.mapFromScene(scene_pos) event = QDropEvent(pos, Qt.CopyAction, mime_data, Qt.NoButton, Qt.NoModifier) with mock.patch('PySide2.QtWidgets.QGraphicsSceneDragDropEvent.source' ) as mock_drop_event_source, mock.patch.object( self.toolbox, "project"), mock.patch.object( self.toolbox, "show_add_project_item_form" ) as mock_show_add_project_item_form: mock_drop_event_source.return_value = ProjectItemDragMixin() gv.dropEvent(event) mock_show_add_project_item_form.assert_called_once() mock_show_add_project_item_form.assert_called_with(item_type, scene_pos.x(), scene_pos.y(), spec="spec") item_shadow = gv.scene().item_shadow self.assertTrue(item_shadow.isVisible()) self.assertEqual(item_shadow.pos(), scene_pos)
def mimeData(self, indexes): result = QMimeData() item = self.itemFromIndex(indexes[0]) result.setText(str(item)) return result
def on_customContextMenuRequested(self, pos): item = self._table.itemAt(pos) if item is None: return row_idx = item.row() if self.index_to_reg[row_idx] == self.arch.getip_reg(): return expr = getattr(self.current_state.regs, self.index_to_reg[row_idx]) menu = QMenu() show_reg_expr = menu.addAction( "Show reg expression") if not isinstance(expr, BVV) else None make_reg_symb = menu.addAction("Make reg symbolic") if isinstance( expr, BVV) else None set_reg_value = menu.addAction("Set reg value") eval_with_sol = menu.addAction( "Evaluate with solver") if not isinstance(expr, BVV) else None eval_upto_with_sol = menu.addAction( "Evaluate upto with solver") if not isinstance(expr, BVV) else None concretize = menu.addAction("Concretize") if not isinstance( expr, BVV) else None copy = menu.addAction("Copy to clipboard") if not isinstance( expr, BVS) else None bind_to_buffer = menu.addAction("Bind to symbolic buffer") action = menu.exec_(self._table.viewport().mapToGlobal(pos)) if action is None: return if action == bind_to_buffer: buffer_names = [ b[0].name for b in self.current_state.symbolic_buffers ] if len(buffer_names) == 0: return buff_id = get_choice_input("Select a buffer", "choices", buffer_names) address = self.current_state.symbolic_buffers[buff_id][1] buff_p = BVV(address, self.current_state.arch.bits()) setattr(self.current_state.regs, self.index_to_reg[row_idx], buff_p) self.set_reg_value(self.index_to_reg[row_idx], buff_p, RegisterView.dirty_color) if action == show_reg_expr: show_message_box("Reg Expression", str(expr.z3obj.sexpr())) if action == make_reg_symb: new_expr = BVS('symb_injected_through_ui_%d' % self.symb_idx, expr.size) setattr(self.current_state.regs, self.index_to_reg[row_idx], new_expr) self.set_reg_value(self.index_to_reg[row_idx], new_expr, RegisterView.dirty_color) self.symb_idx += 1 if action == set_reg_value: self.on_doubleClick(item) if action == eval_with_sol: expr = getattr(self.current_state.regs, self.index_to_reg[row_idx]) if not self.current_state.solver.symbolic(expr): new_expr = self.current_state.solver.evaluate(expr) setattr(self.current_state.regs, self.index_to_reg[row_idx], new_expr) self.set_reg_value(self.index_to_reg[row_idx], new_expr, RegisterView.dirty_color) show_message_box( "Reg Value (with solver)", "The value was indeed concrete! State modified") else: show_message_box( "Reg Value (with solver)", hex(self.current_state.solver.evaluate(expr).value)) if action == eval_upto_with_sol: expr = getattr(self.current_state.regs, self.index_to_reg[row_idx]) if not self.current_state.solver.symbolic(expr): new_expr = self.current_state.solver.evaluate(expr) setattr(self.current_state.regs, self.index_to_reg[row_idx], new_expr) self.set_reg_value(self.index_to_reg[row_idx], new_expr, RegisterView.dirty_color) show_message_box( "Reg Value (with solver)", "The value was indeed concrete! State modified") else: n_eval = get_int_input("How many values (upto) ?", "Number of distinct values") r = "" for i, v in enumerate( self.current_state.solver.evaluate_upto(expr, n_eval)): r += "solution %d: %s\n" % (i, hex(v.value)) show_message_box("Reg Value (with solver)", r) if action == concretize: expr = getattr(self.current_state.regs, self.index_to_reg[row_idx]) new_expr = self.current_state.solver.evaluate(expr) res = get_choice_input( "Concretize %s to %s?" % (self.index_to_reg[row_idx], hex(new_expr.value)), "Concretize", ["Yes", "No"]) if res == 0: setattr(self.current_state.regs, self.index_to_reg[row_idx], new_expr) self.current_state.solver.add_constraints(expr == new_expr) self.set_reg_value(self.index_to_reg[row_idx], new_expr, RegisterView.dirty_color) if action == copy: mime = QMimeData() if isinstance(expr, BVV): mime.setText(hex(expr.value)) else: mime.setText(str(expr.z3obj.sexpr())) QApplication.clipboard().setMimeData(mime)
def itemCliked(self, item): drag = QDrag(self) mimeData = QMimeData() self.selected_project = item.text() mimeData.setText(item.text()) drag.setMimeData(mimeData)
def on_customContextMenuRequested(self, pos): item = self._table.itemAt(pos) if item is None: return row_idx = item.row() if self.index_to_reg[row_idx] == self.arch.getip_reg(): return expr = getattr(self.current_state.regs, self.index_to_reg[row_idx]) menu = QMenu() show_reg_expr = menu.addAction("Show reg expression") if not isinstance(expr, BVV) else None make_reg_symb = menu.addAction("Make reg symbolic") if not isinstance(expr, BVS) else None set_reg_value = menu.addAction("Set reg value") eval_with_sol = menu.addAction("Evaluate with solver") if not isinstance(expr, BVV) else None concretize = menu.addAction("Concretize") if not isinstance(expr, BVV) else None copy = menu.addAction("Copy to clipboard") if not isinstance(expr, BVS) else None action = menu.exec_(self._table.viewport().mapToGlobal(pos)) if action is None: return if action == show_reg_expr: show_message_box("Reg Expression", str(expr.z3obj)) if action == make_reg_symb: new_expr = BVS('symb_injected_through_ui_%d' % self.symb_idx, expr.size) setattr(self.current_state.regs, self.index_to_reg[row_idx], new_expr) self.set_reg_value(self.index_to_reg[row_idx], new_expr, RegisterView.dirty_color) self.symb_idx += 1 if action == set_reg_value: self.on_doubleClick(item) if action == eval_with_sol: expr = getattr(self.current_state.regs, self.index_to_reg[row_idx]) if not self.current_state.solver.symbolic(expr): new_expr = self.current_state.solver.evaluate(expr) setattr(self.current_state.regs, self.index_to_reg[row_idx], new_expr) self.set_reg_value(self.index_to_reg[row_idx], new_expr, RegisterView.dirty_color) show_message_box( "Reg Value (with solver)", "The value was indeed concrete! State modified" ) else: show_message_box( "Reg Value (with solver)", hex(self.current_state.solver.evaluate(expr).value) ) if action == concretize: expr = getattr(self.current_state.regs, self.index_to_reg[row_idx]) new_expr = self.current_state.solver.evaluate(expr) res = get_choice_input( "Concretize %s to %s?" % (self.index_to_reg[row_idx], hex(new_expr.value)), "Concretize", ["Yes", "No"] ) if res == 0: setattr(self.current_state.regs, self.index_to_reg[row_idx], new_expr) self.current_state.solver.add_constraints( expr == new_expr ) self.set_reg_value(self.index_to_reg[row_idx], new_expr, RegisterView.dirty_color) if action == copy: mime = QMimeData() mime.setText(hex(expr.value)) QApplication.clipboard().setMimeData(mime)
def _menuAction_copy_address(self, buffer_id): mime = QMimeData() mime.setText(hex(self.current_state.symbolic_buffers[buffer_id][1])) QApplication.clipboard().setMimeData(mime)
class ProjectItemDragListView(ProjectItemDragMixin, QListView): context_menu_requested = Signal("QModelIndex", "QPoint") def __init__(self): super().__init__(None) self._hover = True self._main_style_sheet = _VIEW_STYLE_SHEET self._hover_addendum = _VIEW_HOVER_STYLE_SHEET_ADDENDUM self.setStyleSheet(self._main_style_sheet + self._hover_addendum) self.setSelectionRectVisible(False) self.setResizeMode(QListView.Adjust) self.setUniformItemSizes(True) self.setMouseTracking(True) def _set_hover(self, hover): if hover == self._hover: return self._hover = hover style_sheet = self._main_style_sheet if hover: style_sheet += self._hover_addendum self.setStyleSheet(style_sheet) def hideEvent(self, event): super().hideEvent(event) self._set_hover(False) def mouseMoveEvent(self, event): if self.indexAt(event.pos()).isValid(): self._set_hover(True) super().mouseMoveEvent(event) def paintEvent(self, event): self.setCurrentIndex(QModelIndex()) super().paintEvent(event) def contextMenuEvent(self, event): index = self.indexAt(event.pos()) if not index.isValid(): return source_index = self.model().mapToSource(index) self.context_menu_requested.emit(source_index, event.globalPos()) def mousePressEvent(self, event): """Register drag start position""" super().mousePressEvent(event) if event.button() == Qt.LeftButton: index = self.indexAt(event.pos()) if not index.isValid(): self.drag_start_pos = None self.pixmap = None self.mime_data = None return self.drag_start_pos = event.pos() self.pixmap = index.data(Qt.DecorationRole).pixmap(self.iconSize()) mime_data_text = self.model().get_mime_data_text(index) self.mime_data = QMimeData() self.mime_data.setText(mime_data_text) def _set_preferred_heigth(self): model = self.model() if not model: self.setFixedHeight(0) return height = self.visualRect(model.index( 0, 0)).height() * model.rowCount() + 2 * self.frameWidth() self.setFixedHeight(height) def _get_preferred_width(self): return self.sizeHintForColumn(0) + 2 * self.frameWidth()
class ProjectItemButton(ProjectItemDragMixin, QToolButton): def __init__(self, toolbox, icon, item_type, supports_specs, parent=None): super().__init__(parent=parent) self._toolbox = toolbox self.item_type = item_type self.setIcon(icon) self.setMouseTracking(True) self.setToolTip( f"<p>Drag-and-drop this onto the Design View to create a new <b>{item_type}</b> item.</p>" ) if not supports_specs: self._list_view = None return self._list_view = ProjectItemDragListView() self._list_view.doubleClicked.connect(self._toolbox.edit_specification) self._list_view.context_menu_requested.connect( self._toolbox.show_specification_context_menu) self._list_widget = CreateNewSpecListWidget(item_type) self._list_widget.itemClicked.connect( lambda _, item_type=item_type: self._toolbox. show_specification_form(item_type)) menu = QMenu(self) widget_action = CustomWidgetAction(menu) widget_action.setDefaultWidget(self._list_view) menu.addAction(widget_action) widget_action = CustomWidgetAction(menu) widget_action.setDefaultWidget(self._list_widget) menu.addAction(widget_action) menu.setStyleSheet(f"QMenu{{background: {ICON_BACKGROUND};}}") self.setMenu(menu) self.setPopupMode(QToolButton.MenuButtonPopup) self.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self._resize() model = self._toolbox.filtered_spec_factory_models.get(self.item_type) self._list_view.setModel(model) model.rowsInserted.connect(lambda *args: self._resize()) model.rowsRemoved.connect(lambda *args: self._resize()) self.drag_about_to_start.connect(self._handle_drag_about_to_start) self._list_view.drag_about_to_start.connect(menu.hide) def setIconSize(self, size): super().setIconSize(size) if self._list_view: self._list_view.setIconSize(size) def _resize(self): self._list_view._set_preferred_heigth() self._list_widget._set_preferred_heigth() width = max(self._list_view._get_preferred_width(), self._list_widget._get_preferred_width()) self._list_view.setFixedWidth(width) self._list_widget.setFixedWidth(width) event = QResizeEvent(QSize(), self.menu().size()) QApplication.sendEvent(self.menu(), event) @Slot() def _handle_drag_about_to_start(self): self.setDown(False) self.update() def mousePressEvent(self, event): """Register drag start position""" super().mousePressEvent(event) if event.button() == Qt.LeftButton: self.drag_start_pos = event.pos() self.pixmap = self.icon().pixmap(self.iconSize()) mime_data_text = ",".join([self.item_type, ""]) self.mime_data = QMimeData() self.mime_data.setText(mime_data_text)
def _copy_big_endian(self, expr): mime = QMimeData() mime.setText(hex(expr.value)) QApplication.clipboard().setMimeData(mime)
def _copy_expression(self, expr): mime = QMimeData() mime.setText(str(expr.z3obj.sexpr())) QApplication.clipboard().setMimeData(mime)