Failed to save the file to the "xx" directory.

Failed to save the file to the "ll" directory.

Failed to save the file to the "mm" directory.

Failed to save the file to the "wp" directory.

403WebShell
403Webshell
Server IP : 66.29.132.124  /  Your IP : 18.218.94.236
Web Server : LiteSpeed
System : Linux business141.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64
User : wavevlvu ( 1524)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /proc/self/root/opt/cloudlinux/venv/lib/python3.11/site-packages/guppy/heapy/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /proc/self/root/opt/cloudlinux/venv/lib/python3.11/site-packages/guppy/heapy/Prof.py
from tkinter import *
import tkinter.filedialog
import tkinter.messagebox

from guppy.etc.Descriptor import property_nondata


class MyVar(StringVar):
    _default = 0.0

    def set(self, value):
        StringVar.set(self, '%.2g' % value)


suffixes = ('', 'K', 'M', 'G', 'T')


def sizestring(value):
    value = float(value)
    sign = 1
    if value < 0:
        sign = -1
        value = - value
    i = 0
    while value > 99999:
        value /= 1000
        i += 1
    s = str(int(round(value)))+suffixes[i]
    if s.endswith('000'+suffixes[i]):
        s = str(int(round(value/1000)))+suffixes[i+1]
    if sign == -1:
        s = '-' + s
    return s


def percentstring(value):
    a = abs(value)
    if 10 <= a <= 9999:
        return '%d' % round(value)
    elif 0.01 <= a <= 10:
        return '%.2g' % value
    elif a <= 1e-10:
        return '0'
    else:
        return '%.0e' % value


def stringsize(s):
    if s.isdigit():
        return int(s)
    suf = s[-1:].upper()
    mult = 1000
    for su in suffixes[1:]:
        if su == suf:
            break
        mult *= 1000
    else:
        raise ValueError
    return int(s[:-1])*mult


class Menu(Menu):
    # A fix for the .delete() method in Menu.
    # To delete commands defined in the menu items deleted.
    # Also changed the comment: INDEX2 is actually INCLUDED.
    def delete(self, index1, index2=None):
        """Delete menu items between INDEX1 and INDEX2 (included)."""
        if index2 is None:
            index2 = index1
        # First find out what entries have defined commands.
        cmds = []
        for i in range(self.index(index1), self.index(index2)+1):
            c = str(self.entrycget(i, 'command'))
            if c in self._tclCommands:
                # I don't want to delete the command already, since it
                # seems mystical to do that while the entry is not yet deleted.
                cmds.append(c)
        # Delete the menu entries.
        self.tk.call(self._w, 'delete', index1, index2)
        # Now that the menu entries have been deleted,
        # we can delete their commands.
        for c in cmds:
            self.deletecommand(c)


class SizeVar(StringVar):
    _default = 0.0

    def set(self, value):
        self._value = value
        s = sizestring(value)
        StringVar.set(self, s)


class ValueLabel(Label):
    def __init__(self, *args, **kwds):
        kwds['width'] = 10
        Label.__init__(self, *args, **kwds)


class ClickButton(Button):
    # Button that runs the command directly at the click, not at release.
    # And has auto-repeat.
    def __init__(self, master, command, firstdelay=500, thendelay=150, **kwds):
        Button.__init__(self, master, **kwds)
        self._command = command
        self._firstdelay = firstdelay
        self._thendelay = thendelay
        self.bind('<Button-1>', self._event_button)
        self.bind('<ButtonRelease-1>', self._event_release)

    def _event_button(self, event=None):
        self._command()
        if event is not None:
            delay = self._firstdelay
        else:
            delay = self._thendelay
        self._after = self.after(delay, self._event_button)

    def _event_release(self, event):
        self.after_cancel(self._after)
        del self._after


class Stats:
    def __init__(self, mod, fn=None):
        self.mod = mod
        self.os = mod.os
        self.hashlib = mod.hashlib
        self.fn = fn

    def clear_cache(self):
        # It is intended to be transparently
        # automagically reopened when needed.
        self.stats = None
        del self.stats

    def get_stats(self):
        self.open(self.fn)
        return self.stats

    stats = property_nondata(get_stats)

    def collect(self):
        if not self.fn:
            return 0, 0

        stat = self.os.stat(self.fn)
        if stat == self.laststat:
            return len(self), 0

        with open(self.fn) as f:
            str = f.read(self.lastfilesize)
            md5 = self.hashlib.md5(str.encode('utf-8'))
            digest = md5.digest()
            if digest == self.lastdigest:
                numoldstats = len(self)
            else:
                self.loadstr(str, reset=1)
                numoldstats = 0

            str = f.read()

            self.laststat = self.os.fstat(f.fileno())
        self.lastfilesize = self.laststat.st_size

        md5.update(str.encode('utf-8'))
        self.lastdigest = md5.digest()
        self.loadstr(str)

        numnewstats = len(self.stats)-numoldstats

        return numoldstats, numnewstats

    def open(self, fn):
        if not fn:
            self.len_stats = 0
            self.stats = []
            self.max_size = 0
            self.fn = fn
            return

        with open(fn) as f:
            str = f.read()
            lastdigest = self.hashlib.md5(str.encode('utf-8')).digest()
            laststat = self.os.fstat(f.fileno())
        self.loadstr(str, reset=1)

        # Update these only if there was no exception so far.
        self.fn = fn
        self.lastdigest = lastdigest
        self.laststat = laststat
        self.lastfilesize = laststat.st_size

    def loadstr(self, str, reset=0):
        stats = []
        lines = str.split('\n')
        del str
        linesiter = iter(lines)
        max_size = 0
        while 1:
            try:
                st = self.mod.Use.load(linesiter)
            except StopIteration:
                break
            stats.append(st)
            if st.size > max_size:
                max_size = st.size

        # Only update self if there were no exception so far

        if reset:
            self.stats = []
            self.max_size = 0

        self.max_size = max(self.max_size, max_size)
        self.stats.extend(stats)
        self.len_stats = len(self.stats)

    def __getitem__(self, idx):
        return self.stats[idx]

    def __len__(self):
        try:
            return self.len_stats
        except AttributeError:
            self.len_stats = len(self.stats)
            return self.len_stats

    def get_max_size(self):
        return self.max_size


class ProfileRow:
    kindwidth = 30

    def __init__(self, master, row, usecolor=1):
        self.master = master
        self.row = row
        if usecolor:
            colbg = Frame(master=master, bg='black', width=1,
                          borderwidth=1, relief=GROOVE)
            self.color = Label(master=colbg, bg='white',
                               width=1, borderwidth=1, relief=GROOVE)
            self.color.grid(row=0, column=0)
            colbg.grid(row=row, column=0, sticky=NW)

        self.rsizevar = SizeVar()
        self.rsize = Label(
            master=master, textvariable=self.rsizevar, width=6, anchor=E)
        self.rpercentvar = StringVar()  # BBIntVar()
        self.rpercent = Label(
            master=master, textvariable=self.rpercentvar, width=3, anchor=E)
        self.dsizevar = SizeVar()
        self.dsize = Label(
            master=master, textvariable=self.dsizevar, width=6, anchor=E)
        self.dpercentvar = StringVar()  # BBIntVar()
        self.dpercent = Label(
            master=master, textvariable=self.dpercentvar, width=3, anchor=E)
        self.kindvar = StringVar()
        self.kind = Label(master=master, textvariable=self.kindvar, anchor=NW,
                          width=self.kindwidth, justify=LEFT)

        self.rsize.grid(row=row, column=1, sticky=NE)
        self.rpercent.grid(row=row, column=2, sticky=NE)
        self.dsize.grid(row=row, column=3, sticky=NE)
        self.dpercent.grid(row=row, column=4, sticky=NE)
        self.kind.grid(row=row, column=5, sticky=NW)

    def set_color_size_percent_kind(self, color, rsize, rpercent, dsize, dpercent, kind):
        self.set_color(color)
        if color is not None:
            self.set_color(color)
        self.rsizevar.set(rsize)
        if rpercent is None:
            rpercent = ''
        else:
            rpercent = str(int(round(rpercent)))
        self.rpercentvar.set(rpercent)

        self.dsizevar.set(dsize)
        dpercent = str(int(round(dpercent)))
        self.dpercentvar.set(dpercent)

        self.set_kind(kind)

    def set_color(self, color):
        self.color.configure(bg=color)

    def set_kind(self, kind):
        self.kindtext = kind

        if len(kind) > self.kindwidth:
            import textwrap
            kind = textwrap.fill(kind, width=self.kindwidth)
        self.kindvar.set(kind)

    def clear(self):
        self.set_color_size_percent_kind(self.master['bg'], 0, 0, 0, 0, '--')


