ede/ede-desktop/IconDialog.cpp
Sanel Zukan bee5fd8fb9 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...
2013-06-24 14:40:28 +00:00

236 lines
6.2 KiB
C++

/*
* $Id: ede-panel.cpp 3463 2012-12-17 15:49:33Z karijes $
*
* Copyright (C) 2006-2013 Sanel Zukan
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <ctype.h>
#include <limits.h>
#include <FL/Fl_Window.H>
#include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Choice.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_Shared_Image.H>
#include <FL/Fl_File_Chooser.H>
#include <edelib/Nls.h>
#include <edelib/String.h>
#include <edelib/IconChooser.h>
#include <edelib/DesktopFile.h>
#include <edelib/Debug.h>
#include <edelib/Directory.h>
#include <edelib/File.h>
#include <edelib/StrUtil.h>
#include <edelib/Util.h>
#include <edelib/MessageBox.h>
#include <edelib/IconLoader.h>
#include "IconDialog.h"
#include "DesktopIcon.h"
#include "Desktop.h"
#include "Globals.h"
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"
/* it is safe to be globals */
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, old_desktop_path;
static DesktopIcon *curr_icon;
/* the only supported type for now is application */
static Fl_Menu_Item menu_items[] = {
{_("Application"), 0, 0, 0},
{0}
};
static bool is_empty(const char *str) {
if(!str) return true;
const char *p = str;
while(*p++)
if(!isspace(*p)) return false;
return true;
}
inline bool is_empty_input(Fl_Input *i) {
return is_empty(i->value());
}
static void cancel_cb(Fl_Widget*, void*) {
win->hide();
}
static void ok_cb(Fl_Widget*, void *d) {
if(is_empty_input(name) || is_empty_input(execute) || !img->image()) {
/* do nothing */
win->hide();
return;
}
Desktop *self = (Desktop*)d;
DesktopFile df;
df.create_new(DESK_FILE_TYPE_APPLICATION);
df.set_name(name->value());
if(comment->value())
df.set_comment(comment->value());
df.set_icon((img_path.length() > 1) ? img_path.c_str() : DEFAULT_ICON);
df.set_exec(execute->value());
/* determine filename and save it */
String file = name->value();
const char *fp = file.c_str();
str_tolower((unsigned char*)fp);
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) {
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());
}
win->hide();
}
static void img_browse_cb(Fl_Widget*, void*) {
img_path = icon_chooser(ICON_SIZE_HUGE);
if(!img_path.empty())
IconLoader::set(img, img_path.c_str(), ICON_SIZE_HUGE);
}
static void file_browse_cb(Fl_Widget*, void*) {
const char *p = fl_file_chooser(_("Choose program path to execute"), "*", 0, 0);
if(p) execute->value(p);
}
#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"));
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);
ok = new Fl_Button(235, 135, 90, 25, _("&OK"));
ok->callback(ok_cb, self);
cancel = new Fl_Button(330, 135, 90, 25, _("&Cancel"));
cancel->callback(cancel_cb);
win->end();
win->set_modal();
delete df;
delete buf;
Fl::focus(name);
win->show();
}