2009-08-05 08:59:46 +00:00
/ *
2010-01-01 20:11:34 +00:00
Copyright 2010 Hardcoded Software ( http : // www . hardcoded . net )
2009-08-05 08:59:46 +00:00
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
* /
2009-06-01 09:55:11 +00:00
# import "ResultWindow.h"
2009-12-30 16:34:41 +00:00
# import "../../cocoalib/Dialogs.h"
# import "../../cocoalib/ProgressController.h"
# import "../../cocoalib/RegistrationInterface.h"
# import "../../cocoalib/Utils.h"
2009-06-01 09:55:11 +00:00
# import "AppDelegate.h"
# import "Consts.h"
@ implementation ResultWindow
/ * Override * /
- ( void ) awakeFromNib
{
[ super awakeFromNib ] ;
2009-10-30 14:40:17 +00:00
[ [ self window ] setTitle : @ "dupeGuru Music Edition" ] ;
2009-06-01 09:55:11 +00:00
_displayDelta = NO ;
_powerMode = NO ;
_deltaColumns = [ [ NSMutableIndexSet indexSetWithIndexesInRange : NSMakeRange ( 2 , 7 ) ] retain ] ;
[ _deltaColumns removeIndex : 6 ] ;
[ deltaSwitch setSelectedSegment : 0 ] ;
[ pmSwitch setSelectedSegment : 0 ] ;
[ py setDisplayDeltaValues : b2n ( _displayDelta ) ] ;
[ matches setTarget : self ] ;
[ matches setDoubleAction : @ selector ( openSelected : ) ] ;
[ self refreshStats ] ;
[ [ NSNotificationCenter defaultCenter ] addObserver : self selector : @ selector ( resultsMarkingChanged : ) name : ResultsMarkingChangedNotification object : nil ] ;
}
/ * Actions * /
- ( IBAction ) clearIgnoreList : ( id ) sender
{
2010-01-15 10:19:24 +00:00
NSInteger i = n2i ( [ py getIgnoreListCount ] ) ;
2009-06-01 09:55:11 +00:00
if ( ! i )
return ;
if ( [ Dialogs askYesNo : [ NSString stringWithFormat : @ "Do you really want to remove all %d items from the ignore list?" , i ] ] = = NSAlertSecondButtonReturn ) // NO
return ;
[ py clearIgnoreList ] ;
}
- ( IBAction ) filter : ( id ) sender
{
NSUserDefaults * ud = [ NSUserDefaults standardUserDefaults ] ;
[ py setEscapeFilterRegexp : b2n ( ! n2b ( [ ud objectForKey : @ "useRegexpFilter" ] ) ) ] ;
[ py applyFilter : [ filterField stringValue ] ] ;
[ [ NSNotificationCenter defaultCenter ] postNotificationName : ResultsChangedNotification object : self ] ;
}
- ( IBAction ) ignoreSelected : ( id ) sender
{
NSArray * nodeList = [ self getSelected : YES ] ;
if ( ! [ nodeList count ] )
return ;
if ( [ Dialogs askYesNo : [ NSString stringWithFormat : @ "All selected %d matches are going to be ignored in all subsequent scans. Continue?" , [ nodeList count ] ] ] = = NSAlertSecondButtonReturn ) // NO
return ;
[ self performPySelection : [ self getSelectedPaths : YES ] ] ;
[ py addSelectedToIgnoreList ] ;
[ py removeSelected ] ;
[ [ NSNotificationCenter defaultCenter ] postNotificationName : ResultsChangedNotification object : self ] ;
}
- ( IBAction ) markAll : ( id ) sender
{
[ py markAll ] ;
[ [ NSNotificationCenter defaultCenter ] postNotificationName : ResultsMarkingChangedNotification object : self ] ;
}
- ( IBAction ) markInvert : ( id ) sender
{
[ py markInvert ] ;
[ [ NSNotificationCenter defaultCenter ] postNotificationName : ResultsMarkingChangedNotification object : self ] ;
}
- ( IBAction ) markNone : ( id ) sender
{
[ py markNone ] ;
[ [ NSNotificationCenter defaultCenter ] postNotificationName : ResultsMarkingChangedNotification object : self ] ;
}
- ( IBAction ) markSelected : ( id ) sender
{
[ self performPySelection : [ self getSelectedPaths : YES ] ] ;
[ py toggleSelectedMark ] ;
[ [ NSNotificationCenter defaultCenter ] postNotificationName : ResultsMarkingChangedNotification object : self ] ;
}
- ( IBAction ) markToggle : ( id ) sender
{
OVNode * node = [ matches itemAtRow : [ matches clickedRow ] ] ;
[ self performPySelection : [ NSArray arrayWithObject : p2a ( [ node indexPath ] ) ] ] ;
[ py toggleSelectedMark ] ;
[ [ NSNotificationCenter defaultCenter ] postNotificationName : ResultsMarkingChangedNotification object : self ] ;
}
- ( IBAction ) openSelected : ( id ) sender
{
[ self performPySelection : [ self getSelectedPaths : NO ] ] ;
[ py openSelected ] ;
}
- ( IBAction ) refresh : ( id ) sender
{
[ [ NSNotificationCenter defaultCenter ] postNotificationName : ResultsChangedNotification object : self ] ;
}
- ( IBAction ) removeDeadTracks : ( id ) sender
{
[ ( PyDupeGuru * ) py scanDeadTracks ] ;
}
- ( IBAction ) removeMarked : ( id ) sender
{
int mark_count = [ [ py getMarkCount ] intValue ] ;
if ( ! mark_count )
return ;
if ( [ Dialogs askYesNo : [ NSString stringWithFormat : @ "You are about to remove %d files from results. Continue?" , mark_count ] ] = = NSAlertSecondButtonReturn ) // NO
return ;
[ py removeMarked ] ;
[ [ NSNotificationCenter defaultCenter ] postNotificationName : ResultsChangedNotification object : self ] ;
}
- ( IBAction ) removeSelected : ( id ) sender
{
NSArray * nodeList = [ self getSelected : YES ] ;
if ( ! [ nodeList count ] )
return ;
if ( [ Dialogs askYesNo : [ NSString stringWithFormat : @ "You are about to remove %d files from results. Continue?" , [ nodeList count ] ] ] = = NSAlertSecondButtonReturn ) // NO
return ;
[ self performPySelection : [ self getSelectedPaths : YES ] ] ;
[ py removeSelected ] ;
[ [ NSNotificationCenter defaultCenter ] postNotificationName : ResultsChangedNotification object : self ] ;
}
- ( IBAction ) renameSelected : ( id ) sender
{
2010-01-15 10:19:24 +00:00
NSInteger col = [ matches columnWithIdentifier : @ "0" ] ;
NSInteger row = [ matches selectedRow ] ;
2009-06-01 09:55:11 +00:00
[ matches editColumn : col row : row withEvent : [ NSApp currentEvent ] select : YES ] ;
}
- ( IBAction ) resetColumnsToDefault : ( id ) sender
{
NSMutableArray * columnsOrder = [ NSMutableArray array ] ;
[ columnsOrder addObject : @ "0" ] ;
[ columnsOrder addObject : @ "2" ] ;
[ columnsOrder addObject : @ "3" ] ;
[ columnsOrder addObject : @ "4" ] ;
[ columnsOrder addObject : @ "16" ] ;
NSMutableDictionary * columnsWidth = [ NSMutableDictionary dictionary ] ;
[ columnsWidth setObject : i2n ( 214 ) forKey : @ "0" ] ;
[ columnsWidth setObject : i2n ( 63 ) forKey : @ "2" ] ;
[ columnsWidth setObject : i2n ( 50 ) forKey : @ "3" ] ;
[ columnsWidth setObject : i2n ( 50 ) forKey : @ "4" ] ;
[ columnsWidth setObject : i2n ( 57 ) forKey : @ "16" ] ;
[ self restoreColumnsPosition : columnsOrder widths : columnsWidth ] ;
}
- ( IBAction ) revealSelected : ( id ) sender
{
[ self performPySelection : [ self getSelectedPaths : NO ] ] ;
[ py revealSelected ] ;
}
- ( IBAction ) startDuplicateScan : ( id ) sender
{
if ( [ matches numberOfRows ] > 0 )
{
if ( [ Dialogs askYesNo : @ "Are you sure you want to start a new duplicate scan?" ] = = NSAlertSecondButtonReturn ) // NO
return ;
}
NSUserDefaults * ud = [ NSUserDefaults standardUserDefaults ] ;
PyDupeGuru * _py = ( PyDupeGuru * ) py ;
[ _py setScanType : [ ud objectForKey : @ "scanType" ] ] ;
[ _py enable : [ ud objectForKey : @ "scanTagTrack" ] scanForTag : @ "track" ] ;
[ _py enable : [ ud objectForKey : @ "scanTagArtist" ] scanForTag : @ "artist" ] ;
[ _py enable : [ ud objectForKey : @ "scanTagAlbum" ] scanForTag : @ "album" ] ;
[ _py enable : [ ud objectForKey : @ "scanTagTitle" ] scanForTag : @ "title" ] ;
[ _py enable : [ ud objectForKey : @ "scanTagGenre" ] scanForTag : @ "genre" ] ;
[ _py enable : [ ud objectForKey : @ "scanTagYear" ] scanForTag : @ "year" ] ;
[ _py setMinMatchPercentage : [ ud objectForKey : @ "minMatchPercentage" ] ] ;
[ _py setWordWeighting : [ ud objectForKey : @ "wordWeighting" ] ] ;
[ _py setMixFileKind : [ ud objectForKey : @ "mixFileKind" ] ] ;
[ _py setMatchSimilarWords : [ ud objectForKey : @ "matchSimilarWords" ] ] ;
2010-01-15 10:19:24 +00:00
NSInteger r = n2i ( [ py doScan ] ) ;
2009-06-01 09:55:11 +00:00
[ matches reloadData ] ;
[ self refreshStats ] ;
if ( r = = 1 )
[ Dialogs showMessage : @ "You cannot make a duplicate scan with only reference directories." ] ;
if ( r = = 3 )
{
[ Dialogs showMessage : @ "The selected directories contain no scannable file." ] ;
[ app toggleDirectories : nil ] ;
}
}
- ( IBAction ) toggleDelta : ( id ) sender
{
if ( [ deltaSwitch selectedSegment ] = = 1 )
[ deltaSwitch setSelectedSegment : 0 ] ;
else
[ deltaSwitch setSelectedSegment : 1 ] ;
[ self changeDelta : sender ] ;
}
/ * Public * /
- ( void ) initResultColumns
{
NSTableColumn * refCol = [ matches tableColumnWithIdentifier : @ "0" ] ;
_resultColumns = [ [ NSMutableArray alloc ] init ] ;
[ _resultColumns addObject : [ matches tableColumnWithIdentifier : @ "0" ] ] ; // File Name
[ _resultColumns addObject : [ self getColumnForIdentifier : 1 title : @ "Directory" width : 120 refCol : refCol ] ] ;
2009-10-30 14:40:17 +00:00
NSTableColumn * sizeCol = [ self getColumnForIdentifier : 2 title : @ "Size (MB)" width : 63 refCol : refCol ] ;
[ [ sizeCol dataCell ] setAlignment : NSRightTextAlignment ] ;
[ _resultColumns addObject : sizeCol ] ;
NSTableColumn * timeCol = [ self getColumnForIdentifier : 3 title : @ "Time" width : 50 refCol : refCol ] ;
[ [ timeCol dataCell ] setAlignment : NSRightTextAlignment ] ;
[ _resultColumns addObject : timeCol ] ;
NSTableColumn * brCol = [ self getColumnForIdentifier : 4 title : @ "Bitrate" width : 50 refCol : refCol ] ;
[ [ brCol dataCell ] setAlignment : NSRightTextAlignment ] ;
[ _resultColumns addObject : brCol ] ;
2009-06-01 09:55:11 +00:00
[ _resultColumns addObject : [ self getColumnForIdentifier : 5 title : @ "Sample Rate" width : 60 refCol : refCol ] ] ;
[ _resultColumns addObject : [ self getColumnForIdentifier : 6 title : @ "Kind" width : 40 refCol : refCol ] ] ;
[ _resultColumns addObject : [ self getColumnForIdentifier : 7 title : @ "Creation" width : 120 refCol : refCol ] ] ;
[ _resultColumns addObject : [ self getColumnForIdentifier : 8 title : @ "Modification" width : 120 refCol : refCol ] ] ;
[ _resultColumns addObject : [ self getColumnForIdentifier : 9 title : @ "Title" width : 120 refCol : refCol ] ] ;
[ _resultColumns addObject : [ self getColumnForIdentifier : 10 title : @ "Artist" width : 120 refCol : refCol ] ] ;
[ _resultColumns addObject : [ self getColumnForIdentifier : 11 title : @ "Album" width : 120 refCol : refCol ] ] ;
[ _resultColumns addObject : [ self getColumnForIdentifier : 12 title : @ "Genre" width : 80 refCol : refCol ] ] ;
[ _resultColumns addObject : [ self getColumnForIdentifier : 13 title : @ "Year" width : 40 refCol : refCol ] ] ;
[ _resultColumns addObject : [ self getColumnForIdentifier : 14 title : @ "Track Number" width : 40 refCol : refCol ] ] ;
[ _resultColumns addObject : [ self getColumnForIdentifier : 15 title : @ "Comment" width : 120 refCol : refCol ] ] ;
2009-10-30 14:40:17 +00:00
[ _resultColumns addObject : [ self getColumnForIdentifier : 16 title : @ "Match %" width : 57 refCol : refCol ] ] ;
2009-06-01 09:55:11 +00:00
[ _resultColumns addObject : [ self getColumnForIdentifier : 17 title : @ "Words Used" width : 120 refCol : refCol ] ] ;
[ _resultColumns addObject : [ self getColumnForIdentifier : 18 title : @ "Dupe Count" width : 80 refCol : refCol ] ] ;
}
/ * Delegate * /
- ( void ) outlineView : ( NSOutlineView * ) outlineView willDisplayCell : ( id ) cell forTableColumn : ( NSTableColumn * ) tableColumn item : ( id ) item
{
OVNode * node = item ;
if ( [ [ tableColumn identifier ] isEqual : @ "mark" ] )
{
[ cell setEnabled : [ node isMarkable ] ] ;
}
if ( [ cell isKindOfClass : [ NSTextFieldCell class ] ] )
{
// Determine if the text color will be blue due to directory being reference .
NSTextFieldCell * textCell = cell ;
if ( [ node isMarkable ] )
[ textCell setTextColor : [ NSColor blackColor ] ] ;
else
[ textCell setTextColor : [ NSColor blueColor ] ] ;
if ( ( _displayDelta ) && ( _powerMode || ( [ node level ] > 1 ) ) )
{
int i = [ [ tableColumn identifier ] intValue ] ;
if ( [ _deltaColumns containsIndex : i ] )
[ textCell setTextColor : [ NSColor orangeColor ] ] ;
}
}
}
/ * Notifications * /
- ( void ) jobCompleted : ( NSNotification * ) aNotification
{
[ super jobCompleted : aNotification ] ;
id lastAction = [ [ ProgressController mainProgressController ] jobId ] ;
if ( [ lastAction isEqualTo : jobScanDeadTracks ] )
{
2010-01-15 10:19:24 +00:00
NSInteger deadTrackCount = [ ( PyDupeGuru * ) py deadTrackCount ] ;
2009-06-01 09:55:11 +00:00
if ( deadTrackCount > 0 )
{
NSString * msg = @ "Your iTunes Library contains %d dead tracks ready to be removed. Continue?" ;
if ( [ Dialogs askYesNo : [ NSString stringWithFormat : msg , deadTrackCount ] ] = = NSAlertFirstButtonReturn )
[ ( PyDupeGuru * ) py removeDeadTracks ] ;
}
else
{
[ Dialogs showMessage : @ "You have no dead tracks in your iTunes Library" ] ;
}
}
}
- ( void ) outlineViewSelectionDidChange : ( NSNotification * ) notification
{
[ self performPySelection : [ self getSelectedPaths : NO ] ] ;
[ py refreshDetailsWithSelected ] ;
[ [ NSNotificationCenter defaultCenter ] postNotificationName : DuplicateSelectionChangedNotification object : self ] ;
}
- ( void ) resultsMarkingChanged : ( NSNotification * ) aNotification
{
[ matches invalidateMarkings ] ;
[ self refreshStats ] ;
}
@ end