diff options
Diffstat (limited to 'kftpgrabber/src/kftpsession.cpp')
-rw-r--r-- | kftpgrabber/src/kftpsession.cpp | 920 |
1 files changed, 920 insertions, 0 deletions
diff --git a/kftpgrabber/src/kftpsession.cpp b/kftpgrabber/src/kftpsession.cpp new file mode 100644 index 0000000..126eb3e --- /dev/null +++ b/kftpgrabber/src/kftpsession.cpp @@ -0,0 +1,920 @@ +/* + * 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/config.h" +#include "misc/filter.h" + +#include <qdir.h> +#include <qobjectlist.h> + +#include <kmessagebox.h> +#include <klocale.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) + : QObject(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->QObject::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) + : QObject(), + 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(); + + QString 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()) { + QString 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 + QCString 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(QObject *parent, QTabWidget *stat, KFTPTabWidget *left, KFTPTabWidget *right) + : QObject(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(QWidget*)), this, SLOT(slotActiveChanged(QWidget*))); + connect(right, SIGNAL(currentChanged(QWidget*)), this, SLOT(slotActiveChanged(QWidget*))); + + connect(left, SIGNAL(closeRequest(QWidget*)), this, SLOT(slotSessionCloseRequest(QWidget*))); + connect(right, SIGNAL(closeRequest(QWidget*)), this, SLOT(slotSessionCloseRequest(QWidget*))); +} + +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(QListViewItem*)), this, SLOT(slotSwitchFocus())); + connect(session->getFileView()->getTreeView(), SIGNAL(clicked(QListViewItem*)), 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("system"), 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(QObject *object, QEvent *event) +{ + if (event->type() == QEvent::FocusIn || event->type() == QEvent::MouseButtonPress) { + switchFocusToObject(object); + } + + return false; +} + +void Manager::slotSwitchFocus() +{ + switchFocusToObject(QObject::sender()); +} + +void Manager::switchFocusToObject(const QObject *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: qDebug("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: qDebug("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: qDebug("Invalid side specified!"); break; + } + + return NULL; +} + +void Manager::slotActiveChanged(QWidget *page) +{ + Session *session = find(static_cast<KFTPWidgets::Browser::View*>(page)); + setActive(session); +} + +void Manager::slotSessionCloseRequest(QWidget *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" |