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 
22 
24 
25 C4DownloadDlg::C4DownloadDlg(const char *szDLType) : C4GUI::Dialog(C4GUI_ProgressDlgWdt, 100, FormatString(LoadResStr("IDS_CTL_DL_TITLE"), szDLType).getData(), false), szError(nullptr)
26 {
27 #ifdef HAVE_WINSOCK
28  fWinSock = AcquireWinSock();
29 #endif
30  // add all elements - will be reposisioned when text is displayed
32  AddElement(pStatusLabel = new C4GUI::Label("", C4Rect(), ACenter, C4GUI_MessageFontClr, &::GraphicsResource.TextFont, false));
33  pProgressBar = nullptr; // created when necessary
34  AddElement(pCancelBtn = new C4GUI::CancelButton(C4Rect()));
35 }
36 
38 {
39 #ifdef HAVE_WINSOCK
40  if (fWinSock) ReleaseWinSock();
41 #endif
42 }
43 
44 void C4DownloadDlg::SetStatus(const char *szNewText, int32_t iProgressPercent)
45 {
46  // get positions
48  // place icon
49  pIcon->SetBounds(caMain.GetFromLeft(C4GUI_IconWdt, C4GUI_IconWdt));
50  // place message label
51  // use text with line breaks
52  StdStrBuf sMsgBroken;
53  int iMsgHeight = ::GraphicsResource.TextFont.BreakMessage(szNewText, caMain.GetInnerWidth(), &sMsgBroken, true);
54  pStatusLabel->SetBounds(caMain.GetFromTop(iMsgHeight));
55  pStatusLabel->SetText(sMsgBroken.getData());
56  // place progress bar
57  if (iProgressPercent >= 0)
58  {
59  if (!pProgressBar)
60  {
61  AddElement(pProgressBar = new C4GUI::ProgressBar(caMain.GetFromTop(C4GUI_ProgressDlgPBHgt)));
62  }
63  else
64  {
65  pProgressBar->SetBounds(caMain.GetFromTop(C4GUI_ProgressDlgPBHgt));
66  }
67  pProgressBar->SetProgress(iProgressPercent);
68  }
69  else
70  {
71  // no progress desired
72  if (pProgressBar) { delete pProgressBar; pProgressBar = nullptr; }
73  }
74  // place button
75  caMain.ExpandLeft(C4GUI_DefDlgIndent*2 + C4GUI_IconWdt);
76  C4GUI::ComponentAligner caButtonArea(caMain.GetFromTop(C4GUI_ButtonAreaHgt), 0,0);
77  pCancelBtn->SetBounds(caButtonArea.GetCentered(C4GUI_DefButtonWdt, C4GUI_ButtonHgt));
78  pCancelBtn->SetToolTip(LoadResStr("IDS_DL_CANCEL"));
79  // resize to actually needed size
80  SetClientSize(GetClientRect().Wdt, GetClientRect().Hgt - caMain.GetHeight());
81 }
82 
84 {
85  // continue query process
86  if (!HTTPClient.Execute())
87  {
88  // query aborted
89  Close(false);
90  return;
91  }
92  if (!HTTPClient.isBusy())
93  {
94  // download done or aborted
95  Close(HTTPClient.isSuccess());
96  return;
97  }
98  StdStrBuf sStatus; int32_t iProgress = -1;
99  StdStrBuf sSize("");
100  // download in progress: Update status
101  if (!HTTPClient.isConnected())
102  {
103  // still connecting
104  sStatus.Ref(LoadResStr("IDS_DL_STATUSCONNECTING"));
105  }
106  else
107  {
108  // header received?
109  size_t iSize = HTTPClient.getTotalSize();
110  if (!iSize)
111  {
112  // file size unknown: No header received.
113  sStatus.Ref(LoadResStr("IDS_PRC_CONNECTED"));
114  }
115  else
116  {
117  // file size known: Download in progress
118  sStatus.Ref(LoadResStr("IDS_CTL_DL_PROGRESS"));
119  if (iSize <= 1024)
120  sSize.Format(" (%ld Bytes)", (long)iSize);
121  else if (iSize <= 1024*1024)
122  sSize.Format(" (%ld KB)", (long)(iSize/1024));
123  else
124  sSize.Format(" (%ld MB)", (long)(iSize/1024/1024));
125  iProgress = int64_t(100) * HTTPClient.getDownloadedSize() / iSize;
126  }
127  }
128  const char *szStatusString = LoadResStr("IDS_PRC_DOWNLOADINGFILE");
129  SetStatus(FormatString(szStatusString, GetFilename(HTTPClient.getRequest())).getData(), iProgress );
130 }
131 
133 {
134  // user cancelled
135  HTTPClient.Cancel(LoadResStr("IDS_ERR_USERCANCEL"));
136 }
137 
139 {
140  // own error?
141  if (szError) return szError;
142  // fallback to HTTP error
143  return HTTPClient.GetError();
144 }
145 
146 bool C4DownloadDlg::ShowModal(C4GUI::Screen *pScreen, const char *szURL, const char *szSaveAsFilename)
147 {
148  // reset error
149  szError = nullptr;
150  // initial text
151  if (!HTTPClient.Init()) return false;
152  HTTPClient.SetServer(szURL);
153  // show dlg
154  if (!Show(pScreen, true)) return false;
155  // start query
156  if (!HTTPClient.Query(nullptr, true)) return false;
157  // first time status update
158  OnIdle();
159  // cycle until query is finished or aborted
160  if (!DoModal()) return false;
161  // download successful: Save file
162  if (!HTTPClient.getResultBin().SaveToFile(szSaveAsFilename))
163  {
164  // file saving failed
165  szError = LoadResStr("IDS_FAIL_SAVE");
166  return false;
167  }
168  return true;
169 }
170 
171 bool C4DownloadDlg::DownloadFile(const char *szDLType, C4GUI::Screen *pScreen, const char *szURL, const char *szSaveAsFilename, const char *szNotFoundMessage)
172 {
173  // log it
174  LogF(LoadResStr("IDS_PRC_DOWNLOADINGFILE"), szURL);
175  // show download dialog
176  C4DownloadDlg *pDlg = new C4DownloadDlg(szDLType);
177  if (!pDlg->ShowModal(pScreen, szURL, szSaveAsFilename))
178  {
179  // show an appropriate error
180  const char *szError = pDlg->GetError();
181  if (!szError || !*szError) szError = LoadResStr("IDS_PRC_UNKOWNERROR");
182  StdStrBuf sError;
183  sError.Format(LoadResStr("IDS_PRC_DOWNLOADERROR"), GetFilename(szURL), szError);
184  // it's a 404: display extended message
185  if (SSearch(szError, "404") && szNotFoundMessage)
186  { sError.Append("|"); sError.Append(szNotFoundMessage); }
187  // display message
188  pScreen->ShowMessageModal(sError.getData(), FormatString(LoadResStr("IDS_CTL_DL_TITLE"), szDLType).getData(), C4GUI::MessageDialog::btnOK, C4GUI::Ico_Error, nullptr);
189  delete pDlg;
190  return false;
191  }
192  LogF(LoadResStr("IDS_PRC_DOWNLOADCOMPLETE"), szURL);
193  delete pDlg;
194  return true;
195 }
char * GetFilename(char *szPath)
Definition: StdFile.cpp:45
const char * getData() const
Definition: StdBuf.h:442
#define C4GUI_ButtonAreaHgt
Definition: C4Gui.h:113
#define C4GUI_ButtonHgt
Definition: C4Gui.h:111
void SetClientSize(int32_t iToWdt, int32_t iToHgt)
#define C4GUI_MessageFontClr
Definition: C4Gui.h:43
C4Network2HTTPClient HTTPClient
const char * SSearch(const char *szString, const char *szIndex)
Definition: Standard.cpp:341
void SetToolTip(const char *szNewTooltip, bool is_immediate=false)
Definition: C4Gui.cpp:409
void Close(bool fOK)
Definition: C4Rect.h:27
virtual const char * GetError() const
Definition: C4NetIO.h:284
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:174
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:41
size_t getTotalSize() const
#define C4GUI_ProgressDlgPBHgt
Definition: C4Gui.h:137
void Append(const char *pnData, size_t iChars)
Definition: StdBuf.h:519
C4Rect & GetClientRect() override
Definition: C4Gui.h:864
C4DownloadDlg(const char *szDLType)
#define C4GUI_DefButtonWdt
Definition: C4Gui.h:114
void UserClose(bool fOK) override
void OnIdle() override
bool ShowModal(C4GUI::Screen *pScreen, const char *szURL, const char *szSaveAsFilename)
const char * GetError()
bool SaveToFile(const char *szFile) const
Definition: StdBuf.cpp:53
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:455
bool Init(uint16_t iPort=addr_t::IPPORT_NONE) override
Definition: C4NetIO.cpp:806
#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
void SetProgress(int32_t iToProgress)
Definition: C4Gui.h:578
bool Query(const StdBuf &Data, bool fBinary)
bool LogF(const char *strMessage,...)
Definition: C4Log.cpp:250
bool Execute(int iMaxTime, pollfd *readyfds) override
bool SetServer(const char *szServerAddress)
~C4DownloadDlg() override
void SetText(const char *szToText, bool fAllowHotkey=true)
Definition: C4GuiLabels.cpp:74
int iSize
Definition: TstC4NetIO.cpp:32
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
const StdBuf & getResultBin() const