#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# hylaPEx, an hylafax client written in python
#
# www.unipex.it/hylapex/
#
# License:
# GNU General Public License (GPL)
# For more info see LICENSE.txt and LICENSE-GPL.txt
#
# Copyright (C) 2004-2006 Unipex s.r.l., All Rights Reserved.
# Via Vittorio Veneto 83/A
# 33050 Gonars (UD) - Italy
# phone 0039 0432 931511 - fax 0039 0432 931378
# www.unipex.it - michele.petrazzo@unipex.it
USE_TWISTED_WXREACTOR = 0
import os, sys, pprint, codecs
try:
from pycrash.utils import HTMLPyCrash
usePyCrash = 1
except ImportError:
usePyCrash = 0
#import wxversion
#wxversion.select("2.8")
import wx
print "wx version:", wx.__version__
if not USE_TWISTED_WXREACTOR:
try:
from twisted.internet import threadedselectreactor
print "no twisted threadedselectreactor"
except ImportError:
import threadedselectreactor
threadedselectreactor.install()
else:
from twisted.internet import wxreactor
wxreactor.install()
from twisted.internet import reactor,threads,defer
from operator import itemgetter
from itertools import ifilter
import wx.grid
import sys, os, string, getopt, shutil, time, datetime, webbrowser, tempfile, subprocess, traceback
#utils
from library.utils import empty_tmp_hylapex,del_tmp,ctrl_path_gs,contr_path,read_pref
PATHS = contr_path()
from library.ftp import hylaproto,hylaproto_t
from library import utils
import leng, dlp, wx_util, img_view, p_fb
from library.ftp import read_conf
from library.ftp import filters
import info, threading, thread
from library.options import options
from library.gui import send
from library.observable import Observable
from library.constants import *
from library.db.fax_db_archive import ArchiveDb
from library.named_pipes import named_pipe
from library import alarm
from library import i18n
I18N = i18n.i18n()
import FreeImagePy
if sys.platform.startswith("win"):
from library.send_email_mapi import SendMail
class my_var:
pass
class BT(wx.Button):
def __init__(self, parent, label, eventBind=None, funcBind=None):
super(BT, self).__init__(parent, -1, label)
if eventBind and funcBind:
try:
self.Bind(eventBind, funcBind)
except:
pass
class frm_hylapex(wx.Frame):
def _init_ctrls(self, prnt):
super(frm_hylapex, self).__init__(prnt, -1 )
self.SetBackgroundColour(wx.Colour(235, 235, 235))
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
self.grData = wx_util.sortGrid(self, -1, internalTable=1)
self.grData.CreateGrid(0,0)
self.grData.SetColLabelSize(22)
self.grData.SetRowLabelSize(40)
self.grData.EnableEditing(False)
#I use one because I don't find where are wx.GridSelectRows const
self.grData.SetSelectionMode(1)
#Set the grid rows colors
self.grData.enablePostSortCall(self.setColour)
self.grData.Bind(wx.grid.EVT_GRID_CELL_LEFT_DCLICK, self.OnCellLeftDclick)
self.grData.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK, self.OnCellRightClick)
self.grData.Bind(wx.EVT_KEY_DOWN, self.OnGridCellKey)
self.btNew = BT(self, self.ren.get('btnew'), wx.EVT_BUTTON, self.OnBtNewLClick)
self.btModify = BT(self, self.ren.get('btmodify'), wx.EVT_BUTTON, self.OnBtModify)
self.btSuspend = BT(self, self.ren.get('btsuspend'), wx.EVT_BUTTON, self.OnBtSuspend)
self.btDelete = BT(self, self.ren.get('btdelete'), wx.EVT_BUTTON, self.OnBtDelete)
self.btConfig = BT(self, self.ren.get('btconfig'), wx.EVT_BUTTON, self.OnBtConfig)
self.btInfo = BT(self, self.ren.get('btinfo'), wx.EVT_BUTTON, self.OnBtInfo)
self.btUpdate = BT(self, self.ren.get('btupdate'), wx.EVT_BUTTON, self.OnBtUpdate)
self.btFaxout = BT(self, self.ren.get('btfaxout'), wx.EVT_BUTTON, self.OnBtOut)
self.btFaxin = BT(self, self.ren.get('btfaxin'), wx.EVT_BUTTON, self.OnBtFaxIn)
self.btFaxdone = BT(self, self.ren.get('btfaxdone'), wx.EVT_BUTTON, self.OnBtFaxDone)
self.btFaxbook = BT(self, self.ren.get('btfaxbook'), wx.EVT_BUTTON, self.OnBtFaxBook)
self.btExit = wx.BitmapButton(self, -1, wx.NullBitmap, size=wx.Size(30, 30))
self.btExit.Bind(wx.EVT_BUTTON, self.OnBtExit)
#self.btExit = BT(self, 'Exit', wx.EVT_BUTTON, self.OnBtExit)
self.btInfo.SetForegroundColour(wx.RED) # wx.Colour(166, 9, 52)
self.txtStatus = wx.StaticText(self, -1, '', style = wx.STATIC_BORDER | wx.ST_NO_AUTORESIZE )
self.chk_my = wx.CheckBox(self, -1, self.ren.get('chk_my'))
self.chk_my.Bind(wx.EVT_CHECKBOX, self.OnChk_myCheckbox)
self.chk_autoupdate = wx.CheckBox(self, -1, self.ren.get('chk_autoupdate'))
self.chk_filter_view = wx.CheckBox(self, -1, self.ren.get('chk_filter_view'))
self.chk_filter_view.Bind(wx.EVT_CHECKBOX, self.OnChk_filter_viewCheckbox)
self.chk_autoupdate.Bind(wx.EVT_CHECKBOX, self.OnChk_autoupdate)
self.lblAreon = wx.StaticText(self, -1, self.ren.get('lblareon'))
self.lbl_whereUare = wx.StaticText(self, -1, '')
fontLbl = wx.Font(12,wx.SWISS,wx.NORMAL,wx.BOLD, False, 'Arial')
self.lblAreon.SetFont(fontLbl)
self.lbl_whereUare.SetFont(fontLbl)
self.lblSearch = wx.StaticText(self, -1, self.ren.get('search', 1))
self.lblSearch.SetFont(wx.Font(10,wx.SWISS,wx.NORMAL,wx.BOLD, False, 'Arial'))
self.lblSearch.SetForegroundColour(wx.Colour(23, 48, 217))
self.lblSearch.Bind(wx.EVT_LEFT_DOWN, self.OnLblSearch)
self.btSizer = wx.FlexGridSizer(2,9)
btExitSizer = wx.BoxSizer(wx.HORIZONTAL)
statusSizer = wx.BoxSizer(wx.HORIZONTAL)
chkSizer = wx.BoxSizer(wx.HORIZONTAL)
self.gridSizer = wx.BoxSizer(wx.HORIZONTAL)
self.frameSizer = wx.BoxSizer(wx.VERTICAL)
space = wx.Size(0,0)
self.btSizer.Add(self.lblAreon, 0, wx.ALIGN_CENTER)
self.btSizer.Add(self.lbl_whereUare, 0, wx.ALIGN_CENTER)
self.btSizer.Add(space, 0)
self.btSizer.Add(self.btFaxbook, 1, wx.EXPAND)
self.btSizer.Add(space, 0)
self.btSizer.Add(space, 0)
self.btSizer.Add(space, 0)
self.btSizer.Add(space, 0)
self.btSizer.Add(self.btInfo, 0, 0)
self.btSizer.Add(self.btNew, 0, 0)
self.btSizer.Add(self.btConfig, 0, wx.RIGHT, 5)
self.btSizer.Add(self.btFaxout, 0, wx.LEFT, 5)
self.btSizer.Add(self.btFaxin, 0, wx.EXPAND)
self.btSizer.Add(self.btFaxdone, 0, wx.RIGHT, 5)
self.btSizer.Add(self.btUpdate, 0, wx.LEFT, 5)
self.btSizer.Add(self.btModify, 0, 0)
self.btSizer.Add(self.btSuspend, 0, 0)
self.btSizer.Add(self.btDelete, 0, wx.ALIGN_CENTER)
btExitSizer.Add(self.btSizer, 1, wx.EXPAND)
btExitSizer.Add(self.btExit, 0, wx.ALIGN_CENTER | wx.ALL, 5)
statusSizer.Add(self.txtStatus, 1, wx.EXPAND)
statusSizer.SetMinSize(wx.Size(40, 40))
chkFlags = wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER
chkSizer.Add(self.chk_my, 1, chkFlags, 5)
chkSizer.Add(self.chk_filter_view, 1, chkFlags, 5)
chkSizer.Add(self.chk_autoupdate, 1, chkFlags, 5)
chkSizer.Add(self.lblSearch, 1, wx.ALIGN_CENTER | wx.EXPAND | wx.LEFT, 40)
self.gridSizer.Add(self.grData, 1, wx.EXPAND)
flagFrame = wx.EXPAND | wx.ALL
#self.frameSizer.Add(self.btSizer, 0, flagFrame)
self.frameSizer.Add(btExitSizer, 0, flagFrame, 5)
self.frameSizer.Add(statusSizer, 0, flagFrame, 5)
self.frameSizer.Add(chkSizer, 0, flagFrame, 5)
self.frameSizer.Add(self.gridSizer, 1, wx.BOTTOM | wx.RIGHT | wx.LEFT | wx.EXPAND, 10)
self.frameSizer.SetMinSize(wx.Size(300,300))
self.SetSizerAndFit(self.frameSizer)
self.CenterOnScreen()
if not sys.platform.startswith("win") and not USE_TWISTED_WXREACTOR:
wx.FutureCall(100, self._call_me)
def _call_me(self):
try:
wx.GetApp().ProcessIdle()
except:
return
try:
wx.FutureCall(100, self._call_me)
except:
pass
def __init__(self, parent, paths):
"""
"""
self._closing = False
self.paths = paths
self.__doc = Observable()
self.__doc.attach(self)
if usePyCrash:
msgForWrite = "Enable PyCrash"
if self._debug1: self._do_debug(msgForWrite)
self.MyCrash = HTMLPyCrash({'AppName': 'Hylapex',
'Version':'2.1.2', 'SendTo': 'Michele Petrazzo'})
self.MyCrash.enable()
self.ren = wx_util.rename_ctrls(self, 'hylapex', self.paths.my_path,
lang = self.paths.language)
self.ren.rename()
self._time = time.time()
self._update_on_air = False
self._update_on_air_db = False
self._time_db_fax = 0
self._init_ctrls(parent)
icon = wx.Icon(os.path.join(self.paths.imgs_dir, 'fax.ico'),wx.BITMAP_TYPE_ICO)
self.SetIcon(icon)
self.offline = 0
self.view_fax = None
self.order = ()
#External filters for data
self._externalFilters = filters.HylapexFilters(1,
file_path=self.paths.file_conf_filters)
self.my_init()
#4 my egg
self.mic = ''
self.fb = ''
dict_img = {self.btExit: 'out.png',}
for inst_but in dict_img:
f = os.path.join(self.paths.imgs_dir, dict_img[inst_but])
#i = wx_util.del_mask2img(f)
inst_but.SetBitmapLabel( wx.Bitmap(f) )
def my_init(self):
"""
"""
del_tmp(self.paths)
self.myleng = leng.l(self.paths)
self.paths.frame_inst = self
#Rename
self._raname_ctrls()
#some vars
self._f_email = None
self._f_send_fax = None
self._f_alarm = None
#Fax server
self.opt_cls = read_conf.conf_parser(self.paths.file_conf_gen,'hylapex')
self.opt_cls.exist()
#Ctrl debug
self._ctrl_debug()
#ctrl options
utils.ctrl_opt_cls_hylapex(self.opt_cls)
self.view = self.opt_cls.get('view')
self.view_prev = self.view
self._opt_date_time = read_conf.conf_parser(self.paths.file_db_DT_rcv,'datetime')
self._opt_lang = read_conf.conf_parser(I18N.fileName, "hylapex")
self._opt_lang.exist()
if self._opt_date_time.exist():
self._opt_date_time.init_sections('datetime')
#Need for backward compatibility
if self.view in VIEW_DICT.values():
self.view = VIEW_RECEIVE
else:
self.view = self.opt_cls.getint('view')
#only for the first time
if not self.view in (VIEW_DONE, VIEW_RECEIVE, VIEW_SEND):
self.view = VIEW_SEND
#Buffer for store the grid data, [data, self.view]
self.bufferGridData = [None, None]
#The search Frame
self.searchFrame = None
self._db_fax_usage = self.opt_cls.getint("db_archive_rcv_usage")
#Load data into self._hy
self._load_srv_hy()
#Load terminal server
self._init_terminal_server()
#Set filter view
self.chk_filter_view.SetValue(
self.opt_cls.getint("chk_filter_%s" % VIEW_DICT[self.view]) )
#Only my fax
chk_priv = self.opt_cls.getint('chk_priv')
if chk_priv:
self.chk_my.SetValue(True)
self._hy.SetFilterOptView("own", True, self.view)
#Init fax db seen
self.__init_fax_db_seen()
#Buffer status message
self._statusMessage = ""
# Set autoupdate
self.chk_autoupdate.SetValue( self.opt_cls.getint("txt_autoupdate") )
#Set the popup menu for the grid
my_var.pop_grid_evt_call = 0
# Update the state of fax
self.view_as_changed = 0
self._firstUpdateDone = 0
self.pop_gr_fb_add = wx.NewId()
self.pop_gr_update = wx.NewId()
self.pop_gr_resend = wx.NewId()
self.pop_gr_send_mail = wx.NewId()
self.pop_gr_suspend = wx.NewId()
self.pop_gr_modify = wx.NewId()
self.pop_gr_delete = wx.NewId()
self.pop_gr_save_pdf = wx.NewId()
self.pop_gr_save_jpg = wx.NewId()
self.pop_gr_save_list = wx.NewId()
self.pop_gr_save_qfile = wx.NewId()
self.pop_gr_show_report = wx.NewId()
self.pop_gr_fax_alarm_new = wx.NewId()
self.pop_gr_fax_alarm_modify = wx.NewId()
self.pop_gr_fax_alarm_delete = wx.NewId()
if self._db_fax_usage:
self.pop_gr_db_rcv_modify = wx.NewId()
self.Bind(wx.EVT_MENU, self.pop_gr_fb_add_evt, id=self.pop_gr_fb_add)
self.Bind(wx.EVT_MENU, self.pop_gr_update_evt, id=self.pop_gr_update)
self.Bind(wx.EVT_MENU, self.pop_gr_resend_evt, id=self.pop_gr_resend)
self.Bind(wx.EVT_MENU, self.pop_gr_send_mail_evt, id=self.pop_gr_send_mail)
self.Bind(wx.EVT_MENU, self.pop_gr_suspend_evt, id=self.pop_gr_suspend)
self.Bind(wx.EVT_MENU, self.pop_gr_modify_evt, id=self.pop_gr_modify)
self.Bind(wx.EVT_MENU, self.pop_gr_delete_evt, id=self.pop_gr_delete)
self.Bind(wx.EVT_MENU, self.pop_gr_save_pdf_evt, id=self.pop_gr_save_pdf)
self.Bind(wx.EVT_MENU, self.pop_gr_save_jpg_evt, id=self.pop_gr_save_jpg)
self.Bind(wx.EVT_MENU, self.pop_gr_save_list_evt, id=self.pop_gr_save_list)
self.Bind(wx.EVT_MENU, self.pop_gr_save_qfile_evt, id=self.pop_gr_save_qfile)
self.Bind(wx.EVT_MENU, self.pop_gr_show_report_evt, id=self.pop_gr_show_report)
self.Bind(wx.EVT_MENU, self.pop_gr_fax_alarm_new_evt, id=self.pop_gr_fax_alarm_new)
self.Bind(wx.EVT_MENU, self.pop_gr_fax_alarm_modify_evt, id=self.pop_gr_fax_alarm_modify)
self.Bind(wx.EVT_MENU, self.pop_gr_fax_alarm_delete_evt, id=self.pop_gr_fax_alarm_delete)
if self._db_fax_usage:
self.Bind(wx.EVT_MENU, self.pop_gr_db_rcv_modify_evt, id=self.pop_gr_db_rcv_modify)
##
## Init methods
##
def _raname_ctrls(self):
self.ren.rename()
def _load_srv_hy(self):
"""Load hylafax server"""
#passwd
passwd = self.opt_cls.get('txt_pass')
#adminpass
adminpasswd = self.opt_cls.get('txt_passwd_admin')
#Time zone option
opt_tzone = 'chk_local_time_zone'
#Time update
timeUpdate = self.opt_cls.getint('txt_update')
srv = self.opt_cls.get('txt_server')
passive = self.opt_cls.getint('chk_passive')
user = self.opt_cls.get('txt_user')
tzone = self.opt_cls.getint(opt_tzone)
filterSnd, filterDone, filterRcv = self._get_filter_hylafax()
#Solve a little issue with the
dateTimeRcv = {}
for k, data in self._opt_date_time.get_items_dict().iteritems():
dateTimeRcv[k] = map(int, self._opt_date_time.getList(k))
cover_not_use = (self.opt_cls.has_option("chk_use_cover") and
self.opt_cls.getint("chk_use_cover") == 0)
if cover_not_use:
## hack ##
# user want to see the to_location field as regardin
if "to_pers" in hylaproto_t.DONE_ORDER:
hylaproto_t.DONE_ORDER[ hylaproto_t.DONE_ORDER.index("to_pers") ] = 'loc'
if "to_pers" in hylaproto_t.SEND_ORDER:
hylaproto_t.SEND_ORDER[ hylaproto_t.SEND_ORDER.index("to_pers") ] = 'loc'
## bad hack ##
if "to_pers" in leng.l.send.order:
leng.l.send.order[leng.l.send.order.index("to_pers") ] = 'loc'
leng.l.send.text["loc"] = "Subject"
if "to_pers" in leng.l.done.order:
leng.l.done.order[leng.l.done.order.index("to_pers") ] = 'loc'
leng.l.done.text["loc"] = "Subject"
d_hfax = {"callBackOnStatus": self._updateStatus,
"dateTimeRcv": dateTimeRcv, "advancedFilters":self._externalFilters,
"debug": self.opt_cls.getint("txt_debug"), "debugFunct":self._do_debug,
}
if self._debug1: self._do_debug("Load hylafax server and fetch data with ftp protocol")
if self._debug2: self._do_debug(time=1)
self._hy = hylaproto_t.HylafaxProto(srv, user, passwd, adminpasswd, passive,
tzone, self._updateFromSrv, self.__srv_err, timeUpdate,
filterSnd, filterDone, filterRcv,
**d_hfax)
self._last_db_rcv = []
if self._db_fax_usage:
d_hfax["fetch_view"] = hylaproto_t.RCV_VIEW
wx.CallAfter(self._load_fax_db)
self._load_srv_hy_old()
self._lastIDFaxRecvBuf = []
def _get_filter_hylafax(self):
""" Return the receive, send and done filter for the server
"""
filterSnd, filterDone, filterRcv = {}, {}, {}
filterNum = self.opt_cls.getint("txt_filter_number")
filterDate = self.opt_cls.getint("txt_filter_days")
lstFilter = ((filterSnd, "receive"), (filterDone, "receive"), (filterRcv, "receive"),)
for d, val in lstFilter:
if not self.opt_cls.getint("chk_filter_" + val): continue
d["n"] = filterNum
d["d"] = filterDate
return filterSnd, filterDone, filterRcv
def _load_fax_db(self):
""" Load the db where fax are stored
"""
if self._debug1: self._do_debug("Load the db where fax are stored")
try:
db_type = self.opt_cls.getint("db_archive_rcv_type")
load_vals = self.opt_cls.get("db_archive_rcv_vals")
self._db_fax = ArchiveDb(load_vals, db_type)
#set the filter, if need
if self.opt_cls.getint("chk_filter_%s" % VIEW_DICT[VIEW_RECEIVE]):
self._db_fax.SetFilterActiveView(1, VIEW_RECEIVE)
#go for an update
self._db_fax_force_update()
except:
self._db_fax = None
msg = traceback.format_exc()
self.__generic_error(msg)
def _load_srv_hy_old(self):
self.hy = hylaproto.Hylafax(self.opt_cls.get('txt_server'),
passive=self.opt_cls.getint('chk_passive'))
self.hy.username = self.opt_cls.get('txt_user')
#Time zone option
opt_tzone = 'chk_local_time_zone'
self.hy.tzone = self.opt_cls.getint(opt_tzone)
#passwd
if self.opt_cls.get('txt_pass') != '': self.hy.password = self.opt_cls.get('txt_pass')
#adminpass
if self.opt_cls.get('txt_passwd_admin') != '': self.hy.adminpass = self.opt_cls.get('txt_passwd_admin')
#self.newHy = newHylaproto()
def __init_fax_db_seen(self):
""" Load the fax db seen
"""
self.fax_db_seen = read_conf.conf_parser(self.paths.file_fax_control, 'fax_receive')
if self.fax_db_seen.exist():
self.fax_db_seen.init_sections(('fax_receive', 'fax_done', 'fax_alarm'))
if not self.fax_db_seen.has_section("fax_alarm"):
self.fax_db_seen.add_section("fax_alarm")
self._db_fax_alarm = alarm.FaxAlarm(self.fax_db_seen)
self._db_fax_alarm.clean_old_alarms()
#
# Right-click event methods
#
def pop_gr_fb_add_evt(self, event):
""" Add the select fax number into the faxbook
"""
row = my_var.pop_grid_evt.GetRow()
rows = self.grData.GetSelectedRows()
if not rows:
rows = (row, )
data_complete = []
for row in rows:
if self.view == VIEW_RECEIVE:
if 'snd' in self.order:
datapass = self.grData.GetCellValue(row, self.order.index('snd'))
else:
return
else:
company = self.grData.GetCellValue(row, self.order.index('comp'))
num = self.grData.GetCellValue(row, self.order.index('num'))
datapass = (company, num)
data_complete.append(datapass)
if not self.fb:
self.fb = frm_fax_book(self, self.paths, fax2add=data_complete)
else:
self.fb.p_fb._add_line(data_complete)
self.fb.Raise()
def pop_gr_resend_evt(self, event):
row = my_var.pop_grid_evt.GetRow()
del my_var.pop_grid_evt
if row == -1:
return
tof = self.__getfile(row)
if tof == F_TYPE_NONE: return
self.txt, self.dim, self.val, self.order = self.myleng.ret(self.view)
if tof in (4,9):
file_path = self.paths.temp_file_tiff
else:
file_path = self.paths.temp_file_ps
frm_snd = self._add_new_send_file(file_path)
if self.view == VIEW_DONE:
frm_snd.gr_dest.AppendRows()
company = self.grData.GetCellValue(row,self.order.index('comp'))
number = self.grData.GetCellValue(row,self.order.index('num'))
#Prefix control
prefix = self.opt_cls.get('txt_prefix')
if prefix and number.startswith(prefix): number = number[ len(prefix): ]
frm_snd.gr_dest.SetCellValue(0, 0, company)
frm_snd.gr_dest.SetCellValue(0, 1, number)
#frm_snd.tctrl_subject.SetValue(subject)
frm_snd.Show(True)
def pop_gr_send_mail_evt(self, evt):
""" Send email
"""
if self._debug1: self._do_debug("Send email")
if self._debug2: self._do_debug("rd_smtp_ext_prog %s" % self.opt_cls.getint("rd_smtp_ext_prog"))
if self._debug2: self._do_debug("rd_smtp_local %s" % self.opt_cls.getint("rd_smtp_local"))
if self._debug2: self._do_debug("rd_smtp_hylapex %s" % self.opt_cls.getint("rd_smtp_hylapex"))
row, _, _ = self._get_gr_row_rcv_rc()
file_save = None
if self._f_email:
file_save = self._create_temp_file('tiff')
else:
file_save = self.paths.temp_file_tiff
if not self.__getfile(row, file_save):
return
self.__save_tiff2pdf('-o', file_save + ".pdf", file_save)
file_save = file_save + ".pdf"
if self.opt_cls.getint("rd_smtp_ext_prog"):
txt_ext_path = self.opt_cls.get("txt_smtp_ext_path").replace("%email_attach%", file_save)
values = [str(x.strip()) for x in txt_ext_path.split("'") if x.strip()]
if not values:
return
msgForWrite = "I'll send email and execute: %s" % " ".join(values)
if self._debug1: self._do_debug(msgForWrite)
try:
cmd = subprocess.Popen(values, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE)
out, err = cmd.communicate()
cmd.wait()
except:
msg = traceback.format_exc()
self.__generic_error(msg, self.ren.get('_error_generic_title'))
return
elif not sys.platform.startswith("win") or self.opt_cls.getint("rd_smtp_hylapex"):
if self._f_email:
self._f_email.add_fax(file_save)
else:
self._f_email = e_mail_frame.EMailFrame(self, self.opt_cls, (file_save, ))
else:
show_err = 0
try:
SendMail("", attachfiles=file_save)
except WindowsError:
msg_err = traceback.format_exc()
print "ERROR on send email with null sender. Try with a fake one"
if "MAPI error 25" in msg_err:
try:
SendMail("null@null.com", attachfiles=file_save)
except:
msg_err = traceback.format_exc()
show_err = 1
else:
show_err = 1
if show_err:
self.__generic_error(msg, self.ren.get('_error_generic_title'))
def pop_gr_db_rcv_modify_evt(self, evt):
""" Modify the values for the db fax received
"""
if self._debug1: self._do_debug("pop_gr_db_rcv_modify_evt")
self.txt, self.dim, self.val, self.order = self.myleng.ret(self.view)
row, img_idx, file_ = self._get_gr_row_rcv_rc()
found = 0
for num, line in enumerate(self._last_db_rcv):
#look if we have the data (that normally are true) and save a lot of time!
if line and line[img_idx] == file_:
found = 1
row = num
break
if found:
#found the data, not need to retrieve it
dta = self._last_db_rcv[row]
else:
if not self._db_fax:
return
dta = self._db_fax.get_rcv_fields_data(self.opt_cls.get("db_archive_rcv_grid"),
file_name=file_)[0]
#fetch the column names and read only flags
val_names, _, _, order = self._get_col_gr_values()
read_only = self._get_col_gr_values_lst(self.view)[3]
#go for modify
self._f_modify_fax_data = db_rcv_modify.ModifyFaxData(self, val_names, dta, read_only,
self._cb_db_rcv_modify_frame, order)
def _cb_db_rcv_modify_frame(self, dta):
""" Callback from modify frame
"""
if self._debug1: self._do_debug("Callback from modify frame")
if self._debug3: self._do_debug(dta)
fax_id = dta["img"]
self._db_fax.set_recv_field_data(fax_id, dta)
self.fax_db_seen.set(fax_id, 1)
new_dta = self._db_fax.get_rcv_fields_data(self.opt_cls.get("db_archive_rcv_grid"),
file_name=fax_id)[0]
for num, line in enumerate(self.bufferGridData[0]):
if line[0] == fax_id:
break
else:
return
self.grData.setRowData(num, new_dta)
#self.bufferGridData[0][num] = new_dta
self._last_db_rcv[num] = new_dta
#self._db_fax_force_update(True)
def pop_gr_update_evt(self, event):
self.OnBtUpdate(my_var.pop_grid_evt)
def pop_gr_suspend_evt(self, event):
row = my_var.pop_grid_evt.GetRow()
if not row == -1:
self.txt, self.dim, self.val, self.order = self.myleng.ret(self.view)
my_var.jobid_modify = self.grData.GetCellValue(row,self.order.index('id'))
my_var.jobstatus_modify = self.grData.GetCellValue(row, self.order.index('stat'))
self.OnBtSuspend(my_var.pop_grid_evt)
def pop_gr_modify_evt(self, event):
self.OnBtModify(my_var.pop_grid_evt)
def pop_gr_delete_evt(self, event):
self.OnBtDelete(my_var.pop_grid_evt)
def pop_gr_save_pdf_evt(self, event):
row = my_var.pop_grid_evt.GetRow()
if row == -1: return
self.__SaveFaxAs('pdf', row)
def pop_gr_save_list_evt(self, event):
"""Respond to the save the list and delete command
"""
lst = self.grData.GetSelectedRows()
if not lst: return
dlg = wx.DirDialog(self, self.ren.get("_select_dest_dir"), "./",
wx.DD_NEW_DIR_BUTTON)
if dlg.ShowModal() == wx.ID_CANCEL:
dlg.Destroy()
return
path = dlg.GetPath()
dlg.Destroy()
if not path: return
self.progFrame = ProgressFrame(self, len(lst))
self.progFrame.Show()
thread.start_new_thread(self.__saveLstMessageAndDelete, (lst, path ))
def pop_gr_save_qfile_evt(self, evt):
""" Save the qfile (log file)
"""
row, _, _ = self._get_gr_row_rcv_rc()
if row == -1: return
path_file = self.opt_cls.get("path_save_qfile")
path_file = os.path.abspath(path_file)
dlg = wx.FileDialog(self, self.ren.get('choose_file', 1), path_file, "hylafax_log_",
"", wx.SAVE)
filename = ''
try:
if dlg.ShowModal() == wx.ID_OK:
filename = dlg.GetPath()
finally:
dlg.Destroy()
if filename == '': return
self.opt_cls.set("path_save_qfile", os.path.dirname(filename))
self._save_qfile(filename, row)
def _save_qfile(self, filename, row=None):
""" Save he qfile on the given filename
"""
if row is None:
row, _, _ = self._get_gr_row_rcv_rc()
if row == -1: return 1
id_ = self.grData.GetCellValue(row, self.order.index('id'))
status, msg = self.hy.get_recvfile('q' + id_, filename , 'doneq')
if self.ctrl_ret_hy((status, msg)):
return
def _create_report_msg(self, row, q_path_out):
"""
"""
data_report_user =self.opt_cls.get("gr_report")
date_time_format = self.opt_cls.get("txt_report_date_hour")
img_idx = self.order.index('id')
file_id = self.grData.GetCellValue(row, img_idx)
if self._save_qfile(q_path_out, row):
return ""
for q_row in open(q_path_out):
q_data, q_value = map(string.strip, q_row.split(":", 1))
if q_data in ("tts", "killtime") and date_time_format != "":
try:
q_value = time.strftime(date_time_format, time.localtime(int(q_value)) )
except:
print traceback.format_exc()
pass
try:
data_report_user = data_report_user.replace("%%%s%%" % q_data, q_value)
except:
print "Error on replace data on pop_gr_show_report_evt", data_report_user, q_data, q_value
return
status = self.grData.GetCellValue(row, self.order.index('stat'))
other = self.myleng.ret('other')
valFound = VIEW_DICT[self.view]
if status in other[valFound]['stat']:
value = status
elif status in other[valFound]['stat'].itervalues():
value = [k for k, v in other[valFound]['stat'].iteritems() if v == status] [0]
else:
return
str_msg_ok = "%msg_ok%"
str_msg_fail = "%msg_failed%"
if value == "F":
#fax failed
data_report_user = data_report_user.replace(str_msg_fail, self.opt_cls.get("txt_report_msg_failed"))
data_report_user = data_report_user.replace(str_msg_ok, "")
else:
data_report_user = data_report_user.replace(str_msg_ok, self.opt_cls.get("txt_report_msg_ok"))
data_report_user = data_report_user.replace(str_msg_fail, "")
return os.linesep.join(data_report_user.replace("\n", "").split(";;;")) + os.linesep
def pop_gr_show_report_evt(self, evt):
""" Show the report according the configuration
"""
path_out = self._create_temp_file(ext="txt")
q_path_out = self._create_temp_file(ext="txt")
f_out = codecs.open(path_out, 'w', encoding="utf8", errors="replace")
sel_rows = self.grData.GetSelectedRows()
if not sel_rows:
sel_rows = [my_var.pop_grid_evt.GetRow()]
msg_out = [self._create_report_msg(row, q_path_out) for row in sel_rows]
exe_report = self.opt_cls.get("txt_exe_report")
f_out.write( (os.linesep + self.opt_cls.get("txt_report_page_separator") + os.linesep*2).join( msg_out ) )
f_out.close()
if sys.platform.startswith("win") and exe_report.count("%") == 2:
#expand vars
var_name, path_exe = exe_report[1:].split("%")
exe_report = os.getenv(var_name)
exe_report = exe_report + path_exe
if exe_report:
try:
subprocess.call([exe_report, path_out])
except:
self.__generic_error("%s\n%s" % ([exe_report, path_out], traceback.format_exc()))
else:
try:
os.system(path_out)
except:
self.__generic_error("%s" % (path_out, traceback.format_exc()))
def pop_gr_save_jpg_evt(self, event):
row = my_var.pop_grid_evt.GetRow()
if row == -1: return
self.__SaveFaxAs('png', row)
def pop_gr_fax_alarm_modify_evt(self, evt):
""" Set or reset the alarm for this fax
"""
id_fax = self._get_fax_id_rc_event()
self._db_fax_alarm.f_modify_alarm(self, id_fax)
def pop_gr_fax_alarm_new_evt(self, evt):
""" Set the alarm for this fax
"""
id_fax = self._get_fax_id_rc_event()
self._db_fax_alarm.f_add_alarm(self, id_fax)
def pop_gr_fax_alarm_delete_evt(self, evt):
""" Delete the alarm fax
"""
id_fax = self._get_fax_id_rc_event()
self._db_fax_alarm.delete_alarm(id_fax)
#
# Event methods
#
def OnClose(self, event=None):
""" User wants to go home :)
"""
self._closing = True
self._close_terminal_server()
reactor.addSystemEventTrigger('after', 'shutdown', self.internalClose, True)
try:
reactor.stop()
msgForWrite = 'ok, start shutdown'
if self._debug1: self._do_debug(msgForWrite)
except:
pass
def OnMouseWheel(self, event):
""" Respond to the scroll mouse
"""
if event.GetWheelRotation() < 0:
self.grData.ScrollLines(2)
else:
self.grData.ScrollLines(-2)
def OnBtOut(self, event):
self._onBtChangeView(VIEW_SEND)
def OnBtFaxIn(self, event):
self._onBtChangeView(VIEW_RECEIVE)
def OnBtFaxDone(self, event):
self._onBtChangeView(VIEW_DONE)
def _onBtChangeView(self, viewFrom):
"""
"""
# If is re-press the same button, only reload
if self.view == viewFrom:
ret = self.agg_view()
else:
self.view_as_changed = True
self.view_prev = self.view
self.view = viewFrom
if viewFrom == VIEW_SEND: _str = "send"
elif viewFrom == VIEW_RECEIVE: _str = "receive"
else: _str = "done"
val_f = self.opt_cls.getint('chk_filter_' + _str)
self.chk_filter_view.SetValue(val_f)
if self._db_fax_usage:
self._db_fax.SetFilterActiveView(val_f, viewFrom)
self._hy.SetFilterActiveView(val_f, viewFrom)
self._fakeUpdate()
def OnBtUpdate(self, event=None):
"""
"""
if self._debug1: self._do_debug("Ob bt update")
my_var.pop_grid_evt_call = 0
if not self._update_on_air:
self._hy.UpdateAll()
self._update_on_air = True
self._update_on_air_db = True
def OnBtModify(self, event):
if not self.view == VIEW_SEND: return
#Modify the job
if my_var.pop_grid_evt_call:
row = my_var.pop_grid_evt.GetRow()
#Here no unset pop_grid_evt_call because
#if we are in send, we must call suspend before
#Suspend_event unset the var.
else:
rows = self.grData.GetSelectedRows()
if not rows: return
row = rows[0]
if row == -1: return
self.txt, self.dim, self.val, self.order = self.myleng.ret(self.view)
my_var.jobid_modify = self.grData.GetCellValue(row,self.order.index('id'))
my_var.jobstatus_modify = self.grData.GetCellValue(row, self.order.index('stat'))
number = self.grData.GetCellValue( row, self.order.index('num') )
company = self.grData.GetCellValue(row, self.order.index('comp') )
prefix = self.opt_cls.get('txt_prefix')
if prefix:
number = number[ len(prefix): ]
mod_frm = modify_frame.create(self, (number, company) ).Show(True)
def OnBtSuspend(self, event):
if not self.view == VIEW_SEND: return
#If called from popup, get id's job from my_var
if my_var.pop_grid_evt_call:
jobid = my_var.jobid_modify
my_var.pop_grid_evt_call = 0
else:
rows = self.grData.GetSelectedRows()
if not rows: return
row = rows[0]
if row == -1: return
jobid = self.grData.GetCellValue(row,0)
self.txt = self.myleng.ret('other')
if my_var.jobstatus_modify == self.txt['send']['stat']['T']:
return
busy = wx.BusyInfo(self.ren.get('_suspend_busy'))
self._hy.SuspendJob(jobid)
#self.ctrl_ret_hy((status, msg))
#self.OnBtUpdate('')
def OnBtDelete(self, event):
""" Respond to the delete
"""
#if self.view == 'receive': return
#If called from popup, get row from my_var
if my_var.pop_grid_evt_call:
#Here no unset pop_grid_evt_call because
#if we are in send, we must call suspend
#Suspend event unset the var.
rows = [my_var.pop_grid_evt.GetRow()]
else:
rows = self.grData.GetSelectedRows()
if not rows or rows[0] == -1:
return
if self._dlg_delete_fax(rows) == wx.ID_NO:
return
self._delete_fax_file(rows)
def OnCellLeftDclick(self, event):
""" Open the file that you click on
"""
if self._debug1: self._do_debug("Open the file that you click on")
row = event.GetRow()
if self._debug1: self._do_debug("Fecth the row %s" % row)
tof = self.__getfile(row)
if tof == F_TYPE_NONE: return
self.ctrl_ret_img_view()
if self.view == VIEW_DONE:
company = self.grData.GetCellValue(row, self.order.index('comp'))
fax_num = self.grData.GetCellValue(row, self.order.index('num'))
fax_date = self.grData.GetCellValue(row, self.order.index('dat'))
status = self.grData.GetCellValue(row, self.order.index('stat'))
stat = self.ren.get('_outcome') +': ' + status.upper()
date = self.ren.get('_date_time') +': ' + fax_date
text = self.ren.get('_fax_send_to') +': ' + company +' - '+ 'fax n: ' + fax_num
prt = [date, text, stat]
#Don't want to print the top message
if self.opt_cls.getint("chk_print_str"):
prt = None
self.view_fax.view_file(tof, text4print = prt)
else:
self.view_fax.view_file(tof)
if self.view == VIEW_RECEIVE:
fax_id = self.grData.GetCellValue(row, self.order.index('img'))
self.fax_db_seen.set(fax_id, 1)
self.setColour()
def _open_popup_on_new_btn(self):
""" opens a popup menu when the user clicks on the new fax button
"""
# menu creation
menu = wx.Menu()
# menu items ids
self.popup_with_file_ID = wx.NewId()
self.popup_only_cover_ID = wx.NewId()
# menu items binding
self.Bind(wx.EVT_MENU, self._on_popup_with_file,
id=self.popup_with_file_ID)
self.Bind(wx.EVT_MENU, self._on_popup_only_cover,
id=self.popup_only_cover_ID)
# adding items
menu.Append(self.popup_with_file_ID, self.ren.get("send_fax_with_file"))
menu.Append(self.popup_only_cover_ID, self.ren.get("send_only_cover"))
# popping up the menu :)
self.PopupMenu(menu)
menu.Destroy()
def _open_send_gui(self, only_cover=False):
""" opens the send frame
"""
filename = ''
if not only_cover:
path_file = self.opt_cls.get("path_new_file")
path_file = os.path.abspath(os.path.dirname(path_file))
dlg = wx.FileDialog(self, self.ren.get('choose_file', 1), path_file, "",
"Acrobat and Postscript (*.ps;*.pdf)|*.ps;*.pdf|Tiff(*.tiff;*.tif)|*.tiff;*.tif", wx.OPEN)
try:
if dlg.ShowModal() == wx.ID_OK:
filename = dlg.GetPath()
finally:
dlg.Destroy()
if not filename:
return
self.opt_cls.set("path_new_file", filename)
self._add_new_send_file(filename)
def OnBtNewLClick(self, evt):
""" left click on "New" button
"""
evt.Skip()
self._open_popup_on_new_btn()
def _on_popup_with_file(self, evt):
""" send fax with file, so open the file dialog to
choose the file
"""
self._open_send_gui()
def _on_popup_only_cover(self, evt):
""" send only the cover, so don't open the file dialog
"""
self._open_send_gui(only_cover=True)
def OnBtConfig(self, event):
"""Open the optrion-frame
"""
#self.view_as_changed = True
#self._save_col_size()
#self.view_as_changed = False
frm_options = options.frm_opt(self, self.opt_cls, self.paths, self.all_fax_view)
frm_options.CenterOnParent()
frm_options.Show(True)
def OnChk_myCheckbox(self, event):
self._hy.SetFilterOptView("own", event.GetInt(), self.view)
self._fakeUpdate()
def OnKeyDown(self, event):
# My eggs
try:
self.mic = self.mic + chr(event.GetKeyCode())
except:
self.mic = self.mic + '1'
if self.mic == 'MICHELE':
wx.MessageBox("Bravo, mi hai scoperto...." +
'\nPer informazioni, contattami.\nmichele.petrazzo@unipex.it',
"Complimenti",
wx.ICON_INFORMATION)
self.mic = ''
event.Skip()
def OnBtInfo(self, event):
""" Show the info messages
"""
info.create(self, self.paths, self.paths.log4write.getAll()).Show(True)
def OnLblSearch(self, event):
""" Respond to the lbl search click
"""
if self.searchFrame:
self.searchFrame.Destroy()
self.searchFrame = searchFrame(self, -1, self.ren.get("search", 1), self.paths)
self.__frameSearchUpdate()
def OnCellRightClick(self, event):
""" Open the menu on the grid
"""
my_var.pop_grid_evt = event
pos_h, pos_l = self.grData.GetPosition()
pos_r_h, pos_r_l = event.GetPosition()
row, _, _ = self._get_gr_row_rcv_rc()
if self.view == VIEW_RECEIVE:
pos_id_fax = self.order.index('img')
else:
pos_id_fax = self.order.index('id')
menu = wx.Menu()
if self._db_fax_usage and self.view == VIEW_RECEIVE:
menu.Append(self.pop_gr_db_rcv_modify, self.ren.get("_fax_rcv_modify"))
menu.AppendSeparator()
menu.Append(self.pop_gr_update, self.ren.get('_update'))
menu.Append(self.pop_gr_delete, self.ren.get('_delete'))
menu.Append(self.pop_gr_fb_add, self.ren.get("_add_to_phonebook"))
if self.view == VIEW_SEND:
menu.Append(self.pop_gr_modify, self.ren.get("_modify"))
menu.Append(self.pop_gr_suspend, self.ren.get("_suspend"))
if self.view != VIEW_SEND:
menu.Append(self.pop_gr_save_jpg, self.ren.get("_save_image"))
menu.Append(self.pop_gr_save_pdf, self.ren.get("_save_pdf"))
menu.Append(self.pop_gr_save_list, self.ren.get("_save_list_delete")) # self.ren.get("_save_pdf"))
if self.view == VIEW_DONE:
menu.Append(self.pop_gr_resend, self.ren.get("_resend_fax"))
else:
menu.Append(self.pop_gr_resend, self.ren.get("_send_fax"))
menu.Append(self.pop_gr_send_mail, self.ren.get("_send_email"))
id_fax = self.grData.GetCellValue(row, pos_id_fax)
if self._db_fax_alarm.has_alarm(id_fax):
#modify of cancel the fax
menu.Append(self.pop_gr_fax_alarm_modify, self.ren.get("_fax_alarm_modify"))
menu.Append(self.pop_gr_fax_alarm_delete, self.ren.get("_fax_alarm_delete"))
else:
#add a new alarm, if need
menu.Append(self.pop_gr_fax_alarm_new, self.ren.get("_fax_alarm_new"))
if self.view == VIEW_DONE:
menu.Append(self.pop_gr_save_qfile, self.ren.get("_save_qfile"))
menu.Append(self.pop_gr_show_report, self.ren.get("_show_report"))
my_var.pop_grid_evt_call = 1
self.PopupMenu(menu, (pos_r_h + pos_h, pos_r_l + pos_l) )
event.Skip()
def OnGridCellKey(self, evt):
"""
"""
rows = sorted(self.grData.GetSelectedRows(), reverse=True)
if not (evt.GetKeyCode() == wx.WXK_DELETE and rows):
evt.Skip()
return
if self._dlg_delete_fax(rows) == wx.ID_NO:
return
else:
self._delete_fax_file(rows)
def OnBtExit(self, event):
self.OnClose(event)
def OnChk_filter_viewCheckbox(self, event):
""" Set the filter on/off
"""
filter_ = event.GetInt()
if self._db_fax_usage and self.view == VIEW_RECEIVE:
self._db_fax.SetFilterActiveView(filter_, self.view)
self._db_fax_force_update(True)
else:
self._hy.SetFilterActiveView(filter_, self.view)
wx.CallAfter(self._fakeUpdate)
def OnChk_autoupdate(self, evt):
""" Modify the update
"""
if not evt.GetInt(): tu = -1
else: tu = self.opt_cls.getint('txt_update')
self._hy.timeUpdate = tu
def OnBtFaxBook(self, event):
if not self.fb:
self.fb = frm_fax_book(self, self.paths)
else:
self.fb.Raise()
#
# Helper fax/job methods
#
def agg_modify(self, data):
""" Reschedule an already send fax
"""
if self._debug1: self._do_debug("Reschedule an already send fax")
if self._debug2: self._do_debug(data)
pry, sendTime, fn, company = data
if my_var.jobstatus_modify != 'T':
self.OnBtSuspend('')
parameter = {}
parameter['DIALSTRING'] = self.opt_cls.get('txt_prefix') + fn
parameter['EXTERNAL'] = self.opt_cls.get('txt_prefix') + fn
if company != '':
parameter['TOCOMPANY'] = company
if sendTime == '0':
parameter['SENDTIME'] = 'Now'
else:
now = time.time()
val = int(sendTime) * 15 * 60 # Every
when = datetime.datetime.fromtimestamp(val + now)
sendTime = "%d%02d%02d%02d%02d" % (when.year, when.month, when.day, when.hour, when.minute)
parameter['SENDTIME'] = sendTime
parameter['LASTTIME'] = '010000' # One day
parameter['SCHEDPRI'] = pry
if self._debug2: self._do_debug(my_var.jobid_modify, parameter)
self._hy.AlterJob(my_var.jobid_modify, parameter)
self.agg_view()
def prep_job_str(self,lst):
""" Prepare the job string
"""
returnString = str()
for l in range(len(lst)):
if l < len(lst) -1:
returnString += '%' + lst[l] + '|'
else:
returnString += '%' + lst[l]
return returnString
def ctrl_ret_hy(self, vals, val = 0):
""" Control the return value from hylafax and
if there's an error, show a message
"""
if self._debug1: self._do_debug("Control the return value from hylafax")
status, msg = vals
if status:
if val:
msg = self.ren.get('_error_connect') + str(msg)
title = self.ren.get('connect_error', 1)
self.SetStatusLabel(self.ren.get('_error_connect_label'), dim =1)
else:
msg = self.ren.get('_error_generic') + str(msg)
title = self.ren.get('_error_generic_title')
self.__generic_error(msg)
self.offline = 1
return 1
else:
return 0
def _getLstNewFax(self):
""" Return a "new fax"
"""
status = self._hy.status
if "rece" in str(status).lower():
msgForWrite = "I'm receceing a fax. I don't show message"
if self._debug1: self._do_debug(msgForWrite)
return []
msg_srv_rec = self._hy.GetDataViewRaw(VIEW_RECEIVE)
order_rec = self.myleng.ret(VIEW_RECEIVE)[3]
if self.offline: return 'err'
#Fax on internal db
fax_db = self.fax_db_seen.options()
#Fax on server
img_pos = order_rec.index('img')
fax_srv_comp = [fax[img_pos] for fax in msg_srv_rec]
#Number of new fax
lstIdNew = list()
for faxid in fax_srv_comp:
if not faxid in fax_db or self.fax_db_seen.getint(faxid) == 2:
#If I'm receiving a fax AND it's the last, don't show the message
#so the user don't receive the error from server
#if "Receiving" in statusMsg and fax == lastFax: continue
self.fax_db_seen.set(faxid, 0)
lstIdNew.append(faxid)
#Control if there are more than 10 new fax
if len(self._lastIDFaxRecvBuf) > len(fax_srv_comp) + 10:
msg = ( "Error on control the fax number received: last %s, now:%s" %
( len(self._lastIDFaxRecvBuf), len(fax_srv_comp) ) )
if self._debug1: self._do_debug(msg)
reactor.callLater(1, self._load_srv_hy)
return []
if not self.chk_filter_view.GetValue():
#Only need for clean db
for fax in fax_db:
if not fax in fax_srv_comp: self.fax_db_seen.remove_option(fax)
self._lastIDFaxRecvBuf = fax_srv_comp[:]
return lstIdNew
def print_new_fax(self):
"""Print if need the new fax"""
if self.opt_cls.getint("chk_print_on_receive"):
for f in self._lstNewFax:
if self._debug1: self._do_debug("Printing %s" % str(f))
self._hy.RetrFile(f, VIEW_RECEIVE,
callBack=self._printOnNewFax, real_filename=str(f))
def contr_new_fax(self):
""" Control and alert if there is a new fax
"""
if self._debug1: self._do_debug("Control and alert if there is a new fax")
if self.offline: return 'err'
#If I don't make the new fax control, exit
if not ( self.opt_cls.getint('chk_new_fax') and not \
self.opt_cls.getint('chk_view_receive') ):
return
if not self._lstNewFax: return
if len(self._lstNewFax) == 1:
msg = self.ren.get('_one_fax_new_1')
title = self.ren.get('_one_fax_new_2')
else:
msg = '%s %s %s'% ( self.ren.get('_more_fax_new_1'), len(self._lstNewFax),
self.ren.get('_more_fax_new_2') )
title = self.ren.get('_more_fax_new_3')
if self._debug2: self._do_debug("New fax received: %s" % str(self._lstNewFax) )
wx.MessageBox(str(msg), str(title), wx.ICON_INFORMATION)
def contr_alarm(self):
""" Control the alarms
"""
if self._debug1: self._do_debug("Control the alarms")
if self.bufferGridData and self.view == VIEW_RECEIVE:
self._db_fax_alarm.clean_no_present(self.bufferGridData[0],
self.order.index('img'))
expired = self._db_fax_alarm.get_expired()
if self._debug3: self._do_debug(expired)
if not expired:
return
wx.MessageBox("%s:\n%s" % (I18N("_fax_alarm_expired"), "\n".join( (x for x in expired) )),
I18N("_fax_alarm_expired"), wx.ICON_INFORMATION)
def _delete_fax_file(self, rows):
"""
"""
if self._debug1: self._do_debug("_delete_fax_file")
if self._debug2: self._do_debug(rows)
for row in sorted(rows, reverse=True):
if self.view != VIEW_RECEIVE:
row_id = self.order.index('id')
else:
row_id = self.order.index('img')
my_var.jobid_modify = row_id
jobid = self.grData.GetCellValue(row, row_id)
if self._debug1: self._do_debug("Delete fax: %s" % jobid)
if self.view != VIEW_RECEIVE:
my_var.jobstatus_modify = self.grData.GetCellValue(row, self.order.index('stat'))
my_var.pop_grid_evt_call = 0
if self._db_fax_usage and self.view == VIEW_RECEIVE:
#delete from db the data
self._db_fax.delete_file(jobid)
wx.CallAfter(self.agg_view)
else:
if self.view == VIEW_SEND:
self._hy.SuspendJob(jobid)
self._hy.DeleteJob(jobid)
#
# Helper grid/view methods
#
def _get_col_gr_values_lst(self, view):
""" Return the values for the grid (for the db talk)
"""
if self._debug1: self._do_debug("Return the values for the grid (for the db talk)")
if not view == VIEW_RECEIVE:
raise ValueError("Not done for now")
else:
lst_ret = [[],[],[],[]]
for row_val in self.opt_cls.get("db_archive_rcv_grid").split(";"):
col_name, col_pers_name, col_size, col_read_only = row_val.split(",")
col_size = int(col_size)
if col_read_only in (0, "0"):
col_read_only = False
else:
col_read_only = True
for num, val in enumerate((col_name, col_pers_name, col_size, col_read_only)):
lst_ret[num].append(val)
if self._debug3: self._do_debug(lst_ret)
return lst_ret
def _set_col_gr_values(self, data, view):
""" Return the values for the grid (for the db talk)
"""
if not view == VIEW_RECEIVE:
raise ValueError("Not done for now")
else:
str_out = ""
lst_data = []
for num_col, col in enumerate(data[0]):
tmp_lst = []
for num_row, row in enumerate(data):
try:
val = row[num_col]
except IndexError:
return
if isinstance(val, bool):
val = int(val)
tmp_lst.append(val)
lst_data.append( ",".join( "%s" % x for x in tmp_lst ) )
self.opt_cls.set("db_archive_rcv_grid", ";".join(lst_data))
def _get_col_gr_values(self, view=None):
""" Return the values need for update the grid.
For now this is return the right values only for fax db receive
"""
if self._debug1: self._do_debug("Return the values need for update the grid")
if view is None: view = self.view
if self.opt_cls.getint('db_archive_rcv_usage') == 1 and view == VIEW_RECEIVE:
col_name, col_pers_name, col_size, col_read_only = self._get_col_gr_values_lst(view)
d_text = {}
d_size = {}
order = []
#Default data that I need!
d_conf = {"Fax id": "img", "Date": "dat"}
for val_order, val_col, size_col in zip(col_name, col_pers_name, col_size):
if not val_order in d_conf:
d_conf[val_order] = val_order
id_col = d_conf[val_order]
d_text[id_col] = val_col
d_size[id_col] = size_col
order.append(id_col)
if self._debug3: self._do_debug(d_text, d_size, order)
return (d_text, d_size, (), order)
else:
return self.myleng.ret(view)
def _save_col_size(self):
""" Save the col size
"""
if self._debug1: self._do_debug("Save the col size")
if not self.view_as_changed:
return
view = self.view_prev
try:
size = [ self.grData.GetColSize(col) for col in xrange( self.grData.GetNumberCols() ) ]
except:
return
if self.opt_cls.getint('db_archive_rcv_usage') and view == VIEW_RECEIVE:
lst_ret = self._get_col_gr_values_lst(view)
lst_ret[2] = size
self._set_col_gr_values(lst_ret, VIEW_RECEIVE)
else:
order = self._get_col_gr_values(view)[3]
try:
dict_size = dict( (col, size) for size, col in zip(size, order) )
except:
dict_size = {}
self.myleng.set(view, dict_size)
self.myleng.save_pref()
def _updateStatus(self):
""" Update the status message from the ftp
"""
if self._debug1: self._do_debug("Update the status message from the ftp")
if self._debug2: self._do_debug(time=1)
self.SetStatusLabel(self._hy.status)
def _updateFromSrv(self):
""" Update called at the end of the ftp update
"""
self._update_on_air = False
if self._debug1: self._do_debug("Update called at the end of the ftp update")
if self._debug2: self._do_debug(time=1)
if not self._firstUpdateDone:
self._firstUpdateDone = 1
self.agg_view(fu=1)
else:
self.agg_view()
def _db_fax_update(self, dta):
""" Update call when db end to retrieve data from db.
Need for put into a thread the hylapex_db connection
"""
if self._debug1: self._do_debug("Update call when db end to retrieve data from db.", time=1)
if isinstance(dta, (list, tuple)):
self._time_db_fax = time.time()
self._last_db_rcv = dta
else:
self.__generic_error(dta)
def agg_view(self, fu=0):
""" Public method called for update the grid
"""
if self._debug1: self._do_debug("agg_view", time=1)
if self._debug2: self._do_debug(story=1)
self.txt, self.dim, _, self.order = self._get_col_gr_values()
self.lbl_whereUare.SetLabel( self.ren.get(VIEW_DICT[self.view], 1) )
self.btSizer.Layout()
#If I can't see the incoming fax, and I'm on receive view,
#clean the grid and return
if self.view == VIEW_RECEIVE and self.opt_cls.getint('chk_view_receive') == 1:
self.redraw_cols()
self.redraw_rows(0)
if self._debug1: self._do_debug("I can't see the incoming fax")
return
if self.offline: return 'err'
if self._db_fax_usage and self.view == VIEW_RECEIVE:
if self._debug2: self._do_debug("DB receive usage")
if not self._last_db_rcv:
msg = []
else:
msg = self._last_db_rcv
if self._update_on_air_db:
self._db_fax_force_update(True)
return
elif time.time() < (self._time_db_fax + self.opt_cls.getint("txt_update")):
self._update_on_air_db = False
msg = self._last_db_rcv
if self._debug1: self._do_debug("Time not passed for db, reused the old data")
else:
if self._debug1: self._do_debug("Time passed for db (or update bt pressed), load data")
self._db_fax_force_update()
else:
if self._debug2: self._do_debug("Normal data usage")
msg = self._hy.GetDataView(self.view)
msgStatus = self._hy.status
self.SetStatusLabel(msgStatus)
#Update the status message
status = self._hy.status
#If all are like previews update, we can go out, so
#save update time!
try:
grData, oldView = self.bufferGridData
if ( [msg, self.view] == self.bufferGridData and self.view == VIEW_RECEIVE):
if self._debug1: self._do_debug("I have the same data, return and save time")
return
except UnicodeError:
pass
try:
self.redraw_cols()
self.redraw_rows( len(msg) )
except:
return
if self._debug3: self._do_debug(msg)
if self._debug2: self._do_debug("Set data start", time=1)
self.grData.setData(msg)
if self._debug2: self._do_debug("Set data end", time=1)
if self.view != VIEW_RECEIVE:
pos_stat = self.order.index('stat')
if self._debug2: self._do_debug("Modify data start", time=1)
other = self.myleng.ret('other')
for row, rowValue in enumerate(msg):
for col, colValue in enumerate(rowValue):
if self.view != VIEW_RECEIVE and col == pos_stat:
valFound = VIEW_DICT[self.view]
if not valFound in other[valFound]['stat']:
continue
else:
colValue = other[valFound]['stat'][colValue]
self.grData.SetCellValue(row, col, colValue)
if self._debug2: self._do_debug("Modify data end", time=1)
if self.view == VIEW_DONE:
dictColType = dict()
dictColType[ self.order.index('id')] = wx_util.TYPE_INT
self.grData.setDataColType( dictColType )
else:
self.grData.setDataColType({})
if self._debug2: self._do_debug("Sort data start", time=1)
# Recall the cols update
if fu:
grData = self.grData.populateSortGrid(colToSort=0)
else:
grData = self.grData.populateSortGrid(update=1)
if self._debug2: self._do_debug("Sort data end", time=1)
self.bufferGridData = [grData, self.view]
self.gridSizer.Layout()
self.__frameSearchUpdate()
if self._firstUpdateDone:
#Control new fax, and print if need
self._lstNewFax = self._getLstNewFax()
wx.CallAfter(self.print_new_fax)
wx.CallAfter(self.contr_new_fax)
wx.CallAfter(self.contr_alarm)
#Send control
if self.opt_cls.getint('chk_send_message'): wx.CallAfter(self.__controlSendFax)
def all_fax_view(self):
""" Set all the fax view (called from configure frame)
"""
if self._debug1: self._do_debug("All fax view")
for i in self.fax_db_seen.options():
self.fax_db_seen.set(i, 1)
if self._debug3: self._do_debug(i)
self.agg_view()
def SetStatusLabel(self, val, dim = None, center=None):
""" Update the current status label with the value
"""
if dim:
f = wx.Font(15, wx.DEFAULT , wx.NORMAL, wx.NORMAL)#, faceName='Arial')
self.txtStatus.SetFont(f)
self.txtStatus.SetForegroundColour(wx.RED)
self.txtStatus.SetLabel(val)
else:
if center: fontDim = 10
else: fontDim = 8
f = wx.Font(fontDim, wx.DEFAULT , wx.NORMAL, wx.NORMAL)#, faceName='Arial')
self.txtStatus.SetFont(f)
self.txtStatus.SetForegroundColour(wx.BLACK)
self.txtStatus.SetLabel(str(val))
def get_filter(self, view):
""" Return the current filter
"""
fv = self.opt_cls.getint('chk_filter_%s' % (view))
if view != self.view:
return ()
if fv == self.chk_filter_view.GetValue():
if fv: return self.__get_filter()
else: return ()
else:
if fv: return ()
else: return self.__get_filter()
def redraw_cols(self):
"""
"""
if self._debug1: self._do_debug("Redraw cols", time=1)
# delete and redraw cols
dict_mis = {}
nc = self.grData.GetNumberCols()
self._save_col_size()
self.view_as_changed = 0
nc2del = nc - len(self.order)
if nc2del > 0:
if self._debug2: self._do_debug("Delete %s" % nc2del, time=1)
self.grData.DeleteCols(0, nc2del)
else:
if self._debug2: self._do_debug("Append %s" % -nc2del, time=1)
self.grData.AppendCols(-nc2del)
self.txt, self.dim, _, self.order = self._get_col_gr_values()
if self._debug2: self._do_debug("Set col size, start", time=1)
for num, col in enumerate(self.order):
self.grData.SetColSize(num, self.dim[col])
self.grData.SetColLabelValue(num, self.txt[col])
if self._debug2: self._do_debug("Set col size, end", time=1)
def redraw_rows(self, nr_now):
"""
"""
if self._debug1: self._do_debug("Redraw rows", time=1)
# delete all rows
nr = self.grData.GetNumberRows()
nr2del = nr - nr_now
if nr2del > 0:
if self._debug2: self._do_debug("Delete %s" % nr2del, time=1)
self.grData.DeleteRows(0, nr2del)
else:
if self._debug2: self._do_debug("Append %s" % -nr2del, time=1)
self.grData.AppendRows(-nr2del)
self.grData.ClearSelection()
def setColour(self, gridData=None):
""" Paint the rows/cols with the appropriate color
"""
if self._debug1: self._do_debug("setColour")
if self._debug2: self._do_debug("Start", time=1)
if gridData:
#Update bufferGridData with the new sorted values
view = self.bufferGridData[1]
self.bufferGridData = gridData, view
else:
gridData = self.bufferGridData[0]
#This append only when I open the program and I go to a view
#where ther is no data
if not gridData: return
cols_val = self.myleng.ret('other')[VIEW_DICT[self.view]]
val_failed = None
colStatus = -1
if self.view == VIEW_DONE:
colStatus = self.order.index('stat')
lstColStatus = [ row[colStatus]
for row in gridData ]
val_failed = cols_val['stat']['F']
val_okSend = cols_val['stat']['D']
if self.view == VIEW_RECEIVE:
idPosition = self.myleng.ret(self.view)[3].index('img')
else:
idPosition = self.myleng.ret(self.view)[3].index('id')
#Control what row are visible
posRowVisible = self.grData.GetViewStart()[1] * self.grData.GetScrollPixelsPerUnit()[1]
firstRowVisible = self.grData.YToRow(posRowVisible)
#Create its list
lstRowVisible = list()
lastRowVisible = 0
for i in range(firstRowVisible, len(gridData)):
if not self.grData.IsVisible(i, 0) and lastRowVisible: break
lastRowVisible = i
lstRowVisible.append(i)
lstRowVisible += [ x for x in range(lastRowVisible, lastRowVisible + 20) ]
if self._debug2: self._do_debug("Start set the color", time=1)
# Take values of col/row for this view and
for row, rowVal in enumerate(gridData):
#This isn't a good solution, but work!
if not row in lstRowVisible: continue
if self.view == VIEW_DONE:
statusCellValue = lstColStatus[row]
else:
statusCellValue = None
#Make a control if the fax are viewed
if self.view == VIEW_RECEIVE and self.opt_cls.getint('chk_new_fax'):
setColor = self.fax_db_seen.getint( rowVal[idPosition] )
else:
setColor = 1
for col, colVal in enumerate( rowVal ):
if self.view != VIEW_SEND and self._db_fax_alarm.has_alarm(rowVal[idPosition]):
color_cell = self._get_gr_color(COLOR_ALARM_FAX)
elif self.view == VIEW_RECEIVE and not setColor:
color_cell = self._get_gr_color(COLOR_NEW_FAX)
elif self.view == VIEW_DONE and (statusCellValue == 'F' or statusCellValue == val_failed):
color_cell = self._get_gr_color(COLOR_FAILED_FAX)
else:
color_cell = wx.WHITE
self.grData.SetCellBackgroundColour(row, col, color_cell)
if col == colStatus and self.view == VIEW_DONE:
if statusCellValue == 'F':
self.grData.SetCellValue(row, col, val_failed)
elif statusCellValue == 'D':
self.grData.SetCellValue(row, col, val_okSend)
if self._debug2: self._do_debug("End set the color, start refresh", time=1)
self.grData.Refresh()
if self._debug2: self._do_debug("End refresh", time=1)
def internalClose(self, *args, **kargs):
""" Close twisted and the application
"""
self.__doc.detach(self)
try:
self.fax_db_seen.exit()
if usePyCrash and self.MyCrash.getNumberOfRaisedExceptions():
fileToSave = self.paths.log_file_crash
self.MyCrash.saveToFile(fileToSave)
self.__generic_error( "%s %s" % (self.ren.get('error_append', 1), fileToSave) )
self._hy.Close()
if self.chk_my.IsChecked():
self.opt_cls.set('chk_priv','1')
else:
self.opt_cls.set('chk_priv', '0')
self.opt_cls.set("txt_autoupdate", int(self.chk_autoupdate.GetValue()) )
self.opt_cls.set('view', self.view)
#save the seen fax and alarms
self.fax_db_seen.exit()
#save the cols size
self._save_col_size()
#self.opt_cls.set('chk_filter_view_active', self.chk_filter_view.GetValue())
self.opt_cls.exit()
self.paths.log4write.close()
#Clean up and save the key
opt = self._opt_date_time.options()
for k in self._opt_date_time.options():
if not k in self._hy.dateTimeRcv:
self._opt_date_time.remove_option(k)
for k, value in self._hy.dateTimeRcv.iteritems():
self._opt_date_time.set(k, value)
self._opt_date_time.exit()
self._externalFilters.Close()
if self.view_fax:
self.view_fax.closeLib()
except:
print traceback.format_exc()
pass
self.Destroy()
#
# Terminal server methods
#
def _init_terminal_server(self):
""" Start a new ts session
"""
d_term = threads.deferToThread(self._load_terminal_server)
d_term.addCallback(self._terminal_rcv_data)
d_term.addErrback(self.__generic_error)
def _load_terminal_server(self):
""" Load the pipe for the terminal server function
"""
usr = self._get_username()
if not usr: return
try:
self._pipe_print = named_pipe.NamedPipe("hylapex_%s" % usr)
self._pipe_print.create_server_pipe()
# FIXME: very bad hack for make pipe working on win...
# new code that help?
if sys.platform.startswith("win"):
path_tmp = self._create_temp_file(".ps")
while True:
self._pipe_print.write_pipe(path_tmp)
msg = self._pipe_print.read_pipe()
if msg[0] == 1 or self._closing:
break
time.sleep(1)
else:
path_tmp = self._pipe_print.read_pipe()[1].strip()
return path_tmp
except:
self._pipe_print = None
self.__generic_error(traceback.format_exc())
def _close_terminal_server(self):
""" Close the terminal. If on linux, create a fake write,
so the listener weak-up from the wait.
"""
if self._debug2: self._do_debug("Close the terminal")
usr = self._get_username()
self._pipe_print = named_pipe.NamedPipe("hylapex_%s" % usr)
self._pipe_print.create_client_pipe()
self._pipe_print.write_pipe("Close, please :)")
self._pipe_print.close_pipe()
def _terminal_rcv_data(self, data):
"""
"""
if self._closing:
return
self._init_terminal_server()
self._add_new_send_file(data)
#
# Fax db methods
#
def _db_fax_force_update(self, call_update=None):
"""
"""
if self._debug1: self._do_debug("Force a new update from the db")
if self._debug2: self._do_debug(time=1)
if not self._db_fax:
return
self._time_db_fax = time.time()
filterSnd, filterDone, filterRcv = self._get_filter_hylafax()
cb = [self._db_fax_update]
if call_update:
def _fake_cb(*args):
if self._debug1: self._do_debug("Update db end. Call a fakeupdate")
self._update_on_air_db = False
reactor.callLater(0, self._fakeUpdate)
cb.append(_fake_cb)
self._db_fax.get_rcv_fields_data(self.opt_cls.get("db_archive_rcv_grid"), filterRcv,
callback=cb, errback=self.__generic_error)
#
# Internal methods
#
# Grid methods
def _get_fax_id_rc_event(self):
""" Return the fax identifier.
AAA: Callme only inside a right-click event!
"""
row = my_var.pop_grid_evt.GetRow()
if self.view == VIEW_RECEIVE:
pos_id_fax = self.order.index('img')
else:
pos_id_fax = self.order.index('id')
return self.grData.GetCellValue(row, pos_id_fax)
def _get_gr_row_rcv_rc(self):
""" Return the row, image_idx and file name.
AAA: Callme only inside a right-click event!
"""
if self._debug1: self._do_debug("_get_gr_row_rcv_rc")
row = my_var.pop_grid_evt.GetRow()
if self.view == VIEW_RECEIVE:
img_idx = self.order.index('img')
else:
img_idx = self.order.index('id')
file_ = self.grData.GetCellValue(row, img_idx)
if self._debug3: self._do_debug(("_get_gr_row_rcv_rc", row, img_idx, file_))
return row, img_idx, file_
def _get_gr_color(self, color):
""" Return the grid color
"""
return [int(x) for x in self.opt_cls.getList(color)]
def _create_temp_file(self, ext=None):
""" Common method for create temp file
"""
if self._debug1: self._do_debug("Create temp file")
ext = ext or 'tif'
if not ext.startswith("."):
ext = "." + ext
fd, fo = tempfile.mkstemp(ext, self.paths.temp_prefix, self.paths.tmp_dir)
f = os.fdopen(fd)
f.close()
del f
return fo
def _add_new_send_file(self, file_path):
""" Control if there is an already opened send fax gui and
add the path to it, otherwise open a new one
"""
if self._f_send_fax is None:
self._f_send_fax = hylapex_send.SendGui(self, self.paths,
file2send=file_path, observable=self.__doc)
else:
self._f_send_fax.add_new_fax(file_path)
return self._f_send_fax
def _get_username(self):
""" Return username read from the os
"""
if sys.platform.startswith('win'):
if sys.getwindowsversion()[3] < 2:
usr = ""
else:
usr = os.environ["USERNAME"]
else:
usr = os.environ["USER"]
return usr
def _dlg_delete_fax(self, rows):
""" Ask for fax deletion
"""
if self._debug1: self._do_debug("Ask for fax deletion")
dlg = wx.MessageDialog(self, "%s (%s)" % (self.ren.get("_delete_fax"), len(rows) ),
self.ren.get("_continue_title"), wx.ICON_QUESTION | wx.YES_NO)
ret_value = dlg.ShowModal()
dlg.Destroy()
return ret_value
def _fakeUpdate(self):
""" Control the update. Need because if there is no "first update"
I'm confused about the new fax and, the next time there is a *real*
update I'll advice that all the fax are new!!
"""
if self._debug1: self._do_debug("Fake update")
if not self._firstUpdateDone:
return
else:
self._hy.FakeUpdate()
def _printOnNewFax(self, filename, *args,**kw):
"""
"""
if self.opt_cls.getint("chk_print_on_receive"):
prName = self.opt_cls.get("txt_prt_name_on_new")
else:
return
self.ctrl_ret_img_view()
#Only able to handle tiff files
if not kw.get('filetype', 0) == hylaproto_t.FILE_TYPE_TIFF:
return
ret = self.view_fax._convert_file_tif( filename, type='png')
t = printRcvFax(prName)
if not t.goPrint(ret):
self.__generic_error("%s %s" % (self.ren.get('print_error', 1), kw["real_filename"]) )
def __srv_err(self, *msg):
""" Hylafax server error. Callback
"""
self.SetStatusLabel(self.ren.get('_error_connect_label'))
self.__generic_error(self.ren.get('_error_generic') + str(msg))
def __generic_error(self, msg, title=None):
""" Show a generic error
"""
if self._debug1: self._do_debug("Generic error", msg)
title = title or self.ren.get('_error_generic')
dlg = wx.MessageBox(str(msg), str(title), wx.ICON_ERROR)
self._do_debug(msg)
def __controlSendFax(self):
""" Control the send fax and alert if something new
"""
if self._debug1: self._do_debug("Control the send fax and alert if something new")
if self.offline: return 'err'
#Orders for every view where we'll work
order_send = self.myleng.ret(VIEW_SEND)[3]
order_done = self.myleng.ret(VIEW_DONE)[3]
#positions
id_done_pos = order_done.index('id')
stat_done_pos = order_done.index('stat')
user_done_pos = order_done.index('own')
id_send_pos = order_send.index('id')
user_send_pos = order_send.index('own')
#state
lst_state = [ x.strip() for x in self.ren.conf.get('cho_state_control', 'options').split(',') ]
stateToControl = self.opt_cls.get('cho_state_control')
if not stateToControl in lst_state: return
control_type = lst_state.index(stateToControl)
#the datas: file-saved and server present
fax_done_dict = self.fax_db_seen.get_items_dict('fax_done')
done_data = self._hy.GetDataView(VIEW_DONE)
send_data = self._hy.GetDataView(VIEW_SEND)
if self.offline: return 'err'
try: id_list_done = [ id for id in done_data[id_done_pos] ]
except: return ""
user = self.opt_cls.get('txt_user')
for fax in send_data:
#A new fax to monitoring is detected, set it not 'n' -> new
owner = fax[user_send_pos]
if not owner == user: continue
fax_id_send = fax[id_send_pos]
if not fax_id_send in fax_done_dict.keys():
self.fax_db_seen.set(fax_id_send, 'n', 'fax_done')
state_descr = self.myleng.ret('other')['done']['stat']
#Control if a fax with "n" flag are moved from send to done
for fax in done_data:
state = fax[stat_done_pos]
fax_id_done = fax[id_done_pos]
if fax_id_done in fax_done_dict.keys() and fax_done_dict[fax_id_done] == 'n':
action = 0
if control_type == C_ALWAYS:
action = 1
elif control_type == C_DONE_FAIL and state in ('F', 'D'):
action = 1
elif control_type == C_WHEN_DONE and state == 'D':
action = 1
elif control_type == C_WHEN_FAIL and state == 'F':
action = 1
self.fax_db_seen.set(fax_id_done, '0', 'fax_done')
#send a message, if need
if action: self.__msgAlertSendFax(fax_id_done, state_descr[state])
#Clean the list
for fax in fax_done_dict:
if not fax in id_list_done and not fax_done_dict[fax] == 'n':
if self._debug1: self._do_debug("Clean", fax)
self.fax_db_seen.remove_option(fax, 'fax_done')
def __msgAlertSendFax(self, fax, state):
""" Alert the user when a fax go to done view
"""
if self.offline: return 'err'
if state in ('F', self.myleng.ret('other')['done']['stat']['F']) :
icon = wx.ICON_ERROR
msg = '%s %s %s' % (self.ren.get('_fax_send_msg_failed_1'), fax,
self.ren.get('_fax_send_msg_failed_2') )
else:
icon = wx.ICON_INFORMATION
msg = '%s %s %s' % (self.ren.get('_fax_send_msg_ok_1'), fax,
self.ren.get('_fax_send_msg_ok_2') )
wx.MessageBox(msg, self.ren.get('attention', 1), icon)
def __get_filter(self):
""" Internal filter processing
"""
filter = ()
if self.opt_cls.getint('txt_filter_number'):
filter = ('n', self.opt_cls.getint('txt_filter_number'))
elif self.opt_cls.getint('txt_filter_days'):
filter = ('d', self.opt_cls.getint('txt_filter_days'))
return filter
def __getfile(self, row, file_save=None):
""" Download from the server the file and return the file type
"""
if self._debug1: self._do_debug("Download from the server the file and return the file type")
if self._debug2: self._do_debug(row, file_save)
tmp = {}
self.txt, self.dim, self.val, self.order = self._get_col_gr_values(self.view)
if self.view == VIEW_RECEIVE:
file_ = self.grData.GetCellValue(row, self.order.index('img') )
file_save = file_save or self.paths.temp_file_tiff
if self._debug1: self._do_debug("Fetch: %s, To: %s" % (file_, file_save))
if self._db_fax_usage:
#fetch the file and save to the disk
ret = self._db_fax.get_file(file_)
open(file_save, 'wb').write(ret)
else:
#print file_
status, msg = self.hy.get_recvfile(file_, file_save, 'recvq')
if self.ctrl_ret_hy((status, msg)):
if self._debug1: self._do_debug(status, msg)
return 0
return F_TYPE_TIFF
else:
if self.view == VIEW_DONE:
dir = 'doneq'
else:
dir = 'sendq'
id = self.grData.GetCellValue(row, self.order.index('id'))
try:
file_id = os.path.join(self.paths.tmp_dir , 'id_' + id + '.tmp')
except:
file_id = tempfile.mkstemp(prefix='id_' + id, suffix='.tmp')[1]
status, msg = self.hy.get_recvfile('q' + id, file_id , dir)
if self.ctrl_ret_hy((status, msg)):
if self._debug1: self._do_debug(status, msg)
return 0
tmp_dic = {"_document_": {}}
# Create a dict with the values of the q file
for line in open(file_id, 'r').readlines():
#not need, but better to try
if not ":" in line: continue
prefix, value = line.split(":", 1)
if prefix in DOCS_TYPE:
if prefix.startswith("!"):
prefix = prefix[1:]
#we want to handle only data that we can display
if not prefix in DOCS_TYPE_HANDLE:
continue
#the document are: file_name: type
f_name = os.path.split( value.split(":")[-1].strip() ) [-1]
tmp_dic["_document_"] [f_name] = prefix
else:
tmp_dic[prefix] = value
if len(tmp_dic["_document_"]) > 1:
#we have more than one file. Ask for witch to choose
#only the file name, not its dir
dlg = wx.SingleChoiceDialog(self,
self.ren.get('_fax_choose_more_one'),
self.ren.get('choose_file', 1),
sorted( tmp_dic["_document_"].keys() ), wx.CHOICEDLG_STYLE)
if dlg.ShowModal() == wx.ID_OK:
file_open = str( dlg.GetStringSelection() )
else:
return 0
else:
file_open = tmp_dic["_document_"].keys()[0]
#Get the fax file
pars = [file_open, 'docq']
#type of file
if tmp_dic["_document_"][file_open] in DOCS_TYPE_HANDLE_TIFF:
f_out = self.paths.temp_file_tiff
tof = 4
else:
f_out = self.paths.temp_file_ps
tof = 5
pars.insert(1, f_out)
status, msg = self.hy.get_recvfile(*pars)
#get the file
if self.ctrl_ret_hy((status, msg)):
return 0
return tof
def __SaveFaxAs(self, type, row, rows=None):
""" Save fax as type
"""
if type == 'pdf':
type_descr = "Acrobat(*.pdf)|*.pdf"
else:
type_descr = "%s(*.png)|*.png" % self.ren.get('image', 1)
path_file = self.opt_cls.get("path_save_as")
path_file = os.path.abspath(path_file)
dlg = wx.FileDialog(self, self.ren.get('choose_file', 1), path_file, "",
type_descr, wx.SAVE)
filename = ''
try:
if dlg.ShowModal() == wx.ID_OK:
filename = dlg.GetPath()
finally:
dlg.Destroy()
if filename == '': return
self.opt_cls.set("path_save_as", os.path.dirname(filename))
tof = self.__getfile(row)
if tof == F_TYPE_NONE: return
self.ctrl_ret_img_view()
if type == 'png':
if tof in F_TYPES_TIFF:
#filename = os.path.splitext(filename)[0]
ret = self.view_fax._convert_file_tif( self.paths.temp_file_tiff, filename, type='png')
self.__get_ret_code_tif(ret, filename)
else:
ret = self.view_fax._convert_files_ps( self.paths.temp_file_ps, \
fo=filename, tofo='png16m', ext='png')
ret = self.view_fax._convert_end(ret)
self.__get_ret_code_tif(ret, filename)
else:
if tof in F_TYPES_TIFF:
self.__save_tiff2pdf('-o', filename, self.paths.temp_file_tiff)
self.__ok_save()
else:
ret = self.view_fax._convert_files_ps(
self.paths.temp_file_ps, filename,'pdfwrite', 'pdf')
self.__get_ret_code_pdf(ret, filename)
self.__ok_save()
def __save_tiff2pdf(self, *args):
""" Convert and save the tiff file to pdf file
@parm args: pass me the right arguments
"""
args = [self.paths.tiff2pdf] + list(args)
if self._debug1: self._do_debug("I execute: %s" % str(args))
out, err = subprocess.Popen(args, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
if self._debug1: self._do_debug(err)
if self._debug1: self._do_debug(out)
def __get_ret_code_tif(self, code, filename):
for f in code:
shutil.move(f, os.path.join(os.path.dirname(filename), os.path.split(f)[1]))
self.__ok_save()
def __get_ret_code_pdf(self, ret, filename):
f_name, ext = ret
shutil.move(f_name +'1.'+ ext, \
os.path.join(os.path.dirname(filename), filename))
def __ok_save(self, *args):
dlg = wx.MessageDialog(None, self.ren.get("_saved_success"),
self.ren.get('ended', 1), wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
def __selColNumber(self, lstRows, rowSel):
""" Select the rows passed
called from search frame
"""
if not lstRows: return
for num, row in enumerate(lstRows):
if num == 0: self.grData.SelectRow(row)
else: self.grData.SelectRow(row, True)
self.grData.MakeCellVisible(rowSel,0)
def ctrl_ret_img_view(self):
"""
"""
ret, msg, inst = hylapex_send.new_view_fax(self, self.opt_cls, self.paths)
if ret:
self.__generic_error("Error:%s" % msg +"\nTip: You have select to use freeimage, but\n" +
"you haven't set the freeimage path. Go to configure")
#If I have already my class, don't re-set
if not msg == 'ok_yet':
setattr(self, 'view_fax', inst)
def __frameSearchUpdate(self):
""" Add the field data to the search frame
"""
if self.searchFrame:
colNames = [self.txt[x] for x in self.order]
self.searchFrame.goSearch(self.bufferGridData[0], colNames, self.__selColNumber)
def contr_date(self):
key = ['time']
val = [str(time.time())]
month_sec = 60*60*24*30
file = read_conf.conf(os.path.join(self.paths.my_path, 'hyla.pyd'),key,val)
if file.exist():
file.write(key, val)
return 0
else:
opt = file.read()
time_init = float(opt['time'])
time_rest = time.time() - time_init
if time_rest > month_sec:
return 1
def __saveLstMessageAndDelete(self, lst, path):
""" Internal method called by a thread
"""
grData = self.bufferGridData[0]
order = self.myleng.ret(self.view)[3]
if self.view == VIEW_RECEIVE: posImg = order.index("img")
else:
posImg = order.index("id")
posDate = order.index("dat")
posNum = order.index("num")
for num, row in enumerate(lst):
tof = self.__getfile(row)
if tof == F_TYPE_NONE: continue
self.ctrl_ret_img_view()
imgId = grData[row][posImg]
if self.view == VIEW_RECEIVE:
fName = "fax_in_%s " % os.path.splitext(imgId[3:])[0]
dictData = self.view_fax.getTiffInfo(self.paths.temp_file_tiff)
if "Date & Time" in dictData:
fName += dictData["Date & Time"].replace(":", "_")
else:
fName = "fax_out_%s %s %s" % \
(imgId, grData[row][posDate], grData[row][posNum])
fName = fName.replace("/", "-").replace(":", "-")
prefix = self.opt_cls.get("prefix")
if prefix: fName = fName.replace(prefix, '')
fName = os.path.join(path, fName +'.pdf')
if tof in F_TYPES_TIFF:
self.__save_tiff2pdf('-o', fName, self.paths.temp_file_tiff)
else:
ret = self.view_fax._convert_files_ps(
self.paths.temp_file_ps, fName, 'pdfwrite', 'pdf')
self.__get_ret_code_pdf(ret, fName)
#Update the label
wx.CallAfter(self.progFrame.setValue, num+1)
wx.CallAfter(self.progFrame.Destroy)
wx.CallAfter(self.__askForDelete, lst)
def __askForDelete(self, lst):
""" Ask for delete the fax and optionally, delete them
"""
if self._debug1: self._do_debug("ask for delete")
dlg = wx.MessageDialog(self, self.ren.get("_delete_fax"),
self.ren.get("_continue_title"), wx.ICON_QUESTION | wx.YES_NO)
ret_value = dlg.ShowModal()
if ret_value == wx.ID_NO:
if self._debug2: self._do_debug("Don't want to delete")
dlg.Destroy()
return
dlg.Destroy()
for row in lst:
jobid = self.grData.GetCellValue(row,0)
my_var.jobid_modify = jobid
status, msg = self.hy.deletejob(jobid)
self.ctrl_ret_hy((status, msg))
self.agg_view()
self.__ok_save()
def _timeCtrl(self):
""" Control the time passed
"""
time_passed = time.time() - self._time
self._time = time.time()
return time_passed, self._time
def update(self):
""" Doc/view
"""
type_, val = self.__doc.get()
if type_ == OBS_FR_HY_UPDATE:
self.OnBtUpdate()
elif type_ == OBS_FR_SEND_CLOSE:
self._f_send_fax = None
#
# Debug functions
#
def _ctrl_debug(self):
""" Control and set the variables for the debug
"""
debug_value = self.opt_cls.getint("txt_debug")
utils.do_debug.set_debug_level({"1": debug_value > 0, "2": debug_value > 1,
"3": debug_value > 2, "4": debug_value > 3})
self._debug1 = debug_value > 0
self._debug2 = debug_value > 1
self._debug3 = debug_value > 2
self._debug4 = debug_value > 3
def _do_debug(self, *args, **kw):
""" Wrote to the log debug functs
"""
utils.do_debug(*args, **kw)
return
args = list(args)
if kw.pop("time", None) or self._debug4:
args += ["TIME PASSED: %s" % str(self._timeCtrl())]
if kw.pop("story", None) or self._debug4:
args = utils.create_story_call() + args
args += [ "%s:%s" % (str(k), str(v)) for k, v in kw.iteritems() ]
msg = "\n".join( ("DEBUG: %s" % str(x).rstrip() for x in args) )
if self._debug2:
print msg
self.paths.log4write.write(msg)
if sys.platform == "win32":
miniFrame = wx.MiniFrame
else:
miniFrame = wx.Frame
class printRcvFax(object):
"""
"""
def __init__(self, printerName):
"""
"""
self._printer = printerName
def goPrint(self, fileNames):
"""
"""
printData = wx.PrintData()
printData.SetPaperId(wx.PAPER_A4)
printData.SetPrintMode(wx.PRINT_MODE_PRINTER)
printData.SetPrinterName(self._printer)
pdd = wx.PrintDialogData(printData)
pdd.SetNoCopies(1)
pdd.SetToPage( len(fileNames) )
printer = wx.Printer(pdd)
printout = myPrintOut(fileNames)
return printer.Print(None, printout, False)
class myPrintOut(wx.Printout):
""" Class to perform the print for the new fax """
def __init__(self, images):
super(myPrintOut, self).__init__()
self._images = images
self.pages = len(images)
print "init"
def GetPageInfo(self):
return (1, self.pages, 1, self.pages)
def OnPrintPage(self, page):
dc = self.GetDC()
#Load the file
bmap = wx.Bitmap( self._images[page-1] )
maxX, maxY = bmap.GetWidth(), bmap.GetHeight()
# Get the size of the DC in pixels
(w, h) = dc.GetSizeTuple()
#Better size
if maxY < maxX:
maxY = int ( maxX * ( 1.0 * h / w ) )
img = wx.ImageFromBitmap( bmap )
img.Rescale(maxX, maxY)
bmap = wx.BitmapFromImage( img )
# Let's have at least 50 device units margin
marginX = 10
marginY = 10
# Add the margin to the graphic size
maxX = maxX + (2 * marginX)
maxY = maxY + (2 * marginY)
# Calculate a suitable scaling factor
scaleX = float(w) / maxX
scaleY = float(h) / maxY
# Use x or y scaling factor, whichever fits on the DC
actualScale = min(scaleX, scaleY)
# Calculate the position on the DC for centering the graphic
posX = (w - (maxX * actualScale)) / 2.0
posY = (h - (maxY * actualScale)) / 2.0
# Set the scale and origin
dc.SetUserScale(actualScale, actualScale)
dc.DrawBitmap(bmap, 0, 30, True)
return True
def HasPage(self, page):
if page <= self.pages:
return True
else:
return False
def OnBeginDocument(self, stpg, endpg):
if not wx.Printout.OnBeginDocument(self, stpg, endpg):
return False
return True
class ProgressFrame(miniFrame):
def __init__(self, prnt, range, title = "Progress"):
super(ProgressFrame, self).__init__(prnt,-1, title)
self.SetBackgroundColour(wx.Colour(235, 235, 235))
self.range = range
self.msgWait = "Wait... File"
self.lblMsgWait = wx.StaticText(self, -1, self.msgWait)
self.gauge = wx.Gauge(self, -1, range)
self.gauge.SetMinSize(wx.Size(150,20))
sz = wx.BoxSizer(wx.VERTICAL)
sz.Add(self.lblMsgWait, 0, wx.EXPAND)
sz.Add(self.gauge, 0, wx.EXPAND)
self.SetSizerAndFit(sz)
self.SetAutoLayout(True)
self.CenterOnParent()
def setValue(self, value):
"""
"""
self.lblMsgWait.SetLabel("%s %s di %s" % (self.msgWait, value, self.range) )
self.gauge.SetValue(value)
class searchFrame(wx.Frame):
def __init__(self, prnt, id, title, paths):
super(searchFrame, self).__init__(prnt, id, title,
style=wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX |
wx.CLIP_CHILDREN | wx.RESIZE_BORDER)
self.SetBackgroundColour(wx.Colour(235, 235, 235))
self.paths = paths
parent = wx.Panel(self)
self.txtSearch = wx.TextCtrl(parent)
self.choCol = wx.Choice(parent)
self.btSerch = wx.Button(parent, label="Search")
self.lstResult = wx.ListBox(parent)
self.Bind(wx.EVT_CLOSE, self.onClose)
self.btSerch.Bind(wx.EVT_BUTTON, self.onBtSerch)
self.lstResult.Bind(wx.EVT_LISTBOX, self.onLstClick)
self.lblSearch = wx.StaticText(parent, label = "Text")
self.lblField = wx.StaticText(parent, label = "Field")
szCtrl = wx.FlexGridSizer(3, 2)
szCtrl.AddGrowableRow(2)
szCtrl.AddGrowableCol(1)
szBt = wx.BoxSizer(wx.HORIZONTAL)
self.szAll = wx.BoxSizer(wx.VERTICAL)
szCtrl.Add(self.lblSearch, 0, wx.ALIGN_CENTER | wx.ALL, 5)
szCtrl.Add(self.txtSearch, 0, wx.ALIGN_CENTER | wx.ALL | wx.EXPAND, 5)
szCtrl.Add(self.lblField, 0, wx.ALIGN_CENTER | wx.ALL, 5)
szCtrl.Add(self.choCol, 0, wx.ALIGN_CENTER | wx.ALL | wx.EXPAND, 5)
self.lblResult = wx.StaticText(parent, label = "Risulatati")
szCtrl.Add(self.lblResult, 0, wx.ALIGN_CENTER | wx.ALL, 5)
szCtrl.Add(self.lstResult, 1, wx.ALIGN_CENTER | wx.ALL | wx.EXPAND, 5)
szBt.Add(self.btSerch, 1, wx.ALIGN_CENTER | wx.ALL , 5)
self.szAll.Add(szCtrl, 1, wx.EXPAND, 5)
self.szAll.Add(szBt, 0, wx.EXPAND, 5)
self.szAll.Layout()
parent.SetSizerAndFit(self.szAll)
self.SetSize(parent.GetSize())
self.CenterOnParent()
#Rename controls
self.ren = wx_util.rename_ctrls(self, 'searchframe', self.paths.my_path,
lang = self.paths.language)
self.ren.rename()
self.Show()
def goSearch(self, data, colList, functToCall):
""" Receive the data from the parent form
"""
self.data = data
self.colList = colList
self.__functToCall = functToCall
self.choCol.Clear()
self.choCol.AppendItems(colList)
def onBtSerch(self, event):
""" Respond to the search button
"""
strToSearch = self.txtSearch.GetValue().lower()
colStr = self.choCol.GetStringSelection()
if not colStr in self.colList: return
colPos = self.colList.index(colStr)
lstToSearch = [ x[colPos] for x in self.data]
self.lstResult.Clear()
self.lstFind = list()
for num, i in enumerate(lstToSearch):
if i.lower().find(strToSearch) != -1:
id = self.data[num][0]
self.lstResult.Append(id, num)
self.lstFind.append(num)
def onLstClick(self, event):
""" Called on list click
"""
sel = event.GetSelection()
if sel == -1: return
rowSel = self.lstResult.GetClientData(sel)
self.__functToCall(self.lstFind, rowSel)
def onClose(self, event):
""" Update the parent variables
"""
self.GetParent().searchFrame = None
event.Skip()
#-------------------------------------------------------------------------------
class frm_fax_book(wx.Frame):
def __init__(self, parent, paths, fax2add = ''):
wx.Frame.__init__(self, parent, title='Fax book')
self.Bind(wx.EVT_CLOSE, self.Onfrm_fax_bookClose)
self.opt_cls = parent.opt_cls
self.p_fb = p_fb.wxPanel1(self, paths, use = 'fb', fax2add=fax2add)
self.SetClientSize( self.p_fb.GetSize() )
self.Show()
def Onfrm_fax_bookClose(self, event):
self.p_fb.close()
event.Skip()
class MyApp(wx.App):
def OnInit(self):
global PATHS
PATHS.log4write.write(PATHS.__dict__)
wx.InitAllImageHandlers()
reactor.interleave(wx.CallAfter)
if len(sys.argv) > 1:
my_name = os.path.basename(sys.argv[0])
#Only needed when we are called from hylaprint
if not (my_name == 'hylapex.py' or my_name == 'hylapex.exe'):
sys.argv.insert(0, 'hylapex.py')
my_var.printer = 0
try:
optlist, args = getopt.getopt(sys.argv[1:],'f:r:')
if '-r' in optlist[0]:
my_var.printer = 1
PATHS.temp_file_ps = os.path.abspath(optlist[0][1])
if '-f' in optlist[0]:
PATHS.temp_file_ps = os.path.abspath(optlist[0][1])
arg = 1
except getopt.GetoptError, oE:
sys.stderr.write(str(oE) + '\n')
PATHS.log4write.write(oE)
print 'Not use correctly'
print 'Usage %s or' % (sys.argv[0])
print 'Usage %s -r (only 4 redmon on win32 or print use on other OS) or' % (sys.argv[0])
print 'Usage %s -f filename.ps|.pdf|.tiff' % (sys.argv[0])
#reactor.stop()
sys.exit()
else:
my_var.printer = 0
arg = 0
if read_pref(PATHS):
return True
if not arg:
self.main = frm_hylapex(None, PATHS)
self.SetTopWindow(self.main)
self.main.Show()
else:
if not my_var.printer:
self.main = frm_hylapex(None, PATHS)
self.SetTopWindow(self.main)
self.main.Show()
PATHS.log4write.write(arg)
PATHS.log4write.write(my_var.printer)
if my_var.printer:
frm_snd = hylapex_send.SendGui(None, PATHS, state='r')
else:
frm_snd = hylapex_send.SendGui(self.main, PATHS, state='p')
frm_snd.Show(True)
return True
def main():
app = MyApp(0)
if USE_TWISTED_WXREACTOR:
reactor.registerWxApp(app)
reactor.run()
else:
app.MainLoop()
if __name__ == '__main__':
#paths = contr_path()
main()
|