#!/usr/bin/env python
# based on sample code from Johannes Sasongko <sasongko@gmail.com>

import locale
import logging

logging.basicConfig(format='[%(asctime)s] %(levelname)s %(threadName)s %(name)s:%(lineno)d %(funcName)s %(message)s', level=logging.DEBUG)
logger = logging.getLogger(__name__)

from gi.repository import GLib, Gio, Gtk

class FileBrowser(Gtk.Window):

        def __init__(self):

                Gtk.Window.__init__(self)

                logger.info('')
                self.set_default_size(400, 400)

                # Columns:
                # 0 = the GFile object
                # 1 = filename
                # 2 = size

                self.model = Gtk.ListStore(Gio.File, str, str)

                view = Gtk.TreeView(self.model)
                view.set_rules_hint(True)
                view.connect('row-activated', self._row_activated)

                column = Gtk.TreeViewColumn("Filename", Gtk.CellRendererText(), text=1)
                view.append_column(column)

                render = Gtk.CellRendererText()
                render.props.xalign = 1
                column = Gtk.TreeViewColumn("Size", render, text=2)
                view.append_column(column)

                sw = Gtk.ScrolledWindow()
                sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
                sw.add(view)

                self.add(sw)
                self.connect('destroy', Gtk.main_quit)
                self.show_all()

        def _row_activated(self, view, path, column):
                logger.info('')
                model = view.get_model()
                row = model[path]
                if row[2] == '<dir>':
                        self.browse(row[0])
                else:
                        print "Activating %s" % row[0].get_parse_name()

        def browse(self, directory):

                logger.info(directory.get_uri())

                subdirs = []
                files = []

                infos = directory.enumerate_children('standard::*,time::*,access::*', Gio.FileQueryInfoFlags.NONE, None)
                for info in infos:
                        if info.get_is_hidden():
                                continue
                        name = info.get_name()
                        child = directory.get_child(name)
                        display = info.get_display_name()
                        sortname = GLib.utf8_collate_key_for_filename(GLib.utf8_casefold(display, -1), -1)
                        if info.get_file_type() == Gio.FileType.DIRECTORY:
                                subdirs.append((sortname, child, display + '/'))
                        else:
                                if info.get_attribute_boolean('access::can-execute'):
                                        display += '*'
                                size = round(info.get_size() / 1024)
                                size = locale.format_string(u"%d KiB", size, True)
                                files.append((sortname, child, display, size))

                subdirs.sort()
                files.sort()

                info = directory.query_info('standard::display-name', Gio.FileQueryInfoFlags.NONE, None)
                self.set_title(info.get_display_name())

                self.model.clear()
                parent = directory.get_parent()
                if parent:
                        self.model.append((parent, '../', "<dir>"))
                for sortname, child, display in subdirs:
                        self.model.append((child, display, "<dir>"))
                for sortname, child, display, size in files:
                        self.model.append((child, display, size))

                logger.info('done')

def run(path='/'):
        f = Gio.file_new_for_path(path)
        browser = FileBrowser()
        browser.browse(f)
        Gtk.main()

if __name__ == '__main__':
        import sys
        run(*sys.argv[1:])
