Added libdownload from xeD.

This commit is contained in:
plfiorini 2010-07-10 13:37:58 +00:00
parent 30470d4816
commit 082f2ad34e
26 changed files with 3739 additions and 1 deletions

View File

@ -5,6 +5,7 @@ SubInclude TOP libs ;
SubInclude TOP application ; SubInclude TOP application ;
SubInclude TOP protocols ; SubInclude TOP protocols ;
SubInclude TOP smileys ; SubInclude TOP smileys ;
SubInclude TOP tests ;
UninstallTarget $(CAYA_DIRECTORY) ; UninstallTarget $(CAYA_DIRECTORY) ;
UninstallTarget $(COMMON_INCLUDE_DIRECTORY)/caya ; UninstallTarget $(COMMON_INCLUDE_DIRECTORY)/caya ;

View File

@ -45,7 +45,10 @@ LOCATE on $(HCACHEFILE) $(JCACHEFILE) = $(GENERATED_DIR) ;
# Perform configuration checks # Perform configuration checks
include [ FDirName $(JAM_DIR) CheckRules ] ; include [ FDirName $(JAM_DIR) CheckRules ] ;
CheckGccPlatform ; CheckGccPlatform ;
CheckOpenSSL ; CheckCurl ;
if ! $(HAVE_CURL) {
Echo "** Caya needs Curl" ;
}
# Include jam scripts # Include jam scripts
include [ FDirName $(JAM_DIR) HelperRules ] ; include [ FDirName $(JAM_DIR) HelperRules ] ;

View File

@ -83,6 +83,7 @@ StatusView::StatusView(const char* name)
void void
StatusView::AttachedToWindow() StatusView::AttachedToWindow()
{ {
fNickname->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
fNickname->SetTarget(this); fNickname->SetTarget(this);
fStatusMenu->SetTargetForItems(this); fStatusMenu->SetTargetForItems(this);
} }

View File

@ -48,3 +48,30 @@ rule CheckOpenSSL
HAVE_OPENSSL = $(haveLibs) ; HAVE_OPENSSL = $(haveLibs) ;
} }
} }
rule CheckCurl
{
# CheckCurl ;
# Check for Curl and defined HAVE_CURL according, it also defines
# CURL_INCLUDE_DIR and CURL_LIBRARY_DIR with location of respectively
# include and library files.
HAVE_CURL = ;
CURL_INCLUDE_DIR = ;
CURL_LIBRARY_DIR = ;
local haveHeaders = [ Glob $(COMMON_INCLUDE_DIRECTORY)/curl : curl.h ] ;
if $(haveHeaders) {
CURL_INCLUDE_DIR = $(COMMON_INCLUDE_DIRECTORY)/curl ;
local haveLibs = [ Glob $(COMMON_LIB_DIRECTORY) : libcurl.so ] ;
if $(haveLibs) {
CURL_LIBRARY_DIR = $(COMMON_LIB_DIRECTORY) ;
Echo Curl Headers: $(CURL_INCLUDE_DIR) ;
Echo Curl Libs: $(CURL_LIBRARY_DIR) ;
}
HAVE_CURL = $(haveLibs) ;
}
}

View File

@ -1,6 +1,7 @@
SubDir TOP libs ; SubDir TOP libs ;
# Include all the components. # Include all the components.
SubInclude TOP libs libdownload ;
SubInclude TOP libs librunview ; SubInclude TOP libs librunview ;
SubInclude TOP libs libsupport ; SubInclude TOP libs libsupport ;
SubInclude TOP libs libinterface ; SubInclude TOP libs libinterface ;

29
libs/libdownload/Action.h Normal file
View File

@ -0,0 +1,29 @@
/*
* Copyright 2010, Andrea Anzani. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _ACTION_H
#define _ACTION_H
#include <Message.h>
#include <String.h>
#define ActionID bigtime_t
class Action
{
public:
Action() { fActionID = 0; }
virtual ~Action() {}
virtual status_t Perform(BMessage* errors) = 0;
virtual BString GetDescription() = 0;
void SetActionID(const ActionID id) { fActionID = id; }
ActionID GetActionID() const { return fActionID; }
private:
ActionID fActionID;
};
#endif //_ACTION_H

View File

@ -0,0 +1,285 @@
/*
* Copyright 2010, Andrea Anzani. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Andrea Anzani, andrea.anzani@gmail.com
*/
#include <File.h>
#include <Path.h>
#include <Mime.h>
#include <NodeInfo.h>
#include "ActionDownload.h"
#include "DownloadManager.h"
ActionDownload::ActionDownload(BString URL,
entry_ref dest,
bool allowResume,
BLooper* target,
uint32 msg)
:
Action(),
fUrl(URL),
fDest(dest),
fTarget(target),
fMsg(msg),
fAllowResume(allowResume)
{
file = NULL;
curl = NULL;
resuming = 0.0;
SetShouldStop(false);
}
ActionDownload::~ActionDownload()
{
}
void
ActionDownload::SetDownloadManager(DownloadManager* downloadManager)
{
fDownloadManager = downloadManager;
}
status_t
ActionDownload::openFile(BMessage* errors)
{
uint32 openMode = 0;
if (fAllowResume)
openMode = B_WRITE_ONLY | B_CREATE_FILE | B_OPEN_AT_END;
else
openMode = B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE;
if (file) return B_ERROR;
file = new BFile(&fDest, openMode);
if (!file || file->InitCheck() != B_OK) {
BString err("Can't open file!");
errors->AddInt32("status", ERROR_OPENFILE);
errors->AddString("error", err);
return B_ERROR;
}
return B_OK;
}
status_t
ActionDownload::Perform(BMessage* errors)
{
//is it these the right place?
fillMessage(this, errors);
//
CURLcode res;
status_t status = B_OK;
curl = curl_easy_init();
if (!curl) {
BString err("Internal error (CURL can't' init)!");
errors->AddInt32("status", ERROR_CURL_INIT);
errors->AddString("error", err);
return B_ERROR;
}
curl_easy_setopt(curl, CURLOPT_URL, fUrl.String());
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, callback);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this );
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, save_file);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION , 1); //follow the white link!
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER , FALSE); //https
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST , FALSE); //https
curl_easy_setopt(curl, CURLOPT_FAILONERROR , 1);
if (fDownloadManager)
fDownloadManager->FinishCurl(curl);
//RESUME
if (fAllowResume) {
BNode stat(&fDest);
// file->Seek(SEEK_END,0);
// size_t resume = (size_t)file->Position();
off_t size = 0;
stat.GetSize(&size);
off_t resume = size;
if ( resume > 0 ) {
curl_easy_setopt(curl, CURLOPT_RESUME_FROM, resume);
resuming = (double)resume;
}
}
BMessage connect(*errors);
connect.what = fMsg;
connect.AddInt32("status", OK_CONNECTING);
fTarget->PostMessage(&connect);
res = curl_easy_perform(curl);
if (res != 0) {
BString err("Can't connect!");
errors->AddInt32("status", ERROR_PERFORMING);
errors->AddString("error", err);
errors->AddInt32("curl_error", res);
errors->AddBool("should_stop", ShouldStop());
status = B_ERROR;
} else {
errors->AddInt32("status", OK_DOWNLOADED);
}
curl_easy_cleanup(curl);
errors->AddString("path", GetLocalPath());
errors->AddRef("entry", &fDest);
BMimeType mime;
if (fFileType != "")
BNodeInfo(file).SetType(fFileType.String());
else {
status_t guess = BMimeType::GuessMimeType(&fDest, &mime); // :( return B_ERROR.. why????????????
if (guess == B_OK)
BNodeInfo(file).SetType(mime.Type());
}
delete file;
file = NULL;
if (res == CURLE_BAD_DOWNLOAD_RESUME || res == CURLE_HTTP_RANGE_ERROR) {
// sarebbe bello chiedere.. va be per ora ci riprova e basta!
fAllowResume = false;
errors->MakeEmpty();
Perform(errors);
}
return status;
}
BString
ActionDownload::GetDescription()
{
return "HTTP File download";
}
BString
ActionDownload::GetLocalPath()
{
return BPath(&fDest).Path();
}
void
ActionDownload::fillMessage(ActionDownload* ad, BMessage* msg)
{
//fill with common fileds
int32 what = msg->what; //preserve original what.
*msg = ad->extraInfo;
msg->AddInt64("sid", ad->GetActionID());
msg->AddString("url", ad->fUrl);
msg->what = what;
}
void
ActionDownload::sendProgressX(ActionDownload* ad, double max, double current)
{
BMessage msg(ad->fMsg);
fillMessage(ad, &msg);
msg.AddInt32("status", OK_PROGRESS);
msg.AddFloat("max_progress", (float)max);
msg.AddFloat("current_progress", (float)current);
float div = 0.0;
if (max > 0.0)
div = ((float)current / (float)max ) * 100;
msg.AddInt32("percentage_progress", (int32)floor(div));
double speed = 0;
if (curl_easy_getinfo(ad->curl, CURLINFO_SPEED_DOWNLOAD, &speed) == CURLE_OK)
msg.AddFloat("download_speed", (float)speed);
//TOTALE:
if (curl_easy_getinfo(ad->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &speed) == CURLE_OK)
msg.AddFloat("total_size", (float)speed);
// ATTUALE: CURLINFO_SIZE_DOWNLOAD
if (curl_easy_getinfo(ad->curl, CURLINFO_SIZE_DOWNLOAD, &speed) == CURLE_OK)
msg.AddFloat("actual_size", (float)speed);
char* array = NULL;
if (curl_easy_getinfo(ad->curl, CURLINFO_EFFECTIVE_URL, &array) == CURLE_OK)
msg.AddString("effective_url", BString(array));
if (ad->fFileType == "" && curl_easy_getinfo(ad->curl, CURLINFO_CONTENT_TYPE, &array) == CURLE_OK) {
ad->fFileType.SetTo(array);
BNodeInfo(ad->file).SetType(ad->fFileType.String());
msg.AddString("filetype", BString(array));
}
ad->fTarget->PostMessage(&msg);
}
/*
void
ActionDownload::sendError(BLooper* looper,uint32 amsg,Status st,BString descr){
BMessage msg(amsg);
msg.AddInt32("status",st);
msg.AddString("error",descr);
looper->PostMessage(&msg);
}
*/
//
int
ActionDownload::callback(void* data,
double dltotal,
double dlnow,
double ,
double )
{
ActionDownload* ad = ((ActionDownload*)data);
if (ad->fTarget)
sendProgressX(ad, ad->resuming + dltotal, ad->resuming + dlnow);
return 0;
}
size_t
ActionDownload::save_file( void* ptr, size_t size, size_t nmemb, void* data)
{
ActionDownload* ad = ((ActionDownload*)data);
if (!ad->file) {
BMessage errors; //FIIX: how to report these errors??
if (ad->openFile(&errors) != B_OK) {
printf("ERROR: can't create destination file!\n");
return 0;
}
}
BFile* file = ad->file;
if (ad->ShouldStop()) return 0;
return file->Write(ptr, size * nmemb);
}

