1
0
mirror of https://github.com/arsenetar/dupeguru.git synced 2025-03-10 05:34:36 +00:00

Removed temporary objp conversion hacks.

--HG--
branch : objp
This commit is contained in:
Virgil Dupras 2012-01-13 15:25:34 -05:00
parent 950cd0c341
commit 55db21f3e0
29 changed files with 88 additions and 86 deletions

View File

@ -179,7 +179,7 @@ def build_cocoa_bridging_interfaces():
import objp.p2o import objp.p2o
add_to_pythonpath('cocoa') add_to_pythonpath('cocoa')
add_to_pythonpath('cocoalib') add_to_pythonpath('cocoalib')
from cocoa.inter2 import (PyGUIObject, GUIObjectView, PyColumns, ColumnsView, PyOutline, from cocoa.inter import (PyGUIObject, GUIObjectView, PyColumns, ColumnsView, PyOutline,
OutlineView, PySelectableList, SelectableListView, PyTable, TableView, PyFairware) OutlineView, PySelectableList, SelectableListView, PyTable, TableView, PyFairware)
from inter.details_panel import PyDetailsPanel, DetailsPanelView from inter.details_panel import PyDetailsPanel, DetailsPanelView
from inter.directory_outline import PyDirectoryOutline, DirectoryOutlineView from inter.directory_outline import PyDirectoryOutline, DirectoryOutlineView

View File

@ -62,7 +62,7 @@ http://www.hardcoded.net/licenses/bsd_license
- (DetailsPanel *)createDetailsPanel - (DetailsPanel *)createDetailsPanel
{ {
return [[DetailsPanel alloc] init]; return [[DetailsPanel alloc] initWithPyRef:[model detailsPanel]];
} }
- (NSString *)homepageURL - (NSString *)homepageURL
@ -210,7 +210,7 @@ http://www.hardcoded.net/licenses/bsd_license
/* model --> view */ /* model --> view */
- (void)showExtraFairwareReminder - (void)showExtraFairwareReminder
{ {
ExtraFairwareReminder *dialog = [[ExtraFairwareReminder alloc] init]; ExtraFairwareReminder *dialog = [[ExtraFairwareReminder alloc] initWithPyRef:[model extraFairwareReminder]];
[dialog start]; [dialog start];
[NSApp runModalForWindow:[dialog window]]; [NSApp runModalForWindow:[dialog window]];
[dialog close]; [dialog close];

View File

@ -7,16 +7,17 @@ http://www.hardcoded.net/licenses/bsd_license
*/ */
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import <Python.h>
#import "PyDetailsPanel.h" #import "PyDetailsPanel.h"
@interface DetailsPanel : NSWindowController @interface DetailsPanel : NSWindowController
{ {
IBOutlet NSTableView *detailsTable; IBOutlet NSTableView *detailsTable;
PyDetailsPanel *py; PyDetailsPanel *model;
} }
- (id)init; - (id)initWithPyRef:(PyObject *)aPyRef;
- (PyDetailsPanel *)py; - (PyDetailsPanel *)model;
- (BOOL)isVisible; - (BOOL)isVisible;
- (void)toggleVisibility; - (void)toggleVisibility;

View File

@ -10,26 +10,26 @@ http://www.hardcoded.net/licenses/bsd_license
#import "Utils.h" #import "Utils.h"
@implementation DetailsPanel @implementation DetailsPanel
- (id)init - (id)initWithPyRef:(PyObject *)aPyRef
{ {
self = [super initWithWindowNibName:@"DetailsPanel"]; self = [super initWithWindowNibName:@"DetailsPanel"];
[self window]; //So the detailsTable is initialized. [self window]; //So the detailsTable is initialized.
py = [[PyDetailsPanel alloc] initWithModel:findHackishModel(@"details_panel")]; model = [[PyDetailsPanel alloc] initWithModel:aPyRef];
[py bindCallback:createCallback(@"DetailsPanelView", self)]; [model bindCallback:createCallback(@"DetailsPanelView", self)];
[py connect]; [model connect];
return self; return self;
} }
- (void)dealloc - (void)dealloc
{ {
[py disconnect]; [model disconnect];
[py release]; [model release];
[super dealloc]; [super dealloc];
} }
- (PyDetailsPanel *)py - (PyDetailsPanel *)model
{ {
return (PyDetailsPanel *)py; return (PyDetailsPanel *)model;
} }
- (void)refreshDetails - (void)refreshDetails
@ -56,12 +56,12 @@ http://www.hardcoded.net/licenses/bsd_license
/* NSTableView Delegate */ /* NSTableView Delegate */
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{ {
return [[self py] numberOfRows]; return [[self model] numberOfRows];
} }
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)column row:(NSInteger)row - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)column row:(NSInteger)row
{ {
return [[self py] valueForColumn:[column identifier] row:row]; return [[self model] valueForColumn:[column identifier] row:row];
} }
/* Python --> Cocoa */ /* Python --> Cocoa */

