[nemiver/profiler: 1/11] Support for multiple perspective
- From: Fabien Parent <fparent src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nemiver/profiler: 1/11] Support for multiple perspective
- Date: Sun, 17 Jun 2012 14:09:58 +0000 (UTC)
commit aeec338ed540f7ea4766349a12d01784c3684e90
Author: Fabien Parent <parent f gmail com>
Date: Mon May 21 21:42:34 2012 +0200
Support for multiple perspective
src/main.cc | 488 +++--------------------
src/persp/dbgperspective/nmv-dbg-perspective.cc | 430 ++++++++++++++++++++-
src/persp/dbgperspective/nmv-dbg-perspective.h | 4 +-
src/persp/nmv-i-perspective.h | 31 +-
src/workbench/nmv-i-workbench.h | 9 +-
src/workbench/nmv-workbench.cc | 201 +++++++---
ui/workbench.ui | 71 +++-
7 files changed, 699 insertions(+), 535 deletions(-)
---
diff --git a/src/main.cc b/src/main.cc
index 3114fb1..86f3c16 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -36,7 +36,7 @@
#include "nmv-ui-utils.h"
#include "nmv-proc-mgr.h"
#include "nmv-env.h"
-#include "nmv-dbg-perspective.h"
+#include "nmv-i-perspective.h"
#include "nmv-i-conf-mgr.h"
using namespace std;
@@ -45,87 +45,25 @@ using nemiver::common::DynamicModuleManager;
using nemiver::common::Initializer;
using nemiver::IWorkbench;
using nemiver::IWorkbenchSafePtr;
-using nemiver::IDBGPerspective;
+using nemiver::IPerspective;
+using nemiver::IPerspectiveSafePtr;
using nemiver::common::UString;
using nemiver::common::GCharSafePtr;
-using nemiver::ISessMgr;
-
-static const UString DBGPERSPECTIVE_PLUGIN_NAME = "dbgperspective";
-static gchar *gv_env_vars = 0;
-static gchar *gv_process_to_attach_to = 0;
-static bool gv_list_sessions = false;
-static bool gv_purge_sessions = false;
-static int gv_execute_session = 0;
-static bool gv_last_session = false;
+
static gchar *gv_log_domains=0;
-static bool gv_log_debugger_output = false;
static bool gv_show_version = false;
-static bool gv_use_launch_terminal = false;
-static gchar *gv_remote = 0;
-static gchar *gv_solib_prefix = 0;
-static gchar *gv_gdb_binary_filepath = 0;
-static gchar *gv_core_path = 0;
+static gchar *gv_tool = (gchar*) "dbgperspective";
static GOptionEntry entries[] =
{
{
- "env",
- 0,
- 0,
- G_OPTION_ARG_STRING,
- &gv_env_vars,
- _("Set the environment of the program to debug"),
- "<\"var0=val0 var1=val1 var2=val2 ...\">"
- },
- {
- "attach",
+ "tool",
0,
0,
G_OPTION_ARG_STRING,
- &gv_process_to_attach_to,
- _("Attach to a process"),
- "<pid|process name>"
- },
- {
- "load-core",
- 0,
- 0,
- G_OPTION_ARG_STRING,
- &gv_core_path,
- _("Load a core file"),
- "</path/to/core/file>"
- },
- { "list-sessions",
- 0,
- 0,
- G_OPTION_ARG_NONE,
- &gv_list_sessions,
- _("List the saved debugging sessions"),
- 0
- },
- { "purge-sessions",
- 0,
- 0,
- G_OPTION_ARG_NONE,
- &gv_purge_sessions,
- _("Erase the saved debugging sessions"),
- 0
- },
- { "session",
- 0,
- 0,
- G_OPTION_ARG_INT,
- &gv_execute_session,
- _("Debug the program that was of session number N"),
- "<N>"
- },
- { "last",
- 0,
- 0,
- G_OPTION_ARG_NONE,
- &gv_last_session,
- _("Execute the last session"),
- 0
+ &gv_tool,
+ _("Use the nemiver tool named <name>"),
+ "<name>"
},
{ "log-domains",
0,
@@ -135,50 +73,6 @@ static GOptionEntry entries[] =
_("Enable logging domains DOMAINS"),
"<DOMAINS>"
},
- { "log-debugger-output",
- 0,
- 0,
- G_OPTION_ARG_NONE,
- &gv_log_debugger_output,
- _("Log the debugger output"),
- 0
- },
- { "use-launch-terminal",
- 0,
- 0,
- G_OPTION_ARG_NONE,
- &gv_use_launch_terminal,
- _("Use this terminal as the debugee's terminal"),
- 0
- },
- {
- "remote",
- 0,
- 0,
- G_OPTION_ARG_STRING,
- &gv_remote,
- _("Connect to remote target specified by HOST:PORT"),
- "<HOST:PORT|serial-line-path>"
- },
- {
- "solib-prefix",
- 0,
- 0,
- G_OPTION_ARG_STRING,
- &gv_solib_prefix,
- _("Where to look for shared libraries loaded by the inferior. "
- "Use in conjunction with --remote"),
- "</path/to/prefix>"
- },
- {
- "gdb-binary",
- 0,
- 0,
- G_OPTION_ARG_STRING,
- &gv_gdb_binary_filepath,
- _("Set the path of the GDB binary to use to debug the inferior"),
- "</path/to/gdb>"
- },
{
"version",
0,
@@ -265,6 +159,18 @@ init_option_context ()
THROW_IF_FAIL (gtk_option_group);
g_option_context_add_group (context.get (),
gtk_option_group.release ());
+
+ std::list<IPerspectiveSafePtr>::iterator perspective;
+ std::list<IPerspectiveSafePtr> perspectives = s_workbench->perspectives ();
+ for (perspective = perspectives.begin ();
+ perspective != perspectives.end ();
+ ++perspective) {
+ if (*perspective && (*perspective)->option_group ()) {
+ g_option_context_add_group
+ (context.get (), (*perspective)->option_group ());
+ }
+ }
+
return context.release ();
}
@@ -335,51 +241,21 @@ parse_command_line (int& a_argc,
return false;
}
- if (a_argv != inf_argv) {
- memmove (a_argv, inf_argv, inf_argc * sizeof (char*));
- a_argc = inf_argc;
+ IPerspectiveSafePtr perspective = s_workbench->get_perspective (gv_tool);
+ if (!perspective) {
+ std::cerr << "Invalid tool name: " << gv_tool << std::endl;
+ return false;
}
- //***************************************************************
- // Here goes some sanity checking on the command line parsed so far.
- //****************************************************************
-
- // If the user wants to debug a binary running on a remote target,
- // make sure she provides us with a local copy of the binary too.
- if (gv_remote) {
- if (a_argc < 1 || a_argv[0][0] == '-') {
- cerr << _("Please provide a local copy of the binary "
- "you intend to debug remotely.\n"
- "Like this:\n")
- << "nemiver --remote=" << gv_remote
- << " <binary-copy>\n\n";
- cerr << _("Otherwise, find below the full set of Nemiver options.\n");
- GCharSafePtr help_message;
- help_message.reset (g_option_context_get_help (context.get (),
- true, 0));
- cerr << help_message.get () << std::endl;
- return false;
- }
+ if (!perspective->process_options (context.get (), inf_argc, inf_argv)) {
+ return false;
}
- // If the user wants to analyse a core dump, make sure she
- // provides us with a path to the binary that generated the core
- // dump too.
- if (gv_core_path) {
- if (a_argc < 1 || a_argv[0][0] == '-') {
- cerr << _("Please provide the path to the binary "
- "that generated the core file too.\n"
- "Like this:\n")
- << "nemiver --load-core=\""
- << gv_core_path << "\" </path/to/binary>\n\n";
- cerr << _("Otherwise, find below the full set of Nemiver options.\n");
- GCharSafePtr help_message;
- help_message.reset (g_option_context_get_help (context.get (),
- true, 0));
- cerr << help_message.get () << std::endl;
- return false;
- }
+ if (a_argv != inf_argv) {
+ memmove (a_argv, inf_argv, inf_argc * sizeof (char*));
+ a_argc = inf_argc;
}
+
return true;
}
@@ -388,10 +264,6 @@ parse_command_line (int& a_argc,
static bool
process_non_gui_options ()
{
- if (gv_log_debugger_output) {
- LOG_STREAM.enable_domain ("gdbmi-output-domain");
- }
-
if (gv_show_version) {
cout << PACKAGE_VERSION << endl;
return false;
@@ -406,255 +278,7 @@ process_non_gui_options ()
LOG_STREAM.enable_domain (*iter);
}
}
- return true;
-}
-
-/// Load the debugger perspective.
-static IDBGPerspective*
-load_debugger_perspective ()
-{
- return dynamic_cast<IDBGPerspective*> (s_workbench->get_perspective
- (DBGPERSPECTIVE_PLUGIN_NAME));
-}
-
-/// Return true if Nemiver should keep going after the GUI option(s)
-/// have been processed.
-static bool
-process_gui_options (int& a_argc, char** a_argv)
-{
- if (gv_purge_sessions) {
- IDBGPerspective *debug_persp = load_debugger_perspective ();
- if (debug_persp) {
- debug_persp->session_manager ().delete_sessions ();
- }
- return false;
- }
-
- if (gv_process_to_attach_to) {
- using nemiver::common::IProcMgrSafePtr;
- using nemiver::common::IProcMgr;
- IDBGPerspective *debug_persp = load_debugger_perspective ();
- if (!debug_persp) {
- cerr << "Could not get the debugging perspective" << endl;
- return false;
- }
- int pid = atoi (gv_process_to_attach_to);
- if (!pid) {
- IProcMgrSafePtr proc_mgr = IProcMgr::create ();
- if (!proc_mgr) {
- cerr << "Could not create proc mgr" << endl;
- return false;
- }
- IProcMgr::Process process;
- if (!proc_mgr->get_process_from_name (gv_process_to_attach_to,
- process, true)) {
- cerr << "Could not find any process named '"
- << gv_process_to_attach_to
- << "'"
- << endl;
- return false;
- }
- pid = process.pid ();
- }
- if (!pid) {
- cerr << "Could not find any process '"
- << gv_process_to_attach_to
- << "'"
- << endl;
- return false;
- } else {
- debug_persp->uses_launch_terminal (gv_use_launch_terminal);
- debug_persp->attach_to_program (pid);
- }
- }
-
- if (gv_list_sessions) {
- IDBGPerspective *debug_persp = load_debugger_perspective ();
- if (debug_persp) {
- debug_persp->session_manager ().load_sessions ();
- list<ISessMgr::Session>::iterator session_iter;
- list<ISessMgr::Session>& sessions =
- debug_persp->session_manager ().sessions ();
- for (session_iter = sessions.begin ();
- session_iter != sessions.end ();
- ++session_iter) {
- cout << session_iter->session_id ()
- << " "
- << session_iter->properties ()["sessionname"]
- << "\n";
- }
- return false;
- } else {
- cerr << "Could not find the debugger perpective plugin";
- return false;
- }
- }
-
- if (gv_execute_session) {
- IDBGPerspective *debug_persp = load_debugger_perspective ();
- if (debug_persp) {
- debug_persp->session_manager ().load_sessions ();
- list<ISessMgr::Session>::iterator session_iter;
- list<ISessMgr::Session>& sessions =
- debug_persp->session_manager ().sessions ();
- bool found_session=false;
- debug_persp->uses_launch_terminal (gv_use_launch_terminal);
- for (session_iter = sessions.begin ();
- session_iter != sessions.end ();
- ++session_iter) {
- if (session_iter->session_id () == gv_execute_session) {
- debug_persp->execute_session (*session_iter);
- found_session = true;
- break;
- }
- }
-
- if (!found_session) {
- cerr << "Could not find session of number "
- << gv_execute_session
- << "\n";
- return false;
- }
- return true;
- } else {
- cerr << "Could not find the debugger perpective plugin";
- return false;
- }
- }
-
- //execute the last session if one exists
- if (gv_last_session) {
- IDBGPerspective *debug_persp = load_debugger_perspective ();
- if (debug_persp) {
- debug_persp->session_manager ().load_sessions ();
- list<ISessMgr::Session>& sessions =
- debug_persp->session_manager ().sessions ();
- if (!sessions.empty ()) {
- debug_persp->uses_launch_terminal (gv_use_launch_terminal);
- list<ISessMgr::Session>::iterator session_iter,
- latest_session_iter;
- glong time_val = 0;
- for (session_iter = sessions.begin ();
- session_iter != sessions.end ();
- ++session_iter) {
- std::map<UString, UString>::const_iterator map_iter =
- session_iter->properties ().find ("lastruntime");
- if (map_iter != session_iter->properties ().end ()) {
- glong new_time = atoi (map_iter->second.c_str ());
- if (new_time > time_val) {
- time_val = new_time;
- latest_session_iter = session_iter;
- }
- }
- }
- debug_persp->execute_session (*latest_session_iter);
- } else {
- cerr << "Could not find any sessions"
- << "\n";
- return false;
- }
- return true;
- } else {
- cerr << "Could not find the debugger perpective plugin";
- return false;
- }
- }
-
- // Load and analyse a core file
- if (gv_core_path) {
- IDBGPerspective *debug_persp = load_debugger_perspective ();
- if (debug_persp == 0) {
- cerr << "Could not find the debugger perpective plugin";
- return false;
- }
- UString prog_path = a_argv[0];
- THROW_IF_FAIL (!prog_path.empty ());
- debug_persp->load_core_file (prog_path, gv_core_path);
- return true;
- }
-
- vector<UString> prog_args;
- UString prog_path;
- // Here, a_argc is the argument count of the inferior program.
- // It's zero if there is there is no inferior program.
- // Otherwise it equals the number of arguments to the inferior program + 1
- if (a_argc > 0)
- prog_path = a_argv[0];
- for (int i = 1; i < a_argc; ++i) {
- prog_args.push_back (Glib::locale_to_utf8 (a_argv[i]));
- }
- IDBGPerspective *debug_persp =
- dynamic_cast<IDBGPerspective*> (s_workbench->get_perspective
- (DBGPERSPECTIVE_PLUGIN_NAME));
- if (debug_persp) {
- if (gv_gdb_binary_filepath) {
- char *debugger_full_path = realpath (gv_gdb_binary_filepath, 0);
- if (debugger_full_path) {
- nemiver::IDebuggerSafePtr debugger = debug_persp->debugger ();
- if (!debugger) {
- cerr << "Could not get the debugger instance" << endl;
- return false;
- }
- debugger->set_non_persistent_debugger_path (debugger_full_path);
- free (debugger_full_path);
- } else {
- LOG_ERROR ("Could not resolve the full path of the debugger");
- }
- }
- map<UString, UString> env;
- if (gv_env_vars) {
- vector<UString> env_vars =
- UString (Glib::locale_to_utf8 (gv_env_vars)).split (" ");
- for (vector<UString>::const_iterator it = env_vars.begin ();
- it != env_vars.end ();
- ++it) {
- vector<UString> env_var = it->split ("=");
- if (env_var.size () != 2) {
- continue;
- }
- UString name = env_var[0];
- name.chomp ();
- UString value = env_var[1];
- value.chomp ();
- LOG_DD ("got env var: " << name << "=" << value);
- env[name] = value;
- }
- }
- if (gv_remote) {
- // The user asked to connect to a remote target.
- std::string host;
- unsigned port = 0;
- std::string solib_prefix;
-
- if (gv_solib_prefix)
- solib_prefix = gv_solib_prefix;
-
- if (nemiver::str_utils::parse_host_and_port (gv_remote,
- host, port)) {
- // So it looks like gv_remote has the form
- // "host:port", so let's try to connect to that.
- debug_persp->connect_to_remote_target (host, port,
- prog_path,
- solib_prefix);
- } else {
- // We think gv_remote contains a serial line address.
- // Let's try to connect via the serial line then.
- debug_persp->connect_to_remote_target (gv_remote,
- prog_path,
- solib_prefix);
- }
- } else if (!prog_path.empty ()) {
- // The user wants to debug a local program
- debug_persp->uses_launch_terminal (gv_use_launch_terminal);
- debug_persp->execute_program (prog_path,
- prog_args,
- env);
- }
- } else {
- cerr << "Could not find the debugger perspective plugin\n";
- return false;
- }
return true;
}
@@ -670,13 +294,6 @@ main (int a_argc, char *a_argv[])
Initializer::do_init ();
Gtk::Main gtk_kit (a_argc, a_argv);
- if (parse_command_line (a_argc, a_argv) == false)
- return -1;
-
- if (process_non_gui_options () != true) {
- return -1;
- }
-
//********************************************
//load and init the workbench dynamic module
//********************************************
@@ -687,43 +304,34 @@ main (int a_argc, char *a_argv[])
THROW_IF_FAIL (s_workbench);
LOG_D ("workbench refcount: " << (int) s_workbench->get_refcount (),
"refcount-domain");
+ s_workbench->do_init_dev ();
+
+ if (parse_command_line (a_argc, a_argv) == false)
+ return -1;
+
+ if (process_non_gui_options () != true) {
+ return -1;
+ }
s_workbench->do_init (gtk_kit);
LOG_D ("workbench refcount: " << (int) s_workbench->get_refcount (),
"refcount-domain");
- if (process_gui_options (a_argc, a_argv) != true) {
+ IPerspectiveSafePtr perspective = s_workbench->get_perspective (gv_tool);
+ if (!perspective) {
+ std::cerr << "Invalid tool name: " << gv_tool << std::endl;
+ return -1;
+ }
+
+ if (!perspective->process_gui_options (a_argc, a_argv)) {
return -1;
}
+ s_workbench->select_perspective (perspective);
+
//intercept ctrl-c/SIGINT
signal (SIGINT, sigint_handler);
- if (gv_use_launch_terminal) {
- // So the user wants the inferior to use the terminal Nemiver was
- // launched from, for input/output.
- //
- // Letting the inferior use the terminal from which Nemiver was
- // launched from implies calling the "set inferior-tty" GDB command,
- // when we are using the GDB backend.
- // That command is implemented using the TIOCSCTTY ioctl. It sets the
- // terminal as the controlling terminal of the inferior process. But that
- // ioctl requires (among other things) that the terminal shall _not_ be
- // the controlling terminal of any other process in another process
- // session already. Otherwise, GDB spits the error:
- // "GDB: Failed to set controlling terminal: operation not
- // permitted"
- // The problem is, Nemiver itself uses that terminal as a
- // controlling terminal. So Nemiver itself must relinquish its
- // controlling terminal to avoid letting the ioctl fail.
- // We do so by calling the setsid function below.
- // The problem is that setsid will fail with EPERM if Nemiver is
- // started as a process group leader already.
- // Trying ioctl (tty_fd, TIOCNOTTY, 0) does not seem to properly
- // disconnect Nemiver from its terminal either. Sigh.
- setsid ();
- }
-
gtk_kit.run (s_workbench->get_root_window ());
NEMIVER_CATCH_NOX
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index d48115f..002909f 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -147,6 +147,127 @@ const Gtk::StockID STOCK_STEP_OUT (STEP_OUT);
const char *PROG_ARG_SEPARATOR = "#DUMMY-SEP007#";
+static gchar *gv_env_vars = 0;
+static gchar *gv_process_to_attach_to = 0;
+static bool gv_list_sessions = false;
+static bool gv_purge_sessions = false;
+static int gv_execute_session = 0;
+static bool gv_last_session = false;
+static bool gv_log_debugger_output = false;
+static bool gv_use_launch_terminal = false;
+static gchar *gv_remote = 0;
+static gchar *gv_solib_prefix = 0;
+static gchar *gv_gdb_binary_filepath = 0;
+static gchar *gv_core_path = 0;
+
+static const GOptionEntry entries[] =
+{
+ {
+ "env",
+ 0,
+ 0,
+ G_OPTION_ARG_STRING,
+ &gv_env_vars,
+ _("Set the environment of the program to debug"),
+ "<\"var0=val0 var1=val1 var2=val2 ...\">"
+ },
+ {
+ "attach",
+ 0,
+ 0,
+ G_OPTION_ARG_STRING,
+ &gv_process_to_attach_to,
+ _("Attach to a process"),
+ "<pid|process name>"
+ },
+ {
+ "load-core",
+ 0,
+ 0,
+ G_OPTION_ARG_STRING,
+ &gv_core_path,
+ _("Load a core file"),
+ "</path/to/core/file>"
+ },
+ { "list-sessions",
+ 0,
+ 0,
+ G_OPTION_ARG_NONE,
+ &gv_list_sessions,
+ _("List the saved debugging sessions"),
+ 0
+ },
+ { "purge-sessions",
+ 0,
+ 0,
+ G_OPTION_ARG_NONE,
+ &gv_purge_sessions,
+ _("Erase the saved debugging sessions"),
+ 0
+ },
+ { "session",
+ 0,
+ 0,
+ G_OPTION_ARG_INT,
+ &gv_execute_session,
+ _("Debug the program that was of session number N"),
+ "<N>"
+ },
+ { "last",
+ 0,
+ 0,
+ G_OPTION_ARG_NONE,
+ &gv_last_session,
+ _("Execute the last session"),
+ 0
+ },
+ { "log-debugger-output",
+ 0,
+ 0,
+ G_OPTION_ARG_NONE,
+ &gv_log_debugger_output,
+ _("Log the debugger output"),
+ 0
+ },
+ { "use-launch-terminal",
+ 0,
+ 0,
+ G_OPTION_ARG_NONE,
+ &gv_use_launch_terminal,
+ _("Use this terminal as the debugee's terminal"),
+ 0
+ },
+ {
+ "remote",
+ 0,
+ 0,
+ G_OPTION_ARG_STRING,
+ &gv_remote,
+ _("Connect to remote target specified by HOST:PORT"),
+ "<HOST:PORT|serial-line-path>"
+ },
+ {
+ "solib-prefix",
+ 0,
+ 0,
+ G_OPTION_ARG_STRING,
+ &gv_solib_prefix,
+ _("Where to look for shared libraries loaded by the inferior. "
+ "Use in conjunction with --remote"),
+ "</path/to/prefix>"
+ },
+ {
+ "gdb-binary",
+ 0,
+ 0,
+ G_OPTION_ARG_STRING,
+ &gv_gdb_binary_filepath,
+ _("Set the path of the GDB binary to use to debug the inferior"),
+ "</path/to/gdb>"
+ },
+ {0, 0, 0, (GOptionArg) 0, 0, 0, 0}
+};
+
class DBGPerspective;
static void
@@ -491,6 +612,14 @@ public:
virtual ~DBGPerspective ();
+ GOptionGroup* option_group () const;
+
+ bool process_options (GOptionContext *a_context, int a_argc, char **a_argv);
+
+ bool process_gui_options (int a_argc, char **a_argv);
+
+ const UString& name () const;
+
void do_init (IWorkbench *a_workbench);
const UString& get_perspective_identifier ();
@@ -503,7 +632,7 @@ public:
IWorkbench& get_workbench ();
- void edit_workbench_menu ();
+ std::list<Gtk::UIManager::ui_merge_id> edit_workbench_menu ();
SourceEditor* create_source_editor (Glib::RefPtr<Gsv::Buffer> &a_source_buf,
bool a_asm_view,
@@ -873,6 +1002,7 @@ struct DBGPerspective::Priv {
SafePtr<Gtk::ScrolledWindow> thread_list_scrolled_win;
SafePtr<Gtk::HPaned> call_stack_paned;
SafePtr<Gtk::HPaned> context_paned;
+ GOptionGroup *option_group;
Glib::RefPtr<Gtk::ActionGroup> target_connected_action_group;
Glib::RefPtr<Gtk::ActionGroup> target_not_started_action_group;
@@ -882,6 +1012,7 @@ struct DBGPerspective::Priv {
Glib::RefPtr<Gtk::ActionGroup> opened_file_action_group;
Glib::RefPtr<Gtk::UIManager> ui_manager;
Glib::RefPtr<Gtk::IconFactory> icon_factory;
+ Gtk::UIManager::ui_merge_id memoryview_merge_id;
Gtk::UIManager::ui_merge_id menubar_merge_id;
Gtk::UIManager::ui_merge_id toolbar_merge_id;
Gtk::UIManager::ui_merge_id contextual_menu_merge_id;
@@ -973,6 +1104,8 @@ struct DBGPerspective::Priv {
reused_session (false),
debugger_has_just_run (false),
debugger_engine_alive (false),
+ option_group (0),
+ memoryview_merge_id (0),
menubar_merge_id (0),
toolbar_merge_id (0),
contextual_menu_merge_id(0),
@@ -996,6 +1129,9 @@ struct DBGPerspective::Priv {
var_popup_tip_x (0),
var_popup_tip_y (0)
{
+ option_group =
+ g_option_group_new ("debugger", _("Debugger"), "Blabla", 0, 0);
+ g_option_group_add_entries (option_group, entries);
}
Layout&
@@ -3022,7 +3158,8 @@ DBGPerspective::add_perspective_menu_entries ()
relative_path = Glib::build_filename ("menus", "memoryview-menu.xml");
THROW_IF_FAIL (build_absolute_resource_path
(Glib::filename_to_utf8 (relative_path), absolute_path));
- workbench ().get_ui_manager ()->add_ui_from_file
+ m_priv->memoryview_merge_id =
+ workbench ().get_ui_manager ()->add_ui_from_file
(Glib::filename_to_utf8 (absolute_path));
#endif // WITH_MEMORYVIEW
}
@@ -5227,12 +5364,16 @@ DBGPerspective::get_workbench ()
return workbench ();
}
-void
+std::list<Gtk::UIManager::ui_merge_id>
DBGPerspective::edit_workbench_menu ()
{
CHECK_P_INIT;
add_perspective_menu_entries ();
+ std::list<Gtk::UIManager::ui_merge_id> merge_ids;
+ merge_ids.push_back (m_priv->menubar_merge_id);
+ merge_ids.push_back (m_priv->memoryview_merge_id);
+ return merge_ids;
}
SourceEditor*
@@ -5333,6 +5474,20 @@ DBGPerspective::open_file ()
bring_source_as_current (*(paths.begin()));
}
+GOptionGroup*
+DBGPerspective::option_group () const
+{
+ THROW_IF_FAIL (m_priv);
+ return m_priv->option_group;
+}
+
+const UString&
+DBGPerspective::name () const
+{
+ static const UString s_name ("Debugger");
+ return s_name;
+}
+
bool
DBGPerspective::open_file (const UString &a_path, int current_line)
{
@@ -7993,6 +8148,275 @@ DBGPerspective::debugger ()
return m_priv->debugger;
}
+bool
+DBGPerspective::process_options (GOptionContext *a_context,
+ int a_argc,
+ char **a_argv)
+{
+ // If the user wants to debug a binary running on a remote target,
+ // make sure she provides us with a local copy of the binary too.
+ if (gv_remote) {
+ if (a_argc < 1 || a_argv[0][0] == '-') {
+ cerr << _("Please provide a local copy of the binary "
+ "you intend to debug remotely.\n"
+ "Like this:\n")
+ << "nemiver --remote=" << gv_remote
+ << " <binary-copy>\n\n";
+ cerr << _("Otherwise, find below the full set of nemiver options."
+ "\n");
+ GCharSafePtr help_message;
+ help_message.reset (g_option_context_get_help
+ (a_context, true, m_priv->option_group));
+ cerr << help_message.get () << std::endl;
+ return false;
+ }
+ }
+
+ // If the user wants to analyse a core dump, make sure she
+ // provides us with a path to the binary that generated the core
+ // dump too.
+ if (gv_core_path) {
+ if (a_argc < 1 || a_argv[0][0] == '-') {
+ cerr << _("Please provide the path to the binary "
+ "that generated the core file too.\n"
+ "Like this:\n")
+ << "nemiver --load-core=\""
+ << gv_core_path << "\" </path/to/binary>\n\n";
+ cerr << _("Otherwise, find below the full set of nemiver options."
+ "\n");
+ GCharSafePtr help_message;
+ help_message.reset (g_option_context_get_help
+ (a_context, true, m_priv->option_group));
+ cerr << help_message.get () << std::endl;
+ return false;
+ }
+ }
+
+ if (gv_log_debugger_output) {
+ LOG_STREAM.enable_domain ("gdbmi-output-domain");
+ }
+
+ if (gv_purge_sessions) {
+ session_manager ().delete_sessions ();
+ }
+
+ if (gv_list_sessions) {
+ session_manager ().load_sessions ();
+ list<ISessMgr::Session>::iterator session_iter;
+ list<ISessMgr::Session>& sessions = session_manager ().sessions ();
+ for (session_iter = sessions.begin ();
+ session_iter != sessions.end ();
+ ++session_iter) {
+ cout << session_iter->session_id ()
+ << " "
+ << session_iter->properties ()["sessionname"]
+ << "\n";
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool
+DBGPerspective::process_gui_options (int a_argc, char **a_argv)
+{
+ if (gv_process_to_attach_to) {
+ using nemiver::common::IProcMgrSafePtr;
+ using nemiver::common::IProcMgr;
+ int pid = atoi (gv_process_to_attach_to);
+ if (!pid) {
+ IProcMgrSafePtr proc_mgr = IProcMgr::create ();
+ if (!proc_mgr) {
+ cerr << "Could not create proc mgr" << std::endl;
+ return false;
+ }
+ IProcMgr::Process process;
+ if (!proc_mgr->get_process_from_name (gv_process_to_attach_to,
+ process, true)) {
+ cerr << "Could not find any process named '"
+ << gv_process_to_attach_to
+ << "'"
+ << std::endl;
+ return false;
+ }
+ pid = process.pid ();
+ }
+ if (!pid) {
+ cerr << "Could not find any process '"
+ << gv_process_to_attach_to
+ << "'"
+ << std::endl;
+ return false;
+ } else {
+ uses_launch_terminal (gv_use_launch_terminal);
+ attach_to_program (pid);
+ }
+ }
+
+ if (gv_execute_session) {
+ session_manager ().load_sessions ();
+ list<ISessMgr::Session>::iterator session_iter;
+ list<ISessMgr::Session>& sessions = session_manager ().sessions ();
+ bool found_session = false;
+ uses_launch_terminal (gv_use_launch_terminal);
+ for (session_iter = sessions.begin ();
+ session_iter != sessions.end ();
+ ++session_iter) {
+ if (session_iter->session_id () == gv_execute_session) {
+ execute_session (*session_iter);
+ found_session = true;
+ break;
+ }
+ }
+
+ if (!found_session) {
+ cerr << "Could not find session of number "
+ << gv_execute_session
+ << "\n";
+ return false;
+ }
+ return true;
+ }
+
+ //execute the last session if one exists
+ if (gv_last_session) {
+ session_manager ().load_sessions ();
+ list<ISessMgr::Session>& sessions = session_manager ().sessions ();
+ if (!sessions.empty ()) {
+ uses_launch_terminal (gv_use_launch_terminal);
+ list<ISessMgr::Session>::iterator session_iter,
+ latest_session_iter;
+ glong time_val = 0;
+ for (session_iter = sessions.begin ();
+ session_iter != sessions.end ();
+ ++session_iter) {
+ std::map<UString, UString>::const_iterator map_iter =
+ session_iter->properties ().find ("lastruntime");
+ if (map_iter != session_iter->properties ().end ()) {
+ glong new_time = atoi (map_iter->second.c_str ());
+ if (new_time > time_val) {
+ time_val = new_time;
+ latest_session_iter = session_iter;
+ }
+ }
+ }
+ execute_session (*latest_session_iter);
+ } else {
+ cerr << "Could not find any sessions"
+ << "\n";
+ return false;
+ }
+ return true;
+ }
+
+ // Load and analyse a core file
+ if (gv_core_path) {
+ UString prog_path = a_argv[0];
+ THROW_IF_FAIL (!prog_path.empty ());
+ load_core_file (prog_path, gv_core_path);
+ return true;
+ }
+
+ vector<UString> prog_args;
+ UString prog_path;
+ // Here, a_argc is the argument count of the inferior program.
+ // It's zero if there is there is no inferior program.
+ // Otherwise it equals the number of arguments to the inferior program + 1
+ if (a_argc > 0)
+ prog_path = a_argv[0];
+ for (int i = 1; i < a_argc; ++i) {
+ prog_args.push_back (Glib::locale_to_utf8 (a_argv[i]));
+ }
+
+ if (gv_gdb_binary_filepath) {
+ char *debugger_full_path = realpath (gv_gdb_binary_filepath, 0);
+ if (debugger_full_path) {
+ if (!debugger ()) {
+ cerr << "Could not get the debugger instance" << std::endl;
+ return false;
+ }
+ debugger ()->set_non_persistent_debugger_path (debugger_full_path);
+ free (debugger_full_path);
+ } else {
+ LOG_ERROR ("Could not resolve the full path of the debugger");
+ }
+ }
+
+ std::map<UString, UString> env;
+ if (gv_env_vars) {
+ std::vector<UString> env_vars =
+ UString (Glib::locale_to_utf8 (gv_env_vars)).split (" ");
+ for (std::vector<UString>::const_iterator it = env_vars.begin ();
+ it != env_vars.end ();
+ ++it) {
+ std::vector<UString> env_var = it->split ("=");
+ if (env_var.size () != 2) {
+ continue;
+ }
+ UString name = env_var[0];
+ name.chomp ();
+ UString value = env_var[1];
+ value.chomp ();
+ LOG_DD ("got env var: " << name << "=" << value);
+ env[name] = value;
+ }
+ }
+
+ if (gv_remote) {
+ // The user asked to connect to a remote target.
+ std::string host;
+ unsigned port = 0;
+ std::string solib_prefix;
+
+ if (gv_solib_prefix) {
+ solib_prefix = gv_solib_prefix;
+ }
+
+ if (nemiver::str_utils::parse_host_and_port (gv_remote, host,
+ port)) {
+ // So it looks like gv_remote has the form
+ // "host:port", so let's try to connect to that.
+ connect_to_remote_target (host, port, prog_path, solib_prefix);
+ } else {
+ // We think gv_remote contains a serial line address.
+ // Let's try to connect via the serial line then.
+ connect_to_remote_target (gv_remote, prog_path, solib_prefix);
+ }
+ } else if (!prog_path.empty ()) {
+ // The user wants to debug a local program
+ uses_launch_terminal (gv_use_launch_terminal);
+ execute_program (prog_path, prog_args, env, ".", false);
+ }
+
+ if (gv_use_launch_terminal) {
+ // So the user wants the inferior to use the terminal Nemiver was
+ // launched from, for input/output.
+ //
+ // Letting the inferior use the terminal from which Nemiver was
+ // launched from implies calling the "set inferior-tty" GDB command,
+ // when we are using the GDB backend.
+ // That command is implemented using the TIOCSCTTY ioctl. It sets the
+ // terminal as the controlling terminal of the inferior process. But that
+ // ioctl requires (among other things) that the terminal shall _not_ be
+ // the controlling terminal of any other process in another process
+ // session already. Otherwise, GDB spits the error:
+ // "GDB: Failed to set controlling terminal: operation not
+ // permitted"
+ // The problem is, Nemiver itself uses that terminal as a
+ // controlling terminal. So Nemiver itself must relinquish its
+ // controlling terminal to avoid letting the ioctl fail.
+ // We do so by calling the setsid function below.
+ // The problem is that setsid will fail with EPERM if Nemiver is
+ // started as a process group leader already.
+ // Trying ioctl (tty_fd, TIOCNOTTY, 0) does not seem to properly
+ // disconnect Nemiver from its terminal either. Sigh.
+ setsid ();
+ }
+
+ return true;
+}
+
IConfMgr&
DBGPerspective::get_conf_mgr ()
{
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.h b/src/persp/dbgperspective/nmv-dbg-perspective.h
index efa0b3f..4886547 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.h
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.h
@@ -79,7 +79,7 @@ public:
virtual IWorkbench& get_workbench () = 0;
- virtual void edit_workbench_menu () = 0;
+ virtual std::list<Gtk::UIManager::ui_merge_id> edit_workbench_menu () = 0;
virtual void open_file () = 0;
@@ -186,6 +186,8 @@ public:
virtual sigc::signal<void>& layout_changed_signal () = 0;
+ virtual const UString& name () const = 0;
+
virtual bool agree_to_shutdown () = 0;
};//end class IDBGPerspective
diff --git a/src/persp/nmv-i-perspective.h b/src/persp/nmv-i-perspective.h
index c0440f1..444ae45 100644
--- a/src/persp/nmv-i-perspective.h
+++ b/src/persp/nmv-i-perspective.h
@@ -65,6 +65,16 @@ protected:
public:
+ virtual bool process_gui_options (int a_argc, char **a_argv) = 0;
+
+ virtual bool process_options (GOptionContext *a_context,
+ int a_argc,
+ char **a_argv) = 0;
+
+ virtual GOptionGroup* option_group () const = 0;
+
+ virtual const UString& name () const = 0;
+
/// initialize the perspective within the context of
/// of the workbench that loads it.
/// \param a_workbench, the workbench that loaded the
@@ -92,26 +102,7 @@ public:
/// This method is only called once, during the
/// perspective's initialisation time,
/// by the workbench.
- virtual void edit_workbench_menu () = 0;
-
- /// \brief open a source file from a url
- /// \param a_uri the uri of the file to open
- /// \param a_cur_line the line to flag as being the current exceution line
- /// if set to -1, this parameter is ignored.
- virtual bool open_file (const UString &a_uri, int a_cur_line=-1) = 0;
-
- /// \brief open a source file
- ///
- /// Let the user choose the set of files to open
- /// via a file chooser dialog and open them.
- virtual void open_file () = 0;
-
- /// \brief close the currently selected file
- virtual void close_current_file () = 0;
-
- /// \brief closes a file
- /// \param a_uri the uri that identifies the file to close
- virtual void close_file (const UString &a_uri) = 0;
+ virtual std::list<Gtk::UIManager::ui_merge_id> edit_workbench_menu () = 0;
/// \brief load a menu file
/// \param a_filename the file name of the menu file.
diff --git a/src/workbench/nmv-i-workbench.h b/src/workbench/nmv-i-workbench.h
index 0ae7531..f668ef5 100644
--- a/src/workbench/nmv-i-workbench.h
+++ b/src/workbench/nmv-i-workbench.h
@@ -69,6 +69,7 @@ using nemiver::common::UString;
class IWorkbench;
typedef SafePtr<IWorkbench, ObjectRef, ObjectUnref> IWorkbenchSafePtr;
+typedef SafePtr<IPerspective, ObjectRef, ObjectUnref> IPerspectiveSafePtr;
/// \brief the interface of the Workbench.
/// The workbench is what you see graphically when you use
@@ -136,8 +137,14 @@ public:
/// \return the Gtk::UIManager of the workbench
virtual Glib::RefPtr<Gtk::UIManager>& get_ui_manager () = 0;
+ virtual std::list<IPerspectiveSafePtr> perspectives () const = 0;
+
/// \return the perspective that which name matches a_name
- virtual IPerspective* get_perspective (const UString &a_name) = 0;
+ virtual IPerspectiveSafePtr get_perspective (const UString &a_name) = 0;
+
+ virtual void select_perspective (IPerspectiveSafePtr &a_perspective) = 0;
+
+ virtual void do_init_dev () = 0;
/// set the configuration manager used by this interface
virtual void do_init (IConfMgrSafePtr &) = 0;
diff --git a/src/workbench/nmv-workbench.cc b/src/workbench/nmv-workbench.cc
index e82c13d..b4e24b8 100644
--- a/src/workbench/nmv-workbench.cc
+++ b/src/workbench/nmv-workbench.cc
@@ -86,6 +86,7 @@ private:
void on_contents_menu_item_action ();
void on_shutting_down_signal ();
void on_perspective_layout_changed_signal (IPerspectiveSafePtr);
+ void on_perspective_changed ();
//************************
//</slots (signal callbacks)>
//************************
@@ -100,10 +101,11 @@ private:
list<Gtk::Widget*> &a_tbs);
void add_perspective_body (IPerspectiveSafePtr &a_perspective,
Gtk::Widget *a_body);
+ void add_perspective_to_perspective_selector
+ (IPerspectiveSafePtr &a_perspective);
bool remove_perspective_body (IPerspectiveSafePtr &a_perspective);
void remove_all_perspective_bodies ();
void disconnect_all_perspective_signals ();
- void select_perspective (IPerspectiveSafePtr &a_perspective);
void save_window_geometry ();
@@ -118,8 +120,10 @@ private:
public:
Workbench (DynamicModule *a_dynmod);
virtual ~Workbench ();
+ void do_init_dev ();
void do_init (Gtk::Main &a_main);
void do_init (IConfMgrSafePtr &);
+ void select_perspective (IPerspectiveSafePtr &a_perspective);
void shut_down ();
Glib::RefPtr<Gtk::ActionGroup> get_default_action_group ();
Glib::RefPtr<Gtk::ActionGroup> get_debugger_ready_action_group ();
@@ -128,7 +132,8 @@ public:
Gtk::Window& get_root_window ();
void set_title_extension (const UString &a_str);
Glib::RefPtr<Gtk::UIManager>& get_ui_manager () ;
- IPerspective* get_perspective (const UString &a_name);
+ IPerspectiveSafePtr get_perspective (const UString &a_name);
+ std::list<IPerspectiveSafePtr> perspectives () const;
void set_configuration_manager (IConfMgrSafePtr &);
IConfMgrSafePtr get_configuration_manager () ;
Glib::RefPtr<Glib::MainContext> get_main_context () ;
@@ -145,6 +150,7 @@ struct Workbench::Priv {
Gtk::Widget *menubar;
Gtk::Notebook *toolbar_container;
Gtk::Notebook *bodies_container;
+ Gtk::ComboBoxText *persp_selector_combobox;
PluginManagerSafePtr plugin_manager;
list<IPerspectiveSafePtr> perspectives;
map<IPerspective*, int> toolbars_index_map;
@@ -153,6 +159,7 @@ struct Workbench::Priv {
IConfMgrSafePtr conf_mgr;
sigc::signal<void> shutting_down_signal;
UString base_title;
+ std::list<Gtk::UIManager::ui_merge_id> perspective_menubar_merge_ids;
Priv () :
initialized (false),
@@ -193,6 +200,28 @@ Workbench::query_for_shutdown ()
//*********************
//signal slots methods
//*********************
+void
+Workbench::on_perspective_changed ()
+{
+ NEMIVER_TRY
+
+ THROW_IF_FAIL (m_priv);
+ THROW_IF_FAIL (m_priv->persp_selector_combobox);
+
+ UString name = m_priv->persp_selector_combobox->get_active_text ();
+ std::list<IPerspectiveSafePtr>::iterator iter;
+ for (iter = m_priv->perspectives.begin ();
+ iter != m_priv->perspectives.end ();
+ ++iter) {
+ if ((*iter)->name () == name) {
+ select_perspective (*iter);
+ return;
+ }
+ }
+
+ NEMIVER_CATCH
+}
+
bool
Workbench::on_delete_event (GdkEventAny* a_event)
{
@@ -346,16 +375,9 @@ Workbench::do_init (IConfMgrSafePtr &a_conf_mgr)
set_configuration_manager (a_conf_mgr);
}
-/// Initialize the workbench by doing all the graphical plumbling
-/// needed to setup the perspectives held by this workbench. Calling
-/// this function is mandatory prior to using the workbench.
-///
-/// \param a_main the Gtk main object the workbench is going to use.
void
-Workbench::do_init (Gtk::Main &a_main)
+Workbench::do_init_dev ()
{
- LOG_FUNCTION_SCOPE_NORMAL_DD;
-
DynamicModule::Loader *loader =
get_dynamic_module ().get_module_loader ();
THROW_IF_FAIL (loader);
@@ -364,6 +386,56 @@ Workbench::do_init (Gtk::Main &a_main)
loader->get_dynamic_module_manager ();
THROW_IF_FAIL (dynmod_manager);
+ m_priv->plugin_manager =
+ PluginManagerSafePtr (new PluginManager (*dynmod_manager));
+
+ NEMIVER_TRY
+
+ std::map<UString, PluginSafePtr>::const_iterator plugin_iter;
+ Plugin::EntryPointSafePtr entry_point;
+ IPerspectiveSafePtr perspective;
+
+ m_priv->plugin_manager->load_plugins ();
+
+ //**************************************************************
+ //store the list of perspectives we may have loaded as plugins,
+ //and init each of them.
+ //**************************************************************
+ for (plugin_iter = m_priv->plugin_manager->plugins_map ().begin ();
+ plugin_iter != m_priv->plugin_manager->plugins_map ().end ();
+ ++plugin_iter) {
+ LOG_D ("plugin '"
+ << plugin_iter->second->descriptor ()->name ()
+ << "' refcount: "
+ << (int) plugin_iter->second->get_refcount (),
+ "refcount-domain");
+ if (plugin_iter->second && plugin_iter->second->entry_point_ptr ()) {
+ entry_point = plugin_iter->second->entry_point_ptr ();
+ perspective = entry_point.do_dynamic_cast<IPerspective> ();
+ if (perspective) {
+ m_priv->perspectives.push_front (perspective);
+ LOG_D ("perspective '"
+ << perspective->get_perspective_identifier ()
+ << "' refcount: "
+ << (int) perspective->get_refcount (),
+ "refcount-domain");
+ }
+ }
+ }
+
+ NEMIVER_CATCH
+}
+
+/// Initialize the workbench by doing all the graphical plumbling
+/// needed to setup the perspectives held by this workbench. Calling
+/// this function is mandatory prior to using the workbench.
+///
+/// \param a_main the Gtk main object the workbench is going to use.
+void
+Workbench::do_init (Gtk::Main &a_main)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
m_priv->main = &a_main;
// set the icon that will be used by all workbench windows that don't
@@ -394,15 +466,8 @@ Workbench::do_init (Gtk::Main &a_main)
m_priv->initialized = true;
- m_priv->plugin_manager =
- PluginManagerSafePtr (new PluginManager (*dynmod_manager));
-
NEMIVER_TRY
- m_priv->plugin_manager->load_plugins ();
-
- map<UString, PluginSafePtr>::const_iterator plugin_iter;
IPerspectiveSafePtr perspective;
- Plugin::EntryPointSafePtr entry_point;
list<Gtk::Widget*> toolbars;
//**************************************************************
@@ -410,41 +475,31 @@ Workbench::do_init (Gtk::Main &a_main)
//and init each of them.
//**************************************************************
IWorkbench *workbench = dynamic_cast<IWorkbench*> (this);
- for (plugin_iter = m_priv->plugin_manager->plugins_map ().begin ();
- plugin_iter != m_priv->plugin_manager->plugins_map ().end ();
- ++plugin_iter) {
- LOG_D ("plugin '"
- << plugin_iter->second->descriptor ()->name ()
- << "' refcount: "
- << (int) plugin_iter->second->get_refcount (),
- "refcount-domain");
- if (plugin_iter->second && plugin_iter->second->entry_point_ptr ()) {
- entry_point = plugin_iter->second->entry_point_ptr ();
- perspective = entry_point.do_dynamic_cast<IPerspective> ();
- if (perspective) {
- m_priv->perspectives.push_front (perspective);
- perspective->do_init (workbench);
- perspective->layout_changed_signal ().connect
- (sigc::bind<IPerspectiveSafePtr> (sigc::mem_fun
- (*this,
- &Workbench::on_perspective_layout_changed_signal),
- perspective));
- perspective->edit_workbench_menu ();
- toolbars.clear ();
- perspective->get_toolbars (toolbars);
- add_perspective_toolbars (perspective, toolbars);
- add_perspective_body (perspective, perspective->get_body ());
- LOG_D ("perspective '"
- << perspective->get_perspective_identifier ()
- << "' refcount: "
- << (int) perspective->get_refcount (),
- "refcount-domain");
- }
+ std::list<IPerspectiveSafePtr>::iterator iter;
+ for (iter = m_priv->perspectives.begin ();
+ iter != m_priv->perspectives.end ();
+ ++iter) {
+ perspective = *iter;
+ if (perspective) {
+ perspective->do_init (workbench);
+ perspective->layout_changed_signal ().connect
+ (sigc::bind<IPerspectiveSafePtr> (sigc::mem_fun
+ (*this,
+ &Workbench::on_perspective_layout_changed_signal),
+ perspective));
+ toolbars.clear ();
+ perspective->get_toolbars (toolbars);
+ add_perspective_to_perspective_selector (perspective);
+ add_perspective_toolbars (perspective, toolbars);
+ add_perspective_body (perspective, perspective->get_body ());
}
}
if (!m_priv->perspectives.empty ()) {
- select_perspective (*m_priv->perspectives.begin ());
+ perspective = *m_priv->perspectives.begin ();
+ THROW_IF_FAIL (perspective);
+ m_priv->persp_selector_combobox->set_active_text
+ (perspective->name ());
}
NEMIVER_CATCH
}
@@ -514,7 +569,14 @@ Workbench::get_ui_manager ()
return m_priv->ui_manager;
}
-IPerspective*
+std::list<IPerspectiveSafePtr>
+Workbench::perspectives () const
+{
+ THROW_IF_FAIL (m_priv);
+ return m_priv->perspectives;
+}
+
+IPerspectiveSafePtr
Workbench::get_perspective (const UString &a_name)
{
list<IPerspectiveSafePtr>::const_iterator iter;
@@ -522,11 +584,11 @@ Workbench::get_perspective (const UString &a_name)
iter != m_priv->perspectives.end ();
++iter) {
if ((*iter)->descriptor ()->name () == a_name) {
- return iter->get ();
+ return *iter;
}
}
- LOG_ERROR ("could not find perspective: '" << a_name << "'");
- return 0;
+
+ return IPerspectiveSafePtr ();
}
/// Set the configuration manager
@@ -772,6 +834,13 @@ Workbench::init_toolbar ()
m_priv->toolbar_container =
ui_utils::get_widget_from_gtkbuilder<Gtk::Notebook> (m_priv->builder,
"toolbarcontainer");
+
+ m_priv->persp_selector_combobox =
+ ui_utils::get_widget_from_gtkbuilder<Gtk::ComboBoxText>
+ (m_priv->builder, "perspectiveselector");
+ m_priv->persp_selector_combobox->set_entry_text_column (0);
+ m_priv->persp_selector_combobox->signal_changed ().connect (sigc::mem_fun
+ (*this, &Workbench::on_perspective_changed));
}
void
@@ -806,6 +875,18 @@ Workbench::add_perspective_toolbars (IPerspectiveSafePtr &a_perspective,
}
void
+Workbench::add_perspective_to_perspective_selector
+ (IPerspectiveSafePtr &a_perspective)
+{
+ THROW_IF_FAIL (m_priv);
+ THROW_IF_FAIL (a_perspective);
+ THROW_IF_FAIL (m_priv->persp_selector_combobox);
+
+ m_priv->persp_selector_combobox->append
+ (a_perspective->name ());
+}
+
+void
Workbench::add_perspective_body (IPerspectiveSafePtr &a_perspective,
Gtk::Widget *a_body)
{
@@ -923,6 +1004,7 @@ Workbench::select_perspective (IPerspectiveSafePtr &a_perspective)
THROW_IF_FAIL (m_priv);
THROW_IF_FAIL (m_priv->toolbar_container);
THROW_IF_FAIL (m_priv->bodies_container);
+ THROW_IF_FAIL (a_perspective);
map<IPerspective*, int>::const_iterator iter, nil;
int toolbar_index=0, body_index=0;
@@ -939,9 +1021,24 @@ Workbench::select_perspective (IPerspectiveSafePtr &a_perspective)
body_index = iter->second;
}
+ std::list<Gtk::UIManager::ui_merge_id>::iterator merge_id;
+ for (merge_id = m_priv->perspective_menubar_merge_ids.begin ();
+ merge_id != m_priv->perspective_menubar_merge_ids.end ();
+ ++merge_id) {
+ m_priv->ui_manager->remove_ui (*merge_id);
+ }
+ m_priv->perspective_menubar_merge_ids =
+ a_perspective->edit_workbench_menu ();
+
m_priv->toolbar_container->set_current_page (toolbar_index);
m_priv->bodies_container->set_current_page (body_index);
+
+ UString name = m_priv->persp_selector_combobox->get_active_text ();
+ if (a_perspective->name () != name) {
+ m_priv->persp_selector_combobox->set_active_text
+ (a_perspective->name ());
+ }
}
class WorkbenchModule : public DynamicModule {
diff --git a/ui/workbench.ui b/ui/workbench.ui
index 22d555b..aafc74b 100644
--- a/ui/workbench.ui
+++ b/ui/workbench.ui
@@ -1,9 +1,9 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <!-- interface-requires gtk+ 2.6 -->
- <!-- interface-naming-policy toplevel-contextual -->
+ <!-- interface-requires gtk+ 3.0 -->
<object class="GtkWindow" id="workbench">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="title" translatable="yes">Nemiver</property>
<property name="default_width">800</property>
<property name="default_height">600</property>
@@ -11,11 +11,11 @@
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
+ <property name="can_focus">False</property>
<child>
<object class="GtkVBox" id="menucontainer">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
+ <property name="can_focus">False</property>
<child>
<placeholder/>
</child>
@@ -29,53 +29,82 @@
<child>
<object class="GtkVBox" id="toolbarvbox">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
+ <property name="can_focus">False</property>
<child>
- <object class="GtkNotebook" id="toolbarcontainer">
+ <object class="GtkBox" id="toolbarhbox">
<property name="visible">True</property>
- <property name="show_tabs">False</property>
- <property name="show_border">False</property>
+ <property name="can_focus">False</property>
<child>
- <object class="GtkVBox" id="emptytoolbar">
+ <object class="GtkNotebook" id="toolbarcontainer">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
+ <property name="can_focus">False</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
<child>
- <placeholder/>
+ <object class="GtkVBox" id="emptytoolbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">label1</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
</child>
</object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
</child>
- <child type="tab">
- <object class="GtkLabel" id="label1">
+ <child>
+ <object class="GtkComboBoxText" id="perspectiveselector">
<property name="visible">True</property>
- <property name="label" translatable="yes">label1</property>
+ <property name="can_focus">False</property>
+ <property name="id_column">0</property>
</object>
<packing>
- <property name="tab_fill">False</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
</packing>
</child>
</object>
<packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
+ <property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="bodybox">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
+ <property name="can_focus">False</property>
<child>
<object class="GtkNotebook" id="bodynotebook">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="show_tabs">False</property>
<child>
<object class="GtkVBox" id="emptybody">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
+ <property name="can_focus">False</property>
<child>
<placeholder/>
</child>
@@ -84,6 +113,7 @@
<child type="tab">
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">label2</property>
</object>
<packing>
@@ -92,11 +122,15 @@
</child>
</object>
<packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
@@ -104,3 +138,4 @@
</child>
</object>
</interface>
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]