View File

@ -0,0 +1,107 @@
/*
* Copyright 2010, Andrea Anzani. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _ACTION_DOWNLOAD_H
#define _ACTION_DOWNLOAD_H
#include <curl/curl.h>
#include <Entry.h>
#include <Looper.h>
#include <File.h>
#include <SupportDefs.h>
#include <DownloadManager.h>
#include "Action.h"
class ActionDownload : public Action
{
public:
enum Status {
ERROR_OPENFILE, // 0
ERROR_CURL_INIT, // 1
ERROR_PERFORMING, // 2
OK_CONNECTING, // 3
OK_PROGRESS, // 4
OK_DOWNLOADED // 5
};
ActionDownload(BString URL, entry_ref dest,
bool allowResume, BLooper* target = NULL, uint32 msg = 0);
virtual ~ActionDownload();
status_t Perform(BMessage* errors);
BString GetDescription();
BString GetLocalPath();
void SetLooper(BLooper* loop, uint32 msg) {
fTarget = loop;
fMsg = msg;
};
BLooper* Looper() {
return fTarget;
}
uint32 MessageWhat() {
return fMsg;
}
// For compatibility:
void SetExtraData(BString extra) {
extraInfo.AddString("extra", extra);
}
void SetKey(BString key, BString data) {
extraInfo.AddString(key.String(), data);
}
void SetRef(BString key, entry_ref* ref) {
extraInfo.AddRef(key.String(), ref);
}
status_t GetRef(BString key, entry_ref* ref) {
return extraInfo.FindRef(key.String(), ref);
}
BString GetKey(BString key) {
BString data;
extraInfo.FindString(key.String(), &data);
return data;
}
void SetShouldStop(bool stop) {
fShouldStop = stop;
}
bool ShouldStop() {
return fShouldStop;
}
void SetDownloadManager(DownloadManager* downloadManager);
private:
status_t openFile(BMessage*);
static void fillMessage(ActionDownload*, BMessage*);
static void sendProgressX(ActionDownload*, double max, double current);
//curl callbacks:
static size_t save_file ( void* ptr, size_t size, size_t nmemb, void* stream);
static int callback (void* clientp, double dltotal, double dlnow, double , double);
CURL* curl;
BString fUrl;
entry_ref fDest;
BLooper* fTarget;
uint32 fMsg;
BMessage extraInfo;
bool fShouldStop;
BFile* file;
double resuming;
bool fAllowResume;
DownloadManager* fDownloadManager;
BString fFileType;
};
#endif // _ACTION_DOWNLOAD_H

View File

@ -0,0 +1,190 @@
/*
* Copyright 2010, Andrea Anzani. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Andrea Anzani, andrea.anzani@gmail.com
*/
#include <Messenger.h>
#include "DownloadManager.h"
#include "ActionDownload.h"
#define DEFAULT_ITEMS_DOWNLOAD 1
DownloadManager::DownloadManager(BLooper* target): fTarget(target)
{
}
void
DownloadManager::Enqueue(QueueType type, ActionDownload* ad)
{
if (!fQueue[type]) {
fQueue[type] = new QueueFileDownload("queue_downloads", DEFAULT_ITEMS_DOWNLOAD, fTarget, DOWNLOAD_INFO);
}
ad->SetDownloadManager(this);
fQueue[type]->AddAction(ad);
}
void
DownloadManager::TryStopCurrentAction(QueueType type, BString key, BString value)
{
if (!fQueue[type]) {
return;
}
if (fQueue[type]->Lock()) {
for (int i = 0; i < fQueue[type]->CountThreads(); i++) {
ActionDownload* ad = (ActionDownload*)fQueue[type]->CurrentAction(i);
if (ad && ad->GetKey(key).Compare(value.String()) == 0 )
ad->SetShouldStop(true);
}
fQueue[type]->Unlock();
}
}
bool
DownloadManager::RemoveFromQueue(QueueType type , BString key, BString value)
{
if (!fQueue[type]) {
return true;
}
if (fQueue[type]->Lock()) {
for (int32 i = 0; i < fQueue[type]->CountActions(); i++) {
ActionDownload* ad = (ActionDownload*)fQueue[type]->ActionAt(i);
if (ad->GetKey(key).Compare(value.String()) == 0 ) {
fQueue[type]->RemoveActionAt(i);
fQueue[type]->Unlock();
return true;
}
}
for (int i = 0; i < fQueue[type]->CountThreads(); i++) {
ActionDownload* ad = (ActionDownload*)fQueue[type]->CurrentAction(i);
if (ad && ad->GetKey(key).Compare(value.String()) == 0 )
ad->SetShouldStop(true);
}
fQueue[type]->Unlock();
return false;
}
return false;
}
void
DownloadManager::RemoveQueue(QueueType type, BList* removed)
{
if (!fQueue[type]) {
return;
}
fQueue[type]->Lock();
while (fQueue[type]->CountActions()) {
// ActionDownload *ad = (ActionDownload*)fQueue[type]->ActionAt(0);
fQueue[type]->RemoveActionAt(0);
}
// ***************************************
// we did not unlock
// so no one can add new item.
// ***************************************
for (int i = 0; i < fQueue[type]->CountThreads(); i++) {
if (fQueue[type]->CurrentAction(i))
removed->AddItem( (void*)fQueue[type]->CurrentAction(i));
}
}
void
DownloadManager::LoadProxySetting(BMessage* data)
{
bool value;
fEnabled = false;
fAddress.SetTo("");
fUserpwd.SetTo("");
fPort = 0;
if (data->FindBool("enable", &value) == B_OK)
fEnabled = value;
if (!fEnabled)
return;
BString username, password;
data->FindString("username", &username);
data->FindInt32("port", &fPort);
data->FindString("address", &fAddress);
data->FindString("password", &password);
if (username != "" || password != "")
fUserpwd << username << ":" << password;
}
void
DownloadManager::LoadDownloadSetting(BMessage* data)
{
//FIXME: fQueue[XXX] can be null.
//here magic stuff! :=)
int32 number = 1;
if (data->FindInt32("max_downloads", &number) == B_OK) {
fQueue[DOWNLOADS_QUEUE]->SetDownloadCount(number);
}
}
void
DownloadManager::FinishCurl(CURL* curl)
{
if (!fEnabled)
return;
curl_easy_setopt(curl, CURLOPT_PROXY, fAddress.String());
curl_easy_setopt(curl, CURLOPT_PROXYPORT, fPort);
curl_easy_setopt(curl, CURLOPT_PROXYTYPE , CURLPROXY_HTTP);
if (fUserpwd != "")
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD , fUserpwd.String() );
}
thread_id
DownloadManager::SingleThreadAction(ActionDownload* action)
{
action->SetDownloadManager(this);
if (action->Looper() == NULL) {
action->SetLooper(fTarget, DOWNLOAD_INFO);
}
thread_id id = spawn_thread(DownloadManager::SingleThreadPerform, "single_action_thread", B_NORMAL_PRIORITY, (void*)action);
resume_thread(id);
return id;
}
int32
DownloadManager::SingleThreadPerform(void* a)
{
ActionDownload* ad = (ActionDownload*)a;
// perform the action
BMessage err;
//status_t status =
ad->Perform(&err);
// do post-perform!
if (ad->Looper()) {
err.what = ad->MessageWhat();
BMessenger(ad->Looper()).SendMessage(&err);
}
return 0;
}

