Updated the qt part of dupeguru to adjust to the latest column reorganization.

This commit is contained in:
Virgil Dupras 2011-11-28 10:27:17 -05:00
parent 9226a4fb7c
commit d9ae967439
12 changed files with 80 additions and 172 deletions

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Created By: Virgil Dupras
# Created On: 2010-04-12
# Copyright 2011 Hardcoded Software (http://www.hardcoded.net)
@ -9,11 +8,21 @@
from hscommon.notify import Listener
from hscommon.gui.table import GUITable, Row
from hscommon.gui.column import Column, Columns
from hscommon.trans import trget
coltr = trget('columns')
class ProblemTable(GUITable, Listener):
COLUMNS = [
Column('path', coltr("File Path")),
Column('msg', coltr("Error Message")),
]
def __init__(self, view, problem_dialog):
GUITable.__init__(self)
Listener.__init__(self, problem_dialog)
self.columns = Columns(self)
self.view = view
self.dialog = problem_dialog

View File

@ -53,6 +53,12 @@ class DupeGuru(QObject):
LOGO_NAME = '<replace this>'
NAME = '<replace this>'
DETAILS_DIALOG_CLASS = None
RESULT_WINDOW_CLASS = ResultWindow
RESULT_MODEL_CLASS = None
PREFERENCES_CLASS = None
PREFERENCES_DIALOG_CLASS = None
def __init__(self):
QObject.__init__(self)
appdata = str(QDesktopServices.storageLocation(QDesktopServices.DataLocation))
@ -65,7 +71,7 @@ class DupeGuru(QObject):
sys.stderr = SysWrapper()
if sys.stdout is None:
sys.stdout = SysWrapper()
self.prefs = self._create_preferences()
self.prefs = self.PREFERENCES_CLASS()
self.prefs.load()
self.model = self.MODELCLASS(view=self, appdata=appdata)
self._setup()
@ -77,12 +83,12 @@ class DupeGuru(QObject):
self._update_options()
self.recentResults = Recent(self, 'recentResults')
self.recentResults.mustOpenItem.connect(self.model.load_from)
self.resultWindow = self._create_result_window()
self.resultWindow = self.RESULT_WINDOW_CLASS(self)
self._progress = Progress(self.resultWindow)
self.directories_dialog = DirectoriesDialog(self.resultWindow, self)
self.details_dialog = self._create_details_dialog(self.resultWindow)
self.details_dialog = self.DETAILS_DIALOG_CLASS(self.resultWindow, self)
self.problemDialog = ProblemDialog(parent=self.resultWindow, app=self)
self.preferences_dialog = self._create_preferences_dialog(self.resultWindow)
self.preferences_dialog = self.PREFERENCES_DIALOG_CLASS(self.resultWindow, self)
self.about_box = AboutBox(self.resultWindow, self)
self.directories_dialog.show()
@ -119,19 +125,6 @@ class DupeGuru(QObject):
self.model.options['clean_empty_dirs'] = self.prefs.remove_empty_folders
self.model.options['ignore_hardlink_matches'] = self.prefs.ignore_hardlink_matches
#--- Virtual
def _create_details_dialog(self, parent):
raise NotImplementedError()
def _create_result_window(self):
return ResultWindow(app=self)
def _create_preferences(self):
raise NotImplementedError()
def _create_preferences_dialog(self, parent):
raise NotImplementedError()
#--- Public
def add_selected_to_ignore_list(self):
dupes = self.model.without_ref(self.model.selected_dupes)

View File

@ -11,13 +11,6 @@ from PyQt4.QtGui import QApplication
from qtlib.preferences import Preferences as PreferencesBase
class Preferences(PreferencesBase):
# (width, is_visible)
COLUMNS_DEFAULT_ATTRS = []
def __init__(self):
PreferencesBase.__init__(self)
self.reset_columns()
def _load_specific(self, settings):
# load prefs specific to the dg edition
pass
@ -34,13 +27,6 @@ class Preferences(PreferencesBase):
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)]):
if width > 0:
self.columns_width[index] = width
self.columns_visible = get('ColumnsVisible', self.columns_visible)
self.tableFontSize = get('TableFontSize', self.tableFontSize)
self.resultWindowIsMaximized = get('ResultWindowIsMaximized', self.resultWindowIsMaximized)
self.resultWindowRect = self.get_rect('ResultWindowRect', self.resultWindowRect)
@ -76,10 +62,6 @@ class Preferences(PreferencesBase):
self._reset_specific()
def reset_columns(self):
self.columns_width = [width for width, _ in self.COLUMNS_DEFAULT_ATTRS]
self.columns_visible = [visible for _, visible in self.COLUMNS_DEFAULT_ATTRS]
def _save_specific(self, settings):
# save prefs specific to the dg edition
pass
@ -94,8 +76,6 @@ class Preferences(PreferencesBase):
set_('DebugMode', self.debug_mode)
set_('DestinationType', self.destination_type)
set_('CustomCommand', self.custom_command)
set_('ColumnsWidth', self.columns_width)
set_('ColumnsVisible', self.columns_visible)
set_('Language', self.language)
set_('TableFontSize', self.tableFontSize)

