1
0
mirror of https://github.com/arsenetar/dupeguru.git synced 2025-05-08 09:49:51 +00:00

Compare commits

..

No commits in common. "091cae0cc69f00fb80f667e1e9a48a9bfe4d94fa" and "1db93fd1422bf4df291c55bf20febfd62502ec74" have entirely different histories.

9 changed files with 38 additions and 129 deletions

View File

@ -154,8 +154,6 @@ class DupeGuru(Broadcaster):
"ignore_hardlink_matches": False,
"copymove_dest_type": DestType.RELATIVE,
"picture_cache_type": self.PICTURE_CACHE_TYPE,
"include_exists_check": True,
"rehash_ignore_mtime": False,
}
self.selected_dupes = []
self.details_panel = DetailsPanel(self)
@ -557,9 +555,7 @@ class DupeGuru(Broadcaster):
# a workaround to make the damn thing work.
exepath, args = match.groups()
path, exename = op.split(exepath)
p = subprocess.Popen(
exename + args, shell=True, cwd=path, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)
p = subprocess.Popen(exename + args, shell=True, cwd=path, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = p.stdout.read()
logging.info("Custom command %s %s: %s", exename, args, output)
else:
@ -796,7 +792,6 @@ class DupeGuru(Broadcaster):
Scans folders selected in :attr:`directories` and put the results in :attr:`results`
"""
scanner = self.SCANNER_CLASS()
fs.filesdb.ignore_mtime = self.options["rehash_ignore_mtime"] is True
if not self.directories.has_any_file():
self.view.show_message(tr("The selected directories contain no scannable file."))
return

View File

@ -100,14 +100,11 @@ class FilesDB:
create_table_query = "CREATE TABLE IF NOT EXISTS files (path TEXT PRIMARY KEY, size INTEGER, mtime_ns INTEGER, entry_dt DATETIME, digest BLOB, digest_partial BLOB, digest_samples BLOB)"
drop_table_query = "DROP TABLE IF EXISTS files;"
select_query = "SELECT {key} FROM files WHERE path=:path AND size=:size and mtime_ns=:mtime_ns"
select_query_ignore_mtime = "SELECT {key} FROM files WHERE path=:path AND size=:size"
insert_query = """
INSERT INTO files (path, size, mtime_ns, entry_dt, {key}) VALUES (:path, :size, :mtime_ns, datetime('now'), :value)
ON CONFLICT(path) DO UPDATE SET size=:size, mtime_ns=:mtime_ns, entry_dt=datetime('now'), {key}=:value;
"""
ignore_mtime = False
def __init__(self):
self.conn = None
self.cur = None
@ -149,12 +146,9 @@ class FilesDB:
mtime_ns = stat.st_mtime_ns
try:
with self.lock:
if self.ignore_mtime:
self.cur.execute(self.select_query_ignore_mtime.format(key=key), {"path": str(path), "size": size})
else:
self.cur.execute(
self.select_query.format(key=key), {"path": str(path), "size": size, "mtime_ns": mtime_ns}
)
self.cur.execute(
self.select_query.format(key=key), {"path": str(path), "size": size, "mtime_ns": mtime_ns}
)
result = self.cur.fetchone()
if result:

View File

@ -171,8 +171,7 @@ class Scanner:
matches = [m for m in matches if m.first.path not in toremove or m.second.path not in toremove]
if not self.mix_file_kind:
matches = [m for m in matches if get_file_ext(m.first.name) == get_file_ext(m.second.name)]
if self.include_exists_check:
matches = [m for m in matches if m.first.path.exists() and m.second.path.exists()]
matches = [m for m in matches if m.first.path.exists() and m.second.path.exists()]
matches = [m for m in matches if not (m.first.is_ref and m.second.is_ref)]
if ignore_list:
matches = [m for m in matches if not ignore_list.are_ignored(str(m.first.path), str(m.second.path))]
@ -213,4 +212,3 @@ class Scanner:
large_size_threshold = 0
big_file_size_threshold = 0
word_weighting = False
include_exists_check = True

View File

@ -36,83 +36,83 @@ msgstr ""
msgid "Sending to Trash"
msgstr ""
#: core\app.py:293
#: core\app.py:291
msgid "A previous action is still hanging in there. You can't start a new one yet. Wait a few seconds, then try again."
msgstr ""
#: core\app.py:304
#: core\app.py:302
msgid "No duplicates found."
msgstr ""
#: core\app.py:319
#: core\app.py:317
msgid "All marked files were copied successfully."
msgstr ""
#: core\app.py:321
#: core\app.py:319
msgid "All marked files were moved successfully."
msgstr ""
#: core\app.py:323
#: core\app.py:321
msgid "All marked files were deleted successfully."
msgstr ""
#: core\app.py:325
#: core\app.py:323
msgid "All marked files were successfully sent to Trash."
msgstr ""
#: core\app.py:330
#: core\app.py:328
msgid "Could not load file: {}"
msgstr ""
#: core\app.py:386
#: core\app.py:384
msgid "'{}' already is in the list."
msgstr ""
#: core\app.py:388
#: core\app.py:386
msgid "'{}' does not exist."
msgstr ""
#: core\app.py:396
#: core\app.py:394
msgid "All selected %d matches are going to be ignored in all subsequent scans. Continue?"
msgstr ""
#: core\app.py:473
#: core\app.py:471
msgid "Select a directory to copy marked files to"
msgstr ""
#: core\app.py:475
#: core\app.py:473
msgid "Select a directory to move marked files to"
msgstr ""
#: core\app.py:514
#: core\app.py:512
msgid "Select a destination for your exported CSV"
msgstr ""
#: core\app.py:520 core\app.py:781 core\app.py:791
#: core\app.py:518 core\app.py:773 core\app.py:783
msgid "Couldn't write to file: {}"
msgstr ""
#: core\app.py:543
#: core\app.py:541
msgid "You have no custom command set up. Set it up in your preferences."
msgstr ""
#: core\app.py:705 core\app.py:717
#: core\app.py:697 core\app.py:709
msgid "You are about to remove %d files from results. Continue?"
msgstr ""
#: core\app.py:753
#: core\app.py:745
msgid "{} duplicate groups were changed by the re-prioritization."
msgstr ""
#: core\app.py:801
#: core\app.py:792
msgid "The selected directories contain no scannable file."
msgstr ""
#: core\app.py:817
#: core\app.py:808
msgid "Collecting files to scan"
msgstr ""
#: core\app.py:867
#: core\app.py:858
msgid "%s (%d discarded)"
msgstr ""

View File

@ -1092,25 +1092,3 @@ msgstr ""
#: qt\search_edit.py:78
msgid "Search..."
msgstr ""
#: qt\preferences_dialog.py:219
msgid ""
"These options are for advanced users or for very specific situations, most "
"users should not have to modify these."
msgstr ""
#: qt\preferences_dialog.py:225
msgid "Include existence check after scan completion"
msgstr ""
#: qt\preferences_dialog.py:227
msgid "Ignore difference in mtime when loading cached digests"
msgstr ""
#: qt\progress_window.py:64
msgid "Cancel?"
msgstr ""
#: qt\progress_window.py:65
msgid "Are you sure you want to cancel? All progress will be lost."
msgstr ""

View File

@ -193,8 +193,6 @@ class DupeGuru(QObject):
self.model.options["scanned_tags"] = scanned_tags
self.model.options["match_scaled"] = self.prefs.match_scaled
self.model.options["picture_cache_type"] = self.prefs.picture_cache_type
self.model.options["include_exists_check"] = self.prefs.include_exists_check
self.model.options["rehash_ignore_mtime"] = self.prefs.rehash_ignore_mtime
if self.details_dialog:
self.details_dialog.update_options()

View File

@ -161,8 +161,6 @@ class Preferences(PreferencesBase):
self.ignore_hardlink_matches = get("IgnoreHardlinkMatches", self.ignore_hardlink_matches)
self.use_regexp = get("UseRegexp", self.use_regexp)
self.remove_empty_folders = get("RemoveEmptyFolders", self.remove_empty_folders)
self.rehash_ignore_mtime = get("RehashIgnoreMTime", self.rehash_ignore_mtime)
self.include_exists_check = get("IncludeExistsCheck", self.include_exists_check)
self.debug_mode = get("DebugMode", self.debug_mode)
self.profile_scan = get("ProfileScan", self.profile_scan)
self.destination_type = get("DestinationType", self.destination_type)
@ -233,8 +231,6 @@ class Preferences(PreferencesBase):
self.use_regexp = False
self.ignore_hardlink_matches = False
self.remove_empty_folders = False
self.rehash_ignore_mtime = False
self.include_exists_check = True
self.debug_mode = False
self.profile_scan = False
self.destination_type = 1
@ -287,8 +283,6 @@ class Preferences(PreferencesBase):
set_("IgnoreHardlinkMatches", self.ignore_hardlink_matches)
set_("UseRegexp", self.use_regexp)
set_("RemoveEmptyFolders", self.remove_empty_folders)
set_("RehashIgnoreMTime", self.rehash_ignore_mtime)
set_("IncludeExistsCheck", self.include_exists_check)
set_("DebugMode", self.debug_mode)
set_("ProfileScan", self.profile_scan)
set_("DestinationType", self.destination_type)

View File

@ -47,9 +47,8 @@ class Sections(Flag):
GENERAL = auto()
DISPLAY = auto()
ADVANCED = auto()
DEBUG = auto()
ALL = GENERAL | DISPLAY | ADVANCED | DEBUG
ALL = GENERAL | DISPLAY | DEBUG
class PreferencesDialogBase(QDialog):
@ -214,19 +213,6 @@ use the modifier key to drag the floating window around"
details_groupbox.setLayout(self.details_groupbox_layout)
self.displayVLayout.addWidget(details_groupbox)
def _setup_advanced_page(self):
tab_label = QLabel(
tr(
"These options are for advanced users or for very specific situations, most users should not have to modify these."
),
wordWrap=True,
)
self.advanced_vlayout.addWidget(tab_label)
self._setupAddCheckbox("include_exists_check_box", tr("Include existence check after scan completion"))
self.advanced_vlayout.addWidget(self.include_exists_check_box)
self._setupAddCheckbox("rehash_ignore_mtime_box", tr("Ignore difference in mtime when loading cached digests"))
self.advanced_vlayout.addWidget(self.rehash_ignore_mtime_box)
def _setupDebugPage(self):
self._setupAddCheckbox("debugModeBox", tr("Debug mode (restart required)"))
self._setupAddCheckbox("profile_scan_box", tr("Profile scan operation"))
@ -258,20 +244,16 @@ use the modifier key to drag the floating window around"
self.tabwidget = QTabWidget()
self.page_general = QWidget()
self.page_display = QWidget()
self.page_advanced = QWidget()
self.page_debug = QWidget()
self.widgetsVLayout = QVBoxLayout()
self.page_general.setLayout(self.widgetsVLayout)
self.displayVLayout = QVBoxLayout()
self.displayVLayout.setSpacing(5) # arbitrary value, might conflict with style
self.page_display.setLayout(self.displayVLayout)
self.advanced_vlayout = QVBoxLayout()
self.page_advanced.setLayout(self.advanced_vlayout)
self.debugVLayout = QVBoxLayout()
self.page_debug.setLayout(self.debugVLayout)
self._setupPreferenceWidgets()
self._setupDisplayPage()
self._setup_advanced_page()
self._setupDebugPage()
# self.mainVLayout.addLayout(self.widgetsVLayout)
self.buttonBox = QDialogButtonBox(self)
@ -283,11 +265,9 @@ use the modifier key to drag the floating window around"
self.layout().setSizeConstraint(QLayout.SetFixedSize)
self.tabwidget.addTab(self.page_general, tr("General"))
self.tabwidget.addTab(self.page_display, tr("Display"))
self.tabwidget.addTab(self.page_advanced, tr("Advanced"))
self.tabwidget.addTab(self.page_debug, tr("Debug"))
self.displayVLayout.addStretch(0)
self.widgetsVLayout.addStretch(0)
self.advanced_vlayout.addStretch(0)
self.debugVLayout.addStretch(0)
def _load(self, prefs, setchecked, section):
@ -338,9 +318,6 @@ use the modifier key to drag the floating window around"
except KeyError:
selected_lang = self.supportedLanguages["en"]
self.languageComboBox.setCurrentText(selected_lang)
if section & Sections.ADVANCED:
setchecked(self.rehash_ignore_mtime_box, prefs.rehash_ignore_mtime)
setchecked(self.include_exists_check_box, prefs.include_exists_check)
if section & Sections.DEBUG:
setchecked(self.debugModeBox, prefs.debug_mode)
setchecked(self.profile_scan_box, prefs.profile_scan)
@ -357,8 +334,6 @@ use the modifier key to drag the floating window around"
prefs.use_regexp = ischecked(self.useRegexpBox)
prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox)
prefs.ignore_hardlink_matches = ischecked(self.ignoreHardlinkMatches)
prefs.rehash_ignore_mtime = ischecked(self.rehash_ignore_mtime_box)
prefs.include_exists_check = ischecked(self.include_exists_check_box)
prefs.debug_mode = ischecked(self.debugModeBox)
prefs.profile_scan = ischecked(self.profile_scan_box)
prefs.reference_bold_font = ischecked(self.reference_bold_font)

View File

@ -5,7 +5,7 @@
# http://www.gnu.org/licenses/gpl-3.0.html
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import QDialog, QMessageBox, QVBoxLayout, QLabel, QProgressBar, QPushButton
from PyQt5.QtWidgets import QProgressDialog
from hscommon.trans import tr
@ -25,60 +25,37 @@ class ProgressWindow:
def refresh(self): # Labels
if self._window is not None:
self._window.setWindowTitle(self.model.jobdesc_textfield.text)
self._label.setText(self.model.progressdesc_textfield.text)
self._window.setLabelText(self.model.progressdesc_textfield.text)
def set_progress(self, last_progress):
if self._window is not None:
if last_progress < 0:
self._progress_bar.setRange(0, 0)
self._window.setRange(0, 0)
else:
self._progress_bar.setRange(0, 100)
self._progress_bar.setValue(last_progress)
self._window.setRange(0, 100)
self._window.setValue(last_progress)
def show(self):
flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint
self._window = QDialog(self.parent, flags)
self._setup_ui()
self._window = QProgressDialog("", tr("Cancel"), 0, 100, self.parent, flags)
self._window.setModal(True)
self._window.setAutoReset(False)
self._window.setAutoClose(False)
self._timer = QTimer(self._window)
self._timer.timeout.connect(self.model.pulse)
self._window.show()
self._window.canceled.connect(self.model.cancel)
self._timer.start(500)
def _setup_ui(self):
self._window.setWindowTitle(tr("Cancel"))
vertical_layout = QVBoxLayout(self._window)
self._label = QLabel("", self._window)
vertical_layout.addWidget(self._label)
self._progress_bar = QProgressBar(self._window)
self._progress_bar.setRange(0, 100)
vertical_layout.addWidget(self._progress_bar)
self._cancel_button = QPushButton(tr("Cancel"), self._window)
self._cancel_button.clicked.connect(self.cancel)
vertical_layout.addWidget(self._cancel_button)
def cancel(self):
if self._window is not None:
confirm_dialog = QMessageBox(
QMessageBox.Icon.Question,
tr("Cancel?"),
tr("Are you sure you want to cancel? All progress will be lost."),
QMessageBox.StandardButton.No | QMessageBox.StandardButton.Yes,
self._window,
)
confirm_dialog.setDefaultButton(QMessageBox.StandardButton.No)
result = confirm_dialog.exec_()
if result != QMessageBox.StandardButton.Yes:
return
self.close()
def close(self):
# it seems it is possible for close to be called without a corresponding
# show, only perform a close if there is a window to close
if self._window is not None:
self._timer.stop()
del self._timer
# For some weird reason, canceled() signal is sent upon close, whether the user canceled
# or not. If we don't want a false cancellation, we have to disconnect it.
self._window.canceled.disconnect()
self._window.close()
self._window.setParent(None)
self._window = None
self.model.cancel()