View File

@ -0,0 +1,56 @@
/*
* Copyright 2006-2010, Andrea Anzani. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _DOWNLOAD_MANAGER_H
#define _DOWNLOAD_MANAGER_H
#include <Looper.h>
#include <List.h>
#include <SupportDefs.h>
#include <curl/curl.h>
#include "QueueFileDownload.h"
#define DOWNLOAD_INFO 'dwni'
class ActionDownload;
class DownloadManager
{
public:
enum QueueType {
DOWNLOADS_QUEUE = 0
};
DownloadManager(BLooper* target);
void Enqueue(QueueType, ActionDownload*);
void TryStopCurrentAction(QueueType, BString key, BString value);
bool RemoveFromQueue(QueueType, BString key, BString value);
void RemoveQueue(QueueType, BList* removed);
void LoadProxySetting(BMessage* data);
void LoadDownloadSetting(BMessage* data);
thread_id SingleThreadAction(ActionDownload* action);
void FinishCurl(CURL* curl);
private:
static int32 SingleThreadPerform(void* a);
QueueFileDownload* fQueue[3];
// Proxy
int32 fPort;
BString fAddress;
BString fUserpwd;
bool fEnabled;
BLooper* fTarget;
};
#endif // _DOWNLOAD_MANAGER_H

16
libs/libdownload/Jamfile Normal file
View File

@ -0,0 +1,16 @@
SubDir TOP libs libdownload ;
SubDirSysHdrs [ FDirName $(TOP) ] ;
SubDirSysHdrs [ FDirName $(CURL_INCLUDE_DIR) ] ;
StaticLibrary libdownload.a :
ActionDownload.cpp
DownloadManager.cpp
QueueFileDownload.cpp
QueueMultiActions.cpp
StripeView.cpp
PercentageWindow.cpp
: be $(TARGET_LIBSTDC++) translation curl
;
LINKFLAGS on libdownload.a += -L$(CURL_LIBRARY_DIR) ;

View File

@ -0,0 +1,872 @@
/*
Open Tracker License
Terms and Conditions
Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice applies to all licensees
and shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Be Incorporated shall not be
used in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from Be Incorporated.
Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
of Be Incorporated in the United States and other countries. Other brand product
names are registered trademarks or trademarks of their respective holders.
All rights reserved.
*/
/****************************************************************************
** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING **
** **
** DANGER, WILL ROBINSON! **
** **
** The interfaces contained here are part of BeOS's **
** **
** >> PRIVATE NOT FOR PUBLIC USE << **
** **
** implementation. **
** **
** These interfaces WILL CHANGE in future releases. **
** If you use them, your app WILL BREAK at some future time. **
** **
** (And yes, this does mean that binaries built from OpenTracker will not **
** be compatible with some future releases of the OS. When that happens, **
** we will provide an updated version of this file to keep compatibility.) **
** **
** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING **
****************************************************************************/
//
// ObjectList is a wrapper around BList that adds type safety,
// optional object ownership, search, insert operations, etc.
//
#ifndef __OBJECT_LIST__
#define __OBJECT_LIST__
#ifndef _BE_H
#include <List.h>
#endif
#include <SupportDefs.h>
template<class T> class BObjectList;
template<class T>
struct UnaryPredicate {
virtual int operator()(const T*) const
// virtual could be avoided here if FindBinaryInsertionIndex,
// etc. were member template functions
{
return 0;
}
private:
static int _unary_predicate_glue(const void* item, void* context);
friend class BObjectList<T>;
};
template<class T>
int
UnaryPredicate<T>::_unary_predicate_glue(const void* item, void* context)
{
return ((UnaryPredicate<T> *)context)->operator()((const T*)item);
}
class _PointerList_ : public BList
{
public:
_PointerList_(const _PointerList_ &list);
_PointerList_(int32 itemsPerBlock = 20, bool owning = false);
~_PointerList_();
typedef void *(* GenericEachFunction)(void*, void*);
typedef int (* GenericCompareFunction)(const void*, const void*);
typedef int (* GenericCompareFunctionWithState)(const void*, const void*,
void*);
typedef int (* UnaryPredicateGlue)(const void*, void*);
void* EachElement(GenericEachFunction, void*);
void SortItems(GenericCompareFunction);
void SortItems(GenericCompareFunctionWithState, void* state);
void HSortItems(GenericCompareFunction);
void HSortItems(GenericCompareFunctionWithState, void* state);
void* BinarySearch(const void*, GenericCompareFunction) const;
void* BinarySearch(const void*, GenericCompareFunctionWithState, void* state) const;
int32 BinarySearchIndex(const void*, GenericCompareFunction) const;
int32 BinarySearchIndex(const void*, GenericCompareFunctionWithState, void* state) const;
int32 BinarySearchIndexByPredicate(const void*, UnaryPredicateGlue) const;
bool Owning() const;
bool ReplaceItem(int32, void*);
protected:
bool owning;
};
template<class T>
class BObjectList : private _PointerList_
{
public:
// iteration and sorting
typedef T *(* EachFunction)(T*, void*);
typedef const T *(* ConstEachFunction)(const T*, void*);
typedef int (* CompareFunction)(const T*, const T*);
typedef int (* CompareFunctionWithState)(const T*, const T*, void* state);
BObjectList(int32 itemsPerBlock = 20, bool owning = false);
BObjectList(const BObjectList& list);
// clones list; if list is owning, makes copies of all
// the items
virtual ~BObjectList();
BObjectList& operator=(const BObjectList& list);
// clones list; if list is owning, makes copies of all
// the items
// adding and removing
// ToDo:
// change Add calls to return const item
bool AddItem(T*);
bool AddItem(T*, int32);
bool AddList(BObjectList*);
bool AddList(BObjectList*, int32);
bool RemoveItem(T*, bool deleteIfOwning = true);
// if owning, deletes the removed item
T* RemoveItemAt(int32);
// returns the removed item
void MakeEmpty(bool deleteIfOwning = true);
// item access
T* ItemAt(int32) const;
bool ReplaceItem(int32 index, T*);
// if list is owning, deletes the item at <index> first
T* SwapWithItem(int32 index, T* newItem);
// same as ReplaceItem, except does not delete old item at <index>,
// returns it instead
T* FirstItem() const;
T* LastItem() const;
// misc. getters
int32 IndexOf(const T*) const;
bool HasItem(const T*) const;
bool IsEmpty() const;
int32 CountItems() const;
T* EachElement(EachFunction, void*);
const T* EachElement(ConstEachFunction, void*) const;
void SortItems(CompareFunction);
void SortItems(CompareFunctionWithState, void* state);
void HSortItems(CompareFunction);
void HSortItems(CompareFunctionWithState, void* state);
// linear search, returns first item that matches predicate
const T* FindIf(const UnaryPredicate<T> &) const;
T* FindIf(const UnaryPredicate<T> &);
// list must be sorted with CompareFunction for these to work
T* BinarySearch(const T&, CompareFunction) const;
T* BinarySearch(const T&, CompareFunctionWithState, void* state) const;
template<typename Key>
T* BinarySearchByKey(const Key& key, int (*compare)(const Key*, const T*))
const;
template<typename Key>
T* BinarySearchByKey(const Key& key,
int (*compare)(const Key*, const T*, void*), void* state) const;
int32 BinarySearchIndex(const T& item, CompareFunction compare) const;
int32 BinarySearchIndex(const T& item, CompareFunctionWithState compare,
void* state) const;
template<typename Key>
int32 BinarySearchIndexByKey(const Key& key,
int (*compare)(const Key*, const T*)) const;
// Binary insertion - list must be sorted with CompareFunction for
// these to work
// simple insert
bool BinaryInsert(T*, CompareFunction);
bool BinaryInsert(T*, CompareFunctionWithState, void* state);
bool BinaryInsert(T*, const UnaryPredicate<T> &);
// unique insert, returns false if item already in list
bool BinaryInsertUnique(T*, CompareFunction);
bool BinaryInsertUnique(T*, CompareFunctionWithState, void* state);
bool BinaryInsertUnique(T*, const UnaryPredicate<T> &);
// insert a copy of the item, returns new inserted item
T* BinaryInsertCopy(const T& copyThis, CompareFunction);
T* BinaryInsertCopy(const T& copyThis, CompareFunctionWithState, void* state);
// insert a copy of the item if not in list already
// returns new inserted item or existing item in case of a conflict
T* BinaryInsertCopyUnique(const T& copyThis, CompareFunction);
T* BinaryInsertCopyUnique(const T& copyThis, CompareFunctionWithState, void* state);
int32 FindBinaryInsertionIndex(const UnaryPredicate<T> &, bool* alreadyInList = 0) const;
// returns either the index into which a new item should be inserted
// or index of an existing item that matches the predicate
// deprecated API, will go away
BList* AsBList() {
return this;
}
const BList* AsBList() const {
return this;
}
private:
void SetItem(int32, T*);
};
template<class Item, class Result, class Param1>
Result
WhileEachListItem(BObjectList<Item> *list, Result (Item::*func)(Param1), Param1 p1)
{
Result result = 0;
int32 count = list->CountItems();
for (int32 index = 0; index < count; index++)
if ((result = (list->ItemAt(index)->*func)(p1)) != 0)
break;
return result;
}
template<class Item, class Result, class Param1>
Result
WhileEachListItem(BObjectList<Item> *list, Result (*func)(Item*, Param1), Param1 p1)
{
Result result = 0;
int32 count = list->CountItems();
for (int32 index = 0; index < count; index++)
if ((result = (*func)(list->ItemAt(index), p1)) != 0)
break;
return result;
}
template<class Item, class Result, class Param1, class Param2>
Result
WhileEachListItem(BObjectList<Item> *list, Result (Item::*func)(Param1, Param2),
Param1 p1, Param2 p2)
{
Result result = 0;
int32 count = list->CountItems();
for (int32 index = 0; index < count; index++)
if ((result = (list->ItemAt(index)->*func)(p1, p2)) != 0)
break;
return result;
}
template<class Item, class Result, class Param1, class Param2>
Result
WhileEachListItem(BObjectList<Item> *list, Result (*func)(Item*, Param1, Param2),
Param1 p1, Param2 p2)
{
Result result = 0;
int32 count = list->CountItems();
for (int32 index = 0; index < count; index++)
if ((result = (*func)(list->ItemAt(index), p1, p2)) != 0)
break;
return result;
}
template<class Item, class Result, class Param1, class Param2, class Param3, class Param4>
Result
WhileEachListItem(BObjectList<Item> *list, Result (*func)(Item*, Param1, Param2,
Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4)
{
Result result = 0;
int32 count = list->CountItems();
for (int32 index = 0; index < count; index++)
if ((result = (*func)(list->ItemAt(index), p1, p2, p3, p4)) != 0)
break;
return result;
}
template<class Item, class Result>
void
EachListItemIgnoreResult(BObjectList<Item> *list, Result (Item::*func)())
{
int32 count = list->CountItems();
for (int32 index = 0; index < count; index++)
(list->ItemAt(index)->*func)();
}
template<class Item, class Param1>
void
EachListItem(BObjectList<Item> *list, void (*func)(Item*, Param1), Param1 p1)
{
int32 count = list->CountItems();
for (int32 index = 0; index < count; index++)
(func)(list->ItemAt(index), p1);
}
template<class Item, class Param1, class Param2>
void
EachListItem(BObjectList<Item> *list, void (Item::*func)(Param1, Param2),
Param1 p1, Param2 p2)
{
int32 count = list->CountItems();
for (int32 index = 0; index < count; index++)
(list->ItemAt(index)->*func)(p1, p2);
}
template<class Item, class Param1, class Param2>
void
EachListItem(BObjectList<Item> *list, void (*func)(Item*, Param1, Param2),
Param1 p1, Param2 p2)
{
int32 count = list->CountItems();
for (int32 index = 0; index < count; index++)
(func)(list->ItemAt(index), p1, p2);
}
template<class Item, class Param1, class Param2, class Param3>
void
EachListItem(BObjectList<Item> *list, void (*func)(Item*, Param1, Param2,
Param3), Param1 p1, Param2 p2, Param3 p3)
{
int32 count = list->CountItems();
for (int32 index = 0; index < count; index++)
(func)(list->ItemAt(index), p1, p2, p3);
}
template<class Item, class Param1, class Param2, class Param3, class Param4>
void
EachListItem(BObjectList<Item> *list, void (*func)(Item*, Param1, Param2,
Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4)
{
int32 count = list->CountItems();
for (int32 index = 0; index < count; index++)
(func)(list->ItemAt(index), p1, p2, p3, p4);
}
// inline code
inline bool
_PointerList_::Owning() const
{
return owning;
}
template<class T>
BObjectList<T>::BObjectList(int32 itemsPerBlock, bool owning)
: _PointerList_(itemsPerBlock, owning)
{
}
template<class T>
BObjectList<T>::BObjectList(const BObjectList<T> &list)
: _PointerList_(list)
{
owning = list.owning;
if (owning) {
// make our own copies in an owning list
int32 count = list.CountItems();
for (int32 index = 0; index < count; index++) {
T* item = list.ItemAt(index);
if (item)
item = new T(*item);
SetItem(index, item);
}
}
}
template<class T>
BObjectList<T>::~BObjectList()
{
if (Owning())
// have to nuke elements first
MakeEmpty();
}
template<class T>
BObjectList<T> &
BObjectList<T>::operator=(const BObjectList<T> &list)
{
owning = list.owning;
BObjectList<T> &result = (BObjectList<T> &)_PointerList_::operator=(list);
if (owning) {
// make our own copies in an owning list
int32 count = list.CountItems();
for (int32 index = 0; index < count; index++) {
T* item = list.ItemAt(index);
if (item)
item = new T(*item);
SetItem(index, item);
}
}
return result;
}
template<class T>
bool
BObjectList<T>::AddItem(T* item)
{
// need to cast to void * to make T work for const pointers
return _PointerList_::AddItem((void*)item);
}
template<class T>
bool
BObjectList<T>::AddItem(T* item, int32 atIndex)
{
return _PointerList_::AddItem((void*)item, atIndex);
}
template<class T>
bool
BObjectList<T>::AddList(BObjectList<T> *newItems)
{
return _PointerList_::AddList(newItems);
}
template<class T>
bool
BObjectList<T>::AddList(BObjectList<T> *newItems, int32 atIndex)
{
return _PointerList_::AddList(newItems, atIndex);
}
template<class T>
bool
BObjectList<T>::RemoveItem(T* item, bool deleteIfOwning)
{
bool result = _PointerList_::RemoveItem((void*)item);
if (result && Owning() && deleteIfOwning)
delete item;
return result;
}
template<class T>
T *
BObjectList<T>::RemoveItemAt(int32 index)
{
return (T*)_PointerList_::RemoveItem(index);
}
template<class T>
inline T *
BObjectList<T>::ItemAt(int32 index) const
{
return (T*)_PointerList_::ItemAt(index);
}
template<class T>
bool
BObjectList<T>::ReplaceItem(int32 index, T* item)
{
if (owning)
delete ItemAt(index);
return _PointerList_::ReplaceItem(index, (void*)item);
}
template<class T>
T *
BObjectList<T>::SwapWithItem(int32 index, T* newItem)
{
T* result = ItemAt(index);
_PointerList_::ReplaceItem(index, (void*)newItem);
return result;
}
template<class T>
void
BObjectList<T>::SetItem(int32 index, T* newItem)
{
_PointerList_::ReplaceItem(index, (void*)newItem);
}
template<class T>
int32
BObjectList<T>::IndexOf(const T* item) const
{
return _PointerList_::IndexOf((void*)item);
}
template<class T>
T *
BObjectList<T>::FirstItem() const
{
return (T*)_PointerList_::FirstItem();
}
template<class T>
T *
BObjectList<T>::LastItem() const
{
return (T*)_PointerList_::LastItem();
}
template<class T>
bool
BObjectList<T>::HasItem(const T* item) const
{
return _PointerList_::HasItem((void*)item);
}
template<class T>
bool
BObjectList<T>::IsEmpty() const
{
return _PointerList_::IsEmpty();
}
template<class T>
int32
BObjectList<T>::CountItems() const
{
return _PointerList_::CountItems();
}
template<class T>
void
BObjectList<T>::MakeEmpty(bool deleteIfOwning)
{
if (owning && deleteIfOwning) {
int32 count = CountItems();
for (int32 index = 0; index < count; index++)
delete ItemAt(index);
}
_PointerList_::MakeEmpty();
}
template<class T>
T *
BObjectList<T>::EachElement(EachFunction func, void* params)
{
return (T*)_PointerList_::EachElement((GenericEachFunction)func, params);
}
template<class T>
const T *
BObjectList<T>::EachElement(ConstEachFunction func, void* params) const
{
return (const T*)
const_cast<BObjectList<T> *>(this)->_PointerList_::EachElement(
(GenericEachFunction)func, params);
}
template<class T>
const T *
BObjectList<T>::FindIf(const UnaryPredicate<T> &predicate) const
{
int32 count = CountItems();
for (int32 index = 0; index < count; index++)
if (predicate.operator()(ItemAt(index)) == 0)
return ItemAt(index);
return 0;
}
template<class T>
T *
BObjectList<T>::FindIf(const UnaryPredicate<T> &predicate)
{
int32 count = CountItems();
for (int32 index = 0; index < count; index++)
if (predicate.operator()(ItemAt(index)) == 0)
return ItemAt(index);
return 0;
}
template<class T>
void
BObjectList<T>::SortItems(CompareFunction function)
{
_PointerList_::SortItems((GenericCompareFunction)function);
}
template<class T>
void
BObjectList<T>::SortItems(CompareFunctionWithState function, void* state)
{
_PointerList_::SortItems((GenericCompareFunctionWithState)function, state);
}
template<class T>
void
BObjectList<T>::HSortItems(CompareFunction function)
{
_PointerList_::HSortItems((GenericCompareFunction)function);
}
template<class T>
void
BObjectList<T>::HSortItems(CompareFunctionWithState function, void* state)
{
_PointerList_::HSortItems((GenericCompareFunctionWithState)function, state);
}
template<class T>
T *
BObjectList<T>::BinarySearch(const T& key, CompareFunction func) const
{
return (T*)_PointerList_::BinarySearch(&key,
(GenericCompareFunction)func);
}
template<class T>
T *
BObjectList<T>::BinarySearch(const T& key, CompareFunctionWithState func, void* state) const
{
return (T*)_PointerList_::BinarySearch(&key,
(GenericCompareFunctionWithState)func, state);
}
template<class T>
template<typename Key>
T *
BObjectList<T>::BinarySearchByKey(const Key& key,
int (*compare)(const Key*, const T*)) const
{
return (T*)_PointerList_::BinarySearch(&key,
(GenericCompareFunction)compare);
}
template<class T>
template<typename Key>
T *
BObjectList<T>::BinarySearchByKey(const Key& key,
int (*compare)(const Key*, const T*, void*), void* state) const
{
return (T*)_PointerList_::BinarySearch(&key,
(GenericCompareFunctionWithState)compare, state);
}
template<class T>
int32
BObjectList<T>::BinarySearchIndex(const T& item, CompareFunction compare) const
{
return _PointerList_::BinarySearchIndex(&item,
(GenericCompareFunction)compare);
}
template<class T>
int32
BObjectList<T>::BinarySearchIndex(const T& item,
CompareFunctionWithState compare, void* state) const
{
return _PointerList_::BinarySearchIndex(&item,
(GenericCompareFunctionWithState)compare, state);
}
template<class T>
template<typename Key>
int32
BObjectList<T>::BinarySearchIndexByKey(const Key& key,
int (*compare)(const Key*, const T*)) const
{
return _PointerList_::BinarySearchIndex(&key,
(GenericCompareFunction)compare);
}
template<class T>
bool
BObjectList<T>::BinaryInsert(T* item, CompareFunction func)
{
int32 index = _PointerList_::BinarySearchIndex(item,
(GenericCompareFunction)func);
if (index >= 0) {
// already in list, add after existing
return AddItem(item, index + 1);
}
return AddItem(item, -index - 1);
}
template<class T>
bool
BObjectList<T>::BinaryInsert(T* item, CompareFunctionWithState func, void* state)
{
int32 index = _PointerList_::BinarySearchIndex(item,
(GenericCompareFunctionWithState)func, state);
if (index >= 0) {
// already in list, add after existing
return AddItem(item, index + 1);
}
return AddItem(item, -index - 1);
}
template<class T>
bool
BObjectList<T>::BinaryInsertUnique(T* item, CompareFunction func)
{
int32 index = _PointerList_::BinarySearchIndex(item,
(GenericCompareFunction)func);
if (index >= 0)
return false;
return AddItem(item, -index - 1);
}
template<class T>
bool
BObjectList<T>::BinaryInsertUnique(T* item, CompareFunctionWithState func, void* state)
{
int32 index = _PointerList_::BinarySearchIndex(item,
(GenericCompareFunctionWithState)func, state);
if (index >= 0)
return false;
return AddItem(item, -index - 1);
}
template<class T>
T *
BObjectList<T>::BinaryInsertCopy(const T& copyThis, CompareFunction func)
{
int32 index = _PointerList_::BinarySearchIndex(&copyThis,
(GenericCompareFunction)func);
if (index >= 0)
index++;
else
index = -index - 1;
T* newItem = new T(copyThis);
AddItem(newItem, index);
return newItem;
}
template<class T>
T *
BObjectList<T>::BinaryInsertCopy(const T& copyThis, CompareFunctionWithState func, void* state)
{
int32 index = _PointerList_::BinarySearchIndex(&copyThis,
(GenericCompareFunctionWithState)func, state);
if (index >= 0)
index++;
else
index = -index - 1;
T* newItem = new T(copyThis);
AddItem(newItem, index);
return newItem;
}
template<class T>
T *
BObjectList<T>::BinaryInsertCopyUnique(const T& copyThis, CompareFunction func)
{
int32 index = _PointerList_::BinarySearchIndex(&copyThis,
(GenericCompareFunction)func);
if (index >= 0)
return ItemAt(index);
index = -index - 1;
T* newItem = new T(copyThis);
AddItem(newItem, index);
return newItem;
}
template<class T>
T *
BObjectList<T>::BinaryInsertCopyUnique(const T& copyThis, CompareFunctionWithState func,
void* state)
{
int32 index = _PointerList_::BinarySearchIndex(&copyThis,
(GenericCompareFunctionWithState)func, state);
if (index >= 0)
return ItemAt(index);
index = -index - 1;
T* newItem = new T(copyThis);
AddItem(newItem, index);
return newItem;
}
template<class T>
int32
BObjectList<T>::FindBinaryInsertionIndex(const UnaryPredicate<T> &pred, bool* alreadyInList)
const
{
int32 index = _PointerList_::BinarySearchIndexByPredicate(&pred,
(UnaryPredicateGlue)&UnaryPredicate<T>::_unary_predicate_glue);
if (alreadyInList)
*alreadyInList = index >= 0;
if (index < 0)
index = -index - 1;
return index;
}
template<class T>
bool
BObjectList<T>::BinaryInsert(T* item, const UnaryPredicate<T> &pred)
{
return AddItem(item, FindBinaryInsertionIndex(pred));
}
template<class T>
bool
BObjectList<T>::BinaryInsertUnique(T* item, const UnaryPredicate<T> &pred)
{
bool alreadyInList;
int32 index = FindBinaryInsertionIndex(pred, &alreadyInList);
if (alreadyInList)
return false;
AddItem(item, index);
return true;
}
#endif /* __OBJECT_LIST__ */

View File

@ -0,0 +1,114 @@
/*
* Copyright 2010, Andrea Anzani. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Andrea Anzani, andrea.anzani@gmail.com
*/
#include "PercentageWindow.h"
#include "StripeView.h"
#include <Alert.h>
#include <StringView.h>
#include <Messenger.h>
#define DEFAULT_RECT BRect(0, 0, 310, 75)
static const int kTextIconOffsetSpace = 30;
PercentageWindow::PercentageWindow(const char* title, const char* text, BBitmap* icon) : BWindow(DEFAULT_RECT, title, B_MODAL_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE)
{
// Set up the "_master_" view
StripeView* masterView = new StripeView(Bounds());
AddChild(masterView);
masterView->SetBitmap(icon);
kTextIconOffset = 0;
if (masterView->Bitmap())
kTextIconOffset = masterView->Bitmap()->Bounds().right + kTextIconOffsetSpace;
//ok, un String
//il percentage (a 0) con testo percentuale
float maxW;
BStringView* text_string = new BStringView(BRect(kTextIconOffset, 6, 0, 0), "_text", text);
masterView->AddChild(text_string);
text_string->ResizeToPreferred();
maxW = text_string->Frame().right + 6;
BRect rect(text_string->Frame());
rect.OffsetBy(0, text_string->Bounds().Height() + 6);
perc = new BStringView(rect, "_percentage", "100%");
masterView->AddChild(perc);
perc->ResizeToPreferred();
if (perc->Frame().right + 6 > maxW)
maxW = perc->Frame().right + 6;
perc->SetText("0%");
maxW += kTextIconOffsetSpace;
ResizeTo(maxW, Bounds().bottom);
rect = Bounds();
rect.top = perc->Frame().bottom + 6;
rect.left = perc->Frame().left;
rect.right -= kTextIconOffsetSpace;
pw = new BStatusBar(rect, "status_bar", NULL, NULL);
pw->SetMaxValue(100.0);
masterView->AddChild(pw);
// pw->ResizeToPreferred();
ResizeTo(Bounds().right, pw->Frame().bottom + 5);
SetLook(B_FLOATING_WINDOW_LOOK);
MoveTo(BAlert::AlertPosition(Frame().Width(), Frame().Height()));
}
void
PercentageWindow::SetPercentage(int p)
{
BString text;
text << p << "%";
if (Lock()) {
perc->SetText(text.String());
pw->SetTo((float)p);
Unlock();
}
}
int
PercentageWindow::GetPercentage()
{
return (int)pw->CurrentValue();
}
bool
PercentageWindow::QuitRequested()
{
if (fLooper)
BMessenger(fLooper).SendMessage(fMsg);
return true;
}
void
PercentageWindow::Go(BLooper* lop, int32 msg)
{
fLooper = lop;
fMsg = msg;
Show();
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2010, Andrea Anzani. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _PercentageWindow_H_
#define _PercentageWindow_H_
#include <Window.h>
#include <Looper.h>
#include <Bitmap.h>
#include <String.h>
#include <StatusBar.h>
class ReflowingTextView;
class BStringView;
class PercentageWindow : public BWindow
{
public:
PercentageWindow(const char* title, const char* text, BBitmap* icon = NULL);
void Go(BLooper* lop = NULL, int32 msg = 0);
void SetPercentage(int perc);
int GetPercentage();
bool QuitRequested();
private:
BLooper* fLooper;
int32 fMsg;
float kTextIconOffset;
BStringView* perc;
BStatusBar* pw;
};
#endif

1054
libs/libdownload/Queue.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
/*
* Copyright 2010, Andrea Anzani. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Andrea Anzani, andrea.anzani@gmail.com
*/
#include "QueueFileDownload.h"
#include "ActionDownload.h"
#include "Messenger.h"
void
QueueFileDownload::ActionReadyToPerform(Action* action)
{
ActionDownload* ad = dynamic_cast<ActionDownload*>(action);
if (!ad) return;
ad->SetLooper(fLooper, fMsg);
}
void
QueueFileDownload::ActionPerformed(Action* action, status_t state, BMessage* msg)
{
ActionDownload* ad = dynamic_cast<ActionDownload*>(action);
if (!ad) return;
BMessage notify(*msg);
notify.what = fMsg;
if (fLooper)
BMessenger(fLooper).SendMessage(&notify);
return;
}
void
QueueFileDownload::SuppressAction(Action* action)
{
ActionDownload* ad = dynamic_cast<ActionDownload*>(action);
if (!ad) return;
ad->SetShouldStop(true);
}
//--

View File

@ -0,0 +1,33 @@
/*
* Copyright 2010, Andrea Anzani. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef QueueFileDownload_H_
#define QueueFileDownload_H_
#include <Looper.h>
#include "QueueMultiActions.h"
class QueueFileDownload : public QueueMultiActions
{
public:
QueueFileDownload(const char* name, int howMany, BLooper* target, uint32 msg)
:
QueueMultiActions(name, howMany)
{
fMsg = msg;
fLooper = target;
}
protected:
void ActionPerformed(Action*, status_t, BMessage*);
void ActionReadyToPerform(Action*);
void SuppressAction(Action*);
private:
BLooper* fLooper;
uint32 fMsg;
};
#endif

View File

@ -0,0 +1,255 @@
/*
* Copyright 2010, Andrea Anzani. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Andrea Anzani, andrea.anzani@gmail.com
*/
#include "QueueMultiActions.h"
#include <Message.h>
#include <stdio.h>
#define CHKLOCK if(!IsLocked()) debugger("\nQueueMultiActions must me locked!\n");
QueueMultiActions::QueueMultiActions(const char* name, int count)
{
fCount = count;
if (count > MAX_MULTI)
debugger("wrong number of multi download settings");
for (int j = 0; j < MAX_MULTI; j++) {
fCurrentAction[j] = NULL;
fID[j] = 0;
}
fName.SetTo(name);
for (int i = 0; i < fCount; i++) {
BString n(name);
n << "'s enemy #" << i;
token* tok = new token;
tok->qa = this;
tok->index = i;
fID[i] = spawn_thread(QueueMultiActions::ManageTheQueue, n.String(), B_NORMAL_PRIORITY, tok);
//printf("Thread ready [%s] %ld\n",n.String(),fID[i]);
}
fLock = create_sem(1, name);
fLocked = false;
}
QueueMultiActions::~QueueMultiActions()
{
if (Lock()) {
for (int i = 0; i < fCount; i++) {
suspend_thread(fID[i]);
exit_thread(fID[i]);
}
delete_sem(fLock);
}
}
bool
QueueMultiActions::Lock()
{
status_t value = acquire_sem(fLock) ;
if (value == B_NO_ERROR) {
fLocked = true;
}
return (value == B_NO_ERROR);
}
void
QueueMultiActions::Unlock()
{
fLocked = false;
release_sem(fLock);
}
void
QueueMultiActions::SetDownloadCount(int fProposedCount)
{
if (Lock()) {
if (fProposedCount == fCount || fProposedCount <= 0 || fProposedCount > MAX_MULTI) {
Unlock();
return;
}
if (fProposedCount > fCount) {
for (int i = fCount; i < fProposedCount; i++) {
if ( fID[i] == 0) {
BString n = fName;
n << "'s enemy #" << i;
token* tok = new token;
tok->qa = this;
tok->index = i;
fID[i] = spawn_thread(QueueMultiActions::ManageTheQueue, n.String(), B_NORMAL_PRIORITY, tok);
//printf("Thread ready [%s] %ld\n",n.String(),fID[i]);
}
}
} else {
//uhm what to do?
for (int i = fProposedCount; i < fCount; i++) {
SuppressAction(fCurrentAction[i]);
}
}
fCount = fProposedCount;
//NotifyALL
for (int i = 0; i < fCount; i++)
resume_thread(fID[i]);
Unlock();
}
}
void
QueueMultiActions::AddAction(Action* a)
{
//FIX!
//esiste già un azione con lo stesso ID???
if (Lock()) {
//printf("adding %ld - Action name %s\n",fID,a->GetDescription().String());
fList.AddItem(a);
if (fList.CountItems() <= fCount) { //Auto-start thread
for (int i = 0; i < fCount; i++)
resume_thread(fID[i]);
}
Unlock();
}
}
Action*
QueueMultiActions::CurrentAction(int index)
{
CHKLOCK;
return fCurrentAction[index];
}
void
QueueMultiActions::SetCurrentAction(Action* action, int index)
{
CHKLOCK;
fCurrentAction[index] = action;
}
int32
QueueMultiActions::CountActions()
{
CHKLOCK;
return fList.CountItems();
}
Action*
QueueMultiActions::ActionAt(int32 pos)
{
CHKLOCK;
return fList.ItemAt(pos);
}
void
QueueMultiActions::RemoveActionAt(int32 pos)
{
CHKLOCK;
fList.RemoveItemAt(pos);
}
bool
QueueMultiActions::IsLocked()
{
return fLocked;
}
void
QueueMultiActions::KIllThread(int id)
{
fID[id] = 0;
}
int32
QueueMultiActions::ManageTheQueue(void* data)
{
token* tok = (token*)data;
QueueMultiActions* qa = tok->qa;
int index = tok->index;
//printf("Thread started %ld\n",qa->fID[index]);
while (true) {
Action* last = NULL;
if (qa->Lock()) {
//printf("Thread executing PID %ld Count %ld\n",qa->fID[index],qa->fList.CountItems());
if (qa->fList.CountItems() > 0) {
// remove and delete the action.
last = qa->fList.ItemAt(0);
qa->fList.RemoveItemAt(0);
qa->SetCurrentAction(last, index);
} else {
last = NULL;
qa->SetCurrentAction(last, index);
}
qa->Unlock();
}
if (last) {
// pop the action
qa->ActionReadyToPerform(last);
// perform the action
BMessage err;
status_t status = last->Perform(&err);
// do post-perform!
qa->ActionPerformed(last, status, &err);
if (qa->Lock()) {
qa->SetCurrentAction(NULL, index);
delete last;
qa->Unlock();
}
} else {
//printf("Thread suspend PID %ld Count %ld\n",qa->fID[index],qa->fList.CountItems());
suspend_thread(qa->fID[index]);
}
//Check my life?
if (qa->Lock()) {
if ( index >= qa->fCount) {
qa->KIllThread(index);
qa->Unlock();
//printf("Thread died PID %ld\n",qa->fID[index]);
return 0; //bye-bye world!
}
qa->Unlock();
}
} //while
}

View File

@ -0,0 +1,73 @@
/*
* Copyright 2010, Andrea Anzani. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef QueueMultiActions_H_
#define QueueMultiActions_H_
#include <Looper.h>
#include <ObjectList.h>
#include <OS.h>
#include "Action.h"
#define MAX_MULTI 5
class QueueMultiActions
{
public:
QueueMultiActions(const char* name, int count);
virtual ~QueueMultiActions();
void AddAction(Action* );
//BEFORE CALLING CurrentAction, you MUST Lock() the Queue!
Action* CurrentAction(int index);
int32 CountActions();
int CountThreads() {
return fCount;
}
Action* ActionAt(int32 pos);
void RemoveActionAt(int32 pos);
void SetDownloadCount(int count);
bool Lock();
void Unlock();
bool IsLocked();
protected:
static int32 ManageTheQueue(void*);
virtual void ActionReadyToPerform(Action*) = 0;
virtual void ActionPerformed(Action*, status_t, BMessage*) = 0;
virtual void SuppressAction(Action*) = 0;
private:
struct token {
int index;
QueueMultiActions* qa;
};
void SetCurrentAction(Action*, int index);
void KIllThread(int id);
Action* fCurrentAction[MAX_MULTI];
thread_id fID[MAX_MULTI];
sem_id fLock;
BObjectList<Action> fList;
bool fLocked;
int fCount;
BString fName;
};
#endif

View File

@ -0,0 +1,232 @@
/*
* Copyright 2010, Andrea Anzani. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Andrea Anzani, andrea.anzani@gmail.com
*/
#include "ReflowingTextView.h"
const bigtime_t RTV_HIDE_DELAY = 1500000;
const bigtime_t RTV_SHOW_DELAY = 750000;
enum {
RTV_SHOW_TOOLTIP = 0x1000,
RTV_HIDE_TOOLTIP
};
ReflowingTextView::ReflowingTextView(BRect frame, const char* name, BRect textRect, uint32 resizeMask, uint32 flags) : BTextView(frame, name, textRect, resizeMask, flags), _showTipRunner(NULL), _canShow(false), _urlTip(NULL), _currentLinkStart(-1)
{
// empty
}
ReflowingTextView::~ReflowingTextView()
{
if ((_urlTip) && (_urlTip->Lock())) _urlTip->Quit();
delete _showTipRunner;
}
void ReflowingTextView::AttachedToWindow()
{
BTextView::AttachedToWindow();
// FixTextRect();
}
void ReflowingTextView::FrameResized(float w, float h)
{
BTextView::FrameResized(w, h);
// FixTextRect();
}
void ReflowingTextView::MouseMoved(BPoint where, uint32 code, const BMessage* msg)
{
const URLLink* link = NULL;
if (code == B_INSIDE_VIEW) {
link = GetURLAt(where);
#ifdef B_BEOS_VERSION_5
SetViewCursor((link != NULL) ? B_CURSOR_SYSTEM_DEFAULT : B_CURSOR_I_BEAM);
#else
be_app->SetCursor((link != NULL) ? B_HAND_CURSOR : B_I_BEAM_CURSOR);
#endif
}
BString scratch;
const BString* urlString = link ? &link->GetURL() : &scratch;
if ((link) && (urlString->Length() == 0)) {
char* buf = new char[link->GetLength()+1];
GetText(link->GetStart(), link->GetLength(), buf);
buf[link->GetLength()] = '\0';
scratch = buf;
delete [] buf;
urlString = &scratch;
}
int32 linkStart = link ? (int32)link->GetStart() : -1;
if (linkStart != _currentLinkStart) {
_currentLinkStart = linkStart;
_currentURLString = *urlString;
if (linkStart >= 0) {
if ((_canShow == false) && ((_showTipRunner == NULL) || (_runnerWillHide))) {
// Schedule unsetting the show flag
delete _showTipRunner;
_runnerWillHide = false;
_showTipRunner = new BMessageRunner(this, new BMessage(RTV_SHOW_TOOLTIP), RTV_SHOW_DELAY, 1);
}
} else {
if (_canShow) {
// schedule a delayed show
delete _showTipRunner;
_runnerWillHide = true;
_showTipRunner = new BMessageRunner(this, new BMessage(RTV_HIDE_TOOLTIP), RTV_HIDE_DELAY, 1);
} else if ((_showTipRunner) && (_runnerWillHide == false)) {
delete _showTipRunner; // cancel the pending show!
_showTipRunner = NULL;
}
}
UpdateToolTip();
}
BTextView::MouseMoved(where, code, msg);
}
void ReflowingTextView::MessageReceived(BMessage* msg)
{
switch (msg->what) {
case RTV_SHOW_TOOLTIP:
delete _showTipRunner;
_showTipRunner = NULL;
_canShow = true;
UpdateToolTip();
break;
case RTV_HIDE_TOOLTIP:
delete _showTipRunner;
_showTipRunner = NULL;
_canShow = false;
UpdateToolTip();
break;
default:
BTextView::MessageReceived(msg);
break;
}
}
void ReflowingTextView::UpdateToolTip()
{
if ((_canShow) && (_currentLinkStart >= 0)) {
if (_urlTip == NULL) {
_urlTip = new BWindow(BRect(0, 0, 5, 5), NULL, B_NO_BORDER_WINDOW_LOOK, B_FLOATING_ALL_WINDOW_FEEL, B_NOT_MOVABLE | B_NOT_CLOSABLE | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AVOID_FOCUS);
BView* blackBorder = new BView(_urlTip->Bounds(), NULL, B_FOLLOW_ALL_SIDES, 0);
const rgb_color black = {0, 0, 0, 255};
blackBorder->SetViewColor(black);
_urlTip->AddChild(blackBorder);
const rgb_color hiliteYellow = {255, 255, 200, 255};
BRect inset = blackBorder->Bounds();
inset.InsetBy(1, 1);
BView* yellowInterior = new BView(inset, NULL, B_FOLLOW_ALL_SIDES, 0);
yellowInterior->SetLowColor(hiliteYellow);
yellowInterior->SetViewColor(hiliteYellow);
blackBorder->AddChild(yellowInterior);
_urlStringView = new BStringView(yellowInterior->Bounds(), NULL, "", B_FOLLOW_ALL_SIDES);
_urlStringView->SetLowColor(hiliteYellow);
_urlStringView->SetViewColor(hiliteYellow);
yellowInterior->AddChild(_urlStringView);
}
if (_urlTip->Lock()) {
font_height ttfh;
_urlStringView->GetFontHeight(&ttfh);
float urlHeight = 20.0f;
BPoint pt = PointAt(_currentLinkStart, &urlHeight);
_urlTip->MoveTo(ConvertToScreen(pt) + BPoint(15.0f, -(ttfh.ascent + ttfh.descent + 3.0f)));
_urlTip->ResizeTo(muscleMin(_urlStringView->StringWidth(_currentURLString.String()) + 4.0f, 400.0f), ttfh.ascent + ttfh.descent + 2.0f);
_urlStringView->SetText(_currentURLString.String());
_urlTip->SetWorkspaces(B_CURRENT_WORKSPACE);
if (_urlTip->IsHidden()) _urlTip->Show();
_urlTip->Unlock();
}
} else if (_urlTip) {
if (_urlTip->Lock()) {
if (_urlTip->IsHidden() == false) _urlTip->Hide();
_urlTip->Unlock();
}
}
}
void ReflowingTextView::MouseDown(BPoint where)
{
if (IsFocus() == false) MakeFocus();
const URLLink* url = GetURLAt(where);
if (url) {
char* allocBuf = NULL;
const char* buf = url->GetURL().String();
if (buf[0] == '\0') {
buf = allocBuf = new char[url->GetLength()+1];
GetText(url->GetStart(), url->GetLength(), allocBuf);
allocBuf[url->GetLength()] = '\0';
}
if (strncasecmp(buf, "beshare://", 10) == 0) {
char* argv[] = {(char*) &buf[10]};
// be_roster->Launch(BESHARE_MIME_TYPE, ARRAYITEMS(argv), argv);
} else if (strncasecmp(buf, "beshare:", 8) == 0) {
BMessage msg(_queryMessage);
msg.AddString("query", &buf[8]);
_commandTarget.SendMessage(&msg);
} else if (strncasecmp(buf, "share:", 6) == 0) {
BMessage msg(_queryMessage);
msg.AddString("query", &buf[6]);
_commandTarget.SendMessage(&msg);
} else if (strncasecmp(buf, "priv:", 5) == 0) {
BMessage msg(_privMessage);
msg.AddString("users", &buf[5]);
_commandTarget.SendMessage(&msg);
} else if (strncasecmp(buf, "audio://", 8) == 0) {
BMessage msg(B_REFS_RECEIVED);
BString temp("http://");
temp += &buf[8];
msg.AddString("be:url", temp);
be_roster->Launch("audio/x-scpls", &msg);
} else be_roster->Launch(strncasecmp(buf, "mailto:", 7) ? "text/html" : "text/x-email", 1, const_cast<char**>(&buf));
delete [] allocBuf;
}
BTextView::MouseDown(where);
}
void ReflowingTextView::FixTextRect()
{
BRect t(Frame());
SetTextRect(t);
}
void ReflowingTextView::Clear()
{
Delete(0, TextLength() - 1);
_urls.Clear();
}
void ReflowingTextView::AddURLRegion(uint32 start, uint32 len, const BString& optHiddenURL)
{
_urls.AddTail(URLLink(start, len, optHiddenURL));
}
void ReflowingTextView::SetCommandURLTarget(const BMessenger& target, const BMessage& queryMsg, const BMessage& privMsg)
{
_commandTarget = target;
_queryMessage = queryMsg;
_privMessage = privMsg;
}
const ReflowingTextView::URLLink* ReflowingTextView::GetURLAt(BPoint pt) const
{
uint32 offset = (uint32) OffsetAt(pt);
for (int i = _urls.GetNumItems() - 1; i >= 0; i--) {
const URLLink& url = _urls[i];
if ((offset >= url.GetStart()) && (offset < url.GetStart() + url.GetLength())) return &url;
}
return NULL;
}

View File

@ -0,0 +1,95 @@
/*
* Copyright 2010, Andrea Anzani. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef REFLOWING_TEXT_VIEW_H
#define REFLOWING_TEXT_VIEW_H
#include <app/AppDefs.h>
#include <app/Application.h>
#include <app/Roster.h>
#include <app/MessageFilter.h>
#include <app/Message.h>
#include <app/MessageRunner.h>
#include <app/Messenger.h>
#include <interface/StringView.h>
#include <interface/TextView.h>
#include <interface/Window.h>
#include "Queue.h"
#include <String.h>
//#include "BeShareNameSpace.h"
/* Subsclass of BTextView that automatically reflows the text when it is resized */
class ReflowingTextView : public BTextView
{
public:
ReflowingTextView(BRect frame, const char* name, BRect textRect, uint32 resizeMask, uint32 flags = B_WILL_DRAW | B_PULSE_NEEDED);
virtual ~ReflowingTextView();
virtual void AttachedToWindow();
virtual void FrameResized(float w, float h);
virtual void MessageReceived(BMessage* msg);
virtual void MouseMoved(BPoint where, uint32 code, const BMessage* msg);
virtual void MouseDown(BPoint where);
void FixTextRect();
void Clear();
void AddURLRegion(uint32 start, uint32 len, const BString& optHiddenURL);
void SetCommandURLTarget(const BMessenger& target, const BMessage& queryMsg, const BMessage& privMsg);
private:
void UpdateToolTip();
/* A simple little data class that remembers stuff we need to remember about hyperlinks in the text view */
class URLLink
{
public:
URLLink() : _start(0), _len(0) {
/* empty */
}
URLLink(uint32 start, uint32 len, const BString& optURL) : _start(start), _len(len), _url(optURL) {
/* empty */
}
inline uint32 GetStart() const {
return _start;
}
inline uint32 GetLength() const {
return _len;
}
const BString& GetURL() const {
return _url;
}
private:
uint32 _start;
uint32 _len;
BString _url;
};
const URLLink* GetURLAt(BPoint pt) const;
Queue<URLLink> _urls;
BMessenger _commandTarget;
BMessage _queryMessage;
BMessage _privMessage;
BMessageRunner* _showTipRunner;
bool _runnerWillHide; // If true, the runner is a hide-runner.
bool _canShow;
BWindow* _urlTip;
BStringView* _urlStringView;
int32 _currentLinkStart;
BString _currentURLString;
};
#endif

View File

@ -0,0 +1,63 @@
/*
* Copyright 2010, Andrea Anzani. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Andrea Anzani, andrea.anzani@gmail.com
*/
#include "StripeView.h"
static const int kIconStripeWidth = 30;
StripeView::StripeView(BRect frame)
: BView(frame, "StripeView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
fIconBitmap(NULL)
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
}
StripeView::StripeView(BMessage* archive)
: BView(archive),
fIconBitmap(NULL)
{
}
StripeView::~StripeView() {}
StripeView*
StripeView::Instantiate(BMessage* archive)
{
if (!validate_instantiation(archive, "StripeView"))
return NULL;
return new StripeView(archive);
}
status_t
StripeView::Archive(BMessage* archive, bool deep)
{
return BView::Archive(archive, deep);
}
void
StripeView::Draw(BRect updateRect)
{
// Here's the fun stuff
if (fIconBitmap) {
BRect StripeRect = Bounds();
StripeRect.right = kIconStripeWidth;
SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
FillRect(StripeRect);
SetDrawingMode(B_OP_ALPHA);
DrawBitmapAsync(fIconBitmap, BPoint(18, 6));
SetDrawingMode(B_OP_COPY);
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2010, Andrea Anzani. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _StripeView_H_
#define _StripeView_H_
#include <View.h>
class StripeView : public BView
{
public:
StripeView(BRect frame);
StripeView(BMessage* archive);
~StripeView();
static StripeView* Instantiate(BMessage* archive);
status_t Archive(BMessage* archive, bool deep = true);
virtual void Draw(BRect updateRect);
// These functions (or something analogous) are missing from libbe.so's
// dump. I can only assume that the bitmap is a public var in the
// original implementation -- or BPAlert is a friend of StripeView.
// Neither one is necessary, since I can just add these.
void SetBitmap(BBitmap* Icon) {
fIconBitmap = Icon;
}
BBitmap* Bitmap() {
return fIconBitmap;
}
private:
BBitmap* fIconBitmap;
};
#endif

4
tests/Jamfile Normal file
View File

@ -0,0 +1,4 @@
SubDir TOP tests ;
# Include all the components
SubInclude TOP tests libdownload ;

12
tests/libdownload/Jamfile Normal file
View File

@ -0,0 +1,12 @@
SubDir TOP tests libdownload ;
SubDirSysHdrs [ FDirName $(TOP) libs libdownload ] ;
Application DownloadTest :
TheApp.cpp
: be $(TARGET_LIBSTDC++) translation libdownload.a curl
;
Depends DownloadTest : libdownload.a ;
LINKFLAGS on DownloadTest += -L$(CURL_LIBRARY_DIR) ;

View File

@ -0,0 +1,92 @@
#include <stdio.h>
#include <Application.h>
#include "DownloadManager.h"
#include "ActionDownload.h"
#include <Entry.h>
#include "PercentageWindow.h"
#include <TranslationUtils.h>
class TestApp : public BApplication
{
public:
TestApp():BApplication("application/xeD.libdownload.test"){};
void ReadyToRun()
{
printf("Ready To Run\n");
entry_ref ref;
get_ref_for_path("test.xxx", &ref);
ActionDownload* ad = new ActionDownload("http://www.webelin.it/website/wp-content/uploads/pdf/newsletter-webelin.pdf", ref, false);
BBitmap* icon = BTranslationUtils::GetBitmap("/boot/home/image.bmp");
percWindow = new PercentageWindow("Download test","Downloading useless test stuff...", icon);
percWindow->Show();
/*BMessage msg;
msg.AddBool("enable", true);
msg.AddString("username", "");
msg.AddString("address", "");
msg.AddString("password", "");
msg.AddInt32("port", 8080);
*/
fDownloadManager = new DownloadManager(this);
//fDownloadManager->LoadProxySetting(&msg);
fDownloadManager->SingleThreadAction(ad);
percWindow->SetPercentage(0);
}
void MessageReceived(BMessage* msg)
{
if (msg->what == DOWNLOAD_INFO)
{
int32 status = msg->FindInt32("status");
switch (status)
{
case ActionDownload::ERROR_OPENFILE:
printf("Error openig dest file\n");
break;
case ActionDownload::ERROR_CURL_INIT:
printf("Error while init curl\n");
break;
case ActionDownload::ERROR_PERFORMING:
printf("Error performing download\n");
msg->PrintToStream();
break;
case ActionDownload::OK_CONNECTING:
printf("Connecting\n");
break;
case ActionDownload::OK_PROGRESS:
printf("Progress\n");
msg->PrintToStream();
percWindow->SetPercentage(msg->FindInt32("percentage_progress"));
break;
case ActionDownload::OK_DOWNLOADED:
printf("Downloaded\n");
break;
default:
msg->PrintToStream();
break;
};
}
else
BApplication::MessageReceived(msg);
}
private:
DownloadManager* fDownloadManager;
PercentageWindow* percWindow;
};
int main()
{
TestApp tApp;
tApp.Run();
return 0;
}