2022-03-29 03:18:34 +00:00
#!/usr/bin/env python3
# requires: pywin32, pillow, qtpy, a module compatible with qtpy (try pyqt5)
import sys
import ctypes
import traceback
import win32clipboard
oldexcepthook = sys . excepthook
def newexcepthook ( type , value , tb ) :
excText = " " . join ( traceback . format_exception ( type , value , tb ) )
try :
for window in windows :
try :
window . close ( )
except :
pass
except :
pass
output = ctypes . windll . user32 . MessageBoxW ( None , u " " + excText + " \n The program must close. Copy exception to clipboard? " , u " Unhandled exception - batchprint " , 0x00000114 )
if output == 6 :
copyString ( excText )
oldexcepthook ( type , value , tb )
sys . excepthook = newexcepthook
def copyString ( s ) :
win32clipboard . OpenClipboard ( )
win32clipboard . EmptyClipboard ( )
win32clipboard . SetClipboardText ( s , win32clipboard . CF_UNICODETEXT )
win32clipboard . CloseClipboard ( )
import os
p = os . path . join
pUp = os . path . dirname
s = False
if getattr ( sys , ' frozen ' , False ) and hasattr ( sys , ' _MEIPASS ' ) :
s = os . path . realpath ( sys . executable )
else :
s = os . path . realpath ( __file__ )
sp = pUp ( s )
import winreg
import subprocess
import win32print
import win32ui
import PIL . Image
import PIL . ImageWin
import time
import qtpy
import qtpy . QtGui as QtGui
from qtpy . QtGui import *
from qtpy . QtWidgets import *
from qtpy . QtCore import *
2023-08-23 23:43:00 +00:00
# https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-getdevicecaps
HORZRES = 8
VERTRES = 10
2022-03-29 03:18:34 +00:00
PHYSICALWIDTH = 110
PHYSICALHEIGHT = 111
2023-08-23 23:43:00 +00:00
PHYSICALOFFSETX = 112
PHYSICALOFFSETY = 113
2022-03-29 03:18:34 +00:00
def getPrinters ( ) :
hive = winreg . ConnectRegistry ( None , winreg . HKEY_LOCAL_MACHINE )
key = winreg . OpenKey ( hive , r " SYSTEM \ CurrentControlSet \ Control \ Print \ Printers " )
printers = [ ]
index = 0
while True :
try :
printers . append ( winreg . EnumKey ( key , index ) )
index + = 1
except OSError :
break
winreg . CloseKey ( key )
hive . Close ( )
return printers
def printerOpenProperties ( printerName ) :
subprocess . Popen ( [ " rundll32 " , " printui.dll,PrintUIEntry " , " /e " , " /n " + printerName ] ) . wait ( )
def printerOpenQueue ( printerName ) :
subprocess . Popen ( [ " rundll32 " , " printui.dll,PrintUIEntry " , " /o " , " /n " + printerName ] )
class printerWindow ( QMainWindow ) :
def __init__ ( self , printers , * args , * * kwargs ) :
super ( ) . __init__ ( * args , * * kwargs )
self . cTitle = " Choose a printer - batchprint "
self . setWindowTitle ( self . cTitle )
self . cWidth = 320
self . cHeight = 82
self . resize ( self . cWidth , self . cHeight )
self . cPrinters = printers
self . cCreateElements ( )
def cCreateElements ( self ) :
self . cLabel = QLabel ( self )
self . cLabel . setText ( " Choose a printer: " )
self . cLabel . setAlignment ( Qt . AlignCenter )
self . cDropdown = QComboBox ( self )
2023-08-23 11:55:19 +00:00
self . cDropdown . addItems ( self . cPrinters )
try :
with open ( p ( sp , " lastprinter.txt " ) , " r " , encoding = " utf-8 " ) as f :
printer = f . read ( )
self . cDropdown . setCurrentIndex ( self . cPrinters . index ( printer ) )
except :
pass
2022-03-29 03:18:34 +00:00
self . cButton = QPushButton ( self )
self . cButton . setText ( " OK " )
self . cButton . clicked . connect ( self . cOpenList )
2023-08-23 11:56:31 +00:00
self . cButtonSettings = QPushButton ( self )
self . cButtonSettings . setText ( " Settings " )
self . cButtonSettings . clicked . connect ( self . cOpenSettings )
2022-03-29 03:18:34 +00:00
self . cResizeElements ( )
self . show ( )
def cResizeElements ( self ) :
self . cLabel . move ( 0 , 5 )
self . cLabel . resize ( self . cWidth , 15 )
self . cDropdown . move ( 10 , 25 )
self . cDropdown . resize ( self . cWidth - 20 , 22 )
self . cButton . move ( self . cWidth - 64 - 5 , self . cHeight - 22 - 5 )
self . cButton . resize ( 64 , 22 )
2023-08-23 11:56:48 +00:00
self . cButtonSettings . move ( 5 , self . cHeight - 22 - 5 )
self . cButtonSettings . resize ( 64 , 22 )
2022-03-29 03:18:34 +00:00
def resizeEvent ( self , event ) :
self . cWidth = self . width ( )
self . cHeight = self . height ( )
self . cResizeElements ( )
def closeEvent ( self , event ) :
windows . remove ( self )
def cOpenList ( self ) :
printer = self . cDropdown . currentText ( )
2023-08-23 11:55:19 +00:00
try :
with open ( p ( sp , " lastprinter.txt " ) , " w " , encoding = " utf-8 " ) as f :
f . write ( printer )
except :
pass
2022-03-29 03:18:34 +00:00
self . close ( )
2023-08-23 23:43:00 +00:00
#printerOpenQueue(printer)
2022-03-29 03:18:34 +00:00
windows . append ( queueWindow ( printer ) )
2023-08-23 11:56:31 +00:00
def cOpenSettings ( self ) :
printer = self . cDropdown . currentText ( )
2023-08-23 23:43:00 +00:00
self . hide ( )
2023-08-23 11:56:31 +00:00
printerOpenProperties ( printer )
2023-08-23 23:43:00 +00:00
self . cOpenList ( )
2022-03-29 03:18:34 +00:00
class queueWindow ( QMainWindow ) :
def __init__ ( self , printer , * args , * * kwargs ) :
super ( ) . __init__ ( * args , * * kwargs )
self . setAcceptDrops ( True )
self . cWidth = 240
self . cHeight = 200
self . resize ( self . cWidth , self . cHeight )
self . cPrinter = printer
self . cDC = win32ui . CreateDC ( )
self . cDC . CreatePrinterDC ( printer )
2023-08-23 23:43:00 +00:00
self . cPrinterPhysicalSize = [ self . cDC . GetDeviceCaps ( PHYSICALWIDTH ) , self . cDC . GetDeviceCaps ( PHYSICALHEIGHT ) ]
self . cPrinterPrintSize = [ self . cDC . GetDeviceCaps ( HORZRES ) , self . cDC . GetDeviceCaps ( VERTRES ) ]
self . cPrinterPrintOffset = [ self . cDC . GetDeviceCaps ( PHYSICALOFFSETX ) , self . cDC . GetDeviceCaps ( PHYSICALOFFSETY ) ]
self . cTitle = printer + " ( " + str ( self . cPrinterPrintSize [ 0 ] ) + " x " + str ( self . cPrinterPrintSize [ 1 ] ) + " ) - batchprint "
self . setWindowTitle ( self . cTitle )
2022-03-29 03:18:34 +00:00
self . cCreateElements ( )
def cCreateElements ( self ) :
self . cLabel = QLabel ( self )
self . cLabel . setText ( " Drag & Drop images here " )
self . cLabel . setAlignment ( Qt . AlignCenter )
self . cLabel . setWordWrap ( True )
2023-08-23 11:56:48 +00:00
self . cTick = QCheckBox ( self )
2023-08-23 23:43:00 +00:00
self . cTick . setText ( " Do not scale/rotate " )
2023-08-23 11:56:48 +00:00
self . cTick . setChecked ( False )
try :
with open ( p ( sp , " rawprint.txt " ) , encoding = " utf-8 " ) as f :
rawprint = int ( f . read ( ) )
if rawprint : self . cTick . setChecked ( True )
except :
pass
2022-03-29 03:18:34 +00:00
self . cResizeElements ( )
self . show ( )
def cResizeElements ( self ) :
self . cLabel . move ( 0 , 0 )
self . cLabel . resize ( self . cWidth , self . cHeight )
2023-08-23 23:43:00 +00:00
self . cTick . move ( 5 , 0 )
self . cTick . resize ( self . cWidth - 10 , 22 )
2022-03-29 03:18:34 +00:00
def resizeEvent ( self , event ) :
self . cWidth = self . width ( )
self . cHeight = self . height ( )
self . cResizeElements ( )
def dragEnterEvent ( self , event ) :
self . activateWindow ( )
if event . mimeData ( ) . hasUrls ( ) :
self . cLabel . setStyleSheet ( " font-weight: bold " )
event . accept ( )
def dragLeaveEvent ( self , event ) :
self . cLabel . setStyleSheet ( " " )
def dropEvent ( self , event ) :
self . cLabel . setStyleSheet ( " " )
2023-08-23 11:56:48 +00:00
rawprint = self . cTick . isChecked ( )
2022-03-29 03:18:34 +00:00
for url in event . mimeData ( ) . urls ( ) :
path = str ( url . toLocalFile ( ) ) . replace ( " / " , os . path . sep )
self . cLabel . setText ( path . rsplit ( os . path . sep , 1 ) [ - 1 ] + " ... " )
self . repaint ( )
bmp = PIL . Image . open ( path )
2023-08-23 11:56:48 +00:00
if not rawprint :
if bmp . size [ 1 ] > bmp . size [ 0 ] :
2023-08-23 23:43:00 +00:00
if self . cPrinterPrintSize [ 0 ] > self . cPrinterPrintSize [ 1 ] :
2023-08-23 11:56:48 +00:00
bmp = bmp . transpose ( PIL . Image . ROTATE_90 )
elif bmp . size [ 0 ] > bmp . size [ 1 ] :
2023-08-23 23:43:00 +00:00
if self . cPrinterPrintSize [ 1 ] > self . cPrinterPrintSize [ 0 ] :
2023-08-23 11:56:48 +00:00
bmp = bmp . transpose ( PIL . Image . ROTATE_90 )
2023-08-23 23:43:00 +00:00
imWidth = self . cPrinterPrintSize [ 0 ]
imHeight = self . cPrinterPrintSize [ 1 ]
2023-08-23 11:56:48 +00:00
else :
imWidth = bmp . size [ 0 ]
imHeight = bmp . size [ 1 ]
2022-03-29 03:18:34 +00:00
self . cDC . StartDoc ( path )
self . cDC . StartPage ( )
dib = PIL . ImageWin . Dib ( bmp )
2023-08-23 23:43:00 +00:00
dib . draw ( self . cDC . GetHandleOutput ( ) , (
self . cPrinterPrintOffset [ 0 ] , self . cPrinterPrintOffset [ 1 ] ,
imWidth , imHeight
) )
2022-03-29 03:18:34 +00:00
self . cDC . EndPage ( )
self . cDC . EndDoc ( )
self . cLabel . setText ( " Drag & Drop images here " )
def closeEvent ( self , event ) :
2023-08-23 11:56:48 +00:00
try :
with open ( p ( sp , " rawprint.txt " ) , " w " , encoding = " utf-8 " ) as f :
if self . cTick . isChecked ( ) :
f . write ( " 1 " )
else :
f . write ( " 0 " )
except :
pass
2022-03-29 03:18:34 +00:00
self . cDC . DeleteDC ( )
windows . remove ( self )
windows = [ ]
printers = getPrinters ( )
app = QApplication ( sys . argv )
windows . append ( printerWindow ( printers ) )
app . exec_ ( )