bluedevil: pull upstream changes

This commit is contained in:
Ivailo Monev 2014-12-26 21:08:09 +00:00
parent 18b3256542
commit 7e830bdd87
21 changed files with 585 additions and 480 deletions

View file

@ -3,7 +3,7 @@ project(bluedevil)
find_package(KDE4 REQUIRED)
set(CMAKE_BLUEDEVIL_VERSION_MAJOR 2)
set(CMAKE_BLUEDEVIL_VERSION_MINOR 0)
set(CMAKE_BLUEDEVIL_VERSION_MINOR 1)
set(CMAKE_BLUEDEVIL_VERSION_PATCH 0)
set(CMAKE_BLUEDEVIL_VERSION_STRING "${CMAKE_BLUEDEVIL_VERSION_MAJOR}.${CMAKE_BLUEDEVIL_VERSION_MINOR}.${CMAKE_BLUEDEVIL_VERSION_PATCH}")
configure_file(version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/version.h)

View file

@ -36,6 +36,7 @@
#include <KPluginFactory>
#include <kfileplacesmodel.h>
#include <kdirnotify.h>
#include <ksharedconfig.h>
#include <bluedevil/bluedevilmanager.h>
#include <bluedevil/bluedeviladapter.h>
@ -62,10 +63,9 @@ struct BlueDevilDaemon::Private
Adapter *m_adapter;
QDBusServiceWatcher *m_monolithicWatcher;
FileReceiver *m_fileReceiver;
QList <DeviceInfo> m_discovered;
QTimer m_timer;
QTimer m_timer;
KComponentData m_componentData;
QHash<QString, bool> m_adapterPoweredHash;
KSharedConfig::Ptr m_config;
};
BlueDevilDaemon::BlueDevilDaemon(QObject *parent, const QList<QVariant>&)
@ -81,8 +81,8 @@ BlueDevilDaemon::BlueDevilDaemon(QObject *parent, const QList<QVariant>&)
d->m_fileReceiver = 0;
d->m_monolithicWatcher = new QDBusServiceWatcher("org.kde.bluedevilmonolithic"
, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForUnregistration, this);
d->m_timer.setInterval(20000);
d->m_timer.setSingleShot(true);
d->m_config = KSharedConfig::openConfig("bluedevilglobalrc");
KAboutData aboutData(
"bluedevildaemon",
@ -102,10 +102,15 @@ BlueDevilDaemon::BlueDevilDaemon(QObject *parent, const QList<QVariant>&)
aboutData.setProgramIconName("preferences-system-bluetooth");
d->m_componentData = KComponentData(aboutData);
connect(d->m_monolithicWatcher, SIGNAL(serviceUnregistered(const QString &)), SLOT(monolithicFinished(const QString &)));
connect(d->m_monolithicWatcher, SIGNAL(serviceUnregistered(QString)), SLOT(monolithicFinished(QString)));
connect(&d->m_timer, SIGNAL(timeout()), SLOT(stopDiscovering()));
connect(Manager::self(), SIGNAL(usableAdapterChanged(Adapter*)),
this, SLOT(usableAdapterChanged(Adapter*)));
connect(Manager::self(), SIGNAL(adapterAdded(Adapter*)),
this, SLOT(adapterAdded(Adapter*)));
connect(Manager::self(), SIGNAL(adapterRemoved(Adapter*)),
this, SLOT(adapterRemoved(Adapter*)));
// Catch suspend/resume events
QDBusConnection::systemBus().connect("org.freedesktop.login1",
@ -117,6 +122,8 @@ BlueDevilDaemon::BlueDevilDaemon(QObject *parent, const QList<QVariant>&)
);
d->m_status = Private::Offline;
restoreAdaptersState();
usableAdapterChanged(Manager::self()->usableAdapter());
if (!Manager::self()->adapters().isEmpty()) {
@ -126,6 +133,8 @@ BlueDevilDaemon::BlueDevilDaemon(QObject *parent, const QList<QVariant>&)
BlueDevilDaemon::~BlueDevilDaemon()
{
saveAdaptersState();
if (d->m_status == Private::Online) {
offlineMode();
}
@ -147,23 +156,10 @@ void BlueDevilDaemon::login1PrepareForSleep(bool active)
{
if (active) {
kDebug(dblue()) << "About to suspend";
d->m_adapterPoweredHash.clear();
Q_FOREACH (Adapter *adapter, Manager::self()->adapters()) {
kDebug(dblue()) << "Saving" << adapter->address() << adapter->isPowered();
d->m_adapterPoweredHash.insert(adapter->address(), adapter->isPowered());
}
saveAdaptersState();
} else {
kDebug(dblue()) << "About to resume";
QHashIterator<QString, bool> it(d->m_adapterPoweredHash);
while (it.hasNext()) {
it.next();
Adapter *adapter = adapterForAddress(it.key());
if (adapter) {
kDebug(dblue()) << "Restoring" << adapter->address() << it.value();
adapter->setPowered(it.value());
}
}
d->m_adapterPoweredHash.clear();
restoreAdaptersState();
}
}
@ -175,41 +171,55 @@ bool BlueDevilDaemon::isOnline()
return true;
}
QMapDeviceInfo BlueDevilDaemon::knownDevices()
QMapDeviceInfo BlueDevilDaemon::allDevices()
{
QMapDeviceInfo devices;
QList<Device*> list = Manager::self()->usableAdapter()->devices();
QList <Device* > list = Manager::self()->usableAdapter()->devices();
kDebug(dblue()) << "List: " << list.length();
DeviceInfo info;
Q_FOREACH(Device *const device, list) {
info["name"] = device->friendlyName();
info["icon"] = device->icon();
info["address"] = device->address();
info["UUIDs"] = device->UUIDs().join(",");
devices[device->address()] = info;
Q_FOREACH (Device *const device, list) {
devices[device->address()] = deviceToInfo(device);
}
if (!d->m_timer.isActive()) {
kDebug(dblue()) << "Start Discovery";
Manager::self()->usableAdapter()->startStableDiscovery();
d->m_discovered.clear();
d->m_timer.start();
}
return devices;
}
Q_FOREACH(const DeviceInfo& info, d->m_discovered) {
if (!devices.contains(info["address"])) {
devices[info["address"]] = info;
DeviceInfo BlueDevilDaemon::device(const QString &address)
{
Q_FOREACH (Device *const device, Manager::self()->devices()) {
if (device->address() == address) {
return deviceToInfo(device);
}
}
return devices;
return DeviceInfo();
}
void BlueDevilDaemon::startDiscovering(quint32 timeout)
{
if (!d->m_adapter) {
return;
}
kDebug(dblue()) << "Start discovering for" << timeout << "ms";
d->m_adapter->startDiscovery();
if (timeout > 0) {
d->m_timer.start(timeout);
}
}
void BlueDevilDaemon::stopDiscovering()
{
kDebug(dblue()) << "Stopping discovering";
d->m_timer.stop();
Manager::self()->usableAdapter()->stopDiscovery();
if (!d->m_adapter) {
return;
}
kDebug(dblue()) << "Stop discovering";
if (d->m_adapter->isDiscovering()) {
d->m_adapter->stopDiscovery();
}
}
void BlueDevilDaemon::executeMonolithic()
@ -246,9 +256,7 @@ void BlueDevilDaemon::onlineMode()
d->m_bluezAgent = new BluezAgent(new QObject());
connect(d->m_bluezAgent, SIGNAL(agentReleased()), this, SLOT(agentReleased()));
connect(d->m_adapter, SIGNAL(deviceFound(Device*)), this, SLOT(deviceFound(Device*)));
connect(&d->m_timer, SIGNAL(timeout()), d->m_adapter, SLOT(stopDiscovery()));
FileReceiverSettings::self()->readConfig();
if (!d->m_fileReceiver && FileReceiverSettings::self()->enabled()) {
@ -314,9 +322,6 @@ void BlueDevilDaemon::offlineMode()
d->m_placesModel->removePlace(index);
}
if (BlueDevil::Manager::self()->adapters().isEmpty()) {
killMonolithic();
}
d->m_status = Private::Offline;
}
@ -344,10 +349,23 @@ void BlueDevilDaemon::usableAdapterChanged(Adapter *adapter)
}
}
void BlueDevilDaemon::adapterAdded(Adapter *adapter)
{
restoreAdapterState(adapter);
}
void BlueDevilDaemon::adapterRemoved(Adapter *adapter)
{
Q_UNUSED(adapter)
if (BlueDevil::Manager::self()->adapters().isEmpty()) {
killMonolithic();
}
}
void BlueDevilDaemon::deviceFound(Device *device)
{
kDebug(dblue()) << "DeviceFound: " << device->name();
d->m_discovered.append(deviceToInfo(device));
org::kde::KDirNotify::emitFilesAdded("bluetooth:/");
}
@ -361,15 +379,55 @@ void BlueDevilDaemon::monolithicQuit(QDBusPendingCallWatcher* watcher)
}
}
void BlueDevilDaemon::saveAdaptersState()
{
Manager *manager = Manager::self();
if (!manager) {
return;
}
KConfigGroup adaptersGroup = d->m_config->group("Adapters");
Q_FOREACH (Adapter *adapter, manager->adapters()) {
const QString key = QString("%1_powered").arg(adapter->address());
adaptersGroup.writeEntry<bool>(key, adapter->isPowered());
}
d->m_config->sync();
}
// New adapters are automatically powered on
void BlueDevilDaemon::restoreAdaptersState()
{
Manager *manager = Manager::self();
if (!manager) {
return;
}
KConfigGroup adaptersGroup = d->m_config->group("Adapters");
Q_FOREACH (Adapter *adapter, manager->adapters()) {
const QString key = QString("%1_powered").arg(adapter->address());
adapter->setPowered(adaptersGroup.readEntry<bool>(key, true));
}
}
void BlueDevilDaemon::restoreAdapterState(Adapter *adapter)
{
KConfigGroup adaptersGroup = d->m_config->group("Adapters");
const QString key = QString("%1_powered").arg(adapter->address());
adapter->setPowered(adaptersGroup.readEntry<bool>(key, true));
}
DeviceInfo BlueDevilDaemon::deviceToInfo(Device *const device) const
{
DeviceInfo info;
info["name"] = device->friendlyName();
info["icon"] = device->icon();
info["address"] = device->address();
info["discovered"] = "true";
info["UBI"] = device->UBI();
info["UUIDs"] = device->UUIDs().join(",");
return info;
}

