/************************************************************************* * UrBackup - Client/Server backup system * Copyright (C) 2011-2015 Martin Raiber * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . **************************************************************************/ #include "Status.h" #include "main.h" #include "TranslationHelper.h" #include "stringtools.h" extern wxString res_path; extern wxString ico_ext; extern wxBitmapType ico_type; const int reset_error_count=20; namespace { wxString getInternetConnectionStatus(wxString str, unsigned int last_seen) { if(str==wxT("initializing")) { return _("Initializing."); } else if(str==wxT("wait_local")) { return _("Waiting for local UrBackup server."); } else if(str==wxT("connected_local")) { unsigned int min_last_seen = (last_seen/1000)/60; wxString last_seen; last_seen << min_last_seen; return _("Connected to local UrBackup server.")+wxT("\n")+_("Not trying to connect to Internet server.")+wxT("\n")+ trans_1(_("Local server last seen _1_ minutes ago."), last_seen); } else if(str==wxT("no_server")) { return _("No Internet server configured."); } else if(str==wxT("connected")) { return _("Connected to Internet server"); } else if(str==wxT("connecting_failed")) { return _("Could not connect to Internet server. Server unreachable."); } else if(str.find(wxT("error:"))==0) { return trans_1(_("Error: _1_"), str.substr(6)); } return str; } std::string PrettyPrintTime(wxLongLong_t ms) { std::string ret; unsigned int c_s=1000; unsigned int c_m=c_s*60; unsigned int c_h=c_m*60; unsigned int c_d=c_h*24; if( ms>c_d) { wxLongLong_t t=ms/c_d; if(!ret.empty()) ret+=" "; ret+=nconvert(t)+wxT(" ")+wxPLURAL("day", "days", static_cast(t)); ms-=t*c_d; } if( ms>c_h) { wxLongLong_t t=ms/c_h; if(!ret.empty()) ret+=" "; ret+=nconvert(t)+wxT(" ")+wxPLURAL("hour", "hours", static_cast(t)); ms-=t*c_h; } if( ms>c_m) { wxLongLong_t t=ms/c_m; if(!ret.empty()) ret+=" "; ret+=nconvert(t)+wxT(" ")+wxPLURAL("minute", "minutes", static_cast(t)); ms-=t*c_m; } return ret; } } Status* Status::instance = NULL; Status::Status(wxWindow* parent, wxLongLong_t follow_only_process_id) : GUIStatus(parent, follow_only_process_id) { SetIcon(wxIcon(res_path+wxT("backup-ok.")+ico_ext, ico_type)); if(updateStatus(0)) { SetFocus(); Raise(); Show(true); #if !defined(__WXMAC__) && !defined(__linux__) RequestUserAttention(); #endif if (follow_only_process_id == 0) { instance = this; } Start(1000); } #ifndef __APPLE__ SetDoubleBuffered(true); #endif error_count=reset_error_count; } bool Status::updateStatus(int errcnt) { SStatusDetails status_details = Connector::getStatusDetails(&connection); if(!status_details.ok) { if(errcnt-1<=0) { Stop(); wxMessageBox(_("There was an error. Currently nothing can be backed up."), wxT("UrBackup"), wxOK|wxICON_ERROR); Close(); } return false; } if (follow_only_process_id != 0) { for (size_t i = 0; i < status_details.running_processes.size();) { if (status_details.running_processes[i].process_id != follow_only_process_id) { status_details.running_processes.erase(status_details.running_processes.begin() + i); } else { ++i; } } } if(last_status_details == status_details) { return true; } last_status_details = status_details; if (!status_details.running_processes.empty()) { if (status_details.running_processes.size() < m_processItem.size()) { removeCurrentProcesses(status_details.running_processes.size()); } else { resizeForProcesses(status_details.running_processes.size()); } for (size_t i = 0; i < status_details.running_processes.size(); ++i) { SProcessItem& item = m_processItem[i]; SRunningProcess& proc = status_details.running_processes[i]; wxString status_text = getStatusText(proc.action); item.m_gauge1->Enable(); if (proc.percent_done >= 0) { item.m_gauge1->SetValue(proc.percent_done); } else { item.m_gauge1->Pulse(); } wxString eta_text = wxEmptyString; if (proc.eta_ms>0) { eta_text = trans_1(_("ETA: Approx. _1_"), PrettyPrintTime(proc.eta_ms)); eta_text += " "; } if (!proc.details.empty()) { if (proc.action == "RESTORE_FILES") { eta_text += trans_2(_("File: _1_"), proc.details, wxString(convert(proc.detail_pc))); } else if (proc.action == "INCRI" || proc.action == "FULLI") { eta_text += trans_1(_("Volume: _1_"), proc.details); } if (proc.detail_pc != -1) { if (proc.action == "RESTORE_FILES") { wxString s; s << proc.detail_pc; eta_text += getPercentText(s); } } } item.m_staticText312->SetLabel(eta_text); wxString s; s << proc.percent_done; status_text += wxT(" "); status_text += getPercentText(s); item.m_staticText31->SetLabel(status_text); } } else { removeCurrentProcesses(1); SProcessItem& item = m_processItem[0]; item.m_staticText312->SetLabel(wxEmptyString); item.m_gauge1->SetValue(0); item.m_gauge1->Disable(); if (follow_only_process_id == 0) { item.m_staticText31->SetLabel(_("Idle.")); } else { item.m_staticText31->SetLabel(_("Restore finished.")); } } if (follow_only_process_id == 0) { if (status_details.last_backup_time>0) { wxDateTime lastbackup_dt((wxLongLong)(status_details.last_backup_time * 1000)); m_staticText37->SetLabel(trans_1(_("Last backup on _1_"), lastbackup_dt.Format())); } else { m_staticText37->SetLabel(wxEmptyString); } wxString servers_text; for (size_t i = 0; iSetLabel(wxEmptyString); } else { m_staticText32->SetLabel(_("Servers:")); } m_staticText33->SetLabel(servers_text); m_staticText35->SetLabel(getInternetConnectionStatus(status_details.internet_status, status_details.time_since_last_lan_connection)); } relayout(); return true; } void Status::Notify(void) { if(!IsVisible()) { Stop(); return; } if(!updateStatus(error_count)) { --error_count; } else { error_count=reset_error_count; } } Status* Status::getInstance() { return instance; } void Status::OnClose() { if (follow_only_process_id == 0) { instance = NULL; } if (connection.client != NULL) { connection.client->Destroy(); connection.client = NULL; } Destroy(); }