Disable clipboardsharing in view only mode.
[kdenetwork.git] / kget / core / kget.cpp
blobd5a5c2437a64d6c052ac91fa1bd16956923e51c4
1 /* This file is part of the KDE project
3 Copyright (C) 2005 Dario Massarin <nekkar@libero.it>
4 Copyright (C) 2007-2008 Lukas Appelhans <l.appelhans@gmx.de>
5 Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org>
6 Copyright (C) 2008 Dario Freddi <drf54321@gmail.com>
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
14 #include "core/kget.h"
16 #include "mainwindow.h"
17 #include "core/transfer.h"
18 #include "core/transferdatasource.h"
19 #include "core/transfergroup.h"
20 #include "core/transfergrouphandler.h"
21 #include "core/transfertreemodel.h"
22 #include "core/transfertreeselectionmodel.h"
23 #include "core/plugin/plugin.h"
24 #include "core/plugin/transferfactory.h"
25 #include "core/observer.h"
26 #include "core/kuiserverjobs.h"
27 #include "core/transfergroupscheduler.h"
28 #include "settings.h"
30 #include <kio/netaccess.h>
31 #include <kinputdialog.h>
32 #include <kfiledialog.h>
33 #include <kmessagebox.h>
34 #include <klocale.h>
35 #include <kstandarddirs.h>
36 #include <kservicetypetrader.h>
37 #include <kiconloader.h>
38 #include <kactioncollection.h>
39 #include <kio/renamedialog.h>
40 #include <KSystemTrayIcon>
41 #include <KSharedConfig>
42 #include <KPluginInfo>
44 #include <QTextStream>
45 #include <QDomElement>
46 #include <QApplication>
47 #include <QClipboard>
48 #include <QAbstractItemView>
50 /**
51 * This is our KGet class. This is where the user's transfers and searches are
52 * stored and organized.
53 * Use this class from the views to add or remove transfers or searches
54 * In order to organize the transfers inside categories we have a TransferGroup
55 * class. By definition, a transfer must always belong to a TransferGroup. If we
56 * don't want it to be displayed by the gui inside a specific group, we will put
57 * it in the group named "Not grouped" (better name?).
58 **/
60 KGet& KGet::self( MainWindow * mainWindow )
62 if(mainWindow)
64 m_mainWindow = mainWindow;
65 m_jobManager = new KUiServerJobs(m_mainWindow);
68 static KGet m;
69 return m;
72 void KGet::addObserver(ModelObserver * observer)
74 kDebug(5001);
76 m_observers.append(observer);
78 //Update the new observer with the TransferGroups objects of the model
79 QList<TransferGroup *>::const_iterator it = m_transferTreeModel->transferGroups().begin();
80 QList<TransferGroup *>::const_iterator itEnd = m_transferTreeModel->transferGroups().end();
82 for( ; it!=itEnd ; ++it )
84 postAddedTransferGroupEvent(*it, observer);
87 kDebug(5001) << " >>> EXITING";
90 void KGet::delObserver(ModelObserver * observer)
92 m_observers.removeAll(observer);
95 bool KGet::addGroup(const QString& groupName)
97 kDebug(5001);
99 // Check if a group with that name already exists
100 if(m_transferTreeModel->findGroup(groupName))
101 return false;
103 TransferGroup * group = new TransferGroup(m_transferTreeModel, m_scheduler, groupName);
104 m_transferTreeModel->addGroup(group);
106 //post notifications
107 postAddedTransferGroupEvent(group);
109 return true;
112 void KGet::delGroup(const QString& groupName)
114 TransferGroup * group = m_transferTreeModel->findGroup(groupName);
116 if(group)
118 m_transferTreeModel->delGroup(group);
119 postRemovedTransferGroupEvent(group);
120 delete(group);
124 void KGet::renameGroup(const QString& oldName, const QString& newName)
126 TransferGroup *group = m_transferTreeModel->findGroup(oldName);
128 if(group)
130 group->handler()->setName(newName);
134 QStringList KGet::transferGroupNames()
136 QStringList names;
138 foreach(TransferGroup *group, m_transferTreeModel->transferGroups()) {
139 names << group->name();
142 return names;
145 void KGet::addTransfer(KUrl srcUrl, QString destDir, // krazy:exclude=passbyvalue
146 const QString& groupName, bool start)
148 kDebug(5001) << "Source:" << srcUrl.url();
150 KUrl destUrl;
152 if ( srcUrl.isEmpty() )
154 //No src location: we let the user insert it manually
155 srcUrl = urlInputDialog();
156 if( srcUrl.isEmpty() )
157 return;
160 if ( !isValidSource( srcUrl ) )
161 return;
163 if (destDir.isEmpty())
165 if (Settings::useDefaultDirectory())
166 destDir = KUrl(Settings::defaultDirectory()).path();
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::Iterator it = srcUrls.begin();
214 KUrl::List::Iterator 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 destDir = KUrl(Settings::defaultDirectory()).path();
248 QString checkExceptions = getSaveDirectoryFromExceptions(*it);
249 if (Settings::enableExceptions() && !checkExceptions.isEmpty())
250 destDir = checkExceptions;
252 destUrl = getValidDestUrl(destDir, *it);
254 if(!isValidDestUrl(destUrl))
255 continue;
257 createTransfer(*it, destUrl, groupName, start);
262 bool KGet::delTransfer(TransferHandler * transfer)
264 Transfer * t = transfer->m_transfer;
265 t->stop();
267 m_transferTreeModel->delTransfer(t);
269 //Here I delete the Transfer. The other possibility is to move it to a list
270 //and to delete all these transfers when kget gets closed. Obviously, after
271 //the notification to the views that the transfer has been removed, all the
272 //pointers to it are invalid.
273 transfer->postDeleteEvent();
274 delete t;
275 return true;
278 void KGet::moveTransfer(TransferHandler * transfer, const QString& groupName)
280 Q_UNUSED(transfer);
281 Q_UNUSED(groupName);
284 void KGet::redownloadTransfer(TransferHandler * transfer)
286 QString group = transfer->group()->name();
287 QString src = transfer->source().url();
288 QString dest = transfer->dest().url();
289 bool running = false;
290 if (transfer->status() == Job::Running)
291 running = true;
293 KGet::delTransfer(transfer);
294 KGet::addTransfer(src, dest, group, running);
297 QList<TransferHandler *> KGet::selectedTransfers()
299 // kDebug(5001) << "KGet::selectedTransfers";
301 QList<TransferHandler *> selectedTransfers;
303 QModelIndexList selectedIndexes = m_selectionModel->selectedRows();
305 foreach(const QModelIndex &currentIndex, selectedIndexes)
307 if(!m_transferTreeModel->isTransferGroup(currentIndex))
308 selectedTransfers.append(static_cast<TransferHandler *> (currentIndex.internalPointer()));
311 return selectedTransfers;
314 // This is the code that was used in the old selectedTransfers function
315 /* QList<TransferGroup *>::const_iterator it = m_transferTreeModel->transferGroups().begin();
316 QList<TransferGroup *>::const_iterator itEnd = m_transferTreeModel->transferGroups().end();
318 for( ; it!=itEnd ; ++it )
320 TransferGroup::iterator it2 = (*it)->begin();
321 TransferGroup::iterator it2End = (*it)->end();
323 for( ; it2!=it2End ; ++it2 )
325 Transfer * transfer = (Transfer*) *it2;
327 if( transfer->isSelected() )
328 selectedTransfers.append( transfer->handler() );
331 return selectedTransfers;*/
334 QList<TransferHandler *> KGet::finishedTransfers()
336 QList<TransferHandler *> finishedTransfers;
338 foreach(TransferHandler *transfer, allTransfers())
340 if (transfer->status() == Job::Finished) {
341 finishedTransfers << transfer;
344 return finishedTransfers;
347 QList<TransferGroupHandler *> KGet::selectedTransferGroups()
349 QList<TransferGroupHandler *> selectedTransferGroups;
351 QModelIndexList selectedIndexes = m_selectionModel->selectedRows();
353 foreach(const QModelIndex &currentIndex, selectedIndexes)
355 if(m_transferTreeModel->isTransferGroup(currentIndex))
356 selectedTransferGroups.append(static_cast<TransferGroupHandler *> (currentIndex.internalPointer()));
359 return selectedTransferGroups;
362 TransferTreeSelectionModel * KGet::selectionModel()
364 return m_selectionModel;
367 void KGet::addTransferView(QAbstractItemView * view)
369 view->setModel(m_transferTreeModel);
372 void KGet::load( QString filename ) // krazy:exclude=passbyvalue
374 kDebug(5001) << "(" << filename << ")";
376 if(filename.isEmpty())
377 filename = KStandardDirs::locateLocal("appdata", "transfers.kgt");
379 QString tmpFile;
381 //Try to save the transferlist to a temporary location
382 if(!KIO::NetAccess::download(KUrl(filename), tmpFile, 0))
383 return;
385 QFile file(tmpFile);
386 QDomDocument doc;
388 kDebug(5001) << "file:" << filename;
390 if(doc.setContent(&file))
392 QDomElement root = doc.documentElement();
394 QDomNodeList nodeList = root.elementsByTagName("TransferGroup");
395 int nItems = nodeList.length();
397 for( int i = 0 ; i < nItems ; i++ )
399 TransferGroup * foundGroup = m_transferTreeModel->findGroup( nodeList.item(i).toElement().attribute("Name") );
401 kDebug(5001) << "KGet::load -> group = " << nodeList.item(i).toElement().attribute("Name");
403 if( !foundGroup )
405 kDebug(5001) << "KGet::load -> group not found";
407 TransferGroup * newGroup = new TransferGroup(m_transferTreeModel, m_scheduler);
409 m_transferTreeModel->addGroup(newGroup);
411 newGroup->load(nodeList.item(i).toElement());
413 //Post notifications
414 postAddedTransferGroupEvent(newGroup);
416 else
418 kDebug(5001) << "KGet::load -> group found";
420 //A group with this name already exists.
421 //Integrate the group's transfers with the ones read from file
422 foundGroup->load(nodeList.item(i).toElement());
426 else
428 kWarning(5001) << "Error reading the transfers file";
431 addObserver(new GenericModelObserver());
434 void KGet::save( QString filename, bool plain ) // krazy:exclude=passbyvalue
436 if ( !filename.isEmpty()
437 && QFile::exists( filename )
438 && (KMessageBox::questionYesNoCancel(0,
439 i18n("The file %1 already exists.\nOverwrite?", filename),
440 i18n("Overwrite existing file?"), KStandardGuiItem::yes(),
441 KStandardGuiItem::no(), KStandardGuiItem::cancel(), "QuestionFilenameExists" )
442 != KMessageBox::Yes) )
443 return;
445 if(filename.isEmpty())
446 filename = KStandardDirs::locateLocal("appdata", "transfers.kgt");
448 QFile file(filename);
449 if ( !file.open( QIODevice::WriteOnly ) )
451 //kWarning(5001)<<"Unable to open output file when saving";
452 KMessageBox::error(0,
453 i18n("Unable to save to: %1", filename),
454 i18n("Error"));
456 return;
459 if (plain) {
460 QTextStream out(&file);
461 foreach(TransferHandler *handler, allTransfers()) {
462 out << handler->source().prettyUrl() << endl;
465 else {
466 QDomDocument doc(QString("KGetTransfers"));
467 QDomElement root = doc.createElement("Transfers");
468 doc.appendChild(root);
470 QList<TransferGroup *>::const_iterator it = m_transferTreeModel->transferGroups().begin();
471 QList<TransferGroup *>::const_iterator itEnd = m_transferTreeModel->transferGroups().end();
473 for ( ; it!=itEnd ; ++it )
475 QDomElement e = doc.createElement("TransferGroup");
476 root.appendChild(e);
477 (*it)->save(e);
480 QTextStream stream( &file );
481 doc.save( stream, 0 );
483 file.close();
486 TransferFactory * KGet::factory(TransferHandler * transfer)
488 return transfer->m_transfer->factory();
491 KActionCollection * KGet::actionCollection()
493 return m_mainWindow->actionCollection();
496 void KGet::setSchedulerRunning(bool running)
498 if(running)
500 m_scheduler->stop(); //stopall first, to have a clean startingpoint
501 m_scheduler->start();
503 else
504 m_scheduler->stop();
507 bool KGet::schedulerRunning()
509 return (m_scheduler->countRunningJobs() > 0);
512 QList<TransferHandler*> KGet::allTransfers()
514 QList<TransferHandler*> transfers;
516 foreach (TransferGroup *group, KGet::m_transferTreeModel->transferGroups())
518 transfers << group->handler()->transfers();
520 return transfers;
523 QList<TransferGroupHandler*> KGet::allTransferGroups()
525 QList<TransferGroupHandler*> transfergroups;
527 foreach (TransferGroup *group, KGet::m_transferTreeModel->transferGroups())
529 transfergroups << group->handler();
531 return transfergroups;
534 TransferHandler * KGet::findTransfer(const KUrl &src)
536 return KGet::m_transferTreeModel->findTransfer(src)->handler();
539 void KGet::checkSystemTray()
541 kDebug(5001);
542 bool running = false;
544 foreach (TransferHandler *handler, KGet::allTransfers())
546 if (handler->status() == Job::Running)
547 running = true;
549 if (running)
550 continue;
553 m_mainWindow->setSystemTrayDownloading(running);
556 void KGet::settingsChanged()
558 kDebug(5001);
560 QList<TransferFactory*>::const_iterator it = m_transferFactories.constBegin();
561 QList<TransferFactory*>::const_iterator itEnd = m_transferFactories.constEnd();
563 for( ; it!=itEnd ; ++it )
565 (*it)->settingsChanged();
569 void KGet::registerKJob(KJob *job)
571 m_jobManager->registerJob(job);
574 void KGet::unregisterKJob(KJob *job)
576 m_jobManager->unregisterJob(job);
579 void KGet::reloadKJobs()
581 m_jobManager->reload();
584 QStringList KGet::defaultFolders(const KUrl &filename, const QString &groupname)
586 kDebug(5001) << filename << groupname;
588 QStringList list;
589 const QString saveDirectoryFromExceptions = KGet::getSaveDirectoryFromExceptions(filename);
590 if (Settings::enableExceptions() && !saveDirectoryFromExceptions.isEmpty())
591 list.append(saveDirectoryFromExceptions);
593 TransferGroup * group = KGet::m_transferTreeModel->findGroup(groupname);
595 if (!group->defaultFolder().isEmpty())
596 list.append(group->defaultFolder());
598 if (Settings::useDefaultDirectory())
599 list.append(Settings::defaultDirectory());
601 if (!Settings::lastDirectory().isEmpty() &&
602 QString::compare(Settings::lastDirectory(), Settings::defaultDirectory()) != 0)
603 list.append(Settings::lastDirectory());
605 if (list.isEmpty())
606 list.append(QDir::homePath());//If we have no defaultDir, we return the home-dir
608 for (int i = 0; i < list.size(); i++)
610 list[i] = KUrl(list[i]).path();
612 return list;
615 void KGet::setGlobalDownloadLimit(int limit)
617 m_scheduler->setDownloadLimit(limit);
618 if (!limit)
619 m_scheduler->calculateDownloadLimit();
622 void KGet::setGlobalUploadLimit(int limit)
624 m_scheduler->setUploadLimit(limit);
625 if (!limit)
626 m_scheduler->calculateUploadLimit();
629 void KGet::calculateGlobalSpeedLimits()
631 if (m_scheduler->downloadLimit())//TODO: Remove this and the both other hacks in the 2 upper functions with a better replacement
632 m_scheduler->calculateDownloadLimit();
633 if (m_scheduler->uploadLimit())
634 m_scheduler->calculateUploadLimit();
637 void KGet::calculateGlobalDownloadLimit()
639 m_scheduler->calculateDownloadLimit();
642 void KGet::calculateGlobalUploadLimit()
644 m_scheduler->calculateUploadLimit();
647 // ------ STATIC MEMBERS INITIALIZATION ------
648 QList<ModelObserver *> KGet::m_observers;
649 TransferTreeModel * KGet::m_transferTreeModel;
650 TransferTreeSelectionModel * KGet::m_selectionModel;
651 QList<TransferFactory *> KGet::m_transferFactories;
652 TransferGroupScheduler * KGet::m_scheduler = new TransferGroupScheduler();
653 MainWindow * KGet::m_mainWindow = 0;
654 KUiServerJobs * KGet::m_jobManager = 0;
656 // ------ PRIVATE FUNCTIONS ------
657 KGet::KGet()
659 m_transferTreeModel = new TransferTreeModel(m_scheduler);
660 m_selectionModel = new TransferTreeSelectionModel(m_transferTreeModel);
662 //Load all the available plugins
663 loadPlugins();
665 //Create the default group
666 addGroup(i18n("My Downloads"));
669 KGet::~KGet()
671 delete m_scheduler;
674 bool KGet::createTransfer(const KUrl &src, const KUrl &dest, const QString& groupName,
675 bool start, const QDomElement * e)
677 kDebug(5001) << "srcUrl= " << src.url() << " "
678 << "destUrl= " << dest.url()
679 << "group= _" << groupName << "_" << endl;
681 TransferGroup * group = m_transferTreeModel->findGroup(groupName);
682 if (group==0)
684 kDebug(5001) << "KGet::createTransfer -> group not found";
685 group = m_transferTreeModel->transferGroups().first();
687 Transfer * newTransfer;
689 QList<TransferFactory *>::iterator it = m_transferFactories.begin();
690 QList<TransferFactory *>::iterator itEnd = m_transferFactories.end();
692 for( ; it!=itEnd ; ++it)
694 kDebug(5001) << "Trying plugin n.plugins=" << m_transferFactories.size();
695 if((newTransfer = (*it)->createTransfer(src, dest, group, m_scheduler, e)))
697 // kDebug(5001) << "KGet::createTransfer -> CREATING NEW TRANSFER ON GROUP: _" << group->name() << "_";
698 m_transferTreeModel->addTransfer(newTransfer, group);
700 if(start)
701 newTransfer->handler()->start();
703 if (newTransfer->percent() != 100) //Don't add a finished observer if the Transfer has already been finished
704 newTransfer->handler()->addObserver(new GenericTransferObserver());
706 return true;
709 kDebug(5001) << "Warning! No plugin found to handle the given url";
710 return false;
713 TransferDataSource * KGet::createTransferDataSource(const KUrl &src)
715 kDebug(5001);
716 QList<TransferFactory *>::iterator it = m_transferFactories.begin();
717 QList<TransferFactory *>::iterator itEnd = m_transferFactories.end();
719 TransferDataSource *dataSource;
720 for( ; it!=itEnd ; ++it)
722 dataSource = (*it)->createTransferDataSource(src);
723 if(dataSource)
724 return dataSource;
726 return 0;
729 void KGet::postAddedTransferGroupEvent(TransferGroup * group, ModelObserver * observer)
731 kDebug(5001);
732 if(observer)
734 observer->addedTransferGroupEvent(group->handler());
735 return;
738 QList<ModelObserver *>::iterator it = m_observers.begin();
739 QList<ModelObserver *>::iterator itEnd = m_observers.end();
741 for(; it!=itEnd; ++it)
743 kDebug(5001) << "message posted";
745 (*it)->addedTransferGroupEvent(group->handler());
749 void KGet::postRemovedTransferGroupEvent(TransferGroup * group, ModelObserver * observer)
751 if(observer)
753 observer->removedTransferGroupEvent(group->handler());
754 return;
757 QList<ModelObserver *>::iterator it = m_observers.begin();
758 QList<ModelObserver *>::iterator itEnd = m_observers.end();
760 for(; it!=itEnd; ++it)
762 (*it)->removedTransferGroupEvent(group->handler());
766 KUrl KGet::urlInputDialog()
768 QString newtransfer;
769 bool ok = false;
771 KUrl clipboardUrl = KUrl(QApplication::clipboard()->text(QClipboard::Clipboard).trimmed());
772 if (clipboardUrl.isValid())
773 newtransfer = clipboardUrl.url();
775 while (!ok)
777 newtransfer = KInputDialog::getText(i18n("New Download"), i18n("Enter URL:"), newtransfer, &ok, 0);
779 if (!ok)
781 //user pressed cancel
782 return KUrl();
785 KUrl src = KUrl(newtransfer);
786 if(src.isValid())
787 return src;
788 else
789 ok = false;
791 return KUrl();
794 QString KGet::destInputDialog()
796 QString destDir = KFileDialog::getExistingDirectory(Settings::lastDirectory());
798 Settings::setLastDirectory( destDir );
799 return destDir;
802 QString KGet::getSaveDirectoryFromExceptions(const KUrl &filename)
804 QString destDir;
806 const QStringList list = Settings::extensionsFolderList();
807 QStringList::ConstIterator it = list.begin();
808 const QStringList::ConstIterator end = list.end();
809 while (it != end) {
810 // odd list items are regular expressions for extensions
811 QString ext = *it;
812 ++it;
813 QString path = *it;
814 ++it;
816 if (!ext.startsWith('*'))
817 ext = '*' + ext;
819 QRegExp rexp(ext);
820 rexp.setPatternSyntax(QRegExp::Wildcard);
822 if (rexp.exactMatch(filename.url())) {
823 destDir = path;
824 break;
828 return KUrl(destDir).path();
831 bool KGet::isValidSource(const KUrl &source)
833 // Check if the URL is well formed
834 if (!source.isValid())
836 KMessageBox::error(0,
837 i18n("Malformed URL:\n%1", source.prettyUrl()),
838 i18n("Error"));
840 return false;
842 // Check if the URL contains the protocol
843 if ( source.protocol().isEmpty() ){
845 KMessageBox::error(0, i18n("Malformed URL, protocol missing:\n%1", source.prettyUrl()),
846 i18n("Error"));
848 return false;
850 // Check if a transfer with the same url already exists
851 Transfer * transfer = m_transferTreeModel->findTransfer( source );
852 if ( transfer )
854 if ( transfer->status() == Job::Finished )
856 // transfer is finished, ask if we want to download again
857 if (KMessageBox::questionYesNoCancel(0,
858 i18n("URL already saved:\n%1\nDownload again?", source.prettyUrl()),
859 i18n("Download URL again?"), KStandardGuiItem::yes(),
860 KStandardGuiItem::no(), KStandardGuiItem::cancel(), "QuestionUrlAlreadySaved" )
861 == KMessageBox::Yes)
863 transfer->stop();
864 TransferHandler * th = transfer->handler();
865 KGet::delTransfer(th);
866 return true;
869 else
871 //Transfer is already in list and not finished, ...
872 return false;
874 return false;
876 return true;
879 bool KGet::isValidDestDirectory(const QString & destDir)
881 kDebug(5001) << destDir;
882 if (!QFileInfo(destDir).isDir())
884 if (QFileInfo(KUrl(destDir).directory()).isWritable())
885 return (!destDir.isEmpty());
886 if (!QFileInfo(KUrl(destDir).directory()).isWritable() && !destDir.isEmpty())
887 KMessageBox::error(0, i18n("Directory is not writable"));
889 else
891 if (QFileInfo(destDir).isWritable())
892 return (!destDir.isEmpty());
893 if (!QFileInfo(destDir).isWritable() && !destDir.isEmpty())
894 KMessageBox::error(0, i18n("Directory is not writable"));
896 return false;
899 bool KGet::isValidDestUrl(const KUrl &destUrl)
901 if(KIO::NetAccess::exists(destUrl, KIO::NetAccess::DestinationSide, 0))
903 if (KMessageBox::warningYesNoCancel(0,
904 i18n("Destination file \n%1\nalready exists.\n"
905 "Do you want to overwrite it?", destUrl.prettyUrl()))
906 == KMessageBox::Yes)
908 safeDeleteFile( destUrl );
909 return true;
911 else
912 return false;
914 if (m_transferTreeModel->findTransferByDestination(destUrl) || destUrl.isEmpty())
915 return false;
917 return true;
919 KIO::open_RenameDlg(i18n("File already exists"),
920 (*it).url(), destUrl.url(),
921 KIO::M_MULTI);
925 KUrl KGet::getValidDestUrl(const QString& destDir, const KUrl &srcUrl)
927 if ( !isValidDestDirectory(destDir) )
928 return KUrl();
930 // create a proper destination file from destDir
931 KUrl destUrl = KUrl( destDir );
932 QString filename = srcUrl.fileName();
934 if ( filename.isEmpty() )
936 // simply use the full url as filename
937 filename = KUrl::toPercentEncoding( srcUrl.prettyUrl(), "/" );
938 kDebug(5001) << " Filename is empty. Setting to " << filename;
939 kDebug(5001) << " srcUrl = " << srcUrl.url();
940 kDebug(5001) << " prettyUrl = " << srcUrl.prettyUrl();
942 if (QFileInfo(destUrl.path()).isDir())
944 kDebug(5001) << " Filename is not empty";
945 destUrl.adjustPath( KUrl::AddTrailingSlash );
946 destUrl.setFileName( filename );
948 if (!isValidDestUrl(destUrl))
950 kDebug(5001) << " destUrl " << destUrl.path() << " is not valid";
951 return KUrl();
953 return destUrl;
956 void KGet::loadPlugins()
958 m_transferFactories.clear();
959 // Add versioning constraint
960 QString
961 str = "[X-KDE-KGet-framework-version] == ";
962 str += QString::number( FrameworkVersion );
963 str += " and ";
964 str += "[X-KDE-KGet-rank] > 0";
965 str += " and ";
966 str += "[X-KDE-KGet-plugintype] == ";
968 KService::List offers;
970 //TransferFactory plugins
971 offers = KServiceTypeTrader::self()->query( "KGet/Plugin", str + "'TransferFactory'" );
973 //Here we use a QMap only to easily sort the plugins by rank
974 QMap<int, KService::Ptr> services;
975 QMap<int, KService::Ptr>::iterator it;
977 for ( int i = 0; i < offers.count(); ++i )
979 services[ offers[i]->property( "X-KDE-KGet-rank" ).toInt() ] = offers[i];
980 kDebug(5001) << " TransferFactory plugin found:" << endl <<
981 " rank = " << offers[i]->property( "X-KDE-KGet-rank" ).toInt() << endl <<
982 " plugintype = " << offers[i]->property( "X-KDE-KGet-plugintype" ) << endl;
985 //I must fill this pluginList before and my m_transferFactories list after.
986 //This because calling the KLibLoader::globalLibrary() erases the static
987 //members of this class (why?), such as the m_transferFactories list.
988 QList<KGetPlugin *> pluginList;
990 KConfigGroup plugins = KConfigGroup(KGlobal::config(), "Plugins");
992 for( it = services.begin(); it != services.end(); ++it )
994 KPluginInfo info(*it);
995 info.load(plugins);
997 if( !info.isPluginEnabled() ) {
998 kDebug(5001) << "TransferFactory plugin (" << (*it)->library()
999 << ") found, but not enabled";
1000 continue;
1003 KGetPlugin * plugin;
1004 if( (plugin = createPluginFromService(*it)) != 0 )
1006 QString pluginName = info.name();
1008 pluginList.prepend(plugin);
1009 kDebug(5001) << "TransferFactory plugin (" << (*it)->library()
1010 << ") found and added to the list of available plugins";
1013 else
1014 kDebug(5001) << "Error loading TransferFactory plugin ("
1015 << (*it)->library() << ")";
1018 QList<KGetPlugin *>::iterator it2 = pluginList.begin();
1019 QList<KGetPlugin *>::iterator it2End = pluginList.end();
1021 for( ; it2!=it2End ; ++it2 )
1022 m_transferFactories.append( qobject_cast<TransferFactory *>(*it2) );
1024 kDebug(5001) << "Number of factories = " << m_transferFactories.size();
1027 KGetPlugin * KGet::createPluginFromService( const KService::Ptr &service )
1029 //try to load the specified library
1030 KPluginFactory *factory = KPluginLoader(service->library()).factory();
1032 if (!factory)
1034 KMessageBox::error(0, i18n("<html><p>Plugin loader could not load the plugin:<br/><i>%1</i></p></html>",
1035 service->library()));
1036 kError(5001) << "KPluginFactory could not load the plugin:" << service->library();
1037 return 0;
1039 KGetPlugin * plugin = factory->create< TransferFactory >(KGet::m_mainWindow);
1041 return plugin;
1044 bool KGet::safeDeleteFile( const KUrl& url )
1046 if ( url.isLocalFile() )
1048 QFileInfo info( url.path() );
1049 if ( info.isDir() )
1051 KGet::showNotification(m_mainWindow, KNotification::Notification,
1052 i18n("Not deleting\n%1\nas it is a directory.", url.prettyUrl()),
1053 "dialog-info");
1054 return false;
1056 KIO::NetAccess::del( url, 0L );
1057 return true;
1060 else
1061 KGet::showNotification(m_mainWindow, KNotification::Notification,
1062 i18n("Not deleting\n%1\nas it is not a local file.", url.prettyUrl()),
1063 "dialog-info");
1064 return false;
1067 void KGet::showNotification(QWidget *parent, KNotification::StandardEvent eventId,
1068 const QString &text, const QString &icon)
1070 KNotification::event(eventId, text, KIcon(icon).pixmap(KIconLoader::Small), parent);
1073 GenericModelObserver::GenericModelObserver(QObject *parent) : QObject(parent)
1075 m_groupObserver = new GenericTransferGroupObserver();
1078 GenericModelObserver::~GenericModelObserver()
1080 delete m_groupObserver;
1083 void GenericModelObserver::addedTransferGroupEvent(TransferGroupHandler * group)
1085 Q_UNUSED(group)
1086 kDebug() << "OBSERVER :: Adding group " << group;
1087 group->addObserver(m_groupObserver);
1089 // we need to do this to add the genericTransfer to all the transfers under the group
1090 m_groupObserver->addTransferGroup(group);
1092 KGet::save();
1095 void GenericModelObserver::removedTransferGroupEvent(TransferGroupHandler * group)
1097 Q_UNUSED(group)
1098 group->delObserver(m_groupObserver);
1099 KGet::save();