Index: src/ch/MainWnd.cpp
===================================================================
diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/ch/MainWnd.cpp	(.../MainWnd.cpp)	(revision 12a1725bfd04b0f55fd0fda302975fdcd4174943)
+++ src/ch/MainWnd.cpp	(.../MainWnd.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -76,7 +76,8 @@
 	m_pdlgStatus(NULL),
 	m_pdlgMiniView(NULL),
 	m_dwLastTime(0),
-	m_tasks()
+	m_tasks(),
+	m_spTaskMgrStats(new chcore::TTaskManagerStatsSnapshot)
 {
 }
 
@@ -362,10 +363,9 @@
 		{
 			if (m_tasks.GetSize() != 0)
 			{
-				chcore::TTaskManagerStatsSnapshot tTMStats;
-				m_tasks.GetStatsSnapshot(tTMStats);
+				m_tasks.GetStatsSnapshot(m_spTaskMgrStats);
 
-				_sntprintf(text, _MAX_PATH, _T("%s - %d %%"), GetApp().GetAppName(), tTMStats.GetGlobalProgressInPercent());
+				_sntprintf(text, _MAX_PATH, _T("%s - %.0f %%"), GetApp().GetAppName(), m_spTaskMgrStats->GetCombinedProgress() * 100.0);
 				m_ctlTray.SetTooltipText(text);
 			}
 			else
Index: src/ch/MainWnd.h
===================================================================
diff -u -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/ch/MainWnd.h	(.../MainWnd.h)	(revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0)
+++ src/ch/MainWnd.h	(.../MainWnd.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -32,48 +32,22 @@
 {
 public:
 	CMainWnd();
+	virtual ~CMainWnd();
+
 	DECLARE_DYNCREATE(CMainWnd)
 
 	BOOL Create();
 
-// Attributes
-public:
-	CTrayIcon m_ctlTray;
-	
-	chcore::TTaskManager m_tasks;
-	chcore::IFeedbackHandlerFactory* m_pFeedbackFactory;
-	chcore::TSharedMemory m_tCHExtharedMemory;
-
-	CMiniViewDlg* m_pdlgMiniView;
-	CStatusDlg* m_pdlgStatus;
-
-	DWORD m_dwLastTime;
-	UINT m_uiTaskbarRestart;
-
-// Operations
-public:
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CMainFrame)
-	protected:
+protected:
 	virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
-	//}}AFX_VIRTUAL
 
-// Implementation
-public:
-	virtual ~CMainWnd();
-
-// Generated message map functions
-protected:
 	BOOL RegisterClass();
 	int ShowTrayIcon();
 	void ShowStatusWindow(const chcore::TTaskPtr& spSelect = chcore::TTaskPtr());
 	void PrepareToExit();
 
 	void ProcessCommandLine(const TCommandLineParser& rCommandLine);
 
-	//{{AFX_MSG(CMainWnd)
 	afx_msg void OnPopupShowStatus();
 	afx_msg void OnPopupShowOptions();
 	afx_msg void OnClose();
@@ -89,11 +63,25 @@
 	afx_msg void OnPopupUnregisterdll();
 	afx_msg void OnAppExit();
 	afx_msg void OnPopupHelp();
-	//}}AFX_MSG
 	afx_msg LRESULT OnTrayNotification(WPARAM wParam, LPARAM lParam);
-	DECLARE_MESSAGE_MAP()
-public:
 	afx_msg void OnPopupCheckForUpdates();
+
+	DECLARE_MESSAGE_MAP()
+
+private:
+	chcore::TTaskManagerStatsSnapshotPtr m_spTaskMgrStats;
+
+	CTrayIcon m_ctlTray;
+
+	chcore::TTaskManager m_tasks;
+	chcore::IFeedbackHandlerFactory* m_pFeedbackFactory;
+	chcore::TSharedMemory m_tCHExtharedMemory;
+
+	CMiniViewDlg* m_pdlgMiniView;
+	CStatusDlg* m_pdlgStatus;
+
+	DWORD m_dwLastTime;
+	UINT m_uiTaskbarRestart;
 };
 
 /////////////////////////////////////////////////////////////////////////////
Index: src/ch/MiniViewDlg.cpp
===================================================================
diff -u -r35f5463cd2ef65053a99d40f50965771a801be3e -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/ch/MiniViewDlg.cpp	(.../MiniViewDlg.cpp)	(revision 35f5463cd2ef65053a99d40f50965771a801be3e)
+++ src/ch/MiniViewDlg.cpp	(.../MiniViewDlg.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -45,7 +45,8 @@
 // CMiniViewDlg dialog
 
 CMiniViewDlg::CMiniViewDlg(chcore::TTaskManager* pArray, bool *pbHide, CWnd* pParent /*=NULL*/)
-	:ictranslate::CLanguageDialog(IDD_MINIVIEW_DIALOG, pParent, &m_bLock)
+	:ictranslate::CLanguageDialog(IDD_MINIVIEW_DIALOG, pParent, &m_bLock),
+	m_spTaskMgrStats(new chcore::TTaskManagerStatsSnapshot)
 {
 	COLORREF cr3DFace = GetSysColor(COLOR_3DFACE);
 	m_brBackground.CreateSolidBrush(cr3DFace);
@@ -191,36 +192,47 @@
 
 void CMiniViewDlg::RefreshStatus()
 {
+	if(!m_pTasks)
+		return;
+
+	m_pTasks->GetStatsSnapshot(m_spTaskMgrStats);
+
 	int index=0;
 	_PROGRESSITEM_* pItem=NULL;
 
 	if(GetPropValue<PP_MVSHOWSINGLETASKS>(GetConfig()))
 	{
-		for(size_t stIndex = 0; stIndex < m_pTasks->GetSize(); ++stIndex)
+		size_t stTasksCount = m_spTaskMgrStats->GetTaskStatsCount();
+		for(size_t stIndex = 0; stIndex < stTasksCount; ++stIndex)
 		{
-			chcore::TTaskPtr spTask = m_pTasks->GetAt(stIndex);
-			spTask->GetMiniSnapshot(&m_tMiniDisplayData);
+			chcore::TTaskStatsSnapshotPtr spTaskStats = m_spTaskMgrStats->GetTaskStatsAt(stIndex);
+			chcore::ETaskCurrentState eTaskState = spTaskStats->GetTaskState();
 
-			if(m_tMiniDisplayData.m_eTaskState != chcore::eTaskState_Finished && m_tMiniDisplayData.m_eTaskState != chcore::eTaskState_Cancelled)
+			if(eTaskState != chcore::eTaskState_Finished && eTaskState != chcore::eTaskState_Cancelled)
 			{
 				pItem = m_ctlStatus.GetItemAddress(index++);
 
 				// load
-				if(m_tMiniDisplayData.m_eTaskState == chcore::eTaskState_Error)
+				if(eTaskState == chcore::eTaskState_Error)
 					pItem->m_crColor=RGB(255, 0, 0);
-				else if(m_tMiniDisplayData.m_eTaskState == chcore::eTaskState_Paused)
+				else if(eTaskState == chcore::eTaskState_Paused)
 					pItem->m_crColor=RGB(255, 255, 0);
-				else if(m_tMiniDisplayData.m_eTaskState == chcore::eTaskState_Waiting)
+				else if(eTaskState == chcore::eTaskState_Waiting)
 					pItem->m_crColor=RGB(50, 50, 50);
 				else
 					pItem->m_crColor=RGB(0, 255, 0);
 
-				if(m_tMiniDisplayData.m_strPath.IsEmpty())
-					pItem->m_strText = GetResManager().LoadString(IDS_NONEINPUTFILE_STRING);
-				else
-					pItem->m_strText = m_tMiniDisplayData.m_strPath;
-				pItem->m_uiPos = boost::numeric_cast<int>(m_tMiniDisplayData.m_dPercent);
-				pItem->m_spTask = spTask;
+				chcore::TString strPath;
+				chcore::TSubTaskStatsSnapshotPtr spSubtaskStats = spTaskStats->GetSubTasksStats().GetCurrentSubTaskSnapshot();
+				if(spSubtaskStats)
+					strPath = spSubtaskStats->GetCurrentPath();
+
+				if(strPath.IsEmpty())
+					strPath = GetResManager().LoadString(IDS_NONEINPUTFILE_STRING);
+
+				pItem->m_strText = strPath;
+				pItem->m_uiPos = boost::numeric_cast<int>(spTaskStats->GetCombinedProgress() * 100.0);
+				pItem->m_stTaskUniqueSessionID = spTaskStats->GetSessionUniqueID();
 			}
 		}
 	}
@@ -258,15 +270,12 @@
 		}
 	}
 
-	chcore::TTaskManagerStatsSnapshot tTMStats;
-	m_pTasks->GetStatsSnapshot(tTMStats);
-
 	// add all state
 	pItem=m_ctlStatus.GetItemAddress(index++);
 	pItem->m_crColor=GetSysColor(COLOR_HIGHLIGHT);
 	pItem->m_strText=GetResManager().LoadString(IDS_MINIVIEWALL_STRING);
-	pItem->m_uiPos = boost::numeric_cast<int>(tTMStats.GetGlobalProgressInPercent());
-	pItem->m_spTask.reset();
+	pItem->m_uiPos = boost::numeric_cast<int>(m_spTaskMgrStats->GetCombinedProgress() * 100.0);
+	pItem->m_stTaskUniqueSessionID = NO_TASK_SESSION_UNIQUE_ID;
 
 	// get rid of the rest
 	m_ctlStatus.SetSmoothProgress(GetPropValue<PP_MVUSESMOOTHPROGRESS>(GetConfig()));
@@ -427,7 +436,7 @@
 			if (iSel == LB_ERR || (size_t)iSel >= pDlg->m_ctlStatus.m_vItems.size())
 				return;
 
-			chcore::TTaskPtr spTask = pDlg->m_ctlStatus.m_vItems.at(iSel)->m_spTask;
+			chcore::TTaskPtr spTask = pDlg->m_pTasks->GetTaskBySessionUniqueID(pDlg->m_ctlStatus.m_vItems.at(iSel)->m_stTaskUniqueSessionID);
 			if(spTask)
 				spTask->PauseProcessing();
 			else
@@ -534,7 +543,8 @@
 			int iSel=pDlg->m_ctlStatus.GetCurSel();
 			if (iSel == LB_ERR || (size_t)iSel >= pDlg->m_ctlStatus.m_vItems.size())
 				return;
-			chcore::TTaskPtr spTask = pDlg->m_ctlStatus.m_vItems.at(iSel)->m_spTask;
+
+			chcore::TTaskPtr spTask = pDlg->m_pTasks->GetTaskBySessionUniqueID(pDlg->m_ctlStatus.m_vItems.at(iSel)->m_stTaskUniqueSessionID);
 			if (spTask)
 			{
 				if(spTask->GetTaskState() == chcore::eTaskState_Waiting)
@@ -578,7 +588,8 @@
 		int iSel=pDlg->m_ctlStatus.GetCurSel();
 		if (iSel == LB_ERR || (size_t)iSel >= pDlg->m_ctlStatus.m_vItems.size())
 			return;
-		chcore::TTaskPtr spTask = pDlg->m_ctlStatus.m_vItems.at(iSel)->m_spTask;
+
+		chcore::TTaskPtr spTask = pDlg->m_pTasks->GetTaskBySessionUniqueID(pDlg->m_ctlStatus.m_vItems.at(iSel)->m_stTaskUniqueSessionID);
 		if(spTask)
 			spTask->CancelProcessing();
 		else
@@ -632,7 +643,8 @@
 			int iSel=pDlg->m_ctlStatus.GetCurSel();
 			if (iSel == LB_ERR || (size_t)iSel >= pDlg->m_ctlStatus.m_vItems.size())
 				return;
-			chcore::TTaskPtr spTask = pDlg->m_ctlStatus.m_vItems.at(iSel)->m_spTask;
+
+			chcore::TTaskPtr spTask = pDlg->m_pTasks->GetTaskBySessionUniqueID(pDlg->m_ctlStatus.m_vItems.at(iSel)->m_stTaskUniqueSessionID);
 			if(spTask)
 				spTask->RestartProcessing();
 			else
@@ -790,11 +802,8 @@
 	if(iSel == LB_ERR || (size_t)iSel >= m_ctlStatus.m_vItems.size())
 		return;
 
-	chcore::TTaskPtr spTask = m_ctlStatus.m_vItems.at(iSel)->m_spTask;
-	if(spTask)
-		GetParent()->PostMessage(WM_MINIVIEWDBLCLK, 0, (LPARAM)spTask->GetSessionUniqueID());
-	else
-		GetParent()->PostMessage(WM_MINIVIEWDBLCLK, 0, (LPARAM)NO_TASK_SESSION_UNIQUE_ID);
+	size_t stSessionUniqueID = m_ctlStatus.m_vItems.at(iSel)->m_stTaskUniqueSessionID;
+	GetParent()->PostMessage(WM_MINIVIEWDBLCLK, 0, (LPARAM)stSessionUniqueID);
 }
 
 void CMiniViewDlg::OnLanguageChanged()
Index: src/ch/MiniViewDlg.h
===================================================================
diff -u -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/ch/MiniViewDlg.h	(.../MiniViewDlg.h)	(revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0)
+++ src/ch/MiniViewDlg.h	(.../MiniViewDlg.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -69,40 +69,10 @@
 	virtual UINT GetLanguageUpdateOptions() { return LDF_NODIALOGSIZE; };
 	virtual void OnLanguageChanged();
 
-	// from CMainWnd
-	chcore::TTaskManager *m_pTasks;
-
-	CBrush m_brBackground;
-	int m_iLastHeight;
-	bool m_bShown;
-	_PROGRESSITEM_ item;
-
-	// cache
-	chcore::TASK_MINI_DISPLAY_DATA m_tMiniDisplayData;
-	bool m_bActive;
-
-	// lock
-	static bool m_bLock;
-	bool *m_pbHide;		// does the big status dialog visible ?
-
-	// in onmousemove points to last pressed button
-	int m_iIndex;
-
-	CProgressListBox	m_ctlStatus;
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CMiniViewDlg)
-	public:
-	protected:
+protected:
 	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
 	virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
-	//}}AFX_VIRTUAL
 
-// Implementation
-protected:
-	// Generated message map functions
-	//{{AFX_MSG(CMiniViewDlg)
 	afx_msg HBRUSH OnCtlColor(CDC*, CWnd*, UINT);
 	virtual BOOL OnInitDialog();
 	afx_msg void OnTimer(UINT_PTR nIDEvent);
@@ -116,11 +86,32 @@
 	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
 	afx_msg void OnSettingChange(UINT uFlags, LPCTSTR lpszSection);
 	afx_msg void OnDblclkProgressList();
-	//}}AFX_MSG
+
 	DECLARE_MESSAGE_MAP()
-};
 
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+public:
+	static bool m_bLock;
 
+private:
+	// from CMainWnd
+	chcore::TTaskManager *m_pTasks;
+	chcore::TTaskManagerStatsSnapshotPtr m_spTaskMgrStats;
+
+	CBrush m_brBackground;
+	int m_iLastHeight;
+	bool m_bShown;
+	_PROGRESSITEM_ item;
+
+	// cache
+	bool m_bActive;
+
+	// lock
+	bool *m_pbHide;		// is the big status dialog visible ?
+
+	// in onmousemove points to last pressed button
+	int m_iIndex;
+
+	CProgressListBox	m_ctlStatus;
+};
+
 #endif
Index: src/ch/ProgressListBox.h
===================================================================
diff -u -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/ch/ProgressListBox.h	(.../ProgressListBox.h)	(revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0)
+++ src/ch/ProgressListBox.h	(.../ProgressListBox.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -30,7 +30,7 @@
 
 	COLORREF m_crColor;
 
-	chcore::TTaskPtr m_spTask;
+	size_t m_stTaskUniqueSessionID;
 };
 
 class CProgressListBox : public CListBox
Index: src/ch/StatusDlg.cpp
===================================================================
diff -u -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/ch/StatusDlg.cpp	(.../StatusDlg.cpp)	(revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f)
+++ src/ch/StatusDlg.cpp	(.../StatusDlg.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -41,21 +41,15 @@
 // CStatusDlg dialog
 
 CStatusDlg::CStatusDlg(chcore::TTaskManager* pTasks, CWnd* pParent /*=NULL*/)
-	: ictranslate::CLanguageDialog(CStatusDlg::IDD, pParent, &m_bLock)
+	: ictranslate::CLanguageDialog(CStatusDlg::IDD, pParent, &m_bLock),
+	m_spTaskMgrStats(new chcore::TTaskManagerStatsSnapshot),
+	m_pTasks(pTasks)
 {
-	//{{AFX_DATA_INIT(CStatusDlg)
-	//}}AFX_DATA_INIT
-	m_i64LastProcessed=0;
-	m_i64LastAllTasksProcessed=0;
-	m_pTasks=pTasks;
-	m_dwLastUpdate=0;
-
 	RegisterStaticExControl(AfxGetInstanceHandle());
 }
 
 CStatusDlg::~CStatusDlg()
 {
-
 }
 
 void CStatusDlg::DoDataExchange(CDataExchange* pDX)
@@ -207,6 +201,10 @@
 		GetDlgItem(IDC_TASKTIME_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYTIMETEXT_STRING));
 
 		m_ctlTaskCountProgress.SetPos(0);
+		m_ctlTaskSizeProgress.SetPos(0);
+		m_ctlCurrentObjectProgress.SetPos(0);
+		m_ctlSubTaskCountProgress.SetPos(0);
+		m_ctlSubTaskSizeProgress.SetPos(0);
 	}
 }
 
@@ -226,36 +224,24 @@
 	CLanguageDialog::OnTimer(nIDEvent);
 }
 
-void CStatusDlg::AddTaskInfo(int nPos, const chcore::TTaskPtr& spTask, DWORD dwCurrentTime)
-{
-	_ASSERTE(spTask != NULL);
-	if(spTask == NULL)
-		return;
-
-	// get data snapshot from task
-	chcore::TASK_DISPLAY_DATA td;
-	spTask->GetSnapshot(&td);
-
-	// set (update/add new) entry in the task list (on the left)
-	SetTaskListEntry(td, nPos, spTask);
-
-	// right side update
-	if(spTask == m_spSelectedItem)
-		UpdateTaskStatsDetails(td, dwCurrentTime);
-}
-
 void CStatusDlg::OnSetBuffersizeButton()
 {
 	chcore::TTaskPtr spTask = GetSelectedItemPointer();
 	if(!spTask)
 		return;
 
-	CBufferSizeDlg dlg;
-	chcore::TTaskStatsSnapshot tTaskStats;
-	spTask->GetTaskStats(tTaskStats);
+	int iCurrentBufferIndex = 0;
+	chcore::TTaskStatsSnapshotPtr spTaskStats = m_spTaskMgrStats->GetTaskStatsForSessionUniqueID(GetSelectedItemSessionUniqueID());
+	if(spTaskStats)
+	{
+		chcore::TSubTaskStatsSnapshotPtr spSubTaskStats = spTaskStats->GetSubTasksStats().GetCurrentSubTaskSnapshot();
+		if(spSubTaskStats)
+			iCurrentBufferIndex = spSubTaskStats->GetCurrentBufferIndex();
+	}
 
+	CBufferSizeDlg dlg;
 	spTask->GetBufferSizes(dlg.m_bsSizes);
-	dlg.m_iActiveIndex = tTaskStats.GetCurrentSubTaskStats().GetCurrentBufferIndex();
+	dlg.m_iActiveIndex = iCurrentBufferIndex;
 	if(dlg.DoModal() == IDOK)
 		spTask->SetBufferSizes(dlg.m_bsSizes);
 }