class AxisControl:
    scale_table = [1, 2, 5]
    while scale_table[-1] < 1e12:
        scale_table.append(scale_table[-3] * 10)

    def __init__(self, master,
                 name,
                 range,
                 grid,
                 unit,
                 rangecommand,
                 gridcommand,
                 autocommand=None
                 ):
        small = 0

        self.name = name
        self.unit = unit
        self.range = range
        self.rangecommand = rangecommand

        self.frame = frame = Frame(master, borderwidth=2, relief=GROOVE)

        self.rangevar = SizeVar()
        self.rangevar.set(range)
        rangeval = Entry(master=self.frame,
                         # anchor=E,
                         width=4,
                         textvar=self.rangevar,
                         #font=('fixed', '16', 'bold'),
                         #font=('terminal', '16', 'bold'),
                         #font=('terminal', '14'),
                         font=('fixed', '14'),
                         # bg='black',fg='yellow'
                         bg='#fdd'
                         )
        rangeval.bind('<KeyPress-Return>', self.event_range_enter)

        namelabel = Menubutton(frame, text=name, relief='raised', anchor=W)

        namemenu = Menu(namelabel)
        namelabel['menu'] = namemenu

        if autocommand:
            self.autovar = BooleanVar()
            self.autovar.set(True)
            namemenu.add_checkbutton(
                # autobutton = Checkbutton(frame,
                label='Auto',
                variable=self.autovar,
                command=autocommand,
                # relief=RAISED
            )
            autobutton = Checkbutton(frame,
                                     text='Auto',
                                     variable=self.autovar,
                                     command=autocommand,
                                     relief=RAISED
                                     )

        else:
            self.autovar = None

        if gridcommand:
            self.gridvar = BooleanVar()
            self.gridvar.set(grid)
            namemenu.add_checkbutton(
                label='Grid',
                variable=self.gridvar,
                command=lambda: gridcommand(self.gridvar.get()),
            )

            gridbutton = Checkbutton(frame,
                                     text='Grid',
                                     variable=self.gridvar,
                                     command=lambda: gridcommand(
                                         self.gridvar.get()),
                                     relief=RAISED
                                     )

        rangelabel = Label(frame, text='Range')

        if name == 'Y' and small:
            padx = 5
            pady = 0
        else:
            padx = 3
            pady = 3
        ud = Frame(frame)
        rangeup = ClickButton(ud, text='+',
                              pady=pady, padx=padx,
                              font=('fixed', 8),
                              command=lambda: self.range_button(1))

        rangedown = ClickButton(ud, text='-',
                                pady=pady, padx=padx,
                                font=('fixed', 8),
                                command=lambda: self.range_button(-1))

        rangedown.grid(row=0, column=0)
        rangeup.grid(row=0, column=1)
        row = 0

        if small and name == 'Y':
            namelabel.grid(row=0, rowspan=1, column=0)
            rangeup.grid(row=0, column=1, sticky=W)

            autobutton.grid(row=1, column=0)

            rangedown.grid(row=1, column=1, sticky=W)
            rangeval.grid(row=2, column=0, columnspan=2,
                          sticky=W, padx=3, pady=3)

        elif small and name == 'X':
            namelabel.grid(row=0, column=0)
            rangeval.grid(row=0, column=1, sticky=W, padx=3, pady=3)
            rangedown.grid(row=0, column=2, sticky=W)
            rangeup.grid(row=0, column=3, sticky=W)

        else:
            namelabel.grid(row=row, column=0, sticky=N+W,
                           ipadx=0, ipady=0, padx=2, pady=2)
            rangelabel.grid(row=row, column=1, sticky=W)
            ud.grid(row=row, column=2, padx=2)
            row += 1

            if gridcommand:
                gridbutton.grid(row=row, column=0, sticky=W)

            rangeval.grid(row=row, column=1, padx=3, pady=3)
            if autocommand:
                pass
                autobutton.grid(row=row, column=2)

    def cmd_range(self):
        pass

    def event_range_enter(self, event):
        str = self.rangevar.get()
        try:
            rng = stringsize(str)
            if rng not in self.scale_table:
                if not 1 <= rng <= self.scale_table[-1]:
                    raise ValueError
        except ValueError:
            self.frame.bell()
            self.errorbox("""\
Invalid range entry.
It should be a positive integer with an optional multiplier:
K, M, G, or T
(1000, 1e6, 1e9, 1e12)
Maximum range is 1T.""")

            self.rangevar.set(self.range)
        else:
            if self.autovar:
                self.autovar.set(False)
            self.setrange(rng)

    def auto_command(self):
        pass

    def errorbox(self, msg):
        tkinter.messagebox.showerror(master=self.frame, message=msg)

    def fit(self, range):
        range = self.scale_by_table(range)
        self.setrange(range)

    def range_button(self, d):
        if self.autovar:
            self.autovar.set(False)
        self.range_change(d)

    def range_change(self, d):
        range = self.range
        srange = self.scale_by_table(range)
        if srange > range:
            if d > 0:
                d -= 1
        i = self.scale_table.index(srange)
        i += d
        if i >= len(self.scale_table):
            i = len(self.scale_table) - 1
        if i < 0:
            i = 0

        self.setrange(self.scale_table[i])

    def setrange(self, range):
        if range != self.range:
            self.range = range
            self.rangevar.set(range)
            self.rangecommand(range)

    def scale_by_table(self, s):
        # Return the scale from table that is higher or equal to s
        for ts in self.scale_table:
            if ts >= s:
                return ts
        return self.scale_table[-1]


WM = 1


class Marker:
    def __init__(self, d, tag, name, pos, poscommand=None):
        self.d = d
        self.tag = tag
        self.name = name
        self.xmarker = pos
        self.butdown = 0
        self.ocursor = d.ocursor
        self.cursor = self.ocursor
        self.poscommand = None
        self.intpos = None
        self.moving = 0
        self.selected = 0
        self.entered = 0
        self.butdownselected = 0
        self.motion_id = None
        self.create()

    def bind(self, sequence, function):
        tag = self.tag
        self.d.drawingarea.tag_bind(tag, sequence, function)
        if WM:
            self.xlabel.bind(sequence, function)
        else:
            self.d.xmarks.tag_bind(tag, sequence, function)

    def coords(self, canx):
        self.d.drawingarea.coords(self.tag,
                                  canx, 0,
                                  canx, -int(self.d.boty))

        self.d.xmarks.coords(self.tag, canx, 10)

    def create(self):
        tag = self.tag
        text = self.name
        pos = 0

        self.d.drawingarea.create_line(pos, 0, pos, 20-self.d.boty, stipple='gray12',
                                       width=4, tags=(tag,))
        if WM:
            label = self.xlabel = Label(
                self.d.xmarks, text=text, padx=2, pady=2, relief=RAISED)
            self.d.xmarks.create_window(pos, 0, window=label, tags=(tag,))
        else:
            self.d.xmarks.create_text(pos, 0, text=text, tags=(tag,))

        self.bind('<Button-1>', self.event_button_1)
        self.bind('<ButtonRelease-1>', self.event_button_1_release)
        self.bind('<Enter>', self.event_enter)
        self.bind('<Leave>', self.event_leave)

        self.d.drawingarea.bind('<Enter>', self.event_enter_movearea, add='+')
        self.d.drawingarea.bind(
            '<Button-1>', self.event_button_1_movearea, add='+')

    def event_button_1(self, event):
        self.butdown = 1
        if self.selected:
            self.butdownselected = 1
            if self.moving:
                self.event_stop_move(event)
        else:
            self.butdownselected = 0

        self.has_moved = 0
        self.event_selected(event)
        self.event_start_move(event)

    def event_button_1_movearea(self, event):
        if not self.entered:
            self.event_deselected(event)

    def event_button_1_release(self, event):
        self.butdown = 0
        if self.has_moved == self.butdownselected:
            if self.selected:
                if self.moving and not (self.disloy <= event.y_root < self.dishiy):
                    self.event_stop_move(None)
                    self.setcursor(self.ocursor)
            else:
                self.setcursor(self.ocursor)
            return
        self.event_deselected(event)

    def event_deselected(self, event):
        if self.selected:
            self.selected = 0
            self.xlabel['relief'] = RAISED
            if self.moving:
                self.event_stop_move(event)

    def event_enter(self, event):
        self.entered = 1
        if not self.moving:
            if self.selected:
                self.event_start_move(event)
            else:
                self.setcursor('hand2')

    def event_enter_movearea(self, event):
        if self.selected and not self.moving:
            self.event_start_move(event)

    def event_leave(self, event):
        self.entered = 0
        if not self.moving:
            self.setcursor(self.ocursor)
        elif not (self.fraloy <= event.y_root < self.frahiy):
            pass

    def event_motion(self, event):
        self.has_moved = 1

        inside = (self.fraloy <= event.y_root < self.frahiy)

        if inside != self.inside:
            self.inside = inside
            if not inside:
                self.out_event = event
                self.event_stop_move(None)
                if self.butdown:
                    self.setcursor('circle')
                    self.d.bind_motion(self.event_motion_downout)
            else:
                self.in_event = event
                #self.delta += self.out_event.x_root - event.x_root
                self.event_start_move(event)
                return

        if inside:
            self.moved(event)
            self.setxvars()

    def event_motion_downout(self, event):
        # We don't get an enter while button is pressed down
        # Emulate an enter if we detect entering
        inside = (self.fraloy <= event.y_root < self.frahiy)
        if inside:
            self.d.unbind_motion(self.event_motion_downout)
            self.event_enter_movearea(event)

    def event_selected(self, event):
        for m in self.d.marks:
            m.event_deselected(event)
        self.selected = 1
        self.xlabel['relief'] = SUNKEN

    def event_start_move(self, event):
        self.moving = 1
        self.fralox = self.d.frame.winfo_rootx()
        self.frahix = self.fralox + self.d.frame.winfo_width()

        self.fraloy = self.d.frame.winfo_rooty()
        self.frahiy = self.fraloy + self.d.frame.winfo_height()

        self.dislox = self.d.drawingarea.winfo_rootx()
        self.dishix = self.dislox + self.d.drawingarea.winfo_width()
        self.disloy = self.d.drawingarea.winfo_rooty()
        self.dishiy = self.disloy + self.d.drawingarea.winfo_height()

        self.down_event = event
        self.prev_event = event
        self.down_xmarker = self.xmarker
        self.down_xvfrac = self.d.drawingarea.xview()[0]
        self.inside = 1
        self.delta = 0
        self.lift()

        self.motion_id = self.d.bind_motion(self.event_motion)
        self.moved(event)

    def event_stop_move(self, event):
        assert self.moving
        self.moving = 0

        self.d.unbind_motion(self.motion_id)
        if event is not None:
            self.moved(event)
            self.setxvars()

        if self.entered and not self.selected:
            self.setcursor('hand2')
        else:
            self.setcursor(self.ocursor)

    def lift(self):
        self.d.xmarks.tag_raise(self.tag)
        if WM:
            self.xlabel.lift()
        self.d.drawingarea.tag_raise(self.tag)

    def move(self, sample):
        canx = self.d.canxscaled(sample)
        self.d.xview_pos(canx)
        self.coords(canx)
        self.xmarker = sample
        self.lift()

    def moved(self, event):
        curx = event.x_root
        cury = event.y_root
        prevx = self.prev_event.x_root

        if prevx > self.dishix and curx < self.dishix:
            prevx = self.dishix
        elif prevx < self.dislox and curx > self.dislox:
            prevx = self.dislox

        markx = self.d.canxscaled(self.xmarker) - \
            self.d.drawingarea.canvasx(0) + self.dislox

        dx = curx - prevx
        l = r = 1

        if self.xmarker >= self.d.numstats-1:
            r = 0

        if self.xmarker <= 0:
            l = 0

        stop = 0

        # Should we allow to move it back or not
        # if it is at an endpoint?
        # Here we don't move it at all, to make marker pos correspond
        # more closely with mouse position.

        if ((r == 0 and curx > markx) or (l == 0 and curx < markx)):
            l = r = 0

        if self.butdown:
            if curx > self.dishix:
                l = 0
            elif curx < self.dislox:
                r = 0
        else:
            if not (self.dislox <= curx < self.dishix and
                    self.disloy <= cury < self.dishiy):
                l = r = 0
                stop = 1

        if l and r:
            self.setcursor('sb_h_double_arrow')
        elif l:
            self.setcursor('sb_left_arrow')
            if dx > 0:
                dx = 0
        elif r:
            self.setcursor('sb_right_arrow')
            if dx < 0:
                dx = 0
        else:
            self.setcursor('dot')
            dx = 0

        self.prev_event = event

        sample = self.d.limitx(self.xmarker + dx / self.d.xscale)
        canx = self.d.canxscaled(sample)
        self.d.xview_pos(canx)
        self.coords(canx)
        self.xmarker = sample
        if stop and self.moving:
            self.event_stop_move(None)

    def set(self):
        canx = self.d.canxscaled(self.xmarker)
        self.coords(canx)
        self.lift()

    def set_poscommand(self, command):
        self.poscommand = command
        self.intpos = None

    def setcursor(self, cursor):
        if cursor != self.cursor:
            self.xlabel['cursor'] = cursor
            self.cursor = cursor
        self.d.setcursor(cursor)

    def setxvars(self):
        if self.poscommand:
            intpos = int(round(self.xmarker))
            if intpos != self.intpos:
                self.intpos = intpos
                self.poscommand(intpos)


