Added libdownload from xeD.
This commit is contained in:
parent
30470d4816
commit
082f2ad34e
1
Jamfile
1
Jamfile
|
@ -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 ;
|
||||||
|
|
5
Jamrules
5
Jamrules
|
@ -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 ] ;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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 ;
|
||||||
|
|
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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) ;
|
|
@ -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(©This,
|
||||||
|
(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(©This,
|
||||||
|
(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(©This,
|
||||||
|
(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(©This,
|
||||||
|
(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__ */
|
|
@ -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();
|
||||||
|
}
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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(¬ify);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QueueFileDownload::SuppressAction(Action* action)
|
||||||
|
{
|
||||||
|
ActionDownload* ad = dynamic_cast<ActionDownload*>(action);
|
||||||
|
if (!ad) return;
|
||||||
|
|
||||||
|
ad->SetShouldStop(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -0,0 +1,4 @@
|
||||||
|
SubDir TOP tests ;
|
||||||
|
|
||||||
|
# Include all the components
|
||||||
|
SubInclude TOP tests libdownload ;
|
|
@ -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) ;
|
|
@ -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;
|
||||||
|
}
|
Ŝarĝante…
Reference in New Issue