@@ -273,6 +259,19 @@
 	return chcore::TTaskPtr();
 }
 
+size_t CStatusDlg::GetSelectedItemSessionUniqueID()
+{
+	// returns ptr to a TTask for a given element in listview
+	if(m_ctlStatusList.GetSelectedCount() == 1)
+	{
+		POSITION pos = m_ctlStatusList.GetFirstSelectedItemPosition();
+		int nPos = m_ctlStatusList.GetNextSelectedItem(pos);
+		return m_ctlStatusList.GetItemData(nPos);
+	}
+
+	return std::numeric_limits<size_t>::max();
+}
+
 void CStatusDlg::StickDialogToScreenEdge()
 {
 	// get coord of screen and window
@@ -288,16 +287,16 @@
 void CStatusDlg::ApplyButtonsState()
 {
 	// remember ptr to TTask
-	m_spSelectedItem=GetSelectedItemPointer();
+	chcore::TTaskPtr spSelectedTask = GetSelectedItemPointer();
 
 	// set status of buttons pause/resume/cancel
-	if (m_spSelectedItem != NULL)
+	if (spSelectedTask != NULL)
 	{
 		GetDlgItem(IDC_RESTART_BUTTON)->EnableWindow(true);
 		GetDlgItem(IDC_SHOW_LOG_BUTTON)->EnableWindow(true);
 		GetDlgItem(IDC_DELETE_BUTTON)->EnableWindow(true);
 		
-		if (m_spSelectedItem->GetTaskState() == chcore::eTaskState_Finished || m_spSelectedItem->GetTaskState() == chcore::eTaskState_Cancelled)
+		if (spSelectedTask->GetTaskState() == chcore::eTaskState_Finished || spSelectedTask->GetTaskState() == chcore::eTaskState_Cancelled)
 		{
 			GetDlgItem(IDC_CANCEL_BUTTON)->EnableWindow(false);
 			GetDlgItem(IDC_PAUSE_BUTTON)->EnableWindow(false);
@@ -306,15 +305,15 @@
 		else
 		{
 			// pause/resume
-			if (m_spSelectedItem->GetTaskState() == chcore::eTaskState_Paused)
+			if (spSelectedTask->GetTaskState() == chcore::eTaskState_Paused)
 			{
 				GetDlgItem(IDC_PAUSE_BUTTON)->EnableWindow(false);
 				GetDlgItem(IDC_RESUME_BUTTON)->EnableWindow(true);
 			}
 			else
 			{
 				GetDlgItem(IDC_PAUSE_BUTTON)->EnableWindow(true);
-				if (m_spSelectedItem->GetTaskState() == chcore::eTaskState_Waiting)
+				if (spSelectedTask->GetTaskState() == chcore::eTaskState_Waiting)
 					GetDlgItem(IDC_RESUME_BUTTON)->EnableWindow(true);
 				else
 					GetDlgItem(IDC_RESUME_BUTTON)->EnableWindow(false);
@@ -363,37 +362,39 @@
 		if (LOWORD(wParam) >= ID_POPUP_TIME_CRITICAL && LOWORD(wParam) <= ID_POPUP_IDLE)
 		{
 			// processing priority
-			if ( (m_spSelectedItem=GetSelectedItemPointer()) == NULL )
+			chcore::TTaskPtr spSelectedTask = GetSelectedItemPointer();
+
+			if(spSelectedTask == NULL)
 				return ictranslate::CLanguageDialog::OnCommand(wParam, lParam);
 			
 			switch (LOWORD(wParam))
 			{
 			case ID_POPUP_TIME_CRITICAL:
-				m_spSelectedItem->SetPriority(THREAD_PRIORITY_TIME_CRITICAL);
+				spSelectedTask->SetPriority(THREAD_PRIORITY_TIME_CRITICAL);
 				GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_TIME_CRITICAL)));
 				break;
 			case ID_POPUP_HIGHEST:
-				m_spSelectedItem->SetPriority(THREAD_PRIORITY_HIGHEST);
+				spSelectedTask->SetPriority(THREAD_PRIORITY_HIGHEST);
 				GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_HIGHEST)));
 				break;
 			case ID_POPUP_ABOVE_NORMAL:
-				m_spSelectedItem->SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
+				spSelectedTask->SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
 				GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_ABOVE_NORMAL)));
 				break;
 			case ID_POPUP_NORMAL:
-				m_spSelectedItem->SetPriority(THREAD_PRIORITY_NORMAL);
+				spSelectedTask->SetPriority(THREAD_PRIORITY_NORMAL);
 				GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_NORMAL)));
 				break;
 			case ID_POPUP_BELOW_NORMAL:
-				m_spSelectedItem->SetPriority(THREAD_PRIORITY_BELOW_NORMAL);
+				spSelectedTask->SetPriority(THREAD_PRIORITY_BELOW_NORMAL);
 				GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_BELOW_NORMAL)));
 				break;
 			case ID_POPUP_LOWEST:
-				m_spSelectedItem->SetPriority(THREAD_PRIORITY_LOWEST);
+				spSelectedTask->SetPriority(THREAD_PRIORITY_LOWEST);
 				GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_LOWEST)));
 				break;
 			case ID_POPUP_IDLE:
-				m_spSelectedItem->SetPriority(THREAD_PRIORITY_IDLE);
+				spSelectedTask->SetPriority(THREAD_PRIORITY_IDLE);
 				GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_IDLE)));
 				break;
 			}
@@ -549,8 +550,19 @@
 	}
 }
 
-LPTSTR CStatusDlg::FormatTime(time_t timeSeconds, LPTSTR lpszBuffer, size_t stMaxBufferSize)
+LPTSTR CStatusDlg::FormatTime(unsigned long long timeSeconds, LPTSTR lpszBuffer, size_t stMaxBufferSize)
 {
+	if(timeSeconds > 30*24*3600)	// more than 30 days
+	{
+		// we need those pragmas to disable lv4 warning "warning C4428: universal-character-name encountered in source"
+		// which incorrectly warns about the infinity char embedded in a string.
+#pragma warning(push)
+#pragma warning(disable: 4428)
+		_tcscpy_s(lpszBuffer, stMaxBufferSize, L"\u221E");
+#pragma warning(pop)
+		return lpszBuffer;
+	}
+
 	long lDays = boost::numeric_cast<long>(timeSeconds/86400);
 	timeSeconds %= 86400;
 	long lHours = boost::numeric_cast<long>(timeSeconds/3600);
@@ -573,70 +585,53 @@
 
 LPTSTR CStatusDlg::FormatTimeMiliseconds(unsigned long long timeMiliSeconds, LPTSTR lpszBuffer, size_t stMaxBufferSize)
 {
-	time_t timeSeconds = timeMiliSeconds / 1000;
+	unsigned long long timeSeconds = timeMiliSeconds / 1000;
 	return FormatTime(timeSeconds, lpszBuffer, stMaxBufferSize);
 }
 
 void CStatusDlg::RefreshStatus()
 {
 	// remember address of a current selection
-	m_spSelectedItem=GetSelectedItemPointer();
+	size_t stSelectedTaskSessionUniqueID = GetSelectedItemSessionUniqueID();
 
-	// current time
-	DWORD dwCurrentTime=GetTickCount();
+	// get all the stats needed
+	m_pTasks->GetStatsSnapshot(m_spTaskMgrStats);
 
 	// get rid of item after the current part
-	m_ctlStatusList.LimitItems(boost::numeric_cast<int>(m_pTasks->GetSize()));
+	m_ctlStatusList.LimitItems(boost::numeric_cast<int>(m_spTaskMgrStats->GetTaskStatsCount()));
 
 	// add task info
-	for(size_t stIndex = 0; stIndex < m_pTasks->GetSize(); ++stIndex)
+	for(size_t stIndex = 0; stIndex < m_spTaskMgrStats->GetTaskStatsCount(); ++stIndex)
 	{
-		AddTaskInfo(boost::numeric_cast<int>(stIndex), m_pTasks->GetAt(stIndex), dwCurrentTime);
+		chcore::TTaskStatsSnapshotPtr spTaskStats = m_spTaskMgrStats->GetTaskStatsAt(stIndex);
+		// set (update/add new) entry in the task list (on the left)
+		SetTaskListEntry(stIndex, spTaskStats);
+
+		// right side update
+		if(spTaskStats->GetSessionUniqueID() == stSelectedTaskSessionUniqueID)
+			UpdateTaskStatsDetails(spTaskStats);
 	}
 
-	// percent
-	chcore::TTaskManagerStatsSnapshot tTMStats;
-	m_pTasks->GetStatsSnapshot(tTMStats);
-
 	// set title
-	if (m_pTasks->GetSize() != 0)
-		_sntprintf(m_szData, _MAX_PATH, _T("%s [%.0f %%]"), GetResManager().LoadString(IDS_STATUSTITLE_STRING), tTMStats.GetGlobalProgressInPercent());
-	else
-		_sntprintf(m_szData, _MAX_PATH, _T("%s"), GetResManager().LoadString(IDS_STATUSTITLE_STRING));
-	
-	// if changed
-	CString strTemp;
-	GetWindowText(strTemp);
-	if (strTemp != CString(m_szData)) 
-		SetWindowText(m_szData);
-	
+	SetWindowTitle(GetProgressWindowTitleText());
+
 	// refresh overall progress
-	m_ctlProgressAll.SetPos(boost::numeric_cast<int>(tTMStats.GetGlobalProgressInPercent()));
+	m_ctlProgressAll.SetRange(0, 100);
+	m_ctlProgressAll.SetPos(boost::numeric_cast<int>(m_spTaskMgrStats->GetCombinedProgress() * 100.0));
 	
 	// progress - count of processed data/count of data
-	strTemp=GetSizeString(tTMStats.GetProcessedSize(), m_szData, _MAX_PATH)+CString(_T("/"));
-	strTemp+=GetSizeString(tTMStats.GetTotalSize(), m_szData, _MAX_PATH);
+	CString strTemp;
+	strTemp=GetSizeString(m_spTaskMgrStats->GetProcessedSize(), m_szData, _MAX_PATH)+CString(_T("/"));
+	strTemp+=GetSizeString(m_spTaskMgrStats->GetTotalSize(), m_szData, _MAX_PATH);
 	GetDlgItem(IDC_GLOBALPROCESSED_STATIC)->SetWindowText(strTemp);
 	
 	// transfer
-	if (m_i64LastAllTasksProcessed == 0)
-		m_i64LastAllTasksProcessed=tTMStats.GetProcessedSize();
-	
-	if (dwCurrentTime-m_dwLastUpdate != 0)
-		strTemp=GetSizeString( (static_cast<double>(tTMStats.GetProcessedSize()) - static_cast<double>(m_i64LastAllTasksProcessed))/static_cast<double>(static_cast<double>(dwCurrentTime-m_dwLastUpdate)/1000.0), m_szData, _MAX_PATH);
-	else
-		strTemp=GetSizeString( 0ULL, m_szData, _MAX_PATH);
-	
-	GetDlgItem(IDC_GLOBALTRANSFER_STATIC)->SetWindowText(strTemp+_T("/s"));
-	m_i64LastAllTasksProcessed=tTMStats.GetProcessedSize();
-	m_dwLastUpdate=dwCurrentTime;
+	CString strSpeed = GetSpeedString(m_spTaskMgrStats->GetSizeSpeed(), m_spTaskMgrStats->GetAvgSizeSpeed(), m_spTaskMgrStats->GetCountSpeed(), m_spTaskMgrStats->GetAvgCountSpeed());
+	GetDlgItem(IDC_GLOBALTRANSFER_STATIC)->SetWindowText(strSpeed);
 
 	// if selection's missing - hide controls
 	if (m_ctlStatusList.GetSelectedCount() == 0)
-	{
 		EnableControls(false);
-		m_i64LastProcessed=0;
-	}
 	else
 		EnableControls();		// enable controls
 	
@@ -660,7 +655,7 @@
 {
 	// show log
 	chcore::TTaskPtr spTask = GetSelectedItemPointer();
-	if (!spTask)
+	if(!spTask)
 		return;
 
 	unsigned long lResult = (unsigned long)(ShellExecute(this->m_hWnd, _T("open"), _T("notepad.exe"), spTask->GetRelatedPath(chcore::TTask::ePathType_TaskLogFile).ToString(), NULL, SW_SHOWNORMAL));
@@ -688,7 +683,7 @@
 	StickDialogToScreenEdge();
 }
 
-void CStatusDlg::SetBufferSizesString(UINT uiValue, int iIndex)
+void CStatusDlg::SetBufferSizesString(unsigned long long ullValue, int iIndex)
 {
 	TCHAR szData[1024];
 	switch(iIndex)
@@ -713,7 +708,7 @@
 		szData[0] = _T('\0');
 	}
 
-	_tcscat(szData, GetSizeString((ull_t)uiValue, m_szData, _MAX_PATH));
+	_tcscat(szData, GetSizeString(ullValue, m_szData, _MAX_PATH));
 
 	GetDlgItem(IDC_BUFFERSIZE_STATIC)->SetWindowText(szData);
 }
@@ -877,12 +872,12 @@
 	InitializeResizableControls();
 }
 
