LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-13-2021, 08:22 PM   #16
CliveMcCarthy
LQ Newbie
 
Registered: Aug 2021
Posts: 13

Original Poster
Rep: Reputation: Disabled

My top Gtk window has a grid in it so having attached my image_strip[] widgets in event_boxes[] I then just hang the event_boxes[] in the grid ?
 
Old 08-13-2021, 08:27 PM   #17
EdGr
Member
 
Registered: Dec 2010
Location: California, USA
Distribution: I run my own OS
Posts: 691

Rep: Reputation: 329Reputation: 329Reputation: 329Reputation: 329
Yes, I think you understand how to solve this.
Ed
 
Old 08-13-2021, 08:36 PM   #18
CliveMcCarthy
LQ Newbie
 
Registered: Aug 2021
Posts: 13

Original Poster
Rep: Reputation: Disabled
It isn't liking:

gtk_container_add(GTK_CONTAINER(event_box[k]), image_strip[k]);

Last edited by CliveMcCarthy; 08-13-2021 at 08:39 PM.
 
Old 08-13-2021, 08:38 PM   #19
EdGr
Member
 
Registered: Dec 2010
Location: California, USA
Distribution: I run my own OS
Posts: 691

Rep: Reputation: 329Reputation: 329Reputation: 329Reputation: 329
What is the error message?
Ed
 
Old 08-13-2021, 08:43 PM   #20
CliveMcCarthy
LQ Newbie
 
Registered: Aug 2021
Posts: 13

Original Poster
Rep: Reputation: Disabled
it seg faults !


