Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

495 lines
14 KiB

  1. //====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
  2. //
  3. // This is a helper class designed to help with the chains of modal dialogs
  4. // encountered when trying to open or save a particular file
  5. //
  6. //=============================================================================
  7. #include "vgui_controls/FileOpenStateMachine.h"
  8. #include "tier1/keyvalues.h"
  9. #include "vgui_controls/FileOpenDialog.h"
  10. #include "vgui_controls/MessageBox.h"
  11. #include "vgui_controls/perforcefilelistframe.h"
  12. #include "vgui_controls/savedocumentquery.h"
  13. #include "filesystem.h"
  14. #include "p4lib/ip4.h"
  15. #include "tier2/tier2.h"
  16. #include "tier0/icommandline.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. using namespace vgui;
  20. //-----------------------------------------------------------------------------
  21. // Constructor
  22. //-----------------------------------------------------------------------------
  23. FileOpenStateMachine::FileOpenStateMachine( vgui::Panel *pParent, IFileOpenStateMachineClient *pClient ) : BaseClass( pParent, "FileOpenStateMachine" )
  24. {
  25. m_pClient = pClient;
  26. m_CompletionState = SUCCESSFUL;
  27. m_CurrentState = STATE_NONE;
  28. m_pContextKeyValues = NULL;
  29. SetVisible( false );
  30. }
  31. FileOpenStateMachine::~FileOpenStateMachine()
  32. {
  33. CleanUpContextKeyValues();
  34. }
  35. //-----------------------------------------------------------------------------
  36. // Cleans up keyvalues
  37. //-----------------------------------------------------------------------------
  38. void FileOpenStateMachine::CleanUpContextKeyValues()
  39. {
  40. if ( m_pContextKeyValues )
  41. {
  42. m_pContextKeyValues->deleteThis();
  43. m_pContextKeyValues = NULL;
  44. }
  45. }
  46. //-----------------------------------------------------------------------------
  47. // Returns the state machine completion state
  48. //-----------------------------------------------------------------------------
  49. FileOpenStateMachine::CompletionState_t FileOpenStateMachine::GetCompletionState()
  50. {
  51. return m_CompletionState;
  52. }
  53. //-----------------------------------------------------------------------------
  54. // Utility to set the completion state
  55. //-----------------------------------------------------------------------------
  56. void FileOpenStateMachine::SetCompletionState( FileOpenStateMachine::CompletionState_t state )
  57. {
  58. m_CompletionState = state;
  59. if ( m_CompletionState == IN_PROGRESS )
  60. return;
  61. m_CurrentState = STATE_NONE;
  62. KeyValues *kv = new KeyValues( "FileStateMachineFinished" );
  63. kv->SetInt( "completionState", m_CompletionState );
  64. kv->SetBool( "wroteFile", m_bWroteFile );
  65. kv->SetString( "fullPath", m_FileName.Get() );
  66. kv->SetString( "fileType", m_bIsOpeningFile ? m_OpenFileType.Get() : m_SaveFileType.Get() );
  67. if ( m_pContextKeyValues )
  68. {
  69. kv->AddSubKey( m_pContextKeyValues );
  70. m_pContextKeyValues = NULL;
  71. }
  72. PostActionSignal( kv );
  73. }
  74. //-----------------------------------------------------------------------------
  75. // Called by the message box in OverwriteFileDialog
  76. //-----------------------------------------------------------------------------
  77. void FileOpenStateMachine::OnOverwriteFile( )
  78. {
  79. CheckOutDialog( );
  80. }
  81. void FileOpenStateMachine::OnCancelOverwriteFile( )
  82. {
  83. SetCompletionState( FILE_NOT_OVERWRITTEN );
  84. }
  85. //-----------------------------------------------------------------------------
  86. // Shows the overwrite existing file dialog
  87. //-----------------------------------------------------------------------------
  88. void FileOpenStateMachine::OverwriteFileDialog( )
  89. {
  90. if ( !g_pFullFileSystem->FileExists( m_FileName ) )
  91. {
  92. CheckOutDialog( );
  93. return;
  94. }
  95. m_CurrentState = STATE_SHOWING_OVERWRITE_DIALOG;
  96. char pBuf[1024];
  97. Q_snprintf( pBuf, sizeof(pBuf), "File already exists. Overwrite it?\n\n\"%s\"\n", m_FileName.Get() );
  98. vgui::MessageBox *pMessageBox = new vgui::MessageBox( "Overwrite Existing File?", pBuf, GetParent() );
  99. pMessageBox->AddActionSignalTarget( this );
  100. pMessageBox->SetOKButtonVisible( true );
  101. pMessageBox->SetOKButtonText( "Yes" );
  102. pMessageBox->SetCancelButtonVisible( true );
  103. pMessageBox->SetCancelButtonText( "No" );
  104. pMessageBox->SetCloseButtonVisible( false );
  105. pMessageBox->SetCommand( new KeyValues( "OverwriteFile" ) );
  106. pMessageBox->SetCancelCommand( new KeyValues( "CancelOverwriteFile" ) );
  107. pMessageBox->DoModal();
  108. }
  109. //-----------------------------------------------------------------------------
  110. // Used to open a particular file in perforce, and deal with all the lovely dialogs
  111. //-----------------------------------------------------------------------------
  112. void FileOpenStateMachine::OnFileSelectionCancelled()
  113. {
  114. if ( m_CurrentState == STATE_SHOWING_SAVE_DIALOG )
  115. {
  116. SetCompletionState( FILE_SAVE_NAME_NOT_SPECIFIED );
  117. return;
  118. }
  119. if ( m_CurrentState == STATE_SHOWING_OPEN_DIALOG )
  120. {
  121. SetCompletionState( FILE_OPEN_NAME_NOT_SPECIFIED );
  122. return;
  123. }
  124. Assert(0);
  125. }
  126. //-----------------------------------------------------------------------------
  127. // Used to open a particular file in perforce, and deal with all the lovely dialogs
  128. //-----------------------------------------------------------------------------
  129. void FileOpenStateMachine::OnFileSelected( KeyValues *pKeyValues )
  130. {
  131. if ( m_CurrentState == STATE_SHOWING_SAVE_DIALOG )
  132. {
  133. m_FileName = pKeyValues->GetString( "fullpath" );
  134. const char *pFilterInfo = pKeyValues->GetString( "filterinfo" );
  135. if ( pFilterInfo )
  136. {
  137. m_SaveFileType = pFilterInfo;
  138. }
  139. OverwriteFileDialog();
  140. return;
  141. }
  142. if ( m_CurrentState == STATE_SHOWING_OPEN_DIALOG )
  143. {
  144. m_FileName = pKeyValues->GetString( "fullpath" );
  145. const char *pFilterInfo = pKeyValues->GetString( "filterinfo" );
  146. if ( pFilterInfo )
  147. {
  148. m_OpenFileType = pFilterInfo;
  149. }
  150. ReadFile( );
  151. return;
  152. }
  153. Assert(0);
  154. }
  155. //-----------------------------------------------------------------------------
  156. // Writes the file out
  157. //-----------------------------------------------------------------------------
  158. void FileOpenStateMachine::WriteFile()
  159. {
  160. m_CurrentState = STATE_WRITING_FILE;
  161. if ( !m_pClient->OnWriteFileToDisk( m_FileName, m_SaveFileType, m_pContextKeyValues ) )
  162. {
  163. SetCompletionState( ERROR_WRITING_FILE );
  164. return;
  165. }
  166. m_bWroteFile = true;
  167. if ( m_bShowPerforceDialogs )
  168. {
  169. m_CurrentState = STATE_SHOWING_PERFORCE_ADD_DIALOG;
  170. ShowPerforceQuery( GetParent(), m_FileName, this, NULL, PERFORCE_ACTION_FILE_ADD );
  171. return;
  172. }
  173. if ( !m_bIsOpeningFile )
  174. {
  175. SetCompletionState( SUCCESSFUL );
  176. return;
  177. }
  178. OpenFileDialog();
  179. }
  180. //-----------------------------------------------------------------------------
  181. // Called by the message box in MakeFileWriteableDialog
  182. //-----------------------------------------------------------------------------
  183. void FileOpenStateMachine::OnMakeFileWriteable( )
  184. {
  185. if ( !g_pFullFileSystem->SetFileWritable( m_FileName, true ) )
  186. {
  187. SetCompletionState( ERROR_MAKING_FILE_WRITEABLE );
  188. return;
  189. }
  190. WriteFile();
  191. }
  192. void FileOpenStateMachine::OnCancelMakeFileWriteable( )
  193. {
  194. SetCompletionState( FILE_NOT_MADE_WRITEABLE );
  195. }
  196. //-----------------------------------------------------------------------------
  197. // Shows the make file writeable dialog
  198. //-----------------------------------------------------------------------------
  199. void FileOpenStateMachine::MakeFileWriteableDialog( )
  200. {
  201. // If the file is writeable, write it!
  202. if ( !g_pFullFileSystem->FileExists( m_FileName ) || g_pFullFileSystem->IsFileWritable( m_FileName ) )
  203. {
  204. WriteFile();
  205. return;
  206. }
  207. // If it's in perforce, and not checked out, then we must abort.
  208. bool bIsInPerforce = p4->IsFileInPerforce( m_FileName );
  209. bool bIsOpened = ( p4->GetFileState( m_FileName ) != P4FILE_UNOPENED );
  210. if ( bIsInPerforce && !bIsOpened )
  211. {
  212. SetCompletionState( FILE_NOT_CHECKED_OUT );
  213. return;
  214. }
  215. m_CurrentState = STATE_SHOWING_MAKE_FILE_WRITEABLE_DIALOG;
  216. char pBuf[1024];
  217. Q_snprintf( pBuf, sizeof(pBuf), "Encountered read-only file. Should it be made writeable?\n\n\"%s\"\n", m_FileName.Get() );
  218. vgui::MessageBox *pMessageBox = new vgui::MessageBox( "Make File Writeable?", pBuf, GetParent() );
  219. pMessageBox->AddActionSignalTarget( this );
  220. pMessageBox->SetOKButtonVisible( true );
  221. pMessageBox->SetOKButtonText( "Yes" );
  222. pMessageBox->SetCancelButtonVisible( true );
  223. pMessageBox->SetCancelButtonText( "No" );
  224. pMessageBox->SetCloseButtonVisible( false );
  225. pMessageBox->SetCommand( new KeyValues( "MakeFileWriteable" ) );
  226. pMessageBox->SetCancelCommand( new KeyValues( "CancelMakeFileWriteable" ) );
  227. pMessageBox->DoModal();
  228. }
  229. //-----------------------------------------------------------------------------
  230. // Called when ShowPerforceQuery completes
  231. //-----------------------------------------------------------------------------
  232. void FileOpenStateMachine::OnPerforceQueryCompleted( KeyValues *pKeyValues )
  233. {
  234. if ( m_CurrentState == STATE_SHOWING_CHECK_OUT_DIALOG )
  235. {
  236. if ( pKeyValues->GetInt( "operationPerformed" ) == 0 )
  237. {
  238. SetCompletionState( FILE_NOT_CHECKED_OUT );
  239. return;
  240. }
  241. MakeFileWriteableDialog();
  242. return;
  243. }
  244. if ( m_CurrentState == STATE_SHOWING_PERFORCE_ADD_DIALOG )
  245. {
  246. if ( !m_bIsOpeningFile )
  247. {
  248. SetCompletionState( SUCCESSFUL );
  249. return;
  250. }
  251. OpenFileDialog();
  252. return;
  253. }
  254. Assert(0);
  255. }
  256. //-----------------------------------------------------------------------------
  257. // Used to open a particular file in perforce, and deal with all the lovely dialogs
  258. //-----------------------------------------------------------------------------
  259. void FileOpenStateMachine::CheckOutDialog( )
  260. {
  261. if ( m_bShowPerforceDialogs )
  262. {
  263. m_CurrentState = STATE_SHOWING_CHECK_OUT_DIALOG;
  264. ShowPerforceQuery( GetParent(), m_FileName, this, NULL, PERFORCE_ACTION_FILE_EDIT );
  265. return;
  266. }
  267. WriteFile();
  268. }
  269. //-----------------------------------------------------------------------------
  270. // These 3 messages come from the savedocumentquery dialog
  271. //-----------------------------------------------------------------------------
  272. void FileOpenStateMachine::OnSaveFile()
  273. {
  274. if ( !m_FileName[0] || !Q_IsAbsolutePath( m_FileName ) )
  275. {
  276. m_CurrentState = STATE_SHOWING_SAVE_DIALOG;
  277. FileOpenDialog *pDialog = new FileOpenDialog( GetParent(), "Save As", false );
  278. m_pClient->SetupFileOpenDialog( pDialog, false, m_SaveFileType, m_pContextKeyValues );
  279. pDialog->AddActionSignalTarget( this );
  280. pDialog->DoModal( );
  281. return;
  282. }
  283. CheckOutDialog( );
  284. }
  285. void FileOpenStateMachine::OnMarkNotDirty()
  286. {
  287. if ( !m_bIsOpeningFile )
  288. {
  289. SetCompletionState( SUCCESSFUL );
  290. return;
  291. }
  292. // Jump right to opening the file
  293. OpenFileDialog( );
  294. }
  295. void FileOpenStateMachine::OnCancelSaveDocument()
  296. {
  297. SetCompletionState( FILE_SAVE_CANCELLED );
  298. }
  299. //-----------------------------------------------------------------------------
  300. // Show the save document query dialog
  301. //-----------------------------------------------------------------------------
  302. void FileOpenStateMachine::ShowSaveQuery( )
  303. {
  304. m_CurrentState = STATE_SHOWING_SAVE_DIRTY_FILE_DIALOG;
  305. ShowSaveDocumentQuery( GetParent(), m_FileName, m_SaveFileType, 0, this, NULL );
  306. }
  307. //-----------------------------------------------------------------------------
  308. // Used to save a specified file, and deal with all the lovely dialogs
  309. //-----------------------------------------------------------------------------
  310. void FileOpenStateMachine::SaveFile( KeyValues *pContextKeyValues, const char *pFileName, const char *pFileType, int nFlags )
  311. {
  312. CleanUpContextKeyValues();
  313. SetCompletionState( IN_PROGRESS );
  314. m_pContextKeyValues = pContextKeyValues;
  315. m_FileName = pFileName;
  316. m_SaveFileType = pFileType;
  317. m_OpenFileType = NULL;
  318. m_OpenFileName = NULL;
  319. // Clear the P4 dialog flag for SDK users and licensees without Perforce
  320. if ( g_pFullFileSystem->IsSteam() || CommandLine()->FindParm( "-nop4" ) )
  321. {
  322. nFlags &= ~FOSM_SHOW_PERFORCE_DIALOGS;
  323. }
  324. m_bShowPerforceDialogs = ( nFlags & FOSM_SHOW_PERFORCE_DIALOGS ) != 0;
  325. m_bShowSaveQuery = ( nFlags & FOSM_SHOW_SAVE_QUERY ) != 0;
  326. m_bIsOpeningFile = false;
  327. m_bWroteFile = false;
  328. if ( m_bShowSaveQuery )
  329. {
  330. ShowSaveQuery();
  331. return;
  332. }
  333. OnSaveFile();
  334. }
  335. //-----------------------------------------------------------------------------
  336. // Reads the file in
  337. //-----------------------------------------------------------------------------
  338. void FileOpenStateMachine::ReadFile()
  339. {
  340. m_CurrentState = STATE_READING_FILE;
  341. if ( !m_pClient->OnReadFileFromDisk( m_FileName, m_OpenFileType, m_pContextKeyValues ) )
  342. {
  343. SetCompletionState( ERROR_READING_FILE );
  344. return;
  345. }
  346. SetCompletionState( SUCCESSFUL );
  347. }
  348. //-----------------------------------------------------------------------------
  349. // Shows the open file dialog
  350. //-----------------------------------------------------------------------------
  351. void FileOpenStateMachine::OpenFileDialog( )
  352. {
  353. m_CurrentState = STATE_SHOWING_OPEN_DIALOG;
  354. if ( m_OpenFileName.IsEmpty() )
  355. {
  356. FileOpenDialog *pDialog = new FileOpenDialog( GetParent(), "Open", true );
  357. m_pClient->SetupFileOpenDialog( pDialog, true, m_OpenFileType, m_pContextKeyValues );
  358. pDialog->AddActionSignalTarget( this );
  359. pDialog->DoModal( );
  360. }
  361. else
  362. {
  363. m_FileName = m_OpenFileName;
  364. ReadFile();
  365. }
  366. }
  367. //-----------------------------------------------------------------------------
  368. // Opens a file, saves an existing one if necessary
  369. //-----------------------------------------------------------------------------
  370. void FileOpenStateMachine::OpenFile( const char *pOpenFileType, KeyValues *pContextKeyValues, const char *pSaveFileName, const char *pSaveFileType, int nFlags )
  371. {
  372. CleanUpContextKeyValues();
  373. SetCompletionState( IN_PROGRESS );
  374. m_pContextKeyValues = pContextKeyValues;
  375. m_FileName = pSaveFileName;
  376. m_SaveFileType = pSaveFileType;
  377. m_OpenFileType = pOpenFileType;
  378. m_OpenFileName = NULL;
  379. m_bShowPerforceDialogs = ( nFlags & FOSM_SHOW_PERFORCE_DIALOGS ) != 0;
  380. m_bShowSaveQuery = ( nFlags & FOSM_SHOW_SAVE_QUERY ) != 0;
  381. m_bIsOpeningFile = true;
  382. m_bWroteFile = false;
  383. if ( m_bShowSaveQuery )
  384. {
  385. ShowSaveQuery();
  386. return;
  387. }
  388. OpenFileDialog();
  389. }
  390. //-----------------------------------------------------------------------------
  391. // Version of OpenFile that skips browsing for a particular file to open
  392. //-----------------------------------------------------------------------------
  393. void FileOpenStateMachine::OpenFile( const char *pOpenFileName, const char *pOpenFileType, KeyValues *pContextKeyValues, const char *pSaveFileName, const char *pSaveFileType, int nFlags )
  394. {
  395. CleanUpContextKeyValues();
  396. SetCompletionState( IN_PROGRESS );
  397. m_pContextKeyValues = pContextKeyValues;
  398. m_FileName = pSaveFileName;
  399. m_SaveFileType = pSaveFileType;
  400. m_OpenFileType = pOpenFileType;
  401. m_bShowPerforceDialogs = ( nFlags & FOSM_SHOW_PERFORCE_DIALOGS ) != 0;
  402. m_bShowSaveQuery = ( nFlags & FOSM_SHOW_SAVE_QUERY ) != 0;
  403. m_bIsOpeningFile = true;
  404. m_bWroteFile = false;
  405. m_OpenFileName = pOpenFileName;
  406. if ( m_bShowSaveQuery )
  407. {
  408. ShowSaveQuery();
  409. return;
  410. }
  411. OpenFileDialog();
  412. }