Upstream tarball 9445
[amule.git] / src / PartFileConvert.cpp
blob6b12fe31ba734833effbbfdfa6d9fe2b8d34d8ae
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.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 if (!file->LoadPartFile(thePrefs::GetTempDir(), file->GetPartMetFileName(), false)) {
458 //delete file;
459 file->Delete();
460 return CONV_BADFORMAT;
463 if (s_pfconverting->partmettype == PMT_NEWOLD || s_pfconverting->partmettype == PMT_SPLITTED ) {
464 file->SetCompletedSize(file->transferred);
465 file->m_iGainDueToCompression = 0;
466 file->m_iLostDueToCorruption = 0;
469 UpdateGUI(100, _("Adding download and saving new partfile"));
471 theApp->downloadqueue->AddDownload(file, thePrefs::AddNewFilesPaused(), 0);
472 file->SavePartFile();
474 if (file->GetStatus(true) == PS_READY) {
475 theApp->sharedfiles->SafeAddKFile(file); // part files are always shared files
478 if (s_pfconverting->removeSource) {
479 CPath oldFile = finder.GetFirstFile(CDirIterator::File, filepartindex + wxT(".*"));
480 while (oldFile.IsOk()) {
481 CPath::RemoveFile(folder.JoinPaths(oldFile));
482 oldFile = finder.GetNextFile();
485 if (s_pfconverting->partmettype == PMT_SPLITTED) {
486 CPath::RemoveDir(folder);
490 return CONV_OK;
493 void CPartFileConvert::UpdateGUI(float percent, wxString text, bool fullinfo)
495 if (!IsMain()) {
496 wxMutexGuiEnter();
499 if (s_convertgui) {
500 s_convertgui->m_pb_current->SetValue((int)percent);
501 wxString buffer = wxString::Format(wxT("%.2f %%"), percent);
502 wxStaticText* percentlabel = dynamic_cast<wxStaticText*>(s_convertgui->FindWindow(IDC_CONV_PROZENT));
503 percentlabel->SetLabel(buffer);
505 if (!text.IsEmpty()) {
506 dynamic_cast<wxStaticText*>(s_convertgui->FindWindow(IDC_CONV_PB_LABEL))->SetLabel(text);
509 percentlabel->GetParent()->Layout();
511 if (fullinfo) {
512 dynamic_cast<wxStaticBoxSizer*>(IDC_CURJOB)->GetStaticBox()->SetLabel(s_pfconverting->folder.GetPrintable());
516 if (!IsMain()) {
517 wxMutexGuiLeave();
521 void CPartFileConvert::UpdateGUI(ConvertJob* job)
523 if (!IsMain()) {
524 wxMutexGuiEnter();
526 if (s_convertgui) {
527 s_convertgui->UpdateJobInfo(job);
529 if (!IsMain()) {
530 wxMutexGuiLeave();
534 void CPartFileConvert::ShowGUI(wxWindow* parent)
536 if (s_convertgui) {
537 s_convertgui->Show(true);
538 s_convertgui->Raise();
539 } else {
540 s_convertgui = new CPartFileConvertDlg(parent);
541 s_convertgui->Show(true);
543 wxMutexLocker lock(s_mutex);
544 if (s_pfconverting) {
545 UpdateGUI(s_pfconverting);
546 UpdateGUI(50, _("Fetching status..."), true);
549 // fill joblist
550 for (std::list<ConvertJob*>::iterator it = s_jobs.begin(); it != s_jobs.end(); ++it) {
551 s_convertgui->AddJob(*it);
552 UpdateGUI(*it);
557 void CPartFileConvert::CloseGUI()
559 if (s_convertgui) {
560 s_convertgui->Show(false);
561 s_convertgui->Destroy();
562 s_convertgui = NULL;
566 void CPartFileConvert::RemoveAllJobs()
568 wxMutexLocker lock(s_mutex);
569 for (std::list<ConvertJob*>::iterator it = s_jobs.begin(); it != s_jobs.end(); ++it) {
570 if (s_convertgui) {
571 s_convertgui->RemoveJob(*it);
573 delete *it;
575 s_jobs.clear();
578 void CPartFileConvert::RemoveJob(ConvertJob* job)
580 wxMutexLocker lock(s_mutex);
581 for (std::list<ConvertJob*>::iterator it = s_jobs.begin(); it != s_jobs.end(); ++it) {
582 if (*it == job) {
583 if (s_convertgui) {
584 s_convertgui->RemoveJob(job);
586 s_jobs.erase(it);
587 delete *it;
592 void CPartFileConvert::RemoveAllSuccJobs()
594 wxMutexLocker lock(s_mutex);
595 for (std::list<ConvertJob*>::iterator it = s_jobs.begin(); it != s_jobs.end(); ++it) {
596 if ((*it)->state == CONV_OK) {
597 if (s_convertgui) {
598 s_convertgui->RemoveJob(*it);
600 s_jobs.erase(it);
601 delete *it;
606 wxString CPartFileConvert::GetReturncodeText(int ret)
608 switch (ret) {
609 case CONV_OK : return _("Completed");
610 case CONV_INPROGRESS : return _("In progress");
611 case CONV_OUTOFDISKSPACE : return _("ERROR: Out of diskspace");
612 case CONV_PARTMETNOTFOUND : return _("ERROR: Partmet not found");
613 case CONV_IOERROR : return _("ERROR: IO error!");
614 case CONV_FAILED : return _("ERROR: Failed!");
615 case CONV_QUEUE : return _("Queued");
616 case CONV_ALREADYEXISTS : return _("Already downloading");
617 case CONV_BADFORMAT : return _("Unknown or bad tempfile format.");
618 default: return wxT("?");
623 CConvertListCtrl::CConvertListCtrl(wxWindow* parent, wxWindowID winid, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name)
624 : wxListCtrl(parent, winid, pos, size, style, validator, name)
626 InsertColumn(0, _("File name"), wxLIST_FORMAT_LEFT, 200);
627 InsertColumn(1, _("State"), wxLIST_FORMAT_LEFT, 100);
628 InsertColumn(2, _("Size"), wxLIST_FORMAT_LEFT, 100);
629 InsertColumn(3, _("Filehash"), wxLIST_FORMAT_LEFT, 100);
632 #ifndef __WXMSW__
633 /* XPM */
634 static const char * convert_xpm[] = {
635 "16 16 9 1",
636 " c None",
637 ". c #B20000",
638 "+ c #FF0000",
639 "@ c #FF7F7F",
640 "# c #008000",
641 "$ c #33B200",
642 "% c #10E500",
643 "& c #59FE4C",
644 "* c #FFB2B2",
645 " . ",
646 " .+. ",
647 " .+@+. ",
648 " .+@+. ",
649 ". .+@+.#######",
650 ".. .+@+. #$%%&#",
651 ".+.+@+. #$%%#",
652 ".@+@+. #$%$%#",
653 ".@@+. #$%$#$#",
654 ".*@@+. #$%$# ##",
655 ".......#$%$# #",
656 " #$%$# ",
657 " #$%$# ",
658 " #$%$# ",
659 " #$# ",
660 " # "};
661 #endif /* ! __WXMSW__ */
663 // Modeless Dialog Implementation
664 // CPartFileConvertDlg dialog
666 BEGIN_EVENT_TABLE(CPartFileConvertDlg, wxDialog)
667 EVT_BUTTON(IDC_ADDITEM, CPartFileConvertDlg::OnAddFolder)
668 EVT_BUTTON(IDC_RETRY, CPartFileConvertDlg::RetrySel)
669 EVT_BUTTON(IDC_CONVREMOVE, CPartFileConvertDlg::RemoveSel)
670 EVT_BUTTON(wxID_CANCEL, CPartFileConvertDlg::OnCloseButton)
671 EVT_CLOSE(CPartFileConvertDlg::OnClose)
672 END_EVENT_TABLE()
674 CPartFileConvertDlg::CPartFileConvertDlg(wxWindow* parent)
675 : wxDialog(parent, -1, _("Import partfiles"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
677 convertDlg(this, true, true);
679 m_joblist = CastChild(IDC_JOBLIST, CConvertListCtrl);
680 m_pb_current = CastChild(IDC_CONV_PB_CURRENT, wxGauge);
682 SetIcon(wxICON(convert));
684 // for some reason, if I try to get the mutex from the dialog
685 // it will end up in a deadlock(?) and I have to kill aMule
686 CastChild(IDC_RETRY, wxButton)->Enable(false);
687 CastChild(IDC_CONVREMOVE, wxButton)->Enable(false);
690 // CPartFileConvertDlg message handlers
692 void CPartFileConvertDlg::OnAddFolder(wxCommandEvent& WXUNUSED(event))
694 wxString folder = ::wxDirSelector(
695 _("Please choose a folder to search for temporary downloads! (subfolders will be included)"),
696 wxStandardPaths::Get().GetDocumentsDir(), wxDD_DEFAULT_STYLE,
697 wxDefaultPosition, this);
698 if (!folder.IsEmpty()) {
699 int reply = wxMessageBox(_("Do you want the source files of succesfully imported downloads be deleted?"),
700 _("Remove sources?"),
701 wxYES_NO | wxCANCEL | wxICON_QUESTION, this);
702 if (reply != wxCANCEL) {
703 CPartFileConvert::ScanFolderToAdd(CPath(folder), (reply == wxYES));
708 void CPartFileConvertDlg::OnClose(wxCloseEvent& WXUNUSED(event))
710 CPartFileConvert::CloseGUI();
713 void CPartFileConvertDlg::OnCloseButton(wxCommandEvent& WXUNUSED(event))
715 CPartFileConvert::CloseGUI();
718 void CPartFileConvertDlg::UpdateJobInfo(ConvertJob* job)
720 if (!job) {
721 dynamic_cast<wxStaticBoxSizer*>(IDC_CURJOB)->GetStaticBox()->SetLabel(_("Waiting..."));
722 CastChild(IDC_CONV_PROZENT, wxStaticText)->SetLabel(wxEmptyString);
723 m_pb_current->SetValue(0);
724 CastChild(IDC_CONV_PB_LABEL, wxStaticText)->SetLabel(wxEmptyString);
725 return;
728 wxString buffer;
730 // search jobitem in listctrl
731 long itemnr = m_joblist->FindItem(-1, reinterpret_cast<wxUIntPtr>(job));
732 if (itemnr != -1) {
733 m_joblist->SetItem(itemnr, 0, job->filename.IsOk() ? job->folder.GetPrintable() : job->filename.GetPrintable() );
734 m_joblist->SetItem(itemnr, 1, CPartFileConvert::GetReturncodeText(job->state) );
735 if (job->size > 0) {
736 buffer = CFormat(_("%s (Disk: %s)")) % CastItoXBytes(job->size) % CastItoXBytes(job->spaceneeded);
737 m_joblist->SetItem(itemnr, 2, buffer );
738 } else {
739 m_joblist->SetItem(itemnr, 2, wxEmptyString);
741 m_joblist->SetItem(itemnr, 3, job->filehash);
743 } else {
744 // AddJob(job); why???
748 void CPartFileConvertDlg::RemoveJob(ConvertJob* job)
750 long itemnr = m_joblist->FindItem(-1, reinterpret_cast<wxUIntPtr>(job));
751 if (itemnr != -1) {
752 m_joblist->DeleteItem(itemnr);
756 void CPartFileConvertDlg::AddJob(ConvertJob* job)
758 long ix = m_joblist->InsertItem(m_joblist->GetItemCount(), job->folder.GetPrintable());
759 if (ix != -1) {
760 m_joblist->SetItemData(ix, reinterpret_cast<wxUIntPtr>(job));
761 m_joblist->SetItem(ix, 1, CPartFileConvert::GetReturncodeText(job->state));
765 void CPartFileConvertDlg::RemoveSel(wxCommandEvent& WXUNUSED(event))
767 if (m_joblist->GetSelectedItemCount() == 0) return;
769 long itemnr = m_joblist->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
770 while (itemnr != -1) {
771 ConvertJob* job = (ConvertJob*)m_joblist->GetItemData(itemnr);
772 if (job->state != CONV_INPROGRESS) {
773 // this will remove the job from both gui and list
774 CPartFileConvert::RemoveJob(job);
776 itemnr = m_joblist->GetNextItem(itemnr, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
780 void CPartFileConvertDlg::RetrySel(wxCommandEvent& WXUNUSED(event))
782 if (m_joblist->GetSelectedItemCount() == 0) return;
784 long itemnr = m_joblist->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
785 while (itemnr != -1) {
786 ConvertJob* job = (ConvertJob*)m_joblist->GetItemData(itemnr);
787 wxMutexLocker lock(CPartFileConvert::s_mutex);
788 if (job->state != CONV_OK && job->state != CONV_INPROGRESS) {
789 job->state = CONV_QUEUE;
790 UpdateJobInfo(job);
793 wxMutexLocker lock(CPartFileConvert::s_mutex);
794 CPartFileConvert::StartThread();
797 #endif
798 // File_checked_for_headers