[haiku-commits] haiku: hrev47067 - src/apps/haikudepot

  • From: superstippi@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 28 Mar 2014 23:49:07 +0100 (CET)

hrev47067 adds 3 changesets to branch 'master'
old head: a04a520b0d0c0d075c2a002bb42a1fe7be20ca69
new head: 5bd5f161e896a560c55776fbbada27b47e0794c8
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=5bd5f16+%5Ea04a520

----------------------------------------------------------------------------

22949ba: HaikuDepot: SharedBitmap: Added loading from buffers.
  
   Refactored loading from a buffer when loading from resources and
   re-used that for instantiating a SharedBitmap from a BMallocIO.

b34f1a8: HaikuDepot: Refactored setting title and icon in listview...
  
  ... so that it is also done when a package state change notification
  is received that has the icon bit set.

5bd5f16: HaikuDepot: Populate package icons from web app.
  
   * Transformed ConnectionTest into WebAppInterface
   * Added methods to Model to trigger the population of all packages
     with additional information that is needed in the list view.
   * This launches a thread which tries to retrieve icons for all known
     packages from depot.haiku-os.org. This is uncached and very slow. I
     guess it could even be fast enough with a change to the protocol where
     icons are not retrieved one at a time.

                                      [ Stephan Aßmus <superstippi@xxxxxx> ]

----------------------------------------------------------------------------

11 files changed, 464 insertions(+), 294 deletions(-)
src/apps/haikudepot/ConnectionTest.cpp  | 214 ----------------------------
src/apps/haikudepot/ConnectionTest.h    |  30 ----
src/apps/haikudepot/Jamfile             |   9 +-
src/apps/haikudepot/MainWindow.cpp      |   3 +
src/apps/haikudepot/Model.cpp           | 104 +++++++++++++-
src/apps/haikudepot/Model.h             |  15 +-
src/apps/haikudepot/PackageInfo.cpp     | 119 +++++++++++-----
src/apps/haikudepot/PackageInfo.h       |  10 ++
src/apps/haikudepot/PackageListView.cpp |  24 +++-
src/apps/haikudepot/WebAppInterface.cpp | 196 +++++++++++++++++++++++++
src/apps/haikudepot/WebAppInterface.h   |  34 +++++

############################################################################

Commit:      22949ba2effc01699eb47262e2061326547b1591
URL:         http://cgit.haiku-os.org/haiku/commit/?id=22949ba
Author:      Stephan Aßmus <superstippi@xxxxxx>
Date:        Fri Mar 28 22:43:04 2014 UTC

HaikuDepot: SharedBitmap: Added loading from buffers.

 Refactored loading from a buffer when loading from resources and
 re-used that for instantiating a SharedBitmap from a BMallocIO.

----------------------------------------------------------------------------

diff --git a/src/apps/haikudepot/PackageInfo.cpp 
b/src/apps/haikudepot/PackageInfo.cpp
index 4a7ae89..71457dc 100644
--- a/src/apps/haikudepot/PackageInfo.cpp
+++ b/src/apps/haikudepot/PackageInfo.cpp
@@ -26,6 +26,8 @@ SharedBitmap::SharedBitmap(BBitmap* bitmap)
        :
        BReferenceable(),
        fResourceID(-1),