View file

@ -50,16 +50,30 @@ public:
virtual ~BlueDevilDaemon();
public Q_SLOTS:
/**
* Returns whether the daemon is in online mode (eg. Bluez services are
* running and we have usable adapter)
*/
Q_SCRIPTABLE bool isOnline();
/**
* This slot will return a list of devices made of: configured and discovered devices.
* Going deeper, the first time that this slot is called a discovery of X seconds will start
* Then if this slot is consulted again it will return configured and discovered device. Once
* the discovery ends it won't start a new discovery until N seconds pass.
* Returns QMap<Address, DeviceInfo> with all known devices
*/
Q_SCRIPTABLE QMapDeviceInfo knownDevices();
Q_SCRIPTABLE QMapDeviceInfo allDevices();
/**
* Returns DeviceInfo for one device.
*/
Q_SCRIPTABLE DeviceInfo device(const QString &address);
/**
* Starts discovery for timeout miliseconds (0 = forever)
*/
Q_SCRIPTABLE void startDiscovering(quint32 timeout);
/**
* Stops discovery (if it was previously started)
*/
Q_SCRIPTABLE void stopDiscovering();
private:
@ -82,6 +96,9 @@ private Q_SLOTS:
*/
void usableAdapterChanged(Adapter *adapter);
void adapterAdded(Adapter *adapter);
void adapterRemoved(Adapter *adapter);
/**
* When the agent is released this is called to unload it
*/
@ -97,7 +114,11 @@ private:
void executeMonolithic();
void killMonolithic();
DeviceInfo deviceToInfo (Device *const device) const;
void saveAdaptersState();
void restoreAdaptersState();
void restoreAdapterState(Adapter *adapter);
DeviceInfo deviceToInfo(Device *const device) const;
private:
struct Private;

View file

