Skip to content

Instantly share code, notes, and snippets.

@shadeslayer
Created July 2, 2011 02:28
Show Gist options
  • Select an option

  • Save shadeslayer/1059688 to your computer and use it in GitHub Desktop.

Select an option

Save shadeslayer/1059688 to your computer and use it in GitHub Desktop.
/*
Copyright © 2011 Rohan Garg <[email protected]>
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) version 3 or any later version
accepted by the membership of KDE e.V. (or its successor approved
by the membership of KDE e.V.), which shall act as a proxy
defined in Section 14 of version 3 of the license.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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, see <http://www.gnu.org/licenses/>.
*/
#include "Module.h"
#include "ui_Module.h"
#include <QDebug>
#include <KAboutData>
#include <KPluginFactory>
#include <KStandardDirs>
#include "Version.h"
#include "server_interface.h"
#include "session_interface.h"
K_PLUGIN_FACTORY_DECLARATION(KcmSynqConfigFactory);
Module::Module(QWidget *parent, const QVariantList &args) :
KCModule(KcmSynqConfigFactory::componentData(), parent, args),
ui(new Ui::MainWidget)
{
//Register custom types
syncevolution_qt_dbus_register_types();
KAboutData *about = new KAboutData("kcm-synq", 0,
ki18n("Synq Configuration"),
global_s_versionStringFull,
ki18n("Configure your synq accounts"),
KAboutData::License_GPL_V3,
ki18n("Copyright 2011 Rohan Garg"),
KLocalizedString(), QByteArray(),
"[email protected]");
about->addAuthor(ki18n("Rohan Garg"), ki18n("shadeslayer"), "[email protected]");
setAboutData(about);
server = new OrgSyncevolutionServerInterface("org.syncevolution", "/org/syncevolution/Server", QDBusConnection::sessionBus());
if (server->isValid()) {
server->Attach();
ui->setupUi(this);
ui->addAccountButton->setIcon(KIcon("list-add"));
ui->removeAccountButton->setIcon(KIcon("edit-delete"));
//Add list of configured profiles
ui->listWidget->addItems(server->GetConfigs(false));
//Add list of available templates
ui->templateList->addItems(server->GetConfigs(true));
//Sync type map, used for mapping sync type from combobox to a sync property
syncType = new QStringMap;
syncType->insert("Two Way", "two-way");
syncType->insert("Refresh from server", "refresh-server");
syncType->insert("Refresh from client", "refresh-client");
syncType->insert("One way from server", "one-way-server");
syncType->insert("One way from client", "one-way-client");
nameDatabaseMap.clear();
setSyncOptions(ui->templateList->currentText());
connect(ui->templateList, SIGNAL(currentIndexChanged(QString)), this, SLOT(setSyncOptions(QString)));
connect(ui->addAccountButton, SIGNAL(clicked(bool)), this, SLOT(addProfile(bool)));
connect(ui->removeAccountButton, SIGNAL(clicked(bool)), this, SLOT(removeProfile(bool)), Qt::BlockingQueuedConnection);
connect(server, SIGNAL(ConfigChanged()), this, SLOT(reloadConfigList()));
connect(ui->listWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(showConfig(QListWidgetItem*)));
} else {
QVBoxLayout *layout = new QVBoxLayout(this);
QListWidget *list = new QListWidget(this);
layout->addWidget(list);
new ErrorOverlay(this, "Could not find the SyncEvolution DBus Server", this);
return;
}
// We have no help so remove the button from the buttons.
setButtons(buttons() ^ KCModule::Help);
}
Module::~Module()
{
server->Detach();
delete ui;
}
void Module::setSyncOptions(QString serverName)
{
QDBusObjectPath sessionPath = server->StartSession(ui->templateList->currentText());
OrgSyncevolutionSessionInterface *session = new OrgSyncevolutionSessionInterface("org.syncevolution", sessionPath.path(), QDBusConnection::sessionBus());
QStringMultiMap templateConfig = server->GetConfig(serverName, true);
ui->addressResourceList->clear();
ui->calendarResourceList->clear();
ui->memoResourceList->clear();
ui->taskResourceList->clear();
nameDatabaseMap.clear();
QArrayOfDatabases addressBookDatabase = session->GetDatabases("addressbook");
foreach(SyncDatabase tempAddressbook, addressBookDatabase) {
ui->addressResourceList->addItem(tempAddressbook.name);
nameDatabaseMap.insert(tempAddressbook.name, tempAddressbook.source);
}
ui->addressResourceList->addItem("New Addressbook resource");
QArrayOfDatabases calendarDatabase = session->GetDatabases("calendar");
foreach(SyncDatabase tempcalendar, calendarDatabase) {
ui->calendarResourceList->addItem(tempcalendar.name);
nameDatabaseMap.insert(tempcalendar.name, tempcalendar.source);
}
ui->calendarResourceList->addItem("New Calendar resource");
QArrayOfDatabases memoDatabase = session->GetDatabases("memo");
foreach(SyncDatabase tempmemo, memoDatabase) {
ui->memoResourceList->addItem(tempmemo.name);
nameDatabaseMap.insert(tempmemo.name, tempmemo.source);
}
ui->memoResourceList->addItem("New Memo resouce");
QArrayOfDatabases tasksDatabase = session->GetDatabases("todo");
foreach(SyncDatabase temptasks, tasksDatabase) {
ui->taskResourceList->addItem(temptasks.name);
nameDatabaseMap.insert(temptasks.name, temptasks.source);
}
ui->taskResourceList->addItem("New Tasks resource");
ui->syncURL->setText(templateConfig.value("").value("syncURL"));
if(ui->listWidget->count() == 0) {
ui->removeAccountButton->setDisabled(true);
}
session->Detach();
}
void Module::addProfile(bool)
{
qDebug() << "Adding a new profile";
readConfigFromUI();
QDBusObjectPath sessionPath = server->StartSession(ui->listWidget->currentItem()->text());
OrgSyncevolutionSessionInterface *session = new OrgSyncevolutionSessionInterface("org.syncevolution", sessionPath.path(), QDBusConnection::sessionBus());
session->SetConfig(false, false, config);
ui->listWidget->addItem(ui->profileName->text());
}
void Module::removeProfile(bool)
{
qDebug() << "WARNING : Removing Config " << ui->profileName->text();
server->Attach();
QDBusObjectPath sessionPath = server->StartSession(ui->profileName->text());
session = new OrgSyncevolutionSessionInterface("org.syncevolution", sessionPath.path(), QDBusConnection::sessionBus());
qDebug() << sessionPath.path() << " " << session->path() << " " << session->GetStatus();
connect(session, SIGNAL(StatusChanged(QString,uint,QSyncStatusMap)), this, SLOT(actuallyDeleteConfig(QString,uint,QSyncStatusMap)));
//TODO: We should ideally have some sort of error handling over here, before we detach and delete the listwidget, consult and implement later on
return;
}
void Module::reloadConfigList()
{
ui->listWidget->clear();
ui->listWidget->addItems(server->GetConfigs(false));
if(ui->listWidget->count() == 0) {
ui->removeAccountButton->setDisabled(true);
}
}
void Module::showConfig(QListWidgetItem* selectedProfile)
{
QStringMultiMap readConfig;
QDBusObjectPath sessionPath = server->StartSession(selectedProfile->text());
OrgSyncevolutionSessionInterface *session = new OrgSyncevolutionSessionInterface("org.syncevolution", sessionPath.path(), QDBusConnection::sessionBus());
readConfig = session->GetConfig(false);
QStringMap configMap = readConfig[""];
//Hide template list because the template name isn't stored
ui->templateList->hide();
ui->label->hide();
ui->profileName->setText(configMap["configName"]);
ui->usernameInput->setText(configMap["username"]);
ui->passwordInput->setText(configMap["password"]);
ui->syncURL->setText(configMap["syncURL"]);
configMap = readConfig["source/addressbook"];
delete session;
}
void Module::readConfigFromUI()
{
config.clear();
//Initial config from UI
QStringMap tempConfig1;
tempConfig1.insert("templateName", ui->templateList->currentText());
tempConfig1.insert("configName", ui->profileName->text());
tempConfig1.insert("username", ui->usernameInput->text());
tempConfig1.insert("password", ui->passwordInput->text());
tempConfig1.insert("syncURL", ui->syncURL->text());
config.insert("", tempConfig1);
tempConfig1.clear();
if(ui->checkContacts->isChecked()){
//Insert Config for addressbook
tempConfig1.insert("backend", "addressbook");
tempConfig1.insert("database", nameDatabaseMap.value(ui->addressResourceList->currentText()));
tempConfig1.insert("sync", syncType->value(ui->contactSyncType->currentText()));
config.insert("source/addressbook", tempConfig1);
tempConfig1.clear();
}
if(ui->checkCalendar->isChecked()){
//Insert Config for Calendars
tempConfig1.insert("backend", "calendar");
tempConfig1.insert("database", nameDatabaseMap.value(ui->calendarResourceList->currentText()));
tempConfig1.insert("sync", syncType->value(ui->calendarSyncType->currentText()));
config.insert("source/calendar", tempConfig1);
tempConfig1.clear();
}
if(ui->checkMemos->isChecked()){
//Insert Config for Memos
tempConfig1.insert("backend", "memo");
tempConfig1.insert("database", nameDatabaseMap.value(ui->memoResourceList->currentText()));
tempConfig1.insert("sync", syncType->value(ui->memoSyncType->currentText()));
config.insert("source/memo", tempConfig1);
tempConfig1.clear();
}
if(ui->checkTasks->isChecked()){
//Insert Config for todo
tempConfig1.insert("backend", "todo");
tempConfig1.insert("database", nameDatabaseMap.value(ui->taskResourceList->currentText()));
tempConfig1.insert("sync", syncType->value(ui->taskSyncType->currentText()));
config.insert("source/todo", tempConfig1);
tempConfig1.clear();
}
}
void Module::actuallyDeleteConfig(QString, uint, QSyncStatusMap )
{
QStringMultiMap emptyConfig;
qDebug() << "Trying to remove config " << session->GetStatus();
session->SetConfig(false, false, emptyConfig);
}
////
ErrorOverlay::ErrorOverlay(QWidget *baseWidget, const QString &details, QWidget *parent) :
QWidget(parent ? parent : baseWidget->window()),
m_BaseWidget(baseWidget)
{
// Build the UI
QVBoxLayout *layout = new QVBoxLayout;
layout->setSpacing(10);
QLabel *pixmap = new QLabel();
pixmap->setPixmap(KIcon("dialog-error").pixmap(64));
QLabel *message = new QLabel(i18n("Something went terribly wrong and the SyncEvolution backend could not be initialized.\n"
"It is likely your system is missing the SyncEvolution package.\n"
"Please install it and restart this module."));
message->setAlignment(Qt::AlignHCenter);
pixmap->setAlignment(Qt::AlignHCenter);
layout->addStretch();
layout->addWidget(pixmap);
layout->addWidget(message);
layout->addStretch();
setLayout(layout);
// Draw the transparent overlay background
QPalette p = palette();
p.setColor(backgroundRole(), QColor(0, 0, 0, 128));
p.setColor(foregroundRole(), Qt::white);
setPalette(p);
setAutoFillBackground(true);
m_BaseWidget->installEventFilter(this);
reposition();
}
ErrorOverlay::~ErrorOverlay()
{
}
void ErrorOverlay::reposition()
{
if (!m_BaseWidget) {
return;
}
// reparent to the current top level widget of the base widget if needed
// needed eg. in dock widgets
if (parentWidget() != m_BaseWidget->window()) {
setParent(m_BaseWidget->window());
}
// follow base widget visibility
// needed eg. in tab widgets
if (!m_BaseWidget->isVisible()) {
hide();
return;
}
show();
// follow position changes
const QPoint topLevelPos = m_BaseWidget->mapTo(window(), QPoint(0, 0));
const QPoint parentPos = parentWidget()->mapFrom(window(), topLevelPos);
move(parentPos);
// follow size changes
// TODO: hide/scale icon if we don't have enough space
resize(m_BaseWidget->size());
}
bool ErrorOverlay::eventFilter(QObject * object, QEvent * event)
{
if (object == m_BaseWidget &&
(event->type() == QEvent::Move || event->type() == QEvent::Resize ||
event->type() == QEvent::Show || event->type() == QEvent::Hide ||
event->type() == QEvent::ParentChange)) {
reposition();
}
return QWidget::eventFilter(object, event);
}
/*
Copyright © 2011 Rohan Garg <[email protected]>
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) version 3 or any later version
accepted by the membership of KDE e.V. (or its successor approved
by the membership of KDE e.V.), which shall act as a proxy
defined in Section 14 of version 3 of the license.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef MODULE_H
#define MODULE_H
#include <KCModule>
#include "dbustypes.h"
class QListWidgetItem;
namespace Ui
{
class MainWidget;
}
class OrgSyncevolutionServerInterface;
class OrgSyncevolutionSessionInterface;
class Module : public KCModule
{
Q_OBJECT
public:
/**
* Constructor.
*/
Module(QWidget *parent, const QVariantList &args = QVariantList());
/**
* Destructor.
*/
~Module();
private:
/**
* UI
*/
Ui::MainWidget *ui;
OrgSyncevolutionServerInterface *server;
OrgSyncevolutionSessionInterface *session;
QStringMultiMap config;
QStringMap *syncType;
QStringMap nameDatabaseMap;
public:
void readConfigFromUI();
public slots:
void addProfile(bool);
void removeProfile(bool);
void reloadConfigList();
void showConfig(QListWidgetItem* selectedProfile);
void setSyncOptions(QString);
void actuallyDeleteConfig(QString,uint,QSyncStatusMap);
};
// Helper class for drawing error overlays
class ErrorOverlay : public QWidget
{
Q_OBJECT
public:
explicit ErrorOverlay(QWidget *baseWidget, const QString &details, QWidget *parent = 0);
~ErrorOverlay();
void startSyncEvoDBusServer(Qt::AlignmentFlag AlignHCenter);
protected:
bool eventFilter(QObject *object, QEvent *event);
private:
void reposition();
private:
QWidget *m_BaseWidget;
};
#endif // MODULE_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment