#  PMail - GNOME/GTK/Python email client
#  Copyright (C) 2000 Scott Bender <sbender@harmony-ds.com>

#  This file is part of PMail.

#  PMail 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.

#  PMail 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 GNU Emacs; see the file COPYING.  If not, write to
#  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
#  Boston, MA 02111-1307, USA.  

from gtk import *
import gtk
import GtkExtra
try:
  import gnome
  import gnome.mime
except:
  pass
import os
import string
from popen2 import *

import mail
import config
try:
  import _pmailextensions
except:
  pass
import GladeWindow
import FrontEnd
import XmHTMLMsgWindow
import TextMsgWindow


def center_dialog(dialog, parent = None):
  if parent == None:
    parent = FrontEnd.mainWindow._window  
  _pmailextensions.window_set_parent(dialog._o, parent._o)  
  #dialog.set_position(WIN_POS_CENTER)
  #if not parent:
  #  find the main window
  #print parent._window['x'], parent._window['y']
  #parent = parent.get_toplevel()
  #print parent.get_allocation()


def selected_option(optionMenu):
  a =  optionMenu.get_menu().get_active()
  idx = 0
  for c in optionMenu.get_menu().children():
    if c == a:
      break
    idx = idx + 1
  return idx

def selected_menu_item(menu):
  a =  menu.get_active()
  idx = 0
  for c in menu.children():
    if c == a:
      break
    idx = idx + 1
  return idx, c

def old_get_password(title, message, parent):
    win = GtkExtra._EntryDialog(message, TRUE)
    win.set_title(title)
    center_dialog(win, parent)
    win.show()
    mainloop()
    return win.ret


def __add_option_mailboxes(menu, boxes, ind):
  if boxes and len(boxes):
    for box in boxes:
      item = GtkMenuItem(ind + box.path())
      menu.append(item)
      item.show()
      item.set_data('folder', box)
      __add_option_mailboxes(menu, box.mailboxes(), ind + '    ')
  
def folder_option_menu(omenu=None, do_none=1, exclude_classes=['POPSource'], none_name='None'):
  if not omenu:
    omenu = GtkOptionMenu()
    #menu = GtkMenu()

  menu = GtkMenu()
  
  folders = []
  anyitems = 0
  if do_none:
    item = GtkMenuItem(none_name)
    menu.append(item)
    item.show()
    item.set_data('folder', 'None')
    anyitems  = anyitems + 1

  sources = mail.get_sources()
  for source in sources:
    if not exclude_classes or source.__class__.__name__ not in exclude_classes:
      item = GtkMenuItem(source.name())
      item.set_sensitive(0)
      menu.append(item)
      item.show()
      __add_option_mailboxes(menu, source.mailboxes(), '    ')
      #item.set_data('folder', source)
      anyitems = anyitems + 1

  if anyitems:
    omenu.set_menu(menu)
    menu.show()

  return omenu

def __add_menu_mailboxes(entries, name, action, arg, boxes):
  if boxes and len(boxes):
    for box in boxes:
      e = (name + box.path(), None, action, arg, box)
      entries.append(e)
      __add_menu_mailboxes(entries, name, action, arg, box.mailboxes())
  

def folder_menu_entries(name, action, arg=None, exclude_class='POPSource'):
  entries = []

  if name:
    name = name + '/'
  else:
    name = ''

  sources = mail.get_sources()
  for source in sources:
    if not exclude_class or source.__class__.__name__ != exclude_class:
      __add_menu_mailboxes(entries, name+source.name() + '/', action, arg,
                      source.mailboxes())

  return entries

def fill_option_menu(omenu, strings, menu_data=None):
  if not omenu:
    omenu = GtkOptionMenu()

  menu = GtkMenu()
  omenu.set_menu(menu)
  
  folders = []

  idx = 0
  for s in strings:
    item = GtkMenuItem(s)
    menu.append(item)
    item.show()
    if menu_data:
      item.set_data('data', menu_data[idx])
      idx = idx + 1

  menu.show()

  return omenu
    
    
def select_folder_option(optionMenu, box):
  #print 'selecting:', box
  history = 0
  if box:
    idx = 0
    for c in optionMenu.get_menu().children():
      if c.get_data('folder') == box:
        #print 'found:', c.get_data('folder').path()
        history =  idx
      idx = idx + 1
  optionMenu.set_history(history)
  return history
        

def set_radio(obj, name, value):
  exec 'obj._%s_%s.set_active(1)' % (name, value)

def get_radio(obj, name):
  for i in range(10):
    try: 
      exec 'a = obj._%s_%d.get_active()' % (name, i)
      if a:
        return i
    except AttributeError:
      return None
  
