sgrepmdi.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. #SGrepMDI is by Gordon McMillan (gmcm@hypernet.com)
  2. #It does basically what Find In Files does in MSVC with a couple enhancements.
  3. # - It saves any directories in the app's ini file (if you want to get rid
  4. # of them you'll have to edit the file)
  5. # - "Directories" can be directories,
  6. # - semicolon separated lists of "directories",
  7. # - environment variables that evaluate to "directories",
  8. # - registry path names that evaluate to "directories",
  9. # - all of which is recursive, so you can mix them all up.
  10. # - It is MDI, so you can 'nest' greps and return to earlier ones,
  11. # (ie, have multiple results open at the same time)
  12. # - Like FIF, double clicking a line opens an editor and takes you to the line.
  13. # - You can highlight text, right click and start a new grep with the selected
  14. # text as search pattern and same directories etc as before.
  15. # - You can save grep parameters (so you don't lose your hardearned pattern)
  16. # from File|Save
  17. # - You can save grep results by right clicking in the result window.
  18. # Hats off to Mark Hammond for providing an environment where I could cobble
  19. # something like this together in a couple evenings!
  20. import win32ui
  21. import win32api
  22. from pywin.mfc import docview, dialog, window
  23. import win32con
  24. import string
  25. import re
  26. import glob
  27. import os
  28. import stat
  29. import glob
  30. from . import scriptutils
  31. def getsubdirs(d):
  32. dlist = []
  33. flist = glob.glob(d+'\\*')
  34. for f in flist:
  35. if os.path.isdir(f):
  36. dlist.append(f)
  37. dlist = dlist + getsubdirs(f)
  38. return dlist
  39. class dirpath:
  40. def __init__(self, str, recurse=0):
  41. dp = str.split(';')
  42. dirs = {}
  43. for d in dp:
  44. if os.path.isdir(d):
  45. d = d.lower()
  46. if d not in dirs:
  47. dirs[d] = None
  48. if recurse:
  49. subdirs = getsubdirs(d)
  50. for sd in subdirs:
  51. sd = sd.lower()
  52. if sd not in dirs:
  53. dirs[sd] = None
  54. elif os.path.isfile(d):
  55. pass
  56. else:
  57. x = None
  58. if d in os.environ:
  59. x = dirpath(os.environ[d])
  60. elif d[:5] == 'HKEY_':
  61. keystr = d.split('\\')
  62. try:
  63. root = eval('win32con.'+keystr[0])
  64. except:
  65. win32ui.MessageBox("Can't interpret registry key name '%s'" % keystr[0])
  66. try:
  67. subkey = '\\'.join(keystr[1:])
  68. val = win32api.RegQueryValue(root, subkey)
  69. if val:
  70. x = dirpath(val)
  71. else:
  72. win32ui.MessageBox("Registry path '%s' did not return a path entry" % d)
  73. except:
  74. win32ui.MessageBox("Can't interpret registry key value: %s" % keystr[1:])
  75. else:
  76. win32ui.MessageBox("Directory '%s' not found" % d)
  77. if x:
  78. for xd in x:
  79. if xd not in dirs:
  80. dirs[xd] = None
  81. if recurse:
  82. subdirs = getsubdirs(xd)
  83. for sd in subdirs:
  84. sd = sd.lower()
  85. if sd not in dirs:
  86. dirs[sd] = None
  87. self.dirs = []
  88. for d in list(dirs.keys()):
  89. self.dirs.append(d)
  90. def __getitem__(self, key):
  91. return self.dirs[key]
  92. def __len__(self):
  93. return len(self.dirs)
  94. def __setitem__(self, key, value):
  95. self.dirs[key] = value
  96. def __delitem__(self, key):
  97. del self.dirs[key]
  98. def __getslice__(self, lo, hi):
  99. return self.dirs[lo:hi]
  100. def __setslice__(self, lo, hi, seq):
  101. self.dirs[lo:hi] = seq
  102. def __delslice__(self, lo, hi):
  103. del self.dirs[lo:hi]
  104. def __add__(self, other):
  105. if type(other) == type(self) or type(other) == type([]):
  106. return self.dirs + other.dirs
  107. def __radd__(self, other):
  108. if type(other) == type(self) or type(other) == type([]):
  109. return other.dirs + self.dirs
  110. # Group(1) is the filename, group(2) is the lineno.
  111. #regexGrepResult=regex.compile("^\\([a-zA-Z]:.*\\)(\\([0-9]+\\))")
  112. regexGrep=re.compile(r"^([a-zA-Z]:[^(]*)\(([0-9]+)\)")
  113. #these are the atom numbers defined by Windows for basic dialog controls
  114. BUTTON = 0x80
  115. EDIT = 0x81
  116. STATIC = 0x82
  117. LISTBOX = 0x83
  118. SCROLLBAR = 0x84
  119. COMBOBOX = 0x85
  120. class GrepTemplate(docview.RichEditDocTemplate):
  121. def __init__(self):
  122. docview.RichEditDocTemplate.__init__(self, win32ui.IDR_TEXTTYPE, GrepDocument, GrepFrame, GrepView)
  123. self.SetDocStrings("\nGrep\nGrep\nGrep params (*.grep)\n.grep\n\n\n")
  124. win32ui.GetApp().AddDocTemplate(self)
  125. self.docparams = None
  126. def MatchDocType(self, fileName, fileType):
  127. doc = self.FindOpenDocument(fileName)
  128. if doc: return doc
  129. ext = os.path.splitext(fileName)[1].lower()
  130. if ext =='.grep':
  131. return win32ui.CDocTemplate_Confidence_yesAttemptNative
  132. return win32ui.CDocTemplate_Confidence_noAttempt
  133. def setParams(self, params):
  134. self.docparams = params
  135. def readParams(self):
  136. tmp = self.docparams
  137. self.docparams = None
  138. return tmp
  139. class GrepFrame(window.MDIChildWnd):
  140. # The template and doc params will one day be removed.
  141. def __init__(self, wnd = None):
  142. window.MDIChildWnd.__init__(self, wnd)
  143. class GrepDocument(docview.RichEditDoc):
  144. def __init__(self, template):
  145. docview.RichEditDoc.__init__(self, template)
  146. self.dirpattern = ''
  147. self.filpattern = ''
  148. self.greppattern = ''
  149. self.casesensitive = 1
  150. self.recurse = 1
  151. self.verbose = 0
  152. def OnOpenDocument(self, fnm):
  153. #this bizarre stuff with params is so right clicking in a result window
  154. #and starting a new grep can communicate the default parameters to the
  155. #new grep.
  156. try:
  157. params = open(fnm,'r').read()
  158. except:
  159. params = None
  160. self.setInitParams(params)
  161. return self.OnNewDocument()
  162. def OnCloseDocument(self):
  163. try:
  164. win32ui.GetApp().DeleteIdleHandler(self.SearchFile)
  165. except:
  166. pass
  167. return self._obj_.OnCloseDocument()
  168. def saveInitParams(self):
  169. # Only save the flags, not the text boxes.
  170. paramstr = "\t%s\t\t%d\t%d" % (self.filpattern, self.casesensitive, self.recurse)
  171. win32ui.WriteProfileVal("Grep", "Params", paramstr)
  172. def setInitParams(self, paramstr):
  173. if paramstr is None:
  174. paramstr = win32ui.GetProfileVal("Grep", "Params", '\t\t\t1\t0\t0')
  175. params = paramstr.split('\t')
  176. if len(params) < 3:
  177. params = params + ['']*(3-len(params))
  178. if len(params) < 6:
  179. params = params + [0]*(6-len(params))
  180. self.dirpattern = params[0]
  181. self.filpattern = params[1]
  182. self.greppattern = params[2]
  183. self.casesensitive = int(params[3])
  184. self.recurse = int(params[4])
  185. self.verbose = int(params[5])
  186. # setup some reasonable defaults.
  187. if not self.dirpattern:
  188. try:
  189. editor=win32ui.GetMainFrame().MDIGetActive()[0].GetEditorView()
  190. self.dirpattern=os.path.abspath(os.path.dirname(editor.GetDocument().GetPathName()))
  191. except (AttributeError, win32ui.error):
  192. self.dirpattern = os.getcwd()
  193. if not self.filpattern:
  194. self.filpattern = "*.py"
  195. def OnNewDocument(self):
  196. if self.dirpattern == '':
  197. self.setInitParams(greptemplate.readParams())
  198. d = GrepDialog(self.dirpattern, self.filpattern, self.greppattern, self.casesensitive, self.recurse, self.verbose)
  199. if d.DoModal() == win32con.IDOK:
  200. self.dirpattern = d['dirpattern']
  201. self.filpattern = d['filpattern']
  202. self.greppattern = d['greppattern']
  203. self.casesensitive = d['casesensitive']
  204. self.recurse = d['recursive']
  205. self.verbose = d['verbose']
  206. self.doSearch()
  207. self.saveInitParams()
  208. return 1
  209. return 0 # cancelled - return zero to stop frame creation.
  210. def doSearch(self):
  211. self.dp = dirpath(self.dirpattern, self.recurse)
  212. self.SetTitle("Grep for %s in %s" % (self.greppattern, self.filpattern))
  213. #self.text = []
  214. self.GetFirstView().Append('#Search '+self.dirpattern+'\n')
  215. if self.verbose:
  216. self.GetFirstView().Append('# ='+repr(self.dp.dirs)+'\n')
  217. self.GetFirstView().Append('# Files '+self.filpattern+'\n')
  218. self.GetFirstView().Append('# For '+self.greppattern+'\n')
  219. self.fplist = self.filpattern.split(';')
  220. if self.casesensitive:
  221. self.pat = re.compile(self.greppattern)
  222. else:
  223. self.pat = re.compile(self.greppattern, re.IGNORECASE)
  224. win32ui.SetStatusText("Searching. Please wait...", 0)
  225. self.dpndx = self.fpndx = 0
  226. self.fndx = -1
  227. if not self.dp:
  228. self.GetFirstView().Append("# ERROR: '%s' does not resolve to any search locations" % self.dirpattern)
  229. self.SetModifiedFlag(0)
  230. else:
  231. self.flist = glob.glob(self.dp[0]+'\\'+self.fplist[0])
  232. win32ui.GetApp().AddIdleHandler(self.SearchFile)
  233. def SearchFile(self, handler, count):
  234. self.fndx = self.fndx + 1
  235. if self.fndx < len(self.flist):
  236. f = self.flist[self.fndx]
  237. if self.verbose:
  238. self.GetFirstView().Append('# ..'+f+'\n')
  239. # Directories may match the file type pattern, and files may be removed
  240. # while grep is running
  241. if os.path.isfile(f):
  242. win32ui.SetStatusText("Searching "+f, 0)
  243. lines = open(f, 'r').readlines()
  244. for i in range(len(lines)):
  245. line = lines[i]
  246. if self.pat.search(line) != None:
  247. self.GetFirstView().Append(f+'('+repr(i+1) + ') '+line)
  248. else:
  249. self.fndx = -1
  250. self.fpndx = self.fpndx + 1
  251. if self.fpndx < len(self.fplist):
  252. self.flist = glob.glob(self.dp[self.dpndx] + '\\' + self.fplist[self.fpndx])
  253. else:
  254. self.fpndx = 0
  255. self.dpndx = self.dpndx + 1
  256. if self.dpndx < len(self.dp):
  257. self.flist = glob.glob(self.dp[self.dpndx] + '\\' + self.fplist[self.fpndx])
  258. else:
  259. win32ui.SetStatusText("Search complete.", 0)
  260. self.SetModifiedFlag(0) # default to not modified.
  261. try:
  262. win32ui.GetApp().DeleteIdleHandler(self.SearchFile)
  263. except:
  264. pass
  265. return 0
  266. return 1
  267. def GetParams(self):
  268. return self.dirpattern+'\t'+self.filpattern+'\t'+self.greppattern+'\t'+repr(self.casesensitive)+'\t'+repr(self.recurse)+'\t'+repr(self.verbose)
  269. def OnSaveDocument(self, filename):
  270. # print 'OnSaveDocument() filename=',filename
  271. savefile = open(filename,"wb")
  272. txt = self.GetParams()+'\n'
  273. # print 'writing',txt
  274. savefile.write(txt)
  275. savefile.close()
  276. self.SetModifiedFlag(0)
  277. return 1
  278. ID_OPEN_FILE = 0xe400
  279. ID_GREP = 0xe401
  280. ID_SAVERESULTS = 0x402
  281. ID_TRYAGAIN = 0x403
  282. class GrepView(docview.RichEditView):
  283. def __init__(self, doc):
  284. docview.RichEditView.__init__(self, doc)
  285. self.SetWordWrap(win32ui.CRichEditView_WrapNone)
  286. self.HookHandlers()
  287. def OnInitialUpdate(self):
  288. rc = self._obj_.OnInitialUpdate()
  289. format = (-402653169, 0, 200, 0, 0, 0, 49, 'Courier New')
  290. self.SetDefaultCharFormat(format)
  291. return rc
  292. def HookHandlers(self):
  293. self.HookMessage(self.OnRClick, win32con.WM_RBUTTONDOWN)
  294. self.HookCommand(self.OnCmdOpenFile, ID_OPEN_FILE)
  295. self.HookCommand(self.OnCmdGrep, ID_GREP)
  296. self.HookCommand(self.OnCmdSave, ID_SAVERESULTS)
  297. self.HookCommand(self.OnTryAgain, ID_TRYAGAIN)
  298. self.HookMessage(self.OnLDblClick,win32con.WM_LBUTTONDBLCLK)
  299. def OnLDblClick(self,params):
  300. line = self.GetLine()
  301. regexGrepResult = regexGrep.match(line)
  302. if regexGrepResult:
  303. fname = regexGrepResult.group(1)
  304. line = int(regexGrepResult.group(2))
  305. scriptutils.JumpToDocument(fname, line)
  306. return 0 # dont pass on
  307. return 1 # pass it on by default.
  308. def OnRClick(self, params):
  309. menu = win32ui.CreatePopupMenu()
  310. flags=win32con.MF_STRING|win32con.MF_ENABLED
  311. lineno = self._obj_.LineFromChar(-1) #selection or current line
  312. line = self._obj_.GetLine(lineno)
  313. regexGrepResult = regexGrep.match(line)
  314. if regexGrepResult:
  315. self.fnm = regexGrepResult.group(1)
  316. self.lnnum = int(regexGrepResult.group(2))
  317. menu.AppendMenu(flags, ID_OPEN_FILE, "&Open "+self.fnm)
  318. menu.AppendMenu(win32con.MF_SEPARATOR)
  319. menu.AppendMenu(flags, ID_TRYAGAIN, "&Try Again")
  320. charstart, charend = self._obj_.GetSel()
  321. if charstart != charend:
  322. linestart = self._obj_.LineIndex(lineno)
  323. self.sel = line[charstart-linestart:charend-linestart]
  324. menu.AppendMenu(flags, ID_GREP, "&Grep for "+self.sel)
  325. menu.AppendMenu(win32con.MF_SEPARATOR)
  326. menu.AppendMenu(flags, win32ui.ID_EDIT_CUT, 'Cu&t')
  327. menu.AppendMenu(flags, win32ui.ID_EDIT_COPY, '&Copy')
  328. menu.AppendMenu(flags, win32ui.ID_EDIT_PASTE, '&Paste')
  329. menu.AppendMenu(flags, win32con.MF_SEPARATOR);
  330. menu.AppendMenu(flags, win32ui.ID_EDIT_SELECT_ALL, '&Select all')
  331. menu.AppendMenu(flags, win32con.MF_SEPARATOR);
  332. menu.AppendMenu(flags, ID_SAVERESULTS, 'Sa&ve results')
  333. menu.TrackPopupMenu(params[5])
  334. return 0
  335. def OnCmdOpenFile(self, cmd, code):
  336. doc = win32ui.GetApp().OpenDocumentFile(self.fnm)
  337. if doc:
  338. vw = doc.GetFirstView()
  339. #hope you have an editor that implements GotoLine()!
  340. try:
  341. vw.GotoLine(int(self.lnnum))
  342. except:
  343. pass
  344. return 0
  345. def OnCmdGrep(self, cmd, code):
  346. curparamsstr = self.GetDocument().GetParams()
  347. params = curparamsstr.split('\t')
  348. params[2] = self.sel
  349. greptemplate.setParams('\t'.join(params))
  350. greptemplate.OpenDocumentFile()
  351. return 0
  352. def OnTryAgain(self, cmd, code):
  353. greptemplate.setParams(self.GetDocument().GetParams())
  354. greptemplate.OpenDocumentFile()
  355. return 0
  356. def OnCmdSave(self, cmd, code):
  357. flags = win32con.OFN_OVERWRITEPROMPT
  358. dlg = win32ui.CreateFileDialog(0, None, None, flags, "Text Files (*.txt)|*.txt||", self)
  359. dlg.SetOFNTitle("Save Results As")
  360. if dlg.DoModal() == win32con.IDOK:
  361. pn = dlg.GetPathName()
  362. self._obj_.SaveTextFile(pn)
  363. return 0
  364. def Append(self, strng):
  365. numlines = self.GetLineCount()
  366. endpos = self.LineIndex(numlines-1) + len(self.GetLine(numlines-1))
  367. self.SetSel(endpos, endpos)
  368. self.ReplaceSel(strng)
  369. class GrepDialog(dialog.Dialog):
  370. def __init__(self, dp, fp, gp, cs, r, v):
  371. style = win32con.DS_MODALFRAME | win32con.WS_POPUP | win32con.WS_VISIBLE | win32con.WS_CAPTION | win32con.WS_SYSMENU | win32con.DS_SETFONT
  372. CS = win32con.WS_CHILD | win32con.WS_VISIBLE
  373. tmp = [ ["Grep", (0, 0, 210, 90), style, None, (8, "MS Sans Serif")], ]
  374. tmp.append([STATIC, "Grep For:", -1, (7, 7, 50, 9), CS ])
  375. tmp.append([EDIT, gp, 101, (52, 7, 144, 11), CS | win32con.WS_TABSTOP | win32con.ES_AUTOHSCROLL | win32con.WS_BORDER])
  376. tmp.append([STATIC, "Directories:", -1, (7, 20, 50, 9), CS ])
  377. tmp.append([EDIT, dp, 102, (52, 20, 128, 11), CS | win32con.WS_TABSTOP | win32con.ES_AUTOHSCROLL | win32con.WS_BORDER])
  378. tmp.append([BUTTON, '...', 110, (182,20, 16, 11), CS | win32con.BS_PUSHBUTTON | win32con.WS_TABSTOP])
  379. tmp.append([STATIC, "File types:", -1, (7, 33, 50, 9), CS ])
  380. tmp.append([EDIT, fp, 103, (52, 33, 128, 11), CS | win32con.WS_TABSTOP | win32con.ES_AUTOHSCROLL | win32con.WS_BORDER ])
  381. tmp.append([BUTTON, '...', 111, (182,33, 16, 11), CS | win32con.BS_PUSHBUTTON | win32con.WS_TABSTOP])
  382. tmp.append([BUTTON,'Case sensitive', 104, (7, 45, 72, 9), CS | win32con.BS_AUTOCHECKBOX | win32con.BS_LEFTTEXT| win32con.WS_TABSTOP])
  383. tmp.append([BUTTON,'Subdirectories', 105, (7, 56, 72, 9), CS | win32con.BS_AUTOCHECKBOX | win32con.BS_LEFTTEXT| win32con.WS_TABSTOP])
  384. tmp.append([BUTTON,'Verbose', 106, (7, 67, 72, 9), CS | win32con.BS_AUTOCHECKBOX | win32con.BS_LEFTTEXT| win32con.WS_TABSTOP])
  385. tmp.append([BUTTON,'OK', win32con.IDOK, (166,53, 32, 12), CS | win32con.BS_DEFPUSHBUTTON| win32con.WS_TABSTOP])
  386. tmp.append([BUTTON,'Cancel', win32con.IDCANCEL, (166,67, 32, 12), CS | win32con.BS_PUSHBUTTON| win32con.WS_TABSTOP])
  387. dialog.Dialog.__init__(self, tmp)
  388. self.AddDDX(101,'greppattern')
  389. self.AddDDX(102,'dirpattern')
  390. self.AddDDX(103,'filpattern')
  391. self.AddDDX(104,'casesensitive')
  392. self.AddDDX(105,'recursive')
  393. self.AddDDX(106,'verbose')
  394. self._obj_.data['greppattern'] = gp
  395. self._obj_.data['dirpattern'] = dp
  396. self._obj_.data['filpattern'] = fp
  397. self._obj_.data['casesensitive'] = cs
  398. self._obj_.data['recursive'] = r
  399. self._obj_.data['verbose'] = v
  400. self.HookCommand(self.OnMoreDirectories, 110)
  401. self.HookCommand(self.OnMoreFiles, 111)
  402. def OnMoreDirectories(self, cmd, code):
  403. self.getMore('Grep\\Directories', 'dirpattern')
  404. def OnMoreFiles(self, cmd, code):
  405. self.getMore('Grep\\File Types', 'filpattern')
  406. def getMore(self, section, key):
  407. self.UpdateData(1)
  408. #get the items out of the ini file
  409. ini = win32ui.GetProfileFileName()
  410. secitems = win32api.GetProfileSection(section, ini)
  411. items = []
  412. for secitem in secitems:
  413. items.append(secitem.split('=')[1])
  414. dlg = GrepParamsDialog(items)
  415. if dlg.DoModal() == win32con.IDOK:
  416. itemstr = ';'.join(dlg.getItems())
  417. self._obj_.data[key] = itemstr
  418. #update the ini file with dlg.getNew()
  419. i = 0
  420. newitems = dlg.getNew()
  421. if newitems:
  422. items = items + newitems
  423. for item in items:
  424. win32api.WriteProfileVal(section, repr(i), item, ini)
  425. i = i + 1
  426. self.UpdateData(0)
  427. def OnOK(self):
  428. self.UpdateData(1)
  429. for id, name in [(101,'greppattern'), (102,'dirpattern'), (103,'filpattern')]:
  430. if not self[name]:
  431. self.GetDlgItem(id).SetFocus()
  432. win32api.MessageBeep()
  433. win32ui.SetStatusText("Please enter a value")
  434. return
  435. self._obj_.OnOK()
  436. class GrepParamsDialog(dialog.Dialog):
  437. def __init__(self, items):
  438. self.items = items
  439. self.newitems = []
  440. style = win32con.DS_MODALFRAME | win32con.WS_POPUP | win32con.WS_VISIBLE | win32con.WS_CAPTION | win32con.WS_SYSMENU | win32con.DS_SETFONT
  441. CS = win32con.WS_CHILD | win32con.WS_VISIBLE
  442. tmp = [ ["Grep Parameters", (0, 0, 205, 100), style, None, (8, "MS Sans Serif")], ]
  443. tmp.append([LISTBOX, '', 107, (7, 7, 150, 72), CS | win32con.LBS_MULTIPLESEL| win32con.LBS_STANDARD | win32con.LBS_HASSTRINGS | win32con.WS_TABSTOP | win32con.LBS_NOTIFY])
  444. tmp.append([BUTTON,'OK', win32con.IDOK, (167, 7, 32, 12), CS | win32con.BS_DEFPUSHBUTTON| win32con.WS_TABSTOP])
  445. tmp.append([BUTTON,'Cancel', win32con.IDCANCEL, (167,23, 32, 12), CS | win32con.BS_PUSHBUTTON| win32con.WS_TABSTOP])
  446. tmp.append([STATIC,'New:', -1, (2, 83, 15, 12), CS])
  447. tmp.append([EDIT, '', 108, (18, 83, 139, 12), CS | win32con.WS_TABSTOP | win32con.ES_AUTOHSCROLL | win32con.WS_BORDER])
  448. tmp.append([BUTTON,'Add', 109, (167,83, 32, 12), CS | win32con.BS_PUSHBUTTON| win32con.WS_TABSTOP])
  449. dialog.Dialog.__init__(self, tmp)
  450. self.HookCommand(self.OnAddItem, 109)
  451. self.HookCommand(self.OnListDoubleClick, 107)
  452. def OnInitDialog(self):
  453. lb = self.GetDlgItem(107)
  454. for item in self.items:
  455. lb.AddString(item)
  456. return self._obj_.OnInitDialog()
  457. def OnAddItem(self, cmd, code):
  458. eb = self.GetDlgItem(108)
  459. item = eb.GetLine(0)
  460. self.newitems.append(item)
  461. lb = self.GetDlgItem(107)
  462. i = lb.AddString(item)
  463. lb.SetSel(i, 1)
  464. return 1
  465. def OnListDoubleClick(self, cmd, code):
  466. if code == win32con.LBN_DBLCLK:
  467. self.OnOK()
  468. return 1
  469. def OnOK(self):
  470. lb = self.GetDlgItem(107)
  471. self.selections = lb.GetSelTextItems()
  472. self._obj_.OnOK()
  473. def getItems(self):
  474. return self.selections
  475. def getNew(self):
  476. return self.newitems
  477. try:
  478. win32ui.GetApp().RemoveDocTemplate(greptemplate)
  479. except NameError:
  480. pass
  481. greptemplate = GrepTemplate()