[Thunar-workers] CVS: design/ui ThunarFileInfo.py, NONE, 1.1 ThunarIconView.py, NONE, 1.1 ThunarListView.py, NONE, 1.1 ThunarMimeDatabase.py, NONE, 1.1 ThunarModel.py, NONE, 1.1 ThunarTreePane.py, NONE, 1.1 ChangeLog, 1.5, 1.6 Main.py, 1.1.1.1, 1.2 ThunarPropertiesDialog.py, 1.4, 1.5 ThunarView.py, 1.1.1.1, 1.2 ThunarWindow.py, 1.1.1.1, 1.2 thunar.ui, 1.1.1.1, 1.2

Benedikt Meurer benny at xfce.org
Sun Feb 27 19:13:52 CET 2005


Update of /var/cvs/thunar/design/ui
In directory espresso.foo-projects.org:/tmp/cvs-serv27506

Modified Files:
	ChangeLog Main.py ThunarPropertiesDialog.py ThunarView.py 
	ThunarWindow.py thunar.ui 
Added Files:
	ThunarFileInfo.py ThunarIconView.py ThunarListView.py 
	ThunarMimeDatabase.py ThunarModel.py ThunarTreePane.py 
Log Message:
2005-02-27	Benedikt Meurer <benny at xfce.org>

	* rox/: Use parts of the ROX Python libraries for the browser-like
	  prototype.
	* Main.py, ThunarFileInfo.py, ThunarListView.py, ThunarMimeDatabase.py,
	  ThunarModel.py, ThunarPropertiesDialog.py, ThunarTreePane.py,
	  ThunarView.py, ThunarWindow.py, thunar.ui: More work on the
	  browser-like prototype. It is now possible to browse your file system,
	  similar to the spatial prototype.




--- NEW FILE: ThunarFileInfo.py ---
#!/usr/bin/env python
# vi:set ts=4 sw=4 et ai nocindent:
#
# $Id: ThunarFileInfo.py,v 1.1 2005/02/27 18:13:49 benny Exp $
#
# Copyright (c) 2005 Benedikt Meurer <benny at xfce.org>
# All rights reserved.
#
# This program 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 2, or (at your option)
# any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#

import dircache, pwd, os, stat, time

import pygtk
pygtk.require('2.0')
import gobject
import gtk

from ThunarMimeDatabase import ThunarMimeDatabase

class ThunarFileInfo(gobject.GObject):
    def __init__(self, path):
        gobject.GObject.__init__(self)
        self.mimedb = ThunarMimeDatabase()

        # build up a normalized path
        self.path = ''
        for name in path.split('/'):
            if name:
                self.path += '/' + name
        if not self.path:
            self.path = '/'

        try:
            self.stat = os.stat(self.path)
        except OSError:
            self.stat = os.lstat(self.path)


    def render_icon(self, size):
        theme = gtk.icon_theme_get_default()
        icon = None
        try:
            if self.is_home(): icon = theme.load_icon('gnome-fs-home', size, 0)
        except:
            pass
        try:
            if not icon and self.is_desktop(): icon = theme.load_icon('gnome-fs-desktop', size, 0)
        except:
            pass
        try:
            if not icon and self.path == '/': icon = theme.load_icon('gnome-dev-harddisk', size, 0)
        except:
            pass
        if not icon:
            icon = self.get_mime_info().render_icon(size)
        return icon

    def is_home(self):
        home = pwd.getpwuid(os.getuid()).pw_dir
        return os.path.samefile(home, self.path)

    def is_desktop(self):
        home = pwd.getpwuid(os.getuid()).pw_dir
        return os.path.samefile(os.path.join(home, 'Desktop'), self.path)

    def get_mime_info(self):
        return self.mimedb.match(self.path)

    def get_name(self):
        name = os.path.basename(self.path)
        if not name:
            name = '/'
        return name

    def get_path(self):
        return self.path

    def get_visible_name(self):
        name = self.get_name()
        if name == '/':
            name = 'Filesystem'
        return name

    def get_size(self):
        if self.is_directory():
            return '-'
        return _humanize_size(self.stat[stat.ST_SIZE])

    def get_atime(self):
        return time.strftime('%x %X', time.localtime(self.stat[stat.ST_ATIME]))

    def get_mtime(self):
        return time.strftime('%x %X', time.localtime(self.stat[stat.ST_MTIME]))

    def is_directory(self):
        return stat.S_ISDIR(self.stat[stat.ST_MODE])

    def get_permissions(self):
        from stat import S_ISDIR, S_IMODE
        mode = self.stat[stat.ST_MODE]
        if S_ISDIR(mode):   result = 'd'
        else:               result = '-'
        mode = S_IMODE(mode)
        if mode & 0400: result += 'r'
        else:           result += '-'
        if mode & 0200: result += 'w'
        else:           result += '-'
        if mode & 0100: result += 'x'
        else:           result += '-'
        if mode & 0040: result += 'r'
        else:           result += '-'
        if mode & 0020: result += 'w'
        else:           result += '-'
        if mode & 0010: result += 'x'
        else:           result += '-'
        if mode & 0004: result += 'r'
        else:           result += '-'
        if mode & 0002: result += 'w'
        else:           result += '-'
        if mode & 0001: result += 'x'
        else:           result += '-'
        return result

    def get_parent(self):
        if self.path == '/':
            return None
        else:
            return ThunarFileInfo(self.path[0:self.path.rfind('/')])



def _humanize_size(size):
    if size > 1024 * 1024 * 1024:
        return '%.1f GB' % (size / (1024 * 1024 * 1024))
    elif size > 1024 * 1024:
        return '%.1f MB' % (size / (1024 * 1024))
    elif size > 1024:
        return '%.1f KB' % (size / 1024)
    else:
        return '%d B' % size




--- NEW FILE: ThunarIconView.py ---
#!/usr/bin/env python
# vi:set ts=4 sw=4 et ai nocindent:
#
# $Id: ThunarIconView.py,v 1.1 2005/02/27 18:13:49 benny Exp $
#
# Copyright (c) 2005 Benedikt Meurer <benny at xfce.org>
# All rights reserved.
#
# This program 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 2, or (at your option)
# any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#

import pygtk
pygtk.require('2.0')
import gobject
import gtk

import pyexo
pyexo.require('0.3')
import exo

from ThunarFileInfo import ThunarFileInfo
from ThunarModel import ThunarModel
from ThunarView import ThunarView

signals_registered = False

class ThunarIconView(exo.IconView, ThunarView):
    def __init__(self, dir_info):
        exo.IconView.__init__(self, ThunarModel(dir_info))
        ThunarView.__init__(self)

        # register signals
        global signals_registered
        if not signals_registered:
            gobject.signal_new('activated', self, gobject.SIGNAL_RUN_LAST, \
                               gobject.TYPE_NONE, [ThunarFileInfo])
            gobject.signal_new('context-menu', self, gobject.SIGNAL_RUN_LAST, \
                               gobject.TYPE_NONE, [])
            signals_registered = True

        self.set_text_column(ThunarModel.COLUMN_NAME)
        self.set_pixbuf_column(ThunarModel.COLUMN_ICONHUGE)

        self.set_selection_mode(gtk.SELECTION_MULTIPLE)

        self.connect('item-activated', lambda self, path: self._activated(path))
        self.connect('button-press-event', lambda self, event: self._button_press_event(event))
        

    def get_selected_files(self):
        paths = self.get_selected_items()
        list = []
        for path in paths:
            iter = self.get_model().get_iter(path)
            list.append(self.get_model().get(iter, ThunarModel.COLUMN_FILEINFO)[0])
        return list


    def _activated(self, path):
        iter = self.get_model().get_iter(path)
        info = self.get_model().get(iter, ThunarModel.COLUMN_FILEINFO)[0]
        if info.is_directory():
            self.activated(info)


    def _button_press_event(self, event):
        if event.button == 3 and event.type == gtk.gdk.BUTTON_PRESS:
            path = self.get_path_at_pos(int(event.x), int(event.y))
            if path:
                if not self.path_is_selected(path):
                    self.unselect_all()
                    self.select_path(path)
                self.grab_focus()
                self.context_menu()
            return True
        elif (event.button == 1 or event.button == 2) and event.type == gtk.gdk._2BUTTON_PRESS:
            path = self.get_path_at_pos(int(event.x), int(event.y))
            if path:
                iter = self.get_model().get_iter(path)
                if event.button == 1:
                    self.unselect_all()
                    self.select_path(path)
                info = self.get_model().get(iter, ThunarModel.COLUMN_FILEINFO)[0]
                if info.is_directory():
                    self.activated(info)
                if event.button == 2 or (event.state & gtk.gdk.SHIFT_MASK) != 0:
                    self.get_toplevel().destroy()
            return True
        return False

