First implementation of ClipboardService. Implement pdf viewing and downloading via ClipboardService.

master
Tomeu Vizoso 18 years ago
parent 66acd2a91b
commit 59d57a03d9

1
.gitignore vendored

@ -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

@ -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())

@ -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

@ -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")
)

@ -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

@ -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;
}

@ -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 */

@ -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;
}

@ -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__

@ -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 \

@ -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;
}

@ -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;
}

@ -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);
}

@ -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

@ -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;

@ -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);
}

@ -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

@ -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);
}

@ -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__ */

@ -1,3 +1,3 @@
VOID:OBJECT,STRING,LONG,LONG
VOID:OBJECT,LONG
VOID:STRING,STRING,STRING
VOID:OBJECT

@ -1 +1 @@
SUBDIRS = presence nm
SUBDIRS = presence nm clipboard

@ -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...'

@ -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)

@ -0,0 +1,4 @@
[D-BUS Service]
Name = org.laptop.Clipboard
Exec = @bindir@/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()

@ -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)

@ -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)

@ -7,6 +7,8 @@ sugar_PYTHON = \
FirstTimeDialog.py \
BuddyIcon.py \
BuddyMenu.py \
ClipboardIcon.py \
ClipboardMenu.py \
OverlayWindow.py \
Shell.py \
dconmanager.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.')

@ -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()

@ -2,6 +2,7 @@ sugardir = $(pkgdatadir)/shell/view/frame
sugar_PYTHON = \
__init__.py \
ActivitiesBox.py \
ClipboardBox.py \
FriendsBox.py \
PanelWindow.py \
Frame.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)

@ -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

@ -1,4 +1,4 @@
SUBDIRS = activity chat graphics p2p presence
SUBDIRS = activity chat clipboard graphics p2p presence
sugardir = $(pythondir)/sugar
sugar_PYTHON = \

@ -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

@ -0,0 +1,5 @@
sugardir = $(pythondir)/sugar/clipboard
sugar_PYTHON = \
__init__.py \
ClipboardService.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();

@ -4,6 +4,7 @@ sugar_PYTHON = \
bubble.py \
canvasicon.py \
colors.py \
ClipboardBubble.py \
grid.py \
iconcolor.py \
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)

Loading…
Cancel
Save