mirror of
https://github.com/arsenetar/dupeguru.git
synced 2025-03-10 05:34:36 +00:00
Updated hscommon to its tip.
Because the latest changes in hscommon include the introduction of a base GUIObject which significantly changes view setting mechanisms, significant adjustments had to be made in dupeGuru.
This commit is contained in:
parent
878c744c21
commit
49a7043b4d
@ -37,7 +37,7 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
[_recentResults setDelegate:self];
|
[_recentResults setDelegate:self];
|
||||||
_resultWindow = [self createResultWindow];
|
_resultWindow = [self createResultWindow];
|
||||||
_directoryPanel = [self createDirectoryPanel];
|
_directoryPanel = [self createDirectoryPanel];
|
||||||
_detailsPanel = nil; // Lazily loaded
|
_detailsPanel = [self createDetailsPanel];
|
||||||
_aboutBox = nil; // Lazily loaded
|
_aboutBox = nil; // Lazily loaded
|
||||||
_preferencesPanel = nil; // Lazily loaded
|
_preferencesPanel = nil; // Lazily loaded
|
||||||
[[[self directoryPanel] window] makeKeyAndOrderFront:self];
|
[[[self directoryPanel] window] makeKeyAndOrderFront:self];
|
||||||
@ -83,8 +83,6 @@ http://www.hardcoded.net/licenses/bsd_license
|
|||||||
|
|
||||||
- (DetailsPanel *)detailsPanel
|
- (DetailsPanel *)detailsPanel
|
||||||
{
|
{
|
||||||
if (!_detailsPanel)
|
|
||||||
_detailsPanel = [self createDetailsPanel];
|
|
||||||
return _detailsPanel;
|
return _detailsPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,10 +9,9 @@
|
|||||||
from hscommon.notify import Listener
|
from hscommon.notify import Listener
|
||||||
from hscommon.gui.base import NoopGUI
|
from hscommon.gui.base import NoopGUI
|
||||||
|
|
||||||
class GUIObject(Listener):
|
class DupeGuruGUIObject(Listener):
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
Listener.__init__(self, app)
|
Listener.__init__(self, app)
|
||||||
self.view = NoopGUI()
|
|
||||||
self.app = app
|
self.app = app
|
||||||
|
|
||||||
def directories_changed(self):
|
def directories_changed(self):
|
||||||
|
@ -6,15 +6,16 @@
|
|||||||
# 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/bsd_license
|
# http://www.hardcoded.net/licenses/bsd_license
|
||||||
|
|
||||||
from .base import GUIObject
|
from hscommon.gui.base import GUIObject
|
||||||
|
from .base import DupeGuruGUIObject
|
||||||
|
|
||||||
class DetailsPanel(GUIObject):
|
class DetailsPanel(GUIObject, DupeGuruGUIObject):
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
GUIObject.__init__(self, app)
|
GUIObject.__init__(self)
|
||||||
|
DupeGuruGUIObject.__init__(self, app)
|
||||||
self._table = []
|
self._table = []
|
||||||
|
|
||||||
def connect(self):
|
def _view_updated(self):
|
||||||
GUIObject.connect(self)
|
|
||||||
self._refresh()
|
self._refresh()
|
||||||
self.view.refresh()
|
self.view.refresh()
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
from hscommon.gui.tree import Tree, Node
|
from hscommon.gui.tree import Tree, Node
|
||||||
|
|
||||||
from ..directories import DirectoryState
|
from ..directories import DirectoryState
|
||||||
from .base import GUIObject
|
from .base import DupeGuruGUIObject
|
||||||
|
|
||||||
STATE_ORDER = [DirectoryState.Normal, DirectoryState.Reference, DirectoryState.Excluded]
|
STATE_ORDER = [DirectoryState.Normal, DirectoryState.Reference, DirectoryState.Excluded]
|
||||||
|
|
||||||
@ -54,17 +54,16 @@ class DirectoryNode(Node):
|
|||||||
self._tree.update_all_states()
|
self._tree.update_all_states()
|
||||||
|
|
||||||
|
|
||||||
class DirectoryTree(GUIObject, Tree):
|
class DirectoryTree(Tree, DupeGuruGUIObject):
|
||||||
#--- model -> view calls:
|
#--- model -> view calls:
|
||||||
# refresh()
|
# refresh()
|
||||||
# refresh_states() # when only states label need to be refreshed
|
# refresh_states() # when only states label need to be refreshed
|
||||||
#
|
#
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
GUIObject.__init__(self, app)
|
|
||||||
Tree.__init__(self)
|
Tree.__init__(self)
|
||||||
|
DupeGuruGUIObject.__init__(self, app)
|
||||||
|
|
||||||
def connect(self):
|
def _view_updated(self):
|
||||||
GUIObject.connect(self)
|
|
||||||
self._refresh()
|
self._refresh()
|
||||||
self.view.refresh()
|
self.view.refresh()
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
# 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/bsd_license
|
# http://www.hardcoded.net/licenses/bsd_license
|
||||||
|
|
||||||
|
from hscommon.gui.base import GUIObject
|
||||||
from hscommon.gui.selectable_list import GUISelectableList
|
from hscommon.gui.selectable_list import GUISelectableList
|
||||||
|
|
||||||
class CriterionCategoryList(GUISelectableList):
|
class CriterionCategoryList(GUISelectableList):
|
||||||
@ -39,8 +40,9 @@ class PrioritizationList(GUISelectableList):
|
|||||||
del prilist[i]
|
del prilist[i]
|
||||||
self._refresh_contents()
|
self._refresh_contents()
|
||||||
|
|
||||||
class PrioritizeDialog:
|
class PrioritizeDialog(GUIObject):
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
|
GUIObject.__init__(self)
|
||||||
self.app = app
|
self.app = app
|
||||||
self.categories = [cat(app.results) for cat in app._prioritization_categories()]
|
self.categories = [cat(app.results) for cat in app._prioritization_categories()]
|
||||||
self.category_list = CriterionCategoryList(self)
|
self.category_list = CriterionCategoryList(self)
|
||||||
@ -48,6 +50,9 @@ class PrioritizeDialog:
|
|||||||
self.criteria_list = GUISelectableList()
|
self.criteria_list = GUISelectableList()
|
||||||
self.prioritizations = []
|
self.prioritizations = []
|
||||||
self.prioritization_list = PrioritizationList(self)
|
self.prioritization_list = PrioritizationList(self)
|
||||||
|
|
||||||
|
#--- Override
|
||||||
|
def _view_updated(self):
|
||||||
self.category_list.select(0)
|
self.category_list.select(0)
|
||||||
|
|
||||||
#--- Private
|
#--- Private
|
||||||
|
@ -21,7 +21,6 @@ class ProblemTable(GUITable):
|
|||||||
def __init__(self, problem_dialog):
|
def __init__(self, problem_dialog):
|
||||||
GUITable.__init__(self)
|
GUITable.__init__(self)
|
||||||
self.columns = Columns(self)
|
self.columns = Columns(self)
|
||||||
self.view = None
|
|
||||||
self.dialog = problem_dialog
|
self.dialog = problem_dialog
|
||||||
|
|
||||||
#--- Override
|
#--- Override
|
||||||
|
@ -11,7 +11,7 @@ from operator import attrgetter
|
|||||||
from hscommon.gui.table import GUITable, Row
|
from hscommon.gui.table import GUITable, Row
|
||||||
from hscommon.gui.column import Columns
|
from hscommon.gui.column import Columns
|
||||||
|
|
||||||
from .base import GUIObject
|
from .base import DupeGuruGUIObject
|
||||||
|
|
||||||
class DupeRow(Row):
|
class DupeRow(Row):
|
||||||
def __init__(self, table, group, dupe):
|
def __init__(self, table, group, dupe):
|
||||||
@ -51,20 +51,18 @@ class DupeRow(Row):
|
|||||||
self._app.mark_dupe(self._dupe, value)
|
self._app.mark_dupe(self._dupe, value)
|
||||||
|
|
||||||
|
|
||||||
class ResultTable(GUIObject, GUITable):
|
class ResultTable(GUITable, DupeGuruGUIObject):
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
GUIObject.__init__(self, app)
|
|
||||||
GUITable.__init__(self)
|
GUITable.__init__(self)
|
||||||
|
DupeGuruGUIObject.__init__(self, app)
|
||||||
self.columns = Columns(self, prefaccess=app, savename='ResultTable')
|
self.columns = Columns(self, prefaccess=app, savename='ResultTable')
|
||||||
self._power_marker = False
|
self._power_marker = False
|
||||||
self._delta_values = False
|
self._delta_values = False
|
||||||
self._sort_descriptors = ('name', True)
|
self._sort_descriptors = ('name', True)
|
||||||
|
|
||||||
#--- Override
|
#--- Override
|
||||||
def connect(self):
|
def _view_updated(self):
|
||||||
GUIObject.connect(self)
|
|
||||||
self._refresh_with_view()
|
self._refresh_with_view()
|
||||||
self.columns.restore_columns()
|
|
||||||
|
|
||||||
def _restore_selection(self, previous_selection):
|
def _restore_selection(self, previous_selection):
|
||||||
if self.app.selected_dupes:
|
if self.app.selected_dupes:
|
||||||
|
@ -6,11 +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/bsd_license
|
# http://www.hardcoded.net/licenses/bsd_license
|
||||||
|
|
||||||
from .base import GUIObject
|
from .base import DupeGuruGUIObject
|
||||||
|
|
||||||
class StatsLabel(GUIObject):
|
class StatsLabel(DupeGuruGUIObject):
|
||||||
def connect(self):
|
def _view_updated(self):
|
||||||
GUIObject.connect(self)
|
|
||||||
self.view.refresh()
|
self.view.refresh()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -18,7 +18,7 @@ import hscommon.util
|
|||||||
from hscommon.testutil import CallLogger, eq_, log_calls
|
from hscommon.testutil import CallLogger, eq_, log_calls
|
||||||
from jobprogress.job import Job
|
from jobprogress.job import Job
|
||||||
|
|
||||||
from .base import DupeGuru
|
from .base import DupeGuru, TestApp
|
||||||
from .results_test import GetTestGroups
|
from .results_test import GetTestGroups
|
||||||
from .. import app, fs, engine
|
from .. import app, fs, engine
|
||||||
from ..gui.details_panel import DetailsPanel
|
from ..gui.details_panel import DetailsPanel
|
||||||
@ -32,7 +32,7 @@ def add_fake_files_to_directories(directories, files):
|
|||||||
|
|
||||||
class TestCaseDupeGuru:
|
class TestCaseDupeGuru:
|
||||||
def test_apply_filter_calls_results_apply_filter(self, monkeypatch):
|
def test_apply_filter_calls_results_apply_filter(self, monkeypatch):
|
||||||
dgapp = DupeGuru()
|
dgapp = TestApp().app
|
||||||
monkeypatch.setattr(dgapp.results, 'apply_filter', log_calls(dgapp.results.apply_filter))
|
monkeypatch.setattr(dgapp.results, 'apply_filter', log_calls(dgapp.results.apply_filter))
|
||||||
dgapp.apply_filter('foo')
|
dgapp.apply_filter('foo')
|
||||||
eq_(2, len(dgapp.results.apply_filter.calls))
|
eq_(2, len(dgapp.results.apply_filter.calls))
|
||||||
@ -42,7 +42,7 @@ class TestCaseDupeGuru:
|
|||||||
eq_('foo', call['filter_str'])
|
eq_('foo', call['filter_str'])
|
||||||
|
|
||||||
def test_apply_filter_escapes_regexp(self, monkeypatch):
|
def test_apply_filter_escapes_regexp(self, monkeypatch):
|
||||||
dgapp = DupeGuru()
|
dgapp = TestApp().app
|
||||||
monkeypatch.setattr(dgapp.results, 'apply_filter', log_calls(dgapp.results.apply_filter))
|
monkeypatch.setattr(dgapp.results, 'apply_filter', log_calls(dgapp.results.apply_filter))
|
||||||
dgapp.apply_filter('()[]\\.|+?^abc')
|
dgapp.apply_filter('()[]\\.|+?^abc')
|
||||||
call = dgapp.results.apply_filter.calls[1]
|
call = dgapp.results.apply_filter.calls[1]
|
||||||
@ -65,7 +65,7 @@ class TestCaseDupeGuru:
|
|||||||
# XXX This monkeypatch is temporary. will be fixed in a better monkeypatcher.
|
# XXX This monkeypatch is temporary. will be fixed in a better monkeypatcher.
|
||||||
monkeypatch.setattr(app, 'smart_copy', hscommon.conflict.smart_copy)
|
monkeypatch.setattr(app, 'smart_copy', hscommon.conflict.smart_copy)
|
||||||
monkeypatch.setattr(os, 'makedirs', lambda path: None) # We don't want the test to create that fake directory
|
monkeypatch.setattr(os, 'makedirs', lambda path: None) # We don't want the test to create that fake directory
|
||||||
dgapp = DupeGuru()
|
dgapp = TestApp().app
|
||||||
dgapp.directories.add_path(p)
|
dgapp.directories.add_path(p)
|
||||||
[f] = dgapp.directories.get_files()
|
[f] = dgapp.directories.get_files()
|
||||||
dgapp.copy_or_move(f, True, 'some_destination', 0)
|
dgapp.copy_or_move(f, True, 'some_destination', 0)
|
||||||
@ -79,7 +79,7 @@ class TestCaseDupeGuru:
|
|||||||
sourcepath = tmppath + 'source'
|
sourcepath = tmppath + 'source'
|
||||||
io.mkdir(sourcepath)
|
io.mkdir(sourcepath)
|
||||||
io.open(sourcepath + 'myfile', 'w')
|
io.open(sourcepath + 'myfile', 'w')
|
||||||
app = DupeGuru()
|
app = TestApp().app
|
||||||
app.directories.add_path(tmppath)
|
app.directories.add_path(tmppath)
|
||||||
[myfile] = app.directories.get_files()
|
[myfile] = app.directories.get_files()
|
||||||
monkeypatch.setattr(app, 'clean_empty_dirs', log_calls(lambda path: None))
|
monkeypatch.setattr(app, 'clean_empty_dirs', log_calls(lambda path: None))
|
||||||
@ -95,7 +95,7 @@ class TestCaseDupeGuru:
|
|||||||
|
|
||||||
|
|
||||||
# At some point, any() was used in a wrong way that made Scan() wrongly return 1
|
# At some point, any() was used in a wrong way that made Scan() wrongly return 1
|
||||||
app = DupeGuru()
|
app = TestApp().app
|
||||||
f1, f2 = [FakeFile('foo') for i in range(2)]
|
f1, f2 = [FakeFile('foo') for i in range(2)]
|
||||||
f1.is_ref, f2.is_ref = (False, False)
|
f1.is_ref, f2.is_ref = (False, False)
|
||||||
assert not (bool(f1) and bool(f2))
|
assert not (bool(f1) and bool(f2))
|
||||||
@ -109,7 +109,7 @@ class TestCaseDupeGuru:
|
|||||||
tmppath = Path(str(tmpdir))
|
tmppath = Path(str(tmpdir))
|
||||||
io.open(tmppath + 'myfile', 'w').write('foo')
|
io.open(tmppath + 'myfile', 'w').write('foo')
|
||||||
os.link(str(tmppath + 'myfile'), str(tmppath + 'hardlink'))
|
os.link(str(tmppath + 'myfile'), str(tmppath + 'hardlink'))
|
||||||
app = DupeGuru()
|
app = TestApp().app
|
||||||
app.directories.add_path(tmppath)
|
app.directories.add_path(tmppath)
|
||||||
app.scanner.scan_type = ScanType.Contents
|
app.scanner.scan_type = ScanType.Contents
|
||||||
app.options['ignore_hardlink_matches'] = True
|
app.options['ignore_hardlink_matches'] = True
|
||||||
@ -120,7 +120,7 @@ class TestCaseDupeGuru:
|
|||||||
# Issue #140
|
# Issue #140
|
||||||
# It's possible that rename operation has its selected row swept off from under it, thus
|
# It's possible that rename operation has its selected row swept off from under it, thus
|
||||||
# making the selected row None. Don't crash when it happens.
|
# making the selected row None. Don't crash when it happens.
|
||||||
dgapp = DupeGuru()
|
dgapp = TestApp().app
|
||||||
# selected_row is None because there's no result.
|
# selected_row is None because there's no result.
|
||||||
assert not dgapp.result_table.rename_selected('foo') # no crash
|
assert not dgapp.result_table.rename_selected('foo') # no crash
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ class TestCaseDupeGuru_clean_empty_dirs:
|
|||||||
monkeypatch.setattr(hscommon.util, 'delete_if_empty', log_calls(lambda path, files_to_delete=[]: None))
|
monkeypatch.setattr(hscommon.util, 'delete_if_empty', log_calls(lambda path, files_to_delete=[]: None))
|
||||||
# XXX This monkeypatch is temporary. will be fixed in a better monkeypatcher.
|
# XXX This monkeypatch is temporary. will be fixed in a better monkeypatcher.
|
||||||
monkeypatch.setattr(app, 'delete_if_empty', hscommon.util.delete_if_empty)
|
monkeypatch.setattr(app, 'delete_if_empty', hscommon.util.delete_if_empty)
|
||||||
self.app = DupeGuru()
|
self.app = TestApp().app
|
||||||
|
|
||||||
def test_option_off(self, do_setup):
|
def test_option_off(self, do_setup):
|
||||||
self.app.clean_empty_dirs(Path('/foo/bar'))
|
self.app.clean_empty_dirs(Path('/foo/bar'))
|
||||||
@ -164,20 +164,14 @@ class TestCaseDupeGuru_clean_empty_dirs:
|
|||||||
|
|
||||||
class TestCaseDupeGuruWithResults:
|
class TestCaseDupeGuruWithResults:
|
||||||
def pytest_funcarg__do_setup(self, request):
|
def pytest_funcarg__do_setup(self, request):
|
||||||
# XXX eventually, convert this to TestApp-based tests
|
app = TestApp()
|
||||||
self.app = DupeGuru()
|
self.app = app.app
|
||||||
self.objects,self.matches,self.groups = GetTestGroups()
|
self.objects,self.matches,self.groups = GetTestGroups()
|
||||||
self.app.results.groups = self.groups
|
self.app.results.groups = self.groups
|
||||||
self.dpanel = self.app.details_panel
|
self.dpanel = app.dpanel
|
||||||
self.dpanel.view = CallLogger()
|
self.dtree = app.dtree
|
||||||
self.dtree = self.app.directory_tree
|
self.rtable = app.rtable
|
||||||
self.dtree.view = CallLogger()
|
self.rtable.refresh()
|
||||||
self.rtable_gui = CallLogger()
|
|
||||||
self.rtable = self.app.result_table
|
|
||||||
self.rtable.view = self.rtable_gui
|
|
||||||
self.dpanel.connect()
|
|
||||||
self.dtree.connect()
|
|
||||||
self.rtable.connect()
|
|
||||||
tmpdir = request.getfuncargvalue('tmpdir')
|
tmpdir = request.getfuncargvalue('tmpdir')
|
||||||
tmppath = Path(str(tmpdir))
|
tmppath = Path(str(tmpdir))
|
||||||
io.mkdir(tmppath + 'foo')
|
io.mkdir(tmppath + 'foo')
|
||||||
@ -422,16 +416,14 @@ class TestCaseDupeGuru_renameSelected:
|
|||||||
groups = engine.get_groups(matches)
|
groups = engine.get_groups(matches)
|
||||||
g = groups[0]
|
g = groups[0]
|
||||||
g.prioritize(lambda x:x.name)
|
g.prioritize(lambda x:x.name)
|
||||||
app = DupeGuru()
|
app = TestApp()
|
||||||
app.results.groups = groups
|
app.app.results.groups = groups
|
||||||
self.app = app
|
self.app = app.app
|
||||||
|
self.rtable = app.rtable
|
||||||
|
self.rtable.refresh()
|
||||||
self.groups = groups
|
self.groups = groups
|
||||||
self.p = p
|
self.p = p
|
||||||
self.files = files
|
self.files = files
|
||||||
self.rtable_gui = CallLogger()
|
|
||||||
self.rtable = self.app.result_table
|
|
||||||
self.rtable.view = self.rtable_gui
|
|
||||||
self.rtable.connect()
|
|
||||||
|
|
||||||
def test_simple(self, do_setup):
|
def test_simple(self, do_setup):
|
||||||
app = self.app
|
app = self.app
|
||||||
@ -477,10 +469,9 @@ class TestAppWithDirectoriesInTree:
|
|||||||
io.mkdir(p + 'sub1')
|
io.mkdir(p + 'sub1')
|
||||||
io.mkdir(p + 'sub2')
|
io.mkdir(p + 'sub2')
|
||||||
io.mkdir(p + 'sub3')
|
io.mkdir(p + 'sub3')
|
||||||
self.app = DupeGuru()
|
app = TestApp()
|
||||||
self.dtree = self.app.directory_tree
|
self.app = app.app
|
||||||
self.dtree.view = CallLogger()
|
self.dtree = app.dtree
|
||||||
self.dtree.connect()
|
|
||||||
self.dtree.add_directory(p)
|
self.dtree.add_directory(p)
|
||||||
self.dtree.view.clear_calls()
|
self.dtree.view.clear_calls()
|
||||||
|
|
||||||
|
@ -36,6 +36,9 @@ class DupeGuruView:
|
|||||||
def set_default(self, key_name, value):
|
def set_default(self, key_name, value):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def show_message(self, msg):
|
||||||
|
pass
|
||||||
|
|
||||||
def ask_yes_no(self, prompt):
|
def ask_yes_no(self, prompt):
|
||||||
return True # always answer yes
|
return True # always answer yes
|
||||||
|
|
||||||
@ -144,7 +147,11 @@ class TestApp(TestAppBase):
|
|||||||
self.rtable = link_gui(self.app.result_table)
|
self.rtable = link_gui(self.app.result_table)
|
||||||
self.dtree = link_gui(self.app.directory_tree)
|
self.dtree = link_gui(self.app.directory_tree)
|
||||||
self.dpanel = link_gui(self.app.details_panel)
|
self.dpanel = link_gui(self.app.details_panel)
|
||||||
|
self.slabel = link_gui(self.app.stats_label)
|
||||||
self.pdialog = PrioritizeDialog(self.app)
|
self.pdialog = PrioritizeDialog(self.app)
|
||||||
|
link_gui(self.pdialog.category_list)
|
||||||
|
link_gui(self.pdialog.criteria_list)
|
||||||
|
link_gui(self.pdialog.prioritization_list)
|
||||||
|
|
||||||
#--- Helpers
|
#--- Helpers
|
||||||
def select_pri_criterion(self, name):
|
def select_pri_criterion(self, name):
|
||||||
|
@ -16,13 +16,13 @@ class DetailsDialog(QDialog):
|
|||||||
QDialog.__init__(self, parent, Qt.Tool)
|
QDialog.__init__(self, parent, Qt.Tool)
|
||||||
self.app = app
|
self.app = app
|
||||||
self.model = app.model.details_panel
|
self.model = app.model.details_panel
|
||||||
self.model.view = self
|
|
||||||
self._setupUi()
|
self._setupUi()
|
||||||
if self.app.prefs.detailsWindowRect is not None:
|
if self.app.prefs.detailsWindowRect is not None:
|
||||||
self.setGeometry(self.app.prefs.detailsWindowRect)
|
self.setGeometry(self.app.prefs.detailsWindowRect)
|
||||||
self.tableModel = DetailsModel(self.model)
|
self.tableModel = DetailsModel(self.model)
|
||||||
# tableView is defined in subclasses
|
# tableView is defined in subclasses
|
||||||
self.tableView.setModel(self.tableModel)
|
self.tableView.setModel(self.tableModel)
|
||||||
|
self.model.view = self
|
||||||
|
|
||||||
self.app.willSavePrefs.connect(self.appWillSavePrefs)
|
self.app.willSavePrefs.connect(self.appWillSavePrefs)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user