openclonk/src/network/C4Network2ResDlg.cpp

215 lines
6.5 KiB
C++

/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
* Copyright (c) 2009-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.
*/
// resource display list box
#include "C4Include.h"
#include "network/C4Network2Dialogs.h"
#include "control/C4PlayerInfo.h"
#include "game/C4Application.h"
#include "game/C4FullScreen.h"
#include "graphics/C4GraphicsResource.h"
#include "gui/C4GameLobby.h"
#include "network/C4Network2.h"
#include "network/C4Network2Players.h"
// ----------- C4Network2ResDlg::ListItem ----------------------------------------------------------------
C4Network2ResDlg::ListItem::ListItem(C4Network2ResDlg *pForResDlg, const C4Network2Res *pByRes)
: pSaveBtn(nullptr)
{
// init by res core (2do)
iResID = pByRes->getResID();
const char *szFilename = GetFilename(pByRes->getCore().getFileName());
// get size
int iIconSize = ::GraphicsResource.TextFont.GetLineHeight();
int iWidth = pForResDlg->GetItemWidth();
int iVerticalIndent = 2;
SetBounds(C4Rect(0, 0, iWidth, iIconSize+2*iVerticalIndent));
C4GUI::ComponentAligner ca(GetContainedClientRect(), 0,iVerticalIndent);
// create subcomponents
pFileIcon = new C4GUI::Icon(ca.GetFromLeft(iIconSize), C4GUI::Ico_Resource);
pLabel = new C4GUI::Label(szFilename, iIconSize + IconLabelSpacing,iVerticalIndent, ALeft);
pProgress = nullptr;
// add components
AddElement(pFileIcon); AddElement(pLabel);
// tooltip
SetToolTip(LoadResStr("IDS_DESC_RESOURCE"));
// add to listbox (will eventually get moved)
pForResDlg->AddElement(this);
// first-time update
Update(pByRes);
}
void C4Network2ResDlg::ListItem::Update(const C4Network2Res *pByRes)
{
// update progress label
iProgress = pByRes->getPresentPercent();
if (iProgress < 100)
{
StdStrBuf progress;
progress.Format("%d%%", iProgress);
if (pProgress)
pProgress->SetText(progress.getData());
else
{
pProgress = new C4GUI::Label(progress.getData(), GetBounds().Wdt - IconLabelSpacing, 0, ARight);
pProgress->SetToolTip(LoadResStr("IDS_NET_RESPROGRESS_DESC"));
AddElement(pProgress);
}
}
else if (pProgress) { delete pProgress; pProgress=nullptr; }
// update disk icon
if (IsSavePossible())
{
if (!pSaveBtn)
{
pSaveBtn = new C4GUI::CallbackButtonEx<C4Network2ResDlg::ListItem, C4GUI::IconButton>(C4GUI::Ico_Save, GetToprightCornerRect(16,16,2,1), 0, this, &ListItem::OnButtonSave);
AddElement(pSaveBtn);
}
}
else if (pSaveBtn)
delete pSaveBtn;
}
void C4Network2ResDlg::ListItem::OnButtonSave(C4GUI::Control *pButton)
{
LocalSaveResource(false);
}
void C4Network2ResDlg::ListItem::OnButtonSaveConfirm(C4GUI::Element *pNull)
{
LocalSaveResource(true);
}
void C4Network2ResDlg::ListItem::LocalSaveResource(bool fDoOverwrite)
{
// get associated resource
C4Network2Res::Ref pRes = GetRefRes();
if (!pRes) return;
const char *szResFile = pRes->getFile();
StdCopyStrBuf strErrCopyFile(LoadResStr("IDS_NET_ERR_COPYFILE"));
if (!pRes->isTempFile())
{
GetScreen()->ShowMessage(LoadResStr("IDS_NET_ERR_COPYFILE_LOCAL"), strErrCopyFile.getData(), C4GUI::Ico_Error);
return;
}
const char *szFilename = GetFilename(pRes->getCore().getFileName());
/* const char *szSpecialPath = "";
if (WildcardMatch(C4CFN_PlayerFiles, szFilename))
// write players to player path
szSpecialPath = Config.General.PlayerPath;
*/
const char *szTarget = Config.AtUserDataPath(szFilename);
if (!fDoOverwrite && ItemExists(szTarget))
{
// show a confirmation dlg, asking whether the resource should be overwritten
GetScreen()->ShowRemoveDlg(new C4GUI::ConfirmationDialog(
FormatString(LoadResStr("IDS_NET_RES_SAVE_OVERWRITE"), GetFilename(szTarget)).getData(), LoadResStr("IDS_NET_RES_SAVE"),
new C4GUI::CallbackHandler<C4Network2ResDlg::ListItem>(this, &C4Network2ResDlg::ListItem::OnButtonSaveConfirm), C4GUI::MessageDialog::btnYesNo));
return;
}
if (!C4Group_CopyItem(szResFile, szTarget))
GetScreen()->ShowMessage(strErrCopyFile.getData(), strErrCopyFile.getData(), C4GUI::Ico_Error);
else
{
GetScreen()->ShowMessage(FormatString(LoadResStr("IDS_NET_RES_SAVED_DESC"), GetFilename(szTarget)).getData(),
LoadResStr("IDS_NET_RES_SAVED"), C4GUI::Ico_Save);
}
}
C4Network2Res::Ref C4Network2ResDlg::ListItem::GetRefRes()
{
// forward to network reslist
return ::Network.ResList.getRefRes(iResID);
}
bool C4Network2ResDlg::ListItem::IsSavePossible()
{
// check resource
bool fCanSave = false;
C4Network2Res::Ref pRes = GetRefRes();
if (!pRes) return false;
// temp files from network folder only
if (pRes->isTempFile())
{
// check type
C4Network2ResType eType = pRes->getType();
if ((eType == NRT_Player && Config.Lobby.AllowPlayerSave) || eType == NRT_Scenario || eType == NRT_Definitions)
// check complete
if (!pRes->isLoading())
// save OK
fCanSave = true;
}
return fCanSave;
}
// ----------- C4Network2ResDlg -----------------------------------------------------------------------
C4Network2ResDlg::C4Network2ResDlg(const C4Rect &rcBounds, bool fActive) : ListBox(rcBounds)
{
// 2do
// initially active?
if (fActive) Activate();
}
void C4Network2ResDlg::Activate()
{
// create timer if necessary
Application.Add(this);
// force an update
Update();
}
void C4Network2ResDlg::Deactivate()
{
// release timer if set
Application.Remove(this);
}
void C4Network2ResDlg::Update()
{
// check through own resources and current res list
ListItem *pItem = static_cast<ListItem *>(pClientWindow->GetFirst()), *pNext;
C4Network2Res *pRes; int iResID=-1;
while ((pRes = ::Network.ResList.getRefNextRes(++iResID)))
{
iResID = pRes->getResID();
// resource checking: deleted resource(s) present?
while (pItem && (pItem->GetResID() < iResID))
{
pNext = static_cast<ListItem *>(pItem->GetNext());
delete pItem; pItem = pNext;
}
// same resource present for update?
if (pItem && pItem->GetResID() == iResID)
{
pItem->Update(pRes);
pItem = static_cast<ListItem *>(pItem->GetNext());
}
else
// not present: insert (or add if pItem=nullptr)
InsertElement(new ListItem(this, pRes), pItem);
}
// del trailing items
while (pItem)
{
pNext = static_cast<ListItem *>(pItem->GetNext());
delete pItem; pItem = pNext;
}
}