LUAEditorFindDialog.cpp 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/Serialization/SerializeContext.h>
  9. #include <AzCore/Script/ScriptAsset.h>
  10. #include <AzCore/StringFunc/StringFunc.h>
  11. #include <AzCore/Casting/numeric_cast.h>
  12. #include <AzCore/Component/TickBus.h>
  13. #include "LUAEditorFindDialog.hxx"
  14. #include "LUAEditorMainWindow.hxx"
  15. #include "LUAEditorContextMessages.h"
  16. #include "LUAEditorBlockState.h"
  17. #include <Source/LUA/ui_LUAEditorFindDialog.h>
  18. #include <QMessageBox>
  19. #include <QListWidgetItem>
  20. #include <QTextDocument>
  21. #include <QTimer>
  22. namespace LUAEditorInternal
  23. {
  24. // this stuff goes in the user preferences rather than the global stuff:
  25. class FindSavedState
  26. : public AZ::UserSettings
  27. {
  28. public:
  29. AZ_RTTI(FindSavedState, "{2B880623-63A9-4B39-B8B9-47609590D7D2}", AZ::UserSettings);
  30. AZ_CLASS_ALLOCATOR(FindSavedState, AZ::SystemAllocator);
  31. FindSavedState()
  32. {
  33. m_lastSearchInFilesMode = 0;
  34. m_findWrap = true;
  35. }
  36. int m_lastSearchInFilesMode;
  37. bool m_findWrap;
  38. static void Reflect(AZ::ReflectContext* reflection)
  39. {
  40. AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
  41. if (serializeContext)
  42. {
  43. serializeContext->Class<FindSavedState>()
  44. ->Field("m_lastSearchInFilesMode", &FindSavedState::m_lastSearchInFilesMode)
  45. ->Field("m_findWrap", &FindSavedState::m_findWrap);
  46. }
  47. }
  48. };
  49. }
  50. namespace LUAEditor
  51. {
  52. extern AZ::Uuid ContextID;
  53. //////////////////////////////////////////////////////////////////////////
  54. //find dialog
  55. // QDialog(/*parent*/) strip the parent from QDialog and this window will no longer be forced on top all the time
  56. LUAEditorFindDialog::LUAEditorFindDialog(QWidget* parent)
  57. : QDialog(parent)
  58. {
  59. pLUAEditorMainWindow = qobject_cast<LUAEditorMainWindow*>(parent);
  60. AZ_Assert(pLUAEditorMainWindow, "Parent Widget is NULL or not the LUAEditorMainWindow!");
  61. m_bAnyDocumentsOpen = false;
  62. LUAViewMessages::Bus::Handler::BusConnect();
  63. m_bWasFindInAll = false;
  64. m_gui = azcreate(Ui::LUAEditorFindDialog, ());
  65. m_gui->setupUi(this);
  66. this->setFixedSize(this->size());
  67. m_gui->searchDownRadioButton->setChecked(true);
  68. m_gui->searchAndReplaceGroupBox->setChecked(false);
  69. m_gui->regularExpressionCheckBox->setChecked(false);
  70. auto pState = AZ::UserSettings::CreateFind<LUAEditorInternal::FindSavedState>(AZ_CRC_CE("FindInCurrent"), AZ::UserSettings::CT_LOCAL);
  71. m_gui->wrapCheckBox->setChecked((pState ? pState->m_findWrap : true));
  72. connect(m_gui->wrapCheckBox, &QCheckBox::stateChanged, this, [](int newState)
  73. {
  74. auto pState = AZ::UserSettings::CreateFind<LUAEditorInternal::FindSavedState>(AZ_CRC_CE("FindInCurrent"), AZ::UserSettings::CT_LOCAL);
  75. pState->m_findWrap = (newState == Qt::Checked);
  76. });
  77. m_bFoundFirst = false;
  78. m_bLastForward = m_gui->searchDownRadioButton->isChecked();
  79. m_bLastWrap = m_gui->wrapCheckBox->isChecked();
  80. //stored dialog state for find/replace
  81. m_bCaseSensitiveIsChecked = false;
  82. m_bWholeWordIsChecked = false;
  83. m_bRegExIsChecked = false;
  84. //find in files stuff
  85. m_bCancelFindSignal = false;
  86. m_bFindThreadRunning = false;
  87. //replace in files stuff
  88. m_bCancelReplaceSignal = false;
  89. m_bReplaceThreadRunning = false;
  90. connect(m_gui->searchWhereComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &LUAEditorFindDialog::OnSearchWhereChanged);
  91. connect(this, &LUAEditorFindDialog::triggerFindInFilesNext, this, &LUAEditorFindDialog::FindInFilesNext, Qt::QueuedConnection);
  92. connect(this, &LUAEditorFindDialog::triggerReplaceInFilesNext, this, &LUAEditorFindDialog::ReplaceInFilesNext, Qt::QueuedConnection);
  93. connect(this, &LUAEditorFindDialog::triggerFindNextInView, this, &LUAEditorFindDialog::FindNextInView, Qt::QueuedConnection);
  94. QString stylesheet(R"(QLabel[LUAEditorFindDialogLabel="true"],QGroupBox,QCheckBox,QRadioButton,QPushButton
  95. {
  96. font-size: 12px;
  97. };
  98. QLabel[IdleLabel="true"]
  99. {
  100. font-size:18px;
  101. }
  102. )");
  103. setStyleSheet(stylesheet);
  104. }
  105. LUAViewWidget* LUAEditorFindDialog::GetViewFromParent()
  106. {
  107. LUAViewWidget* pLUAViewWidget = pLUAEditorMainWindow->GetCurrentView();
  108. return pLUAViewWidget;
  109. }
  110. LUAEditorFindDialog::~LUAEditorFindDialog()
  111. {
  112. LUAViewMessages::Bus::Handler::BusDisconnect();
  113. azdestroy(m_gui);
  114. }
  115. void LUAEditorFindDialog::SetAnyDocumentsOpen(bool value)
  116. {
  117. m_bAnyDocumentsOpen = value;
  118. m_gui->searchWhereComboBox->clear();
  119. if (m_bAnyDocumentsOpen)
  120. {
  121. m_gui->searchWhereComboBox->addItem(tr("Current File"));
  122. m_gui->searchWhereComboBox->addItem(tr("All Open Files"));
  123. m_gui->searchWhereComboBox->setCurrentIndex(0);
  124. // TODO: Enable when asset database is in used
  125. //m_gui->searchWhereComboBox->addItem(tr("All LUA Assets"));
  126. // since at least one document is open take this opportunity
  127. // to copy any selected text block to the string to find in the dialog
  128. LUAViewWidget* pLUAViewWidget = GetViewFromParent();
  129. if (pLUAViewWidget)
  130. {
  131. if (pLUAViewWidget->HasSelectedText())
  132. {
  133. QString qstr = pLUAViewWidget->GetSelectedText();
  134. m_gui->txtFind->setText(qstr);
  135. }
  136. }
  137. }
  138. else
  139. {
  140. // TODO: Enable when asset database is in used
  141. //m_gui->searchWhereComboBox->addItem(tr("All LUA Assets"));
  142. m_gui->searchWhereComboBox->setCurrentIndex(0);
  143. }
  144. m_gui->txtFind->setFocus();
  145. m_gui->txtFind->selectAll();
  146. }
  147. // make the "find next" button match the file scope from the pull-down menu
  148. void LUAEditorFindDialog::OnSearchWhereChanged(int index)
  149. {
  150. if (m_bAnyDocumentsOpen)
  151. {
  152. switch (index)
  153. {
  154. case 0:
  155. m_gui->findNextButton->setEnabled(true);
  156. break;
  157. case 1:
  158. case 2:
  159. m_gui->findNextButton->setEnabled(false);
  160. break;
  161. }
  162. }
  163. m_gui->findNextButton->setDefault(m_gui->findNextButton->isEnabled());
  164. m_gui->findAllButton->setDefault(!m_gui->findNextButton->isEnabled());
  165. m_gui->findNextButton->setAutoDefault(m_gui->findNextButton->isEnabled());
  166. m_gui->findAllButton->setAutoDefault(!m_gui->findNextButton->isEnabled());
  167. }
  168. void LUAEditorFindDialog::SaveState()
  169. {
  170. if (m_bAnyDocumentsOpen)
  171. {
  172. auto pState = AZ::UserSettings::CreateFind<LUAEditorInternal::FindSavedState>(m_bWasFindInAll ? AZ_CRC_CE("LUAFindInAny") : AZ_CRC_CE("FindInCurrent"), AZ::UserSettings::CT_LOCAL);
  173. pState->m_lastSearchInFilesMode = m_gui->searchWhereComboBox->currentIndex();
  174. }
  175. }
  176. void LUAEditorFindDialog::SetToFindInAllOpen(bool findInAny)
  177. {
  178. m_bWasFindInAll = findInAny;
  179. // restore prior global mode:
  180. if (m_bAnyDocumentsOpen)
  181. {
  182. auto pState = AZ::UserSettings::Find<LUAEditorInternal::FindSavedState>(findInAny ? AZ_CRC_CE("LUAFindInAny") : AZ_CRC_CE("FindInCurrent"), AZ::UserSettings::CT_LOCAL);
  183. if (pState)
  184. {
  185. m_gui->searchWhereComboBox->setCurrentIndex(pState->m_lastSearchInFilesMode); // theres three options!
  186. m_gui->findNextButton->setEnabled(m_gui->searchWhereComboBox->currentIndex() == 0);
  187. }
  188. else
  189. {
  190. // TODO: When the asset database is in use, this test may want to default to AllLUAAssets instead
  191. m_gui->searchWhereComboBox->setCurrentIndex(findInAny ? AllOpenDocs : CurrentDoc);
  192. m_gui->findNextButton->setEnabled(m_gui->searchWhereComboBox->currentIndex() == 0);
  193. }
  194. }
  195. else
  196. {
  197. m_gui->searchWhereComboBox->setCurrentIndex(CurrentDoc); // theres only one option, no files are open
  198. m_gui->findNextButton->setEnabled(false);
  199. }
  200. m_gui->findNextButton->setDefault(m_gui->findNextButton->isEnabled());
  201. m_gui->findAllButton->setDefault(!m_gui->findNextButton->isEnabled());
  202. m_gui->findNextButton->setAutoDefault(m_gui->findNextButton->isEnabled());
  203. m_gui->findAllButton->setAutoDefault(!m_gui->findNextButton->isEnabled());
  204. m_gui->findAllButton->setEnabled(pLUAEditorMainWindow->HasAtLeastOneFileOpen());
  205. m_gui->replaceButton->setEnabled(pLUAEditorMainWindow->HasAtLeastOneFileOpen());
  206. m_gui->replaceAllButton->setEnabled(pLUAEditorMainWindow->HasAtLeastOneFileOpen());
  207. if (m_bWasFindInAll)
  208. {
  209. this->setWindowTitle("Find in files...");
  210. }
  211. else
  212. {
  213. this->setWindowTitle("Find...");
  214. }
  215. }
  216. void LUAEditorFindDialog::ResetSearch()
  217. {
  218. m_bFoundFirst = false;
  219. }
  220. // currently used to mark a wrap point for multiple-view searching
  221. void LUAEditorFindDialog::SetNewSearchStarting(bool bOverride, bool bSearchForwards)
  222. {
  223. if (bOverride && bSearchForwards)
  224. {
  225. m_gui->searchDownRadioButton->setChecked(true);
  226. }
  227. else if (bOverride)
  228. {
  229. m_gui->searchUpRadioButton->setChecked(true);
  230. }
  231. m_WrapWidget = GetViewFromParent();
  232. if (m_WrapWidget)
  233. {
  234. m_WrapWidget->GetCursorPosition(m_WrapLine, m_WrapIndex);
  235. }
  236. }
  237. void LUAEditorFindDialog::OnFindNext()
  238. {
  239. if (m_bFindThreadRunning)
  240. {
  241. m_bCancelFindSignal = true;
  242. }
  243. LUAViewWidget* pLUAViewWidget = pLUAEditorMainWindow->GetCurrentView();
  244. if (!pLUAViewWidget)
  245. {
  246. return;
  247. }
  248. if (!m_gui->txtFind->text().isEmpty())
  249. {
  250. if (m_lastSearchText != m_gui->txtFind->text() || m_bLastWrap != m_gui->wrapCheckBox->isChecked())
  251. {
  252. m_bFoundFirst = false;
  253. }
  254. //if we switched from finding forward to backward after finding a first
  255. //the the cursor will be in front of the last find, so the first finding backward
  256. //will re-find the current find (the one we are already found). This is unintuitive
  257. //to the user so instead we find backward to move the cursor to the beginning
  258. //of the current selection then call find next to actually find the next previous
  259. //occurrence as the user intended
  260. //whats strange is this only happens for find backward, find forward seems
  261. //to be smart enough to take this into account already.... so on do another find next
  262. //if searching up
  263. if (m_bFoundFirst &&
  264. m_bLastForward != m_gui->searchDownRadioButton->isChecked())
  265. {
  266. m_findOperation = pLUAViewWidget->FindFirst(m_gui->txtFind->text(),
  267. m_gui->regularExpressionCheckBox->isChecked(),
  268. m_gui->caseSensitiveCheckBox->isChecked(),
  269. m_gui->wholeWordsCheckBox->isChecked(),
  270. m_gui->wrapCheckBox->isChecked(),
  271. m_gui->searchDownRadioButton->isChecked());
  272. if (!m_gui->searchDownRadioButton->isChecked())
  273. {
  274. pLUAViewWidget->FindNext(m_findOperation);
  275. }
  276. }
  277. else if (m_bFoundFirst)
  278. {
  279. pLUAViewWidget->FindNext(m_findOperation);
  280. }
  281. else
  282. {
  283. // if moving backwards move the last result's cursor back one character
  284. // because it's placed at the end of the word and searching back from
  285. // the end of the word simply returns the word again
  286. if (!m_gui->searchDownRadioButton->isChecked())
  287. {
  288. pLUAViewWidget->MoveCursor(-1);
  289. }
  290. m_findOperation = pLUAViewWidget->FindFirst(m_gui->txtFind->text(),
  291. m_gui->regularExpressionCheckBox->isChecked(),
  292. m_gui->caseSensitiveCheckBox->isChecked(),
  293. m_gui->wholeWordsCheckBox->isChecked(),
  294. m_gui->wrapCheckBox->isChecked(),
  295. m_gui->searchDownRadioButton->isChecked());
  296. }
  297. m_lastSearchText = m_gui->txtFind->text();
  298. m_bLastForward = m_gui->searchDownRadioButton->isChecked();
  299. m_bLastWrap = m_gui->wrapCheckBox->isChecked();
  300. }
  301. else
  302. {
  303. QMessageBox::warning(this, "Error!", "You may not search for an empty string!");
  304. }
  305. if (!m_findOperation)
  306. {
  307. QMessageBox::warning(this, "Search failed!", tr("Could not find \"%1\" within/further this context.").arg(m_gui->txtFind->text()));
  308. }
  309. }
  310. void LUAEditorFindDialog::FindInView(LUAViewWidget* pLUAViewWidget, QListWidget* pCurrentFindListView)
  311. {
  312. if (!pLUAViewWidget)
  313. {
  314. return;
  315. }
  316. pLUAViewWidget->SetCursorPosition(0, 0);
  317. auto findOperation = pLUAViewWidget->FindFirst(m_gui->txtFind->text(),
  318. m_gui->regularExpressionCheckBox->isChecked(),
  319. m_gui->caseSensitiveCheckBox->isChecked(),
  320. m_gui->wholeWordsCheckBox->isChecked(),
  321. false,
  322. m_gui->searchDownRadioButton->isChecked());
  323. if (findOperation)
  324. {
  325. emit triggerFindNextInView(&findOperation, pLUAViewWidget, pCurrentFindListView);
  326. }
  327. }
  328. void LUAEditorFindDialog::FindNextInView(LUAViewWidget::FindOperation* operation, LUAViewWidget* pLUAViewWidget, QListWidget* pCurrentFindListView)
  329. {
  330. int line = 0;
  331. int index = 0;
  332. pLUAViewWidget->GetCursorPosition(line, index);
  333. QString itemText;
  334. QString lineTxt;
  335. lineTxt.setNum(line + 1); //files are 1 based
  336. AZStd::string assetFileName(pLUAViewWidget->m_Info.m_assetName + ".lua");
  337. itemText = assetFileName.c_str();
  338. itemText += "(";
  339. itemText += lineTxt;
  340. itemText += "): ";
  341. itemText += pLUAViewWidget->GetLineText(line).trimmed();
  342. QListWidgetItem* pItem = new QListWidgetItem(pCurrentFindListView);
  343. pItem->setText(itemText);
  344. //char buf[64];
  345. //pLUAViewWidget->m_Info.m_assetId.ToString(buf,AZ_ARRAY_SIZE(buf),true,true);
  346. pItem->setData(Qt::UserRole + 1, QVariant(/*buf*/ pLUAViewWidget->m_Info.m_assetId.c_str()));
  347. AZStd::string assetFileName2(pLUAViewWidget->m_Info.m_assetName + ".lua");
  348. pItem->setData(Qt::UserRole + 2, QVariant(assetFileName2.c_str()));
  349. pItem->setData(Qt::UserRole + 3, QVariant(line));
  350. pItem->setData(Qt::UserRole + 4, QVariant(index));
  351. pItem->setData(Qt::UserRole + 5, QVariant(m_gui->txtFind->text().length()));
  352. pCurrentFindListView->addItem(pItem);
  353. pLUAViewWidget->FindNext(*operation);
  354. if (operation && !m_bCancelFindSignal)
  355. {
  356. emit triggerFindNextInView(operation, pLUAViewWidget, pCurrentFindListView);
  357. }
  358. else
  359. {
  360. BusyOff();
  361. }
  362. }
  363. void LUAEditorFindDialog::OnFindAll()
  364. {
  365. if (m_bReplaceThreadRunning)
  366. {
  367. QMessageBox::warning(this, "Error!", "You may not run Find ALL while a Replace All is running!");
  368. return;
  369. }
  370. m_resultList.clear();
  371. m_bCancelFindSignal = false;
  372. m_bFindThreadRunning = true;
  373. int widgetIndex = 0;
  374. if (m_gui->m_find1RadioButton->isChecked())
  375. {
  376. widgetIndex = 0;
  377. }
  378. else if (m_gui->m_find2RadioButton->isChecked())
  379. {
  380. widgetIndex = 1;
  381. }
  382. else if (m_gui->m_find3RadioButton->isChecked())
  383. {
  384. widgetIndex = 2;
  385. }
  386. else if (m_gui->m_find4RadioButton->isChecked())
  387. {
  388. widgetIndex = 3;
  389. }
  390. pLUAEditorMainWindow->SetCurrentFindListWidget(widgetIndex);
  391. auto resultsWidget = pLUAEditorMainWindow->GetFindResultsWidget(widgetIndex);
  392. resultsWidget->Clear();
  393. pLUAEditorMainWindow->ResetSearchClicks();
  394. if (!m_gui->txtFind->text().isEmpty())
  395. {
  396. int theMode = m_gui->searchWhereComboBox->currentIndex();
  397. if (!m_bAnyDocumentsOpen)
  398. {
  399. // TODO: Enable when the asset database is used.
  400. //theMode = AllLUAAssets;
  401. }
  402. else
  403. {
  404. theMode = AllOpenDocs;
  405. }
  406. BusyOn();
  407. m_lastSearchWhere = theMode;
  408. if (theMode == CurrentDoc)
  409. {
  410. FindInFilesSetUp(theMode, resultsWidget);
  411. emit triggerFindInFilesNext(theMode);
  412. }
  413. else if (theMode == AllOpenDocs)
  414. {
  415. FindInFilesSetUp(theMode, resultsWidget);
  416. emit triggerFindInFilesNext(theMode);
  417. }
  418. else if (theMode == AllLUAAssets)
  419. {
  420. FindInFilesSetUp(theMode, resultsWidget);
  421. emit triggerFindInFilesNext(theMode);
  422. }
  423. }
  424. else
  425. {
  426. QMessageBox::warning(this, "Error!", "You may not search for an empty string!");
  427. }
  428. }
  429. void LUAEditorFindDialog::FindInFilesSetUp(int theMode, FindResults* resultsWidget)
  430. {
  431. m_FIFData.m_TotalMatchesFound = 0;
  432. m_FIFData.m_OpenView = pLUAEditorMainWindow->GetAllViews();
  433. if (theMode == CurrentDoc)
  434. {
  435. m_FIFData.m_openViewIter = m_FIFData.m_OpenView.begin();
  436. while (*m_FIFData.m_openViewIter != pLUAEditorMainWindow->GetCurrentView() && m_FIFData.m_openViewIter != m_FIFData.m_OpenView.end())
  437. {
  438. ++m_FIFData.m_openViewIter;
  439. }
  440. }
  441. else
  442. {
  443. m_FIFData.m_openViewIter = m_FIFData.m_OpenView.begin();
  444. }
  445. m_FIFData.m_resultsWidget = resultsWidget;
  446. //get a list of all the lua assets info
  447. m_dFindAllLUAAssetsInfo.clear();
  448. if (theMode == AllLUAAssets)
  449. {
  450. AZ_Assert(false, "Fix assets!");
  451. //AZ::u32 platformFeatureFlags = PLATFORM_FEATURE_FLAGS_ALL;
  452. //EditorFramework::EditorAssetCatalogMessages::Bus::BroadcastResult(
  453. // platformFeatureFlags, &EditorFramework::EditorAssetCatalogMessages::Bus::Events::GetCurrentPlatformFeatureFlags);
  454. //EditorFramework::EditorAssetCatalogMessages::Bus::Broadcast(
  455. // &EditorFramework::EditorAssetCatalogMessages::Bus::Events::FindEditorAssetsByType,
  456. // m_dFindAllLUAAssetsInfo,
  457. // AZ::ScriptAsset::StaticAssetType(),
  458. // platformFeatureFlags);
  459. }
  460. m_SearchText = m_gui->txtFind->text();
  461. m_FIFData.m_dOpenView.clear();
  462. m_FIFData.m_bWholeWordIsChecked = m_gui->wholeWordsCheckBox->isChecked();
  463. m_FIFData.m_bRegExIsChecked = m_gui->regularExpressionCheckBox->isChecked();
  464. m_FIFData.m_bCaseSensitiveIsChecked = m_gui->caseSensitiveCheckBox->isChecked();
  465. if (m_FIFData.m_bWholeWordIsChecked)
  466. {
  467. if (!m_SearchText.startsWith("\b", Qt::CaseInsensitive) &&
  468. !m_SearchText.endsWith("\b", Qt::CaseInsensitive))
  469. {
  470. m_FIFData.m_SearchText = "\\b";
  471. m_FIFData.m_SearchText += m_SearchText;
  472. m_FIFData.m_SearchText += "\\b";
  473. }
  474. }
  475. else
  476. {
  477. m_FIFData.m_SearchText = m_SearchText;
  478. }
  479. m_FIFData.m_assetInfoIter = m_dFindAllLUAAssetsInfo.begin();
  480. }
  481. void LUAEditorFindDialog::FindInFilesNext(int theMode)
  482. {
  483. // one at a time parse the open documents and store their name strings away
  484. if ((!m_bCancelFindSignal) && m_FIFData.m_openViewIter != m_FIFData.m_OpenView.end())
  485. {
  486. // this block mimics the original FindInView() call, localized to the FIF callback scheme
  487. bool syncResult = pLUAEditorMainWindow->SyncDocumentToContext((*m_FIFData.m_openViewIter)->m_Info.m_assetId);
  488. if (syncResult)
  489. {
  490. // successful sync between the QScintilla document and the raw buffer version that we need
  491. const char* buffer = nullptr;
  492. AZStd::size_t actualSize = 0;
  493. Context_DocumentManagement::Bus::Broadcast(
  494. &Context_DocumentManagement::Bus::Events::GetDocumentData,
  495. (*m_FIFData.m_openViewIter)->m_Info.m_assetId,
  496. &buffer,
  497. actualSize);
  498. /************************************************************************/
  499. /* Open files are similar but not identical to closed file processing */
  500. /************************************************************************/
  501. char* pBuf = (char*)azmalloc(actualSize + 1);
  502. char* pCur = pBuf;
  503. pCur[actualSize] = '\0';
  504. memcpy(pCur, buffer, actualSize);
  505. AZStd::vector<char*> dLines;
  506. AZStd::string assetName = (*m_FIFData.m_openViewIter)->m_Info.m_assetName + ".lua";
  507. while (aznumeric_cast<size_t>(pCur - pBuf) <= actualSize)
  508. {
  509. dLines.push_back(pCur);
  510. while (*pCur != '\n' && aznumeric_cast<size_t>(pCur - pBuf) <= actualSize)
  511. {
  512. pCur++;
  513. }
  514. if (aznumeric_cast<size_t>(pCur - pBuf) <= actualSize)
  515. {
  516. *pCur = '\0';
  517. pCur++;
  518. }
  519. }
  520. for (int line = 0; line < dLines.size(); ++line)
  521. {
  522. ResultEntry entry;
  523. entry.m_lineText = dLines[line];
  524. QRegExp regex(m_FIFData.m_SearchText, m_FIFData.m_bCaseSensitiveIsChecked ? Qt::CaseSensitive : Qt::CaseInsensitive);
  525. int index = 0;
  526. if (m_FIFData.m_bRegExIsChecked || m_FIFData.m_bWholeWordIsChecked)
  527. {
  528. index = entry.m_lineText.indexOf(regex, index);
  529. }
  530. else
  531. {
  532. index = entry.m_lineText.indexOf(m_FIFData.m_SearchText, index, m_FIFData.m_bCaseSensitiveIsChecked ? Qt::CaseSensitive : Qt::CaseInsensitive);
  533. }
  534. if (index > -1)
  535. {
  536. const auto& docInfo = (*m_FIFData.m_openViewIter)->m_Info;
  537. ++m_FIFData.m_TotalMatchesFound;
  538. QString qAssetName = assetName.c_str();
  539. if (m_resultList.find(qAssetName) == m_resultList.end())
  540. {
  541. m_resultList[qAssetName].m_assetId = docInfo.m_assetId;
  542. }
  543. entry.m_lineNumber = line + 1;
  544. entry.m_lineText = entry.m_lineText.trimmed();
  545. while (index > -1)
  546. {
  547. if (m_FIFData.m_bRegExIsChecked || m_FIFData.m_bWholeWordIsChecked)
  548. {
  549. entry.m_matches.push_back(AZStd::make_pair(index, regex.matchedLength()));
  550. }
  551. else
  552. {
  553. entry.m_matches.push_back(AZStd::make_pair(index, m_FIFData.m_SearchText.length()));
  554. }
  555. index++;
  556. if (m_FIFData.m_bRegExIsChecked || m_FIFData.m_bWholeWordIsChecked)
  557. {
  558. index = entry.m_lineText.indexOf(regex, index);
  559. }
  560. else
  561. {
  562. index = entry.m_lineText.indexOf(m_FIFData.m_SearchText, index, m_FIFData.m_bCaseSensitiveIsChecked ? Qt::CaseSensitive : Qt::CaseInsensitive);
  563. }
  564. }
  565. m_resultList[qAssetName].m_entries.push_back(entry);
  566. }
  567. }
  568. azfree(pBuf);
  569. }
  570. /************************************************************************/
  571. /* */
  572. /************************************************************************/
  573. if (theMode == CurrentDoc)
  574. {
  575. m_FIFData.m_dOpenView.push_back((*m_FIFData.m_openViewIter)->m_Info.m_assetName + ".lua");
  576. m_FIFData.m_openViewIter = m_FIFData.m_OpenView.end();
  577. }
  578. else
  579. {
  580. ++m_FIFData.m_openViewIter;
  581. if (m_FIFData.m_openViewIter == m_FIFData.m_OpenView.end())
  582. {
  583. for (AZStd::vector<LUAViewWidget*>::iterator openViewIter = m_FIFData.m_OpenView.begin();
  584. openViewIter != m_FIFData.m_OpenView.end(); ++openViewIter)
  585. {
  586. m_FIFData.m_dOpenView.push_back((*openViewIter)->m_Info.m_assetName + ".lua");
  587. }
  588. }
  589. }
  590. emit triggerFindInFilesNext(theMode);
  591. return;
  592. }
  593. if ((!m_bCancelFindSignal) && m_FIFData.m_assetInfoIter != m_dFindAllLUAAssetsInfo.end())
  594. {
  595. // from the previously prepared list of strings of names of open files, is THIS asset open?
  596. bool bIsOpen = false;
  597. for (AZStd::vector<AZStd::string>::iterator iter = m_FIFData.m_dOpenView.begin();
  598. !bIsOpen && iter != m_FIFData.m_dOpenView.end(); ++iter)
  599. {
  600. AZ_Assert(false, "check under!");
  601. //if (*iter == m_FIFData.m_assetInfoIter->m_physicalPath)
  602. if (*iter == *m_FIFData.m_assetInfoIter)
  603. {
  604. bIsOpen = true;
  605. break;
  606. }
  607. }
  608. if (!bIsOpen)
  609. {
  610. /* AZ::IO::Stream* pStream = AZ::IO::g_streamer->RegisterStream(m_FIFData.m_assetInfoIter->m_StreamName.c_str());
  611. if (!pStream)
  612. {
  613. AZ_TracePrintf("LUA", "FindInFilesNext (%s) NULL stream\n",m_FIFData.m_assetInfoIter->m_StreamName);
  614. }
  615. else
  616. {
  617. size_t fileSize = pStream->Size();
  618. char* buf = (char*)dhmalloc(fileSize+1);
  619. buf[fileSize]='\0';
  620. size_t offset=0;
  621. while(size_t bytesRead = AZ::IO::g_streamer->Read(pStream,offset,fileSize-offset,buf+offset))
  622. {
  623. offset += bytesRead;
  624. if(offset == fileSize)
  625. break;
  626. }
  627. AZ::IO::g_streamer->UnRegisterStream(pStream);
  628. char* pCur = buf;
  629. AZStd::vector<char*> dLines;
  630. while(aznumeric_cast<size_t>(pCur - buf) <= fileSize)
  631. {
  632. dLines.push_back(pCur);
  633. while(*pCur != '\n' && aznumeric_cast<size_t>(pCur - buf) <= fileSize)
  634. pCur++;
  635. if(aznumeric_cast<size_t>(pCur - buf) <= fileSize)
  636. {
  637. *pCur = '\0';
  638. pCur++;
  639. }
  640. }
  641. for(int line=0; line<dLines.size(); ++line)
  642. {
  643. ResultEntry entry;
  644. entry.m_lineText = dLines[line];
  645. QRegExp regex(m_FIFData.m_SearchText, m_FIFData.m_bCaseSensitiveIsChecked ? Qt::CaseSensitive : Qt::CaseInsensitive);
  646. int index = 0;
  647. if(m_FIFData.m_bRegExIsChecked || m_FIFData.m_bWholeWordIsChecked)
  648. index = entry.m_lineText.indexOf(regex, index);
  649. else
  650. index = entry.m_lineText.indexOf(m_FIFData.m_SearchText, index, m_FIFData.m_bCaseSensitiveIsChecked ? Qt::CaseSensitive : Qt::CaseInsensitive);
  651. if(index > -1)
  652. {
  653. ++m_FIFData.m_TotalMatchesFound;
  654. QString qAssetName = assetName.c_str();
  655. if (m_resultList.find(qAssetName) == m_resultList.end())
  656. {
  657. m_resultList[qAssetName].m_assetId = AZ::Data::AssetId::CreateNull();
  658. }
  659. entry.m_lineNumber = line;
  660. entry.m_lineText = entry.m_lineText.trimmed();
  661. while (index > -1)
  662. {
  663. if (m_FIFData.m_bRegExIsChecked || m_FIFData.m_bWholeWordIsChecked)
  664. {
  665. entry.m_matches.push_back(AZStd::make_pair(index, regex.matchedLength()));
  666. }
  667. else
  668. {
  669. entry.m_matches.push_back(AZStd::make_pair(index, m_FIFData.m_SearchText.length()));
  670. }
  671. index++;
  672. if (m_FIFData.m_bRegExIsChecked || m_FIFData.m_bWholeWordIsChecked)
  673. index = entry.m_lineText.indexOf(regex, index);
  674. else
  675. index = entry.m_lineText.indexOf(m_FIFData.m_SearchText, index, m_FIFData.m_bCaseSensitiveIsChecked ? Qt::CaseSensitive : Qt::CaseInsensitive);
  676. }
  677. m_resultList[qAssetName].m_entries.push_back(entry);
  678. }
  679. }
  680. dhfree(buf);
  681. }
  682. */
  683. }
  684. ++m_FIFData.m_assetInfoIter;
  685. emit triggerFindInFilesNext(theMode);
  686. return;
  687. }
  688. if (!m_resultList.empty() || m_bCancelFindSignal)
  689. {
  690. if (!m_bCancelFindSignal)
  691. {
  692. PostProcessOn();
  693. AZ::SystemTickBus::QueueFunction(&LUAEditorFindDialog::ProcessFindItems, this);
  694. }
  695. else
  696. {
  697. BusyOff();
  698. }
  699. m_bFindThreadRunning = false;
  700. AZ_TracePrintf("LUA", "Find In Files Matches Found = %d\n", m_FIFData.m_TotalMatchesFound);
  701. }
  702. else
  703. {
  704. m_bFindThreadRunning = false;
  705. BusyOff();
  706. }
  707. }
  708. void LUAEditorFindDialog::ProcessFindItems()
  709. {
  710. auto doc = m_FIFData.m_resultsWidget->Document();
  711. auto setFoldLevel = [&doc](int lineNum, int foldLevel, int depth)
  712. {
  713. QTBlockState blockState;
  714. auto block = doc->findBlockByNumber(lineNum);
  715. AZ_Assert(block.isValid(), "should only be setting fold level on a just added line");
  716. blockState.m_qtBlockState = block.userState();
  717. blockState.m_blockState.m_uninitialized = 0;
  718. blockState.m_blockState.m_folded = 0;
  719. blockState.m_blockState.m_foldLevel = foldLevel;
  720. blockState.m_blockState.m_syntaxHighlighterState = depth;
  721. block.setUserState(blockState.m_qtBlockState);
  722. };
  723. int currentLine = 0;
  724. m_FIFData.m_resultsWidget->Clear();
  725. QString hits;
  726. if (m_FIFData.m_TotalMatchesFound == 1)
  727. {
  728. hits.append("hit");
  729. }
  730. else
  731. {
  732. hits.append("hits");
  733. }
  734. QString files;
  735. if (m_resultList.size() == 1)
  736. {
  737. files.append("file");
  738. }
  739. else
  740. {
  741. files.append("files");
  742. }
  743. QString header("Find \"%1\" (%2 %4 in %3 %5)");
  744. header = header.arg(m_FIFData.m_SearchText).arg(m_FIFData.m_TotalMatchesFound).arg(m_resultList.size()).arg(hits).arg(files);
  745. m_FIFData.m_resultsWidget->AppendPlainText(header);
  746. setFoldLevel(currentLine, 0, 0);
  747. for (auto iter = m_resultList.begin(); iter != m_resultList.end(); ++iter)
  748. {
  749. ++currentLine;
  750. if (iter->m_entries.size() == 1)
  751. {
  752. hits = "hit";
  753. }
  754. else
  755. {
  756. hits = "hits";
  757. }
  758. QString text("\t\"%1\" (%2 %3)");
  759. text = text.arg(iter.key()).arg(iter->m_entries.size()).arg(hits);
  760. m_FIFData.m_resultsWidget->AppendPlainText(text);
  761. setFoldLevel(currentLine, 1, 1);
  762. for (auto& entry : iter->m_entries)
  763. {
  764. ++currentLine;
  765. text = "\t\t\tLine %1: %2";
  766. text = text.arg(entry.m_lineNumber).arg(entry.m_lineText);
  767. m_FIFData.m_resultsWidget->AppendPlainText(text);
  768. AZ_Assert(!entry.m_matches.empty(), "shouldn't be an entry at all if there wasn't at least one match");
  769. setFoldLevel(currentLine, 1, 2);
  770. auto block = doc->findBlockByNumber(currentLine);
  771. AZ_Assert(block.isValid(), "should only be setting data on a just added line");
  772. auto resultsWidget = m_FIFData.m_resultsWidget;
  773. auto assignAssetId = [resultsWidget](const AZStd::string& assetName, const AZStd::string& assetId) {resultsWidget->AssignAssetId(assetName, assetId); };
  774. block.setUserData(aznew FindResultsBlockInfo {iter->m_assetId, iter.key().toUtf8().data(), entry.m_lineNumber,
  775. entry.m_matches[0].first, assignAssetId});
  776. }
  777. setFoldLevel(currentLine, 0, 2);
  778. }
  779. m_FIFData.m_resultsWidget->FinishedAddingText(m_FIFData.m_SearchText, m_FIFData.m_bRegExIsChecked,
  780. m_FIFData.m_bWholeWordIsChecked, m_FIFData.m_bCaseSensitiveIsChecked);
  781. BusyOff();
  782. int findWindow = 0;
  783. if (m_gui->m_find1RadioButton->isChecked())
  784. {
  785. findWindow = 0;
  786. }
  787. else if (m_gui->m_find2RadioButton->isChecked())
  788. {
  789. findWindow = 1;
  790. }
  791. else if (m_gui->m_find3RadioButton->isChecked())
  792. {
  793. findWindow = 2;
  794. }
  795. else if (m_gui->m_find4RadioButton->isChecked())
  796. {
  797. findWindow = 3;
  798. }
  799. //get the find tab and let see it
  800. QTabWidget* pLuaFindTabWidget = pLUAEditorMainWindow->GetFindTabWidget();
  801. AZ_Assert(pLuaFindTabWidget, "LUAEditorMainWindow cant find the FindTabWidget!");
  802. pLuaFindTabWidget->show();
  803. pLuaFindTabWidget->raise();
  804. pLuaFindTabWidget->activateWindow();
  805. pLuaFindTabWidget->setFocus();
  806. pLUAEditorMainWindow->OnOpenFindView(findWindow);
  807. m_resultList.clear();
  808. }
  809. void LUAEditorFindDialog::OnCancel()
  810. {
  811. m_bCancelFindSignal = true;
  812. m_bCancelReplaceSignal = true;
  813. //this->close();
  814. }
  815. void LUAEditorFindDialog::OnReplace()
  816. {
  817. if (m_bFindThreadRunning)
  818. {
  819. m_bCancelFindSignal = true;
  820. }
  821. LUAViewWidget* pLUAViewWidget = GetViewFromParent();
  822. if (!pLUAViewWidget)
  823. {
  824. return;
  825. }
  826. if (pLUAViewWidget->HasSelectedText())
  827. {
  828. if (pLUAViewWidget->m_Info.m_bSourceControl_BusyRequestingEdit ||
  829. pLUAViewWidget->m_Info.m_bSourceControl_BusyGettingStats ||
  830. pLUAViewWidget->m_Info.m_bSourceControl_Ready == false)
  831. {
  832. AZ::SystemTickBus::QueueFunction(&LUAEditorFindDialog::OnReplace, this);
  833. }
  834. else if (!pLUAViewWidget->m_Info.m_bSourceControl_CanWrite &&
  835. pLUAViewWidget->m_Info.m_bSourceControl_CanCheckOut)
  836. {
  837. // check it out for edit
  838. Context_DocumentManagement::Bus::Broadcast(
  839. &Context_DocumentManagement::Bus::Events::DocumentCheckOutRequested, pLUAViewWidget->m_Info.m_assetId);
  840. AZ::SystemTickBus::QueueFunction(&LUAEditorFindDialog::OnReplace, this);
  841. }
  842. else if (!pLUAViewWidget->m_Info.m_bSourceControl_CanWrite)
  843. {
  844. QMessageBox::warning(this, "Error!", "Can not check out file for replace!");
  845. }
  846. else
  847. {
  848. pLUAViewWidget->ReplaceSelectedText(m_gui->txtReplaceWith->text());
  849. int startLine = 0;
  850. int startIndex = 0;
  851. pLUAViewWidget->GetCursorPosition(startLine, startIndex);
  852. pLUAViewWidget->SetCursorPosition(startLine, startIndex + 1);
  853. OnFindNext();
  854. }
  855. }
  856. else
  857. {
  858. OnFindNext();
  859. }
  860. }
  861. void LUAEditorFindDialog::ReplaceInFilesSetUp()
  862. {
  863. BusyOn();
  864. m_bReplaceThreadRunning = true;
  865. m_bCancelReplaceSignal = false;
  866. //get a list of all the lua assets info
  867. m_RIFData.m_dReplaceProcessList.clear();
  868. m_RIFData.m_dReplaceAllLUAAssetsInfo.clear();
  869. AZ_Assert(false, "Fix assets!");
  870. //AZ::u32 platformFeatureFlags = PLATFORM_FEATURE_FLAGS_ALL;
  871. //EditorFramework::EditorAssetCatalogMessages::Bus::BroadcastResult(
  872. // platformFeatureFlags, &EditorFramework::EditorAssetCatalogMessages::Bus::Events::GetCurrentPlatformFeatureFlags);
  873. //EditorFramework::EditorAssetCatalogMessages::Bus::Broadcast(
  874. // &EditorFramework::EditorAssetCatalogMessages::Bus::Events::FindEditorAssetsByType,
  875. // m_RIFData.m_dReplaceAllLUAAssetsInfo,
  876. // AZ::ScriptAsset::StaticAssetType(),
  877. // platformFeatureFlags);
  878. m_RIFData.m_OpenView = pLUAEditorMainWindow->GetAllViews();
  879. m_SearchText = m_gui->txtFind->text();
  880. m_RIFData.m_dOpenView.clear();
  881. for (auto iter = m_RIFData.m_OpenView.begin(); iter != m_RIFData.m_OpenView.end(); ++iter)
  882. {
  883. m_RIFData.m_dOpenView.push_back((*iter)->m_Info.m_assetName + ".lua");
  884. }
  885. m_RIFData.m_bWholeWordIsChecked = m_gui->wholeWordsCheckBox->isChecked();
  886. m_RIFData.m_bRegExIsChecked = m_gui->regularExpressionCheckBox->isChecked();
  887. m_RIFData.m_bCaseSensitiveIsChecked = m_gui->caseSensitiveCheckBox->isChecked();
  888. if (m_RIFData.m_bWholeWordIsChecked)
  889. {
  890. if (!m_SearchText.startsWith("\b", Qt::CaseInsensitive) &&
  891. !m_SearchText.endsWith("\b", Qt::CaseInsensitive))
  892. {
  893. m_RIFData.m_SearchText = "\\b";
  894. m_RIFData.m_SearchText += m_SearchText;
  895. m_RIFData.m_SearchText += "\\b";
  896. }
  897. }
  898. else
  899. {
  900. m_RIFData.m_SearchText = m_SearchText;
  901. }
  902. m_RIFData.m_assetInfoIter = m_RIFData.m_dReplaceAllLUAAssetsInfo.begin();
  903. }
  904. void LUAEditorFindDialog::ReplaceInFilesNext()
  905. {
  906. if (m_bCancelReplaceSignal)
  907. {
  908. BusyOff();
  909. m_bReplaceThreadRunning = false;
  910. m_bCancelReplaceSignal = false;
  911. return; // return with no timer set to call back ends this run
  912. }
  913. if (m_RIFData.m_assetInfoIter != m_RIFData.m_dReplaceAllLUAAssetsInfo.end())
  914. {
  915. //for each asset name, if the asset is not open already, open it search it and close it
  916. {
  917. bool bIsOpen = false;
  918. for (AZStd::vector<AZStd::string>::iterator openViewIter = m_RIFData.m_dOpenView.begin();
  919. openViewIter != m_RIFData.m_dOpenView.end(); ++openViewIter)
  920. {
  921. // is this the right check?
  922. if (*openViewIter == *m_RIFData.m_assetInfoIter)
  923. //if (*openViewIter == m_RIFData.m_assetInfoIter->m_physicalPath)
  924. {
  925. bIsOpen = true;
  926. break;
  927. }
  928. }
  929. if (!bIsOpen)
  930. {
  931. /*
  932. AZ::IO::Stream* pStream = AZ::IO::g_streamer->RegisterStream(m_RIFData.m_assetInfoIter->m_StreamName.c_str());
  933. if (!pStream)
  934. {
  935. AZ_TracePrintf("LUA", "ReplaceInFilesNext (%s) NULL stream\n",m_FIFData.m_assetInfoIter->m_StreamName);
  936. }
  937. else
  938. {
  939. size_t fileSize = pStream->Size();
  940. char* buf = (char*)dhmalloc(fileSize+1);
  941. buf[fileSize]=NULL;
  942. size_t offset=0;
  943. while(size_t bytesRead = AZ::IO::g_streamer->Read(pStream,offset,fileSize-offset,buf+offset))
  944. {
  945. offset += bytesRead;
  946. if(offset == fileSize)
  947. break;
  948. }
  949. AZ::IO::g_streamer->UnRegisterStream(pStream);
  950. char* pCur = buf;
  951. AZStd::vector<char*> dLines;
  952. while(aznumeric_cast<size_t>(pCur - buf) <= fileSize)
  953. {
  954. dLines.push_back(pCur);
  955. while(*pCur != '\n' && aznumeric_cast<size_t>(pCur - buf) <= fileSize)
  956. pCur++;
  957. if(aznumeric_cast<size_t>(pCur - buf) <= fileSize)
  958. {
  959. *pCur = NULL;
  960. pCur++;
  961. }
  962. }
  963. for(AZStd::size_t line=0; line<dLines.size(); ++line)
  964. {
  965. QString str(dLines[line]);
  966. QRegExp regex(m_RIFData.m_SearchText, m_bCaseSensitiveIsChecked ? Qt::CaseSensitive : Qt::CaseInsensitive);
  967. int index = 0;
  968. if(m_bRegExIsChecked || m_bWholeWordIsChecked)
  969. index = str.indexOf(regex, index);
  970. else
  971. index = str.indexOf(m_RIFData.m_SearchText, index, m_bCaseSensitiveIsChecked ? Qt::CaseSensitive : Qt::CaseInsensitive);
  972. if(index > -1)
  973. {
  974. m_RIFData.m_dReplaceProcessList.push_back(assetName.c_str());
  975. line = dLines.size();
  976. }
  977. }
  978. delete buf;
  979. }
  980. */
  981. }
  982. }
  983. ++m_RIFData.m_assetInfoIter;
  984. // are we done with the search and dispatch?
  985. if (m_RIFData.m_assetInfoIter == m_RIFData.m_dReplaceAllLUAAssetsInfo.end())
  986. {
  987. if (!m_RIFData.m_dReplaceProcessList.empty())
  988. {
  989. PostReplaceOn();
  990. QTimer::singleShot(0, this, &LUAEditorFindDialog::ProcessReplaceItems);
  991. }
  992. else
  993. {
  994. m_bReplaceThreadRunning = false;
  995. m_bCancelReplaceSignal = false;
  996. BusyOff();
  997. }
  998. return;
  999. }
  1000. QTimer::singleShot(1, this, &LUAEditorFindDialog::ReplaceInFilesNext);
  1001. }
  1002. }
  1003. void LUAEditorFindDialog::ProcessReplaceItems()
  1004. {
  1005. if (m_bCancelReplaceSignal)
  1006. {
  1007. BusyOff();
  1008. m_bReplaceThreadRunning = false;
  1009. m_bCancelReplaceSignal = false;
  1010. return; // return with no timer set to call back ends this run
  1011. }
  1012. if (!m_RIFData.m_dReplaceProcessList.empty())
  1013. {
  1014. AZStd::string assetName = AZStd::move(m_RIFData.m_dReplaceProcessList.back());
  1015. m_RIFData.m_dReplaceProcessList.pop_back();
  1016. m_RIFData.m_waitingForOpenToComplete.insert(assetName);
  1017. //split physical path into the components saved by the database
  1018. AZStd::string projectRoot, databaseRoot, databasePath, databaseFile, fileExtension;
  1019. if (!AZ::StringFunc::AssetDatabasePath::Split(assetName.c_str(), &projectRoot, &databaseRoot, &databasePath, &databaseFile, &fileExtension))
  1020. {
  1021. AZ_Warning("LUAEditorFindDialog", false, AZStd::string::format("<span severity=\"err\">Path is invalid: '%s'</span>", assetName.c_str()).c_str());
  1022. return;
  1023. }
  1024. //find it in the database
  1025. //AZStd::vector<EditorFramework::EditorAsset> dAssetInfo;
  1026. //EditorFramework::EditorAssetCatalogMessages::Bus::Broadcast(
  1027. // &EditorFramework::EditorAssetCatalogMessages::Bus::Events::FindEditorAssetsByName,
  1028. // dAssetInfo,
  1029. // databaseRoot.c_str(),
  1030. // databasePath.c_str(),
  1031. // databaseFile.c_str(),
  1032. // fileExtension.c_str());
  1033. //if (dAssetInfo.empty())
  1034. // return;
  1035. //request it be opened
  1036. //EditorFramework::AssetManagementMessages::Bus::Event(
  1037. // LUAEditor::ContextID,
  1038. // &EditorFramework::AssetManagementMessages::Bus::Events::AssetOpenRequested,
  1039. // dAssetInfo[0].m_databaseAsset.m_assetId,
  1040. // AZ::ScriptAsset::StaticAssetType());
  1041. QTimer::singleShot(0, this, &LUAEditorFindDialog::ProcessReplaceItems);
  1042. }
  1043. else
  1044. {
  1045. // getting here means we've dispatched all the requests to open the files.
  1046. if ((m_PendingReplaceInViewOperations.empty()) && (m_RIFData.m_waitingForOpenToComplete.empty()))
  1047. {
  1048. BusyOff();
  1049. m_bReplaceThreadRunning = false;
  1050. m_bCancelReplaceSignal = false;
  1051. }
  1052. }
  1053. }
  1054. void LUAEditorFindDialog::OnDataLoadedAndSet(const DocumentInfo& info, LUAViewWidget* pLUAViewWidget)
  1055. {
  1056. auto searcher = m_RIFData.m_waitingForOpenToComplete.find(info.m_assetName);
  1057. if (searcher != m_RIFData.m_waitingForOpenToComplete.end())
  1058. {
  1059. m_RIFData.m_waitingForOpenToComplete.erase(searcher);
  1060. bool wasEmpty = m_PendingReplaceInViewOperations.empty();
  1061. m_PendingReplaceInViewOperations.push_back(pLUAViewWidget);
  1062. // only start iterating the first time:
  1063. if (wasEmpty)
  1064. {
  1065. QTimer::singleShot(0, this, &LUAEditorFindDialog::OnReplaceInViewIterate);
  1066. }
  1067. }
  1068. }
  1069. void LUAEditorFindDialog::OnReplaceInViewIterate()
  1070. {
  1071. if ((m_PendingReplaceInViewOperations.empty()) && (m_RIFData.m_waitingForOpenToComplete.empty()))
  1072. {
  1073. BusyOff();
  1074. m_bCancelReplaceSignal = false;
  1075. m_bReplaceThreadRunning = false;
  1076. return;
  1077. }
  1078. LUAViewWidget* pWidget = m_PendingReplaceInViewOperations.back();
  1079. int result = ReplaceInView(pWidget);
  1080. if (m_bCancelReplaceSignal)
  1081. {
  1082. BusyOff();
  1083. m_bReplaceThreadRunning = false;
  1084. m_bCancelReplaceSignal = false;
  1085. return;
  1086. }
  1087. // any result besides -2 means we're done with this item:
  1088. if (result != -2)
  1089. {
  1090. m_PendingReplaceInViewOperations.pop_back();
  1091. }
  1092. if (!m_PendingReplaceInViewOperations.empty())
  1093. {
  1094. QTimer::singleShot(0, this, &LUAEditorFindDialog::OnReplaceInViewIterate);
  1095. }
  1096. if ((m_PendingReplaceInViewOperations.empty()) && (m_RIFData.m_waitingForOpenToComplete.empty()))
  1097. {
  1098. BusyOff();
  1099. m_bCancelReplaceSignal = false;
  1100. m_bReplaceThreadRunning = false;
  1101. return;
  1102. }
  1103. }
  1104. int LUAEditorFindDialog::ReplaceInView(LUAViewWidget* pLUAViewWidget)
  1105. {
  1106. if (m_bCancelReplaceSignal)
  1107. {
  1108. BusyOff();
  1109. m_bReplaceThreadRunning = false;
  1110. m_bCancelReplaceSignal = false;
  1111. return 0;
  1112. }
  1113. if (pLUAViewWidget->m_Info.m_bSourceControl_BusyRequestingEdit ||
  1114. pLUAViewWidget->m_Info.m_bSourceControl_BusyGettingStats ||
  1115. pLUAViewWidget->m_Info.m_bSourceControl_Ready == false)
  1116. {
  1117. return -2;
  1118. }
  1119. else if (!pLUAViewWidget->m_Info.m_bSourceControl_CanWrite &&
  1120. pLUAViewWidget->m_Info.m_bSourceControl_CanCheckOut)
  1121. {
  1122. // check it out for edit
  1123. Context_DocumentManagement::Bus::Broadcast(
  1124. &Context_DocumentManagement::Bus::Events::DocumentCheckOutRequested, pLUAViewWidget->m_Info.m_assetId);
  1125. return -2;
  1126. }
  1127. else if (!pLUAViewWidget->m_Info.m_bSourceControl_CanWrite)
  1128. {
  1129. QMessageBox::warning(this, "Can not check out file!", (pLUAViewWidget->m_Info.m_assetName + ".lua").c_str());
  1130. return -1;
  1131. }
  1132. int count = 0;
  1133. pLUAViewWidget->SetCursorPosition(0, 0);
  1134. const int advance = m_gui->txtReplaceWith->text().size();
  1135. int firstFoundLine = 0;
  1136. int firstFoundIndex = 0;
  1137. if (pLUAViewWidget->FindFirst(m_gui->txtFind->text(),
  1138. m_gui->regularExpressionCheckBox->isChecked(),
  1139. m_gui->caseSensitiveCheckBox->isChecked(),
  1140. m_gui->wholeWordsCheckBox->isChecked(),
  1141. m_gui->wrapCheckBox->isChecked(),
  1142. m_gui->searchDownRadioButton->isChecked()))
  1143. {
  1144. pLUAViewWidget->GetCursorPosition(firstFoundLine, firstFoundIndex);
  1145. pLUAViewWidget->ReplaceSelectedText(m_gui->txtReplaceWith->text());
  1146. count++;
  1147. while (pLUAViewWidget->FindFirst(m_gui->txtFind->text(),
  1148. m_gui->regularExpressionCheckBox->isChecked(),
  1149. m_gui->caseSensitiveCheckBox->isChecked(),
  1150. m_gui->wholeWordsCheckBox->isChecked(),
  1151. m_gui->wrapCheckBox->isChecked(),
  1152. m_gui->searchDownRadioButton->isChecked()))
  1153. {
  1154. int startLine = 0;
  1155. int startIndex = 0;
  1156. pLUAViewWidget->GetCursorPosition(startLine, startIndex);
  1157. if (startLine == firstFoundLine && startIndex == firstFoundIndex)
  1158. {
  1159. break;
  1160. }
  1161. pLUAViewWidget->ReplaceSelectedText(m_gui->txtReplaceWith->text());
  1162. pLUAViewWidget->GetCursorPosition(startLine, startIndex);
  1163. pLUAViewWidget->SetCursorPosition(startLine, startIndex + advance);
  1164. count++;
  1165. }
  1166. }
  1167. return count;
  1168. }
  1169. void LUAEditorFindDialog::OnReplaceAll()
  1170. {
  1171. if (m_bFindThreadRunning)
  1172. {
  1173. QMessageBox::warning(this, "Error!", "You may not run Replace ALL while a Find All is running!");
  1174. return;
  1175. }
  1176. if (!m_gui->txtFind->text().isEmpty())
  1177. {
  1178. int theMode = m_gui->searchWhereComboBox->currentIndex();
  1179. if (!m_bAnyDocumentsOpen)
  1180. {
  1181. theMode = AllLUAAssets;
  1182. }
  1183. m_lastSearchWhere = theMode;
  1184. if (theMode == CurrentDoc)
  1185. {
  1186. BusyOn();
  1187. m_PendingReplaceInViewOperations.push_back(pLUAEditorMainWindow->GetCurrentView());
  1188. QTimer::singleShot(0, this, &LUAEditorFindDialog::OnReplaceInViewIterate);
  1189. }
  1190. else if (theMode == AllOpenDocs || theMode == AllLUAAssets)
  1191. {
  1192. BusyOn();
  1193. AZStd::vector<LUAViewWidget*> dOpenView = pLUAEditorMainWindow->GetAllViews();
  1194. for (AZStd::vector<LUAViewWidget*>::iterator openViewIter = dOpenView.begin(); openViewIter != dOpenView.end(); ++openViewIter)
  1195. {
  1196. m_PendingReplaceInViewOperations.push_back(*openViewIter);
  1197. }
  1198. QTimer::singleShot(0, this, &LUAEditorFindDialog::OnReplaceInViewIterate);
  1199. if (theMode == AllLUAAssets)
  1200. {
  1201. ReplaceInFilesSetUp();
  1202. emit triggerReplaceInFilesNext();
  1203. }
  1204. }
  1205. }
  1206. else
  1207. {
  1208. QMessageBox::warning(this, "Error!", "You may not replace an empty string!");
  1209. }
  1210. }
  1211. void LUAEditorFindDialog::BusyOn()
  1212. {
  1213. m_gui->cancelButton->setEnabled(true);
  1214. m_gui->busyLabel->setText("Working");
  1215. }
  1216. void LUAEditorFindDialog::BusyOff()
  1217. {
  1218. m_gui->cancelButton->setEnabled(false);
  1219. m_gui->busyLabel->setText("Idle");
  1220. }
  1221. void LUAEditorFindDialog::PostProcessOn()
  1222. {
  1223. m_gui->cancelButton->setEnabled(false);
  1224. m_gui->busyLabel->setText("List Prep");
  1225. }
  1226. void LUAEditorFindDialog::PostReplaceOn()
  1227. {
  1228. BusyOff();
  1229. m_bReplaceThreadRunning = false;
  1230. m_gui->cancelButton->setEnabled(true);
  1231. m_gui->busyLabel->setText("Replacing");
  1232. }
  1233. void LUAEditorFindDialog::showEvent(QShowEvent* event)
  1234. {
  1235. raise();
  1236. QDialog::showEvent(event);
  1237. }
  1238. void LUAEditorFindDialog::Reflect(AZ::ReflectContext* reflection)
  1239. {
  1240. LUAEditorInternal::FindSavedState::Reflect(reflection);
  1241. }
  1242. }//namespace LUAEditor
  1243. #include <Source/LUA/moc_LUAEditorFindDialog.cpp>