mirror of
https://github.com/uroni/urbackup_frontend_wx.git
synced 2025-10-26 11:19:28 +00:00
405 lines
9.6 KiB
C++
405 lines
9.6 KiB
C++
#include "SelectRestoreWindowsComponents.h"
|
|
#include "checked.xpm"
|
|
#include "unchecked.xpm"
|
|
#include <wx/filename.h>
|
|
#include <wx/dir.h>
|
|
#include <random>
|
|
#include "stringtools.h"
|
|
#include "SelectWindowsComponents.h"
|
|
#include "json/json.h"
|
|
#include "RestoreWindowsComponents.h"
|
|
|
|
extern wxString res_path;
|
|
extern wxString ico_ext;
|
|
extern wxBitmapType ico_type;
|
|
extern std::string g_res_path;
|
|
|
|
RetrieveComponentBackups::RetrieveComponentBackups()
|
|
: wxThread(wxTHREAD_JOINABLE), success(false)
|
|
{
|
|
}
|
|
|
|
RetrieveComponentBackups::~RetrieveComponentBackups()
|
|
{
|
|
}
|
|
|
|
wxThread::ExitCode RetrieveComponentBackups::Entry()
|
|
{
|
|
filelist = Connector::getFileList("windows_components_config", access_error);
|
|
|
|
if (Connector::hasError())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
success = true;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
SelectRestoreComponents::SelectRestoreComponents(wxWindow * parent)
|
|
: GUISelectRestoreComponents(parent), canSelectBackup(false), retrievingBackupConfig(false), backupid(0)
|
|
{
|
|
retrieveComponentBackups.Run();
|
|
|
|
Start(200);
|
|
|
|
m_listBox1->Append(_("Loading..."));
|
|
|
|
wxIcon icons[2];
|
|
icons[0] = wxIcon(unchecked_xpm);
|
|
icons[1] = wxIcon(checked_xpm);
|
|
|
|
int icon_width = icons[0].GetWidth();
|
|
int icon_height = icons[0].GetHeight();
|
|
|
|
selectList = new wxImageList(icon_width, icon_height, true);
|
|
iconList = new wxImageList(icon_width, icon_height, true);
|
|
|
|
for (size_t i = 0; i < WXSIZEOF(icons); i++)
|
|
selectList->Add(icons[i]);
|
|
|
|
m_treeCtrl1->AssignStateImageList(selectList);
|
|
m_treeCtrl1->AddRoot(_("Loading..."));
|
|
}
|
|
|
|
void SelectRestoreComponents::Notify(void)
|
|
{
|
|
if (!retrieveComponentBackups.IsAlive()
|
|
&& !canSelectBackup)
|
|
{
|
|
retrieveComponentBackups.Wait();
|
|
canSelectBackup = true;
|
|
|
|
if (!retrieveComponentBackups.hasSuccess())
|
|
{
|
|
Stop();
|
|
wxMessageBox(_("Error retrieving Windows component backups: ") +
|
|
accessErrorToString(retrieveComponentBackups.getAccessError()), wxT("UrBackup"), wxOK | wxICON_ERROR);
|
|
Start(200);
|
|
return;
|
|
}
|
|
|
|
m_listBox1->Clear();
|
|
|
|
for (size_t i = 0; i < retrieveComponentBackups.getFileList().size(); ++i)
|
|
{
|
|
wxDateTime logtime_dt((wxLongLong)(retrieveComponentBackups.getFileList()[i].backuptime * 1000));
|
|
|
|
m_listBox1->Append(logtime_dt.Format());
|
|
}
|
|
|
|
if (!retrieveComponentBackups.getFileList().empty())
|
|
{
|
|
m_listBox1->Select(0);
|
|
wxCommandEvent evt;
|
|
onListBoxSelected(evt);
|
|
}
|
|
}
|
|
|
|
if (retrievingBackupConfig
|
|
&& retrieveComponentConfig.get()
|
|
&& !retrieveComponentConfig->IsAlive())
|
|
{
|
|
retrieveComponentConfig->Wait();
|
|
retrievingBackupConfig = false;
|
|
|
|
if (!retrieveComponentConfig->hasSuccess())
|
|
{
|
|
wxString errmsg = accessErrorToString(retrieveComponentConfig->getAccessError());
|
|
if (!retrieveComponentConfig->getErrMsg().empty())
|
|
{
|
|
errmsg = retrieveComponentConfig->getErrMsg();
|
|
}
|
|
Stop();
|
|
wxMessageBox(_("Error retrieving Windows component configuration: ") +
|
|
errmsg, wxT("UrBackup"), wxOK | wxICON_ERROR);
|
|
Start(200);
|
|
retrieveComponentConfig.reset();
|
|
return;
|
|
}
|
|
|
|
m_treeCtrl1->Delete(m_treeCtrl1->GetRootItem());
|
|
wxTreeItemId rootId = m_treeCtrl1->AddRoot(_("Windows components"));
|
|
|
|
m_treeCtrl1->SetItemState(rootId, 0);
|
|
|
|
SComponent* root = retrieveComponentConfig->getRoot();
|
|
|
|
tree_components[rootId] = root;
|
|
tree_items[root] = rootId;
|
|
|
|
SelectWindowsComponents::addComponents(m_treeCtrl1, iconList, rootId, root, tree_components,
|
|
tree_items, icon_width, icon_height);
|
|
|
|
m_treeCtrl1->SetImageList(iconList);
|
|
|
|
SelectWindowsComponents::selectTreeItems(m_treeCtrl1, tree_items,
|
|
retrieveComponentConfig->getRoot(), retrieveComponentConfig->getRoot(), true);
|
|
|
|
for (std::map<SComponent*, wxTreeItemId>::iterator it = tree_items.begin();
|
|
it != tree_items.end(); ++it)
|
|
{
|
|
m_treeCtrl1->Toggle(it->second);
|
|
}
|
|
|
|
backupid = retrieveComponentConfig->getBackupid();
|
|
componentConfigDir = retrieveComponentConfig->getComponentConfigDir();
|
|
}
|
|
}
|
|
|
|
void SelectRestoreComponents::onListBoxSelected(wxCommandEvent & event)
|
|
{
|
|
if (!canSelectBackup)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int sel = m_listBox1->GetSelection();
|
|
if (sel >= 0)
|
|
{
|
|
while (retrievingBackupConfig
|
|
&& retrieveComponentConfig.get()
|
|
&& retrieveComponentConfig->IsAlive() )
|
|
{
|
|
Sleep(100);
|
|
wxTheApp->SafeYield(NULL, false);
|
|
}
|
|
|
|
m_treeCtrl1->DeleteAllItems();
|
|
tree_components.clear();
|
|
tree_items.clear();
|
|
m_treeCtrl1->SetImageList(NULL);
|
|
iconList->RemoveAll();
|
|
|
|
m_treeCtrl1->AddRoot(_("Loading..."));
|
|
|
|
retrieveComponentConfig.reset(new RetrieveComponentConfig);
|
|
retrieveComponentConfig->reset(retrieveComponentBackups.getFileList()[sel].backupid);
|
|
|
|
retrieveComponentConfig->Run();
|
|
retrievingBackupConfig = true;
|
|
}
|
|
}
|
|
|
|
void SelectRestoreComponents::onStartRestore(wxCommandEvent & event)
|
|
{
|
|
if (backupid == 0)
|
|
{
|
|
wxMessageBox(_("No backup was selected"), wxT("UrBackup"), wxOK | wxICON_ERROR);
|
|
return;
|
|
}
|
|
|
|
std::vector<SComponent> selected_components;
|
|
|
|
for (std::map<SComponent*, wxTreeItemId>::iterator it = tree_items.begin();
|
|
it != tree_items.end(); ++it)
|
|
{
|
|
if (!it->first->is_root)
|
|
{
|
|
int state = m_treeCtrl1->GetItemState(it->second);
|
|
if (state == 1)
|
|
{
|
|
selected_components.push_back(*it->first);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (selected_components.empty())
|
|
{
|
|
wxMessageBox(_("No components selected"), wxT("UrBackup"), wxOK | wxICON_ERROR);
|
|
return;
|
|
}
|
|
|
|
Close();
|
|
|
|
RestoreWindowsComponents* rwc = new RestoreWindowsComponents(NULL,
|
|
backupid, selected_components, componentConfigDir);
|
|
|
|
wxTheApp->SetTopWindow(rwc);
|
|
rwc->ShowModal();
|
|
rwc->Destroy();
|
|
}
|
|
|
|
void SelectRestoreComponents::evtOnTreeStateImageClick(wxTreeEvent & event)
|
|
{
|
|
SComponent* component = tree_components[event.GetItem()];
|
|
|
|
if (component == NULL
|
|
|| retrieveComponentConfig.get()==NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
bool select = m_treeCtrl1->GetItemState(event.GetItem()) == 0;
|
|
|
|
SelectWindowsComponents::selectTreeItems(m_treeCtrl1, tree_items,
|
|
retrieveComponentConfig->getRoot(), component, select);
|
|
}
|
|
|
|
void SelectRestoreComponents::onCancel(wxCommandEvent & event)
|
|
{
|
|
Close();
|
|
}
|
|
|
|
RetrieveComponentConfig::RetrieveComponentConfig()
|
|
: wxThread(wxTHREAD_JOINABLE), success(false)
|
|
{
|
|
root.is_root = true;
|
|
}
|
|
|
|
RetrieveComponentConfig::~RetrieveComponentConfig()
|
|
{
|
|
for (size_t i = 0; i < components.size(); ++i)
|
|
{
|
|
delete components[i];
|
|
}
|
|
|
|
if (!componentConfigDir.empty())
|
|
{
|
|
wxFileName::Rmdir(componentConfigDir, wxPATH_RMDIR_RECURSIVE);
|
|
}
|
|
}
|
|
|
|
wxThread::ExitCode RetrieveComponentConfig::Entry()
|
|
{
|
|
wxMilliClock_t now = wxGetLocalTimeMillis();
|
|
std::random_device rd;
|
|
|
|
componentConfigDir = wxFileName::GetTempDir().Append(wxString::Format(wxT("\\urb_win_comps_%llu_%lu"), now, rd()));
|
|
if (!wxFileName::Mkdir(componentConfigDir))
|
|
{
|
|
componentConfigDir.clear();
|
|
return NULL;
|
|
}
|
|
|
|
SPathMap path_map;
|
|
path_map.source = "C:\\windows_components_config";
|
|
path_map.target = componentConfigDir.ToStdString();
|
|
|
|
std::vector<SPathMap> path_maps;
|
|
path_maps.push_back(path_map);
|
|
|
|
SStartRestore restore_info = Connector::startRestore("windows_components_config", backupid,
|
|
path_maps, access_error, false, true, false, 0);
|
|
|
|
if (!restore_info.ok)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
SConnection connection;
|
|
bool restore_finished = false;
|
|
while (!restore_finished)
|
|
{
|
|
Sleep(100);
|
|
|
|
SStatusDetails status = Connector::getStatusDetails(&connection);
|
|
|
|
if (status.ok)
|
|
{
|
|
for (size_t i = 0; i < status.finished_processes.size(); ++i)
|
|
{
|
|
if (status.finished_processes[i].id == restore_info.process_id)
|
|
{
|
|
restore_finished = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
std::string data = getFile((componentConfigDir + wxT("\\backupcom.xml")).ToStdWstring());
|
|
|
|
if (data.empty())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
std::string info = getFile((componentConfigDir + wxT("\\info.json")).ToStdWstring());
|
|
|
|
if (info.empty())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
wxDir dir(componentConfigDir);
|
|
if (!dir.IsOpened())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
std::vector<std::string> componentXmls;
|
|
wxString filename;
|
|
bool cont = dir.GetFirst(&filename);
|
|
while (cont)
|
|
{
|
|
if ( filename != "backupcom.xml"
|
|
&& filename != "info.json" )
|
|
{
|
|
componentXmls.push_back(getFile((componentConfigDir + wxT("\\") + filename).ToStdWstring()));
|
|
}
|
|
cont = dir.GetNext(&filename);
|
|
}
|
|
|
|
Json::Value info_root;
|
|
Json::Reader reader;
|
|
if (!reader.parse(info, info_root, false))
|
|
{
|
|
return NULL;
|
|
};
|
|
|
|
std::vector<SComponent> filter_except;
|
|
try
|
|
{
|
|
Json::Value selected_components = info_root["selected_components"];
|
|
|
|
for (Json::ArrayIndex i = 0; i < selected_components.size(); ++i)
|
|
{
|
|
Json::Value compInfo = selected_components[i];
|
|
|
|
SComponent comp;
|
|
HRESULT hr = IIDFromString(ConvertToUnicode(compInfo["writerId"].asString()).c_str(),
|
|
&comp.writerId);
|
|
|
|
comp.logicalPath = compInfo["logicalPath"].asString();
|
|
comp.name = compInfo["componentName"].asString();
|
|
|
|
filter_except.push_back(comp);
|
|
}
|
|
}
|
|
catch (std::runtime_error&)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
|
|
if (!WindowsComponentReader::readComponents(data, componentXmls, filter_except, root, components, errmsg))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
success = true;
|
|
|
|
return ExitCode();
|
|
}
|
|
|
|
wxString accessErrorToString(Connector::EAccessError access_error)
|
|
{
|
|
switch (access_error)
|
|
{
|
|
case Connector::EAccessError_Ok:
|
|
return _("Unknown access error");
|
|
case Connector::EAccessError_NoServer:
|
|
return _("Currently not connected to a backup server. No backup server found.");
|
|
case Connector::EAccessError_NoTokens:
|
|
return _("No file backup access tokens found. Did you run a file backup yet?");
|
|
}
|
|
assert(false);
|
|
return wxT("UNDEF");
|
|
}
|