changed: New label formatting that more logically drops separators.
[xbmc:xbmc-antiquated.git] / xbmc / GUIWindowGameSaves.cpp
1 /*\r
2  *      Copyright (C) 2005-2007 Team XboxMediaCenter\r
3  *      http://www.xboxmediacenter.com\r
4  *\r
5  *  This Program is free software; you can redistribute it and/or modify\r
6  *  it under the terms of the GNU General Public License as published by\r
7  *  the Free Software Foundation; either version 2, or (at your option)\r
8  *  any later version.\r
9  *\r
10  *  This Program is distributed in the hope that it will be useful,\r
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
13  *  GNU General Public License for more details.\r
14  *\r
15  *  You should have received a copy of the GNU General Public License\r
16  *  along with GNU Make; see the file COPYING.  If not, write to\r
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
18  *  http://www.gnu.org/copyleft/gpl.html\r
19  *\r
20  */\r
21 \r
22 #include "stdafx.h"\r
23 #include "GUIWindowGameSaves.h"\r
24 #include "util.h"\r
25 #include "FileSystem/ZipManager.h"\r
26 #include "GUIDialogFileBrowser.h"\r
27 #include "GUIWindowFileManager.h"\r
28 #include "GUIPassword.h"\r
29 #include <fstream>\r
30 //#include "Utils\HTTP.h"  // For Download Function\r
31 #include "utils/LabelFormatter.h"\r
32 #include "mediamanager.h"\r
33 \r
34 using namespace XFILE;\r
35 using namespace DIRECTORY;\r
36 \r
37 #define CONTROL_BTNVIEWASICONS     2\r
38 #define CONTROL_BTNSORTBY          3\r
39 #define CONTROL_BTNSORTASC         4\r
40 #define CONTROL_LIST              50\r
41 #define CONTROL_THUMBS            51\r
42 #define CONTROL_LABELFILES        12\r
43 \r
44 CGUIWindowGameSaves::CGUIWindowGameSaves()\r
45 : CGUIMediaWindow(WINDOW_GAMESAVES, "MyGameSaves.xml")\r
46 {\r
47 \r
48 }\r
49 \r
50 CGUIWindowGameSaves::~CGUIWindowGameSaves()\r
51 {\r
52 }\r
53 \r
54 void CGUIWindowGameSaves::GoParentFolder()\r
55 {\r
56   if (m_history.GetParentPath() == m_vecItems.m_strPath)\r
57     m_history.RemoveParentPath();\r
58   CStdString strParent=m_history.RemoveParentPath();\r
59   CStdString strOldPath(m_vecItems.m_strPath);\r
60   CStdString strPath(m_strParentPath);\r
61   VECSHARES shares;\r
62   bool bIsSourceName = false;\r
63 \r
64   SetupShares();\r
65   m_rootDir.GetShares(shares);\r
66 \r
67   int iIndex = CUtil::GetMatchingShare(strPath, shares, bIsSourceName);\r
68 \r
69   if (iIndex > -1)\r
70   {\r
71     if (strPath.size() == 2)\r
72       if (strPath[1] == ':')\r
73         CUtil::AddSlashAtEnd(strPath);\r
74     Update(strPath);\r
75   }\r
76   else\r
77   {\r
78     Update(strParent);\r
79   }\r
80   if (!g_guiSettings.GetBool("filelists.fulldirectoryhistory"))\r
81       m_history.RemoveSelectedItem(strOldPath); //Delete current path\r
82 }\r
83 \r
84 bool CGUIWindowGameSaves::OnClick(int iItem)\r
85 {\r
86   if (!m_vecItems[iItem]->m_bIsFolder)\r
87   {\r
88     OnPopupMenu(iItem);\r
89     return true;\r
90   }\r
91 \r
92   return CGUIMediaWindow::OnClick(iItem);\r
93 }\r
94 \r
95 bool CGUIWindowGameSaves::OnMessage(CGUIMessage& message)\r
96 {\r
97   switch ( message.GetMessage() )\r
98   {\r
99   case GUI_MSG_CLICKED:\r
100     {\r
101       if (message.GetSenderId() == CONTROL_BTNSORTBY)\r
102       {\r
103         if (CGUIMediaWindow::OnMessage(message))\r
104         {\r
105           CGUIViewState::LABEL_MASKS labelMasks;\r
106           m_guiState->GetSortMethodLabelMasks(labelMasks);\r
107           CLabelFormatter formatter("", labelMasks.m_strLabel2File);\r
108           for (int i=0;i<m_vecItems.Size();++i)\r
109             formatter.FormatLabel2(m_vecItems[i]);\r
110           return true;\r
111         }\r
112         else\r
113           return false;\r
114       }\r
115     }\r
116   case GUI_MSG_WINDOW_INIT:\r
117     {\r
118       CStdString strDestination = message.GetStringParam();\r
119       if (m_vecItems.m_strPath == "?")\r
120         m_vecItems.m_strPath = "E:\\udata";\r
121 \r
122       m_rootDir.SetMask("/");\r
123       VECSHARES shares;\r
124       bool bIsSourceName = false;\r
125       SetupShares();\r
126       m_rootDir.GetShares(shares);\r
127       int iIndex = CUtil::GetMatchingShare(strDestination, shares, bIsSourceName);\r
128       // if bIsSourceName == True,   chances are its "Local GameSaves" or something else :D)\r
129       if (iIndex > -1)\r
130       {\r
131         bool bDoStuff = true;\r
132         if (shares[iIndex].m_iHasLock == 2)\r
133         {\r
134           CFileItem item(shares[iIndex]);\r
135           if (!g_passwordManager.IsItemUnlocked(&item,"myprograms"))\r
136           {\r
137             m_vecItems.m_strPath = ""; // no u don't\r
138             bDoStuff = false;\r
139             CLog::Log(LOGINFO, "  Failure! Failed to unlock destination path: %s", strDestination.c_str());\r
140           }\r
141         }\r
142         if (bIsSourceName)\r
143         {\r
144           m_vecItems.m_strPath=shares[iIndex].strPath;\r
145         }\r
146         else if (CDirectory::Exists(strDestination))\r
147         {\r
148           m_vecItems.m_strPath = strDestination;\r
149         }\r
150       }\r
151       return CGUIMediaWindow::OnMessage(message);\r
152     }\r
153     break;\r
154   }\r
155   return CGUIMediaWindow::OnMessage(message);\r
156 }\r
157 \r
158 \r
159 bool CGUIWindowGameSaves::OnPlayMedia(int iItem)\r
160 {\r
161   CFileItem* pItem=m_vecItems[iItem];\r
162   CStdString strPath = pItem->m_strPath;\r
163   return true;\r
164 }\r
165 \r
166 bool CGUIWindowGameSaves::GetDirectory(const CStdString& strDirectory, CFileItemList& items)\r
167 {\r
168   if (!m_rootDir.GetDirectory(strDirectory,items,false))\r
169     return false;\r
170 \r
171   CLog::Log(LOGDEBUG,"CGUIWindowGameSaves::GetDirectory (%s)", strDirectory.c_str());\r
172 \r
173   CStdString strParentPath;\r
174   bool bParentExists = CUtil::GetParentPath(strDirectory, strParentPath);\r
175   if (bParentExists)\r
176     m_strParentPath = strParentPath;\r
177   else\r
178     m_strParentPath = "";\r
179   //FILE *newfile;\r
180   CFile newfile;\r
181   // flatten any folders with 1 save\r
182   DWORD dwTick=timeGetTime();\r
183   bool bProgressVisible = false;\r
184   CGUIDialogProgress* m_dlgProgress = (CGUIDialogProgress*)m_gWindowManager.GetWindow(WINDOW_DIALOG_PROGRESS);\r
185   CGUIViewState::LABEL_MASKS labelMasks;\r
186   m_guiState->GetSortMethodLabelMasks(labelMasks);\r
187   CLabelFormatter formatter("", labelMasks.m_strLabel2File);\r
188   for (int i = 0; i < items.Size(); i++)\r
189   {\r
190     CFileItem *item = items[i];\r
191 \r
192     if (!bProgressVisible && timeGetTime()-dwTick>1500 && m_dlgProgress)\r
193     { // tag loading takes more then 1.5 secs, show a progress dialog\r
194       m_dlgProgress->SetHeading(189);\r
195       m_dlgProgress->SetLine(0, 20120);\r
196       m_dlgProgress->SetLine(1,"");\r
197       m_dlgProgress->SetLine(2, "");\r
198       m_dlgProgress->StartModal();\r
199       bProgressVisible = true;\r
200     }\r
201     if (!item->m_bIsFolder)\r
202     {\r
203       items.Remove(i);\r
204       i--;\r
205       continue;\r
206     }\r
207 \r
208     if (item->m_bIsFolder && !item->IsParentFolder() && !item->m_bIsShareOrDrive)\r
209     {\r
210       if (bProgressVisible)\r
211       {\r
212         m_dlgProgress->SetLine(2,item->GetLabel());\r
213         m_dlgProgress->Progress();\r
214       }\r
215 \r
216       CStdString titlemetaXBX;\r
217       CStdString savemetaXBX;\r
218       CUtil::AddFileToFolder(item->m_strPath, "titlemeta.xbx", titlemetaXBX);\r
219       CUtil::AddFileToFolder(item->m_strPath, "savemeta.xbx", savemetaXBX);\r
220       int domode = 0;\r
221       if (CFile::Exists(titlemetaXBX))\r
222       {\r
223         domode = 1;\r
224         newfile.Open(titlemetaXBX);\r
225       }\r
226       else if (CFile::Exists(savemetaXBX))\r
227       {\r
228         domode = 2;\r
229         newfile.Open(savemetaXBX);\r
230       }\r
231       if (domode != 0)\r
232       {\r
233         WCHAR *yo = new WCHAR[(int)newfile.GetLength()+1];\r
234         newfile.Read(yo,newfile.GetLength());\r
235 \r
236         CStdString strDescription;\r
237         g_charsetConverter.utf16toUTF8(yo, strDescription);\r
238         int poss = strDescription.find("Name=");\r
239         if (poss == -1)\r
240         {\r
241           char *chrtxt = new char[(int)newfile.GetLength()+2];\r
242           newfile.Seek(0);\r
243           newfile.Read(chrtxt,newfile.GetLength());\r
244           chrtxt[(int)newfile.GetLength()+1] = '\n';\r
245           g_charsetConverter.utf16toUTF8(chrtxt, strDescription);\r
246           poss = strDescription.find("Name=");\r
247         }\r
248         newfile.Close();\r
249         int pose = strDescription.find("\n",poss+1);\r
250         strDescription = strDescription.Mid(poss+5, pose - poss-6);\r
251         strDescription = CUtil::MakeLegalFileName(strDescription,false);\r
252 \r
253         if (domode == 1)\r
254         {\r
255           CLog::Log(LOGDEBUG, "Loading GameSave info from %s,  data is %s, located at %i to %i",  titlemetaXBX.c_str(),strDescription.c_str(),poss,pose);\r
256           // check for subfolders with savemeta.xbx\r
257           CFileItemList items2;\r
258           m_rootDir.GetDirectory(item->m_strPath,items2,false);\r
259           int j;\r
260           for (j=0;j<items2.Size();++j)\r
261           {\r
262             if (items2[j]->m_bIsFolder)\r
263             {\r
264               CStdString strPath;\r
265               CUtil::AddFileToFolder(items2[j]->m_strPath,"savemeta.xbx",strPath);\r
266               if (CFile::Exists(strPath))\r
267                 break;\r
268             }\r
269           }\r
270           if (j == items2.Size())\r
271           {\r
272             item->m_bIsFolder = false;\r
273             item->m_strPath = titlemetaXBX;\r
274           }\r
275         }\r
276         else\r
277         {\r
278           CLog::Log(LOGDEBUG, "Loading GameSave info from %s,  data is %s, located at %i to %i", savemetaXBX.c_str(),strDescription.c_str(),poss,pose);\r
279           item->m_bIsFolder = false;\r
280           item->m_strPath = savemetaXBX;\r
281         }\r
282         item->GetMusicInfoTag()->SetTitle(item->GetLabel());  // Note we set ID as the TITLE to save code makign a SORT ID and a ID varible to the FileItem\r
283         item->SetLabel(strDescription);\r
284         item->SetIconImage("defaultProgram.png");\r
285         formatter.FormatLabel2(item);\r
286         item->SetLabelPreformated(true);\r
287       }\r
288     }\r
289   }\r
290   items.SetGameSavesThumbs();\r
291   if (bProgressVisible)\r
292     m_dlgProgress->Close();\r
293 \r
294   return true;\r
295 }\r
296 \r
297 /*\r
298 bool CGUIWindowGameSaves::DownloadSaves(CFileItem item)\r
299 {\r
300   CStdString strURL;\r
301   string theHtml;\r
302   CHTTP http;\r
303 \r
304   strURL.Format("http://www.xboxmediacenter.com/xbmc.php?gameid=%s",item.m_musicInfoTag.GetTitle()); // donnos little fix the unleashx.php is broken (content lenght is greater then lenght sent)\r
305   if (http.Get(strURL, theHtml))\r
306   {\r
307     TiXmlDocument gsXml;\r
308     gsXml.Parse(theHtml.c_str(), 0);\r
309     TiXmlElement *pRootElement = gsXml.RootElement();\r
310     if (pRootElement)\r
311     {\r
312       if (pRootElement->Value())\r
313       {\r
314         if (strcmpi(pRootElement->Value(),"xboxsaves") == 0)\r
315         {\r
316           TiXmlElement* pGame = pRootElement->FirstChildElement("game");\r
317           if (pGame)\r
318           {\r
319             TiXmlElement* pSave = pGame->FirstChildElement("save");\r
320             if (pSave->Value())\r
321             {\r
322               CGUIDialogSelect *pDlg = (CGUIDialogSelect*)m_gWindowManager.GetWindow(WINDOW_DIALOG_SELECT);\r
323               if (pDlg)\r
324               {\r
325                 pDlg->SetHeading(20320);\r
326                 pDlg->Reset();\r
327                 pDlg->EnableButton(false);\r
328                 std::vector<CStdString> vecSaveUrl;\r
329                 vecSaveUrl.clear();\r
330                 while (pSave)\r
331                 {\r
332                   if (pSave->Value())\r
333                   {\r
334                       pDlg->Add(pSave->Attribute("desc"));\r
335                       vecSaveUrl.push_back(pSave->Attribute("url"));\r
336                   }\r
337                   pSave = pSave->NextSiblingElement("save");\r
338                 }\r
339                 //pDlg->Sort();\r
340                 pDlg->DoModal();\r
341                 int iSelectedSave = pDlg->GetSelectedLabel();\r
342                 CLog::Log(LOGINFO,"GSM: %i",  iSelectedSave);\r
343                 if (iSelectedSave > -1)\r
344                 {\r
345                   CLog::Log(LOGINFO,"GSM vecSaveUrl[i] : %s",  vecSaveUrl[iSelectedSave].c_str());\r
346                   if (http.Download(vecSaveUrl[iSelectedSave], "Z:\\gamesave.zip"))\r
347                   {\r
348                     if (g_ZipManager.ExtractArchive("Z:\\gamesave.zip","E:\\"))\r
349                     {\r
350                       ::DeleteFile("E:\\gameid.ini");   // delete file E:\\gameid.ini artifcat continatin info about the save we got\r
351                       CGUIDialogOK::ShowAndGetInput(20317, 0, 20318, 0);\r
352                       return true;\r
353                     }\r
354                   }\r
355                   CGUIDialogOK::ShowAndGetInput(20317, 0, 20319, 0);  // Download Failed\r
356                   CLog::Log(LOGINFO,"GSM: Failed to download: %s",  vecSaveUrl[iSelectedSave].c_str());\r
357                   return true;\r
358                 }\r
359                 CLog::Log(LOGINFO,"GSM: Action Aborted: %s",  vecSaveUrl[iSelectedSave].c_str());\r
360                 return true;\r
361               }\r
362             }\r
363           }\r
364         }\r
365       }\r
366     }\r
367   }\r
368   return false;\r
369 }*/\r
370 \r
371 void CGUIWindowGameSaves::GetContextButtons(int itemNumber, CContextButtons &buttons)\r
372 {\r
373   if (itemNumber < 0 || itemNumber >= m_vecItems.Size() || m_vecItems[itemNumber]->m_bIsShareOrDrive)\r
374     return;\r
375 \r
376   buttons.Add(CONTEXT_BUTTON_COPY, 115);\r
377   buttons.Add(CONTEXT_BUTTON_MOVE, 116);\r
378   buttons.Add(CONTEXT_BUTTON_DELETE, 117);\r
379   // Only add if we are on E:\udata\\r
380   // CStdString strFileName = CUtil::GetFileName(m_vecItems[iItem]->m_strPath);\r
381   // if (!strFileName.Equals("savemeta.xbx"))\r
382   //   buttons.Add(CONTEXT_BUTTON_DOWNLOAD, 20317);\r
383 }\r
384 \r
385 bool CGUIWindowGameSaves::OnContextButton(int itemNumber, CONTEXT_BUTTON button)\r
386 {\r
387   if (itemNumber < 0 || itemNumber >= m_vecItems.Size())\r
388     return false;\r
389 \r
390   VECSHARES localMemShares;\r
391   CVirtualDirectory dir;\r
392 \r
393   CShare share;\r
394   share.strName = "Local GameSaves";\r
395   share.strPath = "E:\\udata";\r
396   share.m_iDriveType = SHARE_TYPE_LOCAL;\r
397   localMemShares.push_back(share);\r
398 \r
399   g_mediaManager.GetLocalDrives(localMemShares);\r
400   dir.SetShares(localMemShares);\r
401   dir.GetShares(localMemShares);\r
402 \r
403   CFileItem item(*m_vecItems[itemNumber]);\r
404   CStdString strFileName = CUtil::GetFileName(item.m_strPath);\r
405   switch (button)\r
406   {\r
407   case CONTEXT_BUTTON_COPY:\r
408     {\r
409       CStdString value;\r
410       if (!CGUIDialogFileBrowser::ShowAndGetDirectory(localMemShares, g_localizeStrings.Get(20328), value, true))\r
411         return true;\r
412       if (!CGUIDialogYesNo::ShowAndGetInput(120,123,20022,20022)) // enable me for confirmation\r
413         return true;\r
414       CStdString path;\r
415       if (strFileName.Equals("savemeta.xbx") || strFileName.Equals("titlemeta.xbx") )\r
416       {\r
417         CUtil::GetDirectory(m_vecItems[itemNumber]->m_strPath,item.m_strPath);\r
418         item.m_bIsFolder = true;\r
419         // first copy the titlemeta dir\r
420         CFileItemList items2;\r
421         CStdString strParent;\r
422         CUtil::GetParentPath(item.m_strPath,strParent);\r
423         CDirectory::GetDirectory(strParent,items2);\r
424         CUtil::AddFileToFolder(value,CUtil::GetFileName(strParent),path);\r
425         for (int j=0;j<items2.Size();++j)\r
426         {\r
427           if (!items2[j]->m_bIsFolder)\r
428           {\r
429             CStdString strDest;\r
430             CUtil::AddFileToFolder(path,CUtil::GetFileName(items2[j]->m_strPath),strDest);\r
431             CFile::Cache(items2[j]->m_strPath,strDest);\r
432           }\r
433         }\r
434         CUtil::AddFileToFolder(path,CUtil::GetFileName(item.m_strPath),path);\r
435       }\r
436       else\r
437       {\r
438         CUtil::AddFileToFolder(value,CUtil::GetFileName(item.m_strPath),path);\r
439       }\r
440 \r
441       item.Select(true);\r
442       CLog::Log(LOGDEBUG,"GSM: Copy of folder confirmed for folder %s",  item.m_strPath.c_str());\r
443       CGUIWindowFileManager::CopyItem(&item,path,true);\r
444       return true;\r
445     }\r
446   case CONTEXT_BUTTON_DELETE:\r
447     {\r
448       CLog::Log(LOGDEBUG,"GSM: Deletion of folder confirmed for folder %s", item.m_strPath.c_str());\r
449       if (strFileName.Equals("savemeta.xbx") || strFileName.Equals("titlemeta.xbx"))\r
450       {\r
451         CUtil::GetDirectory(m_vecItems[itemNumber]->m_strPath,item.m_strPath);\r
452         item.m_bIsFolder = true;\r
453       }\r
454 \r
455       item.Select(true);\r
456       if (CGUIWindowFileManager::DeleteItem(&item))\r
457       {\r
458         CFile::Delete(item.GetThumbnailImage());\r
459         Update(m_vecItems.m_strPath);\r
460       }\r
461       return true;\r
462     }\r
463   case CONTEXT_BUTTON_MOVE:\r
464     {\r
465       CStdString value;\r
466       if (!CGUIDialogFileBrowser::ShowAndGetDirectory(localMemShares, g_localizeStrings.Get(20328) , value,true))\r
467         return true;\r
468       if (!CGUIDialogYesNo::ShowAndGetInput(121,124,20022,20022)) // enable me for confirmation\r
469         return true;\r
470       CStdString path;\r
471       if (strFileName.Equals("savemeta.xbx") || strFileName.Equals("titlemeta.xbx"))\r
472       {\r
473         CUtil::GetDirectory(m_vecItems[itemNumber]->m_strPath,item.m_strPath);\r
474         item.m_bIsFolder = true;\r
475         // first copy the titlemeta dir\r
476         CFileItemList items2;\r
477         CStdString strParent;\r
478         CUtil::GetParentPath(item.m_strPath,strParent);\r
479         CDirectory::GetDirectory(strParent,items2);\r
480 \r
481         CUtil::AddFileToFolder(value,CUtil::GetFileName(strParent),path);\r
482         for (int j=0;j<items2.Size();++j) // only copy main title stuff\r
483         {\r
484           if (!items2[j]->m_bIsFolder)\r
485           {\r
486             CStdString strDest;\r
487             CUtil::AddFileToFolder(path,CUtil::GetFileName(items2[j]->m_strPath),strDest);\r
488             CFile::Cache(items2[j]->m_strPath,strDest);\r
489           }\r
490         }\r
491 \r
492         CUtil::AddFileToFolder(path,CUtil::GetFileName(item.m_strPath),path);\r
493       }\r
494       else\r
495       {\r
496         CUtil::AddFileToFolder(value,CUtil::GetFileName(item.m_strPath),path);\r
497       }\r
498 \r
499       item.Select(true);\r
500       CLog::Log(LOGDEBUG,"GSM: Copy of folder confirmed for folder %s",  item.m_strPath.c_str());\r
501       CGUIWindowFileManager::MoveItem(&item,path,true);\r
502       CDirectory::Remove(item.m_strPath);\r
503       Update(m_vecItems.m_strPath);\r
504       return true;\r
505     }\r
506   /*\r
507   case CONTEXT_BUTTON_DOWNLOAD:\r
508     {\r
509       CHTTP http;\r
510       CStdString strURL;\r
511       if (item.m_musicInfoTag.GetTitle() != "")\r
512       {\r
513         if (!CGUIWindowGameSaves::DownloadSaves(item))\r
514         {\r
515           CGUIDialogOK::ShowAndGetInput(20317, 0, 20321, 0);  // No Saves found\r
516           CLog::Log(LOGINFO,"GSM: No saves available for game on internet: %s",  item.GetLabel().c_str());\r
517         }\r
518         else\r
519         {\r
520           Update(m_vecItems.m_strPath);\r
521         }\r
522       }\r
523       return true;\r
524     }*/\r
525   }\r
526   return false;\r
527 }