BOOL CUploadTransferDC::OnWrite() { ASSUME_LOCK( Transfers.m_pSection ); ASSERT( m_pClient ); m_mOutput.tLast = m_pClient->m_mOutput.tLast; if ( m_pClient->GetOutputLength() != 0 ) // There is data in output buffer return TRUE; if ( m_nState == upsUploading ) { ASSERT( m_nLength != SIZE_UNKNOWN ); // No file data left to transfer if ( m_nPosition >= m_nLength ) { // File completed Uploads.SetStable( GetAverageSpeed() ); m_nState = upsRequest; m_tRequest = GetTickCount(); m_pBaseFile->AddFragment( m_nOffset, m_nLength ); theApp.Message( MSG_INFO, IDS_UPLOAD_FINISHED, (LPCTSTR)m_sName, (LPCTSTR)m_sAddress ); } else { // Reading next data chunk of file QWORD nToRead = min( m_nLength - m_nPosition, (QWORD)Settings.Uploads.ChunkSize ); // ~1000 KB QWORD nRead = 0; auto_array< BYTE > pBuffer( new BYTE[ nToRead ] ); if ( ! ReadFile( m_nFileBase + m_nOffset + m_nPosition, pBuffer.get(), nToRead, &nRead ) || nToRead != nRead ) { // File error return FALSE; } m_pClient->Write( pBuffer.get(), (DWORD)nRead ); m_nPosition += nRead; m_nUploaded += nRead; Statistics.Current.Uploads.Volume += ( nRead / 1024 ); } } else if ( m_nState >= upsResponse ) { // Current transfer completed m_nState = ( m_nState == upsPreQueue ) ? upsQueued : upsRequest; m_tRequest = GetTickCount(); } return TRUE; }
void CStatusLineCtrl::OnPaint(wxPaintEvent&) { wxPaintDC dc(this); wxRect rect = GetRect(); int refresh = 0; if (!m_data.IsOk() || rect.GetWidth() != m_data.GetWidth() || rect.GetHeight() != m_data.GetHeight()) { m_mdc.reset(); m_data = wxBitmap(rect.GetWidth(), rect.GetHeight()); m_mdc = std::make_unique<wxMemoryDC>(m_data); // Use same layout direction as the DC which bitmap is drawn on. // This avoids problem with mirrored characters on RTL locales. m_mdc->SetLayoutDirection(dc.GetLayoutDirection()); refresh = 31; } fz::duration elapsed; int left = -1; wxFileOffset rate; wxString bytes_and_rate; int bar_split = -1; int permill = -1; if (status_.empty()) { if (m_previousStatusText != m_statusText) { // Clear background m_mdc->SetFont(GetFont()); m_mdc->SetPen(GetBackgroundColour()); m_mdc->SetBrush(GetBackgroundColour()); m_mdc->SetTextForeground(GetForegroundColour()); m_mdc->DrawRectangle(0, 0, rect.GetWidth(), rect.GetHeight()); wxCoord h = (rect.GetHeight() - m_textHeight) / 2; m_mdc->DrawText(m_statusText, 50, h); m_previousStatusText = m_statusText; refresh = 0; } } else { if (!m_previousStatusText.empty()) { m_previousStatusText.clear(); refresh = 31; } int elapsed_milli_seconds = 0; if (!status_.started.empty()) { elapsed = fz::datetime::now() - status_.started; elapsed_milli_seconds = static_cast<int>(elapsed.get_milliseconds()); // Assume it doesn't overflow } if (elapsed_milli_seconds / 1000 != m_last_elapsed_seconds) { refresh |= 1; m_last_elapsed_seconds = elapsed_milli_seconds / 1000; } if (COptions::Get()->GetOptionVal(OPTION_SPEED_DISPLAY)) rate = GetMomentarySpeed(); else rate = GetAverageSpeed(elapsed_milli_seconds); if (status_.totalSize > 0 && elapsed_milli_seconds >= 1000 && rate > 0) { wxFileOffset r = status_.totalSize - status_.currentOffset; left = r / rate + 1; if (r) ++left; if (left < 0) left = 0; } if (m_last_left != left) { refresh |= 2; m_last_left = left; } const wxString bytestr = CSizeFormat::Format(status_.currentOffset, true, CSizeFormat::bytes, COptions::Get()->GetOptionVal(OPTION_SIZE_USETHOUSANDSEP) != 0, 0); if (elapsed_milli_seconds >= 1000 && rate > -1) { CSizeFormat::_format format = static_cast<CSizeFormat::_format>(COptions::Get()->GetOptionVal(OPTION_SIZE_FORMAT)); if (format == CSizeFormat::bytes) format = CSizeFormat::iec; const wxString ratestr = CSizeFormat::Format(rate, true, format, COptions::Get()->GetOptionVal(OPTION_SIZE_USETHOUSANDSEP) != 0, COptions::Get()->GetOptionVal(OPTION_SIZE_DECIMALPLACES)); bytes_and_rate.Printf(_("%s (%s/s)"), bytestr, ratestr ); } else bytes_and_rate.Printf(_("%s (? B/s)"), bytestr); if (m_last_bytes_and_rate != bytes_and_rate) { refresh |= 8; m_last_bytes_and_rate = bytes_and_rate; } if (status_.totalSize > 0) { bar_split = static_cast<int>(status_.currentOffset * (PROGRESSBAR_WIDTH - 2) / status_.totalSize); if (bar_split > (PROGRESSBAR_WIDTH - 2)) bar_split = PROGRESSBAR_WIDTH - 2; if (status_.currentOffset > status_.totalSize) permill = 1001; else permill = static_cast<int>(status_.currentOffset * 1000 / status_.totalSize); } if (m_last_bar_split != bar_split || m_last_permill != permill) { refresh |= 4; m_last_bar_split = bar_split; m_last_permill = permill; } } if (refresh) { m_mdc->SetFont(GetFont()); m_mdc->SetPen(GetBackgroundColour()); m_mdc->SetBrush(GetBackgroundColour()); m_mdc->SetTextForeground(GetForegroundColour()); // Get character height so that we can center the text vertically. wxCoord h = (rect.GetHeight() - m_textHeight) / 2; if (refresh & 1) { m_mdc->DrawRectangle(0, 0, m_fieldOffsets[0], rect.GetHeight()); DrawRightAlignedText(*m_mdc, wxTimeSpan::Milliseconds(elapsed.get_milliseconds()).Format(_("%H:%M:%S elapsed")), m_fieldOffsets[0], h); } if (refresh & 2) { m_mdc->DrawRectangle(m_fieldOffsets[0], 0, m_fieldOffsets[1] - m_fieldOffsets[0], rect.GetHeight()); if (left != -1) { wxTimeSpan timeLeft(0, 0, left); DrawRightAlignedText(*m_mdc, timeLeft.Format(_("%H:%M:%S left")), m_fieldOffsets[1], h); } else DrawRightAlignedText(*m_mdc, _("--:--:-- left"), m_fieldOffsets[1], h); } if (refresh & 8) { m_mdc->DrawRectangle(m_fieldOffsets[3], 0, rect.GetWidth() - m_fieldOffsets[3], rect.GetHeight()); m_mdc->DrawText(bytes_and_rate, m_fieldOffsets[3], h); } if (refresh & 16) { m_mdc->DrawRectangle(m_fieldOffsets[1], 0, m_fieldOffsets[2] - m_fieldOffsets[1], rect.GetHeight()); } if (refresh & 4) { m_mdc->DrawRectangle(m_fieldOffsets[2], 0, m_fieldOffsets[3] - m_fieldOffsets[2], rect.GetHeight()); if (bar_split != -1) DrawProgressBar(*m_mdc, m_fieldOffsets[2], 1, rect.GetHeight() - 2, bar_split, permill); } } dc.Blit(0, 0, rect.GetWidth(), rect.GetHeight(), m_mdc.get(), 0, 0); }