- Beggining of dnd support

- Click on selected item to rename
- Fix problems reported by Valgrind
This commit is contained in:
Vedran Ljubovic 2007-07-27 08:36:05 +00:00
parent 67cc5824ec
commit 87ef0c5509
6 changed files with 286 additions and 131 deletions

View File

@ -118,6 +118,10 @@ void EDE_Browser::sort(int column, SortType type, bool reverse) {
int hlen=strlen(h); int hlen=strlen(h);
char colchar = Fl_Icon_Browser::column_char(); char colchar = Fl_Icon_Browser::column_char();
// FIXME sort() shouldn't call column_header() because that calls show_header() and that
// deletes all buttons from header (so they could be recreated). This cause valgrind errors
// since sort is called in button callback - you can't delete a widget in its own callback
// Remove old sort direction symbol (if any) from header // Remove old sort direction symbol (if any) from header
char *delim = 0; char *delim = 0;
int col=0; int col=0;
@ -125,7 +129,7 @@ void EDE_Browser::sort(int column, SortType type, bool reverse) {
bool found=false; bool found=false;
while (delim=strchr(h, colchar)) { while (delim=strchr(h, colchar)) {
if (col==sort_column) { if (col==sort_column) {
strncpy(delim-SYMLEN+1,delim,strlen(delim)+1); for (int i=0; i<=strlen(delim); i++) delim[i-SYMLEN+1]=delim[i];
found=true; found=true;
break; break;
} }
@ -211,8 +215,6 @@ EDE_Browser::EDE_Browser(int X,int Y,int W,int H,const char *L) : Fl_Icon_Browse
totalwidth_(0), column_header_(0), sort_column(0), sort_type(NO_SORT), sort_direction(false) { totalwidth_(0), column_header_(0), sort_column(0), sort_type(NO_SORT), sort_direction(false) {
fprintf (stderr, "ctor(%d,%d,%d,%d)\n",X,Y,W,H);
heading = new Heading(X,Y,W,buttonheight); heading = new Heading(X,Y,W,buttonheight);
heading->end(); heading->end();
heading->hide(); heading->hide();
@ -236,10 +238,20 @@ fprintf (stderr, "ctor(%d,%d,%d,%d)\n",X,Y,W,H);
} }
// Deallocate all memory used by header labels
void EDE_Browser::cleanup_header() {
// Deallocate old button labels
for (int i=0; i<heading->children(); i++) {
char *l = (char*)heading->child(i)->label();
if (l && l[0]!='\0') free(l);
}
heading->clear();
}
//make buttons invisible //make buttons invisible
void EDE_Browser::hide_header() { void EDE_Browser::hide_header() {
if (heading->visible()) resize(x(),y()-buttonheight,w(),h()+buttonheight); if (heading->visible()) resize(x(),y()-buttonheight,w(),h()+buttonheight);
heading->clear(); cleanup_header();
heading->hide(); heading->hide();
} }
@ -248,7 +260,7 @@ void EDE_Browser::show_header() {
int button_x=0; int button_x=0;
char *hdr = column_header_; char *hdr = column_header_;
const int* l = Fl_Icon_Browser::column_widths(); const int* l = Fl_Icon_Browser::column_widths();
heading->clear(); cleanup_header();
for (int i=0; i==0||l[i-1]; i++) { for (int i=0; i==0||l[i-1]; i++) {
// If the button is last, calculate size // If the button is last, calculate size
int button_w = l[i]; int button_w = l[i];
@ -278,7 +290,6 @@ void EDE_Browser::show_header() {
hdr=delim+1; // next field hdr=delim+1; // next field
} }
} }
fprintf (stderr, "showheader calls resize(%d,%d,%d,%d)\n",x(),y(),w(),h());
if (!heading->visible()) resize(x(),y()+buttonheight,w(),h()-buttonheight); if (!heading->visible()) resize(x(),y()+buttonheight,w(),h()-buttonheight);
heading->resizable(0); // We will resize the heading and individual buttons manually heading->resizable(0); // We will resize the heading and individual buttons manually
heading->show(); heading->show();
@ -293,17 +304,19 @@ void EDE_Browser::column_widths(const int* l) {
// if (total>=scroll->w()) { // if (total>=scroll->w()) {
// Fl_Icon_Browser::size(total,h()); // Fl_Icon_Browser::size(total,h());
// } // }
fprintf(stderr, "Total width is: %d\n", totalwidth_);
// If there was heading before, regenerate // If there was heading before, regenerate
if (heading->visible()) if (heading->visible())
heading->size(totalwidth_,buttonheight); heading->size(totalwidth_,buttonheight);
// show_header(); // show_header();
// Second array for the Fl_Browser // Second array for the Fl_Browser
int *tmp = new int[i]; // FIXME: Someone should cleanup this memory sometimes... static int *tmp = 0;
if (tmp) delete[] tmp;
tmp=new int[i]; // FIXME: Dtor should cleanup this memory
for (int j=0; j<i-1; j++) tmp[j]=l[j]; for (int j=0; j<i-1; j++) tmp[j]=l[j];
tmp[i-1]=0; tmp[i-1]=0;
Fl_Icon_Browser::column_widths(tmp); Fl_Icon_Browser::column_widths(tmp);
// delete[] tmp; -- can't do this, browser goes berserk
// Redraw parent so we don't get ugly artifacts after shrinking last button // Redraw parent so we don't get ugly artifacts after shrinking last button
// Doesn't work anymore! // Doesn't work anymore!
@ -315,7 +328,9 @@ const int* EDE_Browser::column_widths() const {
const int *l=Fl_Icon_Browser::column_widths(); const int *l=Fl_Icon_Browser::column_widths();
for (i=0; l[i]; i++) total+=l[i]; for (i=0; l[i]; i++) total+=l[i];
int *tmp = new int[i+2]; // FIXME: Someone should cleanup this memory sometimes... static int *tmp = 0;
if (tmp) delete[] tmp;
tmp=new int[i+2]; // FIXME: Someone should cleanup this memory sometimes...
for (int j=0; l[j]; j++) tmp[j]=l[j]; for (int j=0; l[j]; j++) tmp[j]=l[j];
tmp[i]=(totalwidth_-total); tmp[i]=(totalwidth_-total);
@ -521,7 +536,7 @@ int EDE_Browser::Heading::handle(int event) {
EDE_Browser*b = (EDE_Browser*)parent(); EDE_Browser*b = (EDE_Browser*)parent();
b->column_widths(columns); b->column_widths(columns);
b->redraw(); // OPTIMIZE (some smart damage in column_widths() ?) b->redraw(); // OPTIMIZE (some smart damage in column_widths() ?)
free(columns); delete[] columns;
// There will be many RELEASE events, so we update sx (used when calculating dx) // There will be many RELEASE events, so we update sx (used when calculating dx)
sx=Fl::event_x(); sx=Fl::event_x();

View File

@ -81,6 +81,7 @@ private:
SortType sort_type; SortType sort_type;
bool sort_direction; bool sort_direction;
void cleanup_header();
void hide_header(); void hide_header();
void show_header(); void show_header();
@ -92,6 +93,7 @@ public:
~EDE_Browser() { ~EDE_Browser() {
delete[] column_sort_types_; delete[] column_sort_types_;
cleanup_header();
delete heading; delete heading;
// delete scroll; // delete scroll;
delete hscrollbar; delete hscrollbar;

View File

@ -40,86 +40,10 @@ struct FileItem {
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
/*// Event handler for EditBox
int EditBox::handle(int event) {
if (!this->visible()) return parent()->handle(event);
bool above=false;
//fprintf(stderr,"Editbox event: %d (%s)\n",event,event_name(event));
// Change filename
if (event==KEY && (event_key()==ReturnKey || event_key()==KeypadEnter)) {
// split old filename to path and file
char path[PATH_MAX], file[PATH_MAX];
strcpy(path, (char*)editing_->user_data());
if (path[strlen(path)-1] == '/') path[strlen(path)-1]='\0';
char *p = strrchr(path,'/');
if (p==0 || *p=='\0') {
strcpy(file,path);
path[0]='\0';
} else { // usual case
p++;
strcpy(file,p);
*p='\0';
}
if (strlen(file)!=strlen(text()) || strcmp(file,text())!=0) {
// Create new filename
strncat(path, text(), PATH_MAX-strlen(path));
char oldname[PATH_MAX];
strcpy(oldname, (char*)editing_->user_data());
if (rename(oldname, path) == -1) {
alert(tsprintf(_("Could not rename file! Error was:\n\t%s"), strerror(errno)));
} else {
// Update browser
free(editing_->user_data());
editing_->user_data(strdup(path));
const char* l = editing_->label();
editing_->label(tasprintf("%s%s",text(),strchr(l, '\t')));
}
}
above=true;
}
// Hide editbox
if (above || ( event==KEY && event_key()==EscapeKey ) ) {
this->hide();
return 1;
}
Input::handle(event);
}
// We override hide method to ensure certain things done
void EditBox::hide() {
Input::hide();
// Remove box so it doesn't get in the way
this->x(0);
this->y(0);
this->w(0);
this->h(0);
// Return the browser item into "visible" state
if (editing_) {
editing_->textcolor(textcolor());
editing_->redraw();
parent()->take_focus();
}
}
*/
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
// Type for rename_callback // Type for rename_callback
// I don't know how to do this without creating a new type :( // I don't know how to do this without creating a new type :(
typedef void (my_callback)(const char*); typedef void (rename_callback_type)(const char*);
typedef void (paste_callback_type)(const char*,const char*);
@ -164,17 +88,20 @@ private:
return 1; // don't send keys to view return 1; // don't send keys to view
} }
if (e==FL_MOUSEWHEEL && visible()) view->hide_editbox();
return Fl_Input::handle(e); return Fl_Input::handle(e);
} }
}* editbox_; }* editbox_;
int editbox_row; int editbox_row;
my_callback* rename_callback_; rename_callback_type* rename_callback_;
paste_callback_type* dnd_callback_;
// show editbox at specified row and make the row "invisible" (bgcolor same as fgcolor) // show editbox at specified row and make the row "invisible" (bgcolor same as fgcolor)
void show_editbox(int row) { void show_editbox(int row) {
if (!rename_callback_) return;
if (row<1 || row>size()) return; // nothing selected if (row<1 || row>size()) return; // nothing selected
if (strcmp(text(row), "..")==0) return; // can't rename "go up" button if (text(row)[0]=='.' && text(row)[1]=='.' && text(row)[2]==column_char()) return; // can't rename "go up" button
// unselect the row with focus - it's prettier that way // unselect the row with focus - it's prettier that way
select(row,0); select(row,0);
@ -229,7 +156,37 @@ private:
//hide_editbox(); //hide_editbox();
} }
// Bucket class is used to prevent memleaks
// It stores pointers to allocated memory that will be cleaned up later
// Just remember to call empty() when needed - everything else is automatic :)
class Bucket {
void** items;
int size, capacity;
public:
Bucket() : size(0), capacity(1000), items((void**)malloc(sizeof(void*)*1000)) {
for (int i=0; i<capacity; i++) items[i]=0;
}
~Bucket() { empty(); free(items); }
void add(void* p) {
if (size>=capacity) {
capacity+=1000;
items = (void**)realloc(items,sizeof(void*)*capacity);
for (int i=capacity-1000; i<capacity; i++)
items[i]=0;
}
items[size++]=p;
}
void empty() {
for (int i=0; i<size; i++) {
if (items[i]) free(items[i]);
items[i]=0;
}
size=0;
}
void debug() {
fprintf(stderr, "Bucket size %d, capacity %d\n", size, capacity);
}
} bucket;
public: public:
FileDetailsView(int X, int Y, int W, int H, char*label=0) : EDE_Browser(X,Y,W,H,label) { FileDetailsView(int X, int Y, int W, int H, char*label=0) : EDE_Browser(X,Y,W,H,label) {
@ -255,6 +212,9 @@ public:
editbox_->parent(this); editbox_->parent(this);
editbox_->textsize(12); // FIXME: hack for font size editbox_->textsize(12); // FIXME: hack for font size
editbox_->hide(); editbox_->hide();
rename_callback_ = 0;
dnd_callback_ = 0;
} }
// ~FileDetailsView() { delete browser; } // ~FileDetailsView() { delete browser; }
@ -262,7 +222,9 @@ public:
// Construct browser line // Construct browser line
edelib::String value; edelib::String value;
value = item->name+"\t"+item->description+"\t"+item->size+"\t"+item->date+"\t"+item->permissions; value = item->name+"\t"+item->description+"\t"+item->size+"\t"+item->date+"\t"+item->permissions;
EDE_Browser::insert(row, value.c_str(), strdup(item->realpath.c_str())); // put realpath into data char* realpath = strdup(item->realpath.c_str());
EDE_Browser::insert(row, value.c_str(), realpath); // put realpath into data
bucket.add(realpath);
fprintf (stderr, "value: %s\n", value.c_str()); fprintf (stderr, "value: %s\n", value.c_str());
// Get icon // Get icon
@ -278,24 +240,42 @@ fprintf (stderr, "value: %s\n", value.c_str());
int row = findrow(item->realpath); int row = findrow(item->realpath);
if (row) EDE_Browser::remove(row); if (row) EDE_Browser::remove(row);
} }
void remove(int row) { EDE_Browser::remove(row); } // why???
void update(FileItem *item) { void update(FileItem *item) {
int row=findrow(item->realpath); int row=findrow(item->realpath);
if (row==0) return; if (row==0) return;
EDE_Browser::remove(row);
insert(row, item); //EDE_Browser::remove(row);
// FIXME: this will lose focus, making it impossible to click on something while //insert(row, item);
// this was reimplemented because a) it's unoptimized, b) adds stuff at the end,
// c) causes browser to lose focus, making it impossible to click on something while
// directory is loading // directory is loading
edelib::String value;
value = item->name+"\t"+item->description+"\t"+item->size+"\t"+item->date+"\t"+item->permissions;
char* realpath = strdup(item->realpath.c_str());
text(row, value.c_str());
data(row, realpath);
bucket.add(realpath);
fprintf (stderr, "value: %s\n", value.c_str());
// Get icon
edelib::String icon = edelib::IconTheme::get(item->icon.c_str(),edelib::ICON_SIZE_TINY);
if (icon=="") icon = edelib::IconTheme::get("misc",edelib::ICON_SIZE_TINY,edelib::ICON_CONTEXT_MIMETYPE);
set_icon(row, Fl_Shared_Image::get(icon.c_str()));
} }
// Change color of row to gray // Change color of row to gray
void gray(int row) { void gray(int row) {
if (text(row)[0] == '@' && text(row)[1] == 'C') return; // already greyed if (text(row)[0] == '@' && text(row)[1] == 'C') return; // already greyed
char *ntext = (char*)malloc(sizeof(char)*strlen(text(row))+4); // add 4 places for format chars char *ntext = (char*)malloc(sizeof(char)*strlen(text(row))+5); // add 4 places for format chars
strncpy(ntext+4, text(row), strlen(text(row))); strncpy(ntext+4, text(row), strlen(text(row)));
ntext[0]='@'; ntext[1]='C'; ntext[2]='2'; ntext[3]='5'; ntext[0]='@'; ntext[1]='C'; ntext[2]='2'; ntext[3]='5'; // @C25 - nice shade of gray
ntext[strlen(text(row))+4]='\0'; // in case text(row) was broken
text(row,ntext); text(row,ntext);
free(ntext); bucket.add(ntext);
// grey icon - but how to ungray? // grey icon - but how to ungray?
Fl_Image* im = get_icon(row)->copy(); Fl_Image* im = get_icon(row)->copy();
@ -310,7 +290,7 @@ fprintf (stderr, "value: %s\n", value.c_str());
char *ntext = (char*)malloc(sizeof(char)*strlen(text(row))-4); // 4 places for format chars char *ntext = (char*)malloc(sizeof(char)*strlen(text(row))-4); // 4 places for format chars
strncpy(ntext, text(row)+4, strlen(text(row))-4); strncpy(ntext, text(row)+4, strlen(text(row))-4);
text(row,ntext); text(row,ntext);
free(ntext); bucket.add(ntext);
// don't work // don't work
//Fl_Image* im = get_icon(row); //Fl_Image* im = get_icon(row);
@ -319,8 +299,8 @@ fprintf (stderr, "value: %s\n", value.c_str());
//redraw(); // OPTIMIZE //redraw(); // OPTIMIZE
} }
// Renaming support
int handle(int e) { int handle(int e) {
// Rename support
if (e==FL_KEYBOARD) { if (e==FL_KEYBOARD) {
if (Fl::event_key()==FL_F+2) { if (Fl::event_key()==FL_F+2) {
if (editbox_->visible()) if (editbox_->visible())
@ -330,12 +310,101 @@ fprintf (stderr, "value: %s\n", value.c_str());
} }
} }
if (e==FL_PUSH && editbox_->visible() && !Fl::event_inside(editbox_)) if (e==FL_PUSH && editbox_->visible() && !Fl::event_inside(editbox_))
hide_editbox(); // hide editbox when click outside it hide_editbox(); // hide editbox when user clicks outside of it
if (e==FL_MOUSEWHEEL && editbox_->visible())
hide_editbox(); // hide editbox when scrolling mouse
// Click once on item that is already selected AND focused to rename it
static bool renaming=false;
if (e==FL_PUSH) renaming=false;
if (e==FL_PUSH && !editbox_->visible() && Fl::event_clicks()==0 && Fl::event_button()==1) {
const int* l = column_widths();
if (Fl::event_x()<x() || Fl::event_x()>x()+l[0])
return Fl_Icon_Browser::handle(e); // we're only interested in first column
void* item = item_first();
int focusy=y()-position();
for (int i=1; i<get_focus(); i++) {
focusy+=item_height(item);
if (focusy>Fl::event_y()) break;
item=item_next(item);
}
if (Fl::event_y()<focusy || Fl::event_y()>focusy+item_height(item))
return Fl_Icon_Browser::handle(e); // Click outside selected item
if (selected(get_focus())!=1)
return Fl_Icon_Browser::handle(e); // allow to select item if it's just focused
renaming=true;
}
if (e==FL_RELEASE && renaming && Fl::event_clicks()==0) {
show_editbox(get_focus());
renaming=false;
return 1; // don't pass mouse event, otherwise item will become selected again
}
// Drag&drop support
static int paste_event_y;
/*--- This is to get dnd events from non-fltk apps ---
static bool dragging=false;
if (e==FL_PUSH) dragging=false;
if (e==FL_DND_ENTER) dragging=true;
if (e==FL_RELEASE && dragging) {
paste_event_y=Fl::event_y();
Fl::paste(*this,0);
dragging=false;
}
/*--- End ugly hack ---*/
// Don't unselect on FL_PUSH cause that could be dragging
if (e==FL_PUSH && Fl::event_clicks()!=1) return 1;
if (e==FL_DRAG) {
edelib::String selected_items;
for (int i=1; i<=size(); i++)
if (selected(i)==1) {
if (selected_items != "") selected_items += ",";
selected_items += (char*)data(i);
}
Fl::copy(selected_items.c_str(),selected_items.length(),0);
Fl::dnd();
return 1; // don't do the multiple selection thing from Fl_Browser
}
if (e==FL_DND_RELEASE) {
paste_event_y=Fl::event_y();
Fl::paste(*this,0);
}
if (e==FL_PASTE) {
if (!Fl::event_text() || !Fl::event_length()) return 1;
// Where is the user dropping?
void* item = item_first();
int itemy=y()-position();
int i;
for (i=1; i<=size(); i++) {
itemy+=item_height(item);
if (itemy>paste_event_y) break;
}
dnd_callback_(Fl::event_text(),(const char*)data(i));
}
// if (e==FL_DND_ENTER) { take_focus(); Fl::focus(this); Fl::belowmouse(this); Fl_Icon_Browser::handle(FL_FOCUS); }
// if (e==FL_DND_LEAVE) { take_focus(); Fl::focus(this); Fl::belowmouse(this); Fl_Icon_Browser::handle(FL_FOCUS); }
//fprintf (stderr, "Event: %d\n", e);
return Fl_Icon_Browser::handle(e); return Fl_Icon_Browser::handle(e);
} }
// Setup callback that will be used when renaming // Setup callback that will be used when renaming and dnd
void rename_callback(my_callback* cb) { rename_callback_ = cb; } void rename_callback(rename_callback_type* cb) { rename_callback_ = cb; }
void dnd_callback(paste_callback_type* cb) { dnd_callback_ = cb; }
// Avoid memory leak
void clear() {
fprintf(stderr, "Call FileView::clear()\n");
bucket.empty();
EDE_Browser::clear();
}
}; };

