From b7030a74dd5208afc75be42c81201cfa72ebbcc9 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Tue, 17 Apr 2007 16:53:34 -0300 Subject: [PATCH 1/8] Drag images out of mozilla. --- browser/GeckoBrowserPersist.cpp | 185 +++++++++++++++++++++ browser/GeckoBrowserPersist.h | 19 +++ browser/GeckoDocumentObject.cpp | 187 +++++++++++++++++++++ browser/GeckoDocumentObject.h | 29 ++++ browser/GeckoDragDropHooks.cpp | 185 +++++++++++++++++++++ browser/GeckoDragDropHooks.h | 25 +++ browser/Makefile.am | 9 + browser/sugar-browser.cpp | 218 ++++++------------------- services/clipboard/clipboardobject.py | 11 ++ services/clipboard/clipboardservice.py | 3 +- services/clipboard/typeregistry.py | 21 +++ shell/view/frame/clipboardbox.py | 46 ++++-- 12 files changed, 753 insertions(+), 185 deletions(-) create mode 100644 browser/GeckoBrowserPersist.cpp create mode 100644 browser/GeckoBrowserPersist.h create mode 100644 browser/GeckoDocumentObject.cpp create mode 100644 browser/GeckoDocumentObject.h create mode 100644 browser/GeckoDragDropHooks.cpp create mode 100644 browser/GeckoDragDropHooks.h diff --git a/browser/GeckoBrowserPersist.cpp b/browser/GeckoBrowserPersist.cpp new file mode 100644 index 00000000..48de4d11 --- /dev/null +++ b/browser/GeckoBrowserPersist.cpp @@ -0,0 +1,185 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "GeckoBrowserPersist.h" + +GeckoBrowserPersist::GeckoBrowserPersist(SugarBrowser *browser) + : mBrowser(browser) +{ +} + +GeckoBrowserPersist::~GeckoBrowserPersist() +{ +} + +static nsresult +NewURI(const char *uri, nsIURI **result) +{ + nsresult rv; + + nsCOMPtr mgr; + NS_GetServiceManager (getter_AddRefs (mgr)); + NS_ENSURE_TRUE(mgr, FALSE); + + nsCOMPtr ioService; + rv = mgr->GetServiceByContractID ("@mozilla.org/network/io-service;1", + NS_GET_IID (nsIIOService), + getter_AddRefs(ioService)); + NS_ENSURE_SUCCESS(rv, FALSE); + + nsCString cSpec(uri); + return ioService->NewURI (cSpec, nsnull, nsnull, result); +} + +static nsresult +GetPostData(SugarBrowser *browser, nsIInputStream **postData) +{ +#ifdef HAVE_NS_WEB_BROWSER + nsCOMPtr webBrowser; + gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(browser), + getter_AddRefs(webBrowser)); + NS_ENSURE_TRUE(webBrowser, NS_ERROR_FAILURE); + + nsCOMPtr webNav(do_QueryInterface(webBrowser)); + NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE); + + PRInt32 sindex; + + nsCOMPtr sessionHistory; + webNav->GetSessionHistory(getter_AddRefs(sessionHistory)); + NS_ENSURE_TRUE(sessionHistory, NS_ERROR_FAILURE); + + nsCOMPtr entry; + sessionHistory->GetIndex(&sindex); + sessionHistory->GetEntryAtIndex(sindex, PR_FALSE, getter_AddRefs(entry)); + + nsCOMPtr shEntry(do_QueryInterface(entry)); + if (shEntry) { + shEntry->GetPostData(postData); + } + + return NS_OK; +#endif + return NS_ERROR_NOT_IMPLEMENTED; +} + +bool +GeckoBrowserPersist::SaveURI(const char *uri, const char *filename) +{ + nsresult rv; + + nsCOMPtr sourceURI; + rv = NewURI(uri, getter_AddRefs(sourceURI)); + NS_ENSURE_SUCCESS(rv, FALSE); + + nsCOMPtr destFile = do_CreateInstance("@mozilla.org/file/local;1"); + NS_ENSURE_TRUE(destFile, FALSE); + + destFile->InitWithNativePath(nsCString(filename)); + + nsCOMPtr postData; + GetPostData(mBrowser, getter_AddRefs(postData)); + + nsCOMPtr inputChannel; + rv = NS_NewChannel(getter_AddRefs(inputChannel), sourceURI, + nsnull, nsnull, nsnull, nsIRequest::LOAD_NORMAL); + NS_ENSURE_SUCCESS(rv, FALSE); + + nsCOMPtr httpChannel(do_QueryInterface(inputChannel)); + if (httpChannel) { + nsCOMPtr stream(do_QueryInterface(postData)); + if (stream) + { + // Rewind the postdata stream + stream->Seek(nsISeekableStream::NS_SEEK_SET, 0); + nsCOMPtr uploadChannel(do_QueryInterface(httpChannel)); + NS_ASSERTION(uploadChannel, "http must support nsIUploadChannel"); + // Attach the postdata to the http channel + uploadChannel->SetUploadStream(postData, EmptyCString(), -1); + } + } + + nsCOMPtr stream; + rv = inputChannel->Open(getter_AddRefs(stream)); + NS_ENSURE_SUCCESS(rv, FALSE); + + nsCOMPtr fileOutputStream = + do_CreateInstance(NS_LOCALFILEOUTPUTSTREAM_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, FALSE); + + rv = fileOutputStream->Init(destFile, -1, -1, 0); + NS_ENSURE_SUCCESS(rv, FALSE); + + // Read data from the input and write to the output + char buffer[8192]; + PRUint32 bytesRead; + PRUint32 bytesRemaining; + PRBool cancel = PR_FALSE; + PRBool readError; + + rv = stream->Available(&bytesRemaining); + NS_ENSURE_SUCCESS(rv, FALSE); + + while (!cancel && bytesRemaining) + { + readError = PR_TRUE; + rv = stream->Read(buffer, PR_MIN(sizeof(buffer), bytesRemaining), &bytesRead); + if (NS_SUCCEEDED(rv)) + { + readError = PR_FALSE; + // Write out the data until something goes wrong, or, it is + // all written. We loop because for some errors (e.g., disk + // full), we get NS_OK with some bytes written, then an error. + // So, we want to write again in that case to get the actual + // error code. + const char *bufPtr = buffer; // Where to write from. + while (NS_SUCCEEDED(rv) && bytesRead) + { + PRUint32 bytesWritten = 0; + rv = fileOutputStream->Write(bufPtr, bytesRead, &bytesWritten); + if (NS_SUCCEEDED(rv)) + { + bytesRead -= bytesWritten; + bufPtr += bytesWritten; + bytesRemaining -= bytesWritten; + // Force an error if (for some reason) we get NS_OK but + // no bytes written. + if (!bytesWritten) + { + rv = NS_ERROR_FAILURE; + cancel = PR_TRUE; + } + } + else + { + // Disaster - can't write out the bytes - disk full / permission? + cancel = PR_TRUE; + } + } + } + else + { + // Disaster - can't read the bytes - broken link / file error? + cancel = PR_TRUE; + } + } + NS_ENSURE_SUCCESS(rv, FALSE); + + stream->Close(); + + return TRUE; +} diff --git a/browser/GeckoBrowserPersist.h b/browser/GeckoBrowserPersist.h new file mode 100644 index 00000000..e9767893 --- /dev/null +++ b/browser/GeckoBrowserPersist.h @@ -0,0 +1,19 @@ +#ifndef __GECKO_BROWSER_PERSIST_H__ +#define __GECKO_BROWSER_PERSIST_H__ + +#include "sugar-browser.h" + +class GeckoBrowserPersist +{ +public: + GeckoBrowserPersist(SugarBrowser *browser); + ~GeckoBrowserPersist(); + + bool SaveURI(const char *uri, const char *filename); +private: + SugarBrowser *mBrowser; +protected: + /* additional members */ +}; + +#endif // __GECKO_BROWSER_PERSIST_H__ diff --git a/browser/GeckoDocumentObject.cpp b/browser/GeckoDocumentObject.cpp new file mode 100644 index 00000000..6f034e18 --- /dev/null +++ b/browser/GeckoDocumentObject.cpp @@ -0,0 +1,187 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "GeckoDocumentObject.h" +#include "GeckoBrowserPersist.h" + +GeckoDocumentObject::GeckoDocumentObject(SugarBrowser *browser, nsIDOMNode *node) + : mBrowser(browser), + mNode(node), + mImage(NULL) +{ +} + +GeckoDocumentObject::~GeckoDocumentObject() +{ +} + +bool GeckoDocumentObject::IsImage() +{ + if(mImage) { + return true; + } + + nsresult rv; + + PRUint16 type; + rv = mNode->GetNodeType(&type); + if(NS_FAILED(rv)) return rv; + + nsCOMPtr element = do_QueryInterface(mNode); + if ((nsIDOMNode::ELEMENT_NODE == type) && element) { + nsString uTag; + rv = element->GetLocalName(uTag); + if(NS_FAILED(rv)) return rv; + + nsCString tag; + NS_UTF16ToCString (uTag, NS_CSTRING_ENCODING_UTF8, tag); + + if (g_ascii_strcasecmp (tag.get(), "img") == 0) { + nsCOMPtr imagePtr; + imagePtr = do_QueryInterface(mNode, &rv); + if(NS_FAILED(rv)) return rv; + + mImage = imagePtr; + + return true; + } + } + + return false; +} + +static nsresult +NewURI(const char *uri, nsIURI **result) +{ + nsresult rv; + + nsCOMPtr mgr; + NS_GetServiceManager (getter_AddRefs (mgr)); + NS_ENSURE_TRUE(mgr, FALSE); + + nsCOMPtr ioService; + rv = mgr->GetServiceByContractID ("@mozilla.org/network/io-service;1", + NS_GET_IID (nsIIOService), + getter_AddRefs(ioService)); + NS_ENSURE_SUCCESS(rv, FALSE); + + nsCString cSpec(uri); + return ioService->NewURI (cSpec, nsnull, nsnull, result); +} + +static nsresult +FilenameFromContentDisposition(nsCString contentDisposition, nsCString &fileName) +{ + nsresult rv; + nsCString fallbackCharset; + + nsCOMPtr mimehdrpar = + do_GetService("@mozilla.org/network/mime-hdrparam;1"); + NS_ENSURE_TRUE(mimehdrpar, NS_ERROR_FAILURE); + + nsString aFileName; + rv = mimehdrpar->GetParameter (contentDisposition, "filename", + fallbackCharset, PR_TRUE, nsnull, + aFileName); + + if (NS_FAILED(rv) || !fileName.Length()) { + rv = mimehdrpar->GetParameter (contentDisposition, "name", + fallbackCharset, PR_TRUE, nsnull, + aFileName); + } + + if (NS_SUCCEEDED(rv) && fileName.Length()) { + NS_UTF16ToCString (aFileName, NS_CSTRING_ENCODING_UTF8, fileName); + } + + return NS_OK; +} + +char * +GeckoDocumentObject::GetImageName() +{ + if(!IsImage()) { + return NULL; + } + + nsresult rv; + char *imgURIStr = GetImageURI(); + + nsCOMPtr imageURI; + rv = NewURI(imgURIStr, getter_AddRefs(imageURI)); + NS_ENSURE_SUCCESS(rv, NULL); + + nsCOMPtr mgr; + NS_GetServiceManager (getter_AddRefs (mgr)); + NS_ENSURE_TRUE(mgr, NULL); + + nsCOMPtr imgCache; + rv = mgr->GetServiceByContractID("@mozilla.org/image/cache;1", + NS_GET_IID (imgICache), + getter_AddRefs(imgCache)); + NS_ENSURE_SUCCESS(rv, NULL); + + nsCOMPtr imgProperties; + imgCache->FindEntryProperties(imageURI, getter_AddRefs(imgProperties)); + if (imgProperties) { + nsCOMPtr dispositionCString; + imgProperties->Get("content-disposition", + NS_GET_IID(nsISupportsCString), + getter_AddRefs(dispositionCString)); + if (dispositionCString) { + nsCString contentDisposition; + dispositionCString->GetData(contentDisposition); + FilenameFromContentDisposition(contentDisposition, mImageName); + } + } + + if (!mImageName.Length()) { + nsCOMPtr url(do_QueryInterface(imageURI)); + if (url) { + url->GetFileName(mImageName); + } + } + + return mImageName.Length() ? g_strdup(mImageName.get()) : NULL; +} + +char * +GeckoDocumentObject::GetImageURI() +{ + if(!IsImage()) { + return NULL; + } + + if(!mImageURI.Length()) { + nsresult rv; + nsString img; + rv = mImage->GetSrc(img); + if (NS_FAILED(rv)) return NULL; + + NS_UTF16ToCString (img, NS_CSTRING_ENCODING_UTF8, mImageURI); + } + return g_strdup(mImageURI.get()); +} + +bool +GeckoDocumentObject::SaveImage(const char *filename) +{ + GeckoBrowserPersist browserPersist(mBrowser); + return browserPersist.SaveURI(mImageURI.get(), filename); +} diff --git a/browser/GeckoDocumentObject.h b/browser/GeckoDocumentObject.h new file mode 100644 index 00000000..05328e55 --- /dev/null +++ b/browser/GeckoDocumentObject.h @@ -0,0 +1,29 @@ +#ifndef __GECKO_DOCUMENT_OBJECT_H__ +#define __GECKO_DOCUMENT_OBJECT_H__ + +#include +#include + +#include "sugar-browser.h" + +class GeckoDocumentObject +{ +public: + GeckoDocumentObject(SugarBrowser *browser, nsIDOMNode *node); + ~GeckoDocumentObject(); + + bool IsImage(); + char *GetImageURI(); + char *GetImageName(); + bool SaveImage(const char *filename); +private: + SugarBrowser *mBrowser; + nsCOMPtr mNode; + nsCOMPtr mImage; + nsCString mImageURI; + nsCString mImageName; +protected: + /* additional members */ +}; + +#endif // __GECKO_DOCUMENT_OBJECT_H__ diff --git a/browser/GeckoDragDropHooks.cpp b/browser/GeckoDragDropHooks.cpp new file mode 100644 index 00000000..425ee455 --- /dev/null +++ b/browser/GeckoDragDropHooks.cpp @@ -0,0 +1,185 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "GeckoDragDropHooks.h" +#include "GeckoDocumentObject.h" + +#define TEXT_URI_LIST "text/uri-list" +#define TEXT_X_MOZ_URL "text/x-moz-url" +#define FILE_LOCALHOST "file://" + +//***************************************************************************** +// UriListDataProvider +//***************************************************************************** + +class UriListDataProvider : public nsIFlavorDataProvider +{ +public: + UriListDataProvider(GeckoDocumentObject *mDocumentObject); + virtual ~UriListDataProvider(); + NS_DECL_ISUPPORTS + NS_DECL_NSIFLAVORDATAPROVIDER +private: + GeckoDocumentObject *mDocumentObject; + nsCString mFilePath; +}; + +//***************************************************************************** + +NS_IMPL_ISUPPORTS1(UriListDataProvider, nsIFlavorDataProvider) + +UriListDataProvider::UriListDataProvider(GeckoDocumentObject *documentObject) + : mDocumentObject(documentObject) +{ +} + +UriListDataProvider::~UriListDataProvider() +{ + if(mFilePath.Length()) { + remove(mFilePath.get()); + } + + delete mDocumentObject; +} + +NS_IMETHODIMP +UriListDataProvider::GetFlavorData(nsITransferable *aTransferable, + const char *aFlavor, nsISupports **aData, + PRUint32 *aDataLen) +{ + NS_ENSURE_ARG_POINTER(aData && aDataLen); + + nsresult rv = NS_ERROR_NOT_IMPLEMENTED; + char *image_name; + timeval timestamp; + + *aData = nsnull; + *aDataLen = 0; + + if(g_ascii_strcasecmp(aFlavor, TEXT_URI_LIST) != 0) { + return rv; + } + + gettimeofday(×tamp, NULL); + + mFilePath.Append(g_get_tmp_dir()); + mFilePath.Append("/"); + mFilePath.AppendInt(timestamp.tv_sec); + mFilePath.AppendInt(timestamp.tv_usec); + + image_name = mDocumentObject->GetImageName(); + mFilePath.Append(image_name); + g_free(image_name); + + if(!mDocumentObject->SaveImage(mFilePath.get())) { + return NS_ERROR_FAILURE; + } + + nsCString localURI(FILE_LOCALHOST); + localURI.Append(mFilePath); + + nsString localURI16; + NS_CStringToUTF16(localURI, NS_CSTRING_ENCODING_UTF8, localURI16); + + nsCOMPtr localURIData(do_CreateInstance( + "@mozilla.org/supports-string;1", &rv)); + if(NS_FAILED(rv)) return rv; + + rv = localURIData->SetData(localURI16); + if(NS_FAILED(rv)) return rv; + + CallQueryInterface(localURIData, aData); + *aDataLen = sizeof(nsISupportsString*); + + // FIXME: Why do we need this? Is there a leak in mozilla? + this->Release(); + + return rv; +} + +//***************************************************************************** +// GeckoDragDropHooks +//***************************************************************************** + +NS_IMPL_ISUPPORTS1(GeckoDragDropHooks, nsIClipboardDragDropHooks) + +GeckoDragDropHooks::GeckoDragDropHooks(SugarBrowser *browser) + : mBrowser(browser) +{ +} + +GeckoDragDropHooks::~GeckoDragDropHooks() +{ +} + +NS_IMETHODIMP +GeckoDragDropHooks::AllowStartDrag(nsIDOMEvent *event, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +GeckoDragDropHooks::AllowDrop(nsIDOMEvent *event, nsIDragSession *session, + PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +GeckoDragDropHooks::OnCopyOrDrag(nsIDOMEvent *aEvent, nsITransferable *trans, + PRBool *_retval) +{ + nsresult rv; + + *_retval = true; + + nsCOMPtr mouseEvent; + mouseEvent = do_QueryInterface(aEvent, &rv); + if(NS_FAILED(rv)) return rv; + + nsCOMPtr eventTarget; + rv = mouseEvent->GetTarget(getter_AddRefs(eventTarget)); + if(NS_FAILED(rv)) return rv; + + nsCOMPtr targetNode; + targetNode = do_QueryInterface(eventTarget, &rv); + if(NS_FAILED(rv)) return rv; + + GeckoDocumentObject *documentObject = new GeckoDocumentObject(mBrowser, + targetNode); + if(documentObject->IsImage()) { + rv = trans->RemoveDataFlavor(TEXT_X_MOZ_URL); + if(NS_FAILED(rv)) return rv; + + rv = trans->AddDataFlavor(TEXT_URI_LIST); + if(NS_FAILED(rv)) return rv; + + UriListDataProvider *rawPtr = new UriListDataProvider(documentObject); + nsCOMPtr dataProvider(do_QueryInterface(rawPtr, &rv)); + if(NS_FAILED(rv)) return rv; + + rv = trans->SetTransferData(TEXT_URI_LIST, dataProvider, 0); + if(NS_FAILED(rv)) return rv; + } + + return rv; +} + +NS_IMETHODIMP +GeckoDragDropHooks::OnPasteOrDrop(nsIDOMEvent *event, nsITransferable *trans, + PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} diff --git a/browser/GeckoDragDropHooks.h b/browser/GeckoDragDropHooks.h new file mode 100644 index 00000000..c551c0e5 --- /dev/null +++ b/browser/GeckoDragDropHooks.h @@ -0,0 +1,25 @@ +#ifndef __GECKO_DRAG_DROP_HOOKS_H__ +#define __GECKO_DRAG_DROP_HOOKS_H__ + +#include + +#include "sugar-browser.h" + +class GeckoDragDropHooks : public nsIClipboardDragDropHooks +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSICLIPBOARDDRAGDROPHOOKS + + GeckoDragDropHooks(SugarBrowser *browser); + +private: + ~GeckoDragDropHooks(); + + SugarBrowser *mBrowser; + +protected: + /* additional members */ +}; + +#endif // __GECKO_DRAG_DROP_HOOKS_H__ diff --git a/browser/Makefile.am b/browser/Makefile.am index ae013e01..b4185837 100644 --- a/browser/Makefile.am +++ b/browser/Makefile.am @@ -3,6 +3,7 @@ libsugarbrowser_la_CPPFLAGS = \ $(LIB_CFLAGS) \ $(GECKO_CFLAGS) \ $(NSPR_CFLAGS) \ + -I$(MOZILLA_INCLUDE_DIR)/commandhandler \ -I$(MOZILLA_INCLUDE_DIR)/dom \ -I$(MOZILLA_INCLUDE_DIR)/docshell \ -I$(MOZILLA_INCLUDE_DIR)/exthandler \ @@ -15,6 +16,8 @@ libsugarbrowser_la_CPPFLAGS = \ -I$(MOZILLA_INCLUDE_DIR)/uriloader \ -I$(MOZILLA_INCLUDE_DIR)/webbrwsr \ -I$(MOZILLA_INCLUDE_DIR)/webbrowserpersist \ + -I$(MOZILLA_INCLUDE_DIR)/widget \ + -I$(MOZILLA_INCLUDE_DIR)/xpcom \ -DPLUGIN_DIR=\"$(libdir)/mozilla/plugins\" \ -DSHARE_DIR=\"$(pkgdatadir)\" @@ -26,8 +29,14 @@ libsugarbrowser_la_LIBADD = \ libsugarbrowser_la_SOURCES = \ $(BUILT_SOURCES) \ + GeckoBrowserPersist.h \ + GeckoBrowserPersist.cpp \ GeckoContentHandler.h \ GeckoContentHandler.cpp \ + GeckoDocumentObject.h \ + GeckoDocumentObject.cpp \ + GeckoDragDropHooks.h \ + GeckoDragDropHooks.cpp \ GeckoDownload.h \ GeckoDownload.cpp \ sugar-address-entry.c \ diff --git a/browser/sugar-browser.cpp b/browser/sugar-browser.cpp index cd455b6f..270631b1 100644 --- a/browser/sugar-browser.cpp +++ b/browser/sugar-browser.cpp @@ -23,6 +23,9 @@ #include "sugar-marshal.h" #include "GeckoContentHandler.h" #include "GeckoDownload.h" +#include "GeckoDragDropHooks.h" +#include "GeckoDocumentObject.h" +#include "GeckoBrowserPersist.h" #include #include @@ -56,6 +59,8 @@ #include #include #include +#include +#include enum { PROP_0, @@ -75,6 +80,8 @@ enum { static guint signals[N_SIGNALS]; +static GObjectClass *parent_class = NULL; + static const nsModuleComponentInfo sSugarComponents[] = { { "Gecko Content Handler", @@ -210,25 +217,6 @@ sugar_browser_shutdown(void) G_DEFINE_TYPE(SugarBrowser, sugar_browser, GTK_TYPE_MOZ_EMBED) -static nsresult -NewURI(const char *uri, nsIURI **result) -{ - nsresult rv; - - nsCOMPtr mgr; - NS_GetServiceManager (getter_AddRefs (mgr)); - NS_ENSURE_TRUE(mgr, FALSE); - - nsCOMPtr ioService; - rv = mgr->GetServiceByContractID ("@mozilla.org/network/io-service;1", - NS_GET_IID (nsIIOService), - getter_AddRefs(ioService)); - NS_ENSURE_SUCCESS(rv, FALSE); - - nsCString cSpec(uri); - return ioService->NewURI (cSpec, nsnull, nsnull, result); -} - static nsresult FilenameFromContentDisposition(nsCString contentDisposition, nsCString &fileName) { @@ -258,38 +246,6 @@ FilenameFromContentDisposition(nsCString contentDisposition, nsCString &fileName return NS_OK; } -static nsresult -ImageNameFromCache(nsIURI *imgURI, nsCString &imgName) -{ - nsresult rv; - - nsCOMPtr mgr; - NS_GetServiceManager (getter_AddRefs (mgr)); - NS_ENSURE_TRUE(mgr, NS_ERROR_FAILURE); - - nsCOMPtr imgCache; - rv = mgr->GetServiceByContractID("@mozilla.org/image/cache;1", - NS_GET_IID (imgICache), - getter_AddRefs(imgCache)); - NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); - - nsCOMPtr imgProperties; - imgCache->FindEntryProperties(imgURI, getter_AddRefs(imgProperties)); - if (imgProperties) { - nsCOMPtr dispositionCString; - imgProperties->Get("content-disposition", - NS_GET_IID(nsISupportsCString), - getter_AddRefs(dispositionCString)); - if (dispositionCString) { - nsCString contentDisposition; - dispositionCString->GetData(contentDisposition); - FilenameFromContentDisposition(contentDisposition, imgName); - } - } - - return NS_OK; -} - static SugarBrowserMetadata * sugar_browser_get_document_metadata(SugarBrowser *browser) { @@ -382,13 +338,47 @@ sugar_browser_get_property(GObject *object, } } +static void +sugar_browser_realize(GtkWidget *widget) +{ + GTK_WIDGET_CLASS(parent_class)->realize(widget); + +#ifdef HAVE_NS_WEB_BROWSER + GtkMozEmbed *embed = GTK_MOZ_EMBED(widget); + nsCOMPtr webBrowser; + gtk_moz_embed_get_nsIWebBrowser(embed, getter_AddRefs(webBrowser)); + NS_ENSURE_TRUE(webBrowser, ); + + nsCOMPtr commandManager = do_GetInterface(webBrowser); + if (commandManager) { + nsresult rv; + nsIClipboardDragDropHooks *rawPtr = new GeckoDragDropHooks( + SUGAR_BROWSER(widget)); + nsCOMPtr geckoDragDropHooks( + do_QueryInterface(rawPtr, &rv)); + NS_ENSURE_SUCCESS(rv, ); + + nsCOMPtr DOMWindow = do_GetInterface(webBrowser); + nsCOMPtr cmdParamsObj = do_CreateInstance( + NS_COMMAND_PARAMS_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, ); + cmdParamsObj->SetISupportsValue("addhook", geckoDragDropHooks); + commandManager->DoCommand("cmd_clipboardDragDropHook", cmdParamsObj, + DOMWindow); + } +#endif +} static void sugar_browser_class_init(SugarBrowserClass *browser_class) { - GObjectClass *gobject_class = G_OBJECT_CLASS(browser_class); + GObjectClass *gobject_class = G_OBJECT_CLASS(browser_class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(browser_class); - gobject_class->get_property = sugar_browser_get_property; + parent_class = (GObjectClass *) g_type_class_peek_parent(browser_class); + + gobject_class->get_property = sugar_browser_get_property; + widget_class->realize = sugar_browser_realize; signals[MOUSE_CLICK] = g_signal_new ("mouse_click", SUGAR_TYPE_BROWSER, @@ -570,29 +560,6 @@ location_cb(GtkMozEmbed *embed) update_navigation_properties(browser); } -static char * -get_image_name(const char *uri) -{ - nsresult rv; - - nsCString imgName; - - nsCOMPtr imgURI; - rv = NewURI(uri, getter_AddRefs(imgURI)); - NS_ENSURE_SUCCESS(rv, NULL); - - ImageNameFromCache(imgURI, imgName); - - if (!imgName.Length()) { - nsCOMPtr url(do_QueryInterface(imgURI)); - if (url) { - url->GetFileName(imgName); - } - } - - return imgName.Length() ? g_strdup(imgName.get()) : NULL; -} - static gboolean dom_mouse_click_cb(GtkMozEmbed *embed, nsIDOMMouseEvent *mouseEvent) { @@ -610,36 +577,10 @@ dom_mouse_click_cb(GtkMozEmbed *embed, nsIDOMMouseEvent *mouseEvent) event = sugar_browser_event_new(); - nsresult rv; - - PRUint16 type; - rv = targetNode->GetNodeType(&type); - if (NS_FAILED(rv)) return NS_ERROR_FAILURE; - - nsCOMPtr element = do_QueryInterface(targetNode); - if ((nsIDOMNode::ELEMENT_NODE == type) && element) { - nsString uTag; - rv = element->GetLocalName(uTag); - if (NS_FAILED(rv)) return NS_ERROR_FAILURE; - - nsCString tag; - NS_UTF16ToCString (uTag, NS_CSTRING_ENCODING_UTF8, tag); - - if (g_ascii_strcasecmp (tag.get(), "img") == 0) { - nsString img; - - nsCOMPtr image; - image = do_QueryInterface(targetNode, &rv); - if (NS_FAILED(rv) || !image) return NS_ERROR_FAILURE; - - rv = image->GetSrc(img); - if (NS_FAILED(rv)) return NS_ERROR_FAILURE; - - nsCString cImg; - NS_UTF16ToCString (img, NS_CSTRING_ENCODING_UTF8, cImg); - event->image_uri = g_strdup(cImg.get()); - event->image_name = get_image_name(event->image_uri); - } + GeckoDocumentObject documentObject(browser, targetNode); + if(documentObject.IsImage()) { + event->image_uri = documentObject.GetImageURI(); + event->image_name = documentObject.GetImageName(); } PRUint16 btn = 0; @@ -712,74 +653,13 @@ sugar_browser_grab_focus(SugarBrowser *browser) } } - -static nsresult -GetPostData(SugarBrowser *browser, nsIInputStream **postData) -{ -#ifdef HAVE_NS_WEB_BROWSER - nsCOMPtr webBrowser; - gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(browser), - getter_AddRefs(webBrowser)); - NS_ENSURE_TRUE(webBrowser, NS_ERROR_FAILURE); - - nsCOMPtr webNav(do_QueryInterface(webBrowser)); - NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE); - - PRInt32 sindex; - - nsCOMPtr sessionHistory; - webNav->GetSessionHistory(getter_AddRefs(sessionHistory)); - NS_ENSURE_TRUE(sessionHistory, NS_ERROR_FAILURE); - - nsCOMPtr entry; - sessionHistory->GetIndex(&sindex); - sessionHistory->GetEntryAtIndex(sindex, PR_FALSE, getter_AddRefs(entry)); - - nsCOMPtr shEntry(do_QueryInterface(entry)); - if (shEntry) { - shEntry->GetPostData(postData); - } - - return NS_OK; -#endif - return NS_ERROR_NOT_IMPLEMENTED; -} - gboolean sugar_browser_save_uri(SugarBrowser *browser, const char *uri, const char *filename) { -#ifdef HAVE_NS_WEB_BROWSER - nsresult rv; - - nsCOMPtr sourceURI; - rv = NewURI(uri, getter_AddRefs(sourceURI)); - NS_ENSURE_SUCCESS(rv, FALSE); - - nsCOMPtr destFile = do_CreateInstance("@mozilla.org/file/local;1"); - NS_ENSURE_TRUE(destFile, FALSE); - - destFile->InitWithNativePath(nsCString(filename)); - - nsCOMPtr webBrowser; - gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(browser), - getter_AddRefs(webBrowser)); - NS_ENSURE_TRUE(webBrowser, FALSE); - - nsCOMPtr webPersist = do_QueryInterface (webBrowser); - NS_ENSURE_TRUE(webPersist, FALSE); - - nsCOMPtr postData; - GetPostData(browser, getter_AddRefs(postData)); - - rv = webPersist->SaveURI(sourceURI, nsnull, nsnull, postData, nsnull, destFile); - NS_ENSURE_SUCCESS(rv, FALSE); - - return TRUE; -#else - return FALSE; -#endif + GeckoBrowserPersist browserPersist(browser); + return browserPersist.SaveURI(uri, filename); } gboolean diff --git a/services/clipboard/clipboardobject.py b/services/clipboard/clipboardobject.py index 919acd00..ab00b14d 100644 --- a/services/clipboard/clipboardobject.py +++ b/services/clipboard/clipboardobject.py @@ -1,3 +1,6 @@ +import os +import logging + import typeregistry class ClipboardObject: @@ -8,6 +11,10 @@ class ClipboardObject: self._percent = 0 self._formats = {} + def destroy(self): + for type, format in self._formats.iteritems(): + format.destroy() + def get_id(self): return self._id @@ -49,6 +56,10 @@ class Format: self._data = data self._on_disk = on_disk + def destroy(self): + if self._on_disk: + os.remove(self._data.replace('file://', '')) + def get_type(self): return self._type diff --git a/services/clipboard/clipboardservice.py b/services/clipboard/clipboardservice.py index 0ed423b5..16e37b19 100644 --- a/services/clipboard/clipboardservice.py +++ b/services/clipboard/clipboardservice.py @@ -109,7 +109,8 @@ class ClipboardDBusServiceHelper(dbus.service.Object): @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, in_signature="o", out_signature="") def delete_object(self, object_path): - del self._objects[str(object_path)] + cb_object = self._objects.pop(str(object_path)) + cb_object.destroy() self.object_deleted(object_path) logging.debug('Deleted object with object_id ' + object_path) diff --git a/services/clipboard/typeregistry.py b/services/clipboard/typeregistry.py index b794cee9..b6f4ae1f 100644 --- a/services/clipboard/typeregistry.py +++ b/services/clipboard/typeregistry.py @@ -197,6 +197,26 @@ class OOTextFileType(FileType): return mime_type in cls._types matches_mime_type = classmethod(matches_mime_type) +class UriListFileType(FileType): + + _types = set(['text/uri-list']) + + def get_name(self): + return _('text/uri-list') + + def get_icon(self): + return 'theme:stock-missing' + + def get_preview(self): + return 'preview' + + def get_activity(self): + return '' + + def matches_mime_type(cls, mime_type): + return mime_type in cls._types + matches_mime_type = classmethod(matches_mime_type) + class UnknownFileType(FileType): def get_name(self): return _('Object') @@ -221,6 +241,7 @@ class TypeRegistry: self._types.append(MsWordFileType) self._types.append(RtfFileType) self._types.append(OOTextFileType) + self._types.append(UriListFileType) self._types.append(UriFileType) self._types.append(ImageFileType) self._types.append(AbiwordFileType) diff --git a/shell/view/frame/clipboardbox.py b/shell/view/frame/clipboardbox.py index 2dcad10e..c057a42e 100644 --- a/shell/view/frame/clipboardbox.py +++ b/shell/view/frame/clipboardbox.py @@ -1,4 +1,7 @@ +import shutil +import os import logging + import hippo import gtk @@ -72,13 +75,25 @@ class ClipboardBox(hippo.CanvasBox): if not selection.data: return - logging.debug('ClipboardBox: adding type ' + selection.type + '.') - + logging.debug('ClipboardBox: adding type ' + selection.type + ' ' + selection.data) + cb_service = clipboardservice.get_instance() - cb_service.add_object_format(object_id, - selection.type, - selection.data, - on_disk = False) + if selection.type == 'text/uri-list': + # Copy the file, as it will be deleted when the dnd operation finishes. + file_path = selection.data.replace('file://', '') + new_file_path = os.path.join(os.path.split(file_path)[0], + "cb" + os.path.split(file_path)[1]) + shutil.copyfile(file_path, new_file_path) + + cb_service.add_object_format(object_id, + selection.type, + 'file://' + new_file_path, + on_disk=True) + else: + cb_service.add_object_format(object_id, + selection.type, + selection.data, + on_disk=False) def _object_added_cb(self, cb_service, object_id, name): icon = ClipboardIcon(self._popup_context, object_id, name) @@ -165,15 +180,16 @@ class ClipboardBox(hippo.CanvasBox): def drag_data_received_cb(self, widget, context, x, y, selection, targetType, time): logging.debug('ClipboardBox: got data for target ' + selection.target) - if selection: - object_id = self._context_map.get_object_id(context) - self._add_selection(object_id, selection) - else: - logging.warn('ClipboardBox: empty selection for target ' + selection.target) - - # If it's the last target to be processed, finish the dnd transaction - if not self._context_map.has_context(context): - context.finish(True, False, time) + try: + if selection: + object_id = self._context_map.get_object_id(context) + self._add_selection(object_id, selection) + else: + logging.warn('ClipboardBox: empty selection for target ' + selection.target) + finally: + # If it's the last target to be processed, finish the dnd transaction + if not self._context_map.has_context(context): + context.drop_finish(True, gtk.get_current_event_time()) def drag_data_get_cb(self, widget, context, selection, targetType, eventTime): logging.debug("drag_data_get_cb: requested target " + selection.target) From 734d16022e2e6f7107eb550956b48ba486f99dc4 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Tue, 17 Apr 2007 16:54:01 -0300 Subject: [PATCH 2/8] Don't try to show the popup of a detached canvas icon. --- sugar/graphics/canvasicon.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sugar/graphics/canvasicon.py b/sugar/graphics/canvasicon.py index d50e9f90..14f83519 100644 --- a/sugar/graphics/canvasicon.py +++ b/sugar/graphics/canvasicon.py @@ -369,6 +369,11 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem): if not self._popup: return + if not self.get_context(): + # If we have been detached from our parent, don't show up the popup + # in this case. + return + popup_context = self.get_popup_context() [x, y] = [None, None] From 093ed2f2f263822a7a6dd9e982ac3d4d611b184f Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Tue, 17 Apr 2007 22:46:33 +0200 Subject: [PATCH 3/8] Make it compile with firefox --- browser/GeckoBrowserPersist.cpp | 4 ++++ browser/GeckoDocumentObject.cpp | 4 ++++ browser/GeckoDragDropHooks.cpp | 4 ++++ browser/sugar-browser.cpp | 13 ++++++++++++- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/browser/GeckoBrowserPersist.cpp b/browser/GeckoBrowserPersist.cpp index 48de4d11..5e698d8d 100644 --- a/browser/GeckoBrowserPersist.cpp +++ b/browser/GeckoBrowserPersist.cpp @@ -1,3 +1,5 @@ +#ifdef HAVE_GECKO_1_9 + #include #include @@ -183,3 +185,5 @@ GeckoBrowserPersist::SaveURI(const char *uri, const char *filename) return TRUE; } + +#endif diff --git a/browser/GeckoDocumentObject.cpp b/browser/GeckoDocumentObject.cpp index 6f034e18..fcbbe694 100644 --- a/browser/GeckoDocumentObject.cpp +++ b/browser/GeckoDocumentObject.cpp @@ -1,3 +1,5 @@ +#ifdef HAVE_GECKO_1_9 + #include #include @@ -185,3 +187,5 @@ GeckoDocumentObject::SaveImage(const char *filename) GeckoBrowserPersist browserPersist(mBrowser); return browserPersist.SaveURI(mImageURI.get(), filename); } + +#endif diff --git a/browser/GeckoDragDropHooks.cpp b/browser/GeckoDragDropHooks.cpp index 425ee455..fdca9545 100644 --- a/browser/GeckoDragDropHooks.cpp +++ b/browser/GeckoDragDropHooks.cpp @@ -1,3 +1,5 @@ +#ifdef HAVE_GECKO_1_9 + #include #include @@ -183,3 +185,5 @@ GeckoDragDropHooks::OnPasteOrDrop(nsIDOMEvent *event, nsITransferable *trans, { return NS_ERROR_NOT_IMPLEMENTED; } + +#endif diff --git a/browser/sugar-browser.cpp b/browser/sugar-browser.cpp index 270631b1..273cea8f 100644 --- a/browser/sugar-browser.cpp +++ b/browser/sugar-browser.cpp @@ -23,9 +23,12 @@ #include "sugar-marshal.h" #include "GeckoContentHandler.h" #include "GeckoDownload.h" + +#ifdef HAVE_GECKO_1_9 #include "GeckoDragDropHooks.h" #include "GeckoDocumentObject.h" #include "GeckoBrowserPersist.h" +#endif #include #include @@ -563,7 +566,8 @@ location_cb(GtkMozEmbed *embed) static gboolean dom_mouse_click_cb(GtkMozEmbed *embed, nsIDOMMouseEvent *mouseEvent) { - SugarBrowser *browser = SUGAR_BROWSER(embed); +#ifdef HAVE_GECKO_1_9 + SugarBrowser *browser = SUGAR_BROWSER(embed); SugarBrowserEvent *event; gint return_value = FALSE; @@ -592,6 +596,9 @@ dom_mouse_click_cb(GtkMozEmbed *embed, nsIDOMMouseEvent *mouseEvent) sugar_browser_event_free(event); return return_value; +#else + return FALSE; +#endif } static void @@ -658,8 +665,12 @@ sugar_browser_save_uri(SugarBrowser *browser, const char *uri, const char *filename) { +#ifdef HAVE_GECKO_1_9 GeckoBrowserPersist browserPersist(browser); return browserPersist.SaveURI(uri, filename); +#else + return FALSE; +#endif } gboolean From e9905b5dfcbe3bd7ca00331652e30fe8ab299010 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Tue, 17 Apr 2007 19:31:06 -0300 Subject: [PATCH 4/8] Include config.h before testing for HAVE_GECKO_1_9. --- browser/GeckoBrowserPersist.cpp | 3 ++- browser/GeckoDocumentObject.cpp | 3 ++- browser/GeckoDragDropHooks.cpp | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/browser/GeckoBrowserPersist.cpp b/browser/GeckoBrowserPersist.cpp index 5e698d8d..2c019c53 100644 --- a/browser/GeckoBrowserPersist.cpp +++ b/browser/GeckoBrowserPersist.cpp @@ -1,3 +1,5 @@ +#include + #ifdef HAVE_GECKO_1_9 #include @@ -16,7 +18,6 @@ #include #include -#include #include "GeckoBrowserPersist.h" GeckoBrowserPersist::GeckoBrowserPersist(SugarBrowser *browser) diff --git a/browser/GeckoDocumentObject.cpp b/browser/GeckoDocumentObject.cpp index fcbbe694..fe4a824f 100644 --- a/browser/GeckoDocumentObject.cpp +++ b/browser/GeckoDocumentObject.cpp @@ -1,3 +1,5 @@ +#include + #ifdef HAVE_GECKO_1_9 #include @@ -18,7 +20,6 @@ #include #include -#include #include "GeckoDocumentObject.h" #include "GeckoBrowserPersist.h" diff --git a/browser/GeckoDragDropHooks.cpp b/browser/GeckoDragDropHooks.cpp index fdca9545..d8b0a84b 100644 --- a/browser/GeckoDragDropHooks.cpp +++ b/browser/GeckoDragDropHooks.cpp @@ -1,3 +1,5 @@ +#include + #ifdef HAVE_GECKO_1_9 #include @@ -14,7 +16,6 @@ #include #include -#include #include "GeckoDragDropHooks.h" #include "GeckoDocumentObject.h" From 0d4f555abb9dd2eee4db11f682c8f3021778998f Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Wed, 18 Apr 2007 14:03:33 +0200 Subject: [PATCH 5/8] Switch to the sugar theme --- data/gtkrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/gtkrc b/data/gtkrc index cc0d2caf..cb635362 100644 --- a/data/gtkrc +++ b/data/gtkrc @@ -1,4 +1,4 @@ -gtk-theme-name = "olpc" +gtk-theme-name = "sugar" gtk-icon-theme-name = "olpc" gtk-font-name = "Bitstream Vera Sans 7" gtk-icon-sizes = "gtk-menu=32,32:gtk-button=32,32" From 0bade58c23e53ec87385d88e5cb5b0b8add32d6d Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Wed, 18 Apr 2007 14:06:34 +0200 Subject: [PATCH 6/8] Remove obsolete tests --- tests/test-button.py | 66 ------------------- tests/test-entry.py | 71 -------------------- tests/test-frame.py | 36 ----------- tests/test-label.py | 51 --------------- tests/test-option-menu.py | 64 ------------------ tests/test-theme.py | 121 ----------------------------------- tests/test-window-manager.py | 45 ------------- 7 files changed, 454 deletions(-) delete mode 100755 tests/test-button.py delete mode 100755 tests/test-entry.py delete mode 100755 tests/test-frame.py delete mode 100755 tests/test-label.py delete mode 100755 tests/test-option-menu.py delete mode 100755 tests/test-theme.py delete mode 100644 tests/test-window-manager.py diff --git a/tests/test-button.py b/tests/test-button.py deleted file mode 100755 index 9cceb92d..00000000 --- a/tests/test-button.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python - -# Copyright (C) 2007, One Laptop Per Child -# -# 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 -sys.path.insert(0, '/home/tomeu/sugar-jhbuild/source/sugar') - -import gtk -import hippo - -from sugar.graphics.toolbar import Toolbar -from sugar.graphics.iconbutton import IconButton -from sugar.graphics.toggleiconbutton import ToggleIconButton -from sugar.graphics.button import Button -from sugar.graphics.entry import Entry - -def _button_activated_cb(button): - print "_button_activated_cb" - -def _toggled_changed_cb(button, pspec): - print "Toggle state: %d" % button.props.toggled - -window = gtk.Window() -window.connect("destroy", lambda w: gtk.main_quit()) -window.show() - -canvas = hippo.Canvas() -window.add(canvas) -canvas.show() - -vbox = hippo.CanvasBox() -canvas.set_root(vbox) - -for i in [1, 2]: - toolbar = Toolbar() - toolbar.props.box_width = 400 - vbox.append(toolbar) - - icon_button = IconButton(icon_name='theme:stock-close') - toolbar.append(icon_button) - - toggle = ToggleIconButton(icon_name='theme:stock-back') - toggle.connect('notify::toggled', _toggled_changed_cb) - toolbar.append(toggle) - - button = Button(text='Click me!', icon_name='theme:stock-close') - button.connect('activated', _button_activated_cb) - toolbar.append(button) - - entry = Entry(text='mec') - toolbar.append(entry) - -gtk.main() diff --git a/tests/test-entry.py b/tests/test-entry.py deleted file mode 100755 index 80f0e234..00000000 --- a/tests/test-entry.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python - -# Copyright (C) 2007, One Laptop Per Child -# -# 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 gtk -import hippo - -from sugar.graphics.toolbar import Toolbar -from sugar.graphics.frame import Frame -from sugar.graphics.iconbutton import IconButton -from sugar.graphics.entry import Entry - -def _entry_activated_cb(entry): - print "_entry_activated_cb" - -def _entry_button_activated_cb(entry, action_id): - print "_entry_button_activated_cb: " + str(action_id) - entry.props.text = '' - -window = gtk.Window() -window.connect("destroy", lambda w: gtk.main_quit()) -window.show() - -canvas = hippo.Canvas() -window.add(canvas) -canvas.show() - -vbox = hippo.CanvasBox() -canvas.set_root(vbox) - -for i in [1, 2]: - toolbar = Toolbar() - vbox.append(toolbar) - - button = IconButton('theme:stock-close') - toolbar.append(button) - - BUTTON_DELETE = 1 - entry = Entry() - entry.props.text = 'mec mac' - entry.add_button('theme:stock-close', BUTTON_DELETE) - entry.connect('activated', _entry_activated_cb) - entry.connect('button-activated', _entry_button_activated_cb) - toolbar.append(entry, hippo.PACK_EXPAND) - - entry = Entry() - entry.props.text = 'moc muc' - toolbar.append(entry, hippo.PACK_EXPAND) - - gtk_entry = gtk.Entry() - gtk_entry.props.has_frame = False - #gtk_entry.connect("activate", self._entry_activate_cb) - - gtk_entry_widget = hippo.CanvasWidget() - gtk_entry_widget.props.widget = gtk_entry - toolbar.append(gtk_entry_widget, hippo.PACK_EXPAND) - -gtk.main() diff --git a/tests/test-frame.py b/tests/test-frame.py deleted file mode 100755 index 4a22fd1f..00000000 --- a/tests/test-frame.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python - -# 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 gtk -import hippo - -from sugar.graphics.frame import Frame - -window = gtk.Window() -window.connect("destroy", lambda w: gtk.main_quit()) -window.show() - -canvas = hippo.Canvas() - -frame = Frame() -canvas.set_root(frame) - -window.add(canvas) -canvas.show() - -gtk.main() diff --git a/tests/test-label.py b/tests/test-label.py deleted file mode 100755 index 6e7b6b28..00000000 --- a/tests/test-label.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python - -# Copyright (C) 2007, One Laptop Per Child -# -# 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 gtk -import hippo - -from sugar.graphics.toolbar import Toolbar -from sugar.graphics.label import Label -from sugar.graphics.iconbutton import IconButton - -BUTTON_DELETE = 1 - -window = gtk.Window() -window.connect("destroy", lambda w: gtk.main_quit()) -window.show() - -canvas = hippo.Canvas() -window.add(canvas) -canvas.show() - -vbox = hippo.CanvasBox() -canvas.set_root(vbox) - -toolbar = Toolbar() -vbox.append(toolbar) - -button = IconButton('theme:stock-close') -toolbar.append(button) - -label = Label('mec moc') -toolbar.append(label) - -label = Label() -label.props.text = 'mac mic' -toolbar.append(label) - -gtk.main() diff --git a/tests/test-option-menu.py b/tests/test-option-menu.py deleted file mode 100755 index a9202da8..00000000 --- a/tests/test-option-menu.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python - -# Copyright (C) 2007, One Laptop Per Child -# -# 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 -sys.path.insert(0, '/home/tomeu/sugar-jhbuild/source/sugar') -from gettext import gettext as _ - -import gtk -import hippo - -from sugar.graphics.toolbar import Toolbar -from sugar.graphics.optionmenu import OptionMenu -from sugar.graphics.menu import MenuItem -from sugar.graphics.iconbutton import IconButton - -def _option_menu_changed_cb(option_menu): - print '_option_menu_activated_cb: %i' % option_menu.props.value - -window = gtk.Window() -window.connect("destroy", lambda w: gtk.main_quit()) -window.show() - -canvas = hippo.Canvas() -window.add(canvas) -canvas.show() - -vbox = hippo.CanvasBox() -canvas.set_root(vbox) - -toolbar = Toolbar() -vbox.append(toolbar) - -button = IconButton(icon_name='theme:stock-close') -toolbar.append(button) - -OPTION_ANYTHING = 1 -OPTION_DRAW = 2 -OPTION_WRITE = 3 -OPTION_CHAT = 4 - -option_menu = OptionMenu() -option_menu.add_item(MenuItem(OPTION_ANYTHING, 'Anything')) -option_menu.add_separator() -option_menu.add_item(MenuItem(OPTION_DRAW, 'Draw', 'theme:stock-close')) -option_menu.add_item(MenuItem(OPTION_WRITE, 'Write')) -option_menu.add_item(MenuItem(OPTION_CHAT, 'Chat')) -option_menu.connect('changed', _option_menu_changed_cb) -toolbar.append(option_menu) - -gtk.main() diff --git a/tests/test-theme.py b/tests/test-theme.py deleted file mode 100755 index eae835fc..00000000 --- a/tests/test-theme.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env python - -# 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 pygtk -pygtk.require('2.0') - -import gtk - -# Main window -window = gtk.Window() -window.connect("destroy", lambda w: gtk.main_quit()) -#window.set_border_width(10) - -# Main VBox - -main_vbox = gtk.VBox(homogeneous=False, spacing=0) -window.add(main_vbox) - -############################### ############################## -############################### Menus ############################## -############################### ############################## - -menu = gtk.Menu() -file_menu = gtk.Menu() # Don't need to show menus -edit_menu = gtk.Menu() - -# Create the menu items -dummy_item_1 = gtk.MenuItem("Dummy Item 1") -dummy_item_2 = gtk.MenuItem("Dummy Item 2") -quit_item = gtk.MenuItem("Quit") -dummy_item_3 = gtk.MenuItem("Dummy Item 3") -dummy_item_4 = gtk.MenuItem("Dummy Item 4") -dummy_item_5 = gtk.MenuItem("Dummy Item 5") - -# Add them to the menu -file_menu.append(dummy_item_1) -file_menu.append(dummy_item_2) -file_menu.append(quit_item) - -edit_menu.append(dummy_item_3) -edit_menu.append(dummy_item_4) -edit_menu.append(dummy_item_5) - -# We can attach the Quit menu item to our exit function -quit_item.connect_object ("activate", lambda w: gtk.main_quit (), "file.quit") - -# We do need to show menu items -dummy_item_1.show() -dummy_item_2.show() -quit_item.show() -dummy_item_3.show() -dummy_item_4.show() -dummy_item_5.show() - -# Pack the menu into the menubar -menu_bar = gtk.MenuBar() -main_vbox.pack_start(menu_bar, False, False, 0) -menu_bar.show() - -file_item = gtk.MenuItem("File") -file_item.show() -menu_bar.append(file_item) -file_item.set_submenu(file_menu) - -edit_item = gtk.MenuItem("Edit") -edit_item.show() -menu_bar.append(edit_item) -edit_item.set_submenu(edit_menu) - - -# Scrolled window -scrolled_window = gtk.ScrolledWindow(hadjustment=None, vadjustment=None) -#scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) -scrolled_window.set_border_width(10) -main_vbox.pack_start(scrolled_window, True, True, 0) - -# Vbox inside the scrolled window -vbox = gtk.VBox(homogeneous=False, spacing=10) -scrolled_window.add_with_viewport(vbox) -vbox.set_border_width (10) - -# Label -label = gtk.Label("This is a label") -vbox.pack_start(label, False, False, 0) - -# Entry -entry = gtk.Entry () -entry.set_text("Type some text here") -vbox.pack_start(entry, False, False, 0) - -# Buttons -buttons_hbox = gtk.HBox(homogeneous=False, spacing=5) -vbox.pack_start(buttons_hbox, False, False, 0) - -button_1 = gtk.Button ("Button 1") -buttons_hbox.pack_start(button_1, False, False, 0) - -button_2 = gtk.Button ("Button 2") -buttons_hbox.pack_start(button_2, False, False, 0) - -button_3 = gtk.Button ("Button 3") -buttons_hbox.pack_start(button_3, False, False, 0) - -window.show_all() - -gtk.main() diff --git a/tests/test-window-manager.py b/tests/test-window-manager.py deleted file mode 100644 index 539979de..00000000 --- a/tests/test-window-manager.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python - -# 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 pygtk -pygtk.require('2.0') - -from sugar.session.UITestSession import UITestSession - -session = UITestSession() -session.start() - -import gtk - -def _show_dialog(window): - dialog = gtk.Dialog(title='No Unviewed Media', - parent=window, flags=gtk.DIALOG_MODAL, - buttons=(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) - label = gtk.Label('There is no unviewed media to download.') - dialog.vbox.pack_start(label, True, True, 0) - label.show() - response = dialog.run() - dialog.hide() - del dialog - -window = gtk.Window() -window.show() - -_show_dialog(window) - -gtk.main() From f26ee4056b4d804a5a841d3d0f1fb959fdaa9bea Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Wed, 18 Apr 2007 09:21:49 -0300 Subject: [PATCH 7/8] Assure dragged images have the right file extension. --- browser/GeckoDocumentObject.cpp | 79 ++++++++++++++++++++++++++------- browser/GeckoDocumentObject.h | 2 + browser/GeckoDragDropHooks.cpp | 30 ++++++++++++- 3 files changed, 95 insertions(+), 16 deletions(-) diff --git a/browser/GeckoDocumentObject.cpp b/browser/GeckoDocumentObject.cpp index fe4a824f..26eb13dc 100644 --- a/browser/GeckoDocumentObject.cpp +++ b/browser/GeckoDocumentObject.cpp @@ -116,6 +116,30 @@ FilenameFromContentDisposition(nsCString contentDisposition, nsCString &fileName return NS_OK; } +static nsresult +GetImageProperties(char *imgURIStr, nsIProperties **properties) +{ + nsresult rv; + + nsCOMPtr imageURI; + rv = NewURI(imgURIStr, getter_AddRefs(imageURI)); + if(NS_FAILED(rv)) return rv; + + nsCOMPtr mgr; + NS_GetServiceManager(getter_AddRefs(mgr)); + NS_ENSURE_TRUE(mgr, NS_ERROR_FAILURE); + + nsCOMPtr imgCache; + rv = mgr->GetServiceByContractID("@mozilla.org/image/cache;1", + NS_GET_IID(imgICache), + getter_AddRefs(imgCache)); + if(NS_FAILED(rv)) return rv; + + imgCache->FindEntryProperties(imageURI, properties); + NS_ENSURE_TRUE(mgr, NS_ERROR_FAILURE); + return NS_OK; +} + char * GeckoDocumentObject::GetImageName() { @@ -123,25 +147,16 @@ GeckoDocumentObject::GetImageName() return NULL; } + if(mImageName.Length()) { + return g_strdup(mImageName.get()); + } + nsresult rv; char *imgURIStr = GetImageURI(); - nsCOMPtr imageURI; - rv = NewURI(imgURIStr, getter_AddRefs(imageURI)); - NS_ENSURE_SUCCESS(rv, NULL); - - nsCOMPtr mgr; - NS_GetServiceManager (getter_AddRefs (mgr)); - NS_ENSURE_TRUE(mgr, NULL); - - nsCOMPtr imgCache; - rv = mgr->GetServiceByContractID("@mozilla.org/image/cache;1", - NS_GET_IID (imgICache), - getter_AddRefs(imgCache)); - NS_ENSURE_SUCCESS(rv, NULL); - nsCOMPtr imgProperties; - imgCache->FindEntryProperties(imageURI, getter_AddRefs(imgProperties)); + rv = GetImageProperties(imgURIStr, getter_AddRefs(imgProperties)); + NS_ENSURE_SUCCESS(rv, NULL); if (imgProperties) { nsCOMPtr dispositionCString; imgProperties->Get("content-disposition", @@ -155,6 +170,10 @@ GeckoDocumentObject::GetImageName() } if (!mImageName.Length()) { + nsCOMPtr imageURI; + rv = NewURI(imgURIStr, getter_AddRefs(imageURI)); + NS_ENSURE_SUCCESS(rv, NULL); + nsCOMPtr url(do_QueryInterface(imageURI)); if (url) { url->GetFileName(mImageName); @@ -164,6 +183,36 @@ GeckoDocumentObject::GetImageName() return mImageName.Length() ? g_strdup(mImageName.get()) : NULL; } +char * +GeckoDocumentObject::GetImageMimeType() +{ + if(!IsImage()) { + return NULL; + } + + if(mImageMimeType.Length()) { + return g_strdup(mImageMimeType.get()); + } + + nsresult rv; + char *imgURIStr = GetImageURI(); + + nsCOMPtr imgProperties; + rv = GetImageProperties(imgURIStr, getter_AddRefs(imgProperties)); + NS_ENSURE_SUCCESS(rv, NULL); + if (imgProperties) { + nsCOMPtr typeCString; + imgProperties->Get("type", + NS_GET_IID(nsISupportsCString), + getter_AddRefs(typeCString)); + if (typeCString) { + typeCString->GetData(mImageMimeType); + } + } + + return mImageMimeType.Length() ? g_strdup(mImageMimeType.get()) : NULL; +} + char * GeckoDocumentObject::GetImageURI() { diff --git a/browser/GeckoDocumentObject.h b/browser/GeckoDocumentObject.h index 05328e55..5f4069fc 100644 --- a/browser/GeckoDocumentObject.h +++ b/browser/GeckoDocumentObject.h @@ -15,6 +15,7 @@ public: bool IsImage(); char *GetImageURI(); char *GetImageName(); + char *GetImageMimeType(); bool SaveImage(const char *filename); private: SugarBrowser *mBrowser; @@ -22,6 +23,7 @@ private: nsCOMPtr mImage; nsCString mImageURI; nsCString mImageName; + nsCString mImageMimeType; protected: /* additional members */ }; diff --git a/browser/GeckoDragDropHooks.cpp b/browser/GeckoDragDropHooks.cpp index d8b0a84b..6439f42c 100644 --- a/browser/GeckoDragDropHooks.cpp +++ b/browser/GeckoDragDropHooks.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include "GeckoDragDropHooks.h" #include "GeckoDocumentObject.h" @@ -66,6 +67,9 @@ UriListDataProvider::GetFlavorData(nsITransferable *aTransferable, nsresult rv = NS_ERROR_NOT_IMPLEMENTED; char *image_name; + char *mime_type; + char *file_ext; + nsCString mime_ext; timeval timestamp; *aData = nsnull; @@ -83,7 +87,31 @@ UriListDataProvider::GetFlavorData(nsITransferable *aTransferable, mFilePath.AppendInt(timestamp.tv_usec); image_name = mDocumentObject->GetImageName(); - mFilePath.Append(image_name); + file_ext = strrchr(image_name, '.'); + mime_type = mDocumentObject->GetImageMimeType(); + + nsCOMPtr mimeService(do_GetService("@mozilla.org/mime;1", + &rv)); + NS_ENSURE_SUCCESS(rv, rv); + rv = mimeService->GetPrimaryExtension(nsCString(mime_type), + EmptyCString(), + mime_ext); + NS_ENSURE_SUCCESS(rv, rv); + + if(!file_ext) { + mFilePath.Append(image_name); + mFilePath.Append("."); + mFilePath.Append(mime_ext); + } else if(strcmp(file_ext, mime_ext.get())) { + image_name[strlen(file_ext)] = 0; + mFilePath.Append(image_name); + mFilePath.Append("."); + mFilePath.Append(mime_ext); + } else { + mFilePath.Append(image_name); + } + + g_free(mime_type); g_free(image_name); if(!mDocumentObject->SaveImage(mFilePath.get())) { From 7ef61620f7f7d5e6edbd1da63e2e95c80e7217a3 Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Wed, 18 Apr 2007 16:04:27 +0200 Subject: [PATCH 8/8] Ui test --- tests/test-ui.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100755 tests/test-ui.py diff --git a/tests/test-ui.py b/tests/test-ui.py new file mode 100755 index 00000000..6c1f6676 --- /dev/null +++ b/tests/test-ui.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python + +# 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 gtk + +class Window(gtk.Window): + def __init__(self): + gtk.Window.__init__(self) + self.set_default_size(800, 600) + +window = Window() +window.connect("destroy", lambda w: gtk.main_quit()) +window.show() + +gtk.main()