1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
|
# Created By: Virgil Dupras
# Created On: 2010-02-11
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html
from operator import attrgetter
from hscommon.gui.table import GUITable, Row
from hscommon.gui.column import Columns
from core.gui.base import DupeGuruGUIObject
class DupeRow(Row):
def __init__(self, table, group, dupe):
Row.__init__(self, table)
self._app = table.app
self._group = group
self._dupe = dupe
self._data = None
self._data_delta = None
self._delta_columns = None
def is_cell_delta(self, column_name):
"""Returns whether a cell is in delta mode (orange color).
If the result table is in delta mode, returns True if the column is one of the "delta
columns", that is, one of the columns that display a a differential value rather than an
absolute value.
If not, returns True if the dupe's value is different from its ref value.
"""
if not self.table.delta_values:
return False
if self.isref:
return False
if self._delta_columns is None:
# table.DELTA_COLUMNS are always "delta"
self._delta_columns = self.table.DELTA_COLUMNS.copy()
dupe_info = self.data
if self._group.ref is None:
return False
ref_info = self._group.ref.get_display_info(group=self._group, delta=False)
for key, value in dupe_info.items():
if (key not in self._delta_columns) and (ref_info[key].lower() != value.lower()):
self._delta_columns.add(key)
return column_name in self._delta_columns
@property
def data(self):
if self._data is None:
self._data = self._app.get_display_info(self._dupe, self._group, False)
return self._data
@property
def data_delta(self):
if self._data_delta is None:
self._data_delta = self._app.get_display_info(self._dupe, self._group, True)
return self._data_delta
@property
def isref(self):
return self._dupe is self._group.ref
@property
def markable(self):
return self._app.results.is_markable(self._dupe)
@property
def marked(self):
return self._app.results.is_marked(self._dupe)
@marked.setter
def marked(self, value):
self._app.mark_dupe(self._dupe, value)
class ResultTable(GUITable, DupeGuruGUIObject):
def __init__(self, app):
GUITable.__init__(self)
DupeGuruGUIObject.__init__(self, app)
self._columns = Columns(self, prefaccess=app, savename="ResultTable")
self._power_marker = False
self._delta_values = False
self._sort_descriptors = ("name", True)
# --- Override
def _view_updated(self):
self._refresh_with_view()
def _restore_selection(self, previous_selection):
if self.app.selected_dupes:
to_find = set(self.app.selected_dupes)
indexes = [i for i, r in enumerate(self) if r._dupe in to_find]
self.selected_indexes = indexes
def _update_selection(self):
rows = self.selected_rows
self.app._select_dupes(list(map(attrgetter("_dupe"), rows)))
def _fill(self):
if not self.power_marker:
for group in self.app.results.groups:
self.append(DupeRow(self, group, group.ref))
for dupe in group.dupes:
self.append(DupeRow(self, group, dupe))
else:
for dupe in self.app.results.dupes:
group = self.app.results.get_group_of_duplicate(dupe)
self.append(DupeRow(self, group, dupe))
def _refresh_with_view(self):
self.refresh()
self.view.show_selected_row()
# --- Public
def get_row_value(self, index, column):
try:
row = self[index]
except IndexError:
return "---"
if self.delta_values:
return row.data_delta[column]
else:
return row.data[column]
def rename_selected(self, newname):
row = self.selected_row
if row is None:
# There's all kinds of way the current row can be swept off during rename. When it
# happens, selected_row will be None.
return False
row._data = None
row._data_delta = None
return self.app.rename_selected(newname)
def sort(self, key, asc):
if self.power_marker:
self.app.results.sort_dupes(key, asc, self.delta_values)
else:
self.app.results.sort_groups(key, asc)
self._sort_descriptors = (key, asc)
self._refresh_with_view()
# --- Properties
@property
def power_marker(self):
return self._power_marker
@power_marker.setter
def power_marker(self, value):
if value == self._power_marker:
return
self._power_marker = value
key, asc = self._sort_descriptors
self.sort(key, asc)
# no need to refresh, it has happened in sort()
@property
def delta_values(self):
return self._delta_values
@delta_values.setter
def delta_values(self, value):
if value == self._delta_values:
return
self._delta_values = value
self.refresh()
@property
def selected_dupe_count(self):
return sum(1 for row in self.selected_rows if not row.isref)
# --- Event Handlers
def marking_changed(self):
self.view.invalidate_markings()
def results_changed(self):
self._refresh_with_view()
def results_changed_but_keep_selection(self):
# What we want to to here is that instead of restoring selected *dupes* after refresh, we
# restore selected *paths*.
indexes = self.selected_indexes
self.refresh(refresh_view=False)
self.select(indexes)
self.view.refresh()
def save_session(self):
self._columns.save_columns()
|