1
0
mirror of https://github.com/arsenetar/dupeguru.git synced 2025-03-10 13:44:37 +00:00

The Qt side now makes use of core.gui.details_panel.

This commit is contained in:
Virgil Dupras 2010-02-05 21:09:04 +01:00
parent 484512e35b
commit 8dda616502
9 changed files with 81 additions and 86 deletions

View File

@ -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()

View File

@ -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:

View File

@ -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
View 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()

View File

@ -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):

View File

@ -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)

View File

@ -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)

View File

@ -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()

View File

@ -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)