Package Gnumed :: Package pycommon :: Module gmPrinting |
[frames] | no frames]

# Source Code for Module Gnumed.pycommon.gmPrinting

      1  """GNUmed printing."""
      2  # =======================================================================
      3  __author__  = "K.Hilbert <Karsten.Hilbert@gmx.net>"
      4  __license__ = 'GPL v2 or later (details at http://www.gnu.org)'
      5
      6  # =======================================================================
      7  import logging
      8  import sys
      9  import os
     10  import subprocess
     11  import codecs
     12  import time
     13
     14
     15  if __name__ == '__main__':
     16          sys.path.insert(0, '../../')
     17  from Gnumed.pycommon import gmShellAPI
     18  from Gnumed.pycommon import gmTools
     19  from Gnumed.pycommon import gmLog2
     20
     21
     22  _log = logging.getLogger('gm.printing')
     23
     24
     25  known_printjob_types = [
     26          u'medication_list',
     27          u'generic_document'
     28  ]
     29
     30  external_print_APIs = [
     31          u'gm-print_doc',
     32          u'os_startfile',                # win, mostly
     33          u'gsprint',                             # win
     34          u'acrobat_reader',              # win
     35          u'gtklp',                               # Linux
     36          u'Internet_Explorer',   # win
     37          u'Mac_Preview'                  # MacOSX
     38  ]
     39
     40  #=======================================================================
     41  # internal print API
     42  #-----------------------------------------------------------------------
     43 -def print_files(filenames=None, jobtype=None, print_api=None):
     44
     45          _log.debug('printing "%s": %s', jobtype, filenames)
     46
     47          for fname in filenames:
     48                  try:
     49                          open(fname, 'r').close()
     50                  except:
     51                          _log.exception('cannot open [%s], aborting', fname)
     52                          return False
     53
     54          if jobtype not in known_printjob_types:
     55                  print "unregistered print job type <%s>" % jobtype
     56                  _log.warning('print job type "%s" not registered', jobtype)
     57
     58          if print_api not in external_print_APIs:
     59                  _log.warning('print API "%s" unknown, trying all', print_api)
     60
     61          if print_api == u'os_startfile':
     62                  return _print_files_by_os_startfile(filenames = filenames)
     63          elif print_api == u'gm-print_doc':
     64                  return _print_files_by_shellscript(filenames = filenames, jobtype = jobtype)
     65          elif print_api == u'gsprint':
     66                  return _print_files_by_gsprint_exe(filenames = filenames)
     67          elif print_api == u'acrobat_reader':
     68                  return _print_files_by_acroread_exe(filenames = filenames)
     69          elif print_api == u'gtklp':
     70                  return _print_files_by_gtklp(filenames = filenames)
     71          elif print_api == u'Internet_Explorer':
     72                  return _print_files_by_IE(filenames = filenames)
     73          elif print_api == u'Mac_Preview':
     74                  return _print_files_by_mac_preview(filenames = filenames)
     75
     76          # else try all
     77          if (sys.platform == 'darwin') or (os.name == 'mac'):
     78                  if _print_files_by_mac_preview(filenames = filenames):
     79                          return True
     80          elif os.name == 'posix':
     81                  if _print_files_by_gtklp(filenames = filenames):
     82                          return True
     83          elif os.name == 'nt':
     84                  if _print_files_by_shellscript(filenames = filenames, jobtype = jobtype):
     85                          return True
     86                  if _print_files_by_gsprint_exe(filenames = filenames):
     87                          return True
     88                  if _print_files_by_acroread_exe(filenames = filenames):
     89                          return True
     90                  if _print_files_by_os_startfile(filenames = filenames):
     91                          return True
     92                  if _print_files_by_IE(filenames = filenames):
     93                          return True
     94                  return False
     95
     96          if _print_files_by_shellscript(filenames = filenames, jobtype = jobtype):
     97                  return True
     98
     99          return False
    100  #=======================================================================
    101  # external print APIs
    102  #-----------------------------------------------------------------------
    103 -def _print_files_by_mac_preview(filenames=None):
    104
    105  #       if os.name != 'mac':                            # does not work
    106          if sys.platform != 'darwin':
    107                  _log.debug('MacOSX <open> only available under MacOSX/Darwin')
    108                  return False
    109
    110          for filename in filenames:
    111                  cmd_line = [
    112                          r'open',                                # "open" must be in the PATH
    113                          r'-a Preview',                  # action = Preview
    114                          filename
    115                  ]
    116                  _log.debug('printing with %s' % cmd_line)
    117                  try:
    118                          mac_preview = subprocess.Popen(cmd_line)
    119                  except OSError:
    120                          _log.debug('cannot run <open -a Preview>')
    121                          return False
    122                  mac_preview.communicate()
    123                  if mac_preview.returncode != 0:
    124                          _log.error('<open -a Preview> returned [%s], failed to print', mac_preview.returncode)
    125                          return False
    126
    127          return True
    128  #-----------------------------------------------------------------------
    129 -def _print_files_by_IE(filenames=None):
    130
    131          if os.name != 'nt':
    132                  _log.debug('Internet Explorer only available under Windows')
    133                  return False
    134
    135          try:
    136                  from win32com import client as dde_client
    137          except ImportError:
    138                  _log.exception('<win32com> Python module not available for use in printing')
    139                  return False
    140
    141          try:
    142                  i_explorer = dde_client.Dispatch("InternetExplorer.Application")
    143                  for filename in filenames:
    144                          if i_explorer.Busy:
    145                                  time.sleep(1)
    146                          i_explorer.Navigate(os.path.normpath(filename))
    147                          if i_explorer.Busy:
    148                                  time.sleep(1)
    149                          i_explorer.Document.printAll()
    150                  i_explorer.Quit()
    151          except:
    152                  _log.exception('error calling IE via DDE')
    153                  return False
    154
    155          return True
    156  #-----------------------------------------------------------------------
    157 -def _print_files_by_gtklp(filenames=None):
    158
    159  #       if os.name != 'posix':
    160          if sys.platform != 'linux2':
    161                  _log.debug('<gtklp> only available under Linux')
    162                  return False
    163
    164          cmd_line = [
    165                  r'gtklp',
    166                  r'-i',
    167                  r'-# 1'
    168          ]
    169          cmd_line.extend(filenames)
    170          _log.debug('printing with %s' % cmd_line)
    171          try:
    172                  gtklp = subprocess.Popen(cmd_line)
    173          except OSError:
    174                  _log.debug('cannot run <gtklp>')
    175                  return False
    176          gtklp.communicate()
    177          if gtklp.returncode != 0:
    178                  _log.error('<gtklp> returned [%s], failed to print', gtklp.returncode)
    179                  return False
    180
    181          return True
    182  #-----------------------------------------------------------------------
    183 -def _print_files_by_gsprint_exe(filenames=None):
    184          """Use gsprint.exe from Ghostscript tools. Windows only.
    185
    186          - docs: http://pages.cs.wisc.edu/~ghost/gsview/gsprint.htm
    187          - download: http://www.cs.wisc.edu/~ghost/
    188          """
    189          if os.name != 'nt':
    190                  _log.debug('<gsprint.exe> only available under Windows')
    191                  return False
    192
    193          conf_filename = gmTools.get_unique_filename (
    194                  prefix = 'gm2gsprint-',
    195                  suffix = '.cfg'
    196          ).encode(sys.getfilesystemencoding())
    197
    198          for filename in filenames:
    199                  conf_file = codecs.open(conf_filename, 'wb', 'utf8')
    200                  conf_file.write('-color\n')
    201                  conf_file.write('-query\n')                             # printer setup dialog
    202                  conf_file.write('-all\n')                               # all pages
    203                  conf_file.write('-copies 1\n')
    204                  conf_file.write('%s\n' % os.path.normpath(filename))
    205                  conf_file.close()
    206
    207                  cmd_line = [
    208                          r'gsprint.exe',                                         # "gsprint.exe" must be in the PATH
    209                          r'-config "%s"' % conf_filename
    210                  ]
    211                  _log.debug('printing with %s' % cmd_line)
    212                  try:
    213                          gsprint = subprocess.Popen(cmd_line)
    214                  except OSError:
    215                          _log.debug('cannot run <gsprint.exe>')
    216                          return False
    217                  gsprint.communicate()
    218                  if gsprint.returncode != 0:
    219                          _log.error('<gsprint.exe> returned [%s], failed to print', gsprint.returncode)
    220                          return False
    221
    222          return True
    223  #-----------------------------------------------------------------------
    224 -def _print_files_by_acroread_exe(filenames):
    225          """Use Adobe Acrobat Reader. Windows only.
    226
    227          - docs: http://www.robvanderwoude.com/printfiles.php#PrintPDF
    228          """
    229          if os.name != 'nt':
    230                  _log.debug('Acrobat Reader only used under Windows')
    231                  return False
    232
    233          for filename in filenames:
    234                  cmd_line = [
    235                          r'AcroRd32.exe',                        # "AcroRd32.exe" must be in the PATH
    236                          r'/s',                                          # no splash
    237                          r'/o',                                          # no open-file dialog
    238                          r'/h',                                          # minimized
    239                          r'/p',                                          # go straight to printing dialog
    240                          os.path.normpath(filename)
    241                  ]
    242                  _log.debug('printing with %s' % cmd_line)
    243                  try:
    244                          acroread = subprocess.Popen(cmd_line)
    245                  except OSError:
    246                          _log.debug('cannot run <AcroRd32.exe>')
    247                          cmd_line[0] = r'acroread.exe'                                   # "acroread.exe" must be in the PATH
    248                          _log.debug('printing with %s' % cmd_line)
    249                          try:
    250                                  acroread = subprocess.Popen(cmd_line)
    251                          except OSError:
    252                                  _log.debug('cannot run <acroread.exe>')
    253                                  return False
    254
    255                  acroread.communicate()
    256                  if acroread.returncode != 0:
    257                          _log.error('Acrobat Reader returned [%s], failed to print', acroread.returncode)
    258                          return False
    259
    260          return True
    261  #-----------------------------------------------------------------------
    262 -def _print_files_by_os_startfile(filenames=None):
    263
    264          try:
    265                  os.startfile
    266          except AttributeError:
    267                  _log.error('platform does not support "os.startfile()"')
    268                  return False
    269
    270          _log.debug('printing [%s]', filenames)
    271
    272          for filename in filenames:
    273                  fname = os.path.normcase(os.path.normpath(filename))
    274                  _log.debug('%s -> %s', filename, fname)
    275                  try:
    276                          try:
    277                                  os.startfile(fname, 'print')
    278                          except WindowsError, e:
    279                                  _log.exception('no <print> action defined for this type of file')
    280                                  if e.winerror == 1155:  # try <view> action
    281                                          os.startfile(fname)
    282                  except:
    283                          _log.exception('os.startfile() failed')
    284                          gmLog2.log_stack_trace()
    285                          return False
    286
    287          return True
    288  #-----------------------------------------------------------------------
    289 -def _print_files_by_shellscript(filenames=None, jobtype=None):
    290
    291          paths = gmTools.gmPaths()
    292          local_script = os.path.join(paths.local_base_dir, '..', 'external-tools', 'gm-print_doc')
    293
    294          #candidates = [u'gm-print_doc', u'gm-print_doc.bat', local_script, u'gm-print_doc.bat']
    295          candidates = [u'gm-print_doc', local_script, u'gm-print_doc.bat']
    296          found, binary = gmShellAPI.find_first_binary(binaries = candidates)
    297          if not found:
    298                  binary = r'gm-print_doc.bat'
    299
    300          cmd_line = [
    301                  binary,
    302                  jobtype
    303          ]
    304          cmd_line.extend(filenames)
    305          _log.debug('printing with %s', cmd_line)
    306          try:
    307                  gm_print_doc = subprocess.Popen(cmd_line)
    308          except OSError:
    309                  _log.debug('cannot run <gm_print_doc(.bat)>')
    310                  return False
    311          gm_print_doc.communicate()
    312          if gm_print_doc.returncode != 0:
    313                  _log.error('<gm_print_doc> returned [%s], failed to print', gm_print_doc.returncode)
    314                  return False
    315
    316          return True
    317
    318  #       args = u' %s %s' % (jobtype, filename)
    319  #       success = gmShellAPI.run_first_available_in_shell (
    320  #               binaries = candidates,
    321  #               args = args,
    322  #               blocking = True,
    323  #               run_last_one_anyway = True
    324  #       )
    325  #
    326  #       if success:
    327  #               return True
    328  #
    329  #       _log.error('print command failed')
    330  #       return False
    331  #=======================================================================
    332  # main
    333  #-----------------------------------------------------------------------
    334  if __name__ == '__main__':
    335
    336          if len(sys.argv) < 2:
    337                  sys.exit()
    338
    339          if sys.argv[1] != 'test':
    340                  sys.exit()
    341
    342          from Gnumed.pycommon import gmLog2
    343          from Gnumed.pycommon import gmI18N
    344          gmI18N.activate_locale()
    345          gmI18N.install_domain()
    346
    347          #--------------------------------------------------------------------
    348 -        def test_print_files():
    349                  return print_files(filenames = [sys.argv[2]], jobtype = sys.argv[3])
    350          #--------------------------------------------------------------------
    351 -        def test_print_files_by_shellscript():
    352                  print_files(filenames = [sys.argv[2], sys.argv[2]], jobtype = u'generic_document', print_api = 'gm-print_doc')
    353          #--------------------------------------------------------------------
    354 -        def test_print_files_by_gtklp():
    355                  print_files(filenames = [sys.argv[2], sys.argv[2]], jobtype = u'generic_document', print_api = u'gtklp')
    356          #--------------------------------------------------------------------
    357 -        def test_print_files_by_mac_preview():
    358                  print "testing printing via Mac Preview"
    359                  _print_files_by_mac_preview(filenames = [sys.argv[0]])
    360          #--------------------------------------------------------------------
    361          print test_print_files()
    362          #test_print_files_by_gtklp()
    363          #test_print_files_by_mac_preview()
    364
    365  # =======================================================================
    366