Eskil

Diff
Login

Differences From Artifact [ffe8fedea9]:

To Artifact [20f87e1aa2]:


194
195
196
197
198
199
200






201
202
203
204
205
206
207
208


209
210
211
212


213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212


213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

239
240
241
242
243
244
245







+
+
+
+
+
+






-
-
+
+




+
+


















-







            }
            close $ch1
            close $ch2
        }
    }
    return $eq
}

# Bring up an editor to display a file.
proc EditFile {file} {
    locateEditor ::util(editor)
    exec $::util(editor) $file &
}

snit::widget DirCompare {
    component tree
    component hsb
    component vsb

    option -leftdir
    option -rightdir
    option -leftdir  -default "" -configuremethod SetDirOption
    option -rightdir -default "" -configuremethod SetDirOption

    variable AfterId
    variable IdleQueue
    variable IdleQueueArr
    variable leftMark ""
    variable rightMark ""

    constructor {args} {
        install tree using ttk::treeview $win.tree -height 20 \
                -columns {type status leftfull leftname leftsize leftdate rightfull rightname rightsize rightdate} \
                -displaycolumns {leftname leftsize leftdate rightname rightsize rightdate}
        if {[tk windowingsystem] ne "aqua"} {
            install vsb using ttk::scrollbar $win.vsb -orient vertical \
                    -command "$tree yview"
            install hsb using ttk::scrollbar $win.hsb -orient horizontal \
                    -command "$tree xview"
        } else {
            install vsb using scrollbar $win.vsb -orient vertical \
                    -command "$tree yview"
            install hsb using scrollbar $win.hsb -orient horizontal \
                    -command "$tree xview"
        }
        $tree configure -yscroll "$vsb set" -xscroll "$hsb set"

        $self configurelist $args
        set AfterId ""
        set IdleQueue {}

        $tree heading \#0 -text "Directory"
        $tree heading leftname -text "Name"
        $tree heading leftsize -text "Size"
        $tree heading leftdate -text "Date"
248
249
250
251
252
253
254



































255
256



257
258
259
260
261
262
263
264
265
266

267
268
269
270
271

272
273

274
275
276
277
278
279

280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295

296
297
298
299
300
301
302
303
304
305
306
307
308
309
310

































































311
312
313
314
315
316
317

318
319
320
321
322

323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343

344
345
346
347
348
349
350
351
352
353
354
355

356
357
358
359

360
361

362
363

364
365
366
367
368




369
370

371
372
373

374
375

376
377
378
379
380




381
382
383

384
385
386
387
388
389
390
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296


297
298
299
300
301
302
303
304
305
306



307





308


309


310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417

418
419
420

421

422


423
424
425
426
427
428
429
430
431
432
433








434












435
436
437
438

439
440

441
442

443
444




445
446
447
448
449

450

451

452
453

454
455




456
457
458
459
460
461

462
463
464
465
466
467
468
469







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+







-
-
-
+
-
-
-
-
-
+
-
-
+
-
-




+
















+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+


-

-
+
-
-











-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+



-
+

-
+

-
+

-
-
-
-
+
+
+
+

-
+
-

-
+

-
+

-
-
-
-
+
+
+
+


-
+







        $tree tag configure unknown -foreground grey
        $tree tag configure empty   -foreground grey
        $tree tag configure equal   -foreground {}
        $tree tag configure new     -foreground green
        $tree tag configure old     -foreground blue
        $tree tag configure change  -foreground red

        bind $tree <<TreeviewOpen>> "[mymethod UpdateDirNode] \[%W focus\]"
        bind $tree <Button-3> "[mymethod ContextMenu] %x %y %X %Y"
        bind $tree <Double-ButtonPress-1> "[mymethod DoubleClick] %x %y"

        grid $tree $vsb -sticky nsew
        grid $hsb         -sticky nsew
        grid columnconfigure $win 0 -weight 1
        grid rowconfigure    $win 0 -weight 1

        $self configurelist $args
        #$self ReStart
    }
    destructor {

    }

    method SetDirOption {option value} {
        set options($option) $value
        if {$options(-leftdir) ne "" && \
                [file isdirectory $options(-leftdir)] && \
                $options(-rightdir) ne "" && \
                [file isdirectory $options(-rightdir)]} {
            after idle [mymethod ReStart]
        }
    }

    method ReStart {} {
        # Delete all idle processing
        if {$AfterId ne ""} {
            after cancel $AfterId
        }
        set AfterId ""
        set IdleQueue {}
        array unset IdleQueueArr
        
        # Fill in root data
        $tree set {} type       directory
        # Fill in clean root data
        $tree delete [$tree children {}]
        $tree set {} type directory
        $self SetNodeStatus {} empty
        $tree set {} leftfull   $options(-leftdir)
        $tree set {} leftname   [file tail $options(-leftdir)]
        $tree set {} rightfull  $options(-rightdir)
        $tree set {} rightname  [file tail $options(-rightdir)]

        $self UpdateDirNode {}
        bind $tree <<TreeviewOpen>> "[mymethod UpdateDirNode] \[%W focus\]"
        bind $tree <Button-3> "[mymethod ContextMenu] %x %y %X %Y"

    }
        grid $tree $vsb -sticky nsew
        grid $hsb         -sticky nsew
        grid columnconfigure $win 0 -weight 1
        grid rowconfigure    $win 0 -weight 1
    }

    destructor {

    # Format a time stamp for display
    }

    proc FormatDate {date} {
        clock format $date -format "%Y-%m-%d %H:%M:%S"
    }

    # Remove all equal nodes from tree
    method PruneEqual {} {
        set todo [$tree children {}]
        while {[llength $todo] > 0} {
            set todoNow $todo
            set todo {}
            foreach node $todoNow {
                set status [$tree set $node status]
                if {$status eq "equal"} {
                    $tree delete $node
                } else {
                    eval lappend todo [$tree children $node]
                }
            }
        }
    }

    # Open or close all directories in the tree view
    method OpenAll {{state 1}} {
        set todo [$tree children {}]
        while {[llength $todo] > 0} {
            set todoNow $todo
            set todo {}
            foreach node $todoNow {
                set children [$tree children $node]
                if {[llength $children] > 0} {
                    $tree item $node -open $state
                    eval lappend todo $children
                }
            }
        }
    }

    # Copy a file from one directory to the other
    method CopyFile {node from} {
        global dirdiff Pref

        set lf [$tree set $node leftfull]
        set rf [$tree set $node rightfull]
        set parent [$tree parent $node]
        set lp [$tree set $parent leftfull]
        set rp [$tree set $parent rightfull]

        if {$from eq "left"} {
            set src $lf
            if {$rf ne ""} {
                set dst $rf
            } elseif {$rp ne ""} {
                set dst [file join $rp [file tail $src]]
            } else {
                return
            }
        } elseif {$from eq "right"} {
            set src $rf
            if {$lf ne ""} {
                set dst $lf
            } elseif {$lp ne ""} {
                set dst [file join $lp [file tail $src]]
            } else {
                return
            }
        } else {
            error "Bad to argument to CopyFile: $to"
        }

        if {[file exists $dst]} {
            if {[tk_messageBox -icon question -title "Overwrite file?" -message \
                    "Copy\n$src\noverwriting\n$dst ?" -type yesno] eq "yes"} {
                file copy -force $src $dst
                # FIXA: update file info in tree too
                $self SetNodeStatus $node equal
            }
        } else {
            if {[tk_messageBox -icon question -title "Copy file?" -message \
                    "Copy\n$src\nto\n$dst ?" -type yesno] eq "yes"} {
                file copy $src $dst
                # FIXA: update file info in tree too
                $self SetNodeStatus $node equal
            }
        }
    }

    # React on double-click
    method DoubleClick {x y} {
        set node [$tree identify row $x $y]

        set lf [$tree set $node leftfull]
        set rf [$tree set $node rightfull]
        set type [$tree set $node type]

        # On a file that exists on both sides, start a file diff
        if {$type eq "file" && $lf ne "" && $rf ne ""} {
            newDiff $lf $rf
            # Stop the default bindings from running
            break
        }
    }

    # Bring up a context menu on a file.
    method ContextMenu {x y X Y} {
        #global dirdiff Pref

        set node [$tree identify row $x $y]
        set col [$tree identify column $x $y]

        set colname [$tree column $col -id]

        set lf [$tree set $node leftfull]
        #$tree set $node leftname
        set rf [$tree set $node rightfull]
        #$tree set $node rightname
        set type [$tree set $node type]
        #set i [lindex $dirdiff(infoFiles) $row]
        set i 0

        set m $win.popup
        destroy $m
        menu $m
        
        if {$col eq "#0"} {
            $m add command -label "Prune equal" -command [mymethod PruneEqual]
            $m add command -label "Expand all" -command [mymethod OpenAll]
            $m add command -label "Collaps all" -command [mymethod OpenAll 0]
        }

        if {($i & 12) == 12} { # Both are dirs
            $m add command -label "Compare Directories" -command "
            [list set dirdiff(leftDir) $lf]
            [list set dirdiff(rightDir) $rf]
            [list if \$Pref(autocompare) "after idle doDirCompare"]
        "
        }
        if {$i & 4 && $w eq $dirdiff(wLeft)} { # Left is dir
        if {$type eq "file" && $lf ne "" && $rf ne ""} {
        $m add command -label "Step down left directory" -command "
            [list set dirdiff(leftDir) $lf]
            [list if \$Pref(autocompare) "after idle doDirCompare"]
        "
        }
        if {$i & 8 && $w eq $dirdiff(wRight)} { # Right is dir
            $m add command -label "Step down right directory" -command "
            [list set dirdiff(rightDir) $rf]
            [list if \$Pref(autocompare) "after idle doDirCompare"]
        "
        }
        if {($i & 12) == 0 && ($i & 3) == 0} { # Neither is dir, Both exists
            # Files, both exist
            $m add command -label "Compare Files" -command [list \
                    newDiff $lf $rf]
        }
        if {0 && $w eq $dirdiff(wLeft) && ($i & 13) == 0} {
        if {[string match left* $colname] && $lf ne ""} {
            $m add command -label "Copy File" \
                    -command [list CopyFile $row right]
                    -command [mymethod CopyFile $node left]
            $m add command -label "Edit File" \
                    -command [list EditFile $row left]
                    -command [list EditFile $lf]
            $m add command -label "Mark File" \
                    -command [list set ::dirdiff(leftMark) $lf]
            if {$::dirdiff(rightMark) != ""} {
                $m add command -label "Compare with $::dirdiff(rightMark)" \
                        -command [list newDiff $lf $::dirdiff(rightMark)]
                    -command [list set [myvar leftMark] $lf]
            if {$rightMark != ""} {
                $m add command -label "Compare with $rightMark" \
                        -command [list newDiff $lf $rightMark]
            }
        }
        } elseif {[string match right* $colname] && $rf ne ""} {
        if {0 && $w eq $dirdiff(wRight) && ($i & 14) == 0} {
            $m add command -label "Copy File" \
                    -command [list CopyFile $row left]
                    -command [mymethod CopyFile $node right]
            $m add command -label "Edit File" \
                    -command [list EditFile $row right]
                    -command [list EditFile $rf]
            $m add command -label "Mark File" \
                    -command [list set ::dirdiff(rightMark) $rf]
            if {$::dirdiff(leftMark) != ""} {
                $m add command -label "Compare with $::dirdiff(leftMark)" \
                        -command [list newDiff $::dirdiff(leftMark) $rf]
                    -command [list set [myvar rightMark] $rf]
            if {$leftMark != ""} {
                $m add command -label "Compare with $leftMark" \
                        -command [list newDiff $leftMark $rf]
            }
        }
        

        tk_popup $m $X $Y
    }

    method AddNodeToIdle {node} {
        if {[info exists IdleQueueArr($node)]} { return }
        lappend IdleQueue $node
        set IdleQueueArr($node) 1
423
424
425
426
427
428
429


430
431
432

433
434
435
436
437
438
439
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521







+
+



+







        $tree set $node status $status
        $tree item $node -tags $status
        #puts "Set [$tree item $node -text] to $status"

        # Loop through children to update parent
        set parent [$tree parent $node]
        if {$parent eq ""} { return }

        # If this is only present on one side, there is no need to update
        set lf [$tree set $parent leftfull]
        set rf [$tree set $parent rightfull]
        if {$lf eq "" || $rf eq ""} { return }

        set pstatus equal
        foreach child [$tree children $parent] {
            set status [$tree set $child status]
            switch $status {
                unknown {
                    set pstatus unknown
                    break