!C99Shell v. 2.0 [PHP 7 Update] [25.02.2019]!

Software: Apache/2.2.16 (Debian). PHP/5.3.3-7+squeeze19 

uname -a: Linux mail.tri-specialutilitydistrict.com 2.6.32-5-amd64 #1 SMP Tue May 13 16:34:35 UTC
2014 x86_64
 

uid=33(www-data) gid=33(www-data) groups=33(www-data) 

Safe-mode: OFF (not secure)

/usr/share/pyshared/hamster/widgets/   drwxr-xr-x
Free 130.07 GB of 142.11 GB (91.53%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     facttree.py (18.54 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# - coding: utf-8 -

# Copyright (C) 2008-2009 Toms Bauģis <toms.baugis at gmail.com>

# This file is part of Project Hamster.

# Project Hamster is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# Project Hamster is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with Project Hamster.  If not, see <http://www.gnu.org/licenses/>.

import gtk, gobject
import datetime as dt

from hamster import stuff
from hamster.stuff import format_duration, format_activity
from tags import Tag

import pango

def parent_painter(column, cell, model, iter):
    fact = model.get_value(iter, 0)
    parent_info = model.get_value(iter, 1)

    if fact is None:
        parent_info["first"] = model.get_path(iter) == (0,) # first row
        cell.set_property('data', parent_info)
    else:
        cell.set_property('data', fact)

def action_painter(column, cell, model, iter):
    cell.set_property('xalign', 1)
    cell.set_property('yalign', 0)

    if model.get_value(iter, 0) is None:
        cell.set_property("stock_id", "")
    else:
        cell.set_property("stock_id", "gtk-edit")


class FactTree(gtk.TreeView):
    __gsignals__ = {
        "edit-clicked": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, )),
        "double-click": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, ))
    }

    def __init__(self):
        gtk.TreeView.__init__(self)

        self.set_headers_visible(False)
        self.set_show_expanders(False)

        # fact (None for parent), duration, parent data (if any)
        self.store_model = gtk.ListStore(gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT)
        self.set_model(self.store_model)


        fact_cell = FactCellRenderer()
        fact_column = gtk.TreeViewColumn("", fact_cell, data=0)
        fact_column.set_cell_data_func(fact_cell, parent_painter)
        fact_column.set_expand(True)
        self.append_column(fact_column)

        edit_cell = gtk.CellRendererPixbuf()
        edit_cell.set_property("ypad", 2)
        edit_cell.set_property("mode", gtk.CELL_RENDERER_MODE_ACTIVATABLE)
        self.edit_column = gtk.TreeViewColumn("", edit_cell)
        self.edit_column.set_cell_data_func(edit_cell, action_painter)
        self.append_column(self.edit_column)

        self.connect("row-activated", self._on_row_activated)
        self.connect("button-release-event", self._on_button_release_event)
        self.connect("key-release-event", self._on_key_released)
        self.connect("configure-event", lambda *args: self.columns_autosize())

        self.show()

        self.longest_activity_category = 0 # we will need this for the cell renderer
        self.longest_interval = 0 # we will need this for the cell renderer
        self.longest_duration = 0 # we will need this for the cell renderer
        self.stored_selection = []

        self.box = None


        pixmap = gtk.gdk.Pixmap(None, 10, 10, 1)
        _test_context = pixmap.cairo_create()
        self._test_layout = _test_context.create_layout()
        font = pango.FontDescription(gtk.Style().font_desc.to_string())
        self._test_layout.set_font_description(font)


    def fix_row_heights(self):
        alloc = self.get_allocation()
        if alloc != self.box:
            self.box = alloc
            self.columns_autosize()

    def clear(self):
        self.store_model.clear()
        self.longest_activity_category = 0
        self.longest_interval = 0
        self.longest_duration = 0

    def update_longest_dimensions(self, fact):
        interval = "%s -" % fact["start_time"].strftime("%H:%M")
        if fact["end_time"]:
            interval = "%s %s" % (interval, fact["end_time"].strftime("%H:%M"))
        self._test_layout.set_markup(interval)
        w, h = self._test_layout.get_pixel_size()
        self.longest_interval = max(self.longest_interval, w + 20)


        self._test_layout.set_markup("%s - <small>%s</small> " % (stuff.escape_pango(fact["name"]), stuff.escape_pango(fact["category"])))
        w, h = self._test_layout.get_pixel_size()
        self.longest_activity_category = max(self.longest_activity_category, w + 10)

        self._test_layout.set_markup("%s" % stuff.format_duration(fact["delta"]))
        w, h = self._test_layout.get_pixel_size()
        self.longest_duration = max(self.longest_duration, w)


    def add_fact(self, fact):
        self.update_longest_dimensions(fact)
        self.store_model.append([fact, None])


    def add_group(self, group_label, group_date, facts):
        total = sum([stuff.duration_minutes(fact["delta"]) for fact in facts])

        # adds group of facts with the given label
        self.store_model.append([None, dict(date = group_date,
                                            label = group_label,
                                            duration = total)])

        for fact in facts:
            self.add_fact(fact)


    def get_row(self, path):
        """checks if the path is valid and if so, returns the model row"""
        if path is None or path < 0: return None

        try: # see if path is still valid
            iter = self.store_model.get_iter(path)
            return self.store_model[path]
        except:
            return None

    def id_or_label(self, path):
        """returns id or date, id if it is a fact row or date if it is a group row"""
        row = self.get_row(path)
        if not row: return None

        if row[0]:
            return row[0]['id']
        else:
            return row[1]['label']

    def detach_model(self):
        # ooh, somebody is going for refresh!
        # let's save selection too - maybe it will come handy
        self.store_selection()

        # and now do what we were asked to
        self.set_model()


    def attach_model(self):
        # attach model is also where we calculate the bounding box widths
        self.set_model(self.store_model)

        if self.stored_selection:
            self.restore_selection()


    def store_selection(self):
        selection = self.get_selection()
        model, iter = selection.get_selected()
        self.stored_selection = None
        if iter:
            path = model.get_path(iter)[0]
            prev, cur, next = path - 1, path, path + 1
            self.stored_selection = ((prev, self.id_or_label(prev)),
                                     (cur, self.id_or_label(cur)),
                                     (next, self.id_or_label(next)))


    def restore_selection(self):
        """the code is quite hairy, but works with all kinds of deletes
           and does not select row when it should not.
           TODO - it might be worth replacing this with something much simpler"""
        model = self.store_model

        new_prev_val, new_cur_val, new_next_val = None, None, None
        prev, cur, next = self.stored_selection

        if cur:  new_cur_val  = self.id_or_label(cur[0])
        if prev: new_prev_val = self.id_or_label(prev[0])
        if next: new_next_val = self.id_or_label(next[0])

        path = None
        values = (new_prev_val, new_cur_val, new_next_val)
        paths = (prev, cur, next)

        if cur[1] and cur[1] in values: # simple case
            # look if we can find previous current in the new threesome
            path = paths[values.index(cur[1])][0]
        elif prev[1] and prev[1] == new_prev_val and next[1] and next[1] == new_next_val:
            # on update the ID changes so we find it by matching in between
            path = cur[0]
        elif prev[1] and prev[1] == new_prev_val: # all that's left is delete.
            if new_cur_val:
                path = cur[0]
            else:
                path = prev[0]
        elif not new_prev_val and not new_next_val and new_cur_val:
            # the only record in the tree (no next no previous, but there is current)
            path = cur[0]


        if path is not None:
            selection = self.get_selection()
            selection.select_path(path)

            self.set_cursor_on_cell(path)

    def select_fact(self, fact_id):
        i = 0
        while self.id_or_label(i) and self.id_or_label(i) != fact_id:
            i +=1

        if self.id_or_label(i) == fact_id:
            selection = self.get_selection()
            selection.select_path(i)

    def get_selected_fact(self):
        selection = self.get_selection()
        (model, iter) = selection.get_selected()
        if iter:
            return model[iter][0] or model[iter][1]["date"]
        else:
            return None


    def _on_button_release_event(self, tree, event):
        # a hackish solution to make edit icon keyboard accessible
        pointer = event.window.get_pointer() # x, y, flags
        path = self.get_path_at_pos(pointer[0], pointer[1]) #column, innerx, innery

        if path and path[1] == self.edit_column:
            self.emit("edit-clicked", self.get_selected_fact())
            return True

        return False

    def _on_row_activated(self, tree, path, column):
        if column == self.edit_column:
            self.emit_stop_by_name ('row-activated')
            self.emit("edit-clicked", self.get_selected_fact())
            return True


    def _on_key_released(self, tree, event):
        # capture e keypress and pretend that user click on edit
        if (event.keyval == gtk.keysyms.e):
            self.emit("edit-clicked", self.get_selected_fact())
            return True

        return False



