# Copyright (c) 2001 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# 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 of the License, 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.

"""
Horn View contains Memory View and Event View, Scheduler View, Message View
when Horn is connected to Narval
"""

__revision__ = "$Id: HornView.py,v 1.28 2001/12/07 16:01:33 syt Exp $"


from gtk import *
from MemoryView import MemoryView
from EventView import EventView
from MessageView import MessageView
from SchedulerView import SchedulerView
from HornModel import HornModel
from HornCodes import *
from narval.gui import unicode_to_gtk
from DialogWindow import update_gui


class HornView(GtkWindow):
    """
    View of Horn using singleton pattern
    """

    _DICT_ = {}

    def __init__(self):
        self.__dict__ = self._DICT_

        if not self.__dict__ :
            # get methods from horn gui controller
            from HornGuiController import HornGuiController
            hcontroller = HornGuiController()
            
            # configure main window
            GtkWindow.__init__(self,WINDOW_TOPLEVEL,unicode_to_gtk(_("HORN")))
            self.set_policy(TRUE,TRUE,TRUE);
            self.connect("delete_event",hcontroller.callbacks,EXIT)
            self.set_usize(0,400)

            HornModel().attach_observer(self)

            # message variable
            self._message = None
        
            self._vbox = GtkVBox()
            self.add(self._vbox)

            # include menu
            ag = GtkAccelGroup()
            self.factory = GtkItemFactory(GtkMenuBar, "<main>", ag)
            self.add_accel_group(ag)
            menu_struct =[
                (unicode_to_gtk(_('/_File')),                            None,  None,                    0,     '<Branch>'),
                (unicode_to_gtk(_('/_File/_Narval home...')) ,           None,  hcontroller.callbacks,   HORN_NARVAL_HOME,''),
                (unicode_to_gtk(_('/_File/_Install package...')),        None,  hcontroller.callbacks,   INSTALL_PKG,     ''),
                (unicode_to_gtk(_('/_File/_Uninstall package...')),      None,  hcontroller.callbacks,   UNINSTALL_PKG,     ''),
                (unicode_to_gtk(_('/_File/sep2')),                       None,  None,                    0,  '<Separator>'),
                (unicode_to_gtk(_('/_File/_Quit')),              '<control>Q',  hcontroller.callbacks,   EXIT,          ''),
                (unicode_to_gtk(_('/_Narval')),                          None,  None,                    0,     '<Branch>'),
                (unicode_to_gtk(_('/_Narval/_Connect...')),              None,  hcontroller.callbacks,   NARVAL_CONNECT,   ''),
                (unicode_to_gtk(_('/_Narval/_Disconnect')),              None,  hcontroller.callbacks,   NARVAL_DISCONNECT,   ''),
                (unicode_to_gtk(_('/_Narval/S_uspend')),                 None,  hcontroller.callbacks,   NARVAL_SUSPEND, ''),
                (unicode_to_gtk(_('/_Narval/Ste_p by step')),            None,  hcontroller.callbacks,   NARVAL_STEP,    ''),
                (unicode_to_gtk(_('/_Narval/_Continue')),                None,  hcontroller.callbacks,   NARVAL_CONTINUE,''),
                (unicode_to_gtk(_('/_Narval/sep')),                      None,  None,                    0,   '<Separator>'),
                (unicode_to_gtk(_('/_Narval/Save Recipes')),             None,  hcontroller.callbacks,   NARVAL_SVRECIPES,''),
                (unicode_to_gtk(_('/_Narval/Save Transforms')),          None,  hcontroller.callbacks,   NARVAL_SVTRANSF,''),
                (unicode_to_gtk(_('/_Narval/Start plan...')),            None,  hcontroller.callbacks,   NARVAL_START_PLAN,''),
                (unicode_to_gtk(_('/_Narval/Add element...')),           None,  hcontroller.callbacks,   NARVAL_ADD_ELEMENT,''),
                (unicode_to_gtk(_('/_Actions')),                         None,  None,                    ACT,     '<Branch>'),
                (unicode_to_gtk(_('/_Actions/Save cookbook...')),        None,  hcontroller.callbacks,   ACT_SAVE_COOKBOOK,''),
                (unicode_to_gtk(_('/_Actions/Save all cookbooks')),      None,  hcontroller.callbacks,   ACT_SAVEALL_COOKBOOK,''),            
                (unicode_to_gtk(_('/_Actions/sep2')),                    None,  hcontroller.callbacks,   0,'<Separator>'),
                (unicode_to_gtk(_('/_Actions/New recipe...')),           None,  hcontroller.callbacks,   ACT_ADD_RECIPE,''),
                (unicode_to_gtk(_('/_Actions/Edit recipe...')),          None,  hcontroller.callbacks,   ACT_EDIT_RECIPE,''),
                (unicode_to_gtk(_('/_Actions/Remove recipe...')),        None,  hcontroller.callbacks,   ACT_REM_RECIPE,''),
                (unicode_to_gtk(_('/_Actions/Save recipe...')),          None,  hcontroller.callbacks,   ACT_SAVE_RECIPE,''),
                (unicode_to_gtk(_('/_Actions/sep2')),                    None,  hcontroller.callbacks,   0,'<Separator>'),
                (unicode_to_gtk(_('/_Actions/Edit action...')),          None,  hcontroller.callbacks,   ACT_EDIT_ACTION,''),
                (unicode_to_gtk(_('/_Actions/Remove action...')),        None,  hcontroller.callbacks,   ACT_REM_ACTION,''),
                (unicode_to_gtk(_('/_Actions/sep2')),                    None,  hcontroller.callbacks,   0,'<Separator>'),
                (unicode_to_gtk(_('/_Actions/Edit transformation...')),  None,  hcontroller.callbacks,   ACT_EDIT_TRANSF,''),
                (unicode_to_gtk(_('/_Actions/Remove transformation...')),None,  hcontroller.callbacks,   ACT_REM_TRANSF,''),
                (unicode_to_gtk(_('/_Actions/sep2')),                    None,  None,                    0,'<Separator>'),
                (unicode_to_gtk(_('/_Actions/Clean Event Queue')),       None,  hcontroller.callbacks,   ACT_CLEAN_EVTQ,''),
                (unicode_to_gtk(_('/_Actions/Clean Scheduler Queue')),   None,  hcontroller.callbacks,   ACT_CLEAN_SCHQ,''),
                (unicode_to_gtk(_('/_Actions/Clean Message List')),      None,  hcontroller.callbacks,   ACT_CLEAN_MESS,''),
                (unicode_to_gtk(_('/_Options')),                         None,  None,                    OPTIONS,  '<Branch>'),
                (unicode_to_gtk(_('/_Options/_Monitor plans')),          None,  hcontroller.callbacks,   HORN_MONITOR_PLAN, '<ToggleItem>'),
                (unicode_to_gtk(_('/_Options/sep')),                     None,  None,                    0,  '<Separator>'),
                (unicode_to_gtk(_('/_Options/_Preferences...')),         None,  hcontroller.callbacks,   PREFERENCES,   ''),            
                (unicode_to_gtk(_('/_Help')),                            None,  None,                    0, '<LastBranch>'),
                (unicode_to_gtk(_('/_Help/_Help')),                      None,  hcontroller.callbacks,   HELP,          ''),
                (unicode_to_gtk(_('/_Help/_About')),                     None,  hcontroller.callbacks,   ABOUT,         ''),
                ]

            self.factory.create_items(menu_struct)
            self._menubar = self.factory.get_widget('<main>')
            # self._menubar.set_shadow_type(SHADOW_NONE)
            self._vbox.pack_start(self._menubar,expand=FALSE)

            # create notebook
            self._notebook = GtkNotebook()
            self._vbox.pack_start(self._notebook)

            # status bar
            self._status_bar = GtkStatusbar()
            id = self._status_bar.get_context_id('status')
            self._vbox.pack_end(self._status_bar,expand=FALSE)

            # build notebook and message for status bar
            self.build_notebook()

    ### PUBLIC ###

    def build_notebook(self):
        self.arrow_to_watch()
        # first for the local memory
        if HornModel().narval is not None:
            # lock some menu items
            self.factory.get_widget_by_action(NARVAL_CONNECT).set_sensitive(FALSE)
            self.factory.get_widget_by_action(NARVAL_DISCONNECT).set_sensitive(TRUE)
            self.factory.get_widget_by_action(HORN_NARVAL_HOME).set_sensitive(FALSE)
            self.factory.get_widget_by_action(NARVAL_SUSPEND).set_sensitive(TRUE)
            self.factory.get_widget_by_action(NARVAL_STEP).set_sensitive(TRUE)
            self.factory.get_widget_by_action(INSTALL_PKG).set_sensitive(FALSE)
            self.factory.get_widget_by_action(UNINSTALL_PKG).set_sensitive(FALSE)
            self.factory.get_widget_by_action(NARVAL_CONTINUE).set_sensitive(TRUE)
            self.factory.get_widget_by_action(NARVAL_SVRECIPES).set_sensitive(TRUE)
            self.factory.get_widget_by_action(NARVAL_SVTRANSF).set_sensitive(TRUE)
            self.factory.get_widget_by_action(NARVAL_START_PLAN).set_sensitive(TRUE)
            self.factory.get_widget_by_action(NARVAL_ADD_ELEMENT).set_sensitive(TRUE)
            self.factory.get_widget_by_action(ACT_SAVE_COOKBOOK).set_sensitive(FALSE)
            self.factory.get_widget_by_action(ACT_ADD_RECIPE).set_sensitive(FALSE)
            self.factory.get_widget_by_action(ACT_REM_RECIPE).set_sensitive(FALSE)
            self.factory.get_widget_by_action(ACT_SAVE_RECIPE).set_sensitive(FALSE)
            self.factory.get_widget_by_action(ACT_EDIT_ACTION).set_sensitive(TRUE)
            self.factory.get_widget_by_action(ACT_SAVEALL_COOKBOOK).set_sensitive(FALSE)
            self.factory.get_widget_by_action(ACT_REM_ACTION).set_sensitive(TRUE)
            self.factory.get_widget_by_action(ACT_EDIT_TRANSF).set_sensitive(TRUE)
            self.factory.get_widget_by_action(ACT_REM_TRANSF).set_sensitive(TRUE)
            self.factory.get_widget_by_action(ACT_CLEAN_EVTQ).set_sensitive(TRUE)
            self.factory.get_widget_by_action(ACT_CLEAN_SCHQ).set_sensitive(TRUE)
            self.factory.get_widget_by_action(ACT_CLEAN_MESS).set_sensitive(TRUE)
            w = self.factory.get_widget_by_action(HORN_MONITOR_PLAN) 
            w.set_sensitive(TRUE)
            from PrefModel import PrefModel
            w.set_active(PrefModel().monitoring['destroy'])
            self._notebook.remove_page(self._notebook.page_num(MemoryView()))            
            self._notebook.prepend_page(MemoryView(),GtkLabel(unicode_to_gtk(_("Narval Memory"))))

            # append new pages
            self._notebook.append_page(MessageView(),GtkLabel(unicode_to_gtk(_("Messages"))))
            self._notebook.append_page(EventView(),GtkLabel(unicode_to_gtk(_("Event"))))
            self._notebook.append_page(SchedulerView(),GtkLabel(unicode_to_gtk(_("Scheduler"))))

            from HornGuiController import HornGuiController
            self._status_set_text(unicode_to_gtk(_("Connected")\
                                                 +" "+HornGuiController().host\
                                                 +":"+str(HornGuiController().port)))
        else:
            self._notebook.remove_page(self._notebook.page_num(SchedulerView()))
            self._notebook.remove_page(self._notebook.page_num(EventView()))
            self._notebook.remove_page(self._notebook.page_num(MessageView()))
            self._notebook.remove_page(self._notebook.page_num(MemoryView()))
            self._notebook.prepend_page(MemoryView(),GtkLabel(unicode_to_gtk(_("Local Memory"))))

            # lock some items
            self.factory.get_widget_by_action(NARVAL_CONNECT).set_sensitive(TRUE)
            self.factory.get_widget_by_action(NARVAL_DISCONNECT).set_sensitive(FALSE)
            self.factory.get_widget_by_action(HORN_NARVAL_HOME).set_sensitive(TRUE)
            self.factory.get_widget_by_action(NARVAL_SUSPEND).set_sensitive(FALSE)
            self.factory.get_widget_by_action(NARVAL_STEP).set_sensitive(FALSE)
            self.factory.get_widget_by_action(NARVAL_CONTINUE).set_sensitive(FALSE)
            self.factory.get_widget_by_action(NARVAL_SVRECIPES).set_sensitive(FALSE)
            self.factory.get_widget_by_action(NARVAL_SVTRANSF).set_sensitive(FALSE)
            self.factory.get_widget_by_action(NARVAL_START_PLAN).set_sensitive(FALSE)
            self.factory.get_widget_by_action(NARVAL_ADD_ELEMENT).set_sensitive(FALSE)
            self.factory.get_widget_by_action(ACT_SAVE_COOKBOOK).set_sensitive(TRUE)
            self.factory.get_widget_by_action(ACT_SAVEALL_COOKBOOK).set_sensitive(TRUE)
            self.factory.get_widget_by_action(ACT_SAVE_RECIPE).set_sensitive(TRUE)
            self.factory.get_widget_by_action(ACT_ADD_RECIPE).set_sensitive(TRUE)
            self.factory.get_widget_by_action(ACT_REM_RECIPE).set_sensitive(TRUE)
            self.factory.get_widget_by_action(ACT_EDIT_ACTION).set_sensitive(TRUE)
            self.factory.get_widget_by_action(ACT_REM_ACTION).set_sensitive(TRUE)
            self.factory.get_widget_by_action(ACT_EDIT_TRANSF).set_sensitive(TRUE)
            self.factory.get_widget_by_action(ACT_REM_TRANSF).set_sensitive(TRUE)
            self.factory.get_widget_by_action(ACT_CLEAN_EVTQ).set_sensitive(FALSE)
            self.factory.get_widget_by_action(ACT_CLEAN_SCHQ).set_sensitive(FALSE)
            self.factory.get_widget_by_action(ACT_CLEAN_MESS).set_sensitive(FALSE)       
            self.factory.get_widget_by_action(HORN_MONITOR_PLAN).set_sensitive(FALSE)
            self.factory.get_widget_by_action(INSTALL_PKG).set_sensitive(TRUE)
            self.factory.get_widget_by_action(UNINSTALL_PKG).set_sensitive(TRUE)
            
            self._status_set_text(unicode_to_gtk(_("Not connected")))
        self.message_to_view()

    # Observer interface #######################################################    
    def HornModel_update(self,observable,changes):
        if observable.narval is not None:
            from HornGuiController import HornGuiController
            self._status_set_text(unicode_to_gtk(_("Connected")+" "+HornGuiController().host+":"+str(HornGuiController().port)))
        else:
            self._status_set_text(unicode_to_gtk(_("Not connected")))
            
    def PrefModel_update(self, observable, changes):
        for ch in changes:
            if ch[0] == 'destroy':
                w = self.factory.get_widget_by_action(HORN_MONITOR_PLAN)
                w.set_active(ch[1])

    ## CALLBACKS ##############################################################
    def view_to_message(self,message):
        self._notebook.hide()
        self.factory.get_widget_by_action(ACT).set_sensitive(FALSE)
        self.factory.get_widget_by_action(INSTALL_PKG).set_sensitive(FALSE)
        self.factory.get_widget_by_action(UNINSTALL_PKG).set_sensitive(FALSE)
        self.factory.get_widget_by_action(OPTIONS).set_sensitive(FALSE)
        if not self._message:
            self._message = GtkLabel(message)
            self._vbox.pack_start(self._message)
        else:
            self._message.set_text(message)
        self._message.show()

    def message_to_view(self):
        if self._message:
            self._message.hide()
        self._message = None
        self._notebook.show_all()
        self.factory.get_widget_by_action(ACT).set_sensitive(TRUE)
        self.factory.get_widget_by_action(OPTIONS).set_sensitive(TRUE)
        self.watch_to_arrow()

    def arrow_to_watch(self):
        if self.get_window():
            self.get_window().set_cursor(cursor_new(150))
            update_gui()
            
    def watch_to_arrow(self):
        if self.get_window():
            self.get_window().set_cursor(cursor_new(68))
            update_gui()

    ### PRIVATE ###

    def _status_set_text(self,txt):
        self._status_bar.push(self._status_bar.get_context_id('status'),txt)
        update_gui()