-CString CStatusDlg::GetStatusString(const chcore::TASK_DISPLAY_DATA& rTaskDisplayData)
+CString CStatusDlg::GetStatusString(const chcore::TTaskStatsSnapshotPtr& spTaskStats)
 {
 	CString strStatusText;
 	// status string
 	// first
-	switch(rTaskDisplayData.m_eTaskState)
+	switch(spTaskStats->GetTaskState())
 	{
 	case chcore::eTaskState_Error:
 		{
@@ -927,30 +922,34 @@
 	}
 
 	// second part
-	
-	if(rTaskDisplayData.m_eSubOperationType == chcore::eSubOperation_Deleting)
+	chcore::ESubOperationType eSubOperationType = chcore::eSubOperation_None;
+	chcore::TSubTaskStatsSnapshotPtr spSubtaskStats = spTaskStats->GetSubTasksStats().GetCurrentSubTaskSnapshot();
+	if(spSubtaskStats)
+		eSubOperationType = spSubtaskStats->GetSubOperationType();
+
+	if(eSubOperationType == chcore::eSubOperation_Deleting)
 		strStatusText += GetResManager().LoadString(IDS_STATUS_DELETING_STRING);
-	else if(rTaskDisplayData.m_eSubOperationType == chcore::eSubOperation_Scanning)
+	else if(eSubOperationType == chcore::eSubOperation_Scanning)
 		strStatusText += GetResManager().LoadString(IDS_STATUS_SEARCHING_STRING);
-	else if(rTaskDisplayData.m_eSubOperationType == chcore::eSubOperation_FastMove)
+	else if(eSubOperationType == chcore::eSubOperation_FastMove)
 		strStatusText += GetResManager().LoadString(IDS_STATUS_FASTMOVE_STRING);
-	else if(rTaskDisplayData.m_eOperationType == chcore::eOperation_Copy)
+	else if(spTaskStats->GetOperationType() == chcore::eOperation_Copy)
 		strStatusText += GetResManager().LoadString(IDS_STATUS_COPYING_STRING);
-	else if(rTaskDisplayData.m_eOperationType == chcore::eOperation_Move)
+	else if(spTaskStats->GetOperationType() == chcore::eOperation_Move)
 		strStatusText += GetResManager().LoadString(IDS_STATUS_MOVING_STRING);
 	else
 		strStatusText += GetResManager().LoadString(IDS_STATUS_UNKNOWN_STRING);
 
-	if(rTaskDisplayData.m_pafFilters && !rTaskDisplayData.m_pafFilters->IsEmpty())
+	if(!spTaskStats->GetFilters().IsEmpty())
 		strStatusText += GetResManager().LoadString(IDS_FILTERING_STRING);
 
 	// third part
-	if(rTaskDisplayData.m_bIgnoreDirectories)
+	if(spTaskStats->GetIgnoreDirectories())
 	{
 		strStatusText += _T("/");
 		strStatusText += GetResManager().LoadString(IDS_STATUS_ONLY_FILES_STRING);
 	}
-	if(rTaskDisplayData.m_bCreateEmptyFiles)
+	if(spTaskStats->GetCreateEmptyFiles())
 	{
 		strStatusText += _T("/");
 		strStatusText += GetResManager().LoadString(IDS_STATUS_WITHOUT_CONTENTS_STRING);
@@ -959,150 +958,197 @@
 	return strStatusText;
 }
 
-void CStatusDlg::SetTaskListEntry(const chcore::TASK_DISPLAY_DATA &td, int nPos, const chcore::TTaskPtr& spTask)
+CString CStatusDlg::GetSubtaskName(chcore::ESubOperationType eSubtask) const
 {
+	if(eSubtask == chcore::eSubOperation_Deleting)
+		return GetResManager().LoadString(IDS_STATUS_DELETING_STRING);
+	else if(eSubtask == chcore::eSubOperation_Scanning)
+		return GetResManager().LoadString(IDS_STATUS_SEARCHING_STRING);
+	else if(eSubtask == chcore::eSubOperation_FastMove)
+		return GetResManager().LoadString(IDS_STATUS_FASTMOVE_STRING);
+	else if(eSubtask == chcore::eSubOperation_Copying)
+		return GetResManager().LoadString(IDS_STATUS_COPYING_STRING);
+	else
+		return GetResManager().LoadString(IDS_STATUS_UNKNOWN_STRING);
+}
+
+void CStatusDlg::SetTaskListEntry(size_t stPos, const chcore::TTaskStatsSnapshotPtr& spTaskStats)
+{
 	// index subitem
-	CString strStatusText = GetStatusString(td);
-	CString strTemp;
+	CString strStatusText = GetStatusString(spTaskStats);
 	LVITEM lvi;
 	lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
-	lvi.iItem = nPos;
+	lvi.iItem = boost::numeric_cast<int>(stPos);
 	lvi.iSubItem = 0;
 	lvi.pszText = (PTSTR)(PCTSTR)strStatusText;
 	lvi.cchTextMax = lstrlen(lvi.pszText);
-	lvi.lParam = spTask->GetSessionUniqueID();
-	lvi.iImage = GetImageFromStatus(td.m_eTaskState);
-	if (nPos < m_ctlStatusList.GetItemCount())
+	lvi.lParam = spTaskStats->GetSessionUniqueID();
+	lvi.iImage = GetImageFromStatus(spTaskStats->GetTaskState());
+	if(boost::numeric_cast<int>(stPos) < m_ctlStatusList.GetItemCount())
 		m_ctlStatusList.SetItem(&lvi);
 	else
 		m_ctlStatusList.InsertItem(&lvi);
 
-	// status subitem
+	chcore::TSubTaskStatsSnapshotPtr spSubTaskStats = spTaskStats->GetSubTasksStats().GetCurrentSubTaskSnapshot();
+	chcore::TString strCurrentPath;
+	if(spSubTaskStats)
+	{
+		chcore::TSmartPath path;
+		path.FromString(spSubTaskStats->GetCurrentPath());
+		strCurrentPath = path.GetFileName().ToString();
+	}
+
+	// input file
 	lvi.mask=LVIF_TEXT;
-	lvi.iSubItem=1;
-	if(td.m_strFileName.IsEmpty())
-		strTemp = GetResManager().LoadString(IDS_NONEINPUTFILE_STRING);
-	else
-		strTemp = td.m_strFileName;
-	lvi.pszText=strTemp.GetBuffer(0);
-	strTemp.ReleaseBuffer();
-	lvi.cchTextMax=lstrlen(lvi.pszText);
+	lvi.iSubItem = 1;
+	if(strCurrentPath.IsEmpty())
+		strCurrentPath = GetResManager().LoadString(IDS_NONEINPUTFILE_STRING);
+
+	lvi.pszText = (PTSTR)(PCTSTR)strCurrentPath;;
+	lvi.cchTextMax = lstrlen(lvi.pszText);
 	m_ctlStatusList.SetItem(&lvi);
 
-	// insert 'file' subitem
-	lvi.iSubItem=2;
-	strTemp = td.m_pathDstPath.ToString();
-	lvi.pszText=strTemp.GetBuffer(0);
-	strTemp.ReleaseBuffer();
-	lvi.cchTextMax=lstrlen(lvi.pszText);
+	// destination path
+	lvi.iSubItem = 2;
+	chcore::TString strDestinationPath = spTaskStats->GetDestinationPath();
+	lvi.pszText = (PTSTR)(PCTSTR)strDestinationPath;
+	lvi.cchTextMax = lstrlen(lvi.pszText);
 	m_ctlStatusList.SetItem(&lvi);
 
 	// insert dest subitem
 	lvi.iSubItem=3;
-	_itot(boost::numeric_cast<int>(td.m_dPercent), m_szData, 10);
-	_tcscat(m_szData, _T(" %"));
-	lvi.pszText=m_szData;
-	lvi.cchTextMax=lstrlen(lvi.pszText);
+
+	CString strFmt;
+	strFmt.Format(_T("%.0f %%"), spTaskStats->GetCombinedProgress() * 100.0);
+
+	lvi.pszText = (PTSTR)(PCTSTR)strFmt;
+	lvi.cchTextMax = lstrlen(lvi.pszText);
 	m_ctlStatusList.SetItem(&lvi);
 }
 
 CString CStatusDlg::GetProcessedText(unsigned long long ullProcessedCount, unsigned long long ullTotalCount, unsigned long long ullProcessedSize, unsigned long long ullTotalSize)
 {
 	CString strTemp;
-	_sntprintf(m_szData, _MAX_PATH, _T("%ld/%ld ("), ullProcessedCount, ullTotalCount);
+	_sntprintf(m_szData, _MAX_PATH, _T("%I64u/%I64u ("), ullProcessedCount, ullTotalCount);
 	strTemp = CString(m_szData);
 	strTemp += GetSizeString(ullProcessedSize, m_szData, _MAX_PATH) + CString(_T("/"));
 	strTemp += GetSizeString(ullTotalSize, m_szData, _MAX_PATH) + CString(_T(")"));
 	return strTemp;
 }
 
-void CStatusDlg::UpdateTaskStatsDetails(chcore::TASK_DISPLAY_DATA &td, DWORD dwCurrentTime)
+CString CStatusDlg::GetSpeedString(double dSizeSpeed, double dAvgSizeSpeed, double dCountSpeed, double dAvgCountSpeed) const
 {
-	chcore::TSubTaskStatsSnapshot& tSubTaskStats = td.m_tTaskSnapshot.GetCurrentSubTaskStats();
+	TCHAR szData[_MAX_PATH];
+	CString strSpeedText = GetSizeString(dSizeSpeed, szData, _MAX_PATH);	// last avg
+	CString strAvgSpeedText = GetSizeString(dAvgSizeSpeed, szData, _MAX_PATH);	// last avg
 
+	CString strAvgWord = GetResManager().LoadString(IDS_AVERAGEWORD_STRING);
+
+	// avg transfer
+	CString strFmt;
+	strFmt.Format(_T("%s/s (%s%s/s); %.0f/s (%s%.0f/s)"), strSpeedText, strAvgWord, strAvgSpeedText,
+		dCountSpeed, strAvgWord, dAvgCountSpeed);
+
+	return strFmt;
+}
+
+void CStatusDlg::UpdateTaskStatsDetails(const chcore::TTaskStatsSnapshotPtr& spTaskStats)
+{
+	chcore::TSubTaskStatsSnapshotPtr spSubTaskStats = spTaskStats->GetSubTasksStats().GetCurrentSubTaskSnapshot();
+	_ASSERTE(spSubTaskStats != NULL);
+	if(!spSubTaskStats)
+		return;
+
 	// text progress
-	CString strProcessedText = GetProcessedText(tSubTaskStats.GetProcessedCount(), tSubTaskStats.GetTotalCount(), tSubTaskStats.GetProcessedSize(), tSubTaskStats.GetTotalSize());
+	CString strProcessedText = GetProcessedText(spSubTaskStats->GetProcessedCount(), spSubTaskStats->GetTotalCount(), spSubTaskStats->GetProcessedSize(), spSubTaskStats->GetTotalSize());
 	GetDlgItem(IDC_SUBTASKPROCESSED_STATIC)->SetWindowText(strProcessedText);
 
 	// progress bars
-	m_ctlCurrentObjectProgress.SetProgress(tSubTaskStats.GetCurrentItemProcessedSize(), tSubTaskStats.GetCurrentItemTotalSize());
-	m_ctlSubTaskCountProgress.SetProgress(tSubTaskStats.GetProcessedCount(), tSubTaskStats.GetTotalCount());
-	m_ctlSubTaskSizeProgress.SetProgress(tSubTaskStats.GetProcessedSize(), tSubTaskStats.GetTotalSize());
+	m_ctlCurrentObjectProgress.SetProgress(spSubTaskStats->GetCurrentItemProcessedSize(), spSubTaskStats->GetCurrentItemTotalSize());
+	m_ctlSubTaskCountProgress.SetProgress(spSubTaskStats->GetProcessedCount(), spSubTaskStats->GetTotalCount());
+	m_ctlSubTaskSizeProgress.SetProgress(spSubTaskStats->GetProcessedSize(), spSubTaskStats->GetTotalSize());
 
 	// time information
-	unsigned long long timeTotalEstimated = tSubTaskStats.GetEstimatedTotalTime();
-	unsigned long long timeElapsed = tSubTaskStats.GetTimeElapsed();
+	unsigned long long timeTotalEstimated = spSubTaskStats->GetEstimatedTotalTime();
+	unsigned long long timeElapsed = spSubTaskStats->GetTimeElapsed();
 	unsigned long long timeRemaining = timeTotalEstimated - timeElapsed;
 
 	FormatTimeMiliseconds(timeElapsed, m_szTimeBuffer1, 40);
 	FormatTimeMiliseconds(timeTotalEstimated, m_szTimeBuffer2, 40);
 	FormatTimeMiliseconds(timeRemaining, m_szTimeBuffer3, 40);
 
 	_sntprintf(m_szData, _MAX_PATH, _T("%s / %s (%s)"), m_szTimeBuffer1, m_szTimeBuffer2, m_szTimeBuffer3);
-
 	GetDlgItem(IDC_SUBTASKTIME_STATIC)->SetWindowText(m_szData);
 
 	// speed information
-	CString strSizeSpeed;
-	CString strCountSpeed;
+	CString strSpeed = GetSpeedString(spSubTaskStats->GetSizeSpeed(), spSubTaskStats->GetAvgSizeSpeed(), spSubTaskStats->GetCountSpeed(), spSubTaskStats->GetAvgCountSpeed());
+	GetDlgItem(IDC_SUBTASKTRANSFER_STATIC)->SetWindowText(strSpeed);
 
-	GetSizeString(tSubTaskStats.GetSizeSpeed(), m_szData, _MAX_PATH);
-	strSizeSpeed = m_szData;
-	GetSizeString(tSubTaskStats.GetAvgSizeSpeed(), m_szData, _MAX_PATH);
-	strSizeSpeed.AppendFormat(_T("/s (a: %s/s)"), m_szData);
-
-	strCountSpeed.Format(_T("%.2f/s (a: %.2f/s)"), tSubTaskStats.GetCountSpeed(), tSubTaskStats.GetAvgCountSpeed());
-	GetDlgItem(IDC_SUBTASKTRANSFER_STATIC)->SetWindowText(strSizeSpeed + _T("; ") + strCountSpeed);
-
 	//////////////////////////////////////////////////////
 	// data that can be changed by a thread
-	CString strStatusText = GetStatusString(td);
+	CString strStatusText = GetStatusString(spTaskStats);
 	GetDlgItem(IDC_OPERATION_STATIC)->SetWindowText(strStatusText);	// operation
 
-	if(td.m_strFullFilePath.IsEmpty())
-		GetDlgItem(IDC_SOURCEOBJECT_STATIC)->SetWindowText(GetResManager().LoadString(IDS_NONEINPUTFILE_STRING));
-	else
-		GetDlgItem(IDC_SOURCEOBJECT_STATIC)->SetWindowText(td.m_strFullFilePath);	// src object
+	// subtask name
+	chcore::ESubOperationType eSubOperationType = spSubTaskStats->GetSubOperationType();
+	CString strSubtaskName = GetSubtaskName(eSubOperationType);
+	GetDlgItem(IDC_SUBTASKNAME_STATIC)->SetWindowText(strSubtaskName);
 
+	// current path
+	chcore::TString strPath = spSubTaskStats->GetCurrentPath();
+	if(strPath.IsEmpty())
+		strPath = GetResManager().LoadString(IDS_NONEINPUTFILE_STRING);
+
+	GetDlgItem(IDC_SOURCEOBJECT_STATIC)->SetWindowText(strPath);	// src object
+
 	// count of processed data/overall count of data
-	strProcessedText = GetProcessedText(td.m_stIndex, td.m_stSize, td.m_ullProcessedSize, td.m_ullSizeAll);
+	strProcessedText = GetProcessedText(spTaskStats->GetProcessedCount(), spTaskStats->GetTotalCount(),
+		spTaskStats->GetProcessedSize(), spTaskStats->GetTotalSize());
 	GetDlgItem(IDC_TASKPROCESSED_STATIC)->SetWindowText(strProcessedText);
 
 	// transfer
-	CString strSpeedText;
-	if (m_i64LastProcessed == 0)	// if first time - show average
-		strSpeedText=GetSizeString( td.m_timeElapsed ? td.m_ullProcessedSize/td.m_timeElapsed : 0, m_szData, _MAX_PATH);	// last avg
-	else
-	{
-		if ( (dwCurrentTime-m_dwLastUpdate) != 0)
-			strSpeedText=GetSizeString( (static_cast<double>(td.m_ullProcessedSize) - static_cast<double>(m_i64LastProcessed))/(static_cast<double>(dwCurrentTime-m_dwLastUpdate)/1000.0), m_szData, _MAX_PATH);
-		else
-			strSpeedText=GetSizeString( 0ULL, m_szData, _MAX_PATH);
-	}
+	CString strTaskSpeed = GetSpeedString(spTaskStats->GetSizeSpeed(), spTaskStats->GetAvgSizeSpeed(), spTaskStats->GetCountSpeed(), spTaskStats->GetAvgCountSpeed());
+	GetDlgItem(IDC_TASKTRANSFER_STATIC)->SetWindowText(strTaskSpeed);
 
-	// avg transfer
-	GetDlgItem(IDC_TASKTRANSFER_STATIC)->SetWindowText(strSpeedText+_T("/s (")+CString(GetResManager().LoadString(IDS_AVERAGEWORD_STRING))
-		+CString(GetSizeString(td.m_timeElapsed ? td.m_ullProcessedSize/td.m_timeElapsed : 0, m_szData, _MAX_PATH))+_T("/s )")
-		);
-
 	// elapsed time / estimated total time (estimated time left)
-	FormatTime(td.m_timeElapsed, m_szTimeBuffer1, 40);
-	time_t timeTotal = (td.m_ullProcessedSize == 0) ? 0 : (long)(td.m_ullSizeAll * td.m_timeElapsed / td.m_ullProcessedSize);
-	FormatTime(timeTotal, m_szTimeBuffer2, 40);
-	FormatTime(std::max((time_t)0l, timeTotal - td.m_timeElapsed), m_szTimeBuffer3, 40);
+	timeTotalEstimated = spTaskStats->GetEstimatedTotalTime();
+	timeElapsed = spTaskStats->GetTimeElapsed();
+	timeRemaining = timeTotalEstimated - timeElapsed;
 
+	FormatTimeMiliseconds(timeElapsed, m_szTimeBuffer1, 40);
+	FormatTimeMiliseconds(timeTotalEstimated, m_szTimeBuffer2, 40);
+	FormatTimeMiliseconds(timeRemaining, m_szTimeBuffer3, 40);
+
 	_sntprintf(m_szData, _MAX_PATH, _T("%s / %s (%s)"), m_szTimeBuffer1, m_szTimeBuffer2, m_szTimeBuffer3);
 	GetDlgItem(IDC_TASKTIME_STATIC)->SetWindowText(m_szData);
 
-	// remember current processed data (used for calculating transfer)
-	m_i64LastProcessed=td.m_ullProcessedSize;
-
 	// set progress
-	m_ctlTaskCountProgress.SetPos(boost::numeric_cast<int>(td.m_dPercent));
+	m_ctlTaskCountProgress.SetProgress(spTaskStats->GetProcessedCount(), spTaskStats->GetTotalCount());
+	m_ctlTaskSizeProgress.SetProgress(spTaskStats->GetProcessedSize(), spTaskStats->GetTotalSize());
 
-	SetBufferSizesString(td.m_iCurrentBufferSize, td.m_iCurrentBufferIndex);
+	SetBufferSizesString(spTaskStats->GetCurrentBufferSize(), spSubTaskStats->GetCurrentBufferIndex());
 
-	GetDlgItem(IDC_DESTINATIONOBJECT_STATIC)->SetWindowText(td.m_pathDstPath.ToString());
-	GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(td.m_nPriority)));
-	GetDlgItem(IDC_TASKID_STATIC)->SetWindowText(td.m_strUniqueName);
+	GetDlgItem(IDC_DESTINATIONOBJECT_STATIC)->SetWindowText(spTaskStats->GetDestinationPath());
+	GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING + PriorityToIndex(spTaskStats->GetThreadPriority())));
+	GetDlgItem(IDC_TASKID_STATIC)->SetWindowText(spTaskStats->GetTaskID());
 }
+
+void CStatusDlg::SetWindowTitle(PCTSTR pszText)
+{
+	CString strCurrentTitle;
+	GetWindowText(strCurrentTitle);
+	if(strCurrentTitle != CString(pszText))
+		SetWindowText(pszText);
+}
+
+CString CStatusDlg::GetProgressWindowTitleText() const
+{
+	CString strTitleText;
+
+	if(m_spTaskMgrStats->GetTaskStatsCount() != 0)
+		strTitleText.Format(_T("%s [%.0f %%]"), GetResManager().LoadString(IDS_STATUSTITLE_STRING), m_spTaskMgrStats->GetCombinedProgress() * 100.0);
+	else
+		strTitleText = GetResManager().LoadString(IDS_STATUSTITLE_STRING);
+
+	return strTitleText;
+}
Index: src/ch/StatusDlg.h
===================================================================
diff -u -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/ch/StatusDlg.h	(.../StatusDlg.h)	(revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f)
+++ src/ch/StatusDlg.h	(.../StatusDlg.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -41,18 +41,18 @@
 // Construction
 public:
 	CStatusDlg(chcore::TTaskManager* pTasks, CWnd* pParent = NULL);   // standard constructor
-	~CStatusDlg();
+	virtual ~CStatusDlg();
 
 	void PostCloseMessage();
-	void SetBufferSizesString(UINT uiValue, int iIndex);
+	void SetBufferSizesString(unsigned long long ullValue, int iIndex);
 	void RefreshStatus();
 
 	int GetImageFromStatus(chcore::ETaskCurrentState eState);
 
 	void ApplyButtonsState();
 	chcore::TTaskPtr GetSelectedItemPointer();
+	size_t GetSelectedItemSessionUniqueID();
 
-	void AddTaskInfo(int nPos, const chcore::TTaskPtr& spTask, DWORD dwCurrentTime);
 	void EnableControls(bool bEnable=true);
 
 protected:
@@ -63,17 +63,22 @@
 	virtual void OnLanguageChanged();
 
 	void PrepareResizableControls();
-	CString GetStatusString(const chcore::TASK_DISPLAY_DATA& rTaskDisplayData);
+	CString GetStatusString(const chcore::TTaskStatsSnapshotPtr& spTaskStats);
 
 	void StickDialogToScreenEdge();
 
-	LPTSTR FormatTime(time_t timeSeconds, LPTSTR lpszBuffer, size_t stMaxBufferSize);
+	LPTSTR FormatTime(unsigned long long timeSeconds, LPTSTR lpszBuffer, size_t stMaxBufferSize);
 	LPTSTR FormatTimeMiliseconds(unsigned long long timeMiliSeconds, LPTSTR lpszBuffer, size_t stMaxBufferSize);
 
 	CString GetProcessedText(unsigned long long ullProcessedCount, unsigned long long ullTotalCount, unsigned long long ullProcessedSize, unsigned long long ullTotalSize);
-	void UpdateTaskStatsDetails( chcore::TASK_DISPLAY_DATA &td, DWORD dwCurrentTime );
-	void SetTaskListEntry(const chcore::TASK_DISPLAY_DATA &td, int nPos, const chcore::TTaskPtr& spTask);
+	void UpdateTaskStatsDetails(const chcore::TTaskStatsSnapshotPtr& spTaskStats);
+	void SetTaskListEntry(size_t stPos, const chcore::TTaskStatsSnapshotPtr& spTaskStats);
+	CString GetSubtaskName(chcore::ESubOperationType eSubtask) const;
 
+	CString GetProgressWindowTitleText() const;
+	CString GetSpeedString(double dSizeSpeed, double dAvgSizeSpeed, double dCountSpeed, double dAvgCountSpeed) const;
+	void SetWindowTitle(PCTSTR pszText);
+
 	virtual BOOL OnInitDialog();
 	afx_msg void OnTimer(UINT_PTR nIDEvent);
 	afx_msg void OnPauseButton();
@@ -103,28 +108,24 @@
 
 protected:
 	chcore::TTaskManager* m_pTasks;
-	chcore::TTaskPtr m_spSelectedItem;
 
 	TCHAR m_szData[_MAX_PATH];
 	TCHAR m_szTimeBuffer1[40];
 	TCHAR m_szTimeBuffer2[40];
 	TCHAR m_szTimeBuffer3[40];
 
-	__int64 m_i64LastProcessed;
-	__int64 m_i64LastAllTasksProcessed;
-	DWORD m_dwLastUpdate;
-
 	CImageList m_images;
+	CFFListCtrl m_ctlStatusList;
 
-	CFFListCtrl	m_ctlStatusList;
-
 private:
 	TProgressCtrlEx	m_ctlTaskCountProgress;
 	TProgressCtrlEx	m_ctlTaskSizeProgress;
 	TProgressCtrlEx m_ctlCurrentObjectProgress;
 	TProgressCtrlEx m_ctlSubTaskCountProgress;
 	TProgressCtrlEx m_ctlSubTaskSizeProgress;
 	TProgressCtrlEx	m_ctlProgressAll;
+
+	chcore::TTaskManagerStatsSnapshotPtr m_spTaskMgrStats;
 };
 
 #endif
