buffer.py :  » IDE » PIDA » pida-0.6beta3 » pida » services » buffer » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » IDE » PIDA 
PIDA » pida 0.6beta3 » pida » services » buffer » buffer.py
# -*- coding: utf-8 -*-
"""
    :copyright: 2005-2008 by The PIDA Project
    :license: GPL 2 or later (see README/COPYING/LICENSE)
"""
import os
from tempfile import mkstemp

import gtk

from kiwi.ui.objectlist import Column

# PIDA Imports
from pida.core.service import Service
from pida.core.features import FeaturesConfig
from pida.core.commands import CommandsConfig
from pida.core.options import OptionsConfig,choices
from pida.core.events import EventsConfig
from pida.core.actions import ActionsConfig
from pida.core.pdbus import DbusConfig,EXPORT
from pida.core.actions import TYPE_NORMAL,TYPE_MENUTOOL,TYPE_RADIO,TYPE_TOGGLE

from pida.ui.views import PidaGladeView,WindowConfig
from pida.ui.objectlist import AttrSortCombo
from pida.core.document import Document,DocumentException

from pida.utils.gthreads import gcall

# locale
from pida.core.locale import Locale
locale = Locale('buffer')
_ = locale.gettext

LEXPORT = EXPORT(suffix='buffer')

LIST_COLUMNS = {
'onerow': [
            Column('markup', use_markup=True),
            Column("basename", visible=False, searchable=True),
          ],
'tworow': [
            Column('markup_tworow', use_markup=True),
            Column("basename", visible=False, searchable=True),
          ]
}

class BufferListView(PidaGladeView):

    key = 'buffer.list'
    gladefile = 'buffer_list'
    locale = locale
    icon_name = 'package_office'

    label_text = _('Buffers')

    list_columns = LIST_COLUMNS

    def create_ui(self):
        val = self.svc.opt('display_type')
        self.buffers_ol.set_columns(LIST_COLUMNS[val])
        self.buffers_ol.set_headers_visible(False)
        self._sort_combo = AttrSortCombo(self.buffers_ol,
            [
                ('creation_time', _('Time Opened')),
                ('filename', _('File path')),
                ('basename', _('File name')),
                ('mimetype', _('Mime Type')),
                ('doctype', _('Document Type')),
                ('length', _('File Length')),
                ('modified_time', _('Last Modified')),
                ('usage', _('View Counter')),
                #('Project', _('Project_name'))
            ],
            'creation_time' 
        )
        self._sort_combo.show()
        self.main_vbox.pack_start(self._sort_combo, expand=False)

    def add_document(self, document):
        self.buffers_ol.append(document)

    def remove_document(self, document):
        self.buffers_ol.remove(document)

    def set_document(self, document):
        if self.buffers_ol.get_selected() is not document:
            self.buffers_ol.select(document)

    def view_document(self, document):
        self.svc.view_document(document)
        self.svc.boss.editor.cmd('grab_focus')

    def on_buffers_ol__double_click(self, ol, item):
        self.view_document(item)

    def on_buffers_ol__row_activated(self, ol, item):
        self.view_document(item)

    def on_buffers_ol__right_click(self, ol, item, event=None):
        menu = self.svc.boss.cmd('contexts', 'get_menu', context='file-menu',
                                 document=item, file_name=item.filename)

        # Add some stuff to the menu
        close = self.svc.get_action('close_selected').create_menu_item()
        menu.insert(close, 2)

        menu.show_all()
        menu.popup(None, None, None, event.button, event.time)

        # Must leave the menu in the same state we found it!
        def on_deactivate(menu):
            #menu.remove(sep)
            menu.remove(close)

        menu.connect('deactivate', on_deactivate)

    def get_current_buffer_index(self):
        return self.buffers_ol.index(self.svc.get_current())

    def select_buffer_by_index(self, index):
        self.buffers_ol.select(self.buffers_ol[index])
        self.view_document(self.buffers_ol[index])

    def next_buffer(self):
        index = self.get_current_buffer_index()
        newindex = index + 1
        if newindex == len(self.buffers_ol):
            newindex = 0
        self.select_buffer_by_index(newindex)

    def prev_buffer(self):
        index = self.get_current_buffer_index()
        newindex = index - 1
        if newindex == -1:
            newindex = len(self.buffers_ol) - 1
        self.select_buffer_by_index(newindex)

    def sort(self):
        self._sort_combo._sort()