View File

@ -7,12 +7,13 @@ http://www.hardcoded.net/licenses/bsd_license
*/ */
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import <Python.h>
#import "HSOutline.h" #import "HSOutline.h"
#import "PyDirectoryOutline.h" #import "PyDirectoryOutline.h"
#define DGAddedFoldersNotification @"DGAddedFoldersNotification" #define DGAddedFoldersNotification @"DGAddedFoldersNotification"
@interface DirectoryOutline : HSOutline {} @interface DirectoryOutline : HSOutline {}
- (id)initWithOutlineView:(HSOutlineView *)aOutlineView; - (id)initWithPyRef:(PyObject *)aPyRef outlineView:(HSOutlineView *)aOutlineView;
- (PyDirectoryOutline *)py; - (PyDirectoryOutline *)py;
@end; @end;

View File

@ -10,9 +10,9 @@ http://www.hardcoded.net/licenses/bsd_license
#import "Utils.h" #import "Utils.h"
@implementation DirectoryOutline @implementation DirectoryOutline
- (id)initWithOutlineView:(HSOutlineView *)aOutlineView - (id)initWithPyRef:(PyObject *)aPyRef outlineView:(HSOutlineView *)aOutlineView
{ {
PyDirectoryOutline *model = [[PyDirectoryOutline alloc] initWithModel:findHackishModel(@"directory_tree")]; PyDirectoryOutline *model = [[PyDirectoryOutline alloc] initWithModel:aPyRef];
self = [super initWithPy:model view:aOutlineView]; self = [super initWithPy:model view:aOutlineView];
[model bindCallback:createCallback(@"DirectoryOutlineView", self)]; [model bindCallback:createCallback(@"DirectoryOutlineView", self)];
[model release]; [model release];

View File

@ -24,7 +24,7 @@ http://www.hardcoded.net/licenses/bsd_license
[self fillPopUpMenu]; [self fillPopUpMenu];
_recentDirectories = [[HSRecentFiles alloc] initWithName:@"recentDirectories" menu:[addButtonPopUp menu]]; _recentDirectories = [[HSRecentFiles alloc] initWithName:@"recentDirectories" menu:[addButtonPopUp menu]];
[_recentDirectories setDelegate:self]; [_recentDirectories setDelegate:self];
outline = [[DirectoryOutline alloc] initWithOutlineView:outlineView]; outline = [[DirectoryOutline alloc] initWithPyRef:[model directoryTree] outlineView:outlineView];
[self refreshRemoveButtonText]; [self refreshRemoveButtonText];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(directorySelectionChanged:) [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(directorySelectionChanged:)
name:NSOutlineViewSelectionDidChangeNotification object:outlineView]; name:NSOutlineViewSelectionDidChangeNotification object:outlineView];

View File

@ -13,11 +13,11 @@ http://www.hardcoded.net/licenses/bsd_license
{ {
IBOutlet NSButton *continueButton; IBOutlet NSButton *continueButton;
PyExtraFairwareReminder *py; PyExtraFairwareReminder *model;
NSTimer *timer; NSTimer *timer;
} }
- (id)init; - (id)initWithPyRef:(PyObject *)aPyRef;
- (PyExtraFairwareReminder *)py; - (PyExtraFairwareReminder *)model;
- (void)start; - (void)start;
- (void)updateButton; - (void)updateButton;

View File

@ -10,36 +10,36 @@ http://www.hardcoded.net/licenses/bsd_license
#import "Utils.h" #import "Utils.h"
@implementation ExtraFairwareReminder @implementation ExtraFairwareReminder
- (id)init - (id)initWithPyRef:(PyObject *)aPyRef
{ {
self = [super initWithWindowNibName:@"ExtraFairwareReminder"]; self = [super initWithWindowNibName:@"ExtraFairwareReminder"];
[self window]; [self window];
[continueButton setEnabled:NO]; [continueButton setEnabled:NO];
py = [[PyExtraFairwareReminder alloc] initWithModel:findHackishModel(@"extra_fairware_reminder")]; model = [[PyExtraFairwareReminder alloc] initWithModel:aPyRef];
[py bindCallback:createCallback(@"ExtraFairwareReminderView", self)]; [model bindCallback:createCallback(@"ExtraFairwareReminderView", self)];
return self; return self;
} }
- (void)dealloc - (void)dealloc
{ {
[py release]; [model release];
[timer release]; [timer release];
[super dealloc]; [super dealloc];
} }
- (PyExtraFairwareReminder *)py - (PyExtraFairwareReminder *)model
{ {
return (PyExtraFairwareReminder *)py; return (PyExtraFairwareReminder *)model;
} }
- (void)start - (void)start
{ {
[[self py] start]; [[self model] start];
} }
- (void)updateButton - (void)updateButton
{ {
[[self py] updateButton]; [[self model] updateButton];
} }
- (IBAction)continue:(id)sender - (IBAction)continue:(id)sender

View File

@ -18,13 +18,13 @@ http://www.hardcoded.net/licenses/bsd_license
IBOutlet NSTableView *criteriaTableView; IBOutlet NSTableView *criteriaTableView;
IBOutlet NSTableView *prioritizationTableView; IBOutlet NSTableView *prioritizationTableView;
PyPrioritizeDialog *py; PyPrioritizeDialog *model;
HSPopUpList *categoryPopUp; HSPopUpList *categoryPopUp;
HSSelectableList *criteriaList; HSSelectableList *criteriaList;
PrioritizeList *prioritizationList; PrioritizeList *prioritizationList;
} }
- (id)init; - (id)initWithPyRef:(PyObject *)aPyRef;
- (PyPrioritizeDialog *)py; - (PyPrioritizeDialog *)model;
- (IBAction)addSelected:(id)sender; - (IBAction)addSelected:(id)sender;
- (IBAction)removeSelected:(id)sender; - (IBAction)removeSelected:(id)sender;