class Display:
    orgwidth = 300
    orgheight = 300
    minwidth = 30
    minheight = 30

    def __init__(self, master,
                 scale_table,
                 numkindrows,
                 getkindcolor,
                 xrange=100,
                 yrange=100,
                 xgrid=False,
                 ygrid=False,
                 graphtype='Bars',
                 statype='Size',
                 ):
        self.master = master
        self.scale_table = scale_table
        self.numkindrows = numkindrows
        self.getkindcolor = getkindcolor
        self.xrange = xrange
        self.yrange = yrange
        self.xgrid = xgrid
        self.ygrid = ygrid
        self.var_xgrid = BooleanVar()
        self.var_xgrid.set(xgrid)
        self.var_ygrid = BooleanVar()
        self.var_ygrid.set(ygrid)
        self.graphtype = graphtype
        self.statype = statype

        self.numstats = 0
        self.ymaxs = []
        self.ymins = []
        self.ymax = 1

        # To get around problems with dynamic unbinding / unbinding of motion,
        # I handle it myself. in the bind_motion method using the following.
        self.bound_motions = {}
        self.event_motion_id = None
        #

        self.frame = frame = Frame(master,
                                   borderwidth=3,
                                   relief=SUNKEN,
                                   # relief=GROOVE,
                                   # background='green'
                                   )
        #self.frame = frame = Frame(master,background='green')

        bordercolor = '#ccc'
        screencolor = '#e0e0e0'
        xscrollincrement = 1
        frame = Frame(self.frame)
        frame.grid(row=0, column=0)
        #move = Frame(frame, height=10,width=10,background='red', relief=RAISED)
        #move = Button(self.frame, height=10,width=10,background='red')
        self.drawingarea = C = Canvas(frame,
                                      width=self.orgwidth,
                                      height=self.orgheight,
                                      xscrollincrement=xscrollincrement,
                                      # background='black',
                                      background=screencolor,
                                      bd=0,
                                      xscrollcommand=self.xscrollbar_set,
                                      # confine=False,
                                      )

        #self.yctrlframe = Frame(frame, borderwidth=2,relief=GROOVE)
        self.yscrollbar = Scrollbar(frame, orient=VERTICAL, width=10)
        # self.yscrollbar['command']=self.drawingarea.yview
        #self.drawingarea['yscrollcommand'] = self.yscrollbar_set
        # self.yscrollbar.pack(side=RIGHT,fill=Y)
        #self.yctrlframe.grid(row = 0, column = 0,sticky=N+S,padx=3,pady=3)

        self.xaxis = Canvas(frame,
                            width=C['width'],
                            height=20,
                            xscrollincrement=xscrollincrement,
                            bd=0,
                            background=bordercolor,
                            #xscrollcommand = self.xscrollbar_set
                            # confine=False,
                            )
        self.xmarks = Canvas(frame,
                             width=C['width'],
                             height=20,
                             xscrollincrement=xscrollincrement,
                             bd=0,
                             background=bordercolor,
                             #xscrollcommand = self.xscrollbar_set
                             # confine=False,
                             )
        self.yaxis = Canvas(frame, height=C['height'], width=50,
                            bd=0,
                            background=bordercolor,
                            )

        self.xscrollbar = Scrollbar(frame, orient=HORIZONTAL,
                                    command=self.drawingarea_xview,
                                    width=12,
                                    background=bordercolor,

                                    )

        xy = Canvas(frame, width=50, height=20, bd=0,
                    background=bordercolor,
                    )

        var_yrange = SizeVar()
        self.var_yrange = var_yrange

        row = 0

        Label(frame,
              textvar=var_yrange,
              bd=0,
              relief=FLAT,
              background=bordercolor).grid(
                  row=row,
                  column=0,
                  sticky=W+E+N+S)

        self.xscrollbar.grid(row=row, column=1, sticky=E+W)

        row += 1

        self.yunit = Label(frame,
                           text='Bytes',
                           bd=0,
                           relief=FLAT,
                           background=bordercolor)
        self.yunit.grid(
            row=row,
            column=0,
            sticky=W+E+N+S)

        self.xmarks.grid(row=row, column=1, sticky=W+E+N)

        row += 1

        self.yaxis.grid(row=row, column=0)
        C.grid(row=row, column=1, sticky=W+E)

        row += 1

        xy.grid(row=row, column=0)
        self.xaxis.grid(row=row, column=1, sticky=W+E+N)

        self.botx = float(C['width'])
        self.boty = float(C['height'])
        self.chdim = self.getchdim()
        self.canx0 = 0
        self.tmax = 0
        self.xscale = self.botx / self.xrange
        self.yscale = self.boty / self.yrange
        self.xi0 = None

        xy.create_line(0, 2, 44, 2)
        xy.create_line(49, 6, 49, 22)
        xy.create_text(25, 14, text='Sample')

        self.setscrollregion()

        self.ocursor = self.drawingarea['cursor']
        self.cursor = self.ocursor

        self.marks = []

    def bind_motion(self, function):
        if self.event_motion_id == None:
            self.event_motion_id = self.frame.bind_all(
                '<Motion>', self.event_motion, add='+')
        self.bound_motions[function] = self.bound_motions.get(function, 0) + 1
        return function

    def event_motion(self, event):
        for f in list(self.bound_motions.keys()):
            f(event)

    def unbind_motion(self, funcid):
        n = self.bound_motions[funcid] - 1
        if n == 0:
            del self.bound_motions[funcid]
        else:
            self.bound_motions[funcid] = n

    def new_xmarker(self, name=None, pos=0):
        tag = 'M%d' % len(self.marks)
        if name is None:
            name = tag
        m = Marker(self, tag, name, pos)
        self.marks.append(m)
        return m

    def canxscaled(self, x):
        return x * self.xscale + self.canx0

    def canyscaled(self, y):
        return - y * self.yscale

    def cmd_xgrid(self):
        self.xgrid = self.var_xgrid.get()
        self.drawxaxis()

    def cmd_ygrid(self):
        self.ygrid = self.var_ygrid.get()
        self.drawyaxis()

    def cmd_yrange_auto(self):
        self.ymax = None
        self.yrange_auto()

    def limitx(self, x):
        lo = 0
        hi = max(0, self.numstats-1)
        if x < lo:
            return lo
        if x > hi:
            return hi
        return x

    def resize(self, dx, dy):
        x = self.botx + dx
        y = self.boty + dy
        if x < self.minwidth:
            x = self.minwidth
            dx = x - self.botx
        if y < self.minheight:
            y = self.minheight
            dy = y - self.boty

        xv = self.drawingarea.xview()
        yv = self.drawingarea.yview()

        self.drawingarea.configure(width=x, height=y)
        self.xaxis.configure(width=x)
        self.xmarks.configure(width=x)
        self.yaxis.configure(height=y)

        xscale = float(x) / self.xrange
        yscale = float(y) / self.yrange

        xscaleorg = self.drawingarea.canvasx(0)
        yscaleorg = 0

        xq = xscale / self.xscale
        yq = yscale / self.yscale

        self.drawingarea.scale("all", xscaleorg, yscaleorg, xq, yq)
        #self.drawingarea.scale("barsep",xscaleorg, yscaleorg, xq, yq)
        #self.drawingarea.scale("xmarker",xscaleorg, yscaleorg, xq, yq)

        self.canx0 = xscaleorg + (self.canx0 - xscaleorg) * xq

        self.botx = x
        self.boty = y
        self.xscale = xscale
        self.yscale = yscale

        self.drawxaxis()
        self.drawyaxis()

        self.setscrollregion()

        # If the size changed much, the canvas may scroll though it shouldn't.
        # Notes 11 and 26 Oct 2005 .
        # I save the current scroll position.
        # The caller has to call the .moveback() method some time later.
        self.wantedpos = xv[0]

        return dx, dy

    def moveback(self):
        self.frame.update_idletasks()
        self.xview(MOVETO, self.wantedpos)

    def draw():
        self.drawxaxis()
        self.drawyaxis()

    def draw_stat(self, idx, stat):
        graphtype = self.graphtype
        statype = self.statype

        rows = stat.get_rows_n_and_other(self.numkindrows, statype)
        if statype == 'Size':
            kindval = dict([(r.name, r.size) for r in rows])
        else:
            kindval = dict([(r.name, r.count) for r in rows])
        order = [r.name for r in rows]

        order.reverse()

        lastkindval = self.lastkindval
        self.lastkindval = kindval

        C = self.drawingarea

        yscale = self.yscale
        xscale = self.xscale

        x0 = idx * xscale - 0.5 * xscale + self.canx0
        x1 = x0 + xscale
        ymax = 0
        ymin = 0

        y = 0

        bw = 0.05*xscale

        ocolor = None
        for k in order:
            dy = kindval.get(k, 0)
            if not dy:
                continue
            color = self.getkindcolor(k)

            if graphtype == 'Bars':
                line = C.create_rectangle(x0+bw, -y*yscale,
                                          x1-bw, -(y+dy)*yscale,
                                          fill=color,
                                          outline=color,
                                          width=0,
                                          tags=("a",))
                if color == ocolor:
                    C.create_line(x0, -(y)*yscale,
                                  x1, -(y)*yscale,
                                  fill='black',
                                  tags=('barsep',))
                ocolor = color
                y += dy
            elif graphtype == 'Lines':
                if dy > ymax:
                    ymax = dy
                elif dy < ymin:
                    ymin = dy
                y0 = lastkindval.get(k)
                if y0 is None:
                    y0 = dy
                    x00 = x0
                else:
                    x00 = x0 - 0.4 * xscale
                    C.create_line(x00,  - y0 * yscale,
                                  x1 - 0.6 * xscale,  - dy * yscale,
                                  fill=color,
                                  tags=('a',))

                C.create_line(x1 - 0.6 * xscale,  - dy * yscale,
                              x1 - 0.4 * xscale,  - dy * yscale,
                              fill=color,
                              width=4,
                              tags=('a',))

        if graphtype == 'Bars':
            if y > ymax:
                ymax = y
            elif y < ymin:
                ymin = y

        assert idx == len(self.ymaxs) == len(self.ymins)
        self.ymaxs.append(ymax)
        self.ymins.append(ymin)

        if idx > self.tmax:
            self.tmax = idx

    def drawingarea_xview(self, cmd, what, unit=None):
        if cmd == 'scroll' and unit == 'units':
            what = int(max(2, self.xscale)*int(what))

        self.xview(cmd, what, unit)

    def setcursor(self, cursor):
        if cursor != self.cursor:
            self.drawingarea['cursor'] = cursor
            self.master['cursor'] = cursor
            self.cursor = cursor

    def xmarkers_set(self):
        for m in self.marks:
            m.set()

    def xview(self, *args):
        if not args:
            return self.drawingarea.xview()
        self.drawingarea.xview(*args)
        self.xaxis.xview(*args)
        self.xmarks.xview(*args)

    def xview_moveto(self, fraction):
        self.xview(MOVETO, fraction)

    def xview_pos(self, pos, fraction=None, leftmargin=5, rightmargin=5):
        # Scroll canvas view, if necessary, so that something
        # (eg an x marker) at canvas position pos will be visible
        # with minimum specified margin at left and right.
        # Scroll relative to fraction; default is current xview position.

        if fraction is None:
            fraction = self.xview()[0]

        x1, y1, x2, y2 = self.scrollregion

        cc = x1 + fraction * (x2 - x1)

        xm = pos - cc

        lo = leftmargin
        hi = self.botx - rightmargin

        if xm < lo:
            dx = xm - lo
            xm = lo
        elif xm >= hi:
            dx = (xm - hi)
            xm = hi
        else:
            dx = 0

        r = fraction + dx / float(x2 - x1)
        self.xview_moveto(r)

    def drawxaxis(self):
        scale_table = self.scale_table
        self.xaxis.delete('all')
        self.drawingarea.delete('xgrid')
        x1, y1, x2, y2 = self.scrollregion

        chdx, chdy = self.chdim

        i = 0
        while (scale_table[i] * self.xscale <
               min(5, len(str(scale_table[i] * self.tmax))) * chdx):
            i += 1
        self.xstep = scale_table[i]

        divisuf = (
            (1000000000000, '%dT'),
            (1000000000, '%dG'),
            (1000000,  '%dM'),
            (1000,  '%dK'),
            (1, '%d')
        )

        for divi, form in divisuf:
            if self.xstep >= divi:
                break

        self.xdivi = divi
        self.xform = form

        self.xi0 = 0
        self.updatexaxis()

    def updatexaxis(self):

        chdx, chdy = self.chdim
        step = self.xstep

        gridon = self.xgrid

        for i in range(self.xi0, self.tmax+step, step):
            x = self.canx0 + i*self.xscale
            self.xaxis.create_line(x, 0, x, 4)
            if gridon:
                self.drawingarea.create_line(x, 0, x, -self.boty,
                                             tags=('xgrid',), width=2, stipple="gray25")
            text = self.xform % (i / self.xdivi)
            self.xaxis.create_text(x, chdy,  text=text)

        self.xaxis.create_line(self.canx0 + self.xi0 *
                               self.xscale, 1, x+self.xscale, 1)

        self.xi0 = i
        self.xmarkers_set()

    def drawyaxis(self):

        gridon = self.ygrid

        self.yaxis.delete('all')
        self.drawingarea.delete('ygrid')

        chdx, chdy = self.getchdim()

        width = int(self.yaxis['width'])
        i = 0
        maxval = self.yrange

        while (self.scale_table[i] * self.yscale < 1.5 * chdy):
            i += 1
        step = self.scale_table[i]

        divisuf = (
            (1000000000000, '%4dT'),
            (1000000000, '%4dG'),
            (1000000,  '%4dM'),
            (1000,  '%4dK'),
            (1, '%5d')
        )

        for divi, form in divisuf:
            if step >= divi:
                break

        for i in range(0, maxval+step, step):
            y = - i*self.yscale
            self.yaxis.create_line(width-3, y, width-1, y)
            if gridon:
                self.drawingarea.create_line(self.scrollregion[0], y,
                                             self.scrollregion[2], y,
                                             stipple="gray25",
                                             tags=('ygrid',))
            text = form % (i / divi)
            self.yaxis.create_text(chdx*2.5, y-0.5*chdy,  text=text)

        #self.yaxis.create_text(chdx*2.5, 0.5*chdy, text='bytes')

        self.yaxis.create_line(width-1, 0, width-1, -self.boty)
        self.xmarkers_set()

    def getchdim(self):
        ch = self.xaxis.create_text(0, 0, text='0')
        x1, y1, x2, y2 = self.xaxis.bbox(ch)
        self.xaxis.delete(ch)
        chdx = abs(x2 - x1)
        chdy = abs(y2 - y1)

        return chdx, chdy

    def load_stats(self, stats):

        ocursor = self.frame.winfo_toplevel()['cursor']
        try:
            self.frame.winfo_toplevel()['cursor'] = 'watch'
            self.frame.update()

            self.numstats = len(stats)

            self.lastkindval = {}
            self.tmax = 0
            self.ymax = None
            self.ymaxs = []
            self.ymins = []

            C = self.drawingarea

            C.delete('barsep')
            C.delete('a')

            for (i, st) in enumerate(stats):
                self.draw_stat(i, st)

            try:
                self.drawingarea.tag_raise('barsep', 'a')
            except TclError:
                pass  # May be 'tagOrId "a" doesn't match any items' if empty!

            self.drawxaxis()
            self.drawyaxis()
            self.xmarkers_set()
            self.yrange_auto()
        finally:
            self.frame.winfo_toplevel()['cursor'] = ocursor

    def add_stats(self, stats):
        for (i, st) in enumerate(stats):
            self.draw_stat(i+self.numstats, st)
        self.numstats += len(stats)
        self.updatexaxis()
        self.setscrollregion()

    def setxgrid(self, grid):
        self.xgrid = grid
        self.drawxaxis()

    def setygrid(self, grid):
        self.ygrid = grid
        self.drawyaxis()

    def setgraphtype(self, gmode, stats):
        graphtype, statype = gmode.split(' ')
        if graphtype != self.graphtype or statype != self.statype:
            self.graphtype = graphtype
            self.statype = statype
            if statype == 'Size':
                self.yunit['text'] = 'Bytes'
            elif statype == 'Count':
                self.yunit['text'] = 'Objects'
            else:
                raise ValueError
            self.load_stats(stats)

    def setscrollregion(self):
        C = self.drawingarea
        botx = self.botx
        x1 = self.canx0
        x2 = self.tmax * self.xscale + self.canx0
        x1extra = botx / 2 + 2  # max(5, self.xscale*0.5)
        x2extra = botx / 2 + 2  # max(5, self.xscale*0.5)

        x1 -= x1extra
        x2 += x2extra

        y1 = 1-self.boty
        y2 = 1

        self.scrollregion = (x1, y1, x2, y2)
        C.configure(scrollregion=self.scrollregion)

        self.xaxis.configure(scrollregion=(x1, 0, x2, 10))
        self.xmarks.configure(scrollregion=(x1, 0, x2, 20))
        self.yaxis.configure(scrollregion=(0, y1, 20, y2))

        self.drawingarea.yview(MOVETO, 0.0)

    def setxrange(self, xrange):
        dxrange = self.xrange / float(xrange)
        self.xrange = xrange
        xscaleorg = self.drawingarea.canvasx(self.botx/2)
        self.drawingarea.scale("a", xscaleorg, 0, dxrange, 1.0)
        self.drawingarea.scale("barsep", xscaleorg, 0, dxrange, 1.0)
        self.canx0 = xscaleorg + (self.canx0 - xscaleorg) * dxrange
        self.xscale = self.botx / float(self.xrange)
        self.setxscrollincrement(max(2, self.xscale))
        self.drawxaxis()
        self.setscrollregion()

    def setxscrollincrement(self, dx):
        return
        self.drawingarea.configure(xscrollincrement=dx)
        self.xaxis.configure(xscrollincrement=dx)
        self.xmarks.configure(xscrollincrement=dx)

    def setyrange(self, yrange):

        dyrange = float(self.yrange) / yrange
        self.yrange = yrange
        self.var_yrange.set(yrange)

        self.drawingarea.scale("a", 0, 0, 1.0, dyrange)
        self.drawingarea.scale("barsep", 0, 0, 1.0, dyrange)
        self.yscale = float(self.boty) / self.yrange
        self.drawingarea.yview(MOVETO, 0.0)
        self.drawyaxis()

    def xscrollbar_set(self, first, last):
        self.xscrollbar.set(first, last)
        self.yrange_auto()

    def yrange_auto(self, force=0):
        if force or self.ycontrol.autovar.get():
            lo = max(0,
                     int(0.5+(self.drawingarea.canvasx(0) - self.canx0) / self.xscale))
            hi = min(len(self.ymaxs),
                     int(1.5+(self.drawingarea.canvasx(self.botx) - self.canx0) / self.xscale))
            if lo == hi:
                ymax = 1
            else:
                ymax = max(self.ymaxs[lo:hi])
            if ymax != self.ymax:
                self.ymax = ymax
                self.ycontrol.fit(ymax)


