[Thunar-workers] CVS: design/ui/spatial ThunarFolderDatabase.py, NONE, 1.1 ThunarIconView.py, NONE, 1.1 ThunarListView.py, NONE, 1.1 ThunarPropertiesDialog.py, NONE, 1.1 .cvsignore, 1.1, 1.2 Main.py, 1.1, 1.2 ThunarFileInfo.py, 1.1, 1.2 ThunarModel.py, 1.1, 1.2 ThunarParentSelector.py, 1.1, 1.2 ThunarStatusBar.py, 1.1, 1.2 ThunarView.py, 1.1, 1.2 ThunarWindow.py, 1.1, 1.2 thunar.ui, 1.1, 1.2

Benedikt Meurer benny at xfce.org
Mon Feb 21 21:27:02 CET 2005


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

Modified Files:
	.cvsignore Main.py ThunarFileInfo.py ThunarModel.py 
	ThunarParentSelector.py ThunarStatusBar.py ThunarView.py 
	ThunarWindow.py thunar.ui 
Added Files:
	ThunarFolderDatabase.py ThunarIconView.py ThunarListView.py 
	ThunarPropertiesDialog.py 
Log Message:
2005-02-21	Benedikt Meurer <benny at xfce.org>

	* spatial/: More work on the spatial prototype, including separate
	  ListView and IconView support (IconView is only available with
	  very recent libexo-0.3 from Subversion repository). The new prototype
	  includes various ideas that were taken from the Spatial Nautilus,
	  the Spatial Finder (maybe someday I'll read the whole article) and
	  Tracker (the BeOS file manager).




--- NEW FILE: ThunarFolderDatabase.py ---
#!/usr/bin/env python
# vi:set ts=4 sw=4 et ai nocindent:
#
# $Id: ThunarFolderDatabase.py,v 1.1 2005/02/21 20:26:59 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 xml.dom.minidom

db = None
def get_folder_db():
    global db
    if not db:
        db = ThunarFolderDatabase()
    return db


class ThunarFolderProperties:
    def __init__(self, geometry, iconview):
        self.geometry = geometry
        self.iconview = iconview


class ThunarFolderDatabase:
    def __init__(self):
        self.folders = {}

        try:
            self._load()
        except:
            pass


    def lookup(self, path):
        if self.folders.has_key(path):
            return self.folders[path]
        return None


    def insert(self, path, geometry, iconview):
        if self.folders.has_key(path):
            del self.folders[path]
        self.folders[path] = ThunarFolderProperties(geometry, iconview)


    def sync(self):
        fp = open('folders.xml', 'w')
        fp.write("""<?xml version="1.0" encoding="UTF-8"?>
<folders>
""")
        for key in self.folders.keys():
            folder = self.folders[key]
            fp.write('<folder path="%s" geometry="%s" iconview="%s" />' \
                % (key, folder.geometry, int(folder.iconview)))

        fp.write("""
</folders>
""")
        fp.close()


    def _load(self):
        doc = xml.dom.minidom.parse('folders.xml')
        assert doc.documentElement.tagName == 'folders'
        for node in doc.getElementsByTagName('folder'):
            path = '%s' % node.getAttribute('path')
            geometry = '%s' % node.getAttribute('geometry')
            iconview = int(node.getAttribute('iconview'))
            self.folders[path] = ThunarFolderProperties(geometry, iconview)


--- 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/21 20:26:59 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/21 20:26:59 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:
            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, [])
            gobject.signal_new('selection-changed', self, gobject.SIGNAL_RUN_LAST, \
                               gobject.TYPE_NONE, [])
            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: ThunarPropertiesDialog.py ---