def iconfile_for_mimetype(mime_type):
  pixmap_file =  _pmailextensions.gnome_mime_get_value (mime_type, "icon-filename");

  if not pixmap_file or not os.path.exists(pixmap_file):
    ir = '/usr/share/pixmaps/mc/i-regular.png'    
    if os.path.exists(ir):
      pixmap_file = '/usr/share/pixmaps/mc/i-regular.png'
    else:
      ir = '/usr/local/share/pixmaps/mc/i-regular.png'
      if os.path.exists(ir):
        pixmap_file = ir
      else:
        pixmap_file = _pmailextensions.gnome_mime_get_value ('text/plain', "icon-filename");

  return pixmap_file


def exec_mime_open(type, key, filename):
  #FIXME: will need changes for windows

  opencmd = _pmailextensions.gnome_mime_get_value(type, key)
  needs_terminal = gnome.mime.needsterminal(type, key)

  if opencmd == None:
    opencmd = _pmailextensions.gnome_mime_get_value('text/plain', 'open')


  dir = None
  if string.find(filename, '/') != -1:
    dir, name = os.path.split(filename)
  if not dir:
    dir = ''
  
  s = string.replace(opencmd, '%f', filename)
  s = string.replace(s, '%d', dir)

  idx = string.find(s, '%{')
  while idx != -1:
    ridx = idx + string.find(s[idx:], '}')
    param_name = s[idx+2:ridx]

    val = input_box('Flags', param_name)
    if not val: #canceled
      return
    s = string.replace(s, s[idx:ridx+1], val)
    idx = string.find(s, '%{')

  if needs_terminal:
    s = 'gnome-terminal -e "%s"' % s

  #print s

  popen2('/bin/sh -c \'cd %s; %s\'' % (config.getParam(None, 'Other', 'attachment_dir', '/tmp'), s))


def exec_browser(url):
  #FIXME: will need changes for windows

  type = 'text/html'
  key = 'open'
  opencmd = _pmailextensions.gnome_mime_get_value(type, key)
  needs_terminal = gnome.mime.needsterminal(type, key)

  if opencmd == None:
    self.log_error('Unable to find html viewer in mime-types')
    return

  idx = string.find(opencmd, ' ')
  if idx != -1:
    s = opencmd[:idx]
    s = s + ' ' + url
    if needs_terminal:
      s = 'gnome-terminal -e "%s"' % s
    popen2('/bin/sh -c \'cd %s; %s\'' % (config.getParam(None, 'Other', 'attachment_dir', '/tmp'), s))


__ires = None
def input_box(title="Input Box", message="", value = None,
              modal=TRUE, parent=None):
  def callback(a):
    global __ires
    __ires = a
  global __ires
  __res = None

  if parent == None:
    parent = FrontEnd.mainWindow._window
  
  box = gnome.ui.GnomeRequestDialog(0,
                                    message,
                                    value,
                                    100,
                                    callback,
                                    parent)
  box.set_title(title)
  box.set_modal(1)
  box.run()
  return __ires

__last_dir = None

def file_selection_box(filename = None, title = 'Open', modal=TRUE, parent=None):
  global __last_dir
  if not filename and __last_dir:
    filename = __last_dir
  win = GtkExtra._FileSelection(TRUE)
  center_dialog(win, parent)
  win.set_title(title)
  if filename:
    win.set_filename(filename)
  win.show()
  mainloop()
  res =  win.ret

  if res:
    __last_dir = os.path.split(res)[0] + os.sep

  return res

__pres = None
def get_password(title, message, parent=None):
  def callback(a):
    global __pres
    __pres = a
  global __pres
  __pres = None

  if parent == None:
    parent = FrontEnd.mainWindow._window
  
  box = gnome.ui.GnomeRequestDialog(1,
                                    message,
                                    None,
                                    100,
                                    callback,
                                    parent)
  box.set_title(title)
  box.set_modal(1)
  box.run()
  return __pres
    

__qres = None
def question_box(title, message, parent=None):
  def callback(a):
    global __qres
    __qres = a
  global __qres
  __qres = None

  if parent == None:
    parent = FrontEnd.mainWindow._window
  
  box = gnome.ui.GnomeQuestionDialog(message,
                                    callback,
                                    parent)
  box.set_title(title)
  box.set_modal(1)
  box.run()
  return not __qres

def alert_box(message, parent=None):
  def callback(a):
    global __qres
    __qres = a
  global __qres
  __qres = None

  if parent == None and FrontEnd.mainWindow:
    parent = FrontEnd.mainWindow._window
  
  box = gnome.ui.GnomeErrorDialog(message, parent)
  #box.set_title(title)
  box.set_modal(1)
  box.run()
  return 