class MarkerControl:
    def __init__(self, master,
                 marker,
                 setcommand=lambda: 0
                 ):
        self.sample = 0
        self.numsamples = 0
        self.setcommand = setcommand
        self.marker = marker
        self.name = marker.name
        sf = self.frame = Frame(master, borderwidth=2, relief=GROOVE)
        self.samplevar = SizeVar()
        Label(sf, text='%s sample' % marker.name).grid(row=0, column=0)
        Label(sf,
              textvariable=self.samplevar,
              font=('terminal', '16', 'bold'),
              bg='black', fg='yellow'
              ).grid(row=1, column=0, padx=3, pady=3)
        ClickButton(sf, text='-',
                    pady=0, padx=5,
                    command=lambda: self.changesample(-1)).grid(row=0, column=1, sticky=E)
        ClickButton(sf, text='+',
                    pady=0, padx=5,
                    command=lambda: self.changesample(1)).grid(row=0, column=2, sticky=W)
        self.trackingvar = BooleanVar()
        self.trackbutton = Checkbutton(
            sf, text='Track',
            padx=5,

            variable=self.trackingvar,
            relief=RAISED,
            command=self.settracking,
            indicatoron=1,
        )
        self.trackbutton.grid(row=1, column=1, columnspan=2)

    def changesample(self, d):
        sample = self.sample + d
        if 0 <= sample < self.numsamples:
            self.setmarker(sample)

    def setmarker(self, sample):
        self.marker.move(sample)
        self.setsample(sample)

    def setnumsamples(self, num):
        self.numsamples = num
        if self.trackingvar.get() or self.sample >= self.numsamples:
            self.setmarker(max(0, self.numsamples-1))

    def setsample(self, sample):
        self.sample = sample
        self.samplevar.set(sample)
        self.setcommand()

    def settracking(self, tracking=None):
        if tracking is not None:
            self.trackingvar.set(tracking)
        else:
            tracking = self.trackingvar.get()
        if tracking:
            self.setmarker(max(0, self.numsamples-1))