#!/usr/bin/env python
# vi:set ts=4 sw=4 et ai nocindent:
#
# $Id: ThunarPropertiesDialog.py,v 1.1 2005/02/21 20:26:59 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

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())

        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()

        row = 0

        ### {
        box = gtk.HBox(False, 6)
        table.attach(box, 0, 1, row, row + 1, gtk.FILL, gtk.FILL)
        box.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('<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(info.get_visible_name())
        table.attach(entry, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
        entry.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>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(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 ### }

        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()

            hbox = gtk.HBox(False, 6)
            table.attach(hbox, 1, 2, row, row + 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
            hbox.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('Xfce Media Player')
            label.set_alignment(0.0, 0.5)
            label.set_selectable(True)
            hbox.pack_start(label, False, True, 0)
            label.show()

            button = gtk.Button('Ch_ange')
            hbox.pack_end(button, False, False, 0)
            button.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>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(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 ### }

        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(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('<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(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 ### }

        ### {
        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 ### }

        ### {
        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_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 ### }



        ###
        ### 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()

        row = 0

        ### {
        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()

        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 ### }

        ### {
        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>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('Read')
        table.attach(button, 1, 2, row, row + 1, gtk.FILL, gtk.FILL)
        button.show()

        button = gtk.CheckButton('Write')
        table.attach(button, 2, 3, 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 ### }

        ### {
        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('Read')
        table.attach(button, 1, 2, row, row + 1, gtk.FILL, gtk.FILL)
        button.show()

        button = gtk.CheckButton('Write')
        table.attach(button, 2, 3, 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 ### }

        ### {
        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('Read')
        table.attach(button, 1, 2, row, row + 1, gtk.FILL, gtk.FILL)
        button.show()

        button = gtk.CheckButton('Write')
        table.attach(button, 2, 3, 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 ### }

        ### {
        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('Set user ID')
        table.attach(button, 1, 4, row, row + 1, gtk.FILL, gtk.FILL)
        button.show()
        row += 1 ### }

        ### {
        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('Sticky')
        table.attach(button, 1, 4, row, row + 1, gtk.FILL, gtk.FILL)
        button.show()
        row += 1 ### }

        ### {
        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>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()

        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: .cvsignore
===================================================================
RCS file: /var/cvs/thunar/design/ui/spatial/.cvsignore,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- .cvsignore	20 Feb 2005 22:09:55 -0000	1.1
+++ .cvsignore	21 Feb 2005 20:26:59 -0000	1.2
@@ -1,2 +1,3 @@
 *.pyc
 .*.swp
+folders.xml

Index: Main.py
===================================================================
RCS file: /var/cvs/thunar/design/ui/spatial/Main.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- Main.py	20 Feb 2005 22:09:55 -0000	1.1
+++ Main.py	21 Feb 2005 20:26:59 -0000	1.2
@@ -28,6 +28,8 @@
 pygtk.require('2.0')
 import gtk
 
+import ThunarFolderDatabase
+
 from ThunarFileInfo import ThunarFileInfo
 from ThunarWindow import ThunarWindow
 
@@ -44,3 +46,4 @@
     main = Main()
     main.run()
 
+    ThunarFolderDatabase.get_folder_db().sync()

Index: ThunarFileInfo.py
===================================================================
RCS file: /var/cvs/thunar/design/ui/spatial/ThunarFileInfo.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- ThunarFileInfo.py	20 Feb 2005 22:09:55 -0000	1.1
+++ ThunarFileInfo.py	21 Feb 2005 20:26:59 -0000	1.2
@@ -22,7 +22,7 @@
 # 02111-1307, USA.
 #
 
-import dircache, os, stat, time
+import dircache, pwd, os, stat, time
 
 import pygtk
 pygtk.require('2.0')
@@ -47,6 +47,33 @@
         self.stat = os.stat(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)
 
@@ -66,14 +93,45 @@
         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

Index: ThunarModel.py
===================================================================
RCS file: /var/cvs/thunar/design/ui/spatial/ThunarModel.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- ThunarModel.py	20 Feb 2005 22:09:55 -0000	1.1
+++ ThunarModel.py	21 Feb 2005 20:26:59 -0000	1.2
@@ -33,20 +33,25 @@
 
 class ThunarModel(gtk.ListStore):
     COLUMN_ICON     = 0
-    COLUMN_NAME     = 1
-    COLUMN_SIZE     = 2
-    COLUMN_MTIME    = 3
-    COLUMN_KIND     = 4
-    COLUMN_FILEINFO = 5
+    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
@@ -55,7 +60,8 @@
             mime_info = file_info.get_mime_info()
 
             self.append([
-                mime_info.render_icon(16),
+                file_info.render_icon(16),
+                file_info.render_icon(48),
                 file_info.get_visible_name(),
                 file_info.get_size(),
                 file_info.get_mtime(),
@@ -64,4 +70,23 @@
             ])
 
 
+    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

Index: ThunarParentSelector.py
===================================================================
RCS file: /var/cvs/thunar/design/ui/spatial/ThunarParentSelector.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- ThunarParentSelector.py	20 Feb 2005 22:09:55 -0000	1.1
+++ ThunarParentSelector.py	21 Feb 2005 20:26:59 -0000	1.2
@@ -38,22 +38,23 @@
         # register signals
         global signals_registered
         if not signals_registered:
-            gobject.signal_new('selected', self, gobject.SIGNAL_RUN_LAST, \
+            gobject.signal_new('activated', self, gobject.SIGNAL_RUN_LAST, \
                                gobject.TYPE_NONE, [ThunarFileInfo])
             signals_registered = True
 
         self.unset_flags(gtk.CAN_FOCUS)
         self.set_relief(gtk.RELIEF_NONE)
-        self.connect('clicked', lambda self: self._selector_clicked())
+        self.connect('pressed', lambda self: self._selector_clicked())
         self.file_info = dir_info
 
         box = gtk.HBox(False, 6)
+        box.set_border_width(0)
         self.add(box)
         box.show()
 
         mime_info = self.file_info.get_mime_info()
         self.image = gtk.Image()
-        self.image.set_from_pixbuf(mime_info.render_icon(16))
+        self.image.set_from_pixbuf(dir_info.render_icon(16))
         box.pack_start(self.image, False, False, 0)
         self.image.show()
 
@@ -86,9 +87,8 @@
         menu = gtk.Menu()
         file_info = self.file_info
         while file_info:
-            mime_info = file_info.get_mime_info()
             name = file_info.get_visible_name()
-            icon = mime_info.render_icon(16)
+            icon = file_info.render_icon(16)
 
             image = gtk.Image()
             image.set_from_pixbuf(icon)
@@ -96,7 +96,7 @@
             item = gtk.ImageMenuItem(name)
             item.set_image(image)
             item.set_data('info', file_info)
-            item.connect('activate', lambda item: self.emit('selected', item.get_data('info')))
+            item.connect('activate', lambda item: self.emit('activated', item.get_data('info')))
             menu.prepend(item)
             item.show()
             if not first: first = item
@@ -112,4 +112,4 @@
         menu.select_item(first)
         loop.run()
         menu.grab_remove()
-
+        self.released()

Index: ThunarStatusBar.py
===================================================================
RCS file: /var/cvs/thunar/design/ui/spatial/ThunarStatusBar.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- ThunarStatusBar.py	20 Feb 2005 22:09:55 -0000	1.1
+++ ThunarStatusBar.py	21 Feb 2005 20:26:59 -0000	1.2
@@ -39,11 +39,12 @@
         # register signals
         global signals_registered
         if not signals_registered:
-            gobject.signal_new('selected', self, gobject.SIGNAL_RUN_LAST, \
+            gobject.signal_new('activated', self, gobject.SIGNAL_RUN_LAST, \
                                gobject.TYPE_NONE, [ThunarFileInfo])
             signals_registered = True
 
         frame = gtk.Frame()
+        frame.set_border_width(0)
         shadow_type = self.style_get_property('shadow_type')
         frame.set_property('shadow_type', shadow_type)
         self.pack_start(frame, False, False, 0)
@@ -51,6 +52,6 @@
         frame.show()
 
         selector = ThunarParentSelector(dir_info)
-        selector.connect('selected', lambda widget, info: self.emit('selected', info))
+        selector.connect('activated', lambda widget, info: self.emit('activated', info))
         frame.add(selector)
         selector.show()

Index: ThunarView.py
===================================================================
RCS file: /var/cvs/thunar/design/ui/spatial/ThunarView.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- ThunarView.py	20 Feb 2005 22:09:55 -0000	1.1
+++ ThunarView.py	21 Feb 2005 20:26:59 -0000	1.2
@@ -30,57 +30,25 @@
 from ThunarFileInfo import ThunarFileInfo
 from ThunarModel import ThunarModel
 
-signals_registered = False
-
-class ThunarView(gtk.TreeView):
-    def __init__(self, dir_info):
-        gtk.TreeView.__init__(self)
-
-        # register signals
-        global signals_registered
-        if not signals_registered:
-            gobject.signal_new('selected', self, gobject.SIGNAL_RUN_LAST, \
-                               gobject.TYPE_NONE, [ThunarFileInfo])
-            signals_registered = True
+class ThunarView(gobject.GInterface):
+    def __init__(self):
+        return
 
-        self.set_model(ThunarModel(dir_info))
+    def get_selected_files(self):
+        pass
 
-        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()
-        column.pack_start(renderer, False)
-        column.add_attribute(renderer, 'text', ThunarModel.COLUMN_SIZE)
-        self.append_column(column)
+    def select_all(self):
+        pass
 
-        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)
+    def activated(self, info):
+        self.emit('activated', info)
 
-        self.set_rules_hint(True)
-        self.set_headers_clickable(True)
 
-        self.connect('row-activated', lambda tree, path, column: tree._activated(path))
+    def context_menu(self):
+        self.emit('context-menu')
 
 
-    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.emit('selected', info)
+    def selection_changed(self):
+        self.emit('selection-changed')

Index: ThunarWindow.py
===================================================================
RCS file: /var/cvs/thunar/design/ui/spatial/ThunarWindow.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- ThunarWindow.py	20 Feb 2005 22:09:55 -0000	1.1
+++ ThunarWindow.py	21 Feb 2005 20:26:59 -0000	1.2
@@ -22,56 +22,101 @@
 # 02111-1307, USA.
 #
 
+import dircache, os
 import weakref, gc
+import shelve, pickle
 
 import pygtk
 pygtk.require('2.0')
+import gobject
 import gtk
 
+from ThunarFileInfo import ThunarFileInfo
+from ThunarFolderDatabase import get_folder_db
+from ThunarListView import ThunarListView
+from ThunarPropertiesDialog import ThunarPropertiesDialog
 from ThunarStatusBar import ThunarStatusBar
-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
 
 windows = weakref.WeakValueDictionary()
 
 class ThunarWindow(gtk.Window):
-    def destroyed(self):
+    def _destroyed(self):
         del windows[self.dir_info.get_path()] 
         gc.collect()
         if len(windows) == 0:
             gtk.main_quit()
 
-    def __init__(self, dir_info):
+
+    def _save_state(self):
+        db = get_folder_db()
+        x, y = self.get_position()
+        w, h = self.get_size()
+        geometry = '%sx%s+%s+%s' % (w, h, x, y)
+        iconview = self.action_group.get_action('view-as-icons').get_active()
+        db.insert(self.dir_info.get_path(), geometry, iconview)
+        folder = db.lookup(self.dir_info.get_path())
+
+
+    def __init__(self, dir_info, use_icon_view = True):
         gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
-        self.connect('destroy', lambda self: self.destroyed())
+        self.set_icon(dir_info.render_icon(48))
+        self.connect('destroy', lambda self: self._destroyed())
 
         global windows
         self.dir_info = dir_info
         windows[dir_info.get_path()] = self
 
         self.set_title(dir_info.get_visible_name())
-        self.set_default_size(400,350)
 
-        action_group = gtk.ActionGroup('thunar-window')
-        action_group.add_actions([
-          ('file-menu', None, '_File'),
-          ('close-parent-folders', None, 'Close _Parent Folders', '<Control><Shift>W', None, lambda ign, self: self._close_parent_folders()),
-          ('close-window', gtk.STOCK_CLOSE, '_Close', '<Control>W', None, lambda ign, self: self.destroy()),
+        foldersdb = get_folder_db()
+        folder = foldersdb.lookup(dir_info.get_path())
+        if folder:
+            use_icon_view = folder.iconview
+            self.set_geometry_hints(None, -1, -1, -1, -1, 0, 0, 1, 1)
+            self.parse_geometry(folder.geometry)
+        else:
+            self.set_default_size(400,350)
+
+        self.action_group = gtk.ActionGroup('thunar-window')
+        self.action_group.add_actions([
+            ('file-menu', None, '_File'),
+            ('open-parent', None, 'Open _Parent', '<Alt>Up', None, lambda ign, self: self._action_open_parent()),
+            ('open-location', None, 'Open _Location', '<Ctrl>L', None, lambda ign, self: self._action_open_location()),
+            ('get-info', gtk.STOCK_PROPERTIES, 'Get _Info...', '<Alt>Return', None, lambda ign, self: self._action_get_info()),
+            ('close-parent-folders', None, 'Close P_arent Folders', '<Control><Shift>W', None, lambda ign, self: self._action_close_parent_folders()),
+            ('close-all-folders', None, 'Clos_e All Folders', '<Control>Q', None, lambda ign, self: gtk.main_quit()),
+            ('close-window', gtk.STOCK_CLOSE, '_Close', '<Control>W', None, lambda ign, self: self.destroy()),
         ], self)
-        action_group.add_actions([
-          ('window-menu', None, '_Window'),
+        self.action_group.add_actions([
+            ('view-menu', None, '_View'),
+            ('select-all', None, 'Select _All', '<Control>A', None, lambda ign, self: self.view.select_all()),
         ], 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.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._view_toggled(), 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)
 
         self.ui_manager = gtk.UIManager()
-        self.ui_manager.insert_action_group(action_group, 0)
+        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.action_group.get_action('get-info').set_property('sensitive', False)
+        self.action_group.get_action('open-parent').set_property('sensitive', dir_info.get_parent() != None)
+
         main_vbox = gtk.VBox(False, 0)
         self.add(main_vbox)
         main_vbox.show()
@@ -80,23 +125,40 @@
         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)
-        main_vbox.pack_start(swin, True, True, 0)
-        swin.show()
+        self.swin = gtk.ScrolledWindow(None, None)
+        self.swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+        main_vbox.pack_start(self.swin, True, True, 0)
+        self.swin.show()
 
-        self.view = ThunarView(dir_info)
-        self.view.connect('selected', lambda widget, info: self.open_dir(info))
-        swin.add(self.view)
+        if icon_view_support and use_icon_view:
+            self.view = ThunarIconView(dir_info)
+            self.action_group.get_action('view-as-icons').set_active(True)
+        else:
+            self.view = ThunarListView(dir_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.open_dir(info))
+        self.view.connect('selection-changed', lambda widget: self._selection_changed())
+        self.swin.add(self.view)
         self.view.show()
 
         self.status_bar = ThunarStatusBar(dir_info)
-        self.status_bar.connect('selected', lambda widget, info: self.open_dir(info))
+        self.status_bar.connect('activated', lambda widget, info: self.open_dir(info))
         main_vbox.pack_start(self.status_bar, False, False, 0)
         self.status_bar.show()
+        self.status_id = self.status_bar.get_context_id('Selection state')
 
+        # get initial state right
+        self._selection_changed()
 
-    def _close_parent_folders(self):
+
+        self.connect('unrealize', lambda self: self._save_state())
+        self.connect_after('configure-event', lambda self, ev: self._save_state())
+
+
+    def _action_close_parent_folders(self):
         dir_info = self.dir_info.get_parent()
         while dir_info:
             if windows.has_key(dir_info.get_path()):
@@ -104,11 +166,166 @@
             dir_info = dir_info.get_parent()
 
 
+    def _action_get_info(self):
+        infos = self.view.get_selected_files()
+        for info in infos:
+            dialog = ThunarPropertiesDialog(self, info)
+            dialog.show()
+
+    
+    def _action_open_parent(self):
+        dir_info = self.dir_info.get_parent()
+        if dir_info:
+            self.open_dir(dir_info)
+
+
+    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.dir_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.open_dir(info)
+            except:
+                pass
+        dialog.destroy()
+
+
+    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))
+
+
+    def _fill_submenu(self, menu, info):
+        if menu.get_children():
+            return
+
+        item = gtk.MenuItem('Open this folder')
+        item.connect('activate', lambda widget: self.open_dir(info))
+        menu.append(item)
+        item.show()
+
+        separator = None
+
+        names = dircache.listdir(info.get_path())[:]
+        names.sort()
+        for name in names:
+            if name.startswith('.'):
+                continue
+
+            child = ThunarFileInfo(os.path.join(info.get_path(), name))
+            if not child.is_directory():
+                continue
+
+            if not separator:
+                separator = gtk.SeparatorMenuItem()
+                menu.append(separator)
+                separator.show()
+
+            item = self._create_dir_item(child)
+            menu.append(item)
+            item.show()
+
+
+    def _create_dir_item(self, info):
+        item = gtk.ImageMenuItem()
+        label = gtk.Label(info.get_visible_name())
+        label.set_alignment(0.0, 0.5)
+        item.add(label)
+        label.show()
+        image = gtk.Image()
+        image.set_from_pixbuf(info.render_icon(16))
+        image.show()
+        item.set_image(image)
+
+        if info.is_directory():
+            submenu = gtk.Menu()
+            item.set_submenu(submenu)
+            submenu.connect('show', lambda menu: self._fill_submenu(menu, info))
+
+        return item
+
+
+    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 = self._create_dir_item(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 = self.action_group.get_action('get-info').create_menu_item()
+        menu.append(item)
+        item.show()
+
+        menu.popup(None, None, None, 3, gtk.get_current_event_time())
+
+
+    def _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.dir_info)
+        else:
+            self.view = ThunarListView(self.dir_info)
+        self.view.connect('context-menu', lambda view: self._context_menu())
+        self.view.connect('activated', lambda widget, info: self.open_dir(info))
+        self.view.connect('selection-changed', lambda widget: self._selection_changed())
+        self.swin.add(self.view)
+        self.view.show()
+
+        self._save_state()
+
+
     def open_dir(self, dir_info):
         gc.collect()
         try:
             window = windows[dir_info.get_path()]
             window.present()
         except:
-            window = ThunarWindow(dir_info)
+            window = ThunarWindow(dir_info, self.action_group.get_action('view-as-icons').get_active())
             window.show()

Index: thunar.ui
===================================================================
RCS file: /var/cvs/thunar/design/ui/spatial/thunar.ui,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- thunar.ui	20 Feb 2005 22:09:55 -0000	1.1
+++ thunar.ui	21 Feb 2005 20:26:59 -0000	1.2
@@ -26,11 +26,21 @@
 <ui>
   <menubar name="main-menu">
     <menu action="file-menu">
+      <menuitem action="open-parent" />
+      <menuitem action="open-location" />
+      <separator />
+      <menuitem action="get-info" />
+      <separator />
       <menuitem action="close-parent-folders" />
+      <menuitem action="close-all-folders" />
       <menuitem action="close-window" />
     </menu>
 
-    <menu action="window-menu">
+    <menu action="view-menu">
+      <menuitem action="select-all" />
+      <separator />
+      <menuitem action="view-as-icons" />
+      <menuitem action="view-as-list" />
     </menu>
 
     <menu action="help-menu">




More information about the Thunar-workers mailing list