CraftLaunch APIリファレンス

clnch_misc.py

00001 import sys
00002 import os
00003 import shutil
00004 import datetime
00005 import ctypes
00006 
00007 import pyauto
00008 import cterm
00009 
00010 import clnch_resource
00011 from cterm.cterm_const import *
00012 
00013 import clnch_native
00014 
00015 #--------------------------------------------------------------------
00016 
00017 use_slash = False
00018 ignore_1second = True
00019 
00020 #--------------------------------------------------------------------
00021 
00022 class ScrollInfo:
00023 
00024     def __init__( self ):
00025         self.pos = 0
00026 
00027     def makeVisible( self, index, visible_height, margin=0 ):
00028         if margin > visible_height/2 : margin = visible_height/2
00029         if index < self.pos + margin :
00030             self.pos = index - margin
00031         elif index > self.pos + visible_height - 1 - margin :
00032             self.pos = index - visible_height + 1 + margin
00033         if self.pos<0 : self.pos=0
00034 
00035 #--------------------------------------------------------------------
00036 
00037 
00038 ## キーイベント
00039 #
00040 #  仮想キーコードとモディファイアキーの情報を組み合わせたクラスです。\n
00041 #  キーボードからの入力に動作を割り当てるために使用します。
00042 #
00043 #  @sa ChrEvent
00044 #  @sa KeyMapCondition
00045 #
00046 class KeyEvent:
00047 
00048     ## コンストラクタ
00049     #  @param self  -
00050     #  @param vk    仮想キーコード
00051     #  @param mod   モディファイアキー
00052     def __init__( self, vk, mod ):
00053         self.vk = vk
00054         self.mod = mod
00055 
00056 
00057 ## 文字入力イベント
00058 #
00059 #  入力された文字の情報を持つクラスです。\n
00060 #  キーボードからの入力に動作を割り当てるために使用します。
00061 #
00062 #  @sa KeyEvent
00063 #  @sa KeyMapCondition
00064 #
00065 class ChrEvent:
00066 
00067     ## コンストラクタ
00068     #  @param self  -
00069     #  @param ch    文字
00070     def __init__( self, ch ):
00071         if isinstance(ch,str):
00072             ch = ord(ch)
00073         self.ch = ch
00074 
00075 
00076 ## キーマップの入力条件
00077 #
00078 #  KeyEvent または ChrEvent とファイルリストの選択状態を組み合わせたクラスです。\n
00079 #  キーボードからの入力に動作を割り当てるために使用します。
00080 #  
00081 #  @sa KeyEvent
00082 #  @sa ChrEvent
00083 #
00084 class KeyMapCondition:
00085 
00086     ## コンストラクタ
00087     #  @param self          -
00088     #  @param input_event   入力イベントオブジェクト ( KeyEvent または ChrEvent )
00089     #  @param select        ファイルリストのアイテムの選択状態 \n ( None:気にしない  True:選択されている  False:選択されていない )
00090     def __init__( self, input_event, select=None ):
00091         self.input_event = input_event
00092         self.select = select
00093 
00094     def __hash__(self):
00095         if isinstance(self.input_event,KeyEvent):
00096             return self.input_event.vk
00097         elif isinstance(self.input_event,ChrEvent):
00098             return self.input_event.ch
00099         else:
00100             assert(False)
00101 
00102     def __eq__(self,rhs):
00103         if isinstance(self.input_event,KeyEvent):
00104             if isinstance(rhs.input_event,KeyEvent):
00105                 if self.input_event.vk!=rhs.input_event.vk : return False
00106                 if self.input_event.mod!=rhs.input_event.mod : return False
00107                 if self.select!=None and rhs.select!=None:
00108                     if callable(self.select):self.select = self.select()
00109                     if callable(rhs.select):rhs.select = rhs.select()
00110                     if self.select!=rhs.select : return False
00111                 return True
00112             else:
00113                 return False
00114         elif isinstance(self.input_event,ChrEvent):
00115             if isinstance(rhs.input_event,ChrEvent):
00116                 if self.input_event.ch!=rhs.input_event.ch : return False
00117                 if callable(self.select):self.select = self.select()
00118                 if callable(rhs.select):rhs.select = rhs.select()
00119                 if self.select!=None and rhs.select!=None:
00120                     if callable(self.select):self.select = self.select()
00121                     if callable(rhs.select):rhs.select = rhs.select()
00122                     if self.select!=rhs.select : return False
00123                 return True
00124             else:
00125                 return False
00126         return False
00127 
00128 
00129 class KeyMap(dict):
00130     def __setitem__( self, key, value ):
00131         if isinstance(key,KeyEvent):
00132             key = KeyMapCondition( key )
00133         elif isinstance(key,ChrEvent):
00134             key = KeyMapCondition( key )
00135         elif isinstance(key,int):
00136             key = KeyMapCondition( KeyEvent(key,0) )
00137         elif isinstance(key,str) and len(key)==1:
00138             key = KeyMapCondition( ChrEvent(key) )
00139         dict.__setitem__( self, key, value )
00140 
00141 #--------------------------------------------------------------------
00142 
00143 def getFileSizeString(size):
00144     
00145     if size < 1000:
00146         return "%dB" % ( size, )
00147     
00148     if size < 1000*1024:
00149         s = "%.1fK" % ( size / float(1024), )
00150         if len(s)<=6 : return s
00151 
00152     if size < 1000*1024*1024:
00153         s = "%.1fM" % ( size / float(1024*1024), )
00154         if len(s)<=6 : return s
00155 
00156     if size < 1000*1024*1024*1024:
00157         s = "%.1fG" % ( size / float(1024*1024*1024), )
00158         if len(s)<=6 : return s
00159     
00160     return "%.1fT" % ( size / float(1024*1024*1024*1024), )
00161 
00162 #--------------------------------------------------------------------
00163 
00164 def detectTextEncoding( data, maxline=1000 ):
00165 
00166     if data[:3] == "\xEF\xBB\xBF":
00167         return 'utf-8', data[3:]
00168     elif data[:2] == "\xFF\xFE":
00169         return 'utf-16-le', data[2:]
00170     elif data[:2] == "\xFE\xFF":
00171         return 'utf-16-be', data[2:]
00172 
00173     if data.find('\0')>=0 : return None, data
00174 
00175     lines = data.splitlines()
00176 
00177     encoding_list = [
00178         [ 'ascii', 0 ],
00179         [ 'shift-jis', 0 ],
00180         [ 'euc-jp', 0 ],
00181         [ 'iso-2022-jp', 0 ],
00182         [ 'utf-8', 0 ],
00183     ]
00184 
00185     numline_read = 0
00186 
00187     for line in lines:
00188 
00189         for encoding in encoding_list:
00190             try:
00191                 uniode_line = unicode( line, encoding[0] )
00192             except UnicodeDecodeError:
00193                 encoding[1] -= 1
00194             else:
00195                 if len(uniode_line)<len(line):
00196                     encoding[1] += 1
00197 
00198         numline_read += 1
00199         if numline_read >= maxline : break
00200 
00201     best_encoding = [ None, -1 ]
00202 
00203     for encoding in encoding_list:
00204         if encoding[1]>best_encoding[1]:
00205             best_encoding = encoding
00206 
00207     return best_encoding[0], data
00208 
00209 #--------------------------------------------------------------------
00210 
00211 def getDesktopPath():
00212 
00213     MAX_PATH = 260
00214     CSIDL_DESKTOPDIRECTORY = 0x10
00215 
00216     buf = ctypes.create_unicode_buffer(MAX_PATH)
00217     ctypes.windll.shell32.SHGetSpecialFolderPathW( None, buf, CSIDL_DESKTOPDIRECTORY, 0 )
00218 
00219     return buf.value
00220 
00221 
00222 def getDrives():
00223     drives = ""
00224     drive_bits = ctypes.windll.kernel32.GetLogicalDrives()
00225     for i in xrange(26):
00226         if drive_bits & (1<<i):
00227             drives += chr(ord('A')+i)
00228     return drives
00229 
00230 
00231 def getDriveType(drive):
00232 
00233     DRIVE_TYPE_UNDTERMINED = 0
00234     DRIVE_ROOT_NOT_EXIST = 1
00235     DRIVE_REMOVABLE = 2
00236     DRIVE_FIXED = 3
00237     DRIVE_REMOTE = 4
00238     DRIVE_CDROM = 5
00239     DRIVE_RAMDISK = 6
00240 
00241     if type(drive)==type(''):
00242         drive = unicode(drive,'mbcs')
00243 
00244     drive_type = ctypes.windll.kernel32.GetDriveTypeW(drive)
00245 
00246     if drive_type==DRIVE_TYPE_UNDTERMINED:
00247         return u""
00248     elif drive_type==DRIVE_ROOT_NOT_EXIST:
00249         return u""
00250     elif drive_type==DRIVE_REMOVABLE:
00251         return u"Removable"
00252     elif drive_type==DRIVE_FIXED:
00253         return u"HDD"
00254     elif drive_type==DRIVE_REMOTE:
00255         return u"Network"
00256     elif drive_type==DRIVE_CDROM:
00257         return u"CD/DVD"
00258     elif drive_type==DRIVE_RAMDISK:
00259         return u"Ramdisk"
00260     return u""
00261 
00262 
00263 # "C:\" の形式で渡す必要がある
00264 def getDriveDisplayName(drive):
00265 
00266     MAX_PATH = 260
00267     HICON = ctypes.c_int
00268 
00269     class SHFILEINFO(ctypes.Structure):
00270         _fields_ = [("hIcon", HICON),
00271                     ("iIcon", ctypes.c_int),
00272                     ("dwAttributes", ctypes.c_uint),
00273                     ("szDisplayName", ctypes.c_wchar * MAX_PATH),
00274                     ("szTypeName", ctypes.c_wchar * 80)]
00275 
00276     SHGFI_ICON              = 0x000000100
00277     SHGFI_DISPLAYNAME       = 0x000000200
00278     SHGFI_TYPENAME          = 0x000000400
00279     SHGFI_ATTRIBUTES        = 0x000000800
00280     SHGFI_ICONLOCATION      = 0x000001000
00281     SHGFI_EXETYPE           = 0x000002000
00282     SHGFI_SYSICONINDEX      = 0x000004000
00283     SHGFI_LINKOVERLAY       = 0x000008000
00284     SHGFI_SELECTED          = 0x000010000
00285     SHGFI_ATTR_SPECIFIED    = 0x000020000
00286     SHGFI_LARGEICON         = 0x000000000
00287     SHGFI_SMALLICON         = 0x000000001
00288     SHGFI_OPENICON          = 0x000000002
00289     SHGFI_SHELLICONSIZE     = 0x000000004
00290     SHGFI_PIDL              = 0x000000008
00291     SHGFI_USEFILEATTRIBUTES = 0x000000010
00292 
00293     if type(drive)==type(''):
00294         drive = unicode(drive,'mbcs')
00295 
00296     shfileinfo = SHFILEINFO()
00297 
00298     flags = SHGFI_DISPLAYNAME
00299     ctypes.windll.shell32.SHGetFileInfoW(
00300         drive,
00301         0,
00302         ctypes.byref(shfileinfo),
00303         ctypes.sizeof(shfileinfo),
00304         flags
00305         )
00306 
00307     return shfileinfo.szDisplayName
00308 
00309 
00310 FILE_ATTRIBUTE_READONLY  = 0x00000001
00311 FILE_ATTRIBUTE_HIDDEN    = 0x00000002
00312 FILE_ATTRIBUTE_SYSTEM    = 0x00000004
00313 FILE_ATTRIBUTE_DIRECTORY = 0x00000010
00314 FILE_ATTRIBUTE_ARCHIVE   = 0x00000020
00315 FILE_ATTRIBUTE_DEVICE    = 0x00000040
00316 FILE_ATTRIBUTE_NORMAL    = 0x00000080
00317 
00318 def getFileAttribute(filename):
00319 
00320     if type(filename)==type(''):
00321         filename = unicode(filename,'mbcs')
00322 
00323     return ctypes.windll.kernel32.GetFileAttributesW(filename)
00324 
00325 
00326 def setFileAttribute(filename,attribute):
00327 
00328     if type(filename)==type(''):
00329         filename = unicode(filename,'mbcs')
00330 
00331     return ctypes.windll.kernel32.SetFileAttributesW(filename,attribute)
00332 
00333 
00334 def deleteFilesUsingRecycleBin( hwnd, filename_list ):
00335 
00336     class SHFILEOPSTRUCT(ctypes.Structure):
00337         _fields_ = [("hwnd", ctypes.c_int),
00338                     ("wFunc", ctypes.c_int),
00339                     ("pFrom", ctypes.c_wchar_p),
00340                     ("pTo", ctypes.c_wchar_p),
00341                     ("fFlags", ctypes.c_short),
00342                     ("fAnyOperationsAborted", ctypes.c_byte),
00343                     ("hNameMappings", ctypes.c_void_p),
00344                     ("lpszProgressTitle", ctypes.c_wchar_p)]
00345 
00346     joint_filenames = u""
00347     for filename in filename_list:
00348         filename = filename.replace(u"/",u"\\")
00349         joint_filenames += filename
00350         joint_filenames += u'\0'
00351     joint_filenames += u'\0'
00352 
00353     fileopdata = SHFILEOPSTRUCT()
00354     
00355     FO_MOVE   = 1
00356     FO_COPY   = 2
00357     FO_DELETE = 3
00358     FO_RENAME = 4
00359 
00360     FOF_MULTIDESTFILES          = 1
00361     FOF_CONFIRMMOUSE            = 2
00362     FOF_SILENT                  = 4
00363     FOF_RENAMEONCOLLISION       = 8
00364     FOF_NOCONFIRMATION          = 16
00365     FOF_WANTMAPPINGHANDLE       = 32
00366     FOF_ALLOWUNDO               = 64
00367     FOF_FILESONLY               = 128
00368     FOF_SIMPLEPROGRESS          = 256
00369     FOF_NOCONFIRMMKDIR          = 512
00370     FOF_NOERRORUI               = 1024
00371     FOF_NOCOPYSECURITYATTRIBS   = 2048
00372 
00373     fileopdata.hwnd = hwnd
00374     fileopdata.wFunc = FO_DELETE
00375     fileopdata.pFrom = joint_filenames
00376     fileopdata.pTo = 0
00377     fileopdata.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION
00378     #fileopdata.fFlags = FOF_ALLOWUNDO
00379     fileopdata.fAnyOperationsAborted = 0
00380     fileopdata.hNameMappings = 0
00381     fileopdata.lpszProgressTitle = 0;
00382 
00383     return ctypes.windll.shell32.SHFileOperationW(
00384         ctypes.byref(fileopdata)
00385         )
00386 
00387 #--------------------------------------------------------------------
00388 
00389 _net_connection_handler = None
00390 
00391 def registerNetConnectionHandler(handler):
00392     global _net_connection_handler
00393     _net_connection_handler = handler
00394 
00395 def checkNetConnection(path):
00396     unc = os.path.splitunc(path)
00397     if unc[0]:
00398         remote_resource_name = unc[0].replace('/','\\').rstrip('\\')
00399         try:
00400             _net_connection_handler(remote_resource_name)
00401         except Exception, e:
00402             print e
00403 
00404 #--------------------------------------------------------------------
00405 
00406 CF_UNICODETEXT = 13
00407 GHND = 66
00408 
00409 def getClipboardText():
00410     text = u""
00411     if ctypes.windll.user32.OpenClipboard(ctypes.c_int(0)):
00412         hClipMem = ctypes.windll.user32.GetClipboardData(ctypes.c_int(CF_UNICODETEXT))
00413         ctypes.windll.kernel32.GlobalLock.restype = ctypes.c_wchar_p
00414         text = ctypes.windll.kernel32.GlobalLock(ctypes.c_int(hClipMem))
00415         ctypes.windll.kernel32.GlobalUnlock(ctypes.c_int(hClipMem))
00416         ctypes.windll.user32.CloseClipboard()
00417     return text
00418 
00419 def setClipboardText(text):
00420     if type(text)==type(''):
00421         text = unicode(text,'mbcs')
00422     bufferSize = (len(text)+1)*2
00423     hGlobalMem = ctypes.windll.kernel32.GlobalAlloc(ctypes.c_int(GHND), ctypes.c_int(bufferSize))
00424     ctypes.windll.kernel32.GlobalLock.restype = ctypes.c_void_p
00425     lpGlobalMem = ctypes.windll.kernel32.GlobalLock(ctypes.c_int(hGlobalMem))
00426     ctypes.cdll.msvcrt.memcpy(lpGlobalMem, ctypes.c_wchar_p(text), ctypes.c_int(bufferSize))
00427     ctypes.windll.kernel32.GlobalUnlock(ctypes.c_int(hGlobalMem))
00428     if ctypes.windll.user32.OpenClipboard(0):
00429         ctypes.windll.user32.EmptyClipboard()
00430         ctypes.windll.user32.SetClipboardData(ctypes.c_int(CF_UNICODETEXT), ctypes.c_int(hGlobalMem))
00431         ctypes.windll.user32.CloseClipboard()
00432 
00433 #--------------------------------------------------------------------
00434 
00435 SW_NORMAL = 1
00436 
00437 def shellExecute( hwnd, verb, file, param, directory, swmode=SW_NORMAL, raise_error=False ):
00438 
00439     if type(verb)==type(''):
00440         verb = unicode(verb,'mbcs')
00441 
00442     if type(file)==type(''):
00443         file = unicode(file,'mbcs')
00444 
00445     if type(param)==type(''):
00446         param = unicode(param,'mbcs')
00447 
00448     if type(directory)==type(''):
00449         directory = unicode(directory,'mbcs')
00450 
00451     result = ctypes.windll.shell32.ShellExecuteW( hwnd, verb, file, param, directory, swmode )
00452     
00453     if raise_error and result<=32:
00454         
00455         ERROR_FILE_NOT_FOUND    = 2
00456         ERROR_PATH_NOT_FOUND    = 3
00457         ERROR_BAD_FORMAT        = 11
00458         SE_ERR_FNF              = 2
00459         SE_ERR_PNF              = 3
00460         SE_ERR_ACCESSDENIED     = 5
00461         SE_ERR_OOM              = 8
00462         SE_ERR_DLLNOTFOUND      = 32
00463         SE_ERR_SHARE            = 26
00464         SE_ERR_ASSOCINCOMPLETE  = 27
00465         SE_ERR_DDETIMEOUT       = 28
00466         SE_ERR_DDEFAIL          = 29
00467         SE_ERR_DDEBUSY          = 30
00468         SE_ERR_NOASSOC          = 31
00469 
00470         # FIXME : WindowsのAPIをつかってメッセージを取得したい ( FormatMessage ? )
00471         errno_msg_map = {
00472             0                       : u"メモリまたはリソースが不足しています。",
00473             ERROR_FILE_NOT_FOUND    : u"指定されたファイルが見つかりませんでした。",
00474             ERROR_PATH_NOT_FOUND    : u"指定されたパスが見つかりませんでした。",
00475             ERROR_BAD_FORMAT        : u".exe ファイルが無効です。Win32 の .exe ではないか、.exe イメージ内にエラーがあります。",
00476             SE_ERR_ACCESSDENIED     : u"オペレーティングシステムが、指定されたファイルへのアクセスを拒否しました。",
00477             SE_ERR_ASSOCINCOMPLETE  : u"ファイル名の関連付けが不完全または無効です。",
00478             SE_ERR_DDEBUSY          : u"ほかの DDE トランザクションが現在処理中なので、DDE トランザクションを完了できませんでした。",
00479             SE_ERR_DDEFAIL          : u"DDE トランザクションが失敗しました。",
00480             SE_ERR_DDETIMEOUT       : u"要求がタイムアウトしたので、DDE トランザクションを完了できませんでした。",
00481             SE_ERR_DLLNOTFOUND      : u"指定されたダイナミックリンクライブラリ(DLL)が見つかりませんでした。",
00482             SE_ERR_FNF              : u"指定されたファイルが見つかりませんでした。",
00483             SE_ERR_NOASSOC          : u"指定されたファイル拡張子に関連付けられたアプリケーションがありません。印刷可能ではないファイルを印刷しようとした場合も、このエラーが返ります。",
00484             SE_ERR_OOM              : u"操作を完了するのに十分なメモリがありません。",
00485             SE_ERR_PNF              : u"指定されたパスが、見つかりませんでした。",
00486             SE_ERR_SHARE            : u"共有違反が発生しました。",
00487         }
00488         
00489         try:
00490             msg = errno_msg_map[result]
00491         except:
00492             msg = u"エラーが発生しました。(%d)" % (result,)
00493 
00494         raise WindowsError( msg.encode("mbcs") )
00495 
00496 #--------------------------------------------------------------------
00497 
00498 def getDiskSize(drive):
00499 
00500     if type(drive)==type(''):
00501         drive = unicode(drive,'mbcs')
00502 
00503     free_size_for_user = ctypes.c_longlong()
00504     total_size = ctypes.c_longlong()
00505     free_size = ctypes.c_longlong()
00506     ctypes.windll.kernel32.GetDiskFreeSpaceExW( drive, ctypes.pointer(free_size_for_user), ctypes.pointer(total_size), ctypes.pointer(free_size) )
00507 
00508     return (free_size.value,total_size.value)
00509 
00510 #--------------------------------------------------------------------
00511 
00512 def compareTime( t1, t2 ):
00513     
00514     if ignore_1second:
00515         delta = abs( datetime.datetime(*t1) - datetime.datetime(*t2) )
00516         if delta.days==0 and delta.seconds<=1 : return 0
00517 
00518     return cmp(t1,t2)
00519 
00520 #--------------------------------------------------------------------
00521 
00522 WM_CLOSE = 16
00523 
00524 def terminateProcess(pid):
00525 
00526     def callback( wnd, arg ):
00527         wnd_pid = ctypes.c_int(0)
00528         ctypes.windll.user32.GetWindowThreadProcessId( wnd.getHWND(), ctypes.byref(wnd_pid) )
00529         if wnd_pid.value==pid:
00530             wnd.sendMessage( WM_CLOSE, 0, 0 )
00531             return False
00532         return True
00533     pyauto.Window.enum( callback, None )
00534 
00535 #--------------------------------------------------------------------
00536 
00537 def findExistingClnchWindow():
00538     found = [None]
00539     def callback( wnd, arg ):
00540         if wnd.getClassName()==u"ClnchWindowClass" and wnd.getText()==clnch_resource.clnch_appname:
00541             print wnd.getText()
00542             found[0] = wnd
00543             return False
00544         return True
00545     pyauto.Window.enum( callback, None )
00546     return found[0]
00547     
00548 #--------------------------------------------------------------------
00549 
00550 _temp_num = 1
00551 _temp_dir_name = ""
00552 
00553 def _deleteTempDirs( main_window ):
00554     
00555     wnd = pyauto.Window.fromHWND(main_window.getHWND())
00556     class_name = wnd.getClassName()
00557     clnch_window_list = []
00558 
00559     def callback( wnd, arg ):
00560         if wnd.getClassName() == class_name:
00561             clnch_window_list.append(wnd)
00562         return True
00563 
00564     pyauto.Window.enum( callback, None )
00565     
00566     if len(clnch_window_list)==1:
00567         clnch_dirname = os.path.split(sys.argv[0])[0]
00568         shutil.rmtree( os.path.join( clnch_dirname, "tmp" ), ignore_errors=True )
00569 
00570 def initTemp( main_window ):
00571     global _temp_dir_name
00572     _deleteTempDirs(main_window)
00573     _temp_dir_name = "%08x" % main_window.getHWND()
00574     clnch_dirname = os.path.split(sys.argv[0])[0]
00575     os.makedirs( os.path.join( clnch_dirname, "tmp", _temp_dir_name ) )
00576 
00577 def destroyTemp( main_window ):
00578     global _temp_dir_name
00579     clnch_dirname = os.path.split(sys.argv[0])[0]
00580     shutil.rmtree( os.path.join( clnch_dirname, "tmp", _temp_dir_name ), ignore_errors=True )
00581     _deleteTempDirs(main_window)
00582 
00583 def getTempDir(prefix):
00584 
00585     global _temp_num
00586     global _temp_dir_name
00587 
00588     clnch_dirname = os.path.split(sys.argv[0])[0]
00589 
00590     while 1:
00591         path = os.path.join( clnch_dirname, "tmp", _temp_dir_name, prefix+"%08x"%_temp_num )
00592         _temp_num += 1
00593         if not os.path.exists(path) : break
00594     
00595     os.mkdir(path)
00596     
00597     return path
00598 
00599 #--------------------------------------------------------------------
00600 
00601 ELLIPSIS_NONE  = 0
00602 ELLIPSIS_RIGHT = 1
00603 ELLIPSIS_MID   = 2
00604 
00605 ALIGN_LEFT   = 0
00606 ALIGN_CENTER = 1
00607 ALIGN_RIGHT  = 2
00608 
00609 def adjustStringWidth( window, s, width, align=ALIGN_LEFT, ellipsis=ELLIPSIS_NONE ):
00610 
00611     if ellipsis==ELLIPSIS_RIGHT:
00612         original_width = window.getStringWidth(s)
00613         if original_width>width:
00614             str_width = 0
00615             pos = 0
00616             while True:
00617                 char_width = window.getStringWidth(s[pos])
00618                 if str_width + char_width >= width-1 :
00619                     if str_width + char_width == width-1:
00620                         return u"%s\u22ef" % (s[:pos+1])
00621                     else:
00622                         return u"%s\u22ef " % (s[:pos])
00623                 str_width += char_width
00624                 pos += 1
00625 
00626     elif ellipsis==ELLIPSIS_MID:
00627 
00628         original_width = window.getStringWidth(s)
00629         if original_width>width:
00630             left_width = (width-1)/2
00631             str_width = 0
00632             pos = 0
00633             while True:
00634                 char_width = window.getStringWidth(s[pos])
00635                 if str_width + char_width >= left_width :
00636                     if str_width + char_width == left_width:
00637                         str_width += char_width
00638                     break
00639                 str_width += char_width
00640                 pos += 1
00641             left_string = s[:pos]
00642 
00643             right_width = width-str_width-1
00644             str_width = 0
00645             pos = len(s)
00646             while True:
00647                 pos -= 1
00648                 char_width = window.getStringWidth(s[pos])
00649                 if str_width + char_width >= right_width :
00650                     if str_width + char_width == right_width:
00651                         str_width += char_width
00652                     break
00653                 str_width += char_width
00654             right_string = s[pos:]
00655             return u"%s\u22ef%s" % (left_string,right_string)
00656 
00657     elif ellipsis==ELLIPSIS_NONE:
00658         original_width = window.getStringWidth(s)
00659         if original_width>width:
00660             left_width = width
00661             pos = 0
00662             while True:
00663                 left_width -= window.getStringWidth(s[pos])
00664                 if left_width < 0 : break
00665                 pos += 1
00666             return s[:pos]
00667 
00668     else:
00669         assert(0)
00670 
00671     if align==ALIGN_LEFT:
00672         return s + u' '*( width - original_width )
00673 
00674     elif align==ALIGN_RIGHT:
00675         return u' '*( width - original_width ) + s
00676 
00677     elif align==ALIGN_CENTER:
00678         delta = width - original_width
00679         left_space = delta/2
00680         right_space = delta - left_space
00681         return u' '*left_space + s + u' '*right_space
00682 
00683     else:
00684         assert(0)
00685 
00686 #--------------------------------------------------------------------
00687 
00688 def wordbreak_TextFile( s, pos, step ):
00689 
00690     word_break_chars1 = "\"!@#$%^&*()+|~-=\`[]{};:',./<>?"
00691     word_break_chars2 = " \t"
00692 
00693     while True:
00694         if pos<=0 : return 0
00695         if pos>=len(s) : return len(s)
00696 
00697         if s[pos-1] in word_break_chars1:
00698             left_char_type = 1
00699         elif s[pos-1] in word_break_chars2:
00700             left_char_type = 2
00701         else:
00702             left_char_type = 0
00703 
00704         if s[pos] in word_break_chars1:
00705             right_char_type = 1
00706         elif s[pos] in word_break_chars2:
00707             right_char_type = 2
00708         else:
00709             right_char_type = 0
00710 
00711         if left_char_type!=0:
00712             if right_char_type==0:
00713                 return pos
00714 
00715         pos += step
00716 
00717 def wordbreak_Filename( s, pos, step ):
00718 
00719     word_break_chars1 = "\"!@#$%^&*()+|~-=\`[]{};:',./<>?"
00720     word_break_chars2 = " \t"
00721 
00722     while True:
00723         if pos<=0 : return 0
00724         if pos>=len(s) : return len(s)
00725 
00726         if s[pos-1] in word_break_chars1:
00727             left_char_type = 1
00728         elif s[pos-1] in word_break_chars2:
00729             left_char_type = 2
00730         else:
00731             left_char_type = 0
00732 
00733         if s[pos] in word_break_chars1:
00734             right_char_type = 1
00735         elif s[pos] in word_break_chars2:
00736             right_char_type = 2
00737         else:
00738             right_char_type = 0
00739 
00740         if left_char_type==1:
00741             if right_char_type!=1:
00742                 return pos
00743         elif left_char_type==2:
00744             if right_char_type!=2:
00745                 return pos
00746 
00747         pos += step
00748 
00749 #--------------------------------------------------------------------
00750 
00751 ## @addtogroup global グローバル関数
00752 ## @{
00753 
00754 ## ファイルパスを連結する
00755 #
00756 #  @param *args     連結される任意の個数のパス
00757 #  @return          連結結果のパス
00758 #
00759 #  ファイルパスの連結処理に加えて、ディレクトリ区切り文字の \\ と / の置き換え処理も行います。\n\n
00760 #
00761 #  この関数の動きは os.path.join() に似せてありますが、
00762 #  os.path.join() とは違い、UNC形式 ( //machine/share/ で始まるもの ) のパスを扱うことが出来ます。
00763 #
00764 def joinPath(*args):
00765     left = 0
00766     for i in xrange(len(args)):
00767         if os.path.splitunc(args[i])[0]:
00768             left = i
00769     path = os.path.join( *args[left:] )
00770     path = replacePath(path)
00771     return path
00772 
00773 ## ファイルパスをディレクトリ名とファイル名に分離する
00774 #
00775 #  @param path     分離されるパス
00776 #  @return         ( ディレクトリ名, ファイル名 )
00777 #
00778 #  この関数の動きは os.path.split() に似せてありますが、
00779 #  os.path.split() とは違い、UNC形式 ( //machine/share/ で始まるもの ) のパスを扱うことが出来ます。
00780 #
00781 def splitPath(path):
00782     unc = os.path.splitunc(path)
00783     if not unc[1]:
00784         return unc
00785     return os.path.split( path )
00786 
00787 
00788 ## 拡張子がN文字以下でASCII文字だけからなるときだけ分離する
00789 #
00790 #  @param path     分離されるパス
00791 #  @param maxlen   拡張子とみなす最大の長さ (ピリオドを含む)
00792 #  @return         ( ファイル名本体, 拡張子 )
00793 #
00794 #  この関数の動きは os.path.splitext() に似せてありますが、
00795 #  os.path.splitext() とは違い、長い拡張子を分離しないことが出来ます。
00796 #
00797 def splitExt( path, maxlen=5 ):
00798     last_period_pos = path.rfind(".")
00799     if last_period_pos>0 and last_period_pos>=len(path)-maxlen:
00800         for i in xrange( last_period_pos+1, len(path) ):
00801             if path[i]>=u'\u0100' : return path, None
00802         return path[:last_period_pos], path[last_period_pos:]
00803     return path, None
00804 
00805 ## ファイルパスのルートディレクトリ部分を取得する
00806 #
00807 #  @param path     元になるパス
00808 #  @return         ルートディレクトリのパス
00809 #
00810 def rootPath(path):
00811     unc = os.path.splitunc(path)
00812     if not unc[1]:
00813         return unc[0]
00814     while True:
00815         new_path, name = os.path.split(path)
00816         if new_path == path : return path
00817         path = new_path
00818 
00819 ## ファイルパスを標準化する
00820 #
00821 #  @param path     元になるパス
00822 #  @return         標準化されたのパス
00823 #
00824 #  os.path.normpath() 相当の処理に加え、ディレクトリ区切り文字の \\ と / の置き換え処理を行います。
00825 #
00826 def normPath(path):
00827     path = os.path.normpath(path)
00828     path = replacePath(path)
00829     return path
00830 
00831 ## ディレクトリ区切り文字を設定にしたがって置き換える
00832 #
00833 #  @param path     元になるパス
00834 #  @return         置換されたパス
00835 #
00836 #  ディレクトリ区切り文字の \\ と / の置き換え処理を行います。
00837 #
00838 def replacePath(path):
00839     if use_slash:
00840         return path.replace(u"\\",u"/")
00841     else:
00842         return path.replace(u"/",u"\\")
00843 
00844 ## @} global
00845 
00846 #--------------------------------------------------------------------
00847 
00848 def replaceMacro( s, map = { "%%" : "%" }, environ=True ):
00849     
00850     search_pos = 0
00851     
00852     while 1:
00853     
00854         var_start = s.find('%',search_pos)
00855         if var_start < 0 : break;
00856 
00857         var_end = s.find('%',var_start+1)
00858         if var_end < 0 : break;
00859 
00860         try:
00861             after = map[ s[ var_start : var_end+1 ] ]
00862             s = s[:var_start] + after + s[var_end+1:]
00863             search_pos += len(after)
00864             continue
00865         except KeyError:
00866             pass
00867 
00868         if environ:
00869             try:
00870                 after = os.environ[ s[ var_start + 1 : var_end ] ]
00871                 s = s[:var_start] + after + s[var_end+1:]
00872                 search_pos += len(after)
00873                 continue
00874             except KeyError:
00875                 pass
00876 
00877         search_pos += 1
00878 
00879     return s
00880 
00881 def joinArgs( args ):
00882     result = ''
00883     for arg in args:
00884         if arg.find(' ') >= 0 :
00885             result += ' '+ '"' + arg + '"'
00886         else:
00887             result += ' '+ arg
00888     return result.strip()
00889 
00890 #--------------------------------------------------------------------
00891 
00892 def adjustWindowPosition( base_window, new_window, default_up ):
00893 
00894     base_window_rect = base_window.getWindowRect()
00895     
00896     x = base_window_rect[0]
00897     y1 = base_window_rect[1]
00898     y2 = base_window_rect[3]
00899     
00900     if default_up:
00901         y = y1
00902         origin = ORIGIN_Y_BOTTOM
00903     else:
00904         y = y2
00905         origin = ORIGIN_Y_TOP
00906            
00907     monitor_info_list = pyauto.Window.getMonitorInfo()
00908     for monitor_info in monitor_info_list:
00909         if monitor_info[0][0] <= x < monitor_info[0][2] and monitor_info[0][1] <= y1 < monitor_info[0][3]:
00910             base_window_rect = new_window.getWindowRect()
00911             char_w, char_h = new_window.getCharSize()
00912             if default_up:
00913                 if y1 - (base_window_rect[3]-base_window_rect[1]) < monitor_info[1][1]:
00914                     y = y2
00915                     origin = ORIGIN_Y_TOP
00916             else:
00917                 if y2 + (base_window_rect[3]-base_window_rect[1]) >= monitor_info[1][3]:
00918                     y = y1
00919                     origin = ORIGIN_Y_BOTTOM
00920             break
00921 
00922     new_window.setPosSize( x, y, new_window.width(), new_window.height(), origin )

Copyright © 2009 craftware. All rights reserved.