PageRenderTime 73ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/harbour-3.0.0/contrib/hbide/idefindreplace.prg

#
Unknown | 1458 lines | 1144 code | 314 blank | 0 comment | 0 complexity | cc9fb31eb4cb42ed59ff1d586ce531aa MD5 | raw file
Possible License(s): AGPL-1.0, BSD-3-Clause, CC-BY-SA-3.0, LGPL-3.0, GPL-2.0, LGPL-2.0, LGPL-2.1
  1. /*
  2. * $Id: idefindreplace.prg 16884 2011-06-18 01:36:48Z vouchcac $
  3. */
  4. /*
  5. * Harbour Project source code:
  6. *
  7. * Copyright 2009 Pritpal Bedi <pritpal@vouchcac.com>
  8. * www - http://harbour-project.org
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2, or (at your option)
  13. * any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this software; see the file COPYING. If not, write to
  22. * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  23. * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
  24. *
  25. * As a special exception, the Harbour Project gives permission for
  26. * additional uses of the text contained in its release of Harbour.
  27. *
  28. * The exception is that, if you link the Harbour libraries with other
  29. * files to produce an executable, this does not by itself cause the
  30. * resulting executable to be covered by the GNU General Public License.
  31. * Your use of that executable is in no way restricted on account of
  32. * linking the Harbour library code into it.
  33. *
  34. * This exception does not however invalidate any other reasons why
  35. * the executable file might be covered by the GNU General Public License.
  36. *
  37. * This exception applies only to the code released by the Harbour
  38. * Project under the name Harbour. If you copy code from other
  39. * Harbour Project or Free Software Foundation releases into a copy of
  40. * Harbour, as the General Public License permits, the exception does
  41. * not apply to the code that you add in this way. To avoid misleading
  42. * anyone as to the status of such modified files, you must delete
  43. * this exception notice from them.
  44. *
  45. * If you write modifications of your own for Harbour, it is your choice
  46. * whether to permit this exception to apply to your modifications.
  47. * If you do not wish that, delete this exception notice.
  48. *
  49. */
  50. /*----------------------------------------------------------------------*/
  51. /*----------------------------------------------------------------------*/
  52. /*----------------------------------------------------------------------*/
  53. /*
  54. * EkOnkar
  55. * ( The LORD is ONE )
  56. *
  57. * Harbour-Qt IDE
  58. *
  59. * Pritpal Bedi <pritpal@vouchcac.com>
  60. * 28Dec2009
  61. */
  62. /*----------------------------------------------------------------------*/
  63. /*----------------------------------------------------------------------*/
  64. /*----------------------------------------------------------------------*/
  65. #include "hbide.ch"
  66. #include "common.ch"
  67. #include "hbclass.ch"
  68. #include "hbqtgui.ch"
  69. /*----------------------------------------------------------------------*/
  70. CLASS IdeUpDown INHERIT IdeObject
  71. METHOD new( oIde )
  72. METHOD create( oIde )
  73. METHOD destroy()
  74. METHOD show()
  75. METHOD position()
  76. METHOD execEvent( cEvent, p )
  77. ENDCLASS
  78. /*----------------------------------------------------------------------*/
  79. METHOD IdeUpDown:new( oIde )
  80. ::oIde := oIde
  81. RETURN Self
  82. /*----------------------------------------------------------------------*/
  83. METHOD IdeUpDown:position()
  84. LOCAL qRect, qHSBar, qVSBar, qEdit
  85. IF !empty( qEdit := ::oEM:getEditCurrent() )
  86. ::oUI:setParent( qEdit )
  87. qHSBar := qEdit:horizontalScrollBar()
  88. qVSBar := qEdit:verticalScrollBar()
  89. qRect := qEdit:geometry()
  90. ::oUI:move( qRect:width() - ::oUI:width() - iif( qVSBar:isVisible(), qVSBar:width() , 0 ), ;
  91. qRect:height() - ::oUI:height() - iif( qHSBar:isVisible(), qHSBar:height(), 0 ) )
  92. ENDIF
  93. RETURN Self
  94. /*----------------------------------------------------------------------*/
  95. METHOD IdeUpDown:show()
  96. LOCAL oEdit
  97. IF !empty( oEdit := ::oEM:getEditObjectCurrent() )
  98. oEdit:qEdit:hbGetSelectionInfo()
  99. IF oEdit:aSelectionInfo[ 1 ] > -1
  100. ::oUI:setEnabled( .t. )
  101. ELSE
  102. ::oUI:setEnabled( .f. )
  103. ENDIF
  104. ENDIF
  105. RETURN Self
  106. /*----------------------------------------------------------------------*/
  107. METHOD IdeUpDown:create( oIde )
  108. DEFAULT oIde TO ::oIde
  109. ::oIde := oIde
  110. ::oUI := hbide_getUI( "updown_v" )
  111. ::oUI:setWindowFlags( hb_bitOr( Qt_Tool, Qt_FramelessWindowHint ) )
  112. ::oUI:setFocusPolicy( Qt_NoFocus )
  113. ::oUI:q_buttonPrev:setIcon( hbide_image( "go-prev" ) )
  114. ::oUI:q_buttonPrev:setToolTip( "Find Previous" )
  115. ::oUI:q_buttonPrev:connect( "clicked()", {|| ::execEvent( "buttonPrev_clicked" ) } )
  116. //
  117. ::oUI:q_buttonNext:setIcon( hbide_image( "go-next" ) )
  118. ::oUI:q_buttonNext:setToolTip( "Find Next" )
  119. ::oUI:q_buttonNext:connect( "clicked()", {|| ::execEvent( "buttonNext_clicked" ) } )
  120. //
  121. ::oUI:q_buttonFirst:setIcon( hbide_image( "go-first" ) )
  122. ::oUI:q_buttonFirst:setToolTip( "Find First" )
  123. ::oUI:q_buttonFirst:connect( "clicked()", {|| ::execEvent( "buttonFirst_clicked" ) } )
  124. //
  125. ::oUI:q_buttonLast:setIcon( hbide_image( "go-last" ) )
  126. ::oUI:q_buttonLast:setToolTip( "Find Last" )
  127. ::oUI:q_buttonLast:connect( "clicked()", {|| ::execEvent( "buttonLast_clicked" ) } )
  128. //
  129. ::oUI:q_buttonAll:setIcon( hbide_image( "hilight-all" ) )
  130. ::oUI:q_buttonAll:setToolTip( "Highlight All" )
  131. ::oUI:q_buttonAll:connect( "clicked()", {|| ::execEvent( "buttonAll_clicked" ) } )
  132. RETURN Self
  133. /*----------------------------------------------------------------------*/
  134. METHOD IdeUpDown:execEvent( cEvent, p )
  135. LOCAL cText, oEdit
  136. HB_SYMBOL_UNUSED( p )
  137. IF !empty( oEdit := ::oEM:getEditObjectCurrent() )
  138. cText := oEdit:getSelectedText()
  139. ENDIF
  140. IF !empty( cText )
  141. SWITCH cEvent
  142. CASE "buttonPrev_clicked"
  143. oEdit:findEx( cText, QTextDocument_FindBackward, 0 )
  144. EXIT
  145. CASE "buttonNext_clicked"
  146. oEdit:findEx( cText, 0, 0 )
  147. EXIT
  148. CASE "buttonFirst_clicked"
  149. oEdit:findEx( cText, 0, 1 )
  150. EXIT
  151. CASE "buttonLast_clicked"
  152. oEdit:findEx( cText, QTextDocument_FindBackward, 2 )
  153. EXIT
  154. CASE "buttonAll_clicked"
  155. oEdit:highlightAll( cText )
  156. EXIT
  157. ENDSWITCH
  158. ENDIF
  159. RETURN Self
  160. /*----------------------------------------------------------------------*/
  161. METHOD IdeUpDown:destroy()
  162. IF hb_isObject( ::oUI )
  163. ::oUI:destroy()
  164. ENDIF
  165. RETURN Self
  166. /*----------------------------------------------------------------------*/
  167. //
  168. /*----------------------------------------------------------------------*/
  169. CLASS IdeSearchReplace INHERIT IdeObject
  170. DATA oXbp
  171. DATA qFindLineEdit
  172. DATA qReplLineEdit
  173. DATA nCurDirection INIT 0
  174. DATA cFind INIT ""
  175. METHOD new( oIde )
  176. METHOD create( oIde )
  177. METHOD destroy()
  178. METHOD beginFind()
  179. METHOD setFindString( cText )
  180. METHOD find( cText, lBackward )
  181. METHOD startFromTop()
  182. ENDCLASS
  183. /*----------------------------------------------------------------------*/
  184. METHOD IdeSearchReplace:new( oIde )
  185. ::oIde := oIde
  186. RETURN Self
  187. /*----------------------------------------------------------------------*/
  188. METHOD IdeSearchReplace:create( oIde )
  189. DEFAULT oIde TO ::oIde
  190. ::oIde := oIde
  191. ::oUI := hbide_getUI( "searchreplace" )
  192. ::oUI:setFocusPolicy( Qt_StrongFocus )
  193. ::oUI:q_frameFind:setStyleSheet( "" )
  194. ::oUI:q_frameReplace:setStyleSheet( "" )
  195. ::oUI:q_buttonClose:setIcon( hbide_image( "closetab" ) )
  196. ::oUI:q_buttonClose:setToolTip( "Close" )
  197. ::oUI:q_buttonClose:connect( "clicked()", {|| ::oUI:hide() } )
  198. ::oUI:q_buttonNext:setIcon( hbide_image( "next" ) )
  199. ::oUI:q_buttonNext:setToolTip( "Find Next" )
  200. ::oUI:q_buttonNext:connect( "clicked()", {|| ::find( ::cFind ), ::oIde:manageFocusInEditor() } )
  201. ::oUI:q_buttonPrev:setIcon( hbide_image( "previous" ) )
  202. ::oUI:q_buttonPrev:setToolTip( "Find Previous" )
  203. ::oUI:q_buttonPrev:connect( "clicked()", {|| ::find( ::cFind, .t. ), ::oIde:manageFocusInEditor() } )
  204. ::oUI:q_checkReplace:setChecked( .f. )
  205. ::oUI:q_checkReplace:connect( "stateChanged(int)", {|i| ;
  206. ::oUI:q_comboReplace:setEnabled( i == 2 ), ;
  207. ::oUI:q_buttonReplace:setEnabled( i == 2 ), ;
  208. iif( i == 2, ::oUI:q_frameReplace:show(), ::oUI:q_frameReplace:hide() ) } )
  209. ::qFindLineEdit := ::oUI:q_comboFind:lineEdit()
  210. ::qFindLineEdit:setFocusPolicy( Qt_StrongFocus )
  211. ::qFindLineEdit:setStyleSheet( "background-color: white;" )
  212. ::qFindLineEdit:connect( "textChanged(QString)", {|cText| ::setFindString( cText ) } )
  213. ::qFindLineEdit:connect( "returnPressed()" , {|| ::find( ::cFind ) } )
  214. ::qReplLineEdit := ::oUI:q_comboReplace:lineEdit()
  215. ::qReplLineEdit:setFocusPolicy( Qt_StrongFocus )
  216. ::qReplLineEdit:setStyleSheet( "background-color: white;" )
  217. ::oUI:q_checkReplace:setEnabled( .f. )
  218. ::oUI:q_frameReplace:hide()
  219. RETURN Self
  220. /*----------------------------------------------------------------------*/
  221. METHOD IdeSearchReplace:destroy()
  222. IF hb_isObject( ::oUI )
  223. ::qFindLineEdit:disconnect( "textChanged(QString)" )
  224. ::qFindLineEdit:disconnect( "returnPressed()" )
  225. ::oUI:destroy()
  226. ENDIF
  227. RETURN Self
  228. /*----------------------------------------------------------------------*/
  229. METHOD IdeSearchReplace:find( cText, lBackward )
  230. LOCAL qCursor, qDoc, qCur, qReg
  231. LOCAL lFound := .f.
  232. LOCAL nFlags := 0
  233. DEFAULT lBackward TO .f.
  234. ::nCurDirection := iif( lBackward, QTextDocument_FindBackward, 0 )
  235. IF len( cText ) > 0
  236. qCursor := ::qCurEdit:textCursor()
  237. IF ::oUI:q_checkRegEx:isChecked()
  238. qDoc := ::qCurEdit:document()
  239. qReg := QRegExp()
  240. qReg:setPattern( cText )
  241. qReg:setCaseSensitivity( iif( ::oUI:q_checkMatchCase:isChecked(), Qt_CaseSensitive, Qt_CaseInsensitive ) )
  242. nFlags += ::nCurDirection
  243. nFlags += iif( ::oUI:q_checkWhole:isChecked(), QTextDocument_FindWholeWords, 0 )
  244. qCur := qDoc:find( qReg, qCursor, nFlags )
  245. lFound := ! qCur:isNull()
  246. IF lFound
  247. ::qCurEdit:setTextCursor( qCur )
  248. ENDIF
  249. ELSE
  250. nFlags += iif( ::oUI:q_checkMatchCase:isChecked(), QTextDocument_FindCaseSensitively, 0 )
  251. nFlags += iif( ::oUI:q_checkWhole:isChecked(), QTextDocument_FindWholeWords, 0 )
  252. nFlags += ::nCurDirection
  253. lFound := ::oEM:getEditCurrent():find( cText, nFlags )
  254. ENDIF
  255. IF ! lFound
  256. ::qCurEdit:setTextCursor( qCursor )
  257. ::oUI:q_checkReplace:setChecked( .f. )
  258. ::oUI:q_checkReplace:setEnabled( .f. )
  259. ELSE
  260. ::oUI:q_checkReplace:setEnabled( .t. )
  261. ::qCurEdit:centerCursor()
  262. ENDIF
  263. ENDIF
  264. RETURN lFound
  265. /*----------------------------------------------------------------------*/
  266. METHOD IdeSearchReplace:beginFind()
  267. ::oUI:q_checkReplace:setChecked( .f. )
  268. ::oUI:q_checkReplace:setEnabled( .f. )
  269. ::oUI:q_radioTop:setChecked( .t. )
  270. ::oUI:show()
  271. ::cFind := ""
  272. ::qFindLineEdit:activateWindow()
  273. ::qFindLineEdit:setFocus()
  274. ::qFindLineEdit:selectAll()
  275. RETURN Self
  276. /*----------------------------------------------------------------------*/
  277. METHOD IdeSearchReplace:setFindString( cText )
  278. LOCAL qCursor, nPos
  279. IF empty( cText )
  280. RETURN .f.
  281. ENDIF
  282. qCursor := ::qCurEdit:textCursor()
  283. IF ::oUI:q_radioTop:isChecked()
  284. nPos := qCursor:position()
  285. qCursor:setPosition( 0 )
  286. ::qCurEdit:setTextCursor( qCursor )
  287. ENDIF
  288. IF ! ::find( cText )
  289. IF !empty( nPos )
  290. qCursor:setPosition( nPos )
  291. ::qCurEdit:setTextCursor( qCursor )
  292. ENDIF
  293. ::cFind := ""
  294. ::qFindLineEdit:setStyleSheet( getStyleSheet( "PathIsWrong", ::nAnimantionMode ) )
  295. ELSE
  296. ::cFind := cText
  297. ::qFindLineEdit:setStyleSheet( "background-color: white;" )
  298. ENDIF
  299. RETURN Self
  300. /*----------------------------------------------------------------------*/
  301. METHOD IdeSearchReplace:startFromTop()
  302. LOCAL qCursor
  303. qCursor := ::qCurEdit:textCursor()
  304. qCursor:setPosition( 0 )
  305. ::qCurEdit:setTextCursor( qCursor )
  306. ::find( ::cFind )
  307. RETURN Self
  308. /*----------------------------------------------------------------------*/
  309. /*----------------------------------------------------------------------*/
  310. /*----------------------------------------------------------------------*/
  311. // IdeFindReplace
  312. /*----------------------------------------------------------------------*/
  313. /*----------------------------------------------------------------------*/
  314. /*----------------------------------------------------------------------*/
  315. CLASS IdeFindReplace INHERIT IdeObject
  316. DATA qLineEdit
  317. METHOD new( oIde )
  318. METHOD create( oIde )
  319. METHOD destroy()
  320. METHOD show()
  321. METHOD onClickReplace()
  322. METHOD replaceSelection( cReplWith )
  323. METHOD replace()
  324. METHOD onClickFind()
  325. METHOD find( lWarn )
  326. METHOD updateFindReplaceData( cMode )
  327. ENDCLASS
  328. /*----------------------------------------------------------------------*/
  329. METHOD IdeFindReplace:new( oIde )
  330. ::oIde := oIde
  331. RETURN Self
  332. /*----------------------------------------------------------------------*/
  333. METHOD IdeFindReplace:destroy()
  334. IF !empty( ::oUI )
  335. ::qLineEdit:disConnect( "returnPressed()" )
  336. ::oUI:destroy()
  337. ENDIF
  338. RETURN Self
  339. /*----------------------------------------------------------------------*/
  340. METHOD IdeFindReplace:create( oIde )
  341. DEFAULT oIde TO ::oIde
  342. ::oIde := oIde
  343. ::oUI := hbide_getUI( "finddialog", ::oIde:oDlg:oWidget )
  344. ::oUI:setWindowFlags( Qt_Sheet )
  345. aeval( ::oINI:aFind , {|e| ::oUI:q_comboFindWhat:addItem( e ) } )
  346. aeval( ::oINI:aReplace, {|e| ::oUI:q_comboReplaceWith:addItem( e ) } )
  347. ::oUI:q_radioFromCursor:setChecked( .t. )
  348. ::oUI:q_radioDown:setChecked( .t. )
  349. ::oUI:q_buttonFind :connect( "clicked()", {|| ::onClickFind() } )
  350. ::oUI:q_buttonReplace:connect( "clicked()", {|| ::onClickReplace() } )
  351. ::oUI:q_buttonClose :connect( "clicked()", {|| ::oIde:oINI:cFindDialogGeometry := hbide_posAndSize( ::oUI:oWidget ), ::oUI:hide() } )
  352. ::oUI:q_comboFindWhat:connect( "editTextChanged(QString)", {|| ::oUI:q_radioEntire:setChecked( .t. ) } )
  353. ::oUI:q_comboFindWhat:connect( "currentIndexChanged(QString)", {|p| ::oIde:oSBar:getItem( SB_PNL_SEARCH ):caption := "FIND: " + p } )
  354. ::oUI:q_checkListOnly:connect( "stateChanged(int)", {|p| ;
  355. ::oUI:q_comboReplaceWith:setEnabled( p == 0 ), ;
  356. iif( p == 1, ::oUI:q_buttonReplace:setEnabled( .f. ), NIL ) } )
  357. ::qLineEdit := ::oUI:q_comboFindWhat:lineEdit()
  358. RETURN Self
  359. /*----------------------------------------------------------------------*/
  360. METHOD IdeFindReplace:show()
  361. LOCAL cText
  362. ::oUI:q_buttonReplace:setEnabled( .f. )
  363. ::oUI:q_checkGlobal:setEnabled( .f. )
  364. ::oUI:q_checkNoPrompting:setEnabled( .f. )
  365. ::oUI:q_checkListOnly:setChecked( .f. )
  366. ::oIde:setPosByIniEx( ::oUI:oWidget, ::oINI:cFindDialogGeometry )
  367. ::oUI:q_comboFindWhat:setFocus()
  368. IF !empty( cText := ::oEM:getSelectedText() )
  369. ::qLineEdit:setText( cText )
  370. ENDIF
  371. ::qLineEdit:selectAll()
  372. ::oUI:show()
  373. RETURN Self
  374. /*----------------------------------------------------------------------*/
  375. METHOD IdeFindReplace:onClickReplace()
  376. ::updateFindReplaceData( "replace" )
  377. IF ::oUI:q_comboReplaceWith:isEnabled()
  378. ::replace()
  379. ENDIF
  380. RETURN Self
  381. /*----------------------------------------------------------------------*/
  382. METHOD IdeFindReplace:replaceSelection( cReplWith )
  383. LOCAL nB, nL, cBuffer, qCursor
  384. DEFAULT cReplWith TO ""
  385. qCursor := ::qCurEdit:textCursor()
  386. IF qCursor:hasSelection() .and. !empty( cBuffer := qCursor:selectedText() )
  387. nL := len( cBuffer )
  388. nB := qCursor:position() - nL
  389. qCursor:beginEditBlock()
  390. qCursor:removeSelectedText()
  391. qCursor:insertText( cReplWith )
  392. qCursor:setPosition( nB )
  393. qCursor:movePosition( QTextCursor_NextCharacter, QTextCursor_KeepAnchor, len( cReplWith ) )
  394. ::qCurEdit:setTextCursor( qCursor )
  395. qCursor:endEditBlock()
  396. ENDIF
  397. RETURN Self
  398. /*----------------------------------------------------------------------*/
  399. METHOD IdeFindReplace:replace()
  400. LOCAL cReplWith
  401. LOCAL nFound
  402. IF !empty( ::qCurEdit )
  403. cReplWith := ::oUI:q_comboReplaceWith:lineEdit():text()
  404. ::replaceSelection( cReplWith )
  405. IF ::oUI:q_checkGlobal:isChecked()
  406. IF ::oUI:q_checkNoPrompting:isChecked()
  407. nFound := 1
  408. DO WHILE ::find( .f. )
  409. nFound++
  410. ::replaceSelection( cReplWith )
  411. ENDDO
  412. ::oDK:setStatusText( SB_PNL_MAIN, "Replaced [" + hb_ntos( nFound ) + "] : " + cReplWith )
  413. ::oUI:q_buttonReplace:setEnabled( .f. )
  414. ::oUI:q_checkGlobal:setChecked( .f. )
  415. ::oUI:q_checkNoPrompting:setChecked( .f. )
  416. ELSE
  417. ::find()
  418. ENDIF
  419. ENDIF
  420. ENDIF
  421. RETURN Self
  422. /*----------------------------------------------------------------------*/
  423. METHOD IdeFindReplace:onClickFind()
  424. LOCAL lFound, nPos, qCursor
  425. ::updateFindReplaceData( "find" )
  426. IF ::oUI:q_radioEntire:isChecked()
  427. ::oUI:q_radioFromCursor:setChecked( .t. )
  428. qCursor := ::qCurEdit:textCursor()
  429. nPos := qCursor:position()
  430. qCursor:setPosition( 0 )
  431. ::qCurEdit:setTextCursor( qCursor )
  432. IF !( lFound := ::find() )
  433. qCursor:setPosition( nPos )
  434. ::qCurEdit:setTextCursor( qCursor )
  435. ENDIF
  436. ELSE
  437. lFound := ::find()
  438. ENDIF
  439. IF lFound
  440. ::oUI:q_buttonReplace:setEnabled( .t. )
  441. ::oUI:q_checkGlobal:setEnabled( .t. )
  442. ::oUI:q_checkNoPrompting:setEnabled( .t. )
  443. ELSE
  444. ::oUI:q_buttonReplace:setEnabled( .f. )
  445. ::oUI:q_checkGlobal:setEnabled( .f. )
  446. ::oUI:q_checkNoPrompting:setEnabled( .f. )
  447. ::oUI:q_buttonFind:activateWindow()
  448. ::oUI:q_buttonFind:setFocus()
  449. ENDIF
  450. RETURN Self
  451. /*----------------------------------------------------------------------*/
  452. METHOD IdeFindReplace:find( lWarn )
  453. LOCAL nFlags
  454. LOCAL cText := ::oUI:q_comboFindWhat:lineEdit():text()
  455. LOCAL lFound := .f.
  456. DEFAULT lWarn TO .t.
  457. IF !empty( cText )
  458. nFlags := 0
  459. nFlags += iif( ::oUI:q_checkMatchCase:isChecked(), QTextDocument_FindCaseSensitively, 0 )
  460. nFlags += iif( ::oUI:q_radioUp:isChecked(), QTextDocument_FindBackward, 0 )
  461. IF !( lFound := ::oEM:getEditObjectCurrent():findEx( cText, nFlags ) ) .AND. lWarn
  462. hbide_showWarning( "Cannot find : " + cText )
  463. ENDIF
  464. ENDIF
  465. RETURN lFound
  466. /*----------------------------------------------------------------------*/
  467. METHOD IdeFindReplace:updateFindReplaceData( cMode )
  468. LOCAL cData
  469. IF cMode == "find"
  470. cData := ::oUI:q_comboFindWhat:lineEdit():text()
  471. IF !empty( cData )
  472. IF ascan( ::oINI:aFind, {|e| e == cData } ) == 0
  473. hb_ains( ::oINI:aFind, 1, cData, .t. )
  474. ::oUI:q_comboFindWhat:insertItem( 0, cData )
  475. ENDIF
  476. ENDIF
  477. //
  478. ::oDK:setStatusText( SB_PNL_SEARCH, cData )
  479. ELSE
  480. cData := ::oUI:q_comboReplaceWith:lineEdit():text()
  481. IF !empty( cData )
  482. IF ascan( ::oINI:aReplace, cData ) == 0
  483. hb_ains( ::oINI:aReplace, 1, cData, .t. )
  484. ::oUI:q_comboReplaceWith:insertItem( 0, cData )
  485. ENDIF
  486. ENDIF
  487. ENDIF
  488. RETURN Self
  489. /*----------------------------------------------------------------------*/
  490. //
  491. // Class IdeFindInFiles
  492. //
  493. /*----------------------------------------------------------------------*/
  494. #define L2S( l ) iif( l, "Yes", "No" )
  495. #define F_BLACK '<font color = black>'
  496. #define F_GREEN '<font color = green>'
  497. #define F_RED '<font color = red>'
  498. #define F_CYAN '<font color = cyan>'
  499. #define F_BLUE '<font color = blue>'
  500. #define F_YELLOW '<font color = yellow>'
  501. #define F_SECTION '<font color=GoldenRod size="6">'
  502. #define F_SECTION_ITEM '<font color=blue size="5">'
  503. #define F_INFO '<font color=LightBlue>'
  504. #define F_FILE '<font color=green>'
  505. #define F_SEARCH '<font color=IndianRed>'
  506. #define F_END '</font>'
  507. #define LOG_MISSING 1
  508. #define LOG_FINDS 2
  509. #define LOG_SEPARATOR 3
  510. #define LOG_FLAGS 4
  511. #define LOG_TERMINATED 5
  512. #define LOG_SECTION 6
  513. #define LOG_SECTION_ITEM 7
  514. #define LOG_EMPTY 8
  515. #define LOG_INFO 9
  516. /*----------------------------------------------------------------------*/
  517. CLASS IdeFindInFiles INHERIT IdeObject
  518. DATA aItems INIT {}
  519. DATA lStop INIT .f.
  520. DATA aInfo INIT {}
  521. DATA nSearched INIT 0
  522. DATA nFounds INIT 0
  523. DATA nMisses INIT 0
  524. DATA cOrigExpr
  525. DATA compRegEx
  526. DATA cReplWith
  527. DATA lRegEx INIT .F.
  528. DATA lListOnly INIT .T.
  529. DATA lMatchCase INIT .F.
  530. DATA lNotDblClick INIT .F.
  531. DATA lShowOnCreate INIT .T.
  532. DATA lInDockWindow INIT .F.
  533. DATA qEditFind
  534. METHOD new( oIde, lShowOnCreate )
  535. METHOD create( oIde, lShowOnCreate )
  536. METHOD destroy()
  537. METHOD show()
  538. METHOD print()
  539. METHOD paintRequested( qPrinter )
  540. METHOD find()
  541. METHOD findInABunch( aFiles )
  542. METHOD showLog( nType, cMsg, aLines )
  543. METHOD execEvent( cEvent, p )
  544. METHOD execContextMenu( p )
  545. METHOD buildUI()
  546. ENDCLASS
  547. /*----------------------------------------------------------------------*/
  548. METHOD IdeFindInFiles:new( oIde, lShowOnCreate )
  549. ::oIde := oIde
  550. ::lShowOnCreate := lShowOnCreate
  551. RETURN Self
  552. /*----------------------------------------------------------------------*/
  553. METHOD IdeFindInFiles:create( oIde, lShowOnCreate )
  554. DEFAULT oIde TO ::oIde
  555. DEFAULT lShowOnCreate TO ::lShowOnCreate
  556. ::oIde := oIde
  557. ::lShowOnCreate := lShowOnCreate
  558. RETURN Self
  559. /*----------------------------------------------------------------------*/
  560. METHOD IdeFindInFiles:destroy()
  561. LOCAL qItem
  562. IF !empty( ::oUI )
  563. ::qEditFind:disConnect( "returnPressed()" )
  564. FOR EACH qItem IN ::aItems
  565. qItem := NIL
  566. NEXT
  567. ::oUI:destroy()
  568. ENDIF
  569. RETURN Self
  570. /*----------------------------------------------------------------------*/
  571. METHOD IdeFindInFiles:buildUI()
  572. LOCAL cText, qLineEdit, aProjList, cProj, qItem, n
  573. ::oUI := hbide_getUI( "findinfilesex" )
  574. ::oFindDock:oWidget:setWidget( ::oUI )
  575. ::oUI:q_buttonFolder:setIcon( ::resPath + "folder.png" )
  576. aeval( ::oINI:aFind , {|e| ::oUI:q_comboExpr:addItem( e ) } )
  577. aeval( ::oINI:aReplace, {|e| ::oUI:q_comboRepl:addItem( e ) } )
  578. aeval( ::oINI:aFolders, {|e| ::oUI:q_comboFolder:addItem( e ) } )
  579. n := ascan( ::oINI:aFind, {|e| e == ::cWrkFind } )
  580. ::oUI:q_comboExpr:setCurrentIndex( n-1 )
  581. n := ascan( ::oINI:aReplace, {|e| e == ::cWrkReplace } )
  582. ::oUI:q_comboRepl:setCurrentIndex( n - 1 )
  583. n := ascan( ::oIni:aFolders, {|e| e == ::cWrkFolderFind } )
  584. ::oUI:q_comboFolder:setCurrentIndex( n - 1 )
  585. ::oUI:q_comboFolder:setEnabled( .f. )
  586. ::oUI:q_checkFolders:setChecked( .f. )
  587. ::oUI:q_checkSubFolders:setChecked( .f. )
  588. ::oUI:q_checkSubFolders:setEnabled( .f. )
  589. ::oUI:q_buttonRepl:setEnabled( .f. )
  590. ::oUI:q_buttonStop:setEnabled( .f. )
  591. ::oUI:q_comboRepl:setEnabled( .f. )
  592. ::oUI:q_checkListOnly:setChecked( .t. )
  593. ::oUI:q_checkPrg:setChecked( .t. )
  594. qLineEdit := ::oUI:q_comboExpr:lineEdit()
  595. IF !empty( ::oEM )
  596. IF !empty( cText := ::oEM:getSelectedText() )
  597. qLineEdit:setText( cText )
  598. ENDIF
  599. ENDIF
  600. qLineEdit:selectAll()
  601. /* Populate Projects Name */
  602. IF !empty( ::oPM )
  603. aProjList := ::oPM:getProjectsTitleList()
  604. FOR EACH cProj IN aProjList
  605. IF !empty( cProj )
  606. qItem := QListWidgetItem()
  607. qItem:setFlags( Qt_ItemIsUserCheckable + Qt_ItemIsEnabled + Qt_ItemIsSelectable )
  608. qItem:setText( cProj )
  609. qItem:setCheckState( 0 )
  610. //::oUI:q_listProjects:addItem_1( qItem )
  611. ::oUI:q_listProjects:addItem( qItem )
  612. aadd( ::aItems, qItem )
  613. ENDIF
  614. NEXT
  615. ENDIF
  616. ::oUI:q_editResults:setReadOnly( .t. )
  617. //::oUI:q_editResults:setFontFamily( "Courier New" )
  618. //::oUI:q_editResults:setFontPointSize( 10 )
  619. ::oUI:q_editResults:setFont( ::oIde:oFont:oWidget )
  620. ::oUI:q_editResults:setContextMenuPolicy( Qt_CustomContextMenu )
  621. ::oUI:q_labelStatus:setText( "Ready" )
  622. ::oUI:q_comboExpr:setFocus()
  623. /* Attach all signals */
  624. //
  625. ::oUI:q_buttonClose :connect( "clicked()" , {| | ::execEvent( "buttonClose" ) } )
  626. ::oUI:q_buttonFolder :connect( "clicked()" , {| | ::execEvent( "buttonFolder" ) } )
  627. ::oUI:q_buttonFind :connect( "clicked()" , {| | ::execEvent( "buttonFind" ) } )
  628. ::oUI:q_buttonRepl :connect( "clicked()" , {| | ::execEvent( "buttonRepl" ) } )
  629. ::oUI:q_buttonStop :connect( "clicked()" , {| | ::execEvent( "buttonStop" ) } )
  630. ::oUI:q_checkAll :connect( "stateChanged(int)" , {|p| ::execEvent( "checkAll", p ) } )
  631. ::oUI:q_comboExpr :connect( "currentIndexChanged(QString)", {|p| ::execEvent( "comboFind", p ) } )
  632. ::oUI:q_checkListOnly:connect( "stateChanged(int)" , {|p| ::execEvent( "checkListOnly", p ) } )
  633. ::oUI:q_checkFolders :connect( "stateChanged(int)" , {|p| ::execEvent( "checkFolders", p ) } )
  634. ::oUI:q_editResults :connect( "copyAvailable(bool)" , {|l| ::execEvent( "editResults", l ) } )
  635. ::oUI:q_editResults :connect( "customContextMenuRequested(QPoint)", {|p| ::execEvent( "editResults-contextMenu", p ) } )
  636. ::qEditFind := ::oUI:q_comboExpr:lineEdit()
  637. ::qEditFind:connect( "returnPressed()", {|| ::execEvent( "buttonFind" ) } )
  638. RETURN Self
  639. /*----------------------------------------------------------------------*/
  640. METHOD IdeFindInFiles:execEvent( cEvent, p )
  641. LOCAL cPath, qLineEdit, qCursor, cSource, v, nInfo
  642. SWITCH cEvent
  643. CASE "buttonClose"
  644. ::oFindDock:hide()
  645. EXIT
  646. CASE "comboFind"
  647. ::oIde:oSBar:getItem( SB_PNL_SEARCH ):caption := "FIND: " + p
  648. EXIT
  649. CASE "checkListOnly"
  650. ::oUI:q_comboRepl:setEnabled( p == 0 )
  651. ::oUI:q_buttonRepl:setEnabled( !( p == 1 ) )
  652. EXIT
  653. CASE "checkFolders"
  654. ::oUI:q_comboFolder:setEnabled( p == 2 )
  655. ::oUI:q_checkSubFolders:setEnabled( p == 2 )
  656. EXIT
  657. CASE "buttonFind"
  658. ::find()
  659. EXIT
  660. CASE "buttonRepl"
  661. EXIT
  662. CASE "buttonStop"
  663. ::lStop := .t.
  664. EXIT
  665. CASE "buttonFolder"
  666. cPath := hbide_fetchADir( ::oDlg, "Select a folder for search operation", ::cLastFileOpenPath )
  667. IF !empty( cPath )
  668. ::oIde:cLastFileOpenPath := cPath
  669. qLineEdit := ::oUI:q_comboFolder:lineEdit()
  670. qLineEdit:setText( cPath )
  671. IF ascan( ::oINI:aFolders, {|e| e == cPath } ) == 0
  672. hb_ains( ::oINI:aFolders, 1, cPath, .t. )
  673. ENDIF
  674. ::oUI:q_comboFolder:insertItem( 0, cPath )
  675. ENDIF
  676. EXIT
  677. CASE "checkAll"
  678. v := !( p == 0 )
  679. ::oUI:q_checkPrg:setChecked( v )
  680. ::oUI:q_checkC:setChecked( v )
  681. ::oUI:q_checkCpp:setChecked( v )
  682. ::oUI:q_checkCh:setChecked( v )
  683. ::oUI:q_checkH:setChecked( v )
  684. ::oUI:q_checkRc:setChecked( v )
  685. EXIT
  686. CASE "editResults-contextMenu"
  687. ::execContextMenu( p )
  688. EXIT
  689. CASE "editResults"
  690. IF p .AND. ! ::lNotDblClick
  691. qCursor := ::oUI:q_editResults:textCursor()
  692. nInfo := qCursor:blockNumber() + 1
  693. IF nInfo <= len( ::aInfo ) .AND. ::aInfo[ nInfo, 1 ] == -2
  694. cSource := ::aInfo[ nInfo, 2 ]
  695. ::oSM:editSource( cSource, 0, 0, 0, NIL, NIL, .f., .t. )
  696. qCursor := ::oIde:qCurEdit:textCursor()
  697. qCursor:setPosition( 0 )
  698. qCursor:movePosition( QTextCursor_Down, QTextCursor_MoveAnchor, ::aInfo[ nInfo, 3 ] - 1 )
  699. qCursor:movePosition( QTextCursor_Right, QTextCursor_MoveAnchor, ::aInfo[ nInfo, 4 ] - 1 )
  700. qCursor:movePosition( QTextCursor_Right, QTextCursor_KeepAnchor, len( ::aInfo[ nInfo, 5 ] ) )
  701. ::oIde:qCurEdit:setTextCursor( qCursor )
  702. ::oIde:manageFocusInEditor()
  703. ENDIF
  704. ELSE
  705. ::lNotDblClick := .F.
  706. ENDIF
  707. EXIT
  708. ENDSWITCH
  709. RETURN Self
  710. /*----------------------------------------------------------------------*/
  711. METHOD IdeFindInFiles:execContextMenu( p )
  712. LOCAL nLine, qCursor, qMenu, qAct, cAct, cFind
  713. qCursor := ::oUI:q_editResults:textCursor()
  714. nLine := qCursor:blockNumber() + 1
  715. IF nLine <= len( ::aInfo )
  716. qMenu := QMenu( ::oUI:q_editResults )
  717. qMenu:addAction( "Copy" )
  718. qMenu:addAction( "Select All" )
  719. qMenu:addAction( "Clear" )
  720. qMenu:addAction( "Print" )
  721. qMenu:addAction( "Save as..." )
  722. qMenu:addSeparator()
  723. qMenu:addAction( "Find" )
  724. qMenu:addSeparator()
  725. IF ::aInfo[ nLine, 1 ] == -2 /* Found Line */
  726. qMenu:addAction( "Replace Line" )
  727. ELSEIF ::aInfo[ nLine, 1 ] == -1 /* Source File */
  728. qMenu:addAction( "Open" )
  729. qMenu:addAction( "Replace All" )
  730. ENDIF
  731. qMenu:addSeparator()
  732. qMenu:addAction( "Zoom In" )
  733. qMenu:addAction( "Zoom Out" )
  734. IF ( qAct := qMenu:exec( ::oUI:q_editResults:mapToGlobal( QPoint( p ) ) ) ):hasValidPointer()
  735. cAct := qAct:text()
  736. SWITCH cAct
  737. CASE "Save as..."
  738. EXIT
  739. CASE "Find"
  740. IF !empty( cFind := hbide_fetchAString( ::oUI:q_editResults, , "Find what?", "Find" ) )
  741. ::lNotDblClick := .T.
  742. IF !( ::oUI:q_editResults:find( cFind, 0 ) )
  743. MsgBox( "Not Found" )
  744. ENDIF
  745. ENDIF
  746. EXIT
  747. CASE "Print"
  748. ::print()
  749. EXIT
  750. CASE "Clear"
  751. ::oUI:q_editResults:clear()
  752. ::aInfo := {}
  753. EXIT
  754. CASE "Copy"
  755. ::lNotDblClick := .T.
  756. ::oUI:q_editResults:copy()
  757. EXIT
  758. CASE "Select All"
  759. ::oUI:q_editResults:selectAll()
  760. EXIT
  761. CASE "Replace Line"
  762. EXIT
  763. CASE "Replace Source"
  764. EXIT
  765. CASE "Zoom In"
  766. ::oUI:q_editResults:zoomIn()
  767. EXIT
  768. CASE "Zoom Out"
  769. ::oUI:q_editResults:zoomOut()
  770. EXIT
  771. ENDSWITCH
  772. ENDIF
  773. ENDIF
  774. RETURN Self
  775. /*----------------------------------------------------------------------*/
  776. METHOD IdeFindInFiles:show()
  777. IF empty( ::oUI )
  778. ::buildUI()
  779. ENDIF
  780. RETURN Self
  781. /*----------------------------------------------------------------------*/
  782. METHOD IdeFindInFiles:find()
  783. LOCAL lPrg, lC, lCpp, lH, lCh, lRc, a_
  784. LOCAL lTabs, lSubF, lSubP, cFolder, qItem, aFilter, cExt, cMask, cWrkFolder, cProjPath
  785. LOCAL nStart, nEnd, cSource, aDir, cProjTitle, aProjFiles
  786. LOCAL aOpenSrc := {}
  787. LOCAL aFolderSrc := {}
  788. LOCAL aProjSrc := {}
  789. LOCAL aProjs := {}
  790. LOCAL aPaths := {}
  791. IF empty( ::cOrigExpr := ::oUI:q_comboExpr:currentText() )
  792. RETURN Self
  793. ENDIF
  794. ::lListOnly := ::oUI:q_checkListOnly:isChecked()
  795. ::lMatchCase := ::oUI:q_checkMatchCase:isChecked()
  796. ::cReplWith := ::oUI:q_comboRepl:currentText()
  797. ::lRegEx := ::oUI:q_checkRegEx:isChecked()
  798. IF ::lRegEx
  799. ::compRegEx := hb_regExComp( ::cOrigExpr, ::lMatchCase )
  800. IF ! hb_isRegEx( ::compRegEx )
  801. MsgBox( "Error in Regular Expression" )
  802. RETURN Self
  803. ENDIF
  804. ENDIF
  805. cFolder := ::oUI:q_comboFolder:currentText()
  806. cWrkFolder := cFolder
  807. lTabs := ::oUI:q_checkOpenTabs:isChecked()
  808. lSubF := ::oUI:q_checkSubFolders:isChecked()
  809. lSubP := ::oUI:q_checkSubProjects:isChecked()
  810. /* Type of files */
  811. lPrg := ::oUi:q_checkPrg:isChecked()
  812. lC := ::oUI:q_checkC:isChecked()
  813. lCpp := ::oUI:q_checkCpp:isChecked()
  814. lH := ::oUI:q_checkH:isChecked()
  815. lCh := ::oUI:q_checkCh:isChecked()
  816. lRc := ::oUI:q_checkRc:isChecked() /* Conceptually it is now lText */
  817. aFilter := hbide_buildFilter( lPrg, lC, lCpp, lH, lCh, lRc )
  818. /* Process Open Tabs */
  819. IF lTabs
  820. FOR EACH a_ IN ::aTabs
  821. cSource := a_[ 2 ]:sourceFile
  822. IF hbide_isSourceOfType( cSource, aFilter )
  823. aadd( aOpenSrc, cSource )
  824. ENDIF
  825. NEXT
  826. ENDIF
  827. /* Process Folder */
  828. IF ::oUI:q_checkFolders:isChecked() .AND. ! empty( cFolder )
  829. hbide_fetchSubPaths( @aPaths, cFolder, ::oUI:q_checkSubFolders:isChecked() )
  830. FOR EACH cFolder IN aPaths
  831. FOR EACH cExt IN aFilter
  832. cMask := hbide_pathToOsPath( cFolder + cExt )
  833. aDir := directory( cMask )
  834. FOR EACH a_ IN aDir
  835. aadd( aFolderSrc, cFolder + a_[ 1 ] )
  836. NEXT
  837. NEXT
  838. NEXT
  839. ENDIF
  840. /* Process Projects */
  841. IF !empty( ::aItems )
  842. FOR EACH qItem IN ::aItems
  843. IF qItem:checkState() == 2
  844. aadd( aProjs, qItem:text() )
  845. ENDIF
  846. NEXT
  847. ENDIF
  848. IF !empty( aProjs )
  849. FOR EACH cProjTitle IN aProjs
  850. a_:= {}
  851. IF !empty( aProjFiles := ::oPM:getSourcesByProjectTitle( cProjTitle ) )
  852. cProjPath := ::oPM:getProjectPathFromTitle( cProjTitle )
  853. FOR EACH cSource IN aProjFiles
  854. IF hbide_isSourceOfType( cSource, aFilter )
  855. aadd( a_, hbide_syncProjPath( cProjPath, hbide_stripFilter( cSource ) ) )
  856. ENDIF
  857. NEXT
  858. ENDIF
  859. IF !empty( a_ )
  860. aadd( aProjSrc, { cProjTitle, a_ } )
  861. ENDIF
  862. NEXT
  863. ENDIF
  864. /* Supress Find button - user must not click it again */
  865. ::oUI:q_buttonFind:setEnabled( .f. )
  866. ::oUI:q_buttonStop:setEnabled( .t. )
  867. ::nSearched := 0
  868. ::nFounds := 0
  869. ::nMisses := 0
  870. ::oUI:q_labelStatus:setText( "Ready" )
  871. /* Fun Begins */
  872. ::showLog( LOG_SEPARATOR )
  873. ::showLog( LOG_FLAGS, "[Begins: " + dtoc( date() ) + "-" + time() + "][" + "Find Expression: " + ::cOrigExpr + "]" )
  874. ::showLog( LOG_FLAGS, hbide_getFlags( lPrg, lC, lCpp, lH, lCh, lRc, lTabs, lSubF, lSubP, ::lRegEx, ::lListOnly, ::lMatchCase ) )
  875. ::showLog( LOG_EMPTY )
  876. nStart := seconds()
  877. IF lTabs
  878. ::showLog( LOG_SECTION, "OpenTabs" )
  879. IF !empty( aOpenSrc )
  880. ::findInABunch( aOpenSrc )
  881. ELSE
  882. ::showLog( LOG_INFO, "No matching files found" )
  883. ENDIF
  884. ENDIF
  885. IF ::oUI:q_checkFolders:isChecked() .AND. ! empty( cFolder )
  886. ::showLog( LOG_SECTION, "Folders" )
  887. IF !empty( aFolderSrc )
  888. ::showLog( LOG_SECTION_ITEM, "Folder: " + cFolder )
  889. ::findInABunch( aFolderSrc )
  890. ELSE
  891. ::showLog( LOG_INFO, "No matching files found" )
  892. ENDIF
  893. ENDIF
  894. IF !empty( aProjs )
  895. ::showLog( LOG_SECTION, "Projects" )
  896. IF !empty( aProjSrc )
  897. FOR EACH a_ IN aProjSrc
  898. ::showLog( LOG_SECTION_ITEM, "Project: " + a_[ 1 ] )
  899. ::findInABunch( a_[ 2 ] )
  900. NEXT
  901. ELSE
  902. ::showLog( LOG_INFO, "No matching files found" )
  903. ENDIF
  904. ENDIF
  905. nEnd := seconds()
  906. ::showLog( LOG_EMPTY )
  907. ::showLog( LOG_FLAGS, "[Ends:" + dtoc( date() ) + "-" + time() + "-" + hb_ntos( nEnd - nStart ) + " Secs]" + ;
  908. "[Searched: " + hb_ntos( ::nSearched ) + "][Finds: " + hb_ntos( ::nFounds ) + "]" + ;
  909. "[Files not found: " + hb_ntos( ::nMisses ) + "]" )
  910. ::showLog( LOG_SEPARATOR )
  911. ::showLog( LOG_EMPTY )
  912. ::oUI:q_labelStatus:setText( "[ Time: " + hb_ntos( nEnd - nStart ) + " ] " + ;
  913. "[ Searched: " + hb_ntos( ::nSearched ) + " ] [ Finds: " + hb_ntos( ::nFounds ) + " ] " + ;
  914. "[ Files not found: " + hb_ntos( ::nMisses ) + " ]" )
  915. ::lStop := .f.
  916. ::oUI:q_buttonStop:setEnabled( .f. )
  917. ::oUI:q_buttonFind:setEnabled( .t. )
  918. IF ::nFounds > 0
  919. IF ascan( ::oINI:aFind, {|e| e == ::cOrigExpr } ) == 0
  920. hb_ains( ::oINI:aFind, 1, ::cOrigExpr, .t. )
  921. ::oUI:q_comboFolder:insertItem( 0, ::cOrigExpr )
  922. ENDIF
  923. ::oIde:cWrkFind := ::cOrigExpr
  924. ::oIde:cWrkFolderFind := cWrkFolder
  925. ENDIF
  926. RETURN Self
  927. /*----------------------------------------------------------------------*/
  928. METHOD IdeFindInFiles:findInABunch( aFiles )
  929. LOCAL s, cExpr, nLine, aLines, aBuffer, cLine, nNoMatch, aMatch, regEx
  930. nNoMatch := 0
  931. FOR EACH s IN aFiles
  932. IF ::lStop /* Stop button is pressed */
  933. ::showLog( LOG_EMPTY )
  934. ::showLog( LOG_TERMINATED )
  935. EXIT
  936. ENDIF
  937. aLines := {}
  938. s := hbide_pathToOSPath( s )
  939. IF hb_fileExists( s )
  940. ::nSearched++
  941. aBuffer := hb_ATokens( StrTran( hb_MemoRead( s ), Chr( 13 ) ), Chr( 10 ) )
  942. nLine := 0
  943. IF ::lRegEx
  944. regEx := ::compRegEx
  945. FOR EACH cLine IN aBuffer
  946. nLine++
  947. // exp, string, lMatchCase, lNewLine, nMaxMatch, nMatchWhich, lMatchOnly
  948. IF !empty( aMatch := hb_regExAll( regEx, cLine, ::lMatchCase, .F., 0, 1, .F. ) )
  949. aadd( aLines, { nLine, cLine, aMatch } )
  950. ENDIF
  951. NEXT
  952. ELSE
  953. IF ::lMatchCase
  954. cExpr := ::cOrigExpr
  955. FOR EACH cLine IN aBuffer
  956. nLine++
  957. IF cExpr $ cLine
  958. aadd( aLines, { nLine, cLine, NIL } )
  959. ENDIF
  960. NEXT
  961. ELSE
  962. cExpr := lower( ::cOrigExpr )
  963. FOR EACH cLine IN aBuffer
  964. nLine++
  965. IF cExpr $ lower( cLine )
  966. aadd( aLines, { nLine, cLine, NIL } )
  967. ENDIF
  968. NEXT
  969. ENDIF
  970. ENDIF
  971. IF len( aLines ) > 0
  972. ::showLog( LOG_FINDS, s, aLines )
  973. ::nFounds++
  974. ELSE
  975. nNoMatch++
  976. ENDIF
  977. ELSE
  978. ::showLog( LOG_MISSING, s )
  979. ::nMisses++
  980. ENDIF
  981. NEXT
  982. IF nNoMatch == len( aFiles )
  983. ::showLog( LOG_INFO, "Searched (" + hb_ntos( len( aFiles ) ) + ") files, no matches found" )
  984. ENDIF
  985. RETURN Self
  986. /*----------------------------------------------------------------------*/
  987. METHOD IdeFindInFiles:showLog( nType, cMsg, aLines )
  988. LOCAL a_, n, cPre, cPost, nWidth, cText, nB, cL, nL, cT, cExp, aM
  989. LOCAL qCursor, qResult
  990. qResult := ::oUI:q_editResults
  991. DEFAULT cMsg TO ""
  992. cMsg := hbide_convertHtmlDelimiters( cMsg )
  993. qCursor := ::oUI:q_editResults:textCursor()
  994. SWITCH nType
  995. CASE LOG_SEPARATOR
  996. qResult:append( F_BLACK + hbide_outputLine( "=", 68 ) + F_END )
  997. aadd( ::aInfo, { 0, NIL, NIL } )
  998. EXIT
  999. CASE LOG_FLAGS
  1000. qResult:append( F_BLACK + cMsg + F_END )
  1001. aadd( ::aInfo, { 0, NIL, NIL } )
  1002. EXIT
  1003. CASE LOG_INFO
  1004. qResult:append( F_INFO + "<i>" + cMsg + "</i>" + F_END )
  1005. aadd( ::aInfo, { 0, NIL, NIL } )
  1006. EXIT
  1007. CASE LOG_SECTION
  1008. qResult:append( F_SECTION + "<u>" + cMsg + "</u>" + F_END )
  1009. aadd( ::aInfo, { 0, NIL, NIL } )
  1010. EXIT
  1011. CASE LOG_SECTION_ITEM
  1012. qResult:append( F_SECTION_ITEM + cMsg + F_END )
  1013. aadd( ::aInfo, { 0, NIL, NIL } )
  1014. EXIT
  1015. CASE LOG_FINDS
  1016. cText := F_FILE + "<b>" + cMsg + " ( "+ hb_ntos( len( aLines ) ) + " )" + "</b>" + F_END
  1017. ::oUI:q_editResults:append( cText )
  1018. ::oUI:q_labelStatus:setText( cText )
  1019. aadd( ::aInfo, { -1, cMsg, NIL } )
  1020. n := 0
  1021. aeval( aLines, {|a_| n := max( n, a_[ 1 ] ) } )
  1022. nWidth := iif( n < 10, 1, iif( n < 100, 2, iif( n < 1000, 3, iif( n < 10000, 4, iif( n < 100000, 5, 7 ) ) ) ) )
  1023. IF ::lRegEx
  1024. FOR EACH a_ IN aLines
  1025. nL := a_[ 1 ]
  1026. aM := a_[ 3 ]
  1027. nB := aM[ 1, 2 ]
  1028. cL := hbide_buildResultLine( a_[ 2 ], aM )
  1029. cT := aM[ 1, 1 ]
  1030. qResult:append( F_BLACK + "&nbsp;&nbsp;&nbsp;(" + strzero( nL, nWidth ) + ")&nbsp;&nbsp;" + cL + F_END )
  1031. aadd( ::aInfo, { -2, cMsg, nL, nB, cT } )
  1032. qCursor:movePosition( QTextCursor_Down )
  1033. NEXT
  1034. ELSE
  1035. cExp := iif( ::lMatchCase, ::cOrigExpr, lower( ::cOrigExpr ) )
  1036. FOR EACH a_ IN aLines
  1037. nL := a_[ 1 ]
  1038. cL := a_[ 2 ]
  1039. //nB := at( cExp, cL )
  1040. nB := at( cExp, iif( ::lMatchCase, cL, lower( cL ) ) )
  1041. cPre := substr( cL, 1, nB - 1 )
  1042. cPost := substr( cL, nB + len( cExp ) )
  1043. cT := substr( cL, nB, len( cExp ) )
  1044. cL := hbide_convertHtmlDelimiters( cPre ) + F_SEARCH + "<b>" + hbide_convertHtmlDelimiters( cT ) + ;
  1045. "</b>" + F_END + hbide_convertHtmlDelimiters( cPost )
  1046. qResult:append( F_BLACK + "&nbsp;&nbsp;&nbsp;(" + strzero( nL, nWidth ) + ")&nbsp;&nbsp;" + cL + F_END )
  1047. // mode, source, line#, pos, slctn
  1048. aadd( ::aInfo, { -2, cMsg, nL, nB, cT } )
  1049. qCursor:movePosition( QTextCursor_Down )
  1050. NEXT
  1051. ENDIF
  1052. EXIT
  1053. CASE LOG_TERMINATED
  1054. qResult:append( F_RED + "---------------- Terminated ---------------" + F_END )
  1055. aadd( ::aInfo, { 0, NIL, NIL } )
  1056. EXIT
  1057. CASE LOG_MISSING
  1058. qResult:append( F_RED + cMsg + F_END )
  1059. aadd( ::aInfo, { 0, NIL, NIL } )
  1060. EXIT
  1061. CASE LOG_EMPTY
  1062. qResult:append( F_BLACK + " " + F_END )
  1063. aadd( ::aInfo, { 0, NIL, NIL } )
  1064. EXIT
  1065. ENDSWITCH
  1066. qCursor:movePosition( QTextCursor_Down )
  1067. ::oUI:q_editResults:setTextCursor( qCursor )
  1068. QApplication():processEvents()
  1069. RETURN Self
  1070. /*----------------------------------------------------------------------*/
  1071. STATIC FUNCTION hbide_buildResultLine( cLine, aM )
  1072. LOCAL cT, cR, i
  1073. FOR i := 1 TO len( aM )
  1074. cR := aM[ i, 1 ]
  1075. cT := replicate( chr( 255 ), len( aM[ i, 1 ] ) )
  1076. cLine := strtran( cLine, cR, cT, 1, 1 )
  1077. NEXT
  1078. FOR i := 1 TO len( aM )
  1079. cR := replicate( chr( 255 ), len( aM[ i, 1 ] ) )
  1080. cT := F_SEARCH + "<b>" + hbide_convertHtmlDelimiters( aM[ i, 1 ] ) + "</b>" + F_END
  1081. cLine := strtran( cLine, cR, cT, 1, 1 )
  1082. NEXT
  1083. RETURN cLine
  1084. /*----------------------------------------------------------------------*/
  1085. METHOD IdeFindInFiles:print()
  1086. LOCAL qDlg
  1087. qDlg := QPrintPreviewDialog( ::oUI )
  1088. qDlg:setWindowTitle( "Harbour-QT Preview Dialog" )
  1089. qDlg:connect( "paintRequested(QPrinter*)", {|p| ::paintRequested( p ) } )
  1090. qDlg:exec()
  1091. qDlg:disconnect( "paintRequested(QPrinter*)" )
  1092. RETURN self
  1093. /*----------------------------------------------------------------------*/
  1094. METHOD IdeFindInFiles:paintRequested( qPrinter )
  1095. ::oUI:q_editResults:print( qPrinter )
  1096. RETURN Self
  1097. /*----------------------------------------------------------------------*/
  1098. STATIC FUNCTION hbide_buildFilter( lPrg, lC, lCpp, lH, lCh, lTxt )
  1099. LOCAL aFilter := {}
  1100. LOCAL aExt
  1101. IF lPrg
  1102. aadd( aFilter, "*.prg" )
  1103. ENDIF
  1104. IF lC
  1105. aadd( aFilter, "*.c" )
  1106. ENDIF
  1107. IF lCpp
  1108. aadd( aFilter, "*.cpp" )
  1109. ENDIF
  1110. IF lh
  1111. aadd( aFilter, "*.h" )
  1112. ENDIF
  1113. IF lCh
  1114. aadd( aFilter, "*.ch" )
  1115. aadd( aFilter, "*.h" )
  1116. ENDIF
  1117. IF lTxt
  1118. aExt := hb_atokens( hbide_setIde():oINI:cTextFileExtensions, "," )
  1119. aeval( aExt, {|e| iif( empty( e ), NIL, aadd( aFilter, e ) ) } )
  1120. ENDIF
  1121. RETURN aFilter
  1122. /*----------------------------------------------------------------------*/
  1123. STATIC FUNCTION hbide_getFlags( lPrg, lC, lCpp, lH, lCh, lRc, lTabs, lSubF, lSubP, lRegEx, lListOnly, lMatchCase )
  1124. LOCAL s := ""
  1125. HB_SYMBOL_UNUSED( lTabs )
  1126. HB_SYMBOL_UNUSED( lSubF )
  1127. HB_SYMBOL_UNUSED( lSubP )
  1128. HB_SYMBOL_UNUSED( lListOnly )
  1129. s += "[.prg=" + L2S( lPrg ) + "]"
  1130. s += "[.c=" + L2S( lC ) + "]"
  1131. s += "[.cpp=" + L2S( lCpp ) + "]"
  1132. s += "[.h=" + L2S( lH ) + "]"
  1133. s += "[.ch=" + L2S( lCh ) + "]"
  1134. s += "[.rc=" + L2S( lRc ) + "]"
  1135. s += "[RegEx=" + L2S( lRegEx ) + "]"
  1136. s += "[Case=" + L2S( lMatchCase ) + "]"
  1137. RETURN s
  1138. /*----------------------------------------------------------------------*/
  1139. STATIC FUNCTION hbide_isSourceOfType( cSource, aFilter )
  1140. LOCAL cExt
  1141. hb_fNameSplit( cSource, , , @cExt )
  1142. cExt := lower( cExt )
  1143. RETURN ascan( aFilter, {|e| cExt $ e } ) > 0
  1144. /*----------------------------------------------------------------------*/