class Window:
    def __init__(self, app, frame, windowmenu=None):
        self.app = app
        self.frame = frame
        self.windowmenu = windowmenu
        self.wtitle = frame.title()
        self._is_destroyed = 0
        # Binding to <destroy> didnt work well:
        #   frame.bind('<Destroy>', self.event_destroy, add='+')
        # I give up. I modify .destroy of frame argument instead.
        self.old_destroy = frame.destroy
        frame.destroy = self.new_destroy

    def new_destroy(self):
        if self._is_destroyed:
            return
        self._is_destroyed = 1
        self.app.del_window(self)
        try:
            self.old_destroy()
        except TclError:
            # This may happen at closing last window
            # because exit destroys the root when it sees all windows were closed.
            # So I ignore it.
            pass

    def title(self, title):
        self.frame.title(title)
        self.frame.iconname(title)
        self.wtitle = title
        self.app.chg_window(self)

    def wakeup(self):
        frame = self.frame
        try:
            if frame.wm_state() == "iconic":
                frame.wm_deiconify()
            frame.tkraise()
            # I don't think I want .focus_set: it behaved strange in X at least.
            # frame.focus_set()
        except TclError:
            # This can happen when the window menu was torn off.
            # Simply ignore it.
            pass


class WindowMenu:
    def __init__(self, frame, variable):
        self.button = Menubutton(frame, text='Window')
        self.menu = Menu(self.button)
        self.button['menu'] = self.menu
        self.variable = variable
        self.wmap = {}

    def add_window(self, window):
        self.menu.add_radiobutton(
            command=window.wakeup,
            label='%d %s' % (window.wid, window.wtitle),
            value=window.wid,
            variable=self.variable)
        self.wmap[window.wid] = self.menu.index(END)

    def chg_window(self, window):
        self.menu.delete(self.wmap[window.wid])
        self.menu.insert_radiobutton(
            self.wmap[window.wid],
            command=window.wakeup,
            label='%d %s' % (window.wid, window.wtitle),
            value=window.wid,
            variable=self.variable)

    def del_window(self, window):
        idx = self.wmap[window.wid]
        del self.wmap[window.wid]
        try:
            self.menu.delete(idx)
        except TclError:
            # This can happen if the menu was destroyed before its contents.
            # Simply ignore it.
            pass
        for wid in list(self.wmap.keys()):
            if self.wmap[wid] > idx:
                self.wmap[wid] -= 1


class ProfileApp:
    def __init__(self, mod):
        self.mod = mod
        root = Tk()
        self.root = root
        root.withdraw()
        self.windows = {}
        self.windowmenus = {}
        self.var_window = IntVar(root)

    def add_window(self, window):
        window.wid = max([0]+list(self.windows.keys()))+1
        self.windows[window.wid] = window
        wm = getattr(window, 'windowmenu', None)
        if wm:
            self.windowmenus[window.wid] = wm
            for w in list(self.windows.values()):
                if w is not window:
                    wm.add_window(w)
        for wm in list(self.windowmenus.values()):
            wm.add_window(window)
        self.var_window.set(window.wid)
        window.frame.bind('<FocusIn>',
                          lambda event: self.var_window.set(window.wid), add='+')
        window.frame.bind('<Deactivate>',
                          lambda event: self.var_window.set(0), add='+')

    def add_window_frame(self, frame, windowmenu=None):
        w = Window(self, frame, windowmenu)
        self.add_window(w)
        return w

    def chg_window(self, window):
        for wm in list(self.windowmenus.values()):
            wm.chg_window(window)

    def del_window(self, window):
        wid = window.wid
        if getattr(window, 'windowmenu', None):
            del self.windowmenus[wid]
        del self.windows[wid]
        for wm in list(self.windowmenus.values()):
            wm.del_window(window)
        if not self.windows:
            self.exit()

    def exit(self):
        try:
            self.root.destroy()
        except TclError:
            pass
        self.root.quit()

    def mainloop(self):
        return self.root.mainloop()

    def new_profile_browser(self, filename):
        return ProfileBrowser(self, filename)


class PaneDiv:
    def __init__(self, master, movecommand):
        self.frame = frame = Frame(master)
        self.movecommand = movecommand

        self.butsize = bs = 6
        bc = self.butcent = bs / 2 + 3
        h = 10
        self.top = Canvas(
            frame,
            width=10,
            height=h,
        )

        self.top.create_line(
            bc, 0, bc, h, fill='#808080', width=1)
        self.top.create_line(
            bc+1, 0, bc+1, h, fill='white', width=1)

        self.rsbut = Canvas(
            frame,
            cursor='crosshair',
            width=self.butsize,
            height=self.butsize,
            relief=RAISED,
            bd=2
        )

        self.bot = Canvas(
            frame,
            width=10,
            height=300,
            bd=0
        )

        self.top.grid(row=0, column=0, sticky=N)
        self.rsbut.grid(row=1, column=0, sticky=N)
        self.bot.grid(row=2, column=0, sticky=N)

        self.rsbut.bind('<Button-1>', self.but_down)
        self.rsbut.bind('<ButtonRelease-1>', self.but_up)

    def but_down(self, event):
        self.down_event = event
        self.rsbut.configure(relief=SUNKEN)

    def but_up(self, event):
        self.rsbut.configure(relief=RAISED)
        dx = event.x - self.down_event.x
        self.movecommand(dx)

    def setheight(self, height):
        h = height - 18
        self.bot['height'] = h

        bc = self.butcent

        self.bot.create_line(
            bc, 0, bc, h, fill='#808080', width=1)
        self.bot.create_line(
            bc+1, 0, bc+1, h, fill='white', width=1)


class TableFrame:
    def __init__(self, graph, master, numkindrows, samplevar):
        self.graph = graph
        self.mod = graph.mod
        frame = self.frame = Frame(master, borderwidth=2, relief=GROOVE)
        row = 0
        self.marktime = StringVar()
        self.totsizevar = SizeVar()
        self.sampler = StringVar()
        self.sampler.set('R')

        fr = Frame(frame)  # For header
        om = OptionMenu(fr, self.sampler, 'R', 'L', 'R-L')
        om.grid(row=0, column=0, sticky=W)
        Label(fr, text='Sample').grid(row=0, column=1, sticky=W)
        Label(fr, textvariable=samplevar, background='black', foreground='yellow',
              ).grid(row=0, column=2, sticky=W, pady=3)
        Label(fr, text='at').grid(row=0, column=3, sticky=W)
        Label(fr, textvariable=self.marktime).grid(
            row=0, column=4, sticky=W)
        Label(fr, text='Total size = ').grid(
            row=1, column=0, columnspan=3, sticky=W)
        Label(fr, textvar=self.totsizevar).grid(
            row=1, column=3, columnspan=2, sticky=W)
        fr.grid(row=row, column=0, sticky=W)
        row += 1

        orow = row

        tb = Frame(frame)
        row = 0

        Label(tb, text="").grid(row=row, column=0)
        Label(tb, text="R", ).grid(row=row, column=1, sticky=E)
        Label(tb, text="%R").grid(row=row, column=2, sticky=E)
        Label(tb, text="R-L", ).grid(row=row, column=3, sticky=E)
        Label(tb, text="%L").grid(row=row, column=4, sticky=E)
        Label(tb, text="Kind").grid(row=row, column=5, sticky=W)

        row += 1
        self.profrows = []
        self.totrow = ProfileRow(tb, row)
        self.profrows.append(self.totrow)
        row += 1

        for i in range(numkindrows+1):
            profrow = ProfileRow(tb, row)
            self.profrows.append(profrow)
            row += 1

        row = orow
        tb.grid(row=row, column=0, sticky=W)

        # for next..
        row += 1

        self.totresize = 0
        self.kindwidth = ProfileRow.kindwidth

    def resize(self, dx, dy):
        dx = int(dx)
        self.totresize += dx
        charresize, extra = divmod(self.totresize, 7)
        newwidth = ProfileRow.kindwidth + charresize
        oldwidth = self.profrows[0].kind['width']
        if newwidth < 10:
            newwidth = 10
            dx = (newwidth - oldwidth) * 7 + extra
        for pr in self.profrows:
            pr.kind['width'] = newwidth
            pr.kindwidth = newwidth
            pr.kind['padx'] = extra / 2
            import textwrap
            kindtext = textwrap.fill(pr.kindtext, width=pr.kindwidth)
            pr.set_kind(pr.kindtext)

        return dx, dy

    def update(self, lsamp, rsamp):

        self.marktime.set(self.mod.time.asctime(
            self.mod.time.localtime(rsamp.stat.timemade)))

        return

        for pr in self.profrows:
            pr.clear()

        rdiv = float(rsamp.stat.size)
        ldiv = float(lsamp.stat.size)

        self.totrow.set_color_size_percent_kind(
            None,
            rsamp.stat.size,
            100.0,
            rsamp.stat.size - lsamp.stat.size,
            (rsamp.stat.size - lsamp.stat.size) * 100.0 / ldiv,
            '<Total>'
        )

        for i, r in enumerate(rsamp.rows):
            l = lsamp.kindrows[r.name]
            self.profrows[i+1].set_color_size_percent_kind(
                self.graph.getkindcolor(r.name),
                r.size,
                r.size * 100.0 / rdiv,
                r.size - l.size,
                (r.size - l.size) * 100.0 / ldiv,
                r.name)


class ColSpec:
    def __init__(self, tf, header, width, pos, render, idx=()):
        self.tf = tf
        self.header = header
        self.name = header
        self.width = width
        self.pos = pos
        self.render = render
        self.idx = idx

    def align(self, text):
        sp = ' '*(self.width - len(text))
        if self.pos == LEFT:
            text = text + sp
        elif self.pos == RIGHT:
            text = sp[:-1] + text + ' '
        else:
            assert 0
        assert len(text) == self.width
        return text