@ -34,44 +34,45 @@
#include <KProcess>
#include <KLocalizedString>
#include <bluedevil/bluedevil.h>
using namespace BlueDevil;
K_PLUGIN_FACTORY(SendFileItemActionFactory, registerPlugin<SendFileItemAction>();)
K_EXPORT_PLUGIN(SendFileItemActionFactory("SendFileItemAction", "bluedevil"))
SendFileItemAction::SendFileItemAction(QObject* parent, const QVariantList& args): KFileItemActionPlugin(parent)
SendFileItemAction::SendFileItemAction(QObject *parent, const QVariantList &args)
: KFileItemActionPlugin(parent)
{
Q_UNUSED(args)
qDBusRegisterMetaType<DeviceInfo>();
qDBusRegisterMetaType<QMapDeviceInfo>();
m_kded = new org::kde::BlueDevil("org.kde.kded", "/modules/bluedevil",
QDBusConnection::sessionBus(), this);
}
QList< QAction* > SendFileItemAction::actions(const KFileItemListProperties& fileItemInfos, QWidget* parentWidget) const
QList<QAction*> SendFileItemAction::actions(const KFileItemListProperties &fileItemInfos, QWidget *parentWidget) const
{
Q_UNUSED(parentWidget)
QList< QAction* > list;
QList<QAction*> list;
// Don't show the action for files that we can't send or when Bluetooth is offline.
if (!fileItemInfos.isLocal() || !m_kded->isOnline()) {
return list;
}
SendFileItemAction *hack = const_cast<SendFileItemAction*>(this);
hack->m_fileItemInfos = fileItemInfos;
//If there is no adaptor, there is no bluetooth
if (!Manager::self()->usableAdapter()) {
return list;
}
Adapter *adapter = Manager::self()->usableAdapter();
QAction *menuAction = new QAction(KIcon("preferences-system-bluetooth"), i18n("Send via Bluetooth"), hack);
QMenu *menu = new QMenu();
//If we have configured devices, put them first
QList< Device * > devices = adapter->devices();
if (!devices.isEmpty()) {
Q_FOREACH(Device *device, devices) {
if (device->UUIDs().contains("00001105-0000-1000-8000-00805F9B34FB", Qt::CaseInsensitive)) {
QAction *action = new QAction(KIcon(device->icon()), device->name(), hack);
connect(action, SIGNAL(triggered(bool)), this, SLOT(deviceTriggered()));
action->setData(device->UBI());
menu->addAction(action);
}
const QMapDeviceInfo &devices = m_kded->allDevices().value();
Q_FOREACH (const DeviceInfo &device, devices) {
if (device["UUIDs"].contains("00001105-0000-1000-8000-00805F9B34FB")) {
QAction *action = new QAction(KIcon(device["icon"]), device["name"], hack);
connect(action, SIGNAL(triggered(bool)), this, SLOT(deviceTriggered()));
action->setData(device["UBI"]);
menu->addAction(action);
}
}

View file

@ -24,23 +24,26 @@
#include <kfileitemactionplugin.h>
#include <KFileItemListProperties>
#include "kded_bluedevil.h"
class QAction;
class KFileItemListProperties;
class QWidget;
class SendFileItemAction : public KFileItemActionPlugin
{
Q_OBJECT
Q_OBJECT
public:
SendFileItemAction(QObject* parent, const QVariantList &args);
virtual QList< QAction* > actions(const KFileItemListProperties& fileItemInfos, QWidget* parentWidget) const;
virtual QList<QAction*> actions(const KFileItemListProperties &fileItemInfos, QWidget *parentWidget) const;
private Q_SLOTS:
void deviceTriggered();
void otherTriggered();
private:
org::kde::BlueDevil *m_kded;
KFileItemListProperties m_fileItemInfos;
};
#endif // SENDFILEITEMACTION_H
#endif // SENDFILEITEMACTION_H

View file

@ -61,8 +61,8 @@ AdapterSettings::AdapterSettings(Adapter *adapter, KCModule *parent)
buttonGroup->addButton(m_alwaysVisible);
buttonGroup->addButton(m_temporaryVisible);
m_name->setText(adapter->alias());
m_nameOrig = adapter->alias();
m_name->setText(adapter->name());
m_nameOrig = adapter->name();
m_hiddenOrig = false;
m_alwaysVisibleOrig = false;
m_temporaryVisibleOrig = false;
@ -118,9 +118,9 @@ AdapterSettings::AdapterSettings(Adapter *adapter, KCModule *parent)
connect(m_powered, SIGNAL(stateChanged(int)), this, SLOT(slotSettingsChanged()));
if (BlueDevil::Manager::self()->usableAdapter() == adapter) {
setTitle(i18n("Default adapter: %1 (%2)", adapter->alias(), adapter->address()));
setTitle(i18n("Default adapter: %1 (%2)", adapter->systemName(), adapter->address()));
} else {
setTitle(i18n("Adapter: %1 (%2)", adapter->alias(), adapter->address()));
setTitle(i18n("Adapter: %1 (%2)", adapter->systemName(), adapter->address()));
}
}
@ -135,13 +135,12 @@ bool AdapterSettings::isModified() const
m_temporaryVisible->isChecked() != m_temporaryVisibleOrig ||
m_discoverTime->value() != m_discoverTimeOrig || m_powered->isChecked() != m_poweredOrig;
}
#include <QDebug>
void AdapterSettings::applyChanges()
{
if (m_name->text() != m_nameOrig) {
qDebug() << "Setting alias";
m_adapter->setAlias(m_name->text());
}
m_adapter->setName(m_name->text());
}
if (m_hidden->isChecked()) {
m_adapter->setDiscoverable(false);
@ -188,7 +187,7 @@ void AdapterSettings::readChanges()
{
blockSignals(true);
m_nameOrig = m_adapter->alias();
m_nameOrig = m_adapter->name();
m_hiddenOrig = !m_adapter->isDiscoverable();
m_alwaysVisibleOrig = m_adapter->isDiscoverable() && !m_adapter->discoverableTimeout();
m_temporaryVisibleOrig = m_adapter->isDiscoverable() && m_adapter->discoverableTimeout();
@ -204,9 +203,9 @@ void AdapterSettings::readChanges()
m_discoverTimeLabel->setText(i18np("1 minute", "%1 minutes", m_discoverTime->value()));
if (BlueDevil::Manager::self()->usableAdapter() == m_adapter) {
setTitle(i18n("Default adapter: %1 (%2)", m_adapter->alias(), m_adapter->address()));
setTitle(i18n("Default adapter: %1 (%2)", m_adapter->systemName(), m_adapter->address()));
} else {
setTitle(i18n("Adapter: %1 (%2)", m_adapter->alias(), m_adapter->address()));
setTitle(i18n("Adapter: %1 (%2)", m_adapter->systemName(), m_adapter->address()));
}
blockSignals(false);

View file

@ -32,6 +32,7 @@
#include <kcolorscheme.h>
#include <kstandarddirs.h>
#include <klocalizedstring.h>
#include <kmessagewidget.h>
#include <QtGui/QLabel>
#include <QtGui/QWidget>
@ -39,93 +40,12 @@
#include <QtGui/QBoxLayout>
#include <QtGui/QPaintEvent>
#if KDE_IS_VERSION(4,6,41)
#include <kmessagewidget.h>
#else
class ErrorWidget
: public QWidget
{
public:
ErrorWidget(QWidget *parent = 0);
virtual ~ErrorWidget();
void setIcon(const QString &icon);
void setText(const QString &reason);
void addAction(KPushButton *action);
protected:
virtual void paintEvent(QPaintEvent *event);
private:
QLabel *m_icon;
QLabel *m_reason;
QHBoxLayout *m_actions;
};
ErrorWidget::ErrorWidget(QWidget *parent)
: QWidget(parent)
, m_icon(new QLabel(this))
, m_reason(new QLabel(this))
, m_actions(new QHBoxLayout)
{
setAutoFillBackground(false);
m_actions->addStretch();
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(m_icon);
layout->addWidget(m_reason, 1);
QVBoxLayout *outter = new QVBoxLayout;
outter->addLayout(layout);
outter->addLayout(m_actions);
setLayout(outter);
}
ErrorWidget::~ErrorWidget()
{
}
void ErrorWidget::setIcon(const QString &icon)
{
m_icon->setPixmap(KIconLoader::global()->loadIcon(icon, KIconLoader::Dialog));
}
void ErrorWidget::setText(const QString &reason)
{
m_reason->setText(reason);
}
void ErrorWidget::addAction(KPushButton *action)
{
action->setAutoFillBackground(false);
m_actions->addWidget(action);
}
void ErrorWidget::paintEvent(QPaintEvent *event)
{
const QRect r = event->rect();
const KColorScheme colorScheme(QPalette::Active, KColorScheme::Window);
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
QPainterPath path;
path.addRoundedRect(0, 0, r.width(), r.height(), 10, 10);
p.fillPath(path, colorScheme.background(KColorScheme::NegativeBackground));
QWidget::paintEvent(event);
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
SystemCheck::SystemCheck(QWidget *parent)
: QObject(parent)
, m_kded(new KDED("org.kde.kded", "/kded", QDBusConnection::sessionBus()))
, m_parent(parent)
, m_noAdaptersError(0)
, m_noUsableAdapterError(0)
, m_notDiscoverableAdapterError(0)
, m_disabledNotificationsError(0)
{
@ -133,9 +53,6 @@ SystemCheck::SystemCheck(QWidget *parent)
SystemCheck::~SystemCheck()
{
m_noAdaptersError = 0;
m_notDiscoverableAdapterError = 0;
m_disabledNotificationsError = 0;
delete m_kded;
}
@ -145,18 +62,22 @@ void SystemCheck::createWarnings(QVBoxLayout *layout)
return;
}
#if KDE_IS_VERSION(4,6,41)
m_noAdaptersError = new KMessageWidget(m_parent);
m_noAdaptersError->setMessageType(KMessageWidget::Error);
m_noAdaptersError->setCloseButtonVisible(false);
#else
m_noAdaptersError = new ErrorWidget(m_parent);
m_noAdaptersError->setIcon("window-close");
#endif
m_noAdaptersError->setText(i18n("No Bluetooth adapters have been found."));
layout->addWidget(m_noAdaptersError);
#if KDE_IS_VERSION(4,6,41)
m_noUsableAdapterError = new KMessageWidget(m_parent);
m_noUsableAdapterError->setMessageType(KMessageWidget::Warning);
m_noUsableAdapterError->setCloseButtonVisible(false);
m_noUsableAdapterError->setText(i18n("Your Bluetooth adapter is powered off."));
KAction *fixNoUsableAdapter = new KAction(KIcon("dialog-ok-apply"), i18nc("Action to fix a problem", "Fix it"), m_noUsableAdapterError);
connect(fixNoUsableAdapter, SIGNAL(triggered(bool)), this, SLOT(fixNoUsableAdapterError()));
m_noUsableAdapterError->addAction(fixNoUsableAdapter);
layout->addWidget(m_noUsableAdapterError);
m_notDiscoverableAdapterError = new KMessageWidget(m_parent);
m_notDiscoverableAdapterError->setMessageType(KMessageWidget::Warning);
m_notDiscoverableAdapterError->setCloseButtonVisible(false);
@ -164,19 +85,10 @@ void SystemCheck::createWarnings(QVBoxLayout *layout)
KAction *fixNotDiscoverableAdapter = new KAction(KIcon("dialog-ok-apply"), i18nc("Action to fix a problem", "Fix it"), m_notDiscoverableAdapterError);
connect(fixNotDiscoverableAdapter, SIGNAL(triggered(bool)), this, SLOT(fixNotDiscoverableAdapterError()));
m_notDiscoverableAdapterError->addAction(fixNotDiscoverableAdapter);
#else
m_notDiscoverableAdapterError = new ErrorWidget(m_parent);
m_notDiscoverableAdapterError->setIcon("edit-find");
KPushButton *fixNotDiscoverableAdapter = new KPushButton(KIcon("dialog-ok-apply"), i18nc("Action to fix a problem", "Fix it"), m_notDiscoverableAdapterError);
connect(fixNotDiscoverableAdapter, SIGNAL(clicked()), this, SLOT(fixNotDiscoverableAdapterError()));
m_notDiscoverableAdapterError->addAction(fixNotDiscoverableAdapter);
#endif
m_notDiscoverableAdapterError->setText(i18n("Your default Bluetooth adapter is not visible for remote devices."));
layout->addWidget(m_notDiscoverableAdapterError);
#if KDE_IS_VERSION(4,6,41)
m_disabledNotificationsError = new KMessageWidget(m_parent);
m_disabledNotificationsError->setMessageType(KMessageWidget::Warning);
m_disabledNotificationsError->setCloseButtonVisible(false);
@ -184,19 +96,10 @@ void SystemCheck::createWarnings(QVBoxLayout *layout)
KAction *fixDisabledNotifications = new KAction(KIcon("dialog-ok-apply"), i18nc("Action to fix a problem", "Fix it"), m_disabledNotificationsError);
connect(fixDisabledNotifications, SIGNAL(triggered(bool)), this, SLOT(fixDisabledNotificationsError()));
m_disabledNotificationsError->addAction(fixDisabledNotifications);
#else
m_disabledNotificationsError = new ErrorWidget(m_parent);
m_disabledNotificationsError->setIcon("preferences-desktop-notification");
KPushButton *fixDisabledNotifications = new KPushButton(KIcon("dialog-ok-apply"), i18nc("Action to fix a problem", "Fix it"), m_disabledNotificationsError);
connect(fixDisabledNotifications, SIGNAL(clicked()), this, SLOT(fixDisabledNotificationsError()));
m_disabledNotificationsError->addAction(fixDisabledNotifications);
#endif
m_disabledNotificationsError->setText(i18n("Interaction with Bluetooth system is not optimal."));
layout->addWidget(m_disabledNotificationsError);
#if KDE_IS_VERSION(4,6,41)
m_noKDEDRunning = new KMessageWidget(m_parent);
m_noKDEDRunning ->setMessageType(KMessageWidget::Warning);
m_noKDEDRunning->setCloseButtonVisible(false);
@ -204,14 +107,6 @@ void SystemCheck::createWarnings(QVBoxLayout *layout)
KAction *fixNoKDEDRunning = new KAction(KIcon("dialog-ok-apply"), i18nc("Action to fix a problem", "Fix it"), m_noKDEDRunning);
connect(fixNoKDEDRunning, SIGNAL(triggered(bool)), this, SLOT(fixNoKDEDRunning()));
m_noKDEDRunning->addAction(fixNoKDEDRunning);
#else
m_noKDEDRunning = new ErrorWidget(m_parent);
m_noKDEDRunning->setIcon("dialog-warning");
KPushButton *fixNoKDEDRunning = new KPushButton(KIcon("dialog-ok-apply"), i18nc("Action to fix a problem", "Fix it"), m_noKDEDRunning);
connect(fixNoKDEDRunning, SIGNAL(clicked()), this, SLOT(fixNoKDEDRunning()));
m_noKDEDRunning->addAction(fixNoKDEDRunning);
#endif
m_noKDEDRunning->setText(i18n("Bluetooth is not completely enabled."));
layout->addWidget(m_noKDEDRunning);
@ -259,6 +154,7 @@ void SystemCheck::updateInformationState()
{
m_noAdaptersError->setEnabled(true);
m_noAdaptersError->setVisible(false);
m_noUsableAdapterError->setVisible(false);
m_notDiscoverableAdapterError->setVisible(false);
m_disabledNotificationsError->setVisible(false);
m_noKDEDRunning->setVisible(false);
@ -268,9 +164,14 @@ void SystemCheck::updateInformationState()
return;
}
if (BlueDevil::Manager::self()->adapters().isEmpty()) {
m_noAdaptersError->setVisible(true);
return;
}
BlueDevil::Adapter *const usableAdapter = BlueDevil::Manager::self()->usableAdapter();
if (!usableAdapter) {
m_noAdaptersError->setVisible(true);
m_noUsableAdapterError->setVisible(true);
return;
}
if (!usableAdapter->isDiscoverable()) {
@ -293,6 +194,12 @@ void SystemCheck::fixNoKDEDRunning()
m_kded->loadModule("bluedevil");
}
void SystemCheck::fixNoUsableAdapterError()
{
m_noUsableAdapterError->setVisible(false);
BlueDevil::Manager::self()->adapters().first()->setPowered(true);
}
void SystemCheck::fixNotDiscoverableAdapterError()
{
m_notDiscoverableAdapterError->setVisible(false);

View file

@ -22,19 +22,12 @@
#define BLUEDEVIL_SYSTEM_CHECK_H
#include <QtCore/QObject>
#include <kdeversion.h>
class QVBoxLayout;
class KDED;
#if KDE_IS_VERSION(4,6,41)
class KMessageWidget;
#else
class ErrorWidget;
#endif
class SystemCheck
: public QObject
class SystemCheck : public QObject
{
Q_OBJECT
@ -42,17 +35,6 @@ public:
SystemCheck(QWidget *parent);
virtual ~SystemCheck();
struct SystemCheckResult {
enum Result {
NoWarnings = 0,
BluetoothDisabled,
NoAdapters,
NotificationsDisabled,
DefaultAdapterHidden
} result;
QWidget *warningWidget;
};
void createWarnings(QVBoxLayout *layout);
bool checkKDEDModuleLoaded();
@ -67,23 +49,18 @@ public Q_SLOTS:
private Q_SLOTS:
void fixNoKDEDRunning();
void fixNoUsableAdapterError();
void fixNotDiscoverableAdapterError();
void fixDisabledNotificationsError();
private:
KDED *m_kded;
QWidget *m_parent;
#if KDE_IS_VERSION(4,6,41)
KMessageWidget *m_noAdaptersError;
KMessageWidget *m_noUsableAdapterError;
KMessageWidget *m_noKDEDRunning;
KMessageWidget *m_notDiscoverableAdapterError;
KMessageWidget *m_disabledNotificationsError;
#else
ErrorWidget *m_noAdaptersError;
ErrorWidget *m_noKDEDRunning;
ErrorWidget *m_notDiscoverableAdapterError;
ErrorWidget *m_disabledNotificationsError;
#endif
};
#endif //BLUEDEVIL_SYSTEM_CHECK_H
#endif //BLUEDEVIL_SYSTEM_CHECK_H

View file

@ -5,11 +5,19 @@
<method name="isOnline">
<arg type="b" direction="out"/>
</method>
<method name="knownDevices">
<method name="allDevices">
<arg type="aa{ss}" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QMapDeviceInfo"/>
</method>
<method name="device">
<arg name="address" type="s" direction="in"/>
<arg type="a{ss}" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="DeviceInfo"/>
</method>
<method name="startDiscovering">
<arg name="timeout" type="u" direction="in"/>
</method>
<method name="stopDiscovering">
</method>
</interface>
</node>
</node>

View file

@ -35,10 +35,6 @@
#include <KApplication>
#include <KLocale>
#include <bluedevil/bluedevil.h>
using namespace BlueDevil;
extern "C" int KDE_EXPORT kdemain(int argc, char **argv)
{
KAboutData about("kiobluetooth", "bluedevil", ki18n("kiobluetooth"), bluedevil_version);
@ -70,19 +66,19 @@ KioBluetooth::KioBluetooth(const QByteArray &pool, const QByteArray &app)
s.mimetype = "application/vnd.kde.bluedevil-sendfile";
s.uuid = "00001105-0000-1000-8000-00805F9B34FB";
m_supportedServices.insert("00001105-0000-1000-8000-00805F9B34FB", s);
s.name = i18n("Browse Files");
s.icon = "edit-find";
s.mimetype = "";
s.mimetype = QString();
s.uuid = "00001106-0000-1000-8000-00805F9B34FB";
m_supportedServices.insert("00001106-0000-1000-8000-00805F9B34FB", s);
kDebug() << "Kio Bluetooth instanced!";
m_kded = new org::kde::BlueDevil("org.kde.kded", "/modules/bluedevil", QDBusConnection::sessionBus(), 0);
if (!Manager::self()->usableAdapter()) {
kDebug() << "No available interface";
if (!m_kded->isOnline()) {
kDebug() << "Bluetooth is offline";
infoMessage(i18n("No Bluetooth adapters have been found."));
return;
}
}
@ -100,14 +96,22 @@ QList<KioBluetooth::Service> KioBluetooth::getSupportedServices(const QStringLis
void KioBluetooth::listRemoteDeviceServices()
{
m_kded->stopDiscovering();
infoMessage(i18n("Retrieving services..."));
kDebug() << "Listing remote devices";
m_currentHost = Manager::self()->usableAdapter()->deviceForAddress(m_currentHostname.replace('-', ':').toUpper());
m_currentHostServices = getSupportedServices(m_currentHost->UUIDs());
const DeviceInfo &info = m_kded->device(m_currentHostAddress).value();
if (info.isEmpty()) {
kDebug() << "Invalid hostname!";
infoMessage(i18n("This address is unavailable."));
finished();
return;
}
m_currentHostServices = getSupportedServices(info.value("UUIDs").split(','));
kDebug() << "Num of supported services: " << m_currentHostServices.size();
totalSize(m_currentHostServices.count());
int i = 1;
Q_FOREACH (const Service &service, m_currentHostServices) {
@ -138,19 +142,24 @@ void KioBluetooth::listRemoteDeviceServices()
}
listEntry(KIO::UDSEntry(), true);
infoMessage("");
infoMessage(QString());
finished();
}
void KioBluetooth::listDevices()
{
kDebug() << "Asking kded for devices";
QMapDeviceInfo devices = m_kded->knownDevices().value();
QMapDeviceInfo devices = m_kded->allDevices().value();
kDebug() << devices.keys();
Q_FOREACH(const DeviceInfo device, devices) {
listDevice(device);
}
listEntry(KIO::UDSEntry(), true);
m_kded->startDiscovering(10 * 1000);
infoMessage(i18n("Scanning for new devices..."));
finished();
}
@ -215,24 +224,25 @@ void KioBluetooth::get(const KUrl &url)
finished();
}
void KioBluetooth::setHost(const QString &constHostname, quint16 port, const QString &user,
void KioBluetooth::setHost(const QString &hostname, quint16 port, const QString &user,
const QString &pass)
{
kDebug() << "Setting host: " << constHostname;
kDebug() << "Setting host: " << hostname;
// In this kio only the hostname (constHostname) is used
Q_UNUSED(port)
Q_UNUSED(user)
Q_UNUSED(pass)
QString hostname = constHostname;
hostname = hostname.replace('-', ':').toUpper();
if (hostname.isEmpty()) {
m_hasCurrentHost = false;
} else {
m_hasCurrentHost = true;
m_currentHostname = constHostname;
m_currentHostServices.clear();
m_currentHostname = hostname;
m_currentHostAddress = hostname.toUpper();
m_currentHostAddress.replace(QLatin1Char('-'), QLatin1Char(':'));
}
}

View file

@ -33,13 +33,6 @@
*/
class KioBluetoothPrivate;
namespace BlueDevil {
class Device;
class Adapter;
}
using namespace BlueDevil;
class KioBluetooth : public QObject, public KIO::SlaveBase
{
Q_OBJECT
@ -78,7 +71,7 @@ public:
* difference with @p listDir
*
*/
void setHost(const QString &constHostname, quint16 port, const QString &user, const QString &pass);
void setHost(const QString &hostname, quint16 port, const QString &user, const QString &pass);
/**
* Returns a list of supported service names corresponding to the given uuids list. If an uuid is
@ -117,10 +110,9 @@ private:
QString m_currentHostname;
/**
* Represents the current host when @p hasCurrentHost is set to true. This is set in
* @p listRemoteDeviceServices function.
* Uppercase colon separated address (ex. 00:2A:5E:8E:6E:F5)
*/
Device *m_currentHost;
QString m_currentHostAddress;
/**
* When @p hasCurrentHost to true, this list holds the list of service names provided by the
@ -128,12 +120,6 @@ private:
*/
QList<Service> m_currentHostServices;
/**
* This is an array containing as key the uuid and as value the name of the service that the
* given uuid represents.
*/
QMap<QString, QString> m_serviceNames;
/**
* This is an array containing as key the uuid and as value the name of the service that the
* given uuid represents, and a representative icon. It only contains the supported service names.
@ -146,4 +132,4 @@ private:
org::kde::BlueDevil *m_kded;
};
#endif // KIOBLUETOOTH_H
#endif // KIOBLUETOOTH_H

View file

@ -29,10 +29,6 @@
#include <KAboutData>
#include <KPluginFactory>
#include <bluedevil/bluedevilmanager.h>
#include <bluedevil/bluedeviladapter.h>
using namespace BlueDevil;
K_PLUGIN_FACTORY(ObexFtpFactory,
registerPlugin<ObexFtpDaemon>();)
K_EXPORT_PLUGIN(ObexFtpFactory("obexftpdaemon", "obexftpdaemon"))
@ -55,7 +51,8 @@ ObexFtpDaemon::ObexFtpDaemon(QObject *parent, const QList<QVariant>&)
: KDEDModule(parent)
, d(new Private)
{
d->m_status = Private::Offline;
qDBusRegisterMetaType<DBusManagerStruct>();
qDBusRegisterMetaType<QVariantMapMap>();
KAboutData aboutData(
"obexftpdaemon",
@ -70,23 +67,21 @@ ObexFtpDaemon::ObexFtpDaemon(QObject *parent, const QList<QVariant>&)
aboutData.addAuthor(ki18n("Alejandro Fiestas Olivares"), ki18n("Maintainer"), "afiestas@kde.org",
"http://www.afiestas.org");
connect(Manager::self(), SIGNAL(usableAdapterChanged(Adapter*)),
SLOT(usableAdapterChanged(Adapter*)));
d->m_status = Private::Offline;
d->m_interface = new OrgFreedesktopDBusObjectManagerInterface("org.bluez.obex", "/", QDBusConnection::sessionBus(), this);
connect(d->m_interface, SIGNAL(InterfacesRemoved(QDBusObjectPath,QStringList)),
SLOT(interfaceRemoved(QDBusObjectPath,QStringList)));
d->m_serviceWatcher = new QDBusServiceWatcher("org.bluez.obex", QDBusConnection::sessionBus(),
QDBusServiceWatcher::WatchForUnregistration, this);
QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration, this);
connect(d->m_serviceWatcher, SIGNAL(serviceUnregistered(QString)), SLOT(serviceUnregistered(QString)));
connect(d->m_serviceWatcher, SIGNAL(serviceRegistered(QString)), SLOT(serviceRegistered()));
connect(d->m_serviceWatcher, SIGNAL(serviceUnregistered(QString)), SLOT(serviceUnregistered()));
qDBusRegisterMetaType<DBusManagerStruct>();
qDBusRegisterMetaType<QVariantMapMap>();
//WARNING this blocks if org.bluez in system bus is dead
if (Manager::self()->usableAdapter()) {
if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.bluez.obex")) {
onlineMode();
} else {
offlineMode();
}
}
@ -111,7 +106,7 @@ void ObexFtpDaemon::onlineMode()
void ObexFtpDaemon::offlineMode()
{
kDebug(dobex()) << "Offline mode";
kDebug(dobex());
if (d->m_status == Private::Offline) {
kDebug(dobex()) << "Already in offlineMode";
return;
@ -123,27 +118,24 @@ void ObexFtpDaemon::offlineMode()
d->m_status = Private::Offline;
}
void ObexFtpDaemon::usableAdapterChanged(Adapter *adapter)
bool ObexFtpDaemon::isOnline()
{
if (!adapter) {
offlineMode();
return;
}
onlineMode();
return d->m_status == Private::Online;
}
QString ObexFtpDaemon::session(QString address, const QDBusMessage& msg)
{
kDebug(dobex()) << address;
address.replace("-", ":");
if(d->m_sessionMap.contains(address)) {
if (d->m_sessionMap.contains(address)) {
return d->m_sessionMap[address];
}
//At this point we always want delayed reply
kDebug(dobex()) << "Creating session for" << address;
// At this point we always want delayed reply
msg.setDelayedReply(true);
if (d->m_wipSessions.contains(address)) {
d->m_wipSessions[address]->addMessage(msg);
return QString();
@ -157,30 +149,46 @@ QString ObexFtpDaemon::session(QString address, const QDBusMessage& msg)
return QString();
}
bool ObexFtpDaemon::cancelTransfer(const QString &transfer)
{
// We need this function because kio_obexftp is not owner of the transfer,
// and thus cannot cancel it.
QDBusMessage call = QDBusMessage::createMethodCall("org.bluez.obex",
transfer,
"org.bluez.obex.Transfer1",
"Cancel");
QDBusReply<void> reply = QDBusConnection::sessionBus().call(call);
return reply.isValid();
}
void ObexFtpDaemon::sessionCreated(KJob* job)
{
CreateSessionJob* cJob = qobject_cast<CreateSessionJob*>(job);
kDebug(dobex()) << cJob->path();
d->m_wipSessions.remove(cJob->address());
d->m_sessionMap.insert(cJob->address(), cJob->path());
d->m_reverseSessionMap.insert(cJob->path(), cJob->address());
const QList<QDBusMessage> messages = cJob->messages();
Q_FOREACH(const QDBusMessage &msg, messages) {
Q_FOREACH (const QDBusMessage &msg, cJob->messages()) {
QDBusMessage reply = msg.createReply(cJob->path());
QDBusConnection::sessionBus().asyncCall(reply);
QDBusConnection::sessionBus().send(reply);
}
if (!cJob->error()) {
d->m_sessionMap.insert(cJob->address(), cJob->path());
d->m_reverseSessionMap.insert(cJob->path(), cJob->address());
}
}
void ObexFtpDaemon::serviceUnregistered(const QString& service)
void ObexFtpDaemon::serviceRegistered()
{
if (service != QLatin1String("org.bluez.obex")) {
return;
}
onlineMode();
}
d->m_sessionMap.clear();
d->m_reverseSessionMap.clear();
void ObexFtpDaemon::serviceUnregistered()
{
offlineMode();
}
void ObexFtpDaemon::interfaceRemoved(const QDBusObjectPath &dbusPath, const QStringList& interfaces)
@ -197,4 +205,4 @@ void ObexFtpDaemon::interfaceRemoved(const QDBusObjectPath &dbusPath, const QStr
kDebug(dobex()) << d->m_sessionMap.remove(address);
}
extern int dobex() { static int s_area = KDebug::registerArea("ObexDaemon", false); return s_area; }
extern int dobex() { static int s_area = KDebug::registerArea("ObexDaemon", false); return s_area; }

View file

@ -28,44 +28,28 @@ class KJob;
class QDBusMessage;
class QDBusPendingCallWatcher;
namespace BlueDevil {
class Adapter;
};
using namespace BlueDevil;
class KDE_EXPORT ObexFtpDaemon
: public KDEDModule
class KDE_EXPORT ObexFtpDaemon : public KDEDModule
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.ObexFtp")
public:
/**
* Connects to usableAdapterChanged
*/
ObexFtpDaemon(QObject *parent, const QList<QVariant>&);
virtual ~ObexFtpDaemon();
public Q_SLOTS:
Q_SCRIPTABLE bool isOnline();
Q_SCRIPTABLE QString session(QString address, const QDBusMessage &msg);
Q_SCRIPTABLE bool cancelTransfer(const QString &transfer);
private Q_SLOTS:
void usableAdapterChanged(Adapter* adapter);
void sessionCreated(KJob* job);
void serviceUnregistered(const QString &service);
void serviceRegistered();
void serviceUnregistered();
void interfaceRemoved(const QDBusObjectPath &path, const QStringList &interfaces);
private:
/**
* Called by constructor or eventually by adapterAdded initialize all the helpers
* @see helpers
*/
void onlineMode();
/**
* Called eventually adapterRemoved shutdown all the helpers
* @see helpers
*/
void onlineMode();
void offlineMode();
struct Private;

View file

@ -63,15 +63,12 @@ void CreateSessionJob::createSession()
kDebug(dobex());
QVariantMap args;
args["Target"] = "ftp";
// args["Source"] = "00:02:72:D6:8F:2C";
m_client = new OrgBluezObexClient1Interface("org.bluez.obex",
"/org/bluez/obex",
QDBusConnection::sessionBus(), this);
QDBusPendingReply <QDBusObjectPath > reply = m_client->CreateSession(m_address, args);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply);
kDebug(dobex()) << "DROGUES";
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(sessionCreated(QDBusPendingCallWatcher*)));
}
@ -84,12 +81,6 @@ void CreateSessionJob::sessionCreated(QDBusPendingCallWatcher* watcher)
kDebug(dobex()) << "Error:";
kDebug(dobex()) << reply.error().name();
kDebug(dobex()) << reply.error().message();
// Q_FOREACH(const QDBusMessage &msg, m_msgs) {
// kDebug(dobex()) << msg.service() << msg.path();
// QDBusMessage errorMsg = msg.createErrorReply("org.kde.kded.Error", i18n("Can't stablish connection"));
// QDBusConnection::sessionBus().send(errorMsg);
// }C
// m_status = Error;
setError(reply.error().type());
setErrorText(reply.error().message());
emitResult();
@ -98,4 +89,4 @@ void CreateSessionJob::sessionCreated(QDBusPendingCallWatcher* watcher)
m_path = reply.value().path();
emitResult();
}
}

View file

@ -3,9 +3,16 @@
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.kde.ObexFtp">
<method name="isOnline">
<arg name="online" type="b" direction="out"/>
</method>
<method name="session">
<arg name="address" type="s" direction="in"/>
<arg name="sessionPath" type="s" direction="out"/>
</method>
<method name="cancelTransfer">
<arg name="transfer" type="s" direction="in"/>
<arg name="success" type="b" direction="out"/>
</method>
</interface>
</node>
</node>

View file

@ -52,12 +52,15 @@ extern "C" int KDE_EXPORT kdemain(int argc, char **argv)
return 0;
}
static bool urlIsRoot(const KUrl &url)
{
return (url.directory() == QLatin1String("/") || url.directory().isEmpty()) && url.fileName().isEmpty();
}
KioFtp::KioFtp(const QByteArray &pool, const QByteArray &app)
: SlaveBase("obexftp", pool, app)
, m_transfer(0)
{
m_settingHost = false;
m_timer = new QTimer();
m_timer->setInterval(100);
@ -78,6 +81,47 @@ void KioFtp::launchProgressBar()
m_timer->start();
}
void KioFtp::connectToHost()
{
QDBusPendingReply<QString> reply = m_kded->session(m_host);
reply.waitForFinished();
const QString &sessionPath = reply.value();
if (reply.isError() || sessionPath.isEmpty()) {
kDebug() << reply.error().message();
kDebug() << reply.error().name();
delete m_transfer;
m_transfer = 0;
m_sessionPath.clear();
return;
}
if (m_sessionPath != sessionPath) {
m_statMap.clear();
delete m_transfer;
m_transfer = new org::bluez::obex::FileTransfer1("org.bluez.obex", sessionPath, QDBusConnection::sessionBus());
m_sessionPath = sessionPath;
}
}
bool KioFtp::testConnection()
{
if (!m_kded->isOnline().value()) {
error(KIO::ERR_SLAVE_DEFINED, i18n("Obexd service is not running."));
return false;
}
connectToHost();
if (!m_transfer) {
error(KIO::ERR_COULD_NOT_CONNECT, m_host);
return false;
}
return true;
}
void KioFtp::updateProcess()
{
if (m_counter == 49) {
@ -92,35 +136,27 @@ void KioFtp::updateProcess()
void KioFtp::listDir(const KUrl &url)
{
if (!testConnection()) {
return;
}
kDebug() << "listdir: " << url;
infoMessage(i18n("Retrieving information from remote device..."));
kDebug() << "Asking for listFolder";
kDebug() << "Asking for listFolder" << url.path();
//TODO: Check if changeFolder fails
m_transfer->ChangeFolder(url.path()).waitForFinished();
QDBusPendingReply <QVariantMapList > reply = m_transfer->ListFolder();
reply.waitForFinished();
if (reply.isError()) {
kDebug() << reply.error().message();
error(KIO::ERR_SLAVE_DEFINED, i18n("Bluetooth is not enabled"));
finished();
if (!changeFolder(url.path())) {
return;
}
QVariantMapList folderList = reply.value();
Q_FOREACH(const QVariantMap folder, folderList) {
KIO::UDSEntry entry = entryFromInfo(folder);
KUrl statUrl(url);
statUrl.setFileName(folder["Name"].toString());
if (!m_statMap.contains(statUrl.prettyUrl())) {
kDebug() << "Stat: " << statUrl.prettyUrl() << entry.numberValue(KIO::UDSEntry::UDS_SIZE);
m_statMap.insert(statUrl.prettyUrl(), entry);
}
bool ok;
const QList<KIO::UDSEntry> &list = listFolder(url, &ok);
if (!ok) {
return;
}
Q_FOREACH (const KIO::UDSEntry &entry, list) {
listEntry(entry, false);
}
@ -133,11 +169,13 @@ void KioFtp::copy(const KUrl &src, const KUrl &dest, int permissions, KIO::JobFl
Q_UNUSED(permissions)
Q_UNUSED(flags)
if (!testConnection()) {
return;
}
kDebug() << "copy: " << src.url() << " to " << dest.url();
copyHelper(src, dest);
finished();
}
void KioFtp::rename(const KUrl& src, const KUrl& dest, KIO::JobFlags flags)
@ -146,15 +184,18 @@ void KioFtp::rename(const KUrl& src, const KUrl& dest, KIO::JobFlags flags)
Q_UNUSED(dest)
Q_UNUSED(flags)
error(KIO::ERR_UNSUPPORTED_ACTION, src.prettyUrl());
finished();
error(KIO::ERR_UNSUPPORTED_ACTION, QString());
}
void KioFtp::get(const KUrl& url)
{
if (!testConnection()) {
return;
}
KTemporaryFile tempFile;
tempFile.setSuffix(url.fileName());
tempFile.open();//Create the file
tempFile.open(); // Create the file
kDebug() << tempFile.fileName();
copyHelper(url, KUrl(tempFile.fileName()));
@ -172,6 +213,10 @@ void KioFtp::get(const KUrl& url)
finished();
}
bool KioFtp::cancelTransfer(const QString &transfer)
{
return m_kded->cancelTransfer(transfer);
}
void KioFtp::setHost(const QString &host, quint16 port, const QString &user, const QString &pass)
{
@ -179,35 +224,27 @@ void KioFtp::setHost(const QString &host, quint16 port, const QString &user, con
Q_UNUSED(user)
Q_UNUSED(pass)
m_host = host;
infoMessage(i18n("Connecting to the device"));
kDebug() << "setHost: " << host;
kDebug() << "Waiting to stablish the connection 2";
QDBusPendingReply <QString > reply = m_kded->session(host);
reply.waitForFinished();
kDebug() << "AFTER" << reply.isError();
if (reply.isError()) {
kDebug() << reply.error().message();
kDebug() << reply.error().name();
}
kDebug() << "Got a path" << reply.value();
m_address = host;
m_sessionPath = reply.value();
m_transfer = new org::bluez::obex::FileTransfer1("org.bluez.obex", m_sessionPath, QDBusConnection::sessionBus());
m_statMap.clear();
connectToHost();
}
void KioFtp::del(const KUrl& url, bool isfile)
{
Q_UNUSED(isfile)
kDebug() << "Del: " << url.url();
m_transfer->ChangeFolder(url.directory()).waitForFinished();
m_transfer->Delete(url.fileName()).waitForFinished();
if (!testConnection()) {
return;
}
if (!changeFolder(url.directory())) {
return;
}
if (!deleteFile(url.fileName())) {
return;
}
finished();
}
@ -215,14 +252,28 @@ void KioFtp::mkdir(const KUrl& url, int permissions)
{
Q_UNUSED(permissions)
if (!testConnection()) {
return;
}
kDebug() << "MkDir: " << url.url();
m_transfer->ChangeFolder(url.directory()).waitForFinished();
m_transfer->CreateFolder(url.fileName()).waitForFinished();
if (!changeFolder(url.directory())) {
return;
}
if (!createFolder(url.fileName())) {
return;
}
finished();
}
void KioFtp::stat(const KUrl &url)
{
if (!testConnection()) {
return;
}
kDebug() << "Stat: " << url.url();
kDebug() << "Stat Dir: " << url.directory();
kDebug() << "Stat File: " << url.fileName();
@ -237,8 +288,7 @@ void KioFtp::stat(const KUrl &url)
void KioFtp::copyHelper(const KUrl& src, const KUrl& dest)
{
if (src.scheme() == "obexftp" && dest.scheme() == "obexftp") {
error(KIO::ERR_UNSUPPORTED_ACTION, src.prettyUrl());
//TODO: with obexd this seems possible, we should at least try
copyWithinObexftp(src, dest);
return;
}
@ -253,6 +303,16 @@ void KioFtp::copyHelper(const KUrl& src, const KUrl& dest)
}
kDebug() << "This shouldn't happen...";
}
void KioFtp::copyWithinObexftp(const KUrl &src, const KUrl &dest)
{
kDebug() << "Source: " << src << "Dest:" << dest;
if (!copyFile(src.path(), dest.path())) {
return;
}
finished();
}
@ -260,28 +320,17 @@ void KioFtp::copyFromObexftp(const KUrl& src, const KUrl& dest)
{
kDebug() << "Source: " << src << "Dest:" << dest;
//Just in case the url is not in the stat, some times happens...
if (!m_statMap.contains(src.prettyUrl())) {
kDebug() << "The url is not in the cache, stating it";
statHelper(src);
}
if (m_statMap.value(src.prettyUrl()).isDir()) {
kDebug() << "Skipping to copy: " << src.prettyUrl();
//TODO: Check if dir copying works with obexd
error(KIO::ERR_IS_DIRECTORY, src.prettyUrl());
if (!changeFolder(src.directory())) {
return;
}
kDebug() << "Changing dir:" << src.directory();
m_transfer->ChangeFolder(src.directory()).waitForFinished();
QString dbusPath = m_transfer->GetFile(dest.path(), src.fileName()).value().path();
kDebug() << "Path from GetFile:" << dbusPath;
int size = m_statMap[src.prettyUrl()].numberValue(KIO::UDSEntry::UDS_SIZE);
totalSize(size);
TransferFileJob *getFile = new TransferFileJob(dbusPath, this);
getFile->setSize(size);
getFile->exec();
finished();
@ -291,14 +340,17 @@ void KioFtp::copyToObexftp(const KUrl& src, const KUrl& dest)
{
kDebug() << "Source:" << src << "Dest:" << dest;
kDebug() << "Changing folder: " << dest.directory();
m_transfer->ChangeFolder(dest.directory());
if (!changeFolder(dest.directory())) {
return;
}
QString dbusPath = m_transfer->PutFile(src.path(), dest.fileName()).value().path();
kDebug() << "Path from PutFile: " << dbusPath;
QFile file(src.path());
int size = QFile(src.path()).size();
totalSize(size);
TransferFileJob *putFile = new TransferFileJob(dbusPath, this);
putFile->setSize(file.size());
putFile->exec();
finished();
@ -314,10 +366,10 @@ void KioFtp::statHelper(const KUrl& url)
return;
}
if ((url.directory() == "/" || url.directory().isEmpty()) && url.fileName().isEmpty()) {
if (urlIsRoot(url)) {
kDebug() << "Url is root";
KIO::UDSEntry entry;
entry.insert(KIO::UDSEntry::UDS_NAME, QString::fromLatin1("/"));
entry.insert(KIO::UDSEntry::UDS_NAME, QLatin1String("/"));
entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
entry.insert(KIO::UDSEntry::UDS_ACCESS, 0700);
entry.insert( KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1( "inode/directory" ) );
@ -325,52 +377,146 @@ void KioFtp::statHelper(const KUrl& url)
kDebug() << "Adding stat cached: " << url.prettyUrl();
m_statMap[url.prettyUrl()] = entry;
statEntry(entry);
return;
}
kDebug() << "statMap does NOT contains the url";
//TODO: Check if changeFolder fails
m_transfer->ChangeFolder(url.directory()).waitForFinished();
QVariantMapList folderList = m_transfer->ListFolder().value();
kDebug() << url.directory() << folderList.count();
Q_FOREACH(const QVariantMap folder, folderList) {
KIO::UDSEntry entry = entryFromInfo(folder);
QString fileName = folder["Name"].toString();
if (url.fileName() == fileName) {
statEntry(entry);
}
if (!changeFolder(url.directory())) {
return;
}
//Most probably the client of the kio will stat each file
//so since we are on it, let's cache all of them.
KUrl statUrl(url);
statUrl.setFileName(fileName);
if (!m_statMap.contains(statUrl.prettyUrl())) {
kDebug() << "Stat: " << statUrl.prettyUrl() << entry.stringValue(KIO::UDSEntry::UDS_NAME) << entry.numberValue(KIO::UDSEntry::UDS_SIZE);
m_statMap.insert(statUrl.prettyUrl(), entry);
}
bool ok;
const QList<KIO::UDSEntry> &list = listFolder(url, &ok);
if (!ok) {
return;
}
Q_FOREACH (const KIO::UDSEntry &entry, list) {
statEntry(entry);
}
kDebug() << "Finished";
}
KIO::UDSEntry KioFtp::entryFromInfo(const QVariantMap& info)
QList<KIO::UDSEntry> KioFtp::listFolder(const KUrl &url, bool *ok)
{
kDebug() << info;
QList<KIO::UDSEntry> list;
KIO::UDSEntry entry;
entry.insert(KIO::UDSEntry::UDS_NAME, info["Name"].toString());
entry.insert(KIO::UDSEntry::UDS_CREATION_TIME, info["Created"].toString());
entry.insert(KIO::UDSEntry::UDS_ACCESS, 0700);
entry.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, info["Modified"].toString());
QDBusPendingReply<QVariantMapList> reply = m_transfer->ListFolder();
reply.waitForFinished();
if (info["Type"].toString() == QLatin1String("folder")) {
entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
} else {
entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG);
entry.insert(KIO::UDSEntry::UDS_SIZE, info["Size"].toLongLong());
if (reply.isError()) {
error(KIO::ERR_CANNOT_OPEN_FOR_READING, url.directory());
*ok = false;
return list;
}
return entry;
}
Q_FOREACH (const QVariantMap &item, reply.value()) {
KIO::UDSEntry entry;
entry.insert(KIO::UDSEntry::UDS_NAME, item["Name"].toString());
entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, item["Label"].toString());
entry.insert(KIO::UDSEntry::UDS_ACCESS, 0700);
entry.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, QDateTime::fromString(item["Modified"].toString(), "yyyyMMddThhmmssZ").toTime_t());
entry.insert(KIO::UDSEntry::UDS_SIZE, item["Size"].toLongLong());
if (item["Type"] == QLatin1String("folder")) {
entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, "inode/directory");
} else {
entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG);
}
if (urlIsRoot(url)) {
updateRootEntryIcon(entry, item["Mem-type"].toString());
}
list.append(entry);
// Most probably the client of the kio will stat each file
// so since we are on it, let's cache all of them.
KUrl statUrl(url);
statUrl.setFileName(item["Name"].toString());
if (!m_statMap.contains(statUrl.prettyUrl())) {
kDebug() << "Stat: " << statUrl.prettyUrl() << entry.stringValue(KIO::UDSEntry::UDS_NAME) << entry.numberValue(KIO::UDSEntry::UDS_SIZE);
m_statMap.insert(statUrl.prettyUrl(), entry);
}
}
*ok = true;
return list;
}
bool KioFtp::changeFolder(const QString &folder)
{
QDBusPendingReply<> reply = m_transfer->ChangeFolder(folder);
reply.waitForFinished();
if (reply.isError()) {
error(KIO::ERR_CANNOT_ENTER_DIRECTORY, folder);
return false;
}
return true;
}
bool KioFtp::createFolder(const QString &folder)
{
QDBusPendingReply<> reply = m_transfer->CreateFolder(folder);
reply.waitForFinished();
if (reply.isError()) {
error(KIO::ERR_COULD_NOT_MKDIR, folder);
return false;
}
return true;
}
bool KioFtp::copyFile(const QString &src, const QString &dest)
{
QDBusPendingReply<> reply = m_transfer->CopyFile(src, dest);
reply.waitForFinished();
if (reply.isError()) {
kDebug() << reply.error().message();
// Copying files within obexftp is currently not implemented in obexd
if (reply.error().message() == QLatin1String("Not Implemented")) {
error(KIO::ERR_UNSUPPORTED_ACTION, src);
} else {
error(KIO::ERR_COULD_NOT_WRITE, src);
}
return false;
}
return true;
}
bool KioFtp::deleteFile(const QString &file)
{
QDBusPendingReply<> reply = m_transfer->Delete(file);
reply.waitForFinished();
if (reply.isError()) {
error(KIO::ERR_CANNOT_DELETE, file);
return false;
}
return true;
}
void KioFtp::updateRootEntryIcon(KIO::UDSEntry &entry, const QString &memoryType)
{
const QString &path = entry.stringValue(KIO::UDSEntry::UDS_NAME);
// Nokia (mount-points are C: D: E: ...)
if (path.size() == 2 && path.at(1) == QLatin1Char(':')) {
if (memoryType.startsWith(QLatin1String("DEV"))) {
entry.insert(KIO::UDSEntry::UDS_ICON_NAME, "drive-removable-media");
} else if (memoryType == QLatin1String("MMC")) {
entry.insert(KIO::UDSEntry::UDS_ICON_NAME, "media-flash-sd-mmc");
}
}
// Android
if (entry.stringValue(KIO::UDSEntry::UDS_NAME) == QLatin1String("PHONE_MEMORY")) {
entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, i18n("Phone memory"));
entry.insert(KIO::UDSEntry::UDS_ICON_NAME, "smartphone");
} else if (entry.stringValue(KIO::UDSEntry::UDS_NAME) == QLatin1String("EXTERNAL_MEMORY")) {
entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, i18n("External memory"));
entry.insert(KIO::UDSEntry::UDS_ICON_NAME, "media-flash-sd-mmc");
}
}

View file

@ -50,27 +50,37 @@ public:
virtual void rename(const KUrl& src, const KUrl& dest, KIO::JobFlags flags);
virtual void get(const KUrl& url);
bool cancelTransfer(const QString &transfer);
private Q_SLOTS:
void updateProcess();
KIO::UDSEntry entryFromInfo(const QVariantMap &info);
private:
void copyHelper(const KUrl &src, const KUrl &dest);
void copyWithinObexftp(const KUrl &src, const KUrl &dest);
void copyFromObexftp(const KUrl &src, const KUrl &dest);
void copyToObexftp(const KUrl &src, const KUrl &dest);
void statHelper(const KUrl &url);
QList<KIO::UDSEntry> listFolder(const KUrl &url, bool *ok);
bool changeFolder(const QString &folder);
bool createFolder(const QString &folder);
bool copyFile(const QString &src, const QString &dest);
bool deleteFile(const QString &file);
void updateRootEntryIcon(KIO::UDSEntry &entry, const QString &memoryType);
void launchProgressBar();
void connectToHost();
bool testConnection();
private:
int m_counter;
bool m_settingHost;
QEventLoop m_eventLoop;
int m_counter;
QMap<QString, KIO::UDSEntry> m_statMap;
QString m_address;
QString m_sessionPath;
QTimer *m_timer;
org::kde::ObexFtp *m_kded;
QString m_host;
QString m_sessionPath;
QTimer *m_timer;
org::kde::ObexFtp *m_kded;
OrgBluezObexFileTransfer1Interface *m_transfer;
};
#endif // KIO_OBEXFTP_H

View file

@ -34,7 +34,6 @@ TransferFileJob::TransferFileJob(const QString& path, KioFtp* parent)
, m_speedBytes(0)
, m_parent(parent)
{
}
TransferFileJob::~TransferFileJob()
@ -50,16 +49,7 @@ void TransferFileJob::start()
bool TransferFileJob::doKill()
{
QDBusPendingReply <void > reply = m_transfer->Cancel();
reply.waitForFinished();
return !reply.isError();
}
void TransferFileJob::setSize(int size)
{
kDebug() << size;
m_parent->totalSize(size);
return m_parent->cancelTransfer(m_path);
}
void TransferFileJob::createObjects()
@ -97,7 +87,6 @@ void TransferFileJob::statusChanged(const QVariant& value)
m_time = QTime::currentTime();
return;
} else if (status == QLatin1String("complete")) {
m_parent->finished();
emitResult();
return;
} else if (status == QLatin1String("error")) {
@ -114,7 +103,7 @@ void TransferFileJob::transferChanged(const QVariant& value)
kDebug() << "Transferred: " << value;
if (m_parent->wasKilled()) {
kDebug() << "Kio was killed, aborting task";
m_transfer->Cancel().waitForFinished();
doKill();
emitResult();
return;
}
@ -137,4 +126,4 @@ void TransferFileJob::transferChanged(const QVariant& value)
}
m_parent->processedSize(bytes);
}
}