View File

@ -10,41 +10,42 @@ http://www.hardcoded.net/licenses/bsd_license
#import "Utils.h" #import "Utils.h"
@implementation PrioritizeDialog @implementation PrioritizeDialog
- (id)init - (id)initWithPyRef:(PyObject *)aPyRef
{ {
self = [super initWithWindowNibName:@"PrioritizeDialog"]; self = [super initWithWindowNibName:@"PrioritizeDialog"];
[self window]; [self window];
py = [[PyPrioritizeDialog alloc] initWithModel:findHackishModel(@"prioritize_dialog")]; model = [[PyPrioritizeDialog alloc] initWithModel:aPyRef];
[py bindCallback:createCallback(@"PrioritizeDialogView", self)]; [model bindCallback:createCallback(@"PrioritizeDialogView", self)];
categoryPopUp = [[HSPopUpList alloc] initWithPyRef:[[self py] categoryList] popupView:categoryPopUpView]; categoryPopUp = [[HSPopUpList alloc] initWithPyRef:[[self model] categoryList] popupView:categoryPopUpView];
criteriaList = [[HSSelectableList alloc] initWithPyRef:[[self py] criteriaList] tableView:criteriaTableView]; criteriaList = [[HSSelectableList alloc] initWithPyRef:[[self model] criteriaList] tableView:criteriaTableView];
prioritizationList = [[PrioritizeList alloc] initWithPyRef:[[self py] prioritizationList] tableView:prioritizationTableView]; prioritizationList = [[PrioritizeList alloc] initWithPyRef:[[self model] prioritizationList] tableView:prioritizationTableView];
[py connect]; [model connect];
return self; return self;
} }
- (void)dealloc - (void)dealloc
{ {
[py disconnect]; [model disconnect];
[categoryPopUp release]; [categoryPopUp release];
[criteriaList release]; [criteriaList release];
[prioritizationList release]; [prioritizationList release];
[model release];
[super dealloc]; [super dealloc];
} }
- (PyPrioritizeDialog *)py - (PyPrioritizeDialog *)model
{ {
return (PyPrioritizeDialog *)py; return (PyPrioritizeDialog *)model;
} }
- (IBAction)addSelected:(id)sender - (IBAction)addSelected:(id)sender
{ {
[[self py] addSelected]; [[self model] addSelected];
} }
- (IBAction)removeSelected:(id)sender - (IBAction)removeSelected:(id)sender
{ {
[[self py] removeSelected]; [[self model] removeSelected];
} }
- (IBAction)ok:(id)sender - (IBAction)ok:(id)sender

