You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
835 lines
22 KiB
835 lines
22 KiB
/*
|
|
* This file is part of the KFTPGrabber project
|
|
*
|
|
* Copyright (C) 2003-2004 by the KFTPGrabber developers
|
|
* Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 program is distributed in the hope that it will be useful, but
|
|
* is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
|
|
* warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
|
|
* NON-INFRINGEMENT. See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston,
|
|
* MA 02110-1301, USA.
|
|
*
|
|
* In addition, as a special exception, the copyright holders give
|
|
* permission to link the code of portions of this program with the
|
|
* OpenSSL library under certain conditions as described in each
|
|
* individual source file, and distribute linked combinations
|
|
* including the two.
|
|
* You must obey the GNU General Public License in all respects
|
|
* for all of the code used other than OpenSSL. If you modify
|
|
* file(s) with this exception, you may extend this exception to your
|
|
* version of the file(s), but you are not obligated to do so. If you
|
|
* do not wish to do so, delete this exception statement from your
|
|
* version. If you delete this exception statement from all source
|
|
* files in the program, then also delete it here.
|
|
*/
|
|
|
|
#include <math.h>
|
|
|
|
#include "kftpqueue.h"
|
|
#include "kftpbookmarks.h"
|
|
#include "widgets/systemtray.h"
|
|
#include "kftpqueueprocessor.h"
|
|
#include "kftpsession.h"
|
|
|
|
#include "misc/kftpconfig.h"
|
|
#include "misc/filter.h"
|
|
|
|
#include <tdemessagebox.h>
|
|
#include <tdelocale.h>
|
|
#include <tdeio/renamedlg.h>
|
|
#include <kdiskfreesp.h>
|
|
#include <tdefileitem.h>
|
|
#include <kopenwith.h>
|
|
#include <kstaticdeleter.h>
|
|
#include <kservice.h>
|
|
#include <kuserprofile.h>
|
|
#include <kstandarddirs.h>
|
|
#include <krun.h>
|
|
#include <kmdcodec.h>
|
|
|
|
#include <ntqapplication.h>
|
|
#include <ntqregexp.h>
|
|
#include <ntqobjectlist.h>
|
|
#include <ntqfile.h>
|
|
|
|
using namespace KFTPEngine;
|
|
using namespace KFTPCore::Filter;
|
|
|
|
namespace KFTPQueue {
|
|
|
|
OpenedFile::OpenedFile(TransferFile *transfer)
|
|
: m_source(transfer->getSourceUrl()),
|
|
m_dest(transfer->getDestUrl()),
|
|
m_hash(TQString::null)
|
|
{
|
|
// Calculate the file's MD5 hash
|
|
TQFile file(m_dest.path());
|
|
if (!file.open(IO_ReadOnly)) {
|
|
return;
|
|
}
|
|
|
|
KMD5 context;
|
|
if (context.update(file))
|
|
m_hash = TQString(context.hexDigest());
|
|
file.close();
|
|
}
|
|
|
|
bool OpenedFile::hasChanged()
|
|
{
|
|
// Compare the file's MD5 hash with stored value
|
|
TQFile file(m_dest.path());
|
|
if (!file.open(IO_ReadOnly)) {
|
|
return false;
|
|
}
|
|
|
|
TQString tmp = TQString::null;
|
|
KMD5 context;
|
|
if (context.update(file))
|
|
tmp = TQString(context.hexDigest());
|
|
file.close();
|
|
|
|
return tmp != m_hash;
|
|
}
|
|
|
|
UserDialogRequest::UserDialogRequest(TransferFile *transfer, filesize_t srcSize, time_t srcTime,
|
|
filesize_t dstSize, time_t dstTime)
|
|
: m_transfer(transfer),
|
|
m_srcSize(srcSize),
|
|
m_srcTime(srcTime),
|
|
m_dstSize(dstSize),
|
|
m_dstTime(dstTime)
|
|
{
|
|
}
|
|
|
|
void UserDialogRequest::sendResponse(FileExistsWakeupEvent *event)
|
|
{
|
|
m_transfer->wakeup(event);
|
|
delete this;
|
|
}
|
|
|
|
Manager *Manager::m_self = 0;
|
|
static KStaticDeleter<Manager> staticManagerDeleter;
|
|
|
|
Manager *Manager::self()
|
|
{
|
|
if (!m_self) {
|
|
staticManagerDeleter.setObject(m_self, new Manager());
|
|
}
|
|
|
|
return m_self;
|
|
}
|
|
|
|
Manager::Manager()
|
|
: m_topLevel(new QueueObject(this, QueueObject::Toplevel)),
|
|
m_processingQueue(false),
|
|
m_feDialogOpen(false),
|
|
m_defaultFeAction(FE_DISABLE_ACT)
|
|
{
|
|
m_topLevel->setId(0);
|
|
|
|
m_lastTQID = 1;
|
|
m_curDownSpeed = 0;
|
|
m_curUpSpeed = 0;
|
|
|
|
m_emitUpdate = true;
|
|
|
|
// Create the queue processor object
|
|
m_queueProc = new KFTPQueueProcessor(this);
|
|
|
|
connect(m_queueProc, SIGNAL(queueComplete()), this, SLOT(slotQueueProcessingComplete()));
|
|
connect(m_queueProc, SIGNAL(queueAborted()), this, SLOT(slotQueueProcessingAborted()));
|
|
|
|
// Create the queue converter object
|
|
m_converter = new KFTPQueueConverter(this);
|
|
}
|
|
|
|
Manager::~Manager()
|
|
{
|
|
if (m_self == this)
|
|
staticManagerDeleter.setObject(m_self, 0, false);
|
|
}
|
|
|
|
void Manager::stopAllTransfers()
|
|
{
|
|
if (isProcessing()) {
|
|
abort();
|
|
} else {
|
|
QueueObject *i;
|
|
TQPtrList<QueueObject> sites = topLevelObject()->getChildrenList();
|
|
|
|
for (i = sites.first(); i; i = sites.next()) {
|
|
if (i->isRunning()) {
|
|
i->abort();
|
|
} else {
|
|
QueueObject *t;
|
|
TQPtrList<QueueObject> list = i->getChildrenList();
|
|
|
|
for (t = list.first(); t; t = list.next()) {
|
|
if (t->isRunning())
|
|
t->abort();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Transfer *Manager::findTransfer(long id)
|
|
{
|
|
// First try the cache
|
|
QueueObject *object = m_queueObjectCache[TQString::number(id)];
|
|
|
|
if (!object) {
|
|
object = m_topLevel->findChildObject(id);
|
|
m_queueObjectCache.insert(TQString::number(id), object);
|
|
}
|
|
|
|
return static_cast<Transfer*>(object);
|
|
}
|
|
|
|
Site *Manager::findSite(KURL url, bool noCreate)
|
|
{
|
|
// Reset path
|
|
url.setPath("/");
|
|
|
|
if (url.isLocalFile())
|
|
return NULL;
|
|
|
|
// Find the appropriate site and if one doesn't exist create a new one
|
|
QueueObject *i;
|
|
TQPtrList<QueueObject> sites = topLevelObject()->getChildrenList();
|
|
|
|
for (i = sites.first(); i; i = sites.next()) {
|
|
if (i->getType() == QueueObject::Site) {
|
|
Site *site = static_cast<Site*>(i);
|
|
|
|
if (site->getUrl() == url)
|
|
return site;
|
|
}
|
|
}
|
|
|
|
// The site doesn't exist, let's create one
|
|
if (!noCreate) {
|
|
Site *site = new Site(topLevelObject(), url);
|
|
site->setId(m_lastTQID++);
|
|
emit newSite(site);
|
|
|
|
return site;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void Manager::insertTransfer(Transfer *transfer)
|
|
{
|
|
// Set id
|
|
transfer->setId(m_lastTQID++);
|
|
|
|
// Reparent transfer
|
|
filesize_t size = transfer->getSize();
|
|
transfer->addSize(-size);
|
|
|
|
if (transfer->hasParentObject())
|
|
transfer->parentObject()->delChildObject(transfer);
|
|
|
|
if (transfer->parent())
|
|
transfer->parent()->removeChild(transfer);
|
|
|
|
Site *site = 0;
|
|
|
|
switch (transfer->getTransferType()) {
|
|
case Download: site = findSite(transfer->getSourceUrl()); break;
|
|
case Upload: site = findSite(transfer->getDestUrl()); break;
|
|
case FXP: site = findSite(transfer->getSourceUrl()); break;
|
|
}
|
|
|
|
site->insertChild(transfer);
|
|
site->addChildObject(transfer);
|
|
transfer->addSize(size);
|
|
|
|
emit newTransfer(transfer);
|
|
|
|
if (m_emitUpdate)
|
|
emit queueUpdate();
|
|
}
|
|
|
|
void Manager::insertTransfer(KURLDrag *drag)
|
|
{
|
|
// Decode the drag
|
|
TDEIO::MetaData p_meta;
|
|
KURL::List p_urls;
|
|
KURLDrag::decode(drag, p_urls, p_meta);
|
|
|
|
// TODO make support for local drops - eg. from konqueror, where
|
|
// we get no meta data, so we must get the file info ourselves and
|
|
// reject remote urls (or show a dialog to ask the user if he
|
|
// wants to connect to the remote site)
|
|
|
|
// Now we should add transfers for all URLs
|
|
Transfer *lastTransfer = 0L;
|
|
KURL::List::iterator end(p_urls.end());
|
|
|
|
for (KURL::List::iterator i(p_urls.begin()); i != end; ++i) {
|
|
TQString p_data = p_meta[(*i).htmlURL().local8Bit()];
|
|
TQChar type = p_data.at(0);
|
|
filesize_t size = p_data.section(':', 1, 1).toULongLong();
|
|
KURL sourceUrl = (*i);
|
|
KURL destinationUrl = KURL(p_meta["DestURL"]);
|
|
destinationUrl.addPath(sourceUrl.fileName());
|
|
|
|
// Skip where both files are local
|
|
if (sourceUrl.isLocalFile() && destinationUrl.isLocalFile())
|
|
continue;
|
|
|
|
lastTransfer = spawnTransfer(sourceUrl, destinationUrl, size, type == 'D', true, true, 0L, true);
|
|
}
|
|
|
|
// Execute the transfer if set in configuration
|
|
if (!KFTPCore::Config::queueOnDND() && lastTransfer)
|
|
static_cast<KFTPQueue::Site*>(lastTransfer->parentObject())->delayedExecute();
|
|
}
|
|
|
|
Transfer *Manager::spawnTransfer(KURL sourceUrl, KURL destinationUrl, filesize_t size, bool dir, bool ignoreSkip,
|
|
bool insertToQueue, TQObject *parent, bool noScan)
|
|
{
|
|
const ActionChain *actionChain = Filters::self()->process(sourceUrl, size, dir);
|
|
|
|
if (!ignoreSkip && (actionChain && actionChain->getAction(Action::Skip)))
|
|
return 0;
|
|
|
|
// Determine transfer type
|
|
TransferType type;
|
|
|
|
if (sourceUrl.isLocalFile())
|
|
type = Upload;
|
|
else if (destinationUrl.isLocalFile())
|
|
type = Download;
|
|
else
|
|
type = FXP;
|
|
|
|
// Should we lowercase the destination path ?
|
|
if (actionChain && actionChain->getAction(Action::Lowercase))
|
|
destinationUrl.setPath(destinationUrl.directory() + "/" + destinationUrl.fileName().lower());
|
|
|
|
// Reset a possible preconfigured default action
|
|
setDefaultFileExistsAction();
|
|
|
|
if (!parent)
|
|
parent = this;
|
|
|
|
Transfer *transfer = 0L;
|
|
|
|
if (dir)
|
|
transfer = new TransferDir(parent);
|
|
else {
|
|
transfer = new TransferFile(parent);
|
|
transfer->addSize(size);
|
|
}
|
|
|
|
transfer->setSourceUrl(sourceUrl);
|
|
transfer->setDestUrl(destinationUrl);
|
|
transfer->setTransferType(type);
|
|
|
|
if (insertToQueue) {
|
|
insertTransfer(transfer);
|
|
} else {
|
|
transfer->setId(m_lastTQID++);
|
|
emit newTransfer(transfer);
|
|
}
|
|
|
|
if (dir && !noScan) {
|
|
// This is a directory, we should scan the directory and add all files/dirs found
|
|
// as parent of current object
|
|
KFTPSession::Session *session = KFTPSession::Manager::self()->spawnRemoteSession(KFTPSession::IgnoreSide, sourceUrl, 0, true);
|
|
session->scanDirectory(transfer);
|
|
}
|
|
|
|
return transfer;
|
|
}
|
|
|
|
void Manager::removeTransfer(Transfer *transfer, bool abortSession)
|
|
{
|
|
if (!transfer)
|
|
return;
|
|
|
|
transfer->abort();
|
|
long id = transfer->getId();
|
|
long sid = transfer->parentObject()->getId();
|
|
|
|
// Remove transfer from cache
|
|
m_queueObjectCache.remove(TQString::number(id));
|
|
|
|
// Should the site be removed as well ?
|
|
QueueObject *site = 0;
|
|
if (transfer->parentObject()->getType() == QueueObject::Site && transfer->parentObject()->getChildrenList().count() == 1)
|
|
site = transfer->parentObject();
|
|
|
|
// Signal destruction & delete transfer
|
|
transfer->faceDestruction(abortSession);
|
|
delete transfer;
|
|
|
|
if (site) {
|
|
delete site;
|
|
emit siteRemoved(sid);
|
|
}
|
|
|
|
emit transferRemoved(id);
|
|
|
|
if (m_emitUpdate)
|
|
emit queueUpdate();
|
|
}
|
|
|
|
void Manager::revalidateTransfer(Transfer *transfer)
|
|
{
|
|
QueueObject *i = transfer;
|
|
|
|
while (i) {
|
|
if (i->parentObject() == topLevelObject())
|
|
break;
|
|
|
|
i = i->parentObject();
|
|
}
|
|
|
|
// We have the site
|
|
Site *curSite = static_cast<Site*>(i);
|
|
Site *site = 0;
|
|
|
|
switch (transfer->getTransferType()) {
|
|
case Download: site = findSite(transfer->getSourceUrl()); break;
|
|
case Upload: site = findSite(transfer->getDestUrl()); break;
|
|
case FXP: site = findSite(transfer->getSourceUrl()); break;
|
|
}
|
|
|
|
// If the sites don't match, reparent transfer
|
|
if (site != curSite) {
|
|
transfer->parentObject()->delChildObject(transfer);
|
|
transfer->parent()->removeChild(transfer);
|
|
|
|
site->insertChild(transfer);
|
|
site->addChildObject(transfer);
|
|
|
|
emit transferRemoved(transfer->getId());
|
|
emit newTransfer(transfer);
|
|
|
|
if (curSite->getChildrenList().count() == 0) {
|
|
emit siteRemoved(curSite->getId());
|
|
curSite->deleteLater();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Manager::removeFailedTransfer(FailedTransfer *transfer)
|
|
{
|
|
// Remove the transfer and signal removal
|
|
m_failedTransfers.remove(transfer);
|
|
emit failedTransferRemoved(transfer->getTransfer()->getId());
|
|
|
|
delete transfer;
|
|
}
|
|
|
|
void Manager::clearFailedTransferList()
|
|
{
|
|
// Clear the failed transfers list
|
|
FailedTransfer *transfer;
|
|
TQPtrListIterator<KFTPQueue::FailedTransfer> i(m_failedTransfers);
|
|
|
|
while ((transfer = i.current()) != 0) {
|
|
++i;
|
|
removeFailedTransfer(transfer);
|
|
}
|
|
}
|
|
|
|
void Manager::moveTransferUp(QueueObject *object)
|
|
{
|
|
object->parentObject()->moveChildUp(object);
|
|
|
|
if (m_emitUpdate)
|
|
emit queueUpdate();
|
|
}
|
|
|
|
void Manager::moveTransferDown(QueueObject *object)
|
|
{
|
|
object->parentObject()->moveChildDown(object);
|
|
|
|
if (m_emitUpdate)
|
|
emit queueUpdate();
|
|
}
|
|
|
|
void Manager::moveTransferTop(QueueObject *object)
|
|
{
|
|
object->parentObject()->moveChildTop(object);
|
|
|
|
if (m_emitUpdate)
|
|
emit queueUpdate();
|
|
}
|
|
|
|
void Manager::moveTransferBottom(QueueObject *object)
|
|
{
|
|
object->parentObject()->moveChildBottom(object);
|
|
|
|
if (m_emitUpdate)
|
|
emit queueUpdate();
|
|
}
|
|
|
|
bool Manager::canBeMovedUp(QueueObject *object)
|
|
{
|
|
return object ? object->parentObject()->canMoveChildUp(object) : false;
|
|
}
|
|
|
|
bool Manager::canBeMovedDown(QueueObject *object)
|
|
{
|
|
return object ? object->parentObject()->canMoveChildDown(object) : false;
|
|
}
|
|
|
|
void Manager::doEmitUpdate()
|
|
{
|
|
m_curDownSpeed = 0;
|
|
m_curUpSpeed = 0;
|
|
|
|
topLevelObject()->removeMarkedTransfers();
|
|
|
|
// Get download/upload speeds
|
|
QueueObject *i;
|
|
TQPtrList<QueueObject> sites = topLevelObject()->getChildrenList();
|
|
|
|
for (i = sites.first(); i; i = sites.next()) {
|
|
QueueObject *t;
|
|
TQPtrList<QueueObject> list = i->getChildrenList();
|
|
|
|
for (t = list.first(); t; t = list.next()) {
|
|
KFTPQueue::Transfer *tmp = static_cast<Transfer*>(t);
|
|
|
|
switch (tmp->getTransferType()) {
|
|
case Download: m_curDownSpeed += tmp->getSpeed(); break;
|
|
case Upload: m_curUpSpeed += tmp->getSpeed(); break;
|
|
case FXP: {
|
|
m_curDownSpeed += tmp->getSpeed();
|
|
m_curUpSpeed += tmp->getSpeed();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Emit global update to all GUI objects
|
|
emit queueUpdate();
|
|
}
|
|
|
|
void Manager::start()
|
|
{
|
|
if (m_processingQueue)
|
|
return;
|
|
|
|
m_processingQueue = true;
|
|
|
|
// Now, go trough all queued files and execute them - try to do as little server connects
|
|
// as possible
|
|
m_queueProc->startProcessing();
|
|
}
|
|
|
|
void Manager::abort()
|
|
{
|
|
m_processingQueue = false;
|
|
|
|
// Stop further queue processing
|
|
m_queueProc->stopProcessing();
|
|
|
|
emit queueUpdate();
|
|
}
|
|
|
|
void Manager::slotQueueProcessingComplete()
|
|
{
|
|
m_processingQueue = false;
|
|
|
|
// Queue processing is now complete
|
|
if (KFTPCore::Config::showBalloons())
|
|
KFTPWidgets::SystemTray::self()->showBalloon(i18n("All queued transfers have been completed."));
|
|
|
|
emit queueUpdate();
|
|
}
|
|
|
|
void Manager::slotQueueProcessingAborted()
|
|
{
|
|
m_processingQueue = false;
|
|
}
|
|
|
|
void Manager::clearQueue()
|
|
{
|
|
QueueObject *i;
|
|
TQPtrList<QueueObject> sites = topLevelObject()->getChildrenList();
|
|
|
|
for (i = sites.first(); i; i = sites.next()) {
|
|
QueueObject *t;
|
|
TQPtrList<QueueObject> list = i->getChildrenList();
|
|
|
|
for (t = list.first(); t; t = list.next())
|
|
removeTransfer(static_cast<Transfer*>(t));
|
|
}
|
|
}
|
|
|
|
int Manager::getTransferPercentage()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int Manager::getNumRunning(bool onlyDirs)
|
|
{
|
|
int running = 0;
|
|
|
|
QueueObject *i;
|
|
TQPtrList<QueueObject> sites = topLevelObject()->getChildrenList();
|
|
|
|
for (i = sites.first(); i; i = sites.next()) {
|
|
QueueObject *t;
|
|
TQPtrList<QueueObject> list = i->getChildrenList();
|
|
|
|
for (t = list.first(); t; t = list.next()) {
|
|
if (t->isRunning() && (!onlyDirs || t->isDir()))
|
|
running++;
|
|
}
|
|
|
|
if (i->isRunning())
|
|
running++;
|
|
}
|
|
|
|
return running;
|
|
}
|
|
|
|
int Manager::getNumRunning(const KURL &remoteUrl)
|
|
{
|
|
int running = 0;
|
|
Site *site = findSite(remoteUrl, true);
|
|
|
|
if (site) {
|
|
QueueObject *i;
|
|
TQPtrList<QueueObject> transfers = site->getChildrenList();
|
|
|
|
for (i = transfers.first(); i; i = transfers.next()) {
|
|
if (i->isRunning())
|
|
running++;
|
|
}
|
|
}
|
|
|
|
return running;
|
|
}
|
|
|
|
KFTPEngine::FileExistsWakeupEvent *Manager::fileExistsAction(TransferFile *transfer,
|
|
TQValueList<KFTPEngine::DirectoryEntry> stat)
|
|
{
|
|
FileExistsWakeupEvent *event = new FileExistsWakeupEvent();
|
|
FileExistsActions *fa = NULL;
|
|
FEAction action;
|
|
|
|
filesize_t srcSize = 0;
|
|
time_t srcTime = 0;
|
|
|
|
filesize_t dstSize = 0;
|
|
time_t dstTime = 0;
|
|
|
|
// Check if there is a default action set
|
|
action = getDefaultFileExistsAction();
|
|
|
|
if (action == FE_DISABLE_ACT) {
|
|
switch (transfer->getTransferType()) {
|
|
case KFTPQueue::Download: {
|
|
KFileItem info(KFileItem::Unknown, KFileItem::Unknown, transfer->getDestUrl());
|
|
dstSize = info.size();
|
|
dstTime = info.time(TDEIO::UDS_MODIFICATION_TIME);
|
|
|
|
srcSize = stat[0].size();
|
|
srcTime = stat[0].time();
|
|
|
|
fa = KFTPCore::Config::self()->dActions();
|
|
break;
|
|
}
|
|
case KFTPQueue::Upload: {
|
|
KFileItem info(KFileItem::Unknown, KFileItem::Unknown, transfer->getSourceUrl());
|
|
srcSize = info.size();
|
|
srcTime = info.time(TDEIO::UDS_MODIFICATION_TIME);
|
|
|
|
dstSize = stat[0].size();
|
|
dstTime = stat[0].time();
|
|
|
|
fa = KFTPCore::Config::self()->uActions();
|
|
break;
|
|
}
|
|
case KFTPQueue::FXP: {
|
|
srcSize = stat[0].size();
|
|
srcTime = stat[0].time();
|
|
|
|
dstSize = stat[1].size();
|
|
dstTime = stat[1].time();
|
|
|
|
fa = KFTPCore::Config::self()->fActions();
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Now that we have all data, get the action and do it
|
|
action = fa->getActionForSituation(srcSize, srcTime, dstSize, dstTime);
|
|
}
|
|
|
|
switch (action) {
|
|
default:
|
|
case FE_SKIP_ACT: event->action = FileExistsWakeupEvent::Skip; break;
|
|
case FE_OVERWRITE_ACT: event->action = FileExistsWakeupEvent::Overwrite; break;
|
|
case FE_RESUME_ACT: event->action = FileExistsWakeupEvent::Resume; break;
|
|
case FE_RENAME_ACT:
|
|
case FE_USER_ACT: {
|
|
appendUserDialogRequest(new UserDialogRequest(transfer, srcSize, srcTime, dstSize, dstTime));
|
|
|
|
// Event shall be deferred
|
|
delete event;
|
|
event = 0;
|
|
}
|
|
}
|
|
|
|
return event;
|
|
}
|
|
|
|
void Manager::appendUserDialogRequest(UserDialogRequest *request)
|
|
{
|
|
m_userDialogRequests.append(request);
|
|
|
|
if (m_userDialogRequests.count() == 1) {
|
|
processUserDialogRequest();
|
|
}
|
|
}
|
|
|
|
void Manager::processUserDialogRequest()
|
|
{
|
|
UserDialogRequest *request = m_userDialogRequests.getFirst();
|
|
if (!request)
|
|
return;
|
|
|
|
FEAction action = getDefaultFileExistsAction();
|
|
FileExistsWakeupEvent *event = new FileExistsWakeupEvent();
|
|
|
|
if (action == FE_DISABLE_ACT || action == FE_USER_ACT) {
|
|
// A dialog really needs to be displayed
|
|
TransferFile *transfer = request->getTransfer();
|
|
|
|
TQString newDestPath;
|
|
TDEIO::RenameDlg_Result r = TDEIO::open_RenameDlg(
|
|
i18n("File Exists"),
|
|
transfer->getSourceUrl().prettyURL(),
|
|
transfer->getDestUrl().prettyURL(),
|
|
(TDEIO::RenameDlg_Mode) (TDEIO::M_OVERWRITE | TDEIO::M_RESUME | TDEIO::M_SKIP | TDEIO::M_MULTI),
|
|
newDestPath,
|
|
request->sourceSize(),
|
|
request->destinationSize(),
|
|
request->sourceTime(),
|
|
request->destinationTime()
|
|
);
|
|
|
|
switch (r) {
|
|
case TDEIO::R_RENAME: {
|
|
KURL url = transfer->getDestUrl();
|
|
url.setPath(newDestPath);
|
|
transfer->setDestUrl(url);
|
|
|
|
event->action = FileExistsWakeupEvent::Rename;
|
|
event->newFileName = newDestPath;
|
|
break;
|
|
}
|
|
case TDEIO::R_CANCEL: {
|
|
// Abort queue processing
|
|
abort();
|
|
transfer->abort();
|
|
|
|
// An event is not required, since we will not be recalling the process
|
|
delete event;
|
|
event = 0;
|
|
break;
|
|
}
|
|
case TDEIO::R_AUTO_SKIP: setDefaultFileExistsAction(FE_SKIP_ACT);
|
|
case TDEIO::R_SKIP: event->action = FileExistsWakeupEvent::Skip; break;
|
|
case TDEIO::R_RESUME_ALL: setDefaultFileExistsAction(FE_RESUME_ACT);
|
|
case TDEIO::R_RESUME: event->action = FileExistsWakeupEvent::Resume; break;
|
|
case TDEIO::R_OVERWRITE_ALL: setDefaultFileExistsAction(FE_OVERWRITE_ACT);
|
|
default: event->action = FileExistsWakeupEvent::Overwrite; break;
|
|
}
|
|
} else {
|
|
switch (action) {
|
|
default:
|
|
case FE_SKIP_ACT: event->action = FileExistsWakeupEvent::Skip; break;
|
|
case FE_OVERWRITE_ACT: event->action = FileExistsWakeupEvent::Overwrite; break;
|
|
case FE_RESUME_ACT: event->action = FileExistsWakeupEvent::Resume; break;
|
|
}
|
|
}
|
|
|
|
// Send a response to this request
|
|
request->sendResponse(event);
|
|
|
|
m_userDialogRequests.removeFirst();
|
|
|
|
if (!m_userDialogRequests.isEmpty())
|
|
processUserDialogRequest();
|
|
}
|
|
|
|
void Manager::openAfterTransfer(TransferFile *transfer)
|
|
{
|
|
TQString mimeType = KMimeType::findByURL(transfer->getDestUrl(), 0, true, true)->name();
|
|
KService::Ptr offer = KServiceTypeProfile::preferredService(mimeType, "Application");
|
|
|
|
if (!offer) {
|
|
KOpenWithDlg dialog(KURL::List(transfer->getDestUrl()));
|
|
|
|
if (dialog.exec() == TQDialog::Accepted) {
|
|
offer = dialog.service();
|
|
|
|
if (!offer)
|
|
offer = new KService("", dialog.text(), "");
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
|
|
TQStringList params = KRun::processDesktopExec(*offer, KURL::List(transfer->getDestUrl()), false);
|
|
TDEProcess *p = new TDEProcess(this);
|
|
*p << params;
|
|
|
|
connect(p, SIGNAL(processExited(TDEProcess*)), this, SLOT(slotEditProcessTerminated(TDEProcess*)));
|
|
|
|
p->start();
|
|
|
|
// Save the process
|
|
m_editProcessList.insert(p->pid(), OpenedFile(transfer));
|
|
}
|
|
|
|
void Manager::slotEditProcessTerminated(TDEProcess *p)
|
|
{
|
|
// A process has terminated, we should reupload
|
|
OpenedFile file = m_editProcessList[p->pid()];
|
|
|
|
// Only upload a file if it has been changed
|
|
if (file.hasChanged()) {
|
|
TransferFile *transfer = new TransferFile(KFTPQueue::Manager::self());
|
|
transfer->setSourceUrl(file.destination());
|
|
transfer->setDestUrl(file.source());
|
|
transfer->setTransferType(KFTPQueue::Upload);
|
|
transfer->addSize(KFileItem(KFileItem::Unknown, KFileItem::Unknown, file.destination()).size());
|
|
insertTransfer(transfer);
|
|
|
|
// Execute the transfer
|
|
transfer->delayedExecute();
|
|
}
|
|
|
|
// Cleanup
|
|
m_editProcessList.remove(p->pid());
|
|
p->deleteLater();
|
|
}
|
|
|
|
}
|
|
|
|
#include "kftpqueue.moc"
|