findwin.cpp 63 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629
  1. #include "findwin.h"
  2. #include "scintillaeditview.h"
  3. #include "ccnotepad.h"
  4. #include "progresswin.h"
  5. #include "doctypelistview.h"
  6. #include "filemanager.h"
  7. #include "ccnotepad.h"
  8. #include <QMimeDatabase>
  9. #include <QRadioButton>
  10. #include <QMessageBox>
  11. #include <QFileDialog>
  12. #include <functional>
  13. #include <BoostRegexSearch.h>
  14. #include <QDebug>
  15. enum TAB_TYPES {
  16. FIND_TYPE=0,
  17. RELPACE_TYPE,
  18. DIR_FIND_TYPE,
  19. MARK_TYPE,
  20. };
  21. const int MAX_RECORD_KEY_LENGTH = 20;
  22. FindWin::FindWin(QWidget *parent):QMainWindow(parent), m_editTabWidget(nullptr), m_isFindFirst(true), m_findHistory(nullptr), \
  23. pEditTemp(nullptr), m_curEditWin(nullptr), m_isStatic(false), m_isReverseFind(false), m_pMainPad(parent)
  24. {
  25. ui.setupUi(this);
  26. //默认值要与界面初始值一样。
  27. m_BackwardDir = false;
  28. m_matchWhole = false;
  29. m_matchCase = false;
  30. m_matchWrap = true;
  31. m_extend = false;
  32. m_searchMode = 1;
  33. m_re = false;
  34. m_cs = false;
  35. m_wo = false;
  36. m_wrap = true;
  37. m_forward = true;;//是否向前查找。注意如果向后,要为false
  38. m_extend = false;
  39. m_isFound = false;
  40. connect(ui.findModeRegularBt, &QRadioButton::toggled, this, &FindWin::slot_findModeRegularBtChange);
  41. connect(ui.replaceModeRegularBt, &QRadioButton::toggled, this, &FindWin::slot_replaceModeRegularBtChange);
  42. connect(ui.dealFileType, &QCheckBox::stateChanged, this,&FindWin::slot_dealFileTypeChange);
  43. connect(ui.skipDir, &QCheckBox::stateChanged, this, &FindWin::slot_skipDirChange);
  44. connect(ui.clearBt, &QAbstractButton::clicked, this, &FindWin::sign_clearResult);
  45. connect(ui.findClearBt, &QAbstractButton::clicked, this, &FindWin::sign_clearResult);
  46. connect(ui.findinfilesTab, &QTabWidget::currentChanged, this, &FindWin::slot_tabIndexChange);
  47. #if 0 //这样是无效的,记住一下,不删除,避免后面再做无用功
  48. Qt::WindowFlags m_flags = windowFlags();
  49. //这样使得窗口在上面,不至于总是到后面被挡住。
  50. #if defined (Q_MAC_OS)
  51. setWindowFlags(m_flags | Qt::WindowStaysOnTopHint);
  52. #endif
  53. #endif
  54. raise();
  55. setFocusPolicy(Qt::StrongFocus);
  56. setFocus();
  57. ui.findinfilesTab->setAttribute(Qt::WA_StyledBackground);
  58. ui.findComboBox->installEventFilter(this);
  59. }
  60. FindWin::~FindWin()
  61. {
  62. m_findHistory = nullptr;
  63. if (pEditTemp != nullptr)
  64. {
  65. delete pEditTemp;
  66. pEditTemp = nullptr;
  67. }
  68. }
  69. void FindWin::slot_tabIndexChange(int index)
  70. {
  71. TAB_TYPES type = (TAB_TYPES)index;
  72. if (RELPACE_TYPE == type)
  73. {
  74. ui.replaceTextBox->setFocus();
  75. if (ui.replaceTextBox->currentText().isEmpty() && !ui.findComboBox->currentText().isEmpty())
  76. {
  77. if (ui.findComboBox->currentText().size() < MAX_RECORD_KEY_LENGTH)
  78. {
  79. ui.replaceTextBox->setCurrentText(ui.findComboBox->currentText());
  80. }
  81. }
  82. }
  83. else if(FIND_TYPE == type)
  84. {
  85. ui.findComboBox->setFocus();
  86. if (ui.findComboBox->currentText().isEmpty() && !ui.replaceTextBox->currentText().isEmpty())
  87. {
  88. if (ui.replaceTextBox->currentText().size() < MAX_RECORD_KEY_LENGTH)
  89. {
  90. ui.findComboBox->setCurrentText(ui.replaceTextBox->currentText());
  91. }
  92. }
  93. }
  94. else if (DIR_FIND_TYPE == type)
  95. {
  96. ui.dirFindWhat->setFocus();
  97. }
  98. else if (MARK_TYPE == type)
  99. {
  100. ui.markTextBox->setFocus();
  101. }
  102. m_isFindFirst = true;
  103. if (m_findHistory->isEmpty())
  104. {
  105. return;
  106. }
  107. }
  108. void FindWin::slot_dealFileTypeChange(int state)
  109. {
  110. if (state == Qt::Checked)
  111. {
  112. ui.fileType->setEnabled(true);
  113. }
  114. else
  115. {
  116. ui.fileType->setEnabled(false);
  117. }
  118. }
  119. void FindWin::slot_skipDirChange(int state)
  120. {
  121. if (state == Qt::Checked)
  122. {
  123. ui.skipDirNames->setEnabled(true);
  124. }
  125. else
  126. {
  127. ui.skipDirNames->setEnabled(false);
  128. }
  129. }
  130. //自动调整当前窗口的状态,如果发生了变化,则需要认定为是首次查找
  131. QWidget* FindWin::autoAdjustCurrentEditWin()
  132. {
  133. QWidget* pw = m_editTabWidget->currentWidget();
  134. if (m_curEditWin != pw)
  135. {
  136. m_curEditWin = pw;
  137. m_isFindFirst = true;
  138. }
  139. return pw;
  140. }
  141. void FindWin::setCurrentTab(FindTabIndex index)
  142. {
  143. ui.findinfilesTab->setCurrentIndex(index);
  144. if (FIND_TAB == index)
  145. {
  146. ui.findComboBox->setFocus();
  147. }
  148. else if(REPLACE_TAB == index)
  149. {
  150. ui.replaceTextBox->setFocus();
  151. }
  152. raise();
  153. }
  154. void FindWin::setTabWidget(QTabWidget *editTabWidget)
  155. {
  156. m_editTabWidget = editTabWidget;
  157. }
  158. void FindWin::setFindText(QString &text)
  159. {
  160. ui.findComboBox->setEditText(text);
  161. addFindHistory(text);
  162. }
  163. void FindWin::setReplaceFindText(QString& text)
  164. {
  165. ui.replaceTextBox->setEditText(text);
  166. addFindHistory(text);
  167. }
  168. void FindWin::setDirFindText(QString& text)
  169. {
  170. ui.dirFindWhat->setEditText(text);
  171. addFindHistory(text);
  172. }
  173. void FindWin::disableReplace()
  174. {
  175. ui.tab_replace->setEnabled(false);
  176. }
  177. void FindWin::setFindHistory(QList<QString>* findHistory)
  178. {
  179. m_findHistory = findHistory;
  180. if ((m_findHistory != nullptr) && !m_findHistory->isEmpty())
  181. {
  182. ui.findComboBox->addItems(*m_findHistory);
  183. ui.replaceTextBox->addItems(*m_findHistory);
  184. ui.dirFindWhat->addItems(*m_findHistory);
  185. ui.markTextBox->addItems(*m_findHistory);
  186. ui.findComboBox->clearEditText();
  187. ui.replaceTextBox->clearEditText();
  188. ui.dirFindWhat->clearEditText();
  189. ui.markTextBox->clearEditText();
  190. }
  191. }
  192. //标记高亮所有word单词
  193. int FindWin::markAllWord(QString & word)
  194. {
  195. ui.markTextBox->setCurrentText(word);
  196. ui.findinfilesTab->setCurrentIndex(3);
  197. //发现中文在全词匹配下面不能匹配到单词。最好是英文全词匹配,中文不需要
  198. //但是好像没有一个现成的方法来判断word中的字符。暂时不做全词匹配
  199. ui.markMatchWholeBox->setChecked(false);
  200. ui.markMatchCaseBox->setChecked(true);
  201. return markAll();
  202. }
  203. //删除行首尾的空白字符
  204. void FindWin::removeLineHeadEndBlank(int mode)
  205. {
  206. QWidget* pw = autoAdjustCurrentEditWin();
  207. ScintillaEditView* pEdit = dynamic_cast<ScintillaEditView*>(pw);
  208. if (pEdit != nullptr)
  209. {
  210. if (pEdit->isReadOnly())
  211. {
  212. ui.statusbar->showMessage(tr("The ReadOnly document does not allow this operation."), 8000);
  213. QApplication::beep();
  214. return;
  215. }
  216. ui.findinfilesTab->setCurrentIndex(1);
  217. if (mode == 1)
  218. {
  219. ui.replaceTextBox->setCurrentText("^[ ]+");
  220. }
  221. else if (mode == 2)
  222. {
  223. ui.replaceTextBox->setCurrentText("[ ]+$");
  224. }
  225. ui.replaceWithBox->setText("");
  226. ui.replaceModeRegularBt->setChecked(true);
  227. m_isStatic = true;
  228. slot_replaceAll();
  229. m_isStatic = false;
  230. }
  231. }
  232. void FindWin::focusInEvent(QFocusEvent * ev)
  233. {
  234. QWidget::focusInEvent(ev);
  235. setWindowOpacity(1.0);
  236. }
  237. void FindWin::focusOutEvent(QFocusEvent * ev)
  238. {
  239. QWidget::focusOutEvent(ev);
  240. if (this->isActiveWindow())
  241. {
  242. //当前还是活动窗口,不设置透明
  243. return;
  244. }
  245. else
  246. {
  247. setWindowOpacity(0.6);
  248. //static int i = 0;
  249. //qDebug() << ++i;
  250. }
  251. }
  252. bool FindWin::eventFilter(QObject* watched, QEvent *event)
  253. {
  254. if (watched == ui.findComboBox)
  255. {
  256. if (event->type() == QEvent::KeyPress)
  257. {
  258. QKeyEvent *ke = static_cast<QKeyEvent*>(event);
  259. if (ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return)
  260. {
  261. emit ui.findTextNext->click();
  262. return true; //该事件已经被处理
  263. }
  264. return false;
  265. }
  266. else
  267. {
  268. return false;
  269. }
  270. }
  271. return QWidget::eventFilter(watched, event); // 最后将事件交给上层对话框
  272. }
  273. //从ui读取参数配置到成员变量
  274. void FindWin::updateParameterFromUI()
  275. {
  276. bool extend = false;
  277. if (ui.findinfilesTab->currentIndex() == 0)
  278. {
  279. int searchMode = 0;
  280. if (ui.findModeNormalBt->isChecked())
  281. {
  282. searchMode = 1;
  283. extend = false;
  284. }
  285. else if (ui.findModeRegularBt->isChecked())
  286. {
  287. searchMode = 2;
  288. extend = false;
  289. }
  290. else if (ui.findModeExtendBt->isChecked())
  291. {
  292. searchMode = 1;
  293. extend = true;
  294. }
  295. if (m_searchMode != searchMode)
  296. {
  297. m_searchMode = searchMode;
  298. m_isFindFirst = true;
  299. }
  300. if (m_expr != ui.findComboBox->currentText())
  301. {
  302. m_expr = ui.findComboBox->currentText();
  303. m_isFindFirst = true;
  304. }
  305. if (m_BackwardDir != ui.findBackwardBox->isChecked())
  306. {
  307. m_BackwardDir = ui.findBackwardBox->isChecked();
  308. m_isFindFirst = true;
  309. }
  310. if (m_matchWhole != ui.findMatchWholeBox->isChecked())
  311. {
  312. m_matchWhole = ui.findMatchWholeBox->isChecked();
  313. m_isFindFirst = true;
  314. }
  315. if (m_matchCase != ui.findMatchCaseBox->isChecked())
  316. {
  317. m_matchCase = ui.findMatchCaseBox->isChecked();
  318. m_isFindFirst = true;
  319. }
  320. if (m_matchWrap != ui.findWrapBox->isChecked())
  321. {
  322. m_matchWrap = ui.findWrapBox->isChecked();
  323. m_isFindFirst = true;
  324. }
  325. }
  326. else if (ui.findinfilesTab->currentIndex() == 1)
  327. {
  328. int searchMode = 0;
  329. if (ui.replaceModeNormalBox->isChecked())
  330. {
  331. searchMode = 1;
  332. extend = false;
  333. }
  334. else if (ui.replaceModeRegularBt->isChecked())
  335. {
  336. searchMode = 2;
  337. extend = false;
  338. }
  339. else if (ui.replaceModeExtendBox->isChecked())
  340. {
  341. searchMode = 1;
  342. extend = true;
  343. }
  344. if (m_searchMode != searchMode)
  345. {
  346. m_searchMode = searchMode;
  347. m_isFindFirst = true;
  348. }
  349. if (m_expr != ui.replaceTextBox->currentText())
  350. {
  351. m_expr = ui.replaceTextBox->currentText();
  352. m_isFindFirst = true;
  353. }
  354. if (m_replaceWithText != ui.replaceWithBox->text())
  355. {
  356. m_replaceWithText = ui.replaceWithBox->text();
  357. m_isFindFirst = true;
  358. }
  359. if (m_BackwardDir != ui.replaceBackwardBox->isChecked())
  360. {
  361. m_BackwardDir = ui.replaceBackwardBox->isChecked();
  362. m_isFindFirst = true;
  363. }
  364. if (m_matchWhole != ui.replaceMatchWholeBox->isChecked())
  365. {
  366. m_matchWhole = ui.replaceMatchWholeBox->isChecked();
  367. m_isFindFirst = true;
  368. }
  369. if (m_matchCase != ui.replaceMatchCaseBox->isChecked())
  370. {
  371. m_matchCase = ui.replaceMatchCaseBox->isChecked();
  372. m_isFindFirst = true;
  373. }
  374. if (m_matchWrap != ui.replaceWrapBox->isChecked())
  375. {
  376. m_matchWrap = ui.replaceWrapBox->isChecked();
  377. m_isFindFirst = true;
  378. }
  379. }
  380. else if (ui.findinfilesTab->currentIndex() == 2)
  381. {
  382. int searchMode = 0;
  383. if (ui.dirFindModeNormalBox->isChecked())
  384. {
  385. searchMode = 1;
  386. extend = false;
  387. }
  388. else if (ui.dirFindModeRegularBt->isChecked())
  389. {
  390. searchMode = 2;
  391. extend = false;
  392. }
  393. else if (ui.dirFindModeExtendBox->isChecked())
  394. {
  395. searchMode = 1;
  396. extend = true;
  397. }
  398. if (m_searchMode != searchMode)
  399. {
  400. m_searchMode = searchMode;
  401. m_isFindFirst = true;
  402. }
  403. if (m_expr != ui.dirFindWhat->currentText())
  404. {
  405. m_expr = ui.dirFindWhat->currentText();
  406. m_isFindFirst = true;
  407. }
  408. if (m_replaceWithText != ui.dirReplaceWhat->text())
  409. {
  410. m_replaceWithText = ui.dirReplaceWhat->text();
  411. m_isFindFirst = true;
  412. }
  413. m_BackwardDir = false;
  414. if (m_matchWhole != ui.dirFindMatchWholeBox->isChecked())
  415. {
  416. m_matchWhole = ui.dirFindMatchWholeBox->isChecked();
  417. m_isFindFirst = true;
  418. }
  419. if (m_matchCase != ui.dirFindMatchCaseBox->isChecked())
  420. {
  421. m_matchCase = ui.dirFindMatchCaseBox->isChecked();
  422. m_isFindFirst = true;
  423. }
  424. m_matchWrap = true;
  425. }
  426. else if (ui.findinfilesTab->currentIndex() == 3)
  427. {
  428. int searchMode = 0;
  429. if (ui.markModeNormalBox->isChecked())
  430. {
  431. searchMode = 1;
  432. extend = false;
  433. }
  434. else if (ui.markModeRegularBt->isChecked())
  435. {
  436. searchMode = 2;
  437. extend = false;
  438. }
  439. else if (ui.markModeExtendBox->isChecked())
  440. {
  441. searchMode = 1;
  442. extend = true;
  443. }
  444. if (m_searchMode != searchMode)
  445. {
  446. m_searchMode = searchMode;
  447. m_isFindFirst = true;
  448. }
  449. if (m_expr != ui.markTextBox->currentText())
  450. {
  451. m_expr = ui.markTextBox->currentText();
  452. m_isFindFirst = true;
  453. }
  454. m_BackwardDir = false;
  455. if (m_matchWhole != ui.markMatchWholeBox->isChecked())
  456. {
  457. m_matchWhole = ui.markMatchWholeBox->isChecked();
  458. m_isFindFirst = true;
  459. }
  460. if (m_matchCase != ui.markMatchCaseBox->isChecked())
  461. {
  462. m_matchCase = ui.markMatchCaseBox->isChecked();
  463. m_isFindFirst = true;
  464. }
  465. m_matchWrap = true;
  466. }
  467. m_re = ((m_searchMode == 2) ? true : false);
  468. if (m_cs != m_matchCase)
  469. {
  470. m_cs = m_matchCase;
  471. }
  472. if (m_wo != m_matchWhole)
  473. {
  474. m_wo = m_matchWhole;
  475. }
  476. if (m_wrap != m_matchWrap)
  477. {
  478. m_wrap = m_matchWrap;
  479. }
  480. if (m_extend != extend)
  481. {
  482. m_extend = extend;
  483. m_isFindFirst = true;
  484. }
  485. //本来的m_BackwardDir只控制是否勾选反向
  486. m_forward = !m_BackwardDir;
  487. //m_isReverseFind 控制是否还需要反向一直,只在查找前一个生效,只影响查找界面
  488. if (ui.findinfilesTab->currentIndex() == 0)
  489. {
  490. m_forward = (m_isReverseFind ? !m_forward : m_forward);
  491. }
  492. }
  493. void FindWin::addFindHistory(QString &text)
  494. {
  495. //太长会导致看起来很杂乱,也不记录
  496. if (text.isEmpty() || text.size() >= MAX_RECORD_KEY_LENGTH)
  497. {
  498. return;
  499. }
  500. if ((m_findHistory != nullptr) && (-1 == m_findHistory->indexOf(text)))
  501. {
  502. m_findHistory->push_front(text);
  503. if (m_findHistory->size() >= 15)
  504. {
  505. m_findHistory->takeLast();
  506. }
  507. ui.findComboBox->insertItem(0, text);
  508. ui.replaceTextBox->insertItem(0, text);
  509. ui.dirFindWhat->insertItem(0,text);
  510. ui.markTextBox->insertItem(0, text);
  511. }
  512. }
  513. //检查是否是第一次查找,凡是参数变化了,则认定为是第一次查找。
  514. //因为查找分firstFirst和firstNext,则是qscint特性决定的。所以正确识别第一次查找是必要的
  515. bool FindWin::isFirstFind()
  516. {
  517. return m_isFindFirst;
  518. }
  519. //const QChar *constData() const
  520. bool readBase(const QChar * str, int * value, int base, int size)
  521. {
  522. int i = 0, temp = 0;
  523. *value = 0;
  524. QChar max = QChar(QChar('0').digitValue() + base - 1);
  525. QChar current;
  526. while (i < size)
  527. {
  528. current = str[i];
  529. if (current >= 'A')
  530. {
  531. current = current.digitValue() & 0xdf;
  532. current = current.digitValue() - ('A' - '0' - 10);
  533. }
  534. else if (current > '9')
  535. return false;
  536. if (current >= '0' && current <= max)
  537. {
  538. temp *= base;
  539. temp += (current.digitValue() - '0');
  540. }
  541. else
  542. {
  543. return false;
  544. }
  545. ++i;
  546. }
  547. *value = temp;
  548. return true;
  549. }
  550. int convertExtendedToString(QString& query, QString &result)
  551. { //query may equal to result, since it always gets smaller
  552. int i = 0, j = 0;
  553. int length = query.length();
  554. int charLeft = length;
  555. QChar current;
  556. while (i < length)
  557. { //because the backslash escape quences always reduce the size of the generic_string, no overflow checks have to be made for target, assuming parameters are correct
  558. current = query.at(i);
  559. --charLeft;
  560. if (current == '\\' && charLeft)
  561. { //possible escape sequence
  562. ++i;
  563. --charLeft;
  564. current = query.at(i);
  565. switch (current.toLatin1())
  566. {
  567. case 'r':
  568. result[j] = '\r';
  569. break;
  570. case 'n':
  571. result[j] = '\n';
  572. break;
  573. case '0':
  574. result[j] = '\0';
  575. break;
  576. case 't':
  577. result[j] = '\t';
  578. break;
  579. case '\\':
  580. result[j] = '\\';
  581. break;
  582. case 'b':
  583. case 'd':
  584. case 'o':
  585. case 'x':
  586. case 'u':
  587. {
  588. int size = 0, base = 0;
  589. if (current == 'b')
  590. { //11111111
  591. size = 8, base = 2;
  592. }
  593. else if (current == 'o')
  594. { //377
  595. size = 3, base = 8;
  596. }
  597. else if (current == 'd')
  598. { //255
  599. size = 3, base = 10;
  600. }
  601. else if (current == 'x')
  602. { //0xFF
  603. size = 2, base = 16;
  604. }
  605. else if (current == 'u')
  606. { //0xCDCD
  607. size = 4, base = 16;
  608. }
  609. if (charLeft >= size)
  610. {
  611. int res = 0;
  612. if (readBase(query.constData() + (i + 1), &res, base, size))
  613. {
  614. result[j] = QChar(res);
  615. i += size;
  616. break;
  617. }
  618. }
  619. //not enough chars to make parameter, use default method as fallback
  620. }
  621. default:
  622. { //unknown sequence, treat as regular text
  623. result[j] = '\\';
  624. ++j;
  625. result[j] = current;
  626. break;
  627. }
  628. }
  629. }
  630. else
  631. {
  632. result[j] = query[i];
  633. }
  634. ++i;
  635. ++j;
  636. }
  637. return j;
  638. }
  639. void FindWin::showCallTip(QsciScintilla* pEdit, int pos)
  640. {
  641. QString zeroString(tr("find-regex-zero-length-match"));
  642. QByteArray bytes = zeroString.toUtf8();
  643. bytes.append('\0');
  644. /*int size = bytes.size();
  645. char* newStr = new char[size + 1];
  646. memcpy(newStr, bytes.data(), size);
  647. newStr[bytes.size()] = '\0';*/
  648. pEdit->SendScintilla(SCI_CALLTIPSHOW, pos, (void*)(bytes.data()));
  649. /*delete[]newStr;*/
  650. }
  651. //删除空白行
  652. void FindWin::removeEmptyLine(bool isBlankContained)
  653. {
  654. QWidget* pw = autoAdjustCurrentEditWin();
  655. ScintillaEditView* pEdit = dynamic_cast<ScintillaEditView*>(pw);
  656. if (pEdit != nullptr)
  657. {
  658. if (pEdit->isReadOnly())
  659. {
  660. ui.statusbar->showMessage(tr("The ReadOnly document does not allow this operation."), 8000);
  661. QApplication::beep();
  662. return;
  663. }
  664. ui.findinfilesTab->setCurrentIndex(1);
  665. if (isBlankContained)
  666. {
  667. ui.replaceTextBox->setCurrentText("^[\\t ]*$(\\r\\n|\\r|\\n)");
  668. }
  669. else
  670. {
  671. ui.replaceTextBox->setCurrentText("^$(\\r\\n|\\r|\\n)");
  672. }
  673. ui.replaceWithBox->setText("");
  674. ui.replaceModeRegularBt->setChecked(true);
  675. m_isStatic = true;
  676. slot_replaceAll();
  677. m_isStatic = false;
  678. }
  679. }
  680. void FindWin::findNext()
  681. {
  682. slot_findNext();
  683. }
  684. void FindWin::findPrev()
  685. {
  686. slot_findPrev();
  687. }
  688. /*处理查找时零长的问题。一定要处理,否则会死循环,因为每次都在原地查找。
  689. * 就是把下次查找的startpos往前一个,否则每次都从这个startpos找到自己
  690. */
  691. void FindWin::dealWithZeroFound(QsciScintilla* pEdit)
  692. {
  693. FindState& state = pEdit->getLastFindState();
  694. if (state.targstart == state.targend)
  695. {
  696. //强行加1,否则每次查找总是在同一个地方。
  697. state.startpos++;
  698. }
  699. }
  700. //调整光标变化后,查找位置需要调整的情况
  701. void FindWin::adjustSearchStartPosChange(QsciScintilla* pEdit)
  702. {
  703. int caretPos = pEdit->SendScintilla(SCI_GETCURRENTPOS);
  704. FindState& state = pEdit->getLastFindState();
  705. if (state.targend != caretPos)
  706. {
  707. state.startpos = caretPos;
  708. }
  709. }
  710. /*处理查找时零长的问题。一定要处理,否则会死循环,因为每次都在原地查找。
  711. * 就是把下次查找的startpos往前一个,否则每次都从这个startpos找到自己
  712. * 和dealWithZeroFound是一样的,就是要显示消息而已
  713. */
  714. void FindWin::dealWithZeroFoundShowTip(QsciScintilla* pEdit, bool isShowTip)
  715. {
  716. if (!isShowTip)
  717. {
  718. return dealWithZeroFound(pEdit);
  719. }
  720. FindState& state = pEdit->getLastFindState();
  721. //int linpos = pEdit->SendScintilla(SCI_POSITIONFROMLINE, state.linenum);
  722. int line = 0;
  723. int indexStart = 0;
  724. int indexEnd = 0;
  725. pEdit->lineIndexFromPosition(state.targstart, &line, &indexStart);
  726. pEdit->lineIndexFromPosition(state.targend, &line, &indexEnd);
  727. ui.statusbar->showMessage(tr("target info linenum %1 pos is %2 - %3").arg(state.linenum + 1).arg(indexStart).arg(indexEnd), 8000);
  728. if (state.targstart == state.targend)
  729. {
  730. //强行加1,否则每次查找总是在同一个地方。
  731. //这里有个问题,如果是反向查找,则应该是pos减去1才对。
  732. //不过只有在正则查找才会出现零长,而正则查找时我们不允许反向查找。反向是回调的。
  733. state.startpos++;
  734. showCallTip(pEdit, state.targstart);
  735. }
  736. }
  737. void FindWin::dofindNext()
  738. {
  739. if (ui.findComboBox->currentText().isEmpty())
  740. {
  741. ui.statusbar->showMessage(tr("what find is null !"), 8000);
  742. QApplication::beep();
  743. return;
  744. }
  745. updateParameterFromUI();
  746. QWidget* pw = autoAdjustCurrentEditWin();
  747. QsciScintilla* pEdit = dynamic_cast<QsciScintilla*>(pw);
  748. //第一次查找
  749. if (isFirstFind())
  750. {
  751. if (pEdit != nullptr)
  752. {
  753. QString whatFind = ui.findComboBox->currentText();
  754. addFindHistory(whatFind);
  755. if (m_extend)
  756. {
  757. QString extendFind;
  758. convertExtendedToString(whatFind, extendFind);
  759. whatFind = extendFind;
  760. }
  761. if (!pEdit->findFirst(whatFind, m_re, m_cs, m_wo, m_wrap, m_forward, FINDNEXTTYPE_FINDNEXT, -1, -1, true, false, false))
  762. {
  763. ui.statusbar->showMessage(tr("cant't find text \'%1\'").arg(m_expr), 8000);
  764. QApplication::beep();
  765. m_isFindFirst = true;
  766. }
  767. else
  768. {
  769. m_isFindFirst = false;
  770. dealWithZeroFoundShowTip(pEdit);
  771. }
  772. }
  773. }
  774. else
  775. {
  776. //查找下一个
  777. if (pEdit != nullptr)
  778. {
  779. adjustSearchStartPosChange(pEdit);
  780. if (!pEdit->findNext())
  781. {
  782. ui.statusbar->showMessage(tr("no more find text \'%1\'").arg(m_expr), 8000);
  783. m_isFindFirst = true;
  784. QApplication::beep();
  785. }
  786. else
  787. {
  788. dealWithZeroFoundShowTip(pEdit);
  789. }
  790. }
  791. }
  792. }
  793. //一旦修改条件发生变化,则认定为第一次查找
  794. void FindWin::slot_findNext()
  795. {
  796. if (m_isReverseFind)
  797. {
  798. m_isReverseFind = false;
  799. m_isFindFirst = true;
  800. }
  801. dofindNext();
  802. }
  803. void FindWin::setFindBackward(bool isBackward)
  804. {
  805. if (ui.findBackwardBox->isChecked() != isBackward)
  806. {
  807. ui.findBackwardBox->setChecked(isBackward);
  808. }
  809. }
  810. void FindWin::slot_findPrev()
  811. {
  812. if (!m_isReverseFind)
  813. {
  814. m_isReverseFind = true;
  815. m_isFindFirst = true;
  816. }
  817. dofindNext();
  818. }
  819. //查找计数
  820. void FindWin::slot_findCount()
  821. {
  822. if (ui.findComboBox->currentText().isEmpty())
  823. {
  824. ui.statusbar->showMessage(tr("what find is null !"), 8000);
  825. QApplication::beep();
  826. return;
  827. }
  828. QWidget* pw = autoAdjustCurrentEditWin();
  829. ScintillaEditView* pEdit = dynamic_cast<ScintillaEditView*>(pw);
  830. if (pEdit != nullptr)
  831. {
  832. if (pEdit->isReadOnly())
  833. {
  834. ui.statusbar->showMessage(tr("The ReadOnly document does not allow this operation."), 8000);
  835. QApplication::beep();
  836. return;
  837. }
  838. updateParameterFromUI();
  839. int srcPostion = pEdit->execute(SCI_GETCURRENTPOS);
  840. int firstDisLineNum = pEdit->execute(SCI_GETFIRSTVISIBLELINE);
  841. int countNums = 0;
  842. //无条件进行第一次查找,从0行0列开始查找,而且不回环。如果没有找到,则替换完毕
  843. QString whatFind = ui.findComboBox->currentText();
  844. //这里不能直接修改results.findText的值,该值在外部显示还需要。如果修改则会显示紊乱
  845. if (m_extend)
  846. {
  847. QString extendFind;
  848. convertExtendedToString(whatFind, extendFind);
  849. whatFind = extendFind;
  850. }
  851. //这里的forward一定要是true。回环一定是false
  852. if (!pEdit->findFirst(whatFind, m_re, m_cs, m_wo, false, true, FINDNEXTTYPE_FINDNEXT, 0, 0,false))
  853. {
  854. ui.statusbar->showMessage(tr("count %1 times with \'%2\'").arg(countNums).arg(m_expr), 8000);
  855. QApplication::beep();
  856. m_isFindFirst = true;
  857. return;
  858. }
  859. else
  860. {
  861. dealWithZeroFound(pEdit);
  862. }
  863. ++countNums;
  864. //找到了,增加计数
  865. while (pEdit->findNext())
  866. {
  867. ++countNums;
  868. dealWithZeroFound(pEdit);
  869. }
  870. pEdit->execute(SCI_GOTOPOS, srcPostion);
  871. pEdit->execute(SCI_SETFIRSTVISIBLELINE, firstDisLineNum);
  872. pEdit->execute(SCI_SETXOFFSET, 0);
  873. //全部替换后,下次查找,必须算第一次查找
  874. m_isFindFirst = true;
  875. ui.statusbar->showMessage(tr("count %1 times with \'%2\'").arg(countNums).arg(m_expr), 8000);
  876. }
  877. else
  878. {
  879. ui.statusbar->showMessage(tr("The mode of the current document does not allow this operation."), 8000);
  880. QApplication::beep();
  881. }
  882. }
  883. //去掉行尾的\n\r符号
  884. static QString trimmedEnd(QString lineText)
  885. {
  886. if (lineText.endsWith("\r\n"))
  887. {
  888. return lineText.mid(0, lineText.length()-2);
  889. }
  890. if (lineText.endsWith("\r"))
  891. {
  892. return lineText.mid(0, lineText.length()-1);
  893. }
  894. if (lineText.endsWith("\n"))
  895. {
  896. return lineText.mid(0, lineText.length()-1);
  897. }
  898. return lineText;
  899. }
  900. void FindWin::addCurFindRecord(ScintillaEditView* pEdit, FindRecords& recordRet,bool isMark)
  901. {
  902. FindRecord aRecord;
  903. //看了源码,当前查找到的结果,是会被选中的。所以可通过选中范围,来记录当前被查找中的结果
  904. //光标在选择词的尾部下一个位置
  905. #if 0
  906. aRecord.pos = pEdit->execute(SCI_GETSELECTIONSTART);
  907. aRecord.end = pEdit->execute(SCI_GETSELECTIONEND);
  908. #endif
  909. //加速
  910. FindState& state = pEdit->getLastFindState();
  911. aRecord.pos = state.targstart;
  912. aRecord.end = state.targend;
  913. //mark模式不需要这么多信息,可直接返回
  914. if (!isMark)
  915. {
  916. aRecord.lineNum = pEdit->execute(SCI_LINEFROMPOSITION, aRecord.pos);
  917. aRecord.lineStartPos = pEdit->execute(SCI_POSITIONFROMLINE, aRecord.lineNum);
  918. int lineLens = pEdit->execute(SCI_LINELENGTH, aRecord.lineNum);
  919. if (lineLens <= 0)
  920. {
  921. return;
  922. }
  923. char* lineText = new char[lineLens + 1];
  924. memset(lineText, 0, lineLens + 1);
  925. //这里有个bug,是qscint的,查找最后一行,会漏掉最后一个字符
  926. pEdit->execute(SCI_GETLINE, aRecord.lineNum, reinterpret_cast<sptr_t>(lineText));
  927. //务必要去掉行位的换行,否则显示结果列表会显示换行
  928. aRecord.lineContents = trimmedEnd(QString(lineText));
  929. delete[]lineText;
  930. }
  931. recordRet.records.append(aRecord);
  932. }
  933. //在后台查找
  934. int FindWin::findAtBack(QString keyword)
  935. {
  936. this->setCurrentTab(FIND_TAB);
  937. ui.findComboBox->setCurrentText(keyword);
  938. ui.findBackwardBox->setChecked(false);
  939. ui.findMatchCaseBox->setChecked(true);
  940. ui.findWrapBox->setChecked(false);
  941. ui.findMatchWholeBox->setChecked(false);
  942. ui.findModeNormalBt->setChecked(true);
  943. m_isStatic = true;
  944. int times = findAllInCurDoc();
  945. m_isStatic = false;
  946. return times;
  947. }
  948. //在后台替换
  949. int FindWin::replaceAtBack(QStringList& keyword, QStringList& replace)
  950. {
  951. assert(keyword.size() == replace.size());
  952. this->setCurrentTab(REPLACE_TAB);
  953. QWidget* pw = autoAdjustCurrentEditWin();
  954. ScintillaEditView* pEdit = dynamic_cast<ScintillaEditView*>(pw);
  955. if (pEdit != nullptr)
  956. {
  957. if (pEdit->isReadOnly())
  958. {
  959. ui.statusbar->showMessage(tr("The ReadOnly document does not allow replacement."), 8000);
  960. QApplication::beep();
  961. return 0;
  962. }
  963. }
  964. ui.replaceBackwardBox->setChecked(false);
  965. ui.replaceMatchWholeBox->setChecked(false);
  966. ui.replaceMatchCaseBox->setChecked(true);
  967. ui.replaceWrapBox->setChecked(false);
  968. ui.replaceModeNormalBox->setChecked(true);
  969. m_isStatic = true;
  970. int times = 0;
  971. pEdit->execute(SCI_BEGINUNDOACTION);
  972. ProgressWin* loadFileProcessWin = new ProgressWin(this);
  973. loadFileProcessWin->setWindowModality(Qt::WindowModal);
  974. loadFileProcessWin->info(tr("total %1 keyword, please wait ...").arg(keyword.size()));
  975. loadFileProcessWin->setTotalSteps(keyword.size());
  976. loadFileProcessWin->show();
  977. for (int i = 0; i < keyword.size(); ++i)
  978. {
  979. if (loadFileProcessWin->isCancel())
  980. {
  981. break;
  982. }
  983. ui.replaceTextBox->setCurrentText(keyword.at(i));
  984. ui.replaceWithBox->setText(replace.at(i));
  985. updateParameterFromUI();
  986. QString whatFind = ui.replaceTextBox->currentText();
  987. QString replaceText = ui.replaceWithBox->text();
  988. times += doReplaceAll(pEdit, whatFind, replaceText, false);
  989. loadFileProcessWin->moveStep();
  990. QCoreApplication::processEvents();
  991. }
  992. delete loadFileProcessWin;
  993. pEdit->execute(SCI_ENDUNDOACTION);
  994. m_isStatic = false;
  995. return times;
  996. }
  997. int FindWin::findAllInCurDoc()
  998. {
  999. if (ui.findComboBox->currentText().isEmpty())
  1000. {
  1001. ui.statusbar->showMessage(tr("what find is null !"), 8000);
  1002. QApplication::beep();
  1003. return 0;
  1004. }
  1005. QWidget* pw = autoAdjustCurrentEditWin();
  1006. ScintillaEditView* pEdit = dynamic_cast<ScintillaEditView*>(pw);
  1007. if (pEdit != nullptr)
  1008. {
  1009. if (pEdit->isReadOnly())
  1010. {
  1011. if (!m_isStatic)
  1012. {
  1013. ui.statusbar->showMessage(tr("The ReadOnly document does not allow this operation."), 8000);
  1014. }
  1015. QApplication::beep();
  1016. return 0;
  1017. }
  1018. FindRecords results;
  1019. results.pEdit = pEdit;
  1020. results.findFilePath = pw->property("filePath").toString();
  1021. updateParameterFromUI();
  1022. int srcPostion = pEdit->execute(SCI_GETCURRENTPOS);
  1023. int firstDisLineNum = pEdit->execute(SCI_GETFIRSTVISIBLELINE);
  1024. int replaceNums = 0;
  1025. //无条件进行第一次查找,从0行0列开始查找,而且不回环。如果没有找到,则替换完毕
  1026. QString whatFind = ui.findComboBox->currentText();
  1027. results.findText = whatFind;
  1028. //这里不能直接修改results.findText的值,该值在外部显示还需要。如果修改则会显示紊乱
  1029. if (m_extend)
  1030. {
  1031. QString extendFind;
  1032. convertExtendedToString(whatFind, extendFind);
  1033. whatFind = extendFind;
  1034. }
  1035. //这里的forward一定要是true。回环一定是false
  1036. if (!pEdit->findFirst(whatFind, m_re, m_cs, m_wo, false, true, FINDNEXTTYPE_FINDNEXT, 0, 0))
  1037. {
  1038. ui.statusbar->showMessage(tr("cant't find text \'%1\'").arg(m_expr), 8000);
  1039. if (!m_isStatic)
  1040. {
  1041. QApplication::beep();
  1042. emit sign_findAllInCurDoc(&results);
  1043. }
  1044. m_isFindFirst = true;
  1045. return 0;
  1046. }
  1047. else
  1048. {
  1049. dealWithZeroFound(pEdit);
  1050. }
  1051. addCurFindRecord(pEdit, results);
  1052. ++replaceNums;
  1053. //找到了,把结果收集起来
  1054. while (pEdit->findNext())
  1055. {
  1056. addCurFindRecord(pEdit, results);
  1057. ++replaceNums;
  1058. dealWithZeroFound(pEdit);
  1059. }
  1060. pEdit->execute(SCI_GOTOPOS, srcPostion);
  1061. pEdit->execute(SCI_SETFIRSTVISIBLELINE, firstDisLineNum);
  1062. pEdit->execute(SCI_SETXOFFSET, 0);
  1063. //全部替换后,下次查找,必须算第一次查找
  1064. m_isFindFirst = true;
  1065. ui.statusbar->showMessage(tr("find finished, total %1 found!").arg(replaceNums), 10000);
  1066. emit sign_findAllInCurDoc(&results);
  1067. return replaceNums;
  1068. }
  1069. else
  1070. {
  1071. if (!m_isStatic)
  1072. {
  1073. ui.statusbar->showMessage(tr("The mode of the current document does not allow this operation."), 8000);
  1074. QApplication::beep();
  1075. }
  1076. }
  1077. return 0;
  1078. }
  1079. void FindWin::slot_findAllInCurDoc()
  1080. {
  1081. findAllInCurDoc();
  1082. }
  1083. void FindWin::slot_findAllInOpenDoc()
  1084. {
  1085. if (ui.findComboBox->currentText().isEmpty())
  1086. {
  1087. ui.statusbar->showMessage(tr("what find is null !"), 8000);
  1088. QApplication::beep();
  1089. return;
  1090. }
  1091. QString whatFind = ui.findComboBox->currentText();
  1092. QString originWhatFine = whatFind;
  1093. if (m_extend)
  1094. {
  1095. QString extendFind;
  1096. convertExtendedToString(whatFind, extendFind);
  1097. whatFind = extendFind;
  1098. }
  1099. int replaceNums = 0;
  1100. QVector<FindRecords*>* allOpenFileRecord = new QVector<FindRecords*>();
  1101. for (int i = 0; i < m_editTabWidget->count(); ++i)
  1102. {
  1103. QWidget* pw = m_editTabWidget->widget(i);
  1104. ScintillaEditView* pEdit = dynamic_cast<ScintillaEditView*>(pw);
  1105. if (pEdit != nullptr)
  1106. {
  1107. if (pEdit->isReadOnly())
  1108. {
  1109. continue;
  1110. }
  1111. FindRecords* results = new FindRecords();
  1112. results->pEdit = pEdit;
  1113. results->findFilePath = pw->property("filePath").toString();
  1114. updateParameterFromUI();
  1115. //无条件进行第一次查找,从0行0列开始查找,而且不回环。如果没有找到,则替换完毕
  1116. //results->findText要是有原来的值,因为扩展模式下\r\n不会转义,直接输出会换行显示
  1117. results->findText = originWhatFine;
  1118. if (!pEdit->findFirst(whatFind, m_re, m_cs, m_wo, false, true, FINDNEXTTYPE_FINDNEXT, 0, 0))
  1119. {
  1120. delete results;
  1121. continue;
  1122. }
  1123. else
  1124. {
  1125. dealWithZeroFound(pEdit);
  1126. }
  1127. addCurFindRecord(pEdit, *results);
  1128. ++replaceNums;
  1129. //找到了,把结果收集起来
  1130. while (pEdit->findNext())
  1131. {
  1132. addCurFindRecord(pEdit, *results);
  1133. ++replaceNums;
  1134. dealWithZeroFound(pEdit);
  1135. }
  1136. allOpenFileRecord->append(results);
  1137. }
  1138. }
  1139. //全部替换后,下次查找,必须算第一次查找
  1140. m_isFindFirst = true;
  1141. ui.statusbar->showMessage(tr("find finished, total %1 found!").arg(replaceNums), 10000);
  1142. emit sign_findAllInOpenDoc(allOpenFileRecord, replaceNums, whatFind);
  1143. //释放元素
  1144. for (int i = 0; i < allOpenFileRecord->size(); ++i)
  1145. {
  1146. delete allOpenFileRecord->at(i);
  1147. }
  1148. delete allOpenFileRecord;
  1149. }
  1150. //返回是否查找得到内容
  1151. bool FindWin::replaceFindNext(QsciScintilla* pEdit, bool showZeroFindTip)
  1152. {
  1153. m_isFound = false;
  1154. //第一次查找
  1155. if (m_isFindFirst)
  1156. {
  1157. if (pEdit != nullptr)
  1158. {
  1159. QString whatFind = ui.replaceTextBox->currentText();
  1160. addFindHistory(whatFind);
  1161. if (m_extend)
  1162. {
  1163. QString extendFind;
  1164. convertExtendedToString(whatFind, extendFind);
  1165. whatFind = extendFind;
  1166. }
  1167. if (!pEdit->findFirst(whatFind, m_re, m_cs, m_wo, m_wrap, m_forward, FINDNEXTTYPE_REPLACENEXT))
  1168. {
  1169. ui.statusbar->showMessage(tr("cant't find text \'%1\'").arg(m_expr), 8000);
  1170. QApplication::beep();
  1171. m_isFindFirst = true;
  1172. }
  1173. else
  1174. {
  1175. m_isFound = true;
  1176. m_isFindFirst = false;
  1177. dealWithZeroFoundShowTip(pEdit, showZeroFindTip);
  1178. }
  1179. }
  1180. }
  1181. else
  1182. {
  1183. //查找下一个
  1184. if (pEdit != nullptr)
  1185. {
  1186. adjustSearchStartPosChange(pEdit);
  1187. if (!pEdit->findNext())
  1188. {
  1189. ui.statusbar->showMessage(tr("no more find text \'%1\'").arg(m_expr), 8000);
  1190. m_isFindFirst = true;
  1191. QApplication::beep();
  1192. }
  1193. else
  1194. {
  1195. m_isFound = true;
  1196. dealWithZeroFoundShowTip(pEdit, showZeroFindTip);
  1197. }
  1198. }
  1199. }
  1200. return m_isFound;
  1201. }
  1202. void FindWin::slot_replaceFindNext()
  1203. {
  1204. if (ui.replaceTextBox->currentText().isEmpty())
  1205. {
  1206. ui.statusbar->showMessage(tr("what find is null !"), 8000);
  1207. QApplication::beep();
  1208. return;
  1209. }
  1210. updateParameterFromUI();
  1211. QWidget* pw = autoAdjustCurrentEditWin();
  1212. QsciScintilla* pEdit = dynamic_cast<QsciScintilla*>(pw);
  1213. replaceFindNext(pEdit, true);
  1214. }
  1215. //返回值:是否还可以继续替换
  1216. bool FindWin::replace(ScintillaEditView* pEdit)
  1217. {
  1218. if (isFirstFind())
  1219. {
  1220. replaceFindNext(pEdit, false);
  1221. //如果没有找到,则不替换
  1222. if (!m_isFound)
  1223. {
  1224. return false;
  1225. }
  1226. }
  1227. QString findText = ui.replaceTextBox->currentText();
  1228. QString replaceText = ui.replaceWithBox->text();
  1229. if (m_extend)
  1230. {
  1231. QString extendFind;
  1232. convertExtendedToString(findText, extendFind);
  1233. findText = extendFind;
  1234. QString extendReplace;
  1235. convertExtendedToString(replaceText, extendReplace);
  1236. replaceText = extendReplace;
  1237. }
  1238. //当前有选中内容,而且与待替换内容一样,则直接替换
  1239. if (m_isFound && pEdit->hasSelectedText())
  1240. {
  1241. //如果选中内容,与待查找替换的内容一致,进行替换。前提是在normal模式下
  1242. if ((m_searchMode == 1) && (pEdit->selectedText().compare(findText, (m_cs ? Qt::CaseSensitive : Qt::CaseInsensitive)) == 0))
  1243. {
  1244. pEdit->replace(replaceText);
  1245. return replaceFindNext(pEdit,false);
  1246. }
  1247. else if (m_searchMode == 2)
  1248. {
  1249. //如果是正则表达式模式,则不能使用全部匹配才替换,要使用正则匹配,那样会比较麻烦
  1250. //只有上次查找成功,才替换?
  1251. if (m_isFound)
  1252. {
  1253. pEdit->replace(replaceText);
  1254. return replaceFindNext(pEdit,false);
  1255. }
  1256. else
  1257. {
  1258. ui.statusbar->showMessage(tr("no more replace text \'%1\'").arg(m_expr), 8000);
  1259. QApplication::beep();
  1260. return false;
  1261. }
  1262. }
  1263. else
  1264. {
  1265. ui.statusbar->showMessage(tr("no more replace text \'%1\'").arg(m_expr), 8000);
  1266. QApplication::beep();
  1267. return false;
  1268. }
  1269. }
  1270. else if (m_isFound && m_searchMode == 2)
  1271. {
  1272. //找到了内容,但是因为是0长,而无法选中。这种情况就是0长的情况。只在正则表达式情况出现
  1273. pEdit->replace(replaceText);
  1274. //每次替换后,因为是0长替换,再把下次查找位置加1,否则会一直在原地查找
  1275. dealWithZeroFound(pEdit);
  1276. return replaceFindNext(pEdit,false);
  1277. }
  1278. //当前没有查找到
  1279. return replaceFindNext(pEdit,false);
  1280. }
  1281. //把当前选中的内容,使用文本替换掉
  1282. void FindWin::slot_replace()
  1283. {
  1284. if (ui.replaceTextBox->currentText().isEmpty())
  1285. {
  1286. ui.statusbar->showMessage(tr("what find is null !"), 8000);
  1287. QApplication::beep();
  1288. return;
  1289. }
  1290. QWidget* pw = autoAdjustCurrentEditWin();
  1291. ScintillaEditView* pEdit = dynamic_cast<ScintillaEditView*>(pw);
  1292. if (pEdit != nullptr)
  1293. {
  1294. if (pEdit->isReadOnly())
  1295. {
  1296. ui.statusbar->showMessage(tr("The ReadOnly document does not allow replacement."), 8000);
  1297. QApplication::beep();
  1298. return;
  1299. }
  1300. //切换查询条件后,则是第一次查找。防止前后查找条件发生了变化,
  1301. //导致选中的内容不是需要替换的,所以检查是第一次查找,则查找一下
  1302. updateParameterFromUI();
  1303. replace(pEdit);
  1304. }
  1305. else
  1306. {
  1307. ui.statusbar->showMessage(tr("The mode of the current document does not allow replacement."), 8000);
  1308. QApplication::beep();
  1309. }
  1310. }
  1311. void FindWin::slot_findModeRegularBtChange(bool checked)
  1312. {
  1313. if (checked)
  1314. {
  1315. ui.findBackwardBox->setEnabled(false);
  1316. ui.findBackwardBox->setChecked(false);
  1317. ui.findMatchWholeBox->setEnabled(false);
  1318. ui.findMatchWholeBox->setChecked(false);
  1319. }
  1320. else
  1321. {
  1322. ui.findBackwardBox->setEnabled(true);
  1323. ui.findMatchWholeBox->setEnabled(true);
  1324. }
  1325. m_isFindFirst = true;
  1326. }
  1327. void FindWin::slot_replaceModeRegularBtChange(bool checked)
  1328. {
  1329. if (checked)
  1330. {
  1331. ui.replaceBackwardBox->setEnabled(false);
  1332. ui.replaceBackwardBox->setChecked(false);
  1333. ui.replaceMatchWholeBox->setEnabled(false);
  1334. ui.replaceMatchWholeBox->setChecked(false);
  1335. }
  1336. else
  1337. {
  1338. ui.replaceBackwardBox->setEnabled(true);
  1339. ui.replaceMatchWholeBox->setEnabled(true);
  1340. }
  1341. m_isFindFirst = true;
  1342. }
  1343. #if 0
  1344. //替换当前文档里面的所有
  1345. void FindWin::slot_replaceAll()
  1346. {
  1347. if (ui.replaceTextBox->currentText().isEmpty())
  1348. {
  1349. ui.statusbar->showMessage(tr("what find is null !"), 8000);
  1350. return;
  1351. }
  1352. if (!m_isStatic && QMessageBox::Yes != QMessageBox::question(this, tr("Replace All current Doc"), tr("Are you sure replace all occurrences in current documents?")))
  1353. {
  1354. return;
  1355. }
  1356. QWidget* pw = autoAdjustCurrentEditWin();
  1357. ScintillaEditView* pEdit = dynamic_cast<ScintillaEditView*>(pw);
  1358. if (pEdit != nullptr)
  1359. {
  1360. if (pEdit->isReadOnly())
  1361. {
  1362. ui.statusbar->showMessage(tr("The ReadOnly document does not allow replacement."), 8000);
  1363. QApplication::beep();
  1364. return;
  1365. }
  1366. updateParameterFromUI();
  1367. int srcPostion = pEdit->execute(SCI_GETCURRENTPOS);
  1368. int firstDisLineNum = pEdit->execute(SCI_GETFIRSTVISIBLELINE);
  1369. int replaceNums = 0;
  1370. //无条件进行第一次查找,从0行0列开始查找,而且不回环。如果没有找到,则替换完毕
  1371. QString whatFind = ui.replaceTextBox->currentText();
  1372. QString replaceText = ui.replaceWithBox->currentText();
  1373. if (m_extend)
  1374. {
  1375. QString extendFind;
  1376. convertExtendedToString(whatFind, extendFind);
  1377. whatFind = extendFind;
  1378. QString extendReplace;
  1379. convertExtendedToString(replaceText, extendReplace);
  1380. replaceText = extendReplace;
  1381. }
  1382. if (!pEdit->findFirst(whatFind, m_re, m_cs, m_wo, false, true, FINDNEXTTYPE_REPLACENEXT, 0,0))
  1383. {
  1384. ui.statusbar->showMessage(tr("cant't find text \'%1\'").arg(m_expr), 8000);
  1385. QApplication::beep();
  1386. m_isFindFirst = true;
  1387. return;
  1388. }
  1389. pEdit->execute(SCI_BEGINUNDOACTION);
  1390. pEdit->replace(replaceText);
  1391. dealWithZeroFound(pEdit);
  1392. ++replaceNums;
  1393. //找到了,则自动进行全部替换
  1394. while(pEdit->findNext())
  1395. {
  1396. pEdit->replace(replaceText);
  1397. ++replaceNums;
  1398. dealWithZeroFound(pEdit);
  1399. }
  1400. pEdit->execute(SCI_ENDUNDOACTION);
  1401. pEdit->execute(SCI_GOTOPOS, srcPostion);
  1402. pEdit->execute(SCI_SETFIRSTVISIBLELINE, firstDisLineNum);
  1403. pEdit->execute(SCI_SETXOFFSET, 0);
  1404. //全部替换后,下次查找,必须算第一次查找
  1405. m_isFindFirst = true;
  1406. ui.statusbar->showMessage(tr("replace finished, total %1 replaced!").arg(replaceNums), 10000);
  1407. }
  1408. else
  1409. {
  1410. ui.statusbar->showMessage(tr("The mode of the current document does not allow replacement."), 8000);
  1411. QApplication::beep();
  1412. }
  1413. }
  1414. #endif
  1415. // Find the first occurrence of a string.
  1416. int buildSearchFlags(bool re, bool cs, bool wo, bool wrap, bool forward, FindNextType findNextType, bool posix, bool cxx11)
  1417. {
  1418. int flags = 0;
  1419. flags = (cs ? SCFIND_MATCHCASE : 0) |
  1420. (wo ? SCFIND_WHOLEWORD : 0) |
  1421. (re ? SCFIND_REGEXP : 0) |
  1422. (posix ? SCFIND_POSIX : 0) |
  1423. (cxx11 ? SCFIND_CXX11REGEX : 0);
  1424. switch (findNextType)
  1425. {
  1426. case FINDNEXTTYPE_FINDNEXT:
  1427. flags |= SCFIND_REGEXP_EMPTYMATCH_ALL | SCFIND_REGEXP_SKIPCRLFASONE;
  1428. break;
  1429. case FINDNEXTTYPE_REPLACENEXT:
  1430. flags |= SCFIND_REGEXP_EMPTYMATCH_NOTAFTERMATCH | SCFIND_REGEXP_SKIPCRLFASONE;
  1431. break;
  1432. case FINDNEXTTYPE_FINDNEXTFORREPLACE:
  1433. flags |= SCFIND_REGEXP_EMPTYMATCH_ALL | SCFIND_REGEXP_EMPTYMATCH_ALLOWATSTART | SCFIND_REGEXP_SKIPCRLFASONE;
  1434. break;
  1435. }
  1436. return flags;
  1437. }
  1438. struct FindReplaceInfo
  1439. {
  1440. intptr_t _startRange = -1;
  1441. intptr_t _endRange = -1;
  1442. };
  1443. //返回值替换数量
  1444. int FindWin::doReplaceAll(ScintillaEditView* pEdit, QString &whatFind, QString& replaceText, bool isCombineUndo)
  1445. {
  1446. int replaceNums = 0;
  1447. int srcPostion = pEdit->execute(SCI_GETCURRENTPOS);
  1448. int firstDisLineNum = pEdit->execute(SCI_GETFIRSTVISIBLELINE);
  1449. if (isCombineUndo)
  1450. {
  1451. pEdit->execute(SCI_BEGINUNDOACTION);
  1452. }
  1453. int flags = buildSearchFlags(m_re, m_cs, m_wo, false, true, FINDNEXTTYPE_REPLACENEXT, 0, 0);
  1454. intptr_t targetStart = 0;
  1455. intptr_t targetEnd = 0;
  1456. //Initial range for searching
  1457. pEdit->execute(SCI_SETSEARCHFLAGS, flags);
  1458. FindReplaceInfo findReplaceInfo;
  1459. findReplaceInfo._startRange = 0;
  1460. findReplaceInfo._endRange = pEdit->execute(SCI_GETLENGTH);
  1461. QByteArray pTextFind = whatFind.toUtf8();
  1462. QByteArray pTextReplace = replaceText.toUtf8();
  1463. while (targetStart >= 0)
  1464. {
  1465. targetStart = pEdit->searchInTarget(pTextFind, findReplaceInfo._startRange, findReplaceInfo._endRange);
  1466. // If we've not found anything, just break out of the loop
  1467. if (targetStart == -1 || targetStart == -2)
  1468. break;
  1469. targetEnd = pEdit->execute(SCI_GETTARGETEND);
  1470. if (targetEnd > findReplaceInfo._endRange)
  1471. {
  1472. //we found a result but outside our range, therefore do not process it
  1473. break;
  1474. }
  1475. intptr_t foundTextLen = targetEnd - targetStart;
  1476. intptr_t replaceDelta = 0;
  1477. intptr_t replacedLength;
  1478. if (m_re)
  1479. {
  1480. replacedLength = pEdit->replaceTargetRegExMode(pTextReplace);
  1481. }
  1482. else
  1483. {
  1484. replacedLength = pEdit->replaceTarget(pTextReplace);
  1485. }
  1486. replaceDelta = replacedLength - foundTextLen;
  1487. ++replaceNums;
  1488. // After the processing of the last string occurrence the search loop should be stopped
  1489. // This helps to avoid the endless replacement during the EOL ("$") searching
  1490. if (targetStart + foundTextLen == findReplaceInfo._endRange)
  1491. break;
  1492. findReplaceInfo._startRange = targetStart + foundTextLen + replaceDelta; //search from result onwards
  1493. findReplaceInfo._endRange += replaceDelta; //adjust end of range in case of replace
  1494. }
  1495. if (isCombineUndo)
  1496. {
  1497. pEdit->execute(SCI_ENDUNDOACTION);
  1498. }
  1499. pEdit->execute(SCI_GOTOPOS, srcPostion);
  1500. pEdit->execute(SCI_SETFIRSTVISIBLELINE, firstDisLineNum);
  1501. pEdit->execute(SCI_SETXOFFSET, 0);
  1502. return replaceNums;
  1503. }
  1504. int FindWin::replaceAll()
  1505. {
  1506. if (ui.replaceTextBox->currentText().isEmpty())
  1507. {
  1508. ui.statusbar->showMessage(tr("what find is null !"), 8000);
  1509. return 0;
  1510. }
  1511. if (!m_isStatic && QMessageBox::Yes != QMessageBox::question(this, tr("Replace All current Doc"), tr("Are you sure replace all occurrences in current documents?")))
  1512. {
  1513. return 0;
  1514. }
  1515. QWidget* pw = autoAdjustCurrentEditWin();
  1516. ScintillaEditView* pEdit = dynamic_cast<ScintillaEditView*>(pw);
  1517. if (pEdit != nullptr)
  1518. {
  1519. if (pEdit->isReadOnly())
  1520. {
  1521. ui.statusbar->showMessage(tr("The ReadOnly document does not allow replacement."), 8000);
  1522. QApplication::beep();
  1523. return 0;
  1524. }
  1525. }
  1526. updateParameterFromUI();
  1527. QString whatFind = ui.replaceTextBox->currentText();
  1528. QString replaceText = ui.replaceWithBox->text();
  1529. if (m_extend)
  1530. {
  1531. QString extendFind;
  1532. convertExtendedToString(whatFind, extendFind);
  1533. whatFind = extendFind;
  1534. QString extendReplace;
  1535. convertExtendedToString(replaceText, extendReplace);
  1536. replaceText = extendReplace;
  1537. }
  1538. int replaceNums = doReplaceAll(pEdit, whatFind, replaceText);
  1539. //全部替换后,下次查找,必须算第一次查找
  1540. m_isFindFirst = true;
  1541. ui.statusbar->showMessage(tr("replace finished, total %1 replaced!").arg(replaceNums), 10000);
  1542. return replaceNums;
  1543. }
  1544. //替换当前文档里面的所有。之前的要慢,是因为qscintilla中实时计算了行在屏幕需要的长度。
  1545. //大量的这种计算一行实时长度的操作,非常耗时。查找、标记均不耗时,只有替换修改了文本才耗时。
  1546. void FindWin::slot_replaceAll()
  1547. {
  1548. replaceAll();
  1549. }
  1550. void FindWin::slot_replaceAllInOpenDoc()
  1551. {
  1552. if (ui.replaceTextBox->currentText().isEmpty())
  1553. {
  1554. ui.statusbar->showMessage(tr("what find is null !"), 8000);
  1555. QApplication::beep();
  1556. return;
  1557. }
  1558. if (QMessageBox::Yes != QMessageBox::question(this, tr("Replace All Open Doc"), tr("Are you sure replace all occurrences in all open documents?")))
  1559. {
  1560. return;
  1561. }
  1562. updateParameterFromUI();
  1563. int replaceNums = 0;
  1564. QString whatFind = ui.replaceTextBox->currentText();
  1565. QString whatReplace = m_replaceWithText;
  1566. if (m_extend)
  1567. {
  1568. QString extendFind;
  1569. convertExtendedToString(whatFind, extendFind);
  1570. whatFind = extendFind;
  1571. QString extendReplace;
  1572. convertExtendedToString(whatReplace, extendReplace);
  1573. whatReplace = extendReplace;
  1574. }
  1575. for (int i = 0; i < m_editTabWidget->count(); ++i)
  1576. {
  1577. QWidget* pw = m_editTabWidget->widget(i);
  1578. ScintillaEditView* pEdit = dynamic_cast<ScintillaEditView*>(pw);
  1579. if (pEdit != nullptr)
  1580. {
  1581. //只读的文档不能替换
  1582. if (pEdit->isReadOnly())
  1583. {
  1584. continue;
  1585. }
  1586. replaceNums += doReplaceAll(pEdit, whatFind, whatReplace);
  1587. #if 0
  1588. //无条件进行第一次查找,从0行0列开始查找,而且不回环。如果没有找到,则替换完毕
  1589. if (!pEdit->findFirst(whatFind, m_re, m_cs, m_wo, false, true, FINDNEXTTYPE_REPLACENEXT,0, 0))
  1590. {
  1591. continue;
  1592. }
  1593. pEdit->replace(whatReplace);
  1594. dealWithZeroFound(pEdit);
  1595. ++replaceNums;
  1596. //找到了,则自动进行全部替换
  1597. while (pEdit->findNext())
  1598. {
  1599. pEdit->replace(whatReplace);
  1600. ++replaceNums;
  1601. dealWithZeroFound(pEdit);
  1602. }
  1603. #endif
  1604. }
  1605. }
  1606. //全部替换后,下次查找,必须算第一次查找
  1607. m_isFindFirst = true;
  1608. ui.statusbar->showMessage(tr("Replace in Opened Files: %1 occurrences were replaced.").arg(replaceNums), 10000);
  1609. }
  1610. int FindWin::markAll()
  1611. {
  1612. if (ui.markTextBox->currentText().isEmpty())
  1613. {
  1614. ui.statusbar->showMessage(tr("what mark is null !"), 8000);
  1615. QApplication::beep();
  1616. return 0;
  1617. }
  1618. QWidget* pw = autoAdjustCurrentEditWin();
  1619. ScintillaEditView* pEdit = dynamic_cast<ScintillaEditView*>(pw);
  1620. if (pEdit != nullptr)
  1621. {
  1622. FindRecords* results = new FindRecords;
  1623. results->pEdit = pEdit;
  1624. results->hightLightColor = CCNotePad::s_curMarkColorId;
  1625. results->findFilePath = pw->property("filePath").toString();
  1626. updateParameterFromUI();
  1627. int replaceNums = 0;
  1628. //无条件进行第一次查找,从0行0列开始查找,而且不回环。如果没有找到,则替换完毕
  1629. QString whatMark = ui.markTextBox->currentText();
  1630. results->findText = whatMark;
  1631. if (m_extend)
  1632. {
  1633. QString extendFind;
  1634. convertExtendedToString(whatMark, extendFind);
  1635. whatMark = extendFind;
  1636. }
  1637. int srcPostion = pEdit->execute(SCI_GETCURRENTPOS);
  1638. int firstDisLineNum = pEdit->execute(SCI_GETFIRSTVISIBLELINE);
  1639. if (!pEdit->findFirst(whatMark, m_re, m_cs, m_wo, false, true, FINDNEXTTYPE_FINDNEXT, 0, 0))
  1640. {
  1641. ui.statusbar->showMessage(tr("cant't find text \'%1\'").arg(m_expr), 8000);
  1642. //QApplication::beep();
  1643. return 0;
  1644. }
  1645. else
  1646. {
  1647. //不支持零长的高亮。0长不高亮
  1648. FindState& state = pEdit->getLastFindState();
  1649. if (state.targstart == state.targend)
  1650. {
  1651. ui.statusbar->showMessage(tr("cant't mark text \'%1\'").arg(m_expr), 8000);
  1652. QApplication::beep();
  1653. return 0;
  1654. }
  1655. }
  1656. addCurFindRecord(pEdit, *results, true);
  1657. ++replaceNums;
  1658. //找到了,把结果收集起来
  1659. while (pEdit->findNext())
  1660. {
  1661. addCurFindRecord(pEdit, *results, true);
  1662. ++replaceNums;
  1663. }
  1664. //把结果高亮起来。
  1665. int foundTextLen = 0;
  1666. for (int i = 0, s = results->records.size(); i < s; ++i)
  1667. {
  1668. const FindRecord& rs = results->records.at(i);
  1669. foundTextLen = rs.end - rs.pos;
  1670. if (foundTextLen > 0)
  1671. {
  1672. pEdit->execute(SCI_SETINDICATORCURRENT, CCNotePad::s_curMarkColorId);
  1673. pEdit->execute(SCI_INDICATORFILLRANGE, rs.pos, foundTextLen);
  1674. }
  1675. }
  1676. if (!results->records.isEmpty())
  1677. {
  1678. pEdit->appendMarkRecord(results);
  1679. }
  1680. pEdit->execute(SCI_SETFIRSTVISIBLELINE, firstDisLineNum);
  1681. pEdit->execute(SCI_GOTOPOS, srcPostion);
  1682. pEdit->execute(SCI_SETXOFFSET, 0);
  1683. //全部替换后,下次查找,必须算第一次查找
  1684. m_isFindFirst = true;
  1685. ui.statusbar->showMessage(tr("mark finished, total %1 found!").arg(replaceNums), 10000);
  1686. return replaceNums;
  1687. }
  1688. else
  1689. {
  1690. ui.statusbar->showMessage(tr("The mode of the current document does not allow mark."), 8000);
  1691. QApplication::beep();
  1692. }
  1693. return 0;
  1694. }
  1695. //标记高亮单词
  1696. void FindWin::slot_markAll()
  1697. {
  1698. markAll();
  1699. }
  1700. //取消高亮当前关键字
  1701. void FindWin::slot_clearMark()
  1702. {
  1703. if (ui.markTextBox->currentText().isEmpty())
  1704. {
  1705. ui.statusbar->showMessage(tr("what mark is null !"), 8000);
  1706. QApplication::beep();
  1707. return;
  1708. }
  1709. CCNotePad* pMainPad = dynamic_cast<CCNotePad*>(m_pMainPad);
  1710. if (pMainPad != nullptr)
  1711. {
  1712. pMainPad->clearHighlightWord(ui.markTextBox->currentText());
  1713. }
  1714. }
  1715. //取消所有高亮
  1716. void FindWin::slot_clearAllMark()
  1717. {
  1718. CCNotePad* pMainPad = dynamic_cast<CCNotePad*>(m_pMainPad);
  1719. if (pMainPad != nullptr)
  1720. {
  1721. pMainPad->slot_clearMark();
  1722. }
  1723. }
  1724. //选择查找目录
  1725. void FindWin::slot_dirSelectDest()
  1726. {
  1727. QString curDirPath = ui.destFindDir->text();
  1728. if (curDirPath.isEmpty())
  1729. {
  1730. curDirPath = CCNotePad::s_lastOpenDirPath;
  1731. }
  1732. QString destDir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), curDirPath, QFileDialog::DontResolveSymlinks);
  1733. if (!destDir.isEmpty())
  1734. {
  1735. ui.destFindDir->setText(destDir);
  1736. }
  1737. }
  1738. //在walkDirfile中用作回调函数处理。命中则返回true
  1739. bool FindWin::findTextInFile(QString &filePath, int &findNums, QVector<FindRecords*>* allfileInDirRecord)
  1740. {
  1741. pEditTemp->clear();
  1742. if (0 != FileManager::getInstance().loadFileForSearch(pEditTemp, filePath))
  1743. {
  1744. return false;
  1745. }
  1746. FindRecords* results = new FindRecords();
  1747. //返回结果的edit无条件写无。注意不要忘记
  1748. results->pEdit = nullptr;
  1749. results->findFilePath = filePath;
  1750. //无条件进行第一次查找,从0行0列开始查找,而且不回环。如果没有找到,则替换完毕
  1751. results->findText = m_expr;
  1752. QString whatFind = m_expr;
  1753. if (m_extend)
  1754. {
  1755. QString extendFind;
  1756. convertExtendedToString(whatFind, extendFind);
  1757. whatFind = extendFind;
  1758. }
  1759. if (!pEditTemp->findFirst(whatFind, m_re, m_cs, m_wo, false, m_forward, FINDNEXTTYPE_FINDNEXT, 0, 0,false))
  1760. {
  1761. delete results;
  1762. return false;
  1763. }
  1764. else
  1765. {
  1766. dealWithZeroFound(pEditTemp);
  1767. }
  1768. addCurFindRecord(pEditTemp, *results);
  1769. ++findNums;
  1770. //找到了,把结果收集起来
  1771. while (pEditTemp->findNext())
  1772. {
  1773. addCurFindRecord(pEditTemp, *results);
  1774. ++findNums;
  1775. dealWithZeroFound(pEditTemp);
  1776. }
  1777. allfileInDirRecord->append(results);
  1778. return true;
  1779. }
  1780. //在walkDirfile中用作回调函数处理。命中则返回true 第三个参数不需要,为了复用walkdir,暂时保留和findTextInFile一致
  1781. bool FindWin::replaceTextInFile(QString &filePath, int &replaceNums, QVector<FindRecords*>*)
  1782. {
  1783. pEditTemp->clear();
  1784. if (0 != FileManager::getInstance().loadFileForSearch(pEditTemp, filePath))
  1785. {
  1786. return false;
  1787. }
  1788. QString find = m_expr;
  1789. QString replace = m_replaceWithText;
  1790. if (m_extend)
  1791. {
  1792. QString extendFind;
  1793. convertExtendedToString(find, extendFind);
  1794. find = extendFind;
  1795. QString extendReplace;
  1796. convertExtendedToString(replace, extendReplace);
  1797. replace = extendReplace;
  1798. }
  1799. replaceNums += doReplaceAll(pEditTemp, find, replace);
  1800. #if 0
  1801. if (!pEditTemp->findFirst(find, m_re, m_cs, m_wo, false, m_forward, FINDNEXTTYPE_REPLACENEXT,0, 0,false))
  1802. {
  1803. return false;
  1804. }
  1805. pEditTemp->replace(replace);
  1806. dealWithZeroFound(pEditTemp);
  1807. ++replaceNums;
  1808. //找到了,则自动进行全部替换
  1809. while (pEditTemp->findNext())
  1810. {
  1811. pEditTemp->replace(replace);
  1812. ++replaceNums;
  1813. dealWithZeroFound(pEditTemp);
  1814. }
  1815. #endif
  1816. //必须要保存一下
  1817. emit sign_replaceSaveFile(filePath, pEditTemp);
  1818. return true;
  1819. }
  1820. //非递归版本的递归文件,从CompareDirs中修改而来
  1821. //isSkipBinary:是否跳过二进制
  1822. //isSkipHide:是否处理隐藏文件
  1823. //skipMaxSize::处理文件的最大大小,超过则不处理。如果是0,则表示不跳过任何文件
  1824. //isfilterFileType:过滤类型,只处理这类类型文件 为true时 fileExtType 不能为空
  1825. //fileExtType的格式为:.cpp .h 类似,但是不需要前面的.,传递的时候不传递下来
  1826. int FindWin::walkDirfile(QString path, int &foundTimes, bool isSkipBinary, bool isSkipHide, int skipMaxSize, bool isfilterFileType, QStringList& fileExtType, bool isSkipDir, QStringList & skipDirNames, bool isSkipChildDirs, std::function<bool(QString &, int &, QVector<FindRecords*>* allfileInDirRecord)> foundCallBack, bool isAskAbort)
  1827. {
  1828. QList<QString> dirsList;
  1829. QString oneDir(path);
  1830. dirsList.append(oneDir);
  1831. int fileNums = 0;
  1832. int hitFileNums = 0;
  1833. //再获取文件夹到列表
  1834. QDir::Filters dirfilter;
  1835. if (!isSkipHide)
  1836. {
  1837. dirfilter = QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::NoSymLinks;
  1838. }
  1839. else
  1840. {
  1841. dirfilter = QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks;
  1842. }
  1843. //过滤文件类型。true 合格,需要处理, false 不合格,跳过
  1844. auto fileTypeFilter = [&fileExtType](QFileInfo& fileInfo)->bool {
  1845. QString suffix = fileInfo.suffix();
  1846. if (!suffix.isEmpty())
  1847. {
  1848. return (-1 != fileExtType.indexOf(suffix));
  1849. }
  1850. //对于没有后缀的文件,一律跳过
  1851. return false;
  1852. };
  1853. //是否二进制文件
  1854. auto binaryFiltre = [](QFileInfo& fi)->bool {
  1855. return DocTypeListView::isHexExt(fi.suffix());
  1856. };
  1857. ProgressWin* loadFileProcessWin = new ProgressWin(this);
  1858. loadFileProcessWin->setWindowModality(Qt::WindowModal);
  1859. loadFileProcessWin->info(tr("load dir file in progress\n, please wait ..."));
  1860. loadFileProcessWin->show();
  1861. int dirNums = 0;
  1862. bool firstChildDirs = true;
  1863. int totalStep = 0;
  1864. bool canAbort = true;
  1865. bool canAbortSecond = true;
  1866. if (!isAskAbort)
  1867. {
  1868. canAbort = false;
  1869. canAbortSecond = false;
  1870. }
  1871. while (!dirsList.isEmpty())
  1872. {
  1873. QString curDir = dirsList.takeFirst();
  1874. if (!isSkipChildDirs)
  1875. {
  1876. /*添加path路径文件*/
  1877. QDir dir(curDir); //遍历各级子目录
  1878. QFileInfoList folder_list = dir.entryInfoList(dirfilter); //获取当前所有目录
  1879. for (int i = 0; i != folder_list.size(); ++i) //自动递归添加各目录到上一级目录
  1880. {
  1881. QString namepath = folder_list.at(i).absoluteFilePath(); //获取路径
  1882. QFileInfo folderinfo = folder_list.at(i);
  1883. if (folderinfo.baseName().isEmpty())
  1884. {
  1885. loadFileProcessWin->info(tr("skip dir %1").arg(namepath));
  1886. continue;
  1887. }
  1888. QString name = folderinfo.fileName(); //获取目录名
  1889. if (isSkipDir && (-1 != skipDirNames.indexOf(name)))
  1890. {
  1891. loadFileProcessWin->info(tr("skip dir %1").arg(namepath));
  1892. continue;
  1893. }
  1894. dirsList.push_front(namepath);
  1895. dirNums++;
  1896. loadFileProcessWin->info(tr("found %1 dir %2").arg(dirNums).arg(namepath));
  1897. QCoreApplication::processEvents(/*QEventLoop::ExcludeUserInputEvents*/);
  1898. }
  1899. if (firstChildDirs)
  1900. {
  1901. totalStep = dirNums;
  1902. loadFileProcessWin->setTotalSteps(dirNums);
  1903. firstChildDirs = false;
  1904. }
  1905. if (dirsList.size() < totalStep)
  1906. {
  1907. totalStep = dirsList.size();
  1908. loadFileProcessWin->moveStep();
  1909. }
  1910. }
  1911. QDir dir_file(curDir);
  1912. if (!isSkipHide)
  1913. {
  1914. dir_file.setFilter(QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden | QDir::NoSymLinks);//获取当前所有文件
  1915. }
  1916. else
  1917. {
  1918. dir_file.setFilter(QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks);//获取当前所有文件
  1919. }
  1920. QFileInfoList list_file = dir_file.entryInfoList();
  1921. for (int i = 0; i < list_file.size(); ++i)
  1922. { //将当前目录中所有文件添加到treewidget中
  1923. QFileInfo fileInfo = list_file.at(i);
  1924. QString namepath = list_file.at(i).absoluteFilePath(); //获取路径
  1925. //不支持所有文件,仅仅支持指定类型文件。没有通过
  1926. if (isfilterFileType && !fileTypeFilter(fileInfo))
  1927. {
  1928. loadFileProcessWin->info(tr("ext type skip file %1").arg(namepath));
  1929. continue;
  1930. }
  1931. //大小过滤
  1932. if ((skipMaxSize != 0) && fileInfo.size() > skipMaxSize)
  1933. {
  1934. continue;
  1935. }
  1936. //二进制过滤//对于二进制文件该如何处理,我觉得必须要过滤,暂时不处理
  1937. if (isSkipBinary &&binaryFiltre(fileInfo))
  1938. {
  1939. continue;
  1940. }
  1941. //回调处理该函数
  1942. if (foundCallBack(namepath, foundTimes, nullptr))
  1943. {
  1944. ++hitFileNums;
  1945. }
  1946. if (i % 2 == 0)
  1947. {
  1948. if (loadFileProcessWin->isCancel())
  1949. {
  1950. loadFileProcessWin->info(tr("found in dir canceled ..."));
  1951. break;
  1952. }
  1953. QCoreApplication::processEvents();
  1954. }
  1955. if ((canAbort && (hitFileNums > 100 || foundTimes > 1000)) || (canAbortSecond && foundTimes > 8000))
  1956. {
  1957. int ret = QMessageBox::question(this, tr("Continue Find ?"), tr("The search results have been greater than %1 times in %2 files, and more may be slow. Continue to search?").arg(foundTimes).arg(hitFileNums), tr("Yes"), tr("Abort"));
  1958. if(ret == 1)
  1959. {
  1960. loadFileProcessWin->setCancel();
  1961. break;
  1962. }
  1963. else
  1964. {
  1965. if (canAbort && (hitFileNums > 100 || foundTimes > 1000))
  1966. {
  1967. canAbort = false;
  1968. }
  1969. if ((canAbortSecond && foundTimes > 8000))
  1970. {
  1971. canAbortSecond = false;
  1972. }
  1973. }
  1974. }
  1975. }
  1976. fileNums += list_file.size();
  1977. if (loadFileProcessWin->isCancel())
  1978. {
  1979. break;
  1980. }
  1981. }
  1982. if (loadFileProcessWin != nullptr)
  1983. {
  1984. delete loadFileProcessWin;
  1985. loadFileProcessWin = nullptr;
  1986. }
  1987. return fileNums;
  1988. }
  1989. //在目标文件夹中查找
  1990. void FindWin::slot_dirFindAll()
  1991. {
  1992. QString dirPath = ui.destFindDir->text().trimmed();
  1993. QString whatFind = ui.dirFindWhat->currentText();
  1994. if (dirPath.isEmpty())
  1995. {
  1996. ui.statusbar->showMessage(tr("please select find dest dir !"), 8000);
  1997. QApplication::beep();
  1998. return;
  1999. }
  2000. if(whatFind.isEmpty())
  2001. {
  2002. ui.statusbar->showMessage(tr("what find is null !"), 8000);
  2003. QApplication::beep();
  2004. return;
  2005. }
  2006. QDir dir(dirPath);
  2007. if (!dir.exists())
  2008. {
  2009. ui.statusbar->showMessage(tr("dest dir %1 not exist !").arg(dirPath), 8000);
  2010. QApplication::beep();
  2011. return;
  2012. }
  2013. bool isfilterFileType = ui.dealFileType->isChecked();
  2014. bool isSkipDirs = ui.skipDir->isChecked();
  2015. QStringList fileExtTypeList;
  2016. QStringList skipDirNameList;
  2017. if (isfilterFileType)
  2018. {
  2019. QString fileExtType = ui.fileType->text().trimmed();
  2020. if (fileExtType.isEmpty() || (fileExtType == "*.*"))
  2021. {
  2022. isfilterFileType = false;
  2023. }
  2024. else
  2025. {
  2026. //格式是*.h:*.c:*.cpp类似的
  2027. QStringList typeList = fileExtType.split(":");
  2028. foreach (QString var, typeList)
  2029. {
  2030. if (var.size() >= 3)
  2031. {
  2032. //只取后面的h或或cpp后缀
  2033. fileExtTypeList.append(var.mid(2));
  2034. }
  2035. }
  2036. if (fileExtTypeList.isEmpty())
  2037. {
  2038. isfilterFileType = false;
  2039. }
  2040. }
  2041. }
  2042. if (isSkipDirs)
  2043. {
  2044. QString dirNames = ui.skipDirNames->text().trimmed();
  2045. if (dirNames.isEmpty())
  2046. {
  2047. isSkipDirs = false;
  2048. }
  2049. else
  2050. {
  2051. QStringList nameList = dirNames.split(":");
  2052. foreach(QString var, nameList)
  2053. {
  2054. if (var.size() > 0)
  2055. {
  2056. //只取后面的h或或cpp后缀
  2057. skipDirNameList.append(var);
  2058. }
  2059. }
  2060. if (skipDirNameList.isEmpty())
  2061. {
  2062. isSkipDirs = false;
  2063. }
  2064. }
  2065. }
  2066. bool isSkipBinary = ui.skipBinary->isChecked();
  2067. bool isSkipHide = ui.skipHideFile->isChecked();
  2068. int skipMaxSize = (ui.skipFileMaxSize->isChecked()) ? ui.maxFileSizeSpinBox->value()*1024*1024:0;
  2069. bool isSkipChildDir = ui.skipChildDirs->isChecked();
  2070. updateParameterFromUI();
  2071. if (pEditTemp == nullptr)
  2072. {
  2073. pEditTemp = new ScintillaEditView(nullptr);
  2074. }
  2075. int foundNums = 0;
  2076. QVector<FindRecords*>* allfileInDirRecord = new QVector<FindRecords*>();
  2077. std::function<bool(QString &, int &, QVector<FindRecords*>* allfileInDirRecord)> foundCallBack = std::bind(&FindWin::findTextInFile, this, std::placeholders::_1, std::placeholders::_2, allfileInDirRecord);
  2078. int filesNum = walkDirfile(dirPath, foundNums, isSkipBinary, isSkipHide, skipMaxSize, isfilterFileType, fileExtTypeList, isSkipDirs, skipDirNameList, isSkipChildDir, foundCallBack);
  2079. //全部替换后,下次查找,必须算第一次查找
  2080. m_isFindFirst = true;
  2081. ui.statusbar->showMessage(tr("find finished, total %1 found in %2 file!").arg(foundNums).arg(filesNum), 10000);
  2082. //复用了这个信号函数,没有新做消息,要注意
  2083. emit sign_findAllInOpenDoc(allfileInDirRecord, foundNums, whatFind);
  2084. addFindHistory(whatFind);
  2085. //释放元素
  2086. for (int i = 0; i < allfileInDirRecord->size(); ++i)
  2087. {
  2088. delete allfileInDirRecord->at(i);
  2089. }
  2090. delete allfileInDirRecord;
  2091. }
  2092. //目录中直接替换
  2093. void FindWin::slot_dirReplaceAll()
  2094. {
  2095. QString dirPath = ui.destFindDir->text();
  2096. QString whatFind = ui.dirFindWhat->currentText();
  2097. QString dirReplaceWhat = ui.dirReplaceWhat->text();
  2098. if (dirPath.isEmpty())
  2099. {
  2100. ui.statusbar->showMessage(tr("please select find dest dir !"), 8000);
  2101. QApplication::beep();
  2102. return;
  2103. }
  2104. if (whatFind.isEmpty())
  2105. {
  2106. ui.statusbar->showMessage(tr("what find is null !"), 8000);
  2107. QApplication::beep();
  2108. return;
  2109. }
  2110. if (QMessageBox::Yes != QMessageBox::question(this, tr("Replace All Dirs"), tr("Are you sure replace all \"%1\" to \"%2\" occurrences in selected dirs ?").arg(whatFind).arg(dirReplaceWhat)))
  2111. {
  2112. return;
  2113. }
  2114. bool isfilterFileType = ui.dealFileType->isChecked();
  2115. QStringList fileExtTypeList;
  2116. bool isSkipDirs = ui.skipDir->isChecked();
  2117. QStringList skipDirNameList;
  2118. if (isfilterFileType)
  2119. {
  2120. QString fileExtType = ui.fileType->text().trimmed();
  2121. if (fileExtType.isEmpty() || (fileExtType == "*.*"))
  2122. {
  2123. isfilterFileType = false;
  2124. }
  2125. else
  2126. {
  2127. //格式是*.h:*.c:*.cpp类似的
  2128. QStringList typeList = fileExtType.split(":");
  2129. foreach(QString var, typeList)
  2130. {
  2131. if (var.size() >= 3)
  2132. {
  2133. //只取后面的h或或cpp后缀
  2134. fileExtTypeList.append(var.mid(2));
  2135. }
  2136. }
  2137. if (fileExtTypeList.isEmpty())
  2138. {
  2139. isfilterFileType = false;
  2140. }
  2141. }
  2142. }
  2143. if (isSkipDirs)
  2144. {
  2145. QString dirNames = ui.skipDirNames->text().trimmed();
  2146. if (dirNames.isEmpty())
  2147. {
  2148. isSkipDirs = false;
  2149. }
  2150. else
  2151. {
  2152. QStringList nameList = dirNames.split(":");
  2153. foreach(QString var, nameList)
  2154. {
  2155. if (var.size() > 0)
  2156. {
  2157. //只取后面的h或或cpp后缀
  2158. skipDirNameList.append(var);
  2159. }
  2160. }
  2161. if (skipDirNameList.isEmpty())
  2162. {
  2163. isSkipDirs = false;
  2164. }
  2165. }
  2166. }
  2167. bool isSkipBinary = ui.skipBinary->isChecked();
  2168. bool isSkipHide = ui.skipHideFile->isChecked();
  2169. int skipMaxSize = (ui.skipFileMaxSize->isChecked()) ? ui.maxFileSizeSpinBox->value() * 1024 * 1024 : 0;
  2170. bool isSkipChildDir = ui.skipChildDirs->isChecked();
  2171. updateParameterFromUI();
  2172. if (pEditTemp == nullptr)
  2173. {
  2174. pEditTemp = new ScintillaEditView(nullptr);
  2175. }
  2176. int replaceNums = 0;
  2177. std::function<bool(QString &, int &, QVector<FindRecords*>* allfileInDirRecord)> foundCallBack = std::bind(&FindWin::replaceTextInFile, this, std::placeholders::_1, std::placeholders::_2, nullptr);
  2178. int filesNum = walkDirfile(dirPath, replaceNums, isSkipBinary, isSkipHide, skipMaxSize, isfilterFileType, fileExtTypeList, isSkipDirs, skipDirNameList,isSkipChildDir, foundCallBack,false);
  2179. //全部替换后,下次查找,必须算第一次查找
  2180. m_isFindFirst = true;
  2181. ui.statusbar->showMessage(tr("replace finished, total %1 replace in %2 file!").arg(replaceNums).arg(filesNum), 10000);
  2182. }