class BufferActionsConfig(ActionsConfig):

    def create_actions(self):
        self.create_action(
            'open_file',
            TYPE_NORMAL,
            _('_Open File'),
            _('Open a file with a graphical file browser'),
            gtk.STOCK_OPEN,
            self.on_open_file,
            '<Shift><Control>O',
        )

        self.create_action(
            'open-for-file',
            TYPE_NORMAL,
            _('Open File'),
            _('Open this file'),
            gtk.STOCK_OPEN,
            self.on_open_for_file,
        )

        self.create_action(
            'new_file',
            TYPE_NORMAL,
            _('_New File'),
            _('Create a new file'),
            gtk.STOCK_NEW,
            self.on_new_file,
            '<Shift><Control>N',
        )

        self.create_action(
            'create_file',
            TYPE_NORMAL,
            _('Cr_eate File'),
            _('Create a new file'),
            gtk.STOCK_ADD,
            self.on_add_file,
            '<Shift><Control>A',
        )

        self.create_action(
            'close',
            TYPE_NORMAL,
            _('_Close Document'),
            _('Close the current document'),
            gtk.STOCK_CLOSE,
            self.on_close,
            '<Shift><Control>W',
        )

        self.create_action(
            'close_all',
            TYPE_NORMAL,
            _('Close all Documents'),
            _('Close all documents'),
            '',
            self.on_close_all,
            '',
        )
        self.create_action(
            'switch_next_buffer',
            TYPE_NORMAL,
            _('_Next Buffer'),
            _('Switch to the next buffer'),
            gtk.STOCK_GO_DOWN,
            self.on_next_buffer,
            '<Alt>Down',
        )

        self.create_action(
            'switch_prev_buffer',
            TYPE_NORMAL,
            _('_Previous Buffer'),
            _('Switch to the previous buffer'),
            gtk.STOCK_GO_UP,
            self.on_prev_buffer,
            '<Alt>Up',
        )
        self.create_action(
            'show_buffer_list',
            TYPE_NORMAL,
            _('Show _buffer browser'),
            _('Displays the buffer window'),
            '',
            self.on_show_buffer,
            '<Shift><Control>b',
            global_=True
        )

        self.create_action(
            'close_selected',
            TYPE_NORMAL,
            _('_Close Document'),
            _('Close the selected document'),
            gtk.STOCK_CLOSE,
            self.on_close_selected,
        )

    def on_open_file(self, action):
        project = self.svc.boss.cmd('project', 'get_current_project')
        if project:
            current_folder = project.source_directory
        else:
            current_folder = None 
        file_name = self.svc.boss.window.open_dlg(folder=current_folder)
        if file_name:
            self.svc.open_file(file_name)

    def on_new_file(self, action):
        self.svc.new_file()

    def on_add_file(self, action):
        current_folder = self.svc.boss.cmd('filemanager', 'get_browsed_path')
        file_name = self.svc.boss.window.save_dlg(folder=current_folder)
        if file_name:
            f = open(file_name, 'w')
            f.close()
            self.svc.open_file(file_name)

    def on_close(self, action):
        self.svc.close_current()

    def on_close_all(self, action):
        self.svc.close_all()

    def on_open_for_file(self, action):
        file_name = action.contexts_kw['file_name']
        self.svc.open_file(file_name)

    def on_next_buffer(self, action):
        self.svc.get_view().next_buffer()

    def on_prev_buffer(self, action):
        self.svc.get_view().prev_buffer()

    def on_show_buffer(self, action):
        self.svc.cmd('present_view')

    def on_close_selected(self, action):
        document = action.contexts_kw.get('document')
        self.svc.close_file(document=document)

