mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-24 19:02:53 +00:00
433 lines
15 KiB
C++
433 lines
15 KiB
C++
/*
|
|
* Copyright 2009 Andrew Stromme <astromme@chatonka.com>
|
|
* Copyright 2012 Jeremy Whiting <jpwhiting@kde.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Library General Public License as
|
|
* published by the Free Software Foundation; either version 2, or
|
|
* (at your option) any later version.
|
|
*
|
|
* 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 Library General Public
|
|
* License along with this program; if not, write to the
|
|
* Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "rememberthemilk-plasmoid.h"
|
|
|
|
// Qt Includes
|
|
#include <QPushButton>
|
|
#include <QCheckBox>
|
|
#include <QTreeView>
|
|
|
|
// KDE Includes
|
|
#include <KConfigDialog>
|
|
#include <KDebug>
|
|
#include <KToolInvocation>
|
|
|
|
// Plasma Includes
|
|
#include <Plasma/Theme>
|
|
#include <Plasma/Service>
|
|
#include <Plasma/Animator>
|
|
#include <Plasma/TreeView>
|
|
#include <Plasma/TabBar>
|
|
#include <Plasma/Label>
|
|
#include <Plasma/LineEdit>
|
|
#include <Plasma/ServiceJob>
|
|
|
|
// Local
|
|
#include "ui_authenticate.h"
|
|
#include "ui_general.h"
|
|
#include "taskmodel.h"
|
|
#include "tasksortfilter.h"
|
|
#include <KLineEdit>
|
|
|
|
RememberTheMilkPlasmoid::RememberTheMilkPlasmoid(QObject* parent, const QVariantList& args)
|
|
: Plasma::PopupApplet(parent, args),
|
|
m_authenticated(false),
|
|
m_sortBy(SortDue),
|
|
m_taskEditor(0),
|
|
m_engine(0),
|
|
m_taskService(0),
|
|
m_graphicsWidget(0),
|
|
m_authService(0),
|
|
m_authWidgetUi(new Ui::AuthWidget),
|
|
m_generalOptionsUi(new Ui::GeneralWidget)
|
|
{
|
|
setBackgroundHints(DefaultBackground);
|
|
setPopupIcon("view-pim-journal"); // TODO: Create/Find better item
|
|
m_authWidget = new QWidget();
|
|
m_authWidgetUi->setupUi(m_authWidget);
|
|
m_authWidgetUi->webView->hide();
|
|
m_generalOptions = new QWidget();
|
|
connect(m_authWidgetUi->signupLabel, SIGNAL(leftClickedUrl(QString)), KToolInvocation::self(), SLOT(invokeBrowser(QString)));
|
|
m_generalOptionsUi->setupUi(m_generalOptions);
|
|
m_generalOptionsUi->sortType->addItem(i18n("Due Date"));
|
|
m_generalOptionsUi->sortType->addItem(i18n("Priority"));
|
|
}
|
|
|
|
RememberTheMilkPlasmoid::~RememberTheMilkPlasmoid() {
|
|
if (hasFailedToLaunch()) {
|
|
kDebug() << "failed to launch";
|
|
}
|
|
delete m_authWidget;
|
|
delete m_authWidgetUi;
|
|
|
|
delete m_generalOptions;
|
|
delete m_generalOptionsUi;
|
|
}
|
|
|
|
void RememberTheMilkPlasmoid::init() {
|
|
setAspectRatioMode(Plasma::IgnoreAspectRatio);
|
|
|
|
graphicsWidget();
|
|
|
|
if (!m_engine || !m_engine->isValid()) {
|
|
return Plasma::Applet::init();
|
|
}
|
|
|
|
m_engine->connectSource("Auth", this);
|
|
|
|
m_authService = m_engine->serviceForSource("Auth");
|
|
m_authService->setParent(this);
|
|
connect(m_authService, SIGNAL(finished(Plasma::ServiceJob*)), SLOT(jobFinished(Plasma::ServiceJob*)));
|
|
|
|
configChanged();
|
|
|
|
Plasma::Applet::init();
|
|
setAssociatedApplicationUrls(KUrl("http://rememberthemilk.com"));
|
|
}
|
|
|
|
|
|
void RememberTheMilkPlasmoid::startAuth()
|
|
{
|
|
disconnect(m_authWidgetUi->authenticateButton, SIGNAL(clicked(bool)), this, SLOT(startAuth()));
|
|
connect(m_authWidgetUi->authenticateButton, SIGNAL(clicked(bool)), this, SLOT(continueAuth()));
|
|
m_authWidgetUi->authenticateButton->setText(i18n("Click to finish authentication"));
|
|
|
|
KConfigGroup cg = m_authService->operationDescription("StartLogin");
|
|
Plasma::ServiceJob* authJob = m_authService->startOperationCall(cg);
|
|
connect(authJob, SIGNAL(finished(KJob*)), SLOT(authJobFinished(KJob*)));
|
|
busyUntil(authJob);
|
|
busyUntil(0); // Sets busy until we manually call jobFinished(0). Busy until first tasks refresh
|
|
m_authenticated = false;
|
|
}
|
|
|
|
void RememberTheMilkPlasmoid::authJobFinished(KJob* job)
|
|
{
|
|
Plasma::ServiceJob *authJob = qobject_cast<Plasma::ServiceJob*>(job);
|
|
QString url = authJob->result().toString();
|
|
m_authWidgetUi->webView->setUrl(QUrl(url));
|
|
m_authWidgetUi->webView->show();
|
|
}
|
|
|
|
void RememberTheMilkPlasmoid::continueAuth()
|
|
{
|
|
KConfigGroup cg = m_authService->operationDescription("Login");
|
|
Plasma::ServiceJob* authJob = m_authService->startOperationCall(cg);
|
|
busyUntil(authJob);
|
|
busyUntil(0); // Sets busy until we manually call jobFinished(0). Busy until first tasks refresh
|
|
m_authenticated = false;
|
|
}
|
|
|
|
void RememberTheMilkPlasmoid::configAccepted() {
|
|
switch(m_generalOptionsUi->sortType->currentIndex()) {
|
|
case 0:
|
|
setSortBy(SortDue);
|
|
break;
|
|
case 1:
|
|
setSortBy(SortPriority);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void RememberTheMilkPlasmoid::configFinished()
|
|
{
|
|
m_authWidget->setParent(0); // We don't want these widgets destroyed along with the configuration window
|
|
m_generalOptions->setParent(0); // They are reused later
|
|
}
|
|
|
|
void RememberTheMilkPlasmoid::createConfigurationInterface(KConfigDialog* parent) {
|
|
connect(parent, SIGNAL(finished()), this, SLOT(configFinished()));
|
|
connect(parent, SIGNAL(applyClicked()), this, SLOT(configAccepted()));
|
|
connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted()));
|
|
connect(m_authWidgetUi->authenticateButton, SIGNAL(clicked(bool)), this, SLOT(startAuth()));
|
|
|
|
m_generalOptionsUi->sortType->setCurrentIndex(m_sortBy);
|
|
|
|
KPageWidgetItem* general = parent->addPage(m_generalOptions, i18n("General"), "configure", i18n("General Configuration Options"));
|
|
KPageWidgetItem* auth = parent->addPage(m_authWidget, i18n("Authentication"), icon(), i18n("Remember The Milk Authentication"));
|
|
|
|
if (!m_authenticated)
|
|
parent->setCurrentPage(auth);
|
|
else
|
|
parent->setCurrentPage(general);
|
|
|
|
connect(m_generalOptionsUi->sortType, SIGNAL(currentIndexChanged(int)), parent, SLOT(settingsModified()));
|
|
connect(this, SIGNAL(authenticated()), parent, SLOT(settingsModified()));
|
|
}
|
|
|
|
void RememberTheMilkPlasmoid::setSortBy(SortBy sortBy)
|
|
{
|
|
m_filterModel->setSortBy(sortBy);
|
|
m_model->setDropType(sortBy);
|
|
switch (sortBy) {
|
|
case SortPriority:
|
|
config().writeEntry("SortBy", "Priority");
|
|
m_delegate->setSmallTasks(false);
|
|
break;
|
|
case SortDue:
|
|
config().writeEntry("SortBy", "Date");
|
|
m_delegate->setSmallTasks(true);
|
|
break;
|
|
}
|
|
|
|
m_sortBy = sortBy;
|
|
}
|
|
|
|
void RememberTheMilkPlasmoid::dataUpdated(const QString& name, const Plasma::DataEngine::Data& data) {
|
|
if (name == "Auth") {
|
|
m_authenticated = data.value("ValidToken").toBool();
|
|
kDebug() << "Auth: " << m_authenticated;
|
|
|
|
m_authWidgetUi->webView->hide();
|
|
if (m_authenticated) {
|
|
m_authWidgetUi->authStatus->setText(i18n("Authenticated"));
|
|
m_authWidgetUi->kled->setState(KLed::On);
|
|
m_authWidgetUi->kled->setColor(Qt::green);
|
|
} else {
|
|
m_authWidgetUi->authStatus->setText(i18n("Not Authenticated"));
|
|
m_authWidgetUi->kled->setState(KLed::Off);
|
|
m_authWidgetUi->kled->setColor(Qt::red);
|
|
m_busyUntil.clear(); // no longer trying to authenticate
|
|
setBusy(false);
|
|
}
|
|
|
|
if (m_authenticated) {
|
|
setConfigurationRequired(false);
|
|
m_token = data.value("Token").toString();
|
|
config().writeEntry("token", m_token);
|
|
m_engine->connectSource("Lists", this);
|
|
m_engine->connectSource("Tasks", this);
|
|
busyUntil(0);
|
|
|
|
emit authenticated();
|
|
}
|
|
else if (m_categoriesBar->count() == 1 && m_lists.isEmpty())
|
|
m_categoriesBar->nativeWidget()->setTabText(0, i18n("Login Failed. Please try again."));
|
|
}
|
|
else if (name == "Lists") {
|
|
if (m_categoriesBar->count() == 1 && m_lists.isEmpty())
|
|
m_categoriesBar->removeTab(0); // remove "refreshing" tab;
|
|
//while (m_categoriesBar->count())
|
|
// m_categoriesBar->removeTab(0);
|
|
//m_lists.clear(); //FIXME: What happens when a list is deleted?
|
|
foreach(const QString &key, data.keys()) {
|
|
if (!m_lists.contains(key.toULongLong())) {
|
|
m_categoriesBar->addTab(data.value(key).toString());
|
|
m_lists.append(key.toULongLong());
|
|
}
|
|
m_model->listUpdate(key.toULongLong());
|
|
}
|
|
int current = config().readEntry("CurrentList").toInt();
|
|
if (m_categoriesBar->count() >= current) {
|
|
m_categoriesBar->setCurrentIndex(current);
|
|
listChanged(current); // doesn't always update.. i.e if current is actually the current
|
|
}
|
|
|
|
}
|
|
else if (name == "Tasks") {
|
|
if (data.keys().count() > 0)
|
|
jobFinished(0); // No longer busy.
|
|
}
|
|
}
|
|
|
|
void RememberTheMilkPlasmoid::listChanged(int pos)
|
|
{
|
|
if (pos < 0 || pos >= m_lists.size())
|
|
return;
|
|
|
|
config().writeEntry("CurrentList", pos);
|
|
m_model->switchToList(m_lists.at(pos));
|
|
}
|
|
|
|
void RememberTheMilkPlasmoid::createTask(const QString& task)
|
|
{
|
|
if (!m_taskService) {
|
|
m_taskService = m_engine->serviceForSource("Tasks");
|
|
m_taskService->setParent(this);
|
|
connect(m_taskService, SIGNAL(finished(Plasma::ServiceJob*)), SLOT(jobFinished(Plasma::ServiceJob*)));
|
|
}
|
|
KConfigGroup cg = m_taskService->operationDescription("create");
|
|
cg.writeEntry("task", task);
|
|
kDebug() << "QString::number(m_model->currentList()->id)";
|
|
cg.writeEntry("listid", m_model->currentList()->id);
|
|
busyUntil(m_taskService->startOperationCall(cg));
|
|
}
|
|
|
|
void RememberTheMilkPlasmoid::onTaskEditorHide() {
|
|
m_tasksView->nativeWidget()->setEnabled(true);
|
|
m_priorityLabel->setText(i18n("Remember The Milk Tasks"));
|
|
}
|
|
|
|
void RememberTheMilkPlasmoid::showTaskEditor(QModelIndex index) {
|
|
if (index.data(Qt::RTMItemType).toInt() != RTMTaskItem) // We have a header rather than a task.
|
|
return;
|
|
m_taskEditor->setModelIndex(index);
|
|
m_taskEditor->hide();
|
|
m_taskEditor->show();
|
|
m_tasksView->nativeWidget()->setEnabled(false);
|
|
m_taskEditor->setEnabled(true);
|
|
m_taskEditor->startAnimation(m_tasksView->size());
|
|
m_priorityLabel->setText(i18n("Editing Task: ") + index.data(Qt::RTMNameRole).toString());
|
|
|
|
geometryChanged();
|
|
}
|
|
|
|
void RememberTheMilkPlasmoid::busyUntil(Plasma::ServiceJob* job)
|
|
{
|
|
setBusy(true);
|
|
m_busyUntil.append(job);
|
|
}
|
|
|
|
void RememberTheMilkPlasmoid::jobFinished(Plasma::ServiceJob* job)
|
|
{
|
|
if (m_busyUntil.contains(job)) {
|
|
m_busyUntil.removeAll(job);
|
|
}
|
|
if (m_busyUntil.isEmpty())
|
|
setBusy(false);
|
|
}
|
|
|
|
void RememberTheMilkPlasmoid::resizeEvent(QGraphicsSceneResizeEvent* event) {
|
|
if (m_taskEditor)
|
|
m_taskEditor->resize(m_tasksView->size());
|
|
Plasma::Applet::resizeEvent(event);
|
|
}
|
|
|
|
QGraphicsWidget* RememberTheMilkPlasmoid::graphicsWidget() {
|
|
if (m_graphicsWidget)
|
|
return m_graphicsWidget;
|
|
|
|
m_engine = dataEngine("rtm");
|
|
|
|
if (!m_engine || !m_engine->isValid()) {
|
|
setFailedToLaunch(true, i18n("Failed to load the Remember The Milk DataEngine"));
|
|
return m_graphicsWidget;
|
|
}
|
|
|
|
m_graphicsWidget = new QGraphicsWidget(this);
|
|
|
|
m_model = new TaskModel(m_engine, this);
|
|
connect(m_model, SIGNAL(jobStarted(Plasma::ServiceJob*)), SLOT(busyUntil(Plasma::ServiceJob*)));
|
|
connect(m_model, SIGNAL(jobFinished(Plasma::ServiceJob*)), SLOT(jobFinished(Plasma::ServiceJob*)));
|
|
|
|
m_priorityLabel = new Plasma::Label(this);
|
|
m_priorityLabel->setAlignment(Qt::AlignHCenter);
|
|
m_priorityLabel->setText(i18n("Remember The Milk Tasks"));
|
|
|
|
m_categoriesBar = new Plasma::TabBar(this);
|
|
m_categoriesBar->addTab(i18n("No Data Yet. Refreshing..."));
|
|
|
|
connect(m_categoriesBar, SIGNAL(currentChanged(int)), SLOT(listChanged(int)));
|
|
|
|
QPalette palette;
|
|
palette.setBrush(QPalette::Background, Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor));
|
|
palette.setBrush(QPalette::Text, Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor));
|
|
|
|
|
|
m_delegate = new TaskItemDelegate(this);
|
|
|
|
m_filterModel = new TaskSortFilter(m_model, this);
|
|
connect(m_model, SIGNAL(modelUpdated()), m_filterModel, SLOT(listChanged()));
|
|
|
|
m_tasksView = new Plasma::TreeView(this);
|
|
m_tasksView->installEventFilter(m_delegate);
|
|
m_tasksView->setModel(m_filterModel);
|
|
m_tasksView->nativeWidget()->setItemDelegate(m_delegate);
|
|
m_tasksView->nativeWidget()->header()->setHidden(true);
|
|
m_tasksView->nativeWidget()->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
|
m_tasksView->nativeWidget()->setRootIsDecorated(false);
|
|
m_tasksView->nativeWidget()->setIndentation(0);
|
|
m_tasksView->nativeWidget()->viewport()->setAutoFillBackground(false);
|
|
m_tasksView->nativeWidget()->viewport()->setPalette( palette );
|
|
m_tasksView->nativeWidget()->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
m_tasksView->nativeWidget()->setDragEnabled(true);
|
|
m_tasksView->nativeWidget()->setAcceptDrops(true);
|
|
m_tasksView->nativeWidget()->viewport()->setAcceptDrops(true);
|
|
m_tasksView->nativeWidget()->setDropIndicatorShown(false);
|
|
m_tasksView->nativeWidget()->setDragDropMode(QAbstractItemView::DragDrop);
|
|
m_tasksView->nativeWidget()->setSortingEnabled(true);
|
|
m_tasksView->nativeWidget()->sortByColumn(0, Qt::AscendingOrder);
|
|
m_tasksView->nativeWidget()->expandAll();
|
|
|
|
connect(m_tasksView->nativeWidget(), SIGNAL(clicked(QModelIndex)), this, SLOT(showTaskEditor(QModelIndex)));
|
|
|
|
m_searchLine = new Plasma::LineEdit(this);
|
|
m_searchLine->nativeWidget()->setClearButtonShown(true);
|
|
m_searchLine->nativeWidget()->setClickMessage(i18n("Filter Tasks..."));
|
|
connect(m_searchLine->nativeWidget(), SIGNAL(textChanged(QString)), m_filterModel, SLOT(setFilterWildcard(QString)));
|
|
|
|
m_addTaskLine = new Plasma::LineEdit(this); // must wait for plasma theming (4.3?) to get a themed lineedit
|
|
|
|
m_addTaskLine->nativeWidget()->setClearButtonShown(true);
|
|
m_addTaskLine->nativeWidget()->setClickMessage(i18n("Create New Task..."));
|
|
|
|
connect(m_addTaskLine->nativeWidget(), SIGNAL(returnPressed(QString)), m_addTaskLine->nativeWidget(), SLOT(clear()));
|
|
connect(m_addTaskLine->nativeWidget(), SIGNAL(returnPressed(QString)), this, SLOT(createTask(QString)));
|
|
|
|
kDebug() << "Creating layout";
|
|
|
|
m_mainLayout = new QGraphicsLinearLayout(Qt::Vertical, m_graphicsWidget);
|
|
|
|
m_mainLayout->addItem(m_priorityLabel);
|
|
m_mainLayout->addItem(m_categoriesBar);
|
|
m_mainLayout->addItem(m_searchLine);
|
|
m_mainLayout->addItem(m_tasksView);
|
|
m_mainLayout->addItem(m_addTaskLine);
|
|
|
|
m_graphicsWidget->setLayout(m_mainLayout);
|
|
m_graphicsWidget->setMinimumSize(250, 300);
|
|
m_graphicsWidget->setPreferredSize(300, 500);
|
|
|
|
m_taskEditor = new TaskEditor(m_engine, m_tasksView);
|
|
m_taskEditor->hide();
|
|
connect(m_taskEditor, SIGNAL(requestDiscardChanges()), this, SLOT(onTaskEditorHide()));
|
|
connect(m_taskEditor, SIGNAL(requestSaveChanges()), this, SLOT(onTaskEditorHide()));
|
|
connect(m_taskEditor, SIGNAL(jobStarted(Plasma::ServiceJob*)), SLOT(busyUntil(Plasma::ServiceJob*)));
|
|
connect(m_taskEditor, SIGNAL(jobFinished(Plasma::ServiceJob*)), SLOT(jobFinished(Plasma::ServiceJob*)));
|
|
|
|
return m_graphicsWidget;
|
|
}
|
|
|
|
void RememberTheMilkPlasmoid::configChanged()
|
|
{
|
|
KConfigGroup cg = config();
|
|
m_token = cg.readEntry("token");
|
|
kDebug() << "Token from config: " << m_token;
|
|
|
|
if (m_token.isNull())
|
|
setConfigurationRequired(true, i18n("Authentication to Remember The Milk needed"));
|
|
else {
|
|
KConfigGroup cg = m_authService->operationDescription("AuthWithToken");
|
|
cg.writeEntry("token", m_token);
|
|
busyUntil(m_authService->startOperationCall(cg));
|
|
busyUntil(0); // Sets busy until we manually call jobFinished(0). Busy until first tasks refresh
|
|
}
|
|
|
|
QString sortBy = config().readEntry("SortBy").toLower();
|
|
kDebug() << "Config says sort by " << sortBy;
|
|
if (sortBy == "date" || sortBy == "due")
|
|
setSortBy(SortDue);
|
|
else if (sortBy == "priority")
|
|
setSortBy(SortPriority);
|
|
else
|
|
setSortBy(SortDue); // Default
|
|
}
|
|
|
|
#include "moc_rememberthemilk-plasmoid.cpp"
|