mtpview/MainWindow.cpp
Anton Stankevich bb2022736b Fix unused var.
2024-10-26 18:23:46 +00:00

314 lines
10 KiB
C++

#include <libmtp.h>
#include "App.h"
#include "MainWindow.h"
#include <Button.h>
#include <ListItem.h>
#include <ScrollView.h>
#include <Path.h>
#include <Alert.h>
//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<BStringItem*>(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);
alert->Go();
//Quit(); //Leads to crash
}