Upstream tarball 9744
[amule.git] / src / PartFileConvert.cpp
blob039072f805e4b59e21a1209bc26e2a8901254493
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-2008 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 AddLogLineNS(_("Waiting for partfile convert thread to die..."));
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.WriteAt(ba, chunkstart, toReadWrite);
386 filename = finder.GetNextFile();
388 delete[] ba;
389 } catch (const CSafeIOException& e) {
390 AddDebugLogLineM(true, logPfConvert, wxT("IO error while converting partfiles: ") + e.what());
392 delete[] ba;
393 file->Delete();
394 return CONV_IOERROR;
397 file->m_hpartfile.Close();
399 // import an external common format partdownload
400 else //if (pfconverting->partmettype==PMT_DEFAULTOLD || pfconverting->partmettype==PMT_NEWOLD || Shareaza )
402 if (!s_pfconverting->removeSource) {
403 wxMutexLocker lock(s_mutex);
404 s_pfconverting->spaceneeded = oldfile.GetFileSize();
407 UpdateGUI(s_pfconverting);
409 sint64 freespace = CPath::GetFreeSpaceAt(thePrefs::GetTempDir());
410 if (freespace == wxInvalidOffset) {
411 delete file;
412 return CONV_IOERROR;
413 } else if (!s_pfconverting->removeSource && (freespace < s_pfconverting->spaceneeded)) {
414 delete file;
415 return CONV_OUTOFDISKSPACE;
418 file->CreatePartFile();
419 newfilename = file->GetFullName();
421 file->m_hpartfile.Close();
423 bool ret = false;
425 UpdateGUI(92, _("Copy"));
427 CPath::RemoveFile(newfilename.RemoveExt());
428 if (!oldfile.FileExists()) {
429 // data file does not exist. well, then create a 0 byte big one
430 CFile datafile;
431 ret = datafile.Create(newfilename.RemoveExt());
432 } else if (s_pfconverting->removeSource) {
433 ret = CPath::RenameFile(oldfile, newfilename.RemoveExt());
434 } else {
435 ret = CPath::CloneFile(oldfile, newfilename.RemoveExt(), false);
437 if (!ret) {
438 file->Delete();
439 //delete file;
440 return CONV_FAILED;
445 UpdateGUI(94, _("Retrieving source downloadfile information"));
447 CPath::RemoveFile(newfilename);
448 if (s_pfconverting->removeSource) {
449 CPath::RenameFile(folder.JoinPaths(partfile), newfilename);
450 } else {
451 CPath::CloneFile(folder.JoinPaths(partfile), newfilename, false);
454 file->m_hashlist.clear();
456 if (!file->LoadPartFile(thePrefs::GetTempDir(), file->GetPartMetFileName(), false)) {
457 //delete file;
458 file->Delete();
459 return CONV_BADFORMAT;
462 if (s_pfconverting->partmettype == PMT_NEWOLD || s_pfconverting->partmettype == PMT_SPLITTED ) {
463 file->SetCompletedSize(file->transferred);
464 file->m_iGainDueToCompression = 0;
465 file->m_iLostDueToCorruption = 0;
468 UpdateGUI(100, _("Adding download and saving new partfile"));
470 theApp->downloadqueue->AddDownload(file, thePrefs::AddNewFilesPaused(), 0);
471 file->SavePartFile();
473 if (file->GetStatus(true) == PS_READY) {
474 theApp->sharedfiles->SafeAddKFile(file); // part files are always shared files
477 if (s_pfconverting->removeSource) {
478 CPath oldFile = finder.GetFirstFile(CDirIterator::File, filepartindex + wxT(".*"));
479 while (oldFile.IsOk()) {
480 CPath::RemoveFile(folder.JoinPaths(oldFile));
481 oldFile = finder.GetNextFile();
484 if (s_pfconverting->partmettype == PMT_SPLITTED) {
485 CPath::RemoveDir(folder);
489 return CONV_OK;
492 void CPartFileConvert::UpdateGUI(float percent, wxString text, bool fullinfo)
494 if (!IsMain()) {
495 wxMutexGuiEnter();
498 if (s_convertgui) {
499 s_convertgui->m_pb_current->SetValue((int)percent);
500 wxString buffer = wxString::Format(wxT("%.2f %%"), percent);
501 wxStaticText* percentlabel = dynamic_cast<wxStaticText*>(s_convertgui->FindWindow(IDC_CONV_PROZENT));
502 percentlabel->SetLabel(buffer);
504 if (!text.IsEmpty()) {
505 dynamic_cast<wxStaticText*>(s_convertgui->FindWindow(IDC_CONV_PB_LABEL))->SetLabel(text);
508 percentlabel->GetParent()->Layout();
510 if (fullinfo) {
511 dynamic_cast<wxStaticBoxSizer*>(IDC_CURJOB)->GetStaticBox()->SetLabel(s_pfconverting->folder.GetPrintable());
515 if (!IsMain()) {
516 wxMutexGuiLeave();
520 void CPartFileConvert::UpdateGUI(ConvertJob* job)
522 if (!IsMain()) {
523 wxMutexGuiEnter();
525 if (s_convertgui) {
526 s_convertgui->UpdateJobInfo(job);
528 if (!IsMain()) {
529 wxMutexGuiLeave();
533 void CPartFileConvert::ShowGUI(wxWindow* parent)
535 if (s_convertgui) {
536 s_convertgui->Show(true);
537 s_convertgui->Raise();
538 } else {
539 s_convertgui = new CPartFileConvertDlg(parent);
540 s_convertgui->Show(true);
542 wxMutexLocker lock(s_mutex);
543 if (s_pfconverting) {
544 UpdateGUI(s_pfconverting);
545 UpdateGUI(50, _("Fetching status..."), true);
548 // fill joblist
549 for (std::list<ConvertJob*>::iterator it = s_jobs.begin(); it != s_jobs.end(); ++it) {
550 s_convertgui->AddJob(*it);
551 UpdateGUI(*it);
556 void CPartFileConvert::CloseGUI()
558 if (s_convertgui) {
559 s_convertgui->Show(false);
560 s_convertgui->Destroy();
561 s_convertgui = NULL;
565 void CPartFileConvert::RemoveAllJobs()
567 wxMutexLocker lock(s_mutex);
568 for (std::list<ConvertJob*>::iterator it = s_jobs.begin(); it != s_jobs.end(); ++it) {
569 if (s_convertgui) {
570 s_convertgui->RemoveJob(*it);
572 delete *it;
574 s_jobs.clear();
577 void CPartFileConvert::RemoveJob(ConvertJob* job)
579 wxMutexLocker lock(s_mutex);
580 for (std::list<ConvertJob*>::iterator it = s_jobs.begin(); it != s_jobs.end(); ++it) {
581 if (*it == job) {
582 if (s_convertgui) {
583 s_convertgui->RemoveJob(job);
585 s_jobs.erase(it);
586 delete *it;
591 void CPartFileConvert::RemoveAllSuccJobs()
593 wxMutexLocker lock(s_mutex);
594 for (std::list<ConvertJob*>::iterator it = s_jobs.begin(); it != s_jobs.end(); ++it) {
595 if ((*it)->state == CONV_OK) {
596 if (s_convertgui) {
597 s_convertgui->RemoveJob(*it);
599 s_jobs.erase(it);
600 delete *it;
605 wxString CPartFileConvert::GetReturncodeText(int ret)
607 switch (ret) {
608 case CONV_OK : return _("Completed");
609 case CONV_INPROGRESS : return _("In progress");
610 case CONV_OUTOFDISKSPACE : return _("ERROR: Out of diskspace");
611 case CONV_PARTMETNOTFOUND : return _("ERROR: Partmet not found");
612 case CONV_IOERROR : return _("ERROR: IO error!");
613 case CONV_FAILED : return _("ERROR: Failed!");
614 case CONV_QUEUE : return _("Queued");
615 case CONV_ALREADYEXISTS : return _("Already downloading");
616 case CONV_BADFORMAT : return _("Unknown or bad tempfile format.");
617 default: return wxT("?");
622 CConvertListCtrl::CConvertListCtrl(wxWindow* parent, wxWindowID winid, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name)
623 : wxListCtrl(parent, winid, pos, size, style, validator, name)
625 InsertColumn(0, _("File name"), wxLIST_FORMAT_LEFT, 200);
626 InsertColumn(1, _("State"), wxLIST_FORMAT_LEFT, 100);
627 InsertColumn(2, _("Size"), wxLIST_FORMAT_LEFT, 100);
628 InsertColumn(3, _("Filehash"), wxLIST_FORMAT_LEFT, 100);
631 #ifndef __WXMSW__
632 /* XPM */
633 static const char * convert_xpm[] = {
634 "16 16 9 1",
635 " c None",
636 ". c #B20000",
637 "+ c #FF0000",
638 "@ c #FF7F7F",
639 "# c #008000",
640 "$ c #33B200",
641 "% c #10E500",
642 "& c #59FE4C",
643 "* c #FFB2B2",
644 " . ",
645 " .+. ",
646 " .+@+. ",
647 " .+@+. ",
648 ". .+@+.#######",
649 ".. .+@+. #$%%&#",
650 ".+.+@+. #$%%#",
651 ".@+@+. #$%$%#",
652 ".@@+. #$%$#$#",
653 ".*@@+. #$%$# ##",
654 ".......#$%$# #",
655 " #$%$# ",
656 " #$%$# ",
657 " #$%$# ",
658 " #$# ",
659 " # "};
660 #endif /* ! __WXMSW__ */
662 // Modeless Dialog Implementation
663 // CPartFileConvertDlg dialog
665 BEGIN_EVENT_TABLE(CPartFileConvertDlg, wxDialog)
666 EVT_BUTTON(IDC_ADDITEM, CPartFileConvertDlg::OnAddFolder)
667 EVT_BUTTON(IDC_RETRY, CPartFileConvertDlg::RetrySel)
668 EVT_BUTTON(IDC_CONVREMOVE, CPartFileConvertDlg::RemoveSel)
669 EVT_BUTTON(wxID_CANCEL, CPartFileConvertDlg::OnCloseButton)
670 EVT_CLOSE(CPartFileConvertDlg::OnClose)
671 END_EVENT_TABLE()
673 CPartFileConvertDlg::CPartFileConvertDlg(wxWindow* parent)
674 : wxDialog(parent, -1, _("Import partfiles"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
676 convertDlg(this, true, true);
678 m_joblist = CastChild(IDC_JOBLIST, CConvertListCtrl);
679 m_pb_current = CastChild(IDC_CONV_PB_CURRENT, wxGauge);
681 SetIcon(wxICON(convert));
683 // for some reason, if I try to get the mutex from the dialog
684 // it will end up in a deadlock(?) and I have to kill aMule
685 CastChild(IDC_RETRY, wxButton)->Enable(false);
686 CastChild(IDC_CONVREMOVE, wxButton)->Enable(false);
689 // CPartFileConvertDlg message handlers
691 void CPartFileConvertDlg::OnAddFolder(wxCommandEvent& WXUNUSED(event))
693 wxString folder = ::wxDirSelector(
694 _("Please choose a folder to search for temporary downloads! (subfolders will be included)"),
695 wxStandardPaths::Get().GetDocumentsDir(), wxDD_DEFAULT_STYLE,
696 wxDefaultPosition, this);
697 if (!folder.IsEmpty()) {
698 int reply = wxMessageBox(_("Do you want the source files of succesfully imported downloads be deleted?"),
699 _("Remove sources?"),
700 wxYES_NO | wxCANCEL | wxICON_QUESTION, this);
701 if (reply != wxCANCEL) {
702 CPartFileConvert::ScanFolderToAdd(CPath(folder), (reply == wxYES));
707 void CPartFileConvertDlg::OnClose(wxCloseEvent& WXUNUSED(event))
709 CPartFileConvert::CloseGUI();
712 void CPartFileConvertDlg::OnCloseButton(wxCommandEvent& WXUNUSED(event))
714 CPartFileConvert::CloseGUI();
717 void CPartFileConvertDlg::UpdateJobInfo(ConvertJob* job)
719 if (!job) {
720 dynamic_cast<wxStaticBoxSizer*>(IDC_CURJOB)->GetStaticBox()->SetLabel(_("Waiting..."));
721 CastChild(IDC_CONV_PROZENT, wxStaticText)->SetLabel(wxEmptyString);
722 m_pb_current->SetValue(0);
723 CastChild(IDC_CONV_PB_LABEL, wxStaticText)->SetLabel(wxEmptyString);
724 return;
727 wxString buffer;
729 // search jobitem in listctrl
730 long itemnr = m_joblist->FindItem(-1, reinterpret_cast<wxUIntPtr>(job));
731 if (itemnr != -1) {
732 m_joblist->SetItem(itemnr, 0, job->filename.IsOk() ? job->folder.GetPrintable() : job->filename.GetPrintable() );
733 m_joblist->SetItem(itemnr, 1, CPartFileConvert::GetReturncodeText(job->state) );
734 if (job->size > 0) {
735 buffer = CFormat(_("%s (Disk: %s)")) % CastItoXBytes(job->size) % CastItoXBytes(job->spaceneeded);
736 m_joblist->SetItem(itemnr, 2, buffer );
737 } else {
738 m_joblist->SetItem(itemnr, 2, wxEmptyString);
740 m_joblist->SetItem(itemnr, 3, job->filehash);
742 } else {
743 // AddJob(job); why???
747 void CPartFileConvertDlg::RemoveJob(ConvertJob* job)
749 long itemnr = m_joblist->FindItem(-1, reinterpret_cast<wxUIntPtr>(job));
750 if (itemnr != -1) {
751 m_joblist->DeleteItem(itemnr);
755 void CPartFileConvertDlg::AddJob(ConvertJob* job)
757 long ix = m_joblist->InsertItem(m_joblist->GetItemCount(), job->folder.GetPrintable());
758 if (ix != -1) {
759 m_joblist->SetItemData(ix, reinterpret_cast<wxUIntPtr>(job));
760 m_joblist->SetItem(ix, 1, CPartFileConvert::GetReturncodeText(job->state));
764 void CPartFileConvertDlg::RemoveSel(wxCommandEvent& WXUNUSED(event))
766 if (m_joblist->GetSelectedItemCount() == 0) return;
768 long itemnr = m_joblist->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
769 while (itemnr != -1) {
770 ConvertJob* job = (ConvertJob*)m_joblist->GetItemData(itemnr);
771 if (job->state != CONV_INPROGRESS) {
772 // this will remove the job from both gui and list
773 CPartFileConvert::RemoveJob(job);
775 itemnr = m_joblist->GetNextItem(itemnr, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
779 void CPartFileConvertDlg::RetrySel(wxCommandEvent& WXUNUSED(event))
781 if (m_joblist->GetSelectedItemCount() == 0) return;
783 long itemnr = m_joblist->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
784 while (itemnr != -1) {
785 ConvertJob* job = (ConvertJob*)m_joblist->GetItemData(itemnr);
786 wxMutexLocker lock(CPartFileConvert::s_mutex);
787 if (job->state != CONV_OK && job->state != CONV_INPROGRESS) {
788 job->state = CONV_QUEUE;
789 UpdateJobInfo(job);
792 wxMutexLocker lock(CPartFileConvert::s_mutex);
793 CPartFileConvert::StartThread();
796 #endif
797 // File_checked_for_headers