class BufferListConfig(WindowConfig):
    key = BufferListView.key
    label_text = BufferListView.label_text
    description = "Buffer List"

class BufferFeaturesConfig(FeaturesConfig):

    def subscribe_all_foreign(self):
        self.subscribe_foreign('contexts', 'file-menu',
            (self.svc.get_action_group(), 'buffer-file-menu.xml'))
        self.subscribe_foreign('window', 'window-config',
            BufferListConfig)

class BufferEventsConfig(EventsConfig):

    def create(self):
        self.publish('document-saved', 'document-changed', 
            'document-typchanged', 'document-closed', 'document-opened', 
            'document-goto')
        self.subscribe('document-saved', self.on_document_change)
        self.subscribe('document-changed', self.on_document_change)
        self.subscribe('document-typchanged', self.on_document_change)

    def on_document_change(self, *args, **kwargs):
        # we have to update the document buffer when one doc changes as
        # the list should be sorted all the time
        self.svc.get_view().sort()

class BufferOptionsConfig(OptionsConfig):
    def create_options(self):
        self.create_option(
            'display_type',
            _('Display notebook title'),
            choices({'onerow':_('One Row'), 
                     'tworow':_('Filename and Path seperate ')}),
            'tworow',
            _('Type to display in the Buffer window'),
            self.on_display_type_change
        )

    def on_display_type_change(self, option):
        self.svc.get_view().buffers_ol.set_columns(
            LIST_COLUMNS[option.value])


class BufferCommandsConfig(CommandsConfig):

    def open_file(self, file_name=None, document=None, line=None, offset=None):
        if not file_name and not document:
            return
        self.svc.open_file(file_name, document, line=line, offset=offset)

    def open_files(self, files):
        self.svc.open_files(files)

    def close_file(self, file_name=None, document=None):
        if not file_name and not document:
            return
        self.svc.close_file(file_name=file_name, document=document)

    def close_all(self):
        self.svc.close_all()

    def current_file_saved(self):
        self.svc.file_saved()

    def get_view(self):
        return self.svc.get_view()

    def get_current(self):
        return self.svc.get_current()

    def get_documents(self):
        return self.svc.get_documents()

    def present_view(self):
        view = self.svc.get_view()
        return self.svc.boss.cmd('window', 'present_view',
            view=view)
        view.buffers_ol.grab_focus()

    def get_document_by_id(self, document_id=None):
        if id_:
            return self.svc._documents.get(id_, None)

class BufferDbusConfig(DbusConfig):
    
    @LEXPORT(in_signature='s')
    def open_file(self, file_name):
        self.svc.open_file(file_name)

    @LEXPORT(in_signature='as')
    def open_files(self, files):
        self.svc.open_files(files)
        
    @LEXPORT(in_signature='s')
    def close_file(self, file_name):
        self.svc.close_file(file_name)
        
    @LEXPORT(out_signature='i')
    def get_open_documents_count(self):
        return len(self.svc._documents)

    @LEXPORT(out_signature='a(isiia{ss})')
    def get_documents(self):
        return [
                 (x.unique_id, x.filename, 
                       x.doctype and x.doctype.internal or '', 
                       x.creation_time,
                       # extended values
                       {})
                  for x in self.svc._documents.itervalues()
               ]
               