--- NEW FILE: ThunarListView.py ---
#!/usr/bin/env python
# vi:set ts=4 sw=4 et ai nocindent:
#
# $Id: ThunarListView.py,v 1.1 2005/02/27 18:13:49 benny Exp $
#
# Copyright (c) 2005 Benedikt Meurer <benny at xfce.org>
# All rights reserved.
#
# This program 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 2, or (at your option)
# any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#

import pygtk
pygtk.require('2.0')
import gobject
import gtk

from ThunarFileInfo import ThunarFileInfo
from ThunarModel import ThunarModel
from ThunarView import ThunarView

signals_registered = False

class ThunarListView(gtk.TreeView, ThunarView):
    def __init__(self, dir_info):
        gtk.TreeView.__init__(self)
        ThunarView.__init__(self)

        # register signals
        global signals_registered
        if not signals_registered:
            try:
                gobject.signal_new('activated', self, gobject.SIGNAL_RUN_LAST, \
                                   gobject.TYPE_NONE, [ThunarFileInfo])
            except:
                pass
            try:
                gobject.signal_new('context-menu', self, gobject.SIGNAL_RUN_LAST, \
                                   gobject.TYPE_NONE, [])
            except:
                pass
            try:
                gobject.signal_new('selection-changed', self, gobject.SIGNAL_RUN_LAST, \
                                   gobject.TYPE_NONE, [])
            except:
                pass
            signals_registered = True

        self.set_model(ThunarModel(dir_info))

        column = gtk.TreeViewColumn('Name')
        renderer = gtk.CellRendererPixbuf()
        column.pack_start(renderer, False)
        column.add_attribute(renderer, 'pixbuf', ThunarModel.COLUMN_ICON)
        renderer = gtk.CellRendererText()
        column.pack_start(renderer, True)
        column.add_attribute(renderer, 'text', ThunarModel.COLUMN_NAME)
        self.append_column(column)
        self.set_expander_column(column)

        column = gtk.TreeViewColumn('Size')
        renderer = gtk.CellRendererText()
        renderer.set_property('xalign', 1.0)
        column.pack_start(renderer, True)
        column.add_attribute(renderer, 'text', ThunarModel.COLUMN_SIZE)
        self.append_column(column)

        column = gtk.TreeViewColumn('Modified')
        renderer = gtk.CellRendererText()
        column.pack_start(renderer, False)
        column.add_attribute(renderer, 'text', ThunarModel.COLUMN_MTIME)
        self.append_column(column)

        column = gtk.TreeViewColumn('Kind')
        renderer = gtk.CellRendererText()
        column.pack_start(renderer, False)
        column.add_attribute(renderer, 'text', ThunarModel.COLUMN_KIND)
        self.append_column(column)

        self.set_rules_hint(True)
        self.set_headers_clickable(True)

        self.get_selection().set_mode(gtk.SELECTION_MULTIPLE)

        self.connect('row-activated', lambda tree, path, column: self._activated(path))
        self.connect('button-press-event', lambda tree, event: self._button_press_event(event))
        self.get_selection().connect('changed', lambda selection: self.selection_changed())


    def get_selected_files(self):
        selection = self.get_selection()
        model, paths = selection.get_selected_rows()
        list = []
        for path in paths:
            iter = model.get_iter(path)
            list.append(model.get(iter, ThunarModel.COLUMN_FILEINFO)[0])
        return list


    def select_all(self):
        self.get_selection().select_all()


    def _activated(self, path):
        iter = self.get_model().get_iter(path)
        info = self.get_model().get(iter, ThunarModel.COLUMN_FILEINFO)[0]
        if info.is_directory():
            self.activated(info)


    def _button_press_event(self, event):
        if event.button == 3 and event.type == gtk.gdk.BUTTON_PRESS:
            path, column, x, y = self.get_path_at_pos(int(event.x), int(event.y))
            if path:
                selection = self.get_selection()
                if not selection.path_is_selected(path):
                    selection.unselect_all()
                    selection.select_path(path)
                self.grab_focus()
                self.context_menu()
            return True
        elif (event.button == 1 or event.button == 2) and event.type == gtk.gdk._2BUTTON_PRESS:
            path, column, x, y = self.get_path_at_pos(int(event.x), int(event.y))
            if path:
                iter = self.get_model().get_iter(path)
                if event.button == 1:
                    selection = self.get_selection()
                    selection.unselect_all()
                    selection.select_path(path)
                info = self.get_model().get(iter, ThunarModel.COLUMN_FILEINFO)[0]
                if info.is_directory():
                    self.activated(info)
                if event.button == 2 or (event.state & gtk.gdk.SHIFT_MASK) != 0:
                    self.get_toplevel().destroy()
            return True
        return False

--- NEW FILE: ThunarMimeDatabase.py ---
#!/usr/bin/env python
# vi:set ts=4 sw=4 et ai nocindent:
#
# $Id: ThunarMimeDatabase.py,v 1.1 2005/02/27 18:13:49 benny Exp $
#
# Copyright (c) 2005 Benedikt Meurer <benny at xfce.org>
# All rights reserved.
#
# This program 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 2, or (at your option)
# any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#

import pygtk
pygtk.require('2.0')
import gobject
import gtk

import rox, rox.mime


class ThunarMimeDatabase:
    def match(self, path):
        type = rox.mime.get_type(path)
        return ThunarMimeInfo(type)


class ThunarMimeInfo:
    def __init__(self, type):
        self.theme = gtk.icon_theme_get_default()
        self.type = type

    def get_comment(self):
        return self.type.get_comment()

    def render_icon(self, size):
        type = '%s' % self.type
        try:
            name = 'mime-' + type.replace('/', ':')
            icon = self.theme.load_icon(name, size, 0)
        except gobject.GError:
            try:
                name = 'gnome-mime-' + type.replace('/', '-')
                icon = self.theme.load_icon(name, size, 0)
            except gobject.GError:
                try:
                    name = 'mime-' + type.split('/')[0]
                    icon = self.theme.load_icon(name, size, 0)
                except gobject.GError:
                    try:
                        name = 'gnome-mime-' + type.split('/')[0]
                        icon = self.theme.load_icon(name, size, 0)
                    except gobject.GError:
                        name = 'gnome-mime-application-octet-stream'
                        icon = self.theme.load_icon(name, size, 0)
        return icon

--- NEW FILE: ThunarModel.py ---
#!/usr/bin/env python
# vi:set ts=4 sw=4 et ai nocindent:
#
# $Id: ThunarModel.py,v 1.1 2005/02/27 18:13:49 benny Exp $
#
# Copyright (c) 2005 Benedikt Meurer <benny at xfce.org>
# All rights reserved.
#
# This program 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 2, or (at your option)
# any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#

import dircache, os

import pygtk
pygtk.require('2.0')
import gobject
import gtk

from ThunarFileInfo import ThunarFileInfo

class ThunarModel(gtk.ListStore):
    COLUMN_ICON     = 0
    COLUMN_ICONHUGE = 1
    COLUMN_NAME     = 2
    COLUMN_SIZE     = 3
    COLUMN_MTIME    = 4
    COLUMN_KIND     = 5
    COLUMN_FILEINFO = 6

    def __init__(self, dir_info):
        gtk.ListStore.__init__(self, gtk.gdk.Pixbuf,\
                               gtk.gdk.Pixbuf, \
                               gobject.TYPE_STRING, \
                               gobject.TYPE_STRING, \
                               gobject.TYPE_STRING, \
                               gobject.TYPE_STRING, \
                               ThunarFileInfo)

        self.set_default_sort_func(self._compare)
        self.set_sort_column_id(-1, gtk.SORT_ASCENDING)

        for name in dircache.listdir(dir_info.get_path()):
            if name.startswith('.'):
                continue

            file_info = ThunarFileInfo(os.path.join(dir_info.get_path(), name))
            mime_info = file_info.get_mime_info()

            self.append([
                file_info.render_icon(16),
                file_info.render_icon(48),
                file_info.get_visible_name(),
                file_info.get_size(),
                file_info.get_mtime(),
                mime_info.get_comment(),
                file_info
            ])


    def _compare(self, model, iter1, iter2):
        info1 = self.get(iter1, self.COLUMN_FILEINFO)[0]
        info2 = self.get(iter2, self.COLUMN_FILEINFO)[0]

        if info1 and not info2:
            return -1
        elif not info1 and info2:
            return 1

        if info1.is_directory() and not info2.is_directory():
            return -1
        elif info2.is_directory() and not info1.is_directory():
            return 1

        if info1.get_visible_name() < info2.get_visible_name():
            return -1
        elif info1.get_visible_name() > info2.get_visible_name():
            return 1

        return 0