View File

@ -157,6 +157,7 @@ char *simpleopener(const char* mimetype) {
if (buf[0]=='\0' || buf[1]=='\0' || buf[0]=='#') continue; if (buf[0]=='\0' || buf[1]=='\0' || buf[0]=='#') continue;
buf[strlen(buf)-1]='\0'; buf[strlen(buf)-1]='\0';
char *tmp = strstr(buf, "||"); char *tmp = strstr(buf, "||");
if (!tmp) continue; // malformatted opener
*tmp = '\0'; *tmp = '\0';
sopeners* q = new sopeners; sopeners* q = new sopeners;
q->type=strdup(buf); q->type=strdup(buf);
@ -215,7 +216,7 @@ void loaddir(const char *path) {
if (path[0] == '~') // Expand tilde if (path[0] == '~') // Expand tilde
snprintf(current_dir,PATH_MAX,"%s/%s",getenv("HOME"),path+1); snprintf(current_dir,PATH_MAX,"%s/%s",getenv("HOME"),path+1);
else else
strcpy(current_dir,path); if (path!=current_dir) strcpy(current_dir,path);
} else } else
strcpy(current_dir,getenv("HOME")); strcpy(current_dir,getenv("HOME"));
@ -255,7 +256,9 @@ fprintf (stderr, "loaddir(%s) = (%s)\n",path,current_dir);
} }
// set window label // set window label
win->label(tasprintf(_("%s - File manager"), current_dir)); // unlike fltk2, labels can be pointers to static char
win->label(tsprintf(_("%s - File manager"), current_dir));
statusbar->label(tsprintf(_("Scanning directory %s..."), current_dir));
view->clear(); view->clear();
@ -264,6 +267,7 @@ fprintf (stderr, "loaddir(%s) = (%s)\n",path,current_dir);
for (int i=0; i<size; i++) { for (int i=0; i<size; i++) {
char *n = files[i]->d_name; //shortcut char *n = files[i]->d_name; //shortcut
if (i>0) free(files[i-1]); // see scandir(3)
// don't show . (current directory) // don't show . (current directory)
if (strcmp(n,".")==0) continue; if (strcmp(n,".")==0) continue;
@ -301,6 +305,7 @@ fprintf (stderr, "loaddir(%s) = (%s)\n",path,current_dir);
item_list[fsize++] = item; item_list[fsize++] = item;
} }
free(files[size-1]); free(files); // see scandir(3)
// Populate view // Populate view
@ -355,7 +360,7 @@ fprintf (stderr, "ICON: %s !!!!!\n", icon.c_str());
// f_bfree is size available to root // f_bfree is size available to root
double percent = double(statfs_buffer.f_blocks-statfs_buffer.f_bavail)/statfs_buffer.f_blocks*100; double percent = double(statfs_buffer.f_blocks-statfs_buffer.f_bavail)/statfs_buffer.f_blocks*100;
char *tmp = strdup(nice_size(totalsize)); // nice_size() operates on a static char buffer, we can't use two calls at the same time char *tmp = strdup(nice_size(totalsize)); // nice_size() operates on a static char buffer, we can't use two calls at the same time
statusbar->label(tasprintf(_("Filesystem %s, Size %s, Free %s (%4.1f%% used)"), find_fs_for(current_dir), tmp, nice_size(freesize), percent)); statusbar->label(tsprintf(_("Filesystem %s, Size %s, Free %s (%4.1f%% used)"), find_fs_for(current_dir), tmp, nice_size(freesize), percent));
free(tmp); free(tmp);
} else } else
statusbar->label(_("Error reading filesystem information!")); statusbar->label(_("Error reading filesystem information!"));
@ -363,11 +368,6 @@ fprintf (stderr, "ICON: %s !!!!!\n", icon.c_str());
/*-----------------------------------------------------------------
File moving and copying operations
-------------------------------------------------------------------*/
/*----------------------------------------------------------------- /*-----------------------------------------------------------------
Main menu callbacks Main menu callbacks
-------------------------------------------------------------------*/ -------------------------------------------------------------------*/
@ -386,9 +386,6 @@ fprintf (stderr,"enter\n");
tm=newtm; tm=newtm;
if (view->value()==0) return; // This can happen while efiler is loading if (view->value()==0) return; // This can happen while efiler is loading
char* filename = strdup(view->text(view->value()));
if (char*k = strchr(filename, view->column_char())) *k='\0';
char* path = (char*)view->data(view->value()); char* path = (char*)view->data(view->value());
fprintf(stderr, "Path: %s (ev %d)\n",path,Fl::event()); fprintf(stderr, "Path: %s (ev %d)\n",path,Fl::event());
@ -411,15 +408,21 @@ fprintf (stderr,"enter\n");
const char *o2 = tsprintf(opener,path); const char *o2 = tsprintf(opener,path);
fprintf (stderr, "run_program: %s\n", o2); fprintf (stderr, "run_program: %s\n", o2);
// construct filename for the message
char* filename = strdup(view->text(view->value()));
if (char*k = strchr(filename, view->column_char())) *k='\0';
if (opener) { if (opener) {
int k=edelib::run_program(o2,false); fprintf(stderr, "retval: %d\n", k); int k=edelib::run_program(o2,false); fprintf(stderr, "retval: %d\n", k);
} else } else
statusbar->label(tasprintf(_("No program to open %s!"), filename)); statusbar->label(tsprintf(_("No program to open %s!"), filename));
free(filename); free(filename);
rlim->rlim_cur = old_rlimit; rlim->rlim_cur = old_rlimit;
setrlimit (RLIMIT_CORE, rlim); setrlimit (RLIMIT_CORE, rlim);
free(rlim);
} }
} // open_cb } // open_cb
@ -525,6 +528,7 @@ edelib::IconTheme::init("crystalsvg");
view->callback(open_cb); view->callback(open_cb);
// callback for renaming // callback for renaming
view->rename_callback(do_rename); view->rename_callback(do_rename);
view->dnd_callback(dnd_cb);
Fl_Group *sbgroup = new Fl_Group(0, default_window_height-statusbar_height, default_window_width, statusbar_height); Fl_Group *sbgroup = new Fl_Group(0, default_window_height-statusbar_height, default_window_width, statusbar_height);
statusbar = new Fl_Box(2, default_window_height-statusbar_height+2, statusbar_width, statusbar_height-4); statusbar = new Fl_Box(2, default_window_height-statusbar_height+2, statusbar_width, statusbar_height-4);

