OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4DownloadDlg.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2007-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2013-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 // HTTP download dialog; downloads a file
17 
18 #include "C4Include.h"
19 #include "gui/C4DownloadDlg.h"
20 
21 #include "lib/C4Log.h"
23 
25 
26 C4DownloadDlg::C4DownloadDlg(const char *szDLType) : C4GUI::Dialog(C4GUI_ProgressDlgWdt, 100, FormatString(LoadResStr("IDS_CTL_DL_TITLE"), szDLType).getData(), false), szError(nullptr)
27 {
28 #ifdef HAVE_WINSOCK
29  fWinSock = AcquireWinSock();
30 #endif
31  // add all elements - will be reposisioned when text is displayed
33  AddElement(pStatusLabel = new C4GUI::Label("", C4Rect(), ACenter, C4GUI_MessageFontClr, &::GraphicsResource.TextFont, false));
34  pProgressBar = nullptr; // created when necessary
35  AddElement(pCancelBtn = new C4GUI::CancelButton(C4Rect()));
36 }
37 
39 {
40 #ifdef HAVE_WINSOCK
41  if (fWinSock) ReleaseWinSock();
42 #endif
43 }
44 
45 void C4DownloadDlg::SetStatus(const char *szNewText, int32_t iProgressPercent)
46 {
47  // get positions
49  // place icon
50  pIcon->SetBounds(caMain.GetFromLeft(C4GUI_IconWdt, C4GUI_IconWdt));
51  // place message label
52  // use text with line breaks
53  StdStrBuf sMsgBroken;
54  int iMsgHeight = ::GraphicsResource.TextFont.BreakMessage(szNewText, caMain.GetInnerWidth(), &sMsgBroken, true);
55  pStatusLabel->SetBounds(caMain.GetFromTop(iMsgHeight));
56  pStatusLabel->SetText(sMsgBroken.getData());
57  // place progress bar
58  if (iProgressPercent >= 0)
59  {
60  if (!pProgressBar)
61  {
62  AddElement(pProgressBar = new C4GUI::ProgressBar(caMain.GetFromTop(C4GUI_ProgressDlgPBHgt)));
63  }
64  else
65  {
66  pProgressBar->SetBounds(caMain.GetFromTop(C4GUI_ProgressDlgPBHgt));
67  }
68  pProgressBar->SetProgress(iProgressPercent);
69  }
70  else
71  {
72  // no progress desired
73  if (pProgressBar) { delete pProgressBar; pProgressBar = nullptr; }
74  }
75  // place button
76  caMain.ExpandLeft(C4GUI_DefDlgIndent*2 + C4GUI_IconWdt);
77  C4GUI::ComponentAligner caButtonArea(caMain.GetFromTop(C4GUI_ButtonAreaHgt), 0,0);
78  pCancelBtn->SetBounds(caButtonArea.GetCentered(C4GUI_DefButtonWdt, C4GUI_ButtonHgt));
79  pCancelBtn->SetToolTip(LoadResStr("IDS_DL_CANCEL"));
80  // resize to actually needed size
81  SetClientSize(GetClientRect().Wdt, GetClientRect().Hgt - caMain.GetHeight());
82 }
83 
85 {
86  // continue query process
87  if (!HTTPClient.Execute())
88  {
89  // query aborted
90  Close(false);
91  return;
92  }
93  if (!HTTPClient.isBusy())
94  {
95  // download done or aborted
96  Close(HTTPClient.isSuccess());
97  return;
98  }
99  StdStrBuf sStatus; int32_t iProgress = -1;
100  StdStrBuf sSize("");
101  // download in progress: Update status
102  if (!HTTPClient.isConnected())
103  {
104  // still connecting
105  sStatus.Ref(LoadResStr("IDS_DL_STATUSCONNECTING"));
106  }
107  else
108  {
109  // header received?
110  size_t iSize = HTTPClient.getTotalSize();
111  if (!iSize)
112  {
113  // file size unknown: No header received.
114  sStatus.Ref(LoadResStr("IDS_PRC_CONNECTED"));
115  }
116  else
117  {
118  // file size known: Download in progress
119  sStatus.Ref(LoadResStr("IDS_CTL_DL_PROGRESS"));
120  if (iSize <= 1024)
121  sSize.Format(" (%ld Bytes)", (long)iSize);
122  else if (iSize <= 1024*1024)
123  sSize.Format(" (%ld KB)", (long)(iSize/1024));
124  else
125  sSize.Format(" (%ld MB)", (long)(iSize/1024/1024));
126  iProgress = int64_t(100) * HTTPClient.getDownloadedSize() / iSize;
127  }
128  }
129  const char *szStatusString = LoadResStr("IDS_PRC_DOWNLOADINGFILE");
130  SetStatus(FormatString(szStatusString, GetFilename(HTTPClient.getRequest())).getData(), iProgress );
131 }
132 
134 {
135  // user cancelled
136  HTTPClient.Cancel(LoadResStr("IDS_ERR_USERCANCEL"));
137 }
138 
140 {
141  // own error?
142  if (szError) return szError;
143  // fallback to HTTP error
144  return HTTPClient.GetError();
145 }
146 
147 bool C4DownloadDlg::ShowModal(C4GUI::Screen *pScreen, const char *szURL, const char *szSaveAsFilename)
148 {
149  // reset error
150  szError = nullptr;
151  // initial text
152  if (!HTTPClient.Init()) return false;
153  HTTPClient.SetServer(szURL);
154  // show dlg
155  if (!Show(pScreen, true)) return false;
156  // start query
157  if (!HTTPClient.Query(nullptr, true)) return false;
158  // first time status update
159  OnIdle();
160  // cycle until query is finished or aborted
161  if (!DoModal()) return false;
162  // download successful: Save file
163  if (!HTTPClient.getResultBin().SaveToFile(szSaveAsFilename))
164  {
165  // file saving failed
166  szError = LoadResStr("IDS_FAIL_SAVE");
167  return false;
168  }
169  return true;
170 }
171 
172 bool C4DownloadDlg::DownloadFile(const char *szDLType, C4GUI::Screen *pScreen, const char *szURL, const char *szSaveAsFilename, const char *szNotFoundMessage)
173 {
174  // log it
175  LogF(LoadResStr("IDS_PRC_DOWNLOADINGFILE"), szURL);
176  // show download dialog
177  C4DownloadDlg *pDlg = new C4DownloadDlg(szDLType);
178  if (!pDlg->ShowModal(pScreen, szURL, szSaveAsFilename))
179  {
180  // show an appropriate error
181  const char *szError = pDlg->GetError();
182  if (!szError || !*szError) szError = LoadResStr("IDS_PRC_UNKOWNERROR");
183  StdStrBuf sError;
184  sError.Format(LoadResStr("IDS_PRC_DOWNLOADERROR"), GetFilename(szURL), szError);
185  // it's a 404: display extended message
186  if (SSearch(szError, "404") && szNotFoundMessage)
187  { sError.Append("|"); sError.Append(szNotFoundMessage); }
188  // display message
189  pScreen->ShowMessageModal(sError.getData(), FormatString(LoadResStr("IDS_CTL_DL_TITLE"), szDLType).getData(), C4GUI::MessageDialog::btnOK, C4GUI::Ico_Error, nullptr);
190  delete pDlg;
191  return false;
192  }
193  LogF(LoadResStr("IDS_PRC_DOWNLOADCOMPLETE"), szURL);
194  delete pDlg;
195  return true;
196 }
char * GetFilename(char *szPath)
Definition: StdFile.cpp:55
const char * getData() const
Definition: StdBuf.h:450
#define C4GUI_ButtonAreaHgt
Definition: C4Gui.h:113
#define C4GUI_ButtonHgt
Definition: C4Gui.h:111
virtual bool Execute(int iMaxTime, pollfd *readyfds)
void SetClientSize(int32_t iToWdt, int32_t iToHgt)
#define C4GUI_MessageFontClr
Definition: C4Gui.h:43
C4Network2HTTPClient HTTPClient
virtual void UserClose(bool fOK)
const char * SSearch(const char *szString, const char *szIndex)
Definition: Standard.cpp:333
void SetToolTip(const char *szNewTooltip, bool is_immediate=false)
Definition: C4Gui.cpp:410
virtual void OnIdle()
void Close(bool fOK)
Definition: C4Rect.h:29
virtual const char * GetError() const
Definition: C4NetIO.h:285
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:181
virtual C4Rect & GetClientRect()
Definition: C4Gui.h:864
void AddElement(Element *pChild)
size_t getDownloadedSize() const
C4GraphicsResource GraphicsResource
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
void Cancel(const char *szReason)
static bool DownloadFile(const char *szDLType, C4GUI::Screen *pScreen, const char *szURL, const char *szSaveAsFilename, const char *szNotFoundMessage=nullptr)
bool Show(Screen *pOnScreen, bool fCB)
bool ShowMessageModal(const char *szMessage, const char *szCaption, DWORD dwButtons, Icons icoIcon, int32_t *piConfigDontShowAgainSetting=nullptr)
#define C4GUI_IconWdt
Definition: C4Gui.h:93
const int ACenter
Definition: C4Surface.h:43
size_t getTotalSize() const
#define C4GUI_ProgressDlgPBHgt
Definition: C4Gui.h:137
virtual ~C4DownloadDlg()
void Append(const char *pnData, size_t iChars)
Definition: StdBuf.h:527
C4DownloadDlg(const char *szDLType)
#define C4GUI_DefButtonWdt
Definition: C4Gui.h:114
bool ShowModal(C4GUI::Screen *pScreen, const char *szURL, const char *szSaveAsFilename)
const char * GetError()
bool SaveToFile(const char *szFile) const
Definition: StdBuf.cpp:60
std::tuple< std::string, int > BreakMessage(const char *szMsg, int iWdt, bool fCheckMarkup, float fZoom=1.0f)
void Ref(const char *pnData)
Definition: StdBuf.h:463
#define C4GUI_ProgressDlgWdt
Definition: C4Gui.h:130
const char * getRequest() const
void SetBounds(const C4Rect &rcNewBound)
Definition: C4Gui.h:446
#define C4GUI_DefDlgIndent
Definition: C4Gui.h:132
virtual bool Init(uint16_t iPort=addr_t::IPPORT_NONE)
Definition: C4NetIO.cpp:824
void SetProgress(int32_t iToProgress)
Definition: C4Gui.h:578
bool Query(const StdBuf &Data, bool fBinary)
bool LogF(const char *strMessage,...)
Definition: C4Log.cpp:253
bool SetServer(const char *szServerAddress)
void SetText(const char *szToText, bool fAllowHotkey=true)
Definition: C4GuiLabels.cpp:74
int iSize
Definition: TstC4NetIO.cpp:35
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:277
const StdBuf & getResultBin() const