/** * This file is part of the KAudioCreator package * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome dot net) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "jobqueimp.h" #include "job.h" #include "prefs.h" #include <tqpushbutton.h> #include <tqlabel.h> #include <tqpainter.h> #include <kconfig.h> #include <kglobal.h> #include <kdebug.h> #include <kiconloader.h> #include <kmessagebox.h> #include <kurl.h> #include <tqfile.h> #include <tqregexp.h> #include <tqfileinfo.h> #include <kstandarddirs.h> #include <knotifyclient.h> #include <tqdir.h> #define HEADER_JOB 0 #define HEADER_PROGRESS 1 #define HEADER_DESCRIPTION 2 #define ICON_LOC HEADER_DESCRIPTION #define DEFAULT_HIGHEST_NUMBER 9 /** * Constructor, set up signals. * @param parent - parent widget * @param name - widget name */ JobQueImp::JobQueImp( TQWidget* parent, const char* name) : JobQue(parent,name),highestNumber(DEFAULT_HIGHEST_NUMBER), currentId(0){ connect(removeSelected,TQT_SIGNAL(clicked()), this, TQT_SLOT( removeSelectedJob())); connect(removeAll, TQT_SIGNAL(clicked()), this, TQT_SLOT(removeAllJobs())); connect(removeDoneJobs, TQT_SIGNAL(clicked()), this, TQT_SLOT(clearDoneJobs())); } /** * Return a buffer of "000" so that new, updated jobs strings will be able to * sort via the columns. * Based upon a highest number that is kept. * @param number the number to fill out. */ TQString JobQueImp::getStringFromNumber(int number){ if(number > highestNumber){ int diff = TQString("%1").tqarg(number).length() - TQString("%1").tqarg(highestNumber).length(); highestNumber = number; if(diff > 0){ // We have to update all of the cells. QueListViewItem * currentItem = (QueListViewItem*)todoQue->firstChild(); while( currentItem != NULL ){ currentItem->setText(HEADER_JOB, "0" + currentItem->text(HEADER_JOB)); currentItem = (QueListViewItem*)currentItem->itemBelow(); } } } TQString buffer = ""; uint newLength = TQString("%1").tqarg(highestNumber).length() - TQString("%1").tqarg(number).length(); for(uint i=0; i < newLength; i++) buffer += "0"; return buffer; } /** * Add a new job to the que * @param id the id of the job. * @param name the name of the job. */ void JobQueImp::addJob(Job*job, const TQString &name ){ if(!job) return; job->id = ++currentId; QueListViewItem *currentItem = new QueListViewItem(todoQue, TQString("%1%2").tqarg(getStringFromNumber(currentId)).tqarg(currentId), "0", name); currentItem->setPixmap(ICON_LOC, SmallIcon("player_pause", currentItem->height()-2)); queLabel->setText(i18n("Number of jobs in the queue: %1").tqarg(todoQue->childCount())); } /** * Locate the job and update the progress. * @param id the id of the job to update * @param progress the new progress of the job. */ void JobQueImp::updateProgress(int id, int progress){ int currentJobCount = numberOfJobsNotFinished(); QueListViewItem * currentItem = (QueListViewItem*)todoQue->firstChild(); TQString buffer = getStringFromNumber(id); buffer += TQString("%1").tqarg(id); // Find the current item while( currentItem != NULL ){ if(currentItem->text(HEADER_JOB) == buffer) break; currentItem = (QueListViewItem*)currentItem->nextSibling(); } if( !currentItem ){ kdDebug(60002) << "JobQueImp::updateProgress An update was received about a job, but the job couldn't be found: " << id << endl; return; } // Only update the % if it changed. if(currentItem->percentDone == progress) return; currentItem->percentDone = progress; currentItem->tqrepaint(); // Update the icon if needed if(progress > 0 && progress < 100 && !currentItem->progressing ){ currentItem->setPixmap(ICON_LOC, SmallIcon("gear", currentItem->height()-2)); currentItem->progressing = true; } else if(progress == -1){ currentItem->setPixmap(ICON_LOC, SmallIcon("button_cancel", currentItem->height()-2)); } else if(progress == 100){ // Remove the job if requested. if(Prefs::removeCompletedJobs()){ removeJob(currentItem, false); return; } currentItem->setPixmap(ICON_LOC, SmallIcon("button_ok", currentItem->height())); } if(currentJobCount > 0 && numberOfJobsNotFinished() == 0) KNotifyClient::event("no jobs left"); } /** * Remove job listed in item * @param item to remove. Note that it WILL be deleted and set to NULL. * @param kill kill the actual job/process. A bool here because this CAN cause * a race condition when the encoder is 100%, but hasn't exited. * @param prompt the user if the job isn't finished * @return bool if remove was successfull or not. */ bool JobQueImp::removeJob(QueListViewItem *item, bool kill, bool prompt){ if(!item) return false; if(item->percentDone < 100 && item->percentDone > -1 && (prompt && KMessageBox::questionYesNo(this, i18n("KAudioCreator has not finished %1. Remove anyway?").tqarg(item->text(HEADER_DESCRIPTION)), i18n("Unfinished Job in Queue"), KStdGuiItem::del(), i18n("Keep")) == KMessageBox::No )) return false; // "Thread" safe if(!item) return false; if(kill) emit (removeJob(item->text(HEADER_JOB).toInt())); todoQue->takeItem(item); delete(item); item = NULL; // See if the Que needs to be updated... if(todoQue->childCount() == 0){ queLabel->setText(i18n("No jobs are in the queue")); highestNumber = DEFAULT_HIGHEST_NUMBER; currentId = 0; } else queLabel->setText(i18n("Number of jobs in the queue: %1").tqarg(todoQue->childCount())); return true; } /** * Remove the currently selected Job */ void JobQueImp::removeSelectedJob(){ QueListViewItem * currentItem = (QueListViewItem*)todoQue->firstChild(); while(currentItem != NULL){ if(currentItem->isSelected()){ QueListViewItem *t = currentItem; currentItem = (QueListViewItem*)currentItem->nextSibling(); removeJob(t); } else currentItem = (QueListViewItem*)currentItem->nextSibling(); } } /** * Remove all of the jobs in the list. */ void JobQueImp::removeAllJobs(){ // First determine if there are jobs not finished and prompt once here bool finished=true; QueListViewItem * item = (QueListViewItem*)todoQue->firstChild(); while( item != NULL ){ if(item && item->percentDone < 100 && item->percentDone > -1) finished = false; item = (QueListViewItem*)item->nextSibling(); } if(!finished){ if(KMessageBox::questionYesNo(this, i18n("KAudioCreator has not finished all of the jobs. Remove them anyway?"), i18n("Unfinished Job in Queue"), KStdGuiItem::del(), i18n("Keep")) == KMessageBox::No ) return; } QueListViewItem * currentItem = (QueListViewItem*)todoQue->firstChild(); while( currentItem != NULL ){ QueListViewItem *next = (QueListViewItem*)currentItem->nextSibling(); removeJob(currentItem, true, false); currentItem = next; } } /** * Remove any jobs that are in the list that are done. */ void JobQueImp::clearDoneJobs(){ QueListViewItem * currentItem = (QueListViewItem*)todoQue->firstChild(); while( currentItem != NULL ){ QueListViewItem *itemToRemove = NULL; if( currentItem->percentDone == 100 ){ itemToRemove = currentItem; } currentItem = (QueListViewItem*)currentItem->itemBelow(); if(itemToRemove){ emit (removeJob(itemToRemove->text(HEADER_JOB).toInt())); todoQue->takeItem(itemToRemove); } } if(todoQue->childCount() == 0){ queLabel->setText(i18n("No jobs are in the queue")); highestNumber = DEFAULT_HIGHEST_NUMBER; currentId = 0; } else queLabel->setText(i18n("Number of jobs in the queue: %1").tqarg(todoQue->childCount())); } /** * Return the number of jobs in the que that don't have 100% or Error in the * Progress column * @return the number of jobs that are in the que that haven't been finished. */ int JobQueImp::numberOfJobsNotFinished(){ int totalJobsToDo = 0; QueListViewItem * currentItem = (QueListViewItem*)todoQue->firstChild(); while( currentItem != NULL ){ if( currentItem->percentDone == 100 || currentItem->percentDone == -1 ){ } else totalJobsToDo++; currentItem = (QueListViewItem*)currentItem->itemBelow(); } return totalJobsToDo; } /** * The tqrepaint function overloaded so that we can have a built in progressbar. */ void QueListViewItem::paintCell (TQPainter * p,const TQColorGroup &cg,int column, int width,int align){ if(column != HEADER_PROGRESS){ TQListViewItem::paintCell(p,cg,column,width,align); return; } p->setPen(cg.base()); p->drawRect(0,0,width,height()); if(isSelected()) p->fillRect(1,1,width-2,height()-2,cg.highlight()); else p->fillRect(1,1,width-2,height()-2,cg.base()); int percent = (int)(((double)(width-2)) * (percentDone/100)); p->fillRect(1,1,percent,height()-2,cg.mid()); // show the text p->setPen(cg.text()); if(isSelected()) p->setPen(cg.highlightedText()); if(percentDone != -1) p->drawText(0,0,width-1,height()-1,AlignCenter,TQString().setNum((int)percentDone) + "%"); else p->drawText(0,0,width-1,height()-1,AlignCenter,i18n("Error")); } /** * Header for built in treelist item so we can have a progress bar in them. */ QueListViewItem::QueListViewItem(TQListView *parent, const TQString id, const TQString p , const TQString name, const TQString d, const TQString e) : TQListViewItem(parent, id, p, name,d,e), percentDone(0), progressing(false) { } #include "jobqueimp.moc"