View File

@ -88,9 +88,9 @@ void do_cut_copy(bool m_copy) {
// Update statusbar // Update statusbar
if (m_copy) if (m_copy)
statusbar->label(tasprintf(_("Selected %d items for copying"), nselected)); statusbar->label(tsprintf(_("Selected %d items for copying"), nselected));
else else
statusbar->label(tasprintf(_("Selected %d items for moving"), nselected)); statusbar->label(tsprintf(_("Selected %d items for moving"), nselected));
} }
@ -149,19 +149,20 @@ bool my_copy(const char* src, const char* dest) {
if (q == 0) return true; else return false; if (q == 0) return true; else return false;
} }
if ( !edelib::file_writeable(dest) ) // edelib::file_writeable() returns false if dest doesn't exist
/* if ( !edelib::file_writeable(dest) )
{ {
// here was choice_alert // here was choice_alert
int q = fl_choice(tsprintf(_("Cannot create file %s"),dest), _("&Stop"), _("&Continue"), 0); int q = fl_choice(tsprintf(_("Cannot create file %s"),dest), _("&Stop"), _("&Continue"), 0);
if (q == 0) return true; else return false; if (q == 0) return true; else return false;
} }*/
// we will try to preserve permissions etc. cause that's usually what people want // we will try to preserve permissions etc. cause that's usually what people want
if (!edelib::file_copy(src,dest,true)) if (!edelib::file_copy(src,dest,true))
fl_alert(tsprintf(_("Error copying %s to %s"),src,dest)); fl_alert(tsprintf(_("Error copying %s to %s"),src,dest));
fclose(fold); // fclose(fold);
fclose(fnew); // fclose(fnew);
return true; return true;
} }
@ -239,6 +240,7 @@ void do_paste() {
} }
rename(cut_copy_buffer[i],newname); rename(cut_copy_buffer[i],newname);
free(cut_copy_buffer[i]); free(cut_copy_buffer[i]);
free(newname);
} }
free(cut_copy_buffer); free(cut_copy_buffer);
cut_copy_buffer=0; cut_copy_buffer=0;
@ -263,6 +265,7 @@ void do_paste() {
if (strcmp(srcdir,current_dir)==0) { if (strcmp(srcdir,current_dir)==0) {
fl_alert(_("You cannot copy a file onto itself!")); fl_alert(_("You cannot copy a file onto itself!"));
free(srcdir);
return; return;
} }
@ -333,13 +336,22 @@ void do_paste() {
} }
progress_window->hide(); progress_window->hide();
// Deallocate files_list[][]
for (int i=0; i<list_size; i++)
free(files_list[i]);
free(files_list);
// Reload current dir // Reload current dir
loaddir(current_dir); loaddir(current_dir);
// select the just pasted files and cleanup memory
for (int i=0; i<list_size; i++) {
char* tmp = strrchr(files_list[i],'/')+1;
// if (!tmp) { fprintf (stderr, "not found\n"); continue; }
// tmp++;
for (int j=1; j<=view->size(); j++)
if (strncmp(tmp, view->text(j), strlen(tmp))==0)
view->select(j,1);
free(files_list[i]);
}
free(files_list);
free(srcdir);
} }
} }
@ -350,11 +362,9 @@ void do_delete() {
int list_size = 0, list_capacity = 1000; int list_size = 0, list_capacity = 1000;
char** files_list = (char**)malloc(sizeof(char**)*list_capacity); char** files_list = (char**)malloc(sizeof(char**)*list_capacity);
for (int i=1; i<=view->size(); i++) { for (int i=1; i<=view->size(); i++)
if (view->selected(i)==1) { if (view->selected(i)==1)
expand_dirs((char*)view->data(i), files_list, list_size, list_capacity); expand_dirs((char*)view->data(i), files_list, list_size, list_capacity);
}
}
if (list_size==0) { //nothing selected, use the focused item if (list_size==0) { //nothing selected, use the focused item
int i=view->get_focus(); int i=view->get_focus();
@ -374,7 +384,10 @@ void do_delete() {
// delete // delete
for (int i=0; i<list_size; i++) for (int i=0; i<list_size; i++)
edelib::file_remove(files_list[i]); edelib::file_remove(files_list[i]);
loaddir(current_dir); // loaddir(current_dir); - optimized
for (int i=1; i<=view->size(); i++)
if (view->selected(i)==1)
view->remove(i);
} }
@ -405,3 +418,52 @@ void do_rename(const char* c) {
} }
} }
// Drag & drop callback - mostly copied from do_cut_copy()
void dnd_cb(const char* from,const char* to) {
fprintf (stderr, "PASTE from '%s', to '%s'\n",from,to);
return;
char *t = (char*)to;
if (!fl_filename_isdir(to))
t=current_dir;
/*
// Clear cut/copy buffer and optionally ungray the previously cutted icons
if (cut_copy_buffer) {
for (int i=0; cut_copy_buffer[i]; i++)
free(cut_copy_buffer[i]);
free(cut_copy_buffer);
if (!operation_is_copy) {
for (int i=1; i<=num; i++)
view->ungray(i);
}
}
// Allocate buffer
cut_copy_buffer = (char**)malloc(sizeof(char*) * (nselected+2));
// Add selected files to buffer
int buf=0;
for (int i=1; i<=num; i++)
if (view->selected(i)==1)
cut_copy_buffer[buf++] = strdup((char*)view->data(i));
// We don't know yet if this is cut or copy, so no need to gray anything
//
// Clear cut/copy buffer and optionally ungray the previously cutted icons
if (cut_copy_buffer) {
for (int i=0; cut_copy_buffer[i]; i++)
free(cut_copy_buffer[i]);
free(cut_copy_buffer);
if (!operation_is_copy) {
for (int i=1; i<=num; i++)
view->ungray(i);
}
}
int c = fl_choice(tsprintf(_("Do you want to copy or move file %s to directory %s?"), k+1), _("Do&n't delete"), _("&Delete"), 0);*/
}

View File

@ -20,6 +20,9 @@ void do_delete();
// Rename the file with focus to given name // Rename the file with focus to given name
void do_rename(const char*); void do_rename(const char*);
// Callback for drag&drop operations
void dnd_cb(const char*from,const char*to);
extern FileDetailsView* view; extern FileDetailsView* view;
extern Fl_Box* statusbar; extern Fl_Box* statusbar;