# Service class
class Buffer(Service):
    """
    Buffer is a graphical manager for editor buffers.
    """ 

    commands_config = BufferCommandsConfig
    actions_config = BufferActionsConfig
    events_config = BufferEventsConfig
    features_config = BufferFeaturesConfig
    dbus_config = BufferDbusConfig
    options_config = BufferOptionsConfig

    def pre_start(self):
        self._documents = {}
        self._current = None
        self._view = BufferListView(self)
        self.get_action('close').set_sensitive(False)
        self._refresh_buffer_action_sensitivities()

    def get_view(self):
        return self._view

    def _refresh_buffer_action_sensitivities(self):
        for action_name in ['switch_next_buffer', 'switch_prev_buffer']:
            self.get_action(action_name).set_sensitive(len(self._documents) > 0)

    def new_file(self, temp_file=False):
        # some editors don't support the new_file feature, so we have to 
        # fall back and create a tmp file
        if temp_file or not 'new_file' in self.boss.editor.features:
            fd, file_name = mkstemp()
            os.close(fd)
            self.open_file(file_name)
        else:
            document = Document(self.boss)
            self._add_document(document)
            self._current = document
            self._view.set_document(document)
            self.boss.editor.cmd('open', document=document)
            self.emit('document-changed', document=document)
            self.emit('document-opened', document=document)

    def open_file(self, file_name=None, document=None, line=None, offset=None):
        if file_name:
            file_name = os.path.realpath(file_name)
        if not document:
            document = self._get_document_for_filename(file_name)
        if document is None:
            if not os.path.isfile(file_name):
                return False
            document = Document(self.boss, file_name)
            self._add_document(document)
        self.view_document(document, line=line, offset=offset)
        self.emit('document-opened', document=document)
        return document

    def open_files(self, files):
        if not files:
            # empty list
            return
        docs = []
        for file_name in files:
            document = Document(self.boss, file_name)
            self._add_document(document)
            docs.append(document)
        self.boss.editor.cmd('open_list', documents=docs)
        for document in docs:
            self.emit('document-opened', document=document)

    def recover_loading_error(self, error):
        # recover from a loading exception
        if error.document:
            filename = error.document.filename
        else:
            filename = ""
        self.notify_user(error.message, title=_("Can't load file %s") % filename )
        self.log('error loading file(s): %s' %error.message)
        if error.document:
            self._remove_document(error.document)
        # switch to the first doc to make sure editor gets consistent
        if self._documents:
            self.view_document(self._documents[self._documents.keys()[0]])
        #self.log.exception(err)

    def close_current(self):
        document = self._current
        if document is not None:
            if self.boss.editor.cmd('close', document=document):
                self._remove_document(document)
                self.emit('document-closed', document=document)

    def close_file(self, file_name = None, document = None):
        if not document:
            document = self._get_document_for_filename(file_name)
        if document is not None:
            if self.boss.editor.cmd('close', document=document):
                self._remove_document(document)
                self.emit('document-closed', document=document)

    def close_all(self):
        docs = self._documents.values()[:]
        for document in docs:
            if self.boss.editor.cmd('close', document=document):
                self._remove_document(document)
                self.emit('document-closed', document=document)
            else:
                break

    def _get_document_for_filename(self, file_name):
        for uid, doc in self._documents.iteritems():
            if doc.filename == file_name:
                return doc

    def _add_document(self, document):
        self._documents[document.unique_id] = document
        self._view.add_document(document)
        self._refresh_buffer_action_sensitivities()

    def _remove_document(self, document):
        "_remove_doc", document
        del self._documents[document.unique_id]
        self._view.remove_document(document)
        self._refresh_buffer_action_sensitivities()

    def view_document(self, document, line=None, offset=None):
        if document is not None and self._current != document:
            self._current = document
            self._current.usage += 1
            self._view.set_document(document)
            try:
                self.boss.editor.cmd('open', document=document)
            except DocumentException, e:
                # document can't be loaded. we have to remove the document from 
                # the system
                self.recover_loading_error(e)
                return
            self.emit('document-changed', document=document)
        if offset is not None:
            if line is not None:
                raise ValueError('Cannot pass offset and line')
            else:
                gcall(self.boss.editor.set_cursor_position, offset)
        elif line is not None:
            gcall(self.boss.editor.goto_line, line)
        self.get_action('close').set_sensitive(document is not None)

    def file_saved(self):
        self.emit('document-saved', document=self._current)

    def get_current(self):
        return self._current

    def get_documents(self):
        return self._documents


# Required Service attribute for service loading
Service = Buffer



# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.