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.
921 lines
26 KiB
921 lines
26 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 "kftpsession.h"
|
|
#include "kftpapi.h"
|
|
#include "browser/detailsview.h"
|
|
#include "browser/treeview.h"
|
|
#include "browser/view.h"
|
|
#include "kftpbookmarks.h"
|
|
#include "misc.h"
|
|
#include "widgets/systemtray.h"
|
|
#include "mainactions.h"
|
|
|
|
#include "misc/kftpconfig.h"
|
|
#include "misc/filter.h"
|
|
|
|
#include <ntqdir.h>
|
|
#include <ntqobjectlist.h>
|
|
|
|
#include <tdemessagebox.h>
|
|
#include <tdelocale.h>
|
|
#include <kdebug.h>
|
|
#include <kpassdlg.h>
|
|
#include <kstaticdeleter.h>
|
|
|
|
using namespace KFTPGrabberBase;
|
|
using namespace KFTPEngine;
|
|
using namespace KFTPCore::Filter;
|
|
|
|
namespace KFTPSession {
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//////////////////////// Connection ///////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
Connection::Connection(Session *session, bool primary)
|
|
: TQObject(session),
|
|
m_primary(primary),
|
|
m_busy(false),
|
|
m_aborting(false),
|
|
m_scanning(false)
|
|
{
|
|
// Create the actual connection client
|
|
m_client = new KFTPEngine::Thread();
|
|
|
|
connect(m_client->eventHandler(), SIGNAL(engineEvent(KFTPEngine::Event*)), this, SLOT(slotEngineEvent(KFTPEngine::Event*)));
|
|
|
|
// If this is not a core session connection, connect
|
|
if (!primary) {
|
|
// Connect to the server
|
|
KURL url = session->getClient()->socket()->getCurrentUrl();
|
|
|
|
KFTPBookmarks::Manager::self()->setupClient(session->getSite(), m_client);
|
|
m_client->connect(url);
|
|
}
|
|
}
|
|
|
|
Connection::~Connection()
|
|
{
|
|
delete m_client;
|
|
}
|
|
|
|
bool Connection::isConnected()
|
|
{
|
|
return !static_cast<Session*>(parent())->isRemote() || m_client->socket()->isConnected();
|
|
}
|
|
|
|
void Connection::acquire(KFTPQueue::Transfer *transfer)
|
|
{
|
|
if (m_busy || !static_cast<Session*>(parent())->isRemote())
|
|
return;
|
|
|
|
m_curTransfer = transfer;
|
|
m_busy = true;
|
|
|
|
connect(transfer, SIGNAL(transferComplete(long)), this, SLOT(slotTransferCompleted()));
|
|
connect(transfer, SIGNAL(transferAbort(long)), this, SLOT(slotTransferCompleted()));
|
|
|
|
emit connectionAcquired();
|
|
}
|
|
|
|
void Connection::remove()
|
|
{
|
|
// Disconnect all signals from the transfer
|
|
if (m_curTransfer)
|
|
m_curTransfer->TQObject::disconnect(this);
|
|
|
|
m_curTransfer = 0L;
|
|
m_busy = false;
|
|
|
|
emit connectionRemoved();
|
|
emit static_cast<Session*>(parent())->freeConnectionAvailable();
|
|
}
|
|
|
|
void Connection::abort()
|
|
{
|
|
if (m_aborting || !m_client->socket()->isBusy())
|
|
return;
|
|
|
|
// Emit the signal before aborting
|
|
emit aborting();
|
|
|
|
// Abort transfer
|
|
m_aborting = true;
|
|
m_client->abort();
|
|
m_aborting = false;
|
|
}
|
|
|
|
void Connection::scanDirectory(KFTPQueue::Transfer *parent)
|
|
{
|
|
// Lock the connection and the transfer
|
|
acquire(parent);
|
|
parent->lock();
|
|
|
|
m_scanning = true;
|
|
|
|
if (isConnected())
|
|
m_client->scan(parent->getSourceUrl());
|
|
}
|
|
|
|
void Connection::addScannedDirectory(KFTPEngine::DirectoryTree *tree, KFTPQueue::Transfer *parent)
|
|
{
|
|
// Directories
|
|
DirectoryTree::DirIterator dirEnd = tree->directories()->end();
|
|
for (DirectoryTree::DirIterator i = tree->directories()->begin(); i != dirEnd; i++) {
|
|
KURL sourceUrlBase = parent->getSourceUrl();
|
|
KURL destUrlBase = parent->getDestUrl();
|
|
|
|
sourceUrlBase.addPath((*i)->info().filename());
|
|
destUrlBase.addPath((*i)->info().filename());
|
|
|
|
// Check if we should skip this entry
|
|
const ActionChain *actionChain = Filters::self()->process(sourceUrlBase, 0, true);
|
|
|
|
if (actionChain && actionChain->getAction(Action::Skip))
|
|
continue;
|
|
|
|
// Add directory transfer
|
|
KFTPQueue::TransferDir *transfer = new KFTPQueue::TransferDir(parent);
|
|
transfer->setSourceUrl(sourceUrlBase);
|
|
transfer->setDestUrl(destUrlBase);
|
|
transfer->setTransferType(parent->getTransferType());
|
|
transfer->setId(KFTPQueue::Manager::self()->nextTransferId());
|
|
|
|
emit KFTPQueue::Manager::self()->newTransfer(transfer);
|
|
|
|
addScannedDirectory(*i, transfer);
|
|
|
|
if (KFTPCore::Config::skipEmptyDirs() && !transfer->hasChildren())
|
|
KFTPQueue::Manager::self()->removeTransfer(transfer, false);
|
|
}
|
|
|
|
// Files
|
|
DirectoryTree::FileIterator fileEnd = tree->files()->end();
|
|
for (DirectoryTree::FileIterator i = tree->files()->begin(); i != fileEnd; i++) {
|
|
KURL sourceUrlBase = parent->getSourceUrl();
|
|
KURL destUrlBase = parent->getDestUrl();
|
|
|
|
sourceUrlBase.addPath((*i).filename());
|
|
destUrlBase.addPath((*i).filename());
|
|
|
|
// Check if we should skip this entry
|
|
const ActionChain *actionChain = Filters::self()->process(sourceUrlBase, (*i).size(), false);
|
|
|
|
if (actionChain && actionChain->getAction(Action::Skip))
|
|
continue;
|
|
|
|
// Add file transfer
|
|
KFTPQueue::TransferFile *transfer = new KFTPQueue::TransferFile(parent);
|
|
transfer->addSize((*i).size());
|
|
transfer->setSourceUrl(sourceUrlBase);
|
|
transfer->setDestUrl(destUrlBase);
|
|
transfer->setTransferType(parent->getTransferType());
|
|
transfer->setId(KFTPQueue::Manager::self()->nextTransferId());
|
|
|
|
emit KFTPQueue::Manager::self()->newTransfer(transfer);
|
|
}
|
|
}
|
|
|
|
void Connection::slotEngineEvent(KFTPEngine::Event *event)
|
|
{
|
|
switch (event->type()) {
|
|
case Event::EventDisconnect: {
|
|
emit connectionLost(this);
|
|
break;
|
|
}
|
|
case Event::EventConnect: {
|
|
emit connectionEstablished();
|
|
|
|
if (m_scanning) {
|
|
// Connected successfully, let's scan
|
|
m_client->scan(m_curTransfer->getSourceUrl());
|
|
}
|
|
break;
|
|
}
|
|
case Event::EventError: {
|
|
ErrorCode error = event->getParameter(0).asErrorCode();
|
|
|
|
if (m_scanning && (error == ConnectFailed || error == LoginFailed || error == OperationFailed)) {
|
|
// Scanning should be aborted, since there was an error
|
|
m_scanning = false;
|
|
m_curTransfer->unlock();
|
|
remove();
|
|
|
|
emit static_cast<Session*>(parent())->dirScanDone();
|
|
}
|
|
break;
|
|
}
|
|
case Event::EventScanComplete: {
|
|
if (m_scanning) {
|
|
// We have the listing
|
|
DirectoryTree *tree = static_cast<DirectoryTree*>(event->getParameter(0).asData());
|
|
addScannedDirectory(tree, m_curTransfer);
|
|
delete tree;
|
|
|
|
m_scanning = false;
|
|
m_curTransfer->unlock();
|
|
remove();
|
|
|
|
emit static_cast<Session*>(parent())->dirScanDone();
|
|
}
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
void Connection::slotTransferCompleted()
|
|
{
|
|
// Remove the lock
|
|
remove();
|
|
}
|
|
|
|
void Connection::reconnect()
|
|
{
|
|
if (!m_client->socket()->isConnected()) {
|
|
KFTPBookmarks::Manager::self()->setupClient(static_cast<Session*>(parent())->getSite(), m_client);
|
|
m_client->connect(m_client->socket()->getCurrentUrl());
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////
|
|
//////////////////// Session ////////////////////
|
|
////////////////////////////////////////////////////////
|
|
|
|
Session::Session(Side side)
|
|
: TQObject(),
|
|
m_side(side),
|
|
m_remote(false),
|
|
m_aborting(false),
|
|
m_registred(false),
|
|
m_site(0)
|
|
{
|
|
// Register this session
|
|
Manager::self()->registerSession(this);
|
|
}
|
|
|
|
Session::~Session()
|
|
{
|
|
}
|
|
|
|
KFTPEngine::Thread *Session::getClient()
|
|
{
|
|
// Return the first (core) connection's client
|
|
return m_connections.at(0)->getClient();
|
|
}
|
|
|
|
bool Session::isConnected()
|
|
{
|
|
// If there are no connections, just check if the session is remote
|
|
if (m_connections.count() == 0)
|
|
return !m_remote;
|
|
|
|
return m_connections.at(0)->isConnected();
|
|
}
|
|
|
|
void Session::slotClientEngineEvent(KFTPEngine::Event *event)
|
|
{
|
|
switch (event->type()) {
|
|
case Event::EventConnect: {
|
|
// ***************************************************************************
|
|
// ****************************** EventConnect *******************************
|
|
// ***************************************************************************
|
|
m_remote = true;
|
|
m_aborting = false;
|
|
m_lastUrl = getClient()->socket()->getCurrentUrl();
|
|
|
|
TQString siteName;
|
|
if (m_site)
|
|
siteName = m_site->getAttribute("name");
|
|
else
|
|
siteName = m_lastUrl.host();
|
|
|
|
Manager::self()->getTabs(m_side)->changeTab(m_fileView, siteName);
|
|
Manager::self()->getStatTabs()->changeTab(m_log, i18n("Log (%1)").arg(siteName));
|
|
Manager::self()->getStatTabs()->showPage(m_log);
|
|
Manager::self()->doEmitUpdate();
|
|
|
|
KURL homeUrl = getClient()->socket()->getCurrentUrl();
|
|
|
|
if (m_site && !m_site->getProperty("defremotepath").isEmpty())
|
|
homeUrl.setPath(m_site->getProperty("defremotepath"));
|
|
else
|
|
homeUrl.setPath(getClient()->socket()->getDefaultDirectory());
|
|
|
|
m_fileView->setHomeUrl(homeUrl);
|
|
m_fileView->goHome();
|
|
|
|
Session *opposite = Manager::self()->getActive(oppositeSide(m_side));
|
|
|
|
if (m_site && !opposite->isRemote()) {
|
|
TQString localPath = m_site->getProperty("deflocalpath");
|
|
|
|
if (!localPath.isEmpty())
|
|
opposite->getFileView()->openUrl(KURL(localPath));
|
|
}
|
|
break;
|
|
}
|
|
case Event::EventDisconnect: {
|
|
// ***************************************************************************
|
|
// **************************** EventDisconnect ******************************
|
|
// ***************************************************************************
|
|
m_remote = false;
|
|
m_aborting = false;
|
|
|
|
Manager::self()->getTabs(m_side)->changeTab(m_fileView, i18n("Local Session"));
|
|
Manager::self()->getStatTabs()->changeTab(m_log, "[" + i18n("Log") + "]");
|
|
Manager::self()->doEmitUpdate();
|
|
|
|
m_fileView->setHomeUrl(KURL(KFTPCore::Config::defLocalDir()));
|
|
m_fileView->goHome();
|
|
break;
|
|
}
|
|
case Event::EventCommand: m_log->ftpLog(1, event->getParameter(0).asString()); break;
|
|
case Event::EventMultiline: m_log->ftpLog(2, event->getParameter(0).asString()); break;
|
|
case Event::EventResponse: m_log->ftpLog(0, event->getParameter(0).asString()); break;
|
|
case Event::EventMessage: m_log->ftpLog(3, event->getParameter(0).asString()); break;
|
|
case Event::EventRetrySuccess: {
|
|
// ***************************************************************************
|
|
// ************************** EventRetrySuccess ******************************
|
|
// ***************************************************************************
|
|
if (KFTPCore::Config::showRetrySuccessBalloon()) {
|
|
KFTPWidgets::SystemTray::self()->showBalloon(i18n("Connection with %1 has been successfully established.").arg(getClient()->socket()->getCurrentUrl().host()));
|
|
}
|
|
break;
|
|
}
|
|
case Event::EventReloadNeeded: {
|
|
// We should only do refreshes if the queue is not being processed
|
|
if (KFTPQueue::Manager::self()->getNumRunning() == 0)
|
|
m_fileView->reload();
|
|
break;
|
|
}
|
|
case Event::EventPubkeyPassword: {
|
|
// A public-key authentication password was requested
|
|
TQString pass;
|
|
int ret = KPasswordDialog::getPassword(pass, i18n("Please provide your private key decryption password."));
|
|
|
|
if (ret == KPasswordDialog::Accepted) {
|
|
PubkeyWakeupEvent *event = new PubkeyWakeupEvent();
|
|
event->password = pass;
|
|
|
|
getClient()->wakeup(event);
|
|
} else {
|
|
getClient()->abort();
|
|
}
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
void Session::scanDirectory(KFTPQueue::Transfer *parent, Connection *connection)
|
|
{
|
|
// Go trough all files in path and add them as transfers that have parent as their parent
|
|
// transfer
|
|
KURL path = parent->getSourceUrl();
|
|
|
|
if (path.isLocalFile()) {
|
|
connect(new DirectoryScanner(parent), SIGNAL(completed()), this, SIGNAL(dirScanDone()));
|
|
} else if (m_remote) {
|
|
if (!connection) {
|
|
if (!isFreeConnection()) {
|
|
emit dirScanDone();
|
|
return;
|
|
}
|
|
|
|
// Assign a new connection (it might be unconnected!)
|
|
connection = assignConnection();
|
|
}
|
|
|
|
connection->scanDirectory(parent);
|
|
}
|
|
}
|
|
|
|
void Session::abort()
|
|
{
|
|
if (m_aborting)
|
|
return;
|
|
|
|
m_aborting = true;
|
|
|
|
emit aborting();
|
|
|
|
// Abort all connections
|
|
Connection *conn;
|
|
for (conn = m_connections.first(); conn; conn = m_connections.next()) {
|
|
conn->abort();
|
|
}
|
|
|
|
m_aborting = false;
|
|
}
|
|
|
|
void Session::reconnect(const KURL &url)
|
|
{
|
|
// Set the reconnect url
|
|
m_reconnectUrl = url;
|
|
|
|
if (m_remote && getClient()->socket()->isConnected()) {
|
|
abort();
|
|
|
|
connect(getClient()->eventHandler(), SIGNAL(disconnected()), this, SLOT(slotStartReconnect()));
|
|
getClient()->disconnect();
|
|
} else {
|
|
// The session is already disconnected, just call the slot
|
|
slotStartReconnect();
|
|
}
|
|
}
|
|
|
|
void Session::slotStartReconnect()
|
|
{
|
|
disconnect(getClient()->eventHandler(), SIGNAL(disconnected()), this, SLOT(slotStartReconnect()));
|
|
|
|
// Reconnect only if this is a remote url
|
|
if (!m_reconnectUrl.isLocalFile()) {
|
|
KFTPBookmarks::Manager::self()->setupClient(m_site, getClient());
|
|
getClient()->connect(m_reconnectUrl);
|
|
}
|
|
|
|
// Invalidate the url
|
|
m_reconnectUrl = KURL();
|
|
}
|
|
|
|
int Session::getMaxThreadCount()
|
|
{
|
|
// First get the global thread count
|
|
int count = KFTPCore::Config::threadCount();
|
|
|
|
if (!KFTPCore::Config::threadUsePrimary())
|
|
count++;
|
|
|
|
// Try to see if threads are disabled for this site
|
|
if (count > 1 && isRemote()) {
|
|
if (m_site && m_site->getIntProperty("disableThreads"))
|
|
return 1;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
bool Session::isFreeConnection()
|
|
{
|
|
unsigned int max = getMaxThreadCount();
|
|
unsigned int free = 0;
|
|
|
|
if ((m_connections.count() < max && max > 1) || !isRemote())
|
|
return true;
|
|
|
|
Connection *conn;
|
|
for (conn = m_connections.first(); conn; conn = m_connections.next()) {
|
|
if (!conn->isBusy() && (!conn->isPrimary() || KFTPCore::Config::threadUsePrimary() || max == 1))
|
|
free++;
|
|
}
|
|
|
|
return free > 0;
|
|
}
|
|
|
|
Connection *Session::assignConnection()
|
|
{
|
|
unsigned int max = getMaxThreadCount();
|
|
|
|
if (m_connections.count() == 0) {
|
|
// We need a new core connection
|
|
Connection *conn = new Connection(this, true);
|
|
m_connections.append(conn);
|
|
|
|
Manager::self()->doEmitUpdate();
|
|
|
|
return conn;
|
|
} else {
|
|
// Find a free connection
|
|
Connection *conn;
|
|
for (conn = m_connections.first(); conn; conn = m_connections.next()) {
|
|
if (!conn->isBusy() && (!conn->isPrimary() || KFTPCore::Config::threadUsePrimary() || max == 1))
|
|
return conn;
|
|
}
|
|
|
|
// No free connection has been found, but we may be able to create
|
|
// another (if we are within limits)
|
|
if (m_connections.count() < max) {
|
|
conn = new Connection(this);
|
|
m_connections.append(conn);
|
|
|
|
Manager::self()->doEmitUpdate();
|
|
|
|
return conn;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void Session::disconnectAllConnections()
|
|
{
|
|
// Abort any possible transfers first
|
|
abort();
|
|
|
|
// Now disconnect all connections
|
|
Connection *conn;
|
|
|
|
for (conn = m_connections.first(); conn; conn = m_connections.next()) {
|
|
if (conn->getClient()->socket()->isConnected()) {
|
|
conn->getClient()->disconnect();
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////
|
|
/////////////////////// Manager ////////////////////////
|
|
////////////////////////////////////////////////////////
|
|
|
|
Manager *Manager::m_self = 0;
|
|
|
|
Manager *Manager::self()
|
|
{
|
|
return m_self;
|
|
}
|
|
|
|
Manager::Manager(TQObject *parent, TQTabWidget *stat, KFTPTabWidget *left, KFTPTabWidget *right)
|
|
: TQObject(parent),
|
|
m_statTabs(stat),
|
|
m_leftTabs(left),
|
|
m_rightTabs(right),
|
|
m_active(0),
|
|
m_leftActive(0),
|
|
m_rightActive(0)
|
|
{
|
|
Manager::m_self = this;
|
|
|
|
// Connect some signals
|
|
connect(left, SIGNAL(currentChanged(TQWidget*)), this, SLOT(slotActiveChanged(TQWidget*)));
|
|
connect(right, SIGNAL(currentChanged(TQWidget*)), this, SLOT(slotActiveChanged(TQWidget*)));
|
|
|
|
connect(left, SIGNAL(closeRequest(TQWidget*)), this, SLOT(slotSessionCloseRequest(TQWidget*)));
|
|
connect(right, SIGNAL(closeRequest(TQWidget*)), this, SLOT(slotSessionCloseRequest(TQWidget*)));
|
|
}
|
|
|
|
void Manager::registerSession(Session *session)
|
|
{
|
|
m_active = session;
|
|
|
|
// Create some new stuff and assign it to the session
|
|
session->assignConnection();
|
|
session->m_fileView = new KFTPWidgets::Browser::View(0L, "", session->getClient(), session);
|
|
session->m_log = new KFTPWidgets::LogView();
|
|
|
|
// Install event filters
|
|
session->getFileView()->getDetailsView()->installEventFilter(this);
|
|
session->getFileView()->getTreeView()->installEventFilter(this);
|
|
session->getFileView()->m_toolBarFirst->installEventFilter(this);
|
|
session->getFileView()->m_toolBarSecond->installEventFilter(this);
|
|
|
|
connect(session->getFileView()->getDetailsView(), SIGNAL(clicked(TQListViewItem*)), this, SLOT(slotSwitchFocus()));
|
|
connect(session->getFileView()->getTreeView(), SIGNAL(clicked(TQListViewItem*)), this, SLOT(slotSwitchFocus()));
|
|
connect(session->getFileView()->m_toolBarFirst, SIGNAL(clicked(int)), this, SLOT(slotSwitchFocus()));
|
|
connect(session->getFileView()->m_toolBarSecond, SIGNAL(clicked(int)), this, SLOT(slotSwitchFocus()));
|
|
|
|
// Connect some signals
|
|
connect(session->getClient()->eventHandler(), SIGNAL(engineEvent(KFTPEngine::Event*)), session, SLOT(slotClientEngineEvent(KFTPEngine::Event*)));
|
|
|
|
// Assign GUI positions
|
|
m_statTabs->addTab(session->m_log, "[" + i18n("Log") + "]");
|
|
getTabs(session->m_side)->addTab(session->m_fileView, KFTPGrabberBase::loadSmallIcon("computer"), i18n("Session"));
|
|
|
|
// Actually add the session
|
|
m_sessionList.append(session);
|
|
session->m_registred = true;
|
|
}
|
|
|
|
KFTPWidgets::Browser::View *Manager::getActiveView()
|
|
{
|
|
if (m_active)
|
|
return m_active->getFileView();
|
|
|
|
return 0;
|
|
}
|
|
|
|
Session *Manager::getActiveSession()
|
|
{
|
|
return m_active;
|
|
}
|
|
|
|
bool Manager::eventFilter(TQObject *object, TQEvent *event)
|
|
{
|
|
if (event->type() == TQEvent::FocusIn || event->type() == TQEvent::MouseButtonPress) {
|
|
switchFocusToObject(object);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void Manager::slotSwitchFocus()
|
|
{
|
|
switchFocusToObject(TQObject::sender());
|
|
}
|
|
|
|
void Manager::switchFocusToObject(const TQObject *object)
|
|
{
|
|
if (!object)
|
|
return;
|
|
|
|
for (;;) {
|
|
if (object->isA("KFTPWidgets::Browser::View"))
|
|
break;
|
|
|
|
if (!(object = object->parent()))
|
|
break;
|
|
}
|
|
|
|
if (object) {
|
|
// We have the proper object
|
|
Session *session = find(static_cast<const KFTPWidgets::Browser::View*>(object));
|
|
|
|
if (session && session != m_active) {
|
|
m_active = session;
|
|
|
|
// Open the current session's log tab
|
|
if (session->isRemote())
|
|
m_statTabs->showPage(session->getLog());
|
|
}
|
|
}
|
|
}
|
|
|
|
void Manager::unregisterSession(Session *session)
|
|
{
|
|
// Destroy all objects related to the session and remove it
|
|
getTabs(session->m_side)->removePage(session->m_fileView);
|
|
m_statTabs->removePage(session->m_log);
|
|
|
|
if (session->getClient()->socket()->isConnected()) {
|
|
session->abort();
|
|
session->getClient()->disconnect();
|
|
}
|
|
|
|
// Delete objects
|
|
session->m_fileView->deleteLater();
|
|
session->m_log->deleteLater();
|
|
|
|
// Actually remove the session
|
|
m_sessionList.remove(session);
|
|
delete session;
|
|
|
|
// Emit update
|
|
emit update();
|
|
}
|
|
|
|
void Manager::doEmitUpdate()
|
|
{
|
|
emit update();
|
|
}
|
|
|
|
void Manager::disconnectAllSessions()
|
|
{
|
|
Session *i;
|
|
|
|
for (i = m_sessionList.first(); i; i = m_sessionList.next())
|
|
i->disconnectAllConnections();
|
|
}
|
|
|
|
Session *Manager::find(KFTPEngine::Thread *client)
|
|
{
|
|
Session *i;
|
|
|
|
for (i = m_sessionList.first(); i; i = m_sessionList.next()) {
|
|
if (i->getClient() == client)
|
|
return i;
|
|
}
|
|
|
|
return 0L;
|
|
}
|
|
|
|
Session *Manager::find(KFTPWidgets::Browser::View *fileView)
|
|
{
|
|
Session *i;
|
|
|
|
for (i = m_sessionList.first(); i; i = m_sessionList.next()) {
|
|
if (i->m_fileView == fileView)
|
|
return i;
|
|
}
|
|
|
|
return 0L;
|
|
}
|
|
|
|
Session *Manager::find(KFTPWidgets::LogView *log)
|
|
{
|
|
Session *i;
|
|
|
|
for (i = m_sessionList.first(); i; i = m_sessionList.next()) {
|
|
if (i->m_log == log)
|
|
return i;
|
|
}
|
|
|
|
return 0L;
|
|
}
|
|
|
|
Session *Manager::find(const KURL &url, bool mustUnlock)
|
|
{
|
|
if (url.isLocalFile())
|
|
return find(true);
|
|
|
|
Session *i;
|
|
|
|
for (i = m_sessionList.first(); i; i = m_sessionList.next()) {
|
|
KURL tmp = i->getClient()->socket()->getCurrentUrl();
|
|
tmp.setPath(url.path());
|
|
|
|
if (tmp == url && i->isRemote() && i->isConnected() && (!mustUnlock || i->isFreeConnection()))
|
|
return i;
|
|
}
|
|
|
|
return 0L;
|
|
}
|
|
|
|
Session *Manager::find(bool local)
|
|
{
|
|
Session *i;
|
|
|
|
for (i = m_sessionList.first(); i; i = m_sessionList.next()) {
|
|
if (i->m_remote != local)
|
|
return i;
|
|
}
|
|
|
|
return 0L;
|
|
}
|
|
|
|
Session *Manager::findLast(const KURL &url, Side side)
|
|
{
|
|
if (url.isLocalFile())
|
|
return find(true);
|
|
|
|
Session *i;
|
|
|
|
for (i = m_sessionList.first(); i; i = m_sessionList.next()) {
|
|
KURL tmp = i->m_lastUrl;
|
|
tmp.setPath(url.path());
|
|
|
|
if (tmp == url && !i->isRemote() && (i->getSide() || side == IgnoreSide))
|
|
return i;
|
|
}
|
|
|
|
return 0L;
|
|
}
|
|
|
|
Session *Manager::spawnLocalSession(Side side, bool forceNew)
|
|
{
|
|
// Creates a new local session
|
|
Session *session = 0L;
|
|
|
|
if (forceNew || (session = find(true)) == 0L || (session->m_side != side && side != IgnoreSide)) {
|
|
side = side == IgnoreSide ? LeftSide : side;
|
|
|
|
session = new Session(side);
|
|
session->m_remote = false;
|
|
getTabs(side)->changeTab(session->m_fileView, i18n("Local Session"));
|
|
getStatTabs()->changeTab(session->m_log, "[" + i18n("Log") + "]");
|
|
}
|
|
|
|
setActive(session);
|
|
return session;
|
|
}
|
|
|
|
Session *Manager::spawnRemoteSession(Side side, const KURL &remoteUrl, KFTPBookmarks::Site *site, bool mustUnlock)
|
|
{
|
|
// Creates a new remote session and connects it to the correct server
|
|
Session *session;
|
|
|
|
if (remoteUrl.isLocalFile())
|
|
return spawnLocalSession(side);
|
|
|
|
if ((session = find(remoteUrl, mustUnlock)) == 0L || (session->m_side != side && side != IgnoreSide)) {
|
|
// Try to find the session that was last connected to this URL
|
|
if ((session = findLast(remoteUrl, side)) == 0L) {
|
|
// Attempt to reuse a local session if one exists one the right side
|
|
session = getActive(RightSide);
|
|
|
|
if (session->isRemote()) {
|
|
side = side == IgnoreSide ? RightSide : side;
|
|
session = new Session(side);
|
|
}
|
|
}
|
|
|
|
// Try to find the site by url if it is not set
|
|
if (!site)
|
|
site = KFTPBookmarks::Manager::self()->findSite(remoteUrl);
|
|
|
|
// Set properties
|
|
session->m_remote = true;
|
|
session->m_site = site;
|
|
m_active = session;
|
|
|
|
KFTPBookmarks::Manager::self()->setupClient(site, session->getClient());
|
|
session->getClient()->connect(remoteUrl);
|
|
}
|
|
|
|
return session;
|
|
}
|
|
|
|
void Manager::setActive(Session *session)
|
|
{
|
|
// Make a session active on its own side ;)
|
|
Session *oldActive = getActive(session->m_side);
|
|
|
|
oldActive ? oldActive->m_active = false : 0;
|
|
session->m_active = true;
|
|
|
|
switch (session->m_side) {
|
|
case LeftSide: m_leftActive = session; break;
|
|
case RightSide: m_rightActive = session; break;
|
|
case IgnoreSide: tqDebug("Invalid side specified!"); return;
|
|
}
|
|
|
|
// Refresh the GUI
|
|
getTabs(session->m_side)->showPage(session->m_fileView);
|
|
}
|
|
|
|
Session *Manager::getActive(Side side)
|
|
{
|
|
switch (side) {
|
|
case LeftSide: return m_leftActive;
|
|
case RightSide: return m_rightActive;
|
|
case IgnoreSide: tqDebug("Invalid side specified!"); break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
KFTPTabWidget *Manager::getTabs(Side side)
|
|
{
|
|
switch (side) {
|
|
case LeftSide: return m_leftTabs;
|
|
case RightSide: return m_rightTabs;
|
|
case IgnoreSide: tqDebug("Invalid side specified!"); break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void Manager::slotActiveChanged(TQWidget *page)
|
|
{
|
|
Session *session = find(static_cast<KFTPWidgets::Browser::View*>(page));
|
|
setActive(session);
|
|
}
|
|
|
|
void Manager::slotSessionCloseRequest(TQWidget *page)
|
|
{
|
|
Session *session = find(static_cast<KFTPWidgets::Browser::View*>(page));
|
|
|
|
if (getTabs(session->m_side)->count() == 1) {
|
|
KMessageBox::error(0L, i18n("At least one session must remain open on each side."));
|
|
return;
|
|
}
|
|
|
|
if ((session->m_remote && session->getClient()->socket()->isBusy()) || !session->isFreeConnection()) {
|
|
KMessageBox::error(0L, i18n("Please finish all transfers before closing the session."));
|
|
return;
|
|
} else {
|
|
// Remove the session
|
|
if (session->getClient()->socket()->isConnected()) {
|
|
if (KMessageBox::questionYesNo(0L, i18n("This session is currently connected. Are you sure you wish to disconnect?"), i18n("Close Session")) == KMessageBox::No)
|
|
return;
|
|
}
|
|
|
|
unregisterSession(session);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#include "kftpsession.moc"
|