forked from Mirrors/openclonk
197 lines
5.9 KiB
C++
197 lines
5.9 KiB
C++
/*
|
|
* OpenClonk, http://www.openclonk.org
|
|
*
|
|
* Copyright (c) 2007-2009, RedWolf Design GmbH, http://www.clonk.de/
|
|
* Copyright (c) 2013-2016, The OpenClonk Team and contributors
|
|
*
|
|
* Distributed under the terms of the ISC license; see accompanying file
|
|
* "COPYING" for details.
|
|
*
|
|
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
|
|
* See accompanying file "TRADEMARK" for details.
|
|
*
|
|
* To redistribute this file separately, substitute the full license texts
|
|
* for the above references.
|
|
*/
|
|
// HTTP download dialog; downloads a file
|
|
|
|
#include "C4Include.h"
|
|
#include "gui/C4DownloadDlg.h"
|
|
|
|
#include "lib/C4Log.h"
|
|
#include "graphics/C4GraphicsResource.h"
|
|
|
|
C4Network2HTTPClient HTTPClient;
|
|
|
|
C4DownloadDlg::C4DownloadDlg(const char *szDLType) : C4GUI::Dialog(C4GUI_ProgressDlgWdt, 100, FormatString(LoadResStr("IDS_CTL_DL_TITLE"), szDLType).getData(), false), szError(nullptr)
|
|
{
|
|
#ifdef HAVE_WINSOCK
|
|
fWinSock = AcquireWinSock();
|
|
#endif
|
|
// add all elements - will be reposisioned when text is displayed
|
|
AddElement(pIcon = new C4GUI::Icon(C4Rect(), C4GUI::Ico_NetWait));
|
|
AddElement(pStatusLabel = new C4GUI::Label("", C4Rect(), ACenter, C4GUI_MessageFontClr, &::GraphicsResource.TextFont, false));
|
|
pProgressBar = nullptr; // created when necessary
|
|
AddElement(pCancelBtn = new C4GUI::CancelButton(C4Rect()));
|
|
}
|
|
|
|
C4DownloadDlg::~C4DownloadDlg()
|
|
{
|
|
#ifdef HAVE_WINSOCK
|
|
if (fWinSock) ReleaseWinSock();
|
|
#endif
|
|
}
|
|
|
|
void C4DownloadDlg::SetStatus(const char *szNewText, int32_t iProgressPercent)
|
|
{
|
|
// get positions
|
|
C4GUI::ComponentAligner caMain(GetClientRect(), C4GUI_DefDlgIndent, C4GUI_DefDlgIndent, true);
|
|
// place icon
|
|
pIcon->SetBounds(caMain.GetFromLeft(C4GUI_IconWdt, C4GUI_IconWdt));
|
|
// place message label
|
|
// use text with line breaks
|
|
StdStrBuf sMsgBroken;
|
|
int iMsgHeight = ::GraphicsResource.TextFont.BreakMessage(szNewText, caMain.GetInnerWidth(), &sMsgBroken, true);
|
|
pStatusLabel->SetBounds(caMain.GetFromTop(iMsgHeight));
|
|
pStatusLabel->SetText(sMsgBroken.getData());
|
|
// place progress bar
|
|
if (iProgressPercent >= 0)
|
|
{
|
|
if (!pProgressBar)
|
|
{
|
|
AddElement(pProgressBar = new C4GUI::ProgressBar(caMain.GetFromTop(C4GUI_ProgressDlgPBHgt)));
|
|
}
|
|
else
|
|
{
|
|
pProgressBar->SetBounds(caMain.GetFromTop(C4GUI_ProgressDlgPBHgt));
|
|
}
|
|
pProgressBar->SetProgress(iProgressPercent);
|
|
}
|
|
else
|
|
{
|
|
// no progress desired
|
|
if (pProgressBar) { delete pProgressBar; pProgressBar = nullptr; }
|
|
}
|
|
// place button
|
|
caMain.ExpandLeft(C4GUI_DefDlgIndent*2 + C4GUI_IconWdt);
|
|
C4GUI::ComponentAligner caButtonArea(caMain.GetFromTop(C4GUI_ButtonAreaHgt), 0,0);
|
|
pCancelBtn->SetBounds(caButtonArea.GetCentered(C4GUI_DefButtonWdt, C4GUI_ButtonHgt));
|
|
pCancelBtn->SetToolTip(LoadResStr("IDS_DL_CANCEL"));
|
|
// resize to actually needed size
|
|
SetClientSize(GetClientRect().Wdt, GetClientRect().Hgt - caMain.GetHeight());
|
|
}
|
|
|
|
void C4DownloadDlg::OnIdle()
|
|
{
|
|
// continue query process
|
|
if (!HTTPClient.Execute())
|
|
{
|
|
// query aborted
|
|
Close(false);
|
|
return;
|
|
}
|
|
if (!HTTPClient.isBusy())
|
|
{
|
|
// download done or aborted
|
|
Close(HTTPClient.isSuccess());
|
|
return;
|
|
}
|
|
StdStrBuf sStatus; int32_t iProgress = -1;
|
|
StdStrBuf sSize("");
|
|
// download in progress: Update status
|
|
if (!HTTPClient.isConnected())
|
|
{
|
|
// still connecting
|
|
sStatus.Ref(LoadResStr("IDS_DL_STATUSCONNECTING"));
|
|
}
|
|
else
|
|
{
|
|
// header received?
|
|
size_t iSize = HTTPClient.getTotalSize();
|
|
if (!iSize)
|
|
{
|
|
// file size unknown: No header received.
|
|
sStatus.Ref(LoadResStr("IDS_PRC_CONNECTED"));
|
|
}
|
|
else
|
|
{
|
|
// file size known: Download in progress
|
|
sStatus.Ref(LoadResStr("IDS_CTL_DL_PROGRESS"));
|
|
if (iSize <= 1024)
|
|
sSize.Format(" (%ld Bytes)", (long)iSize);
|
|
else if (iSize <= 1024*1024)
|
|
sSize.Format(" (%ld KB)", (long)(iSize/1024));
|
|
else
|
|
sSize.Format(" (%ld MB)", (long)(iSize/1024/1024));
|
|
iProgress = int64_t(100) * HTTPClient.getDownloadedSize() / iSize;
|
|
}
|
|
}
|
|
const char *szStatusString = LoadResStr("IDS_PRC_DOWNLOADINGFILE");
|
|
SetStatus(FormatString(szStatusString, GetFilename(HTTPClient.getRequest())).getData(), iProgress );
|
|
}
|
|
|
|
void C4DownloadDlg::UserClose(bool fOK)
|
|
{
|
|
// user cancelled
|
|
HTTPClient.Cancel(LoadResStr("IDS_ERR_USERCANCEL"));
|
|
}
|
|
|
|
const char *C4DownloadDlg::GetError()
|
|
{
|
|
// own error?
|
|
if (szError) return szError;
|
|
// fallback to HTTP error
|
|
return HTTPClient.GetError();
|
|
}
|
|
|
|
bool C4DownloadDlg::ShowModal(C4GUI::Screen *pScreen, const char *szURL, const char *szSaveAsFilename)
|
|
{
|
|
// reset error
|
|
szError = nullptr;
|
|
// initial text
|
|
if (!HTTPClient.Init()) return false;
|
|
HTTPClient.SetServer(szURL);
|
|
// show dlg
|
|
if (!Show(pScreen, true)) return false;
|
|
// start query
|
|
if (!HTTPClient.Query(nullptr, true)) return false;
|
|
// first time status update
|
|
OnIdle();
|
|
// cycle until query is finished or aborted
|
|
if (!DoModal()) return false;
|
|
// download successful: Save file
|
|
if (!HTTPClient.getResultBin().SaveToFile(szSaveAsFilename))
|
|
{
|
|
// file saving failed
|
|
szError = LoadResStr("IDS_FAIL_SAVE");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool C4DownloadDlg::DownloadFile(const char *szDLType, C4GUI::Screen *pScreen, const char *szURL, const char *szSaveAsFilename, const char *szNotFoundMessage)
|
|
{
|
|
// log it
|
|
LogF(LoadResStr("IDS_PRC_DOWNLOADINGFILE"), szURL);
|
|
// show download dialog
|
|
C4DownloadDlg *pDlg = new C4DownloadDlg(szDLType);
|
|
if (!pDlg->ShowModal(pScreen, szURL, szSaveAsFilename))
|
|
{
|
|
// show an appropriate error
|
|
const char *szError = pDlg->GetError();
|
|
if (!szError || !*szError) szError = LoadResStr("IDS_PRC_UNKOWNERROR");
|
|
StdStrBuf sError;
|
|
sError.Format(LoadResStr("IDS_PRC_DOWNLOADERROR"), GetFilename(szURL), szError);
|
|
// it's a 404: display extended message
|
|
if (SSearch(szError, "404") && szNotFoundMessage)
|
|
{ sError.Append("|"); sError.Append(szNotFoundMessage); }
|
|
// display message
|
|
pScreen->ShowMessageModal(sError.getData(), FormatString(LoadResStr("IDS_CTL_DL_TITLE"), szDLType).getData(), C4GUI::MessageDialog::btnOK, C4GUI::Ico_Error, nullptr);
|
|
delete pDlg;
|
|
return false;
|
|
}
|
|
LogF(LoadResStr("IDS_PRC_DOWNLOADCOMPLETE"), szURL);
|
|
delete pDlg;
|
|
return true;
|
|
}
|