--- NEW FILE: ThunarTreePane.py ---
#!/usr/bin/env python
# vi:set ts=4 sw=4 et ai nocindent:
#
# $Id: ThunarTreePane.py,v 1.1 2005/02/27 18:13:49 benny Exp $
#
# Copyright (c) 2005 Benedikt Meurer <benny at xfce.org>
# All rights reserved.
#
# This program 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 2, or (at your option)
# any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#

import dircache, os

import pygtk
pygtk.require('2.0')
import gobject
import gtk

from ThunarFileInfo import ThunarFileInfo

signals_registered = False

class ThunarTreePane(gtk.TreeView):
    COLUMN_NAME = 0
    COLUMN_ICON = 1
    COLUMN_BOLD = 2
    COLUMN_INFO = 3

    ICON_SIZE = 24

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

        # register signals
        global signals_registered
        if not signals_registered:
            gobject.signal_new('directory-changed', self, gobject.SIGNAL_RUN_LAST, \
                               gobject.TYPE_NONE, [ThunarFileInfo])
            signals_registered = True

        self.model = gtk.TreeStore(gobject.TYPE_STRING, gtk.gdk.Pixbuf, gobject.TYPE_INT, ThunarFileInfo)

        info = ThunarFileInfo(os.getenv('HOME'))
        row = self.model.append(None, ['Home Folder', info.render_icon(ThunarTreePane.ICON_SIZE), 800, info])
        self.model.append(row, [None, None, 0, None])
        self.home_path = self.model.get_path(row)

        theme = gtk.icon_theme_get_default()
        try:
            icon = theme.load_icon('gnome-dev-cdrom', ThunarTreePane.ICON_SIZE, 0)
        except:
            icon = None
        row = self.model.append(None, ['Removable Media', icon, 800, None])
        self.model.append(row, [None, None, 0, None])

        info = ThunarFileInfo('/')
        row = self.model.append(None, ['Filesystem', info.render_icon(ThunarTreePane.ICON_SIZE), 800, info])
        self.model.append(row, [None, None, 0, None])
        self.fs_path = self.model.get_path(row)

        self.set_model(self.model)

        column = gtk.TreeViewColumn('Name')
        renderer = gtk.CellRendererPixbuf()
        column.pack_start(renderer, False)
        column.add_attribute(renderer, 'pixbuf', ThunarTreePane.COLUMN_ICON)
        renderer = gtk.CellRendererText()
        column.pack_start(renderer, True)
        column.add_attribute(renderer, 'text', ThunarTreePane.COLUMN_NAME)
        column.add_attribute(renderer, 'weight', ThunarTreePane.COLUMN_BOLD)
        self.append_column(column)
        self.set_expander_column(column)

        self.set_rules_hint(False)
        self.set_headers_visible(False)

        self.get_selection().connect('changed', lambda ign: self._selection_changed())
        self.connect('row-expanded', lambda self, iter, path: self._row_expanded(iter, path))


    def _row_expanded(self, iter, path):
        if self.model.iter_n_children(iter) != 1:
            return
        info = self.model.get(iter, ThunarTreePane.COLUMN_INFO)[0]
        if not info:
            return
        child = self.model.iter_nth_child(iter, 0)
        info = self.model.get(child, ThunarTreePane.COLUMN_INFO)[0]
        if info:
            return
        parent_info = self.model.get(iter, ThunarTreePane.COLUMN_INFO)[0]
        names = dircache.listdir(parent_info.get_path())[:]
        names.sort()
        for name in names:
            if name.startswith('.'):
                continue
            
            file_info = ThunarFileInfo(os.path.join(parent_info.get_path(), name))
            if not file_info.is_directory():
                continue

            row = self.model.append(iter, [file_info.get_visible_name(), file_info.render_icon(ThunarTreePane.ICON_SIZE), 400, file_info])
            self.model.append(row, [None, None, 0, None])

        self.model.remove(child)


    def _selection_changed(self):
        model, iter = self.get_selection().get_selected()
        if iter:
            info = self.model.get(iter, self.COLUMN_INFO)[0]
            self.emit('directory-changed', info)
        

    def select_by_info(self, info):
        tpath = self.fs_path

        components = []
        tmp = info
        while tmp:
            if tmp.get_path() == ThunarFileInfo(os.getenv('HOME')).get_path():
                tpath = self.home_path
                break
            elif tmp.get_path() == '/':
                break
            components.append(tmp)
            tmp = tmp.get_parent()

        components.reverse()

        for c in components:
            self.expand_to_path(tpath)
            parent_iter = self.model.get_iter(tpath)
            child_iter = self.model.iter_children(parent_iter)
            while child_iter:
                child_info = self.model.get(child_iter, self.COLUMN_INFO)[0]
                if child_info.get_path() == c.get_path():
                    break
                child_iter = self.model.iter_next(child_iter)

            if not child_iter:
                return
            tpath = self.model.get_path(child_iter)

        self.get_selection().select_path(tpath)
        self.scroll_to_cell(tpath)

Index: ChangeLog
===================================================================
RCS file: /var/cvs/thunar/design/ui/ChangeLog,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- ChangeLog	21 Feb 2005 20:26:59 -0000	1.5
+++ ChangeLog	27 Feb 2005 18:13:49 -0000	1.6
@@ -1,3 +1,13 @@
+2005-02-27	Benedikt Meurer <benny at xfce.org>
+
+	* rox/: Use parts of the ROX Python libraries for the browser-like
+	  prototype.
+	* Main.py, ThunarFileInfo.py, ThunarListView.py, ThunarMimeDatabase.py,
+	  ThunarModel.py, ThunarPropertiesDialog.py, ThunarTreePane.py,
+	  ThunarView.py, ThunarWindow.py, thunar.ui: More work on the
+	  browser-like prototype. It is now possible to browse your file system,
+	  similar to the spatial prototype.
+
 2005-02-21	Benedikt Meurer <benny at xfce.org>
 
 	* spatial/: More work on the spatial prototype, including separate

Index: Main.py
===================================================================
RCS file: /var/cvs/thunar/design/ui/Main.py,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- Main.py	14 Feb 2005 20:45:05 -0000	1.1.1.1
+++ Main.py	27 Feb 2005 18:13:49 -0000	1.2
@@ -22,15 +22,18 @@
 # 02111-1307, USA.
 #
 
+import os
+
 import pygtk
 pygtk.require('2.0')
 import gtk
 
+from ThunarFileInfo import ThunarFileInfo
 from ThunarWindow import ThunarWindow
 
 class Main:
   def __init__(self):
-    self.window = ThunarWindow()
+    self.window = ThunarWindow(ThunarFileInfo(os.getcwd()))
     self.window.connect('destroy', gtk.main_quit)
 
   def run(self):

Index: ThunarPropertiesDialog.py
===================================================================
RCS file: /var/cvs/thunar/design/ui/ThunarPropertiesDialog.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- ThunarPropertiesDialog.py	17 Feb 2005 16:07:19 -0000	1.4
+++ ThunarPropertiesDialog.py	27 Feb 2005 18:13:49 -0000	1.5
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-# vi:set ts=2 sw=2 et ai nocindent:
+# vi:set ts=4 sw=4 et ai nocindent:
 #
 # $Id$
 #
@@ -27,439 +27,382 @@
 import gobject
 import gtk
 