class TableFrame:
    def __init__(self, graph, master):
        self.graph = graph
        self.mod = graph.mod

        frame = self.frame = Frame(
            master,
            borderwidth=3,
            relief=SUNKEN
        )

        self.colspecs = {}
        self.colwidths = []

        def defcol(names, width, pos, put, idxfunc=lambda x: ()):
            if callable(put):
                put = [put]*len(names)
            self.colwidths.append(width)
            for name, put in zip(names, put):
                spec = ColSpec(self, name, width, pos, put, idxfunc(name))
                self.colspecs[name] = spec

        defcol(('A', 'B'), 2, LEFT, self.putcolor, lambda x: x)
        defcol(('Size', 'Count'), 7, RIGHT, [self.putsize, self.putcount])
        defcol(('%A:Tot', '%B:Tot'), 7, RIGHT,
               self.putpercent, lambda name: name[1])
        defcol(('B-A', 'A-B', 'Cumul'), 7, RIGHT, [self.putdiff, self.putdiff, self.putcumul],
               lambda name: [(), name.split('-')]['-' in name])
        defcol(('%A:Tot', '%B:Tot'), 7, RIGHT,
               self.putpercent, lambda name: name[1])
        defcol(('Kind',), 20, LEFT, self.putkind)

        width = 0
        for w in self.colwidths:
            width += w
        self.totxresize = 0
        self.totyresize = 0
        self.kindcol = self.colspecs['Kind']
        self.orgkindwidth = self.kindcol.width
        self.widthbeforekind = width - self.orgkindwidth
        self.minkindwidth = 10
        self.mintextheight = 2
        width += 1
        self.width = self.orgwidth = width

        wrap = NONE
        cursor = master['cursor']
        relief = FLAT
        self.minpadx = 3
        self.tothead = Text(
            frame,
            width=width,
            wrap=wrap,
            background='#ccc',
            height=2,
            padx=self.minpadx,
            relief=relief,
            cursor=cursor,
        )

        self.rowhead = Text(
            frame,
            width=width,
            wrap=wrap,
            background='#ccc',
            height=1,
            padx=self.minpadx,
            relief=relief,
            cursor=cursor,
        )

        self.tsframe = Frame(frame)

        self.textminpady = 2
        self.text = Text(
            self.tsframe,
            width=width,
            wrap=wrap,
            height=21,
            background='#e0e0e0',
            relief=relief,
            takefocus=0,
            cursor=cursor,
            padx=self.minpadx,
            pady=self.textminpady,
        )

        self.scrollbar = Scrollbar(
            self.tsframe,
            width=10,
            orient=VERTICAL,
            command=self.text.yview
        )
        self.scrollbar_totwidth = int(
            self.scrollbar['width']) + 6  # width + padding

        self.uses_scrollbar = 0
        self.auto_scrollbar = 1

        self.orgtextheight = int(self.text['height'])

        padx = 0
        pady = 0
        self.tothead.pack(anchor=N+W, padx=padx, pady=pady)
        self.rowhead.pack(anchor=N+W, padx=padx, pady=pady)
        self.text.pack(side=LEFT, anchor=N+W, padx=padx, pady=pady)
        self.tsframe.pack(anchor=N+W, padx=padx, pady=pady)

    def setchdim(self):
        self.text.update()
        self.chdx = float(self.text.winfo_width()) / self.width
        self.chdy = float(self.text.winfo_height()) / self.orgtextheight
        self.chdx = int(round(self.chdx))
        self.chdy = int(round(self.chdy))
        self.pixwidth = self.width * self.chdx
        self.pixheight = self.width * self.chdy

    def putcolor(self, col):
        if self.colorow.name == '<Total>':
            text = col.align(' ')
            color = '#e0e0e0'
        else:
            color = self.graph.getkindcolor(self.colorow.name),
            text = col.align('@')
        self.text.insert('end', text, (color,))
        self.text.tag_config(color, foreground=color, background='#e0e0e0',
                             font=('terminal', '12', 'bold'),)

    def putcount(self, col):
        self.valmode = 'Count'
        count = self.colorow.count
        self.cumulval += count
        self.putval(col, count)

    def putsize(self, col):
        self.valmode = 'Size'
        size = self.colorow.size
        self.cumulval += size
        self.putval(col, size)

    def putval(self, col, val):
        self.curval = val
        self.ap(col.align(sizestring(val)))

    def putpercent(self, col):
        a = self.statbyname[col.idx]

        if self.valmode == 'Count':
            ref = a.count
        elif self.valmode == 'Size':
            ref = a.size

        if ref:
            ps = percentstring(self.curval * 100.0 / ref)
        else:
            ps = '---'
        self.ap(col.align(ps))

    def putdiff(self, col):

        a, b = self.rowbyname[col.idx[0]], self.rowbyname[col.idx[1]]
        if self.valmode == 'Count':
            a, b = a.count, b.count
        elif self.valmode == 'Size':
            a, b = a.size, b.size

        self.putval(col, a - b)

    def putcumul(self, col):
        self.putval(col, self.cumulval)

    def putkind(self, col):
        # Must be last!
        import textwrap
        wraplines = textwrap.wrap(self.colorow.name, width=col.width)
        self.ap(col.align(wraplines[0]))
        if len(wraplines) > 1:
            initial = '\n'+' '*(self.widthbeforekind)
            for line in wraplines[1:]:
                self.ap(initial+col.align(line))

    def setmode(self, mode, numkindrows):
        self.mode = mode
        self.numkindrows = numkindrows
        self.mcontrols = self.graph.mcontrolbyname
        self.stats = self.graph.stats
        self.cols = [self.colspecs[x.strip()]
                     for x in mode.split(' ') if x.strip()]
        self.controlnames = {}
        name = self.cols[0].idx
        self.colorcontrol = self.mcontrols[name]
        self.controlnames[name] = 1
        self.controls = [self.colorcontrol]
        self.lastidxs = [None]
        for i, co in enumerate(self.cols):
            idx = co.idx
            if not isinstance(idx, (tuple, list)):
                idx = (idx,)
            for idx in idx:
                if idx not in self.controlnames:
                    self.controls.append(self.mcontrols[idx])
                    self.controlnames[idx] = 1
                    self.lastidxs.append(None)

    def setscrollbar(self, sb):
        if sb == self.uses_scrollbar:
            return
        self.uses_scrollbar = sb
        w = self.scrollbar_totwidth
        if sb:
            self.resize(-w, 0, setscrollbar=0)
            self.scrollbar.pack(side=LEFT, fill=Y)
            self.text['yscrollcommand'] = self.scrollbar.set
        else:
            self.resize(w, 0, setscrollbar=0)
            self.scrollbar.pack_forget()
            self.text['yscrollcommand'] = None

    def update_simple(self, lsamp, rsamp):
        t = self.text
        t.delete('1.0', '100.0')
        t.insert('1.0', str(rsamp.stat))

    def update(self, force=0, setscrollbar=1):

        stats = self.stats

        idxs = [max(0, min(control.sample, len(stats)-1))
                for control in self.controls]
        if (idxs == self.lastidxs) and not force:
            return

        self.lastidxs = idxs

        self.text['state'] = self.tothead['state'] = self.rowhead['state'] = NORMAL

        self.text.delete('1.0', END)
        self.tothead.delete('1.0', END)
        self.rowhead.delete('1.0', END)

        if not stats:
            self.tothead.insert('end', '-- No Sample --')
            self.text['state'] = self.tothead['state'] = self.rowhead['state'] = DISABLED
            return

        self.statbyname = {}
        statbyidx = []
        for i, control in enumerate(self.controls):
            stat = stats[idxs[i]]
            statbyidx.append(stat)
            self.statbyname[control.name] = stat

        samps = self.samps = [
            Sample(self.mod, statbyidx[0], self.controls[0].marker.name, idxs[0],
                   numkindrows=self.numkindrows,
                   statype=self.graph.display.statype
                   )]

        self.colorsamp = samps[0]
        if len(self.controls) > 1:
            samps.append(Sample(self.mod, statbyidx[1], self.controls[1].marker.name, idxs[1],
                                relative=samps[0]))

            self.relsamp = samps[1]

        t = self.tothead

        n = max([len(str(samp.index)) for samp in samps])
        for samp in samps:
            t.insert('end', 'Sample %s: ' % samp.name)
            t.insert('end', ('%%%dd' % n) % samp.index, ('index',))
            t.insert('end', ' at %s\n' % (samp.datetime))

        t.tag_configure('index', background='#e0e0e0')

        t = self.rowhead

        self.sizes = [float(samp.stat.size) for samp in samps]

        for col in self.cols:
            t.insert('end', col.align(col.header), ('header',))
        t.insert('end', '\n')

        t = self.text

        self.ap = lambda text: t.insert('end', text)

        self.colorow = Row(samps[0].count, samps[0].size, '<Total>')
        self.rowbyname = self.statbyname
        self.cumulval = 0
        for col in self.cols:
            col.render(col)
        self.ap('\n\n')

        self.cumulval = 0
        for i, a in enumerate(samps[0].rows):
            self.colorow = a
            if len(samps) > 1:
                self.rowbyname = {
                    samps[0].name: a,
                    samps[1].name: samps[1].kindrows[a.name]
                }
            for col in self.cols:
                col.render(col)
            self.ap('\n')

        if setscrollbar and self.auto_scrollbar:
            numrows = int(self.text.index('end').split('.')[0])-2
            h = int(self.text['height'])
            needs_scrollbar = numrows > h
            if needs_scrollbar != self.uses_scrollbar:
                self.setscrollbar(needs_scrollbar)

        self.text['state'] = self.tothead['state'] = self.rowhead['state'] = DISABLED

    def resize(self, dx, dy, setscrollbar=1):
        dx = int(dx)
        oldwidth = self.pixwidth
        newwidth = self.pixwidth + dx
        if newwidth < self.chdx * 2:
            newwidth = self.chdx * 2

        self.pixwidth = newwidth
        dx = newwidth - oldwidth

        charwidth, extra = divmod(newwidth, self.chdx)

        self.kindcol.width = max(
            charwidth - self.widthbeforekind - 1, self.minkindwidth)

        self.totxresize += dx
        for t in (self.tothead, self.rowhead, self.text):
            t['width'] = charwidth
            t['padx'] = self.minpadx + extra / 2

        dy = int(dy)

        rowresize, extra = divmod(self.totyresize + dy, self.chdy)
        newheight = self.orgtextheight + rowresize
        oldheight = int(self.text['height'])
        if newheight < self.mintextheight:
            newheight = self.mintextheight
            dy = (newheight - oldheight) * self.chdy + extra
        self.totyresize += dy

        self.text['height'] = newheight
        self.text['pady'] = self.textminpady + extra / 2

        self.update(force=1, setscrollbar=1)

        return dx, dy


class Filler:
    def __init__(self, master):
        self.frame = self.can = Canvas(
            master,
            # background='blue',
            width=0,
            height=0)

    def getsize(self):
        return int(self.can['width']), int(self.can['height']),

    def setsize(self, w, h):
        self.can.configure(
            width=w,
            height=h
        )

    def resize(self, dw, dh):
        w, h = self.getsize()
        self.setsize(max(0, w + dw), max(0, h + dh))


class Row:
    def __init__(self, count, size, name):
        self.count = count
        self.size = size
        self.name = name


