mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
- Beggining of dnd support
- Click on selected item to rename - Fix problems reported by Valgrind
This commit is contained in:
parent
67cc5824ec
commit
87ef0c5509
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);*/
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user