class FactCellRenderer(gtk.GenericCellRenderer):
    """ We need all kinds of wrapping and spanning and the treeview just does
        not cut it"""

    __gproperties__ = {
        "data": (gobject.TYPE_PYOBJECT, "Data", "Data", gobject.PARAM_READWRITE),
    }

    def __init__(self):
        gtk.GenericCellRenderer.__init__(self)
        self.height = 0
        self.data = None

        default_font = gtk.Style().font_desc.to_string()
        self.label_font = pango.FontDescription(default_font)
        self.label_font_size = 10

        self.selected_color = gtk.Style().text[gtk.STATE_SELECTED]
        self.normal_color = gtk.Style().text[gtk.STATE_NORMAL]

        self.tag_font = pango.FontDescription(default_font)
        self.tag_font.set_size(pango.SCALE * 8)

        self.layout, self.tag_layout = None, None

        self.col_padding = 10
        self.row_padding = 4


        self.labels = {}

    def do_set_property (self, pspec, value):
        setattr(self, pspec.name, value)

    def do_get_property(self, pspec):
        return getattr (self, pspec.name)


    def set_text(self, text):
        # sets text and returns width and height of the layout
        self.layout.set_text(text)
        w, h = self.layout.get_pixel_size()
        return w, h

    def on_render (self, window, widget, background_area, cell_area, expose_area, flags):
        if not self.data:
            return

        """
          ASCII Art
          --------------+--------------------------------------------+-------+---+
          13:12 - 17:18 | Some activity - category, tag, tag, tag,   | 14:44 | E |
                        | tag, tag, some description in grey italics |       |   |
          --------------+--------------------------------------------+-------+---+
        """


        context = window.cairo_create()
        if not self.layout:
            self.layout = context.create_layout()
            self.layout.set_font_description(self.label_font)

            self.tag_layout = context.create_layout()
            self.tag_layout.set_font_description(self.tag_font)


        if "id" in self.data:
            fact, parent = self.data, None
        else:
            parent, fact = self.data, None




        x, y, width, height = cell_area
        context.translate(x, y)

        current_fact = widget.get_selected_fact()

        if parent:
            text_color = self.normal_color
            # if we are selected, change font color appropriately
            if current_fact and isinstance(current_fact, dt.date) \
               and current_fact == parent["date"]:
                text_color = self.selected_color

            self.set_color(context, text_color)

            self.layout.set_markup("<b>%s</b>" % stuff.escape_pango(parent["label"]))
            if self.data["first"]:
                y = 5
            else:
                y = 20

            context.move_to(5, y)
            context.show_layout(self.layout)

            self.layout.set_markup("<b>%s</b>" % stuff.format_duration(parent["duration"]))
            label_w, label_h = self.layout.get_pixel_size()

            context.move_to(width - label_w, y)
            context.show_layout(self.layout)

        else:
            text_color = self.normal_color
            selected = False
            # if we are selected, change font color appropriately
            if current_fact and isinstance(current_fact, dt.date) == False \
               and current_fact["id"] == fact["id"]:
                text_color = self.selected_color
                selected = True

            def show_label(label, x, y, w):
                self.layout.set_markup(label)
                context.move_to(x, y)
                if w:
                    self.layout.set_width(w)
                context.show_layout(self.layout)

            self.set_color(context, text_color)

            labels = self.labels[fact["id"]]
            show_label(*labels["interval"])

            # for the right-aligned delta with have reserved space for scrollbar
            # but about it's existance we find only on expose, so we realign
            self.layout.set_markup(labels["delta"][0])
            w, h = self.layout.get_pixel_size()
            context.move_to(width - w, labels["delta"][2])
            context.show_layout(self.layout)

            show_label(*labels["activity"])

            if fact["category"]:
                if not selected:
                    self.set_color(context, widget.get_style().text[gtk.STATE_INSENSITIVE])

                show_label(*labels["category"])


            if fact["tags"]:
                start_x, start_y, cell_end = labels["tags"][1:]
                cur_x, cur_y = start_x, start_y

                for i, tag in enumerate(fact["tags"]):
                    tag_w, tag_h = Tag.tag_size(tag, self.tag_layout)

                    if i > 0 and cur_x + tag_w >= cell_end:
                        cur_x = start_x
                        cur_y += tag_h + 4

                    Tag(context, self.tag_layout, True, tag, None,
                        gtk.gdk.Rectangle(cur_x, cur_y, cell_end - cur_x, height - cur_y))

                    cur_x += tag_w + 4


            if fact["description"]:
                self.set_color(context, text_color)
                show_label(*labels["description"])



    def set_color(self, context, color):
        context.set_source_rgba(*self.color_to_cairo_rgba(color))

    def color_to_cairo_rgba(self, c, a=1):
        return c.red/65535.0, c.green/65535.0, c.blue/65535.0, a


    def get_fact_size(self, widget):
        """determine size and save calculated coordinates"""

        if not self.data or "id" not in self.data:
            return None
        fact = self.data
        pixmap = gtk.gdk.Pixmap(None, 10, 10, 1)
        context = pixmap.cairo_create()

        layout = context.create_layout()
        layout.set_font_description(self.label_font)
        x, y, width, height = widget.get_allocation()

        labels = {}

        cell_width = width - 45

        """ start time and end time at beginning of column """
        interval = fact["start_time"].strftime("%H:%M -")
        if fact["end_time"]:
            interval = "%s %s" % (interval, fact["end_time"].strftime("%H:%M"))
        labels["interval"] = (interval, self.col_padding, 2, -1)

        """ duration at the end """
        delta = stuff.format_duration(fact["delta"])
        layout.set_markup(delta)
        duration_w, duration_h = layout.get_pixel_size()
        labels["delta"] = (delta, cell_width - duration_w, 2, -1)


        """ activity, category, tags, description in middle """
        # we want our columns look aligned, so we will do fixed offset from
        # both sides, in letter length

        cell_start = widget.longest_interval
        cell_width = cell_width - widget.longest_interval - widget.longest_duration


        layout.set_markup(stuff.escape_pango(fact["name"]))
        label_w, label_h = layout.get_pixel_size()

        labels["activity"] = (stuff.escape_pango(fact["name"]), cell_start, 2, -1)
        labels["category"] = (" - <small>%s</small>" % stuff.escape_pango(fact["category"]),
                              cell_start + label_w, 2, -1)


        tag_cell_start = cell_start + widget.longest_activity_category
        tag_cell_end = cell_start + cell_width

        cell_height = label_h + 4

        cur_x, cur_y = tag_cell_start, 2
        if fact["tags"]:
            layout.set_font_description(self.tag_font)

            for i, tag in enumerate(fact["tags"]):
                tag_w, tag_h = Tag.tag_size(tag, layout)

                if i > 0 and cur_x + tag_w >= tag_cell_end:
                    cur_x = tag_cell_start
                    cur_y += tag_h + 4
                cur_x += tag_w + 4

            cell_height = max(cell_height, cur_y + tag_h + 4)

            labels["tags"] = (None, tag_cell_start, 2, tag_cell_end)

            layout.set_font_description(self.label_font)


        # see if we can fit in single line
        # if not, put description under activity
        if fact["description"]:
            description = "<small>%s</small>" % stuff.escape_pango(fact["description"])
            layout.set_markup(description)
            label_w, label_h = layout.get_pixel_size()

            x, y = cur_x, cur_y
            width = cell_start + cell_width - x

            if x + label_w > width:
                x = cell_start
                y = cell_height
                width = cell_width

            layout.set_width(width * pango.SCALE)
            label_w, label_h = layout.get_pixel_size()

            labels["description"] = (description, x, y, width * pango.SCALE)

            cell_height = y + label_h + 4

        self.labels[fact["id"]] = labels
        return (0, 0, 0, cell_height)


    def on_get_size (self, widget, cell_area):
        if "id" in self.data: # fact
            return self.get_fact_size(widget)
        else:
            if self.data["first"]:
                return (0, 0, 0, 25)
            else:
                return (0, 0, 0, 40)

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.0 [PHP 7 Update] [25.02.2019] maintained by KaizenLouie | C99Shell Github | Generation time: 0.0089 ]--