class Category(QWidget): def __init__(self, name, categoryTotal, transactions, state): ## initialCollapsed = True ## QWidget.__init__(self) self.name = name self.state = state self.transactions = [] self.categoryTotal = categoryTotal self.collapsed = initialCollapsed self.sectionLayout = QVBoxLayout() self.gridContainer = QWidget() self.transactionArea = QScrollArea() self.progressBar = ProgressBar() self.addHeader() self.addBody(transactions) self.setLayout(self.sectionLayout) self.setAcceptDrops(True) def addHeader(self): self.headerText = QLabel() self.headerText.setText(self.name) # self.headerText.setFont(self.boldFont) self.headerText.setCursor(Qt.PointingHandCursor) self.headerText.mousePressEvent = self.toggleCollapsed self.headerText.setMinimumWidth(100) self.collapseButton = QLabel() self.collapseButton.setText('⊞' if self.collapsed else '⊟') self.collapseButton.setMaximumWidth(12) self.collapseButton.setCursor(Qt.PointingHandCursor) self.collapseButton.setToolTip('collapse') self.collapseButton.mousePressEvent = self.toggleCollapsed self.progressBar = ProgressBar(self.name == 'Income') self.progressBar.setCursor(Qt.PointingHandCursor) self.progressBar.mousePressEvent = lambda event: self.promptEditVal( self.name, self.categoryTotal) self.progressBar.setToolTip('Edit Max') self.uncategorizedAmtDisplay = QLabel() self.uncategorizedAmtDisplay.setText('${:.2f}'.format( self.categoryTotal)) self.uncategorizedAmtDisplay.setAlignment(Qt.AlignRight | Qt.AlignVCenter) header = QHBoxLayout() header.addWidget(self.collapseButton) header.addWidget(self.headerText) if self.name != 'Uncategorized': header.addWidget(self.progressBar) if self.name != 'Income': self.headerText.setContextMenuPolicy(Qt.CustomContextMenu) self.connect( self.headerText, SIGNAL('customContextMenuRequested(const QPoint &)'), self.titleContextMenu) else: header.addWidget(self.uncategorizedAmtDisplay) self.sectionLayout.addLayout(header) def addBody(self, transactions): self.transactionGrid = QVBoxLayout() self.addTransactions(transactions) def addTransactions(self, transactions): self.transactions += transactions clearLayout(self.transactionGrid) self.transactionGrid = QVBoxLayout() self.transactions.sort(key=lambda t: t.date) for idx, transaction in enumerate(self.transactions): line = TransactionLine(transaction) line.setContextMenuPolicy(Qt.CustomContextMenu) self.connect(line, SIGNAL('customContextMenuRequested(const QPoint &)'), lambda event, t=line: self.lineContextMenu(t)) line.adjustSize() self.transactionGrid.addWidget(line) self.gridContainer.deleteLater() self.gridContainer = QWidget() self.gridContainer.setLayout(self.transactionGrid) self.transactionArea.deleteLater() self.transactionArea.setParent(None) self.transactionArea = QScrollArea() self.transactionArea.setWidget(self.gridContainer) self.transactionArea.setWidgetResizable(True) if self.collapsed: self.transactionArea.hide() self.sectionLayout.addWidget(self.transactionArea) self.sectionLayout.setMargin(0) self.updateAmtDisplay() # if self.name != 'Uncategorized': # self.toggleCollapsed(None) def removeTransaction(self, transaction): newTransactions = self.transactions newTransactions.remove(transaction) self.transactions = [] self.addTransactions(newTransactions) def updateAmtDisplay(self): totalAmount = 0 if len(self.transactions): for idx, transaction in enumerate(self.transactions): totalAmount += float(transaction.amt) if self.name == 'Uncategorized': self.uncategorizedAmtDisplay.setText('$' + str(totalAmount)) else: self.progressBar.updateValues(self.categoryTotal, totalAmount) def lineContextMenu(self, transactionLine): menu = QMenu(self) editAction = QAction('Edit Transaction Name') # editAction.triggered.connect(lambda evt: self.editTransaction(transactionLine)) menu.addAction(editAction) menu.exec_(QCursor.pos()) def titleContextMenu(self, event): menu = QMenu(self) editAction = QAction('Edit Name') editAction.triggered.connect(self.promptEditTitle) removeAction = QAction('Remove Category') removeAction.triggered.connect(self.removeCategory) menu.addAction(editAction) menu.addAction(removeAction) menu.exec_(QCursor.pos()) def toggleCollapsed(self, event): if not event or event.button() == Qt.MouseButton.LeftButton: self.collapsed = not self.collapsed if self.collapsed: self.collapseButton.setText('⊞') self.transactionArea.hide() self.collapseButton.setToolTip('expand') else: self.collapseButton.setText('⊟') self.transactionArea.show() self.collapseButton.setToolTip('collapse') def dragEnterEvent(self, event): if event.mimeData().hasText() and self.name != 'Income': event.setDropAction(Qt.CopyAction) event.accept() else: event.ignore() def dropEvent(self, event): if event.mimeData().hasText(): transactionTitle = event.mimeData().text() self.state.next(Events.transaction_drop_event, transactionTitle, self.name) def getTransactions(self): return self.transactions def removeCategory(self): self.state.next(Events.remove_category, self.name, self.transactions) def promptEditVal(self, title, currentAmount): modal = EditCategoryTotalModal() data = modal.getData(currentAmount) if data: self.state.next(Events.update_category_total, self.name, int(data)) self.categoryTotal = int(data) self.updateAmtDisplay() def promptEditTitle(self): modal = EditTextModal(self.name, 'Edit Title') data = modal.getData() if data: self.state.next(Events.update_category_title, self.name, data) self.name = data self.headerText.setText(self.name)
class SlideShow(QObject): current_index_changed = Signal(int) clicked = Signal() key_pressed = Signal(QEvent) def __init__(self, parent, base_widget, is_animated=True): QObject.__init__(self, parent) self._base_widget = base_widget # has to be stacked widget self._is_animated = is_animated self._slides_count = self._base_widget.count() self._scroll_area = QScrollArea(parent) self._scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self._scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self._scroll_area.setFrameShape(QFrame.NoFrame) self._scroll_area.mouseReleaseEvent = self._on_mouse_release_event self._scroll_area.keyPressEvent = self._on_key_pressed self._slide_width = None self._current_index = 0 self._is_moving = False self._orig_resize_event = self._base_widget.resizeEvent self._base_widget.resizeEvent = self._resizeEvent self._animation_time = 300 self._animation_steps = 50 def _construct_ribbon(self): self._ribbon = QWidget() self._layout = QHBoxLayout() self._ribbon.setLayout(self._layout) x = 0 for i in range(self._slides_count): self._base_widget.setCurrentIndex(i) widget = self._base_widget.currentWidget() if widget: new_widget = self._grab(widget) self._layout.addWidget(new_widget) x += self._slide_width def _grab(self, widget): new_widget = QLabel() pixmap = widget.grab() new_widget.setPixmap(pixmap) return new_widget def _resizeEvent(self, *args, **kwargs): self._orig_resize_event(*args, **kwargs) if not self._slide_width: self._scroll_area.setGeometry(self._base_widget.geometry()) self._slide_width = self._base_widget.widget(0).width() QTimer.singleShot(50, self._show) def _show(self): self._construct_ribbon() self._scroll_area.setWidget(self._ribbon) self._scroll_area.setAlignment(Qt.AlignCenter) self._scroll_area.show() self._scroll_area.setFocus() def _on_mouse_release_event(self, ev): self.clicked.emit() def _on_key_pressed(self, ev): self.key_pressed.emit(ev) def setAnimated(self, is_animated, animation_time=None, animation_steps=None): self._is_animated = is_animated if animation_time: self._animation_time = animation_time if animation_steps: self._animation_steps = animation_steps def is_moving(self): return self._is_moving def setCurrentIndex(self, new_index): new_index = max(new_index, 0) new_index = min(new_index, self._slides_count - 1) if new_index == self._current_index or self._is_moving: return is_animated = self._is_animated and \ abs(self._current_index - new_index) == 1 self._move(new_index, is_animated) def _move(self, new_index, is_animated): self._is_moving = True source_x = self._current_index * self._slide_width target_x = new_index * self._slide_width if not is_animated: dx = target_x - source_x self._ribbon.scroll(-dx, 0) self._finish_moving(new_index) else: animation_interval = self._animation_time // self._animation_steps dx = (target_x - source_x) // self._animation_steps self._move_animated(source_x, target_x, dx, animation_interval, new_index) def _move_animated(self, source_x, target_x, dx, animation_interval, new_index): if target_x == source_x: self._finish_moving(new_index) return if target_x > source_x: dx = min(dx, target_x - source_x) else: dx = -min(-dx, source_x - target_x) self._ribbon.scroll(-dx, 0) source_x += dx QTimer.singleShot( animation_interval, lambda: self._move_animated( source_x, target_x, dx, animation_interval, new_index)) def _finish_moving(self, new_index): self._current_index = new_index self.current_index_changed.emit(self._current_index) self._is_moving = False def widget(self): return self._scroll_area
for x in range(im.width()): for y in range(im.height()): if x % 2 == 0: im.setPixel(x, y, QColor('white').rgb()) else: im.setPixel(x, y, QColor('black').rgb()) # im.setPixel(x, y, QColor(255, x*2.56, y*2.56, 255).rgb()) im.save('test.png') if __name__ == "__main__": app = QApplication(sys.argv) window = IconEditor() img = QImage() if img.load("./mouse.png"): print('Image loaded successfully') window.setIconImage(img) else: print('Failed to load mouse.png image') # window.show() scrollArea = QScrollArea() scrollArea.setWidget(window) scrollArea.viewport().setBackgroundRole(QPalette.Dark) scrollArea.viewport().setAutoFillBackground(True) scrollArea.setWindowTitle("Icon Editor") scrollArea.show() # testImage() sys.exit(app.exec_())