__fres = None
__fdone = 0
def select_folder_box(message, selected, title=None, parent=None):
  def callback(a):
    global __fres
    global __fdone
    __fres = a
    __fdone = 1
  global __fres
  global __fdone
  __fres = None
  __fdone = 0
  box = FolderSelector(message, selected, callback, title)
  if parent:
    box.set_parent(parent._window)
  box._window.show()
  while not __fdone:
    mainiteration(0)
  print 'hello'
  return __fres

class FolderSelector(GladeWindow.Window):
  def __init__(self, message, selected, callback, title):
    GladeWindow.Window.__init__(self)

    sigs = { 'ok': self.ok, 'cancel': self.cancel }
    self._glade.signal_autoconnect(sigs)
    self._callback = callback

    self._message.set_text(message)

    self._selected_folder = selected
    folder_option_menu(self._folder_menu, do_none=0)
    self._folder_menu.get_menu().connect('selection_done',
                                         self.folder_selected)
    select_folder_option(self._folder_menu, selected)
    
    if title: self._window.set_title(title)
    

  def ok(self, d):
    self._callback(self._selected_folder)
    self._window.destroy()
    del self

  def cancel(self, d):
    self._callback(None)
    self._window.destroy()
    del self

  def folder_selected(self, d):
    idx, item = selected_menu_item(d)
    folder = item.get_data('folder')
    self._selected_folder = folder
    

# On IRIX we're running Gtk+ version 1.2.3.  On Solaris and Linux we're
# running 1.2.6.
# On Linux, when performing a "manual" event loop to update the display,
# you gotta be careful to release the Gtk+ mutex by calling
# threads_(enter|leave).  If you don't, the app will lock up when it
# checks for pending events.
# On IRIX, you can't call threads_enter, because we're using an old
# version of pygtk which doesn't expose the threads_(enter|leave)
# calls.
# On Solaris, you can't call threads_(enter|leave) because if you do
# the app will lock up when it checks for pending events.
#
# This all seems pretty bogus.  But the following code works...

if 0:
  def update():
    mainiteration(FALSE)
    
elif sys.platform[:5] == "linux":
    def update():
        """Update the UI: flush pending rqsts and process pending events."""
        gtk.gdk_flush()
        #gtk.threads_leave()
        while gtk.events_pending():
            gtk.mainiteration(0)
        #1ugtk.threads_enter()

elif sys.platform[:5] == "sunos":
    def update():
        """Update the UI: flush pending rqsts and process pending events."""
        gtk.gdk_flush()
        while gtk.events_pending():
            gtk.mainiteration(0)

else:
    # For IRIX w. Gtk+ 1.2.3:
    def update():
        """Update the UI: flush pending rqsts and process pending events."""
        # This solution was recommended on the pygtk mailing list, 
        # by Bernhard Herzog <herzog@online.de>, the author of Sketch.
        # Speculation is that this is all due to a bug in recent versions
        # of Gtk+, e.g. 1.2.3 - 1.2.6.
        if hasattr(gtk, "gdk_flush"):
            gtk.gdk_flush()
        if hasattr(gtk, "threads_leave"):
            gtk.threads_leave()
        while gtk.events_pending():
            gtk.mainiteration(0)
        if hasattr(gtk, "threads_enter"):
            gtk.threads_enter()

__gtk_version = None


def gtk_version():
  global __gtk_version
  if not __gtk_version:
    try:
      possibilities = [config.gtk_config,
                       "/usr/bin/gtk_config",
                       "/usr/local/bin/gtk_config"]
      for f in possibilities:
        if os.path.exists(f):
          fm, to = popen2(f + ' --version')
          s = fm.read()
          ss = string.split(s, '\n')
          __gtk_version = ss[0]
    except:
      pass

  if not __gtk_version:
    print 'Could not find gtk-config: put its path into %s, assuming 1.2.6' % \
          os.path.join(config.datadir, 'config/paths.py')
    __gtk_version = '1.2.6'
    
    #sys.exit(2)
  return __gtk_version


def gtk_major():
  return string.atoi(gtk_version()[0])

def gtk_minor():
  return string.atoi(gtk_version()[2])

def gtk_micro():
  return string.atoi(gtk_version()[4])

def get_int_from_text(name, entry):
  txt = entry.get_text()
  try:
    res = string.atoi(txt)
  except ValueError:
    alert_box('Invalid number \'%s\' for %s' % (txt, name))
    return None
  return res
