#include #include "App.h" #include "MainWindow.h" #include #include #include #include #include //extern LIBMTP_mtpdevice_t * detected_device; //extern App *app; //extern LIBMTP_mtpdevice_t *detected_device=0; extern MainWindow *mainwin; extern bool finish_read_device; int sendfile_function(char * from_path, int32_t parent_id, int32_t & ret_newFileID); int progress (uint64_t const sent, uint64_t const total, void const * const data); void file_list(LIBMTP_mtpdevice_t *device, LIBMTP_devicestorage_t *storage, uint32_t leaf, int depth, BListItem * parentItem = NULL); enum { M_DOWNLOAD_FILE = 'dlfl', M_UPLOAD_FILE = 'upfl', M_SET_TITLE = 'sttl' }; FileItem::FileItem(LIBMTP_mtpdevice_t * device, LIBMTP_devicestorage_t *storage, int id, BString filename, bool isFile, int depth) :BStringItem(filename, depth, false) { this->fDevice=device; this->fStorage = storage; this->fId=id; this->fIsFile=isFile; } inline BListItem * add_sub_files_under (BListItem * item, void* arg) { FileItem * fileItem =((FileItem * ) item ); if (fileItem->isFolder()) { fprintf(stdout, "Getting sub files for %d\n", fileItem->fileId()); file_list(fileItem->device(), fileItem->storage(), fileItem->fileId(), fileItem->OutlineLevel() +1, fileItem); } return item; } void FileItem::SetExpanded(bool expanded) { BStringItem::SetExpanded(expanded); if (expanded) { //This code newer called //fprintf(stdout, "Expanded!!!\n"); //mainwin->listView()->EachItemUnder(this, true, &add_sub_files_under, NULL); } } MainWindow::MainWindow(void) : BWindow(BRect(100,100,500,400),"MTP view",B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE) { // Here we will make a BView that covers the white area so that we can set the // "background color" BRect r(Bounds()); BView *top = new BView(r,"topview",B_FOLLOW_ALL,B_WILL_DRAW); AddChild(top); // ui_color() returns a system color, such as the window tab color, menu text color, // and so forth. top->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); // Create a button and place it at the bottom right corner of the window. The empty BRect // that we use for the BButton's frame is because we're going to have it resize itself and // then move it to the corner based on the actual size of the button download = new BButton(BRect(),"downloadbutton","Download", new BMessage(M_DOWNLOAD_FILE), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); download->SetEnabled(false); top->AddChild(download); download->ResizeToPreferred(); upload = new BButton(BRect(),"uploadbutton","Upload", new BMessage(M_UPLOAD_FILE), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); top->AddChild(upload); upload->ResizeToPreferred(); // Bottom right corner of the window with 10 pixels of padding between the button and the // window edge. 10 pixels is kind of a de facto standard for control padding. download->MoveTo(Bounds().right - download->Bounds().Width() - 10.0, Bounds().bottom - download->Bounds().Height() - 10.0); upload->MoveTo(Bounds().right - download->Bounds().Width()-upload->Bounds().Width() - 20.0, Bounds().bottom - upload->Bounds().Height() - 10.0); r = Bounds(); r.InsetBy(10.0,10.0); // When working with BScrollViews, you must compensate for the width/height of the scrollbars. // B_V_SCROLL_BAR_WIDTH is a defined constant for the width of the vertical scroll bar. r.right -= B_V_SCROLL_BAR_WIDTH; // Frame() works like Bounds() except that it returns the size and location of the control // in the coordinate space of the parent view. This will make fListView's bottom stop 10 // pixels above the button. r.bottom = download->Frame().top - 10.0 - B_H_SCROLL_BAR_HEIGHT; // Most of these parameters are exactly the same as for BView except that we can also // specify whether the user is able to select just 1 item in the list or multiple items by // clicking on items while holding a modifier key on the keyboard. fListView = new BOutlineListView(r,"sportlist",B_SINGLE_SELECTION_LIST,B_FOLLOW_ALL); // We didn't call AddChild on fListView because our BScrollView will do that for us. When // created, it creates scrollbars and targets the specified view for any scrolling they do. // When the BScrollView is attached to the window, it calls AddChild on fListView for us. // If we call AddChild on fListView before we create this scrollview, our program will drop // to the debugger when we call AddChild on the BScrollView -- a BView can have only one parent. BScrollView *scrollView = new BScrollView("scrollview",fListView, B_FOLLOW_ALL, 0,true,true); top->AddChild(scrollView); // A BListView's selection message is sent to the window any time that the list's selection // changes. fListView->SetSelectionMessage(new BMessage(M_SET_TITLE)); messenger = new BMessenger(this); openPanel = new BFilePanel(B_OPEN_PANEL, messenger, NULL, B_FILE_NODE, false); //savePanel = new BFilePanel(B_SAVE_PANEL, messenger, NULL, B_DIRECTORY_NODE, false); //B_DIRECTORY_NODE has no effect savePanel = new BFilePanel(B_SAVE_PANEL, messenger, NULL, B_FILE_NODE, false); uploadDownloadNotification = new BNotification (B_PROGRESS_NOTIFICATION); uploadDownloadNotification->SetGroup("mtpview"); selectedItem = NULL; //openPanel->SetTarget(messenger); //savePanel->SetTarget(messenger); printf("MainWindow created\n" ); } void MainWindow::MessageReceived(BMessage *msg) { switch (msg->what) { case M_DOWNLOAD_FILE: { int32 selection = fListView->CurrentSelection(); if (selection < 0) { break; } selectedItem = (FileItem*)fListView->ItemAt(selection); if (selectedItem) { printf("Show save dialog\n" ); savePanel->SetSaveText(selectedItem->Text()); savePanel->Show(); } break; } case M_UPLOAD_FILE: { int32 selection = fListView->CurrentSelection(); if (selection < 0) { break; } selectedItem = (FileItem*)fListView->ItemAt(selection); if (selectedItem) { printf("Show open dialog\n" ); openPanel->Show(); } break; } case M_SET_TITLE: { int32 selection = fListView->CurrentSelection(); if (selection < 0) { // This code is here because when we press the Reset button, the selection // changes and an M_SET_TITLE message is sent, but because nothing is // selected, CurrentSelection() returns -1. SetTitle("MTP view"); selectedItem = NULL; break; } //BStringItem *item = dynamic_cast(fListView->ItemAt(selection)); selectedItem = (FileItem*)fListView->ItemAt(selection); if (selectedItem) { SetTitle(selectedItem->Text()); download->SetEnabled((selectedItem->isFile()) && finish_read_device); upload->SetEnabled((!selectedItem->isFile()) && finish_read_device); } break; } case B_REFS_RECEIVED:{ printf(" User select Open\n" ); if (selectedItem) { entry_ref ref; if (msg->FindRef("refs", &ref) == B_OK) { BEntry entry; if (entry.SetTo(&ref) == B_OK) { BPath path; entry.GetPath(&path); char openFileName[B_FILE_NAME_LENGTH]; strcpy(openFileName, path.Path()); printf("Try to upload %s to dir %d %s\n", openFileName, selectedItem->fileId(), selectedItem->Text()); int newFileId=0; uploadDownloadNotification->SetTitle("Uploading"); uploadDownloadNotification->SetContent(openFileName); uploadDownloadNotification->SetMessageID("mainwindow_progress"); //uploadDownloadNotification->SetProgress(0.5); //uploadDownloadNotification->Send(); int send_res = sendfile_function(openFileName, selectedItem->fileId(), newFileId); if (send_res == 0) { FileItem * newFileItem = new FileItem(selectedItem->device(),selectedItem->storage(), newFileId, path.Leaf(), true, selectedItem->OutlineLevel() +1); listView()->AddUnder(newFileItem, selectedItem); printf("File added to listView\n" ); } else showErrorAlert("Cannot send file"); } } else printf(" No refs in message\n" ); } break; } case B_SAVE_REQUESTED: { printf(" User select Save\n" ); if (selectedItem) { entry_ref ref; if (msg->FindRef("directory", &ref) == B_OK) { BEntry entry; if (entry.SetTo(&ref) == B_OK) { BPath path; entry.GetPath(&path); char fullSaveFileName [B_FILE_NAME_LENGTH]; const char * shortSaveFileName = NULL;// [B_FILE_NAME_LENGTH]; strcpy (fullSaveFileName, path.Path()); strcat(fullSaveFileName, "/"); if (msg->FindString("name", &shortSaveFileName) == B_OK) { strcat(fullSaveFileName, shortSaveFileName); } //strcat(fullSaveFileName, selectedItem->Text()); printf("Try to download %d %s to %s\n", selectedItem->fileId(), selectedItem->Text(), fullSaveFileName); uploadDownloadNotification->SetTitle("Downloading"); uploadDownloadNotification->SetContent(selectedItem->Text()); uploadDownloadNotification->SetMessageID("mainwindow_progress"); //uploadDownloadNotification->SetProgress(0.5); //uploadDownloadNotification->Send(); if (LIBMTP_Get_File_To_File(selectedItem->device(), selectedItem->fileId(), /*selectedItem->Text()*/ fullSaveFileName, progress, NULL) != 0 ){ printf("\nError getting file from MTP device.\n"); LIBMTP_Dump_Errorstack(selectedItem->device()); LIBMTP_Clear_Errorstack(selectedItem->device()); } else printf("OK\n"); } } } break; } case B_CANCEL: { printf(" User select Cancel\n" ); break; } default: { BWindow::MessageReceived(msg); break; } } } void MainWindow::showErrorAlert(const char * message) { BAlert* alert = new BAlert("MTP Error", message, "Ok", NULL, NULL, B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT); alert->SetShortcut(0, B_ESCAPE); int32 button_index = alert->Go(); //Quit(); //Leads to crash }