- grep FIXME
- When the module is unloaded, kill all processes blocking in read
- or block unloading until all processes have exited
- - Find out what happened here:
-
- - Hopefully the oops at the end of this file is gone now that
- we use mmput/get_task_mm. For older kernels those symbols
- are not exported though, so we will probably have to either
- use the old way (directly accessing the mm's) or just not
- support those kernels.
* Interface
- If the current profile has a name, display it in the title bar
- Sould just install the kernel module if it running as root, pop up
a dialog if not. Note we must be able to start without module now,
since it is useful to just load profiles from disk.
+ - Is there a portable way of asking for the root password?
+ - Install a small suid program that only inserts the module?
+ (instant security hole ..)
- hook up menu items view/start etc (or possibly get rid of them or
move them)
- Consider expanding a few more levels of a new descendants tree
- - give profiles on the command line
* Build system
- Need to make "make install" work (how do you know where to install
- .desktop file
- translation should be hooked up
+
+
+
+
Before 1.2:
- Make busy cursors more intelligent
- speedprof seems to report that lots of time is spent in
stack_stash_foreach() and also in generate_key()
- add an 'everything' object. It is really needed for a lot of things
-- make profile.c more agnostic to processes and functions etc. Ideally
- it should just take a set of stack traces containing "presentation
- objects" and do something sensible with it.
- Non-GUI version that can save in a format the GUI can understand.
Could be used for profiling startup etc. Would preferably be able to
- possibly add dependency on glib 2.8 if it is released at that point.
(g_file_replace())
+
+
+
Later:
- Find out how to hack around gtk+ bug causing multiple double clicks
been read will stay in cache (for short profile runs you can assume that with disk,
but not for long ones).
+
+
+
DONE:
+- give profiles on the command line
+
+- Hopefully the oops at the end of this file is gone now that
+ we use mmput/get_task_mm. For older kernels those symbols
+ are not exported though, so we will probably have to either
+ use the old way (directly accessing the mm's) or just not
+ support those kernels.
+
- Need an icon
- hook up about box
- fix leaks
+- Find out what happened here:
+
Apr 11 15:42:08 great-sage-equal-to-heaven kernel: Unable to handle kernel NULL pointer dereference at virtual address 000001b8
Apr 11 15:42:08 great-sage-equal-to-heaven kernel: printing eip:
Apr 11 15:42:08 great-sage-equal-to-heaven kernel: c017342c
GtkWidget * start_item;
GtkWidget * profile_item;
- GtkWidget * open_item;
+ GtkWidget * reset_item;
GtkWidget * save_as_item;
+ GtkWidget * open_item;
+
GtkWidget * samples_label;
Profile * profile;
break;
}
+ gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (active_radio_button), TRUE);
+
+ /* "profile" widgets */
gtk_widget_set_sensitive (GTK_WIDGET (app->profile_button),
sensitive_profile_button);
+ gtk_widget_set_sensitive (GTK_WIDGET (app->profile_item),
+ sensitive_profile_button);
- gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (active_radio_button), TRUE);
-
+ /* "save as" widgets */
gtk_widget_set_sensitive (GTK_WIDGET (app->save_as_button),
sensitive_save_as_button);
-
+ gtk_widget_set_sensitive (app->save_as_item, sensitive_save_as_button);
+
+ /* "start" widgets */
gtk_widget_set_sensitive (GTK_WIDGET (app->start_button),
- sensitive_start_button);
+ sensitive_start_button);
+ gtk_widget_set_sensitive (GTK_WIDGET (app->start_item),
+ sensitive_start_button);
#if 0
/* FIXME: gtk+ doesn't handle changes in sensitivity in response
*/
gtk_widget_set_sensitive (GTK_WIDGET (app->reset_button),
sensitive_reset_button);
+ gtk_widget_set_sensitive (GTK_WIDGET (app->reset_item),
+ sensitive_reset_button);
#endif
gtk_widget_set_sensitive (GTK_WIDGET (app->object_view), sensitive_tree_views);
gtk_show_about_dialog (GTK_WINDOW (app->main_window),
"logo", app->icon,
"name", APPLICATION_NAME,
-#if 0
- "copyright", "Copyright S"OSLASH"ren Sandmann",
-#endif
- "comments", "FIXME, write something informative here",
+ "copyright", "Copyright 2004-2005, S"OSLASH"ren Sandmann",
NULL);
}
}
static void
-on_save_as_clicked (gpointer widget, gpointer data)
+on_save_as_clicked (gpointer widget,
+ gpointer data)
{
Application *app = data;
GtkWidget *dialog;
}
static void
-on_open_clicked (gpointer widget, gpointer data)
+set_loaded_profile (Application *app,
+ const char *name,
+ Profile *profile)
+{
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (profile != NULL);
+
+ set_busy (app->main_window, TRUE);
+
+ delete_data (app);
+
+ app->state = DISPLAYING;
+
+ app->n_samples = profile_get_size (profile);
+
+ app->profile = profile;
+ app->profile_from_file = TRUE;
+
+ fill_lists (app);
+
+ update_sensitivity (app);
+
+ set_busy (app->main_window, FALSE);
+}
+
+static void
+show_could_not_open (Application *app,
+ const char *filename,
+ GError *err)
+{
+ sorry (app->main_window,
+ "Could not open %s: %s",
+ filename,
+ err->message);
+}
+
+static void
+on_open_clicked (gpointer widget,
+ gpointer data)
{
Application *app = data;
+ gchar *filename = NULL;
Profile *profile = NULL;
GtkWidget *dialog;
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
{
GError *err = NULL;
- gchar *filename;
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
if (!profile)
{
set_busy (dialog, FALSE);
-
- sorry (app->main_window, "Could not open %s: %s",
- filename, err->message);
-
+
+ show_could_not_open (app, filename, err);
+ g_error_free (err);
g_free (filename);
+
+ filename = NULL;
goto retry;
}
set_busy (dialog, FALSE);
-
- g_free (filename);
}
-
+
gtk_widget_destroy (dialog);
- set_busy (app->main_window, TRUE);
-
if (profile)
{
- delete_data (app);
-
- app->state = DISPLAYING;
-
- app->n_samples = profile_get_size (profile);
-
- app->profile = profile;
- app->profile_from_file = TRUE;
-
- fill_lists (app);
-
- update_sensitivity (app);
- }
+ g_assert (filename);
+ set_loaded_profile (app, filename, profile);
- set_busy (app->main_window, FALSE);
+ g_free (filename);
+ }
}
static void
}
static void
-on_object_selection_changed (GtkTreeSelection *selection, gpointer data)
+on_object_selection_changed (GtkTreeSelection *selection,
+ gpointer data)
{
Application *app = data;
GtkTreePath *path;
}
static void
-really_goto_object (Application *app, ProfileObject *object)
+really_goto_object (Application *app,
+ ProfileObject *object)
{
GtkTreeModel *profile_objects;
GtkTreeIter iter;
/* Menu items */
app->start_item = glade_xml_get_widget (xml, "start_item");
app->profile_item = glade_xml_get_widget (xml, "profile_item");
+ app->reset_item = glade_xml_get_widget (xml, "reset_item");
app->open_item = glade_xml_get_widget (xml, "open_item");
app->save_as_item = glade_xml_get_widget (xml, "save_as_item");
g_assert (app->save_as_item);
g_assert (app->open_item);
+#if 0
g_signal_connect (G_OBJECT (app->start_item), "activate",
- G_CALLBACK (on_start_toggled), app);
+ G_CALLBACK (toggle_start_button), app);
g_signal_connect (G_OBJECT (app->profile_item), "activate",
G_CALLBACK (on_profile_toggled), app);
+ g_signal_connect (G_OBJECT (app->reset_item), "activate",
+ G_CALLBACK (on_reset_clicked), app);
+#endif
+
g_signal_connect (G_OBJECT (app->open_item), "activate",
G_CALLBACK (on_open_clicked), app);
g_signal_connect (G_OBJECT (app->save_as_item), "activate",
G_CALLBACK (on_save_as_clicked), app);
-
+
/* quit */
g_signal_connect (G_OBJECT (glade_xml_get_widget (xml, "quit")), "activate",
G_CALLBACK (on_delete), NULL);
return app;
}
+typedef struct
+{
+ const char *filename;
+ Application *app;
+} FileOpenData;
+
+static gboolean
+load_file (gpointer data)
+{
+ FileOpenData *file_open_data = data;
+ const char *filename = file_open_data->filename;
+ Application *app = file_open_data->app;
+ GError *err = NULL;
+ Profile *profile;
+
+ set_busy (app->main_window, TRUE);
+
+ profile = profile_load (filename, &err);
+
+ set_busy (app->main_window, FALSE);
+
+ if (profile)
+ {
+ set_loaded_profile (app, filename, profile);
+ }
+ else
+ {
+ show_could_not_open (app, filename, err);
+ g_error_free (err);
+ }
+
+ return FALSE;
+}
+
int
main (int argc, char **argv)
{
build_gui (app);
update_sensitivity (app);
+
+ if (argc > 1)
+ {
+ FileOpenData *file_open_data = g_new0 (FileOpenData, 1);
+
+file_open_data->filename = argv[1];
+ file_open_data->app = app;
+
+ g_idle_add (load_file, file_open_data);
+ }
gtk_main ();