diff --git a/ede-desktop/Desktop.cpp b/ede-desktop/Desktop.cpp index 0cf3ca1..ab3df29 100644 --- a/ede-desktop/Desktop.cpp +++ b/ede-desktop/Desktop.cpp @@ -365,7 +365,7 @@ DesktopIcon *Desktop::read_desktop_file(const char *path, const char *base, Desk * try to load it as plain .desktop file by looking only at extension * TODO: MimeType can be used here too */ - if(!str_ends(path, ".desktop")) + if(!str_ends(path, EDE_DESKTOP_DESKTOP_EXT)) return ret; DesktopFile df; @@ -435,7 +435,7 @@ bool Desktop::remove_icon(DesktopIcon *di, bool real_delete) { if(real_delete) { if(di->get_icon_type() == DESKTOP_ICON_TYPE_FOLDER) { if(!dir_empty(di->get_path())) { - alert(_("This folder is not empty. Recursive removal of not empty folders is not yet implemented :S")); + alert(_("This folder is not empty. Recursive removal of not empty folders is not yet supported")); return false; } ret = dir_remove(di->get_path()); @@ -462,6 +462,10 @@ bool Desktop::rename_icon(DesktopIcon *di, const char *name) { return df.save(di->get_path()); } +void Desktop::edit_icon(DesktopIcon *di) { + icon_dialog_icon_edit(this, di); +} + bool Desktop::save_icons_positions(void) { DesktopConfig pos; DesktopIcon *o; diff --git a/ede-desktop/Desktop.h b/ede-desktop/Desktop.h index 7ea3997..50410a4 100644 --- a/ede-desktop/Desktop.h +++ b/ede-desktop/Desktop.h @@ -80,6 +80,7 @@ public: void arrange_icons(void); bool remove_icon(DesktopIcon *di, bool real_delete); bool rename_icon(DesktopIcon *di, const char *name); + void edit_icon(DesktopIcon *di); bool save_icons_positions(void); bool create_folder(const char *name); diff --git a/ede-desktop/DesktopIcon.cpp b/ede-desktop/DesktopIcon.cpp index 2734852..bcbaf9b 100644 --- a/ede-desktop/DesktopIcon.cpp +++ b/ede-desktop/DesktopIcon.cpp @@ -60,12 +60,12 @@ EDELIB_NS_USING(ICON_SIZE_TINY) EDELIB_NS_USING(ICON_SIZE_HUGE) static void open_cb(Fl_Widget*, void* d); -static void rename_cb(Fl_Widget*, void* d); +static void edit_cb(Fl_Widget*, void* d); static void delete_cb(Fl_Widget*, void* d); static MenuItem icon_menu[] = { {_("&Open"), 0, open_cb, 0}, - {_("&Rename"), 0, rename_cb, 0}, + {_("&Edit"), 0, edit_cb, 0}, {_("&Delete"), 0, delete_cb, 0}, {0} }; @@ -80,23 +80,30 @@ static MenuItem icon_trash_menu[] = { #endif static void open_cb(Fl_Widget*, void* d) { - DesktopIcon* o = (DesktopIcon*)d; + DesktopIcon *o = (DesktopIcon*)d; run_async("ede-launch %s", o->get_cmd()); } -static void rename_cb(Fl_Widget*, void* d) { - DesktopIcon* di = (DesktopIcon*)d; +static void edit_cb(Fl_Widget*, void* d) { + DesktopIcon *di = (DesktopIcon*)d; + ((Desktop*)di->parent())->edit_icon(di); +} - const char* new_name = input(_("Change desktop icon name to:"), di->label()); +# if 0 +static void rename_cb(Fl_Widget*, void* d) { + DesktopIcon *di = (DesktopIcon*)d; + + const char *new_name = input(_("Change desktop icon name to:"), di->label()); if(new_name) { bool saved = ((Desktop*)di->parent())->rename_icon(di, new_name); if(!saved) alert(_("Unable to rename this icon. Please check if you have enough permissions to do so")); } } +#endif static void delete_cb(Fl_Widget*, void* d) { - DesktopIcon* di = (DesktopIcon*)d; + DesktopIcon *di = (DesktopIcon*)d; if(ask(_("This icon will be permanently deleted. Are you sure?"))) ((Desktop*)di->parent())->remove_icon(di, true); @@ -135,7 +142,7 @@ void DesktopIcon::set_image(const char *name) { E_RETURN_IF_FAIL(IconLoader::set(this, name, ICON_SIZE_HUGE)); /* fetch image object for sizes */ - Fl_Image* img = image(); + Fl_Image *img = image(); int img_w = img->w(), img_h = img->h(); @@ -360,6 +367,7 @@ int DesktopIcon::handle(int event) { /* MenuItem::popup() by default does not call callbacks */ const MenuItem *m = imenu->menu()->popup(Fl::event_x(), Fl::event_y()); + /* call menu callbacks, passing correct parameters */ if(m && m->callback()) m->do_callback(0, this); } diff --git a/ede-desktop/Globals.h b/ede-desktop/Globals.h index 61105d8..a936b9d 100644 --- a/ede-desktop/Globals.h +++ b/ede-desktop/Globals.h @@ -30,4 +30,6 @@ EDELIB_NS_USING_AS(Resource, DesktopConfig) #define EDE_DESKTOP_DAMAGE_OVERLAY 0x20 #define EDE_DESKTOP_DAMAGE_CLEAR_OVERLAY 0x30 +#define EDE_DESKTOP_DESKTOP_EXT ".desktop" + #endif diff --git a/ede-desktop/IconDialog.cpp b/ede-desktop/IconDialog.cpp index baa9ae4..fc6527b 100644 --- a/ede-desktop/IconDialog.cpp +++ b/ede-desktop/IconDialog.cpp @@ -19,6 +19,7 @@ */ #include +#include #include #include @@ -44,8 +45,9 @@ #include "IconDialog.h" #include "DesktopIcon.h" #include "Desktop.h" +#include "Globals.h" -EDELIB_NS_USING_LIST(10, (str_tolower, icon_chooser, dir_home, build_filename, alert, +EDELIB_NS_USING_LIST(12, (str_tolower, icon_chooser, dir_home, build_filename, alert, ask, file_remove, ICON_SIZE_HUGE, String, IconLoader, DesktopFile, DESK_FILE_TYPE_APPLICATION)) #define DEFAULT_ICON "empty" @@ -55,7 +57,8 @@ static Fl_Window *win; static Fl_Button *img, *browse, *ok, *cancel; static Fl_Input *name, *comment, *execute; static Fl_Choice *icon_type; -static String img_path; +static String img_path, old_desktop_path; +static DesktopIcon *curr_icon; /* the only supported type for now is application */ static Fl_Menu_Item menu_items[] = { @@ -105,18 +108,36 @@ static void ok_cb(Fl_Widget*, void *d) { const char *fp = file.c_str(); str_tolower((unsigned char*)fp); - file += ".desktop"; + file += EDE_DESKTOP_DESKTOP_EXT; /* go through the file and replace spaces with '_' */ for(String::size_type i = 0; i < file.length(); i++) if(isspace(file[i])) file[i] = '_'; String path = build_filename(self->desktop_path(), file.c_str()); + + int X = 0, Y = 0; + if(curr_icon) { + X = curr_icon->x(); + Y = curr_icon->y(); + /* try to remove icon from filesystem only when we can't overwrite old icon path */ + self->remove_icon(curr_icon, old_desktop_path != path); + } if(df.save(path.c_str())) { DesktopIcon *ic = self->read_desktop_file(path.c_str(), file.c_str()); - if(ic) self->add(ic); + if(ic) { + if(X > 0 || Y > 0) ic->position(X, Y); + self->add(ic); + } + self->redraw(); + + /* + * In case when we rename icon, icon position will not be saved (because they are saved by icon basename). So + * with different paths we are assured the name was changed and we proceed further. + */ + if(old_desktop_path != path) self->save_icons_positions(); } else { alert(_("Unable to create '%s' file. Received error is: %s\n"), path.c_str(), df.strerror()); } @@ -133,21 +154,68 @@ static void img_browse_cb(Fl_Widget*, void*) { static void file_browse_cb(Fl_Widget*, void*) { const char *p = fl_file_chooser(_("Choose program path to execute"), "*", 0, 0); - if(!p) return; - execute->value(p); + if(p) execute->value(p); } -void icon_dialog_icon_create(Desktop *self) { - win = new Fl_Window(430, 170, _("Create desktop icon")); +#define BUFSIZE PATH_MAX + +void icon_dialog_icon_edit(Desktop *self, DesktopIcon *d) { + const char *lbl = d ? _("Edit desktop icon") : _("Create desktop icon"); + DesktopFile *df = NULL; + char *buf = NULL; + old_desktop_path = ""; + curr_icon = d; + + if(d) { + df = new DesktopFile(); + if(!df->load(d->get_path())) { + delete df; + + int ret = ask(_("Unable to load .desktop file for this icon. Would you like to create new icon instead?")); + if(!ret) return; + + /* force NULL on icon, so we can run dialog in 'create' mode */ + d = NULL; + } + + buf = new char[BUFSIZE]; + old_desktop_path = d->get_path(); + } + + win = new Fl_Window(430, 170, lbl); img = new Fl_Button(10, 10, 75, 75); img->callback(img_browse_cb); img->tooltip(_("Click to select icon")); - IconLoader::set(img, DEFAULT_ICON, ICON_SIZE_HUGE); + + if(d) { + E_ASSERT(df != NULL); + if(df->icon(buf, BUFSIZE)) { + IconLoader::set(img, buf, ICON_SIZE_HUGE); + img_path = buf; + } + } + + /* handles even the case when we are creating the new icon */ + if(!img->image()) { + IconLoader::set(img, DEFAULT_ICON, ICON_SIZE_HUGE); + img_path = DEFAULT_ICON; + } + name = new Fl_Input(205, 10, 215, 25, _("Name:")); + if(d && df->name(buf, BUFSIZE)) + name->value(buf); + comment = new Fl_Input(205, 40, 215, 25, _("Comment:")); + if(d && df->comment(buf, BUFSIZE)) + comment->value(buf); + execute = new Fl_Input(205, 70, 185, 25, _("Execute:")); + if(d && df->exec(buf, BUFSIZE)) + execute->value(buf); + browse = new Fl_Button(395, 70, 25, 25, "..."); browse->callback(file_browse_cb); + icon_type = new Fl_Choice(205, 100, 215, 25, _("Type:")); icon_type->down_box(FL_BORDER_BOX); icon_type->menu(menu_items); @@ -158,10 +226,10 @@ void icon_dialog_icon_create(Desktop *self) { cancel->callback(cancel_cb); win->end(); win->set_modal(); + + delete df; + delete buf; Fl::focus(name); win->show(); } - -void icon_dialog_icon_property(DesktopIcon *d) { -} diff --git a/ede-desktop/IconDialog.h b/ede-desktop/IconDialog.h index 46dad69..96c2cde 100644 --- a/ede-desktop/IconDialog.h +++ b/ede-desktop/IconDialog.h @@ -24,7 +24,7 @@ class DesktopIcon; class Desktop; -void icon_dialog_icon_create(Desktop *d); -void icon_dialog_icon_property(DesktopIcon *d); +void icon_dialog_icon_edit(Desktop *self, DesktopIcon *di); +inline void icon_dialog_icon_create(Desktop *d) { icon_dialog_icon_edit(d, NULL); } #endif diff --git a/ede-desktop/Wallpaper.cpp b/ede-desktop/Wallpaper.cpp index f83eac6..b9f3652 100644 --- a/ede-desktop/Wallpaper.cpp +++ b/ede-desktop/Wallpaper.cpp @@ -476,7 +476,7 @@ int Wallpaper::handle(int event) { void Wallpaper::resize(int X, int Y, int W, int H) { if(X == x() && Y == y() && W == w() && H == h()) return; - + Fl_Box::resize(X, Y, W, H); if(image()) { /* diff --git a/ede-desktop/ede-desktop.h b/ede-desktop/ede-desktop.h deleted file mode 100644 index 60b95ec..0000000 --- a/ede-desktop/ede-desktop.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * $Id$ - * - * ede-desktop, desktop and icon manager - * Part of Equinox Desktop Environment (EDE). - * Copyright (c) 2006-2009 EDE Authors. - * - * This program is licensed under terms of the - * GNU General Public License version 2 or newer. - * See COPYING for details. - */ - -#ifndef __EDE_DESKTOP_H__ -#define __EDE_DESKTOP_H__ - -#ifdef USE_EDELIB_WINDOW -# include -# define EDE_DESKTOP_WINDOW edelib::Window -#else -# include -# include -# define EDE_DESKTOP_WINDOW Fl_Window -#endif - -#include - -#include -#include -#include -#include - -#ifdef EDELIB_HAVE_DBUS -# include -#endif - -#define EDAMAGE_CHILD_LABEL 0x10 -#define EDAMAGE_OVERLAY 0x20 - -#define ICON_NORMAL 1 // .desktop file -#define ICON_TRASH 2 // trash.desktop (specific since have two icons for empty/full) -#define ICON_FILE 3 // real file -#define ICON_SYMLINK 4 // symbolic link - -#define ICON_FACE_ONE 1 // use icon -#define ICON_FACE_TWO 2 // use icon2 - -struct GlobalIconSettings { - int label_background; - int label_foreground; - int label_font; - int label_fontsize; - int label_maxwidth; - bool label_transparent; - bool label_draw; - bool one_click_exec; - bool auto_arrange; - bool same_size; -}; - -/* - * Settings representing related to icon on desktop. To complicate our lives - * (and to, at least, simplify code) it can be: - * - .desktop file content (normal or trash like) - * - real file copied/moved inside ~/Desktop directory - * - symlink in ~/Desktop directory pointing to the real file - */ -struct IconSettings { - int x, y; - int type; // ICON_NORMAL, ICON_TRASH,... - bool cmd_is_url; // interpret cmd as url, like system:/,trash:/,$HOME - - edelib::String name; - edelib::String cmd; - edelib::String icon; - edelib::String icon2; // for stateable icons, like trash (empty/full) - edelib::String key_name; // name used as key when storing positions - edelib::String full_path; // for tracking changes -}; - -/* selection overlay */ -struct SelectionOverlay { - int x, y, w, h; - bool show; -}; - -class Wallpaper; -class DesktopIcon; - -typedef edelib::list DesktopIconList; -typedef edelib::list::iterator DesktopIconListIter; - -typedef edelib::list StringList; -typedef edelib::list::iterator StringListIter; - -class Desktop : public EDE_DESKTOP_WINDOW { -private: - static Desktop* pinstance; - - int selection_x, selection_y; - - /* last recorded pointer position, so icon can be created at position where menu is clicked */ - int last_px, last_py; - - bool moving; - bool do_dirwatch; - - edelib::String desktop_dir_path; - - SelectionOverlay* selbox; - - GlobalIconSettings* gisett; - - edelib::MenuButton* dmenu; - Wallpaper* wallpaper; - -#ifdef EDELIB_HAVE_DBUS - edelib::EdbusConnection* dbus; -#endif - - DesktopIconList icons; - DesktopIconList selectionbuf; - - void init_internals(void); - - void load_icons(const char* path); - void save_icons_positions(void); - IconSettings* read_desktop_file(const char* path); - - void add_icon(DesktopIcon* ic); - - DesktopIcon* find_icon_by_path(const char* path, DesktopIconListIter* pos); - bool remove_icon_by_path(const char* path); - - void auto_arrange(void); - - void unfocus_all(void); - - void select(DesktopIcon* ic, bool do_redraw = true); - void select_only(DesktopIcon* ic); - bool in_selection(const DesktopIcon* ic); - void move_selection(int x, int y, bool apply); - - void select_in_area(void); - - //void dnd_drop_source(const char* src, int src_len, int x, int y); - - DesktopIcon* below_mouse(int px, int py); - -public: - Desktop(); - ~Desktop(); - - virtual void show(void); - virtual void hide(void); - virtual void draw(void); - virtual int handle(int event); - - static void init(void); - static void shutdown(void); - static Desktop* instance(void); - - void read_config(void); - - bool add_icon_by_path(const char* path, edelib::Resource* conf); - bool remove_icon(DesktopIcon *d, bool real_delete); - bool rename_icon(DesktopIcon *d, const char *n); - - void update_workarea(void); - void area(int& X, int& Y, int& W, int& H) { X = x(); Y = y(); W = w(); H = h(); } - - 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; } - - const char *desktop_path(void) { return desktop_dir_path.c_str(); } -}; - -#endif