AIM-PIbd-32-Kurbanova-A-A/aimenv/Lib/site-packages/pythonwin/pywin/framework/app.py
2024-10-02 22:15:59 +04:00

458 lines
16 KiB
Python

# App.py
# Application stuff.
# The application is responsible for managing the main frame window.
#
# We also grab the FileOpen command, to invoke our Python editor
" The PythonWin application code. Manages most aspects of MDI, etc "
import os
import sys
import traceback
import regutil
import win32api
import win32con
import win32ui
from pywin.mfc import afxres, dialog, window
from pywin.mfc.thread import WinApp
from . import scriptutils
## NOTE: App and AppBuild should NOT be used - instead, you should contruct your
## APP class manually whenever you like (just ensure you leave these 2 params None!)
## Whoever wants the generic "Application" should get it via win32iu.GetApp()
# These are "legacy"
AppBuilder = None
App = None # default - if used, must end up a CApp derived class.
# Helpers that should one day be removed!
def AddIdleHandler(handler):
print(
"app.AddIdleHandler is deprecated - please use win32ui.GetApp().AddIdleHandler() instead."
)
return win32ui.GetApp().AddIdleHandler(handler)
def DeleteIdleHandler(handler):
print(
"app.DeleteIdleHandler is deprecated - please use win32ui.GetApp().DeleteIdleHandler() instead."
)
return win32ui.GetApp().DeleteIdleHandler(handler)
# Helper for writing a Window position by name, and later loading it.
def SaveWindowSize(section, rect, state=""):
"""Writes a rectangle to an INI file
Args: section = section name in the applications INI file
rect = a rectangle in a (cy, cx, y, x) tuple
(same format as CREATESTRUCT position tuples)."""
left, top, right, bottom = rect
if state:
state = state + " "
win32ui.WriteProfileVal(section, state + "left", left)
win32ui.WriteProfileVal(section, state + "top", top)
win32ui.WriteProfileVal(section, state + "right", right)
win32ui.WriteProfileVal(section, state + "bottom", bottom)
def LoadWindowSize(section, state=""):
"""Loads a section from an INI file, and returns a rect in a tuple (see SaveWindowSize)"""
if state:
state = state + " "
left = win32ui.GetProfileVal(section, state + "left", 0)
top = win32ui.GetProfileVal(section, state + "top", 0)
right = win32ui.GetProfileVal(section, state + "right", 0)
bottom = win32ui.GetProfileVal(section, state + "bottom", 0)
return (left, top, right, bottom)
def RectToCreateStructRect(rect):
return (rect[3] - rect[1], rect[2] - rect[0], rect[1], rect[0])
# Define FrameWindow and Application objects
#
# The Main Frame of the application.
class MainFrame(window.MDIFrameWnd):
sectionPos = "Main Window"
statusBarIndicators = (
afxres.ID_SEPARATOR, # // status line indicator
afxres.ID_INDICATOR_CAPS,
afxres.ID_INDICATOR_NUM,
afxres.ID_INDICATOR_SCRL,
win32ui.ID_INDICATOR_LINENUM,
win32ui.ID_INDICATOR_COLNUM,
)
def OnCreate(self, cs):
self._CreateStatusBar()
return 0
def _CreateStatusBar(self):
self.statusBar = win32ui.CreateStatusBar(self)
self.statusBar.SetIndicators(self.statusBarIndicators)
self.HookCommandUpdate(self.OnUpdatePosIndicator, win32ui.ID_INDICATOR_LINENUM)
self.HookCommandUpdate(self.OnUpdatePosIndicator, win32ui.ID_INDICATOR_COLNUM)
def OnUpdatePosIndicator(self, cmdui):
editControl = scriptutils.GetActiveEditControl()
value = " " * 5
if editControl is not None:
try:
startChar, endChar = editControl.GetSel()
lineNo = editControl.LineFromChar(startChar)
colNo = endChar - editControl.LineIndex(lineNo)
if cmdui.m_nID == win32ui.ID_INDICATOR_LINENUM:
value = "%0*d" % (5, lineNo + 1)
else:
value = "%0*d" % (3, colNo + 1)
except win32ui.error:
pass
cmdui.SetText(value)
cmdui.Enable()
def PreCreateWindow(self, cc):
cc = self._obj_.PreCreateWindow(cc)
pos = LoadWindowSize(self.sectionPos)
self.startRect = pos
if pos[2] - pos[0]:
rect = RectToCreateStructRect(pos)
cc = cc[0], cc[1], cc[2], cc[3], rect, cc[5], cc[6], cc[7], cc[8]
return cc
def OnDestroy(self, msg):
# use GetWindowPlacement(), as it works even when min'd or max'd
rectNow = self.GetWindowPlacement()[4]
if rectNow != self.startRect:
SaveWindowSize(self.sectionPos, rectNow)
return 0
class CApp(WinApp):
"A class for the application"
def __init__(self):
self.oldCallbackCaller = None
WinApp.__init__(self, win32ui.GetApp())
self.idleHandlers = []
def InitInstance(self):
"Called to crank up the app"
HookInput()
numMRU = win32ui.GetProfileVal("Settings", "Recent File List Size", 10)
win32ui.LoadStdProfileSettings(numMRU)
# self._obj_.InitMDIInstance()
if win32api.GetVersionEx()[0] < 4:
win32ui.SetDialogBkColor()
win32ui.Enable3dControls()
# install a "callback caller" - a manager for the callbacks
# self.oldCallbackCaller = win32ui.InstallCallbackCaller(self.CallbackManager)
self.LoadMainFrame()
self.SetApplicationPaths()
def ExitInstance(self):
"Called as the app dies - too late to prevent it here!"
win32ui.OutputDebug("Application shutdown\n")
# Restore the callback manager, if any.
try:
win32ui.InstallCallbackCaller(self.oldCallbackCaller)
except AttributeError:
pass
if self.oldCallbackCaller:
del self.oldCallbackCaller
self.frame = None # clean Python references to the now destroyed window object.
self.idleHandlers = []
# Attempt cleanup if not already done!
if self._obj_:
self._obj_.AttachObject(None)
self._obj_ = None
global App
global AppBuilder
App = None
AppBuilder = None
return 0
def HaveIdleHandler(self, handler):
return handler in self.idleHandlers
def AddIdleHandler(self, handler):
self.idleHandlers.append(handler)
def DeleteIdleHandler(self, handler):
self.idleHandlers.remove(handler)
def OnIdle(self, count):
try:
ret = 0
handlers = self.idleHandlers[:] # copy list, as may be modified during loop
for handler in handlers:
try:
thisRet = handler(handler, count)
except:
print("Idle handler %s failed" % (repr(handler)))
traceback.print_exc()
print("Idle handler removed from list")
try:
self.DeleteIdleHandler(handler)
except ValueError: # Item not in list.
pass
thisRet = 0
ret = ret or thisRet
return ret
except KeyboardInterrupt:
pass
def CreateMainFrame(self):
return MainFrame()
def LoadMainFrame(self):
"Create the main applications frame"
self.frame = self.CreateMainFrame()
self.SetMainFrame(self.frame)
self.frame.LoadFrame(win32ui.IDR_MAINFRAME, win32con.WS_OVERLAPPEDWINDOW)
self.frame.DragAcceptFiles() # we can accept these.
self.frame.ShowWindow(win32ui.GetInitialStateRequest())
self.frame.UpdateWindow()
self.HookCommands()
def OnHelp(self, id, code):
try:
if id == win32ui.ID_HELP_GUI_REF:
helpFile = regutil.GetRegisteredHelpFile("Pythonwin Reference")
helpCmd = win32con.HELP_CONTENTS
else:
helpFile = regutil.GetRegisteredHelpFile("Main Python Documentation")
helpCmd = win32con.HELP_FINDER
if helpFile is None:
win32ui.MessageBox("The help file is not registered!")
else:
from . import help
help.OpenHelpFile(helpFile, helpCmd)
except:
t, v, tb = sys.exc_info()
win32ui.MessageBox(
"Internal error in help file processing\r\n%s: %s" % (t, v)
)
tb = None # Prevent a cycle
def DoLoadModules(self, modules):
# XXX - this should go, but the debugger uses it :-(
# dont do much checking!
for module in modules:
__import__(module)
def HookCommands(self):
self.frame.HookMessage(self.OnDropFiles, win32con.WM_DROPFILES)
self.HookCommand(self.HandleOnFileOpen, win32ui.ID_FILE_OPEN)
self.HookCommand(self.HandleOnFileNew, win32ui.ID_FILE_NEW)
self.HookCommand(self.OnFileMRU, win32ui.ID_FILE_MRU_FILE1)
self.HookCommand(self.OnHelpAbout, win32ui.ID_APP_ABOUT)
self.HookCommand(self.OnHelp, win32ui.ID_HELP_PYTHON)
self.HookCommand(self.OnHelp, win32ui.ID_HELP_GUI_REF)
# Hook for the right-click menu.
self.frame.GetWindow(win32con.GW_CHILD).HookMessage(
self.OnRClick, win32con.WM_RBUTTONDOWN
)
def SetApplicationPaths(self):
# Load the users/application paths
new_path = []
apppath = win32ui.GetProfileVal("Python", "Application Path", "").split(";")
for path in apppath:
if len(path) > 0:
new_path.append(win32ui.FullPath(path))
for extra_num in range(1, 11):
apppath = win32ui.GetProfileVal(
"Python", "Application Path %d" % extra_num, ""
).split(";")
if len(apppath) == 0:
break
for path in apppath:
if len(path) > 0:
new_path.append(win32ui.FullPath(path))
sys.path = new_path + sys.path
def OnRClick(self, params):
"Handle right click message"
# put up the entire FILE menu!
menu = win32ui.LoadMenu(win32ui.IDR_TEXTTYPE).GetSubMenu(0)
menu.TrackPopupMenu(params[5]) # track at mouse position.
return 0
def OnDropFiles(self, msg):
"Handle a file being dropped from file manager"
hDropInfo = msg[2]
self.frame.SetActiveWindow() # active us
nFiles = win32api.DragQueryFile(hDropInfo)
try:
for iFile in range(0, nFiles):
fileName = win32api.DragQueryFile(hDropInfo, iFile)
win32ui.GetApp().OpenDocumentFile(fileName)
finally:
win32api.DragFinish(hDropInfo)
return 0
# No longer used by Pythonwin, as the C++ code has this same basic functionality
# but handles errors slightly better.
# It all still works, tho, so if you need similar functionality, you can use it.
# Therefore I havent deleted this code completely!
# def CallbackManager( self, ob, args = () ):
# """Manage win32 callbacks. Trap exceptions, report on them, then return 'All OK'
# to the frame-work. """
# import traceback
# try:
# ret = apply(ob, args)
# return ret
# except:
# # take copies of the exception values, else other (handled) exceptions may get
# # copied over by the other fns called.
# win32ui.SetStatusText('An exception occured in a windows command handler.')
# t, v, tb = sys.exc_info()
# traceback.print_exception(t, v, tb.tb_next)
# try:
# sys.stdout.flush()
# except (NameError, AttributeError):
# pass
# Command handlers.
def OnFileMRU(self, id, code):
"Called when a File 1-n message is recieved"
fileName = win32ui.GetRecentFileList()[id - win32ui.ID_FILE_MRU_FILE1]
win32ui.GetApp().OpenDocumentFile(fileName)
def HandleOnFileOpen(self, id, code):
"Called when FileOpen message is received"
win32ui.GetApp().OnFileOpen()
def HandleOnFileNew(self, id, code):
"Called when FileNew message is received"
win32ui.GetApp().OnFileNew()
def OnHelpAbout(self, id, code):
"Called when HelpAbout message is received. Displays the About dialog."
win32ui.InitRichEdit()
dlg = AboutBox()
dlg.DoModal()
def _GetRegistryValue(key, val, default=None):
# val is registry value - None for default val.
try:
hkey = win32api.RegOpenKey(win32con.HKEY_CURRENT_USER, key)
return win32api.RegQueryValueEx(hkey, val)[0]
except win32api.error:
try:
hkey = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, key)
return win32api.RegQueryValueEx(hkey, val)[0]
except win32api.error:
return default
scintilla = "Scintilla is Copyright 1998-2008 Neil Hodgson (http://www.scintilla.org)"
idle = "This program uses IDLE extensions by Guido van Rossum, Tim Peters and others."
contributors = "Thanks to the following people for making significant contributions: Roger Upole, Sidnei da Silva, Sam Rushing, Curt Hagenlocher, Dave Brennan, Roger Burnham, Gordon McMillan, Neil Hodgson, Laramie Leavitt. (let me know if I have forgotten you!)"
# The About Box
class AboutBox(dialog.Dialog):
def __init__(self, idd=win32ui.IDD_ABOUTBOX):
dialog.Dialog.__init__(self, idd)
def OnInitDialog(self):
text = (
"Pythonwin - Python IDE and GUI Framework for Windows.\n\n%s\n\nPython is %s\n\n%s\n\n%s\n\n%s"
% (win32ui.copyright, sys.copyright, scintilla, idle, contributors)
)
self.SetDlgItemText(win32ui.IDC_EDIT1, text)
# Get the build number - written by installers.
# For distutils build, read pywin32.version.txt
import sysconfig
site_packages = sysconfig.get_paths()["platlib"]
try:
build_no = (
open(os.path.join(site_packages, "pywin32.version.txt")).read().strip()
)
ver = "pywin32 build %s" % build_no
except EnvironmentError:
ver = None
if ver is None:
# See if we are Part of Active Python
ver = _GetRegistryValue(
"SOFTWARE\\ActiveState\\ActivePython", "CurrentVersion"
)
if ver is not None:
ver = "ActivePython build %s" % (ver,)
if ver is None:
ver = ""
self.SetDlgItemText(win32ui.IDC_ABOUT_VERSION, ver)
self.HookCommand(self.OnButHomePage, win32ui.IDC_BUTTON1)
def OnButHomePage(self, id, code):
if code == win32con.BN_CLICKED:
win32api.ShellExecute(
0, "open", "https://github.com/mhammond/pywin32", None, "", 1
)
def Win32RawInput(prompt=None):
"Provide raw_input() for gui apps"
# flush stderr/out first.
try:
sys.stdout.flush()
sys.stderr.flush()
except:
pass
if prompt is None:
prompt = ""
ret = dialog.GetSimpleInput(prompt)
if ret == None:
raise KeyboardInterrupt("operation cancelled")
return ret
def Win32Input(prompt=None):
"Provide input() for gui apps"
return eval(input(prompt))
def HookInput():
try:
raw_input
# must be py2x...
sys.modules["__builtin__"].raw_input = Win32RawInput
sys.modules["__builtin__"].input = Win32Input
except NameError:
# must be py3k
import code
sys.modules["builtins"].input = Win32RawInput
def HaveGoodGUI():
"""Returns true if we currently have a good gui available."""
return "pywin.framework.startup" in sys.modules
def CreateDefaultGUI(appClass=None):
"""Creates a default GUI environment"""
if appClass is None:
from . import intpyapp # Bring in the default app - could be param'd later.
appClass = intpyapp.InteractivePythonApp
# Create and init the app.
appClass().InitInstance()
def CheckCreateDefaultGUI():
"""Checks and creates if necessary a default GUI environment."""
rc = HaveGoodGUI()
if not rc:
CreateDefaultGUI()
return rc