View File

@ -17,7 +17,7 @@ http://www.hardcoded.net/licenses/bsd_license
PyProblemDialog *model; PyProblemDialog *model;
HSTable *problemTable; HSTable *problemTable;
} }
- (id)init; - (id)initWithPyRef:(PyObject *)aPyRef;
- (void)initializeColumns; - (void)initializeColumns;
- (IBAction)revealSelected:(id)sender; - (IBAction)revealSelected:(id)sender;

View File

@ -10,11 +10,11 @@ http://www.hardcoded.net/licenses/bsd_license
#import "Utils.h" #import "Utils.h"
@implementation ProblemDialog @implementation ProblemDialog
- (id)init - (id)initWithPyRef:(PyObject *)aPyRef
{ {
self = [super initWithWindowNibName:@"ProblemDialog"]; self = [super initWithWindowNibName:@"ProblemDialog"];
[self window]; //So the detailsTable is initialized. [self window]; //So the detailsTable is initialized.
model = [[PyProblemDialog alloc] initWithModel:findHackishModel(@"problem_dialog")]; model = [[PyProblemDialog alloc] initWithModel:aPyRef];
problemTable = [[HSTable alloc] initWithPyRef:[model problemTable] tableView:problemTableView]; problemTable = [[HSTable alloc] initWithPyRef:[model problemTable] tableView:problemTableView];
[self initializeColumns]; [self initializeColumns];
[model connect]; [model connect];

View File

@ -15,7 +15,7 @@ http://www.hardcoded.net/licenses/bsd_license
{ {
NSSet *_deltaColumns; NSSet *_deltaColumns;
} }
- (id)initWithView:(NSTableView *)aTableView; - (id)initWithPyRef:(PyObject *)aPyRef view:(NSTableView *)aTableView;
- (PyResultTable *)model; - (PyResultTable *)model;
- (BOOL)powerMarkerMode; - (BOOL)powerMarkerMode;
- (void)setPowerMarkerMode:(BOOL)aPowerMarkerMode; - (void)setPowerMarkerMode:(BOOL)aPowerMarkerMode;

View File

@ -18,9 +18,9 @@ http://www.hardcoded.net/licenses/bsd_license
@end @end
@implementation ResultTable @implementation ResultTable
- (id)initWithView:(NSTableView *)aTableView; - (id)initWithPyRef:(PyObject *)aPyRef view:(NSTableView *)aTableView
{ {
PyResultTable *m = [[PyResultTable alloc] initWithModel:findHackishModel(@"result_table")]; PyResultTable *m = [[PyResultTable alloc] initWithModel:aPyRef];
self = [super initWithModel:m tableView:aTableView]; self = [super initWithModel:m tableView:aTableView];
[m bindCallback:createCallback(@"ResultTableView", self)]; [m bindCallback:createCallback(@"ResultTableView", self)];
[m release]; [m release];

View File

@ -24,9 +24,9 @@ http://www.hardcoded.net/licenses/bsd_license
columnsMenu = [app columnsMenu]; columnsMenu = [app columnsMenu];
/* Put a cute iTunes-like bottom bar */ /* Put a cute iTunes-like bottom bar */
[[self window] setContentBorderThickness:28 forEdge:NSMinYEdge]; [[self window] setContentBorderThickness:28 forEdge:NSMinYEdge];
table = [[ResultTable alloc] initWithView:matches]; table = [[ResultTable alloc] initWithPyRef:[model resultTable] view:matches];
statsLabel = [[StatsLabel alloc] initWithLabelView:stats]; statsLabel = [[StatsLabel alloc] initWithPyRef:[model statsLabel] view:stats];
problemDialog = [[ProblemDialog alloc] init]; problemDialog = [[ProblemDialog alloc] initWithPyRef:[model problemDialog]];
[self initResultColumns]; [self initResultColumns];
[self fillColumnsMenu]; [self fillColumnsMenu];
[matches setTarget:self]; [matches setTarget:self];
@ -272,10 +272,10 @@ http://www.hardcoded.net/licenses/bsd_license
- (IBAction)reprioritizeResults:(id)sender - (IBAction)reprioritizeResults:(id)sender
{ {
PrioritizeDialog *dlg = [[PrioritizeDialog alloc] init]; PrioritizeDialog *dlg = [[PrioritizeDialog alloc] initWithPyRef:[model prioritizeDialog]];
NSInteger result = [NSApp runModalForWindow:[dlg window]]; NSInteger result = [NSApp runModalForWindow:[dlg window]];
if (result == NSRunStoppedResponse) { if (result == NSRunStoppedResponse) {
[[dlg py] performReprioritization]; [[dlg model] performReprioritization];
} }
[dlg release]; [dlg release];
[[self window] makeKeyAndOrderFront:nil]; [[self window] makeKeyAndOrderFront:nil];

View File

@ -7,13 +7,11 @@ http://www.hardcoded.net/licenses/bsd_license
*/ */
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "HSGUIController.h"
#import "PyStatsLabel.h" #import "PyStatsLabel.h"
@interface StatsLabel : NSObject { @interface StatsLabel : HSGUIController {}
PyStatsLabel *py; - (id)initWithPyRef:(PyObject *)aPyRef view:(NSTextField *)aLabelView;
NSTextField *view; - (PyStatsLabel *)model;
}
- (id)initWithLabelView:(NSTextField *)aLabelView;
- (PyStatsLabel *)py;
- (NSTextField *)labelView; - (NSTextField *)labelView;
@end @end

View File

@ -10,27 +10,27 @@ http://www.hardcoded.net/licenses/bsd_license
#import "Utils.h" #import "Utils.h"
@implementation StatsLabel @implementation StatsLabel
- (id)initWithLabelView:(NSTextField *)aLabelView - (id)initWithPyRef:(PyObject *)aPyRef view:(NSTextField *)aLabelView
{ {
self = [self init]; PyStatsLabel *m = [[PyStatsLabel alloc] initWithModel:aPyRef];
view = [aLabelView retain]; self = [self initWithModel:m view:aLabelView];
py = [[PyStatsLabel alloc] initWithModel:findHackishModel(@"stats_label")]; [m bindCallback:createCallback(@"StatsLabelView", self)];
[py bindCallback:createCallback(@"StatsLabelView", self)]; [m connect];
[[self py] connect]; [m release];
return self; return self;
} }
- (void)dealloc - (void)dealloc
{ {
[[self py] disconnect]; [[self model] disconnect];
[py release]; [model release];
[view release]; [view release];
[super dealloc]; [super dealloc];
} }
- (PyStatsLabel *)py - (PyStatsLabel *)model
{ {
return (PyStatsLabel *)py; return (PyStatsLabel *)model;
} }
- (NSTextField *)labelView - (NSTextField *)labelView
@ -41,6 +41,6 @@ http://www.hardcoded.net/licenses/bsd_license
/* Python --> Cocoa */ /* Python --> Cocoa */
- (void)refresh - (void)refresh
{ {
[[self labelView] setStringValue:[[self py] display]]; [[self labelView] setStringValue:[[self model] display]];
} }
@end @end

View File

@ -4,7 +4,7 @@ from objp.util import pyref, dontwrap
from jobprogress import job from jobprogress import job
import cocoa import cocoa
from cocoa import install_exception_hook, proxy from cocoa import install_exception_hook, proxy
from cocoa.inter2 import PyFairware, FairwareView from cocoa.inter import PyFairware, FairwareView
from hscommon.trans import trget from hscommon.trans import trget
from core.app import JobType from core.app import JobType
@ -45,6 +45,9 @@ class PyDupeGuruBase(PyFairware):
def prioritizeDialog(self) -> pyref: def prioritizeDialog(self) -> pyref:
return self.model.prioritize_dialog return self.model.prioritize_dialog
def problemDialog(self) -> pyref:
return self.model.problem_dialog
def statsLabel(self) -> pyref: def statsLabel(self) -> pyref:
return self.model.stats_label return self.model.stats_label

View File

@ -76,8 +76,6 @@ class DupeGuru(DupeGuruBase):
class PyDupeGuru(PyDupeGuruBase): class PyDupeGuru(PyDupeGuruBase):
def __init__(self): def __init__(self):
self._init(DupeGuru) self._init(DupeGuru)
import __main__
__main__.APP_INSTANCE = self.model
#---Properties #---Properties
def setMinMatchPercentage_(self, percentage: int): def setMinMatchPercentage_(self, percentage: int):

View File

@ -1,4 +1,4 @@
from cocoa.inter2 import PyGUIObject, GUIObjectView from cocoa.inter import PyGUIObject, GUIObjectView
class DetailsPanelView(GUIObjectView): class DetailsPanelView(GUIObjectView):
pass pass

View File

@ -1,5 +1,5 @@
from objp.util import dontwrap from objp.util import dontwrap
from cocoa.inter2 import PyOutline, GUIObjectView from cocoa.inter import PyOutline, GUIObjectView
class DirectoryOutlineView(GUIObjectView): class DirectoryOutlineView(GUIObjectView):
pass pass

View File

@ -1,5 +1,5 @@
from objp.util import dontwrap from objp.util import dontwrap
from cocoa.inter2 import PyGUIObject from cocoa.inter import PyGUIObject
class ExtraFairwareReminderView: class ExtraFairwareReminderView:
def startTimer(self): pass def startTimer(self): pass

View File

@ -1,5 +1,5 @@
from objp.util import pyref from objp.util import pyref
from cocoa.inter2 import PyGUIObject, GUIObjectView from cocoa.inter import PyGUIObject, GUIObjectView
class PrioritizeDialogView(GUIObjectView): class PrioritizeDialogView(GUIObjectView):
pass pass

View File

@ -1,4 +1,4 @@
from cocoa.inter2 import PySelectableList, SelectableListView from cocoa.inter import PySelectableList, SelectableListView
class PrioritizeListView(SelectableListView): class PrioritizeListView(SelectableListView):
pass pass

View File

@ -1,5 +1,5 @@
from objp.util import pyref from objp.util import pyref
from cocoa.inter2 import PyGUIObject from cocoa.inter import PyGUIObject
class PyProblemDialog(PyGUIObject): class PyProblemDialog(PyGUIObject):
def problemTable(self) -> pyref: def problemTable(self) -> pyref:

View File

@ -1,5 +1,5 @@
from objp.util import dontwrap from objp.util import dontwrap
from cocoa.inter2 import PyTable, TableView from cocoa.inter import PyTable, TableView
class ResultTableView(TableView): class ResultTableView(TableView):
def invalidateMarkings(self): pass def invalidateMarkings(self): pass

View File

@ -1,4 +1,4 @@
from cocoa.inter2 import PyGUIObject, GUIObjectView from cocoa.inter import PyGUIObject, GUIObjectView
class StatsLabelView(GUIObjectView): class StatsLabelView(GUIObjectView):
pass pass

View File

@ -7,7 +7,7 @@
from hscommon.trans import install_gettext_trans_under_cocoa from hscommon.trans import install_gettext_trans_under_cocoa
install_gettext_trans_under_cocoa() install_gettext_trans_under_cocoa()
from cocoa.inter2 import PySelectableList, PyColumns, PyTable from cocoa.inter import PySelectableList, PyColumns, PyTable
from inter.details_panel import PyDetailsPanel from inter.details_panel import PyDetailsPanel
from inter.directory_outline import PyDirectoryOutline from inter.directory_outline import PyDirectoryOutline