Skip to content

Commit

Permalink
Merge branch 'unstable' into stable
Browse files Browse the repository at this point in the history
  • Loading branch information
JacobDev1 committed Nov 22, 2023
2 parents 2b08477 + a303956 commit d28690f
Show file tree
Hide file tree
Showing 31 changed files with 572 additions and 282 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bin/* linguist-vendored
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ build
dist
.vscode
__pycache__
tmp.py
tmp.py
env
4 changes: 2 additions & 2 deletions AboutTab.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from VARIABLES import VERSION
from VARIABLES import VERSION, LICENSE_PATH, LICENSE_3RD_PARTY_PATH
from UpdateChecker import UpdateChecker

from PySide6.QtWidgets import(
Expand Down Expand Up @@ -28,7 +28,7 @@ def __init__(self):
self.update_checker = UpdateChecker()

# Label
credits_l = QLabel(f"<h3>XL Converter</h3>Version {VERSION}<br>[email protected]<br>XL Converter is licensed under <a href=\"LICENSE.txt\">GPL v3</a><br><a href=\"LICENSE_3RD_PARTY.txt\">3rd party licenses")
credits_l = QLabel(f"<h3>XL Converter</h3>Version {VERSION}<br>[email protected]<br>XL Converter is licensed under <a href=\"{QUrl.fromLocalFile(LICENSE_PATH).toString()}\">GPL v3</a><br><a href=\"{QUrl.fromLocalFile(LICENSE_3RD_PARTY_PATH).toString()}\">3rd party licenses")
credits_l.setAlignment(Qt.AlignCenter)
credits_l.setOpenExternalLinks(True)

Expand Down
4 changes: 2 additions & 2 deletions Conflicts.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ def checkForConflicts(self, ext, _format, int_e, effort, downscaling):
self.jxl_int_e = False
self.jxl_e = 7
self.jxl_conflict = True
self.conflict_msg.append(f"Intelligent effort is not available for {_format} - defaulted to 7")
self.conflict_msg.append(f"Intelligent effort is not compatible with {ext.upper()} - defaulted to 7")
elif effort > 7: # Efforts bigger than 7 cause the encoder to crash while processing APNGs
self.jxl_e = 7
self.jxl_conflict = True
self.conflict_msg.append(f"Effort bigger than 7 is not available for {_format} - defaulted to 7")
self.conflict_msg.append(f"Efforts bigger than 7 are not compatible with {ext.upper()} - defaulted to 7")

# Downscaling
if downscaling:
Expand Down
13 changes: 9 additions & 4 deletions Data.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,21 @@ def getTimeRemaining(self):

# Extrapolate
remaining = (self.getItemCount() - self.getCompletedItemCount()) * mean(self.completion_times)
h = int(remaining / 3600)
m = int((remaining / 60) % 60)
d = int(remaining / (3600 * 24))
h = int((remaining // 3600) % 24)
m = int((remaining // 60) % 60)
s = int(remaining % 60)

output = ""
if d: output += f"{d} d "
if h: output += f"{h} h "
if m: output += f"{m} m "
if s: output += f"{s} s"
if output == "": output += "0 s"
output += " left"

if output == "":
output = "Almost done..."
else:
output += " left"

return output

Expand Down
153 changes: 92 additions & 61 deletions FileView.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
QTreeWidget,
QAbstractItemView,
QTreeWidgetItem,
QWidget
QWidget,
)

from PySide6.QtCore import(
Expand All @@ -27,11 +27,12 @@ def __init__(self, parent):
self.setDragDropMode(QAbstractItemView.InternalMove) # Required for dropEvent to fire
self.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.sortByColumn(1, Qt.SortOrder.DescendingOrder)

def addItem(self, *fields):
self.addTopLevelItem(QTreeWidgetItem(None, (fields[0],fields[1],fields[2])))

def beforeAddingItems(self):
# Adding items
def addItems(self, items):
self.invisibleRootItem().addChildren([QTreeWidgetItem(None, (fields[0],fields[1],fields[2])) for fields in items])

def startAddingItems(self):
"""Run before adding items"""
self.setSortingEnabled(False)

Expand All @@ -43,99 +44,129 @@ def finishAddingItems(self):
if not self.setting_sorting_disabled:
self.setSortingEnabled(True)

def removeDuplicates(self):
unique_items = set()

for n in range(self.invisibleRootItem().childCount() - 1, -1, -1):
item = self.invisibleRootItem().child(n)
path = item.text(2)
if path in unique_items:
self.log(f"Duplicate found: {path}")
self.takeTopLevelItem(n)
else:
unique_items.add(path)

def disableSorting(self, disabled):
self.setting_sorting_disabled = disabled
self.setSortingEnabled(not disabled)

# Events
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.accept()
else:
event.ignore()

def dropEvent(self, event):
if event.mimeData().hasUrls():
event.accept()

self.beforeAddingItems()
items = []
for i in event.mimeData().urls():
path = ""
if i.isLocalFile():
path = str(i.toLocalFile())
if os.path.isdir(path):
self.log(f"Dropped directory: {path}")
files = scanDir(path)
for i in files:
file_data = stripPathToFilename(i)
for file in files:
file_data = stripPathToFilename(file)
if file_data[1].lower() in ALLOWED_INPUT:
self.addItem(file_data[0],file_data[1],file_data[3])
items.append((file_data[0], file_data[1], file_data[3]))
elif os.path.isfile(path):
self.log(f"Dropped file: {path}")
file_data = stripPathToFilename(path)
if file_data[1].lower() in ALLOWED_INPUT:
self.addItem(file_data[0],file_data[1],file_data[3])
items.append((file_data[0], file_data[1], file_data[3]))
else:
path = str(i.toString())


self.startAddingItems()
self.addItems(items)
# QApplication.processEvents()
self.finishAddingItems()

def keyPressEvent(self, event):
if event.key() == Qt.Key_Delete:
self.log("Pressed \"Delete\"")
selected_indexes = self.selectionModel().selectedIndexes()
deleted_indexes = []
if len(selected_indexes) > 0:
for i in range(len(selected_indexes)-1,0,-1): # Descending, not to shift order
row = selected_indexes[i].row()
if row not in deleted_indexes:
deleted_indexes.append(row)
self.takeTopLevelItem(row)
self.log(f"Removed item from list (index {row})")

# Select next item
item_count = self.invisibleRootItem().childCount()
if item_count > 0:
row = selected_indexes[0].row()
next_row = row
if row == item_count:
next_row -= 1
self.invisibleRootItem().child(next_row).setSelected(True)
# elif event.key() == Qt.Key_Up:
# pass
# elif event.key() == Qt.Key_Down:
# pass

self.deleteSelected()
elif event.key() == Qt.Key_Up:
self.moveSelectionUp()
elif event.key() == Qt.Key_Down:
self.moveSelectionDown()
elif event.key() == Qt.Key_Home:
self.moveSelectionToTop()
elif event.key() == Qt.Key_End:
self.moveSelectionToBottom()

# Navigation
def selectAllItems(self):
item_count = self.invisibleRootItem().childCount()
if self.invisibleRootItem().childCount() > 0:
self.selectAll()

def moveSelectionDown(self):
cur_idx = self.currentIndex()

if item_count > 0:
for i in range(item_count):
item = self.invisibleRootItem().child(i).setSelected(True)
if cur_idx.isValid() and cur_idx.row() < self.model().rowCount(cur_idx.parent()) - 1:
new_idx = self.model().index(cur_idx.row() + 1, cur_idx.column())
self.setCurrentIndex(new_idx)

def moveSelectionUp(self):
cur_idx = self.currentIndex()

def resizeToContent(self):
for i in range(0, self.columnCount() - 1): # The last one resizes with the window
self.resizeColumnToContents(i)
if cur_idx.isValid() and cur_idx.row() > 0:
new_idx = self.model().index(cur_idx.row() - 1, cur_idx.column())
self.setCurrentIndex(new_idx)

def moveSelectionToTop(self):
self.setCurrentIndex(self.model().index(0, 0))

def moveSelectionToBottom(self):
self.setCurrentIndex(self.model().index(self.model().rowCount() - 1, 0))

def scrollToLastItem(self):
item_count = self.invisibleRootItem().childCount()
self.scrollToItem(self.invisibleRootItem().child(item_count - 1))

def resizeToContent(self):
for i in range(0, self.columnCount() - 1): # The last one resizes with the window
self.resizeColumnToContents(i)

# Operations
def deleteSelected(self):
root = self.invisibleRootItem()

def removeDuplicates(self):
"""Remove all duplicates. Avoid calling often."""
item_count = self.invisibleRootItem().childCount()
unique_items = []
selected_indexes = self.selectionModel().selectedIndexes()
if not selected_indexes:
return

selected_rows = sorted(set(idx.row() for idx in selected_indexes), reverse=True)
next_row = -1

if root.childCount() == 0:
next_row = -1
elif selected_rows[0] == root.childCount() - 1:
next_row = max(0, selected_rows[0] - 1)
else:
next_row = selected_rows[0]

for row in selected_rows:
self.takeTopLevelItem(row)
self.log(f"Removed item from list (index {row})")

n = 0
while n < item_count:
item = self.invisibleRootItem().child(n)
if item.text(2) not in unique_items:
unique_items.append(item.text(2))
n += 1
else:
self.log(f"Duplicate found: {item.text(2)}")
self.takeTopLevelItem(n)
item_count -= 1

def disableSorting(self, disabled):
self.setting_sorting_disabled = disabled
self.setSortingEnabled(not disabled)
if root.childCount() > 0:
self.setCurrentIndex(self.model().index(next_row, 0))

# Misc.
def log(self, msg):
if FILEVIEW_LOGS:
print(f"[FileView] {msg}")
32 changes: 19 additions & 13 deletions InputTab.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def __init__(self, settings):
self.file_view = FileView(self)

# Apply Settings
self.disableSorting(settings["settings"]["sorting_disabled"])
self.disableSorting(settings["sorting_disabled"])

# Shortcuts
self.select_all_sc = QShortcut(QKeySequence('Ctrl+A'), self)
Expand Down Expand Up @@ -65,31 +65,37 @@ def addFiles(self):
dlg = QFileDialog()
dlg.setWindowTitle("Add Images")
dlg.setFileMode(QFileDialog.ExistingFiles)
dlg.setNameFilter(listToFilter("Images", ALLOWED_INPUT))
dlg.setNameFilter(listToFilter("Images", ALLOWED_INPUT)) # Filter is used instead of ALLOWED_INPUT

self.file_view.beforeAddingItems()
filepaths = ""
items = []
if dlg.exec():
filepaths = dlg.selectedFiles()
for i in filepaths:
file_data = stripPathToFilename(i)
self.file_view.addItem(file_data[0], file_data[1], file_data[3])
file_paths = dlg.selectedFiles()
for file in file_paths:
file_data = stripPathToFilename(file)
items.append((file_data[0], file_data[1], file_data[3]))

if not items:
return

self.file_view.startAddingItems()
self.file_view.addItems(items)
self.file_view.finishAddingItems()

def addFolder(self):
dlg = QFileDialog()
dlg.setWindowTitle("Add Images from a Folder")
dlg.setFileMode(QFileDialog.Directory)

self.file_view.beforeAddingItems()
items = []
if dlg.exec():
files = scanDir(dlg.selectedFiles()[0])
for i in files:
file_data = stripPathToFilename(i)
if file_data[1] in ALLOWED_INPUT:
self.file_view.addItem(file_data[0], file_data[1], file_data[3])
for file in files:
file_data = stripPathToFilename(file)
if file_data[1].lower() in ALLOWED_INPUT:
items.append((file_data[0], file_data[1], file_data[3]))

self.file_view.startAddingItems()
self.file_view.addItems(items)
self.file_view.finishAddingItems()

def clearInput(self):
Expand Down
5 changes: 3 additions & 2 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
XL Converter is licensed under GNU General Public License v3 (GPLv3) included in this file.
Copyright (c) 2023 CodePoems <[email protected]>
XL Converter is licensed under GNU General Public License v3 (GPLv3).

Copyright (c) 2023 code poems <[email protected]>

-----------------------------------------------------------------------------------

Expand Down
4 changes: 2 additions & 2 deletions ModifyTab.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,9 @@ def __init__(self, settings):
self.wm.loadState()
self.onModeChanged()

if settings["settings"]["disable_downscaling_startup"]:
if settings["disable_downscaling_startup"]:
self.disableDownscaling()
self.toggleCustomResampling(settings["settings"]["custom_resampling"])
self.toggleCustomResampling(settings["custom_resampling"])

# Add to main layout
tab_lt.addWidget(downscale_grp,0,0)
Expand Down
11 changes: 6 additions & 5 deletions OutputTab.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,15 +279,16 @@ def onFormatChange(self):
self.wm.setEnabledByTag("lossless", cur_format in ("JPEG XL", "WEBP"))

# Effort
self.wm.getWidget("int_effort_cb").setEnabled(cur_format == "JPEG XL")
self.wm.getWidget("effort_sb").setEnabled(cur_format in ("JPEG XL", "AVIF"))
self.wm.getWidget("effort_l").setEnabled(cur_format in ("JPEG XL", "AVIF"))

if cur_format == "JPEG XL":
self.wm.getWidget("int_effort_cb").setEnabled(True)
self.onEffortToggled() # This is important to avoid issues with the effort_sb enabled state
else:
self.wm.getWidget("int_effort_cb").setEnabled(False)
self.wm.getWidget("effort_sb").setEnabled(cur_format == "AVIF")
self.onEffortToggled() # It's very important to update int_effort_cb to avoid issues when changing formats while it's enabled

# Disable Quality Slider
self.wm.setEnabledByTag("quality", not cur_format in ("PNG", "Smallest Lossless"))
self.wm.getWidget("quality_l").setEnabled(not cur_format in ("PNG", "Smallest Lossless"))

# Quality Slider Range and label
if cur_format == "AVIF":
Expand Down
Loading

0 comments on commit d28690f

Please sign in to comment.