Index: src/ch/StringHelpers.cpp
===================================================================
diff -u -raa6bff57279b9f9cfc276e9adab2763e2900878d -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/ch/StringHelpers.cpp	(.../StringHelpers.cpp)	(revision aa6bff57279b9f9cfc276e9adab2763e2900878d)
+++ src/ch/StringHelpers.cpp	(.../StringHelpers.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -41,7 +41,7 @@
 }
 #endif
 
-LPTSTR GetSizeString(double dData, LPTSTR pszBuffer, size_t stMaxBufferSize)
+LPCTSTR GetSizeString(double dData, LPTSTR pszBuffer, size_t stMaxBufferSize)
 {
 	if (dData < 0.0)
 		dData=0.0;
@@ -58,7 +58,7 @@
 	return pszBuffer;
 }
 
-LPTSTR GetSizeString(ull_t ullData, LPTSTR pszBuffer, size_t stMaxBufferSize, bool bStrict)
+LPCTSTR GetSizeString(ull_t ullData, LPTSTR pszBuffer, size_t stMaxBufferSize, bool bStrict)
 {
 	if (ullData < 0)
 		ullData=0;
Index: src/ch/StringHelpers.h
===================================================================
diff -u -rd5c3edd0d167db9b5d47d04248820fda49499a5e -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/ch/StringHelpers.h	(.../StringHelpers.h)	(revision d5c3edd0d167db9b5d47d04248820fda49499a5e)
+++ src/ch/StringHelpers.h	(.../StringHelpers.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -24,7 +24,7 @@
 void ExpandFormatString(CString* pstrFmt, DWORD dwError);
 #endif
 
-LPTSTR GetSizeString(double dData, LPTSTR pszBuffer, size_t stMaxBufferSize);
-LPTSTR GetSizeString(ull_t ullData, LPTSTR pszBuffer, size_t stMaxBufferSize, bool bStrict = false);
+LPCTSTR GetSizeString(double dData, LPTSTR pszBuffer, size_t stMaxBufferSize);
+LPCTSTR GetSizeString(ull_t ullData, LPTSTR pszBuffer, size_t stMaxBufferSize, bool bStrict = false);
 
 #endif
Index: src/libchcore/ETaskCurrentState.h
===================================================================
diff -u
--- src/libchcore/ETaskCurrentState.h	(revision 0)
+++ src/libchcore/ETaskCurrentState.h	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -0,0 +1,43 @@
+// ============================================================================
+//  Copyright (C) 2001-2012 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#ifndef __ETASKCURRENTSTATE_H__
+#define __ETASKCURRENTSTATE_H__
+
+#include "libchcore.h"
+
+BEGIN_CHCORE_NAMESPACE
+
+// enum representing current processing state of the task
+enum ETaskCurrentState
+{
+	eTaskState_None,
+	eTaskState_Waiting,
+	eTaskState_Processing,
+	eTaskState_Paused,
+	eTaskState_Cancelled,
+	eTaskState_Error,
+	eTaskState_Finished,
+
+	// insert new values before this one
+	eTaskState_Max
+};
+
+END_CHCORE_NAMESPACE
+
+#endif
Index: src/libchcore/TFileFiltersArray.cpp
===================================================================
diff -u -rba802caea92ee56a154d1da3fe89a4b2f7875f0e -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TFileFiltersArray.cpp	(.../TFileFiltersArray.cpp)	(revision ba802caea92ee56a154d1da3fe89a4b2f7875f0e)
+++ src/libchcore/TFileFiltersArray.cpp	(.../TFileFiltersArray.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -141,4 +141,9 @@
 	return m_vFilters.size();
 }
 
+void TFileFiltersArray::Clear()
+{
+	m_vFilters.clear();
+}
+
 END_CHCORE_NAMESPACE
Index: src/libchcore/TFileFiltersArray.h
===================================================================
diff -u -rba802caea92ee56a154d1da3fe89a4b2f7875f0e -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TFileFiltersArray.h	(.../TFileFiltersArray.h)	(revision ba802caea92ee56a154d1da3fe89a4b2f7875f0e)
+++ src/libchcore/TFileFiltersArray.h	(.../TFileFiltersArray.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -53,6 +53,8 @@
 	bool RemoveAt(size_t stIndex);
 	size_t GetSize() const;
 
+	void Clear();
+
 private:
 #pragma warning(push)
 #pragma warning(disable: 4251)
Index: src/libchcore/TFileInfoArray.cpp
===================================================================
diff -u -r835e0344e9677ff02eb3b539061c48c9f3a616ce -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TFileInfoArray.cpp	(.../TFileInfoArray.cpp)	(revision 835e0344e9677ff02eb3b539061c48c9f3a616ce)
+++ src/libchcore/TFileInfoArray.cpp	(.../TFileInfoArray.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -82,12 +82,12 @@
 	m_bComplete = false;
 }
 
-unsigned long long TFileInfoArray::CalculateTotalSize()
+unsigned long long TFileInfoArray::CalculateTotalSize() const
 {
 	unsigned long long ullSize = 0;
 
 	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	BOOST_FOREACH(TFileInfoPtr& spFileInfo, m_vFiles)
+	BOOST_FOREACH(const TFileInfoPtr& spFileInfo, m_vFiles)
 	{
 		ullSize += spFileInfo->GetLength64();
 	}
Index: src/libchcore/TFileInfoArray.h
===================================================================
diff -u -r835e0344e9677ff02eb3b539061c48c9f3a616ce -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TFileInfoArray.h	(.../TFileInfoArray.h)	(revision 835e0344e9677ff02eb3b539061c48c9f3a616ce)
+++ src/libchcore/TFileInfoArray.h	(.../TFileInfoArray.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -60,7 +60,7 @@
 	unsigned long long CalculatePartialSize(size_t stCount);
 
 	/// Calculates the size of all file info objects inside this object
-	unsigned long long CalculateTotalSize();
+	unsigned long long CalculateTotalSize() const;
 
 	void SetComplete(bool bComplete);
 	bool IsComplete() const;
Index: src/libchcore/TSubTaskArray.cpp
===================================================================
diff -u -r548382442cbf7bed7f744b279ce3f66b54992724 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TSubTaskArray.cpp	(.../TSubTaskArray.cpp)	(revision 548382442cbf7bed7f744b279ce3f66b54992724)
+++ src/libchcore/TSubTaskArray.cpp	(.../TSubTaskArray.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -105,15 +105,13 @@
 ///////////////////////////////////////////////////////////////////////////
 // TSubTasksArray
 
-TSubTasksArray::TSubTasksArray(TTaskLocalStatsInfo& rLocalStats) :
-	m_pSubTaskContext(NULL),
-	m_rLocalStats(rLocalStats)
+TSubTasksArray::TSubTasksArray() :
+	m_pSubTaskContext(NULL)
 {
 }
 
-TSubTasksArray::TSubTasksArray(const TOperationPlan& rOperationPlan, TSubTaskContext& rSubTaskContext, TTaskLocalStatsInfo& rLocalStats) :
-	m_pSubTaskContext(NULL),
-	m_rLocalStats(rLocalStats)
+TSubTasksArray::TSubTasksArray(const TOperationPlan& rOperationPlan, TSubTaskContext& rSubTaskContext) :
+	m_pSubTaskContext(NULL)
 {
 	Init(rOperationPlan, rSubTaskContext);
 }
@@ -133,22 +131,22 @@
 	case eOperation_Copy:
 		{
 			TSubTaskBasePtr spOperation = boost::make_shared<TSubTaskScanDirectories>(boost::ref(rSubTaskContext));
-			AddSubTask(spOperation, 5, true);
+			AddSubTask(spOperation, true);
 			spOperation = boost::make_shared<TSubTaskCopyMove>(boost::ref(rSubTaskContext));
-			AddSubTask(spOperation, 95, false);
+			AddSubTask(spOperation, false);
 
 			break;
 		}
 	case eOperation_Move:
 		{
 			TSubTaskBasePtr spOperation = boost::make_shared<TSubTaskFastMove>(boost::ref(rSubTaskContext));
-			AddSubTask(spOperation, 5, true);
+			AddSubTask(spOperation, true);
 			spOperation = boost::make_shared<TSubTaskScanDirectories>(boost::ref(rSubTaskContext));
-			AddSubTask(spOperation, 5, false);
+			AddSubTask(spOperation, false);
 			spOperation = boost::make_shared<TSubTaskCopyMove>(boost::ref(rSubTaskContext));
-			AddSubTask(spOperation, 85, false);
+			AddSubTask(spOperation, false);
 			spOperation = boost::make_shared<TSubTaskDelete>(boost::ref(rSubTaskContext));
-			AddSubTask(spOperation, 5, false);
+			AddSubTask(spOperation, false);
 
 			break;
 		}
@@ -160,35 +158,34 @@
 void TSubTasksArray::ResetProgressAndStats()
 {
 	m_tProgressInfo.ResetProgress();
-	m_rLocalStats.Clear();
 
-	boost::tuples::tuple<TSubTaskBasePtr, double, bool> tupleRow;
+	std::pair<TSubTaskBasePtr, bool> tupleRow;
 	BOOST_FOREACH(tupleRow, m_vSubTasks)
 	{
-		if(tupleRow.get<0>() == NULL)
+		if(tupleRow.first == NULL)
 			THROW_CORE_EXCEPTION(eErr_InternalProblem);
 
-		tupleRow.get<0>()->Reset();
+		tupleRow.first->Reset();
 	}
 }
 
 void TSubTasksArray::SerializeProgress(TReadBinarySerializer& rSerializer)
 {
 	m_tProgressInfo.Serialize(rSerializer);
-	boost::tuples::tuple<TSubTaskBasePtr, double, bool> tupleRow;
+	std::pair<TSubTaskBasePtr, bool> tupleRow;
 	BOOST_FOREACH(tupleRow, m_vSubTasks)
 	{
-		tupleRow.get<0>()->GetProgressInfo().Serialize(rSerializer);
+		tupleRow.first->GetProgressInfo().Serialize(rSerializer);
 	}
 }
 
 void TSubTasksArray::SerializeProgress(TWriteBinarySerializer& rSerializer) const
 {
 	m_tProgressInfo.Serialize(rSerializer);
-	boost::tuples::tuple<TSubTaskBasePtr, double, bool> tupleRow;
+	std::pair<TSubTaskBasePtr, bool> tupleRow;
 	BOOST_FOREACH(tupleRow, m_vSubTasks)
 	{
-		tupleRow.get<0>()->GetProgressInfo().Serialize(rSerializer);
+		tupleRow.first->GetProgressInfo().Serialize(rSerializer);
 	}
 }
 
@@ -203,16 +200,14 @@
 
 	for(; stSubOperationIndex < m_vSubTasks.size() && eResult == TSubTaskBase::eSubResult_Continue; ++stSubOperationIndex)
 	{
-		boost::tuples::tuple<TSubTaskBasePtr, int, bool>& rCurrentSubTask = m_vSubTasks[stSubOperationIndex];
-		TSubTaskBasePtr spCurrentSubTask = rCurrentSubTask.get<0>();
+		std::pair<TSubTaskBasePtr, bool>& rCurrentSubTask = m_vSubTasks[stSubOperationIndex];
+		TSubTaskBasePtr spCurrentSubTask = rCurrentSubTask.first;
 
-		m_rLocalStats.SetCurrentSubOperationType(spCurrentSubTask->GetSubOperationType());
-
 		// set current sub-operation index to allow resuming
 		m_tProgressInfo.SetSubOperationIndex(stSubOperationIndex);
 
 		// if we run in estimation mode only, then stop processing and return to the caller
-		if(bRunOnlyEstimationSubTasks && !rCurrentSubTask.get<2>())
+		if(bRunOnlyEstimationSubTasks && !rCurrentSubTask.second)
 		{
 			eResult = TSubTaskBase::eSubResult_Continue;
 			break;
@@ -224,42 +219,30 @@
 	return eResult;
 }
 
-void TSubTasksArray::AddSubTask(const TSubTaskBasePtr& spOperation, int iPercent, bool bIsPartOfEstimation)
+void TSubTasksArray::AddSubTask(const TSubTaskBasePtr& spOperation, bool bIsPartOfEstimation)
 {
-	m_vSubTasks.push_back(boost::make_tuple(spOperation, iPercent, bIsPartOfEstimation));
+	m_vSubTasks.push_back(std::make_pair(spOperation, bIsPartOfEstimation));
 }
 
-void TSubTasksArray::GetTaskStats(TTaskStatsSnapshot& rSnapshot) const
+void TSubTasksArray::GetStatsSnapshot(TSubTaskArrayStatsSnapshot& rSnapshot) const
 {
 	rSnapshot.Clear();
 
-	// from local stats
-	m_rLocalStats.GetSnapshot(rSnapshot);
-
 	// current task
 	size_t stSubOperationIndex = m_tProgressInfo.GetSubOperationIndex();
+	rSnapshot.SetCurrentSubtaskIndex(stSubOperationIndex);
 
-	const boost::tuples::tuple<TSubTaskBasePtr, int, bool>& rCurrentSubTask = m_vSubTasks[stSubOperationIndex];
-	TSubTaskBasePtr spCurrentSubTask = rCurrentSubTask.get<0>();
-
-	spCurrentSubTask->GetStatsSnapshot(rSnapshot.GetCurrentSubTaskStats());
-
 	// progress
-	TSubTaskStatsSnapshot tSnapshot;
-	double dTotalProgress = 0.0;
 	for(stSubOperationIndex = 0; stSubOperationIndex < m_vSubTasks.size(); ++stSubOperationIndex)
 	{
-		const boost::tuples::tuple<TSubTaskBasePtr, int, bool>& rCurrentSubTask = m_vSubTasks[stSubOperationIndex];
-		TSubTaskBasePtr spCurrentSubTask = rCurrentSubTask.get<0>();
-		int iSubTaskPercent = rCurrentSubTask.get<1>();
+		const std::pair<TSubTaskBasePtr, bool>& rCurrentSubTask = m_vSubTasks[stSubOperationIndex];
+		TSubTaskBasePtr spCurrentSubTask = rCurrentSubTask.first;
 
-		spCurrentSubTask->GetStatsSnapshot(tSnapshot);
+		TSubTaskStatsSnapshotPtr spSubtaskSnapshot(new TSubTaskStatsSnapshot);
 
-		double dCurrentTaskPercent = tSnapshot.GetProgressInPercent() * iSubTaskPercent / 100.0;
-		dTotalProgress += dCurrentTaskPercent;
+		spCurrentSubTask->GetStatsSnapshot(spSubtaskSnapshot);
+		rSnapshot.AddSubTaskSnapshot(spSubtaskSnapshot);
 	}
-
-	rSnapshot.SetTaskProgressInPercent(dTotalProgress);
 }
 
 END_CHCORE_NAMESPACE
Index: src/libchcore/TSubTaskArray.h
===================================================================
diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TSubTaskArray.h	(.../TSubTaskArray.h)	(revision 12a1725bfd04b0f55fd0fda302975fdcd4174943)
+++ src/libchcore/TSubTaskArray.h	(.../TSubTaskArray.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -27,6 +27,7 @@
 #include <boost/tuple/tuple.hpp>
 #include "TSubTaskBase.h"
 #include "TTaskLocalStats.h"
+#include "TSubTaskArrayStatsSnapshot.h"
 
 BEGIN_CHCORE_NAMESPACE
 
@@ -74,14 +75,14 @@
 class LIBCHCORE_API TSubTasksArray
 {
 public:
-	TSubTasksArray(TTaskLocalStatsInfo& rLocalStats);
-	TSubTasksArray(const TOperationPlan& rOperationPlan, TSubTaskContext& rSubTaskContext, TTaskLocalStatsInfo& rLocalStats);
+	TSubTasksArray();
+	TSubTasksArray(const TOperationPlan& rOperationPlan, TSubTaskContext& rSubTaskContext);
 	~TSubTasksArray();
 
 	void Init(const TOperationPlan& rOperationPlan, TSubTaskContext& rSubTaskContext);
 
 	// Stats handling
-	void GetTaskStats(TTaskStatsSnapshot& rSnapshot) const;
+	void GetStatsSnapshot(TSubTaskArrayStatsSnapshot& rSnapshot) const;
 	void ResetProgressAndStats();
 
 	// progress handling
@@ -94,15 +95,14 @@
 	TSubTasksArray(const TSubTasksArray& rSrc);
 	TSubTasksArray& operator=(const TSubTasksArray& rSrc);
 
-	void AddSubTask(const TSubTaskBasePtr& spOperation, int iPercent, bool bIsPartOfEstimation);
+	void AddSubTask(const TSubTaskBasePtr& spOperation, bool bIsPartOfEstimation);
 
 private:
 	TSubTaskContext* m_pSubTaskContext;
-	TTaskLocalStatsInfo& m_rLocalStats;
 
 #pragma warning(push)
 #pragma warning(disable: 4251)
-	std::vector<boost::tuples::tuple<TSubTaskBasePtr, int, bool> > m_vSubTasks;	// pointer to the subtask object / part of the whole process / is this the part of estimation?
+	std::vector<std::pair<TSubTaskBasePtr, bool> > m_vSubTasks;	// pointer to the subtask object / part of the whole process / is this the part of estimation?
 
 	details::TTaskBasicProgressInfo m_tProgressInfo;
 #pragma warning(pop)
Index: src/libchcore/TSubTaskArrayStatsSnapshot.cpp
===================================================================
diff -u
--- src/libchcore/TSubTaskArrayStatsSnapshot.cpp	(revision 0)
+++ src/libchcore/TSubTaskArrayStatsSnapshot.cpp	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -0,0 +1,62 @@
+// ============================================================================
+//  Copyright (C) 2001-2013 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#include "stdafx.h"
+#include "TSubTaskArrayStatsSnapshot.h"
+#include "ErrorCodes.h"
+#include "TCoreException.h"
+
+BEGIN_CHCORE_NAMESPACE
+
+TSubTaskArrayStatsSnapshot::TSubTaskArrayStatsSnapshot() :
+	m_stCurrentSubtaskIndex(0)
+{
+}
+
+void TSubTaskArrayStatsSnapshot::Clear()
+{
+	m_vSubTaskSnapshots.clear();
+}
+
+void TSubTaskArrayStatsSnapshot::AddSubTaskSnapshot(const TSubTaskStatsSnapshotPtr& spSnapshot)
+{
+	m_vSubTaskSnapshots.push_back(spSnapshot);
+}
+
+TSubTaskStatsSnapshotPtr TSubTaskArrayStatsSnapshot::GetSubTaskSnapshotAt(size_t stIndex) const
+{
+	if(stIndex >= m_vSubTaskSnapshots.size())
+		return TSubTaskStatsSnapshotPtr();
+
+	return m_vSubTaskSnapshots[stIndex];
+}
+
+TSubTaskStatsSnapshotPtr TSubTaskArrayStatsSnapshot::GetCurrentSubTaskSnapshot() const
+{
+	if(m_stCurrentSubtaskIndex >= m_vSubTaskSnapshots.size())
+		return TSubTaskStatsSnapshotPtr();
+
+	return m_vSubTaskSnapshots[m_stCurrentSubtaskIndex];
+}
+
+size_t TSubTaskArrayStatsSnapshot::GetSubTaskSnapshotCount() const
+{
+	return m_vSubTaskSnapshots.size();
+}
+
+END_CHCORE_NAMESPACE
Index: src/libchcore/TSubTaskArrayStatsSnapshot.h
===================================================================
diff -u
--- src/libchcore/TSubTaskArrayStatsSnapshot.h	(revision 0)
+++ src/libchcore/TSubTaskArrayStatsSnapshot.h	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -0,0 +1,52 @@
+// ============================================================================
+//  Copyright (C) 2001-2012 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#ifndef __TSUBTASKARRAYSTATSSNAPSHOT_H__
+#define __TSUBTASKARRAYSTATSSNAPSHOT_H__
+
+#include "libchcore.h"
+#include "TSubTaskStatsSnapshot.h"
+
+BEGIN_CHCORE_NAMESPACE
+
+class LIBCHCORE_API TSubTaskArrayStatsSnapshot
+{
+public:
+	TSubTaskArrayStatsSnapshot();
+
+	void Clear();
+
+	void AddSubTaskSnapshot(const TSubTaskStatsSnapshotPtr& rSnapshot);
+	TSubTaskStatsSnapshotPtr GetSubTaskSnapshotAt(size_t stIndex) const;
+	size_t GetSubTaskSnapshotCount() const;
+	TSubTaskStatsSnapshotPtr GetCurrentSubTaskSnapshot() const;
+
+	size_t GetCurrentSubtaskIndex() const { return m_stCurrentSubtaskIndex; }
+	void SetCurrentSubtaskIndex(size_t val) { m_stCurrentSubtaskIndex = val; }
+
+private:
+	size_t m_stCurrentSubtaskIndex;
+#pragma warning(push)
+#pragma warning(disable: 4251)
+	std::vector<TSubTaskStatsSnapshotPtr> m_vSubTaskSnapshots;
+#pragma warning(pop)
+};
+
+END_CHCORE_NAMESPACE
+
+#endif
Index: src/libchcore/TSubTaskBase.h
===================================================================
diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TSubTaskBase.h	(.../TSubTaskBase.h)	(revision 12a1725bfd04b0f55fd0fda302975fdcd4174943)
+++ src/libchcore/TSubTaskBase.h	(.../TSubTaskBase.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -73,7 +73,7 @@
 	virtual TSubTaskProgressInfo& GetProgressInfo() = 0;
 
 	// stats
-	virtual void GetStatsSnapshot(TSubTaskStatsSnapshot& rStats) const = 0;
+	virtual void GetStatsSnapshot(TSubTaskStatsSnapshotPtr& rStats) const = 0;
 
 protected:
 	// some common operations
Index: src/libchcore/TSubTaskCopyMove.cpp
===================================================================
diff -u -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TSubTaskCopyMove.cpp	(.../TSubTaskCopyMove.cpp)	(revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f)
+++ src/libchcore/TSubTaskCopyMove.cpp	(.../TSubTaskCopyMove.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -151,6 +151,7 @@
 TSubTaskCopyMove::TSubTaskCopyMove(TSubTaskContext& tSubTaskContext) :
 	TSubTaskBase(tSubTaskContext)
 {
+	m_tSubTaskStats.SetSubOperationType(eSubOperation_Copying);
 }
 
 void TSubTaskCopyMove::Reset()
@@ -302,9 +303,15 @@
 	return TSubTaskBase::eSubResult_Continue;
 }
 
-void TSubTaskCopyMove::GetStatsSnapshot(TSubTaskStatsSnapshot& rStats) const
+void TSubTaskCopyMove::GetStatsSnapshot(TSubTaskStatsSnapshotPtr& spStats) const
 {
-	m_tSubTaskStats.GetSnapshot(rStats);
+	m_tSubTaskStats.GetSnapshot(spStats);
+	// if this subtask is not started yet, try to get the most fresh information for processing
+	if(!spStats->IsRunning() && spStats->GetTotalCount() == 0 && spStats->GetTotalSize() == 0)
+	{
+		spStats->SetTotalCount(GetContext().GetFilesCache().GetSize());
+		spStats->SetTotalSize(GetContext().GetFilesCache().CalculateTotalSize());
+	}
 }
 
 TBufferSizes::EBufferType TSubTaskCopyMove::GetBufferIndex(const TBufferSizes& rBufferSizes, const TFileInfoPtr& spFileInfo)
Index: src/libchcore/TSubTaskCopyMove.h
===================================================================
diff -u -rfdf4929dc7df1376ed439b7271765f1a4ca31de6 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TSubTaskCopyMove.h	(.../TSubTaskCopyMove.h)	(revision fdf4929dc7df1376ed439b7271765f1a4ca31de6)
+++ src/libchcore/TSubTaskCopyMove.h	(.../TSubTaskCopyMove.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -83,7 +83,7 @@
 	virtual ESubOperationType GetSubOperationType() const { return eSubOperation_Copying; }
 
 	virtual TSubTaskProgressInfo& GetProgressInfo() { return m_tProgressInfo; }
-	virtual void GetStatsSnapshot(TSubTaskStatsSnapshot& rStats) const;
+	virtual void GetStatsSnapshot(TSubTaskStatsSnapshotPtr& rStats) const;
 
 private:
 	TBufferSizes::EBufferType GetBufferIndex(const TBufferSizes& rBufferSizes, const TFileInfoPtr& spFileInfo);
Index: src/libchcore/TSubTaskDelete.cpp
===================================================================
diff -u -r548382442cbf7bed7f744b279ce3f66b54992724 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TSubTaskDelete.cpp	(.../TSubTaskDelete.cpp)	(revision 548382442cbf7bed7f744b279ce3f66b54992724)
+++ src/libchcore/TSubTaskDelete.cpp	(.../TSubTaskDelete.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -98,6 +98,7 @@
 TSubTaskDelete::TSubTaskDelete(TSubTaskContext& rContext) : 
 	TSubTaskBase(rContext)
 {
+	m_tSubTaskStats.SetSubOperationType(eSubOperation_Deleting);
 }
 
 void TSubTaskDelete::Reset()
@@ -223,9 +224,16 @@
 	return TSubTaskBase::eSubResult_Continue;
 }
 
-void TSubTaskDelete::GetStatsSnapshot(TSubTaskStatsSnapshot& rStats) const
+void TSubTaskDelete::GetStatsSnapshot(TSubTaskStatsSnapshotPtr& spStats) const
 {
-	m_tSubTaskStats.GetSnapshot(rStats);
+	m_tSubTaskStats.GetSnapshot(spStats);
+	// if this subtask is not started yet, try to get the most fresh information for processing
+	if(!spStats->IsRunning() && spStats->GetTotalCount() == 0 && spStats->GetTotalSize() == 0)
+	{
+		spStats->SetTotalCount(GetContext().GetFilesCache().GetSize());
+		spStats->SetTotalSize(0);
+	}
+
 }
 
 END_CHCORE_NAMESPACE
Index: src/libchcore/TSubTaskDelete.h
===================================================================
diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TSubTaskDelete.h	(.../TSubTaskDelete.h)	(revision 12a1725bfd04b0f55fd0fda302975fdcd4174943)
+++ src/libchcore/TSubTaskDelete.h	(.../TSubTaskDelete.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -71,7 +71,7 @@
 	virtual ESubOperationType GetSubOperationType() const { return eSubOperation_Deleting; }
 
 	virtual TSubTaskProgressInfo& GetProgressInfo() { return m_tProgressInfo; }
-	virtual void GetStatsSnapshot(TSubTaskStatsSnapshot& rStats) const;
+	virtual void GetStatsSnapshot(TSubTaskStatsSnapshotPtr& spStats) const;
 
 private:
 #pragma warning(push)
Index: src/libchcore/TSubTaskFastMove.cpp
===================================================================
diff -u -r548382442cbf7bed7f744b279ce3f66b54992724 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TSubTaskFastMove.cpp	(.../TSubTaskFastMove.cpp)	(revision 548382442cbf7bed7f744b279ce3f66b54992724)
+++ src/libchcore/TSubTaskFastMove.cpp	(.../TSubTaskFastMove.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -96,6 +96,7 @@
 TSubTaskFastMove::TSubTaskFastMove(TSubTaskContext& rContext) :
 	TSubTaskBase(rContext)
 {
+	m_tSubTaskStats.SetSubOperationType(eSubOperation_FastMove);
 }
 
 TSubTaskFastMove::~TSubTaskFastMove()
@@ -293,9 +294,9 @@
 	return eSubResult_Continue;
 }
 
-void TSubTaskFastMove::GetStatsSnapshot(TSubTaskStatsSnapshot& rStats) const
+void TSubTaskFastMove::GetStatsSnapshot(TSubTaskStatsSnapshotPtr& spStats) const
 {
-	m_tSubTaskStats.GetSnapshot(rStats);
+	m_tSubTaskStats.GetSnapshot(spStats);
 }
 
 END_CHCORE_NAMESPACE
Index: src/libchcore/TSubTaskFastMove.h
===================================================================
diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TSubTaskFastMove.h	(.../TSubTaskFastMove.h)	(revision 12a1725bfd04b0f55fd0fda302975fdcd4174943)
+++ src/libchcore/TSubTaskFastMove.h	(.../TSubTaskFastMove.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -74,7 +74,7 @@
 	virtual ESubOperationType GetSubOperationType() const { return eSubOperation_Scanning; }
 
 	virtual TSubTaskProgressInfo& GetProgressInfo() { return m_tProgressInfo; }
-	virtual void GetStatsSnapshot(TSubTaskStatsSnapshot& rStats) const;
+	virtual void GetStatsSnapshot(TSubTaskStatsSnapshotPtr& rStats) const;
 
 private:
 	int ScanDirectory(TSmartPath pathDirName, size_t stSrcIndex, bool bRecurse, bool bIncludeDirs, TFileFiltersArray& afFilters);
Index: src/libchcore/TSubTaskScanDirectory.cpp
===================================================================
diff -u -r548382442cbf7bed7f744b279ce3f66b54992724 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TSubTaskScanDirectory.cpp	(.../TSubTaskScanDirectory.cpp)	(revision 548382442cbf7bed7f744b279ce3f66b54992724)
+++ src/libchcore/TSubTaskScanDirectory.cpp	(.../TSubTaskScanDirectory.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -98,6 +98,7 @@
 TSubTaskScanDirectories::TSubTaskScanDirectories(TSubTaskContext& rContext) :
 	TSubTaskBase(rContext)
 {
+	m_tSubTaskStats.SetSubOperationType(eSubOperation_Scanning);
 }
 
 TSubTaskScanDirectories::~TSubTaskScanDirectories()
@@ -281,9 +282,9 @@
 	return eSubResult_Continue;
 }
 
-void TSubTaskScanDirectories::GetStatsSnapshot(TSubTaskStatsSnapshot& rStats) const
+void TSubTaskScanDirectories::GetStatsSnapshot(TSubTaskStatsSnapshotPtr& spStats) const
 {
-	m_tSubTaskStats.GetSnapshot(rStats);
+	m_tSubTaskStats.GetSnapshot(spStats);
 }
 
 int TSubTaskScanDirectories::ScanDirectory(TSmartPath pathDirName, size_t stSrcIndex, bool bRecurse, bool bIncludeDirs, TFileFiltersArray& afFilters)
@@ -300,6 +301,10 @@
 		if(rThreadController.KillRequested())
 			break;
 
+		// tmp
+		Sleep(1000);
+		// /tmp
+
 		if(!spFileInfo->IsDirectory())
 		{
 			if(afFilters.Match(spFileInfo))
Index: src/libchcore/TSubTaskScanDirectory.h
===================================================================
diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TSubTaskScanDirectory.h	(.../TSubTaskScanDirectory.h)	(revision 12a1725bfd04b0f55fd0fda302975fdcd4174943)
+++ src/libchcore/TSubTaskScanDirectory.h	(.../TSubTaskScanDirectory.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -74,7 +74,7 @@
 	virtual ESubOperationType GetSubOperationType() const { return eSubOperation_Scanning; }
 
 	virtual TSubTaskProgressInfo& GetProgressInfo() { return m_tProgressInfo; }
-	virtual void GetStatsSnapshot(TSubTaskStatsSnapshot& rStats) const;
+	virtual void GetStatsSnapshot(TSubTaskStatsSnapshotPtr& spStats) const;
 
 private:
 	int ScanDirectory(TSmartPath pathDirName, size_t stSrcIndex, bool bRecurse, bool bIncludeDirs, TFileFiltersArray& afFilters);
Index: src/libchcore/TSubTaskStatsInfo.cpp
===================================================================
diff -u -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TSubTaskStatsInfo.cpp	(.../TSubTaskStatsInfo.cpp)	(revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f)
+++ src/libchcore/TSubTaskStatsInfo.cpp	(.../TSubTaskStatsInfo.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -58,7 +58,8 @@
 	m_tSizeSpeed(DefaultSpeedTrackTime, DefaultSpeedSampleTime),
 	m_tCountSpeed(DefaultSpeedTrackTime, DefaultSpeedSampleTime),
 	m_ullCurrentItemProcessedSize(0),
-	m_ullCurrentItemTotalSize(0)
+	m_ullCurrentItemTotalSize(0),
+	m_eSubOperationType(eSubOperation_None)
 {
 }
 
@@ -76,27 +77,32 @@
 	m_tCountSpeed.Clear();
 	m_ullCurrentItemProcessedSize = 0;
 	m_ullCurrentItemTotalSize = 0;
+	m_eSubOperationType = eSubOperation_None;
 }
 
-void TSubTaskStatsInfo::GetSnapshot(TSubTaskStatsSnapshot& rStatsSnapshot) const
+void TSubTaskStatsInfo::GetSnapshot(TSubTaskStatsSnapshotPtr& spStatsSnapshot) const
 {
-	rStatsSnapshot.Clear();
+	if(!spStatsSnapshot)
+		THROW_CORE_EXCEPTION(eErr_InvalidArgument);
 
+	spStatsSnapshot->Clear();
+
 	boost::upgrade_lock<boost::shared_mutex> lock(m_lock);
 	UpdateTime(lock);
 
-	rStatsSnapshot.SetRunning(m_bSubTaskIsRunning);
-	rStatsSnapshot.SetProcessedCount(m_stProcessedCount);
-	rStatsSnapshot.SetTotalCount(m_stTotalCount);
-	rStatsSnapshot.SetProcessedSize(m_ullProcessedSize);
-	rStatsSnapshot.SetTotalSize(m_ullTotalSize);
-	rStatsSnapshot.SetCurrentBufferIndex(m_iCurrentBufferIndex);
-	rStatsSnapshot.SetCurrentPath(m_strCurrentPath);
-	rStatsSnapshot.SetTimeElapsed(m_tTimer.GetTotalTime());
-	rStatsSnapshot.SetSizeSpeed(m_tSizeSpeed.GetSpeed());
-	rStatsSnapshot.SetCountSpeed(m_tCountSpeed.GetSpeed());
-	rStatsSnapshot.SetCurrentItemProcessedSize(m_ullCurrentItemProcessedSize);
-	rStatsSnapshot.SetCurrentItemTotalSize(m_ullCurrentItemTotalSize);
+	spStatsSnapshot->SetRunning(m_bSubTaskIsRunning);
+	spStatsSnapshot->SetProcessedCount(m_stProcessedCount);
+	spStatsSnapshot->SetTotalCount(m_stTotalCount);
+	spStatsSnapshot->SetProcessedSize(m_ullProcessedSize);
+	spStatsSnapshot->SetTotalSize(m_ullTotalSize);
+	spStatsSnapshot->SetCurrentBufferIndex(m_iCurrentBufferIndex);
+	spStatsSnapshot->SetCurrentPath(m_strCurrentPath);
+	spStatsSnapshot->SetTimeElapsed(m_tTimer.GetTotalTime());
+	spStatsSnapshot->SetSizeSpeed(m_tSizeSpeed.GetSpeed());
+	spStatsSnapshot->SetCountSpeed(m_tCountSpeed.GetSpeed());
+	spStatsSnapshot->SetCurrentItemProcessedSize(m_ullCurrentItemProcessedSize);
+	spStatsSnapshot->SetCurrentItemTotalSize(m_ullCurrentItemTotalSize);
+	spStatsSnapshot->SetSubOperationType(m_eSubOperationType);
 }
 
 // is running?
Index: src/libchcore/TSubTaskStatsInfo.h
===================================================================
diff -u -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TSubTaskStatsInfo.h	(.../TSubTaskStatsInfo.h)	(revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f)
+++ src/libchcore/TSubTaskStatsInfo.h	(.../TSubTaskStatsInfo.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -27,6 +27,8 @@
 #include "TString.h"
 #include "TSimpleTimer.h"
 #include "TSpeedTracker.h"
+#include "ESubTaskTypes.h"
+#include "TSubTaskStatsSnapshot.h"
 
 BEGIN_CHCORE_NAMESPACE
 
@@ -59,7 +61,7 @@
 
 	void Clear();
 
-	void GetSnapshot(TSubTaskStatsSnapshot& rStatsSnapshot) const;
+	void GetSnapshot(TSubTaskStatsSnapshotPtr& spStatsSnapshot) const;
 
 	void IncreaseProcessedCount(size_t stIncreaseBy);
 	void SetProcessedCount(size_t stIndex);
@@ -84,6 +86,9 @@
 	// current path
 	void SetCurrentPath(const TString& strPath);
 
+	ESubOperationType GetSubOperationType() const { return m_eSubOperationType; }
+	void SetSubOperationType(ESubOperationType val) { m_eSubOperationType = val; }
+
 private:
 	TSubTaskStatsInfo(const TSubTaskStatsInfo&);
 	TSubTaskStatsInfo& operator=(const TSubTaskStatsInfo&);
@@ -117,6 +122,7 @@
 
 	TString m_strCurrentPath;		// currently processed path
 
+	ESubOperationType m_eSubOperationType;
 #pragma warning(push)
 #pragma warning(disable: 4251)
 	mutable boost::shared_mutex m_lock;
Index: src/libchcore/TSubTaskStatsSnapshot.cpp
===================================================================
diff -u -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TSubTaskStatsSnapshot.cpp	(.../TSubTaskStatsSnapshot.cpp)	(revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f)
+++ src/libchcore/TSubTaskStatsSnapshot.cpp	(.../TSubTaskStatsSnapshot.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -42,44 +42,11 @@
 	m_dSizeSpeed(0),
 	m_dCountSpeed(0),
 	m_ullCurrentItemProcessedSize(0),
-	m_ullCurrentItemTotalSize(0)
+	m_ullCurrentItemTotalSize(0),
+	m_eSubOperationType(eSubOperation_None)
 {
 }
 
-TSubTaskStatsSnapshot::TSubTaskStatsSnapshot(const TSubTaskStatsSnapshot& rSrc) :
-	m_bSubTaskIsRunning(rSrc.m_bSubTaskIsRunning),
-	m_ullTotalSize(rSrc.m_ullTotalSize),
-	m_ullProcessedSize(rSrc.m_ullProcessedSize),
-	m_stTotalCount(rSrc.m_stTotalCount),
-	m_stProcessedCount(rSrc.m_stProcessedCount),
-	m_iCurrentBufferIndex(rSrc.m_iCurrentBufferIndex),
-	m_strCurrentPath(rSrc.m_strCurrentPath),
-	m_timeElapsed(rSrc.m_timeElapsed),
-	m_dSizeSpeed(rSrc.m_dSizeSpeed),
-	m_dCountSpeed(rSrc.m_dCountSpeed),
-	m_ullCurrentItemProcessedSize(rSrc.m_ullCurrentItemProcessedSize),
-	m_ullCurrentItemTotalSize(rSrc.m_ullCurrentItemTotalSize)
-{
-}
-
-TSubTaskStatsSnapshot& TSubTaskStatsSnapshot::operator=(const TSubTaskStatsSnapshot& rSrc)
-{
-	m_bSubTaskIsRunning = rSrc.m_bSubTaskIsRunning;
-	m_ullTotalSize = rSrc.m_ullTotalSize;
-	m_ullProcessedSize = rSrc.m_ullProcessedSize;
-	m_stTotalCount = rSrc.m_stTotalCount;
-	m_stProcessedCount = rSrc.m_stProcessedCount;
-	m_iCurrentBufferIndex = rSrc.m_iCurrentBufferIndex;
-	m_strCurrentPath = rSrc.m_strCurrentPath;
-	m_timeElapsed = rSrc.m_timeElapsed;
-	m_dSizeSpeed = rSrc.m_dSizeSpeed;
-	m_dCountSpeed = rSrc.m_dCountSpeed;
-	m_ullCurrentItemProcessedSize = rSrc.m_ullCurrentItemProcessedSize;
-	m_ullCurrentItemTotalSize = rSrc.m_ullCurrentItemTotalSize;
-
-	return *this;
-}
-
 void TSubTaskStatsSnapshot::Clear()
 {
 	m_bSubTaskIsRunning = false;
@@ -94,19 +61,26 @@
 	m_dCountSpeed = 0;
 	m_ullCurrentItemProcessedSize = 0;
 	m_ullCurrentItemTotalSize = 0;
+	m_eSubOperationType = eSubOperation_None;
 }
 
-double TSubTaskStatsSnapshot::CalculateProgressInPercent() const
+double TSubTaskStatsSnapshot::CalculateProgress() const
 {
-	if(m_ullTotalSize != 0)
-		return Math::Div64(m_ullProcessedSize, m_ullTotalSize);
+	// we're treating each of the items as 512B object to process
+	// to have some balance between items' count and items' size in
+	// progress information
+	unsigned long long ullProcessed = 512ULL * m_stProcessedCount + m_ullProcessedSize;
+	unsigned long long ullTotal = 512ULL * m_stTotalCount + m_ullTotalSize;
+
+	if(ullTotal != 0)
+		return Math::Div64(ullProcessed, ullTotal);
 	else
 		return 0.0;
 }
 
 unsigned long long TSubTaskStatsSnapshot::GetEstimatedTotalTime() const
 {
-	double dProgress = CalculateProgressInPercent();
+	double dProgress = CalculateProgress();
 	if(dProgress == 0.0)
 		return std::numeric_limits<unsigned long long>::max();
 	else
@@ -139,4 +113,9 @@
 		return 0.0;
 }
 
+double TSubTaskStatsSnapshot::GetCombinedProgress() const
+{
+	return CalculateProgress();
+}
+
 END_CHCORE_NAMESPACE
Index: src/libchcore/TSubTaskStatsSnapshot.h
===================================================================
diff -u -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TSubTaskStatsSnapshot.h	(.../TSubTaskStatsSnapshot.h)	(revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f)
+++ src/libchcore/TSubTaskStatsSnapshot.h	(.../TSubTaskStatsSnapshot.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -25,6 +25,7 @@
 
 #include "libchcore.h"
 #include "TString.h"
+#include "ESubTaskTypes.h"
 
 BEGIN_CHCORE_NAMESPACE
 
@@ -33,9 +34,6 @@
 public:
 	TSubTaskStatsSnapshot();
 
-	TSubTaskStatsSnapshot(const TSubTaskStatsSnapshot& rSrc);
-	TSubTaskStatsSnapshot& operator=(const TSubTaskStatsSnapshot& rSrc);
-
 	void Clear();
 
 	// is running?
@@ -64,7 +62,7 @@
 	unsigned long long GetCurrentItemTotalSize() const { return m_ullCurrentItemTotalSize; }
 
 	// progress in percent
-	double GetProgressInPercent() const { return CalculateProgressInPercent(); }
+	double GetCombinedProgress() const;	// returns progress [0.0, 1.0]
 
 	// buffer index
 	void SetCurrentBufferIndex(int iCurrentIndex) { m_iCurrentBufferIndex = iCurrentIndex; }
@@ -90,8 +88,11 @@
 	double GetAvgSizeSpeed() const;
 	double GetAvgCountSpeed() const;
 
+	chcore::ESubOperationType GetSubOperationType() const { return m_eSubOperationType; }
+	void SetSubOperationType(chcore::ESubOperationType val) { m_eSubOperationType = val; }
+
 private:
-	double CalculateProgressInPercent() const;
+	double CalculateProgress() const;
 
 private:
 	bool m_bSubTaskIsRunning;
@@ -110,13 +111,17 @@
 	unsigned long long m_ullCurrentItemTotalSize;
 	unsigned long long m_ullCurrentItemProcessedSize;
 
+	ESubOperationType m_eSubOperationType;
+
 	int m_iCurrentBufferIndex;
 
 	TString m_strCurrentPath;		// currently processed path
 
 	unsigned long long m_timeElapsed;			// time really elapsed for the subtask
 };
 
+typedef boost::shared_ptr<TSubTaskStatsSnapshot> TSubTaskStatsSnapshotPtr;
+
 END_CHCORE_NAMESPACE
 
 #endif
Index: src/libchcore/TTask.cpp
===================================================================
diff -u -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TTask.cpp	(.../TTask.cpp)	(revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f)
+++ src/libchcore/TTask.cpp	(.../TTask.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -52,7 +52,7 @@
 	m_stSessionUniqueID(stSessionUniqueID),
 	m_eCurrentState(eTaskState_None),
 	m_tSubTaskContext(m_tTaskDefinition, m_arrSourcePathsInfo, m_files, m_cfgTracker, m_log, piFeedbackHandler, m_workerThread, m_fsLocal),
-	m_tSubTasksArray(m_tLocalStats)
+	m_tSubTasksArray()
 {
 	BOOST_ASSERT(piFeedbackHandler);
 }
@@ -301,61 +301,48 @@
 	}
 }
 
-void TTask::GetMiniSnapshot(TASK_MINI_DISPLAY_DATA *pData)
+void TTask::GetStatsSnapshot(TTaskStatsSnapshotPtr& spSnapshot)
 {
-	TTaskStatsSnapshot tStats;
-	m_tSubTasksArray.GetTaskStats(tStats);
+	if(!spSnapshot)
+		THROW_CORE_EXCEPTION(eErr_InvalidArgument);
 
-	pData->m_strPath = tStats.GetCurrentSubTaskStats().GetCurrentPath();
-	pData->m_dPercent = tStats.GetTaskProgressInPercent();
+	spSnapshot->Clear();
 
 	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	pData->m_eTaskState = m_eCurrentState;
-}
+	m_tSubTasksArray.GetStatsSnapshot(spSnapshot->GetSubTasksStats());
 
-void TTask::GetSnapshot(TASK_DISPLAY_DATA *pData)
-{
-	m_tSubTasksArray.GetTaskStats(pData->m_tTaskSnapshot);
+	m_tLocalStats.GetSnapshot(spSnapshot);
 
-	pData->m_strFullFilePath = pData->m_tTaskSnapshot.GetCurrentSubTaskStats().GetCurrentPath();
-	pData->m_strFileName = chcore::PathFromString(pData->m_strFullFilePath).GetFileName().ToString();
-	pData->m_stIndex = pData->m_tTaskSnapshot.GetCurrentSubTaskStats().GetProcessedCount();
-	pData->m_stSize = pData->m_tTaskSnapshot.GetCurrentSubTaskStats().GetTotalCount();
-	pData->m_ullProcessedSize = pData->m_tTaskSnapshot.GetCurrentSubTaskStats().GetProcessedSize();
-	pData->m_ullSizeAll = pData->m_tTaskSnapshot.GetCurrentSubTaskStats().GetTotalSize();
-	pData->m_eSubOperationType = pData->m_tTaskSnapshot.GetCurrentSubOperationType();
-	pData->m_iCurrentBufferIndex = pData->m_tTaskSnapshot.GetCurrentSubTaskStats().GetCurrentBufferIndex();
-	pData->m_dPercent = pData->m_tTaskSnapshot.GetTaskProgressInPercent();
-	pData->m_timeElapsed = pData->m_tTaskSnapshot.GetTimeElapsed();
+	spSnapshot->SetTaskID(m_tTaskDefinition.GetTaskUniqueID());
+	spSnapshot->SetSessionUniqueID(GetSessionUniqueID());
+	spSnapshot->SetThreadPriority(GetTaskPropValue<eTO_ThreadPriority>(m_tTaskDefinition.GetConfiguration()));
+	spSnapshot->SetDestinationPath(m_tTaskDefinition.GetDestinationPath().ToString());
+	spSnapshot->SetFilters(m_afFilters);
+	spSnapshot->SetTaskState(m_eCurrentState);
+	spSnapshot->SetOperationType(m_tTaskDefinition.GetOperationType());
 
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
+	spSnapshot->SetIgnoreDirectories(GetTaskPropValue<eTO_IgnoreDirectories>(m_tTaskDefinition.GetConfiguration()));
+	spSnapshot->SetCreateEmptyFiles(GetTaskPropValue<eTO_CreateEmptyFiles>(m_tTaskDefinition.GetConfiguration()));
 
-	pData->m_nPriority = GetTaskPropValue<eTO_ThreadPriority>(m_tTaskDefinition.GetConfiguration());
-	pData->m_pathDstPath = m_tTaskDefinition.GetDestinationPath();
-	pData->m_pafFilters = &m_afFilters;
-	pData->m_eTaskState = m_eCurrentState;
-	pData->m_strUniqueName = m_tTaskDefinition.GetTaskUniqueID();
-	pData->m_eOperationType = m_tTaskDefinition.GetOperationType();
+	TSubTaskStatsSnapshotPtr spCurrentSubTask = spSnapshot->GetSubTasksStats().GetCurrentSubTaskSnapshot();
 
-	pData->m_bIgnoreDirectories = GetTaskPropValue<eTO_IgnoreDirectories>(m_tTaskDefinition.GetConfiguration());
-	pData->m_bCreateEmptyFiles = GetTaskPropValue<eTO_CreateEmptyFiles>(m_tTaskDefinition.GetConfiguration());
-
-	switch(pData->m_iCurrentBufferIndex)
+	int iCurrentBufferIndex = spCurrentSubTask ? spCurrentSubTask->GetCurrentBufferIndex() : TBufferSizes::eBuffer_Default;
+	switch(iCurrentBufferIndex)
 	{
 	case TBufferSizes::eBuffer_Default:
-		pData->m_iCurrentBufferSize = GetTaskPropValue<eTO_DefaultBufferSize>(m_tTaskDefinition.GetConfiguration());
+		spSnapshot->SetCurrentBufferSize(GetTaskPropValue<eTO_DefaultBufferSize>(m_tTaskDefinition.GetConfiguration()));
 		break;
 	case TBufferSizes::eBuffer_OneDisk:
-		pData->m_iCurrentBufferSize = GetTaskPropValue<eTO_OneDiskBufferSize>(m_tTaskDefinition.GetConfiguration());
+		spSnapshot->SetCurrentBufferSize(GetTaskPropValue<eTO_OneDiskBufferSize>(m_tTaskDefinition.GetConfiguration()));
 		break;
 	case TBufferSizes::eBuffer_TwoDisks:
-		pData->m_iCurrentBufferSize = GetTaskPropValue<eTO_TwoDisksBufferSize>(m_tTaskDefinition.GetConfiguration());
+		spSnapshot->SetCurrentBufferSize(GetTaskPropValue<eTO_TwoDisksBufferSize>(m_tTaskDefinition.GetConfiguration()));
 		break;
 	case TBufferSizes::eBuffer_CD:
-		pData->m_iCurrentBufferSize = GetTaskPropValue<eTO_CDBufferSize>(m_tTaskDefinition.GetConfiguration());
+		spSnapshot->SetCurrentBufferSize(GetTaskPropValue<eTO_CDBufferSize>(m_tTaskDefinition.GetConfiguration()));
 		break;
 	case TBufferSizes::eBuffer_LAN:
-		pData->m_iCurrentBufferSize = GetTaskPropValue<eTO_LANBufferSize>(m_tTaskDefinition.GetConfiguration());
+		spSnapshot->SetCurrentBufferSize(GetTaskPropValue<eTO_LANBufferSize>(m_tTaskDefinition.GetConfiguration()));
 		break;
 	default:
 		THROW_CORE_EXCEPTION(eErr_UnhandledCase);
@@ -663,11 +650,6 @@
 	return GetRelatedPathNL(ePathType);
 }
 
-void TTask::GetTaskStats(TTaskStatsSnapshot& rSnapshot) const
-{
-	m_tSubTasksArray.GetTaskStats(rSnapshot);
-}
-
 TSmartPath TTask::GetRelatedPathNL(EPathType ePathType)
 {
 	BOOST_ASSERT(!m_strTaskDirectory.IsEmpty() || !m_strFilePath.IsEmpty());
@@ -710,4 +692,9 @@
 	}
 }
 
+bool TTask::IsRunning() const
+{
+	return m_tLocalStats.IsRunning();
+}
+
 END_CHCORE_NAMESPACE
Index: src/libchcore/TTask.h
===================================================================
diff -u -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TTask.h	(.../TTask.h)	(revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f)
+++ src/libchcore/TTask.h	(.../TTask.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -38,64 +38,6 @@
 
 class TBufferSizes;
 
-// enum representing current processing state of the task
-enum ETaskCurrentState
-{
-	eTaskState_None,
-	eTaskState_Waiting,
-	eTaskState_Processing,
-	eTaskState_Paused,
-	eTaskState_Cancelled,
-	eTaskState_Error,
-	eTaskState_Finished,
-
-	// insert new values before this one
-	eTaskState_Max
-};
-
-// structure for getting status of a task
-struct TASK_DISPLAY_DATA
-{
-	chcore::TTaskStatsSnapshot m_tTaskSnapshot;
-
-	TString m_strFullFilePath;
-	TString m_strFileName;
-
-	int m_iCurrentBufferSize;
-	int m_iCurrentBufferIndex;
-	size_t m_stIndex;
-	size_t m_stSize;
-
-	TSmartPath m_pathDstPath;
-	TFileFiltersArray* m_pafFilters;
-
-	ETaskCurrentState m_eTaskState;
-	EOperationType m_eOperationType;
-	ESubOperationType m_eSubOperationType;
-
-	int m_nPriority;
-
-	ull_t m_ullProcessedSize;
-	ull_t m_ullSizeAll;
-	double m_dPercent;
-
-	time_t m_timeElapsed;
-
-	TString m_strUniqueName;	// doesn't change from first setting
-
-	bool m_bIgnoreDirectories;
-	bool m_bCreateEmptyFiles;
-};
-
-struct TASK_MINI_DISPLAY_DATA
-{
-	TString m_strPath;
-
-	ETaskCurrentState m_eTaskState;
-
-	double m_dPercent;
-};
-
 ///////////////////////////////////////////////////////////////////////////
 // TTask
 
@@ -118,6 +60,8 @@
 	void SetTaskState(ETaskCurrentState eTaskState);
 	ETaskCurrentState GetTaskState() const;
 
+	bool IsRunning() const;
+
 	// m_nBufferSize
 	void SetBufferSizes(const TBufferSizes& bsSizes);
 	void GetBufferSizes(TBufferSizes& bsSizes);
@@ -136,8 +80,7 @@
 	void RestartProcessing();	// from beginning
 	void CancelProcessing();	// cancel
 
-	void GetSnapshot(TASK_DISPLAY_DATA *pData);
-	void GetMiniSnapshot(TASK_MINI_DISPLAY_DATA *pData);
+	void GetStatsSnapshot(TTaskStatsSnapshotPtr& spSnapshot);
 
 	void SetTaskDirectory(const TSmartPath& strDir);
 	TSmartPath GetTaskDirectory() const;
@@ -149,9 +92,6 @@
 
 	TSmartPath GetRelatedPath(EPathType ePathType);
 
-	// Stats handling
-	void GetTaskStats(TTaskStatsSnapshot& rSnapshot) const;
-
 private:
 	TTask(IFeedbackHandler* piFeedbackHandler, size_t stSessionUniqueID);
 
Index: src/libchcore/TTaskLocalStats.cpp
===================================================================
diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TTaskLocalStats.cpp	(.../TTaskLocalStats.cpp)	(revision 12a1725bfd04b0f55fd0fda302975fdcd4174943)
+++ src/libchcore/TTaskLocalStats.cpp	(.../TTaskLocalStats.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -41,10 +41,8 @@
 
 TTaskProcessingGuard::~TTaskProcessingGuard()
 {
-	if(!m_bRunningStatePaused)
-		m_rLocalStats.MarkTaskAsNotRunning();
-	if(!m_bTimeTrackingPaused)
-		m_rLocalStats.DisableTimeTracking();
+	m_rLocalStats.MarkTaskAsNotRunning();
+	m_rLocalStats.DisableTimeTracking();
 }
 
 void TTaskProcessingGuard::PauseTimeTracking()
@@ -86,10 +84,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // TTasksGlobalStats members
 TTaskLocalStatsInfo::TTaskLocalStatsInfo() :
-	m_bTaskIsRunning(false),
-	m_timeElapsed(0),
-	m_timeLast(-1),
-	m_eCurrentSubOperationType(eSubOperation_None)
+	m_bTaskIsRunning(false)
 {
 }
 
@@ -100,35 +95,27 @@
 void TTaskLocalStatsInfo::Clear()
 {
 	m_bTaskIsRunning = false;
-	m_timeElapsed = 0;
-	m_timeLast = -1;
-
-	m_eCurrentSubOperationType = eSubOperation_None;
+	m_tTimer.Reset();
 }
 
-void TTaskLocalStatsInfo::GetSnapshot(TTaskStatsSnapshot& rSnapshot) const
+void TTaskLocalStatsInfo::GetSnapshot(TTaskStatsSnapshotPtr& spSnapshot) const
 {
-	rSnapshot.Clear();
-
 	boost::upgrade_lock<boost::shared_mutex> lock(m_lock);
 	UpdateTime(lock);
-	rSnapshot.SetIsTaskIsRunning(m_bTaskIsRunning);
-	rSnapshot.SetCurrentSubOperationType(m_eCurrentSubOperationType);
-	rSnapshot.SetTimeElapsed(m_timeElapsed);
+	spSnapshot->SetTaskRunning(m_bTaskIsRunning);
+	spSnapshot->SetTimeElapsed(m_tTimer.GetTotalTime());
 }
 
 void TTaskLocalStatsInfo::MarkTaskAsRunning()
 {
 	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	if(!m_bTaskIsRunning)
-		m_bTaskIsRunning = true;
+	m_bTaskIsRunning = true;
 }
 
 void TTaskLocalStatsInfo::MarkTaskAsNotRunning()
 {
 	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	if(m_bTaskIsRunning)
-		m_bTaskIsRunning = false;
+	m_bTaskIsRunning = false;
 }
 
 bool TTaskLocalStatsInfo::IsRunning() const
@@ -137,63 +124,22 @@
 	return m_bTaskIsRunning;
 }
 
-void TTaskLocalStatsInfo::SetTimeElapsed(time_t timeElapsed)
+void TTaskLocalStatsInfo::EnableTimeTracking()
 {
 	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	m_timeElapsed = timeElapsed;
+	m_tTimer.Start();
 }
 
-time_t TTaskLocalStatsInfo::GetTimeElapsed()
-{
-	boost::upgrade_lock<boost::shared_mutex> lock(m_lock);
-	UpdateTime(lock);
-
-	return m_timeElapsed;
-}
-
-void TTaskLocalStatsInfo::EnableTimeTracking()
-{
-	boost::upgrade_lock<boost::shared_mutex> lock(m_lock);
-	if(m_timeLast == -1)
-	{
-		boost::upgrade_to_unique_lock<boost::shared_mutex> lock_upgraded(lock);
-		m_timeLast = time(NULL);
-	}
-}
-
 void TTaskLocalStatsInfo::DisableTimeTracking()
 {
-	boost::upgrade_lock<boost::shared_mutex> lock(m_lock);
-	UpdateTime(lock);
-	if(m_timeLast != -1)
-	{
-		boost::upgrade_to_unique_lock<boost::shared_mutex> lock_upgraded(lock);
-		m_timeLast = -1;
-	}
+	boost::unique_lock<boost::shared_mutex> lock(m_lock);
+	m_tTimer.Stop();
 }
 
 void TTaskLocalStatsInfo::UpdateTime(boost::upgrade_lock<boost::shared_mutex>& lock) const
 {
-	if(m_timeLast != -1)
-	{
-		time_t timeCurrent = time(NULL);
-
-		boost::upgrade_to_unique_lock<boost::shared_mutex> lock_upgraded(lock);
-		m_timeElapsed += timeCurrent - m_timeLast;
-		m_timeLast = timeCurrent;
-	}
+	boost::upgrade_to_unique_lock<boost::shared_mutex> lock_upgraded(lock);
+	m_tTimer.Tick();
 }
 
-ESubOperationType TTaskLocalStatsInfo::GetCurrentSubOperationType() const
-{
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
-	return m_eCurrentSubOperationType;
-}
-
-void TTaskLocalStatsInfo::SetCurrentSubOperationType(ESubOperationType eSubOperationType)
-{
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	m_eCurrentSubOperationType = eSubOperationType;
-}
-
 END_CHCORE_NAMESPACE
Index: src/libchcore/TTaskLocalStats.h
===================================================================
diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TTaskLocalStats.h	(.../TTaskLocalStats.h)	(revision 12a1725bfd04b0f55fd0fda302975fdcd4174943)
+++ src/libchcore/TTaskLocalStats.h	(.../TTaskLocalStats.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -26,6 +26,7 @@
 #include "libchcore.h"
 #include "ESubTaskTypes.h"
 #include "TSubTaskStatsInfo.h"
+#include "TTaskStatsSnapshot.h"
 
 BEGIN_CHCORE_NAMESPACE
 
@@ -61,17 +62,17 @@
 	~TTaskLocalStatsInfo();
 
 	void Clear();
-	void GetSnapshot(TTaskStatsSnapshot& rSnapshot) const;
+	void GetSnapshot(TTaskStatsSnapshotPtr& spSnapshot) const;
 
 	void SetCurrentSubOperationType(ESubOperationType eSubOperationType);
 
+	bool IsRunning() const;
+
 protected:
 	// running/not running state
 	void MarkTaskAsRunning();
 	void MarkTaskAsNotRunning();
 
-	bool IsRunning() const;
-
 	// time tracking
 	void EnableTimeTracking();
 	void DisableTimeTracking();
@@ -81,25 +82,18 @@
 	void UpdateTime(boost::upgrade_lock<boost::shared_mutex>& lock) const;
 #pragma warning(pop)
 
-	void SetTimeElapsed(time_t timeElapsed);
-	time_t GetTimeElapsed();
+	void SetTimeElapsed(unsigned long long timeElapsed);
+	unsigned long long GetTimeElapsed();
 
-	// current subtask
-	ESubOperationType GetCurrentSubOperationType() const;
-
 private:
 	TTaskLocalStatsInfo(const TTaskLocalStatsInfo&);
 	TTaskLocalStatsInfo& operator=(const TTaskLocalStatsInfo&);
 
 private:
 	volatile bool m_bTaskIsRunning;
 
-	// time
-	mutable time_t m_timeElapsed;
-	mutable time_t m_timeLast;
+	mutable TSimpleTimer m_tTimer;
 
-	volatile ESubOperationType m_eCurrentSubOperationType;
-
 #pragma warning(push)
 #pragma warning(disable: 4251)
 	mutable boost::shared_mutex m_lock;
Index: src/libchcore/TTaskManager.cpp
===================================================================
diff -u -r548382442cbf7bed7f744b279ce3f66b54992724 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TTaskManager.cpp	(.../TTaskManager.cpp)	(revision 548382442cbf7bed7f744b279ce3f66b54992724)
+++ src/libchcore/TTaskManager.cpp	(.../TTaskManager.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -418,41 +418,28 @@
 	m_pathTasksDir = pathDir;
 }
 
-void TTaskManager::GetStatsSnapshot(TTaskManagerStatsSnapshot& rSnapshot) const
+void TTaskManager::GetStatsSnapshot(TTaskManagerStatsSnapshotPtr& spSnapshot) const
 {
-	boost::shared_lock<boost::shared_mutex> lock(m_lock);
+	if(!spSnapshot)
+		THROW_CORE_EXCEPTION(eErr_InvalidArgument);
 
-	TTaskStatsSnapshot tTaskStats;
+	spSnapshot->Clear();
 
-	size_t stProcessedCount = 0;
-	size_t stTotalCount = 0;
-	unsigned long long ullProcessedSize = 0;
-	unsigned long long ullTotalSize = 0;
-	size_t stRunningTasks = 0;
+	boost::shared_lock<boost::shared_mutex> lock(m_lock);
 
+	size_t stRunningTasks = 0;
 	BOOST_FOREACH(const TTaskPtr& spTask, m_vTasks)
 	{
-		spTask->GetTaskStats(tTaskStats);
-		ETaskCurrentState eState = spTask->GetTaskState();
+		TTaskStatsSnapshotPtr spStats(new TTaskStatsSnapshot);
+		spTask->GetStatsSnapshot(spStats);
 
-		stProcessedCount += tTaskStats.GetCurrentSubTaskStats().GetProcessedCount();
-		stTotalCount += tTaskStats.GetCurrentSubTaskStats().GetTotalCount();
-		ullProcessedSize += tTaskStats.GetCurrentSubTaskStats().GetProcessedSize();
-		ullTotalSize += tTaskStats.GetCurrentSubTaskStats().GetTotalSize();
-
-		if(tTaskStats.IsTaskRunning() && eState == eTaskState_Processing)
+		if(spStats->IsTaskRunning() && spStats->GetTaskState())
 			++stRunningTasks;
+
+		spSnapshot->AddTaskStats(spStats);
 	}
 
-	rSnapshot.SetProcessedCount(stProcessedCount);
-	rSnapshot.SetTotalCount(stTotalCount);
-	rSnapshot.SetProcessedSize(ullProcessedSize);
-	rSnapshot.SetTotalSize(ullTotalSize);
-	rSnapshot.SetRunningTasks(stRunningTasks);
-	if(ullTotalSize)
-		rSnapshot.SetGlobalProgressInPercent(boost::numeric_cast<double>(ullProcessedSize) / boost::numeric_cast<double>(ullTotalSize) * 100.0);
-	else
-		rSnapshot.SetGlobalProgressInPercent(0.0);
+	spSnapshot->SetRunningTasks(stRunningTasks);
 }
 
 size_t TTaskManager::GetCountOfRunningTasks() const
@@ -465,9 +452,7 @@
 
 	BOOST_FOREACH(const TTaskPtr& spTask, m_vTasks)
 	{
-		ETaskCurrentState eState = spTask->GetTaskState();
-		spTask->GetTaskStats(tTaskStats);
-		if(tTaskStats.IsTaskRunning() && eState == eTaskState_Processing)
+		if(spTask->IsRunning() && spTask->GetTaskState() == eTaskState_Processing)
 			++stRunningTasks;
 	}
 
Index: src/libchcore/TTaskManager.h
===================================================================
diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TTaskManager.h	(.../TTaskManager.h)	(revision 12a1725bfd04b0f55fd0fda302975fdcd4174943)
+++ src/libchcore/TTaskManager.h	(.../TTaskManager.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -22,12 +22,12 @@
 #include "libchcore.h"
 #include "FeedbackHandlerBase.h"
 #include "TPath.h"
+#include "TTaskManagerStatsSnapshot.h"
 
 BEGIN_CHCORE_NAMESPACE
 
 class TTaskDefinition;
 class TTask;
-class TTaskManagerStatsSnapshot;
 typedef boost::shared_ptr<TTask> TTaskPtr;
 
 // special value representing no task
@@ -76,7 +76,7 @@
 
 	void SetTasksDir(const TSmartPath& pathDir);
 
-	void GetStatsSnapshot(TTaskManagerStatsSnapshot& rSnapshot) const;
+	void GetStatsSnapshot(TTaskManagerStatsSnapshotPtr& spSnapshot) const;
 	size_t GetCountOfRunningTasks() const;
 
 protected:
Index: src/libchcore/TTaskManagerStatsSnapshot.cpp
===================================================================
diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TTaskManagerStatsSnapshot.cpp	(.../TTaskManagerStatsSnapshot.cpp)	(revision 12a1725bfd04b0f55fd0fda302975fdcd4174943)
+++ src/libchcore/TTaskManagerStatsSnapshot.cpp	(.../TTaskManagerStatsSnapshot.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -22,53 +22,185 @@
 // ============================================================================
 #include "stdafx.h"
 #include "TTaskManagerStatsSnapshot.h"
+#include "MathFunctions.h"
 
 BEGIN_CHCORE_NAMESPACE
 
-
 ////////////////////////////////////////////////////////////////////////////////
 // class TTaskManagerStatsSnapshot
 
 TTaskManagerStatsSnapshot::TTaskManagerStatsSnapshot() :
-	m_stProcessedCount(0),
-	m_stTotalCount(0),
+	m_stRunningTasks(0),
+	m_bCacheFilled(false),
+	m_ullProcessedCount(0),
+	m_ullTotalCount(0),
 	m_ullProcessedSize(0),
 	m_ullTotalSize(0),
-	m_dGlobalProgressInPercent(0.0),
-	m_stRunningTasks(0)
+	m_dCountSpeed(0.0),
+	m_dSizeSpeed(0.0),
+	m_dCombinedProgress(0.0),
+	m_dAvgCountSpeed(0.0),
+	m_dAvgSizeSpeed(0.0)
 {
 }
 
-TTaskManagerStatsSnapshot::TTaskManagerStatsSnapshot(const TTaskManagerStatsSnapshot& rSrc) :
-	m_stProcessedCount(rSrc.m_stProcessedCount),
-	m_stTotalCount(rSrc.m_stTotalCount),
-	m_ullProcessedSize(rSrc.m_ullProcessedSize),
-	m_ullTotalSize(rSrc.m_ullTotalSize),
-	m_dGlobalProgressInPercent(rSrc.m_dGlobalProgressInPercent),
-	m_stRunningTasks(rSrc.m_stRunningTasks)
+void TTaskManagerStatsSnapshot::Clear()
 {
+	m_stRunningTasks = 0;
+	m_bCacheFilled = false;
+	m_ullProcessedCount = 0;
+	m_ullTotalCount = 0;
+	m_ullProcessedSize = 0;
+	m_ullTotalSize = 0;
+	m_dCountSpeed = 0.0;
+	m_dSizeSpeed = 0.0;
+	m_dCombinedProgress = 0.0;
+	m_dAvgCountSpeed = 0.0;
+	m_dAvgSizeSpeed = 0.0;
+
+	m_vTasksSnapshots.clear();
 }
 
-TTaskManagerStatsSnapshot& TTaskManagerStatsSnapshot::operator=(const TTaskManagerStatsSnapshot& rSrc)
+void TTaskManagerStatsSnapshot::AddTaskStats(const TTaskStatsSnapshotPtr& spStats)
 {
-	m_stProcessedCount = rSrc.m_stProcessedCount;
-	m_stTotalCount = rSrc.m_stTotalCount;
-	m_ullProcessedSize = rSrc.m_ullProcessedSize;
-	m_ullTotalSize = rSrc.m_ullTotalSize;
-	m_dGlobalProgressInPercent = rSrc.m_dGlobalProgressInPercent;
-	m_stRunningTasks = rSrc.m_stRunningTasks;
+	m_vTasksSnapshots.push_back(spStats);
+}
 
-	return *this;
+size_t TTaskManagerStatsSnapshot::GetTaskStatsCount() const
+{
+	return m_vTasksSnapshots.size();
 }
 
-void TTaskManagerStatsSnapshot::Clear()
+TTaskStatsSnapshotPtr TTaskManagerStatsSnapshot::GetTaskStatsAt(size_t stIndex) const
 {
-	m_stProcessedCount = 0;
-	m_stTotalCount = 0;
+	if(stIndex >= m_vTasksSnapshots.size())
+		return TTaskStatsSnapshotPtr();
+
+	return m_vTasksSnapshots[stIndex];
+}
+
+TTaskStatsSnapshotPtr TTaskManagerStatsSnapshot::GetTaskStatsForSessionUniqueID(size_t stSessionUniqueID) const
+{
+	BOOST_FOREACH(TTaskStatsSnapshotPtr spStats, m_vTasksSnapshots)
+	{
+		if(spStats->GetSessionUniqueID() == stSessionUniqueID)
+			return spStats;
+	}
+
+	return TTaskStatsSnapshotPtr();
+}
+
+
+void TTaskManagerStatsSnapshot::CalculateProgressAndSpeeds() const
+{
+	m_bCacheFilled = false;
+	m_ullProcessedCount = 0;
+	m_ullTotalCount = 0;
 	m_ullProcessedSize = 0;
 	m_ullTotalSize = 0;
-	m_dGlobalProgressInPercent = 0.0;
-	m_stRunningTasks = 0;
+	m_dCountSpeed = 0.0;
+	m_dSizeSpeed = 0.0;
+	m_dCombinedProgress = 0.0;
+	m_dAvgCountSpeed = 0.0;
+	m_dAvgSizeSpeed = 0.0;
+
+	BOOST_FOREACH(TTaskStatsSnapshotPtr spTaskStats, m_vTasksSnapshots)
+	{
+		m_ullProcessedCount += spTaskStats->GetProcessedCount();
+		m_ullTotalCount += spTaskStats->GetTotalCount();
+
+		m_ullProcessedSize += spTaskStats->GetProcessedSize();
+		m_ullTotalSize += spTaskStats->GetTotalSize();
+
+		m_dCountSpeed += spTaskStats->GetCountSpeed();
+		m_dSizeSpeed += spTaskStats->GetSizeSpeed();
+
+		m_dAvgCountSpeed += spTaskStats->GetAvgCountSpeed();
+		m_dAvgSizeSpeed += spTaskStats->GetAvgSizeSpeed();
+	}
+
+	// we're treating each of the items as 512B object to process
+	// to have some balance between items' count and items' size in
+	// progress information
+	unsigned long long ullProcessed = 512ULL * m_ullProcessedCount + m_ullProcessedSize;
+	unsigned long long ullTotal = 512ULL * m_ullTotalCount + m_ullTotalSize;
+
+	if(ullTotal != 0)
+		m_dCombinedProgress = Math::Div64(ullProcessed, ullTotal);
+
+	m_bCacheFilled = true;
 }
 
+unsigned long long TTaskManagerStatsSnapshot::GetProcessedCount() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	return m_ullProcessedCount;
+}
+
+unsigned long long TTaskManagerStatsSnapshot::GetTotalCount() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	return m_ullTotalCount;
+}
+
+unsigned long long TTaskManagerStatsSnapshot::GetProcessedSize() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	return m_ullProcessedSize;
+}
+
+unsigned long long TTaskManagerStatsSnapshot::GetTotalSize() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	return m_ullTotalSize;
+}
+
+double TTaskManagerStatsSnapshot::GetCountSpeed() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	return m_dCountSpeed;
+}
+
+double TTaskManagerStatsSnapshot::GetSizeSpeed() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	return m_dSizeSpeed;
+}
+
+double TTaskManagerStatsSnapshot::GetCombinedProgress() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	return m_dCombinedProgress;
+}
+
+double TTaskManagerStatsSnapshot::GetAvgCountSpeed() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	return m_dAvgCountSpeed;
+}
+
+double TTaskManagerStatsSnapshot::GetAvgSizeSpeed() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	return m_dAvgSizeSpeed;
+}
+
 END_CHCORE_NAMESPACE
Index: src/libchcore/TTaskManagerStatsSnapshot.h
===================================================================
diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TTaskManagerStatsSnapshot.h	(.../TTaskManagerStatsSnapshot.h)	(revision 12a1725bfd04b0f55fd0fda302975fdcd4174943)
+++ src/libchcore/TTaskManagerStatsSnapshot.h	(.../TTaskManagerStatsSnapshot.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -24,6 +24,7 @@
 #define __TTASKMANAGERSTATSSNAPSHOT_H__
 
 #include "libchcore.h"
+#include "TTaskStatsSnapshot.h"
 
 BEGIN_CHCORE_NAMESPACE
 
@@ -37,36 +38,55 @@
 
 	void Clear();
 
-	size_t GetProcessedCount() const { return m_stProcessedCount; }
-	void SetProcessedCount(size_t stCount) { m_stProcessedCount = stCount; }
+	void AddTaskStats(const TTaskStatsSnapshotPtr& spStats);
+	size_t GetTaskStatsCount() const;
+	TTaskStatsSnapshotPtr GetTaskStatsAt(size_t stIndex) const;
+	TTaskStatsSnapshotPtr GetTaskStatsForSessionUniqueID(size_t stSessionUniqueID) const;
 
-	size_t GetTotalCount() const { return m_stTotalCount; }
-	void SetTotalCount(size_t stTotalCount) { m_stTotalCount = stTotalCount; }
+	size_t GetRunningTasks() const { return m_stRunningTasks; }
+	void SetRunningTasks(size_t stRunningTasks) { m_stRunningTasks = stRunningTasks; }
 
-	unsigned long long GetProcessedSize() const { return m_ullProcessedSize; }
-	void SetProcessedSize(unsigned long long ullProcessedSize) { m_ullProcessedSize = ullProcessedSize; }
+	unsigned long long GetProcessedCount() const;
+	unsigned long long GetTotalCount() const;
+	unsigned long long GetProcessedSize() const;
+	unsigned long long GetTotalSize() const;
 
-	unsigned long long GetTotalSize() const { return m_ullTotalSize; }
-	void SetTotalSize(unsigned long long ullTotalSize) { m_ullTotalSize = ullTotalSize; }
+	double GetCountSpeed() const;
+	double GetAvgCountSpeed() const;
+	double GetSizeSpeed() const;
+	double GetAvgSizeSpeed() const;
 
-	double GetGlobalProgressInPercent() const { return m_dGlobalProgressInPercent; }
-	void SetGlobalProgressInPercent(double dPercent) { m_dGlobalProgressInPercent = dPercent; }
+	double GetCombinedProgress() const;
 
-	size_t GetRunningTasks() const { return m_stRunningTasks; }
-	void SetRunningTasks(size_t stRunningTasks) { m_stRunningTasks = stRunningTasks; }
+private:
+	void CalculateProgressAndSpeeds() const;
 
 private:
-	size_t m_stProcessedCount;
-	size_t m_stTotalCount;
+	size_t m_stRunningTasks;
 
-	unsigned long long m_ullProcessedSize;
-	unsigned long long m_ullTotalSize;
+#pragma warning(push)
+#pragma warning(disable: 4251)
+	std::vector<TTaskStatsSnapshotPtr> m_vTasksSnapshots;
+#pragma warning(pop)
 
-	double m_dGlobalProgressInPercent;
+	// cache for items calculated on-demand
+	mutable bool m_bCacheFilled;
+	mutable unsigned long long m_ullProcessedCount;
+	mutable unsigned long long m_ullTotalCount;
+	mutable unsigned long long m_ullProcessedSize;
+	mutable unsigned long long m_ullTotalSize;
 
-	size_t m_stRunningTasks;
+	mutable double m_dCountSpeed;
+	mutable double m_dSizeSpeed;
+
+	mutable double m_dAvgCountSpeed;
+	mutable double m_dAvgSizeSpeed;
+
+	mutable double m_dCombinedProgress;
 };
 
+typedef boost::shared_ptr<TTaskManagerStatsSnapshot> TTaskManagerStatsSnapshotPtr;
+
 END_CHCORE_NAMESPACE
 
 #endif
Index: src/libchcore/TTaskStatsSnapshot.cpp
===================================================================
diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TTaskStatsSnapshot.cpp	(.../TTaskStatsSnapshot.cpp)	(revision 12a1725bfd04b0f55fd0fda302975fdcd4174943)
+++ src/libchcore/TTaskStatsSnapshot.cpp	(.../TTaskStatsSnapshot.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -22,51 +22,192 @@
 // ============================================================================
 #include "stdafx.h"
 #include "TTaskStatsSnapshot.h"
+#include "MathFunctions.h"
 
 BEGIN_CHCORE_NAMESPACE
 
 ////////////////////////////////////////////////////////////////////////////////
 // TTaskStatsSnapshot members
 
 TTaskStatsSnapshot::TTaskStatsSnapshot() :
-	m_tCurrentSubTaskStats(),
+	m_tSubTasksStats(),
 	m_bTaskIsRunning(false),
-	m_eCurrentSubOperationType(eSubOperation_None),
-	m_timeElapsed(0),
-	m_dTaskProgress(0.0)
+	m_ullTimeElapsed(0),
+	m_iThreadPriority(0),
+	m_strDestinationPath(),
+	m_filters(),
+	m_eTaskState(eTaskState_None),
+	m_strTaskID(),
+	m_eOperationType(eOperation_None),
+	m_bIgnoreDirectories(false),
+	m_bCreateEmptyFiles(false),
+	m_ullCurrentBufferSize(0),
+	m_stSessionUniqueID(0),
+	m_bCacheFilled(false),
+	m_ullProcessedCount(0),
+	m_ullTotalCount(0),
+	m_ullProcessedSize(0),
+	m_ullTotalSize(0),
+	m_dTaskCountSpeed(0.0),
+	m_dTaskSizeSpeed(0.0),
+	m_dCombinedProgress(0.0)
 {
 }
 
-TTaskStatsSnapshot::TTaskStatsSnapshot(const TTaskStatsSnapshot& rSrc) :
-	m_tCurrentSubTaskStats(rSrc.m_tCurrentSubTaskStats),
-	m_bTaskIsRunning(rSrc.m_bTaskIsRunning),
-	m_eCurrentSubOperationType(rSrc.m_eCurrentSubOperationType),
-	m_timeElapsed(rSrc.m_timeElapsed),
-	m_dTaskProgress(rSrc.m_dTaskProgress)
+void TTaskStatsSnapshot::Clear()
 {
+	m_tSubTasksStats.Clear();
+	m_bTaskIsRunning = false;
+	m_ullTimeElapsed = 0;
+	m_iThreadPriority = 0;
+	m_strDestinationPath.Clear();
+	m_filters.Clear();
+	m_eTaskState = eTaskState_None;
+	m_strTaskID.Clear();
+	m_eOperationType = eOperation_None;
+	m_bIgnoreDirectories = false;
+	m_bCreateEmptyFiles = false;
+	m_ullCurrentBufferSize = 0;
+	m_stSessionUniqueID = 0;
+	m_bCacheFilled = false;
+	m_ullProcessedCount = 0;
+	m_ullTotalCount = 0;
+	m_ullProcessedSize = 0;
+	m_ullTotalSize = 0;
+	m_dTaskCountSpeed = 0.0;
+	m_dTaskSizeSpeed = 0.0;
+	m_dCombinedProgress = 0.0;
 }
 
-TTaskStatsSnapshot& TTaskStatsSnapshot::operator=(const TTaskStatsSnapshot& rSrc)
+void TTaskStatsSnapshot::CalculateProgressAndSpeeds() const
 {
-	if(this != &rSrc)
+	m_bCacheFilled = false;
+	m_ullProcessedCount = 0;
+	m_ullTotalCount = 0;
+	m_ullProcessedSize = 0;
+	m_ullTotalSize = 0;
+	m_dTaskCountSpeed = 0.0;
+	m_dTaskSizeSpeed = 0.0;
+	m_dCombinedProgress = 0.0;
+
+	size_t stCount = m_tSubTasksStats.GetSubTaskSnapshotCount();
+	for(size_t stIndex = 0; stIndex < stCount; ++stIndex)
 	{
-		m_tCurrentSubTaskStats = rSrc.m_tCurrentSubTaskStats;
-		m_bTaskIsRunning = rSrc.m_bTaskIsRunning;
-		m_eCurrentSubOperationType = rSrc.m_eCurrentSubOperationType;
-		m_timeElapsed = rSrc.m_timeElapsed;
-		m_dTaskProgress = rSrc.m_dTaskProgress;
+		TSubTaskStatsSnapshotPtr spSubtaskStats = m_tSubTasksStats.GetSubTaskSnapshotAt(stIndex);
+
+		m_ullProcessedCount += spSubtaskStats->GetProcessedCount();
+		m_ullTotalCount += spSubtaskStats->GetTotalCount();
+
+		m_ullProcessedSize += spSubtaskStats->GetProcessedSize();
+		m_ullTotalSize += spSubtaskStats->GetTotalSize();
+
+		m_dTaskCountSpeed += spSubtaskStats->GetCountSpeed();
+		m_dTaskSizeSpeed += spSubtaskStats->GetSizeSpeed();
 	}
 
-	return *this;
+	// we're treating each of the items as 512B object to process
+	// to have some balance between items' count and items' size in
+	// progress information
+	unsigned long long ullProcessed = 512ULL * m_ullProcessedCount + m_ullProcessedSize;
+	unsigned long long ullTotal = 512ULL * m_ullTotalCount + m_ullTotalSize;
+
+	if(ullTotal != 0)
+		m_dCombinedProgress = Math::Div64(ullProcessed, ullTotal);
+
+	m_bCacheFilled = true;
 }
 
-void TTaskStatsSnapshot::Clear()
+unsigned long long TTaskStatsSnapshot::GetProcessedCount() const
 {
-	m_tCurrentSubTaskStats.Clear();
-	m_bTaskIsRunning = false;
-	m_eCurrentSubOperationType = eSubOperation_None;
-	m_timeElapsed = 0;
-	m_dTaskProgress = 0.0;
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	return m_ullProcessedCount;
 }
 
+unsigned long long TTaskStatsSnapshot::GetTotalCount() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	return m_ullTotalCount;
+}
+
+unsigned long long TTaskStatsSnapshot::GetProcessedSize() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	return m_ullProcessedSize;
+}
+
+unsigned long long TTaskStatsSnapshot::GetTotalSize() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	return m_ullTotalSize;
+}
+
+double TTaskStatsSnapshot::GetCountSpeed() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	return m_dTaskCountSpeed;
+}
+
+double TTaskStatsSnapshot::GetSizeSpeed() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	return m_dTaskSizeSpeed;
+}
+
+double TTaskStatsSnapshot::GetCombinedProgress() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	return m_dCombinedProgress;
+}
+
+double TTaskStatsSnapshot::GetAvgCountSpeed() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	if(m_ullTimeElapsed)
+		return Math::Div64(m_ullProcessedCount, m_ullTimeElapsed / 1000);
+	else
+		return 0.0;
+}
+
+double TTaskStatsSnapshot::GetAvgSizeSpeed() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	if(m_ullTimeElapsed)
+		return Math::Div64(m_ullProcessedSize, m_ullTimeElapsed / 1000);
+	else
+		return 0.0;
+}
+
+unsigned long long TTaskStatsSnapshot::GetEstimatedTotalTime() const
+{
+	if(!m_bCacheFilled)
+		CalculateProgressAndSpeeds();
+
+	double dProgress = 0.0;
+	if(m_ullTotalSize != 0)
+		dProgress = Math::Div64(m_ullProcessedSize, m_ullTotalSize);
+
+	if(dProgress == 0.0)
+		return std::numeric_limits<unsigned long long>::max();
+	else
+		return (unsigned long long)(m_ullTimeElapsed * (1.0 / dProgress));
+}
+
 END_CHCORE_NAMESPACE
Index: src/libchcore/TTaskStatsSnapshot.h
===================================================================
diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/TTaskStatsSnapshot.h	(.../TTaskStatsSnapshot.h)	(revision 12a1725bfd04b0f55fd0fda302975fdcd4174943)
+++ src/libchcore/TTaskStatsSnapshot.h	(.../TTaskStatsSnapshot.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -26,45 +26,112 @@
 #include "libchcore.h"
 #include "TSubTaskStatsInfo.h"
 #include "ESubTaskTypes.h"
-#include "TSubTaskStatsSnapshot.h"
+#include "TSubTaskArrayStatsSnapshot.h"
+#include "TFileFiltersArray.h"
+#include "EOperationTypes.h"
+#include "ETaskCurrentState.h"
 
 BEGIN_CHCORE_NAMESPACE
 
 class LIBCHCORE_API TTaskStatsSnapshot
 {
 public:
 	TTaskStatsSnapshot();
-	TTaskStatsSnapshot(const TTaskStatsSnapshot& rSrc);
 
-	TTaskStatsSnapshot& operator=(const TTaskStatsSnapshot& rSrc);
-
 	void Clear();
 
-	const TSubTaskStatsSnapshot& GetCurrentSubTaskStats() const { return m_tCurrentSubTaskStats; }
-	TSubTaskStatsSnapshot& GetCurrentSubTaskStats() { return m_tCurrentSubTaskStats; }
+	// subtasks' stats
+	const TSubTaskArrayStatsSnapshot& GetSubTasksStats() const { return m_tSubTasksStats; }
+	TSubTaskArrayStatsSnapshot& GetSubTasksStats() { return m_tSubTasksStats; }
 
+	// task running
 	bool IsTaskRunning() const { return m_bTaskIsRunning; }
-	void SetIsTaskIsRunning(bool bRunning) { m_bTaskIsRunning = bRunning; }
+	void SetTaskRunning(bool bRunning) { m_bTaskIsRunning = bRunning; }
 
-	ESubOperationType GetCurrentSubOperationType() const { return m_eCurrentSubOperationType; }
-	void SetCurrentSubOperationType(ESubOperationType eSubTaskType) { m_eCurrentSubOperationType = eSubTaskType; }
+	// time elapsed
+	unsigned long long GetTimeElapsed() const { return m_ullTimeElapsed; }
+	void SetTimeElapsed(unsigned long long ullTimeElapsed) { m_ullTimeElapsed = ullTimeElapsed; }
+	unsigned long long GetEstimatedTotalTime() const;
 
-	time_t GetTimeElapsed() const { return m_timeElapsed; }
-	void SetTimeElapsed(time_t timeElapsed) { m_timeElapsed = timeElapsed; }
+	// speed and progress
+	unsigned long long GetProcessedCount() const;
+	unsigned long long GetTotalCount() const;
+	unsigned long long GetProcessedSize() const;
+	unsigned long long GetTotalSize() const;
 
-	double GetTaskProgressInPercent() const { return m_dTaskProgress; }
-	void SetTaskProgressInPercent(double dProgress) { m_dTaskProgress = dProgress; }
+	double GetCountSpeed() const;
+	double GetSizeSpeed() const;
+	double GetAvgCountSpeed() const;
+	double GetAvgSizeSpeed() const;
 
+	double GetCombinedProgress() const;
+
+	// other properties
+	int GetThreadPriority() const { return m_iThreadPriority; }
+	void SetThreadPriority(int val) { m_iThreadPriority = val; }
+	
+	TString GetDestinationPath() const { return m_strDestinationPath; }
+	void SetDestinationPath(const TString& val) { m_strDestinationPath = val; }
+
+	const TFileFiltersArray& GetFilters() const { return m_filters; }
+	void SetFilters(const TFileFiltersArray& val) { m_filters = val; }
+
+	ETaskCurrentState GetTaskState() const { return m_eTaskState; }
+	void SetTaskState(ETaskCurrentState val) { m_eTaskState = val; }
+
+	TString GetTaskID() const { return m_strTaskID; }
+	void SetTaskID(const TString& val) { m_strTaskID = val; }
+
+	EOperationType GetOperationType() const { return m_eOperationType; }
+	void SetOperationType(EOperationType val) { m_eOperationType = val; }
+
+	bool GetIgnoreDirectories() const { return m_bIgnoreDirectories; }
+	void SetIgnoreDirectories(bool val) { m_bIgnoreDirectories = val; }
+
+	bool GetCreateEmptyFiles() const { return m_bCreateEmptyFiles; }
+	void SetCreateEmptyFiles(bool val) { m_bCreateEmptyFiles = val; }
+
+	void SetCurrentBufferSize(unsigned long long ullSize) { m_ullCurrentBufferSize = ullSize; }
+	unsigned long long GetCurrentBufferSize() const { return m_ullCurrentBufferSize; }
+
+	size_t GetSessionUniqueID() const { return m_stSessionUniqueID; }
+	void SetSessionUniqueID(size_t val) { m_stSessionUniqueID = val; }
+
 private:
-	TSubTaskStatsSnapshot m_tCurrentSubTaskStats;
+	void CalculateProgressAndSpeeds() const;
 
-	double m_dTaskProgress;
+private:
+	TSubTaskArrayStatsSnapshot m_tSubTasksStats;
 
 	bool m_bTaskIsRunning;
-	ESubOperationType m_eCurrentSubOperationType;
-	time_t m_timeElapsed;
+	unsigned long long m_ullTimeElapsed;
+
+	int m_iThreadPriority;
+	TString m_strDestinationPath;
+	TFileFiltersArray m_filters;
+	ETaskCurrentState m_eTaskState;
+	TString m_strTaskID;
+	EOperationType m_eOperationType;
+	bool m_bIgnoreDirectories;
+	bool m_bCreateEmptyFiles;
+	unsigned long long m_ullCurrentBufferSize;
+	size_t m_stSessionUniqueID;
+
+	// cache for items calculated on-demand
+	mutable bool m_bCacheFilled;
+	mutable unsigned long long m_ullProcessedCount;
+	mutable unsigned long long m_ullTotalCount;
+	mutable unsigned long long m_ullProcessedSize;
+	mutable unsigned long long m_ullTotalSize;
+
+	mutable double m_dTaskCountSpeed;
+	mutable double m_dTaskSizeSpeed;
+
+	mutable double m_dCombinedProgress;
 };
 
+typedef boost::shared_ptr<TTaskStatsSnapshot> TTaskStatsSnapshotPtr;
+
 END_CHCORE_NAMESPACE
 
 #endif
Index: src/libchcore/libchcore.vc90.vcproj
===================================================================
diff -u -rf18d23588f370de68d37adb285dcf5e046a8d37c -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8
--- src/libchcore/libchcore.vc90.vcproj	(.../libchcore.vc90.vcproj)	(revision f18d23588f370de68d37adb285dcf5e046a8d37c)
+++ src/libchcore/libchcore.vc90.vcproj	(.../libchcore.vc90.vcproj)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
@@ -848,6 +848,14 @@
 					>
 				</File>
 				<File
+					RelativePath=".\TSubTaskArrayStatsSnapshot.cpp"
+					>
+				</File>
+				<File
+					RelativePath=".\TSubTaskArrayStatsSnapshot.h"
+					>
+				</File>
+				<File
 					RelativePath=".\TSubTaskBase.cpp"
 					>
 				</File>