-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathytsage_gui_format_table.py
328 lines (277 loc) · 13.3 KB
/
ytsage_gui_format_table.py
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
QHBoxLayout, QLineEdit, QPushButton, QTableWidget,
QTableWidgetItem, QProgressBar, QLabel, QFileDialog,
QHeaderView, QStyle, QStyleFactory, QComboBox, QTextEdit,
QDialog, QPlainTextEdit, QCheckBox, QButtonGroup, QScrollArea,
QSizePolicy)
from PySide6.QtCore import Qt, Signal, QObject, QThread
from PySide6.QtGui import QIcon, QPalette, QColor, QPixmap
class FormatSignals(QObject):
format_update = Signal(list)
class FormatTableMixin:
def setup_format_table(self):
self.format_signals = FormatSignals()
# Format table with improved styling
self.format_table = QTableWidget()
self.format_table.setColumnCount(8)
self.format_table.setHorizontalHeaderLabels(['Select', 'Quality', 'Extension', 'Resolution', 'File Size', 'Codec', 'Audio', 'Notes'])
# Set specific column widths and resize modes
self.format_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeMode.Fixed) # Select
self.format_table.setColumnWidth(0, 50) # Select column width
self.format_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeMode.Fixed) # Quality
self.format_table.setColumnWidth(1, 100) # Quality width
self.format_table.horizontalHeader().setSectionResizeMode(2, QHeaderView.ResizeMode.Fixed) # Extension
self.format_table.setColumnWidth(2, 80) # Extension width
self.format_table.horizontalHeader().setSectionResizeMode(3, QHeaderView.ResizeMode.Fixed) # Resolution
self.format_table.setColumnWidth(3, 100) # Resolution width
self.format_table.horizontalHeader().setSectionResizeMode(4, QHeaderView.ResizeMode.Fixed) # File Size
self.format_table.setColumnWidth(4, 100) # File Size width
self.format_table.horizontalHeader().setSectionResizeMode(5, QHeaderView.ResizeMode.Fixed) # Codec
self.format_table.setColumnWidth(5, 150) # Codec width
self.format_table.horizontalHeader().setSectionResizeMode(6, QHeaderView.ResizeMode.Fixed) # Audio
self.format_table.setColumnWidth(6, 120) # Audio width
self.format_table.horizontalHeader().setSectionResizeMode(7, QHeaderView.ResizeMode.Stretch) # Notes (will stretch)
# Set vertical header (row numbers) visible to false
self.format_table.verticalHeader().setVisible(False)
# Set selection mode to no selection (since we're using checkboxes)
self.format_table.setSelectionMode(QTableWidget.SelectionMode.NoSelection)
self.format_table.setStyleSheet("""
QTableWidget {
background-color: #363636;
border: 2px solid #3d3d3d;
border-radius: 4px;
gridline-color: #3d3d3d;
}
QTableWidget::item {
padding: 5px;
border-bottom: 1px solid #3d3d3d;
}
QTableWidget::item:selected {
background-color: transparent;
}
QHeaderView::section {
background-color: #2b2b2b;
padding: 5px;
border: 1px solid #3d3d3d;
font-weight: bold;
color: white;
}
QCheckBox::indicator {
width: 16px;
height: 16px;
border-radius: 8px;
}
QCheckBox::indicator:unchecked {
border: 2px solid #666666;
background: #2b2b2b;
}
QCheckBox::indicator:checked {
border: 2px solid #ff0000;
background: #ff0000;
}
QWidget {
background-color: transparent;
}
""")
# Store format checkboxes and formats
self.format_checkboxes = []
self.all_formats = []
# Set table size policies
self.format_table.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
# Set minimum and maximum heights
self.format_table.setMinimumHeight(200)
# Connect the signal
self.format_signals.format_update.connect(self._update_format_table)
return self.format_table
def filter_formats(self):
if not hasattr(self, 'all_formats'):
return
# Clear current table
self.format_table.setRowCount(0)
self.format_checkboxes.clear()
# Determine which formats to show
filtered_formats = []
if hasattr(self, 'video_button') and self.video_button.isChecked():
filtered_formats.extend([f for f in self.all_formats
if f.get('vcodec') != 'none'
and f.get('filesize') is not None])
if hasattr(self, 'audio_button') and self.audio_button.isChecked():
filtered_formats.extend([f for f in self.all_formats
if (f.get('vcodec') == 'none'
or 'audio only' in f.get('format_note', '').lower())
and f.get('acodec') != 'none'
and f.get('filesize') is not None])
# Sort formats by quality
def get_quality(f):
if f.get('vcodec') != 'none':
res = f.get('resolution', '0x0').split('x')[-1]
try:
return int(res)
except ValueError:
return 0
else:
return f.get('abr', 0)
filtered_formats.sort(key=get_quality, reverse=True)
# Update table with filtered formats
self.format_signals.format_update.emit(filtered_formats)
def _update_format_table(self, formats):
self.format_table.setRowCount(0)
self.format_checkboxes.clear()
# Find best quality format for recommendations
best_video_size = max((f.get('filesize', 0) for f in formats if f.get('vcodec') != 'none'), default=0)
for f in formats:
row = self.format_table.rowCount()
self.format_table.insertRow(row)
# Add checkbox
checkbox = QCheckBox()
checkbox.format_id = str(f.get('format_id', ''))
checkbox.clicked.connect(lambda checked, cb=checkbox: self.handle_checkbox_click(cb))
self.format_checkboxes.append(checkbox)
# Create a widget to center the checkbox
checkbox_widget = QWidget()
checkbox_widget.setStyleSheet("background-color: transparent;")
checkbox_layout = QHBoxLayout(checkbox_widget)
checkbox_layout.addWidget(checkbox)
checkbox_layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
checkbox_layout.setContentsMargins(0, 0, 0, 0)
checkbox_layout.setSpacing(0)
self.format_table.setCellWidget(row, 0, checkbox_widget)
# Quality (replacing Format ID)
quality_text = self.get_quality_label(f)
quality_item = QTableWidgetItem(quality_text)
# Set color based on quality
if "Best" in quality_text:
quality_item.setForeground(QColor('#00ff00')) # Green for best quality
elif "High" in quality_text:
quality_item.setForeground(QColor('#00cc00')) # Light green for high quality
elif "Medium" in quality_text:
quality_item.setForeground(QColor('#ffaa00')) # Orange for medium quality
elif "Low" in quality_text:
quality_item.setForeground(QColor('#ff5555')) # Red for low quality
self.format_table.setItem(row, 1, quality_item)
# Extension
self.format_table.setItem(row, 2, QTableWidgetItem(f.get('ext', '').upper()))
# Resolution
resolution = f.get('resolution', 'N/A')
if f.get('vcodec') == 'none':
resolution = 'Audio only'
self.format_table.setItem(row, 3, QTableWidgetItem(resolution))
# File Size
filesize = f"{f.get('filesize', 0) / 1024 / 1024:.2f} MB"
self.format_table.setItem(row, 4, QTableWidgetItem(filesize))
# Codec
if f.get('vcodec') == 'none':
codec = f.get('acodec', 'N/A')
else:
codec = f"{f.get('vcodec', 'N/A')}"
if f.get('acodec') != 'none':
codec += f" / {f.get('acodec', 'N/A')}"
self.format_table.setItem(row, 5, QTableWidgetItem(codec))
# Audio Status
needs_audio = f.get('acodec') == 'none'
audio_status = "Will merge audio" if needs_audio else "✓ Has Audio"
audio_item = QTableWidgetItem(audio_status)
if needs_audio:
audio_item.setForeground(QColor('#ffa500'))
self.format_table.setItem(row, 6, audio_item)
# Add Notes column
notes = self.get_format_notes(f, best_video_size)
notes_item = QTableWidgetItem(notes)
if "✨ Recommended" in notes:
notes_item.setForeground(QColor('#00ff00')) # Green for recommended
elif "💾 Storage friendly" in notes:
notes_item.setForeground(QColor('#00ccff')) # Blue for storage friendly
elif "📱 Mobile friendly" in notes:
notes_item.setForeground(QColor('#ff9900')) # Orange for mobile
self.format_table.setItem(row, 7, notes_item)
def handle_checkbox_click(self, clicked_checkbox):
for checkbox in self.format_checkboxes:
if checkbox != clicked_checkbox:
checkbox.setChecked(False)
def get_selected_format(self):
for checkbox in self.format_checkboxes:
if checkbox.isChecked():
return checkbox.format_id
return None
def update_format_table(self, formats):
self.all_formats = formats
self.format_signals.format_update.emit(formats)
def get_quality_label(self, format_info):
"""Determine quality label based on format information"""
if format_info.get('vcodec') == 'none':
# Audio quality
abr = format_info.get('abr', 0)
if abr >= 256:
return "Best Audio"
elif abr >= 192:
return "High Audio"
elif abr >= 128:
return "Medium Audio"
else:
return "Low Audio"
else:
# Video quality
height = 0
resolution = format_info.get('resolution', '')
if resolution:
try:
height = int(resolution.split('x')[1])
except:
pass
if height >= 2160:
return "Best (4K)"
elif height >= 1440:
return "Best (2K)"
elif height >= 1080:
return "High (1080p)"
elif height >= 720:
return "High (720p)"
elif height >= 480:
return "Medium (480p)"
else:
return "Low Quality"
def get_format_notes(self, format_info, best_video_size):
"""Generate helpful notes about the format"""
if format_info.get('vcodec') == 'none':
# Audio format
abr = format_info.get('abr', 0)
if abr >= 256:
return "✨ Recommended for music"
elif abr >= 128:
return "📱 Mobile friendly"
return "💾 Storage friendly"
else:
# Video format
height = 0
resolution = format_info.get('resolution', '')
if resolution:
try:
height = int(resolution.split('x')[1])
except:
pass
filesize = format_info.get('filesize', 0)
notes = []
# Resolution-based recommendations
if height >= 1440: # 2K or 4K
if filesize == best_video_size:
notes.append("✨ Recommended for high-end displays")
else:
notes.append("🖥️ Best for large screens")
elif height == 1080:
if 'avc1' in format_info.get('vcodec', '').lower():
notes.append("✨ Recommended for most devices")
else:
notes.append("👍 Good balance")
elif height == 720:
notes.append("📱 Mobile friendly")
else:
notes.append("💾 Storage friendly")
# Codec-based notes
if 'av1' in format_info.get('vcodec', '').lower():
notes.append("Better compression")
elif 'vp9' in format_info.get('vcodec', '').lower():
notes.append("Good for Chrome")
# File size note for large files
if filesize > 100 * 1024 * 1024: # More than 100MB
notes.append("Large file")
return " • ".join(notes)