/* Copyright (C) 2008 by John Hobbs john@velvetcache.org This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #include "kicktweet.h" #include "xmlParser.h" #define MENU_TITLE 1 #define MENU_LOGIN 2 #define MENU_LOGOUT 3 #define MENU_TWEET 4 #define MENU_TIMELINES 5 extern "C" { KPanelApplet* init( QWidget *parent, const QString& configFile) { KGlobal::locale()->insertCatalogue("KickTweet"); return new KickTweet(configFile, KPanelApplet::Stretch, KPanelApplet::About, parent, "KickTweet"); } } KickTweet::KickTweet(const QString& configFile, Type type, int actions, QWidget *parent, const char *name) : KPanelApplet(configFile, type, actions, parent, name), busy(false), loggedIn(false) { // Get the current application configuration handle ksConfig = config(); //! \todo Keep the last (few?) tweets in memory. //! \todo How about credentials? Maybe just user names? mainBox = new QHBox(this); tweetText = new QLineEdit(mainBox); tweetText->setMaxLength(140); tweetText->setEnabled(false); watchForFocus(tweetText); // MUST HAVE for focus to land at all! px.load("/usr/share/pixmaps/KickTweet_sm.png"); tweetButton = new QPushButton(px, "", mainBox); connect(tweetButton, SIGNAL(clicked()), this, SLOT(tweetButtonEvent())); mainView = mainBox; mainView->show(); connect(&worker, SIGNAL(loginFinished(vc::TweetResponse)), this, SLOT(cbLogin(vc::TweetResponse))); connect(&worker, SIGNAL(logoutFinished(vc::TweetResponse)), this, SLOT(cbLogout(vc::TweetResponse))); connect(&worker, SIGNAL(sendTweetFinished(vc::TweetResponse)), this, SLOT(cbSendTweet(vc::TweetResponse))); connect(&worker, SIGNAL(shutdownFinished()), this, SLOT(cbShutdownFinished())); connect(&worker, SIGNAL(timelinesFinished(vc::TweetResponse)), this, SLOT(cbShowTimelines(vc::TweetResponse))); menu.insertTitle("KickTweet v"KICKTWEET_VERSION,MENU_TITLE); menu.insertItem("Login", this, SLOT(login()), 0, MENU_LOGIN); menu.insertSeparator(); menu.insertItem("Tweet!", this, SLOT(sendTweet()), 0, MENU_TWEET); menu.insertItem("Timelines", this, SLOT(showTimelines()), 0, MENU_TIMELINES); menu.insertItem("Logout", this, SLOT(logout()), 0, MENU_LOGOUT); menu.insertSeparator(); menu.insertItem("About", this, SLOT(doAbout())); menu.setItemEnabled(MENU_TWEET,false); menu.setItemEnabled(MENU_TIMELINES,false); menu.setItemEnabled(MENU_LOGOUT,false); } KickTweet::~KickTweet() { busy = true; worker.shutdown();; while(busy) sleep(1); } void KickTweet::doAbout () { about(); } void KickTweet::about() { KMessageBox::messageBox(this,KMessageBox::Information, "KickTweet v"KICKTWEET_VERSION"\n(c) John Hobbs 2008\njohn@velvetcache.org\nLicensed under the GPL\nhttp://static.velvetcache.org/projects/kicktweet", "About KickTweet"); } int KickTweet::widthForHeight(int height) const { // Send something static back or the panel freaks out and keeps resizing it. return 110; } int KickTweet::heightForWidth(int width) const { // Send something static back or the panel freaks out and keeps resizing it. return 22; } void KickTweet::resizeEvent(QResizeEvent *e) { mainBox->resize(e->size().width(),e->size().height()); } void KickTweet::tweetButtonEvent () { menu.exec(QCursor::pos()); } void KickTweet::login () { #ifdef _KT_DEBUG std::cout << __PRETTY_FUNCTION__ << std::endl; #endif if(busy) return; bool yesNoMaybePlease = false; QString _username = KInputDialog::getText("KickTweet","Enter your Twitter user name.", "", &yesNoMaybePlease); if("" == _username || !yesNoMaybePlease) return; QCString _password; int result = KPasswordDialog::getPassword(_password, "Enter your Twitter password."); if (KPasswordDialog::Rejected == result || "" == _password) return; tweetButton->setEnabled(false); busy = true; tweetText->setText("Logging in..."); tweetText->repaint(); worker.login(_username,QString(_password)); } void KickTweet::logout () { #ifdef _KT_DEBUG std::cout << __PRETTY_FUNCTION__ << std::endl; #endif busy = true; tweetButton->setEnabled(false); tweetText->setEnabled(false); worker.logout(); } void KickTweet::sendTweet () { #ifdef _KT_DEBUG std::cout << __PRETTY_FUNCTION__ << std::endl; #endif if(busy) return; if("" == tweetText->text().stripWhiteSpace()) // No empty tweets! return; tweetButton->setEnabled(false); tweetText->setEnabled(false); tweetTemp = tweetText->text(); tweetText->setText("Sending..."); tweetText->repaint(); worker.sendTweet(tweetTemp); } void KickTweet::notify (QString message) { #ifdef _KT_DEBUG std::cout << __PRETTY_FUNCTION__ << std::endl; #endif KPassivePopup * pop = new KPassivePopup(KPassivePopup::Balloon, this); pop->setView("KickTweet", message, px); pop->show(tweetButton->mapToGlobal(QPoint(0,0))); } void KickTweet::cbLogin (vc::TweetResponse response) { #ifdef _KT_DEBUG std::cout << __PRETTY_FUNCTION__ << " " << response.toString() << std::endl; #endif tweetButton->setEnabled(true); tweetText->setText(""); busy = false; loggedIn = !response.error; if(loggedIn) { tweetText->setEnabled(true); notify("Logged you in!"); menu.changeTitle(MENU_TITLE, worker.getUsername()); menu.setItemEnabled(MENU_LOGIN,false); menu.setItemEnabled(MENU_LOGOUT,true); menu.setItemEnabled(MENU_TWEET,true); menu.setItemEnabled(MENU_TIMELINES,true); } else notify("Could not log you in!\n"+response.errorString+""); //! \todo Get list of recent updates //! \todo Start polling timer, 30 seconds default? /* Updates/Timer plans: Poll every ~30 seconds for updates to your feed. - Run notify with an image if found (cache it?) + Tweet reply link straight from notify - Add to menu that you can tweet @ someone + Give list of people and a search interface on tweet - Add to menu that you can view your latest feed updates + Shortcut to tweet @ people and specific messages */ /* http://doc.trolltech.com/4.2/timers.html QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(update())); timer->start(1000) */ } void KickTweet::cbSendTweet (vc::TweetResponse response) { #ifdef _KT_DEBUG std::cout << __PRETTY_FUNCTION__ << " " << response.toString() << std::endl; #endif tweetButton->setEnabled(true); busy = false; if(!response.error) { tweetText->setText(""); notify("Tweet sent!"); } else { notify("Ack! Tweet failed:\n"+response.errorString+""); tweetText->setText(tweetTemp); } tweetText->setEnabled(true); } void KickTweet::cbShutdownFinished () { #ifdef _KT_DEBUG std::cout << __PRETTY_FUNCTION__ << std::endl; #endif busy = false; } void KickTweet::cbLogout (vc::TweetResponse response) { #ifdef _KT_DEBUG std::cout << __PRETTY_FUNCTION__ << " " << response.toString() << std::endl; #endif tweetButton->setEnabled(true); busy = false; if(!response.error) { loggedIn = false; tweetText->setText(""); menu.changeTitle(MENU_TITLE, "KickTweet v"KICKTWEET_VERSION); menu.setItemEnabled(MENU_LOGIN,true); menu.setItemEnabled(MENU_LOGOUT,false); menu.setItemEnabled(MENU_TWEET,false); menu.setItemEnabled(MENU_TIMELINES,false); notify("Logged you out!"); } else { tweetText->setEnabled(true); notify("Could not log you out!"); } } void KickTweet::showTimelines () { worker.getTimelines(); } void KickTweet::cbShowTimelines (std::list list) {}