View File

@ -6,17 +6,14 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license
from hscommon.trans import trget
from qtlib.column import Column
from qtlib.table import Table
from core.gui.problem_table import ProblemTable as ProblemTableModel
tr = trget('ui')
class ProblemTable(Table):
COLUMNS = [
Column('path', tr("File Path"), 150),
Column('msg', tr("Error Message"), 150),
Column('path', defaultWidth=150),
Column('msg', defaultWidth=150),
]
def __init__(self, problem_dialog, view):

View File

@ -7,16 +7,16 @@
# http://www.hardcoded.net/licenses/bsd_license
from PyQt4.QtCore import Qt, SIGNAL, QUrl, QRect
from PyQt4.QtGui import (QMainWindow, QMenu, QLabel, QHeaderView, QMessageBox, QInputDialog,
QLineEdit, QDesktopServices, QFileDialog, QMenuBar, QWidget, QVBoxLayout, QAbstractItemView,
QStatusBar, QDialog)
from PyQt4.QtGui import (QMainWindow, QMenu, QLabel, QMessageBox, QInputDialog, QLineEdit,
QDesktopServices, QFileDialog, QMenuBar, QWidget, QVBoxLayout, QAbstractItemView, QStatusBar,
QDialog)
from hscommon.plat import ISOSX, ISLINUX
from hscommon.trans import trget
from hscommon.util import nonone
from qtlib.util import moveToScreenCenter
from .results_model import ResultsModel, ResultsView
from .results_model import ResultsView
from .stats_label import StatsLabel
from .util import createActions
from .prioritize_dialog import PrioritizeDialog
@ -29,9 +29,8 @@ class ResultWindow(QMainWindow):
self.app = app
self._last_filter = None
self._setupUi()
self.resultsModel = ResultsModel(self.app, self.resultsView)
self.resultsModel = app.RESULT_MODEL_CLASS(self.app, self.resultsView)
self.stats = StatsLabel(app, self.statusLabel)
self._load_columns()
self._update_column_actions_status()
self.connect(self.menuColumns, SIGNAL('triggered(QAction*)'), self.columnToggled)
@ -141,14 +140,15 @@ class ResultWindow(QMainWindow):
# Columns menu
menu = self.menuColumns
self._column_actions = []
for index, column in enumerate(self.app.model.COLUMNS):
action = menu.addAction(column.display)
for index, (display, visible) in enumerate(self.app.model.result_table.columns.menu_items()):
action = menu.addAction(display)
action.setCheckable(True)
action.column_index = index
action.setChecked(visible)
action.item_index = index
self._column_actions.append(action)
menu.addSeparator()
action = menu.addAction(tr("Reset to Defaults"))
action.column_index = -1
action.item_index = -1
# Action menu
actionMenu = QMenu(tr("Actions"), self.menubar)
@ -203,21 +203,11 @@ class ResultWindow(QMainWindow):
moveToScreenCenter(self)
#--- Private
def _load_columns(self):
h = self.resultsView.horizontalHeader()
h.setResizeMode(QHeaderView.Interactive)
prefs = self.app.prefs
attrs = list(zip(prefs.columns_width, prefs.columns_visible))
for index, (width, visible) in enumerate(attrs):
h.resizeSection(index, width)
h.setSectionHidden(index, not visible)
h.setResizeMode(0, QHeaderView.Stretch)
def _update_column_actions_status(self):
h = self.resultsView.horizontalHeader()
for action in self._column_actions:
colid = action.column_index
action.setChecked(not h.isSectionHidden(colid))
# Update menu checked state
menu_items = self.app.model.result_table.columns.menu_items()
for action, (display, visible) in zip(self._column_actions, menu_items):
action.setChecked(visible)
#--- Actions
def actionsTriggered(self):
@ -352,26 +342,17 @@ class ResultWindow(QMainWindow):
#--- Events
def appWillSavePrefs(self):
prefs = self.app.prefs
h = self.resultsView.horizontalHeader()
widths = []
visible = []
for i in range(len(self.app.model.COLUMNS)):
widths.append(h.sectionSize(i))
visible.append(not h.isSectionHidden(i))
prefs.columns_width = widths
prefs.columns_visible = visible
prefs.resultWindowIsMaximized = self.isMaximized()
prefs.resultWindowRect = self.geometry()
def columnToggled(self, action):
colid = action.column_index
if colid == -1:
self.app.prefs.reset_columns()
self._load_columns()
index = action.item_index
if index == -1:
self.app.model.result_table.columns.reset_to_defaults()
self._update_column_actions_status()
else:
h = self.resultsView.horizontalHeader()
h.setSectionHidden(colid, not h.isSectionHidden(colid))
self._update_column_actions_status()
visible = self.app.model.result_table.columns.toggle_menu_item(index)
action.setChecked(visible)
def contextMenuEvent(self, event):
self.actionActions.menu().exec_(event.globalPos())

