From b571876fe651cfb843b54bc259dc58d64de5de0c Mon Sep 17 00:00:00 2001 From: Sanel Zukan Date: Mon, 3 Sep 2007 12:26:58 +0000 Subject: [PATCH] Synced code with edelib changes. Directory notifier added (still needs a work). Internal changes for easier directory events handling. --- eiconman/DesktopIcon.cpp | 8 +- eiconman/DesktopIcon.h | 8 ++ eiconman/eiconman.cpp | 289 ++++++++++++++++++++++++++++----------- eiconman/eiconman.h | 16 ++- 4 files changed, 235 insertions(+), 86 deletions(-) diff --git a/eiconman/DesktopIcon.cpp b/eiconman/DesktopIcon.cpp index e4b7e66..1f1deb9 100644 --- a/eiconman/DesktopIcon.cpp +++ b/eiconman/DesktopIcon.cpp @@ -19,10 +19,10 @@ #include #include #include -#include #include #include +#include #include #define USE_SHAPE 1 @@ -63,7 +63,7 @@ void rename_cb(Fl_Widget*, void* d) { DesktopIcon* di = (DesktopIcon*)d; EASSERT(di != NULL); - const char* new_name = fl_input(_("New name"), di->label()); + const char* new_name = edelib::input(_("New name"), di->label()); if(!new_name) return; if(new_name[0] == '\0') @@ -261,6 +261,10 @@ void DesktopIcon::rename(const char* str) { redraw(); } +const edelib::String& DesktopIcon::path(void) { + return settings->full_path; +} + void DesktopIcon::fast_redraw(void) { EASSERT(parent() != NULL && "Impossible !"); diff --git a/eiconman/DesktopIcon.h b/eiconman/DesktopIcon.h index 7fcd08c..bec45c4 100644 --- a/eiconman/DesktopIcon.h +++ b/eiconman/DesktopIcon.h @@ -13,6 +13,8 @@ #ifndef __DESKTOPICON_H__ #define __DESKTOPICON_H__ +#include + #include #include #include @@ -77,6 +79,12 @@ class DesktopIcon : public Fl_Widget { Fl_Image* icon_image(void) { return image(); } void rename(const char* str); + + /* + * make sure this returns String since operator== is + * further used, especially in Desktop + */ + const edelib::String& path(void); }; class MovableIcon : public Fl_Window { diff --git a/eiconman/eiconman.cpp b/eiconman/eiconman.cpp index 890a8ec..acf110d 100644 --- a/eiconman/eiconman.cpp +++ b/eiconman/eiconman.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +35,8 @@ #include #include +#include // sleep + #if 0 #include #endif @@ -111,6 +114,10 @@ void restart_signal(int signum) { EDEBUG(ESTRLOC ": Restarting (got signal %d)\n", signum); } +void dir_watch_cb(const char* dir, const char* changed, int flags, void* data) { + Desktop::instance()->dir_watch(dir, changed, flags); +} + int desktop_xmessage_handler(int event) { #if 0 if(fl_xevent->type == xevent_base + XDamageNotify) { @@ -158,6 +165,7 @@ int desktop_xmessage_handler(int event) { Desktop::Desktop() : DESKTOP_WINDOW(0, 0, 100, 100, "") { selection_x = selection_y = 0; moving = false; + do_dirwatch = true; selbox = new SelectionOverlay; selbox->x = selbox->y = selbox->w = selbox->h = 0; @@ -174,6 +182,8 @@ Desktop::~Desktop() { delete dsett; delete selbox; delete notify; + + edelib::DirWatch::shutdown(); } void Desktop::init_internals(void) { @@ -333,85 +343,148 @@ void Desktop::read_config(void) { return; } dd += "/Desktop"; - load_icons(dd.c_str(), conf); + + /* + * Setup watcher on ~/Desktop directory. All further events will + * be reported to dir_watch() + */ + if(edelib::dir_exists(dd.c_str())) { + load_icons(dd.c_str(), &conf); + + edelib::DirWatch::init(); + edelib::DirWatch::callback(dir_watch_cb); + + if(!edelib::DirWatch::add(dd.c_str(), + edelib::DW_CREATE | edelib::DW_MODIFY | edelib::DW_RENAME | edelib::DW_DELETE)) { + + EWARNING(ESTRLOC ": Can't load %s; icons will not be loaded\n", dd.c_str()); + edelib::DirWatch::shutdown(); + } + } } void Desktop::save_config(void) { // TODO } -void Desktop::load_icons(const char* path, edelib::Config& conf) { +void Desktop::load_icons(const char* path, edelib::Config* conf) { EASSERT(path != NULL); - if(!edelib::dir_exists(path)) { - EDEBUG(ESTRLOC ": %s does not exists\n", path); - return; - } - - edelib::vector lst; - - // list without full path, so we can use name as entry in config file - if(!dir_list(path, lst)) { + edelib::list lst; + // list with full path; icon basename is extracted in add_icon_pathed() + if(!dir_list(path, lst, true)) { EDEBUG(ESTRLOC ": Can't read %s\n", path); return; } - const char* name = NULL; - int icon_x = 0; - int icon_y = 0; - edelib::String full_path; - full_path.reserve(256); + edelib::list::iterator it, it_end; + for(it = lst.begin(), it_end = lst.end(); it != it_end; ++it) + add_icon_pathed((*it).c_str(), conf); +} +bool Desktop::add_icon_pathed(const char* path, edelib::Config* conf) { + EASSERT(path != NULL); + + IconSettings is; bool can_add = false; + const char* base = get_basename(path); - edelib::MimeType mt; - - unsigned int sz = lst.size(); - for(unsigned int i = 0; i < sz; i++) { - name = lst[i].c_str(); + /* + * see is possible .desktop file; icon, name fields are filled from read_desktop_file() + * + * FIXME: maybe the good thing is to use MimeType to check .desktop; + * extension does not have to be always present, or .desktop does not have to be + * Desktop File at all + */ + if(edelib::str_ends(path, ".desktop")) { + if(read_desktop_file(path, is)) + can_add = true; + } else { + edelib::MimeType mt; - full_path = path; - full_path += '/'; - full_path += name; + // then try to figure out it's mime; if fails, ignore it + if(mt.set(path)) { + EDEBUG(ESTRLOC ": Loading icon as mime-type %s\n", mt.icon_name().c_str()); + is.icon = mt.icon_name(); + // icon label path's basename + is.name = base; + is.type = ICON_FILE; - can_add = false; - - IconSettings is; - - // see is possible .desktop file, icon, name fields are filled from read_desktop_file() - if(edelib::str_ends(name, ".desktop")) { - if(read_desktop_file(full_path.c_str(), is)) - can_add = true; + can_add = true; } else { - // then try to figure out it's mime; if fails, ignore it - if(mt.set(full_path.c_str())) { - EDEBUG(ESTRLOC ": Loading icon as mime-type %s\n", mt.icon_name().c_str()); - is.icon = mt.icon_name(); - // icon label is name of file - is.name = name; - is.type = ICON_FILE; - - can_add = true; - } else { - EDEBUG(ESTRLOC ": Failed mime-type for %s, ignoring...\n", name); - can_add = false; - } - } - - if(can_add) { - is.key_name = name; - // random_pos() is used if X/Y keys are not found - conf.get(name, "X", icon_x, random_pos(w() - 10)); - conf.get(name, "Y", icon_y, random_pos(h() - 10)); - - EDEBUG(ESTRLOC ": %s found with: %i %i\n", name, icon_x, icon_y); - is.x = icon_x; - is.y = icon_y; - - DesktopIcon* dic = new DesktopIcon(&gisett, &is, dsett->color); - add_icon(dic); + EDEBUG(ESTRLOC ": Failed mime-type for %s, ignoring...\n", path); + can_add = false; } } + + if(can_add) { + /* + * key_name is section in config file with icon X/Y values + * FIXME: this should be named 'section_name' + */ + is.key_name = base; + + // random_pos() is used if X/Y keys are not found + int icon_x = random_pos(w() - 10); + int icon_y = random_pos(w() - 10); + + if(conf) { + conf->get(base, "X", icon_x, icon_x); + conf->get(base, "Y", icon_y, icon_y); + } + + EDEBUG(ESTRLOC ": %s found with: %i %i\n", base, icon_x, icon_y); + is.x = icon_x; + is.y = icon_y; + is.full_path = path; + + DesktopIcon* dic = new DesktopIcon(&gisett, &is, dsett->color); + add_icon(dic); + } + + return can_add; +} + +DesktopIcon* Desktop::find_icon_pathed(const char* path) { + EASSERT(path != NULL); + + if(icons.empty()) + return NULL; + + DesktopIconListIter it, it_end; + for(it = icons.begin(), it_end = icons.end(); it != it_end; ++it) { + if((*it)->path() == path) + return (*it); + } + + return NULL; +} + +bool Desktop::remove_icon_pathed(const char* path) { + EASSERT(path != NULL); + + if(icons.empty()) + return false; + + DesktopIconListIter it, it_end; + bool found = false; + + for(it = icons.begin(), it_end = icons.end(); it != it_end; ++it) { + if((*it)->path() == path) { + found = true; + break; + } + } + + if(found) { + DesktopIcon* ic = (*it); + icons.erase(it); + // Fl_Group::remove() does not delete child, just pops it out + remove(ic); + delete ic; + } + + return found; } // read .desktop files @@ -425,7 +498,7 @@ bool Desktop::read_desktop_file(const char* path, IconSettings& is) { edelib::DesktopFile dconf; if(!dconf.load(path)) { - EWARNING(ESTRLOC ": Can't read %s\n", path); + EWARNING(ESTRLOC ": Can't read %s (%s)\n", path, dconf.strerror()); return false; } @@ -482,11 +555,12 @@ void Desktop::add_icon(DesktopIcon* ic) { } void Desktop::unfocus_all(void) { - unsigned int sz = icons.size(); DesktopIcon* ic; + DesktopIconListIter it, it_end; + + for(it = icons.begin(), it_end = icons.end(); it != it_end; ++it) { + ic = (*it); - for(unsigned int i = 0; i < sz; i++) { - ic = icons[i]; if(ic->is_focused()) { ic->do_unfocus(); ic->fast_redraw(); @@ -524,9 +598,13 @@ void Desktop::select_only(DesktopIcon* ic) { bool Desktop::in_selection(const DesktopIcon* ic) { EASSERT(ic != NULL); - unsigned int sz = selectionbuff.size(); - for(unsigned int i = 0; i < sz; i++) { - if(ic == selectionbuff[i]) + if(selectionbuff.empty()) + return false; + + DesktopIconListIter it, it_end; + + for(it = selectionbuff.begin(), it_end = selectionbuff.end(); it != it_end; ++it) { + if((*it) == ic) return true; } @@ -534,15 +612,16 @@ bool Desktop::in_selection(const DesktopIcon* ic) { } void Desktop::move_selection(int x, int y, bool apply) { - unsigned int sz = selectionbuff.size(); - if(sz == 0) + if(selectionbuff.empty()) return; int prev_x, prev_y, tmp_x, tmp_y; DesktopIcon* ic; - for(unsigned int i = 0; i < sz; i++) { - ic = selectionbuff[i]; + DesktopIconListIter it, it_end; + + for(it = selectionbuff.begin(), it_end = selectionbuff.end(); it != it_end; ++it) { + ic = (*it); prev_x = ic->drag_icon_x(); prev_y = ic->drag_icon_y(); @@ -575,11 +654,11 @@ void Desktop::move_selection(int x, int y, bool apply) { * and bad things be hapened. */ DesktopIcon* Desktop::below_mouse(int px, int py) { - unsigned int sz = icons.size(); - DesktopIcon* ic = NULL; - for(unsigned int i = 0; i < sz; i++) { - ic = icons[i]; + DesktopIconListIter it, it_end; + + for(it = icons.begin(), it_end = icons.end(); it != it_end; ++it) { + ic = (*it); if(ic->x() < px && ic->y() < py && px < (ic->x() + ic->h()) && py < (ic->y() + ic->h())) return ic; } @@ -613,11 +692,11 @@ void Desktop::select_in_area(void) { * but selbox use relative (event_root). It will work as expected if desktop is at x=0 y=0. * This should be checked further. */ - unsigned int sz = icons.size(); DesktopIcon* ic = NULL; + DesktopIconListIter it, it_end; - for(unsigned int i = 0; i < sz; i++) { - ic = icons[i]; + for(it = icons.begin(), it_end = icons.end(); it != it_end; ++it) { + ic = (*it); EASSERT(ic != NULL && "Impossible to happen"); if(intersects(ax, ay, ax+aw, ay+ah, ic->x(), ic->y(), ic->w()+ic->x(), ic->h()+ic->y())) { @@ -831,6 +910,53 @@ void Desktop::draw(void) { clear_damage(); } +void Desktop::dir_watch(const char* dir, const char* changed, int flags) { + if(!do_dirwatch || !changed || flags == edelib::DW_REPORT_NONE) + return; + + /* + * Check first we don't get any temporary files (starting with '.' + * or ending with '~', like vim does when editing file). For now these + * are only conditions, but I will probably add them more when issues occured. + * + * FIXME: use strcmp() family ? + */ + edelib::String tmp(changed); + if(tmp.empty() || tmp[0] == '.' || tmp[tmp.length()-1] == '~') + return; + + sleep(1); + + if(flags == edelib::DW_REPORT_CREATE) { + EDEBUG(ESTRLOC ": adding %s\n", changed); + + if(find_icon_pathed(changed)) { + EDEBUG(ESTRLOC ": %s already registered; skipping...\n", changed); + return; + } + + /* + * Uh; looks like kernel report event faster than file is created + * (in some cases). This can be bad for .desktop files when are copied + * (eg. on my machine after 'cp Home.desktop foo.desktop', will fail + * to load foo.desktop since it's content is not fully copied). + * Due that we stop for one sec (use usleep() ???) + */ + //sleep(1); + + if(add_icon_pathed(changed, 0)) + redraw(); + + } else if(flags == edelib::DW_REPORT_MODIFY) { + EDEBUG(ESTRLOC ": modified %s\n", changed); + } else if(flags == edelib::DW_REPORT_DELETE) { + EDEBUG(ESTRLOC ": deleted %s\n", changed); + if(remove_icon_pathed(changed)) + redraw(); + } else + EDEBUG(ESTRLOC ": %s changed with %i\n", changed, flags); +} + int Desktop::handle(int event) { switch(event) { case FL_FOCUS: @@ -958,9 +1084,10 @@ int Desktop::handle(int event) { if(!selectionbuff.empty()) selectionbuff.clear(); - for(unsigned int i = 0; i < icons.size(); i++) { - if(icons[i]->is_focused()) - select(icons[i], false); + DesktopIconListIter it, it_end; + for(it = icons.begin(), it_end = icons.end(); it != it_end; ++it) { + if((*it)->is_focused()) + select((*it), false); } return 1; @@ -976,7 +1103,7 @@ int Desktop::handle(int event) { * command for all selected icons ? */ if(selectionbuff.size() == 1 && !moving) - selectionbuff[0]->handle(FL_RELEASE); + (*selectionbuff.begin())->handle(FL_RELEASE); moving = false; return 1; diff --git a/eiconman/eiconman.h b/eiconman/eiconman.h index c78fcb1..8315281 100644 --- a/eiconman/eiconman.h +++ b/eiconman/eiconman.h @@ -19,7 +19,7 @@ #include #include -#include +#include #define EDAMAGE_CHILD_LABEL 0x10 #define EDAMAGE_OVERLAY 0x20 @@ -78,7 +78,8 @@ class NotifyBox; class Fl_Menu_Button; -typedef edelib::vector DesktopIconList; +typedef edelib::list DesktopIconList; +typedef edelib::list::iterator DesktopIconListIter; #define DESKTOP_WINDOW Fl_Window @@ -88,6 +89,7 @@ class Desktop : public DESKTOP_WINDOW { int selection_x, selection_y; bool moving; + bool do_dirwatch; SelectionOverlay* selbox; @@ -103,10 +105,14 @@ class Desktop : public DESKTOP_WINDOW { void init_internals(void); - void load_icons(const char* path, edelib::Config& conf); + void load_icons(const char* path, edelib::Config* conf); bool read_desktop_file(const char* path, IconSettings& is); void add_icon(DesktopIcon* ic); + bool add_icon_pathed(const char* path, edelib::Config* conf); + DesktopIcon* find_icon_pathed(const char* path); + bool remove_icon_pathed(const char* path); + bool update_icon_pathed(const char* path); void unfocus_all(void); @@ -145,6 +151,10 @@ class Desktop : public DESKTOP_WINDOW { void notify_box(const char* msg, bool copy = false); void notify_box_color(Fl_Color col); void notify_desktop_changed(void); + + void dir_watch(const char* dir, const char* changed, int flags); + void dir_watch_on(void) { do_dirwatch = true; } + void dir_watch_off(void) { do_dirwatch = false; } }; #endif