/* WebDownloader for X-Window
* Copyright (C) 1999-2002 Koshelev Maxim
* This Program is free but not GPL!!! You can't modify it
* without agreement with author. You can't distribute modified
* program but you can distribute unmodified program.
*
* 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.
*/
#include <stdio.h>
#include <time.h>
#include "dndtrash.h"
#include "misc.h"
#include "prefs.h"
#include "lod.h"
#include "addd.h"
#include "list.h"
#include "graph.h"
#include "buttons.h"
#include "colors.h"
#include "../main.h"
#include "../var.h"
#include "../ntlocale.h"
#include "../xml.h"
#include <themes.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
extern GtkTargetEntry download_drop_types[];
extern gint n_download_drop_types;
enum DND_MENU_ENUM{
DM_NEW,
DM_PASTE,
DM_AUTOMATED,
DM_DELCOMPLETED,
DM_OPTIONS,
DM_SPEED, DM_SPEED_1, DM_SPEED_2, DM_SPEED_3,
DM_EXIT,
DM_SEP
};
//GtkItemFactory *dnd_trash_item_factory;
GtkUIManager *dnd_trash_ui_manager;
GtkWidget *dnd_trash_window=(GtkWidget *)NULL;
GtkWidget *dnd_trash_menu=(GtkWidget *)NULL;
GtkWidget *dnd_trash_gtk_pixmap; //used for animation/blinking
GtkWidget *dnd_trash_fixed;
GtkWidget *dnd_basket_graph=(GtkWidget *)NULL;;
d4xDownloadQueue *dnd_trash_target_queue=(d4xDownloadQueue *)NULL;
static GdkPixbuf *dnd_trash_pixbuf1=(GdkPixbuf *)NULL,*dnd_trash_pixbuf2=(GdkPixbuf *)NULL;
static GdkBitmap *dnd_trash_mask1=(GdkBitmap*)NULL,*dnd_trash_mask2=(GdkBitmap*)NULL;
static int dnd_trash_raise_count=0;
static time_t dnd_trash_last_raise=0;
GtkTooltips *dnd_trash_tooltips=(GtkTooltips *)NULL;
static gint dnd_trash_moveable,dnd_trash_x,dnd_trash_y,dnd_trash_move_x,dnd_trash_move_y;
static GtkTooltips *dnd_trash_speed_tooltips[2];
static GtkWidget *dnd_trash_speed_menu[2];
char *dnd_trash_tooltip_text=NULL;
float dnd_trash_tooltip_percent=0;
void dnd_trash_set_speed_text(){
char text[MAX_LEN];
if (dnd_trash_speed_menu[0]){
sprintf(text,"%i B/s",CFG.SPEED_LIMIT_1);
gtk_tooltips_set_tip(dnd_trash_speed_tooltips[0],
dnd_trash_speed_menu[0],
text,
(const gchar *)NULL);
};
if (dnd_trash_speed_menu[1]){
sprintf(text,"%i B/s",CFG.SPEED_LIMIT_2);
gtk_tooltips_set_tip(dnd_trash_speed_tooltips[1],
dnd_trash_speed_menu[1],
text,
(const gchar *)NULL);
};
};
/*
static gint dnd_trash_tooltips_draw(GtkWidget *window,GtkTooltips *tooltip){
if (dnd_trash_tooltip_percent<=0.001) return(FALSE);
GtkStyle *style=dnd_trash_tooltips->tip_window->style;
gint y, baseline_skip, gap,pwidth;
GtkTooltipsData *data = dnd_trash_tooltips->active_tips_data;
if (!data) return FALSE;
GdkFont *font=gtk_style_get_font(style);
gap = (font->ascent + font->descent) / 4;
if (gap < 2) gap = 2;
baseline_skip = font->ascent + font->descent + gap;
y = font->ascent + 4;
pwidth=gint(window->allocation.width*(dnd_trash_tooltip_percent/100));
gtk_paint_flat_box(style, window->window,
GTK_STATE_ACTIVE, GTK_SHADOW_NONE,
NULL, window, "tooltip",
0, 0, pwidth, window->allocation.height);
GdkGC *pr_gc=style->fg_gc[GTK_STATE_ACTIVE];
GdkRectangle clip_rectangle;
clip_rectangle.x=0;
clip_rectangle.y=0;
clip_rectangle.height=window->allocation.height;
clip_rectangle.width=pwidth;
gdk_gc_set_clip_rectangle (pr_gc, &clip_rectangle);
gdk_draw_string (window->window, font, pr_gc,
4,y,(char*)(data->row->data));
gdk_gc_set_clip_rectangle (pr_gc, (GdkRectangle *)NULL);
return(FALSE);
};
*/
static void dnd_trash_init_speed_tips(){
char *menu_path[]={
"/DndTrash/Speed/speedlow",
"/DndTrash/Speed/speedmedium"};
for(int i=0;i<sizeof(menu_path)/sizeof(char*);i++){
GtkWidget *menu_item=gtk_ui_manager_get_widget(dnd_trash_ui_manager,menu_path[i]);
dnd_trash_speed_menu[i]=menu_item;
if (menu_item){
GtkTooltips *tooltip=gtk_tooltips_new();
dnd_trash_speed_tooltips[i]=tooltip;
gtk_tooltips_force_window(tooltip);
GtkStyle *current_style=gtk_style_copy(gtk_widget_get_style(tooltip->tip_window));
current_style->bg[GTK_STATE_NORMAL] = LYELLOW;
gtk_widget_set_style(tooltip->tip_window, current_style);
g_object_unref(G_OBJECT(current_style));
gtk_tooltips_enable(tooltip);
};
};
dnd_trash_set_speed_text();
};
void dnd_trash_real_destroy(){
if (dnd_trash_window){
main_window_popup();
gtk_widget_destroy(dnd_trash_window);
dnd_trash_window=(GtkWidget *)NULL;
};
CFG.DND_TRASH=0;
};
void dnd_trash_destroy(){
dnd_trash_real_destroy();
set_dndtrash_button();
};
static GtkWidget *dnd_trash_current_item=NULL;
static int dnd_drag_motion_first=1;
static void dnd_trash_overmenu_populate(tQueue *q,GtkWidget *box,int depth=0){
d4xDownloadQueue *dq=(d4xDownloadQueue *)(q->first());
while(dq){
int len=2*depth;
char *space=new char[len+1];
space[len]=0;
for (int i=0;i<len;i++) space[i]=' ';
char *str=sum_strings(space,dq->name.get(),NULL);
delete[] space;
GtkWidget *menu_item=gtk_menu_item_new_with_label(str);
delete[] str;
g_object_set_data(G_OBJECT(menu_item),"d4x_user_data",dq);
gtk_box_pack_start(GTK_BOX(box),menu_item,FALSE,FALSE,0);
gtk_widget_show(menu_item);
dnd_trash_overmenu_populate(&(dq->child),box,depth+1);
dq=(d4xDownloadQueue *)(dq->prev);
};
};
static GtkWidget *dnd_trash_overmenu=NULL;
void dnd_trash_switch_to_menu(){
dnd_trash_current_item=NULL;
gtk_widget_shape_combine_mask(dnd_trash_window,NULL,0,0);
gtk_widget_ref(dnd_trash_fixed);
gtk_container_remove(GTK_CONTAINER(dnd_trash_window),dnd_trash_fixed);
dnd_trash_overmenu=gtk_vbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(dnd_trash_window),dnd_trash_overmenu);
gtk_container_set_border_width(GTK_CONTAINER(dnd_trash_window),2);
gtk_widget_show(dnd_trash_overmenu);
dnd_trash_overmenu_populate(&D4X_QTREE,dnd_trash_overmenu);
};
void dnd_trash_switch_to_icon(){
gint width,height;
gtk_widget_destroy(dnd_trash_overmenu);
gtk_container_add(GTK_CONTAINER(dnd_trash_window), dnd_trash_fixed);
gtk_container_set_border_width(GTK_CONTAINER(dnd_trash_window),0);
if (CFG.GRAPH_ON_BASKET==0){
gtk_image_set_from_pixbuf(GTK_IMAGE(dnd_trash_gtk_pixmap),
dnd_trash_pixbuf1);
width=gdk_pixbuf_get_width(dnd_trash_pixbuf1);
height=gdk_pixbuf_get_width(dnd_trash_pixbuf1);
gtk_widget_shape_combine_mask(dnd_trash_window, dnd_trash_mask1, 0, 0 );
gtk_window_resize(GTK_WINDOW(dnd_trash_window),width,height);
};
gtk_widget_unref(dnd_trash_fixed);
};
static void d4x_menuitem_foreach1(GtkWidget *widget,gpointer data){
if (GTK_IS_MENU_ITEM (widget)){
GtkWidget **w=(GtkWidget **)data;
gint x,y;
gtk_widget_get_pointer(widget,&x,&y);
if (y>0 && y<=widget->allocation.height)
*w=widget;
};
};
static GtkWidget *d4x_dnd_get_item(GtkWidget *dnd_trash_overmenu){
GtkWidget *rval=NULL;
gtk_container_foreach(GTK_CONTAINER (dnd_trash_overmenu),d4x_menuitem_foreach1,&rval);
return(rval);
};
static gboolean dnd_drag_motion (GtkWidget *widget,
GdkDragContext *context,
gint x,gint y,
guint time,
gpointer data){
if (dnd_drag_motion_first){
if (d4x_only_one_queue()) return(TRUE);
dnd_drag_motion_first=0;
dnd_trash_target_queue=NULL;
dnd_trash_switch_to_menu();
return(TRUE);
};
GtkWidget *menu_item=d4x_dnd_get_item(dnd_trash_overmenu);
if (dnd_trash_current_item!=menu_item &&
dnd_trash_current_item)
gtk_menu_item_deselect(GTK_MENU_ITEM(dnd_trash_current_item));
if (menu_item){
gtk_menu_item_select(GTK_MENU_ITEM(menu_item));
dnd_trash_target_queue=(d4xDownloadQueue *)g_object_get_data(G_OBJECT(menu_item),"d4x_user_data");
dnd_trash_current_item=menu_item;
};
return(TRUE);
};
static gboolean dnd_drag_leave (GtkWidget *widget,
GdkDragContext *context,
gint x,gint y,
guint time,
gpointer data){
if (!dnd_drag_motion_first){
dnd_drag_motion_first=1;
dnd_trash_switch_to_icon();
return(TRUE);
};
return(TRUE);
};
void dnd_trash_motion(GtkWidget *widget,GdkEventMotion *event){
if (dnd_trash_moveable){
gint mx,my;
GdkModifierType modmask;
gdk_window_get_pointer((GdkWindow *)NULL, &mx, &my, &modmask);
dnd_trash_move_x+=mx-dnd_trash_x;
dnd_trash_move_y+=my-dnd_trash_y;
gdk_window_move(widget->window,
dnd_trash_move_x,
dnd_trash_move_y);
dnd_trash_x=mx;
dnd_trash_y=my;
gdk_flush();
};
};
void dnd_trash_menu_popdown(GdkEventButton *event){
gtk_menu_popup(GTK_MENU(dnd_trash_menu),
(GtkWidget *)NULL,
(GtkWidget *)NULL,
(GtkMenuPositionFunc)NULL,
(gpointer)NULL,
event->button,event->time);
};
int dnd_trash_button_press(GtkWidget *widget,GdkEventButton *event){
switch (event->button){
case 3:{
CFG.DND_NEED_POPUP=0;
dnd_trash_menu_popdown(event);
break;
};
case 1:{
if (event->type==GDK_2BUTTON_PRESS)
main_window_toggle();
else{
if (!dnd_trash_moveable){
dnd_trash_move_x=CFG.DND_TRASH_X;
dnd_trash_move_y=CFG.DND_TRASH_Y;
dnd_trash_moveable=1;
dnd_trash_x=gint(event->x_root);
dnd_trash_y=gint(event->y_root);
gtk_grab_add (widget);
gdk_pointer_grab (widget->window,TRUE,
GdkEventMask(GDK_BUTTON_RELEASE_MASK |
GDK_BUTTON_MOTION_MASK |
GDK_POINTER_MOTION_HINT_MASK),
NULL, NULL, 0);
};
};
break;
};
case 2:{
init_add_window();
break;
};
};
return 1;
};
int dnd_trash_button_release(GtkWidget *widget,GdkEventButton *event){
gdk_pointer_ungrab(GDK_CURRENT_TIME);
gdk_flush();
dnd_trash_moveable=0;
gtk_grab_remove (widget);
gdk_pointer_ungrab (0);
return 1;
};
static int dnd_trash_no_expose(){
if (CFG.DND_NEED_POPUP && dnd_trash_window){
time_t now=time(NULL);
if (now == dnd_trash_last_raise)
dnd_trash_raise_count+=1;
else{
dnd_trash_last_raise=now;
dnd_trash_raise_count=1;
};
if (dnd_trash_raise_count<15)
gdk_window_raise(dnd_trash_window->window);
};
return TRUE;
};
static int dnd_trash_configure(GtkWidget *window){
// gdk_window_get_root_origin (window->window, &(CFG.DND_TRASH_X),
// &(CFG.DND_TRASH_Y));
gdk_window_get_position(window->window,&(CFG.DND_TRASH_X),
&(CFG.DND_TRASH_Y));
return(FALSE);
};
/*
static GdkPixbuf *dnd_trash_scale(GdkPixbuf *pixbuf){
int temp,w,h;
gdk_window_get_geometry((GdkWindow *)NULL,&temp,&temp,&w,&h,&temp);
if (w<2048){
float ratio=float(w)/2048.0;
w=gdk_pixbuf_get_width(pixbuf);
h=gdk_pixbuf_get_height(pixbuf);
GdkPixbuf *rval=gdk_pixbuf_scale_simple(pixbuf,gint(float(w)*ratio),gint(float(h)*ratio),GDK_INTERP_HYPER);
gdk_pixbuf_unref(pixbuf);
return(rval);
};
return(pixbuf);
};
*/
void dnd_trash_destroy_theme(){
if (dnd_trash_pixbuf1){
gdk_pixbuf_unref(dnd_trash_pixbuf1);
dnd_trash_pixbuf1=NULL;
};
if (dnd_trash_pixbuf2){
gdk_pixbuf_unref(dnd_trash_pixbuf2);
dnd_trash_pixbuf2=NULL;
};
dnd_trash_tooltip_text=NULL;
if (dnd_trash_tooltips){
gtk_object_destroy(GTK_OBJECT(dnd_trash_tooltips));
dnd_trash_tooltips=NULL;
};
};
void dnd_trash_init(){
CFG.DND_TRASH=1;
CFG.DND_NEED_POPUP=1;
if (dnd_trash_window) return;
dnd_trash_moveable=0;
#include "pixmaps/dndtrash.xpm"
#include "pixmaps/dndtrashi.xpm"
/* GtkWidget is the storage type for widgets */
GtkWidget *pixmap;
GtkStyle *style;
// dnd_trash_window = gtk_window_new( GTK_WINDOW_POPUP );
dnd_trash_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_stick(GTK_WINDOW(dnd_trash_window));
// gtk_window_set_type_hint (GTK_WINDOW(dnd_trash_window),
// GDK_WINDOW_TYPE_HINT_DIALOG);
// gtk_window_set_type_hint (GTK_WINDOW(dnd_trash_window),
// GDK_WINDOW_TYPE_HINT_NORMAL);
gtk_window_set_resizable(GTK_WINDOW(dnd_trash_window),FALSE);
gtk_window_set_wmclass(GTK_WINDOW(dnd_trash_window),"D4X_DnDBasket","D4X");
gtk_window_set_title(GTK_WINDOW (dnd_trash_window), _("DnD basket"));
gtk_widget_set_events(dnd_trash_window,
gtk_widget_get_events(dnd_trash_window) |
GDK_FOCUS_CHANGE_MASK |
GDK_BUTTON_MOTION_MASK |
GDK_POINTER_MOTION_MASK |
GDK_POINTER_MOTION_HINT_MASK |
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_STRUCTURE_MASK |
GDK_VISIBILITY_NOTIFY_MASK |
GDK_EXPOSURE_MASK);
/* create pixmaps first
*/
gint width=0,height=0;
gtk_widget_realize(dnd_trash_window);
gtk_window_set_keep_above (GTK_WINDOW(dnd_trash_window),TRUE);
gtk_window_set_skip_taskbar_hint (GTK_WINDOW(dnd_trash_window),TRUE);
gtk_window_set_skip_pager_hint(GTK_WINDOW(dnd_trash_window),TRUE);
gtk_window_set_accept_focus(GTK_WINDOW(dnd_trash_window),FALSE);
// wm_skip_window(dnd_trash_window);
if (dnd_trash_pixbuf1==NULL){
dnd_trash_pixbuf1=pixbuf_from_theme("dndbasket icon>file",(const char**)dndtrash_xpm);
dnd_trash_pixbuf2=pixbuf_from_theme("dndbasket dropicon>file",(const char**)dndtrashi_xpm);
gdk_pixbuf_ref(dnd_trash_pixbuf2);
gdk_pixbuf_render_pixmap_and_mask(dnd_trash_pixbuf1,NULL,&dnd_trash_mask1,1);
gdk_bitmap_ref(dnd_trash_mask1);
gdk_pixbuf_render_pixmap_and_mask(dnd_trash_pixbuf2,NULL,&dnd_trash_mask2,1);
gdk_bitmap_ref(dnd_trash_mask2);
};
width=gdk_pixbuf_get_width(dnd_trash_pixbuf1);
height=gdk_pixbuf_get_width(dnd_trash_pixbuf1);
d4x_normalize_coords(&(CFG.DND_TRASH_X),&(CFG.DND_TRASH_Y),width,height);
gtk_window_move(GTK_WINDOW(dnd_trash_window), gint(CFG.DND_TRASH_X),gint(CFG.DND_TRASH_Y));
/* Create the main window, and attach delete_event signal to terminate
* the application. Note that the main window will not have a titlebar
* since we're making it a popup. */
// gtk_window_set_transient_for(GTK_WINDOW(dnd_trash_window), GTK_WINDOW(MainWindow));
gtk_window_set_default_size(GTK_WINDOW(dnd_trash_window),width,height);
// gtk_widget_set_events(dnd_trash_window,GDK_ALL_EVENTS_MASK);
g_signal_connect(G_OBJECT (dnd_trash_window), "delete_event",
G_CALLBACK (dnd_trash_destroy), NULL);
g_signal_connect(G_OBJECT (dnd_trash_window), "motion_notify_event",
G_CALLBACK (dnd_trash_motion), NULL);
g_signal_connect(G_OBJECT (dnd_trash_window), "button_press_event",
G_CALLBACK (dnd_trash_button_press), NULL);
g_signal_connect(G_OBJECT (dnd_trash_window), "button_release_event",
G_CALLBACK (dnd_trash_button_release), NULL);
g_signal_connect(G_OBJECT(dnd_trash_window),
"drag_data_received",
G_CALLBACK(list_dnd_drop_internal),
NULL);
g_signal_connect(G_OBJECT (dnd_trash_window), "drag_leave",
G_CALLBACK (dnd_drag_leave), NULL);
g_signal_connect(G_OBJECT (dnd_trash_window),"drag_motion",
G_CALLBACK (dnd_drag_motion),NULL);
gtk_drag_dest_set(GTK_WIDGET(dnd_trash_window),
(GtkDestDefaults)(GTK_DEST_DEFAULT_MOTION |
GTK_DEST_DEFAULT_HIGHLIGHT |
GTK_DEST_DEFAULT_DROP),
download_drop_types, n_download_drop_types,
(GdkDragAction)(GDK_ACTION_COPY|GDK_ACTION_MOVE));
g_signal_connect(G_OBJECT(dnd_trash_window), "visibility_notify_event",
G_CALLBACK(dnd_trash_no_expose),
dnd_trash_window);
g_signal_connect(G_OBJECT(dnd_trash_window), "no_expose_event",
G_CALLBACK(dnd_trash_no_expose),
dnd_trash_window);
gtk_widget_realize(dnd_trash_window);
gdk_window_set_decorations(dnd_trash_window->window,GdkWMDecoration(0));
gtk_widget_show (dnd_trash_window);
/* Now for the pixmap and the pixmap widget */
// gtk_widget_show( pixmap );
/* To display the pixmap, we use a fixed widget to place the pixmap */
dnd_trash_fixed = gtk_fixed_new();
// gtk_widget_set_usize( dnd_trash_fixed, width, height );
// gtk_event_box_new();
if (dnd_basket_graph==NULL){
dnd_basket_graph=my_gtk_graph_new();
D4X_DND_GRAPH=(MyGtkGraph *)dnd_basket_graph;
D4X_DND_GRAPH->show_speed=CFG.SHOW_SPEED_ON_BASKET;
D4X_DND_GRAPH->show_offline=1;
D4X_DND_GRAPH->GlobalM=GraphMeter;
D4X_DND_GRAPH->LocalM=GraphLMeter;
gtk_widget_ref(dnd_basket_graph);
gtk_widget_set_size_request(dnd_basket_graph,50,50);
};
if (CFG.GRAPH_ON_BASKET)
gtk_fixed_put( GTK_FIXED(dnd_trash_fixed), dnd_basket_graph, 0, 0);
else{
dnd_trash_gtk_pixmap = pixmap = gtk_image_new_from_pixbuf(dnd_trash_pixbuf1);
gtk_fixed_put( GTK_FIXED(dnd_trash_fixed), pixmap, 0, 0 );
};
gtk_container_add( GTK_CONTAINER(dnd_trash_window), dnd_trash_fixed );
gtk_widget_show_all( dnd_trash_fixed );
d4xXmlObject *xmltip=d4x_xml_find_obj(D4X_THEME_DATA,"dndbasket tooltip");
if (dnd_trash_tooltips==NULL){
dnd_trash_tooltips=gtk_tooltips_new();
gtk_tooltips_force_window(dnd_trash_tooltips);
GtkStyle *current_style =gtk_style_copy(gtk_widget_get_style(dnd_trash_tooltips->tip_window));
/* FIXME: GTK2
g_signal_connect(G_OBJECT(dnd_trash_tooltips->tip_window), "draw",
G_CALLBACK(dnd_trash_tooltips_draw),NULL);
g_signal_connect(G_OBJECT(dnd_trash_tooltips->tip_window), "expose_event",
G_CALLBACK(dnd_trash_tooltips_draw),NULL);
*/
char *bgcolor=NULL,*fgcolor=NULL;
if (xmltip){
d4xXmlField *fld=NULL;
fld=xmltip->get_attr("bgcolor");
bgcolor=fld?fld->value.get():NULL;
fld=xmltip->get_attr("fgcolor");
fgcolor=fld?fld->value.get():NULL;
};
if (bgcolor){
gdk_color_parse(bgcolor,&(current_style->bg[GTK_STATE_NORMAL]));
current_style->fg[GTK_STATE_ACTIVE]=current_style->bg[GTK_STATE_NORMAL];
}else
current_style->bg[GTK_STATE_NORMAL]=current_style->fg[GTK_STATE_ACTIVE]=LYELLOW;
if (fgcolor)
gdk_color_parse(fgcolor,&(current_style->fg[GTK_STATE_NORMAL]));
current_style->bg[GTK_STATE_ACTIVE]=current_style->fg[GTK_STATE_NORMAL];
gtk_widget_set_style(dnd_trash_tooltips->tip_window, current_style);
};
if (xmltip){
dnd_trash_tooltip_text=xmltip->value.get();
}else
dnd_trash_tooltip_text=_("Drop link here");
gtk_tooltips_set_tip(dnd_trash_tooltips,
dnd_trash_window,
dnd_trash_tooltip_text,
(const gchar *)NULL);
gtk_tooltips_enable(dnd_trash_tooltips);
/* This mask cut out everything except the image */
if (dnd_trash_mask1 && CFG.GRAPH_ON_BASKET==0)
gtk_widget_shape_combine_mask( dnd_trash_window, dnd_trash_mask1,0,0);
/* show the window */
gtk_widget_show( dnd_trash_window );
gdk_window_resize(dnd_trash_window->window,width,height);
set_dndtrash_button();
gdk_window_move(dnd_trash_window->window,CFG.DND_TRASH_X,CFG.DND_TRASH_Y);
g_signal_connect(G_OBJECT(dnd_trash_window), "configure_event",
G_CALLBACK(dnd_trash_configure),
NULL);
gdk_window_set_functions(dnd_trash_window->window,GdkWMFunction(GDK_FUNC_MOVE|GDK_FUNC_CLOSE));
x_opacity_set(dnd_trash_window,(unsigned int)(0xffffffff*0.6));
};
static bool _no_speed_callback_dnd_=false;
void dnd_trash_menu_prepare(){
if (_no_speed_callback_dnd_) return;
_no_speed_callback_dnd_=true;
switch (CFG.SPEED_LIMIT){
case 1:{
GtkAction *action1=gtk_ui_manager_get_action(dnd_trash_ui_manager,"/DndTrash/Speed/speedlow");
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action1),TRUE);
break;
};
case 2:{
GtkAction *action2=gtk_ui_manager_get_action(dnd_trash_ui_manager,"/DndTrash/Speed/speedmedium");
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action2),TRUE);
break;
};
default:{
GtkAction *action3=gtk_ui_manager_get_action(dnd_trash_ui_manager,"/DndTrash/Speed/speedunlim");
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action3),TRUE);
};
};
GtkAction *action=gtk_ui_manager_get_action(dnd_trash_ui_manager,"/DndTrash/offline");
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action),CFG.OFFLINE_MODE?TRUE:FALSE);
g_object_set(G_OBJECT(action),"label",CFG.OFFLINE_MODE?_("Offline"):_("Online"),NULL);
_no_speed_callback_dnd_=false;
};
void dnd_trash_menu_callback(GtkAction *action){
if (_no_speed_callback_dnd_) return;
_no_speed_callback_dnd_=true;
CFG.SPEED_LIMIT=gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action))+1;
set_speed_buttons();
_no_speed_callback_dnd_=false;
};
static void dnd_trash_delete_completed(){
_aa_.del_completed();
};
void dnd_trash_set_del_completed(gint how){
GtkWidget *menu_item=gtk_ui_manager_get_widget(dnd_trash_ui_manager,"/DndTrash/delc");
if (menu_item)
gtk_widget_set_sensitive(menu_item,how);
};
void dnd_trash_offline(){
if (_no_speed_callback_dnd_) return;
_aa_.switch_offline_mode();
};
static gint dnd_trash_menu_umap(){
CFG.DND_NEED_POPUP=1;
dnd_trash_no_expose();
return(FALSE);
};
void dnd_trash_init_menu() {
static char *ui_info=
"<popup name='DndTrash'>"
" <menuitem action='new' />"
" <menuitem action='paste' />"
" <menuitem action='auto' />"
" <menuitem action='delc' />"
" <separator name='sep1' />"
" <menuitem action='props' />"
" <menu action='Speed'>"
" <menuitem action='speedlow' />"
" <menuitem action='speedmedium' />"
" <menuitem action='speedunlim' />"
" </menu>"
" <menuitem action='offline' />"
" <separator name='sep2' />"
" <menuitem action='exit' />"
"</popup>";
static GtkActionEntry entries[] = {
{ "DndTrash", NULL, "DnDTrash" },
{ "Speed", NULL, N_("Speed") },
{ "new", GTK_STOCK_NEW, N_("New Download"), NULL, "add new file to download", G_CALLBACK(init_add_window)},
{ "paste",GTK_STOCK_PASTE,N_("Paste Download"), NULL, "add new from clipboard", G_CALLBACK(init_add_clipboard_window)},
{ "auto",NULL,N_("Automated adding"), NULL, "automated adding many downloads", G_CALLBACK(d4x_automated_add)},
{ "delc",NULL,N_("Delete completed"), NULL, "remove completed downloads", G_CALLBACK(dnd_trash_delete_completed)},
{ "props",GTK_STOCK_PREFERENCES,N_("General options"), NULL, "open main preferences dialog", G_CALLBACK(d4x_prefs_init)},
{ "exit",GTK_STOCK_QUIT,N_("Exit"), NULL, "open main preferences dialog", G_CALLBACK(ask_exit)}
};
static GtkToggleActionEntry toggle_entries[]={
{ "offline",NULL,N_("Online"), NULL, "switch to or from offline mode", G_CALLBACK(dnd_trash_offline),FALSE}
};
static GtkRadioActionEntry radio_entries[] = {
{ "speedlow", NULL, N_("Low"), NULL, "set low traffic limitation", 0 },
{ "speedmedium", NULL, N_("Medium"), NULL, "set medium traffic limitation", 1 },
{ "speedunlim", NULL, N_("Unlimited"), NULL, "set unlimited speed", 2 }
};
GtkActionGroup *action_group = gtk_action_group_new ("QueueActions");
gtk_action_group_set_translate_func(action_group,d4x_menu_translate_func,NULL,NULL);
dnd_trash_ui_manager=gtk_ui_manager_new ();
gtk_action_group_add_actions (action_group, entries, G_N_ELEMENTS (entries), NULL);
gtk_action_group_add_toggle_actions (action_group, toggle_entries, G_N_ELEMENTS (toggle_entries), NULL);
gtk_action_group_add_radio_actions (action_group, radio_entries, G_N_ELEMENTS (radio_entries), CFG.SPEED_LIMIT-1, G_CALLBACK(dnd_trash_menu_callback), NULL);
gtk_ui_manager_insert_action_group (dnd_trash_ui_manager, action_group, 0);
GError *error = NULL;
if (!gtk_ui_manager_add_ui_from_string (dnd_trash_ui_manager, ui_info, -1, &error))
{
g_message ("building menus failed: %s", error->message);
g_error_free (error);
exit (EXIT_FAILURE);
}
dnd_trash_menu = gtk_ui_manager_get_widget (dnd_trash_ui_manager,"/DndTrash");
g_signal_connect(G_OBJECT (dnd_trash_menu), "unmap_event",
G_CALLBACK(dnd_trash_menu_umap), NULL);
dnd_trash_init_speed_tips();
};
static gint dnd_trash_animation_end(gpointer unused){
if (CFG.GRAPH_ON_BASKET) return 0;
gint width,height;
gtk_image_set_from_pixbuf(GTK_IMAGE(dnd_trash_gtk_pixmap),
dnd_trash_pixbuf1);
width=gdk_pixbuf_get_width(dnd_trash_pixbuf1);
height=gdk_pixbuf_get_height(dnd_trash_pixbuf1);
gdk_window_resize(dnd_trash_window->window,width,height);
gtk_widget_shape_combine_mask(dnd_trash_window, dnd_trash_mask1, 0, 0 );
/* draw NOW */
GdkRectangle rect;
rect.x=dnd_trash_gtk_pixmap->allocation.x;
rect.y=dnd_trash_gtk_pixmap->allocation.y;
rect.width=dnd_trash_gtk_pixmap->allocation.width;
rect.height=dnd_trash_gtk_pixmap->allocation.height;
gtk_widget_queue_draw(dnd_trash_gtk_pixmap);
return 0;
};
void dnd_trash_animation(){
if (CFG.GRAPH_ON_BASKET==0 && dnd_trash_window){
gint width,height;
gtk_image_set_from_pixbuf(GTK_IMAGE(dnd_trash_gtk_pixmap),
dnd_trash_pixbuf2);
width=gdk_pixbuf_get_width(dnd_trash_pixbuf2);
height=gdk_pixbuf_get_height(dnd_trash_pixbuf2);
gdk_window_resize(dnd_trash_window->window,width,height);
gtk_widget_shape_combine_mask(dnd_trash_window, dnd_trash_mask2,0, 0 );
GdkRectangle rect;
rect.x=dnd_trash_gtk_pixmap->allocation.x;
rect.y=dnd_trash_gtk_pixmap->allocation.y;
rect.width=dnd_trash_gtk_pixmap->allocation.width;
rect.height=dnd_trash_gtk_pixmap->allocation.height;
gtk_widget_queue_draw(dnd_trash_gtk_pixmap);
// gtk_widget_draw(dnd_trash_gtk_pixmap,&rect);
g_timeout_add (500, dnd_trash_animation_end , NULL);
};
};
void dnd_trash_set_tooltip(const char *str,float percent){
dnd_trash_tooltip_percent=percent;
if (str==NULL)
str=dnd_trash_tooltip_text;
if (str==NULL || dnd_trash_window==NULL) return;
gtk_tooltips_set_tip(dnd_trash_tooltips,
dnd_trash_window,
str,NULL);
};
void dnd_trash_redraw(){
gtk_widget_queue_draw(GTK_WIDGET(dnd_trash_window));
};
syntax highlighted by Code2HTML, v. 0.9.1