View File

@ -15,31 +15,31 @@ from core.gui.result_table import ResultTable as ResultTableModel
class ResultsModel(Table):
def __init__(self, app, view):
model = ResultTableModel(self, app.model)
self._app = app.model
self._delta_columns = app.model.DELTA_COLUMNS
model = app.model.result_table
Table.__init__(self, model, view)
self.model.connect()
app.prefsChanged.connect(self.appPrefsChanged)
app.willSavePrefs.connect(self.appWillSavePrefs)
def columnCount(self, parent):
return len(self._app.COLUMNS)
return len(self.model.COLUMNS)
def data(self, index, role):
if not index.isValid():
return None
row = self.model[index.row()]
column = self.model.COLUMNS[index.column()]
if role == Qt.DisplayRole:
data = row.data_delta if self.model.delta_values else row.data
return data[index.column()]
return data[column.name]
elif role == Qt.CheckStateRole:
if index.column() == 0 and row.markable:
return Qt.Checked if row.marked else Qt.Unchecked
elif role == Qt.ForegroundRole:
if row.isref:
return QBrush(Qt.blue)
elif self.model.delta_values and index.column() in self._delta_columns:
elif self.model.delta_values and column.name in self.model.DELTA_COLUMNS:
return QBrush(QColor(255, 142, 40)) # orange
elif role == Qt.FontRole:
isBold = row.isref
@ -47,8 +47,8 @@ class ResultsModel(Table):
font.setBold(isBold)
return font
elif role == Qt.EditRole:
if index.column() == 0:
return row.data[index.column()]
if column.name == 'name':
return row.data[column.name]
return None
def flags(self, index):
@ -64,26 +64,28 @@ class ResultsModel(Table):
def headerData(self, section, orientation, role):
if role == Qt.DisplayRole:
if orientation == Qt.Horizontal and section < len(self._app.COLUMNS):
return self._app.COLUMNS[section].display
if orientation == Qt.Horizontal and section < len(self.model.COLUMNS):
return self.model.COLUMNS[section].display
return None
def setData(self, index, value, role):
if not index.isValid():
return False
row = self.model[index.row()]
column = self.model.COLUMNS[index.column()]
if role == Qt.CheckStateRole:
if index.column() == 0:
self._app.mark_dupe(row._dupe, value.toBool())
if column.name == 'name':
self.model.app.mark_dupe(row._dupe, value.toBool())
return True
elif role == Qt.EditRole:
if index.column() == 0:
if column.name == 'name':
value = str(value.toString())
return self.model.rename_selected(value)
return False
def sort(self, column, order):
self.model.sort(column, order == Qt.AscendingOrder)
column = self.model.COLUMNS[column]
self.model.sort(column.name, order == Qt.AscendingOrder)
#--- Properties
@property
@ -110,6 +112,9 @@ class ResultsModel(Table):
fm = QFontMetrics(font)
self.view.verticalHeader().setDefaultSectionSize(fm.height()+2)
def appWillSavePrefs(self):
self.model.columns.save_columns()
#--- model --> view
def invalidate_markings(self):
# redraw view

View File

@ -11,6 +11,7 @@ from core_me.app import DupeGuru as DupeGuruModel
from ..base.app import DupeGuru as DupeGuruBase
from .details_dialog import DetailsDialog
from .results_model import ResultsModel
from .preferences import Preferences
from .preferences_dialog import PreferencesDialog
@ -20,6 +21,11 @@ class DupeGuru(DupeGuruBase):
LOGO_NAME = 'logo_me'
NAME = __appname__
DETAILS_DIALOG_CLASS = DetailsDialog
RESULT_MODEL_CLASS = ResultsModel
PREFERENCES_CLASS = Preferences
PREFERENCES_DIALOG_CLASS = PreferencesDialog
def _update_options(self):
DupeGuruBase._update_options(self)
self.model.scanner.min_match_percentage = self.prefs.filter_hardness
@ -41,12 +47,3 @@ class DupeGuru(DupeGuruBase):
scanned_tags.add('year')
self.model.scanner.scanned_tags = scanned_tags
def _create_details_dialog(self, parent):
return DetailsDialog(parent, self)
def _create_preferences(self):
return Preferences()
def _create_preferences_dialog(self, parent):
return PreferencesDialog(parent, self)