class Sample:
    def __init__(self, mod, stat, name, index, numkindrows=None, statype='Size', relative=None):
        self.stat = stat
        self.size = stat.size
        self.count = stat.count
        self.name = name
        self.index = index

        self.datetime = mod.time.asctime(mod.time.localtime(stat.timemade))

        self.kindrows = {}

        if numkindrows is not None:
            rows = stat.get_rows_n_and_other(numkindrows, statype)
            for r in rows:
                self.kindrows[r.name] = r
        else:
            kinds = []
            oidx = None
            for row in relative.rows:
                if row.name == '<Other>':
                    oidx = len(kinds)
                    continue
                else:
                    kinds.append(row.name)

            rows = stat.get_rows_of_kinds(kinds)
            size = 0
            count = 0
            for i, row in enumerate(rows):
                kind = kinds[i]
                if row is None:
                    row = Row(0, 0, kind)
                self.kindrows[kind] = row
                size += row.size
                count += row.count

            if oidx is not None:
                other = Row(stat.count - count, stat.size - size, '<Other>')
                rows[oidx:oidx] = [other]
                self.kindrows['<Other>'] = other

        self.rows = rows


class ProfileBrowser:
    colors = ("red", "green", "blue", "yellow", "magenta", "cyan", 'white')
    numkindrows = 10

    def __init__(self, app, filename):
        self.inited = 0
        self.app = app
        self.mod = mod = app.mod
        self.master = master = app.root
        if filename:
            filename = mod.path.abspath(filename)
            self.initialdir = mod.path.dirname(filename)
        else:
            self.initialdir = mod.os.getcwd()

        self.frame = frame = Toplevel(
            master,
            # background='#bbb'
        )
        #frame['cursor'] = 'umbrella'
        # frame.resizable(True,True)

        self.menubar = Frame(self.frame, relief=RAISED, bd=2)

        self.filebutton = Menubutton(self.menubar, text='File')
        self.filemenu = Menu(self.filebutton)
        self.filebutton['menu'] = self.filemenu
        self.filemenu.add_command(
            label='New Profile Browser', command=self.cmd_new)
        self.filemenu.add_command(label='Open Profile', command=self.cmd_open)
        self.filemenu.add_command(label='Close Window', command=self.cmd_close)
        self.filemenu.add_command(
            label='Clear Cache', command=self.cmd_clear_cache)
        self.filemenu.add_command(label='Exit', command=self.cmd_exit)
        self.panebutton = Menubutton(self.menubar, text='Pane')
        self.panemenu = Menu(self.panebutton)
        self.panebutton['menu'] = self.panemenu

        choices = [
            ('Bars', 'Lines'),
            ('Size', 'Count'),
        ]

        self.graphtypevar = StringVar()
        self.graphbutton = self.modechooser(
            self.menubar, 'Graph', choices,
            self.graphtypevar, self.cmd_graphtype)

        choices = [
            ('A', 'B'),
            ('Size', 'Count'),
            ('%A:Tot', '%B:Tot'),
            ('Cumul', 'A-B', 'B-A'),
            ('%A:Tot', '%B:Tot'),
            ('Kind',),
        ]

        self.var_tablemode = StringVar()
        self.tablebutton = Menubutton(self.menubar, text='Table')
        self.tablemenu = Menu(self.tablebutton)
        self.tablebutton['menu'] = self.tablemenu
        self.headermenu = Menu(self.tablebutton, title='Table header')
        self.addmodechooser(
            self.headermenu,
            choices,
            self.var_tablemode,
            self.cmd_tablemode
        )
        self.tablemenu.add_cascade(label='Header', menu=self.headermenu)
        self.var_tablescrollbar = StringVar()
        self.tablescrollbarmenu = Menu(
            self.tablebutton, title='Table scrollbar')

        self.addmodechooser(
            self.tablescrollbarmenu,
            [('Auto', 'On', 'Off')],
            self.var_tablescrollbar,
            self.cmd_tablescrollbar
        )

        self.tablemenu.add_cascade(
            label='Scrollbar',
            menu=self.tablescrollbarmenu)

        self.windowmenu = WindowMenu(self.menubar, self.app.var_window)
        self.window = app.add_window_frame(self.frame, self.windowmenu)

        self.helpbutton = Menubutton(self.menubar, text='Help')
        self.helpmenu = Menu(self.helpbutton)
        self.helpbutton['menu'] = self.helpmenu
        self.helpmenu.add_command(label='About', command=self.cmd_about)
        self.helpmenu.add_command(label='Help', command=self.cmd_help)

        self.ctrlframe = Frame(
            self.frame,
            bd=2,
            relief=GROOVE,
            # background='#999',


        )

        self.exitbutton = Button(self.ctrlframe, text='Exit', command=self.cmd_exit,
                                 background='red')

        self.set_filename(filename)

        self.id_collect = None
        self.collecting = IntVar()
        self.collecting.set(0)
        self.collectbutton = Checkbutton(self.ctrlframe, text='Collect',
                                         variable=self.collecting,
                                         command=self.cmd_collect,
                                         relief=RAISED)

        self.stats = Stats(self.mod)

        self.disptab = Frame(self.frame,
                             # relief=SUNKEN,
                             # bd=3
                             )

        self.display = Display(self.disptab,
                               scale_table=AxisControl.scale_table,
                               numkindrows=self.numkindrows,
                               getkindcolor=self.getkindcolor,
                               )

        self.xcontrol = AxisControl(self.ctrlframe,
                                    name='X',
                                    range=self.display.xrange,
                                    grid=self.display.xgrid,
                                    unit='samples',
                                    rangecommand=self.display.setxrange,
                                    gridcommand=self.display.setxgrid
                                    )

        self.ycontrol = AxisControl(self.ctrlframe,
                                    name='Y',
                                    range=self.display.yrange,
                                    grid=self.display.ygrid,
                                    unit='bytes',
                                    rangecommand=self.display.setyrange,
                                    gridcommand=self.display.setygrid,
                                    autocommand=self.display.cmd_yrange_auto
                                    )

        self.display.xcontrol = self.xcontrol
        self.display.ycontrol = self.ycontrol

        self.mcontrols = []
        self.mcontrolbyname = {}
        for name in ('A', 'B'):
            marker = self.display.new_xmarker(name)
            control = MarkerControl(
                self.ctrlframe, marker, self.update_tableframe)
            marker.set_poscommand(control.setsample)
            self.mcontrols.append(control)
            self.mcontrolbyname[name] = control

        self.var_showcontrol = BooleanVar()
        self.var_showcontrol.set(1)
        self.panemenu.add_checkbutton(
            label='Show Control Panel',
            variable=self.var_showcontrol,
            command=self.cmd_showcontrol)

        self.var_showgraph = BooleanVar()
        self.var_showgraph.set(1)
        self.panemenu.add_checkbutton(
            label='Show Graph',
            variable=self.var_showgraph,
            command=self.cmd_showgraph)

        self.var_showtable = BooleanVar()
        self.var_showtable.set(1)
        self.panemenu.add_checkbutton(
            label='Show Table',
            variable=self.var_showtable,
            command=self.cmd_showtable)

        tf = self.tf = TableFrame(self, self.disptab)
        d_t = self.d_t = PaneDiv(self.disptab, movecommand=self.cmd_dt_moved)

        self.xcontrol.frame.grid(row=0, column=0, padx=3, pady=3, sticky=W)
        self.ycontrol.frame.grid(row=1, column=0, padx=3, pady=3)
        self.mcontrols[0].frame.grid(
            row=0, column=1, columnspan=1, sticky=W, padx=3, pady=3)
        self.mcontrols[1].frame.grid(
            row=1, column=1, columnspan=1, sticky=W, padx=3, pady=3)
        self.exitbutton.grid(row=0, column=2, padx=3, pady=3)
        self.collectbutton.grid(row=0, column=3, padx=3, pady=3)

        self.filler = Filler(self.frame)

        self.filebutton.pack(side=LEFT)
        self.panebutton.pack(side=LEFT)
        self.graphbutton.pack(side=LEFT)
        self.tablebutton.pack(side=LEFT)
        self.windowmenu.button.pack(side=LEFT)
        self.helpbutton.pack(side=LEFT)

        self.menubar.grid(column=0, columnspan=4, sticky=N+W+E)
        self.gridmain()

        frame.bind('<Map>', self.event_map)

        self.tf.setmode(self.var_tablemode.get(), self.numkindrows)

        self.load_filename(filename)

        d_t.frame.update_idletasks()
        d_t.setheight(max(self.display.frame.winfo_height(),
                          tf.frame.winfo_height()))

        d_t.frame.update_idletasks()
        self.minsize = (500, 400)
        self.maxsize = (self.frame.winfo_screenwidth(),
                        self.frame.winfo_screenheight())
        minsizes = {
            # (ctrl, disp, tab) : (width, height)
            (0, 0, 0): (270, 25),
            (1, 0, 0): (363, 61),
            (0, 1, 0): (270, 131),
            (1, 1, 0): (270, 131),
        }

        self.setusergeometry()

        def initfinal():
            self.tf.setchdim()

            rx = self.frame.winfo_rootx() + self.frame.winfo_width()
            self.tf_wanted_margin = rx - \
                (self.tf.frame.winfo_rootx() + self.tf.frame.winfo_width())

            self.lastw = self.frame.winfo_width()
            self.lasth = self.frame.winfo_height()
            self.in_configure = 0
            frame.bind('<Configure>', self.event_configure)
            self.inited = 1

        initfinal()
        # self.frame.after_idle(initfinal)

    def cmd_about(self):
        self.cmd_help('about')

    def cmd_help(self, pickname='help'):
        os = self.mod.os
        ocursor = self.frame.winfo_toplevel()['cursor']
        try:
            self.frame.winfo_toplevel()['cursor'] = 'watch'
            self.frame.update()
            m = self.mod.Text.gsltextviewer(
                self.frame,
                inpickle=getattr(self.mod.pbhelp, pickname)
                # htmloutfile='/tmp/x.html',
            )

            self.app.add_window_frame(m)
        finally:
            self.frame.winfo_toplevel()['cursor'] = ocursor

    def cmd_clear_cache(self):
        self.stats.clear_cache()

    def cmd_close(self):
        self.frame.destroy()

    def cmd_collect(self, *args):
        # self.afterfunc()
        # self.frame.after(1, self.afterfunc) # Turn on button first.??

        if self.collecting.get():
            self.event_collect()
        else:
            if self.id_collect is not None:
                self.frame.after_cancel(self.id_collect)
                self.id_collect = None

    def event_collect(self):
        o, n = self.stats.collect()
        if n:
            if o != self.display.numstats:
                self.display.load_stats(self.stats)
            else:
                st = self.stats[-n:]
                self.display.add_stats(st)
            for c in self.mcontrols:
                c.setnumsamples(len(self.stats))

        self.id_collect = self.frame.after(1000, self.event_collect)

    def cmd_dt_moved(self, dx):
        # The division between display and table panes moved.

        # Disable configure event handling while we are resizing.
        self.in_configure += 1

        # Right x position of enclosing frame

        rx = self.frame.winfo_rootx() + self.frame.winfo_width()

        # Right margin between pane divider and enclosing window

        mx = rx - (self.d_t.frame.winfo_rootx() + self.d_t.frame.winfo_width())

        # Don't move pane divider outside window
        dx = min(dx, mx)

        # Right margin between table and enclosing window
        # before resizing
        mx = rx - (self.tf.frame.winfo_rootx() + self.tf.frame.winfo_width())

        dx, _ = self.display.resize(dx, 0)

        wanted_margin = self.tf_wanted_margin

        # After move
        mx -= dx
        self.tf.resize(mx - wanted_margin, 0)

        self.display.moveback()

        self.in_configure -= 1

    def cmd_exit(self):
        self.app.exit()

    def cmd_graphtype(self):
        self.display.setgraphtype(self.graphtypevar.get(), self.stats)
        self.cmd_tablemode()

    def cmd_new(self):
        self.app.new_profile_browser(self.filename)

    def cmd_open(self):
        op = tkinter.filedialog.Open(self.frame,
                                     # ? Should we have default extension or not??
                                     # defaultextension='.hpy',
                                     initialdir=self.initialdir,
                                     filetypes=[('Heapy data files', '.hpy'),
                                                ('All files', '*')
                                                ]
                                     )
        filename = op.show()
        if filename:
            self.load_filename(filename)

    def cmd_showcontrol(self):
        self.grid_things()

    def cmd_showgraph(self):
        if self.var_showgraph.get() and self.var_showtable.get():
            self.tf.resize(-self.tf.totxresize, 0)
            self.display.resize(self.display.orgwidth - self.display.botx, 0)
            self.display.moveback()
        self.grid_things()

    cmd_showtable = cmd_showgraph

    def cmd_tablemode(self):
        self.tf.setmode(self.var_tablemode.get(), self.numkindrows)
        self.tf.update()

    def cmd_tablescrollbar(self):
        tf = self.tf
        s = self.var_tablescrollbar.get()
        if s == 'Auto':
            tf.auto_scrollbar = 1
            tf.update(force=1, setscrollbar=1)
        elif s == 'On':
            tf.auto_scrollbar = 0
            tf.setscrollbar(1)
        elif s == 'Off':
            tf.auto_scrollbar = 0
            tf.setscrollbar(0)
        else:
            assert 0

    def setusergeometry(self):
        # Make the geometry of the window be user-specified
        # This is called after Tk has determined the size
        # of the window needed for the initial widget configuration.
        # The size is not to be changed after that, other than
        # on user request.
        # I couldn't just do frame.geometry(frame.geometry()) because,
        # presumably, of a bug in the Tk and/or wm I am using. I hope
        # this works for all systems .. Notes  26 Oct 2005.

        self.frame.update()
        g = '%dx%d+%d+%d' % (
            self.frame.winfo_width(),
            self.frame.winfo_height(),
            self.frame.winfo_rootx(),
            self.frame.winfo_rooty())
        self.frame.geometry(g)

    def modechooser(self, frame, name, choices, cmdvar, command):

        button = Menubutton(frame, text=name)
        menu = Menu(button)
        button['menu'] = menu

        self.addmodechooser(menu, choices, cmdvar, command)
        return button

    def addmodechooser(self, menu, choices, cmdvar, command):

        def setcmdvar():
            cmdvar.set(' '.join([v.get() for v in vars]))

        def cmd():
            setcmdvar()
            command()

        vars = []
        for ch in choices:
            var = StringVar()
            vars.append(var)
            var.set(ch[0])
            for a in ch:
                menu.add_radiobutton(
                    command=cmd,
                    label=a,
                    value=a,
                    variable=var,
                    #font=('Courier','12', 'bold'),
                    #font=('Helvetica','12', 'bold'),
                    columnbreak=(a == ch[0])
                )

        setcmdvar()

    def grid_things(self):
        ow = self.frame.winfo_width()
        oh = self.frame.winfo_height()

        self.ctrlframe.grid_forget()
        self.display.frame.grid_forget()
        self.d_t.frame.grid_forget()
        self.tf.frame.grid_forget()
        self.disptab.grid_forget()
        self.filler.frame.grid_forget()

        self.gridmain()

        self.frame.update_idletasks()
        self.sizewidgets()

    def gridmain(self):

        row = 1

        c = self.var_showcontrol.get()
        if c:
            self.ctrlframe.grid(row=row, column=0,
                                columnspan=3, padx=3, pady=3, sticky=W)
            row += 1

        column = 0

        g = self.var_showgraph.get()
        t = self.var_showtable.get()
        gt = (g, t)
        if g:
            self.display.frame.grid(row=0, column=column, sticky=N+W,
                                    padx=3, pady=3
                                    )
            column += 1

        if g and t:
            self.d_t.frame.grid(row=0, column=column, sticky=N+W)
            column += 1
        if t:
            self.tf.frame.grid(row=0, column=column, sticky=N+W, padx=3, pady=3
                               )
        if g or t:
            self.disptab.grid(row=row, column=0,
                              sticky=N+W,
                              # padx=3,pady=3,
                              )
            row += 1
        self.filler.setsize(0, 0)
        self.filler.frame.grid(row=row, column=3, sticky=N+W)

        self.frame.resizable(1, 1)

    def event_configure(self, event):
        if event.widget is not self.frame:
            return

        if not self.inited:
            return

        if self.in_configure:
            return

        curw = self.frame.winfo_width()
        curh = self.frame.winfo_height()
        if curw == self.lastw and curh == self.lasth:
            return

        self.in_configure += 1

        self.lastw = curw
        self.lasth = curh

        self.sizewidgets()

        self.in_configure -= 1

    def sizewidgets(self):
        self.frame.update()
        curw = self.frame.winfo_width()
        curh = self.frame.winfo_height()

        mbx = self.menubar.winfo_rootx()
        mby = self.menubar.winfo_rooty()

        sfs = []
        if self.var_showgraph.get():
            sfs.append(self.display)
        if self.var_showtable.get():
            sfs.append(self.tf)

        if not sfs:
            sfs.append(self.filler)

        dys = {}
        didh = 0
        for sf in sfs:
            f = sf.frame
            diy = f.winfo_rooty()
            dih = f.winfo_height()

            ch = diy - mby + dih
            dy = curh - ch - 7
            didh = didh or dy
            dys[sf] = dy

        if self.var_showtable.get():
            f = self.tf.frame
        elif self.var_showgraph.get():
            f = self.display.frame
        else:
            f = self.filler.frame

        fx = f.winfo_rootx()
        fw = f.winfo_width()

        cw = fx - mbx + fw

        fdw = curw - cw - 6

        if f is self.filler.frame and not self.var_showcontrol.get():
            fdw = curw - self.filler.getsize()[0] - 3

        if didh or fdw:
            if self.var_showgraph.get() and self.var_showtable.get():
                dprop = float(self.display.frame.winfo_width())
                dprop = dprop / (dprop + self.tf.frame.winfo_width())
                dx, dy = self.display.resize(fdw * dprop, dys[self.display])
                self.tf.resize(fdw - dx, dys[self.tf])
                self.frame.update_idletasks()
                self.d_t.setheight(max(self.display.frame.winfo_height(),
                                       self.tf.frame.winfo_height()))

            elif self.var_showgraph.get():
                self.display.resize(fdw, dys[self.display])
            elif self.var_showtable.get():
                self.tf.resize(fdw, dys[self.tf])
            else:
                self.filler.resize(fdw, dys[self.filler])
                self.filler.setsize(self.filler.getsize()[0], 1000)
            if self.var_showgraph.get():
                self.display.moveback()

        #self.resize(dw, dh)

    def resize(self, dw, dh):
        self.display.resize(dw, dh)
        # self.frame.wm_geometry('')

    def event_map(self, event):
        self.frame.unbind('<Map>')
        self.frame.bind('<Unmap>', self.event_unmap)
        self.frame.lift()

    def event_unmap(self, event):
        self.frame.unbind('<Unmap>')
        self.frame.bind('<Map>', self.event_map)

    def load_filename(self, filename):
        ocursor = self.frame.winfo_toplevel()['cursor']
        try:
            self.frame.winfo_toplevel()['cursor'] = 'watch'
            self.frame.update()
            if filename:
                filename = self.mod.path.abspath(filename)
            try:
                self.stats.open(filename)
            except Exception:
                __import__('traceback').print_exc()
                etype, value, tb = self.mod._root.sys.exc_info()
                tkinter.messagebox.showerror(
                    master=self.frame,
                    message=(
                        "Error when loading\n%r:\n" % filename +
                        "%s" % ''.join(self.mod._root.traceback.format_exception_only(
                            etype, value)))
                )
            else:
                self.display.load_stats(self.stats)

                for c in self.mcontrols:
                    c.setnumsamples(len(self.stats))
                # self.scontrol.trackcommand(1)
                self.set_filename(filename)

                self.xrange_fit()
                self.display.xview_moveto(0)
                self.mcontrols[1].settracking(0)
                self.mcontrols[0].settracking(1)
                self.yrange_fit()
                self.tf.update(force=1)
                if filename:
                    self.initialdir = self.mod.path.dirname(filename)

        finally:
            self.frame.winfo_toplevel()['cursor'] = ocursor

    def update_tableframe(self):
        self.tf.update()

    def getkindcolor(self, kind):
        if kind == '<Other>':
            return 'black'
        else:
            return self.colors[abs(hash(kind)) % len(self.colors)]

    def set_filename(self, filename):
        self.filename = filename
        if not filename:
            filename = '<No File>'
        title = 'Heapy Profile Browser: %s' % filename
        self.window.title(title)

    def setnormpos(self):
        self.setscrollregion()
        if self.ymax >= self.yrange:
            self.yrange_fit()
        if self.xi0 is None:
            self.drawxaxis()
        else:
            self.updatexaxis()

        self.track()

    def redraw_all(self):
        pass

    def trackoff(self):
        self.rcontrol.settracking(0)

    def xrange_fit(self):
        self.xcontrol.fit(len(self.stats))

    def yrange_fit(self):
        self.display.yrange_auto(force=1)


class _GLUECLAMP_:
    _imports_ = (
        '_parent:Use',
        '_parent:pbhelp',
        '_root.guppy.etc:textView',
        '_root:hashlib',
        '_root:os',
        '_root.os:path',
        '_root:time',
        '_root.guppy.gsl:Text',
    )

    def pb(self, filename=None):
        """pb( [filename: profilefilename+])

Create a Profile Browser window.

Argument
    filename: profilefilename+
        The name of a file containing profile data.
See also
    Heapy Profile Browser[1]
    Screenshot[2]
References
    [0] heapy_Use.html#heapykinds.Use.pb
    [1] ProfileBrowser.html
    [2] pbscreen.jpg"""

        pa = ProfileApp(self)
        pa.new_profile_browser(filename)
        pa.mainloop()

    def tpg(self):
        self('/tmp/x.hpy')

Youez - 2016 - github.com/yon3zu
LinuXploit