-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDownloadableImage.py
More file actions
141 lines (111 loc) · 3.99 KB
/
DownloadableImage.py
File metadata and controls
141 lines (111 loc) · 3.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# widgets/DownloadableImage.py
import os
from PySide6.QtWidgets import (
QWidget, QFileDialog, QDialog, QVBoxLayout, QHBoxLayout,
QLabel, QPushButton, QButtonGroup, QRadioButton
)
from PySide6.QtGui import QPixmap, QPainter, QColor, QFont, QIcon, QImage
from PySide6.QtCore import Qt, QSize
class ResolutionDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("Export Resolution")
self.setMinimumWidth(260)
layout = QVBoxLayout(self)
layout.addWidget(QLabel("Select export resolution:"))
self.group = QButtonGroup(self)
r1 = QRadioButton("1× Normal")
r2 = QRadioButton("2× High")
r3 = QRadioButton("4× Ultra")
self.group.addButton(r1, 1)
self.group.addButton(r2, 2)
self.group.addButton(r3, 4)
r2.setChecked(True)
layout.addWidget(r1)
layout.addWidget(r2)
layout.addWidget(r3)
btns = QHBoxLayout()
ok = QPushButton("OK")
cancel = QPushButton("Cancel")
ok.clicked.connect(self.accept)
cancel.clicked.connect(self.reject)
btns.addWidget(ok)
btns.addWidget(cancel)
layout.addLayout(btns)
def selected_scale(self):
return self.group.checkedId()
class DownloadableImage(QWidget):
"""
Auto-fits image to parent width.
No horizontal scroll.
Hover overlay for download.
"""
def __init__(self, qimage: QImage, default_name="image.png", parent=None):
super().__init__(parent)
self.qimage = qimage
self.default_name = default_name
# Original HD pixmap
self.full_pixmap = QPixmap.fromImage(qimage)
# Display pixmap (scaled DOWN only)
self.display_pixmap = self.full_pixmap
self.hover = False
self.setMouseTracking(True)
self.icon = QIcon.fromTheme("download")
def resizeEvent(self, event):
"""
Always scale DOWN to fit width, never scale up.
Ensures no horizontal scroll AND crisp image.
"""
if not self.full_pixmap.isNull():
target_width = min(self.width(), self.full_pixmap.width())
self.display_pixmap = self.full_pixmap.scaledToWidth(
target_width, Qt.SmoothTransformation
)
self.setMinimumHeight(self.display_pixmap.height())
super().resizeEvent(event)
def enterEvent(self, event):
self.hover = True
self.update()
def leaveEvent(self, event):
self.hover = False
self.update()
def mousePressEvent(self, event):
if self.hover:
self.save_image()
def paintEvent(self, event):
painter = QPainter(self)
if not self.display_pixmap.isNull():
painter.drawPixmap(0, 0, self.display_pixmap)
if self.hover:
painter.fillRect(self.rect(), QColor(0, 0, 0, 120))
icon_size = 48
x = (self.width() - icon_size) // 2
y = (self.height() - icon_size) // 2
if not self.icon.isNull():
self.icon.paint(painter, x, y, icon_size, icon_size)
else:
painter.setPen(Qt.white)
painter.setFont(QFont("Segoe UI", 24))
painter.drawText(self.rect(), Qt.AlignCenter, "⬇")
def sizeHint(self):
return QSize(
self.display_pixmap.width(),
self.display_pixmap.height()
)
def save_image(self):
dlg = ResolutionDialog(self)
if dlg.exec() != QDialog.Accepted:
return
scale = dlg.selected_scale()
path, _ = QFileDialog.getSaveFileName(
self, "Save Image", self.default_name, "PNG Files (*.png)"
)
if not path:
return
export = self.qimage.scaled(
self.qimage.width() * scale,
self.qimage.height() * scale,
Qt.KeepAspectRatio,
Qt.SmoothTransformation
)
export.save(path, "PNG")