View file

@ -39,7 +39,6 @@ public:
virtual ~TransferFileJob();
void setSize(int size);
private Q_SLOTS:
void createObjects();
void propertiesChanged(const QString &interface , const QVariantMap &properties , const QStringList &invalidProps);
@ -56,4 +55,4 @@ private:
};
#endif //KIO_GET_FILE_JOB_H
#endif //KIO_GET_FILE_JOB_H

View file

@ -44,7 +44,7 @@ Monolithic::Monolithic(QObject* parent)
offlineMode();
if (!Manager::self()->adapters().isEmpty()) {
if (Manager::self()->usableAdapter()) {
onlineMode();
}
@ -55,7 +55,6 @@ Monolithic::Monolithic(QObject* parent)
setStandardActionsEnabled(false);
setAssociatedWidget(contextMenu());
setStatus(KStatusNotifierItem::Active);
poweredChanged();
}

View file

@ -70,6 +70,7 @@ void SSPPairingPage::initializePage()
void SSPPairingPage::confirmationRequested(quint32 passkey, const QDBusMessage& msg)
{
m_msg = msg;
m_msg.setDelayedReply(true);
KPushButton *matches = new KPushButton(KStandardGuiItem::apply());
matches->setText(i18n("Matches"));
@ -119,6 +120,7 @@ void SSPPairingPage::matchesClicked()
void SSPPairingPage::notMatchClicked()
{
m_buttonClicked = QWizard::CustomButton2;
QDBusConnection::systemBus().send(m_msg.createErrorReply("org.bluez.Rejected", "Rejected"));
wizard()->next();
}