Code:
int main(int argc, char *argv[])
{
	GtkWidget *Steenbeck_isf_button;
	GtkWidget *input_directory_button, *output_directory_button;
	GtkWidget *console;
	GtkWidget *event_box[STRIP_COUNT];
	GtkWidget *image_strip[STRIP_COUNT];
	GtkWidget *mode_entry[STRIP_COUNT];
	char widget_name[10];
	int k;

	gtk_init(&argc, &argv);
	printf("Gtk+ version %d.%d\n", gtk_major_version, gtk_minor_version);
	initialize_film_strip_data();

	top_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	grid = gtk_grid_new();
	gtk_grid_set_row_spacing(GTK_GRID(grid), 2);
	gtk_grid_set_column_spacing(GTK_GRID(grid), 5);
	gtk_container_add(GTK_CONTAINER(top_window), grid);

	input_directory_button	= gtk_button_new_with_label("Select input folder");
	output_directory_button	= gtk_button_new_with_label("Select image folder");
	Steenbeck_isf_button	= gtk_button_new_with_label("Save Steenbeck isf");

	console = install_console(FRAME_WIDTH, FRAME_WIDTH, &console_text_view);

	for(k = 0; k < STRIP_COUNT; k++)
	{
		event_box[k] = gtk_event_box_new();
		//printf("ok here %d\n", k);
		gtk_container_add(GTK_CONTAINER(event_box[k]), image_strip[k]);
 
Old 08-13-2021, 08:48 PM   #21
EdGr
Member
 
Registered: Dec 2010
Location: California, USA
Distribution: I run my own OS
Posts: 691

Rep: Reputation: 329Reputation: 329Reputation: 329Reputation: 329
I don't see any problems in that code.

It is time for gdb. Good luck.

ETA: make sure the arrays are being initialized before gtk_container_add ().
Ed

Last edited by EdGr; 08-13-2021 at 09:03 PM.
 
Old 08-13-2021, 09:25 PM   #22
CliveMcCarthy
LQ Newbie
 
Registered: Aug 2021
Posts: 13

Original Poster
Rep: Reputation: Disabled
the debugger says "g_type_check_instance_is_a" so I suspect I have an erroneous cast. I'll hack away at it.

BTW, thank you for your patience in all this. I was quite surprised that I got the Caja-to-my-code-drop working so easily and figured a drag and drop within my code would be easier. Wrong.
 
Old 08-14-2021, 11:44 AM   #23
CliveMcCarthy
LQ Newbie
 
Registered: Aug 2021
Posts: 13

Original Poster
Rep: Reputation: Disabled
For anyone else that might pass this way here is a 'test' program that does basic drag-and-drop with a couple of buttons. You can drop anything on a button and drag from one button to the other. It uses event_boxes so that the buttons can receive events.

I'm indebted to the help I got here and to this:

https://wiki.gnome.org/action/show/N...gNDropTutorial


Code:
/*------------------------------------------------------------------------------

------------------------------------------------------------------------------*/
#include <gdk/gdk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <glib-object.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
#include <gtk/gtk.h>
#include <string.h>

#define ANSI_COLOR_RED		"\x1b[31m"
#define ANSI_COLOR_GREEN	"\x1b[32m"
#define ANSI_COLOR_RESET	"\x1b[0m"
#define __FUNC__ __func__

/*------------------------------------------------------------------------------

    TARGET_MATE_URI_LIST,
    TARGET_BACKGROUND_RESET,
------------------------------------------------------------------------------*/
#define _BYTE   8
#define _WORD   16
#define _DWORD  32
#define TEXT_BUFFER_SIZE	4097

enum
{
    TARGET_URI_LIST,
    TARGET_PLAIN,
    TARGET_COLOR,
    TARGET_BGIMAGE,
    TARGET_KEYWORD,
	TARGET_INT32,
	TARGET_STRING,
	TARGET_ROOTWIN,
};

// datatype(string), restrictions on DnD(GtkTargetFlags), datatype(int)
GtkTargetEntry target_list[] =
{
    {"text/uri-list",		0,	TARGET_URI_LIST},
    {"text/plain",			0, 	TARGET_PLAIN},
    {"application/x-color",	0,	TARGET_COLOR},
    {"property/bgimage",	0,	TARGET_BGIMAGE},
    {"property/keyword",	0,	TARGET_KEYWORD},
	{"INTEGER",				0,	TARGET_INT32 },
	{"STRING",	 			0,	TARGET_STRING },
	{"application/x-rootwindow-drop", 0, TARGET_ROOTWIN }
};
/*------------------------------------------------------------------------------

------------------------------------------------------------------------------*/
GtkWidget *top_window, *grid;
/*------------------------------------------------------------------------------

	gui_program_error_dialog_box(__FILE__, __LINE__, __FUNC__, "a test error");

------------------------------------------------------------------------------*/
void gui_program_error_dialog_box
(
	const char *path_file, int line, const char *function_name,
	const char *control, ...
)
{
	va_list parms;
	char text[TEXT_BUFFER_SIZE];
	const char *file;
	GtkWidget *dialog;

	va_start(parms, control);
	vsnprintf(text, TEXT_BUFFER_SIZE, control, parms);
	printf(ANSI_COLOR_RED"** error ** %-40s\n", text);
	file = (path_file);
	printf("(in file: %s at line: %d in function: %s)\n"ANSI_COLOR_RESET,
		file, line, function_name);

	dialog = gtk_message_dialog_new
	(
		GTK_WINDOW(top_window),
		GTK_DIALOG_MODAL,
		GTK_MESSAGE_ERROR,
		GTK_BUTTONS_CLOSE,
		"%s\nin function '%s'\nin file '%s' line %d",
			text, function_name, (path_file), line
	);

	gtk_window_set_title(GTK_WINDOW(dialog),
		"Okay, Houston, we've had a problem here.");

	gtk_dialog_run(GTK_DIALOG(dialog));
	gtk_widget_destroy(dialog);
	exit(EXIT_FAILURE);
	va_end(parms);
}
/*------------------------------------------------------------------------------
	gui_program_warning_dialog_box(__FILE__, __LINE__, __FUNC__, "a test error");

------------------------------------------------------------------------------*/
void gui_program_warning_dialog_box
(
	const char *path_file, int line, const char *function_name,
	const char *control, ...
)
{
	va_list parms;
	char text[TEXT_BUFFER_SIZE];
	const char *file;
	GtkWidget *dialog;

	va_start(parms, control);
	vsnprintf(text, TEXT_BUFFER_SIZE, control, parms);
	printf("** warning ** %-40s\n", text);
	file = (path_file);
	printf("(in file: %s at line: %d\nin function: %s)\n",
		file, line, function_name);

	dialog = gtk_message_dialog_new
	(
		GTK_WINDOW(top_window),
		GTK_DIALOG_MODAL,
		GTK_MESSAGE_WARNING,
		GTK_BUTTONS_CLOSE,
		"%s\nin function '%s'\nin file '%s' line %d",
			text, function_name, (path_file), line
	);

	gtk_window_set_title(GTK_WINDOW(dialog), "Oh dear! ");
	gtk_dialog_run(GTK_DIALOG(dialog));
	gtk_widget_destroy(dialog);
	va_end(parms);
}
/*------------------------------------------------------------------------------
	Emitted when DnD begins. This is often used to present custom graphics.
------------------------------------------------------------------------------*/
static void  drag_begin_handler
(
	GtkWidget *widget,
	__attribute__((unused))GdkDragContext *context,
	__attribute__((unused))gpointer user_data
)
{
	const gchar *name = gtk_widget_get_name(widget);
	printf("\n%s\t: drag_begin_handler\n", name);
}
/*------------------------------------------------------------------------------
	Emitted when DnD ends. This is used to clean up any leftover data.
------------------------------------------------------------------------------*/
static void  drag_end_handler
(
	GtkWidget *widget,

	__attribute__((unused))GdkDragContext *context,
	__attribute__((unused))gpointer user_data
)
{
	const gchar *name = gtk_widget_get_name(widget);
	printf("%s\t: drag_end_handler\n\n", name);
}
/*------------------------------------------------------------------------------
	Emitted when a drag is over the destination
------------------------------------------------------------------------------*/
gboolean drag_motion_handler
(
	__attribute__((unused))GtkWidget *widget,
	__attribute__((unused))GdkDragContext *context,
	__attribute__((unused))gint x,
	__attribute__((unused))gint y,
	__attribute__((unused))guint t,
	__attribute__((unused))gpointer user_data
)
{
	const gchar *name = gtk_widget_get_name(widget);
	printf("%s\t: drag_motion_handler\n", name);
	return  FALSE;
}
/*------------------------------------------------------------------------------
	Emitted when a drag leaves the destination
------------------------------------------------------------------------------*/
static void drag_leave_handler
(
	__attribute__((unused))GtkWidget *widget,
	__attribute__((unused))GdkDragContext *context,
	__attribute__((unused))guint time,
	__attribute__((unused))gpointer user_data
)
{
	const gchar *name = gtk_widget_get_name(widget);
	printf("%s\t: drag_leave_handler\n", name);
}
/*------------------------------------------------------------------------------
	Emitted when the user releases(drops) the selection. It should check that
	the drop is over a valid part of the widget(if its a complex widget), and
	itself to return true if the operation should continue. Next choose the
	target type it wishes to ask the source for. Finally call gtk_drag_get_data
	which will emit "drag-data-get" on the source.
------------------------------------------------------------------------------*/
gboolean drag_drop_handler
(
	GtkWidget *widget, GdkDragContext *context,
	__attribute__((unused))gint x,
	__attribute__((unused))gint y, guint time,
	__attribute__((unused))gpointer user_data
)
{
	gboolean	is_valid_drop_site;
	GdkAtom		target_type;
	gpointer	target_data;

	const gchar *name = gtk_widget_get_name(widget);
	printf("%s\t: drag_drop_handler\n", name);

	/* Check to see if(x,y) is a valid drop site within widget */
	is_valid_drop_site = TRUE;

	/* If the source offers a target */
	if(gdk_drag_context_list_targets(context))
	{
		target_data = g_list_nth_data
		(
			gdk_drag_context_list_targets(context),
			TARGET_INT32
		);

		/* Choose the best target type */
		target_type = GDK_POINTER_TO_ATOM(target_data);

		/* Request the data from the source. */
		gtk_drag_get_data
		(
			widget,		 /* will receive 'drag-data-received' signal */
			context,		/* represents the current state of the DnD */
			target_type,	/* the target type we want */
			time			/* time stamp */
		);
	}
	else	/* No target offered by source => error */
	{
		printf("%s\t: No target offered by source\n", name);
		is_valid_drop_site = FALSE;
	}

	return  is_valid_drop_site;
}
/*------------------------------------------------------------------------------
	Emitted when the data has been received from the source. It should check
	the GtkSelectionData sent by the source, and do something with it. Finally
	it needs to finish the operation by calling gtk_drag_finish, which will emit
	the "data-delete" signal if told to.
------------------------------------------------------------------------------*/
void drag_data_received_handler
(
	GtkWidget *widget, GdkDragContext *context,
	__attribute__((unused))gint x,
	__attribute__((unused))gint y,
	GtkSelectionData *selection_data, guint target_type, guint time,
	__attribute__((unused))gpointer data
)
{
	glong   *idata;
	gchar   *sdata;

	gboolean dnd_success = FALSE;
	gboolean delete_selection_data = FALSE;

	const gchar *name = gtk_widget_get_name(widget);
	printf("%s\t: drag_data_received_handler\n", name);

	/* Deal with what we are given from source */
	if((selection_data != NULL)
	&& (gtk_selection_data_get_length(selection_data) >= 0))
	{
		if(gdk_drag_context_get_suggested_action(context) == GDK_ACTION_MOVE)
				delete_selection_data = TRUE;

		// Check that we got the format we can use
		printf(ANSI_COLOR_GREEN"receiving\n"ANSI_COLOR_RESET);
		switch(target_type)
		{
			case TARGET_URI_LIST:
				printf("TARGET_URI_LIST\t: %s\n", name);
				dnd_success = TRUE;
			break;

			case TARGET_INT32:
				idata =(glong*)gtk_selection_data_get_data(selection_data);
				printf("integer\t\t: %ld\n", *idata);
				dnd_success = TRUE;
			break;

			case TARGET_STRING:
				sdata =(gchar*)gtk_selection_data_get_data(selection_data);
				printf("string\t\t: %s\n", sdata);
				dnd_success = TRUE;
			break;

			default:
			gui_program_warning_dialog_box
			(
				__FILE__, __LINE__, __FUNC__,
				"default drag_data_received_handler\n"
			);
		}
	}

	if(dnd_success == FALSE)
	{
		printf("dnd data transfer failed\n");
		gui_program_warning_dialog_box
		(
			__FILE__, __LINE__, __FUNC__,
			"dnd data transfer failed\n"
		);
	}

	gtk_drag_finish(context, dnd_success, delete_selection_data, time);
}
/*------------------------------------------------------------------------------
	Emitted when the destination requests data from the source via
	gtk_drag_get_data. It should attempt to provide its data in the form
	requested in the target_type passed to it from the destination. If it cannot,
	it should default to a "safe" type such as a string or text, even if only to
	print an error. Then use gtk_selection_data_set to put the source data into
	the allocated selection_data object, which will then be passed to the
	destination. This will cause "drag-data-received" to be emitted on the
	destination. GdkSelectionData is based on X's selection mechanism which,
	via X properties, is only capable of storing data in blocks of 8, 16, or
	32 bit units.
------------------------------------------------------------------------------*/
void drag_data_transmit_handler
(
	GtkWidget *widget,
	__attribute__((unused))GdkDragContext *context, GtkSelectionData *selection_data,
	guint target_type,
	__attribute__((unused))guint time,
	__attribute__((unused))gpointer user_data
)
{
	const gchar *name = gtk_widget_get_name(widget);
	const gchar *string_data = "This is data from the source.";
	const glong integer_data = 42;

	printf("%s\t: drag_data_transmit_handler\n", name);
	g_assert(selection_data != NULL);

	printf(ANSI_COLOR_GREEN"sending\n"ANSI_COLOR_RESET);
	switch(target_type)
	{
		case TARGET_URI_LIST:
		// URIs have their own convenience setter functions
		printf("TARGET_URI_LIST\t: %s\n", name);
		break;

		case TARGET_INT32:
		printf("integer\t\t: %ld\n", integer_data);
		gtk_selection_data_set
		(
			selection_data,		 /* Allocated GdkSelectionData object */
			gtk_selection_data_get_target(selection_data), /* target type */
			_DWORD,				 /* number of bits per 'unit' */
			(guchar*) &integer_data,/* pointer to data to be sent */
			sizeof(integer_data)   /* length of data in units */
		);
		break;

		case TARGET_STRING:
		printf("string\t\t: %s\n", string_data);
		gtk_selection_data_set
		(
			selection_data,
			gtk_selection_data_get_target(selection_data),
			_BYTE,
			(guchar*) string_data,
			strlen(string_data)
		);
		break;

		case TARGET_ROOTWIN:
		printf("dropped on the root window\n");
		gui_program_warning_dialog_box
		(
			__FILE__, __LINE__, __FUNC__,
			"dropped on the root window"
		);

		break;

		default:
		gui_program_warning_dialog_box
		(
			__FILE__, __LINE__, __FUNC__,
			"default drag_data_transmit_handler"
		);

		// Default to some a safe target instead of fail.
		g_assert_not_reached();
	}
}
/*------------------------------------------------------------------------------
	Some GTK widgets do not have an X window associated with them,
	so they only show their appearance on their parent widget.
	For this reason, they cannot receive any events,
	If you want components to receive events, you can use event_box.
------------------------------------------------------------------------------*/
void make_window_drag_and_drop
(
	GtkWidget *dnd_window,
	GtkTargetEntry *target_list,
	int n_targets
)
{
	gtk_drag_dest_set
	(
		dnd_window,				// widget that will accept a drop
		GTK_DEST_DEFAULT_MOTION	// default actions for dest on DnD
		| GTK_DEST_DEFAULT_HIGHLIGHT,
		target_list,			// lists of target to support
		n_targets,				// size of list
		GDK_ACTION_COPY			// what to do with data after dropped
	);

	gtk_drag_source_set			// dnd_window must be inside an event_box
	(
		dnd_window,				// widget will be drag-able
		GDK_BUTTON1_MASK,       // modifier that will start a drag
		target_list,            // lists of target to support
		n_targets,				// size of list
		GDK_ACTION_COPY         // what to do with data after dropped
	);

	// connect all possible signals

	g_signal_connect
	(
		dnd_window, "drag-data-received",
		G_CALLBACK
		(
			drag_data_received_handler
		),
		NULL
	);

	g_signal_connect
	(
		dnd_window, "drag-data-get",
		G_CALLBACK
		(
			drag_data_transmit_handler
		),
		NULL
	);

	// these do nothing except report their call
	g_signal_connect(dnd_window, "drag-begin",
			G_CALLBACK(drag_begin_handler), NULL);

	g_signal_connect(dnd_window, "drag-drop",
			G_CALLBACK(drag_drop_handler), NULL);

	g_signal_connect(dnd_window, "drag-leave",
			G_CALLBACK(drag_leave_handler), NULL);

	g_signal_connect(dnd_window, "drag-end",
			G_CALLBACK(drag_end_handler), NULL);
}
/*------------------------------------------------------------------------------

------------------------------------------------------------------------------*/
int main(int argc, char **argv)
{
	GtkWidget	   *top_window;
	GtkWidget	   *hbox;
	GtkWidget	   *dnd_button_1;
	GtkWidget	   *dnd_button_2;
	GtkWidget	   *event_box_1;
	GtkWidget	   *event_box_2;
	GtkWidget	   *directions_label;
	guint		   width	= 200;
	guint		   height	= 200;
	guint		   spacing	= 10;

	gtk_init(&argc, &argv);

	// create all the widgets
	top_window  	= gtk_window_new(GTK_WINDOW_TOPLEVEL);
	hbox			= gtk_box_new(GTK_ORIENTATION_HORIZONTAL, spacing);
/*
	Some GTK widgets do not have an X window associated with them.
	For this reason, they cannot receive any events,
	If you want components to receive events, you can use an event_box.
*/
	event_box_1		= gtk_event_box_new();
	event_box_2		= gtk_event_box_new();
	dnd_button_1	= gtk_button_new_with_label("dnd_window_1");
	dnd_button_2	= gtk_button_new_with_label("dnd_window_2");

	// make the window big enough for some dnd action
	gtk_window_set_default_size(GTK_WINDOW(top_window),	width, height);

	directions_label = gtk_label_new
	(
		"dnd_window_1 <-drag and drop-> dnd_window_2"
	);

	gtk_widget_set_name(dnd_button_1, "dnd_button_1");
	gtk_widget_set_name(dnd_button_2, "dnd_button_2");

	// pack the widgets
	gtk_container_add(GTK_CONTAINER(top_window), hbox);
	gtk_container_add(GTK_CONTAINER(hbox), directions_label);

	// put event boxes in the box
	gtk_container_add(GTK_CONTAINER(hbox), event_box_1);
	gtk_container_add(GTK_CONTAINER(hbox), event_box_2);

	// put buttons in the event boxes
	gtk_container_add(GTK_CONTAINER(event_box_1), dnd_button_1);
	gtk_container_add(GTK_CONTAINER(event_box_2), dnd_button_2);

	// make dnd_button_1 and dnd_button_2 a dnd source and destination.
	make_window_drag_and_drop
	(
		dnd_button_1, target_list, G_N_ELEMENTS(target_list)
	);
	make_window_drag_and_drop
	(
		dnd_button_2, target_list, G_N_ELEMENTS(target_list)
	);

	g_signal_connect(top_window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
	gtk_widget_show_all(top_window);
	gtk_main();

	return 0;
}
/*------------------------------------------------------------------------------
	gtk_event_box_set_above_child((GTK_OBJECT)event_box_1, TRUE);
	gtk_event_box_set_above_child((GTK_OBJECT)event_box_1, TRUE);

------------------------------------------------------------------------------*/
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
LXer: Drag And Drop Files And Folders In Terminal To Print Their Absolute Path LXer Syndicated Linux News 0 10-11-2020 12:30 PM
LXer: VirtualBox 5.0 Brings Full Drag and Drop Between Host and Guest LXer Syndicated Linux News 0 07-10-2015 08:42 AM
moved to Gnome 3 and can't drag and drop urls anymoe pwalden Linux - Desktop 3 01-05-2012 01:52 PM
Drag and Drop Fail kajensen Linux - General 2 09-26-2003 06:08 PM
Drag and Drop Fail kajensen Linux - General 0 09-23-2003 02:47 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:28 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration