Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomeu Vizoso <tomeu@tomeuvizoso.net>2006-11-15 12:56:19 (GMT)
committer Tomeu Vizoso <tomeu@tomeuvizoso.net>2006-11-15 12:56:19 (GMT)
commit59d57a03d9673e4f8f9c07aa7ba84edef32b8976 (patch)
tree825251fb38b27e97555f23d26026f60b7957d3ef
parent66acd2a91b0f0b98ef3428e4a4c14f21d8aa0f1f (diff)
First implementation of ClipboardService. Implement pdf viewing and downloading via ClipboardService.
-rw-r--r--.gitignore1
-rw-r--r--activities/web/webactivity.py33
-rw-r--r--configure.ac2
-rw-r--r--lib/python/_sugar.defs56
-rw-r--r--lib/python/_sugar.override3
-rw-r--r--lib/src/GeckoContentHandler.cpp40
-rw-r--r--lib/src/GeckoContentHandler.h (renamed from lib/src/SugarContentHandler.h)14
-rw-r--r--lib/src/GeckoDownload.cpp129
-rw-r--r--lib/src/GeckoDownload.h (renamed from lib/src/SugarDownload.h)14
-rw-r--r--lib/src/Makefile.am14
-rw-r--r--lib/src/SugarContentHandler.cpp43
-rw-r--r--lib/src/SugarDownload.cpp103
-rw-r--r--lib/src/sugar-browser-chandler.c56
-rw-r--r--lib/src/sugar-browser-chandler.h39
-rw-r--r--lib/src/sugar-browser.cpp22
-rw-r--r--lib/src/sugar-download-manager.c165
-rw-r--r--lib/src/sugar-download-manager.h57
-rw-r--r--lib/src/sugar-download.c108
-rw-r--r--lib/src/sugar-download.h50
-rw-r--r--lib/src/sugar-marshal.list2
-rw-r--r--services/Makefile.am2
-rw-r--r--services/clipboard/ClipboardService.py76
-rw-r--r--services/clipboard/Makefile.am15
-rw-r--r--services/clipboard/__init__.py0
-rw-r--r--services/clipboard/org.laptop.Clipboard.service.in4
-rwxr-xr-xservices/clipboard/sugar-clipboard44
-rw-r--r--shell/view/ClipboardIcon.py38
-rw-r--r--shell/view/ClipboardMenu.py56
-rw-r--r--shell/view/Makefile.am2
-rw-r--r--shell/view/frame/ClipboardBox.py42
-rw-r--r--shell/view/frame/Frame.py6
-rw-r--r--shell/view/frame/Makefile.am1
-rw-r--r--shell/view/stylesheet.py18
-rwxr-xr-xsugar-emulator6
-rw-r--r--sugar/Makefile.am2
-rw-r--r--sugar/clipboard/ClipboardService.py75
-rw-r--r--sugar/clipboard/Makefile.am5
-rw-r--r--sugar/clipboard/__init__.py0
-rw-r--r--sugar/graphics/ClipboardBubble.py131
-rw-r--r--sugar/graphics/Makefile.am1
-rw-r--r--sugar/graphics/menu.py3
41 files changed, 1187 insertions, 291 deletions
diff --git a/.gitignore b/.gitignore
index 0748927..edc5592 100644
--- a/.gitignore
+++ b/.gitignore
@@ -53,3 +53,4 @@ lib/src/sugar-marshal.c
lib/src/sugar-marshal.h
lib/src/stamp-sugar-marshal.c
lib/src/stamp-sugar-marshal.h
+services/clipboard/org.laptop.Clipboard.service
diff --git a/activities/web/webactivity.py b/activities/web/webactivity.py
index 200bd39..14a763d 100644
--- a/activities/web/webactivity.py
+++ b/activities/web/webactivity.py
@@ -18,10 +18,12 @@ from gettext import gettext as _
import gtk
import gtkmozembed
import logging
+import dbus
import _sugar
from sugar.activity import ActivityFactory
from sugar.activity.Activity import Activity
+from sugar.clipboard import ClipboardService
from sugar import env
from sugar.graphics import style
import web.stylesheet
@@ -104,12 +106,33 @@ def start():
style.load_stylesheet(web.stylesheet)
- chandler = _sugar.get_browser_chandler()
- chandler.connect('handle-content', handle_content_cb)
+ download_manager = _sugar.get_download_manager()
+ download_manager.connect('download-started', download_started_cb)
+ download_manager.connect('download-completed', download_completed_cb)
+ download_manager.connect('download-cancelled', download_started_cb)
+ download_manager.connect('download-progress', download_progress_cb)
def stop():
gtkmozembed.pop_startup()
-def handle_content_cb(chandler, url, mimeType, tmpFileName):
- activity = ActivityFactory.create("org.laptop.sugar.Xbook")
- activity.execute("open_document", [tmpFileName])
+def download_started_cb(download_manager, download):
+ name = download.get_url().rsplit('/', 1)[1]
+
+ cbService = ClipboardService.get_instance()
+ cbService.add_object(name,
+ download.get_mime_type(),
+ download.get_file_name())
+
+def download_completed_cb(download_manager, download):
+ cbService = ClipboardService.get_instance()
+ cbService.set_object_state(download.get_file_name(), 100)
+
+def download_cancelled_cb(download_manager, download):
+ #FIXME: Needs to update the state of the object to 'download stopped'.
+ #FIXME: Will do it when we complete progress on the definition of the
+ #FIXME: clipboard API.
+ raise "Cancelling downloads still not implemented."
+
+def download_progress_cb(download_manager, download):
+ cbService = ClipboardService.get_instance()
+ cbService.set_object_state(download.get_file_name(), download.get_percent())
diff --git a/configure.ac b/configure.ac
index fd1539a..e96a4ff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -64,6 +64,7 @@ lib/threadframe/Makefile
services/Makefile
services/presence/Makefile
services/nm/Makefile
+services/clipboard/Makefile
shell/Makefile
shell/conf/Makefile
shell/data/Makefile
@@ -76,6 +77,7 @@ sugar/__installed__.py
sugar/activity/Makefile
sugar/chat/Makefile
sugar/chat/sketchpad/Makefile
+sugar/clipboard/Makefile
sugar/graphics/Makefile
sugar/p2p/Makefile
sugar/presence/Makefile
diff --git a/lib/python/_sugar.defs b/lib/python/_sugar.defs
index 5a31c91..d692be3 100644
--- a/lib/python/_sugar.defs
+++ b/lib/python/_sugar.defs
@@ -35,11 +35,18 @@
(gtype-id "SUGAR_TYPE_PUSH_SCROLLER")
)
-(define-object BrowserChandler
+(define-object DownloadManager
(in-module "Sugar")
(parent "GObject")
- (c-name "SugarBrowserChandler")
- (gtype-id "SUGAR_TYPE_BROWSER_CHANDLER")
+ (c-name "SugarDownloadManager")
+ (gtype-id "SUGAR_TYPE_DOWNLOAD_MANAGER")
+)
+
+(define-object Download
+ (in-module "Sugar")
+ (parent "GObject")
+ (c-name "SugarDownload")
+ (gtype-id "SUGAR_TYPE_DOWNLOAD")
)
;; Enumerations and flags ...
@@ -181,14 +188,45 @@
)
)
-;; From sugar-browser-chandler.h
+;; From sugar-download-manager.h
+
+(define-function sugar_download_manager_get_type
+ (c-name "sugar_download_manager_get_type")
+ (return-type "GType")
+)
+
+(define-function get_download_manager
+ (c-name "sugar_get_download_manager")
+ (return-type "SugarDownloadManager*")
+)
+
+;; From sugar-download.h
-(define-function sugar_browser_chandler_get_type
- (c-name "sugar_browser_chandler_get_type")
+(define-function sugar_download_get_type
+ (c-name "sugar_download_get_type")
(return-type "GType")
)
-(define-function get_browser_chandler
- (c-name "sugar_get_browser_chandler")
- (return-type "SugarBrowserChandler*")
+(define-method get_file_name
+ (of-object "SugarDownload")
+ (c-name "sugar_download_get_file_name")
+ (return-type "const-gchar*")
+)
+
+(define-method get_url
+ (of-object "SugarDownload")
+ (c-name "sugar_download_get_url")
+ (return-type "const-gchar*")
+)
+
+(define-method get_mime_type
+ (of-object "SugarDownload")
+ (c-name "sugar_download_get_mime_type")
+ (return-type "const-gchar*")
+)
+
+(define-method get_percent
+ (of-object "SugarDownload")
+ (c-name "sugar_download_get_percent")
+ (return-type "gint")
)
diff --git a/lib/python/_sugar.override b/lib/python/_sugar.override
index 9d27bbe..212f264 100644
--- a/lib/python/_sugar.override
+++ b/lib/python/_sugar.override
@@ -9,7 +9,8 @@ headers
#include "sugar-address-entry.h"
#include "sugar-tray-manager.h"
#include "sugar-push-scroller.h"
-#include "sugar-browser-chandler.h"
+#include "sugar-download-manager.h"
+#include "sugar-download.h"
%%
modulename gecko
diff --git a/lib/src/GeckoContentHandler.cpp b/lib/src/GeckoContentHandler.cpp
new file mode 100644
index 0000000..4d9de8e
--- /dev/null
+++ b/lib/src/GeckoContentHandler.cpp
@@ -0,0 +1,40 @@
+#include <nsCExternalHandlerService.h>
+#include <nsIFile.h>
+
+#include "GeckoContentHandler.h"
+
+GeckoContentHandler::GeckoContentHandler()
+{
+
+}
+
+GeckoContentHandler::~GeckoContentHandler()
+{
+
+}
+
+NS_IMPL_ISUPPORTS1(GeckoContentHandler, nsIHelperAppLauncherDialog)
+
+NS_IMETHODIMP
+GeckoContentHandler::Show (nsIHelperAppLauncher *aLauncher,
+ nsISupports *aContext,
+ PRUint32 aReason)
+{
+ nsCOMPtr<nsIFile> tmpFile;
+ aLauncher->GetTargetFile(getter_AddRefs(tmpFile));
+
+ aLauncher->SaveToDisk (tmpFile, PR_FALSE);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+GeckoContentHandler::PromptForSaveToFile (nsIHelperAppLauncher *aLauncher,
+ nsISupports *aWindowContext,
+ const PRUnichar *aDefaultFile,
+ const PRUnichar *aSuggestedFileExtension,
+ nsILocalFile **_retval)
+{
+ return NS_OK;
+}
+
diff --git a/lib/src/SugarContentHandler.h b/lib/src/GeckoContentHandler.h
index da5ae40..ef6f3e2 100644
--- a/lib/src/SugarContentHandler.h
+++ b/lib/src/GeckoContentHandler.h
@@ -1,10 +1,10 @@
-#ifndef __SUGAR_CONTENT_HANDLER_H__
-#define __SUGAR_CONTENT_HANDLER_H__
+#ifndef __GECKO_CONTENT_HANDLER_H__
+#define __GECKO_CONTENT_HANDLER_H__
#include <nsCOMPtr.h>
#include <nsIHelperAppLauncherDialog.h>
-#define G_SUGARCONTENTHANDLER_CID \
+#define GECKOCONTENTHANDLER_CID \
{ /* 2321843e-6377-11db-967b-00e08161165f */ \
0x2321843e, \
0x6377, \
@@ -12,17 +12,17 @@
{0x96, 0x7b, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f} \
}
-class GSugarContentHandler : public nsIHelperAppLauncherDialog
+class GeckoContentHandler : public nsIHelperAppLauncherDialog
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIHELPERAPPLAUNCHERDIALOG
- GSugarContentHandler();
- virtual ~GSugarContentHandler();
+ GeckoContentHandler();
+ virtual ~GeckoContentHandler();
private:
};
-#endif /* __SUGAR_CONTENT_HANDLER_H */
+#endif /* __GECKO_CONTENT_HANDLER_H */
diff --git a/lib/src/GeckoDownload.cpp b/lib/src/GeckoDownload.cpp
new file mode 100644
index 0000000..66eb7c8
--- /dev/null
+++ b/lib/src/GeckoDownload.cpp
@@ -0,0 +1,129 @@
+#include "sugar-download-manager.h"
+
+#include "GeckoDownload.h"
+
+GeckoDownload::GeckoDownload ()
+{
+}
+
+GeckoDownload::~GeckoDownload ()
+{
+}
+
+NS_IMPL_ISUPPORTS3 (GeckoDownload,
+ nsIWebProgressListener,
+ nsIWebProgressListener2,
+ nsITransfer)
+
+NS_IMETHODIMP
+GeckoDownload::Init (nsIURI *aSource,
+ nsIURI *aTarget,
+ const nsAString &aDisplayName,
+ nsIMIMEInfo *aMIMEInfo,
+ PRTime aStartTime,
+ nsILocalFile *aTempFile,
+ nsICancelable *aCancelable)
+{
+ mSource = aSource;
+ aTarget->GetPath (mTargetFileName);
+ mMIMEInfo = aMIMEInfo;
+ mTempFile = aTempFile;
+// mCancelable = aCancelable; Just a reminder for when we implement cancelling downloads.
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+GeckoDownload::OnStateChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ PRUint32 aStateFlags,
+ nsresult aStatus)
+{
+ SugarDownloadManager *download_manager = sugar_get_download_manager ();
+
+ if (aStateFlags == STATE_START) {
+
+ nsCString url;
+ nsCString mimeType;
+
+ mMIMEInfo->GetMIMEType (mimeType);
+ mSource->GetSpec (url);
+
+ sugar_download_manager_download_started (download_manager,
+ url.get (),
+ mimeType.get (),
+ mTargetFileName.get ());
+
+ } else if (aStateFlags == STATE_STOP) {
+
+ if (NS_SUCCEEDED (aStatus)) {
+ sugar_download_manager_download_completed (download_manager,
+ mTargetFileName.get ());
+ } else {
+ sugar_download_manager_download_cancelled (download_manager,
+ mTargetFileName.get ());
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+GeckoDownload::OnProgressChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ PRInt32 aCurSelfProgress,
+ PRInt32 aMaxSelfProgress,
+ PRInt32 aCurTotalProgress,
+ PRInt32 aMaxTotalProgress)
+{
+ return OnProgressChange64 (aWebProgress,
+ aRequest,
+ aCurSelfProgress,
+ aMaxSelfProgress,
+ aCurTotalProgress,
+ aMaxTotalProgress);
+}
+
+NS_IMETHODIMP
+GeckoDownload::OnProgressChange64 (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ PRInt64 aCurSelfProgress,
+ PRInt64 aMaxSelfProgress,
+ PRInt64 aCurTotalProgress,
+ PRInt64 aMaxTotalProgress)
+{
+ SugarDownloadManager *download_manager = sugar_get_download_manager ();
+ PRInt32 percentComplete =
+ (PRInt32)(((float)aCurSelfProgress / (float)aMaxSelfProgress) * 100.0);
+
+ sugar_download_manager_update_progress (download_manager,
+ mTargetFileName.get (),
+ percentComplete);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+GeckoDownload::OnLocationChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ nsIURI *location)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+GeckoDownload::OnStatusChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ nsresult aStatus,
+ const PRUnichar *aMessage)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+GeckoDownload::OnSecurityChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ PRUint32 state)
+{
+ return NS_OK;
+}
diff --git a/lib/src/SugarDownload.h b/lib/src/GeckoDownload.h
index b858f53..24bff54 100644
--- a/lib/src/SugarDownload.h
+++ b/lib/src/GeckoDownload.h
@@ -1,5 +1,5 @@
-#ifndef SugarDownload_h__
-#define SugarDownload_h__
+#ifndef __GECKO_DOWNLOAD_H__
+#define __GECKO_DOWNLOAD_H__
#include <nsCOMPtr.h>
#include <nsIInterfaceRequestor.h>
@@ -10,7 +10,7 @@
#include <nsILocalFile.h>
#include <nsStringAPI.h>
-#define G_SUGARDOWNLOAD_CID \
+#define GECKODOWNLOAD_CID \
{ /* b1813bbe-6518-11db-967e-00e08161165f */ \
0xb1813bbe, \
0x6518, \
@@ -18,11 +18,11 @@
{0x96, 0x7e, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f} \
}
-class GSugarDownload : public nsITransfer
+class GeckoDownload : public nsITransfer
{
public:
- GSugarDownload();
- virtual ~GSugarDownload();
+ GeckoDownload();
+ virtual ~GeckoDownload();
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBPROGRESSLISTENER
@@ -36,4 +36,4 @@ protected:
nsILocalFile *mTempFile;
};
-#endif // SugarDownload_h__
+#endif // __GECKO_DOWNLOAD_H__
diff --git a/lib/src/Makefile.am b/lib/src/Makefile.am
index 0224885..3b51f1c 100644
--- a/lib/src/Makefile.am
+++ b/lib/src/Makefile.am
@@ -15,16 +15,18 @@ libsugarprivate_la_SOURCES = \
$(BUILT_SOURCES) \
eggaccelerators.h \
eggaccelerators.c \
+ GeckoContentHandler.h \
+ GeckoContentHandler.cpp \
+ GeckoDownload.h \
+ GeckoDownload.cpp \
sugar-address-entry.h \
sugar-address-entry.c \
sugar-browser.h \
sugar-browser.cpp \
- sugar-browser-chandler.h \
- sugar-browser-chandler.c \
- SugarContentHandler.h \
- SugarContentHandler.cpp \
- SugarDownload.h \
- SugarDownload.cpp \
+ sugar-download.h \
+ sugar-download.c \
+ sugar-download-manager.h \
+ sugar-download-manager.c \
sugar-key-grabber.h \
sugar-key-grabber.c \
sugar-push-scroller.c \
diff --git a/lib/src/SugarContentHandler.cpp b/lib/src/SugarContentHandler.cpp
deleted file mode 100644
index b39b20b..0000000
--- a/lib/src/SugarContentHandler.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-#include <nsCExternalHandlerService.h>
-#include <nsIFile.h>
-
-#include "sugar-browser-chandler.h"
-#include "SugarDownload.h"
-
-#include "SugarContentHandler.h"
-
-GSugarContentHandler::GSugarContentHandler()
-{
-
-}
-
-GSugarContentHandler::~GSugarContentHandler()
-{
-
-}
-
-NS_IMPL_ISUPPORTS1(GSugarContentHandler, nsIHelperAppLauncherDialog)
-
-NS_IMETHODIMP
-GSugarContentHandler::Show (nsIHelperAppLauncher *aLauncher,
- nsISupports *aContext,
- PRUint32 aReason)
-{
- nsCOMPtr<nsIFile> tmpFile;
- aLauncher->GetTargetFile(getter_AddRefs(tmpFile));
-
- aLauncher->SaveToDisk (tmpFile, PR_FALSE);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP GSugarContentHandler::PromptForSaveToFile(
- nsIHelperAppLauncher *aLauncher,
- nsISupports *aWindowContext,
- const PRUnichar *aDefaultFile,
- const PRUnichar *aSuggestedFileExtension,
- nsILocalFile **_retval)
-{
- return NS_OK;
-}
-
diff --git a/lib/src/SugarDownload.cpp b/lib/src/SugarDownload.cpp
deleted file mode 100644
index 9c68b8f..0000000
--- a/lib/src/SugarDownload.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-#include "sugar-browser-chandler.h"
-
-#include "SugarDownload.h"
-
-GSugarDownload::GSugarDownload()
-{
-}
-
-GSugarDownload::~GSugarDownload()
-{
-}
-
-NS_IMPL_ISUPPORTS3 (GSugarDownload,
- nsIWebProgressListener,
- nsIWebProgressListener2,
- nsITransfer)
-
-NS_IMETHODIMP
-GSugarDownload::Init (nsIURI *aSource,
- nsIURI *aTarget,
- const nsAString &aDisplayName,
- nsIMIMEInfo *aMIMEInfo,
- PRTime aStartTime,
- nsILocalFile *aTempFile,
- nsICancelable *aCancelable)
-{
- mSource = aSource;
- aTarget->GetPath(mTargetFileName);
- mMIMEInfo = aMIMEInfo;
- mTempFile = aTempFile;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GSugarDownload::OnStateChange (nsIWebProgress *aWebProgress, nsIRequest *aRequest,
- PRUint32 aStateFlags, nsresult aStatus)
-{
- nsCString url;
- nsCString mimeType;
- nsCString targetURI;
-
- if ((((aStateFlags & STATE_IS_REQUEST) &&
- (aStateFlags & STATE_IS_NETWORK) &&
- (aStateFlags & STATE_STOP)) ||
- aStateFlags == STATE_STOP) &&
- NS_SUCCEEDED (aStatus)) {
-
- mMIMEInfo->GetMIMEType(mimeType);
- mSource->GetSpec(url);
-
- SugarBrowserChandler *browser_chandler = sugar_get_browser_chandler();
- sugar_browser_chandler_handle_content(browser_chandler,
- url.get(),
- mimeType.get(),
- mTargetFileName.get());
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GSugarDownload::OnProgressChange (nsIWebProgress *aWebProgress,
- nsIRequest *aRequest,
- PRInt32 aCurSelfProgress,
- PRInt32 aMaxSelfProgress,
- PRInt32 aCurTotalProgress,
- PRInt32 aMaxTotalProgress)
-{
- return OnProgressChange64 (aWebProgress, aRequest,
- aCurSelfProgress, aMaxSelfProgress,
- aCurTotalProgress, aMaxTotalProgress);
-}
-
-NS_IMETHODIMP
-GSugarDownload::OnProgressChange64 (nsIWebProgress *aWebProgress,
- nsIRequest *aRequest,
- PRInt64 aCurSelfProgress,
- PRInt64 aMaxSelfProgress,
- PRInt64 aCurTotalProgress,
- PRInt64 aMaxTotalProgress)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GSugarDownload::OnLocationChange (nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GSugarDownload::OnStatusChange (nsIWebProgress *aWebProgress, nsIRequest *aRequest,
- nsresult aStatus, const PRUnichar *aMessage)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GSugarDownload::OnSecurityChange (nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state)
-{
- return NS_OK;
-}
diff --git a/lib/src/sugar-browser-chandler.c b/lib/src/sugar-browser-chandler.c
deleted file mode 100644
index a65519a..0000000
--- a/lib/src/sugar-browser-chandler.c
+++ /dev/null
@@ -1,56 +0,0 @@
-#include "sugar-marshal.h"
-#include "sugar-browser-chandler.h"
-
-enum {
- HANDLE_CONTENT,
- LAST_SIGNAL
-};
-static guint signals[LAST_SIGNAL] = { 0 };
-
-G_DEFINE_TYPE(SugarBrowserChandler, sugar_browser_chandler, G_TYPE_OBJECT)
-
-SugarBrowserChandler *browserChandler = NULL;
-
-static void
-sugar_browser_chandler_init(SugarBrowserChandler *browserChandler)
-{
-}
-
-static void
-sugar_browser_chandler_class_init(SugarBrowserChandlerClass *browser_chandler_class)
-{
- signals[HANDLE_CONTENT] =
- g_signal_new ("handle-content",
- G_OBJECT_CLASS_TYPE (browser_chandler_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (SugarBrowserChandlerClass, handle_content),
- NULL, NULL,
- sugar_marshal_VOID__STRING_STRING_STRING,
- G_TYPE_NONE, 3,
- G_TYPE_STRING,
- G_TYPE_STRING,
- G_TYPE_STRING);
-}
-
-SugarBrowserChandler *
-sugar_get_browser_chandler()
-{
- if(browserChandler == NULL)
- browserChandler = g_object_new(SUGAR_TYPE_BROWSER_CHANDLER, NULL);
-
- return browserChandler;
-}
-
-void
-sugar_browser_chandler_handle_content (SugarBrowserChandler *browser_chandler,
- const char *url,
- const char *mime_type,
- const char *tmp_file_name)
-{
- g_signal_emit(browser_chandler,
- signals[HANDLE_CONTENT],
- 0 /* details */,
- url,
- mime_type,
- tmp_file_name);
-}
diff --git a/lib/src/sugar-browser-chandler.h b/lib/src/sugar-browser-chandler.h
deleted file mode 100644
index cccd983..0000000
--- a/lib/src/sugar-browser-chandler.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef __SUGAR_BROWSER_CHANDLER_H__
-#define __SUGAR_BROWSER_CHANDLER_H__
-
-#include <glib-object.h>
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-typedef struct _SugarBrowserChandler SugarBrowserChandler;
-typedef struct _SugarBrowserChandlerClass SugarBrowserChandlerClass;
-
-#define SUGAR_TYPE_BROWSER_CHANDLER (sugar_browser_chandler_get_type())
-#define SUGAR_BROWSER_CHANDLER(object) (G_TYPE_CHECK_INSTANCE_CAST((object), SUGAR_TYPE_BROWSER_CHANDLER, SugarBrowserChandler))
-#define SUGAR_BROWSER_CHANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SUGAR_TYPE_BROWSER_CHANDLER, SugarBrowserChandlerClass))
-#define SUGAR_IS_BROWSER_CHANDLER(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), SUGAR_TYPE_BROWSER_CHANDLER))
-#define SUGAR_IS_BROWSER_CHANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SUGAR_TYPE_BROWSER_CHANDLER))
-#define SUGAR_BROWSER_CHANDLER_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), SUGAR_TYPE_BROWSER_CHANDLER, SugarBrowserChandlerClass))
-
-struct _SugarBrowserChandler {
- GObject base_instance;
-};
-
-struct _SugarBrowserChandlerClass {
- GObjectClass base_class;
-
- void (* handle_content) (char *url, char *tmp_file_name);
-
-};
-
-GType sugar_browser_chandler_get_type (void);
-SugarBrowserChandler *sugar_get_browser_chandler (void);
-void sugar_browser_chandler_handle_content (SugarBrowserChandler *chandler,
- const char *url,
- const char *mime_type,
- const char *tmp_file_name);
-
-G_END_DECLS
-
-#endif
diff --git a/lib/src/sugar-browser.cpp b/lib/src/sugar-browser.cpp
index d2ffb8a..dfd05d7 100644
--- a/lib/src/sugar-browser.cpp
+++ b/lib/src/sugar-browser.cpp
@@ -18,8 +18,8 @@
*/
#include "sugar-browser.h"
-#include "SugarContentHandler.h"
-#include "SugarDownload.h"
+#include "GeckoContentHandler.h"
+#include "GeckoDownload.h"
#include <gtkmozembed_internal.h>
#include <nsCOMPtr.h>
@@ -35,8 +35,8 @@
#include <nsIComponentRegistrar.h>
#include <nsIComponentManager.h>
-NS_GENERIC_FACTORY_CONSTRUCTOR(GSugarContentHandler)
-NS_GENERIC_FACTORY_CONSTRUCTOR(GSugarDownload)
+NS_GENERIC_FACTORY_CONSTRUCTOR(GeckoContentHandler)
+NS_GENERIC_FACTORY_CONSTRUCTOR(GeckoDownload)
enum {
PROP_0,
@@ -50,16 +50,16 @@ enum {
static const nsModuleComponentInfo sSugarComponents[] = {
{
- "Sugar Content Handler",
- G_SUGARCONTENTHANDLER_CID,
+ "Gecko Content Handler",
+ GECKOCONTENTHANDLER_CID,
NS_IHELPERAPPLAUNCHERDLG_CONTRACTID,
- GSugarContentHandlerConstructor
+ GeckoContentHandlerConstructor
},
{
- "Sugar Download",
- G_SUGARDOWNLOAD_CID,
+ "Gecko Download",
+ GECKODOWNLOAD_CID,
NS_TRANSFER_CONTRACTID,
- GSugarDownloadConstructor
+ GeckoDownloadConstructor
}
};
@@ -78,7 +78,7 @@ sugar_browser_startup(void)
PR_TRUE, getter_AddRefs(file));
NS_ENSURE_TRUE(file, FALSE);
- rv = prefService->ReadUserPrefs (file);
+ rv = prefService->ReadUserPrefs (file);
if (NS_FAILED(rv)) {
g_warning ("failed to read default preferences, error: %x", rv);
return FALSE;
diff --git a/lib/src/sugar-download-manager.c b/lib/src/sugar-download-manager.c
new file mode 100644
index 0000000..ead3bc8
--- /dev/null
+++ b/lib/src/sugar-download-manager.c
@@ -0,0 +1,165 @@
+#include "sugar-marshal.h"
+#include "sugar-download.h"
+#include "sugar-download-manager.h"
+
+enum {
+ DOWNLOAD_STARTED,
+ DOWNLOAD_COMPLETED,
+ DOWNLOAD_CANCELLED,
+ DOWNLOAD_PROGRESS,
+ LAST_SIGNAL
+};
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void sugar_download_manager_finalize (GObject *object);
+static void sugar_download_remove_download (gpointer key, gpointer value, gpointer user_data);
+
+G_DEFINE_TYPE (SugarDownloadManager, sugar_download_manager, G_TYPE_OBJECT)
+
+SugarDownloadManager *DownloadManager = NULL;
+
+static void
+sugar_download_manager_init (SugarDownloadManager *download_manager)
+{
+ download_manager->downloads = g_hash_table_new (g_str_hash, g_str_equal);
+}
+
+static void
+sugar_download_manager_class_init (SugarDownloadManagerClass *download_manager_class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (download_manager_class);
+
+ gobject_class->finalize = sugar_download_manager_finalize;
+
+ signals[DOWNLOAD_STARTED] =
+ g_signal_new ("download-started",
+ G_OBJECT_CLASS_TYPE (download_manager_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (SugarDownloadManagerClass, handle_content),
+ NULL, NULL,
+ sugar_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ G_TYPE_OBJECT);
+
+ signals[DOWNLOAD_COMPLETED] =
+ g_signal_new ("download-completed",
+ G_OBJECT_CLASS_TYPE (download_manager_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (SugarDownloadManagerClass, handle_content),
+ NULL, NULL,
+ sugar_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ G_TYPE_OBJECT);
+
+ signals[DOWNLOAD_CANCELLED] =
+ g_signal_new ("download-cancelled",
+ G_OBJECT_CLASS_TYPE (download_manager_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (SugarDownloadManagerClass, handle_content),
+ NULL, NULL,
+ sugar_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ G_TYPE_OBJECT);
+
+ signals[DOWNLOAD_PROGRESS] =
+ g_signal_new ("download-progress",
+ G_OBJECT_CLASS_TYPE (download_manager_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (SugarDownloadManagerClass, handle_content),
+ NULL, NULL,
+ sugar_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ G_TYPE_OBJECT);
+}
+
+static void
+sugar_download_manager_finalize (GObject *object)
+{
+ SugarDownloadManager *download_manager = SUGAR_DOWNLOAD_MANAGER (object);
+ g_hash_table_foreach (download_manager->downloads, sugar_download_remove_download, NULL);
+ g_hash_table_destroy (download_manager->downloads);
+}
+
+static void
+sugar_download_remove_download (gpointer key, gpointer value, gpointer user_data)
+{
+ g_free (value);
+}
+
+SugarDownloadManager *
+sugar_get_download_manager ()
+{
+ if (DownloadManager == NULL)
+ DownloadManager = g_object_new (SUGAR_TYPE_DOWNLOAD_MANAGER, NULL);
+
+ return DownloadManager;
+}
+
+void
+sugar_download_manager_download_started (SugarDownloadManager *download_manager,
+ const char *url,
+ const char *mime_type,
+ const char *file_name)
+{
+ SugarDownload *download = (SugarDownload *) g_hash_table_lookup (
+ download_manager->downloads,
+ file_name);
+
+ g_return_if_fail (download == NULL);
+
+ download = g_object_new (SUGAR_TYPE_DOWNLOAD, NULL);
+ sugar_download_set_url (download, url);
+ sugar_download_set_mime_type (download, mime_type);
+ sugar_download_set_file_name (download, file_name);
+
+ g_hash_table_insert (download_manager->downloads,
+ (gpointer)file_name,
+ download);
+
+ g_signal_emit (download_manager, signals[DOWNLOAD_STARTED], 0, download);
+}
+
+void
+sugar_download_manager_download_completed (SugarDownloadManager *download_manager,
+ const char *file_name)
+{
+ SugarDownload *download = (SugarDownload *) g_hash_table_lookup (
+ download_manager->downloads,
+ file_name);
+
+ g_return_if_fail (download);
+
+ g_signal_emit (download_manager, signals[DOWNLOAD_COMPLETED], 0, download);
+
+ g_hash_table_remove (download_manager->downloads, file_name);
+}
+
+void sugar_download_manager_download_cancelled (SugarDownloadManager *download_manager,
+ const char *file_name)
+{
+ SugarDownload *download = (SugarDownload *) g_hash_table_lookup (
+ download_manager->downloads,
+ file_name);
+
+ g_return_if_fail (download);
+
+ g_signal_emit (download_manager, signals[DOWNLOAD_CANCELLED], 0, download);
+
+ g_hash_table_remove (download_manager->downloads, file_name);
+}
+
+void
+sugar_download_manager_update_progress (SugarDownloadManager *download_manager,
+ const char *file_name,
+ const int percent)
+{
+ SugarDownload *download = (SugarDownload *) g_hash_table_lookup (
+ download_manager->downloads,
+ file_name);
+
+ g_return_if_fail (download);
+
+ sugar_download_set_percent (download, percent);
+
+ g_signal_emit (download_manager, signals [DOWNLOAD_PROGRESS], 0, download);
+}
diff --git a/lib/src/sugar-download-manager.h b/lib/src/sugar-download-manager.h
new file mode 100644
index 0000000..c58436b
--- /dev/null
+++ b/lib/src/sugar-download-manager.h
@@ -0,0 +1,57 @@
+#ifndef __SUGAR_DOWNLOAD_MANAGER_H__
+#define __SUGAR_DOWNLOAD_MANAGER_H__
+
+#include <glib-object.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SugarDownloadManager SugarDownloadManager;
+typedef struct _SugarDownloadManagerClass SugarDownloadManagerClass;
+
+#define SUGAR_TYPE_DOWNLOAD_MANAGER (sugar_download_manager_get_type())
+#define SUGAR_DOWNLOAD_MANAGER(object) (G_TYPE_CHECK_INSTANCE_CAST((object), SUGAR_TYPE_DOWNLOAD_MANAGER, SugarDownloadManager))
+#define SUGAR_DOWNLOAD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SUGAR_TYPE_DOWNLOAD_MANAGER, SugarDownloadManagerClass))
+#define SUGAR_IS_DOWNLOAD_MANAGER(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), SUGAR_TYPE_DOWNLOAD_MANAGER))
+#define SUGAR_IS_DOWNLOAD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SUGAR_TYPE_DOWNLOAD_MANAGER))
+#define SUGAR_DOWNLOAD_MANAGER_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), SUGAR_TYPE_DOWNLOAD_MANAGER, SugarDownloadManagerClass))
+
+struct _SugarDownloadManager {
+ GObject base_instance;
+
+ GHashTable *downloads;
+};
+
+struct _SugarDownloadManagerClass {
+ GObjectClass base_class;
+
+ void (* handle_content) (char *url, char *tmp_file_name);
+
+};
+
+GType sugar_download_manager_get_type(void);
+
+SugarDownloadManager *sugar_get_download_manager(void);
+
+void sugar_download_manager_download_started(
+ SugarDownloadManager *download_manager,
+ const char *url,
+ const char *mime_type,
+ const char *tmp_file_name);
+
+void sugar_download_manager_download_completed(
+ SugarDownloadManager *download_manager,
+ const char *tmp_file_name);
+
+void sugar_download_manager_download_cancelled(
+ SugarDownloadManager *download_manager,
+ const char *tmp_file_name);
+
+void sugar_download_manager_update_progress(
+ SugarDownloadManager *download_manager,
+ const char *tmp_file_name,
+ const int percent);
+
+G_END_DECLS
+
+#endif
diff --git a/lib/src/sugar-download.c b/lib/src/sugar-download.c
new file mode 100644
index 0000000..01ad809
--- /dev/null
+++ b/lib/src/sugar-download.c
@@ -0,0 +1,108 @@
+#include "sugar-download.h"
+
+static void sugar_download_finalize (GObject *object);
+
+G_DEFINE_TYPE (SugarDownload, sugar_download, G_TYPE_OBJECT)
+
+static void
+sugar_download_init (SugarDownload *download)
+{
+ download->file_name = NULL;
+ download->url = NULL;
+ download->mime_type = NULL;
+ download->percent = 0;
+}
+
+static void
+sugar_download_class_init (SugarDownloadClass *download_class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (download_class);
+
+ gobject_class->finalize = sugar_download_finalize;
+}
+
+void
+sugar_download_set_file_name (SugarDownload *download, const gchar *file_name)
+{
+ gchar *new_file_name;
+
+ g_return_if_fail (SUGAR_IS_DOWNLOAD (download));
+
+ new_file_name = g_strdup (file_name);
+ g_free (download->file_name);
+ download->file_name = new_file_name;
+}
+
+void
+sugar_download_set_url (SugarDownload *download, const gchar *url)
+{
+ gchar *new_url;
+
+ g_return_if_fail (SUGAR_IS_DOWNLOAD (download));
+
+ new_url = g_strdup (url);
+ g_free (download->url);
+ download->url = new_url;
+}
+
+void
+sugar_download_set_mime_type (SugarDownload *download, const gchar *mime_type)
+{
+ gchar *new_mime_type;
+
+ g_return_if_fail (SUGAR_IS_DOWNLOAD (download));
+
+ new_mime_type = g_strdup (mime_type);
+ g_free (download->mime_type);
+ download->mime_type = new_mime_type;
+}
+
+void
+sugar_download_set_percent (SugarDownload *download, const gint percent)
+{
+ g_return_if_fail (SUGAR_IS_DOWNLOAD (download));
+
+ download->percent = percent;
+}
+
+const gchar *
+sugar_download_get_file_name (SugarDownload *download)
+{
+ g_return_val_if_fail (SUGAR_IS_DOWNLOAD (download), NULL);
+
+ return download->file_name;
+}
+
+const gchar *
+sugar_download_get_url (SugarDownload *download)
+{
+ g_return_val_if_fail (SUGAR_IS_DOWNLOAD (download), NULL);
+
+ return download->url;
+}
+
+const gchar *
+sugar_download_get_mime_type (SugarDownload *download)
+{
+ g_return_val_if_fail (SUGAR_IS_DOWNLOAD (download), NULL);
+
+ return download->mime_type;
+}
+
+gint
+sugar_download_get_percent (SugarDownload *download)
+{
+ g_return_val_if_fail (SUGAR_IS_DOWNLOAD (download), -1);
+
+ return download->percent;
+}
+
+static void
+sugar_download_finalize (GObject *object)
+{
+ SugarDownload *download = SUGAR_DOWNLOAD (object);
+
+ g_free (download->file_name);
+ g_free (download->url);
+ g_free (download->mime_type);
+}
diff --git a/lib/src/sugar-download.h b/lib/src/sugar-download.h
new file mode 100644
index 0000000..ac3760b
--- /dev/null
+++ b/lib/src/sugar-download.h
@@ -0,0 +1,50 @@
+#ifndef __SUGAR_DOWNLOAD_H__
+#define __SUGAR_DOWNLOAD_H__
+
+#include <glib-object.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SugarDownload SugarDownload;
+typedef struct _SugarDownloadClass SugarDownloadClass;
+
+#define SUGAR_TYPE_DOWNLOAD (sugar_download_get_type())
+#define SUGAR_DOWNLOAD(object) (G_TYPE_CHECK_INSTANCE_CAST((object), SUGAR_TYPE_DOWNLOAD, SugarDownload))
+#define SUGAR_DOWNLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SUGAR_TYPE_DOWNLOAD, SugarDownloadClass))
+#define SUGAR_IS_DOWNLOAD(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), SUGAR_TYPE_DOWNLOAD))
+#define SUGAR_IS_DOWNLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SUGAR_TYPE_DOWNLOAD))
+#define SUGAR_DOWNLOAD_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), SUGAR_TYPE_DOWNLOAD, SugarDownloadClass))
+
+struct _SugarDownload {
+ GObject base_instance;
+
+ gchar *file_name;
+ gchar *url;
+ gchar *mime_type;
+ gint percent;
+};
+
+struct _SugarDownloadClass {
+ GObjectClass base_class;
+};
+
+GType sugar_download_get_type(void);
+
+void sugar_download_set_file_name (SugarDownload *download,
+ const gchar *file_name);
+void sugar_download_set_url (SugarDownload *download,
+ const gchar *url);
+void sugar_download_set_mime_type (SugarDownload *download,
+ const gchar *mime_type);
+void sugar_download_set_percent (SugarDownload *download,
+ const gint percent);
+
+const gchar *sugar_download_get_file_name (SugarDownload *download);
+const gchar *sugar_download_get_url (SugarDownload *download);
+const gchar *sugar_download_get_mime_type (SugarDownload *download);
+gint sugar_download_get_percent (SugarDownload *download);
+
+G_END_DECLS
+
+#endif /* __SUGAR_DOWNLOAD_H__ */
diff --git a/lib/src/sugar-marshal.list b/lib/src/sugar-marshal.list
index 5a0120f..de45d7a 100644
--- a/lib/src/sugar-marshal.list
+++ b/lib/src/sugar-marshal.list
@@ -1,3 +1,3 @@
VOID:OBJECT,STRING,LONG,LONG
VOID:OBJECT,LONG
-VOID:STRING,STRING,STRING
+VOID:OBJECT
diff --git a/services/Makefile.am b/services/Makefile.am
index 1bae7e7..2a0fe5a 100644
--- a/services/Makefile.am
+++ b/services/Makefile.am
@@ -1 +1 @@
-SUBDIRS = presence nm
+SUBDIRS = presence nm clipboard
diff --git a/services/clipboard/ClipboardService.py b/services/clipboard/ClipboardService.py
new file mode 100644
index 0000000..7389c58
--- /dev/null
+++ b/services/clipboard/ClipboardService.py
@@ -0,0 +1,76 @@
+# vi: ts=4 ai noet
+#
+# Copyright (C) 2006, Red Hat, Inc.
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import logging
+import gobject
+import dbus
+import dbus.service
+from sugar import env
+
+class ClipboardDBusServiceHelper(dbus.service.Object):
+
+ _CLIPBOARD_DBUS_INTERFACE = "org.laptop.Clipboard"
+ _CLIPBOARD_OBJECT_PATH = "/org/laptop/Clipboard"
+
+ def __init__(self, parent):
+ self._parent = parent
+
+ bus = dbus.SessionBus()
+ bus_name = dbus.service.BusName(self._CLIPBOARD_DBUS_INTERFACE, bus=bus)
+ dbus.service.Object.__init__(self, bus_name, self._CLIPBOARD_OBJECT_PATH)
+
+ @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
+ in_signature="sss", out_signature="")
+ def add_object(self, name, mimeType, fileName):
+ self.object_added(name, mimeType, fileName)
+ logging.debug('Added object of type ' + mimeType + ' with path at ' + fileName)
+
+ @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
+ in_signature="s", out_signature="")
+ def delete_object(self, fileName):
+ self.object_deleted(fileName)
+ logging.debug('Deleted object with path at ' + fileName)
+
+ @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
+ in_signature="si", out_signature="")
+ def set_object_state(self, fileName, percent):
+ logging.debug('Changed object with path at ' + fileName + ' with percent ' + str(percent))
+ self.object_state_changed(fileName, percent)
+
+ @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="sss")
+ def object_added(self, name, mimeType, fileName):
+ pass
+
+ @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="s")
+ def object_deleted(self, fileName):
+ pass
+
+ @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="si")
+ def object_state_changed(self, fileName, percent):
+ pass
+
+class ClipboardService(object):
+ def __init__(self):
+ self._dbus_helper = ClipboardDBusServiceHelper(self)
+
+ def run(self):
+ loop = gobject.MainLoop()
+ try:
+ loop.run()
+ except KeyboardInterrupt:
+ print 'Ctrl+C pressed, exiting...'
diff --git a/services/clipboard/Makefile.am b/services/clipboard/Makefile.am
new file mode 100644
index 0000000..ccc54f2
--- /dev/null
+++ b/services/clipboard/Makefile.am
@@ -0,0 +1,15 @@
+servicedir = $(datadir)/sugar/services
+service_in_files = org.laptop.Clipboard.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+ @sed -e "s|\@bindir\@|$(bindir)|" $< > $@
+
+sugardir = $(pkgdatadir)/services/clipboard
+sugar_PYTHON = \
+ __init__.py \
+ ClipboardService.py
+
+bin_SCRIPTS = sugar-clipboard
+
+EXTRA_DIST = $(service_in_files) $(bin_SCRIPTS)
diff --git a/services/clipboard/__init__.py b/services/clipboard/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/services/clipboard/__init__.py
diff --git a/services/clipboard/org.laptop.Clipboard.service.in b/services/clipboard/org.laptop.Clipboard.service.in
new file mode 100644
index 0000000..b38bf2b
--- /dev/null
+++ b/services/clipboard/org.laptop.Clipboard.service.in
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name = org.laptop.Clipboard
+Exec = @bindir@/sugar-clipboard
+
diff --git a/services/clipboard/sugar-clipboard b/services/clipboard/sugar-clipboard
new file mode 100755
index 0000000..bcbd280
--- /dev/null
+++ b/services/clipboard/sugar-clipboard
@@ -0,0 +1,44 @@
+#!/usr/bin/python
+# vi: ts=4 ai noet
+#
+# Copyright (C) 2006, Red Hat, Inc.
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import sys
+import logging
+
+from sugar import logger
+logger.start('clipboard')
+
+import gobject
+import pygtk
+pygtk.require('2.0')
+
+import dbus.glib
+
+from sugar import env
+
+sys.path.insert(0, env.get_services_dir())
+
+from clipboard.ClipboardService import ClipboardService
+
+logging.info('Starting clipboard service.')
+
+gobject.threads_init()
+dbus.glib.threads_init()
+
+app = ClipboardService()
+app.run()
diff --git a/shell/view/ClipboardIcon.py b/shell/view/ClipboardIcon.py
new file mode 100644
index 0000000..429fc99
--- /dev/null
+++ b/shell/view/ClipboardIcon.py
@@ -0,0 +1,38 @@
+from sugar.graphics.menuicon import MenuIcon
+from view.ClipboardMenu import ClipboardMenu
+from sugar.activity import ActivityFactory
+from sugar.clipboard import ClipboardService
+
+class ClipboardIcon(MenuIcon):
+
+ def __init__(self, menu_shell, name, file_name):
+ MenuIcon.__init__(self, menu_shell, icon_name='activity-xbook')
+ self._name = name
+ self._file_name = file_name
+ self._percent = 0
+ self.connect('activated', self._icon_activated_cb)
+ self._menu = None
+
+ def create_menu(self):
+ self._menu = ClipboardMenu(self._name, self._percent)
+ self._menu.connect('action', self._popup_action_cb)
+ return self._menu
+
+ def set_percent(self, percent):
+ self._percent = percent
+ if self._menu:
+ self._menu.set_percent(percent)
+
+ def _icon_activated_cb(self, icon):
+ if self._percent == 100:
+ activity = ActivityFactory.create("org.laptop.sugar.Xbook")
+ activity.execute("open_document", [self._file_name])
+
+ def _popup_action_cb(self, popup, action):
+ self.popdown()
+
+ if action == ClipboardMenu.ACTION_STOP_DOWNLOAD:
+ raise "Stopping downloads still not implemented."
+ elif action == ClipboardMenu.ACTION_DELETE:
+ cb_service = ClipboardService.get_instance()
+ cb_service.delete_object(self._file_name)
diff --git a/shell/view/ClipboardMenu.py b/shell/view/ClipboardMenu.py
new file mode 100644
index 0000000..44ca798
--- /dev/null
+++ b/shell/view/ClipboardMenu.py
@@ -0,0 +1,56 @@
+import gtk
+import gobject
+import hippo
+
+from sugar.graphics.menu import Menu
+from sugar.graphics.canvasicon import CanvasIcon
+from sugar.graphics.ClipboardBubble import ClipboardBubble
+from sugar.graphics import style
+
+class ClipboardMenuItem(ClipboardBubble):
+
+ def __init__(self, percent = 0, stylesheet="clipboard.Bubble"):
+ ClipboardBubble.__init__(self, percent = percent)
+ style.apply_stylesheet(self, stylesheet)
+
+class ClipboardMenu(Menu):
+
+ ACTION_DELETE = 0
+ ACTION_SHARE = 1
+ ACTION_STOP_DOWNLOAD = 2
+
+ def __init__(self, name, percent):
+ Menu.__init__(self, name)
+
+ self._progress_bar = ClipboardMenuItem(percent)
+ self._root.append(self._progress_bar)
+
+ #icon = CanvasIcon(icon_name='stock-share-mesh')
+ #self.add_action(icon, ClipboardMenu.ACTION_SHARE)
+
+ self._remove_icon = None
+ self._stop_icon = None
+
+ self._create_icons(percent)
+
+ def _create_icons(self, percent):
+ if percent == 100:
+ if not self._remove_icon:
+ self._remove_icon = CanvasIcon(icon_name='stock-remove')
+ self.add_action(self._remove_icon, ClipboardMenu.ACTION_DELETE)
+
+ if self._stop_icon:
+ self.remove_action(self._stop_icon)
+ self._stop_icon = None
+ else:
+ if not self._stop_icon:
+ self._stop_icon = CanvasIcon(icon_name='stock-close')
+ self.add_action(self._stop_icon, ClipboardMenu.ACTION_STOP_DOWNLOAD)
+
+ if self._remove_icon:
+ self.remove_action(self._remove_icon)
+ self._remove_icon = None
+
+ def set_percent(self, percent):
+ self._progress_bar.set_property('percent', percent)
+ self._create_icons(percent)
diff --git a/shell/view/Makefile.am b/shell/view/Makefile.am
index bf77593..bd90a2d 100644
--- a/shell/view/Makefile.am
+++ b/shell/view/Makefile.am
@@ -7,6 +7,8 @@ sugar_PYTHON = \
FirstTimeDialog.py \
BuddyIcon.py \
BuddyMenu.py \
+ ClipboardIcon.py \
+ ClipboardMenu.py \
OverlayWindow.py \
Shell.py \
dconmanager.py \
diff --git a/shell/view/frame/ClipboardBox.py b/shell/view/frame/ClipboardBox.py
new file mode 100644
index 0000000..849c7e0
--- /dev/null
+++ b/shell/view/frame/ClipboardBox.py
@@ -0,0 +1,42 @@
+import logging
+import dbus
+import hippo
+
+from sugar.graphics import style
+from view.ClipboardIcon import ClipboardIcon
+from sugar.clipboard import ClipboardService
+
+class ClipboardBox(hippo.CanvasBox):
+
+ def __init__(self, frame, menu_shell):
+ hippo.CanvasBox.__init__(self)
+ self._frame = frame
+ self._menu_shell = menu_shell
+ self._icons = {}
+
+ cb_service = ClipboardService.get_instance()
+ cb_service.connect('object-added', self._object_added_cb)
+ cb_service.connect('object-deleted', self._object_deleted_cb)
+ cb_service.connect('object-state-changed', self._object_state_changed_cb)
+
+ def _object_added_cb(self, cb_service, name, mimeType, fileName):
+ icon = ClipboardIcon(self._menu_shell, name, fileName)
+ style.apply_stylesheet(icon, 'frame.BuddyIcon')
+ self.append(icon)
+ self._icons[fileName] = icon
+
+ if not self._frame.is_visible():
+ self._frame.show_and_hide(0.1)
+
+ logging.debug('ClipboardBox: ' + fileName + ' was added.')
+
+ def _object_deleted_cb(self, cb_service, fileName):
+ icon = self._icons[fileName]
+ self.remove(icon)
+ del self._icons[fileName]
+ logging.debug('ClipboardBox: ' + fileName + ' was deleted.')
+
+ def _object_state_changed_cb(self, cb_service, fileName, percent):
+ icon = self._icons[fileName]
+ icon.set_percent(percent)
+ logging.debug('ClipboardBox: ' + fileName + ' state was changed.')
diff --git a/shell/view/frame/Frame.py b/shell/view/frame/Frame.py
index fd3c11e..37f28cb 100644
--- a/shell/view/frame/Frame.py
+++ b/shell/view/frame/Frame.py
@@ -23,6 +23,7 @@ from view.frame.ActivitiesBox import ActivitiesBox
from view.frame.ZoomBox import ZoomBox
from view.frame.overlaybox import OverlayBox
from view.frame.FriendsBox import FriendsBox
+from view.frame.ClipboardBox import ClipboardBox
from view.frame.PanelWindow import PanelWindow
from view.frame.notificationtray import NotificationTray
from view.frame.shutdownicon import ShutdownIcon
@@ -205,7 +206,10 @@ class Frame:
root.append(box)
# Left panel
- self._create_panel(grid, 0, 1, 1, 10)
+ [menu_shell, root] = self._create_panel(grid, 0, 1, 1, 10)
+
+ box = ClipboardBox(self, menu_shell)
+ root.append(box)
def _create_panel(self, grid, x, y, width, height):
panel = PanelWindow()
diff --git a/shell/view/frame/Makefile.am b/shell/view/frame/Makefile.am
index 81a5406..5d96a23 100644
--- a/shell/view/frame/Makefile.am
+++ b/shell/view/frame/Makefile.am
@@ -2,6 +2,7 @@ sugardir = $(pkgdatadir)/shell/view/frame
sugar_PYTHON = \
__init__.py \
ActivitiesBox.py \
+ ClipboardBox.py \
FriendsBox.py \
PanelWindow.py \
Frame.py \
diff --git a/shell/view/stylesheet.py b/shell/view/stylesheet.py
index e6c0688..1870f9c 100644
--- a/shell/view/stylesheet.py
+++ b/shell/view/stylesheet.py
@@ -60,3 +60,21 @@ friends_FriendIcon = {
friends_ActivityIcon = {
'size' : style.standard_icon_size
}
+
+clipboard_bubble = {
+ 'fill-color' : 0x646464FF,
+ 'stroke-color' : 0x646464FF,
+ 'progress-color': 0x333333FF,
+ 'spacing' : style.space_unit,
+ 'padding' : style.space_unit * 1.5
+}
+
+clipboard_menu_item_title = {
+ 'xalign': hippo.ALIGNMENT_START,
+ 'padding-left': 5,
+ 'color' : 0xFFFFFFFF,
+ 'font' : style.get_font_description('Bold', 1.2)
+}
+
+style.register_stylesheet("clipboard.Bubble", clipboard_bubble)
+style.register_stylesheet("clipboard.MenuItem.Title", clipboard_menu_item_title)
diff --git a/sugar-emulator b/sugar-emulator
index 6635a39..a26f0f2 100755
--- a/sugar-emulator
+++ b/sugar-emulator
@@ -40,6 +40,7 @@ if sourcedir:
bin_path = sourcedir
bin_path += ':' + os.path.join(sourcedir, 'shell')
bin_path += ':' + os.path.join(sourcedir, 'services/presence')
+ bin_path += ':' + os.path.join(sourcedir, 'services/clipboard')
if os.environ.has_key('PATH'):
old_path = os.environ['PATH']
@@ -54,6 +55,11 @@ if sourcedir:
bin = os.path.join(sourcedir,
'services/presence/sugar-presence-service')
setup.write_service('org.laptop.Presence', bin,
+ env.get_activity_info_dir())
+
+ bin = os.path.join(sourcedir,
+ 'services/clipboard/sugar-clipboard')
+ setup.write_service('org.laptop.Clipboard', bin,
env.get_activity_info_dir())
from sugar.emulator import Emulator
diff --git a/sugar/Makefile.am b/sugar/Makefile.am
index ae2e2ee..905555a 100644
--- a/sugar/Makefile.am
+++ b/sugar/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = activity chat graphics p2p presence
+SUBDIRS = activity chat clipboard graphics p2p presence
sugardir = $(pythondir)/sugar
sugar_PYTHON = \
diff --git a/sugar/clipboard/ClipboardService.py b/sugar/clipboard/ClipboardService.py
new file mode 100644
index 0000000..7c9dd1f
--- /dev/null
+++ b/sugar/clipboard/ClipboardService.py
@@ -0,0 +1,75 @@
+import dbus
+import gobject
+
+DBUS_SERVICE = "org.laptop.Clipboard"
+DBUS_INTERFACE = "org.laptop.Clipboard"
+DBUS_PATH = "/org/laptop/Clipboard"
+
+class ClipboardService(gobject.GObject):
+
+ __gsignals__ = {
+ 'object-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+ ([str, str, str])),
+ 'object-deleted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+ ([str])),
+ 'object-state-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+ ([str, int])),
+ }
+
+ def __init__(self):
+ gobject.GObject.__init__(self)
+
+ self._dbus_service = None
+ bus = dbus.SessionBus()
+ bus.add_signal_receiver(self._name_owner_changed_cb,
+ signal_name="NameOwnerChanged",
+ dbus_interface="org.freedesktop.DBus")
+ # Try to register to ClipboardService, if we fail, we'll try later.
+ try:
+ self._connect_clipboard_signals()
+ except dbus.DBusException, exception:
+ pass
+
+ def _connect_clipboard_signals(self):
+ bus = dbus.SessionBus()
+ proxy_obj = bus.get_object(DBUS_SERVICE, DBUS_PATH)
+ self._dbus_service = dbus.Interface(proxy_obj, DBUS_SERVICE)
+ self._dbus_service.connect_to_signal('object_added',
+ self._object_added_cb)
+ self._dbus_service.connect_to_signal('object_deleted',
+ self._object_deleted_cb)
+ self._dbus_service.connect_to_signal('object_state_changed',
+ self._object_state_changed_cb)
+
+ def _name_owner_changed_cb(self, name, old, new):
+ if name != DBUS_SERVICE:
+ return
+
+ if (not old and not len(old)) and (new and len(new)):
+ # ClipboardService started up
+ self._connect_clipboard_signals()
+
+ def _object_added_cb(self, name, mimeType, fileName):
+ self.emit('object-added', name, mimeType, fileName)
+
+ def _object_deleted_cb(self, fileName):
+ self.emit('object-deleted', fileName)
+
+ def _object_state_changed_cb(self, fileName, percent):
+ self.emit('object-state-changed', fileName, percent)
+
+ def add_object(self, name, mimeType, fileName):
+ self._dbus_service.add_object(name, mimeType, fileName)
+
+ def delete_object(self, fileName):
+ self._dbus_service.delete_object(fileName)
+
+ def set_object_state(self, fileName, percent):
+ self._dbus_service.set_object_state(fileName, percent)
+
+_clipboard_service = None
+def get_instance():
+ global _clipboard_service
+ if not _clipboard_service:
+ _clipboard_service = ClipboardService()
+ return _clipboard_service
diff --git a/sugar/clipboard/Makefile.am b/sugar/clipboard/Makefile.am
new file mode 100644
index 0000000..dbfabe9
--- /dev/null
+++ b/sugar/clipboard/Makefile.am
@@ -0,0 +1,5 @@
+sugardir = $(pythondir)/sugar/clipboard
+sugar_PYTHON = \
+ __init__.py \
+ ClipboardService.py
+
diff --git a/sugar/clipboard/__init__.py b/sugar/clipboard/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/sugar/clipboard/__init__.py
diff --git a/sugar/graphics/ClipboardBubble.py b/sugar/graphics/ClipboardBubble.py
new file mode 100644
index 0000000..b94fc26
--- /dev/null
+++ b/sugar/graphics/ClipboardBubble.py
@@ -0,0 +1,131 @@
+# Copyright (C) 2006, Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+#TODO: has to be merged with all the existing bubbles in a generic progress bar widget
+
+import math
+
+import gobject
+import gtk
+import hippo
+
+class ClipboardBubble(hippo.CanvasBox, hippo.CanvasItem):
+ __gtype_name__ = 'ClipboardBubble'
+
+ __gproperties__ = {
+ 'fill-color': (object, None, None,
+ gobject.PARAM_READWRITE),
+ 'stroke-color': (object, None, None,
+ gobject.PARAM_READWRITE),
+ 'progress-color': (object, None, None,
+ gobject.PARAM_READWRITE),
+ 'percent' : (object, None, None,
+ gobject.PARAM_READWRITE),
+ }
+
+ def __init__(self, **kwargs):
+ self._stroke_color = 0xFFFFFFFF
+ self._fill_color = 0xFFFFFFFF
+ self._progress_color = 0x000000FF
+ self._percent = 0
+ self._radius = 8
+
+ hippo.CanvasBox.__init__(self, **kwargs)
+
+ def do_set_property(self, pspec, value):
+ if pspec.name == 'fill-color':
+ self._fill_color = value
+ self.emit_paint_needed(0, 0, -1, -1)
+ elif pspec.name == 'stroke-color':
+ self._stroke_color = value
+ self.emit_paint_needed(0, 0, -1, -1)
+ elif pspec.name == 'progress-color':
+ self._progress_color = value
+ self.emit_paint_needed(0, 0, -1, -1)
+ elif pspec.name == 'percent':
+ self._percent = value
+ self.emit_paint_needed(0, 0, -1, -1)
+
+ def do_get_property(self, pspec):
+ if pspec.name == 'fill-color':
+ return self._fill_color
+ elif pspec.name == 'stroke-color':
+ return self._stroke_color
+ elif pspec.name == 'progress-color':
+ return self._progress_color
+ elif pspec.name == 'percent':
+ return self._percent
+
+ def _int_to_rgb(self, int_color):
+ red = (int_color >> 24) & 0x000000FF
+ green = (int_color >> 16) & 0x000000FF
+ blue = (int_color >> 8) & 0x000000FF
+ alpha = int_color & 0x000000FF
+ return (red / 255.0, green / 255.0, blue / 255.0)
+
+ def do_paint_below_children(self, cr, damaged_box):
+ [width, height] = self.get_allocation()
+
+ line_width = 3.0
+ x = line_width
+ y = line_width
+ width -= line_width * 2
+ height -= line_width * 2
+
+ self._paint_ellipse(cr, x, y, width, height, self._fill_color)
+
+ color = self._int_to_rgb(self._stroke_color)
+ cr.set_source_rgb(*color)
+ cr.set_line_width(line_width)
+ cr.stroke();
+
+ self._paint_progress_bar(cr, x, y, width, height, line_width)
+
+ def _paint_progress_bar(self, cr, x, y, width, height, line_width):
+ prog_x = x + line_width
+ prog_y = y + line_width
+ prog_width = (width - (line_width * 2)) * (self._percent / 100.0)
+ prog_height = (height - (line_width * 2))
+
+ self._paint_ellipse(cr, prog_x, prog_y, width, height, self._progress_color)
+
+ def _paint_ellipse(self, cr, x, y, width, height, fill_color):
+ cr.move_to(x + self._radius, y)
+ cr.arc(x + width - self._radius,
+ y + self._radius,
+ self._radius,
+ math.pi * 1.5,
+ math.pi * 2)
+ cr.arc(x + width - self._radius,
+ x + height - self._radius,
+ self._radius,
+ 0,
+ math.pi * 0.5)
+ cr.arc(x + self._radius,
+ y + height - self._radius,
+ self._radius,
+ math.pi * 0.5,
+ math.pi)
+ cr.arc(x + self._radius,
+ y + self._radius,
+ self._radius,
+ math.pi,
+ math.pi * 1.5);
+
+ color = self._int_to_rgb(fill_color)
+ cr.set_source_rgb(*color)
+ cr.fill_preserve();
diff --git a/sugar/graphics/Makefile.am b/sugar/graphics/Makefile.am
index 83b0920..9828c8c 100644
--- a/sugar/graphics/Makefile.am
+++ b/sugar/graphics/Makefile.am
@@ -4,6 +4,7 @@ sugar_PYTHON = \
bubble.py \
canvasicon.py \
colors.py \
+ ClipboardBubble.py \
grid.py \
iconcolor.py \
menu.py \
diff --git a/sugar/graphics/menu.py b/sugar/graphics/menu.py
index dfc0e47..508dbb0 100644
--- a/sugar/graphics/menu.py
+++ b/sugar/graphics/menu.py
@@ -97,6 +97,9 @@ class Menu(gtk.Window):
icon.connect('activated', self._action_clicked_cb, action_id)
self._action_box.append(icon)
+ def remove_action(self, icon):
+ self._action_box.remove(icon)
+
def _item_clicked_cb(self, icon, event, action):
self.emit('action', action)