Mercurial > hg > octave-nkf
changeset 16547:3cd80afc3509
improve debugging with the GUI
* dialog.h, dialog.cc (cd_or_addpath_dialog): New class.
(QUIWidgetCreator::signal_debug_cd_or_addpath): New function.
(QUIWidgetCreator::create_debug_cd_or_addpath_dialog): New signal.
* file-editor-tab.h, file-editor-tab.cc
(file_editor_tab::file_in_path): New function.
(file_editor_tab::add_breakpoint_callback,
file_editor_tab::remove_breakpoint_callback,
file_editor_tab::remove_all_breakpoints_callback): Use file_in_path.
Don't cd to the directory containing the file. Don't add 1 to the
line number.
(file_editor_tab::request_add_breakpoint,
file_editor_tab::request_remove_breakpoint):
Add 1 to the line number.
(file_editor_tab::insert_debugger_pointer,
file_editor_tab::delete_debugger_pointer,
file_editor_tab::do_breakpoint_marker): Subtract 1 from line.
(file_editor_tab::bp_info): Also cache full file name. Change all uses.
* file-editor.h, file-editor.cc (file_editor::request_open_file,
file_editor::handle_delete_debugger_pointer_request):
Don't subtract 1 from line numbers.
* main-window.h, main-window.cc (main_window::connect_uiwidget_links):
Connect uiwidget_creator::create_debug_cd_or_addpath_dialog to
main_window::handle_create_debug_cd_or_addpath_dialog.
(main_window::handle_create_debug_cd_or_addpath_dialog):
New function.
* octave-qt-link.h, octave-qt-link.cc
(octave_qt_link::do_debug_cd_or_addpath_error): New function.
* load-path.h, load-path.cc (load_path::contains_canonical,
load_path::do_contains_canonical): New functions.
* octave-link.h (octave_link::debug_cd_or_addpath_error,
octave_link::do_debug_cd_or_addpath_error): New functions.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 19 Apr 2013 17:36:40 -0400 |
parents | c1e90c7cfd30 |
children | 7a4fd41ac823 |
files | libgui/src/dialog.cc libgui/src/dialog.h libgui/src/m-editor/file-editor-tab.cc libgui/src/m-editor/file-editor-tab.h libgui/src/m-editor/file-editor.cc libgui/src/main-window.cc libgui/src/main-window.h libgui/src/octave-qt-link.cc libgui/src/octave-qt-link.h libinterp/interpfcn/load-path.cc libinterp/interpfcn/load-path.h libinterp/interpfcn/octave-link.h |
diffstat | 12 files changed, 300 insertions(+), 45 deletions(-) [+] |
line wrap: on
line diff
--- a/libgui/src/dialog.cc +++ b/libgui/src/dialog.cc @@ -377,9 +377,89 @@ done (QDialog::Rejected); } - + void InputDialog::reject (void) { buttonCancel_clicked (); } + + +cd_or_addpath_dialog::cd_or_addpath_dialog (const QString& file, + const QString& dir, + bool addpath_option) + : QDialog () +{ + QString prompt_string + = (addpath_option + ? tr ("The file %1 does not exist in the load path. To debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.").arg(file).arg(dir) + : tr ("The file %1 is shadowed by a file with the same name in the load path. To debug the function you are editing, change to the directory %2.").arg(file).arg(dir)); + + QLabel *label = new QLabel (prompt_string); + label->setFixedWidth (500); + label->setWordWrap (true); + // QIcon *question_mark = new QIcon; + QHBoxLayout *horizontalLayout = new QHBoxLayout; + // horizontalLayout->addWidget (question_mark); + horizontalLayout->addWidget (label); + + QPushButton *buttonCd = new QPushButton (tr ("Change directory")); + QPushButton *buttonAddpath = 0; + if (addpath_option) + buttonAddpath = new QPushButton (tr ("Add directory to load path")); + QPushButton *buttonCancel = new QPushButton (tr ("Cancel")); + + QHBoxLayout *buttonsLayout = new QHBoxLayout; + buttonsLayout->addStretch (1); + buttonsLayout->addWidget (buttonCd); + if (addpath_option) + buttonsLayout->addWidget (buttonAddpath); + buttonsLayout->addWidget (buttonCancel); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addLayout (horizontalLayout); + mainLayout->addSpacing (12); + mainLayout->addLayout (buttonsLayout); + setLayout (mainLayout); + + setWindowTitle (tr ("Change Directory or Add Directory to Load Path")); + + connect (buttonCd, SIGNAL (clicked ()), + this, SLOT (buttonCd_clicked ())); + + connect (buttonAddpath, SIGNAL (clicked ()), + this, SLOT (buttonAddpath_clicked ())); + + connect (buttonCancel, SIGNAL (clicked ()), + this, SLOT (buttonCancel_clicked ())); + + connect (this, SIGNAL (finished (int)), + &uiwidget_creator, SLOT (dialog_finished (int))); +} + +void +cd_or_addpath_dialog::buttonCd_clicked (void) +{ + emit finished (1); + done (QDialog::Accepted); +} + +void +cd_or_addpath_dialog::buttonAddpath_clicked (void) +{ + emit finished (2); + done (QDialog::Accepted); +} + +void +cd_or_addpath_dialog::buttonCancel_clicked (void) +{ + emit finished (-1); + done (QDialog::Rejected); +} + +void +cd_or_addpath_dialog::reject (void) +{ + buttonCancel_clicked (); +}
--- a/libgui/src/dialog.h +++ b/libgui/src/dialog.h @@ -101,6 +101,17 @@ return true; }; + // The debug dialog functionality may not really belong here, but it + // seems like the easiest thing to do at the moment. + + bool signal_debug_cd_or_addpath (const QString& file, const QString& dir, + bool addpath_option) + { + emit create_debug_cd_or_addpath_dialog (file, dir, addpath_option); + + return true; + } + const QStringList *get_string_list (void) { return string_list; } void wait (void) @@ -122,6 +133,8 @@ const QIntList&, const QIntList&, const QStringList&); + void create_debug_cd_or_addpath_dialog (const QString&, const QString&, bool); + public slots: void dialog_finished (int result); @@ -219,4 +232,24 @@ void reject (void); }; +class cd_or_addpath_dialog : public QDialog +{ + Q_OBJECT + +public: + + cd_or_addpath_dialog (const QString& file, const QString& dir, + bool addpath_option); + +public slots: + + void buttonCd_clicked (void); + + void buttonAddpath_clicked (void); + + void buttonCancel_clicked (void); + + void reject (void); +}; + #endif
--- a/libgui/src/m-editor/file-editor-tab.cc +++ b/libgui/src/m-editor/file-editor-tab.cc @@ -47,10 +47,13 @@ #include "file-editor-tab.h" #include "file-editor.h" + +#include "builtin-defun-decls.h" +#include "debug.h" +#include "load-path.h" #include "octave-link.h" - -#include "debug.h" #include "oct-env.h" +#include "utils.h" // Make parent null for the file editor tab so that warning // WindowModal messages don't affect grandparents. @@ -195,13 +198,9 @@ else { if (markers_mask && (1 << breakpoint)) - { - request_remove_breakpoint (line); - } + request_remove_breakpoint (line); else - { - request_add_breakpoint (line); - } + request_add_breakpoint (line); } } } @@ -431,42 +430,96 @@ _edit_area->markerDeleteAll (bookmark); } +bool +file_editor_tab::file_in_path (const bp_info& info) +{ + bool ok = false; + bool addpath_option = true; + + std::string curr_dir = octave_env::get_current_directory (); + + if (curr_dir == info.path) + ok = true; + else + { + bool dir_in_load_path = load_path::contains_canonical (info.path); + + std::string base_file = octave_env::base_pathname (info.file); + std::string lp_file = load_path::find_file (base_file); + + if (dir_in_load_path) + { + if (same_file (lp_file, info.file)) + ok = true; + } + else + { + // File directory is not in path. Is the file in the path in + // the current directory? If so, then changing the current + // directory will be needed. Adding directory to path is + // not enough because the file in the current directory would + // still be found. + + if (same_file (lp_file, base_file)) + { + if (same_file (curr_dir, info.path)) + ok = true; + else + addpath_option = false; + } + } + } + + if (! ok) + { + int action + = octave_link::debug_cd_or_addpath_error (info.file, info.path, + addpath_option); + switch (action) + { + case 1: + Fcd (ovl (info.path)); + ok = true; + break; + + case 2: + load_path::prepend (info.path); + ok = true; + break; + + default: + break; + } + } + + return ok; +} + void file_editor_tab::add_breakpoint_callback (const bp_info& info) { - bp_table::intmap intmap; - intmap[0] = info.line + 1; + bp_table::intmap line_info; + line_info[0] = info.line; - std::string previous_directory = octave_env::get_current_directory (); - octave_env::chdir (info.path); - intmap = bp_table::add_breakpoint (info.function_name, intmap); - octave_env::chdir (previous_directory); - // bp_table::add_breakpoint also sets the marker in the editor + if (file_in_path (info)) + bp_table::add_breakpoint (info.function_name, line_info); } void file_editor_tab::remove_breakpoint_callback (const bp_info& info) { - bp_table::intmap intmap; - intmap[0] = info.line + 1; + bp_table::intmap line_info; + line_info[0] = info.line; - std::string previous_directory = octave_env::get_current_directory (); - octave_env::chdir (info.path); - bp_table::remove_breakpoint (info.function_name, intmap); - octave_env::chdir (previous_directory); + if (file_in_path (info)) + bp_table::remove_breakpoint (info.function_name, line_info); } void file_editor_tab::remove_all_breakpoints_callback (const bp_info& info) { - bp_table::intmap intmap; - std::string previous_directory = octave_env::get_current_directory (); - octave_env::chdir (info.path); - intmap = bp_table::remove_all_breakpoints_in_file (info.function_name, true); - octave_env::chdir (previous_directory); - - if (intmap.size() > 0) - _edit_area->markerDeleteAll (breakpoint); + if (file_in_path (info)) + bp_table::remove_all_breakpoints_in_file (info.function_name, true); } void @@ -479,7 +532,7 @@ // We have to cut off the suffix, because octave appends it. function_name.chop (file_info.suffix ().length () + 1); - bp_info info (path, function_name, line); + bp_info info (_file_name, path, function_name, line+1); octave_link::post_event (this, &file_editor_tab::add_breakpoint_callback, info); @@ -495,7 +548,7 @@ // We have to cut off the suffix, because octave appends it. function_name.chop (file_info.suffix ().length () + 1); - bp_info info (path, function_name, line); + bp_info info (_file_name, path, function_name, line+1); octave_link::post_event (this, &file_editor_tab::remove_breakpoint_callback, info); @@ -556,7 +609,7 @@ // We have to cut off the suffix, because octave appends it. function_name.chop (file_info.suffix ().length () + 1); - bp_info info (path, function_name, 0); + bp_info info (_file_name, path, function_name, 0); octave_link::post_event (this, &file_editor_tab::remove_all_breakpoints_callback, info); @@ -1143,7 +1196,7 @@ if (line > 0) { - _edit_area->markerAdd (line, debugger_position); + _edit_area->markerAdd (line-1, debugger_position); center_current_line (); } } @@ -1155,7 +1208,7 @@ return; if (line > 0) - _edit_area->markerDelete (line, debugger_position); + _edit_area->markerDelete (line-1, debugger_position); } void @@ -1167,9 +1220,9 @@ if (line > 0) { if (insert) - _edit_area->markerAdd (line, breakpoint); + _edit_area->markerAdd (line-1, breakpoint); else - _edit_area->markerDelete (line, breakpoint); + _edit_area->markerDelete (line-1, breakpoint); } }
--- a/libgui/src/m-editor/file-editor-tab.h +++ b/libgui/src/m-editor/file-editor-tab.h @@ -122,10 +122,12 @@ struct bp_info { - bp_info (const QString& p, const QString& fn, int l) - : path (p.toStdString ()), function_name (fn.toStdString ()), line (l) + bp_info (const QString& f, const QString& p, const QString& fn, int l) + : file (f.toStdString ()), path (p.toStdString ()), + function_name (fn.toStdString ()), line (l) { } + std::string file; std::string path; std::string function_name; int line; @@ -143,6 +145,9 @@ void do_comment_selected_text (bool comment); void run_file_callback (void); + + bool file_in_path (const bp_info& info); + void add_breakpoint_callback (const bp_info& info); void remove_breakpoint_callback (const bp_info& info); void remove_all_breakpoints_callback (const bp_info& info);
--- a/libgui/src/m-editor/file-editor.cc +++ b/libgui/src/m-editor/file-editor.cc @@ -230,10 +230,10 @@ emit fetab_goto_line (tab, line); if (debug_pointer) - emit fetab_insert_debugger_pointer (tab, line-1); + emit fetab_insert_debugger_pointer (tab, line); if (breakpoint_marker) - emit fetab_do_breakpoint_marker (insert, tab, line-1); + emit fetab_do_breakpoint_marker (insert, tab, line); } emit fetab_set_focus (tab); @@ -258,10 +258,11 @@ emit fetab_goto_line (fileEditorTab, line); if (debug_pointer) - emit fetab_insert_debugger_pointer (fileEditorTab, line-1); + emit fetab_insert_debugger_pointer (fileEditorTab, + line); if (breakpoint_marker) - emit fetab_do_breakpoint_marker - (insert, fileEditorTab, line-1); + emit fetab_do_breakpoint_marker (insert, fileEditorTab, + line); } } else @@ -380,7 +381,7 @@ _tab_widget->setCurrentWidget (tab); if (line > 0) - emit fetab_delete_debugger_pointer (tab, line-1); + emit fetab_delete_debugger_pointer (tab, line); emit fetab_set_focus (tab); }
--- a/libgui/src/main-window.cc +++ b/libgui/src/main-window.cc @@ -592,6 +592,14 @@ SLOT (handle_create_inputlayout (const QStringList&, const QString&, const QIntList&, const QIntList&, const QStringList&))); + + connect (&uiwidget_creator, + SIGNAL (create_debug_cd_or_addpath_dialog (const QString&, + const QString&, bool)), + this, + SLOT (handle_create_debug_cd_or_addpath_dialog (const QString&, + const QString&, + bool))); } // Create a message dialog with specified string, buttons and decorative @@ -648,6 +656,19 @@ input_dialog->show (); } +void +main_window::handle_create_debug_cd_or_addpath_dialog (const QString& file, + const QString& dir, + bool addpath_option) + +{ + cd_or_addpath_dialog *dialog + = new cd_or_addpath_dialog (file, dir, addpath_option); + + dialog->setAttribute (Qt::WA_DeleteOnClose); + dialog->show (); +} + // Main subroutine of the constructor void main_window::construct (void)
--- a/libgui/src/main-window.h +++ b/libgui/src/main-window.h @@ -142,6 +142,9 @@ const QIntList&, const QIntList&, const QStringList&); + void handle_create_debug_cd_or_addpath_dialog (const QString& file, + const QString& dir, + bool addpath_option); // find files dialog void find_files(const QString &startdir=QDir::currentPath()); void find_files_finished(int);
--- a/libgui/src/octave-qt-link.cc +++ b/libgui/src/octave-qt-link.cc @@ -31,6 +31,7 @@ #include "str-vec.h" #include "dialog.h" +#include "error.h" #include "workspace-element.h" #include "octave-qt-link.h" @@ -154,6 +155,20 @@ return retval; } +int +octave_qt_link::do_debug_cd_or_addpath_error (const std::string& file, + const std::string& dir, + bool addpath_option) +{ + uiwidget_creator.signal_debug_cd_or_addpath (QString::fromStdString (file), + QString::fromStdString (dir), + addpath_option); + + uiwidget_creator.wait (); + + return uiwidget_creator.get_dialog_result (); +} + void octave_qt_link::do_change_directory (const std::string& dir) {
--- a/libgui/src/octave-qt-link.h +++ b/libgui/src/octave-qt-link.h @@ -79,6 +79,11 @@ const std::list<int>& nc, const std::list<std::string>& defaults); + int + do_debug_cd_or_addpath_error (const std::string& file, + const std::string& dir, + bool addpath_option); + void do_change_directory (const std::string& dir); void do_set_workspace (bool top_level,
--- a/libinterp/interpfcn/load-path.cc +++ b/libinterp/interpfcn/load-path.cc @@ -353,6 +353,25 @@ return find_dir_info (dir) != dir_info_list.end (); } +bool +load_path::do_contains_canonical (const std::string& dir) const +{ + bool retval = false; + + for (const_dir_info_list_iterator i = dir_info_list.begin (); + i != dir_info_list.end (); + i++) + { + if (same_file (dir, i->dir_name)) + { + retval = true; + break; + } + } + + return retval; +} + void load_path::move_fcn_map (const std::string& dir_name, const string_vector& fcn_files, bool at_end)
--- a/libinterp/interpfcn/load-path.h +++ b/libinterp/interpfcn/load-path.h @@ -89,6 +89,11 @@ instance->do_update (); } + static bool contains_canonical (const std::string& dir_name) + { + return instance_ok () ? instance->do_contains_canonical (dir_name) : false; + } + static std::string find_method (const std::string& class_name, const std::string& meth, std::string& dir_name) @@ -465,6 +470,8 @@ bool contains (const std::string& dir) const; + bool do_contains_canonical (const std::string& dir) const; + void move_fcn_map (const std::string& dir, const string_vector& fcn_files, bool at_end);
--- a/libinterp/interpfcn/octave-link.h +++ b/libinterp/interpfcn/octave-link.h @@ -170,6 +170,14 @@ : std::list<std::string> (); } + static int debug_cd_or_addpath_error (const std::string& file, + const std::string& dir, + bool addpath_option) + { + return enabled () + ? instance->do_debug_cd_or_addpath_error (file, dir, addpath_option) : 0; + } + static void change_directory (const std::string& dir) { if (enabled ()) @@ -341,6 +349,11 @@ const std::list<int>& nc, const std::list<std::string>& defaults) = 0; + virtual int + do_debug_cd_or_addpath_error (const std::string& file, + const std::string& dir, + bool addpath_option) = 0; + virtual void do_change_directory (const std::string& dir) = 0; virtual void