Removing old ede-desktop.h. Adding support for editing existing icons.

Editing will be done simply by creating first .desktop file and letting ede-desktop to read it, performing some
checks to determin if only content was changed or file was renamed. Using this scheme, beside it simplify the code,
it addresses the cases when icon was modified outside the desktop or removed.

These things could be solved by using DirWatch, but I'm trying to rely less on OS notification system...
This commit is contained in:
Sanel Zukan 2013-06-24 14:40:28 +00:00
parent db9e0bad61
commit bee5fd8fb9
8 changed files with 108 additions and 205 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -19,6 +19,7 @@
*/
#include <ctype.h>
#include <limits.h>
#include <FL/Fl_Window.H>
#include <FL/Fl.H>
@ -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) {
}

View File

@ -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

View File

@ -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()) {
/*

View File

@ -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 <edelib/Window.h>
# define EDE_DESKTOP_WINDOW edelib::Window
#else
# include <FL/Fl_Window.H>
# include <FL/Fl_Double_Window.H>
# define EDE_DESKTOP_WINDOW Fl_Window
#endif
#include <FL/Fl_Image.H>
#include <edelib/String.h>
#include <edelib/Resource.h>
#include <edelib/List.h>
#include <edelib/MenuButton.h>
#ifdef EDELIB_HAVE_DBUS
# include <edelib/EdbusConnection.h>
#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<DesktopIcon*> DesktopIconList;
typedef edelib::list<DesktopIcon*>::iterator DesktopIconListIter;
typedef edelib::list<edelib::String> StringList;
typedef edelib::list<edelib::String>::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