00001 import os
00002 import sys
00003 import re
00004 import time
00005 import datetime
00006 import profile
00007 import fnmatch
00008 import threading
00009 import zipfile
00010 import ConfigParser
00011 import filecmp
00012 import traceback
00013
00014 import pyauto
00015 import cterm
00016 from cterm.cterm_const import *
00017
00018 import clnch_statusbar
00019 import clnch_msgbox
00020 import clnch_listwindow
00021 import clnch_consolewindow
00022 import clnch_musicplayer
00023 import clnch_configmenu
00024 import clnch_commandline
00025 import clnch_widget
00026 import clnch_skin
00027 import clnch_misc
00028 import clnch_ini
00029 import clnch_native
00030 import clnch_threadutil
00031 import clnch_subprocess
00032 import clnch_resource
00033 import clnch_colortable
00034 from clnch_resource import *
00035
00036 KeyEvent = clnch_misc.KeyEvent
00037 ChrEvent = clnch_misc.ChrEvent
00038 KeyMapCondition = clnch_misc.KeyMapCondition
00039
00040 os.stat_float_times(False)
00041
00042
00043
00044 PAINT_STATUS_BAR = 1<<14
00045 PAINT_ALL = PAINT_STATUS_BAR
00046
00047 class MainWindow( cterm.Window ):
00048
00049 def __init__( self, config_filename, debug=False, profile=False ):
00050
00051 self.initialized = False
00052
00053 self.config_filename = config_filename
00054
00055 self.debug = debug
00056 self.profile = profile
00057
00058 self.loadState()
00059
00060 clnch_colortable.loadSetting()
00061
00062 self.skin_enabled = False
00063
00064 cterm.Window.__init__(
00065 self,
00066 x=0,
00067 y=0,
00068 width=clnch_ini.getint( "GEOMETRY", "min_width", 18 ),
00069 height=1,
00070 font_name = clnch_ini.get( "FONT", "name", "" ),
00071 font_size = clnch_ini.getint( "FONT", "size", 12 ),
00072 bg_color = clnch_colortable.bg,
00073 border_size = 3,
00074 resizable = False,
00075 title_bar = False,
00076 title = clnch_resource.clnch_appname,
00077 show = False,
00078 cursor = True,
00079 icon=False,
00080 activate_handler = self._onActivate,
00081 close_handler = self._onClose,
00082 endsession_handler = self._onEndSession,
00083 move_handler = self._onMove,
00084 size_handler = self._onSize,
00085 keydown_handler = self._onKeyDown,
00086 char_handler = self._onChar,
00087 lbuttondown_handler = self._onLeftButtonDown,
00088 rbuttondown_handler = self._onRightButtonDown,
00089 )
00090
00091 self.resetPos()
00092
00093 self.updateTopMost()
00094
00095 self.show(True)
00096
00097 self.setCursorPos( -1, -1 )
00098
00099 self.updateHotKey()
00100
00101 self.status_bar = clnch_statusbar.StatusBar()
00102 self.simple_status_bar_layer = clnch_statusbar.SimpleStatusBarLayer()
00103 self.simple_status_bar_resistered = False
00104 self.custom_status_bar_map = {}
00105 self.status_bar_paint_hook = None
00106 self.commandline_edit = None
00107
00108 self.cmd_keymap = clnch_misc.KeyMap()
00109 self.cmd_keymap2 = clnch_misc.KeyMap()
00110 self.compare_list = []
00111 self.sorter_list = []
00112 self.association_list = []
00113 self.editor = u"notepad.exe"
00114 self.clock_format = u"%m/%d(%a) %H:%M"
00115 self.commandline_list = []
00116 self.commandline_history = []
00117 self.commandLineHistoryLoad()
00118
00119 self.launcher = clnch_commandline.commandline_Launcher(self)
00120
00121 self.keydown_hook = None
00122 self.char_hook = None
00123 self.enter_hook = None
00124 self.mouse_event_mask = False
00125
00126 self.quit_requested = False
00127
00128 self.mouse_click_info = None
00129
00130 self.musicplayer = None
00131
00132 self.task_queue = clnch_threadutil.JobQueue()
00133 self.synccall = clnch_threadutil.SyncCall()
00134
00135 self.child_window_lock = threading.RLock()
00136
00137 self.setTimer( self.onTimer, 10 )
00138
00139 clnch_misc.registerNetConnectionHandler( self._onCheckNetConnection )
00140
00141 try:
00142 self.skinInit()
00143 except:
00144 traceback.print_exc()
00145
00146 self.console_window = clnch_consolewindow.ConsoleWindow( self, debug=debug )
00147 self.console_window.registerStdio()
00148
00149 self.updateInactiveBehavior()
00150
00151 self.initialized = True
00152
00153 self.paint()
00154
00155 def destroy(self):
00156 self.console_window.unregisterStdio()
00157 self.console_window.destroy()
00158 cterm.Window.destroy(self)
00159
00160 def onTimer(self):
00161 clnch_threadutil.JobQueue.checkAll()
00162 self.synccall.check()
00163
00164 def subThreadCall( self, func, arg, cancel_func=None, cancel_func_arg=(), raise_error=False, print_traceback=False ):
00165
00166 class SubThread( threading.Thread ):
00167
00168 def __init__( self, main_window ):
00169 threading.Thread.__init__(self)
00170 self.main_window = main_window
00171 self.result = None
00172 self.error = None
00173
00174 def run(self):
00175 try:
00176 self.result = func(*arg)
00177 except Exception, e:
00178 if print_traceback:
00179 traceback.print_exc()
00180 self.error = e
00181
00182 def onKeyDown( vk, mod ):
00183 if vk==VK_ESCAPE:
00184 if cancel_func:
00185 cancel_func(*cancel_func_arg)
00186 return True
00187
00188 def onChar( ch, mod ):
00189 return True
00190
00191 keydown_hook_old = self.keydown_hook
00192 char_hook_old = self.char_hook
00193 mouse_event_mask_old = self.mouse_event_mask
00194
00195 sub_thread = SubThread(self)
00196 sub_thread.start()
00197
00198 self.keydown_hook = onKeyDown
00199 self.char_hook = onChar
00200 self.mouse_event_mask = True
00201
00202 self.removeKeyMessage()
00203 self.messageLoop( sub_thread.isAlive )
00204
00205 sub_thread.join()
00206 result = sub_thread.result
00207 error = sub_thread.error
00208 del sub_thread
00209
00210 self.keydown_hook = keydown_hook_old
00211 self.char_hook = char_hook_old
00212 self.mouse_event_mask = mouse_event_mask_old
00213
00214 if error:
00215 if raise_error:
00216 raise error
00217 else:
00218 print error
00219
00220 return result
00221
00222 def subProcessCall( self, cmd, cwd=None, env=None, enable_cancel=False ):
00223
00224 p = clnch_subprocess.SubProcess(cmd,cwd,env)
00225
00226 if enable_cancel:
00227 cancel_handler = p.cancel
00228 else:
00229 cancel_handler = None
00230
00231 return self.subThreadCall( p, (), cancel_handler )
00232
00233 def taskEnqueue( self, job_item, comment=u"" ):
00234 if comment and self.task_queue.numItems()>0:
00235 self.setStatusMessage( u"タスクを予約しました : %s" % comment, 3000 )
00236 self.task_queue.enqueue(job_item)
00237
00238 def commandLine( self, title, text=u"", selection=None, auto_complete=False, autofix_list=None, update_handler=None, candidate_handler=None, status_handler=None, keydown_handler=None, char_handler=None, enter_handler=None, escape_handler=None ):
00239
00240 if title:
00241 title = u" " + title + u" "
00242 title_width = self.getStringWidth(title)
00243 status_string = [ u"" ]
00244 result = [ None ]
00245
00246 class CommandLine:
00247
00248 def __init__( commandline_self ):
00249 pass
00250
00251 def _onKeyDown( commandline_self, vk, mod ):
00252
00253 if keydown_handler:
00254 if keydown_handler( commandline_self, vk, mod ):
00255 return True
00256
00257 if self.commandline_edit.onKeyDown( vk, mod ):
00258 return True
00259
00260 if vk==VK_RETURN:
00261 result[0] = self.commandline_edit.getText()
00262 if enter_handler:
00263 commandline_self.closeList()
00264 if enter_handler( commandline_self, result[0], mod ):
00265 return True
00266 commandline_self.quit()
00267
00268 elif vk==VK_ESCAPE:
00269 if self.commandline_edit.getText():
00270 self.commandline_edit.clear()
00271 else:
00272 if escape_handler:
00273 if escape_handler(commandline_self):
00274 return True
00275 commandline_self.quit()
00276
00277 return True
00278
00279 def _onChar( commandline_self, ch, mod ):
00280
00281 if char_handler:
00282 if char_handler( commandline_self, ch, mod ):
00283 return True
00284
00285 self.commandline_edit.onChar( ch, mod )
00286
00287 return True
00288
00289 def _onUpdate( commandline_self, update_info ):
00290 if update_handler:
00291 if not update_handler(update_info):
00292 return False
00293 if status_handler:
00294 status_string[0] = status_handler(update_info)
00295 self.paint(PAINT_STATUS_BAR)
00296 commandline_self.updateWindowWidth(update_info.text)
00297
00298 def _onPaint( commandline_self, x, y, width, height ):
00299
00300 if status_string[0]:
00301 status_string_for_paint = u" " + status_string[0] + u" "
00302 else:
00303 status_string_for_paint = u""
00304 status_width = self.getStringWidth(status_string_for_paint)
00305 edit_width = width-title_width-status_width
00306
00307 attr = cterm.Attribute( fg=clnch_colortable.bar_fg )
00308
00309 if self.active:
00310 self.putString( x, y, title_width, height, attr, title )
00311 self.putString( x+width-status_width, y, status_width, height, attr, status_string_for_paint )
00312 else:
00313 self.putString( x, y, title_width, height, attr, u" "*title_width )
00314 self.putString( x+width-status_width, y, status_width, height, attr, u" "*status_width )
00315
00316 if self.skin_enabled:
00317
00318 client_rect = self.getClientRect()
00319 offset_x, offset_y = self.charToClient( 0, 0 )
00320 char_w, char_h = self.getCharSize()
00321 up_shift = 1
00322
00323 self.skin_edit_active.adjust( ( title_width*char_w+offset_x, offset_y-up_shift, edit_width*char_w, char_h+up_shift ) )
00324 self.skin_edit_inactive.adjust( ( title_width*char_w+offset_x, offset_y-up_shift, edit_width*char_w, char_h+up_shift ) )
00325
00326 self.commandline_edit.setPosSize( x+title_width, y, edit_width, height )
00327
00328 self.commandline_edit.enableCursor( self.active )
00329 if not self.active:
00330 self.setCursorPos( -1, -1 )
00331
00332 self.commandline_edit.paint()
00333
00334 def paint(commandline_self):
00335 self.paint()
00336
00337 def getText(commandline_self):
00338 return self.commandline_edit.getText()
00339
00340 def setText( commandline_self, text ):
00341 self.commandline_edit.setText(text)
00342
00343 def getSelection(commandline_self):
00344 return self.commandline_edit.getSelection()
00345
00346 def setSelection(commandline_self,selection):
00347 self.commandline_edit.setSelection(selection)
00348
00349 def selectAll(commandline_self):
00350 self.commandline_edit.selectAll()
00351
00352 def closeList(commandline_self):
00353 self.commandline_edit.closeList()
00354
00355 def updateWindowWidth( commandline_self, text ):
00356 text_width = self.getStringWidth(text)
00357 delta = text_width - self.commandline_edit.width + 2
00358 if delta==0 : return
00359 new_width = self.width() + delta
00360 new_width = max( new_width, clnch_ini.getint( "GEOMETRY", "min_width", 18 ) )
00361 new_width = min( new_width, clnch_ini.getint( "GEOMETRY", "max_width", 80 ) )
00362 window_rect = self.getWindowRect()
00363 self.setPosSize( window_rect[0], window_rect[1], new_width, self.height(), 0 )
00364
00365 def appendHistory(commandline_self,newentry):
00366 newentry_lower = newentry.lower()
00367 for i in xrange(len(self.commandline_history)):
00368 if self.commandline_history[i].lower()==newentry_lower:
00369 del self.commandline_history[i]
00370 break
00371 self.commandline_history.insert( 0, newentry )
00372
00373 if len(self.commandline_history)>1000:
00374 self.commandline_history = self.commandline_history[:1000]
00375
00376 def quit(commandline_self):
00377 commandline_self.updateWindowWidth(u"")
00378 self.quit()
00379
00380 commandline_edit_old = self.commandline_edit
00381 keydown_hook_old = self.keydown_hook
00382 char_hook_old = self.char_hook
00383 mouse_event_mask_old = self.mouse_event_mask
00384 status_bar_paint_hook_old = self.status_bar_paint_hook
00385
00386 commandline = CommandLine()
00387
00388 self.commandline_edit = clnch_widget.EditWidget( self, title_width, self.height()-1, self.width()-title_width, 1, text, selection, auto_complete=auto_complete, no_bg=True, autofix_list=autofix_list, update_handler=commandline._onUpdate, candidate_handler=candidate_handler )
00389 self.keydown_hook = commandline._onKeyDown
00390 self.char_hook = commandline._onChar
00391 self.mouse_event_mask = True
00392 self.status_bar_paint_hook = commandline._onPaint
00393
00394 if status_handler:
00395 status_string[0] = status_handler(clnch_widget.EditWidget.UpdateInfo(text,selection))
00396
00397 if self.skin_enabled:
00398 self.skin_edit_active.show(self.active)
00399 self.skin_edit_inactive.show(not self.active)
00400
00401 self.paint(PAINT_STATUS_BAR)
00402
00403 self.removeKeyMessage()
00404 def checkContinue():
00405 return self.active or len(self.commandline_edit.getText())>0
00406 self.messageLoop( checkContinue )
00407
00408 self.commandline_edit.destroy()
00409
00410 self.enableIme(False)
00411
00412 self.commandline_edit = commandline_edit_old
00413 self.keydown_hook = keydown_hook_old
00414 self.char_hook = char_hook_old
00415 self.mouse_event_mask = mouse_event_mask_old
00416 self.status_bar_paint_hook = status_bar_paint_hook_old
00417
00418 if self.skin_enabled:
00419 self.skin_edit_active.show(False)
00420 self.skin_edit_inactive.show(False)
00421
00422 self.setCursorPos( -1, -1 )
00423 self.skinUpdate()
00424
00425 self.paint(PAINT_STATUS_BAR)
00426
00427 return result[0]
00428
00429 def commandLineHistoryLoad(self):
00430 for i in xrange(1000):
00431 try:
00432 self.commandline_history.append( unicode( clnch_ini.get( "COMMANDLINE", "history_%d"%(i,) ), "utf8" ) )
00433 except:
00434 break
00435
00436 def commandLineHistorySave(self):
00437 i=0
00438 while i<len(self.commandline_history):
00439 clnch_ini.set( "COMMANDLINE", "history_%d"%(i,), self.commandline_history[i].encode("utf8") )
00440 i+=1
00441 while True:
00442 if not clnch_ini.remove_option( "COMMANDLINE", "history_%d"%(i,) ) : break
00443 i+=1
00444
00445 def _onActivate( self, active ):
00446
00447 self.active = active
00448
00449 if self.skin_enabled and self.commandline_edit:
00450 self.skin_edit_active.show(self.active)
00451 self.skin_edit_inactive.show(not self.active)
00452
00453 self.paint()
00454
00455 def _onClose( self ):
00456 self.quit()
00457
00458 def _onEndSession( self ):
00459 self.saveState()
00460 clnch_ini.write()
00461
00462 def _onMove( self, x, y ):
00463
00464 if not self.initialized : return
00465
00466 if self.commandline_edit:
00467 self.commandline_edit.onWindowMove()
00468
00469 def _onSize( self, width, height ):
00470 self.skinUpdate()
00471 self.paint()
00472
00473 def _onKeyDown( self, vk, mod ):
00474
00475
00476
00477 if self.keydown_hook:
00478 if self.keydown_hook( vk, mod ):
00479 return True
00480
00481 return True
00482
00483 def _onChar( self, ch, mod ):
00484
00485
00486
00487 if self.char_hook:
00488 if self.char_hook( ch, mod ):
00489 return
00490
00491 def _onLeftButtonDown( self, x, y, mod ):
00492
00493
00494
00495
00496
00497 self.drag(x,y);
00498
00499 def _onRightButtonDown( self, x, y, mod ):
00500
00501
00502
00503
00504
00505 pass
00506
00507 def _onCheckNetConnection( self, remote_resource_name ):
00508
00509 def addConnection( hwnd, remote_resource_name ):
00510 try:
00511 clnch_native.addConnection( hwnd, remote_resource_name )
00512 except Exception, e:
00513 print u"ERROR : 接続失敗 : %s" % remote_resource_name
00514 print e, "\n"
00515
00516 self.synccall( addConnection, (self.getHWND(), remote_resource_name) )
00517
00518 def ratioToScreen( self, ratio ):
00519 rect = self.getWindowRect()
00520 return ( int(rect[0] * (1-ratio[0]) + rect[2] * ratio[0]), int(rect[1] * (1-ratio[1]) + rect[3] * ratio[1]) )
00521
00522 def centerOfWindowInPixel(self):
00523 rect = self.getWindowRect()
00524 return ( (rect[0]+rect[2])/2, (rect[1]+rect[3])/2 )
00525
00526 def statusBar(self):
00527 return self.status_bar
00528
00529 def registerStatusBar( self, func, priority=-1, interval=None ):
00530
00531 if self.custom_status_bar_map.has_key( func ):
00532 return
00533
00534 class CustomStatusBarLayer(clnch_statusbar.StatusBarLayer):
00535
00536 def __init__( layer_self ):
00537 clnch_statusbar.StatusBarLayer.__init__( layer_self, priority )
00538 if interval:
00539 self.setTimer( layer_self.onTimer, interval )
00540
00541 def destroy( layer_self ):
00542 if interval:
00543 self.killTimer( layer_self.onTimer )
00544
00545 def paint( layer_self, window, x, y, width, height ):
00546 s = u" %s" % ( func(width) )
00547 s = clnch_misc.adjustStringWidth( window, s, width-1 )
00548 attr = cterm.Attribute( fg=clnch_colortable.bar_fg )
00549 window.putString( x, y, width, height, attr, s )
00550
00551 def onTimer( layer_self ):
00552 if self.commandline_edit==None and self.status_bar.isActiveLayer(layer_self):
00553 self.paint( PAINT_STATUS_BAR )
00554
00555 custom_status_bar_layer = CustomStatusBarLayer()
00556 self.status_bar.registerLayer(custom_status_bar_layer)
00557 self.custom_status_bar_map[func] = custom_status_bar_layer
00558
00559 def unregisterStatusBar( self, func ):
00560
00561 if not self.custom_status_bar_map.has_key( func ):
00562 return
00563
00564 custom_status_bar_layer = self.custom_status_bar_map[func]
00565 self.status_bar.unregisterLayer(custom_status_bar_layer)
00566 custom_status_bar_layer.destroy()
00567 del self.custom_status_bar_map[func]
00568
00569 def _onStatusMessageTimedout(self):
00570 self.clearStatusMessage()
00571
00572 def setStatusMessage( self, message, timeout=None, error=False ):
00573
00574 self.simple_status_bar_layer.setMessage(message,error)
00575
00576 if not self.simple_status_bar_resistered:
00577 self.status_bar.registerLayer(self.simple_status_bar_layer)
00578 self.simple_status_bar_resistered = True
00579
00580 if timeout!=None:
00581 self.killTimer( self._onStatusMessageTimedout )
00582 self.setTimer( self._onStatusMessageTimedout, timeout )
00583
00584 self.paint( PAINT_STATUS_BAR )
00585
00586 def clearStatusMessage( self ):
00587 self.simple_status_bar_layer.setMessage(u"")
00588 self.status_bar.unregisterLayer(self.simple_status_bar_layer)
00589 self.simple_status_bar_resistered = False
00590 self.paint( PAINT_STATUS_BAR )
00591 self.killTimer(self._onStatusMessageTimedout)
00592
00593 def cursorFromHistory( self, file_list, history ):
00594 history_item = history.find( file_list.getLocation() )
00595 if history_item==None : return 0
00596 cursor = file_list.indexOf( history_item[1] )
00597 if cursor<0 : return 0
00598 return cursor
00599
00600
00601
00602 def skinInit(self):
00603 self.skin_statusbar = clnch_skin.SkinPlane( self, os.path.join( os.path.split(sys.argv[0])[0], 'skin/statusbar.png' ), 1.5 )
00604 self.skin_edit_active = clnch_skin.SkinPlane( self, os.path.join( os.path.split(sys.argv[0])[0], 'skin/edit_active.png' ), 1 )
00605 self.skin_edit_inactive = clnch_skin.SkinPlane( self, os.path.join( os.path.split(sys.argv[0])[0], 'skin/edit_inactive.png' ), 1 )
00606 self.skin_edit_active.show(False)
00607 self.skin_edit_inactive.show(False)
00608
00609 self.skin_enabled = True
00610
00611 self.skinUpdate()
00612
00613 def skinUpdate(self):
00614
00615 if not self.skin_enabled : return
00616
00617 client_rect = self.getClientRect()
00618 offset_x, offset_y = self.charToClient( 0, 0 )
00619 char_w, char_h = self.getCharSize()
00620
00621 self.skin_statusbar.adjust( ( 0, 0, client_rect[2], client_rect[3] ) )
00622
00623
00624
00625 def updateColor(self):
00626 self.setBGColor( clnch_colortable.bg )
00627 self.paint()
00628
00629
00630
00631 def updateFont(self):
00632 self.setFont( clnch_ini.get( "FONT", "name", "" ), clnch_ini.getint( "FONT", "size", 12 ) )
00633 window_rect = self.getWindowRect()
00634 self.setPosSize( window_rect[0], window_rect[1], self.width(), self.height(), 0 )
00635
00636 self.console_window.updateFont()
00637
00638
00639
00640 def _onTimerTopmost(self):
00641 wnd = pyauto.Window.fromHWND( self.getHWND() )
00642 wnd = wnd.getPrevious()
00643 while wnd:
00644 if( wnd.isVisible()
00645 and not wnd.getClassName().startswith(u"#")
00646 and not wnd.getClassName() in ( u"ClnchWindowClass", u"SysShadow" )
00647 and not wnd.getProcessName().lower().endswith(".scr") ):
00648
00649 self.topmost(True)
00650 break
00651 wnd = wnd.getPrevious()
00652
00653 def updateTopMost(self):
00654
00655 topmost = clnch_ini.getint( "GEOMETRY", "topmost", 0 )
00656 self.topmost(topmost!=0)
00657
00658 if topmost==2:
00659 self.setTimer( self._onTimerTopmost, 10 )
00660 else:
00661 self.killTimer( self._onTimerTopmost )
00662
00663
00664
00665 def resetPos(self):
00666
00667 rect = self.getWindowRect()
00668
00669 monitor = clnch_ini.getint( "GEOMETRY", "monitor", 0 )
00670 x = clnch_ini.getint( "GEOMETRY", "x", 0 )
00671 y = clnch_ini.getint( "GEOMETRY", "y", 0 )
00672
00673 monitor_info_list = pyauto.Window.getMonitorInfo()
00674 if not monitor<len(monitor_info_list):
00675 monitor = 0
00676 x = 0
00677 y = 0
00678
00679 monitor_info = monitor_info_list[monitor]
00680 if x>=0:
00681 x = monitor_info[0][0] + x
00682 else:
00683 x = monitor_info[0][2] + x - (rect[2]-rect[0]) + 1
00684
00685 if y>=0:
00686 y = monitor_info[0][1] + y
00687 else:
00688 y = monitor_info[0][3] + y - (rect[3]-rect[1]) + 1
00689
00690 self.setPosSize( x, y, self.width(), self.height(), 0 )
00691
00692
00693
00694 def _statusbar_Clock( self, width ):
00695 now = datetime.datetime.now()
00696 return now.strftime(self.clock_format)
00697
00698 def updateInactiveBehavior(self):
00699
00700 inactive_behavior = clnch_ini.get( "MISC", "inactive_behavior", "washy" )
00701
00702 if inactive_behavior=="clock":
00703 self.registerStatusBar( self._statusbar_Clock, priority=-1, interval=1000 )
00704 else:
00705 self.unregisterStatusBar( self._statusbar_Clock )
00706
00707
00708
00709 def paint( self, option=PAINT_ALL ):
00710
00711 if not self.initialized : return
00712
00713 if option & PAINT_STATUS_BAR:
00714 if self.status_bar_paint_hook:
00715 self.status_bar_paint_hook( 0, self.height()-1, self.width(), 1 )
00716 else:
00717 self.status_bar.paint( self, 0, self.height()-1, self.width(), 1 )
00718
00719
00720
00721 def configure(self):
00722
00723 default_keymap = clnch_ini.get( "MISC", "default_keymap", "106" )
00724
00725 self.cmd_keymap = clnch_misc.KeyMap()
00726 self.cmd_keymap2 = clnch_misc.KeyMap()
00727 self.cmd_keymap2[ KeyEvent( VK_SPACE, MODKEY_ALT ) ] = self.command_AutoCompleteToggle
00728 self.cmd_keymap[ KeyEvent( VK_OEM_PERIOD, MODKEY_CTRL ) ] = self.command_MusicList
00729 self.cmd_keymap[ KeyEvent( VK_OEM_PERIOD, MODKEY_CTRL|MODKEY_SHIFT ) ] = self.command_MusicStop
00730 if default_keymap=="101":
00731 self.cmd_keymap[ KeyEvent( VK_OEM_2, MODKEY_CTRL ) ] = self.command_ContextMenu
00732 elif default_keymap=="106":
00733 self.cmd_keymap[ KeyEvent( VK_OEM_102, MODKEY_CTRL ) ] = self.command_ContextMenu
00734
00735 self.association_list = [
00736 ( u"*.mp3 *.wma *.wav", self.command_MusicPlay ),
00737 ]
00738
00739 self.commandline_list = [
00740 self.launcher,
00741 clnch_commandline.commandline_ExecuteURL(self),
00742 clnch_commandline.commandline_ExecuteFile(self),
00743 clnch_commandline.commandline_Calculator(self),
00744 ]
00745
00746 self.launcher.command_list = [
00747 ( u"Edit", self.command_Edit ),
00748 ( u"History", self.command_History ),
00749 ( u"Config", self.command_ConfigMenu ),
00750 ( u"Reload", self.command_Reload ),
00751 ( u"About", self.command_About ),
00752 ( u"Quit", self.command_Quit ),
00753 ]
00754
00755 try:
00756 fd = file( self.config_filename, 'r' )
00757 fileimage = fd.read()
00758 user_namespace = {}
00759 code = compile( fileimage, self.config_filename, 'exec' )
00760 exec code in user_namespace, user_namespace
00761 user_namespace["configure"](self)
00762 except:
00763 print u'ERROR : error occured while reading config file.'
00764 traceback.print_exc()
00765
00766
00767 def loadState(self):
00768
00769 if clnch_ini.get( "MISC", "directory_separator", "backslash" )=="slash":
00770 clnch_misc.use_slash = True
00771 else:
00772 clnch_misc.use_slash = False
00773
00774 def saveState(self):
00775
00776 print u"Save State"
00777 try:
00778 clnch_ini.set( "GEOMETRY", "width", str(self.width()) )
00779 clnch_ini.set( "GEOMETRY", "height", str(self.height()) )
00780
00781 self.commandLineHistorySave()
00782
00783 self.console_window.saveState()
00784
00785 if self.musicplayer:
00786 self.musicplayer.save( "MUSIC" )
00787 clnch_ini.set( "MUSIC", "restore", str(1) )
00788 else:
00789 clnch_ini.set( "MUSIC", "restore", str(0) )
00790
00791 except Exception, e:
00792 print u"Failed"
00793 print " %s" % unicode(str(e),'mbcs')
00794 else:
00795 print u'Done.'
00796
00797
00798
00799 def start(self):
00800
00801 print clnch_resource.startupString()
00802
00803
00804 if clnch_ini.getint( "MUSIC", "restore", 0 ):
00805 if self.musicplayer==None:
00806 self.musicplayer = clnch_musicplayer.MusicPlayer(self)
00807 self.musicplayer.load( "MUSIC" )
00808
00809 self.console_window.setAutoShow(True)
00810
00811 def stop(self):
00812 self.console_window.setAutoShow(False)
00813
00814
00815
00816 def _inactiveMessageLoop(self):
00817
00818 inactive_behavior = clnch_ini.get( "MISC", "inactive_behavior", "washy" )
00819
00820 if inactive_behavior in ("washy","hide"):
00821
00822 def _onPaint( x, y, width, height ):
00823 attr = cterm.Attribute( fg=clnch_colortable.bar_fg )
00824 self.putString( x, y, width, height, attr, u" "*width )
00825
00826 status_bar_paint_hook_old = self.status_bar_paint_hook
00827
00828 self.status_bar_paint_hook = _onPaint
00829
00830 if self.skin_enabled:
00831 self.skin_edit_active.show(False)
00832 self.skin_edit_inactive.show(True)
00833
00834 self.paint(PAINT_STATUS_BAR)
00835
00836 if inactive_behavior=="hide":
00837 self.show(False)
00838
00839 self.removeKeyMessage()
00840 def checkContinue():
00841 return not self.active
00842 self.messageLoop( checkContinue )
00843
00844 if inactive_behavior in ("washy","hide"):
00845 self.status_bar_paint_hook = status_bar_paint_hook_old
00846
00847 if self.skin_enabled:
00848 self.skin_edit_active.show(False)
00849 self.skin_edit_inactive.show(False)
00850
00851 self.paint(PAINT_STATUS_BAR)
00852
00853 def topLevelMessageLoop(self):
00854
00855 def onCandidate( update_info ):
00856
00857 left = update_info.text[ : update_info.selection[0] ]
00858 left_lower = left.lower()
00859 pos_arg = left.rfind(";")+1
00860 arg = left[ pos_arg : ]
00861 pos_dir = max( arg.rfind("/")+1, arg.rfind("\\")+1 )
00862 directory = arg[:pos_dir]
00863 directory_lower = directory.lower()
00864 name_prefix = arg[pos_dir:].lower()
00865
00866 candidate_list = []
00867 candidate_map = {}
00868
00869 for item in self.commandline_history:
00870 item_lower = item.lower()
00871 if item_lower.startswith(left_lower) and len(item_lower)!=len(left_lower):
00872 cand = item[ pos_arg + pos_dir : ]
00873 if not candidate_map.has_key(cand):
00874 candidate_list.append( cand )
00875 candidate_map[cand] = True
00876
00877 for commandline_function in self.commandline_list:
00878 for cand in commandline_function.onCandidate( update_info ):
00879 if not candidate_map.has_key(cand):
00880 candidate_list.append( cand )
00881 candidate_map[cand] = True
00882
00883 return candidate_list, pos_arg + pos_dir
00884
00885 def statusString( update_info ):
00886 if update_info.text:
00887 for commandline_function in self.commandline_list:
00888 s = commandline_function.onStatusString(update_info.text)
00889 if s!=None:
00890 return s
00891 return None
00892
00893 def onKeyDown( commandline, vk, mod ):
00894 try:
00895 func = self.cmd_keymap[ KeyMapCondition( KeyEvent(vk,mod) ) ]
00896 quit = True
00897 except KeyError:
00898 try:
00899 func = self.cmd_keymap2[ KeyMapCondition( KeyEvent(vk,mod) ) ]
00900 quit = False
00901 except KeyError:
00902 return
00903 text = commandline.getText()
00904 args = text.split(';')
00905 clnch_commandline.executeCommand( commandline, func, args, 0, text, quit=quit )
00906 return True
00907
00908 def onChar( commandline, ch, mod ):
00909 try:
00910 func = self.cmd_keymap[ KeyMapCondition( ChrEvent(ch) ) ]
00911 except KeyError:
00912 try:
00913 func = self.cmd_keymap2[ KeyMapCondition( ChrEvent(ch) ) ]
00914 quit = False
00915 except KeyError:
00916 return
00917 text = commandline.getText()
00918 args = text.split(';')
00919 clnch_commandline.executeCommand( commandline, func, args, 0, text, quit=quit )
00920 return True
00921
00922 def onEnter( commandline, text, mod ):
00923 for commandline_function in self.commandline_list:
00924 if commandline_function.onEnter( commandline, text, mod ):
00925 break
00926 return True
00927
00928 def onEscape( commandline ):
00929 self.console_window.show(False)
00930 self.resetPos()
00931 self.inactivate()
00932 return True
00933
00934 while not self.quit_requested:
00935
00936 if self.active:
00937 auto_complete = clnch_ini.getint( "MISC", "auto_complete", "1" )
00938 self.commandLine( u"", auto_complete=auto_complete, autofix_list=["\\/",".",";"], candidate_handler=onCandidate, status_handler=statusString, keydown_handler=onKeyDown, char_handler=onChar, enter_handler=onEnter, escape_handler=onEscape )
00939 else:
00940 self._inactiveMessageLoop()
00941
00942
00943
00944 def hotkey_Activate(self):
00945 self.restore()
00946 self.foreground()
00947 if self.isEnabled():
00948 self.activate()
00949
00950 def updateHotKey(self):
00951
00952 activate_vk = clnch_ini.getint( "HOTKEY", "activate_vk", 0 )
00953 activate_mod = clnch_ini.getint( "HOTKEY", "activate_mod", 0 )
00954
00955 self.killHotKey( self.hotkey_Activate )
00956 self.setHotKey( activate_vk, activate_mod, self.hotkey_Activate )
00957
00958
00959
00960
00961
00962 def command_Edit( self, args ):
00963
00964 def edit():
00965 for arg in args:
00966 if not os.path.isfile(arg) : continue
00967 if callable(self.editor):
00968 self.editor(arg)
00969 else:
00970 directory, tmp = os.path.split(arg)
00971 clnch_misc.shellExecute( None, None, self.editor, arg, directory )
00972
00973 self.subThreadCall( edit, () )
00974
00975 def command_ContextMenu( self, args ):
00976
00977 if len(args)<=0 :
00978 return
00979 if not os.path.exists(args[0]) :
00980 return
00981 dirname, name = os.path.split( os.path.normpath(args[0]) )
00982
00983 self.commandline_edit.closeList()
00984
00985 pos = self.charToScreen( self.commandline_edit.x + self.commandline_edit.width, 1 )
00986 self.removeKeyMessage()
00987 clnch_native.popupContextMenu( self.getHWND(), pos[0], pos[1], dirname, [name] )
00988
00989 def command_Quit(self):
00990 self.quit_requested = True
00991 self.quit()
00992
00993 def command_MusicList(self):
00994
00995 if not self.musicplayer:
00996 self.setStatusMessage( u"Musicがありません", 1000, error=True )
00997 return
00998
00999 musicplayer_items, selection = self.musicplayer.getPlayList()
01000
01001 items = []
01002 for music_item in musicplayer_items:
01003 items.append( music_item )
01004
01005 def onKeyDown( vk, mod ):
01006
01007 if vk==VK_OEM_PERIOD and mod==MODKEY_CTRL:
01008 self.musicplayer.pause()
01009 if self.musicplayer.isPlaying():
01010 self.setStatusMessage( u"Music : 再開", 3000 )
01011 else:
01012 self.setStatusMessage( u"Music : 一時停止", 3000 )
01013 list_window.cancel()
01014 return True
01015
01016 elif vk==VK_OEM_PERIOD and mod==MODKEY_CTRL|MODKEY_SHIFT:
01017 self.command_MusicStop()
01018 list_window.cancel()
01019 return True
01020
01021 elif vk==VK_LEFT and mod==MODKEY_CTRL:
01022 self.musicplayer.advance( -10.0 )
01023
01024 elif vk==VK_RIGHT and mod==MODKEY_CTRL:
01025 self.musicplayer.advance( 10.0 )
01026
01027 def onStatusMessage( width, select ):
01028 return u""
01029
01030 pos = self.centerOfWindowInPixel()
01031 list_window = clnch_listwindow.ListWindow( pos[0], pos[1], 5, 1, 80, 16, self, False, u"music player", items, initial_select=selection, keydown_hook=onKeyDown, onekey_search=False, statusbar_handler=onStatusMessage )
01032 clnch_misc.adjustWindowPosition( self, list_window, default_up=False )
01033 list_window.show(True)
01034 self.enable(False)
01035 list_window.messageLoop()
01036 result = list_window.getResult()
01037 self.enable(True)
01038 self.activate()
01039 list_window.destroy()
01040
01041 if result<0 : return
01042
01043 self.musicplayer.select(result)
01044
01045 def command_MusicPlay( self, args ):
01046
01047 playlist = []
01048 selection = 0
01049
01050 for arg in args:
01051 dirname, name = os.path.split(arg)
01052 ext = os.path.splitext(arg)[1].lower()
01053 fileinfo_list = clnch_native.findFile( os.path.join(dirname,"*") )
01054 for fileinfo in fileinfo_list:
01055 if os.path.splitext(fileinfo[0])[1].lower()==ext:
01056 if not (fileinfo[3] & clnch_misc.FILE_ATTRIBUTE_DIRECTORY):
01057 playlist.append( clnch_misc.joinPath( dirname, fileinfo[0] ) )
01058 if arg==args[0] and fileinfo[0].lower()==name.lower():
01059 selection = len(playlist)-1
01060
01061 if len(playlist) :
01062 if self.musicplayer==None:
01063 self.musicplayer = clnch_musicplayer.MusicPlayer(self)
01064 self.musicplayer.setPlayList( playlist, selection )
01065 self.musicplayer.play()
01066
01067 def command_MusicStop(self):
01068 if self.musicplayer:
01069 self.musicplayer.destroy()
01070 self.musicplayer = None
01071 self.setStatusMessage( u"Music : 停止", 3000 )
01072
01073 def command_ShellExecute( self, verb, file, param, directory, swmode=clnch_misc.SW_NORMAL ):
01074
01075 def jobShellExecute( job_item ):
01076
01077 _file = file
01078 _param = param
01079 _directory = directory
01080
01081 if _param==None or len(_param)==0:
01082 _param = u"%param%"
01083
01084 joint_args = clnch_misc.joinArgs(job_item.args)
01085
01086 _file = clnch_misc.replaceMacro( _file, { "%%":"%", "%param%":joint_args }, environ=True )
01087 _param = clnch_misc.replaceMacro( _param, { "%%":"%", "%param%":joint_args }, environ=True )
01088 _directory = clnch_misc.replaceMacro( _directory, { "%%":"%", "%param%":joint_args }, environ=True )
01089
01090 try:
01091 clnch_misc.shellExecute( None, verb, file, _param, directory, swmode, raise_error=True )
01092 except Exception, e:
01093 print u'Error : 実行に失敗'
01094 print u" %s" % unicode(str(e),'mbcs')
01095
01096 def jobShellExecuteFinished( job_item ):
01097 pass
01098
01099 def _shellExecute( args ):
01100 job_item = clnch_threadutil.JobItem( jobShellExecute, jobShellExecuteFinished )
01101 job_item.args = args
01102 self.taskEnqueue( job_item, u"ShellExecute" )
01103
01104 return _shellExecute
01105
01106 def command_URL( self, url, encoding=u"utf8" ):
01107
01108 def jobShellExecute( job_item ):
01109
01110 _url = url
01111
01112 if len(job_item.args) > 0 :
01113 import urllib
01114 keyword = job_item.args[0].encode(encoding)
01115 keyword = urllib.quote_plus(keyword)
01116 else:
01117 keyword = u""
01118
01119 _url = clnch_misc.replaceMacro( _url, { "%%":"%", "%param%":keyword }, environ=False )
01120
01121 clnch_misc.shellExecute( None, None, _url, u"", u"" )
01122
01123 def jobShellExecuteFinished( job_item ):
01124 pass
01125
01126 def _shellExecute( args ):
01127 job_item = clnch_threadutil.JobItem( jobShellExecute, jobShellExecuteFinished )
01128 job_item.args = args
01129 self.taskEnqueue( job_item, u"URL" )
01130
01131 return _shellExecute
01132
01133 def command_History( self, args, mod ):
01134
01135 items = []
01136
01137 for item in self.commandline_history:
01138 if item:
01139 items.append( ( item, ) )
01140
01141 initial_select = 0
01142 max_width = clnch_ini.getint( "GEOMETRY", "max_width", 80 )
01143
01144 def onKeyDown( vk, mod ):
01145 if vk==VK_DELETE and mod==0:
01146 select = list_window.getResult()
01147 self.commandline_history.remove(items[select][0])
01148 list_window.remove(select)
01149 return True
01150
01151 def onStatusMessage( width, select ):
01152 return u""
01153
01154 pos = self.centerOfWindowInPixel()
01155 list_window = clnch_listwindow.ListWindow( pos[0], pos[1], 5, 1, max_width, 16, self, False, u"履歴リスト", items, initial_select=0, keydown_hook=onKeyDown, onekey_search=False, statusbar_handler=onStatusMessage )
01156 clnch_misc.adjustWindowPosition( self, list_window, default_up=True )
01157 list_window.show(True)
01158 self.enable(False)
01159 list_window.messageLoop()
01160 result = list_window.getResult()
01161 self.enable(True)
01162 self.activate()
01163 list_window.destroy()
01164
01165 if result<0 : return
01166
01167 return items[result][0]
01168
01169 def command_ConfigMenu(self):
01170 clnch_configmenu.doConfigMenu(self)
01171
01172 def command_Reload(self):
01173 self.configure()
01174 print u"設定スクリプトをリロードしました.\n"
01175
01176 def command_ConsoleOpen(self):
01177 self.console_window.show(True)
01178 self.activate()
01179
01180 def command_ConsoleClose(self):
01181 self.console_window.show(False)
01182
01183 def command_ConsoleToggle(self):
01184 if self.console_window.isVisible():
01185 self.command_ConsoleClose()
01186 else:
01187 self.command_ConsoleOpen()
01188
01189 def command_AutoCompleteOn(self):
01190 if self.commandline_edit:
01191 print u"自動補完 ON\n"
01192 self.commandline_edit.setAutoComplete(True)
01193
01194 def command_AutoCompleteOff(self):
01195 if self.commandline_edit:
01196 print u"自動補完 OFF\n"
01197 self.commandline_edit.setAutoComplete(False)
01198
01199 def command_AutoCompleteToggle(self):
01200 if self.commandline_edit:
01201 if self.commandline_edit.getAutoComplete():
01202 self.command_AutoCompleteOff()
01203 else:
01204 self.command_AutoCompleteOn()
01205
01206 def command_About(self):
01207 print clnch_resource.startupString()
01208
01209