First bits of the new GroupSettings-Dialog:
[kdenetwork.git] / kget / core / kget.cpp
blob31a5482d6c761cbd25215a56a0f18e91d71b1f91
1 /* This file is part of the KDE project
3 Copyright (C) 2005 Dario Massarin <nekkar@libero.it>
4 Copyright (C) 2007 Lukas Appelhans <l.appelhans@gmx.de>
5 Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org>
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
13 #include "core/kget.h"
15 #include "mainwindow.h"
16 #include "core/transfer.h"
17 #include "core/transferdatasource.h"
18 #include "core/transfergroup.h"
19 #include "core/transfergrouphandler.h"
20 #include "core/transfertreemodel.h"
21 #include "core/transfertreeselectionmodel.h"
22 #include "core/plugin/plugin.h"
23 #include "core/plugin/transferfactory.h"
24 #include "core/observer.h"
25 #include "core/kuiserverjobs.h"
26 #include "settings.h"
28 #include <kio/netaccess.h>
29 #include <kinputdialog.h>
30 #include <kfiledialog.h>
31 #include <kmessagebox.h>
32 #include <klocale.h>
33 #include <kstandarddirs.h>
34 #include <kservicetypetrader.h>
35 #include <kiconloader.h>
36 #include <kactioncollection.h>
37 #include <kio/renamedialog.h>
38 #include <KPassivePopup>
39 #include <KSystemTrayIcon>
41 #include <QTextStream>
42 #include <QDomElement>
43 #include <QApplication>
44 #include <QClipboard>
45 #include <QAbstractItemView>
47 /**
48 * This is our KGet class. This is where the user's transfers and searches are
49 * stored and organized.
50 * Use this class from the views to add or remove transfers or searches
51 * In order to organize the transfers inside categories we have a TransferGroup
52 * class. By definition, a transfer must always belong to a TransferGroup. If we
53 * don't want it to be displayed by the gui inside a specific group, we will put
54 * it in the group named "Not grouped" (better name?).
55 **/
57 KGet& KGet::self( MainWindow * mainWindow )
59 if(mainWindow)
61 m_mainWindow = mainWindow;
64 static KGet m;
65 return m;
68 void KGet::addObserver(ModelObserver * observer)
70 kDebug(5001);
72 m_observers.append(observer);
74 //Update the new observer with the TransferGroups objects of the model
75 QList<TransferGroup *>::const_iterator it = m_transferTreeModel->transferGroups().begin();
76 QList<TransferGroup *>::const_iterator itEnd = m_transferTreeModel->transferGroups().end();
78 for( ; it!=itEnd ; ++it )
80 postAddedTransferGroupEvent(*it, observer);
83 kDebug(5001) << " >>> EXITING";
86 void KGet::delObserver(ModelObserver * observer)
88 m_observers.removeAll(observer);
91 bool KGet::addGroup(const QString& groupName)
93 kDebug(5001);
95 // Check if a group with that name already exists
96 if(m_transferTreeModel->findGroup(groupName))
97 return false;
99 TransferGroup * group = new TransferGroup(m_transferTreeModel, m_scheduler, groupName);
100 m_transferTreeModel->addGroup(group);
102 //post notifications
103 postAddedTransferGroupEvent(group);
105 return true;
108 void KGet::delGroup(const QString& groupName)
110 TransferGroup * group = m_transferTreeModel->findGroup(groupName);
112 if(group)
114 m_transferTreeModel->delGroup(group);
115 postRemovedTransferGroupEvent(group);
116 delete(group);
120 void KGet::renameGroup(const QString& oldName, const QString& newName)
122 TransferGroup *group = m_transferTreeModel->findGroup(oldName);
124 if(group)
126 group->handler()->setName(newName);
130 QStringList KGet::transferGroupNames()
132 QStringList names;
134 foreach(TransferGroup *group, m_transferTreeModel->transferGroups()) {
135 names << group->name();
138 return names;
141 void KGet::addTransfer(KUrl srcUrl, QString destDir, // krazy:exclude=passbyvalue
142 const QString& groupName, bool start)
144 kDebug(5001) << "Source:" << srcUrl.url();
146 KUrl destUrl;
148 if ( srcUrl.isEmpty() )
150 //No src location: we let the user insert it manually
151 srcUrl = urlInputDialog();
152 if( srcUrl.isEmpty() )
153 return;
156 if ( !isValidSource( srcUrl ) )
157 return;
159 if (destDir.isEmpty())
161 if (Settings::useDefaultDirectory())
162 #ifdef Q_OS_WIN //krazy:exclude=cpp
163 destDir = Settings::defaultDirectory().remove("file:///");
164 #else
165 destDir = Settings::defaultDirectory().remove("file://");
166 #endif
168 QString checkExceptions = getSaveDirectoryFromExceptions(srcUrl);
169 if (Settings::enableExceptions() && !checkExceptions.isEmpty())
170 destDir = checkExceptions;
173 if (!isValidDestDirectory(destDir))
174 destDir = destInputDialog();
176 if( (destUrl = getValidDestUrl( destDir, srcUrl )).isEmpty() )
177 return;
179 if(m_transferTreeModel->findTransferByDestination(destUrl) != 0 || (destUrl.isLocalFile() && QFile::exists(destUrl.path()))) {
180 KIO::RenameDialog dlg( m_mainWindow, i18n("Rename transfer"), srcUrl,
181 destUrl, KIO::M_MULTI);
182 if (dlg.exec() == KIO::R_RENAME)
183 destUrl = dlg.newDestUrl();
184 else
185 return;
187 createTransfer(srcUrl, destUrl, groupName, start);
190 void KGet::addTransfer(const QDomElement& e, const QString& groupName)
192 //We need to read these attributes now in order to know which transfer
193 //plugin to use.
194 KUrl srcUrl = KUrl( e.attribute("Source") );
195 KUrl destUrl = KUrl( e.attribute("Dest") );
197 kDebug(5001) << " src= " << srcUrl.url()
198 << " dest= " << destUrl.url()
199 << " group= "<< groupName << endl;
201 if ( srcUrl.isEmpty() || !isValidSource(srcUrl)
202 || !isValidDestDirectory(destUrl.directory()) )
203 return;
205 createTransfer(srcUrl, destUrl, groupName, false, &e);
208 void KGet::addTransfer(KUrl::List srcUrls, QString destDir, // krazy:exclude=passbyvalue
209 const QString& groupName, bool start)
211 KUrl::List urlsToDownload;
213 KUrl::List::ConstIterator it = srcUrls.begin();
214 KUrl::List::ConstIterator itEnd = srcUrls.end();
216 for(; it!=itEnd ; ++it)
218 if ( isValidSource( *it ) )
219 urlsToDownload.append( *it );
222 if ( urlsToDownload.count() == 0 )
223 return;
225 if ( urlsToDownload.count() == 1 )
227 // just one file -> ask for filename
228 addTransfer(srcUrls.first(), destDir + srcUrls.first().fileName(), groupName, start);
229 return;
232 KUrl destUrl;
234 // multiple files -> ask for directory, not for every single filename
235 if (!isValidDestDirectory(destDir) && !Settings::useDefaultDirectory())
236 destDir = destInputDialog();
238 it = urlsToDownload.begin();
239 itEnd = urlsToDownload.end();
241 for ( ; it != itEnd; ++it )
243 if (destDir.isEmpty())
245 if (Settings::useDefaultDirectory())
246 #ifdef Q_OS_WIN //krazy:exclude=cpp
247 destDir = Settings::defaultDirectory().remove("file:///");
248 #else
249 destDir = Settings::defaultDirectory().remove("file://");
250 #endif
252 QString checkExceptions = getSaveDirectoryFromExceptions(*it);
253 if (Settings::enableExceptions() && !checkExceptions.isEmpty())
254 destDir = checkExceptions;
256 destUrl = getValidDestUrl(destDir, *it);
258 if(!isValidDestUrl(destUrl))
259 continue;
261 createTransfer(*it, destUrl, groupName, start);
266 void KGet::delTransfer(TransferHandler * transfer)
268 Transfer * t = transfer->m_transfer;
270 m_transferTreeModel->delTransfer(t);
272 //Here I delete the Transfer. The other possibility is to move it to a list
273 //and to delete all these transfers when kget gets closed. Obviously, after
274 //the notification to the views that the transfer has been removed, all the
275 //pointers to it are invalid.
276 transfer->postDeleteEvent();
277 // TODO: why does it crash if a download is going to be deleted which is not the last in the list?
278 // there are always no problems with the last download.
279 // delete( t );
282 void KGet::moveTransfer(TransferHandler * transfer, const QString& groupName)
284 Q_UNUSED(transfer);
285 Q_UNUSED(groupName);
288 QList<TransferHandler *> KGet::selectedTransfers()
290 // kDebug(5001) << "KGet::selectedTransfers";
292 QList<TransferHandler *> selectedTransfers;
294 QModelIndexList selectedIndexes = m_selectionModel->selectedRows();
296 foreach(QModelIndex currentIndex, selectedIndexes)
298 if(!m_transferTreeModel->isTransferGroup(currentIndex))
299 selectedTransfers.append(static_cast<TransferHandler *> (currentIndex.internalPointer()));
302 return selectedTransfers;
305 // This is the code that was used in the old selectedTransfers function
306 /* QList<TransferGroup *>::const_iterator it = m_transferTreeModel->transferGroups().begin();
307 QList<TransferGroup *>::const_iterator itEnd = m_transferTreeModel->transferGroups().end();
309 for( ; it!=itEnd ; ++it )
311 TransferGroup::iterator it2 = (*it)->begin();
312 TransferGroup::iterator it2End = (*it)->end();
314 for( ; it2!=it2End ; ++it2 )
316 Transfer * transfer = (Transfer*) *it2;
318 if( transfer->isSelected() )
319 selectedTransfers.append( transfer->handler() );
322 return selectedTransfers;*/
325 QList<TransferGroupHandler *> KGet::selectedTransferGroups()
327 QList<TransferGroupHandler *> selectedTransferGroups;
329 QModelIndexList selectedIndexes = m_selectionModel->selectedRows();
331 foreach(QModelIndex currentIndex, selectedIndexes)
333 if(m_transferTreeModel->isTransferGroup(currentIndex))
334 selectedTransferGroups.append(static_cast<TransferGroupHandler *> (currentIndex.internalPointer()));
337 return selectedTransferGroups;
340 TransferTreeSelectionModel * KGet::selectionModel()
342 return m_selectionModel;
345 void KGet::addTransferView(QAbstractItemView * view)
347 view->setModel(m_transferTreeModel);
350 void KGet::load( QString filename ) // krazy:exclude=passbyvalue
352 kDebug(5001) << "(" << filename << ")";
354 if(filename.isEmpty())
355 filename = KStandardDirs::locateLocal("appdata", "transfers.kgt");
357 QString tmpFile;
359 //Try to save the transferlist to a temporary location
360 if(!KIO::NetAccess::download(KUrl(filename), tmpFile, 0))
361 return;
363 QFile file(tmpFile);
364 QDomDocument doc;
366 kDebug(5001) << "file:" << filename;
368 if(doc.setContent(&file))
370 QDomElement root = doc.documentElement();
372 QDomNodeList nodeList = root.elementsByTagName("TransferGroup");
373 int nItems = nodeList.length();
375 for( int i = 0 ; i < nItems ; i++ )
377 TransferGroup * foundGroup = m_transferTreeModel->findGroup( nodeList.item(i).toElement().attribute("Name") );
379 kDebug(5001) << "KGet::load -> group = " << nodeList.item(i).toElement().attribute("Name");
381 if( !foundGroup )
383 kDebug(5001) << "KGet::load -> group not found";
385 TransferGroup * newGroup = new TransferGroup(m_transferTreeModel, m_scheduler);
387 m_transferTreeModel->addGroup(newGroup);
389 newGroup->load(nodeList.item(i).toElement());
391 //Post notifications
392 postAddedTransferGroupEvent(newGroup);
394 else
396 kDebug(5001) << "KGet::load -> group found";
398 //A group with this name already exists.
399 //Integrate the group's transfers with the ones read from file
400 foundGroup->load(nodeList.item(i).toElement());
404 else
406 kWarning(5001) << "Error reading the transfers file";
410 void KGet::save( QString filename ) // krazy:exclude=passbyvalue
412 if ( !filename.isEmpty()
413 && QFile::exists( filename )
414 && (KMessageBox::questionYesNoCancel(0,
415 i18n("The file %1 already exists.\nOverwrite?", filename),
416 i18n("Overwrite existing file?"), KStandardGuiItem::yes(),
417 KStandardGuiItem::no(), KStandardGuiItem::cancel(), "QuestionFilenameExists" )
418 != KMessageBox::Yes) )
419 return;
421 if(filename.isEmpty())
422 filename = KStandardDirs::locateLocal("appdata", "transfers.kgt");
424 QDomDocument doc(QString("KGetTransfers"));
425 QDomElement root = doc.createElement("Transfers");
426 doc.appendChild(root);
428 QList<TransferGroup *>::const_iterator it = m_transferTreeModel->transferGroups().begin();
429 QList<TransferGroup *>::const_iterator itEnd = m_transferTreeModel->transferGroups().end();
431 for ( ; it!=itEnd ; ++it )
433 QDomElement e = doc.createElement("TransferGroup");
434 root.appendChild(e);
435 (*it)->save(e);
437 QFile file(filename);
438 if ( !file.open( QIODevice::WriteOnly ) )
440 //kWarning(5001)<<"Unable to open output file when saving";
441 KMessageBox::error(0,
442 i18n("Unable to save to: %1", filename),
443 i18n("Error"));
444 return;
447 QTextStream stream( &file );
448 doc.save( stream, 0 );
449 file.close();
452 TransferFactory * KGet::factory(TransferHandler * transfer)
454 return transfer->m_transfer->factory();
457 KActionCollection * KGet::actionCollection()
459 return m_mainWindow->actionCollection();
462 void KGet::setSchedulerRunning(bool running)
464 if(running)
466 m_scheduler->stop(); //stopall first, to have a clean startingpoint
467 m_scheduler->start();
469 else
470 m_scheduler->stop();
473 bool KGet::schedulerRunning()
475 return (m_scheduler->countRunningJobs() > 0);
478 void KGet::setPluginsSettingsWidget(KTabWidget * widget)
480 kDebug(5001);
481 QList<TransferFactory *>::iterator it = m_transferFactories.begin();
482 QList<TransferFactory *>::iterator itEnd = m_transferFactories.end();
484 QWidget * settingsWidget;
485 for( ; it!=itEnd ; ++it)
487 KDialog *dialog = static_cast<KDialog*>(widget->parent()->parent());
488 if (!dialog)
489 return;
491 settingsWidget = (*it)->createSettingsWidget(dialog);
492 if(settingsWidget)
493 widget->addTab( settingsWidget, (*it)->displayName() );
497 QList<TransferHandler*> KGet::allTransfers()
499 QList<TransferHandler*> transfers;
501 foreach (TransferGroup *group, KGet::m_transferTreeModel->transferGroups())
503 transfers << group->handler()->transfers();
506 return transfers;
509 void KGet::checkSystemTray()
511 kDebug(5001);
512 bool running = false;
514 foreach (TransferHandler *handler, KGet::allTransfers())
516 if (handler->status() == Job::Running)
517 running = true;
519 if (running)
520 continue;
523 m_mainWindow->setSystemTrayDownloading(running);
526 void KGet::settingsChanged()
528 kDebug(5001);
530 QList<TransferFactory*>::const_iterator it = m_transferFactories.begin();
531 QList<TransferFactory*>::const_iterator itEnd = m_transferFactories.end();
533 for( ; it!=itEnd ; ++it )
535 (*it)->settingsChanged();
539 void KGet::registerKJob(KJob *job)
541 m_jobManager->registerJob(job);
544 void KGet::unregisterKJob(KJob *job)
546 m_jobManager->unregisterJob(job);
549 void KGet::reloadKJobs()
551 m_jobManager->reload();
554 QStringList KGet::defaultFolders(const KUrl &filename, const QString &groupname)
556 kDebug(5001) << filename << groupname;
558 QStringList list;
559 if (Settings::enableExceptions())
560 list.append(KGet::getSaveDirectoryFromExceptions(filename));
562 TransferGroup * group = KGet::m_transferTreeModel->findGroup(groupname);
564 if (!group->defaultFolder().isEmpty())
565 list.append(group->defaultFolder());
567 if (Settings::useDefaultDirectory())
568 list.append(Settings::defaultDirectory());
570 if (!Settings::lastDirectory().isEmpty() &&
571 QString::compare(Settings::lastDirectory(), Settings::defaultDirectory()) != 0)
572 list.append(Settings::lastDirectory());
574 foreach(QString string, list)
576 #ifdef Q_OS_WIN //krazy:exclude=cpp
577 string.remove("file:///");
578 #else
579 string.remove("file://");
580 #endif
583 return list;
586 // ------ STATIC MEMBERS INITIALIZATION ------
587 QList<ModelObserver *> KGet::m_observers;
588 TransferTreeModel * KGet::m_transferTreeModel;
589 TransferTreeSelectionModel * KGet::m_selectionModel;
590 QList<TransferFactory *> KGet::m_transferFactories;
591 Scheduler * KGet::m_scheduler = new Scheduler();
592 MainWindow * KGet::m_mainWindow = 0;
593 KUiServerJobs * KGet::m_jobManager = new KUiServerJobs();
595 // ------ PRIVATE FUNCTIONS ------
596 KGet::KGet()
598 m_transferTreeModel = new TransferTreeModel(m_scheduler);
599 m_selectionModel = new TransferTreeSelectionModel(m_transferTreeModel);
601 //Load all the available plugins
602 loadPlugins();
604 //Create the default group
605 addGroup(i18n("My Downloads"));
608 KGet::~KGet()
610 delete m_scheduler;
613 bool KGet::createTransfer(const KUrl &src, const KUrl &dest, const QString& groupName,
614 bool start, const QDomElement * e)
616 kDebug(5001) << "srcUrl= " << src.url() << " "
617 << "destUrl= " << dest.url()
618 << "group= _" << groupName << "_" << endl;
620 TransferGroup * group = m_transferTreeModel->findGroup(groupName);
621 if (group==0)
623 kDebug(5001) << "KGet::createTransfer -> group not found";
624 group = m_transferTreeModel->transferGroups().first();
626 Transfer * newTransfer;
628 QList<TransferFactory *>::iterator it = m_transferFactories.begin();
629 QList<TransferFactory *>::iterator itEnd = m_transferFactories.end();
631 for( ; it!=itEnd ; ++it)
633 kDebug(5001) << "Trying plugin n.plugins=" << m_transferFactories.size();
634 if((newTransfer = (*it)->createTransfer(src, dest, group, m_scheduler, e)))
636 // kDebug(5001) << "KGet::createTransfer -> CREATING NEW TRANSFER ON GROUP: _" << group->name() << "_";
637 m_transferTreeModel->addTransfer(newTransfer, group);
639 if(start)
640 newTransfer->handler()->start();
642 if (newTransfer->percent() != 100) //Don't add a finished observer if the Transfer has already been finished
643 newTransfer->handler()->addObserver(new TransferFinishedObserver());
645 return true;
648 kDebug(5001) << "Warning! No plugin found to handle the given url";
649 return false;
652 TransferDataSource * KGet::createTransferDataSource(const KUrl &src)
654 kDebug(5001);
655 QList<TransferFactory *>::iterator it = m_transferFactories.begin();
656 QList<TransferFactory *>::iterator itEnd = m_transferFactories.end();
658 TransferDataSource *dataSource;
659 for( ; it!=itEnd ; ++it)
661 dataSource = (*it)->createTransferDataSource(src);
662 if(dataSource)
663 return dataSource;
665 return 0;
668 void KGet::postAddedTransferGroupEvent(TransferGroup * group, ModelObserver * observer)
670 kDebug(5001);
671 if(observer)
673 observer->addedTransferGroupEvent(group->handler());
674 return;
677 QList<ModelObserver *>::iterator it = m_observers.begin();
678 QList<ModelObserver *>::iterator itEnd = m_observers.end();
680 for(; it!=itEnd; ++it)
682 kDebug(5001) << "message posted";
684 (*it)->addedTransferGroupEvent(group->handler());
688 void KGet::postRemovedTransferGroupEvent(TransferGroup * group, ModelObserver * observer)
690 if(observer)
692 observer->removedTransferGroupEvent(group->handler());
693 return;
696 QList<ModelObserver *>::iterator it = m_observers.begin();
697 QList<ModelObserver *>::iterator itEnd = m_observers.end();
699 for(; it!=itEnd; ++it)
701 (*it)->removedTransferGroupEvent(group->handler());
705 KUrl KGet::urlInputDialog()
707 QString newtransfer;
708 bool ok = false;
710 KUrl clipboardUrl = KUrl(QApplication::clipboard()->text(QClipboard::Clipboard).trimmed());
711 if (clipboardUrl.isValid())
712 newtransfer = clipboardUrl.url();
714 while (!ok)
716 newtransfer = KInputDialog::getText(i18n("New Download"), i18n("Enter URL:"), newtransfer, &ok, 0);
718 if (!ok)
720 //user pressed cancel
721 return KUrl();
724 KUrl src = KUrl(newtransfer);
725 if(src.isValid())
726 return src;
727 else
728 ok = false;
730 return KUrl();
733 QString KGet::destInputDialog()
735 QString destDir = KFileDialog::getExistingDirectory(Settings::lastDirectory());
737 Settings::setLastDirectory( destDir );
738 return destDir;
741 QString KGet::getSaveDirectoryFromExceptions(const KUrl &filename)
743 QString destDir;
745 QStringList list = Settings::extensionsFolderList();
746 QStringList::Iterator it = list.begin();
747 QStringList::Iterator end = list.end();
748 while (it != end) {
749 // odd list items are regular expressions for extensions
750 QString ext = *it;
751 ++it;
752 QString path = *it;
753 ++it;
755 if (!ext.startsWith('*'))
756 ext = '*' + ext;
758 QRegExp rexp(ext);
759 rexp.setPatternSyntax(QRegExp::Wildcard);
761 if (rexp.exactMatch(filename.url())) {
762 destDir = path;
763 break;
767 #ifdef Q_OS_WIN //krazy:exclude=cpp
768 destDir = destDir.remove("file:///");
769 #endif
770 return destDir.remove("file://");
773 bool KGet::isValidSource(const KUrl &source)
775 if (!source.isValid())
777 KMessageBox::error(0,
778 i18n("Malformed URL:\n%1", source.prettyUrl()),
779 i18n("Error"));
780 return false;
782 // Check if a transfer with the same url already exists
783 Transfer * transfer = m_transferTreeModel->findTransfer( source );
784 if ( transfer )
786 if ( transfer->status() == Job::Finished )
788 // transfer is finished, ask if we want to download again
789 if (KMessageBox::questionYesNoCancel(0,
790 i18n("URL already saved:\n%1\nDownload again?", source.prettyUrl()),
791 i18n("Download URL again?"), KStandardGuiItem::yes(),
792 KStandardGuiItem::no(), KStandardGuiItem::cancel(), "QuestionUrlAlreadySaved" )
793 == KMessageBox::Yes)
795 //TODO reimplement this
796 //transfer->slotRemove();
797 //checkQueue();
798 return true;
801 else
803 //Transfer is already in list and not finished, ...
804 return false;
806 return false;
808 return true;
811 bool KGet::isValidDestDirectory(const QString & destDir)
813 kDebug(5001) << destDir;
814 if (!QFileInfo(destDir).isDir())
816 if (QFileInfo(KUrl(destDir).directory()).isWritable())
817 return (!destDir.isEmpty());
818 if (!QFileInfo(KUrl(destDir).directory()).isWritable() && !destDir.isEmpty())
819 KMessageBox::error(0, i18n("Directory is not writable"));
821 else
823 if (QFileInfo(destDir).isWritable())
824 return (!destDir.isEmpty());
825 if (!QFileInfo(destDir).isWritable() && !destDir.isEmpty())
826 KMessageBox::error(0, i18n("Directory is not writable"));
828 return false;
831 bool KGet::isValidDestUrl(const KUrl &destUrl)
833 if(KIO::NetAccess::exists(destUrl, KIO::NetAccess::DestinationSide, 0))
835 if (KMessageBox::warningYesNoCancel(0,
836 i18n("Destination file \n%1\nalready exists.\n"
837 "Do you want to overwrite it?", destUrl.prettyUrl()))
838 == KMessageBox::Yes)
840 safeDeleteFile( destUrl );
841 return true;
843 else
844 return false;
846 if (m_transferTreeModel->findTransferByDestination(destUrl) || destUrl.isEmpty())
847 return false;
849 return true;
851 KIO::open_RenameDlg(i18n("File already exists"),
852 (*it).url(), destUrl.url(),
853 KIO::M_MULTI);
857 KUrl KGet::getValidDestUrl(const QString& destDir, const KUrl &srcUrl)
859 if ( !isValidDestDirectory(destDir) )
860 return KUrl();
862 // create a proper destination file from destDir
863 KUrl destUrl = KUrl( destDir );
864 QString filename = srcUrl.fileName();
866 if ( filename.isEmpty() )
868 // simply use the full url as filename
869 filename = KUrl::toPercentEncoding( srcUrl.prettyUrl(), "/" );
870 kDebug(5001) << " Filename is empty. Setting to " << filename;
871 kDebug(5001) << " srcUrl = " << srcUrl.url();
872 kDebug(5001) << " prettyUrl = " << srcUrl.prettyUrl();
874 if (QFileInfo(destUrl.path()).isDir())
876 kDebug(5001) << " Filename is not empty";
877 destUrl.adjustPath( KUrl::AddTrailingSlash );
878 destUrl.setFileName( filename );
880 if (!isValidDestUrl(destUrl))
882 kDebug(5001) << " destUrl " << destUrl.path() << " is not valid";
883 return KUrl();
885 return destUrl;
888 void KGet::loadPlugins()
890 // Add versioning constraint
891 QString
892 str = "[X-KDE-KGet-framework-version] == ";
893 str += QString::number( FrameworkVersion );
894 str += " and ";
895 str += "[X-KDE-KGet-rank] > 0";
896 str += " and ";
897 str += "[X-KDE-KGet-plugintype] == ";
899 KService::List offers;
901 //TransferFactory plugins
902 offers = KServiceTypeTrader::self()->query( "KGet/Plugin", str + "'TransferFactory'" );
904 //Here we use a QMap only to easily sort the plugins by rank
905 QMap<int, KService::Ptr> services;
906 QMap<int, KService::Ptr>::iterator it;
908 for ( int i = 0; i < offers.count(); ++i )
910 services[ offers[i]->property( "X-KDE-KGet-rank" ).toInt() ] = offers[i];
911 kDebug(5001) << " TransferFactory plugin found:" << endl <<
912 " rank = " << offers[i]->property( "X-KDE-KGet-rank" ).toInt() << endl <<
913 " plugintype = " << offers[i]->property( "X-KDE-KGet-plugintype" ) << endl;
916 //I must fill this pluginList before and my m_transferFactories list after.
917 //This because calling the KLibLoader::globalLibrary() erases the static
918 //members of this class (why?), such as the m_transferFactories list.
919 QList<KGetPlugin *> pluginList;
921 for( it = services.begin(); it != services.end(); ++it )
923 KGetPlugin * plugin;
924 if( (plugin = createPluginFromService(*it)) != 0 )
926 pluginList.prepend(plugin);
927 kDebug(5001) << "TransferFactory plugin (" << (*it)->library()
928 << ") found and added to the list of available plugins" << endl;
930 else
931 kDebug(5001) << "Error loading TransferFactory plugin ("
932 << (*it)->library() << ")" << endl;
935 QList<KGetPlugin *>::iterator it2 = pluginList.begin();
936 QList<KGetPlugin *>::iterator it2End = pluginList.end();
938 for( ; it2!=it2End ; ++it2 )
939 m_transferFactories.append( static_cast<TransferFactory *>(*it2) );
941 kDebug(5001) << "Number of factories = " << m_transferFactories.size();
944 KGetPlugin * KGet::createPluginFromService( const KService::Ptr &service )
946 //try to load the specified library
947 KPluginFactory *factory = KPluginLoader(service->library()).factory();
949 if (!factory)
951 KMessageBox::error(0, i18n("<html><p>KPluginFactory could not load the plugin:<br/><i>%1</i></p></html>",
952 service->library()));
953 kError(5001) << "KPluginFactory could not load the plugin:" << service->library();
954 return 0;
956 KGetPlugin * plugin = factory->create< TransferFactory >(0);
958 return plugin;
961 bool KGet::safeDeleteFile( const KUrl& url )
963 if ( url.isLocalFile() )
965 QFileInfo info( url.path() );
966 if ( info.isDir() )
968 KMessageBox::information(0L,i18n("Not deleting\n%1\nas it is a "
969 "directory.", url.prettyUrl()),
970 i18n("Not Deleted"));
971 return false;
973 KIO::NetAccess::del( url, 0L );
974 return true;
977 else
978 KMessageBox::information( 0L,
979 i18n("Not deleting\n%1\nas it is not a local"
980 " file.", url.prettyUrl()),
981 i18n("Not Deleted") );
982 return false;
985 TransferFinishedObserver::TransferFinishedObserver()
986 : TransferObserver()
990 void TransferFinishedObserver::transferChangedEvent(TransferHandler * transfer)
992 kDebug(5001);
994 if (transfer->status() == Job::Finished && Settings::quitAfterCompletedTransfer())
996 checkAndFinish();
999 if (prevStatus != transfer->statusText())//FIXME: HACK: better: check statusFlags if it
1000 { //contains Tc_Status (flags & Transfer::Tc_Status <-doesn't work)
1001 prevStatus = transfer->statusText();
1002 KGet::checkSystemTray();
1006 void TransferFinishedObserver::checkAndFinish()
1008 bool quitFlag = true;
1009 foreach(TransferGroup *transferGroup, KGet::m_transferTreeModel->transferGroups()) {
1010 foreach(TransferHandler *transfer, transferGroup->handler()->transfers()) {
1011 if(transfer->status() != Job::Finished) {
1012 quitFlag = false;
1017 // check if there is some unfinished transfer in scheduler queues
1018 if(quitFlag) {
1019 KPassivePopup *message;
1020 // we have to call diferent message from kpassivePopup
1021 // one with parent as QWidget for the mainWindow
1022 // and another with parent as QSystemTrayIcon if the parent is a systemTray
1023 // so passing the QSystemTrayIcon as QWidget don't work
1024 if(Settings::enableSystemTray())
1026 message = KPassivePopup::message(5000, KGET_QUIT_MESSAGE_TITLE,
1027 KGET_QUIT_MESSAGE,
1028 KGet::m_mainWindow->systemTray());
1030 else
1032 message = KPassivePopup::message(5000, KGET_QUIT_MESSAGE_TITLE,
1033 KGET_QUIT_MESSAGE,
1034 KGet::m_mainWindow);
1037 QObject::connect(message, SIGNAL(destroyed()), KGet::m_mainWindow, SLOT(slotQuit()));