From 39fedaa847ed64b2c0113a75d0f1de29da5876db Mon Sep 17 00:00:00 2001 From: korovkin Date: Sun, 19 Mar 2006 14:59:21 +0000 Subject: Added device browsing and files downloading using OBEX File transfer protocol. --- (limited to 'noncore/net/opietooth/manager/obexftpdialog.cpp') diff --git a/noncore/net/opietooth/manager/obexftpdialog.cpp b/noncore/net/opietooth/manager/obexftpdialog.cpp new file mode 100644 index 0000000..c77d49d --- a/dev/null +++ b/noncore/net/opietooth/manager/obexftpdialog.cpp @@ -0,0 +1,390 @@ +/* $Id$ */ +/* OBEX file browser dialog */ +/*************************************************************************** + * * + * 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 code uses and is based on ObexFTP project code: http://triq.net/obexftp/ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "obexftpdialog.h" +#include "filelistitem.h" + +#include +#include +#include +#include +#include + +using namespace Opie::Core; +using namespace Opie::Ui; + +using namespace OpieTooth; + +#define MAX_PROGRESS 14 //Maximal progress bar + +static void info_cb(int event, const char *msg, int len, void* data); + +/* + * Public constructor + * device - bluetooth address of the device + * port - port to connect to + */ +ObexFtpDialog::ObexFtpDialog(const QString& device, int port, + QWidget* parent, const char* name, bool modal, WFlags fl) + : ObexFtpDialogBase(parent, name, modal, fl), m_device(device), + m_port(port), curdir("") +{ + client = NULL; + transport = OBEX_TRANS_BLUETOOTH; + use_conn = TRUE; + use_path = TRUE; + progressStatus = 0; + localCurdir = "/"; + browseLog->setEdited(FALSE); + fileList->setSorting(1); + fileList->clear(); + fileProgress->setTotalSteps(MAX_PROGRESS); + statusBar->clear(); + localLayout = new QVBoxLayout(localFs); + localLayout->setSpacing( 0 ); + localLayout->setMargin( 0 ); + destFile = new OFileSelector(localFs, + OFileSelector::FileSelector, + OFileSelector::ExtendedAll, localCurdir, ""); + destFile->setCloseVisible(false); + destFile->setNewVisible(false); + localLayout->addWidget(destFile); + connect(browseOK, SIGNAL(clicked()), SLOT(slotBrowse())); + connect(fileList, SIGNAL(clicked(QListViewItem*)), + SLOT(slotCd(QListViewItem*))); + connect(getButton, + SIGNAL(clicked()), + SLOT(getFile())); + connect(destFile, + SIGNAL(dirSelected (const QString&)), + SLOT(updateDir(const QString&))); +} + +ObexFtpDialog::~ObexFtpDialog() +{ + if (client != NULL) { + obexftp_disconnect(client); + obexftp_close(client); + } +} + +/* + * Do device browsing + */ +void ObexFtpDialog::slotBrowse() +{ + stat_entry_t* ent; //Directory entry + void *dir; //Directory to read + const uint8_t use_uuid[] = __UUID_FBS_bytes; + int len = sizeof(UUID_FBS); + FileListItem* root; //root node + stat_entry_t* st; //File statistics + int fsize; //file size + + status(tr("Connecting to ") + m_device); + odebug << "Browse device " << m_device << oendl; + browseLog->clear(); + fileList->clear(); + progressStatus = 0; + fileProgress->reset(); + if (!cli_connect_uuid(use_uuid, len)) { + log("Connection failed"); + errBox("Connection failed"); + status("Connection failed"); + return; + } + else { + log(QString("Connected to ") + m_device); + status(QString("Connected to ") + m_device); + } + /* List folder */ + root = new FileListItem(fileList, NULL); + dir = obexftp_opendir(client, curdir); + while ((ent = obexftp_readdir(dir)) != NULL) { + FileListItem* a; //List view item +#if 0 //Causes sigsegv + if (ent->mode != 16877) { + st = obexftp_stat(client, ent->name); + fsize = st->size; + } + else +#endif + fsize = 0; + log(QString(ent->name) + QString(" ") + + QString::number(ent->mode)); + + a = new FileListItem(fileList, ent, fsize); + } + obexftp_closedir(dir); +} + +//Error message box +int ObexFtpDialog::errBox(QCString msg) +{ + return QMessageBox::critical(this, tr("ObexFTP error"), msg); +} + +int ObexFtpDialog::errBox(QString msg) +{ + return QMessageBox::critical(this, tr("ObexFTP error"), msg); +} + +int ObexFtpDialog::errBox(const char* msg) +{ + return QMessageBox::critical(this, tr("ObexFTP error"), tr(msg)); +} + +//Text in the status bar +void ObexFtpDialog::status(QCString msg) +{ + statusBar->setText(msg); + statusBar->repaint(); +} + +void ObexFtpDialog::status(QString msg) +{ + statusBar->setText(msg); + statusBar->repaint(); +} + +void ObexFtpDialog::status(const char* msg) +{ + statusBar->setText(msg); + statusBar->repaint(); +} + +/* + * Change directory with item under the cursor + */ +void ObexFtpDialog::slotCd(QListViewItem* item) +{ + FileListItem* file = (FileListItem*)item; + int idx; + if (file == NULL) + return; + odebug << "Item " << file->text(0) << " clicked" << oendl; + if (file->gettype() == IS_DIR) { + if (file->text(0) == "../") { + if (curdir.right(1) == "/") + curdir.remove(curdir.length() - 1, 1); + idx = curdir.findRev('/'); + if (idx >= 0) + curdir.remove(idx, curdir.length() - idx); + else + curdir = ""; + } + else { + if (curdir != "" && curdir.right(1) != "/") + curdir += "/"; + curdir += file->text(0); + } + odebug << "Browse " << curdir << oendl; + if (obexftp_setpath(client, curdir, 0) < 0) + log("CD failed"); + slotBrowse(); + } +} + +/* + * Get the file + */ +void ObexFtpDialog::getFile() +{ + FileListItem* file = (FileListItem*)fileList->selectedItem(); + int result; + if (file == NULL) + return; + file2get = "/"; + local = localCurdir; + if (local == "") { + errBox("Select a destination first"); + return; + } + if (local.right(1) != "/") + local += "/"; + if (file->gettype() == IS_FILE) { + file2get += curdir; + if (curdir != "" && curdir.right(1) != "/") + file2get += "/"; + file2get += file->text(0); + local += file->text(0); + odebug << "Copy " << file2get << " to " << local << oendl; + progressStatus = 0; + fileProgress->reset(); + status(tr("Receiving file ") + file2get); + result = obexftp_get(client, local, file2get); + if (result < 0) { + log(file2get + QString(" receive ERROR")); + errBox(file2get + QString(" receive ERROR")); + status(file2get + QString(" receive ERROR")); + } + else { + log(file2get + QString(" received")); + status(file2get + QString(" received")); + destFile->reread(); + } + } +} + +/* connect with given uuid. re-connect every time */ +int ObexFtpDialog::cli_connect_uuid(const uint8_t *uuid, int uuid_len) +{ + int retry; + if (client != NULL) + return TRUE; + /* Open */ + client = obexftp_open (transport, NULL, info_cb, this); + if(client == NULL) { + errBox("Error opening obexftp-client"); + return FALSE; + } + if (!use_conn) + client->quirks &= ~OBEXFTP_CONN_HEADER; + if (!use_path) + client->quirks &= ~OBEXFTP_SPLIT_SETPATH; + for (retry = 0; retry < 3; retry++) { + /* Connect */ + switch (transport) { + case OBEX_TRANS_IRDA: + if (obexftp_connect_uuid(client, NULL, 0, uuid, uuid_len) >= 0) + return TRUE; + break; + case OBEX_TRANS_BLUETOOTH: + if (obexftp_connect_uuid(client, m_device, m_port, + uuid, uuid_len) >= 0) + return TRUE; + break; + default: + errBox("Transport type unknown"); + return FALSE; + } + log(tr("Still trying to connect")); + } + client = NULL; + + return FALSE; +} + +/* + * Put a message to the log window + */ +void ObexFtpDialog::log(QString str) +{ + browseLog->append(str); +} + +void ObexFtpDialog::log(QCString str) +{ + browseLog->append(str); +} + +void ObexFtpDialog::log(QString& str) +{ + browseLog->append(str); +} + +void ObexFtpDialog::log(const char* str) +{ + browseLog->append(str); +} + +void ObexFtpDialog::incProgress() +{ + odebug << "Progress " << progressStatus << oendl; + if (progressStatus < MAX_PROGRESS) { + fileProgress->setProgress(progressStatus++); + } +} + +void ObexFtpDialog::doneProgress() +{ + progressStatus = 0; + fileProgress->reset(); +} + +void ObexFtpDialog::updateDir(const QString& newdir) +{ + localCurdir = newdir; +} + +/* + * Event callback function + */ +static void info_cb(int event, const char *msg, int len, void* data) +{ + ObexFtpDialog* dlg = (ObexFtpDialog*)data; + QCString cmsg(msg, len); //Message to display + + switch (event) { + + case OBEXFTP_EV_ERRMSG: + dlg->log(QCString("Error: ") + cmsg); + break; + + case OBEXFTP_EV_ERR: + dlg->log(QCString("failed: ") + cmsg); + dlg->doneProgress(); + break; + case OBEXFTP_EV_OK: + dlg->log(QCString("done")); + dlg->doneProgress(); + break; + + case OBEXFTP_EV_CONNECTING: + dlg->log(QCString("Connecting...")); + break; + case OBEXFTP_EV_DISCONNECTING: + dlg->log(QCString("Disconnecting...")); + break; + case OBEXFTP_EV_SENDING: + dlg->log(QCString("Sending ") + msg); + break; + case OBEXFTP_EV_RECEIVING: + dlg->log(QCString("Receiving ") + msg); + break; + + case OBEXFTP_EV_LISTENING: + dlg->log(QCString("Waiting for incoming connection")); + break; + + case OBEXFTP_EV_CONNECTIND: + dlg->log(QCString("Incoming connection")); + break; + case OBEXFTP_EV_DISCONNECTIND: + dlg->log(QCString("Disconnecting")); + break; + + case OBEXFTP_EV_INFO: + // 64 bit problems ? + dlg->log(QString("Got info ") + QString::number((int)msg)); + break; + + case OBEXFTP_EV_BODY: + break; + + case OBEXFTP_EV_PROGRESS: + dlg->incProgress(); + break; + } +} + +//eof -- cgit v0.9.0.2