-class ThunarPropertiesDialog(gtk.Dialog):
-  def __init__(self, parent):
-    gtk.Dialog.__init__(self, 'foo.mp3 Properties', parent, gtk.DIALOG_DESTROY_WITH_PARENT,
-                        (gtk.STOCK_HELP, gtk.RESPONSE_HELP, gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
-    self.set_has_separator(False)
-    self.connect('response', lambda self, response: self.destroy())
-
-    tooltips = gtk.Tooltips()
-
-    notebook = gtk.Notebook()
-    self.vbox.pack_start(notebook, True, True, 0)
-    notebook.show()
-
-
-    ###
-    ### General
-    ###
-    table = gtk.Table(2, 4, False)
-    table.set_col_spacings(12)
-    table.set_row_spacings(6)
-    table.set_border_width(6)
-    label = gtk.Label('General')
-    notebook.append_page(table, label)
-    label.show()
-    table.show()
+from ThunarFileInfo import ThunarFileInfo
 
-    row = 0
+class ThunarPropertiesDialog(gtk.Dialog):
+    def __init__(self, parent, info):
+        gtk.Dialog.__init__(self, info.get_visible_name() + ' Info', parent,
+                            gtk.DIALOG_DESTROY_WITH_PARENT,
+                            (gtk.STOCK_HELP, gtk.RESPONSE_HELP,
+                             gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
+        self.set_has_separator(False)
+        self.set_icon(info.render_icon(48))
+        self.connect('response', lambda self, response: self.destroy())
 
-    ### {
-    box = gtk.HBox(False, 6)
-    table.attach(box, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    box.show()
+        tooltips = gtk.Tooltips()
 
-    image = gtk.image_new_from_stock(gtk.STOCK_NEW, gtk.ICON_SIZE_DIALOG)
-    image.set_alignment(0.5, 0.5)
-    box.pack_start(image, False, True, 0)
-    image.show()
+        notebook = gtk.Notebook()
+        self.vbox.pack_start(notebook, True, True, 0)
+        notebook.show()
 
-    label = gtk.Label('<b>Name:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    box.pack_start(label, True, True, 0)
-    label.show()
 
-    entry = gtk.Entry()
-    entry.set_text('foo.mp3')
-    table.attach(entry, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
-    entry.show()
-    row += 1 ### }
+        ###
+        ### General
+        ###
+        table = gtk.Table(2, 4, False)
+        table.set_col_spacings(12)
+        table.set_row_spacings(6)
+        table.set_border_width(6)
+        label = gtk.Label('General')
+        notebook.append_page(table, label)
+        label.show()
+        table.show()
 
-    ### {
-    align = gtk.Alignment(1.0, 1.0, 1.0, 1.0)
-    align.set_size_request(-1, 12)
-    table.attach(align, 0, 1, row, row + 1, 0, 0)
-    align.show()
-    row += 1 ### }
+        row = 0
 
-    ### {
-    label = gtk.Label('<b>Kind:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
+        ### {
+        box = gtk.HBox(False, 6)
+        table.attach(box, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+        box.show()
 
-    ebox = gtk.EventBox()
-    tooltips.set_tip(ebox, 'audio/x-mp3')
-    table.attach(ebox, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
-    ebox.show()
+        image = gtk.Image()
+        image.set_from_pixbuf(info.render_icon(48))
+        image.set_alignment(0.5, 0.5)
+        box.pack_start(image, False, True, 0)
+        image.show()
 
-    label = gtk.Label('MP3 audio')
-    label.set_alignment(0.0, 0.5)
-    label.set_selectable(True)
-    ebox.add(label)
-    label.show()
-    row += 1 ### }
+        label = gtk.Label('<b>Name:</b>')
+        label.set_use_markup(True)
+        label.set_alignment(1.0, 0.5)
+        box.pack_start(label, True, True, 0)
+        label.show()
 
-    ### {
-    label = gtk.Label('<b>Open With:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
+        entry = gtk.Entry()
+        entry.set_text(info.get_visible_name())
+        table.attach(entry, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
+        entry.show()
+        row += 1 ### }
 
-    hbox = gtk.HBox(False, 6)
-    table.attach(hbox, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
-    hbox.show()
+        ### {
+        align = gtk.Alignment(1.0, 1.0, 1.0, 1.0)
+        align.set_size_request(-1, 12)
+        table.attach(align, 0, 1, row, row + 1, 0, 0)
+        align.show()
+        row += 1 ### }
 
-    image = gtk.image_new_from_stock(gtk.STOCK_CDROM, gtk.ICON_SIZE_MENU)
-    hbox.pack_start(image, False, False, 0)
-    image.show()
+        ### {
+        label = gtk.Label('<b>Kind:</b>')
+        label.set_use_markup(True)
+        label.set_alignment(1.0, 0.5)
+        table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+        label.show()
 
-    label = gtk.Label('Xfce Media Player')
-    label.set_alignment(0.0, 0.5)
-    label.set_selectable(True)
-    hbox.pack_start(label, False, True, 0)
-    label.show()
+        label = gtk.Label(info.get_mime_info().get_comment())
+        label.set_alignment(0.0, 0.5)
+        label.set_selectable(True)
+        table.attach(label, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
+        label.show()
+        row += 1 ### }
 
-    button = gtk.Button('Ch_ange')
-    hbox.pack_end(button, False, False, 0)
-    button.show()
-    row += 1 ### }
+        if not info.is_directory():
+            ### {
+            label = gtk.Label('<b>Open With:</b>')
+            label.set_use_markup(True)
+            label.set_alignment(1.0, 0.5)
+            table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+            label.show()
 
-    ### {
-    align = gtk.Alignment(1.0, 1.0, 1.0, 1.0)
-    align.set_size_request(-1, 12)
-    table.attach(align, 0, 1, row, row + 1, 0, 0)
-    align.show()
-    row += 1 ### }
+            hbox = gtk.HBox(False, 6)
+            table.attach(hbox, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
+            hbox.show()
 
-    ### {
-    label = gtk.Label('<b>Location:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
+            image = gtk.image_new_from_stock(gtk.STOCK_CDROM, gtk.ICON_SIZE_MENU)
+            hbox.pack_start(image, False, False, 0)
+            image.show()
 
-    label = gtk.Label('file:///usr/home/bar')
-    label.set_alignment(0.0, 0.5)
-    label.set_selectable(True)
-    table.attach(label, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
-    label.show()
-    row += 1 ### }
+            label = gtk.Label('Xfce Media Player')
+            label.set_alignment(0.0, 0.5)
+            label.set_selectable(True)
+            hbox.pack_start(label, False, True, 0)
+            label.show()
 
-    ### {
-    label = gtk.Label('<b>Size:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
+            button = gtk.Button('Ch_ange')
+            hbox.pack_end(button, False, False, 0)
+            button.show()
+            row += 1 ### }
 
-    label = gtk.Label('3.5 MB')
-    label.set_alignment(0.0, 0.5)
-    label.set_selectable(True)
-    table.attach(label, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
-    label.show()
-    row += 1 ### }
+        ### {
+        align = gtk.Alignment(1.0, 1.0, 1.0, 1.0)
+        align.set_size_request(-1, 12)
+        table.attach(align, 0, 1, row, row + 1, 0, 0)
+        align.show()
+        row += 1 ### }
 
-    ### {
-    label = gtk.Label('<b>Permissions:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
+        ### {
+        label = gtk.Label('<b>Location:</b>')
+        label.set_use_markup(True)
+        label.set_alignment(1.0, 0.5)
+        table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+        label.show()
 
-    label = gtk.Label('-rw-r--r--')
-    label.set_alignment(0.0, 0.5)
-    label.set_selectable(True)
-    table.attach(label, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
-    label.show()
-    row += 1 ### }
+        label = gtk.Label(info.get_parent().get_visible_name())
+        label.set_alignment(0.0, 0.5)
+        label.set_selectable(True)
+        table.attach(label, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
+        label.show()
+        row += 1 ### }
 
-    ### {
-    align = gtk.Alignment(1.0, 1.0, 1.0, 1.0)
-    align.set_size_request(-1, 12)
-    table.attach(align, 0, 1, row, row + 1, 0, 0)
-    align.show()
-    row += 1 ### }
+        if not info.is_directory():
+            ### {
+            label = gtk.Label('<b>Size:</b>')
+            label.set_use_markup(True)
+            label.set_alignment(1.0, 0.5)
+            table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+            label.show()
 
-    ### {
-    label = gtk.Label('<b>Modified:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
+            label = gtk.Label(info.get_size())
+            label.set_alignment(0.0, 0.5)
+            label.set_selectable(True)
+            table.attach(label, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
+            label.show()
+            row += 1 ### }
 
-    label = gtk.Label('2005-02-16 00:20')
-    label.set_alignment(0.0, 0.5)
-    label.set_selectable(True)
-    table.attach(label, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
-    label.show()
-    row += 1 ### }
+        ### {
+        label = gtk.Label('<b>Permissions:</b>')
+        label.set_use_markup(True)
+        label.set_alignment(1.0, 0.5)
+        table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+        label.show()
 
-    ### {
-    label = gtk.Label('<b>Accessed:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
+        label = gtk.Label(info.get_permissions())
+        label.set_alignment(0.0, 0.5)
+        label.set_selectable(True)
+        table.attach(label, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
+        label.show()
+        row += 1 ### }
 
-    label = gtk.Label('2005-02-16 00:20')
-    label.set_alignment(0.0, 0.5)
-    label.set_selectable(True)
-    table.attach(label, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
-    label.show()
-    row += 1 ### }
+        ### {
+        align = gtk.Alignment(1.0, 1.0, 1.0, 1.0)
+        align.set_size_request(-1, 12)
+        table.attach(align, 0, 1, row, row + 1, 0, 0)
+        align.show()
+        row += 1 ### }
 
+        ### {
+        label = gtk.Label('<b>Modified:</b>')
+        label.set_use_markup(True)
+        label.set_alignment(1.0, 0.5)
+        table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+        label.show()
 
+        label = gtk.Label(info.get_mtime())
+        label.set_alignment(0.0, 0.5)
+        label.set_selectable(True)
+        table.attach(label, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
+        label.show()
+        row += 1 ### }
 
-    ###
-    ### Permissions
-    ###
-    table = gtk.Table(4, 5, False)
-    table.set_col_spacings(12)
-    table.set_row_spacings(6)
-    table.set_border_width(6)
-    label = gtk.Label('Permissions')
-    notebook.append_page(table, label)
-    label.show()
-    table.show()
+        ### {
+        label = gtk.Label('<b>Accessed:</b>')
+        label.set_use_markup(True)
+        label.set_alignment(1.0, 0.5)
+        table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+        label.show()
 
-    row = 0
+        label = gtk.Label(info.get_atime())
+        label.set_alignment(0.0, 0.5)
+        label.set_selectable(True)
+        table.attach(label, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
+        label.show()
+        row += 1 ### }
 
-    ### {
-    label = gtk.Label('<b>File Owner:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
 
-    label = gtk.Label('Benedikt Meurer (bmeurer)')
-    label.set_alignment(0.0, 0.5)
-    table.attach(label, 1, 4, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
-    row += 1 ### }
 
-    ### {
-    label = gtk.Label('<b>File Group:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
-
-    align = gtk.Alignment(0.0, 0.5, 0.0, 0.0)
-    table.attach(align, 1, 4, row, row + 1, gtk.FILL, gtk.FILL)
-    align.show()
+        ###
+        ### Permissions
+        ###
+        table = gtk.Table(4, 5, False)
+        table.set_col_spacings(12)
+        table.set_row_spacings(6)
+        table.set_border_width(6)
+        label = gtk.Label('Permissions')
+        notebook.append_page(table, label)
+        label.show()
+        table.show()
 
-    combo = gtk.combo_box_new_text()
-    combo.append_text('staff')
-    combo.append_text('users')
-    combo.append_text('wheel')
-    combo.append_text('www')
-    combo.set_active(1)
-    align.add(combo)
-    combo.show()
-    row += 1 ### }
+        row = 0
 
-    ### {
-    sep = gtk.HSeparator()
-    table.attach(sep, 0, 4, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
-    sep.show()
-    row += 1 ### }
+        ### {
+        label = gtk.Label('<b>File Owner:</b>')
+        label.set_use_markup(True)
+        label.set_alignment(1.0, 0.5)
+        table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+        label.show()
 
-    ### {
-    label = gtk.Label('<b>Owner:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
+        label = gtk.Label('Benedikt Meurer (bmeurer)')
+        label.set_alignment(0.0, 0.5)
+        table.attach(label, 1, 4, row, row + 1, gtk.FILL, gtk.FILL)
+        label.show()
+        row += 1 ### }
 
-    button = gtk.CheckButton('Read')
-    table.attach(button, 1, 2, row, row + 1, gtk.FILL, gtk.FILL)
-    button.show()
+        ### {
+        label = gtk.Label('<b>File Group:</b>')
+        label.set_use_markup(True)
+        label.set_alignment(1.0, 0.5)
+        table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+        label.show()
 
-    button = gtk.CheckButton('Write')
-    table.attach(button, 2, 3, row, row + 1, gtk.FILL, gtk.FILL)
-    button.show()
+        align = gtk.Alignment(0.0, 0.5, 0.0, 0.0)
+        table.attach(align, 1, 4, row, row + 1, gtk.FILL, gtk.FILL)
+        align.show()
 
-    button = gtk.CheckButton('Execute')
-    table.attach(button, 3, 4, row, row + 1, gtk.FILL, gtk.FILL)
-    button.show()
-    row += 1 ### }
+        combo = gtk.combo_box_new_text()
+        combo.append_text('staff')
+        combo.append_text('users')
+        combo.append_text('wheel')
+        combo.append_text('www')
+        combo.set_active(1)
+        align.add(combo)
+        combo.show()
+        row += 1 ### }
 
-    ### {
-    label = gtk.Label('<b>Group:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
+        ### {
+        sep = gtk.HSeparator()
+        table.attach(sep, 0, 4, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
+        sep.show()
+        row += 1 ### }
 
-    button = gtk.CheckButton('Read')
-    table.attach(button, 1, 2, row, row + 1, gtk.FILL, gtk.FILL)
-    button.show()
+        ### {
+        label = gtk.Label('<b>Owner:</b>')
+        label.set_use_markup(True)
+        label.set_alignment(1.0, 0.5)
+        table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+        label.show()
 
-    button = gtk.CheckButton('Write')
-    table.attach(button, 2, 3, row, row + 1, gtk.FILL, gtk.FILL)
-    button.show()
+        button = gtk.CheckButton('Read')
+        table.attach(button, 1, 2, row, row + 1, gtk.FILL, gtk.FILL)
+        button.show()
 
-    button = gtk.CheckButton('Execute')
-    table.attach(button, 3, 4, row, row + 1, gtk.FILL, gtk.FILL)
-    button.show()
-    row += 1 ### }
+        button = gtk.CheckButton('Write')
+        table.attach(button, 2, 3, row, row + 1, gtk.FILL, gtk.FILL)
+        button.show()
 
-    ### {
-    label = gtk.Label('<b>Others:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
+        button = gtk.CheckButton('Execute')
+        table.attach(button, 3, 4, row, row + 1, gtk.FILL, gtk.FILL)
+        button.show()
+        row += 1 ### }
 
-    button = gtk.CheckButton('Read')
-    table.attach(button, 1, 2, row, row + 1, gtk.FILL, gtk.FILL)
-    button.show()
+        ### {
+        label = gtk.Label('<b>Group:</b>')
+        label.set_use_markup(True)
+        label.set_alignment(1.0, 0.5)
+        table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+        label.show()
 
-    button = gtk.CheckButton('Write')
-    table.attach(button, 2, 3, row, row + 1, gtk.FILL, gtk.FILL)
-    button.show()
+        button = gtk.CheckButton('Read')
+        table.attach(button, 1, 2, row, row + 1, gtk.FILL, gtk.FILL)
+        button.show()
 
-    button = gtk.CheckButton('Execute')
-    table.attach(button, 3, 4, row, row + 1, gtk.FILL, gtk.FILL)
-    button.show()
-    row += 1 ### }
+        button = gtk.CheckButton('Write')
+        table.attach(button, 2, 3, row, row + 1, gtk.FILL, gtk.FILL)
+        button.show()
 
-    ### {
-    sep = gtk.HSeparator()
-    table.attach(sep, 0, 4, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
-    sep.show()
-    row += 1 ### }
- 
-    ### {
-    label = gtk.Label('<b>Special flags:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
+        button = gtk.CheckButton('Execute')
+        table.attach(button, 3, 4, row, row + 1, gtk.FILL, gtk.FILL)
+        button.show()
+        row += 1 ### }
 
-    button = gtk.CheckButton('Set user ID')
-    table.attach(button, 1, 4, row, row + 1, gtk.FILL, gtk.FILL)
-    button.show()
-    row += 1 ### }
+        ### {
+        label = gtk.Label('<b>Others:</b>')
+        label.set_use_markup(True)
+        label.set_alignment(1.0, 0.5)
+        table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+        label.show()
 
-    ### {
-    button = gtk.CheckButton('Set group ID')
-    table.attach(button, 1, 4, row, row + 1, gtk.FILL, gtk.FILL)
-    button.show()
-    row += 1 ### }
+        button = gtk.CheckButton('Read')
+        table.attach(button, 1, 2, row, row + 1, gtk.FILL, gtk.FILL)
+        button.show()
 
-    ### {
-    button = gtk.CheckButton('Sticky')
-    table.attach(button, 1, 4, row, row + 1, gtk.FILL, gtk.FILL)
-    button.show()
-    row += 1 ### }
+        button = gtk.CheckButton('Write')
+        table.attach(button, 2, 3, row, row + 1, gtk.FILL, gtk.FILL)
+        button.show()
 
-    ### {
-    sep = gtk.HSeparator()
-    table.attach(sep, 0, 4, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
-    sep.show()
-    row += 1 ### }
+        button = gtk.CheckButton('Execute')
+        table.attach(button, 3, 4, row, row + 1, gtk.FILL, gtk.FILL)
+        button.show()
+        row += 1 ### }
 
-    ### {
-    label = gtk.Label('<b>Text view:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
+        ### {
+        sep = gtk.HSeparator()
+        table.attach(sep, 0, 4, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
+        sep.show()
+        row += 1 ### }
+     
+        ### {
+        label = gtk.Label('<b>Special flags:</b>')
+        label.set_use_markup(True)
+        label.set_alignment(1.0, 0.5)
+        table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+        label.show()
 
-    label = gtk.Label('-rw-r--r--')
-    label.set_alignment(0.0, 0.5)
-    table.attach(label, 1, 4, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
-    label.show()
-    row += 1 ### }
+        button = gtk.CheckButton('Set user ID')
+        table.attach(button, 1, 4, row, row + 1, gtk.FILL, gtk.FILL)
+        button.show()
+        row += 1 ### }
 
-    ### {
-    label = gtk.Label('<b>Number view:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
+        ### {
+        button = gtk.CheckButton('Set group ID')
+        table.attach(button, 1, 4, row, row + 1, gtk.FILL, gtk.FILL)
+        button.show()
+        row += 1 ### }
 
-    label = gtk.Label('0644')
-    label.set_alignment(0.0, 0.5)
-    table.attach(label, 1, 4, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
-    label.show()
-    row += 1 ### }
+        ### {
+        button = gtk.CheckButton('Sticky')
+        table.attach(button, 1, 4, row, row + 1, gtk.FILL, gtk.FILL)
+        button.show()
+        row += 1 ### }
 
-    ### {
-    label = gtk.Label('<b>Last changed:</b>')
-    label.set_use_markup(True)
-    label.set_alignment(1.0, 0.5)
-    table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
-    label.show()
+        ### {
+        sep = gtk.HSeparator()
+        table.attach(sep, 0, 4, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
+        sep.show()
+        row += 1 ### }
 
-    label = gtk.Label('2005-02-15 17:55')
-    label.set_alignment(0.0, 0.5)
-    table.attach(label, 1, 4, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
-    label.show()
-    row += 1 ### }
+        ### {
+        label = gtk.Label('<b>Text view:</b>')
+        label.set_use_markup(True)
+        label.set_alignment(1.0, 0.5)
+        table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+        label.show()
 
+        label = gtk.Label('-rw-r--r--')
+        label.set_alignment(0.0, 0.5)
+        table.attach(label, 1, 4, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
+        label.show()
+        row += 1 ### }
 
+        ### {
+        label = gtk.Label('<b>Number view:</b>')
+        label.set_use_markup(True)
+        label.set_alignment(1.0, 0.5)
+        table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+        label.show()
 
-    ###
-    ### Application
-    ###
-#    vbox = gtk.VBox(False, 6)
-#    vbox.set_border_width(6)
-#    label = gtk.Label('Application')
-#    notebook.append_page(vbox, label)
-#    label.show()
-#    vbox.show()
-#
-#    label = gtk.Label('Select an application to open <i>foo.mp3</i> and all other files of type "MP3 audio"')
-#    label.set_use_markup(True)
-#    label.set_line_wrap(True)
-#    vbox.pack_start(label, False, True, 0)
-#    label.show()
-#
-#    model = gtk.ListStore(gobject.TYPE_BOOLEAN, gobject.TYPE_STRING)
-#    model.append([True, 'Xfce Media Player'])
-#    model.append([False, 'X Multimedia System'])
-#    model.append([False, 'beep-media-player'])
-#
-#    swin = gtk.ScrolledWindow()
-#    swin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
-#    swin.set_shadow_type(gtk.SHADOW_ETCHED_IN)
-#    vbox.pack_start(swin, True, True, 0)
-#    swin.show()
-#
-#    treeview = gtk.TreeView(model)
-#    treeview.set_headers_visible(False)
-#    swin.add(treeview)
-#    treeview.show()
-#    
-#    column = gtk.TreeViewColumn()
-#    renderer = gtk.CellRendererToggle()
-#    renderer.set_radio(True)
-#    column.pack_start(renderer, False)
-#    column.add_attribute(renderer, 'active', 0)
-#    renderer = gtk.CellRendererText()
-#    column.pack_start(renderer, True)
-#    column.add_attribute(renderer, 'text', 1)
-#    treeview.append_column(column)
-#
-#    box = gtk.HButtonBox()
-#    box.set_layout(gtk.BUTTONBOX_END)
-#    box.set_spacing(6)
-#    vbox.pack_start(box, False, False, 6)
-#    box.show()
-#
-#    button = gtk.Button(None, gtk.STOCK_ADD)
-#    box.pack_start(button, False, False, 0)
-#    button.show()
-#
-#    button = gtk.Button(None, gtk.STOCK_REMOVE)
-#    box.pack_start(button, False, False, 0)
-#    button.show()
+        label = gtk.Label('0644')
+        label.set_alignment(0.0, 0.5)
+        table.attach(label, 1, 4, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
+        label.show()
+        row += 1 ### }
 
+        ### {
+        label = gtk.Label('<b>Last changed:</b>')
+        label.set_use_markup(True)
+        label.set_alignment(1.0, 0.5)
+        table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
+        label.show()
 
+        label = gtk.Label('2005-02-15 17:55')
+        label.set_alignment(0.0, 0.5)
+        table.attach(label, 1, 4, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
+        label.show()
+        row += 1 ### }

Index: ThunarView.py
===================================================================
RCS file: /var/cvs/thunar/design/ui/ThunarView.py,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- ThunarView.py	14 Feb 2005 20:45:05 -0000	1.1.1.1
+++ ThunarView.py	27 Feb 2005 18:13:49 -0000	1.2
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-# vi:set ts=2 sw=2 et ai nocindent:
+# vi:set ts=4 sw=4 et ai nocindent:
 #
 # $Id$
 #
@@ -27,59 +27,28 @@
 import gobject
 import gtk
 
-class ThunarView(gtk.TreeView):
-  def __init__(self):
-    gtk.TreeView.__init__(self)
-    self.set_model(self.create_model())
+from ThunarFileInfo import ThunarFileInfo
+from ThunarModel import ThunarModel
 
-    column = gtk.TreeViewColumn('Name')
-    renderer = gtk.CellRendererPixbuf()
-    column.pack_start(renderer, False)
-    column.add_attribute(renderer, 'pixbuf', 0)
-    renderer = gtk.CellRendererText()
-    column.pack_start(renderer, True)
-    column.add_attribute(renderer, 'text', 1)
-    self.append_column(column)
-    self.set_expander_column(column)
+class ThunarView(gobject.GInterface):
+    def __init__(self):
+        return
 
-    column = gtk.TreeViewColumn('Size')
-    renderer = gtk.CellRendererText()
-    column.pack_start(renderer, False)
-    column.add_attribute(renderer, 'text', 2)
-    self.append_column(column)
+    def get_selected_files(self):
+        pass
 
-    column = gtk.TreeViewColumn('Owner')
-    renderer = gtk.CellRendererText()
-    column.pack_start(renderer, False)
-    column.add_attribute(renderer, 'text', 3)
-    self.append_column(column)
 
-    column = gtk.TreeViewColumn('Permissions')
-    renderer = gtk.CellRendererText()
-    column.pack_start(renderer, False)
-    column.add_attribute(renderer, 'text', 4)
-    self.append_column(column)
+    def select_all(self):
+        pass
 
-    self.set_rules_hint(True)
-    self.set_headers_clickable(True)
 
-  def create_model(self):
-    model = gtk.ListStore(gtk.gdk.Pixbuf, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
+    def activated(self, info):
+        self.emit('activated', info)
 
-    model.append([
-      self.render_icon(gtk.STOCK_NEW, gtk.ICON_SIZE_MENU),
-      'test1.txt',
-      '2.0 KB',
-      'Benedikt Meurer',
-      '-rw-r--r--',
-    ])
-    
-    model.append([
-      self.render_icon(gtk.STOCK_NEW, gtk.ICON_SIZE_MENU),
-      'test2.txt',
-      '4.5 KB',
-      'Benedikt Meurer',
-      '-rw-r--r--',
-    ])
 
-    return model
+    def context_menu(self):
+        self.emit('context-menu')
+
+
+    def selection_changed(self):
+        self.emit('selection-changed')

Index: ThunarWindow.py
===================================================================
RCS file: /var/cvs/thunar/design/ui/ThunarWindow.py,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- ThunarWindow.py	14 Feb 2005 20:45:05 -0000	1.1.1.1
+++ ThunarWindow.py	27 Feb 2005 18:13:49 -0000	1.2
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-# vi:set ts=2 sw=2 et ai nocindent:
+# vi:set ts=4 sw=4 et ai nocindent:
 #
 # $Id$
 #
@@ -22,85 +22,312 @@
 # 02111-1307, USA.
 #
 
+import os
+
 import pygtk
 pygtk.require('2.0')
 import gtk
 
+from ThunarModel import ThunarModel
+from ThunarFileInfo import ThunarFileInfo
+from ThunarListView import ThunarListView
+from ThunarTreePane import ThunarTreePane
 from ThunarPropertiesDialog import ThunarPropertiesDialog
-from ThunarView import ThunarView
+
+# the icon view requires libexo-0.3
+try:
+    from ThunarIconView import ThunarIconView
+    icon_view_support = True
+except ImportError:
+    icon_view_support = False
 
 class ThunarWindow(gtk.Window):
-  def __init__(self):
-    gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
-    self.set_title('Thunar')
-    self.set_default_size(400,350)
+    def __init__(self, info):
+        gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
+        self.set_title('Thunar: ' + info.get_visible_name())
+        self.set_icon(info.render_icon(48))
+        self.set_default_size(600,500)
 
-    action_group = gtk.ActionGroup('thunar-window')
-    action_group.add_actions([
-      ('file-menu', None, '_File'),
-      ('properties', gtk.STOCK_PROPERTIES, '_Properties...', '<Alt>Return', None, lambda ign, self: ThunarPropertiesDialog(self).show()),
-      ('close-window', gtk.STOCK_CLOSE, '_Close', '<Control>W', None, lambda ign, self: self.destroy()),
-    ], self)
-    action_group.add_actions([
-      ('edit-menu', None, '_Edit'),
-      ('copy-files', gtk.STOCK_COPY, '_Copy Files', '<Control>C'),
-      ('cut-files', gtk.STOCK_CUT, 'Cu_t Files', '<Control>X'),
-      ('paste-files', gtk.STOCK_PASTE, '_Paste Files', '<Control>V'),
-      ('select-all-files', None, 'Select _All Files', '<Control>S'),
-      ('select-by-pattern', None, 'Select by Pattern', None),
-      ('edit-toolbars', None, '_Edit Toolbars...', None),
-      ('preferences', gtk.STOCK_PREFERENCES, 'Prefere_nces...', None),
-    ], self)
-    action_group.add_actions([
-      ('view-menu', None, '_View'),
-      ('reload', gtk.STOCK_REFRESH, '_Reload', '<Control>R'),
-    ], self)
-    action_group.add_radio_actions([
-      ('view-as-icons', None, 'View as _Icons'),
-      ('view-as-list', None, 'View as _List'),
-    ], 0, None, self)
-    action_group.add_actions([
-      ('go-menu', None, '_Go'),
-      ('go-up', gtk.STOCK_GO_UP, '_Up', '<Alt>Up'),
-      ('go-back', gtk.STOCK_GO_BACK, '_Back', '<Alt>Left'),
-      ('go-forward', gtk.STOCK_GO_FORWARD, '_Forward', '<Alt>Right'),
-      ('go-home', gtk.STOCK_HOME, '_Home Folder'),
-      ('go-location', None, '_Location...'),
-    ], self)
-    action_group.add_actions([
-      ('help-menu', None, '_Help'),
-      ('contents', gtk.STOCK_HELP, '_Contents', 'F1'),
-      ('report-bug', None, '_Report bug'),
-      ('about', gtk.STOCK_DIALOG_INFO, '_About'),
-    ], self)
+        self.bookmarks = []
 
-    self.ui_manager = gtk.UIManager()
-    self.ui_manager.insert_action_group(action_group, 0)
-    self.ui_manager.add_ui_from_file('thunar.ui')
-    self.add_accel_group(self.ui_manager.get_accel_group())
+        self.info = info
 
-    self.main_vbox = gtk.VBox(False, 0)
-    self.add(self.main_vbox)
-    self.main_vbox.show()
+        self.action_group = gtk.ActionGroup('thunar-window')
+        self.action_group.add_actions([
+            ('file-menu', None, '_File'),
+            ('get-info', gtk.STOCK_PROPERTIES, 'Get _Info...', '<Alt>Return', None, lambda ign, self: self._action_get_info()),
+            ('close-window', gtk.STOCK_CLOSE, '_Close', '<Control>W', None, lambda ign, self: self.destroy()),
+        ], self)
+        self.action_group.add_actions([
+            ('edit-menu', None, '_Edit'),
+            ('copy-files', gtk.STOCK_COPY, '_Copy Files', '<Control>C'),
+            ('cut-files', gtk.STOCK_CUT, 'Cu_t Files', '<Control>X'),
+            ('paste-files', gtk.STOCK_PASTE, '_Paste Files', '<Control>V'),
+            ('select-all-files', None, 'Select _All Files', '<Control>S', None, lambda ign, self: self.view.select_all()),
+            ('select-by-pattern', None, 'Select by Pattern', None),
+            ('edit-toolbars', None, '_Edit Toolbars...', None),
+            ('preferences', gtk.STOCK_PREFERENCES, 'Prefere_nces...', None),
+        ], self)
+        self.action_group.add_actions([
+            ('view-menu', None, '_View'),
+            ('reload', gtk.STOCK_REFRESH, '_Reload', '<Control>R', None, lambda ign, self: self._action_open_dir(self.info)),
+        ], self)
+        self.action_group.add_toggle_actions([
+            ('sidepane', None, '_Side Pane', None, None, lambda ign, self: self._action_show_sidepane(), True),
+        ], self)
+        self.action_group.add_radio_actions([
+            ('view-as-icons', None, 'View as _Icons'),
+            ('view-as-list', None, 'View as _List'),
+        ], 0, lambda action, whatever, self: self._action_view_toggled(), self)
+        self.action_group.add_actions([
+            ('go-menu', None, '_Go'),
+            ('go-up', gtk.STOCK_GO_UP, '_Up', '<Alt>Up', None, lambda ign, self: self._action_open_dir(self.info.get_parent())),
+            ('go-back', gtk.STOCK_GO_BACK, '_Back', '<Alt>Left'),
+            ('go-forward', gtk.STOCK_GO_FORWARD, '_Forward', '<Alt>Right'),
+            ('go-home', gtk.STOCK_HOME, '_Home Folder', None, None, lambda ign, self: self._action_open_dir(ThunarFileInfo(os.getenv('HOME')))),
+            ('go-location', None, '_Location...', '<Control>L', None, lambda ign, self: self._action_open_location()),
+        ], self)
+        self.action_group.add_actions([
+            ('bookmarks-menu', None, '_Bookmarks'),
+            ('add-bookmark', gtk.STOCK_ADD, '_Add Bookmark', '<Control>D', None, lambda ign, self: self._action_add_bookmark()),
+        ], self)
+        self.action_group.add_actions([
+            ('help-menu', None, '_Help'),
+            ('contents', gtk.STOCK_HELP, '_Contents', 'F1'),
+            ('report-bug', None, '_Report bug'),
+            ('about', gtk.STOCK_DIALOG_INFO, '_About'),
+        ], self)
 
-    menu_bar = self.ui_manager.get_widget('/main-menu')
-    self.main_vbox.pack_start(menu_bar, False, False, 0)
-    menu_bar.show()
+        self.action_group.get_action('copy-files').set_property('sensitive', False)
+        self.action_group.get_action('cut-files').set_property('sensitive', False)
+        self.action_group.get_action('paste-files').set_property('sensitive', False)
+        self.action_group.get_action('select-by-pattern').set_property('sensitive', False)
+        self.action_group.get_action('edit-toolbars').set_property('sensitive', False)
+        self.action_group.get_action('preferences').set_property('sensitive', False)
+        self.action_group.get_action('go-back').set_property('sensitive', False)
+        self.action_group.get_action('go-forward').set_property('sensitive', False)
+        self.action_group.get_action('contents').set_property('sensitive', False)
+        self.action_group.get_action('report-bug').set_property('sensitive', False)
+        self.action_group.get_action('about').set_property('sensitive', False)
 
-    tool_bar = self.ui_manager.get_widget('/main-toolbar')
-    self.main_vbox.pack_start(tool_bar, False, False, 0)
-    tool_bar.show()
+        self.ui_manager = gtk.UIManager()
+        self.ui_manager.insert_action_group(self.action_group, 0)
+        self.ui_manager.add_ui_from_file('thunar.ui')
+        self.add_accel_group(self.ui_manager.get_accel_group())
 
-    self.main_hbox = gtk.HPaned()
-    self.main_vbox.pack_start(self.main_hbox, True, True, 0)
-    self.main_hbox.show()
+        self.main_vbox = gtk.VBox(False, 0)
+        self.add(self.main_vbox)
+        self.main_vbox.show()
 
+        menu_bar = self.ui_manager.get_widget('/main-menu')
+        self.main_vbox.pack_start(menu_bar, False, False, 0)
+        menu_bar.show()
 
-    swin = gtk.ScrolledWindow(None, None)
-    swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
-    self.main_hbox.add2(swin)
-    swin.show()
+        tool_bar = self.ui_manager.get_widget('/main-toolbar')
+        self.main_vbox.pack_start(tool_bar, False, False, 0)
+        tool_bar.show()
+
+        self.main_hbox = gtk.HPaned()
+        self.main_vbox.pack_start(self.main_hbox, True, True, 0)
+        self.main_hbox.show()
+
+        self.sidepane = gtk.VBox(False, 0)
+        self.main_hbox.add1(self.sidepane)
+        self.sidepane.show()
+
+        swin = gtk.ScrolledWindow(None, None)
+        swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+        self.sidepane.pack_start(swin, True, True, 0)
+        swin.show()
+
+        self.treepane = ThunarTreePane()
+        self.main_hbox.set_position(self.treepane.size_request()[0])
+        self.treepane.select_by_info(self.info)
+        self.treepane_selection_id = self.treepane.connect('directory-changed', lambda ign, info: self._action_open_dir(info))
+        swin.add(self.treepane)
+        self.treepane.show()
+
+        self.swin = gtk.ScrolledWindow(None, None)
+        self.swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+        self.main_hbox.add2(self.swin)
+        self.swin.show()
+
+        if icon_view_support:
+            self.view = ThunarIconView(self.info)
+            self.action_group.get_action('view-as-icons').set_active(True)
+        else:
+            self.view = ThunarListView(self.info)
+            self.action_group.get_action('view-as-list').set_active(True)
+        if not icon_view_support:
+            self.action_group.get_action('view-as-icons').set_property('sensitive', False)
+        self.view.connect('context-menu', lambda view: self._context_menu())
+        self.view.connect('activated', lambda widget, info: self._action_open_dir(info))
+        self.view.connect('selection-changed', lambda widget: self._selection_changed())
+        self.swin.add(self.view)
+        self.view.show()
+
+        self.status_bar = gtk.Statusbar()
+        self.status_id = self.status_bar.get_context_id('Selection state')
+        self.main_vbox.pack_start(self.status_bar, False, False, 0)
+        self.status_bar.show()
+
+        # get initial state right
+        self._selection_changed()
+
+
+    def _action_view_toggled(self):
+        other = self.swin.get_child()
+        if not other:
+            return
+        self.view = None
+        other.destroy()
+        if self.action_group.get_action('view-as-icons').get_active():
+            self.view = ThunarIconView(self.info)
+        else:
+            self.view = ThunarListView(self.info)
+        self.view.connect('context-menu', lambda view: self._context_menu())
+        self.view.connect('activated', lambda widget, info: self._action_open_dir(info))
+        self.view.connect('selection-changed', lambda widget: self._selection_changed())
+        self.swin.add(self.view)
+        self.view.show()
+
+
+    def _action_show_sidepane(self):
+        if self.action_group.get_action('sidepane').get_active():
+            self.sidepane.show()
+        else:
+            self.sidepane.hide()
+
+
+    def _action_get_info(self):
+        infos = self.view.get_selected_files()
+        for info in infos:
+            dialog = ThunarPropertiesDialog(self, info)
+            dialog.show()
+
+
+    def _action_add_bookmark(self):
+        menu = self.ui_manager.get_widget('/main-menu/bookmarks-menu').get_submenu()
+        if not self.bookmarks:
+            item = gtk.SeparatorMenuItem()
+            menu.append(item)
+            item.show()
+        for info in self.bookmarks:
+            if info.get_path() == self.info.get_path():
+                return
+        info = self.info
+        self.bookmarks.append(info)
+        item = gtk.ImageMenuItem(info.get_visible_name())
+        image = gtk.Image()
+        image.set_from_pixbuf(info.render_icon(16))
+        item.set_image(image)
+        item.connect('activate', lambda ign: self._action_open_dir(info))
+        image.show()
+        menu.append(item)
+        item.show()
+
+
+    def _action_open_dir(self, info):
+        model = ThunarModel(info)
+        self.view.set_model(model)
+        self.info = info
+        self.action_group.get_action('go-up').set_property('sensitive', (info.get_parent() != None))
+        self._selection_changed()
+        self.set_title('Thunar: ' + info.get_visible_name())
+        self.set_icon(info.render_icon(48))
+
+        self.treepane.handler_block(self.treepane_selection_id)
+        self.treepane.select_by_info(info)
+        self.treepane.handler_unblock(self.treepane_selection_id)
+
+        # scroll to (0,0)
+        self.swin.get_hadjustment().set_value(0)
+        self.swin.get_vadjustment().set_value(0)
+
+
+    def _action_open_location(self):
+        dialog = gtk.Dialog('Open Location', self, gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_NO_SEPARATOR | gtk.DIALOG_MODAL, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
+        dialog.set_default_response(gtk.RESPONSE_OK)
+        dialog.set_default_size(390, 50)
+
+        hbox = gtk.HBox(False, 12)
+        hbox.set_border_width(12)
+        dialog.vbox.pack_start(hbox, True, True, 0)
+        hbox.show()
+
+        label = gtk.Label('Location:')
+        hbox.pack_start(label, False, False, 0)
+        label.show()
+
+        entry = gtk.Entry()
+        entry.set_text(self.info.get_path())
+        entry.set_activates_default(True)
+        hbox.pack_start(entry)
+        entry.show()
+
+        response = dialog.run()
+        if response == gtk.RESPONSE_OK:
+            try:
+                info = ThunarFileInfo(entry.get_text())
+                self._action_open_dir(info)
+            except:
+                pass
+        dialog.destroy()
+
+
+    def _action_open_in_new_window(self, info):
+        window = ThunarWindow(info)
+        window.show()
+
+
+    def _context_menu(self):
+        files = self.view.get_selected_files()
+        menu = gtk.Menu()
+        if len(files) == 1:
+            info = files[0]
+
+            if info.is_directory():
+                item = gtk.ImageMenuItem('Open')
+                image = gtk.image_new_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_MENU)
+                item.set_image(image)
+                image.show()
+                item.connect('activate', lambda ign: self._action_open_dir(info))
+                menu.append(item)
+                item.show()
+
+                item = gtk.MenuItem('Open in New Window')
+                item.connect('activate', lambda ign: self._action_open_in_new_window(info))
+                menu.append(item)
+                item.show()
+
+                item = gtk.SeparatorMenuItem()
+                menu.append(item)
+                item.show()
+
+            item = gtk.MenuItem('Rename')
+            item.set_sensitive(False)
+            menu.append(item)
+            item.show()
+
+            item = gtk.SeparatorMenuItem()
+            menu.append(item)
+            item.show()
+
+        item = gtk.MenuItem('Get _Info...')
+        item.connect('activate', lambda ign: self._action_get_info())
+        menu.append(item)
+        item.show()
+
+        menu.popup(None, None, None, 3, gtk.get_current_event_time())
+
+
+    def _selection_changed(self):
+        infos = self.view.get_selected_files()
+        self.action_group.get_action('get-info').set_property('sensitive', len(infos) > 0)
+        self.status_bar.pop(self.status_id)
+        if infos:
+            self.status_bar.push(self.status_id, '%d items selected' % len(infos))
+        else:
+            model = self.view.get_model()
+            self.status_bar.push(self.status_id, '%d items' % model.iter_n_children(None))
 
-    self.view = ThunarView()
-    swin.add(self.view)
-    self.view.show()

Index: thunar.ui
===================================================================
RCS file: /var/cvs/thunar/design/ui/thunar.ui,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- thunar.ui	14 Feb 2005 20:45:05 -0000	1.1.1.1
+++ thunar.ui	27 Feb 2005 18:13:49 -0000	1.2
@@ -26,7 +26,7 @@
 <ui>
   <menubar name="main-menu">
     <menu action="file-menu">
-      <menuitem action="properties" />
+      <menuitem action="get-info" />
       <separator />
       <menuitem action="close-window" />
     </menu>
@@ -54,6 +54,9 @@
       <menuitem action="show-hidden-files" />
 -->
       <separator />
+      <menuitem action="sidepane" />
+      <separator />
+
       <menuitem action="view-as-icons" />
       <menuitem action="view-as-list" />
     </menu>
@@ -67,6 +70,10 @@
       <menuitem action="go-location" />
     </menu>
 
+    <menu action="bookmarks-menu">
+      <menuitem action="add-bookmark" />
+    </menu>
+
     <menu action="help-menu">
       <menuitem action="contents" />
       <menuitem action="report-bug" />
@@ -76,8 +83,8 @@
 
   <toolbar name="main-toolbar">
     <toolitem action="go-back" />
-    <toolitem action="go-forward" />
     <toolitem action="go-up" />
+    <toolitem action="go-forward" />
     <separator />
     <toolitem action="reload" />
     <separator />




More information about the Thunar-workers mailing list