bool CRenderingDlg::StartNextJob()
{
	while (m_CurJob < GetJobCount()) {
		CString	s;
		s.Format(IDS_REND_STATUS, m_CurJob, GetJobCount(), 
			round(m_CurJob * 100.0 / GetJobCount()));
		m_Status.SetWindowText(s);	// update status text
		CSnapshot&	Snap = m_Hist->GetItem(m_JobList[m_CurJob]);
		if (m_CurJob > 0) {
			// if previous item has escape times and differs from this item in
			// color only, share previous item's escape times, avoiding render
			CSnapshot&	PrevSnap = m_Hist->GetItem(m_JobList[m_CurJob - 1]);
			if (PrevSnap.HasEscTimes() && Snap.EqualIgnoreColor(PrevSnap))
				Snap.m_EscTimes = PrevSnap.m_EscTimes;	// add a reference
		}
		if (Exporting()) {	// if exporting bitmaps
			m_View->SetSnapshotCached(Snap, TRUE);	// render; allow color remap
		} else {	// not exporting
			if (m_SaveEscTimes && !Snap.HasEscTimes())	// if escape times needed
				Snap.m_Image.SetEmpty();	// delete image to force render
			m_View->SetSnapshotCached(Snap, TRUE);	// render; allow color remap
		}
		if (!m_View->IsIdle())	// if engine is busy doing whatever
			return(TRUE);	// engine will send us UWM_RENDERDONE when it's done
		// engine is idle; assume image and/or escape times were cached
		if (!FinishJob())	// if error finishing job
			return(FALSE);	// abort; assume dialog is already ended
	}
	OnOK();	// no more jobs; success
	return(TRUE);
}
void CJobControlDlg::UpdateStatuses(int OldStatus, int NewStatus)
{
	for (int i = 0; i < GetJobCount(); i++) {
		if (GetStatus(i) == OldStatus)
			SetStatus(i, NewStatus);
	}
}
void CJobControlDlg::Delete(int JobIdx)
{
	m_Job.m_Info.RemoveAt(JobIdx);
	if (!GetJobCount())		// if queue is empty
		m_Job.m_NextID = 0;	// reset unique ID sequence
	UpdateList();
}
bool CRenderingDlg::BuildJobList()
{
	m_View = theApp.GetMain()->GetView();
	if (m_View == NULL)
		return(FALSE);
	COptionsDlg&	opts = theApp.GetMain()->GetOptionsDlg();
	m_CacheImages = opts.GetCacheImages();
	m_SaveEscTimes = opts.GetSaveEscTimes();
	m_RenderCount = 0;
	m_Hist = m_View->GetHistoryView();
	m_Hist->GetSelection(m_JobList);
	int	jobs = GetJobCount();
	for (int i = 0; i < jobs; i++) {
		CSnapshot&	snap = m_Hist->GetItem(m_JobList[i]);
		if (!snap.HasImage() || (!snap.HasEscTimes() && m_SaveEscTimes))
			m_RenderCount++;	// count item as a render
	}
	if (!Exporting()) {	// if not exporting
		if (!m_RenderCount)	// if no items need rendering
			return(TRUE);	// nothing to do
		if (!m_CacheImages) {	// if not caching images
			// multiple render is pointless since images wouldn't be saved
			AfxMessageBox(IDS_REND_CANT_MULTI_RENDER);
			return(FALSE);
		}
	}
	return(TRUE);
}
BOOL CRenderingDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();

	if (!m_Caption.IsEmpty())
		SetWindowText(m_Caption);
	if (BuildJobList()) {	// if job list builds OK
		if (m_RenderCount || Exporting()) {	// if we have work to do
			m_Progress.SetRange32(0, GetJobCount());	// set progress bar range
			// intercept all messages sent by the view's engine; our handlers
			// will forward the messages to the view
			m_PrevEngineWnd = m_View->GetEngine().GetNotifyWnd();
			m_View->GetEngine().SetNotifyWnd(m_hWnd);
			// we don't call StartNextJob directly, because if all the images
			// are cached, StartNextJob finishes all the jobs and calls OnOK
			// before returning, in which case we'll never have been visible;
			// post a message instead, and call StartNextJob from the handler
			PostMessage(UWM_STARTNEXTJOB);
		} else	// job list is empty
			OnOK();	// nothing to do
	} else	// error building job list
		EndDialog(IDABORT);
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}
int CJobControlDlg::FindByStatus(int Status) const
{
	int	jobs = GetJobCount();
	for (int i = 0; i < jobs; i++) {
		if (m_Job.m_Info[i].m_Status == Status)
			return(i);
	}
	return(-1);
}
int CJobControlDlg::FindByID(int JobID) const
{
	int	jobs = GetJobCount();
	for (int i = 0; i < jobs; i++) {
		if (m_Job.m_Info[i].m_ID == JobID)
			return(i);
	}
	return(-1);
}
void CJobControlDlg::Move(int Src, int Dest)
{
	if (Src == Dest)
		return;	// nothing to do
	CJobInfo	info = m_Job.m_Info[Src];
	m_Job.m_Info.RemoveAt(Src);
	m_Job.m_Info.InsertAt(min(Dest, GetJobCount()), info);
	SetCurSel(Dest);
	UpdateList();
}
void CJobControlDlg::OnDestroy() 
{
	if (GetJobCount() || m_JobFileRead) {	// if we have jobs or job file was read
		if (!PathFileExists(m_JobPath)) {	// if job file doesn't exist yet
			CString	JobFolder;
			theApp.GetAppDataFolder(JobFolder);
			theApp.CreateFolder(JobFolder);	// make sure destination folder exists
		}
		m_Job.Write(m_JobPath);	// write jobs
	}
	CToolDlg::OnDestroy();
}
void CJobControlDlg::UpdateUI(int JobIdx)
{
	int	jobs = GetJobCount();
	if (JobIdx < 0)
		JobIdx = GetCurSel();
	// update job positioning buttons
	m_MoveUpBtn.EnableWindow(JobIdx > 0);
	m_MoveDownBtn.EnableWindow(JobIdx >= 0 && JobIdx < jobs - 1);
	// update job status buttons; don't let user change status of running job
	bool	StatChgOK = JobIdx >= 0 && !IsRunning(JobIdx);
	m_PostponeBtn.EnableWindow(StatChgOK);
	m_DeleteBtn.EnableWindow(StatChgOK);
	// update job control buttons
	bool	BatchMode = m_Main->GetBatchMode();	// true if batch jobs are running
	m_StartBtn.EnableWindow(jobs && !BatchMode && FindWaiting() >= 0);
	m_AbortBtn.EnableWindow(jobs && BatchMode);
	m_SkipBtn.EnableWindow(JobIdx >= 0 && BatchMode);
}
void CJobControlDlg::UpdateList()
{
	m_List.SetItemCountEx(GetJobCount(), 0);	// invalidate all items
	UpdateUI();
}
Beispiel #12
0
void glTextureManager::BuildCompressedCache()
{
    idx_sorted_by_distance.Clear();
    
    // Building the cache may take a long time....
    // Be a little smarter.
    // Build a sorted array of chart database indices, sorted on distance from the ownship currently.
    // This way, a user may build a few charts textures for immediate use, then "skip" out on the rest until later.
    int count = 0;
    for(int i = 0; i<ChartData->GetChartTableEntries(); i++) {
        /* skip if not kap */
        const ChartTableEntry &cte = ChartData->GetChartTableEntry(i);
        ChartTypeEnum chart_type = (ChartTypeEnum)cte.GetChartType();
        if(chart_type != CHART_TYPE_KAP)
            continue;
        
        wxString CompressedCacheFilePath = CompressedCachePath(ChartData->GetDBChartFileName(i));
        wxFileName fn(CompressedCacheFilePath);
        //        if(fn.FileExists()) /* skip if file exists */
        //            continue;
        
        idx_sorted_by_distance.Add(i);
        
        count++;
    }  
    
    if(count == 0)
        return;
    
    wxLogMessage(wxString::Format(_T("BuildCompressedCache() count = %d"), count ));
    
    b_inCompressAllCharts = true;
    PurgeJobList();
    ClearAllRasterTextures();
    
    //  Build another array of sorted compression targets.
    //  We need to do this, as the chart table will not be invariant
    //  after the compression threads start, so our index array will be invalid.
    
    ArrayOfCompressTargets ct_array;
    for(unsigned int j = 0; j<idx_sorted_by_distance.GetCount(); j++) {
        
        int i = idx_sorted_by_distance.Item(j);
        
        const ChartTableEntry &cte = ChartData->GetChartTableEntry(i);
        double distance = chart_dist(i);
        
        wxString filename(cte.GetpFullPath(), wxConvUTF8);
        
        compress_target *pct = new compress_target;
        pct->distance = distance;
        pct->chart_path = filename;
        
        ct_array.Add(pct);
    }
    
    // create progress dialog
    long style = wxPD_SMOOTH | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME | wxPD_CAN_SKIP;
    
    wxString msg0;
    msg0 = _T("                                                                               \n  \n  ");
    
    #ifdef __WXQT__    
    msg0 = _T("Very longgggggggggggggggggggggggggggggggggggggggggggg\ngggggggggggggggggggggggggggggggggggggggggggg top line ");
    #endif    
    
    
    for(int i=0 ; i < m_max_jobs+1 ; i++)
        msg0 += _T("\n                                             ");
    
    m_progDialog = new wxGenericProgressDialog();
    
    wxFont *qFont = GetOCPNScaledFont(_("Dialog"));  
    int fontSize = qFont->GetPointSize();
    wxFont *sFont;    
    wxSize csz = cc1->GetClientSize();
    if(csz.x < 500 || csz.y < 500)
        sFont = FontMgr::Get().FindOrCreateFont( 10, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
    else
        sFont = FontMgr::Get().FindOrCreateFont( fontSize, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
    
    m_progDialog->SetFont( *sFont );
    
    //  Should we use "compact" screen layout?
    wxScreenDC sdc;
    int height, width;
    sdc.GetTextExtent(_T("[WWWWWWWWWWWWWWWWWWWWWWWWWWWWWW]"), &width, &height, NULL, NULL, sFont);
    if(width > (csz.x / 2))
        m_bcompact = true;
    
    
    m_progDialog->Create(_("OpenCPN Compressed Cache Update"), msg0, count+1, NULL, style );
    
    //    Make sure the dialog is big enough to be readable
    m_progDialog->Hide();
    wxSize sz = m_progDialog->GetSize();
    sz.x = csz.x * 9 / 10;
    m_progDialog->SetSize( sz );
    
    m_progDialog->Layout();
    wxSize sza = m_progDialog->GetSize();
    
    wxSize pprog_size = sz;
    m_progDialog->Centre();
    m_progDialog->Show();
    m_progDialog->Raise();
    
    m_skipout = false;
    m_skip = false;
    
    for( m_jcnt = 0; m_jcnt<ct_array.GetCount(); m_jcnt++) {
        
        wxString filename = ct_array.Item(m_jcnt).chart_path;
        wxString CompressedCacheFilePath = CompressedCachePath(filename);
        double distance = ct_array.Item(m_jcnt).distance;
        
        ChartBase *pchart = ChartData->OpenChartFromDBAndLock( filename, FULL_INIT );
        if(!pchart) /* probably a corrupt chart */
            continue;
        
        // bad things if more than one texfactory for a chart
            g_glTextureManager->PurgeChartTextures( pchart, true );
            
            
            ChartBaseBSB *pBSBChart = dynamic_cast<ChartBaseBSB*>( pchart );
            if(pBSBChart) {
                
                glTexFactory *tex_fact = new glTexFactory(pchart, g_raster_format);
                
                m_progMsg.Printf( _("Distance from Ownship:  %4.0f NMi\n"), distance);
                m_progMsg.Prepend(_T("Preparing RNC Cache...\n"));
                
                if(m_skipout) {
                    g_glTextureManager->PurgeJobList();
                    ChartData->DeleteCacheChart(pchart);
                    delete tex_fact;
                    break;
                }
                
                int size_X = pBSBChart->GetSize_X();
                int size_Y = pBSBChart->GetSize_Y();
                
                int tex_dim = g_GLOptions.m_iTextureDimension;
                
                int nx_tex = ceil( (float)size_X / tex_dim );
                int ny_tex = ceil( (float)size_Y / tex_dim );
                
                int nt = ny_tex * nx_tex;
                
                wxRect rect;
                rect.y = 0;
                rect.width = tex_dim;
                rect.height = tex_dim;
                for( int y = 0; y < ny_tex; y++ ) {
                    rect.x = 0;
                    for( int x = 0; x < nx_tex; x++ ) {
                        
                        
                        for(int level = 0; level < g_mipmap_max_level + 1; level++ )
                            if(!tex_fact->IsLevelInCache( level, rect, global_color_scheme )){
                                
                                goto schedule;
                            }
                            rect.x += rect.width;
                    }
                    rect.y += rect.height;
                }
                
                //      Free all possible memory
                ChartData->DeleteCacheChart(pchart);
                delete tex_fact;
                continue;
                
                schedule:
                ScheduleJob(tex_fact, wxRect(), 0, false, true, true, false);            
                while(!m_skip) {
                    ::wxYield();
                    int cnt = GetJobCount() - GetRunningJobCount();
                    if(!cnt)
                        break;
                    wxThread::Sleep(1);
                }
                
                if(m_skipout) {
                    g_glTextureManager->PurgeJobList();
                    ChartData->DeleteCacheChart(pchart);
                    delete tex_fact;
                    break;
                }
            }
    }
    
    while(GetRunningJobCount()) {
        wxThread::Sleep(1);
        ::wxYield();
    }
    
    b_inCompressAllCharts = false;
    
    delete m_progDialog;
    m_progDialog = NULL;
}