mirror of
https://github.com/arsenetar/dupeguru.git
synced 2025-03-10 05:34:36 +00:00
The Qt side now makes use of core.gui.details_panel.
This commit is contained in:
parent
484512e35b
commit
8dda616502
11
core/app.py
11
core/app.py
@ -17,6 +17,7 @@ from hsutil import io, files
|
|||||||
from hsutil.path import Path
|
from hsutil.path import Path
|
||||||
from hsutil.reg import RegistrableApplication, RegistrationRequired
|
from hsutil.reg import RegistrableApplication, RegistrationRequired
|
||||||
from hsutil.misc import flatten, first
|
from hsutil.misc import flatten, first
|
||||||
|
from hsutil.notify import Broadcaster
|
||||||
from hsutil.str import escape
|
from hsutil.str import escape
|
||||||
|
|
||||||
from . import directories, results, scanner, export, fs
|
from . import directories, results, scanner, export, fs
|
||||||
@ -33,11 +34,12 @@ class NoScannableFileError(Exception):
|
|||||||
class AllFilesAreRefError(Exception):
|
class AllFilesAreRefError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class DupeGuru(RegistrableApplication):
|
class DupeGuru(RegistrableApplication, Broadcaster):
|
||||||
DEMO_LIMIT_DESC = "In the demo version, only 10 duplicates per session can be sent to the recycle bin, moved or copied."
|
DEMO_LIMIT_DESC = "In the demo version, only 10 duplicates per session can be sent to the recycle bin, moved or copied."
|
||||||
|
|
||||||
def __init__(self, data_module, appdata, appid):
|
def __init__(self, data_module, appdata, appid):
|
||||||
RegistrableApplication.__init__(self, appid)
|
RegistrableApplication.__init__(self, appid)
|
||||||
|
Broadcaster.__init__(self)
|
||||||
self.appdata = appdata
|
self.appdata = appdata
|
||||||
if not op.exists(self.appdata):
|
if not op.exists(self.appdata):
|
||||||
os.makedirs(self.appdata)
|
os.makedirs(self.appdata)
|
||||||
@ -51,6 +53,7 @@ class DupeGuru(RegistrableApplication):
|
|||||||
'escape_filter_regexp': True,
|
'escape_filter_regexp': True,
|
||||||
'clean_empty_dirs': False,
|
'clean_empty_dirs': False,
|
||||||
}
|
}
|
||||||
|
self.selected_dupes = []
|
||||||
|
|
||||||
def _demo_check(self):
|
def _demo_check(self):
|
||||||
if self.registered:
|
if self.registered:
|
||||||
@ -104,6 +107,12 @@ class DupeGuru(RegistrableApplication):
|
|||||||
def _recycle_dupe(dupe):
|
def _recycle_dupe(dupe):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def _select_dupes(self, dupes):
|
||||||
|
if dupes == self.selected_dupes:
|
||||||
|
return
|
||||||
|
self.selected_dupes = dupes
|
||||||
|
self.notify('dupes_selected')
|
||||||
|
|
||||||
def _start_job(self, jobid, func):
|
def _start_job(self, jobid, func):
|
||||||
# func(j)
|
# func(j)
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
@ -15,7 +15,6 @@ from hsutil.cocoa.objcmin import (NSNotificationCenter, NSUserDefaults,
|
|||||||
NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSUserDomainMask,
|
NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSUserDomainMask,
|
||||||
NSWorkspace, NSWorkspaceRecycleOperation)
|
NSWorkspace, NSWorkspaceRecycleOperation)
|
||||||
from hsutil.misc import stripnone
|
from hsutil.misc import stripnone
|
||||||
from hsutil.notify import Broadcaster
|
|
||||||
from hsutil.reg import RegistrationRequired
|
from hsutil.reg import RegistrationRequired
|
||||||
|
|
||||||
from . import app, fs
|
from . import app, fs
|
||||||
@ -37,9 +36,8 @@ def demo_method(method):
|
|||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
class DupeGuru(app.DupeGuru, Broadcaster):
|
class DupeGuru(app.DupeGuru):
|
||||||
def __init__(self, data_module, appdata_subdir, appid):
|
def __init__(self, data_module, appdata_subdir, appid):
|
||||||
Broadcaster.__init__(self)
|
|
||||||
LOGGING_LEVEL = logging.DEBUG if NSUserDefaults.standardUserDefaults().boolForKey_('debug') else logging.WARNING
|
LOGGING_LEVEL = logging.DEBUG if NSUserDefaults.standardUserDefaults().boolForKey_('debug') else logging.WARNING
|
||||||
logging.basicConfig(level=LOGGING_LEVEL, format='%(levelname)s %(message)s')
|
logging.basicConfig(level=LOGGING_LEVEL, format='%(levelname)s %(message)s')
|
||||||
logging.debug('started in debug mode')
|
logging.debug('started in debug mode')
|
||||||
@ -49,7 +47,6 @@ class DupeGuru(app.DupeGuru, Broadcaster):
|
|||||||
app.DupeGuru.__init__(self, data_module, appdata, appid)
|
app.DupeGuru.__init__(self, data_module, appdata, appid)
|
||||||
self.progress = cocoa.ThreadedJobPerformer()
|
self.progress = cocoa.ThreadedJobPerformer()
|
||||||
self.display_delta_values = False
|
self.display_delta_values = False
|
||||||
self.selected_dupes = []
|
|
||||||
|
|
||||||
#--- Override
|
#--- Override
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -92,12 +89,6 @@ class DupeGuru(app.DupeGuru, Broadcaster):
|
|||||||
curr_path = self.directories.get_subfolders(curr_path)[current_index]
|
curr_path = self.directories.get_subfolders(curr_path)[current_index]
|
||||||
return self.get_folder_path(node_path[1:], curr_path)
|
return self.get_folder_path(node_path[1:], curr_path)
|
||||||
|
|
||||||
def _select_dupes(self, dupes):
|
|
||||||
if dupes == self.selected_dupes:
|
|
||||||
return
|
|
||||||
self.selected_dupes = dupes
|
|
||||||
self.notify('dupes_selected')
|
|
||||||
|
|
||||||
#---Public
|
#---Public
|
||||||
def AddSelectedToIgnoreList(self):
|
def AddSelectedToIgnoreList(self):
|
||||||
for dupe in self.selected_dupes:
|
for dupe in self.selected_dupes:
|
||||||
|
@ -65,7 +65,6 @@ class DupeGuru(DupeGuruBase, QObject):
|
|||||||
|
|
||||||
#--- Private
|
#--- Private
|
||||||
def _setup(self):
|
def _setup(self):
|
||||||
self.selected_dupe = None
|
|
||||||
self.prefs = self._create_preferences()
|
self.prefs = self._create_preferences()
|
||||||
self.prefs.load()
|
self.prefs.load()
|
||||||
self._update_options()
|
self._update_options()
|
||||||
@ -179,9 +178,9 @@ class DupeGuru(DupeGuruBase, QObject):
|
|||||||
QDesktopServices.openUrl(url)
|
QDesktopServices.openUrl(url)
|
||||||
|
|
||||||
def open_selected(self):
|
def open_selected(self):
|
||||||
if self.selected_dupe is None:
|
if not self.selected_dupes:
|
||||||
return
|
return
|
||||||
url = QUrl.fromLocalFile(unicode(self.selected_dupe.path))
|
url = QUrl.fromLocalFile(unicode(self.selected_dupes[0].path))
|
||||||
QDesktopServices.openUrl(url)
|
QDesktopServices.openUrl(url)
|
||||||
|
|
||||||
def remove_duplicates(self, duplicates):
|
def remove_duplicates(self, duplicates):
|
||||||
@ -201,14 +200,13 @@ class DupeGuru(DupeGuruBase, QObject):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def reveal_selected(self):
|
def reveal_selected(self):
|
||||||
if self.selected_dupe is None:
|
if not self.selected_dupes:
|
||||||
return
|
return
|
||||||
url = QUrl.fromLocalFile(unicode(self.selected_dupe.path[:-1]))
|
url = QUrl.fromLocalFile(unicode(self.selected_dupe[0].path[:-1]))
|
||||||
QDesktopServices.openUrl(url)
|
QDesktopServices.openUrl(url)
|
||||||
|
|
||||||
def select_duplicate(self, dupe):
|
def select_duplicate(self, dupe):
|
||||||
self.selected_dupe = dupe
|
self._select_dupes([dupe])
|
||||||
self.emit(SIGNAL('duplicateSelected()'))
|
|
||||||
|
|
||||||
def show_about_box(self):
|
def show_about_box(self):
|
||||||
self.about_box.show()
|
self.about_box.show()
|
||||||
|
33
qt/base/details_dialog.py
Normal file
33
qt/base/details_dialog.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Created By: Virgil Dupras
|
||||||
|
# Created On: 2010-02-05
|
||||||
|
# Copyright 2010 Hardcoded Software (http://www.hardcoded.net)
|
||||||
|
#
|
||||||
|
# This software is licensed under the "HS" 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/hs_license
|
||||||
|
|
||||||
|
from PyQt4.QtCore import Qt
|
||||||
|
from PyQt4.QtGui import QDialog
|
||||||
|
|
||||||
|
from core.gui.details_panel import DetailsPanel
|
||||||
|
|
||||||
|
from .details_table import DetailsModel
|
||||||
|
|
||||||
|
class DetailsDialog(QDialog):
|
||||||
|
def __init__(self, parent, app):
|
||||||
|
QDialog.__init__(self, parent, Qt.Tool)
|
||||||
|
self.app = app
|
||||||
|
self.model = DetailsPanel(self, app)
|
||||||
|
self._setupUi()
|
||||||
|
self.tableModel = DetailsModel(self.model)
|
||||||
|
# tableView is defined in subclasses
|
||||||
|
self.tableView.setModel(self.tableModel)
|
||||||
|
|
||||||
|
def _setupUi(self): # Virtual
|
||||||
|
pass
|
||||||
|
|
||||||
|
# model --> view
|
||||||
|
def refresh(self):
|
||||||
|
self.tableModel.reset()
|
||||||
|
|
@ -6,57 +6,35 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.hardcoded.net/licenses/hs_license
|
# http://www.hardcoded.net/licenses/hs_license
|
||||||
|
|
||||||
from PyQt4.QtCore import Qt, SIGNAL, QAbstractTableModel, QVariant
|
from PyQt4.QtCore import Qt, SIGNAL, QAbstractTableModel
|
||||||
from PyQt4.QtGui import QHeaderView, QTableView
|
from PyQt4.QtGui import QHeaderView, QTableView
|
||||||
|
|
||||||
HEADER = ['Attribute', 'Selected', 'Reference']
|
HEADER = ['Attribute', 'Selected', 'Reference']
|
||||||
|
|
||||||
class DetailsModel(QAbstractTableModel):
|
class DetailsModel(QAbstractTableModel):
|
||||||
def __init__(self, app):
|
def __init__(self, model):
|
||||||
QAbstractTableModel.__init__(self)
|
QAbstractTableModel.__init__(self)
|
||||||
self._app = app
|
self.model = model
|
||||||
self._dupe_data = None
|
|
||||||
self._ref_data = None
|
|
||||||
self.connect(app, SIGNAL('duplicateSelected()'), self.duplicateSelected)
|
|
||||||
|
|
||||||
def columnCount(self, parent):
|
def columnCount(self, parent):
|
||||||
return len(HEADER)
|
return len(HEADER)
|
||||||
|
|
||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
if not index.isValid():
|
if not index.isValid():
|
||||||
return QVariant()
|
return None
|
||||||
if role != Qt.DisplayRole:
|
if role != Qt.DisplayRole:
|
||||||
return QVariant()
|
return None
|
||||||
column = index.column()
|
column = index.column()
|
||||||
row = index.row()
|
row = index.row()
|
||||||
if column == 0:
|
return self.model.row(row)[column]
|
||||||
return QVariant(self._app.data.COLUMNS[row]['display'])
|
|
||||||
elif column == 1 and self._dupe_data:
|
|
||||||
return QVariant(self._dupe_data[row])
|
|
||||||
elif column == 2 and self._ref_data:
|
|
||||||
return QVariant(self._ref_data[row])
|
|
||||||
return QVariant()
|
|
||||||
|
|
||||||
def headerData(self, section, orientation, role):
|
def headerData(self, section, orientation, role):
|
||||||
if orientation == Qt.Horizontal and role == Qt.DisplayRole and section < len(HEADER):
|
if orientation == Qt.Horizontal and role == Qt.DisplayRole and section < len(HEADER):
|
||||||
return QVariant(HEADER[section])
|
return HEADER[section]
|
||||||
return QVariant()
|
return None
|
||||||
|
|
||||||
def rowCount(self, parent):
|
def rowCount(self, parent):
|
||||||
return len(self._app.data.COLUMNS)
|
return self.model.row_count()
|
||||||
|
|
||||||
#--- Events
|
|
||||||
def duplicateSelected(self):
|
|
||||||
dupe = self._app.selected_dupe
|
|
||||||
if dupe is None:
|
|
||||||
group = None
|
|
||||||
ref = None
|
|
||||||
else:
|
|
||||||
group = self._app.results.get_group_of_duplicate(dupe)
|
|
||||||
ref = group.ref if group.ref is not dupe else None
|
|
||||||
self._dupe_data = self._app._get_display_info(dupe, group)
|
|
||||||
self._ref_data = self._app._get_display_info(ref, group)
|
|
||||||
self.reset()
|
|
||||||
|
|
||||||
|
|
||||||
class DetailsTable(QTableView):
|
class DetailsTable(QTableView):
|
||||||
|
@ -316,9 +316,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
def resultsReset(self):
|
def resultsReset(self):
|
||||||
self.resultsView.expandAll()
|
self.resultsView.expandAll()
|
||||||
dupe = self.app.selected_dupe
|
if self.app.selected_dupes:
|
||||||
if dupe is not None:
|
[modelIndex] = self.resultsModel.indexesForDupes(self.app.selected_dupes[:1])
|
||||||
[modelIndex] = self.resultsModel.indexesForDupes([dupe])
|
|
||||||
if modelIndex.isValid():
|
if modelIndex.isValid():
|
||||||
flags = QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows
|
flags = QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows
|
||||||
self.resultsView.selectionModel().setCurrentIndex(modelIndex, flags)
|
self.resultsView.selectionModel().setCurrentIndex(modelIndex, flags)
|
||||||
|
@ -6,16 +6,10 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.hardcoded.net/licenses/hs_license
|
# http://www.hardcoded.net/licenses/hs_license
|
||||||
|
|
||||||
from PyQt4.QtCore import Qt
|
from base.details_dialog import DetailsDialog as DetailsDialogBase
|
||||||
from PyQt4.QtGui import QDialog
|
|
||||||
|
|
||||||
from base.details_table import DetailsModel
|
|
||||||
from details_dialog_ui import Ui_DetailsDialog
|
from details_dialog_ui import Ui_DetailsDialog
|
||||||
|
|
||||||
class DetailsDialog(QDialog, Ui_DetailsDialog):
|
class DetailsDialog(DetailsDialogBase, Ui_DetailsDialog):
|
||||||
def __init__(self, parent, app):
|
def _setupUi(self):
|
||||||
QDialog.__init__(self, parent, Qt.Tool)
|
|
||||||
self.app = app
|
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.model = DetailsModel(app)
|
|
||||||
self.tableView.setModel(self.model)
|
|
||||||
|
@ -6,27 +6,25 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.hardcoded.net/licenses/hs_license
|
# http://www.hardcoded.net/licenses/hs_license
|
||||||
|
|
||||||
from PyQt4.QtCore import Qt, SIGNAL, QAbstractTableModel, QVariant
|
from PyQt4.QtCore import Qt
|
||||||
from PyQt4.QtGui import QDialog, QHeaderView, QPixmap
|
from PyQt4.QtGui import QPixmap
|
||||||
|
|
||||||
from base.details_table import DetailsModel
|
from base.details_dialog import DetailsDialog as DetailsDialogBase
|
||||||
from details_dialog_ui import Ui_DetailsDialog
|
from details_dialog_ui import Ui_DetailsDialog
|
||||||
|
|
||||||
class DetailsDialog(QDialog, Ui_DetailsDialog):
|
class DetailsDialog(DetailsDialogBase, Ui_DetailsDialog):
|
||||||
def __init__(self, parent, app):
|
def __init__(self, parent, app):
|
||||||
QDialog.__init__(self, parent, Qt.Tool)
|
DetailsDialogBase.__init__(self, parent, app)
|
||||||
self.app = app
|
|
||||||
self.selectedPixmap = None
|
self.selectedPixmap = None
|
||||||
self.referencePixmap = None
|
self.referencePixmap = None
|
||||||
|
|
||||||
|
def _setupUi(self):
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.model = DetailsModel(app)
|
|
||||||
self.tableView.setModel(self.model)
|
|
||||||
self.connect(app, SIGNAL('duplicateSelected()'), self.duplicateSelected)
|
|
||||||
|
|
||||||
def _update(self):
|
def _update(self):
|
||||||
dupe = self.app.selected_dupe
|
if not self.app.selected_dupes:
|
||||||
if dupe is None:
|
|
||||||
return
|
return
|
||||||
|
dupe = self.app.selected_dupes[0]
|
||||||
group = self.app.results.get_group_of_duplicate(dupe)
|
group = self.app.results.get_group_of_duplicate(dupe)
|
||||||
ref = group.ref
|
ref = group.ref
|
||||||
|
|
||||||
@ -56,11 +54,12 @@ class DetailsDialog(QDialog, Ui_DetailsDialog):
|
|||||||
self._updateImages()
|
self._updateImages()
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
QDialog.show(self)
|
DetailsDialogBase.show(self)
|
||||||
self._update()
|
self._update()
|
||||||
|
|
||||||
#--- Events
|
# model --> view
|
||||||
def duplicateSelected(self):
|
def refresh(self):
|
||||||
|
DetailsDialogBase.refresh(self)
|
||||||
if self.isVisible():
|
if self.isVisible():
|
||||||
self._update()
|
self._update()
|
||||||
|
|
||||||
|
@ -6,16 +6,10 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.hardcoded.net/licenses/hs_license
|
# http://www.hardcoded.net/licenses/hs_license
|
||||||
|
|
||||||
from PyQt4.QtCore import Qt
|
from base.details_dialog import DetailsDialog as DetailsDialogBase
|
||||||
from PyQt4.QtGui import QDialog
|
|
||||||
|
|
||||||
from base.details_table import DetailsModel
|
|
||||||
from details_dialog_ui import Ui_DetailsDialog
|
from details_dialog_ui import Ui_DetailsDialog
|
||||||
|
|
||||||
class DetailsDialog(QDialog, Ui_DetailsDialog):
|
class DetailsDialog(DetailsDialogBase, Ui_DetailsDialog):
|
||||||
def __init__(self, parent, app):
|
def _setupUi(self):
|
||||||
QDialog.__init__(self, parent, Qt.Tool)
|
|
||||||
self.app = app
|
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.model = DetailsModel(app)
|
|
||||||
self.tableView.setModel(self.model)
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user