Added target progress
This commit is contained in:
parent
4ca4916a79
commit
2298a2d670
1
Makefile
1
Makefile
|
@ -23,6 +23,7 @@ dist:
|
|||
@$(TAR) $(PACKAGE)-$(VERSION).tar.gz \
|
||||
$(PACKAGE)-$(VERSION)/src/calendar.c \
|
||||
$(PACKAGE)-$(VERSION)/src/fontsel.c \
|
||||
$(PACKAGE)-$(VERSION)/src/progress.c \
|
||||
$(PACKAGE)-$(VERSION)/src/run.c \
|
||||
$(PACKAGE)-$(VERSION)/src/Makefile \
|
||||
$(PACKAGE)-$(VERSION)/src/project.conf \
|
||||
|
|
15
src/Makefile
15
src/Makefile
|
@ -1,4 +1,4 @@
|
|||
TARGETS = calendar fontsel run
|
||||
TARGETS = calendar fontsel progress run
|
||||
PREFIX = /usr/local
|
||||
DESTDIR =
|
||||
BINDIR = $(PREFIX)/bin
|
||||
|
@ -27,6 +27,12 @@ fontsel_CFLAGS = $(CPPFLAGS) $(CFLAGSF) $(CFLAGS)
|
|||
fontsel: $(fontsel_OBJS)
|
||||
$(CC) -o fontsel $(fontsel_OBJS) $(LDFLAGSF) $(LDFLAGS)
|
||||
|
||||
progress_OBJS = progress.o
|
||||
progress_CFLAGS = $(CPPFLAGS) $(CFLAGSF) $(CFLAGS)
|
||||
|
||||
progress: $(progress_OBJS)
|
||||
$(CC) -o progress $(progress_OBJS) $(LDFLAGSF) $(LDFLAGS)
|
||||
|
||||
run_OBJS = run.o
|
||||
run_CFLAGS = $(CPPFLAGS) $(CFLAGSF) $(CFLAGS)
|
||||
|
||||
|
@ -39,11 +45,14 @@ calendar.o: calendar.c
|
|||
fontsel.o: fontsel.c
|
||||
$(CC) $(fontsel_CFLAGS) -c fontsel.c
|
||||
|
||||
progress.o: progress.c
|
||||
$(CC) $(progress_CFLAGS) -c progress.c
|
||||
|
||||
run.o: run.c
|
||||
$(CC) $(run_CFLAGS) -c run.c
|
||||
|
||||
clean:
|
||||
$(RM) $(calendar_OBJS) $(fontsel_OBJS) $(run_OBJS)
|
||||
$(RM) $(calendar_OBJS) $(fontsel_OBJS) $(progress_OBJS) $(run_OBJS)
|
||||
|
||||
distclean: clean
|
||||
$(RM) $(TARGETS)
|
||||
|
@ -52,11 +61,13 @@ install: all
|
|||
$(MKDIR) $(DESTDIR)$(BINDIR)
|
||||
$(INSTALL) -m 0755 calendar $(DESTDIR)$(BINDIR)/calendar
|
||||
$(INSTALL) -m 0755 fontsel $(DESTDIR)$(BINDIR)/fontsel
|
||||
$(INSTALL) -m 0755 progress $(DESTDIR)$(BINDIR)/progress
|
||||
$(INSTALL) -m 0755 run $(DESTDIR)$(BINDIR)/run
|
||||
|
||||
uninstall:
|
||||
$(RM) $(DESTDIR)$(BINDIR)/calendar
|
||||
$(RM) $(DESTDIR)$(BINDIR)/fontsel
|
||||
$(RM) $(DESTDIR)$(BINDIR)/progress
|
||||
$(RM) $(DESTDIR)$(BINDIR)/run
|
||||
|
||||
.PHONY: all clean distclean install uninstall
|
||||
|
|
215
src/progress.c
Normal file
215
src/progress.c
Normal file
|
@ -0,0 +1,215 @@
|
|||
/* $Id$ */
|
||||
/* Copyright (c) 2007 Pierre Pronchery <khorben@defora.org> */
|
||||
/* This file is part of DeforaOS Desktop Accessories */
|
||||
/* Accessories is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License version 2 as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* Accessories 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
|
||||
* Accessories; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
/* TODO:
|
||||
* - speed estimation
|
||||
* - implement -z
|
||||
* - separate preferences from internal data */
|
||||
|
||||
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
||||
/* types */
|
||||
typedef struct _Prefs
|
||||
{
|
||||
int flags;
|
||||
char * filename;
|
||||
size_t length;
|
||||
/* XXX internal data */
|
||||
int fd;
|
||||
int fds[2];
|
||||
pid_t pid;
|
||||
GtkWidget * progress;
|
||||
} Prefs;
|
||||
#define PREFS_z 0x1
|
||||
|
||||
|
||||
/* progress */
|
||||
/* functions */
|
||||
static int _progress_error(char const * message, int ret);
|
||||
static int _progress_exec(Prefs * prefs, char * argv[]);
|
||||
|
||||
/* callbacks */
|
||||
static gboolean _progress_out(GIOChannel * source, GIOCondition condition,
|
||||
gpointer data);
|
||||
|
||||
static int _progress(Prefs * prefs, char * argv[])
|
||||
{
|
||||
struct stat st;
|
||||
GIOChannel * channel;
|
||||
GtkWidget * window = NULL;
|
||||
GtkWidget * vbox;
|
||||
GtkWidget * widget;
|
||||
|
||||
if(prefs->filename == NULL)
|
||||
prefs->filename = "Standard input";
|
||||
else if((prefs->fd = open(prefs->filename, O_RDONLY)) < 0)
|
||||
return _progress_error(prefs->filename, 1);
|
||||
else if(fstat(prefs->fd, &st) == 0)
|
||||
prefs->length = st.st_size;
|
||||
if(pipe(prefs->fds) != 0)
|
||||
{
|
||||
close(prefs->fd);
|
||||
return _progress_error("pipe", 1);
|
||||
}
|
||||
channel = g_io_channel_unix_new(prefs->fds[1]);
|
||||
g_io_add_watch(channel, G_IO_OUT, _progress_out, prefs);
|
||||
if((prefs->pid = fork()) == -1)
|
||||
{
|
||||
close(prefs->fd);
|
||||
close(prefs->fds[0]);
|
||||
close(prefs->fds[1]);
|
||||
return _progress_error("fork", 1);
|
||||
}
|
||||
if(prefs->pid != 0)
|
||||
return _progress_exec(prefs, argv);
|
||||
close(prefs->fds[0]);
|
||||
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title(GTK_WINDOW(window), "Progress");
|
||||
vbox = gtk_vbox_new(FALSE, 0);
|
||||
widget = gtk_label_new(prefs->filename);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), widget, TRUE, TRUE, 4);
|
||||
prefs->progress = gtk_progress_bar_new();
|
||||
gtk_box_pack_start(GTK_BOX(vbox), prefs->progress, TRUE, TRUE, 4);
|
||||
gtk_container_add(GTK_CONTAINER(window), vbox);
|
||||
gtk_container_set_border_width(GTK_CONTAINER(window), 4);
|
||||
gtk_widget_show_all(window);
|
||||
gtk_main();
|
||||
close(prefs->fd);
|
||||
close(prefs->fds[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _progress_error(char const * message, int ret)
|
||||
{
|
||||
GtkWidget * dialog;
|
||||
|
||||
dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s: %s",
|
||||
message, strerror(errno));
|
||||
gtk_window_set_title(GTK_WINDOW(dialog), "Error");
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int _progress_exec(Prefs * prefs, char * argv[])
|
||||
{
|
||||
close(prefs->fds[1]);
|
||||
if(dup2(prefs->fds[0], 0) == -1)
|
||||
exit(1); /* FIXME warn user */
|
||||
execvp(argv[0], argv);
|
||||
/* FIXME warn user */
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
/* callbacks */
|
||||
static gboolean _progress_out(GIOChannel * source, GIOCondition condition,
|
||||
gpointer data)
|
||||
{
|
||||
static size_t cnt = 0;
|
||||
Prefs * prefs = data;
|
||||
char buf[BUFSIZ];
|
||||
ssize_t len;
|
||||
gsize written;
|
||||
gdouble fraction;
|
||||
|
||||
/* FIXME use g_io_channel_read too? */
|
||||
if(condition != G_IO_OUT
|
||||
|| (len = read(prefs->fd, buf, sizeof(buf))) < 0)
|
||||
{
|
||||
gtk_main_quit();
|
||||
_progress_error(prefs->filename, 0);
|
||||
return FALSE;
|
||||
}
|
||||
if(g_io_channel_write(source, buf, len, &written) != G_IO_ERROR_NONE
|
||||
|| written != (gsize)len)
|
||||
{
|
||||
/* FIXME it may just be that everything was not written
|
||||
* => put buffer and position in Prefs/Progress */
|
||||
gtk_main_quit();
|
||||
_progress_error(prefs->filename, 0);
|
||||
return FALSE;
|
||||
}
|
||||
cnt += len;
|
||||
if(prefs->length == 0 || cnt == 0)
|
||||
gtk_progress_bar_pulse(GTK_PROGRESS_BAR(prefs->progress));
|
||||
else
|
||||
{
|
||||
fraction = cnt;
|
||||
fraction /= prefs->length;
|
||||
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(prefs->progress),
|
||||
fraction);
|
||||
snprintf(buf, sizeof(buf), "%.1f%%", fraction * 100);
|
||||
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(prefs->progress),
|
||||
buf);
|
||||
}
|
||||
if(len == 0)
|
||||
{
|
||||
gtk_main_quit();
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* usage */
|
||||
static int _usage(void)
|
||||
{
|
||||
fputs("Usage: progress [-z][-f file][-l length][-p prefix]"
|
||||
" cmd [args...]\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* main */
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
Prefs prefs;
|
||||
int o;
|
||||
char * p;
|
||||
|
||||
memset(&prefs, 0, sizeof(prefs));
|
||||
gtk_init(&argc, &argv);
|
||||
while((o = getopt(argc, argv, "f:z")) != -1)
|
||||
switch(o)
|
||||
{
|
||||
case 'f':
|
||||
prefs.filename = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
prefs.length = strtol(optarg, &p, 0);
|
||||
/* FIXME check input validation */
|
||||
break;
|
||||
case 'z':
|
||||
prefs.flags |= PREFS_z; /* FIXME implement */
|
||||
break;
|
||||
default:
|
||||
return _usage();
|
||||
}
|
||||
if(argc - optind < 1)
|
||||
return _usage();
|
||||
return _progress(&prefs, &argv[optind]) == 0 ? 0 : 2;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
targets=calendar,fontsel,run
|
||||
targets=calendar,fontsel,progress,run
|
||||
cflags_force=-W -Wall -ansi `pkg-config gtk+-2.0 --cflags`
|
||||
cflags=-g
|
||||
ldflags_force=`pkg-config gtk+-2.0 --libs`
|
||||
|
@ -12,6 +12,10 @@ sources=calendar.c
|
|||
type=binary
|
||||
sources=fontsel.c
|
||||
|
||||
[progress]
|
||||
type=binary
|
||||
sources=progress.c
|
||||
|
||||
[run]
|
||||
type=binary
|
||||
sources=run.c
|
||||
|
|
Loading…
Reference in New Issue
Block a user