/* * Copyright 2012 Adrien Destugues * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #define __STDBOOL_H__ 1 #include #include extern "C" { #include "desktop/download.h" #include "desktop/gui_download.h" #include "utils/utils.h" #include "utils/string.h" } #include "beos/download.h" #include #include #include #include #include #include class NSDownloadWindow: public BWindow { public: NSDownloadWindow(download_context* ctx); ~NSDownloadWindow(); void MessageReceived(BMessage* message); void Progress(int size); void Failure(const char* error); void Success(); private: download_context* ctx; BStatusBar* bar; unsigned long progress; bool success; }; struct gui_download_window { download_context* ctx; NSDownloadWindow* window; BLocker* storageLock; BDataIO* storage; }; NSDownloadWindow::NSDownloadWindow(download_context* ctx) : BWindow(BRect(30, 30, 400, 200), "Downloads", B_TITLED_WINDOW, B_NOT_RESIZABLE) , ctx(ctx) , progress(0) , success(false) { unsigned long dlsize = download_context_get_total_length(ctx); char* buffer = human_friendly_bytesize(dlsize); // Create the status bar BRect rect = Bounds(); rect.InsetBy(3, 3); bar = new BStatusBar(rect, "progress", download_context_get_filename(ctx), buffer); bar->SetMaxValue(dlsize); // Create the backgroundview (just so that the area around the progress bar // is B_PANEL_BACKGROUND_COLOR instead of white) BView* back = new BView(Bounds(), "back", B_FOLLOW_ALL_SIDES, B_WILL_DRAW); back->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); // Add the views to the window back->AddChild(bar); AddChild(back); // Resize the window to leave a margin around the progress bar BRect size = bar->Bounds(); ResizeTo(size.Width() + 6, size.Height() + 6); Show(); } NSDownloadWindow::~NSDownloadWindow() { download_context_abort(ctx); download_context_destroy(ctx); } void NSDownloadWindow::MessageReceived(BMessage* message) { switch(message->what) { case B_SAVE_REQUESTED: { entry_ref directory; const char* name; struct gui_download_window* dw; BFilePanel* source; message->FindRef("directory", &directory); message->FindString("name", &name); message->FindPointer("dw", (void**)&dw); BDirectory dir(&directory); BFile* storage = new BFile(&dir, name, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); dw->storageLock->Lock(); BMallocIO* tempstore = dynamic_cast(dw->storage); storage->Write(tempstore->Buffer(), tempstore->BufferLength()); delete dw->storage; if (success) delete storage; // File is already finished downloading ! else dw->storage = storage; dw->storageLock->Unlock(); message->FindPointer("source", (void**)&source); delete source; break; } default: BWindow::MessageReceived(message); } } void NSDownloadWindow::Progress(int size) { progress += size; char* buffer = human_friendly_bytesize(progress); strcat(buffer, "/"); bar->LockLooper(); bar->Update(size, NULL, buffer); bar->Invalidate(); bar->UnlockLooper(); } void NSDownloadWindow::Success() { bar->LockLooper(); bar->SetBarColor(ui_color(B_SUCCESS_COLOR)); bar->UnlockLooper(); success = true; } void NSDownloadWindow::Failure(const char* error) { bar->LockLooper(); bar->Update(0, NULL, error); bar->SetBarColor(ui_color(B_FAILURE_COLOR)); bar->UnlockLooper(); } static struct gui_download_window *gui_download_window_create(download_context *ctx, struct gui_window *parent) { struct gui_download_window *download = (struct gui_download_window*)malloc(sizeof *download); if (download == NULL) return NULL; download->storageLock = new BLocker("storage_lock"); download->storage = new BMallocIO(); download->ctx = ctx; download->window = new NSDownloadWindow(ctx); // Also ask the user where to save the file BMessage* msg = new BMessage(B_SAVE_REQUESTED); BFilePanel* panel = new BFilePanel(B_SAVE_PANEL, new BMessenger(download->window), NULL, 0, false); panel->SetSaveText(download_context_get_filename(ctx)); msg->AddPointer("source", panel); msg->AddPointer("dw", download); panel->SetMessage(msg); panel->Show(); return download; } static nserror gui_download_window_data(struct gui_download_window *dw, const char *data, unsigned int size) { dw->window->Progress(size); dw->storageLock->Lock(); dw->storage->Write(data, size); dw->storageLock->Unlock(); return NSERROR_OK; } static void gui_download_window_error(struct gui_download_window *dw, const char *error_msg) { dw->window->Failure(error_msg); delete dw->storageLock; delete dw->storage; } static void gui_download_window_done(struct gui_download_window *dw) { dw->window->Success(); dw->storageLock->Lock(); // Only delete if the storage is already a file. Else, we must wait for the // user to select something in the BFilePanel! BFile* file = dynamic_cast(dw->storage); delete file; if (file) delete dw->storageLock; else dw->storageLock->Unlock(); } static struct gui_download_table download_table = { gui_download_window_create, gui_download_window_data, gui_download_window_error, gui_download_window_done, }; struct gui_download_table *beos_download_table = &download_table;