mirror of
https://gitflic.ru/project/astankevich/mtpview.git
synced 2024-11-23 06:58:25 +01:00
314 lines
10 KiB
C++
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
|
|
}
|