mirror of
				https://github.com/arsenetar/dupeguru.git
				synced 2025-09-11 17:58:17 +00:00 
			
		
		
		
	[#32] Internationalized the qt layer and localized it to French.
In the process of doing so, I also added a new preferences_dialog base class to reduce code duplication in the three pref dialogs (I didn't want to copy/paste the language combobox addition three times).
This commit is contained in:
		
							parent
							
								
									7f8a357019
								
							
						
					
					
						commit
						2c127adf59
					
				| @ -17,3 +17,5 @@ cocoa/*/Info.plist | ||||
| cocoa/*/build | ||||
| cocoa/*/dg_cocoa.plugin | ||||
| qt/base/*_rc.py | ||||
| qt/lang/fr.qm | ||||
| qt/lang/en.qm | ||||
| @ -1 +1,2 @@ | ||||
| __version__ = '5.10.4' | ||||
| __version__ = '5.10.4' | ||||
| __appname__ = 'dupeGuru Music Edition' | ||||
| @ -1 +1,2 @@ | ||||
| __version__ = '1.11.3' | ||||
| __version__ = '1.11.3' | ||||
| __appname__ = 'dupeGuru Picture Edition' | ||||
| @ -1 +1,2 @@ | ||||
| __version__ = '2.12.3' | ||||
| __appname__ = 'dupeGuru' | ||||
|  | ||||
| @ -15,9 +15,10 @@ from PyQt4.QtGui import QDesktopServices, QFileDialog, QDialog, QMessageBox, QAp | ||||
| 
 | ||||
| from jobprogress import job | ||||
| from jobprogress.qt import Progress | ||||
| from hscommon.trans import tr, trmsg | ||||
| 
 | ||||
| from core.app import DupeGuru as DupeGuruBase, JOB_SCAN, JOB_LOAD, JOB_MOVE, JOB_COPY, JOB_DELETE | ||||
|      | ||||
| 
 | ||||
| from qtlib.about_box import AboutBox | ||||
| from qtlib.recent import Recent | ||||
| from qtlib.reg import Registration | ||||
| @ -29,11 +30,11 @@ from .problem_dialog import ProblemDialog | ||||
| from .util import createActions | ||||
| 
 | ||||
| JOBID2TITLE = { | ||||
|     JOB_SCAN: "Scanning for duplicates", | ||||
|     JOB_LOAD: "Loading", | ||||
|     JOB_MOVE: "Moving", | ||||
|     JOB_COPY: "Copying", | ||||
|     JOB_DELETE: "Sending files to the recycle bin", | ||||
|     JOB_SCAN: tr("Scanning for duplicates"), | ||||
|     JOB_LOAD: tr("Loading"), | ||||
|     JOB_MOVE: tr("Moving"), | ||||
|     JOB_COPY: tr("Copying"), | ||||
|     JOB_DELETE: tr("Sending files to the recycle bin"), | ||||
| } | ||||
| 
 | ||||
| class DupeGuru(DupeGuruBase, QObject): | ||||
| @ -86,13 +87,13 @@ class DupeGuru(DupeGuruBase, QObject): | ||||
|         # Setup actions that are common to both the directory dialog and the results window. | ||||
|         # (name, shortcut, icon, desc, func) | ||||
|         ACTIONS = [ | ||||
|             ('actionQuit', 'Ctrl+Q', '', "Quit", self.quitTriggered), | ||||
|             ('actionPreferences', 'Ctrl+P', '', "Preferences", self.preferencesTriggered), | ||||
|             ('actionShowHelp', 'F1', '', "dupeGuru Help", self.showHelpTriggered), | ||||
|             ('actionAbout', '', '', "About dupeGuru", self.showAboutBoxTriggered), | ||||
|             ('actionRegister', '', '', "Register dupeGuru", self.registerTriggered), | ||||
|             ('actionCheckForUpdate', '', '', "Check for Update", self.checkForUpdateTriggered), | ||||
|             ('actionOpenDebugLog', '', '', "Open Debug Log", self.openDebugLogTriggered), | ||||
|             ('actionQuit', 'Ctrl+Q', '', tr("Quit"), self.quitTriggered), | ||||
|             ('actionPreferences', 'Ctrl+P', '', tr("Preferences"), self.preferencesTriggered), | ||||
|             ('actionShowHelp', 'F1', '', tr("dupeGuru Help"), self.showHelpTriggered), | ||||
|             ('actionAbout', '', '', tr("About dupeGuru"), self.showAboutBoxTriggered), | ||||
|             ('actionRegister', '', '', tr("Register dupeGuru"), self.registerTriggered), | ||||
|             ('actionCheckForUpdate', '', '', tr("Check for Update"), self.checkForUpdateTriggered), | ||||
|             ('actionOpenDebugLog', '', '', tr("Open Debug Log"), self.openDebugLogTriggered), | ||||
|         ] | ||||
|         createActions(ACTIONS, self) | ||||
|      | ||||
| @ -139,21 +140,21 @@ class DupeGuru(DupeGuruBase, QObject): | ||||
|             args = tuple([j] + list(args)) | ||||
|             self._progress.run(jobid, title, func, args=args) | ||||
|         except job.JobInProgressError: | ||||
|             msg = "A previous action is still hanging in there. You can't start a new one yet. Wait a few seconds, then try again." | ||||
|             msg = trmsg("TaskHangingMsg") | ||||
|             QMessageBox.information(self.resultWindow, 'Action in progress', msg) | ||||
|      | ||||
|     def add_selected_to_ignore_list(self): | ||||
|         dupes = self.without_ref(self.selected_dupes) | ||||
|         if not dupes: | ||||
|             return | ||||
|         title = "Add to Ignore List" | ||||
|         msg = "All selected {0} matches are going to be ignored in all subsequent scans. Continue?".format(len(dupes)) | ||||
|         title = tr("Add to Ignore List") | ||||
|         msg = trmsg("IgnoreConfirmMsg").format(len(dupes)) | ||||
|         if self.confirm(title, msg): | ||||
|             DupeGuruBase.add_selected_to_ignore_list(self) | ||||
|      | ||||
|     def copy_or_move_marked(self, copy): | ||||
|         opname = 'copy' if copy else 'move' | ||||
|         title = "Select a directory to {0} marked files to".format(opname) | ||||
|         opname = tr("copy") if copy else tr("move") | ||||
|         title = trmsg("SelectCopyOrMoveDestinationMsg").format(opname) | ||||
|         flags = QFileDialog.ShowDirsOnly | ||||
|         destination = str(QFileDialog.getExistingDirectory(self.resultWindow, title, '', flags)) | ||||
|         if not destination: | ||||
| @ -165,8 +166,8 @@ class DupeGuru(DupeGuruBase, QObject): | ||||
|         dupes = self.without_ref(self.selected_dupes) | ||||
|         if not dupes: | ||||
|             return | ||||
|         title = "Remove duplicates" | ||||
|         msg = "You are about to remove {0} files from results. Continue?".format(len(dupes)) | ||||
|         title = tr("Remove duplicates") | ||||
|         msg = trmsg("FileRemovalConfirmMsg").format(len(dupes)) | ||||
|         if self.confirm(title, msg): | ||||
|             DupeGuruBase.remove_selected(self) | ||||
|      | ||||
| @ -185,8 +186,8 @@ class DupeGuru(DupeGuruBase, QObject): | ||||
|         if cmd: | ||||
|             self.invoke_command(cmd) | ||||
|         else: | ||||
|             msg = "You have no custom command set up. Please, set it up in your preferences." | ||||
|             QMessageBox.warning(self.resultWindow, 'Custom Command', msg) | ||||
|             msg = trmsg("NoCustomCommandMsg") | ||||
|             QMessageBox.warning(self.resultWindow, tr("Custom Command"), msg) | ||||
|      | ||||
|     def show_details(self): | ||||
|         self.details_dialog.show() | ||||
| @ -212,12 +213,12 @@ class DupeGuru(DupeGuruBase, QObject): | ||||
|             if self.results.problems: | ||||
|                 self.problemDialog.show() | ||||
|             else: | ||||
|                 msg = "All files were processed successfully." | ||||
|                 QMessageBox.information(self.resultWindow, 'Operation Complete', msg) | ||||
|                 msg = trmsg("OperationSuccessMsg") | ||||
|                 QMessageBox.information(self.resultWindow, tr("Operation Complete"), msg) | ||||
|         elif jobid == JOB_SCAN: | ||||
|             if not self.results.groups: | ||||
|                 title = "Scan complete" | ||||
|                 msg = "No duplicates found." | ||||
|                 title = tr("Scan complete") | ||||
|                 msg = trmsg("NoDuplicateFoundMsg") | ||||
|                 QMessageBox.information(self.resultWindow, title, msg) | ||||
|             else: | ||||
|                 self.showResultsWindow() | ||||
|  | ||||
| @ -9,7 +9,9 @@ | ||||
| from PyQt4.QtCore import Qt, SIGNAL, QAbstractTableModel | ||||
| from PyQt4.QtGui import QHeaderView, QTableView | ||||
| 
 | ||||
| HEADER = ['Attribute', 'Selected', 'Reference'] | ||||
| from hscommon.trans import tr | ||||
| 
 | ||||
| HEADER = [tr("Attribute"), tr("Selected"), tr("Reference")] | ||||
| 
 | ||||
| class DetailsModel(QAbstractTableModel): | ||||
|     def __init__(self, model): | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| <!DOCTYPE RCC><RCC version="1.0"> | ||||
| <qresource> | ||||
|     <file alias="en.qm">../lang/en.qm</file> | ||||
|     <file alias="fr.qm">../lang/fr.qm</file> | ||||
|     <file alias="qt_fr.qm">../lang/qt_fr.qm</file> | ||||
|     <file alias="logo_pe">../../images/dgpe_logo_32.png</file> | ||||
|  | ||||
| @ -11,6 +11,7 @@ from PyQt4.QtGui import (QWidget, QFileDialog, QHeaderView, QVBoxLayout, QHBoxLa | ||||
|     QAbstractItemView, QSpacerItem, QSizePolicy, QPushButton, QApplication, QMessageBox, QMainWindow, | ||||
|     QMenuBar, QMenu, QIcon, QPixmap) | ||||
| 
 | ||||
| from hscommon.trans import tr, trmsg | ||||
| from qtlib.recent import Recent | ||||
| from core.app import NoScannableFileError | ||||
| 
 | ||||
| @ -49,9 +50,9 @@ class DirectoriesDialog(QMainWindow): | ||||
|     def _setupActions(self): | ||||
|         # (name, shortcut, icon, desc, func) | ||||
|         ACTIONS = [ | ||||
|             ('actionLoadResults', 'Ctrl+L', '', "Load Results...", self.loadResultsTriggered), | ||||
|             ('actionShowResultsWindow', '', '', "Results Window", self.app.showResultsWindow), | ||||
|             ('actionAddFolder', '', '', "Add Folder...", self.addFolderTriggered), | ||||
|             ('actionLoadResults', 'Ctrl+L', '', tr("Load Results..."), self.loadResultsTriggered), | ||||
|             ('actionShowResultsWindow', '', '', tr("Results Window"), self.app.showResultsWindow), | ||||
|             ('actionAddFolder', '', '', tr("Add Folder..."), self.addFolderTriggered), | ||||
|         ] | ||||
|         createActions(ACTIONS, self) | ||||
|      | ||||
| @ -59,13 +60,13 @@ class DirectoriesDialog(QMainWindow): | ||||
|         self.menubar = QMenuBar(self) | ||||
|         self.menubar.setGeometry(QRect(0, 0, 42, 22)) | ||||
|         self.menuFile = QMenu(self.menubar) | ||||
|         self.menuFile.setTitle("File") | ||||
|         self.menuFile.setTitle(tr("File")) | ||||
|         self.menuView = QMenu(self.menubar) | ||||
|         self.menuView.setTitle("View") | ||||
|         self.menuView.setTitle(tr("View")) | ||||
|         self.menuHelp = QMenu(self.menubar) | ||||
|         self.menuHelp.setTitle("Help") | ||||
|         self.menuHelp.setTitle(tr("Help")) | ||||
|         self.menuLoadRecent = QMenu(self.menuFile) | ||||
|         self.menuLoadRecent.setTitle("Load Recent Results") | ||||
|         self.menuLoadRecent.setTitle(tr("Load Recent Results")) | ||||
|         self.setMenuBar(self.menubar) | ||||
|          | ||||
|         self.menuFile.addAction(self.actionLoadResults) | ||||
| @ -126,10 +127,10 @@ class DirectoriesDialog(QMainWindow): | ||||
|         spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) | ||||
|         self.horizontalLayout.addItem(spacerItem1) | ||||
|         self.loadResultsButton = QPushButton(self.centralwidget) | ||||
|         self.loadResultsButton.setText("Load Results") | ||||
|         self.loadResultsButton.setText(tr("Load Results")) | ||||
|         self.horizontalLayout.addWidget(self.loadResultsButton) | ||||
|         self.scanButton = QPushButton(self.centralwidget) | ||||
|         self.scanButton.setText("Scan") | ||||
|         self.scanButton.setText(tr("Scan")) | ||||
|         self.scanButton.setDefault(True) | ||||
|         self.horizontalLayout.addWidget(self.scanButton) | ||||
|         self.verticalLayout.addLayout(self.horizontalLayout) | ||||
| @ -167,8 +168,8 @@ class DirectoriesDialog(QMainWindow): | ||||
|     def closeEvent(self, event): | ||||
|         event.accept() | ||||
|         if self.app.results.is_modified: | ||||
|             title = "Unsaved results" | ||||
|             msg = "You have unsaved results, do you really want to quit?" | ||||
|             title = tr("Unsaved results") | ||||
|             msg = trmsg("ReallyWantToQuitMsg") | ||||
|             if not self.app.confirm(title, msg): | ||||
|                 event.ignore() | ||||
|         if event.isAccepted(): | ||||
| @ -176,7 +177,7 @@ class DirectoriesDialog(QMainWindow): | ||||
|      | ||||
|     #--- Events | ||||
|     def addFolderTriggered(self): | ||||
|         title = "Select a directory to add to the scanning list" | ||||
|         title = trmsg("SelectFolderToAddMsg") | ||||
|         flags = QFileDialog.ShowDirsOnly | ||||
|         dirpath = str(QFileDialog.getExistingDirectory(self, title, self.lastAddedFolder, flags)) | ||||
|         if not dirpath: | ||||
| @ -189,8 +190,8 @@ class DirectoriesDialog(QMainWindow): | ||||
|         self.app.prefs.directoriesWindowRect = self.geometry() | ||||
|      | ||||
|     def loadResultsTriggered(self): | ||||
|         title = "Select a results file to load" | ||||
|         files = "dupeGuru Results (*.dupeguru)" | ||||
|         title = trmsg("SelectResultToLoadMsg") | ||||
|         files = tr("dupeGuru Results (*.dupeguru)") | ||||
|         destination = QFileDialog.getOpenFileName(self, title, '', files) | ||||
|         if destination: | ||||
|             self.app.load_from(destination) | ||||
| @ -207,15 +208,16 @@ class DirectoriesDialog(QMainWindow): | ||||
|             self.app.remove_directory(row) | ||||
|      | ||||
|     def scanButtonClicked(self): | ||||
|         title = "Start a new scan" | ||||
|         title = tr("Start a new scan") | ||||
|         # XXX must be triggered on unsaved results | ||||
|         if len(self.app.results.groups) > 0: | ||||
|             msg = "Are you sure you want to start a new duplicate scan?" | ||||
|             msg = trmsg("ReallyWantToContinueMsg") | ||||
|             if not self.app.confirm(title, msg): | ||||
|                 return | ||||
|         try: | ||||
|             self.app.start_scanning() | ||||
|         except NoScannableFileError: | ||||
|             msg = "The selected directories contain no scannable file." | ||||
|             msg = trmsg("NoScannableFileMsg") | ||||
|             QMessageBox.warning(self, title, msg) | ||||
|      | ||||
|     def selectionChanged(self, selected, deselected): | ||||
|  | ||||
| @ -12,12 +12,13 @@ from PyQt4.QtCore import QModelIndex, Qt, QRect, QEvent, QPoint, QUrl | ||||
| from PyQt4.QtGui import (QComboBox, QStyledItemDelegate, QMouseEvent, QApplication, QBrush, QStyle, | ||||
|     QStyleOptionComboBox, QStyleOptionViewItemV4) | ||||
| 
 | ||||
| from hscommon.trans import tr | ||||
| from qtlib.tree_model import RefNode, TreeModel | ||||
| 
 | ||||
| from core.gui.directory_tree import DirectoryTree | ||||
| 
 | ||||
| HEADERS = ['Name', 'State'] | ||||
| STATES = ['Normal', 'Reference', 'Excluded'] | ||||
| HEADERS = [tr("Name"), tr("State")] | ||||
| STATES = [tr("Normal"), tr("Reference"), tr("Excluded")] | ||||
| 
 | ||||
| class DirectoriesDelegate(QStyledItemDelegate): | ||||
|     def createEditor(self, parent, option, index): | ||||
|  | ||||
| @ -29,6 +29,8 @@ class Preferences(PreferencesBase): | ||||
|         self.remove_empty_folders = get('RemoveEmptyFolders', self.remove_empty_folders) | ||||
|         self.destination_type = get('DestinationType', self.destination_type) | ||||
|         self.custom_command = get('CustomCommand', self.custom_command) | ||||
|         self.language = get('Language', self.language) | ||||
|          | ||||
|         widths = get('ColumnsWidth', self.columns_width) | ||||
|         # only set nonzero values | ||||
|         for index, width in enumerate(widths[:len(self.columns_width)]): | ||||
| @ -59,6 +61,7 @@ class Preferences(PreferencesBase): | ||||
|         self.remove_empty_folders = False | ||||
|         self.destination_type = 1 | ||||
|         self.custom_command = '' | ||||
|         self.language = '' | ||||
|          | ||||
|         self.resultWindowIsMaximized = False | ||||
|         self.resultWindowRect = None | ||||
| @ -90,6 +93,7 @@ class Preferences(PreferencesBase): | ||||
|         set_('CustomCommand', self.custom_command) | ||||
|         set_('ColumnsWidth', self.columns_width) | ||||
|         set_('ColumnsVisible', self.columns_visible) | ||||
|         set_('Language', self.language) | ||||
|          | ||||
|         set_('ResultWindowIsMaximized', self.resultWindowIsMaximized) | ||||
|         self.set_rect('ResultWindowRect', self.resultWindowRect) | ||||
|  | ||||
							
								
								
									
										164
									
								
								qt/base/preferences_dialog.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								qt/base/preferences_dialog.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,164 @@ | ||||
| # Created By: Virgil Dupras | ||||
| # Created On: 2011-01-21 | ||||
| # Copyright 2011 Hardcoded Software (http://www.hardcoded.net) | ||||
| #  | ||||
| # This software is licensed under the "BSD" License as described in the "LICENSE" file,  | ||||
| # which should be included with this package. The terms are also available at  | ||||
| # http://www.hardcoded.net/licenses/bsd_license | ||||
| 
 | ||||
| import sys | ||||
| from PyQt4.QtCore import SIGNAL, Qt, QSize | ||||
| from PyQt4.QtGui import (QDialog, QDialogButtonBox, QVBoxLayout, QHBoxLayout, QLabel, QComboBox, | ||||
|     QSlider, QSizePolicy, QSpacerItem, QCheckBox, QLineEdit, QMessageBox) | ||||
| 
 | ||||
| from hscommon.trans import tr, trmsg | ||||
| 
 | ||||
| class PreferencesDialogBase(QDialog): | ||||
|     def __init__(self, parent, app): | ||||
|         flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint | ||||
|         QDialog.__init__(self, parent, flags) | ||||
|         self.app = app | ||||
|         self._setupUi() | ||||
|          | ||||
|         self.connect(self.filterHardnessSlider, SIGNAL("valueChanged(int)"), self.filterHardnessLabel.setNum) | ||||
|         self.connect(self.buttonBox, SIGNAL('clicked(QAbstractButton*)'), self.buttonClicked) | ||||
|         self.buttonBox.accepted.connect(self.accept) | ||||
|         self.buttonBox.rejected.connect(self.reject) | ||||
|      | ||||
|     def _setupFilterHardnessBox(self): | ||||
|         self.filterHardnessHLayout = QHBoxLayout() | ||||
|         self.filterHardnessLabel = QLabel(self) | ||||
|         self.filterHardnessLabel.setText(tr("Filter Hardness:")) | ||||
|         self.filterHardnessLabel.setMinimumSize(QSize(0, 0)) | ||||
|         self.filterHardnessHLayout.addWidget(self.filterHardnessLabel) | ||||
|         self.filterHardnessVLayout = QVBoxLayout() | ||||
|         self.filterHardnessVLayout.setSpacing(0) | ||||
|         self.filterHardnessHLayoutSub1 = QHBoxLayout() | ||||
|         self.filterHardnessHLayoutSub1.setSpacing(12) | ||||
|         self.filterHardnessSlider = QSlider(self) | ||||
|         sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) | ||||
|         sizePolicy.setHorizontalStretch(0) | ||||
|         sizePolicy.setVerticalStretch(0) | ||||
|         sizePolicy.setHeightForWidth(self.filterHardnessSlider.sizePolicy().hasHeightForWidth()) | ||||
|         self.filterHardnessSlider.setSizePolicy(sizePolicy) | ||||
|         self.filterHardnessSlider.setMinimum(1) | ||||
|         self.filterHardnessSlider.setMaximum(100) | ||||
|         self.filterHardnessSlider.setTracking(True) | ||||
|         self.filterHardnessSlider.setOrientation(Qt.Horizontal) | ||||
|         self.filterHardnessHLayoutSub1.addWidget(self.filterHardnessSlider) | ||||
|         self.filterHardnessLabel = QLabel(self) | ||||
|         self.filterHardnessLabel.setText("100") | ||||
|         self.filterHardnessLabel.setMinimumSize(QSize(21, 0)) | ||||
|         self.filterHardnessHLayoutSub1.addWidget(self.filterHardnessLabel) | ||||
|         self.filterHardnessVLayout.addLayout(self.filterHardnessHLayoutSub1) | ||||
|         self.filterHardnessHLayoutSub2 = QHBoxLayout() | ||||
|         self.filterHardnessHLayoutSub2.setContentsMargins(-1, 0, -1, -1) | ||||
|         self.moreResultsLabel = QLabel(self) | ||||
|         self.moreResultsLabel.setText(tr("More Results")) | ||||
|         self.filterHardnessHLayoutSub2.addWidget(self.moreResultsLabel) | ||||
|         spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) | ||||
|         self.filterHardnessHLayoutSub2.addItem(spacerItem) | ||||
|         self.fewerResultsLabel = QLabel(self) | ||||
|         self.fewerResultsLabel.setText(tr("Fewer Results")) | ||||
|         self.filterHardnessHLayoutSub2.addWidget(self.fewerResultsLabel) | ||||
|         self.filterHardnessVLayout.addLayout(self.filterHardnessHLayoutSub2) | ||||
|         self.filterHardnessHLayout.addLayout(self.filterHardnessVLayout) | ||||
|      | ||||
|     def _setupBottomPart(self): | ||||
|         # The bottom part of the pref panel is always the same in all editions. | ||||
|         self.languageLabel = QLabel(tr("Language:"), self) | ||||
|         self.widgetsVLayout.addWidget(self.languageLabel) | ||||
|         self.languageComboBox = QComboBox(self) | ||||
|         self.languageComboBox.addItem(tr("English")) | ||||
|         self.languageComboBox.addItem(tr("French")) | ||||
|         self.widgetsVLayout.addWidget(self.languageComboBox) | ||||
|         self.copyMoveLabel = QLabel(self) | ||||
|         self.copyMoveLabel.setText(tr("Copy and Move:")) | ||||
|         self.widgetsVLayout.addWidget(self.copyMoveLabel) | ||||
|         self.copyMoveDestinationComboBox = QComboBox(self) | ||||
|         self.copyMoveDestinationComboBox.addItem(tr("Right in destination")) | ||||
|         self.copyMoveDestinationComboBox.addItem(tr("Recreate relative path")) | ||||
|         self.copyMoveDestinationComboBox.addItem(tr("Recreate absolute path")) | ||||
|         self.widgetsVLayout.addWidget(self.copyMoveDestinationComboBox) | ||||
|         self.customCommandLabel = QLabel(self) | ||||
|         self.customCommandLabel.setText(tr("Custom Command (arguments: %d for dupe, %r for ref):")) | ||||
|         self.widgetsVLayout.addWidget(self.customCommandLabel) | ||||
|         self.customCommandEdit = QLineEdit(self) | ||||
|         self.widgetsVLayout.addWidget(self.customCommandEdit) | ||||
|      | ||||
|     def _setupAddCheckbox(self, name, label, parent=None): | ||||
|         if parent is None: | ||||
|             parent = self | ||||
|         cb = QCheckBox(parent) | ||||
|         cb.setText(label) | ||||
|         setattr(self, name, cb) | ||||
|      | ||||
|     def _setupPreferenceWidgets(self): | ||||
|         # Edition-specific | ||||
|         pass | ||||
|      | ||||
|     def _setupUi(self): | ||||
|         self.setWindowTitle(tr("Preferences")) | ||||
|         self.resize(304, 263) | ||||
|         self.setSizeGripEnabled(False) | ||||
|         self.setModal(True) | ||||
|         self.mainVLayout = QVBoxLayout(self) | ||||
|         self.widgetsVLayout = QVBoxLayout() | ||||
|         self._setupPreferenceWidgets() | ||||
|         self.mainVLayout.addLayout(self.widgetsVLayout) | ||||
|         self.buttonBox = QDialogButtonBox(self) | ||||
|         self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok|QDialogButtonBox.RestoreDefaults) | ||||
|         self.mainVLayout.addWidget(self.buttonBox) | ||||
|         if sys.platform not in {'darwin', 'linux2'}: | ||||
|             self.verticalLayout.removeWidget(self.ignoreHardlinkMatches) | ||||
|             self.ignoreHardlinkMatches.setHidden(True) | ||||
|      | ||||
|     def _load(self, prefs, setchecked): | ||||
|         # Edition-specific | ||||
|         pass | ||||
|      | ||||
|     def _save(self, prefs, ischecked): | ||||
|         # Edition-specific | ||||
|         pass | ||||
|      | ||||
|     def load(self, prefs=None): | ||||
|         if prefs is None: | ||||
|             prefs = self.app.prefs | ||||
|         self.filterHardnessSlider.setValue(prefs.filter_hardness) | ||||
|         self.filterHardnessLabel.setNum(prefs.filter_hardness) | ||||
|         setchecked = lambda cb, b: cb.setCheckState(Qt.Checked if b else Qt.Unchecked) | ||||
|         setchecked(self.mixFileKindBox, prefs.mix_file_kind) | ||||
|         setchecked(self.useRegexpBox, prefs.use_regexp) | ||||
|         setchecked(self.removeEmptyFoldersBox, prefs.remove_empty_folders) | ||||
|         setchecked(self.ignoreHardlinkMatches, prefs.ignore_hardlink_matches) | ||||
|         self.copyMoveDestinationComboBox.setCurrentIndex(prefs.destination_type) | ||||
|         self.customCommandEdit.setText(prefs.custom_command) | ||||
|         langindex = {'fr': 1}.get(self.app.prefs.language, 0) | ||||
|         self.languageComboBox.setCurrentIndex(langindex) | ||||
|         self._load(prefs, setchecked) | ||||
|      | ||||
|     def save(self): | ||||
|         prefs = self.app.prefs | ||||
|         prefs.filter_hardness = self.filterHardnessSlider.value() | ||||
|         ischecked = lambda cb: cb.checkState() == Qt.Checked | ||||
|         prefs.mix_file_kind = ischecked(self.mixFileKindBox) | ||||
|         prefs.use_regexp = ischecked(self.useRegexpBox) | ||||
|         prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox) | ||||
|         prefs.ignore_hardlink_matches = ischecked(self.ignoreHardlinkMatches) | ||||
|         prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex() | ||||
|         prefs.custom_command = str(self.customCommandEdit.text()) | ||||
|         langs = ['en', 'fr'] | ||||
|         lang = langs[self.languageComboBox.currentIndex()] | ||||
|         oldlang = self.app.prefs.language | ||||
|         if oldlang not in langs: | ||||
|             oldlang = 'en' | ||||
|         if lang != oldlang: | ||||
|             QMessageBox.information(self, "", trmsg("NeedsToRestartToApplyLangMsg")) | ||||
|         self.app.prefs.language = lang | ||||
|         self._save(prefs, ischecked) | ||||
|      | ||||
|     #--- Events | ||||
|     def buttonClicked(self, button): | ||||
|         role = self.buttonBox.buttonRole(button) | ||||
|         if role == QDialogButtonBox.ResetRole: | ||||
|             self.resetToDefaults() | ||||
| @ -1,4 +1,3 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| # Created By: Virgil Dupras | ||||
| # Created On: 2010-04-12 | ||||
| # Copyright 2010 Hardcoded Software (http://www.hardcoded.net) | ||||
| @ -11,6 +10,7 @@ from PyQt4.QtCore import Qt | ||||
| from PyQt4.QtGui import (QDialog, QVBoxLayout, QHBoxLayout, QPushButton, QSpacerItem, QSizePolicy, | ||||
|     QLabel, QTableView, QAbstractItemView, QApplication) | ||||
| 
 | ||||
| from hscommon.trans import tr, trmsg | ||||
| from core.gui.problem_dialog import ProblemDialog as ProblemDialogModel | ||||
| from .problem_table import ProblemTable | ||||
| 
 | ||||
| @ -29,11 +29,11 @@ class ProblemDialog(QDialog): | ||||
|         self.closeButton.clicked.connect(self.accept) | ||||
|      | ||||
|     def _setupUi(self): | ||||
|         self.setWindowTitle("Problems!") | ||||
|         self.setWindowTitle(tr("Problems!")) | ||||
|         self.resize(413, 323) | ||||
|         self.verticalLayout = QVBoxLayout(self) | ||||
|         self.label = QLabel(self) | ||||
|         self.label.setText("There were problems processing some (or all) of the files. The cause of these problems are described in the table below. Those files were not removed from your results.") | ||||
|         self.label.setText(trmsg("ProblemsDuringProcessingMsg")) | ||||
|         self.label.setWordWrap(True) | ||||
|         self.verticalLayout.addWidget(self.label) | ||||
|         self.tableView = QTableView(self) | ||||
| @ -47,12 +47,12 @@ class ProblemDialog(QDialog): | ||||
|         self.verticalLayout.addWidget(self.tableView) | ||||
|         self.horizontalLayout = QHBoxLayout() | ||||
|         self.revealButton = QPushButton(self) | ||||
|         self.revealButton.setText("Reveal Selected") | ||||
|         self.revealButton.setText(tr("Reveal Selected")) | ||||
|         self.horizontalLayout.addWidget(self.revealButton) | ||||
|         spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) | ||||
|         self.horizontalLayout.addItem(spacerItem) | ||||
|         self.closeButton = QPushButton(self) | ||||
|         self.closeButton.setText("Close") | ||||
|         self.closeButton.setText(tr("Close")) | ||||
|         self.closeButton.setDefault(True) | ||||
|         self.horizontalLayout.addWidget(self.closeButton) | ||||
|         self.verticalLayout.addLayout(self.horizontalLayout) | ||||
|  | ||||
| @ -7,14 +7,15 @@ | ||||
| # which should be included with this package. The terms are also available at  | ||||
| # http://www.hardcoded.net/licenses/bsd_license | ||||
| 
 | ||||
| from hscommon.trans import tr | ||||
| from qtlib.column import Column | ||||
| from qtlib.table import Table | ||||
| from core.gui.problem_table import ProblemTable as ProblemTableModel | ||||
| 
 | ||||
| class ProblemTable(Table): | ||||
|     COLUMNS = [ | ||||
|         Column('path', 'File Path', 150), | ||||
|         Column('msg', 'Error Message', 150), | ||||
|         Column('path', tr("File Path"), 150), | ||||
|         Column('msg', tr("Error Message"), 150), | ||||
|     ] | ||||
|      | ||||
|     def __init__(self, problem_dialog, view): | ||||
|  | ||||
| @ -9,10 +9,11 @@ | ||||
| import sys | ||||
| 
 | ||||
| from PyQt4.QtCore import Qt, SIGNAL, QUrl, QRect | ||||
| from PyQt4.QtGui import (QMainWindow, QMenu, QPixmap, QIcon, QLabel, QHeaderView, QMessageBox, | ||||
|     QInputDialog, QLineEdit, QDesktopServices, QFileDialog, QMenuBar, QWidget, QVBoxLayout, | ||||
|     QAbstractItemView, QStatusBar) | ||||
| from PyQt4.QtGui import (QMainWindow, QMenu, QLabel, QHeaderView, QMessageBox, QInputDialog, | ||||
|     QLineEdit, QDesktopServices, QFileDialog, QMenuBar, QWidget, QVBoxLayout, QAbstractItemView, | ||||
|     QStatusBar) | ||||
| 
 | ||||
| from hscommon.trans import tr, trmsg | ||||
| from hscommon.util import nonone | ||||
| 
 | ||||
| from .results_model import ResultsModel, ResultsView | ||||
| @ -38,31 +39,31 @@ class ResultWindow(QMainWindow): | ||||
|     def _setupActions(self): | ||||
|         # (name, shortcut, icon, desc, func) | ||||
|         ACTIONS = [ | ||||
|             ('actionDetails', 'Ctrl+I', '', "Details", self.detailsTriggered), | ||||
|             ('actionActions', '', '', "Actions", self.actionsTriggered), | ||||
|             ('actionPowerMarker', 'Ctrl+1', '', "Show Dupes Only", self.powerMarkerTriggered), | ||||
|             ('actionDelta', 'Ctrl+2', '', "Show Delta Values", self.deltaTriggered), | ||||
|             ('actionDeleteMarked', 'Ctrl+D', '', "Send Marked to Recycle Bin", self.deleteTriggered), | ||||
|             ('actionHardlinkMarked', 'Ctrl+Shift+D', '', "Delete Marked and Replace with Hardlinks", self.hardlinkTriggered), | ||||
|             ('actionMoveMarked', 'Ctrl+M', '', "Move Marked to...", self.moveTriggered), | ||||
|             ('actionCopyMarked', 'Ctrl+Shift+M', '', "Copy Marked to...", self.copyTriggered), | ||||
|             ('actionRemoveMarked', 'Ctrl+R', '', "Remove Marked from Results", self.removeMarkedTriggered), | ||||
|             ('actionRemoveSelected', 'Ctrl+Del', '', "Remove Selected from Results", self.removeSelectedTriggered), | ||||
|             ('actionIgnoreSelected', 'Ctrl+Shift+Del', '', "Add Selected to Ignore List", self.addToIgnoreListTriggered), | ||||
|             ('actionMakeSelectedReference', 'Ctrl+Space', '', "Make Selected Reference", self.makeReferenceTriggered), | ||||
|             ('actionOpenSelected', 'Ctrl+O', '', "Open Selected with Default Application", self.openTriggered), | ||||
|             ('actionRevealSelected', 'Ctrl+Shift+O', '', "Open Containing Folder of Selected", self.revealTriggered), | ||||
|             ('actionRenameSelected', 'F2', '', "Rename Selected", self.renameTriggered), | ||||
|             ('actionMarkAll', 'Ctrl+A', '', "Mark All", self.markAllTriggered), | ||||
|             ('actionMarkNone', 'Ctrl+Shift+A', '', "Mark None", self.markNoneTriggered), | ||||
|             ('actionInvertMarking', 'Ctrl+Alt+A', '', "Invert Marking", self.markInvertTriggered), | ||||
|             ('actionMarkSelected', '', '', "Mark Selected", self.markSelectedTriggered), | ||||
|             ('actionClearIgnoreList', '', '', "Clear Ignore List", self.clearIgnoreListTriggered), | ||||
|             ('actionApplyFilter', 'Ctrl+F', '', "Apply Filter", self.applyFilterTriggered), | ||||
|             ('actionCancelFilter', 'Ctrl+Shift+F', '', "Cancel Filter", self.cancelFilterTriggered), | ||||
|             ('actionExport', '', '', "Export To HTML", self.exportTriggered), | ||||
|             ('actionSaveResults', 'Ctrl+S', '', "Save Results...", self.saveResultsTriggered), | ||||
|             ('actionInvokeCustomCommand', 'Ctrl+Alt+I', '', "Invoke Custom Command", self.app.invokeCustomCommand), | ||||
|             ('actionDetails', 'Ctrl+I', '', tr("Details"), self.detailsTriggered), | ||||
|             ('actionActions', '', '', tr("Actions"), self.actionsTriggered), | ||||
|             ('actionPowerMarker', 'Ctrl+1', '', tr("Show Dupes Only"), self.powerMarkerTriggered), | ||||
|             ('actionDelta', 'Ctrl+2', '', tr("Show Delta Values"), self.deltaTriggered), | ||||
|             ('actionDeleteMarked', 'Ctrl+D', '', tr("Send Marked to Recycle Bin"), self.deleteTriggered), | ||||
|             ('actionHardlinkMarked', 'Ctrl+Shift+D', '', tr("Delete Marked and Replace with Hardlinks"), self.hardlinkTriggered), | ||||
|             ('actionMoveMarked', 'Ctrl+M', '', tr("Move Marked to..."), self.moveTriggered), | ||||
|             ('actionCopyMarked', 'Ctrl+Shift+M', '', tr("Copy Marked to..."), self.copyTriggered), | ||||
|             ('actionRemoveMarked', 'Ctrl+R', '', tr("Remove Marked from Results"), self.removeMarkedTriggered), | ||||
|             ('actionRemoveSelected', 'Ctrl+Del', '', tr("Remove Selected from Results"), self.removeSelectedTriggered), | ||||
|             ('actionIgnoreSelected', 'Ctrl+Shift+Del', '', tr("Add Selected to Ignore List"), self.addToIgnoreListTriggered), | ||||
|             ('actionMakeSelectedReference', 'Ctrl+Space', '', tr("Make Selected Reference"), self.makeReferenceTriggered), | ||||
|             ('actionOpenSelected', 'Ctrl+O', '', tr("Open Selected with Default Application"), self.openTriggered), | ||||
|             ('actionRevealSelected', 'Ctrl+Shift+O', '', tr("Open Containing Folder of Selected"), self.revealTriggered), | ||||
|             ('actionRenameSelected', 'F2', '', tr("Rename Selected"), self.renameTriggered), | ||||
|             ('actionMarkAll', 'Ctrl+A', '', tr("Mark All"), self.markAllTriggered), | ||||
|             ('actionMarkNone', 'Ctrl+Shift+A', '', tr("Mark None"), self.markNoneTriggered), | ||||
|             ('actionInvertMarking', 'Ctrl+Alt+A', '', tr("Invert Marking"), self.markInvertTriggered), | ||||
|             ('actionMarkSelected', '', '', tr("Mark Selected"), self.markSelectedTriggered), | ||||
|             ('actionClearIgnoreList', '', '', tr("Clear Ignore List"), self.clearIgnoreListTriggered), | ||||
|             ('actionApplyFilter', 'Ctrl+F', '', tr("Apply Filter"), self.applyFilterTriggered), | ||||
|             ('actionCancelFilter', 'Ctrl+Shift+F', '', tr("Cancel Filter"), self.cancelFilterTriggered), | ||||
|             ('actionExport', '', '', tr("Export To HTML"), self.exportTriggered), | ||||
|             ('actionSaveResults', 'Ctrl+S', '', tr("Save Results..."), self.saveResultsTriggered), | ||||
|             ('actionInvokeCustomCommand', 'Ctrl+Alt+I', '', tr("Invoke Custom Command"), self.app.invokeCustomCommand), | ||||
|         ] | ||||
|         createActions(ACTIONS, self) | ||||
|         self.actionDelta.setCheckable(True) | ||||
| @ -72,17 +73,17 @@ class ResultWindow(QMainWindow): | ||||
|         self.menubar = QMenuBar(self) | ||||
|         self.menubar.setGeometry(QRect(0, 0, 630, 22)) | ||||
|         self.menuFile = QMenu(self.menubar) | ||||
|         self.menuFile.setTitle("File") | ||||
|         self.menuFile.setTitle(tr("File")) | ||||
|         self.menuMark = QMenu(self.menubar) | ||||
|         self.menuMark.setTitle("Mark") | ||||
|         self.menuMark.setTitle(tr("Mark")) | ||||
|         self.menuActions = QMenu(self.menubar) | ||||
|         self.menuActions.setTitle("Actions") | ||||
|         self.menuActions.setTitle(tr("Actions")) | ||||
|         self.menuColumns = QMenu(self.menubar) | ||||
|         self.menuColumns.setTitle("Columns") | ||||
|         self.menuColumns.setTitle(tr("Columns")) | ||||
|         self.menuView = QMenu(self.menubar) | ||||
|         self.menuView.setTitle("View") | ||||
|         self.menuView.setTitle(tr("View")) | ||||
|         self.menuHelp = QMenu(self.menubar) | ||||
|         self.menuHelp.setTitle("Help") | ||||
|         self.menuHelp.setTitle(tr("Help")) | ||||
|         self.setMenuBar(self.menubar) | ||||
|          | ||||
|         self.menuActions.addAction(self.actionDeleteMarked) | ||||
| @ -138,11 +139,11 @@ class ResultWindow(QMainWindow): | ||||
|             action.column_index = index | ||||
|             self._column_actions.append(action) | ||||
|         menu.addSeparator() | ||||
|         action = menu.addAction("Reset to Defaults") | ||||
|         action = menu.addAction(tr("Reset to Defaults")) | ||||
|         action.column_index = -1 | ||||
|          | ||||
|         # Action menu | ||||
|         actionMenu = QMenu('Actions', self.menubar) | ||||
|         actionMenu = QMenu(tr("Actions"), self.menubar) | ||||
|         actionMenu.addAction(self.actionDeleteMarked) | ||||
|         actionMenu.addAction(self.actionHardlinkMarked) | ||||
|         actionMenu.addAction(self.actionMoveMarked) | ||||
| @ -160,7 +161,7 @@ class ResultWindow(QMainWindow): | ||||
|         self.actionActions.setMenu(actionMenu) | ||||
|      | ||||
|     def _setupUi(self): | ||||
|         self.setWindowTitle("dupeGuru Results") | ||||
|         self.setWindowTitle(tr("dupeGuru Results")) | ||||
|         self.resize(630, 514) | ||||
|         self.centralwidget = QWidget(self) | ||||
|         self.verticalLayout_2 = QVBoxLayout(self.centralwidget) | ||||
| @ -222,8 +223,8 @@ class ResultWindow(QMainWindow): | ||||
|         self.app.add_selected_to_ignore_list() | ||||
|      | ||||
|     def applyFilterTriggered(self): | ||||
|         title = "Apply Filter" | ||||
|         msg = "Type the filter you want to apply on your results. See help for details." | ||||
|         title = tr("Apply Filter") | ||||
|         msg = trmsg("TypeFilterMsg") | ||||
|         text = nonone(self._last_filter, '[*]') | ||||
|         answer, ok = QInputDialog.getText(self, title, msg, QLineEdit.Normal, text) | ||||
|         if not ok: | ||||
| @ -236,15 +237,15 @@ class ResultWindow(QMainWindow): | ||||
|         self.app.apply_filter('') | ||||
|      | ||||
|     def clearIgnoreListTriggered(self): | ||||
|         title = "Clear Ignore List" | ||||
|         title = tr("Clear Ignore List") | ||||
|         count = len(self.app.scanner.ignore_list) | ||||
|         if not count: | ||||
|             QMessageBox.information(self, title, "Nothing to clear.") | ||||
|             QMessageBox.information(self, title, trmsg("NothingToClearMsg")) | ||||
|             return | ||||
|         msg = "Do you really want to remove all {0} items from the ignore list?".format(count) | ||||
|         msg = trmsg("ClearIgnoreListConfirmMsg").format(count) | ||||
|         if self.app.confirm(title, msg, QMessageBox.No): | ||||
|             self.app.scanner.ignore_list.Clear() | ||||
|             QMessageBox.information(self, title, "Ignore list cleared.") | ||||
|             QMessageBox.information(self, title, trmsg("IgnoreListClearedMsg")) | ||||
|      | ||||
|     def copyTriggered(self): | ||||
|         self.app.copy_or_move_marked(True) | ||||
| @ -253,8 +254,8 @@ class ResultWindow(QMainWindow): | ||||
|         count = self.app.results.mark_count | ||||
|         if not count: | ||||
|             return | ||||
|         title = "Delete duplicates" | ||||
|         msg = "You are about to send {0} files to the recycle bin. Continue?".format(count) | ||||
|         title = tr("Delete duplicates") | ||||
|         msg = trmsg("SendToTrashConfirmMsg").format(count) | ||||
|         if self.app.confirm(title, msg): | ||||
|             self.app.delete_marked() | ||||
|      | ||||
| @ -278,8 +279,8 @@ class ResultWindow(QMainWindow): | ||||
|         count = self.app.results.mark_count | ||||
|         if not count: | ||||
|             return | ||||
|         title = "Delete and hardlink duplicates" | ||||
|         msg = "You are about to send {0} files to the trash and hardlink them afterwards. Continue?".format(count) | ||||
|         title = tr("Delete and hardlink duplicates") | ||||
|         msg = trmsg("HardlinkConfirmMsg").format(count) | ||||
|         if self.app.confirm(title, msg): | ||||
|             self.app.delete_marked(replace_with_hardlinks=True) | ||||
|      | ||||
| @ -314,8 +315,8 @@ class ResultWindow(QMainWindow): | ||||
|         count = self.app.results.mark_count | ||||
|         if not count: | ||||
|             return | ||||
|         title = "Remove duplicates" | ||||
|         msg = "You are about to remove {0} files from results. Continue?".format(count) | ||||
|         title = tr("Remove duplicates") | ||||
|         msg = trmsg("FileRemovalConfirmMsg").format(count) | ||||
|         if self.app.confirm(title, msg): | ||||
|             self.app.remove_marked() | ||||
|      | ||||
| @ -329,8 +330,8 @@ class ResultWindow(QMainWindow): | ||||
|         self.app.reveal_selected() | ||||
|      | ||||
|     def saveResultsTriggered(self): | ||||
|         title = "Select a file to save your results to" | ||||
|         files = "dupeGuru Results (*.dupeguru)" | ||||
|         title = trmsg("SelectResultToSaveMsg") | ||||
|         files = tr("dupeGuru Results (*.dupeguru)") | ||||
|         destination = QFileDialog.getSaveFileName(self, title, '', files) | ||||
|         if destination: | ||||
|             self.app.save_as(destination) | ||||
|  | ||||
							
								
								
									
										99
									
								
								qt/lang/en.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								qt/lang/en.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,99 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!DOCTYPE TS> | ||||
| <TS version="2.0" language="en_US"> | ||||
| <context> | ||||
| <name>message</name> | ||||
| <message> | ||||
|     <source>TaskHangingMsg</source> | ||||
|     <translation>A previous action is still hanging in there. You can't start a new one yet. Wait a few seconds, then try again.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>IgnoreConfirmMsg</source> | ||||
|     <translation>All selected {} matches are going to be ignored in all subsequent scans. Continue?</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>SelectCopyOrMoveDestinationMsg</source> | ||||
|     <translation>Select a directory to {} marked files to</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>FileRemovalConfirmMsg</source> | ||||
|     <translation>You are about to remove {} files from results. Continue?</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>NoCustomCommandMsg</source> | ||||
|     <translation>You have no custom command set up. Please, set it up in your preferences.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>OperationSuccessMsg</source> | ||||
|     <translation>All files were processed successfully.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>NoDuplicateFoundMsg</source> | ||||
|     <translation>No duplicates found.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>ReallyWantToQuitMsg</source> | ||||
|     <translation>You have unsaved results, do you really want to quit?</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>SelectFolderToAddMsg</source> | ||||
|     <translation>Select a folder to add to the scanning list</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>SelectResultToLoadMsg</source> | ||||
|     <translation>Select a results file to load</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>ReallyWantToContinueMsg</source> | ||||
|     <translation>You have unsaved results, do you really want to continue?</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>NoScannableFileMsg</source> | ||||
|     <translation>The selected folders contain no scannable file.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>ProblemsDuringProcessingMsg</source> | ||||
|     <translation>There were problems processing some (or all) of the files. The cause of these problems are described in the table below. Those files were not removed from your results.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>TypeFilterMsg</source> | ||||
|     <translation>Type the filter you want to apply on your results. See help for details.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>NothingToClearMsg</source> | ||||
|     <translation>Nothing to clear.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>ClearIgnoreListConfirmMsg</source> | ||||
|     <translation>Do you really want to remove all {} items from the ignore list?</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>IgnoreListClearedMsg</source> | ||||
|     <translation>Ignore list cleared.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>SendToTrashConfirmMsg</source> | ||||
|     <translation>You are about to send {} files to the recycle bin. Continue?</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>HardlinkConfirmMsg</source> | ||||
|     <translation>You are about to send {} files to the trash and hardlink them afterwards. Continue?</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>SelectResultToSaveMsg</source> | ||||
|     <translation>Select a file to save your results to</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>NeedsToRestartToApplyLangMsg</source> | ||||
|     <translation>dupeGuru has to restart for language changes to take effect.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>ClearPictureCacheConfirmMsg</source> | ||||
|     <translation>Do you really want to remove all your cached picture analysis?</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>PictureCacheClearedMsg</source> | ||||
|     <translation>Picture cache cleared.</translation> | ||||
| </message> | ||||
| </context> | ||||
| </TS> | ||||
							
								
								
									
										
											BIN
										
									
								
								qt/lang/fr.qm
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								qt/lang/fr.qm
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										524
									
								
								qt/lang/fr.ts
									
									
									
									
									
								
							
							
						
						
									
										524
									
								
								qt/lang/fr.ts
									
									
									
									
									
								
							| @ -4,6 +4,7 @@ | ||||
| <!-- ******** Core ******** --> | ||||
| <context> | ||||
| <name>core</name> | ||||
| <!-- core.* --> | ||||
| <message> | ||||
|     <source>Collecting files to scan</source> | ||||
|     <translation>Collecte des fichiers à scanner</translation> | ||||
| @ -107,5 +108,528 @@ | ||||
|     <source>Sending dupes to the Trash</source> | ||||
|     <translation>Envoi de doublons à la corbeille en cours</translation> | ||||
| </message> | ||||
| 
 | ||||
| <!-- qt.* --> | ||||
| <message> | ||||
|     <source>Sending files to the recycle bin</source> | ||||
|     <translation>Envoi de fichiers à la corbeille</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Quit</source> | ||||
|     <translation>Quitter</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Preferences</source> | ||||
|     <translation>Préférences</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>dupeGuru Help</source> | ||||
|     <translation>Aide dupeGuru</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>About dupeGuru</source> | ||||
|     <translation>À propos de dupeGuru</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Register dupeGuru</source> | ||||
|     <translation>Enregistrer dupeGuru</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Check for Update</source> | ||||
|     <translation>Vérifier les mises à jour</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Open Debug Log</source> | ||||
|     <translation>Ouvrir logs de déboguage</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Add to Ignore List</source> | ||||
|     <translation>Ignorer ces doublons à l'avenir</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>copy</source> | ||||
|     <translation>copier</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>move</source> | ||||
|     <translation>déplacer</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Remove duplicates</source> | ||||
|     <translation>Retirer des doublons</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Custom Command</source> | ||||
|     <translation>Commande personnalisée</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Operation Complete</source> | ||||
|     <translation>Opération complétée</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Scan complete</source> | ||||
|     <translation>Scan complété</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Attribute</source> | ||||
|     <translation>Attribut</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Selected</source> | ||||
|     <translation>Sélectionné</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Reference</source> | ||||
|     <translation>Référence</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Load Results...</source> | ||||
|     <translation>Charger résultats...</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Results Window</source> | ||||
|     <translation>Fenêtre de résultats</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Add Folder...</source> | ||||
|     <translation>Ajouter dossier...</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>File</source> | ||||
|     <translation>Fichier</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>View</source> | ||||
|     <translation>Voir</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Help</source> | ||||
|     <translation>Aide</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Load Recent Results</source> | ||||
|     <translation>Charger résultats récents</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Load Results</source> | ||||
|     <translation>Charger</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Scan</source> | ||||
|     <translation>Scan</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Unsaved results</source> | ||||
|     <translation>Résultats non sauvegardés</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>dupeGuru Results (*.dupeguru)</source> | ||||
|     <translation>Résultats dupeGuru (*.dupeguru)</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Start a new scan</source> | ||||
|     <translation>Commencer un nouveau scan</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Name</source> | ||||
|     <translation>Nom</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>State</source> | ||||
|     <translation>Type</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Normal</source> | ||||
|     <translation>Normal</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Excluded</source> | ||||
|     <translation>Exclus</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Problems!</source> | ||||
|     <translation>Problèmes!</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Reveal Selected</source> | ||||
|     <translation>Révéler Fichier</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Close</source> | ||||
|     <translation>Fermer</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>File Path</source> | ||||
|     <translation>Chemin du fichier</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Error Message</source> | ||||
|     <translation>Message d'erreur</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Details</source> | ||||
|     <translation>Détails</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Actions</source> | ||||
|     <translation>Actions</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Show Dupes Only</source> | ||||
|     <translation>Ne pas montrer les références</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Show Delta Values</source> | ||||
|     <translation>Montrer les valeurs en tant que delta</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Send Marked to Recycle Bin</source> | ||||
|     <translation>Envoyer marqués à la corbeille</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Delete Marked and Replace with Hardlinks</source> | ||||
|     <translation>Remplacer marqués par des hardlinks</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Move Marked to...</source> | ||||
|     <translation>Déplacer marqués vers...</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Copy Marked to...</source> | ||||
|     <translation>Copier marqués vers...</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Remove Marked from Results</source> | ||||
|     <translation>Retirer marqués des résultats</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Remove Selected from Results</source> | ||||
|     <translation>Retirer sélectionnés des résultats</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Add Selected to Ignore List</source> | ||||
|     <translation>Ajouter sélectionnés à la liste de fichiers ignorés</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Make Selected Reference</source> | ||||
|     <translation>Transformer sélectionnés en références</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Open Selected with Default Application</source> | ||||
|     <translation>Ouvrir sélectionné avec l'application par défaut</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Open Containing Folder of Selected</source> | ||||
|     <translation>Ouvrir le dossier contenant le fichier sélectionné</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Rename Selected</source> | ||||
|     <translation>Renommer sélectionné</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Mark All</source> | ||||
|     <translation>Tout marquer</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Mark None</source> | ||||
|     <translation>Tout démarquer</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Invert Marking</source> | ||||
|     <translation>Inverser le marquage</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Mark Selected</source> | ||||
|     <translation>Marquer sélectionnés</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Clear Ignore List</source> | ||||
|     <translation>Vider la liste de fichiers ignorés</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Apply Filter</source> | ||||
|     <translation>Appliquer filtre</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Cancel Filter</source> | ||||
|     <translation>Annuler filtre</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Export To HTML</source> | ||||
|     <translation>Exporter vers HTML</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Save Results...</source> | ||||
|     <translation>Sauvegarder résultats...</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Invoke Custom Command</source> | ||||
|     <translation>Invoquer commande personnalisée</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Mark</source> | ||||
|     <translation>Marquer</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Columns</source> | ||||
|     <translation>Colonnes</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Reset to Defaults</source> | ||||
|     <translation>Réinitialiser</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>dupeGuru Results</source> | ||||
|     <translation>dupeGuru (Résultats)</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Delete duplicates</source> | ||||
|     <translation>Effacement de doublons</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Delete and hardlink duplicates</source> | ||||
|     <translation>Hardlinking de doublons</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Scan Type:</source> | ||||
|     <translation>Type de scan:</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Filename</source> | ||||
|     <translation>Nom de fichier</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Contents</source> | ||||
|     <translation>Contenu</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Filter Hardness:</source> | ||||
|     <translation>Seuil du filtre:</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>More Results</source> | ||||
|     <translation>+ de doublons</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Fewer Results</source> | ||||
|     <translation>- de doublons</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Word weighting</source> | ||||
|     <translation>Proportionalité des mots</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Match similar words</source> | ||||
|     <translation>Comparer les mots similaires</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Can mix file kind</source> | ||||
|     <translation>Comparer les fichiers de différents types</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Use regular expressions when filtering</source> | ||||
|     <translation>Utiliser les expressions régulières pour les filtres</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Remove empty folders on delete or move</source> | ||||
|     <translation>Effacer les dossiers vides après un déplacement</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Ignore files smaller than</source> | ||||
|     <translation>Ignorer les fichiers plus petits que:</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>KB</source> | ||||
|     <translation>KB</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Ignore duplicates hardlinking to the same file</source> | ||||
|     <translation>Ignorer doublons avec hardlink vers le même fichier</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Copy and Move:</source> | ||||
|     <translation>Déplacements de fichiers:</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Right in destination</source> | ||||
|     <translation>Directement à la destination</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Recreate relative path</source> | ||||
|     <translation>Re-créer chemins relatifs</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Recreate absolute path</source> | ||||
|     <translation>Re-créer chemins absolus</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Custom Command (arguments: %d for dupe, %r for ref):</source> | ||||
|     <translation>Commande perso. (arguments: %d pour doublon, %r pour réf):</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Filename - Fields</source> | ||||
|     <translation>Nom de fichier (Champs)</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Filename - Fields (No Order)</source> | ||||
|     <translation>Nom de fichier (Champs sans ordre)</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Tags</source> | ||||
|     <translation>Tags</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Audio Contents</source> | ||||
|     <translation>Contenu Audio</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Tags to scan:</source> | ||||
|     <translation>Tags à scanner:</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Track</source> | ||||
|     <translation>Track</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Artist</source> | ||||
|     <translation>Artiste</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Album</source> | ||||
|     <translation>Album</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Title</source> | ||||
|     <translation>Titre</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Genre</source> | ||||
|     <translation>Genre</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Year</source> | ||||
|     <translation>Année</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Match scaled pictures together</source> | ||||
|     <translation>Comparer les images de taille différente</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Clear Picture Cache</source> | ||||
|     <translation>Vider la cache d'images</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Clear List</source> | ||||
|     <translation>Vider la liste</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>Language:</source> | ||||
|     <translation>Langue:</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>English</source> | ||||
|     <translation>Anglais</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>French</source> | ||||
|     <translation>Français</translation> | ||||
| </message> | ||||
| </context> | ||||
| 
 | ||||
| <!-- ******** Message ******** --> | ||||
| <context> | ||||
| <name>message</name> | ||||
| <message> | ||||
|     <source>TaskHangingMsg</source> | ||||
|     <translation>Une action précédente est encore en cours. Attendez quelques secondes avant d'en repartir une nouvelle.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>IgnoreConfirmMsg</source> | ||||
|     <translation>%d fichiers seront ignorés des prochains scans. Continuer?</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>SelectCopyOrMoveDestinationMsg</source> | ||||
|     <translation>Sélectionnez un dossier vers lequel {} les fichiers marqués.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>FileRemovalConfirmMsg</source> | ||||
|     <translation>{} fichiers seront retirés des résultats. Continuer?</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>NoCustomCommandMsg</source> | ||||
|     <translation>Vous n'avez pas de commande personnalisée. Ajoutez-la dans vos préférences.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>OperationSuccessMsg</source> | ||||
|     <translation>Tous les fichiers ont été traités avec succès.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>NoDuplicateFoundMsg</source> | ||||
|     <translation>Aucun doublon trouvé.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>ReallyWantToQuitMsg</source> | ||||
|     <translation>Vos résultats ne sont pas sauvegardés. Voulez-vous vraiment quitter?</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>SelectFolderToAddMsg</source> | ||||
|     <translation>Sélectionnez un dossier à ajouter à la liste</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>SelectResultToLoadMsg</source> | ||||
|     <translation>Sélectionnez un fichier résultats à charger</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>ReallyWantToContinueMsg</source> | ||||
|     <translation>Vos résultats ne sont pas sauvegardés. Voulez-vous vraiment continuer?</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>NoScannableFileMsg</source> | ||||
|     <translation>Les dossiers sélectionnés ne continnent pas de fichiers valides.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>ProblemsDuringProcessingMsg</source> | ||||
|     <translation>Des problèmes ont été rencontrés lors du traitement de certains fichiers. La nature de ces problèmes est décrite dans la liste ci-dessous. Ces fichiers n'ont pas été retirés des résultats.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>TypeFilterMsg</source> | ||||
|     <translation>Entrer le filtre que vous voulez appliquer sur vos résultats.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>NothingToClearMsg</source> | ||||
|     <translation>Il n'y a rien à vider.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>ClearIgnoreListConfirmMsg</source> | ||||
|     <translation>Voulez-vous vider la liste de fichiers ignorés des {} items qu'elle contient?</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>IgnoreListClearedMsg</source> | ||||
|     <translation>La liste de doublons ignorés a été vidée.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>SendToTrashConfirmMsg</source> | ||||
|     <translation>{} fichiers seront envoyés à la corbeille. Continuer?</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>HardlinkConfirmMsg</source> | ||||
|     <translation>{} fichiers seront envoyés à la corbeille (puis 'hardlinkés'). Continuer?</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>SelectResultToSaveMsg</source> | ||||
|     <translation>Sélectionnez un fichier résultats dans lequel sauvegarder</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>NeedsToRestartToApplyLangMsg</source> | ||||
|     <translation>dupeGuru doit redémarrer pour appliquer le changement de langue.</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>ClearPictureCacheConfirmMsg</source> | ||||
|     <translation>Voulez-vous vraiment vider la cache de vos analyses précédentes?</translation> | ||||
| </message> | ||||
| <message> | ||||
|     <source>PictureCacheClearedMsg</source> | ||||
|     <translation>La cache des analyses précédentes a été vidée.</translation> | ||||
| </message> | ||||
| </context> | ||||
| </TS> | ||||
| @ -6,7 +6,7 @@ | ||||
| # which should be included with this package. The terms are also available at  | ||||
| # http://www.hardcoded.net/licenses/bsd_license | ||||
| 
 | ||||
| from core_me import data, scanner, fs, __version__ | ||||
| from core_me import data, scanner, fs, __appname__ | ||||
| 
 | ||||
| from ..base.app import DupeGuru as DupeGuruBase | ||||
| from .details_dialog import DetailsDialog | ||||
| @ -16,8 +16,7 @@ from .preferences_dialog import PreferencesDialog | ||||
| class DupeGuru(DupeGuruBase): | ||||
|     EDITION = 'me' | ||||
|     LOGO_NAME = 'logo_me' | ||||
|     NAME = 'dupeGuru Music Edition' | ||||
|     VERSION = __version__ | ||||
|     NAME = __appname__ | ||||
|     DELTA_COLUMNS = frozenset([2, 3, 4, 5, 7]) | ||||
|      | ||||
|     def __init__(self): | ||||
|  | ||||
| @ -9,12 +9,13 @@ | ||||
| from PyQt4.QtCore import QSize | ||||
| from PyQt4.QtGui import QVBoxLayout, QAbstractItemView | ||||
| 
 | ||||
| from hscommon.trans import tr | ||||
| from ..base.details_dialog import DetailsDialog as DetailsDialogBase | ||||
| from ..base.details_table import DetailsTable | ||||
| 
 | ||||
| class DetailsDialog(DetailsDialogBase): | ||||
|     def _setupUi(self): | ||||
|         self.setWindowTitle("Details") | ||||
|         self.setWindowTitle(tr("Details")) | ||||
|         self.resize(502, 295) | ||||
|         self.setMinimumSize(QSize(250, 250)) | ||||
|         self.verticalLayout = QVBoxLayout(self) | ||||
|  | ||||
| @ -7,12 +7,14 @@ | ||||
| # http://www.hardcoded.net/licenses/bsd_license | ||||
| 
 | ||||
| import sys | ||||
| from PyQt4.QtCore import SIGNAL, Qt, QSize | ||||
| from PyQt4.QtGui import (QDialog, QDialogButtonBox, QVBoxLayout, QHBoxLayout, QLabel, QComboBox, | ||||
|     QSlider, QSizePolicy, QSpacerItem, QWidget, QCheckBox, QLineEdit, QDialogButtonBox, QApplication) | ||||
| from PyQt4.QtCore import SIGNAL, QSize | ||||
| from PyQt4.QtGui import (QVBoxLayout, QHBoxLayout, QLabel, QComboBox, QSizePolicy, QSpacerItem, | ||||
|     QWidget, QApplication) | ||||
| 
 | ||||
| from hscommon.trans import tr | ||||
| from core.scanner import ScanType | ||||
| 
 | ||||
| from ..base.preferences_dialog import PreferencesDialogBase | ||||
| from . import preferences | ||||
| 
 | ||||
| SCAN_TYPE_ORDER = [ | ||||
| @ -24,169 +26,73 @@ SCAN_TYPE_ORDER = [ | ||||
|     ScanType.ContentsAudio, | ||||
| ] | ||||
| 
 | ||||
| class PreferencesDialog(QDialog): | ||||
| class PreferencesDialog(PreferencesDialogBase): | ||||
|     def __init__(self, parent, app): | ||||
|         flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint | ||||
|         QDialog.__init__(self, parent, flags) | ||||
|         self.app = app | ||||
|         self._setupUi() | ||||
|         PreferencesDialogBase.__init__(self, parent, app) | ||||
|          | ||||
|         self.connect(self.buttonBox, SIGNAL('clicked(QAbstractButton*)'), self.buttonClicked) | ||||
|         self.connect(self.scanTypeComboBox, SIGNAL('currentIndexChanged(int)'), self.scanTypeChanged) | ||||
|         self.connect(self.filterHardnessSlider, SIGNAL("valueChanged(int)"), self.filterHardnessLabel.setNum) | ||||
|         self.buttonBox.accepted.connect(self.accept) | ||||
|         self.buttonBox.rejected.connect(self.reject) | ||||
|      | ||||
|     def _setupUi(self): | ||||
|         self.setWindowTitle("Preferences") | ||||
|         self.resize(325, 360) | ||||
|         self.setSizeGripEnabled(False) | ||||
|         self.setModal(True) | ||||
|         self.verticalLayout_2 = QVBoxLayout(self) | ||||
|         self.verticalLayout = QVBoxLayout() | ||||
|     def _setupPreferenceWidgets(self): | ||||
|         self.horizontalLayout = QHBoxLayout() | ||||
|         self.label_2 = QLabel(self) | ||||
|         self.label_2.setText("Scan Type:") | ||||
|         self.label_2.setText(tr("Scan Type:")) | ||||
|         self.label_2.setMinimumSize(QSize(100, 0)) | ||||
|         self.label_2.setMaximumSize(QSize(100, 16777215)) | ||||
|         self.horizontalLayout.addWidget(self.label_2) | ||||
|         self.scanTypeComboBox = QComboBox(self) | ||||
|         self.scanTypeComboBox.addItem("Filename") | ||||
|         self.scanTypeComboBox.addItem("Filename - Fields") | ||||
|         self.scanTypeComboBox.addItem("Filename - Fields (No Order)") | ||||
|         self.scanTypeComboBox.addItem("Tags") | ||||
|         self.scanTypeComboBox.addItem("Contents") | ||||
|         self.scanTypeComboBox.addItem("Audio Contents") | ||||
|         self.scanTypeComboBox.addItem(tr("Filename")) | ||||
|         self.scanTypeComboBox.addItem(tr("Filename - Fields")) | ||||
|         self.scanTypeComboBox.addItem(tr("Filename - Fields (No Order)")) | ||||
|         self.scanTypeComboBox.addItem(tr("Tags")) | ||||
|         self.scanTypeComboBox.addItem(tr("Contents")) | ||||
|         self.scanTypeComboBox.addItem(tr("Audio Contents")) | ||||
|         self.horizontalLayout.addWidget(self.scanTypeComboBox) | ||||
|         self.verticalLayout.addLayout(self.horizontalLayout) | ||||
|         self.horizontalLayout_3 = QHBoxLayout() | ||||
|         self.label = QLabel(self) | ||||
|         self.label.setText("Filter Hardness:") | ||||
|         self.label.setMinimumSize(QSize(100, 0)) | ||||
|         self.label.setMaximumSize(QSize(100, 16777215)) | ||||
|         self.horizontalLayout_3.addWidget(self.label) | ||||
|         self.verticalLayout_3 = QVBoxLayout() | ||||
|         self.verticalLayout_3.setSpacing(0) | ||||
|         self.horizontalLayout_6 = QHBoxLayout() | ||||
|         self.horizontalLayout_6.setSpacing(12) | ||||
|         self.filterHardnessSlider = QSlider(self) | ||||
|         sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) | ||||
|         sizePolicy.setHorizontalStretch(0) | ||||
|         sizePolicy.setVerticalStretch(0) | ||||
|         sizePolicy.setHeightForWidth(self.filterHardnessSlider.sizePolicy().hasHeightForWidth()) | ||||
|         self.filterHardnessSlider.setSizePolicy(sizePolicy) | ||||
|         self.filterHardnessSlider.setMinimum(1) | ||||
|         self.filterHardnessSlider.setMaximum(100) | ||||
|         self.filterHardnessSlider.setTracking(True) | ||||
|         self.filterHardnessSlider.setOrientation(Qt.Horizontal) | ||||
|         self.horizontalLayout_6.addWidget(self.filterHardnessSlider) | ||||
|         self.filterHardnessLabel = QLabel(self) | ||||
|         self.filterHardnessLabel.setText("100") | ||||
|         self.filterHardnessLabel.setMinimumSize(QSize(21, 0)) | ||||
|         self.horizontalLayout_6.addWidget(self.filterHardnessLabel) | ||||
|         self.verticalLayout_3.addLayout(self.horizontalLayout_6) | ||||
|         self.horizontalLayout_5 = QHBoxLayout() | ||||
|         self.horizontalLayout_5.setContentsMargins(-1, 0, -1, -1) | ||||
|         self.label_4 = QLabel(self) | ||||
|         self.label_4.setText("More Results") | ||||
|         self.horizontalLayout_5.addWidget(self.label_4) | ||||
|         spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) | ||||
|         self.horizontalLayout_5.addItem(spacerItem) | ||||
|         self.label_3 = QLabel(self) | ||||
|         self.label_3.setText("Fewer Results") | ||||
|         self.horizontalLayout_5.addWidget(self.label_3) | ||||
|         self.verticalLayout_3.addLayout(self.horizontalLayout_5) | ||||
|         self.horizontalLayout_3.addLayout(self.verticalLayout_3) | ||||
|         self.verticalLayout.addLayout(self.horizontalLayout_3) | ||||
|         self.widgetsVLayout.addLayout(self.horizontalLayout) | ||||
|         self._setupFilterHardnessBox() | ||||
|         self.widgetsVLayout.addLayout(self.filterHardnessHLayout) | ||||
|         self.widget = QWidget(self) | ||||
|         self.widget.setMinimumSize(QSize(0, 40)) | ||||
|         self.verticalLayout_4 = QVBoxLayout(self.widget) | ||||
|         self.verticalLayout_4.setSpacing(0) | ||||
|         self.verticalLayout_4.setMargin(0) | ||||
|         self.label_6 = QLabel(self.widget) | ||||
|         self.label_6.setText("Tags to scan:") | ||||
|         self.label_6.setText(tr("Tags to scan:")) | ||||
|         self.verticalLayout_4.addWidget(self.label_6) | ||||
|         self.horizontalLayout_2 = QHBoxLayout() | ||||
|         self.horizontalLayout_2.setSpacing(0) | ||||
|         spacerItem1 = QSpacerItem(15, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) | ||||
|         self.horizontalLayout_2.addItem(spacerItem1) | ||||
|         self.tagTrackBox = QCheckBox(self.widget) | ||||
|         self.tagTrackBox.setText("Track") | ||||
|         self._setupAddCheckbox('tagTrackBox', tr("Track"), self.widget) | ||||
|         self.horizontalLayout_2.addWidget(self.tagTrackBox) | ||||
|         self.tagArtistBox = QCheckBox(self.widget) | ||||
|         self.tagArtistBox.setText("Artist") | ||||
|         self._setupAddCheckbox('tagArtistBox', tr("Artist"), self.widget) | ||||
|         self.horizontalLayout_2.addWidget(self.tagArtistBox) | ||||
|         self.tagAlbumBox = QCheckBox(self.widget) | ||||
|         self.tagAlbumBox.setText("Album") | ||||
|         self._setupAddCheckbox('tagAlbumBox', tr("Album"), self.widget) | ||||
|         self.horizontalLayout_2.addWidget(self.tagAlbumBox) | ||||
|         self.tagTitleBox = QCheckBox(self.widget) | ||||
|         self.tagTitleBox.setText("Title") | ||||
|         self._setupAddCheckbox('tagTitleBox', tr("Title"), self.widget) | ||||
|         self.horizontalLayout_2.addWidget(self.tagTitleBox) | ||||
|         self.tagGenreBox = QCheckBox(self.widget) | ||||
|         self.tagGenreBox.setText("Genre") | ||||
|         self._setupAddCheckbox('tagGenreBox', tr("Genre"), self.widget) | ||||
|         self.horizontalLayout_2.addWidget(self.tagGenreBox) | ||||
|         self.tagYearBox = QCheckBox(self.widget) | ||||
|         self.tagYearBox.setText("Year") | ||||
|         self._setupAddCheckbox('tagYearBox', tr("Year"), self.widget) | ||||
|         self.horizontalLayout_2.addWidget(self.tagYearBox) | ||||
|         self.verticalLayout_4.addLayout(self.horizontalLayout_2) | ||||
|         self.verticalLayout.addWidget(self.widget) | ||||
|         self.wordWeightingBox = QCheckBox(self) | ||||
|         self.wordWeightingBox.setText("Word weighting") | ||||
|         self.verticalLayout.addWidget(self.wordWeightingBox) | ||||
|         self.matchSimilarBox = QCheckBox(self) | ||||
|         self.matchSimilarBox.setText("Match similar words") | ||||
|         self.verticalLayout.addWidget(self.matchSimilarBox) | ||||
|         self.mixFileKindBox = QCheckBox(self) | ||||
|         self.mixFileKindBox.setText("Can mix file kind") | ||||
|         self.verticalLayout.addWidget(self.mixFileKindBox) | ||||
|         self.useRegexpBox = QCheckBox(self) | ||||
|         self.useRegexpBox.setText("Use regular expressions when filtering") | ||||
|         self.verticalLayout.addWidget(self.useRegexpBox) | ||||
|         self.removeEmptyFoldersBox = QCheckBox(self) | ||||
|         self.removeEmptyFoldersBox.setText("Remove empty folders on delete or move") | ||||
|         self.verticalLayout.addWidget(self.removeEmptyFoldersBox) | ||||
|         self.ignoreHardlinkMatches = QCheckBox(self) | ||||
|         self.ignoreHardlinkMatches.setText("Ignore duplicates hardlinking to the same file") | ||||
|         self.verticalLayout.addWidget(self.ignoreHardlinkMatches) | ||||
|         self.horizontalLayout_4 = QHBoxLayout() | ||||
|         self.label_5 = QLabel(self) | ||||
|         self.label_5.setText("Copy and Move:") | ||||
|         self.label_5.setMinimumSize(QSize(100, 0)) | ||||
|         self.label_5.setMaximumSize(QSize(100, 16777215)) | ||||
|         self.horizontalLayout_4.addWidget(self.label_5) | ||||
|         self.copyMoveDestinationComboBox = QComboBox(self) | ||||
|         sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) | ||||
|         sizePolicy.setHorizontalStretch(0) | ||||
|         sizePolicy.setVerticalStretch(0) | ||||
|         sizePolicy.setHeightForWidth(self.copyMoveDestinationComboBox.sizePolicy().hasHeightForWidth()) | ||||
|         self.copyMoveDestinationComboBox.setSizePolicy(sizePolicy) | ||||
|         self.copyMoveDestinationComboBox.addItem("Right in destination") | ||||
|         self.copyMoveDestinationComboBox.addItem("Recreate relative path") | ||||
|         self.copyMoveDestinationComboBox.addItem("Recreate absolute path") | ||||
|         self.horizontalLayout_4.addWidget(self.copyMoveDestinationComboBox) | ||||
|         self.verticalLayout.addLayout(self.horizontalLayout_4) | ||||
|         self.label_7 = QLabel(self) | ||||
|         self.label_7.setText("Custom Command (arguments: %d for dupe, %r for ref):") | ||||
|         self.verticalLayout.addWidget(self.label_7) | ||||
|         self.customCommandEdit = QLineEdit(self) | ||||
|         self.verticalLayout.addWidget(self.customCommandEdit) | ||||
|         self.verticalLayout_2.addLayout(self.verticalLayout) | ||||
|         self.buttonBox = QDialogButtonBox(self) | ||||
|         self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok|QDialogButtonBox.RestoreDefaults) | ||||
|         self.verticalLayout_2.addWidget(self.buttonBox) | ||||
|          | ||||
|         if sys.platform not in {'darwin', 'linux2'}: | ||||
|             self.verticalLayout.removeWidget(self.ignoreHardlinkMatches) | ||||
|             self.ignoreHardlinkMatches.setHidden(True) | ||||
|         self.widgetsVLayout.addWidget(self.widget) | ||||
|         self._setupAddCheckbox('wordWeightingBox', tr("Word weighting")) | ||||
|         self.widgetsVLayout.addWidget(self.wordWeightingBox) | ||||
|         self._setupAddCheckbox('matchSimilarBox', tr("Match similar words")) | ||||
|         self.widgetsVLayout.addWidget(self.matchSimilarBox) | ||||
|         self._setupAddCheckbox('mixFileKindBox', tr("Can mix file kind")) | ||||
|         self.widgetsVLayout.addWidget(self.mixFileKindBox) | ||||
|         self._setupAddCheckbox('useRegexpBox', tr("Use regular expressions when filtering")) | ||||
|         self.widgetsVLayout.addWidget(self.useRegexpBox) | ||||
|         self._setupAddCheckbox('removeEmptyFoldersBox', tr("Remove empty folders on delete or move")) | ||||
|         self.widgetsVLayout.addWidget(self.removeEmptyFoldersBox) | ||||
|         self._setupAddCheckbox('ignoreHardlinkMatches', tr("Ignore duplicates hardlinking to the same file")) | ||||
|         self.widgetsVLayout.addWidget(self.ignoreHardlinkMatches) | ||||
|         self._setupBottomPart() | ||||
|      | ||||
|     def load(self, prefs=None): | ||||
|         if prefs is None: | ||||
|             prefs = self.app.prefs | ||||
|         self.filterHardnessSlider.setValue(prefs.filter_hardness) | ||||
|         self.filterHardnessLabel.setNum(prefs.filter_hardness) | ||||
|     def _load(self, prefs, setchecked): | ||||
|         scan_type_index = SCAN_TYPE_ORDER.index(prefs.scan_type) | ||||
|         self.scanTypeComboBox.setCurrentIndex(scan_type_index) | ||||
|         setchecked = lambda cb, b: cb.setCheckState(Qt.Checked if b else Qt.Unchecked) | ||||
|         setchecked(self.tagTrackBox, prefs.scan_tag_track) | ||||
|         setchecked(self.tagArtistBox, prefs.scan_tag_artist) | ||||
|         setchecked(self.tagAlbumBox, prefs.scan_tag_album) | ||||
| @ -195,18 +101,9 @@ class PreferencesDialog(QDialog): | ||||
|         setchecked(self.tagYearBox, prefs.scan_tag_year) | ||||
|         setchecked(self.matchSimilarBox, prefs.match_similar) | ||||
|         setchecked(self.wordWeightingBox, prefs.word_weighting) | ||||
|         setchecked(self.mixFileKindBox, prefs.mix_file_kind) | ||||
|         setchecked(self.ignoreHardlinkMatches, prefs.ignore_hardlink_matches) | ||||
|         setchecked(self.useRegexpBox, prefs.use_regexp) | ||||
|         setchecked(self.removeEmptyFoldersBox, prefs.remove_empty_folders) | ||||
|         self.copyMoveDestinationComboBox.setCurrentIndex(prefs.destination_type) | ||||
|         self.customCommandEdit.setText(prefs.custom_command) | ||||
|      | ||||
|     def save(self): | ||||
|         prefs = self.app.prefs | ||||
|         prefs.filter_hardness = self.filterHardnessSlider.value() | ||||
|     def _save(self, prefs, ischecked): | ||||
|         prefs.scan_type = SCAN_TYPE_ORDER[self.scanTypeComboBox.currentIndex()] | ||||
|         ischecked = lambda cb: cb.checkState() == Qt.Checked | ||||
|         prefs.scan_tag_track = ischecked(self.tagTrackBox) | ||||
|         prefs.scan_tag_artist = ischecked(self.tagArtistBox) | ||||
|         prefs.scan_tag_album = ischecked(self.tagAlbumBox) | ||||
| @ -215,22 +112,11 @@ class PreferencesDialog(QDialog): | ||||
|         prefs.scan_tag_year = ischecked(self.tagYearBox) | ||||
|         prefs.match_similar = ischecked(self.matchSimilarBox) | ||||
|         prefs.word_weighting = ischecked(self.wordWeightingBox) | ||||
|         prefs.mix_file_kind = ischecked(self.mixFileKindBox) | ||||
|         prefs.ignore_hardlink_matches = ischecked(self.ignoreHardlinkMatches) | ||||
|         prefs.use_regexp = ischecked(self.useRegexpBox) | ||||
|         prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox) | ||||
|         prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex() | ||||
|         prefs.custom_command = str(self.customCommandEdit.text()) | ||||
|      | ||||
|     def resetToDefaults(self): | ||||
|         self.load(preferences.Preferences()) | ||||
|      | ||||
|     #--- Events | ||||
|     def buttonClicked(self, button): | ||||
|         role = self.buttonBox.buttonRole(button) | ||||
|         if role == QDialogButtonBox.ResetRole: | ||||
|             self.resetToDefaults() | ||||
|      | ||||
|     def scanTypeChanged(self, index): | ||||
|         scan_type = SCAN_TYPE_ORDER[self.scanTypeComboBox.currentIndex()] | ||||
|         word_based = scan_type in (ScanType.Filename, ScanType.Fields, ScanType.FieldsNoOrder, | ||||
| @ -248,7 +134,6 @@ class PreferencesDialog(QDialog): | ||||
|      | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     import sys | ||||
|     from ..testapp import TestApp | ||||
|     app = QApplication([]) | ||||
|     dgapp = TestApp() | ||||
|  | ||||
| @ -14,7 +14,7 @@ from PyQt4.QtGui import QImage, QImageReader | ||||
| from hscommon.util import get_file_ext | ||||
| 
 | ||||
| from core import fs | ||||
| from core_pe import data as data_pe, __version__ | ||||
| from core_pe import data as data_pe, __appname__ | ||||
| from core_pe.scanner import ScannerPE | ||||
| 
 | ||||
| from ..base.app import DupeGuru as DupeGuruBase | ||||
| @ -58,8 +58,7 @@ class File(fs.File): | ||||
| class DupeGuru(DupeGuruBase): | ||||
|     EDITION = 'pe' | ||||
|     LOGO_NAME = 'logo_pe' | ||||
|     NAME = 'dupeGuru Picture Edition' | ||||
|     VERSION = __version__ | ||||
|     NAME = __appname__ | ||||
|     DELTA_COLUMNS = frozenset([2, 5]) | ||||
|      | ||||
|     def __init__(self): | ||||
|  | ||||
| @ -9,6 +9,7 @@ | ||||
| from PyQt4.QtCore import Qt, QSize | ||||
| from PyQt4.QtGui import QVBoxLayout, QAbstractItemView, QHBoxLayout, QLabel, QSizePolicy, QPixmap | ||||
| 
 | ||||
| from hscommon.trans import tr | ||||
| from ..base.details_dialog import DetailsDialog as DetailsDialogBase | ||||
| from ..base.details_table import DetailsTable | ||||
| 
 | ||||
| @ -19,7 +20,7 @@ class DetailsDialog(DetailsDialogBase): | ||||
|         self.referencePixmap = None | ||||
|      | ||||
|     def _setupUi(self): | ||||
|         self.setWindowTitle("Details") | ||||
|         self.setWindowTitle(tr("Details")) | ||||
|         self.resize(502, 295) | ||||
|         self.setMinimumSize(QSize(250, 250)) | ||||
|         self.verticalLayout = QVBoxLayout(self) | ||||
|  | ||||
| @ -7,148 +7,40 @@ | ||||
| # http://www.hardcoded.net/licenses/bsd_license | ||||
| 
 | ||||
| import sys | ||||
| from PyQt4.QtCore import SIGNAL, Qt, QSize | ||||
| from PyQt4.QtGui import (QDialog, QDialogButtonBox, QVBoxLayout, QHBoxLayout, QLabel, QComboBox, | ||||
|     QSlider, QSizePolicy, QSpacerItem, QWidget, QCheckBox, QLineEdit, QDialogButtonBox, QApplication) | ||||
| from PyQt4.QtGui import QLabel, QApplication | ||||
| 
 | ||||
| from hscommon.trans import tr | ||||
| 
 | ||||
| from ..base.preferences_dialog import PreferencesDialogBase | ||||
| from . import preferences | ||||
| 
 | ||||
| class PreferencesDialog(QDialog): | ||||
|     def __init__(self, parent, app): | ||||
|         flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint | ||||
|         QDialog.__init__(self, parent, flags) | ||||
|         self.app = app | ||||
|         self._setupUi() | ||||
|          | ||||
|         self.connect(self.buttonBox, SIGNAL('clicked(QAbstractButton*)'), self.buttonClicked) | ||||
|         self.connect(self.filterHardnessSlider, SIGNAL("valueChanged(int)"), self.filterHardnessLabel.setNum) | ||||
|         self.buttonBox.accepted.connect(self.accept) | ||||
|         self.buttonBox.rejected.connect(self.reject) | ||||
| class PreferencesDialog(PreferencesDialogBase): | ||||
|     def _setupPreferenceWidgets(self): | ||||
|         self._setupFilterHardnessBox() | ||||
|         self.widgetsVLayout.addLayout(self.filterHardnessHLayout) | ||||
|         self._setupAddCheckbox('matchScaledBox', tr("Match scaled pictures together")) | ||||
|         self.widgetsVLayout.addWidget(self.matchScaledBox) | ||||
|         self._setupAddCheckbox('mixFileKindBox', tr("Can mix file kind")) | ||||
|         self.widgetsVLayout.addWidget(self.mixFileKindBox) | ||||
|         self._setupAddCheckbox('useRegexpBox', tr("Use regular expressions when filtering")) | ||||
|         self.widgetsVLayout.addWidget(self.useRegexpBox) | ||||
|         self._setupAddCheckbox('removeEmptyFoldersBox', tr("Remove empty folders on delete or move")) | ||||
|         self.widgetsVLayout.addWidget(self.removeEmptyFoldersBox) | ||||
|         self._setupAddCheckbox('ignoreHardlinkMatches', tr("Ignore duplicates hardlinking to the same file")) | ||||
|         self.widgetsVLayout.addWidget(self.ignoreHardlinkMatches) | ||||
|         self._setupBottomPart() | ||||
|      | ||||
|     def _setupUi(self): | ||||
|         self.setWindowTitle("Preferences") | ||||
|         self.resize(304, 263) | ||||
|         self.setSizeGripEnabled(False) | ||||
|         self.setModal(True) | ||||
|         self.verticalLayout_2 = QVBoxLayout(self) | ||||
|         self.verticalLayout = QVBoxLayout() | ||||
|         self.horizontalLayout_3 = QHBoxLayout() | ||||
|         self.label = QLabel(self) | ||||
|         self.label.setText("Filter Hardness:") | ||||
|         self.label.setMinimumSize(QSize(0, 0)) | ||||
|         self.horizontalLayout_3.addWidget(self.label) | ||||
|         self.verticalLayout_3 = QVBoxLayout() | ||||
|         self.verticalLayout_3.setSpacing(0) | ||||
|         self.horizontalLayout_6 = QHBoxLayout() | ||||
|         self.horizontalLayout_6.setSpacing(12) | ||||
|         self.filterHardnessSlider = QSlider(self) | ||||
|         sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) | ||||
|         sizePolicy.setHorizontalStretch(0) | ||||
|         sizePolicy.setVerticalStretch(0) | ||||
|         sizePolicy.setHeightForWidth(self.filterHardnessSlider.sizePolicy().hasHeightForWidth()) | ||||
|         self.filterHardnessSlider.setSizePolicy(sizePolicy) | ||||
|         self.filterHardnessSlider.setMinimum(1) | ||||
|         self.filterHardnessSlider.setMaximum(100) | ||||
|         self.filterHardnessSlider.setTracking(True) | ||||
|         self.filterHardnessSlider.setOrientation(Qt.Horizontal) | ||||
|         self.horizontalLayout_6.addWidget(self.filterHardnessSlider) | ||||
|         self.filterHardnessLabel = QLabel(self) | ||||
|         self.filterHardnessLabel.setText("100") | ||||
|         self.filterHardnessLabel.setMinimumSize(QSize(21, 0)) | ||||
|         self.horizontalLayout_6.addWidget(self.filterHardnessLabel) | ||||
|         self.verticalLayout_3.addLayout(self.horizontalLayout_6) | ||||
|         self.horizontalLayout_5 = QHBoxLayout() | ||||
|         self.horizontalLayout_5.setContentsMargins(-1, 0, -1, -1) | ||||
|         self.label_4 = QLabel(self) | ||||
|         self.label_4.setText("More Results") | ||||
|         self.horizontalLayout_5.addWidget(self.label_4) | ||||
|         spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) | ||||
|         self.horizontalLayout_5.addItem(spacerItem) | ||||
|         self.label_3 = QLabel(self) | ||||
|         self.label_3.setText("Fewer Results") | ||||
|         self.horizontalLayout_5.addWidget(self.label_3) | ||||
|         self.verticalLayout_3.addLayout(self.horizontalLayout_5) | ||||
|         self.horizontalLayout_3.addLayout(self.verticalLayout_3) | ||||
|         self.verticalLayout.addLayout(self.horizontalLayout_3) | ||||
|         self.matchScaledBox = QCheckBox(self) | ||||
|         self.matchScaledBox.setText("Match scaled pictures together") | ||||
|         self.verticalLayout.addWidget(self.matchScaledBox) | ||||
|         self.mixFileKindBox = QCheckBox(self) | ||||
|         self.mixFileKindBox.setText("Can mix file kind") | ||||
|         self.verticalLayout.addWidget(self.mixFileKindBox) | ||||
|         self.useRegexpBox = QCheckBox(self) | ||||
|         self.useRegexpBox.setText("Use regular expressions when filtering") | ||||
|         self.verticalLayout.addWidget(self.useRegexpBox) | ||||
|         self.removeEmptyFoldersBox = QCheckBox(self) | ||||
|         self.removeEmptyFoldersBox.setText("Remove empty folders on delete or move") | ||||
|         self.verticalLayout.addWidget(self.removeEmptyFoldersBox) | ||||
|         self.ignoreHardlinkMatches = QCheckBox(self) | ||||
|         self.ignoreHardlinkMatches.setText("Ignore duplicates hardlinking to the same file") | ||||
|         self.verticalLayout.addWidget(self.ignoreHardlinkMatches) | ||||
|         self.horizontalLayout_4 = QHBoxLayout() | ||||
|         self.label_5 = QLabel(self) | ||||
|         self.label_5.setText("Copy and Move:") | ||||
|         self.label_5.setMinimumSize(QSize(0, 0)) | ||||
|         self.horizontalLayout_4.addWidget(self.label_5) | ||||
|         self.copyMoveDestinationComboBox = QComboBox(self) | ||||
|         sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) | ||||
|         sizePolicy.setHorizontalStretch(0) | ||||
|         sizePolicy.setVerticalStretch(0) | ||||
|         sizePolicy.setHeightForWidth(self.copyMoveDestinationComboBox.sizePolicy().hasHeightForWidth()) | ||||
|         self.copyMoveDestinationComboBox.addItem("Right in destination") | ||||
|         self.copyMoveDestinationComboBox.addItem("Recreate relative path") | ||||
|         self.copyMoveDestinationComboBox.addItem("Recreate absolute path") | ||||
|         self.horizontalLayout_4.addWidget(self.copyMoveDestinationComboBox) | ||||
|         self.verticalLayout.addLayout(self.horizontalLayout_4) | ||||
|         self.label_2 = QLabel(self) | ||||
|         self.label_2.setText("Custom Command (arguments: %d for dupe %r for ref):") | ||||
|         self.verticalLayout.addWidget(self.label_2) | ||||
|         self.customCommandEdit = QLineEdit(self) | ||||
|         self.verticalLayout.addWidget(self.customCommandEdit) | ||||
|         self.verticalLayout_2.addLayout(self.verticalLayout) | ||||
|         self.buttonBox = QDialogButtonBox(self) | ||||
|         self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok|QDialogButtonBox.RestoreDefaults) | ||||
|         self.verticalLayout_2.addWidget(self.buttonBox) | ||||
|         if sys.platform not in {'darwin', 'linux2'}: | ||||
|             self.verticalLayout.removeWidget(self.ignoreHardlinkMatches) | ||||
|             self.ignoreHardlinkMatches.setHidden(True) | ||||
|      | ||||
|     def load(self, prefs=None): | ||||
|         if prefs is None: | ||||
|             prefs = self.app.prefs | ||||
|         self.filterHardnessSlider.setValue(prefs.filter_hardness) | ||||
|         self.filterHardnessLabel.setNum(prefs.filter_hardness) | ||||
|         setchecked = lambda cb, b: cb.setCheckState(Qt.Checked if b else Qt.Unchecked) | ||||
|     def _load(self, prefs, setchecked): | ||||
|         setchecked(self.matchScaledBox, prefs.match_scaled) | ||||
|         setchecked(self.mixFileKindBox, prefs.mix_file_kind) | ||||
|         setchecked(self.useRegexpBox, prefs.use_regexp) | ||||
|         setchecked(self.removeEmptyFoldersBox, prefs.remove_empty_folders) | ||||
|         self.copyMoveDestinationComboBox.setCurrentIndex(prefs.destination_type) | ||||
|         self.customCommandEdit.setText(prefs.custom_command) | ||||
|      | ||||
|     def save(self): | ||||
|         prefs = self.app.prefs | ||||
|         prefs.filter_hardness = self.filterHardnessSlider.value() | ||||
|         ischecked = lambda cb: cb.checkState() == Qt.Checked | ||||
|     def _save(self, prefs, ischecked): | ||||
|         prefs.match_scaled = ischecked(self.matchScaledBox) | ||||
|         prefs.mix_file_kind = ischecked(self.mixFileKindBox) | ||||
|         prefs.use_regexp = ischecked(self.useRegexpBox) | ||||
|         prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox) | ||||
|         prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex() | ||||
|         prefs.custom_command = str(self.customCommandEdit.text()) | ||||
|      | ||||
|     def resetToDefaults(self): | ||||
|         self.load(preferences.Preferences()) | ||||
|      | ||||
|     #--- Events | ||||
|     def buttonClicked(self, button): | ||||
|         role = self.buttonBox.buttonRole(button) | ||||
|         if role == QDialogButtonBox.ResetRole: | ||||
|             self.resetToDefaults() | ||||
|      | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     import sys | ||||
|     from ..testapp import TestApp | ||||
|     app = QApplication([]) | ||||
|     dgapp = TestApp() | ||||
|  | ||||
| @ -9,19 +9,20 @@ | ||||
| from PyQt4.QtCore import SIGNAL | ||||
| from PyQt4.QtGui import QMessageBox, QAction | ||||
| 
 | ||||
| from hscommon.trans import tr, trmsg | ||||
| from ..base.result_window import ResultWindow as ResultWindowBase | ||||
| 
 | ||||
| class ResultWindow(ResultWindowBase): | ||||
|     def _setupUi(self): | ||||
|         ResultWindowBase._setupUi(self) | ||||
|         self.actionClearPictureCache = QAction("Clear Picture Cache", self) | ||||
|         self.actionClearPictureCache = QAction(tr("Clear Picture Cache"), self) | ||||
|         self.menuFile.insertAction(self.actionClearIgnoreList, self.actionClearPictureCache) | ||||
|         self.connect(self.actionClearPictureCache, SIGNAL("triggered()"), self.clearPictureCacheTriggered) | ||||
|      | ||||
|     def clearPictureCacheTriggered(self): | ||||
|         title = "Clear Picture Cache" | ||||
|         msg = "Do you really want to remove all your cached picture analysis?" | ||||
|         title = tr("Clear Picture Cache") | ||||
|         msg = trmsg("ClearPictureCacheConfirmMsg") | ||||
|         if self.app.confirm(title, msg, QMessageBox.No): | ||||
|             self.app.scanner.clear_picture_cache() | ||||
|             QMessageBox.information(self, title, "Picture cache cleared.") | ||||
|             QMessageBox.information(self, title, trmsg("PictureCacheClearedMsg")) | ||||
|      | ||||
| @ -6,7 +6,7 @@ | ||||
| # which should be included with this package. The terms are also available at  | ||||
| # http://www.hardcoded.net/licenses/bsd_license | ||||
| 
 | ||||
| from core_se import data, __version__ | ||||
| from core_se import data, __appname__ | ||||
| from core.directories import Directories as DirectoriesBase, STATE_EXCLUDED | ||||
| 
 | ||||
| from ..base.app import DupeGuru as DupeGuruBase | ||||
| @ -26,8 +26,7 @@ class Directories(DirectoriesBase): | ||||
| class DupeGuru(DupeGuruBase): | ||||
|     EDITION = 'se' | ||||
|     LOGO_NAME = 'logo_se' | ||||
|     NAME = 'dupeGuru' | ||||
|     VERSION = __version__ | ||||
|     NAME = __appname__ | ||||
|     DELTA_COLUMNS = frozenset([2, 4]) | ||||
|      | ||||
|     def __init__(self): | ||||
|  | ||||
| @ -9,12 +9,13 @@ | ||||
| from PyQt4.QtCore import QSize | ||||
| from PyQt4.QtGui import QVBoxLayout, QAbstractItemView | ||||
| 
 | ||||
| from hscommon.trans import tr | ||||
| from ..base.details_dialog import DetailsDialog as DetailsDialogBase | ||||
| from ..base.details_table import DetailsTable | ||||
| 
 | ||||
| class DetailsDialog(DetailsDialogBase): | ||||
|     def _setupUi(self): | ||||
|         self.setWindowTitle("Details") | ||||
|         self.setWindowTitle(tr("Details")) | ||||
|         self.resize(502, 186) | ||||
|         self.setMinimumSize(QSize(200, 0)) | ||||
|         self.verticalLayout = QVBoxLayout(self) | ||||
|  | ||||
| @ -7,14 +7,16 @@ | ||||
| # http://www.hardcoded.net/licenses/bsd_license | ||||
| 
 | ||||
| import sys | ||||
| from PyQt4.QtCore import SIGNAL, Qt, QSize | ||||
| from PyQt4.QtGui import (QDialog, QDialogButtonBox, QVBoxLayout, QHBoxLayout, QLabel, QComboBox, | ||||
|     QSlider, QSizePolicy, QSpacerItem, QWidget, QCheckBox, QLineEdit, QDialogButtonBox, QApplication) | ||||
| from PyQt4.QtCore import SIGNAL, QSize | ||||
| from PyQt4.QtGui import (QVBoxLayout, QHBoxLayout, QLabel, QComboBox, QSizePolicy, QSpacerItem, | ||||
|     QWidget, QLineEdit, QApplication) | ||||
| 
 | ||||
| from hscommon.trans import tr | ||||
| from hscommon.util import tryint | ||||
| 
 | ||||
| from core.scanner import ScanType | ||||
| 
 | ||||
| from ..base.preferences_dialog import PreferencesDialogBase | ||||
| from . import preferences | ||||
| 
 | ||||
| SCAN_TYPE_ORDER = [ | ||||
| @ -22,97 +24,41 @@ SCAN_TYPE_ORDER = [ | ||||
|     ScanType.Contents, | ||||
| ] | ||||
| 
 | ||||
| class PreferencesDialog(QDialog): | ||||
| class PreferencesDialog(PreferencesDialogBase): | ||||
|     def __init__(self, parent, app): | ||||
|         flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint | ||||
|         QDialog.__init__(self, parent, flags) | ||||
|         self.app = app | ||||
|         self._setupUi() | ||||
|         PreferencesDialogBase.__init__(self, parent, app) | ||||
|          | ||||
|         self.connect(self.buttonBox, SIGNAL('clicked(QAbstractButton*)'), self.buttonClicked) | ||||
|         self.connect(self.scanTypeComboBox, SIGNAL('currentIndexChanged(int)'), self.scanTypeChanged) | ||||
|         self.connect(self.filterHardnessSlider, SIGNAL("valueChanged(int)"), self.filterHardnessLabel.setNum) | ||||
|         self.buttonBox.accepted.connect(self.accept) | ||||
|         self.buttonBox.rejected.connect(self.reject) | ||||
|      | ||||
|     def _setupUi(self): | ||||
|         self.setWindowTitle("Preferences") | ||||
|         self.resize(308, 361) | ||||
|         self.setSizeGripEnabled(False) | ||||
|         self.setModal(True) | ||||
|         self.verticalLayout_2 = QVBoxLayout(self) | ||||
|         self.verticalLayout = QVBoxLayout() | ||||
|     def _setupPreferenceWidgets(self): | ||||
|         self.horizontalLayout = QHBoxLayout() | ||||
|         self.label_2 = QLabel(self) | ||||
|         self.label_2.setText("Scan Type:") | ||||
|         self.label_2.setText(tr("Scan Type:")) | ||||
|         self.label_2.setMinimumSize(QSize(100, 0)) | ||||
|         self.label_2.setMaximumSize(QSize(100, 16777215)) | ||||
|         self.horizontalLayout.addWidget(self.label_2) | ||||
|         self.scanTypeComboBox = QComboBox(self) | ||||
|         self.scanTypeComboBox.addItem("Filename") | ||||
|         self.scanTypeComboBox.addItem("Contents") | ||||
|         self.scanTypeComboBox.addItem(tr("Filename")) | ||||
|         self.scanTypeComboBox.addItem(tr("Contents")) | ||||
|         self.horizontalLayout.addWidget(self.scanTypeComboBox) | ||||
|         self.verticalLayout.addLayout(self.horizontalLayout) | ||||
|         self.horizontalLayout_3 = QHBoxLayout() | ||||
|         self.label = QLabel(self) | ||||
|         self.label.setText("Filter Hardness:") | ||||
|         self.label.setMinimumSize(QSize(100, 0)) | ||||
|         self.label.setMaximumSize(QSize(100, 16777215)) | ||||
|         self.horizontalLayout_3.addWidget(self.label) | ||||
|         self.verticalLayout_3 = QVBoxLayout() | ||||
|         self.verticalLayout_3.setSpacing(0) | ||||
|         self.horizontalLayout_6 = QHBoxLayout() | ||||
|         self.horizontalLayout_6.setSpacing(12) | ||||
|         self.filterHardnessSlider = QSlider(self) | ||||
|         sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) | ||||
|         sizePolicy.setHorizontalStretch(0) | ||||
|         sizePolicy.setVerticalStretch(0) | ||||
|         sizePolicy.setHeightForWidth(self.filterHardnessSlider.sizePolicy().hasHeightForWidth()) | ||||
|         self.filterHardnessSlider.setSizePolicy(sizePolicy) | ||||
|         self.filterHardnessSlider.setMinimum(1) | ||||
|         self.filterHardnessSlider.setMaximum(100) | ||||
|         self.filterHardnessSlider.setTracking(True) | ||||
|         self.filterHardnessSlider.setOrientation(Qt.Horizontal) | ||||
|         self.horizontalLayout_6.addWidget(self.filterHardnessSlider) | ||||
|         self.filterHardnessLabel = QLabel(self) | ||||
|         self.filterHardnessLabel.setText("100") | ||||
|         self.filterHardnessLabel.setMinimumSize(QSize(21, 0)) | ||||
|         self.horizontalLayout_6.addWidget(self.filterHardnessLabel) | ||||
|         self.verticalLayout_3.addLayout(self.horizontalLayout_6) | ||||
|         self.horizontalLayout_5 = QHBoxLayout() | ||||
|         self.horizontalLayout_5.setContentsMargins(-1, 0, -1, -1) | ||||
|         self.label_4 = QLabel(self) | ||||
|         self.label_4.setText("More Results") | ||||
|         self.horizontalLayout_5.addWidget(self.label_4) | ||||
|         spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) | ||||
|         self.horizontalLayout_5.addItem(spacerItem) | ||||
|         self.label_3 = QLabel(self) | ||||
|         self.label_3.setText("Fewer Results") | ||||
|         self.horizontalLayout_5.addWidget(self.label_3) | ||||
|         self.verticalLayout_3.addLayout(self.horizontalLayout_5) | ||||
|         self.horizontalLayout_3.addLayout(self.verticalLayout_3) | ||||
|         self.verticalLayout.addLayout(self.horizontalLayout_3) | ||||
|         self.widgetsVLayout.addLayout(self.horizontalLayout) | ||||
|         self._setupFilterHardnessBox() | ||||
|         self.widgetsVLayout.addLayout(self.filterHardnessHLayout) | ||||
|         self.widget = QWidget(self) | ||||
|         self.widget.setMinimumSize(QSize(0, 136)) | ||||
|         self.verticalLayout_4 = QVBoxLayout(self.widget) | ||||
|         self.wordWeightingBox = QCheckBox(self.widget) | ||||
|         self.wordWeightingBox.setText("Word weighting") | ||||
|         self._setupAddCheckbox('wordWeightingBox', tr("Word weighting"), self.widget) | ||||
|         self.verticalLayout_4.addWidget(self.wordWeightingBox) | ||||
|         self.matchSimilarBox = QCheckBox(self.widget) | ||||
|         self.matchSimilarBox.setText("Match similar words") | ||||
|         self._setupAddCheckbox('matchSimilarBox', tr("Match similar words"), self.widget) | ||||
|         self.verticalLayout_4.addWidget(self.matchSimilarBox) | ||||
|         self.mixFileKindBox = QCheckBox(self.widget) | ||||
|         self.mixFileKindBox.setText("Can mix file kind") | ||||
|         self._setupAddCheckbox('mixFileKindBox', tr("Can mix file kind"), self.widget) | ||||
|         self.verticalLayout_4.addWidget(self.mixFileKindBox) | ||||
|         self.useRegexpBox = QCheckBox(self.widget) | ||||
|         self.useRegexpBox.setText("Use regular expressions when filtering") | ||||
|         self._setupAddCheckbox('useRegexpBox', tr("Use regular expressions when filtering"), self.widget) | ||||
|         self.verticalLayout_4.addWidget(self.useRegexpBox) | ||||
|         self.removeEmptyFoldersBox = QCheckBox(self.widget) | ||||
|         self.removeEmptyFoldersBox.setText("Remove empty folders on delete or move") | ||||
|         self._setupAddCheckbox('removeEmptyFoldersBox', tr("Remove empty folders on delete or move"), self.widget) | ||||
|         self.verticalLayout_4.addWidget(self.removeEmptyFoldersBox) | ||||
|         self.horizontalLayout_2 = QHBoxLayout() | ||||
|         self.ignoreSmallFilesBox = QCheckBox(self.widget) | ||||
|         self.ignoreSmallFilesBox.setText("Ignore files smaller than") | ||||
|         self._setupAddCheckbox('ignoreSmallFilesBox', tr("Ignore files smaller than"), self.widget) | ||||
|         self.horizontalLayout_2.addWidget(self.ignoreSmallFilesBox) | ||||
|         self.sizeThresholdEdit = QLineEdit(self.widget) | ||||
|         sizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) | ||||
| @ -123,94 +69,43 @@ class PreferencesDialog(QDialog): | ||||
|         self.sizeThresholdEdit.setMaximumSize(QSize(50, 16777215)) | ||||
|         self.horizontalLayout_2.addWidget(self.sizeThresholdEdit) | ||||
|         self.label_6 = QLabel(self.widget) | ||||
|         self.label_6.setText("KB") | ||||
|         self.label_6.setText(tr("KB")) | ||||
|         self.horizontalLayout_2.addWidget(self.label_6) | ||||
|         spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) | ||||
|         self.horizontalLayout_2.addItem(spacerItem1) | ||||
|         self.verticalLayout_4.addLayout(self.horizontalLayout_2) | ||||
|         self.ignoreHardlinkMatches = QCheckBox(self.widget) | ||||
|         self.ignoreHardlinkMatches.setText("Ignore duplicates hardlinking to the same file") | ||||
|         self._setupAddCheckbox('ignoreHardlinkMatches', tr("Ignore duplicates hardlinking to the same file"), self.widget) | ||||
|         self.verticalLayout_4.addWidget(self.ignoreHardlinkMatches) | ||||
|         self.verticalLayout.addWidget(self.widget) | ||||
|         self.horizontalLayout_4 = QHBoxLayout() | ||||
|         self.label_5 = QLabel(self) | ||||
|         self.label_5.setText("Copy and Move:") | ||||
|         self.label_5.setMinimumSize(QSize(100, 0)) | ||||
|         self.label_5.setMaximumSize(QSize(100, 16777215)) | ||||
|         self.horizontalLayout_4.addWidget(self.label_5) | ||||
|         self.copyMoveDestinationComboBox = QComboBox(self) | ||||
|         sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) | ||||
|         sizePolicy.setHorizontalStretch(0) | ||||
|         sizePolicy.setVerticalStretch(0) | ||||
|         sizePolicy.setHeightForWidth(self.copyMoveDestinationComboBox.sizePolicy().hasHeightForWidth()) | ||||
|         self.copyMoveDestinationComboBox.setSizePolicy(sizePolicy) | ||||
|         self.copyMoveDestinationComboBox.addItem("Right in destination") | ||||
|         self.copyMoveDestinationComboBox.addItem("Recreate relative path") | ||||
|         self.copyMoveDestinationComboBox.addItem("Recreate absolute path") | ||||
|         self.horizontalLayout_4.addWidget(self.copyMoveDestinationComboBox) | ||||
|         self.verticalLayout.addLayout(self.horizontalLayout_4) | ||||
|         self.label_7 = QLabel(self) | ||||
|         self.label_7.setText("Custom Command (arguments: %d for dupe, %r for ref):") | ||||
|         self.verticalLayout.addWidget(self.label_7) | ||||
|         self.customCommandEdit = QLineEdit(self) | ||||
|         self.verticalLayout.addWidget(self.customCommandEdit) | ||||
|         self.verticalLayout_2.addLayout(self.verticalLayout) | ||||
|         self.buttonBox = QDialogButtonBox(self) | ||||
|         self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok|QDialogButtonBox.RestoreDefaults) | ||||
|         self.verticalLayout_2.addWidget(self.buttonBox) | ||||
|         self.widgetsVLayout.addWidget(self.widget) | ||||
|         self._setupBottomPart() | ||||
|      | ||||
|     def _setupUi(self): | ||||
|         PreferencesDialogBase._setupUi(self) | ||||
|          | ||||
|         if sys.platform not in {'darwin', 'linux2'}: | ||||
|             self.verticalLayout_4.removeWidget(self.ignoreHardlinkMatches) | ||||
|             self.ignoreHardlinkMatches.setHidden(True) | ||||
|         if sys.platform == 'linux2': | ||||
|             # Under linux, whether it's a Qt layout bug or something else, the size threshold text edit | ||||
|             # doesn't have enough space, so we make the pref pane higher to compensate. | ||||
|             self.resize(self.width(), 400) | ||||
|      | ||||
|     def load(self, prefs=None): | ||||
|         if prefs is None: | ||||
|             prefs = self.app.prefs | ||||
|         self.filterHardnessSlider.setValue(prefs.filter_hardness) | ||||
|         self.filterHardnessLabel.setNum(prefs.filter_hardness) | ||||
|     def _load(self, prefs, setchecked): | ||||
|         scan_type_index = SCAN_TYPE_ORDER.index(prefs.scan_type) | ||||
|         self.scanTypeComboBox.setCurrentIndex(scan_type_index) | ||||
|         setchecked = lambda cb, b: cb.setCheckState(Qt.Checked if b else Qt.Unchecked) | ||||
|         setchecked(self.matchSimilarBox, prefs.match_similar) | ||||
|         setchecked(self.wordWeightingBox, prefs.word_weighting) | ||||
|         setchecked(self.mixFileKindBox, prefs.mix_file_kind) | ||||
|         setchecked(self.ignoreHardlinkMatches, prefs.ignore_hardlink_matches) | ||||
|         setchecked(self.useRegexpBox, prefs.use_regexp) | ||||
|         setchecked(self.removeEmptyFoldersBox, prefs.remove_empty_folders) | ||||
|         setchecked(self.ignoreSmallFilesBox, prefs.ignore_small_files) | ||||
|         self.sizeThresholdEdit.setText(str(prefs.small_file_threshold)) | ||||
|         self.copyMoveDestinationComboBox.setCurrentIndex(prefs.destination_type) | ||||
|         self.customCommandEdit.setText(prefs.custom_command) | ||||
|      | ||||
|     def save(self): | ||||
|         prefs = self.app.prefs | ||||
|         prefs.filter_hardness = self.filterHardnessSlider.value() | ||||
|     def _save(self, prefs, ischecked): | ||||
|         prefs.scan_type = SCAN_TYPE_ORDER[self.scanTypeComboBox.currentIndex()] | ||||
|         ischecked = lambda cb: cb.checkState() == Qt.Checked | ||||
|         prefs.match_similar = ischecked(self.matchSimilarBox) | ||||
|         prefs.word_weighting = ischecked(self.wordWeightingBox) | ||||
|         prefs.mix_file_kind = ischecked(self.mixFileKindBox) | ||||
|         prefs.ignore_hardlink_matches = ischecked(self.ignoreHardlinkMatches) | ||||
|         prefs.use_regexp = ischecked(self.useRegexpBox) | ||||
|         prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox) | ||||
|         prefs.ignore_small_files = ischecked(self.ignoreSmallFilesBox) | ||||
|         prefs.small_file_threshold = tryint(self.sizeThresholdEdit.text()) | ||||
|         prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex() | ||||
|         prefs.custom_command = str(self.customCommandEdit.text()) | ||||
|      | ||||
|     def resetToDefaults(self): | ||||
|         self.load(preferences.Preferences()) | ||||
|      | ||||
|     #--- Events | ||||
|     def buttonClicked(self, button): | ||||
|         role = self.buttonBox.buttonRole(button) | ||||
|         if role == QDialogButtonBox.ResetRole: | ||||
|             self.resetToDefaults() | ||||
|      | ||||
|     def scanTypeChanged(self, index): | ||||
|         scan_type = SCAN_TYPE_ORDER[self.scanTypeComboBox.currentIndex()] | ||||
|         word_based = scan_type == ScanType.Filename | ||||
|  | ||||
| @ -15,12 +15,16 @@ from PyQt4.QtGui import QApplication, QIcon, QPixmap | ||||
| from hscommon.trans import install_qt_trans | ||||
| from qtlib.error_report_dialog import install_excepthook | ||||
| from qt.base import dg_rc | ||||
| from core_{{edition}} import __version__, __appname__ | ||||
| 
 | ||||
| if sys.platform == 'win32': | ||||
|     import qt.base.cxfreeze_fix | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|     app = QApplication(sys.argv) | ||||
|     QCoreApplication.setOrganizationName('Hardcoded Software') | ||||
|     QCoreApplication.setApplicationName(__appname__) | ||||
|     QCoreApplication.setApplicationVersion(__version__) | ||||
|     settings = QSettings() | ||||
|     lang = settings.value('Language').toString() | ||||
|     install_qt_trans(lang) | ||||
| @ -28,9 +32,6 @@ if __name__ == "__main__": | ||||
|     # has been installed | ||||
|     from qt.{{edition}}.app import DupeGuru | ||||
|     app.setWindowIcon(QIcon(QPixmap(":/{0}".format(DupeGuru.LOGO_NAME)))) | ||||
|     QCoreApplication.setOrganizationName('Hardcoded Software') | ||||
|     QCoreApplication.setApplicationName(DupeGuru.NAME) | ||||
|     QCoreApplication.setApplicationVersion(DupeGuru.VERSION) | ||||
|     dgapp = DupeGuru() | ||||
|     install_excepthook() | ||||
|     sys.exit(app.exec_()) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user