+       fBuffer(NULL),
+       fSize(0),
        fMimeType()
 {
        fBitmap[0] = bitmap;
@@ -38,6 +40,8 @@ SharedBitmap::SharedBitmap(int32 resourceID)
        :
        BReferenceable(),
        fResourceID(resourceID),
+       fBuffer(NULL),
+       fSize(0),
        fMimeType()
 {
        fBitmap[0] = NULL;
@@ -50,6 +54,8 @@ SharedBitmap::SharedBitmap(const char* mimeType)
        :
        BReferenceable(),
        fResourceID(-1),
+       fBuffer(NULL),
+       fSize(0),
        fMimeType(mimeType)
 {
        fBitmap[0] = NULL;
@@ -58,18 +64,36 @@ SharedBitmap::SharedBitmap(const char* mimeType)
 }
 
 
+SharedBitmap::SharedBitmap(const BMallocIO& data)
+       :
+       BReferenceable(),
+       fResourceID(-1),
+       fBuffer(new(std::nothrow) uint8[data.BufferLength()]),
+       fSize(data.BufferLength()),
+       fMimeType()
+{
+       if (fBuffer != NULL)
+               memcpy(fBuffer, data.Buffer(), fSize);
+
+       fBitmap[0] = NULL;
+       fBitmap[1] = NULL;
+       fBitmap[2] = NULL;
+}
+
+
 SharedBitmap::~SharedBitmap()
 {
        delete fBitmap[0];
        delete fBitmap[1];
        delete fBitmap[2];
+       delete[] fBuffer;
 }
 
 
 const BBitmap*
 SharedBitmap::Bitmap(Size which)
 {
-       if (fResourceID == -1 && fMimeType.Length() == 0)
+       if (fResourceID == -1 && fMimeType.Length() == 0 && fBuffer == NULL)
                return fBitmap[0];
 
        int32 index = 0;
@@ -93,6 +117,8 @@ SharedBitmap::Bitmap(Size which)
        if (fBitmap[index] == NULL) {
                if (fResourceID >= 0)
                        fBitmap[index] = _CreateBitmapFromResource(size);
+               else if (fBuffer != NULL)
+                       fBitmap[index] = _CreateBitmapFromBuffer(size);
                else if (fMimeType.Length() > 0)
                        fBitmap[index] = _CreateBitmapFromMimeType(size);
        }
@@ -112,45 +138,26 @@ SharedBitmap::_CreateBitmapFromResource(int32 size) const
        size_t dataSize;
        const void* data = resources.LoadResource(B_VECTOR_ICON_TYPE, 
fResourceID,
                &dataSize);
-       if (data != NULL) {
-               BBitmap* bitmap = new BBitmap(BRect(0, 0, size - 1, size - 1), 
0,
-                       B_RGBA32);
-               status = bitmap->InitCheck();
-               if (status == B_OK) {
-                       status = BIconUtils::GetVectorIcon(
-                               reinterpret_cast<const uint8*>(data), dataSize, 
bitmap);
-               };
-
-               if (status != B_OK) {
-                       delete bitmap;
-                       bitmap = NULL;
-               }
-
-               return bitmap;
-       }
+       if (data != NULL)
+               return _LoadIconFromBuffer(data, dataSize, size);
 
        data = resources.LoadResource(B_MESSAGE_TYPE, fResourceID, &dataSize);
-       if (data != NULL) {
-               BMemoryIO stream(data, dataSize);
+       if (data != NULL)
+               return _LoadBitmapFromBuffer(data, dataSize);
 
-               // Try to read as an archived bitmap.
-               BMessage archive;
-               status = archive.Unflatten(&stream);
-               if (status != B_OK)
-                       return NULL;
-
-               BBitmap* bitmap = new BBitmap(&archive);
+       return NULL;
+}
 
-               status = bitmap->InitCheck();
-               if (status != B_OK) {
-                       delete bitmap;
-                       bitmap = NULL;
-               }
 
-               return bitmap;
-       }
+BBitmap*
+SharedBitmap::_CreateBitmapFromBuffer(int32 size) const
+{
+       BBitmap* bitmap = _LoadIconFromBuffer(fBuffer, fSize, size);
+       
+       if (bitmap == NULL)
+               bitmap = _LoadBitmapFromBuffer(fBuffer, fSize);
 
-       return NULL;
+       return bitmap;
 }
 
 
@@ -176,6 +183,50 @@ SharedBitmap::_CreateBitmapFromMimeType(int32 size) const
 }
 
 
+BBitmap*
+SharedBitmap::_LoadBitmapFromBuffer(const void* buffer, size_t size) const
+{
+       BMemoryIO stream(buffer, size);
+
+       // Try to read as an archived bitmap.
+       BMessage archive;
+       status_t status = archive.Unflatten(&stream);
+       if (status != B_OK)
+               return NULL;
+
+       BBitmap* bitmap = new BBitmap(&archive);
+
+       status = bitmap->InitCheck();
+       if (status != B_OK) {
+               delete bitmap;
+               bitmap = NULL;
+       }
+
+       return bitmap;
+}
+
+
+BBitmap*
+SharedBitmap::_LoadIconFromBuffer(const void* data, size_t dataSize,
+       int32 size) const
+{
+       BBitmap* bitmap = new BBitmap(BRect(0, 0, size - 1, size - 1), 0,
+               B_RGBA32);
+       status_t status = bitmap->InitCheck();
+       if (status == B_OK) {
+               status = BIconUtils::GetVectorIcon(
+                       reinterpret_cast<const uint8*>(data), dataSize, bitmap);
+       };
+
+       if (status != B_OK) {
+               delete bitmap;
+               bitmap = NULL;
+       }
+
+       return bitmap;
+}
+
+
 // #pragma mark - UserInfo
 
 
diff --git a/src/apps/haikudepot/PackageInfo.h 
b/src/apps/haikudepot/PackageInfo.h
index d57429f..23a61ec 100644
--- a/src/apps/haikudepot/PackageInfo.h
+++ b/src/apps/haikudepot/PackageInfo.h
@@ -16,6 +16,7 @@
 
 
 class BBitmap;
+class BMallocIO;
 
 
 class SharedBitmap : public BReferenceable {
@@ -30,16 +31,25 @@ public:
                                                                
SharedBitmap(BBitmap* bitmap);
                                                                
SharedBitmap(int32 resourceID);
                                                                
SharedBitmap(const char* mimeType);
+                                                               
SharedBitmap(const BMallocIO& data);
                                                                ~SharedBitmap();
 
                        const BBitmap*          Bitmap(Size which);
 
 private:
                        BBitmap*                        
_CreateBitmapFromResource(int32 size) const;
+                       BBitmap*                        
_CreateBitmapFromBuffer(int32 size) const;
                        BBitmap*                        
_CreateBitmapFromMimeType(int32 size) const;
 
+                       BBitmap*                        
_LoadBitmapFromBuffer(const void* buffer,
+                                                                       size_t 
dataSize) const;
+                       BBitmap*                        
_LoadIconFromBuffer(const void* buffer,
+                                                                       size_t 
dataSize, int32 size) const;
+
 private:
                        int32                           fResourceID;
+                       uint8*                          fBuffer;
+                       size_t                          fSize;
                        BString                         fMimeType;
                        BBitmap*                        fBitmap[3];
 };

############################################################################

Commit:      b34f1a8b118d0f595a1dadaec05431d8ba8bce96
URL:         http://cgit.haiku-os.org/haiku/commit/?id=b34f1a8
Author:      Stephan Aßmus <superstippi@xxxxxx>
Date:        Fri Mar 28 22:44:44 2014 UTC

HaikuDepot: Refactored setting title and icon in listview...

... so that it is also done when a package state change notification
is received that has the icon bit set.

----------------------------------------------------------------------------

diff --git a/src/apps/haikudepot/PackageListView.cpp 
b/src/apps/haikudepot/PackageListView.cpp
index 9be0d83..725bac2 100644
--- a/src/apps/haikudepot/PackageListView.cpp
+++ b/src/apps/haikudepot/PackageListView.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013, Stephan Aßmus <superstippi@xxxxxx>.
+ * Copyright 2013-2014, Stephan Aßmus <superstippi@xxxxxx>.
  * Copyright 2013, Rene Gollent, <rene@xxxxxxxxxxx>.
  * All rights reserved. Distributed under the terms of the MIT License.
  */
@@ -123,6 +123,7 @@ public:
                        const PackageInfoRef& Package() const
                                                                        { 
return fPackage; }
 
+                       void                            UpdateTitle();
                        void                            UpdateState();
                        void                            UpdateRating();
 
@@ -466,10 +467,7 @@ PackageRow::PackageRow(const PackageInfoRef& packageRef,
 
        // Package icon and title
        // NOTE: The icon BBitmap is referenced by the fPackage member.
-       const BBitmap* icon = NULL;
-       if (package.Icon().Get() != NULL)
-               icon = package.Icon()->Bitmap(SharedBitmap::SIZE_16);
-       SetField(new BBitmapStringField(icon, package.Title()), kTitleColumn);
+       UpdateTitle();
 
        // Rating
        UpdateRating();
@@ -482,7 +480,6 @@ PackageRow::PackageRow(const PackageInfoRef& packageRef,
        SetField(new BStringField("0 KiB"), kSizeColumn);
 
        // Status
-       // TODO: Fetch info about installed/deactivated/uninstalled/...
        SetField(new BStringField(package_state_to_string(fPackage)),
                kStatusColumn);
 
@@ -498,6 +495,19 @@ PackageRow::~PackageRow()
 
 
 void
+PackageRow::UpdateTitle()
+{
+       if (fPackage.Get() == NULL)
+               return;
+
+       const BBitmap* icon = NULL;
+       if (fPackage->Icon().Get() != NULL)
+               icon = fPackage->Icon()->Bitmap(SharedBitmap::SIZE_16);
+       SetField(new BBitmapStringField(icon, fPackage->Title()), kTitleColumn);
+}
+
+
+void
 PackageRow::UpdateState()
 {
        if (fPackage.Get() == NULL)
@@ -670,6 +680,8 @@ PackageListView::MessageReceived(BMessage* message)
                                        row->UpdateRating();
                                if ((changes & PKG_CHANGED_STATE) != 0)
                                        row->UpdateState();
+                               if ((changes & PKG_CHANGED_ICON) != 0)
+                                       row->UpdateTitle();
                        }
                        break;
                }

############################################################################

Revision:    hrev47067
Commit:      5bd5f161e896a560c55776fbbada27b47e0794c8
URL:         http://cgit.haiku-os.org/haiku/commit/?id=5bd5f16
Author:      Stephan Aßmus <superstippi@xxxxxx>
Date:        Fri Mar 28 22:46:01 2014 UTC

HaikuDepot: Populate package icons from web app.

 * Transformed ConnectionTest into WebAppInterface
 * Added methods to Model to trigger the population of all packages
   with additional information that is needed in the list view.
 * This launches a thread which tries to retrieve icons for all known
   packages from depot.haiku-os.org. This is uncached and very slow. I
   guess it could even be fast enough with a change to the protocol where
   icons are not retrieved one at a time.

----------------------------------------------------------------------------

diff --git a/src/apps/haikudepot/ConnectionTest.cpp 
b/src/apps/haikudepot/ConnectionTest.cpp
deleted file mode 100644
index 717d326..0000000
--- a/src/apps/haikudepot/ConnectionTest.cpp
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright 2014, Stephan Aßmus <superstippi@xxxxxx>.
- * All rights reserved. Distributed under the terms of the MIT License.
- */
-
-#include "ConnectionTest.h"
-
-#include <stdio.h>
-
-#include <mail_encoding.h>
-
-#include <File.h>
-#include <HttpHeaders.h>
-#include <HttpRequest.h>
-#include <Url.h>
-#include <UrlContext.h>
-#include <UrlProtocolListener.h>
-#include <UrlProtocolRoster.h>
-
-
-class ProtocolListener : public BUrlProtocolListener {
-public:
-       ProtocolListener::ProtocolListener()
-               :
-               fDownloadIO(NULL)
-       {
-       }
-
-       virtual void ConnectionOpened(BUrlRequest* caller)
-       {
-               printf("ConnectionOpened(%p)\n", caller);
-       }
-       
-       virtual void HostnameResolved(BUrlRequest* caller, const char* ip)
-       {
-               printf("HostnameResolved(%p): %s\n", caller, ip);
-       }
-                                                                       
-       virtual void ResponseStarted(BUrlRequest* caller)
-       {
-               printf("ResponseStarted(%p)\n", caller);
-       }
-       
-       virtual void HeadersReceived(BUrlRequest* caller)
-       {
-               printf("HeadersReceived(%p)\n", caller);
-       }
-       
-       virtual void DataReceived(BUrlRequest* caller, const char* data,
-               ssize_t size)
-       {
-               printf("DataReceived(%p): %ld bytes\n", caller, size);
-
-               if (fDownloadIO != NULL)
-                       fDownloadIO->Write(data, size);
-       }
-                                                                       
-       virtual void DownloadProgress(BUrlRequest* caller, ssize_t 
bytesReceived,
-               ssize_t bytesTotal)
-       {
-               printf("DownloadProgress(%p): %ld/%ld\n", caller, bytesReceived,
-                       bytesTotal);
-       }
-                                                                       
-       virtual void UploadProgress(BUrlRequest* caller, ssize_t bytesSent,
-               ssize_t bytesTotal)
-       {
-               printf("UploadProgress(%p): %ld/%ld\n", caller, bytesSent, 
bytesTotal);
-       }
-                                                                               
                                                        
-       virtual void RequestCompleted(BUrlRequest* caller, bool success)
-       {
-               printf("RequestCompleted(%p): %d\n", caller, success);
-       }
-                                                                       
-       virtual void DebugMessage(BUrlRequest* caller,
-               BUrlProtocolDebugMessage type, const char* text)
-       {
-               printf("DebugMessage(%p): %s\n", caller, text);
-       }
-
-       void SetDownloadIO(BDataIO* downloadIO)
-       {
-               fDownloadIO = downloadIO;
-       }
-
-private:
-       BDataIO*                fDownloadIO;
-};
-
-
-ConnectionTest::ConnectionTest(const char* username, const char* password)
-       :
-       BApplication("application/x-vnd.Haiku-HaikuDepot-ConnectionTest"),
-       fUsername(username),
-       fPassword(password)
-{
-}
-
-
-ConnectionTest::~ConnectionTest()
-{
-}
-
-
-void
-ConnectionTest::ReadyToRun()
-{
-       printf("Connecting...\n");
-       
-       _TestDownloadIcon();
-
-       PostMessage(B_QUIT_REQUESTED, this);
-}
-
-
-void
-ConnectionTest::_TestGetPackage()
-{
-       BUrl url("https://depot.haiku-os.org/api/v1/pkg";);
-       
-       ProtocolListener listener;
-       BUrlContext context;
-       BHttpHeaders headers;   
-
-       // Authentication
-       if (!fUsername.IsEmpty() && !fPassword.IsEmpty()) {
-               BString plain;
-               plain << fUsername << ':' << fPassword;
-
-               char base64[1024];
-               ssize_t base64Size = encode_base64(base64, plain, 
plain.Length(),
-                       false);
-
-               if (base64Size > 0 && base64Size <= (ssize_t)sizeof(base64)) {
-                       base64[base64Size] = '\0';
-
-                       BString authorization("Basic ");
-                       authorization << base64;
-                       
-                       headers.AddHeader("Authorization", authorization);
-               }
-       }
-       // Content-Type
-       headers.AddHeader("Content-Type", "application/json");
-
-       BHttpRequest request(url, true, "HTTP", &listener, &context);
-       request.SetMethod(B_HTTP_POST);
-       request.SetHeaders(headers);
-
-       BMallocIO* data = new BMallocIO();
-       
-       BString jsonString
-               =       "{"
-                               "\"jsonrpc\":\"2.0\","
-                               "\"id\":4143431,"
-                               "\"method\":\"getPkg\","
-                               "\"params\":[{"
-                                       "\"name\":\"apr\","
-                                       "\"architectureCode\":\"x86\","
-                                       "\"versionType\":\"NONE\""
-                               "}]"
-                       "}"
-               ;
-       
-       data->WriteAt(0, jsonString.String(), jsonString.Length());
-       data->Seek(0, SEEK_SET);
-       request.AdoptInputData(data);
-
-       thread_id thread = request.Run();
-       wait_for_thread(thread, NULL);
-}
-
-
-void
-ConnectionTest::_TestDownloadIcon()
-{
-       BUrl 
url("https://depot.haiku-os.org/pkgicon/wonderbrush_x86_gcc2.hvif";);
-       
-       BFile file("/boot/home/Desktop/wonderbrush.hvif",
-               B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
-       
-       ProtocolListener listener;
-       listener.SetDownloadIO(&file);
-       
-       // Content-Type
-       BHttpRequest request(url, true, "HTTP", &listener);
-       request.SetMethod(B_HTTP_GET);
-
-       thread_id thread = request.Run();
-       wait_for_thread(thread, NULL);
-}
-
-
-int
-main(int argc, char* argv[])
-{
-       const char* username = "";
-       const char* password = "";
-       
-       for (int i = 1; i < argc; i++) {
-               if (strcmp("-u", argv[i]) == 0 && i < argc - 1)
-                       username = argv[++i];
-               else if (strcmp("-p", argv[i]) == 0 && i < argc - 1)
-                       password = argv[++i];
-       }
-       
-       printf("Using username: %s, password: %s\n", username, password);
-       
-       ConnectionTest(username, password).Run();
-       return 0;
-}
-
-
diff --git a/src/apps/haikudepot/ConnectionTest.h 
b/src/apps/haikudepot/ConnectionTest.h
deleted file mode 100644
index 24c7454..0000000
--- a/src/apps/haikudepot/ConnectionTest.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2014, Stephan Aßmus <superstippi@xxxxxx>.
- * All rights reserved. Distributed under the terms of the MIT License.
- */
-#ifndef CONNECTION_TEST_H
-#define CONNECTION_TEST_H
-
-
-#include <Application.h>
-#include <String.h>
-
-
-class ConnectionTest : public BApplication {
-public:
-                                                               
ConnectionTest(const char* username,
-                                                                       const 
char* password);
-       virtual                                         ~ConnectionTest();
-
-       virtual void                            ReadyToRun();
-
-private:
-                       void                            _TestGetPackage();
-                       void                            _TestDownloadIcon();
-private:
-                       BString                         fUsername;
-                       BString                         fPassword;
-};
-
-
-#endif // CONNECTION_TEST_H
diff --git a/src/apps/haikudepot/Jamfile b/src/apps/haikudepot/Jamfile
index 9ac8a9d..0c9bbe1 100644
--- a/src/apps/haikudepot/Jamfile
+++ b/src/apps/haikudepot/Jamfile
@@ -53,6 +53,7 @@ Application HaikuDepot :
        PackageManager.cpp
        RatePackageWindow.cpp
        support.cpp
+       WebAppInterface.cpp
 
        # package_daemon
        ProblemWindow.cpp
@@ -61,7 +62,7 @@ Application HaikuDepot :
        # text view stuff
        $(textDocumentSources)
 
-       : be package translation libcolumnlistview.a libshared.a
+       : be package netapi translation libcolumnlistview.a libshared.a
                $(TARGET_LIBSTDC++) $(TARGET_LIBSUPC++) localestub
        : HaikuDepot.rdef
 ;
@@ -85,9 +86,3 @@ Application TextDocumentTest :
 
        : be translation libshared.a $(TARGET_LIBSUPC++)
 ;
-
-Application ConnectionTest :
-       ConnectionTest.cpp
-
-       : be netapi translation libshared.a $(TARGET_LIBSUPC++)
-;
diff --git a/src/apps/haikudepot/MainWindow.cpp 
b/src/apps/haikudepot/MainWindow.cpp
index e81df5b..6bc18df 100644
--- a/src/apps/haikudepot/MainWindow.cpp
+++ b/src/apps/haikudepot/MainWindow.cpp
@@ -580,6 +580,9 @@ MainWindow::_RefreshPackageList()
                fModel.AddDepot(it->second);
        }
 
+       // start retrieving package icons and average ratings
+       fModel.PopulateAllPackages();
+
        // compute the OS package dependencies
        try {
                // create the solver
diff --git a/src/apps/haikudepot/Model.cpp b/src/apps/haikudepot/Model.cpp
index 7360124..1cee127 100644
--- a/src/apps/haikudepot/Model.cpp
+++ b/src/apps/haikudepot/Model.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013, Stephan Aßmus <superstippi@xxxxxx>.
+ * Copyright 2013-2014, Stephan Aßmus <superstippi@xxxxxx>.
  * Copyright 2014, Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>.
  * All rights reserved. Distributed under the terms of the MIT License.
  */
@@ -12,6 +12,8 @@
 #include <Autolock.h>
 #include <Catalog.h>
 
+#include "WebAppInterface.h"
+
 
 #undef B_TRANSLATION_CONTEXT
 #define B_TRANSLATION_CONTEXT "Model"
@@ -281,7 +283,10 @@ Model::Model()
        fSearchTermsFilter(PackageFilterRef(new AnyFilter(), true)),
 
        fShowSourcePackages(false),
-       fShowDevelopPackages(false)
+       fShowDevelopPackages(false),
+
+       fPopulateAllPackagesThread(-1),
+       fStopPopulatingAllPackages(false)
 {
        // Don't forget to add new categories to this list:
        fCategories.Add(fCategoryAudio);
@@ -327,6 +332,12 @@ Model::Model()
 }
 
 
+Model::~Model()
+{
+       StopPopulatingAllPackages();
+}
+
+
 PackageList
 Model::CreatePackageList() const
 {
@@ -368,6 +379,7 @@ Model::AddDepot(const DepotInfo& depot)
 void
 Model::Clear()
 {
+       StopPopulatingAllPackages();
        fDepots.Clear();
 }
 
@@ -520,3 +532,91 @@ Model::PopulatePackage(const PackageInfoRef& package, 
uint32 flags)
 
        }
 }
+
+
+void
+Model::PopulateAllPackages()
+{
+       StopPopulatingAllPackages();
+
+       fStopPopulatingAllPackages = false;
+
+       fPopulateAllPackagesThread = spawn_thread(&_PopulateAllPackagesEntry,
+               "Package populator", B_NORMAL_PRIORITY, this);
+       if (fPopulateAllPackagesThread >= 0)
+               resume_thread(fPopulateAllPackagesThread);
+}
+
+
+void
+Model::StopPopulatingAllPackages()
+{
+       if (fPopulateAllPackagesThread < 0)
+               return;
+
+       fStopPopulatingAllPackages = true;
+       wait_for_thread(fPopulateAllPackagesThread, NULL);
+       fPopulateAllPackagesThread = -1;
+}
+
+
+int32
+Model::_PopulateAllPackagesEntry(void* cookie)
+{
+       Model* model = static_cast<Model*>(cookie);
+       model->_PopulateAllPackagesThread();
+       return 0;
+}
+
+
+void
+Model::_PopulateAllPackagesThread()
+{
+       int32 depotIndex = 0;
+       int32 packageIndex = 0;
+
+       while (!fStopPopulatingAllPackages) {
+               // Obtain PackageInfoRef while keeping the depot and package 
lists
+               // locked.
+               PackageInfoRef package;
+               {
+                       BAutolock locker(&fLock);
+                       
+                       if (depotIndex >= fDepots.CountItems())
+                               break;
+                       const DepotInfo& depot = fDepots.ItemAt(depotIndex);
+
+                       const PackageList& packages = depot.Packages();
+                       if (packageIndex >= packages.CountItems()) {
+                               // Need the next depot
+                               packageIndex = 0;
+                               depotIndex++;
+                               continue;
+                       }
+                       
+                       package = packages.ItemAt(packageIndex);
+                       packageIndex++;
+               }
+               
+               if (package.Get() == NULL)
+                       continue;
+       
+               _PopulatePackageIcon(package);
+               // TODO: Average user rating. It needs to be shown in the
+               // list view, so without the user clicking the package.
+       }
+}
+
+
+void
+Model::_PopulatePackageIcon(const PackageInfoRef& package)
+{
+       WebAppInterface interface;
+       BMallocIO buffer;
+
+       status_t status = interface.RetrievePackageIcon(package->Title(), 
&buffer);
+       if (status == B_OK) {
+               BitmapRef bitmapRef(new(std::nothrow)SharedBitmap(buffer), 
true);
+               package->SetIcon(bitmapRef);
+       }
+}
diff --git a/src/apps/haikudepot/Model.h b/src/apps/haikudepot/Model.h
index 950a444..a03b667 100644
--- a/src/apps/haikudepot/Model.h
+++ b/src/apps/haikudepot/Model.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013, Stephan Aßmus <superstippi@xxxxxx>.
+ * Copyright 2013-2014, Stephan Aßmus <superstippi@xxxxxx>.
  * All rights reserved. Distributed under the terms of the MIT License.
  */
 #ifndef MODEL_H
@@ -24,6 +24,7 @@ typedef BReference<PackageFilter> PackageFilterRef;
 class Model {
 public:
                                                                Model();
+       virtual                                         ~Model();
 
                        BLocker*                        Lock()
                                                                        { 
return &fLock; }
@@ -85,6 +86,15 @@ public:
 
                        void                            PopulatePackage(const 
PackageInfoRef& package,
                                                                        uint32 
flags);
+                       void                            PopulateAllPackages();
+                       void                            
StopPopulatingAllPackages();
+
+private:
+       static  int32                           _PopulateAllPackagesEntry(void* 
cookie);
+                       void                            
_PopulateAllPackagesThread();
+
+                       void                            _PopulatePackageIcon(
+                                                                       const 
PackageInfoRef& package);
 
 private:
                        BLocker                         fLock;
@@ -117,6 +127,9 @@ private:
 
                        bool                            fShowSourcePackages;
                        bool                            fShowDevelopPackages;
+
+                       thread_id                       
fPopulateAllPackagesThread;
+       volatile bool                           fStopPopulatingAllPackages;
 };
 
 
diff --git a/src/apps/haikudepot/WebAppInterface.cpp 
b/src/apps/haikudepot/WebAppInterface.cpp
new file mode 100644
index 0000000..bf05e11
--- /dev/null
+++ b/src/apps/haikudepot/WebAppInterface.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2014, Stephan Aßmus <superstippi@xxxxxx>.
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+#include "WebAppInterface.h"
+
+#include <stdio.h>
+
+#include <File.h>
+#include <HttpHeaders.h>
+#include <HttpRequest.h>
+#include <Url.h>
+#include <UrlContext.h>
+#include <UrlProtocolListener.h>
+#include <UrlProtocolRoster.h>
+
+#include "PackageInfo.h"
+
+
+class ProtocolListener : public BUrlProtocolListener {
+public:
+       ProtocolListener::ProtocolListener()
+               :
+               fDownloadIO(NULL)
+       {
+       }
+
+       virtual void ConnectionOpened(BUrlRequest* caller)
+       {
+//             printf("ConnectionOpened(%p)\n", caller);
+       }
+       
+       virtual void HostnameResolved(BUrlRequest* caller, const char* ip)
+       {
+//             printf("HostnameResolved(%p): %s\n", caller, ip);
+       }
+                                                                       
+       virtual void ResponseStarted(BUrlRequest* caller)
+       {
+//             printf("ResponseStarted(%p)\n", caller);
+       }
+       
+       virtual void HeadersReceived(BUrlRequest* caller)
+       {
+//             printf("HeadersReceived(%p)\n", caller);
+       }
+       
+       virtual void DataReceived(BUrlRequest* caller, const char* data,
+               ssize_t size)
+       {
+//             printf("DataReceived(%p): %ld bytes\n", caller, size);
+
+               if (fDownloadIO != NULL)
+                       fDownloadIO->Write(data, size);
+       }
+                                                                       
+       virtual void DownloadProgress(BUrlRequest* caller, ssize_t 
bytesReceived,
+               ssize_t bytesTotal)
+       {
+//             printf("DownloadProgress(%p): %ld/%ld\n", caller, bytesReceived,
+//                     bytesTotal);
+       }
+                                                                       
+       virtual void UploadProgress(BUrlRequest* caller, ssize_t bytesSent,
+               ssize_t bytesTotal)
+       {
+//             printf("UploadProgress(%p): %ld/%ld\n", caller, bytesSent, 
bytesTotal);
+       }
+                                                                               
                                                        
+       virtual void RequestCompleted(BUrlRequest* caller, bool success)
+       {
+//             printf("RequestCompleted(%p): %d\n", caller, success);
+       }
+                                                                       
+       virtual void DebugMessage(BUrlRequest* caller,
+               BUrlProtocolDebugMessage type, const char* text)
+       {
+//             printf("DebugMessage(%p): %s\n", caller, text);
+       }
+
+       void SetDownloadIO(BDataIO* downloadIO)
+       {
+               fDownloadIO = downloadIO;
+       }
+
+private:
+       BDataIO*                fDownloadIO;
+};
+
+
+WebAppInterface::WebAppInterface()
+{
+}
+
+
+WebAppInterface::~WebAppInterface()
+{
+}
+
+
+void
+WebAppInterface::SetAuthorization(const BString& username,
+       const BString& password)
+{
+       fUsername = username;
+       fPassword = password;
+}
+
+
+//void
+//WebAppInterface::_TestGetPackage()
+//{
+//     BUrl url("https://depot.haiku-os.org/api/v1/pkg";);
+//     
+//     ProtocolListener listener;
+//     BUrlContext context;
+//     BHttpHeaders headers;   
+//
+//     // Authentication
+//     if (!fUsername.IsEmpty() && !fPassword.IsEmpty()) {
+//             BString plain;
+//             plain << fUsername << ':' << fPassword;
+//
+//             char base64[1024];
+//             ssize_t base64Size = encode_base64(base64, plain, 
plain.Length(),
+//                     false);
+//
+//             if (base64Size > 0 && base64Size <= (ssize_t)sizeof(base64)) {
+//                     base64[base64Size] = '\0';
+//
+//                     BString authorization("Basic ");
+//                     authorization << base64;
+//                     
+//                     headers.AddHeader("Authorization", authorization);
+//             }
+//     }
+//     // Content-Type
+//     headers.AddHeader("Content-Type", "application/json");
+//
+//     BHttpRequest request(url, true, "HTTP", &listener, &context);
+//     request.SetMethod(B_HTTP_POST);
+//     request.SetHeaders(headers);
+//
+//     BMallocIO* data = new BMallocIO();
+//     
+//     BString jsonString
+//             =       "{"
+//                             "\"jsonrpc\":\"2.0\","
+//                             "\"id\":4143431,"
+//                             "\"method\":\"getPkg\","
+//                             "\"params\":[{"
+//                                     "\"name\":\"apr\","
+//                                     "\"architectureCode\":\"x86\","
+//                                     "\"versionType\":\"NONE\""
+//                             "}]"
+//                     "}"
+//             ;
+//     
+//     data->WriteAt(0, jsonString.String(), jsonString.Length());
+//     data->Seek(0, SEEK_SET);
+//     request.AdoptInputData(data);
+//
+//     thread_id thread = request.Run();
+//     wait_for_thread(thread, NULL);
+//}
+
+
+status_t
+WebAppInterface::RetrievePackageIcon(const BString& packageName,
+       BDataIO* stream)
+{
+       BString urlString = "https://depot.haiku-os.org/pkgicon/";;
+       urlString << packageName << ".hvif";
+       
+       BUrl url(urlString);
+       
+       ProtocolListener listener;
+       listener.SetDownloadIO(stream);
+       
+       BHttpRequest request(url, true, "HTTP", &listener);
+       request.SetMethod(B_HTTP_GET);
+
+       thread_id thread = request.Run();
+       wait_for_thread(thread, NULL);
+
+       const BHttpResult& result = dynamic_cast<const BHttpResult&>(
+               request.Result());
+
+       int32 statusCode = result.StatusCode();
+       
+       if (statusCode == 200)
+               return B_OK;
+
+       return B_ERROR;
+}
diff --git a/src/apps/haikudepot/WebAppInterface.h 
b/src/apps/haikudepot/WebAppInterface.h
new file mode 100644
index 0000000..5635f47
--- /dev/null
+++ b/src/apps/haikudepot/WebAppInterface.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2014, Stephan Aßmus <superstippi@xxxxxx>.
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+#ifndef WEB_APP_INTERFACE_H
+#define WEB_APP_INTERFACE_H
+
+
+#include <Application.h>
+#include <String.h>
+
+
+class BDataIO;
+
+
+class WebAppInterface {
+public:
+                                                               
WebAppInterface();
+       virtual                                         ~WebAppInterface();
+
+                       void                            SetAuthorization(const 
BString& username,
+                                                                       const 
BString& password);
+
+                       status_t                        RetrievePackageIcon(
+                                                                       const 
BString& packageName,
+                                                                       
BDataIO* stream);
+
+private:
+                       BString                         fUsername;
+                       BString                         fPassword;
+};
+
+
+#endif // WEB_APP_INTERFACE_H


Other related posts:

  • » [haiku-commits] haiku: hrev47067 - src/apps/haikudepot - superstippi