Upstream tarball 20080414
[amule.git] / src / PartFileConvert.cpp
blobf33738bbb4ec8eeb700d7809aaebbc28c90e0b44
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )
6 //
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
9 // respective authors.
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include <wx/app.h>
28 #include "PartFileConvert.h"
30 #ifdef CLIENT_GUI
32 // This allows us to compile muuli_wdr
34 CConvertListCtrl::CConvertListCtrl(
35 wxWindow* WXUNUSED(parent),
36 wxWindowID WXUNUSED(winid),
37 const wxPoint& WXUNUSED(pos),
38 const wxSize& WXUNUSED(size),
39 long WXUNUSED(style),
40 const wxValidator& WXUNUSED(validator),
41 const wxString& WXUNUSED(name))
44 #else
46 // Normal compilation
48 #include "amule.h"
49 #include "DownloadQueue.h"
50 #include <common/Format.h>
51 #include "Logger.h"
52 #include "PartFile.h"
53 #include "Preferences.h"
54 #include "SharedFileList.h"
55 #include <common/FileFunctions.h>
57 #include <wx/stdpaths.h>
58 #include "muuli_wdr.h"
61 enum convstatus{
62 CONV_OK = 0,
63 CONV_QUEUE,
64 CONV_INPROGRESS,
65 CONV_OUTOFDISKSPACE,
66 CONV_PARTMETNOTFOUND,
67 CONV_IOERROR,
68 CONV_FAILED,
69 CONV_BADFORMAT,
70 CONV_ALREADYEXISTS
73 struct ConvertJob {
74 CPath folder;
75 CPath filename;
76 wxString filehash;
77 int format;
78 int state;
79 uint32 size;
80 uint32 spaceneeded;
81 uint8 partmettype;
82 bool removeSource;
83 ConvertJob() { size=0; spaceneeded=0; partmettype=PMT_UNKNOWN; removeSource = true; }
84 //~ConvertJob() {}
87 wxThread* CPartFileConvert::s_convertPfThread = NULL;
88 std::list<ConvertJob*> CPartFileConvert::s_jobs;
89 ConvertJob* CPartFileConvert::s_pfconverting = NULL;
90 wxMutex CPartFileConvert::s_mutex;
92 CPartFileConvertDlg* CPartFileConvert::s_convertgui = NULL;
94 int CPartFileConvert::ScanFolderToAdd(const CPath& folder, bool deletesource)
96 int count = 0;
97 CDirIterator finder(folder);
99 CPath file = finder.GetFirstFile(CDirIterator::File, wxT("*.part.met"));
100 while (!file.IsOk()) {
101 ConvertToeMule(folder.JoinPaths(file), deletesource);
102 file = finder.GetNextFile();
103 count++;
105 /* Shareaza
106 file = finder.GetFirstFile(CDirIterator::File, wxT("*.sd"));
107 while (!file.IsEmpty()) {
108 ConvertToeMule(file, deletesource);
109 file = finder.GetNextFile();
110 count++;
114 file = finder.GetFirstFile(CDirIterator::Dir, wxT("*.*"));
115 while (!file.IsOk()) {
116 ScanFolderToAdd(folder.JoinPaths(file), deletesource);
118 file = finder.GetNextFile();
121 return count;
124 void CPartFileConvert::ConvertToeMule(const CPath& file, bool deletesource)
126 if (!file.FileExists()) {
127 return;
130 ConvertJob* newjob = new ConvertJob();
131 newjob->folder = file;
132 newjob->removeSource = deletesource;
133 newjob->state = CONV_QUEUE;
135 wxMutexLocker lock(s_mutex);
137 s_jobs.push_back(newjob);
139 if (s_convertgui) {
140 s_convertgui->AddJob(newjob);
143 StartThread();
146 void CPartFileConvert::StartThread()
148 if (!s_convertPfThread) {
149 s_convertPfThread = new CPartFileConvert();
151 switch ( s_convertPfThread->Create() ) {
152 case wxTHREAD_NO_ERROR:
153 AddDebugLogLineM( false, logPfConvert, wxT("A new thread has been created.") );
154 break;
155 case wxTHREAD_RUNNING:
156 AddDebugLogLineM( true, logPfConvert, wxT("Error, attempt to create a already running thread!") );
157 break;
158 case wxTHREAD_NO_RESOURCE:
159 AddDebugLogLineM( true, logPfConvert, wxT("Error, attempt to create a thread without resources!") );
160 break;
161 default:
162 AddDebugLogLineM( true, logPfConvert, wxT("Error, unknown error attempting to create a thread!") );
165 // The thread shouldn't hog the CPU, as it will already be hogging the HD
166 s_convertPfThread->SetPriority(WXTHREAD_MIN_PRIORITY);
168 s_convertPfThread->Run();
172 void CPartFileConvert::StopThread()
174 if (s_convertPfThread) {
175 s_convertPfThread->Delete();
176 } else {
177 return;
180 printf("Waiting for partfile convert thread to die...\n");
181 while (s_convertPfThread) {
182 wxSleep(1);
186 wxThread::ExitCode CPartFileConvert::Entry()
188 int imported = 0;
190 for (;;)
192 // search next queued job and start it
194 wxMutexLocker lock(s_mutex);
195 s_pfconverting = NULL;
196 for (std::list<ConvertJob*>::iterator it = s_jobs.begin(); it != s_jobs.end(); ++it) {
197 s_pfconverting = *it;
198 if (s_pfconverting->state == CONV_QUEUE) {
199 break;
200 } else {
201 s_pfconverting = NULL;
206 if (s_pfconverting) {
208 wxMutexLocker lock(s_mutex);
209 s_pfconverting->state = CONV_INPROGRESS;
212 UpdateGUI(s_pfconverting);
214 int convertResult = performConvertToeMule(s_pfconverting->folder);
216 wxMutexLocker lock(s_mutex);
217 s_pfconverting->state = convertResult;
220 if (s_pfconverting->state == CONV_OK) {
221 ++imported;
224 if (TestDestroy()) {
225 wxMutexLocker lock(s_mutex);
226 for (std::list<ConvertJob*>::iterator it = s_jobs.begin(); it != s_jobs.end(); ++it) {
227 delete *it;
229 s_jobs.clear();
230 break;
234 UpdateGUI(s_pfconverting);
236 AddLogLineM(true, CFormat(_("Importing %s: %s")) % s_pfconverting->folder % GetReturncodeText(s_pfconverting->state));
237 } else {
238 break; // nothing more to do now
242 // clean up
243 UpdateGUI(NULL);
245 if (imported) {
246 theApp->sharedfiles->PublishNextTurn();
249 AddDebugLogLineM(false, logPfConvert, wxT("No more jobs on queue, exiting from thread."));
251 s_convertPfThread = NULL;
253 return NULL;
256 int CPartFileConvert::performConvertToeMule(const CPath& fileName)
258 wxString filepartindex, buffer;
259 unsigned fileindex;
261 CPath folder = fileName.GetPath();
262 CPath partfile = fileName.GetFullName();
263 CPath newfilename;
265 CDirIterator finder(folder);
267 UpdateGUI(0, _("Reading temp folder"), true);
269 filepartindex = partfile.RemoveAllExt().GetRaw();
271 UpdateGUI(4, _("Retrieving basic information from download info file"));
273 CPartFile* file = new CPartFile();
274 s_pfconverting->partmettype = file->LoadPartFile(folder, partfile, false, true);
276 switch (s_pfconverting->partmettype) {
277 case PMT_UNKNOWN:
278 case PMT_BADFORMAT:
279 delete file;
280 return CONV_BADFORMAT;
283 CPath oldfile = folder.JoinPaths(partfile.RemoveExt());
286 wxMutexLocker lock(s_mutex);
287 s_pfconverting->size = file->GetFileSize();
288 s_pfconverting->filename = file->GetFileName();
289 s_pfconverting->filehash = file->GetFileHash().Encode();
292 UpdateGUI(s_pfconverting);
294 if (theApp->downloadqueue->GetFileByID(file->GetFileHash())) {
295 delete file;
296 return CONV_ALREADYEXISTS;
299 if (s_pfconverting->partmettype == PMT_SPLITTED) {
300 char *ba = new char [PARTSIZE];
302 try {
303 CFile inputfile;
305 // just count
306 unsigned maxindex = 0;
307 unsigned partfilecount = 0;
308 CPath filePath = finder.GetFirstFile(CDirIterator::File, filepartindex + wxT(".*.part"));
309 while (!filePath.IsOk()) {
310 long l;
311 ++partfilecount;
312 filePath.GetFullName().RemoveExt().GetExt().ToLong(&l);
313 fileindex = (unsigned)l;
314 filePath = finder.GetNextFile();
315 // GonoszTopi - why the hell does eMule need this??
316 //if (fileindex == 0) continue;
317 if (fileindex > maxindex) maxindex = fileindex;
319 float stepperpart;
321 wxMutexLocker lock(s_mutex);
322 if (partfilecount > 0) {
323 stepperpart = (80.0f / partfilecount);
324 if (maxindex * PARTSIZE <= s_pfconverting->size) {
325 s_pfconverting->spaceneeded = maxindex * PARTSIZE;
326 } else {
327 s_pfconverting->spaceneeded = ((s_pfconverting->size / PARTSIZE) * PARTSIZE) + (s_pfconverting->size % PARTSIZE);
329 } else {
330 stepperpart = 80.0f;
331 s_pfconverting->spaceneeded = 0;
335 UpdateGUI(s_pfconverting);
337 sint64 freespace = CPath::GetFreeSpaceAt(thePrefs::GetTempDir());
338 if (freespace != wxInvalidOffset) {
339 if (static_cast<uint64>(freespace) < maxindex * PARTSIZE) {
340 delete file;
341 delete [] ba;
342 return CONV_OUTOFDISKSPACE;
346 // create new partmetfile, and remember the new name
347 file->CreatePartFile();
348 newfilename = file->GetFullName();
350 UpdateGUI(8, _("Creating destination file"));
352 file->m_hpartfile.SetLength( s_pfconverting->spaceneeded );
354 unsigned curindex = 0;
355 CPath filename = finder.GetFirstFile(CDirIterator::File, filepartindex + wxT(".*.part"));
356 while (filename.IsOk()) {
357 // stats
358 ++curindex;
359 buffer = wxString::Format(_("Loading data from old download file (%u of %u)"), curindex, partfilecount);
361 UpdateGUI(10 + (curindex * stepperpart), buffer);
363 long l;
364 filename.GetFullName().RemoveExt().GetExt().ToLong(&l);
365 fileindex = (unsigned)l;
366 if (fileindex == 0) {
367 filename = finder.GetNextFile();
368 continue;
371 uint32 chunkstart = (fileindex - 1) * PARTSIZE;
373 // open, read data of the part-part-file into buffer, close file
374 inputfile.Open(filename, CFile::read);
375 uint64 toReadWrite = std::min<uint64>(PARTSIZE, inputfile.GetLength());
376 inputfile.Read(ba, toReadWrite);
377 inputfile.Close();
379 buffer = wxString::Format(_("Saving data block into new single download file (%u of %u)"), curindex, partfilecount);
381 UpdateGUI(10 + (curindex * stepperpart), buffer);
383 // write the buffered data
384 file->m_hpartfile.Seek(chunkstart, wxFromStart);
385 file->m_hpartfile.Write(ba, toReadWrite);
387 filename = finder.GetNextFile();
389 delete[] ba;
390 } catch (const CSafeIOException& e) {
391 AddDebugLogLineM(true, logPfConvert, wxT("IO error while converting partfiles: ") + e.what());
393 delete[] ba;
394 file->Delete();
395 return CONV_IOERROR;
398 file->m_hpartfile.Close();
400 // import an external common format partdownload
401 else //if (pfconverting->partmettype==PMT_DEFAULTOLD || pfconverting->partmettype==PMT_NEWOLD || Shareaza )
403 if (!s_pfconverting->removeSource) {
404 wxMutexLocker lock(s_mutex);
405 s_pfconverting->spaceneeded = oldfile.GetFileSize();
408 UpdateGUI(s_pfconverting);
410 sint64 freespace = CPath::GetFreeSpaceAt(thePrefs::GetTempDir());
411 if (freespace == wxInvalidOffset) {
412 delete file;
413 return CONV_IOERROR;
414 } else if (!s_pfconverting->removeSource && (freespace < s_pfconverting->spaceneeded)) {
415 delete file;
416 return CONV_OUTOFDISKSPACE;
419 file->CreatePartFile();
420 newfilename = file->GetFullName().RemoveExt();
422 file->m_hpartfile.Close();
424 bool ret = false;
426 UpdateGUI(92, _("Copy"));
428 CPath::RemoveFile(newfilename);
429 if (!oldfile.FileExists()) {
430 // data file does not exist. well, then create a 0 byte big one
431 CFile datafile;
432 ret = datafile.Create(newfilename);
433 } else if (s_pfconverting->removeSource) {
434 ret = CPath::RenameFile(oldfile, newfilename);
435 } else {
436 ret = CPath::CloneFile(oldfile, newfilename, false);
438 if (!ret) {
439 file->Delete();
440 //delete file;
441 return CONV_FAILED;
446 UpdateGUI(94, _("Retrieving source downloadfile information"));
448 CPath::RemoveFile(newfilename);
449 if (s_pfconverting->removeSource) {
450 CPath::RenameFile(folder.JoinPaths(partfile), newfilename);
451 } else {
452 CPath::CloneFile(folder.JoinPaths(partfile), newfilename, false);
455 file->m_hashlist.clear();
457 DeleteContents(file->m_gaplist);
459 if (!file->LoadPartFile(thePrefs::GetTempDir(), file->GetPartMetFileName(), false)) {
460 //delete file;
461 file->Delete();
462 return CONV_BADFORMAT;
465 if (s_pfconverting->partmettype == PMT_NEWOLD || s_pfconverting->partmettype == PMT_SPLITTED ) {
466 file->SetCompletedSize(file->transferred);
467 file->m_iGainDueToCompression = 0;
468 file->m_iLostDueToCorruption = 0;
471 UpdateGUI(100, _("Adding download and saving new partfile"));
473 theApp->downloadqueue->AddDownload(file, thePrefs::AddNewFilesPaused(), 0);
474 file->SavePartFile();
476 if (file->GetStatus(true) == PS_READY) {
477 theApp->sharedfiles->SafeAddKFile(file); // part files are always shared files
480 if (s_pfconverting->removeSource) {
481 CPath oldFile = finder.GetFirstFile(CDirIterator::File, filepartindex + wxT(".*"));
482 while (oldFile.IsOk()) {
483 CPath::RemoveFile(folder.JoinPaths(oldFile));
484 oldFile = finder.GetNextFile();
487 if (s_pfconverting->partmettype == PMT_SPLITTED) {
488 CPath::RemoveDir(folder);
492 return CONV_OK;
495 void CPartFileConvert::UpdateGUI(float percent, wxString text, bool fullinfo)
497 if (!IsMain()) {
498 wxMutexGuiEnter();
501 if (s_convertgui) {
502 s_convertgui->m_pb_current->SetValue((int)percent);
503 wxString buffer = wxString::Format(wxT("%.2f %%"), percent);
504 wxStaticText* percentlabel = dynamic_cast<wxStaticText*>(s_convertgui->FindWindow(IDC_CONV_PROZENT));
505 percentlabel->SetLabel(buffer);
507 if (!text.IsEmpty()) {
508 dynamic_cast<wxStaticText*>(s_convertgui->FindWindow(IDC_CONV_PB_LABEL))->SetLabel(text);
511 percentlabel->GetParent()->Layout();
513 if (fullinfo) {
514 dynamic_cast<wxStaticBoxSizer*>(IDC_CURJOB)->GetStaticBox()->SetLabel(s_pfconverting->folder.GetPrintable());
518 if (!IsMain()) {
519 wxMutexGuiLeave();
523 void CPartFileConvert::UpdateGUI(ConvertJob* job)
525 if (!IsMain()) {
526 wxMutexGuiEnter();
528 if (s_convertgui) {
529 s_convertgui->UpdateJobInfo(job);
531 if (!IsMain()) {
532 wxMutexGuiLeave();
536 void CPartFileConvert::ShowGUI(wxWindow* parent)
538 if (s_convertgui) {
539 s_convertgui->Show(true);
540 s_convertgui->Raise();
541 } else {
542 s_convertgui = new CPartFileConvertDlg(parent);
543 s_convertgui->Show(true);
545 wxMutexLocker lock(s_mutex);
546 if (s_pfconverting) {
547 UpdateGUI(s_pfconverting);
548 UpdateGUI(50, _("Fetching status..."), true);
551 // fill joblist
552 for (std::list<ConvertJob*>::iterator it = s_jobs.begin(); it != s_jobs.end(); ++it) {
553 s_convertgui->AddJob(*it);
554 UpdateGUI(*it);
559 void CPartFileConvert::CloseGUI()
561 if (s_convertgui) {
562 s_convertgui->Show(false);
563 s_convertgui->Destroy();
564 s_convertgui = NULL;
568 void CPartFileConvert::RemoveAllJobs()
570 wxMutexLocker lock(s_mutex);
571 for (std::list<ConvertJob*>::iterator it = s_jobs.begin(); it != s_jobs.end(); ++it) {
572 if (s_convertgui) {
573 s_convertgui->RemoveJob(*it);
575 delete *it;
577 s_jobs.clear();
580 void CPartFileConvert::RemoveJob(ConvertJob* job)
582 wxMutexLocker lock(s_mutex);
583 for (std::list<ConvertJob*>::iterator it = s_jobs.begin(); it != s_jobs.end(); ++it) {
584 if (*it == job) {
585 if (s_convertgui) {
586 s_convertgui->RemoveJob(job);
588 s_jobs.erase(it);
589 delete *it;
594 void CPartFileConvert::RemoveAllSuccJobs()
596 wxMutexLocker lock(s_mutex);
597 for (std::list<ConvertJob*>::iterator it = s_jobs.begin(); it != s_jobs.end(); ++it) {
598 if ((*it)->state == CONV_OK) {
599 if (s_convertgui) {
600 s_convertgui->RemoveJob(*it);
602 s_jobs.erase(it);
603 delete *it;
608 wxString CPartFileConvert::GetReturncodeText(int ret)
610 switch (ret) {
611 case CONV_OK : return _("Completed");
612 case CONV_INPROGRESS : return _("In progress");
613 case CONV_OUTOFDISKSPACE : return _("Error: Out of diskspace");
614 case CONV_PARTMETNOTFOUND : return _("Error: Partmet not found");
615 case CONV_IOERROR : return _("Error: IO error!");
616 case CONV_FAILED : return _("Error: Failed!");
617 case CONV_QUEUE : return _("Queued");
618 case CONV_ALREADYEXISTS : return _("Already downloading");
619 case CONV_BADFORMAT : return _("Unknown or bad tempfile format.");
620 default: return wxT("?");
625 CConvertListCtrl::CConvertListCtrl(wxWindow* parent, wxWindowID winid, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name)
626 : wxListCtrl(parent, winid, pos, size, style, validator, name)
628 InsertColumn(0, _("File name"), wxLIST_FORMAT_LEFT, 200);
629 InsertColumn(1, _("State"), wxLIST_FORMAT_LEFT, 100);
630 InsertColumn(2, _("Size"), wxLIST_FORMAT_LEFT, 100);
631 InsertColumn(3, _("Filehash"), wxLIST_FORMAT_LEFT, 100);
634 #ifndef __WXMSW__
635 /* XPM */
636 static char * convert_xpm[] = {
637 "16 16 9 1",
638 " c None",
639 ". c #B20000",
640 "+ c #FF0000",
641 "@ c #FF7F7F",
642 "# c #008000",
643 "$ c #33B200",
644 "% c #10E500",
645 "& c #59FE4C",
646 "* c #FFB2B2",
647 " . ",
648 " .+. ",
649 " .+@+. ",
650 " .+@+. ",
651 ". .+@+.#######",
652 ".. .+@+. #$%%&#",
653 ".+.+@+. #$%%#",
654 ".@+@+. #$%$%#",
655 ".@@+. #$%$#$#",
656 ".*@@+. #$%$# ##",
657 ".......#$%$# #",
658 " #$%$# ",
659 " #$%$# ",
660 " #$%$# ",
661 " #$# ",
662 " # "};
663 #endif /* ! __WXMSW__ */
665 // Modeless Dialog Implementation
666 // CPartFileConvertDlg dialog
668 BEGIN_EVENT_TABLE(CPartFileConvertDlg, wxDialog)
669 EVT_BUTTON(IDC_ADDITEM, CPartFileConvertDlg::OnAddFolder)
670 EVT_BUTTON(IDC_RETRY, CPartFileConvertDlg::RetrySel)
671 EVT_BUTTON(IDC_CONVREMOVE, CPartFileConvertDlg::RemoveSel)
672 EVT_BUTTON(wxID_CANCEL, CPartFileConvertDlg::OnCloseButton)
673 EVT_CLOSE(CPartFileConvertDlg::OnClose)
674 END_EVENT_TABLE()
676 CPartFileConvertDlg::CPartFileConvertDlg(wxWindow* parent)
677 : wxDialog(parent, -1, _("Import partfiles"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
679 convertDlg(this, true, true);
681 m_joblist = CastChild(IDC_JOBLIST, CConvertListCtrl);
682 m_pb_current = CastChild(IDC_CONV_PB_CURRENT, wxGauge);
684 SetIcon(wxICON(convert));
686 // for some reason, if I try to get the mutex from the dialog
687 // it will end up in a deadlock(?) and I have to kill aMule
688 CastChild(IDC_RETRY, wxButton)->Enable(false);
689 CastChild(IDC_CONVREMOVE, wxButton)->Enable(false);
692 // CPartFileConvertDlg message handlers
694 void CPartFileConvertDlg::OnAddFolder(wxCommandEvent& WXUNUSED(event))
696 wxString folder = ::wxDirSelector(
697 _("Please choose a folder to search for temporary downloads! (subfolders will be included)"),
698 wxStandardPaths::Get().GetDocumentsDir(), wxDD_DEFAULT_STYLE,
699 wxDefaultPosition, this);
700 if (!folder.IsEmpty()) {
701 int reply = wxMessageBox(_("Do you want the source files of succesfully imported downloads be deleted?"),
702 _("Remove sources?"),
703 wxYES_NO | wxCANCEL | wxICON_QUESTION, this);
704 if (reply != wxCANCEL) {
705 CPartFileConvert::ScanFolderToAdd(CPath(folder), (reply == wxYES));
710 void CPartFileConvertDlg::OnClose(wxCloseEvent& WXUNUSED(event))
712 CPartFileConvert::CloseGUI();
715 void CPartFileConvertDlg::OnCloseButton(wxCommandEvent& WXUNUSED(event))
717 CPartFileConvert::CloseGUI();
720 void CPartFileConvertDlg::UpdateJobInfo(ConvertJob* job)
722 if (!job) {
723 dynamic_cast<wxStaticBoxSizer*>(IDC_CURJOB)->GetStaticBox()->SetLabel(_("Waiting..."));
724 CastChild(IDC_CONV_PROZENT, wxStaticText)->SetLabel(wxEmptyString);
725 m_pb_current->SetValue(0);
726 CastChild(IDC_CONV_PB_LABEL, wxStaticText)->SetLabel(wxEmptyString);
727 return;
730 wxString buffer;
732 // search jobitem in listctrl
733 long itemnr = m_joblist->FindItem(-1, reinterpret_cast<wxUIntPtr>(job));
734 if (itemnr != -1) {
735 m_joblist->SetItem(itemnr, 0, job->filename.IsOk() ? job->folder.GetPrintable() : job->filename.GetPrintable() );
736 m_joblist->SetItem(itemnr, 1, CPartFileConvert::GetReturncodeText(job->state) );
737 if (job->size > 0) {
738 buffer = CFormat(_("%s (Disk: %s)")) % CastItoXBytes(job->size) % CastItoXBytes(job->spaceneeded);
739 m_joblist->SetItem(itemnr, 2, buffer );
740 } else {
741 m_joblist->SetItem(itemnr, 2, wxEmptyString);
743 m_joblist->SetItem(itemnr, 3, job->filehash);
745 } else {
746 // AddJob(job); why???
750 void CPartFileConvertDlg::RemoveJob(ConvertJob* job)
752 long itemnr = m_joblist->FindItem(-1, reinterpret_cast<wxUIntPtr>(job));
753 if (itemnr != -1) {
754 m_joblist->DeleteItem(itemnr);
758 void CPartFileConvertDlg::AddJob(ConvertJob* job)
760 long ix = m_joblist->InsertItem(m_joblist->GetItemCount(), job->folder.GetPrintable());
761 if (ix != -1) {
762 m_joblist->SetItemData(ix, reinterpret_cast<wxUIntPtr>(job));
763 m_joblist->SetItem(ix, 1, CPartFileConvert::GetReturncodeText(job->state));
767 void CPartFileConvertDlg::RemoveSel(wxCommandEvent& WXUNUSED(event))
769 if (m_joblist->GetSelectedItemCount() == 0) return;
771 long itemnr = m_joblist->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
772 while (itemnr != -1) {
773 ConvertJob* job = (ConvertJob*)m_joblist->GetItemData(itemnr);
774 if (job->state != CONV_INPROGRESS) {
775 // this will remove the job from both gui and list
776 CPartFileConvert::RemoveJob(job);
778 itemnr = m_joblist->GetNextItem(itemnr, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
782 void CPartFileConvertDlg::RetrySel(wxCommandEvent& WXUNUSED(event))
784 if (m_joblist->GetSelectedItemCount() == 0) return;
786 long itemnr = m_joblist->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
787 while (itemnr != -1) {
788 ConvertJob* job = (ConvertJob*)m_joblist->GetItemData(itemnr);
789 wxMutexLocker lock(CPartFileConvert::s_mutex);
790 if (job->state != CONV_OK && job->state != CONV_INPROGRESS) {
791 job->state = CONV_QUEUE;
792 UpdateJobInfo(job);
795 wxMutexLocker lock(CPartFileConvert::s_mutex);
796 CPartFileConvert::StartThread();
799 #endif
800 // File_checked_for_headers