View File

@ -11,28 +11,6 @@ from core.scanner import ScanType
from ..base.preferences import Preferences as PreferencesBase
class Preferences(PreferencesBase):
# (width, is_visible)
COLUMNS_DEFAULT_ATTRS = [
(200, True), # name
(180, True), # path
(60, True), # size
(60, True), # Time
(50, True), # Bitrate
(60, False), # Sample Rate
(40, False), # Kind
(120, False), # modification
(120, False), # Title
(120, False), # Artist
(120, False), # Album
(80, False), # Genre
(40, False), # Year
(40, False), # Track Number
(120, False), # Comment
(60, True), # match %
(120, False), # Words Used
(80, False), # dupe count
]
def _load_specific(self, settings):
get = self.get_value
self.scan_type = get('ScanType', self.scan_type)

View File

@ -18,6 +18,7 @@ from ..base.app import DupeGuru as DupeGuruBase
from .block import getblocks
from .details_dialog import DetailsDialog
from .result_window import ResultWindow
from .results_model import ResultsModel
from .preferences import Preferences
from .preferences_dialog import PreferencesDialog
@ -70,6 +71,12 @@ class DupeGuru(DupeGuruBase):
LOGO_NAME = 'logo_pe'
NAME = __appname__
DETAILS_DIALOG_CLASS = DetailsDialog
RESULT_WINDOW_CLASS = ResultWindow
RESULT_MODEL_CLASS = ResultsModel
PREFERENCES_CLASS = Preferences
PREFERENCES_DIALOG_CLASS = PreferencesDialog
def _setup(self):
self.model.directories.fileclasses = [File]
DupeGuruBase._setup(self)
@ -80,15 +87,3 @@ class DupeGuru(DupeGuruBase):
self.model.scanner.match_scaled = self.prefs.match_scaled
self.model.scanner.threshold = self.prefs.filter_hardness
def _create_details_dialog(self, parent):
return DetailsDialog(parent, self)
def _create_result_window(self):
return ResultWindow(app=self)
def _create_preferences(self):
return Preferences()
def _create_preferences_dialog(self, parent):
return PreferencesDialog(parent, self)

View File

@ -11,18 +11,6 @@ from core.scanner import ScanType
from ..base.preferences import Preferences as PreferencesBase
class Preferences(PreferencesBase):
# (width, is_visible)
COLUMNS_DEFAULT_ATTRS = [
(200, True), # name
(180, True), # path
(60, True), # size
(40, False), # kind
(100, True), # dimensions
(120, False), # modification
(60, True), # match %
(80, False), # dupe count
]
def _load_specific(self, settings):
get = self.get_value
self.scan_type = get('ScanType', self.scan_type)

View File

@ -12,6 +12,7 @@ from core.directories import Directories as DirectoriesBase, DirectoryState
from ..base.app import DupeGuru as DupeGuruBase
from .details_dialog import DetailsDialog
from .results_model import ResultsModel
from .preferences import Preferences
from .preferences_dialog import PreferencesDialog
@ -30,6 +31,11 @@ class DupeGuru(DupeGuruBase):
LOGO_NAME = 'logo_se'
NAME = __appname__
DETAILS_DIALOG_CLASS = DetailsDialog
RESULT_MODEL_CLASS = ResultsModel
PREFERENCES_CLASS = Preferences
PREFERENCES_DIALOG_CLASS = PreferencesDialog
def _setup(self):
self.directories = Directories()
DupeGuruBase._setup(self)
@ -43,12 +49,3 @@ class DupeGuru(DupeGuruBase):
threshold = self.prefs.small_file_threshold if self.prefs.ignore_small_files else 0
self.model.scanner.size_threshold = threshold * 1024 # threshold is in KB. the scanner wants bytes
def _create_details_dialog(self, parent):
return DetailsDialog(parent, self)
def _create_preferences(self):
return Preferences()
def _create_preferences_dialog(self, parent):
return PreferencesDialog(parent, self)

View File

@ -11,18 +11,6 @@ from core.scanner import ScanType
from ..base.preferences import Preferences as PreferencesBase
class Preferences(PreferencesBase):
# (width, is_visible)
COLUMNS_DEFAULT_ATTRS = [
(200, True), # name
(180, True), # path
(60, True), # size
(40, False), # Kind
(120, False), # modification
(60, True), # match %
(120, False), # Words Used
(80, False), # dupe count
]
def _load_specific(self, settings):
get = self.get_value
self.scan_type = get('ScanType', self.scan_type)