[spyder] 02/10: Imported Upstream version 3.0.0~b2+dfsg1

Frédéric-Emmanuel Picca picca at moszumanska.debian.org
Sun Aug 21 17:30:24 UTC 2016


This is an automated email from the git hooks/post-receive script.

picca pushed a commit to branch experimental
in repository spyder.

commit 25fa126279d019eaa7df28b8ba611f36e558ee74
Author: Picca Frédéric-Emmanuel <picca at debian.org>
Date:   Sat Jan 9 12:30:14 2016 +0100

    Imported Upstream version 3.0.0~b2+dfsg1
---
 LICENSE                                            |    5 +-
 MANIFEST.in                                        |    2 +
 PKG-INFO                                           |   17 +-
 README.md                                          |  181 +-
 bootstrap.py                                       |   37 +-
 doc/images/arrayeditor.png                         |  Bin 16921 -> 16940 bytes
 doc/images/console.png                             |  Bin 19289 -> 19376 bytes
 doc/images/dicteditor.png                          |  Bin 12248 -> 12295 bytes
 doc/images/editor1.png                             |  Bin 37110 -> 36959 bytes
 doc/images/editor2.png                             |  Bin 16597 -> 16622 bytes
 doc/images/editor3.png                             |  Bin 45896 -> 45791 bytes
 doc/images/explorer.png                            |  Bin 19692 -> 19642 bytes
 doc/images/explorer_menu1.png                      |  Bin 5790 -> 5836 bytes
 doc/images/explorer_menu2.png                      |  Bin 8293 -> 8333 bytes
 doc/images/findinfiles.png                         |  Bin 20350 -> 20220 bytes
 doc/images/git_install_dialog.png                  |  Bin 30548 -> 30530 bytes
 doc/images/historylog.png                          |  Bin 13058 -> 13057 bytes
 doc/images/inspector_plain.png                     |  Bin 13027 -> 13068 bytes
 doc/images/inspector_rich.png                      |  Bin 13610 -> 13651 bytes
 doc/images/inspector_source.png                    |  Bin 15128 -> 15170 bytes
 doc/images/internalconsole.png                     |  Bin 17420 -> 17424 bytes
 doc/images/ipythonconsole.png                      |  Bin 25401 -> 25406 bytes
 doc/images/ipythonconsolemenu.png                  |  Bin 4357 -> 4434 bytes
 doc/images/ipythonkernelconnect.png                |  Bin 11414 -> 11458 bytes
 doc/images/lightmode.png                           |  Bin 20820 -> 20824 bytes
 doc/images/listeditor.png                          |  Bin 6487 -> 6543 bytes
 doc/images/onlinehelp.png                          |  Bin 14684 -> 14712 bytes
 doc/images/projectexplorer.png                     |  Bin 19459 -> 19407 bytes
 doc/images/projectexplorer2.png                    |  Bin 18252 -> 18164 bytes
 doc/images/pylint.png                              |  Bin 17341 -> 17316 bytes
 doc/images/texteditor.png                          |  Bin 6110 -> 6156 bytes
 doc/images/variableexplorer-imshow.png             |  Bin 57432 -> 58279 bytes
 doc/images/variableexplorer-plot.png               |  Bin 25418 -> 25556 bytes
 doc/images/variableexplorer1.png                   |  Bin 14492 -> 14532 bytes
 doc/images/variableexplorer2.png                   |  Bin 20763 -> 20838 bytes
 doc/options.rst                                    |    9 +-
 doc/spyder_bbg.png                                 |  Bin 7439 -> 7119 bytes
 img_src/spyder.png                                 |  Bin 5538 -> 5610 bytes
 img_src/spyder3.png                                |  Bin 5538 -> 5610 bytes
 scripts/spyder_win_post_install.py                 |    4 +-
 setup.cfg                                          |    5 -
 setup.py                                           |  150 +-
 spyder.egg-info/PKG-INFO                           |   31 -
 spyder.egg-info/SOURCES.txt                        |  692 ---
 spyder.egg-info/dependency_links.txt               |    1 -
 spyder.egg-info/top_level.txt                      |    2 -
 spyderlib/__init__.py                              |    4 +-
 {spyderplugins => spyderlib/config}/__init__.py    |    0
 spyderlib/{baseconfig.py => config/base.py}        |  142 +-
 spyderlib/{guiconfig.py => config/gui.py}          |    8 +-
 spyderlib/{ipythonconfig.py => config/ipython.py}  |   11 +-
 spyderlib/{config.py => config/main.py}            |   83 +-
 spyderlib/{userconfig.py => config/user.py}        |   65 +-
 spyderlib/dependencies.py                          |   12 +-
 spyderlib/fonts/spyder-charmap.json                |   50 +
 spyderlib/fonts/spyder.ttf                         |  Bin 0 -> 8704 bytes
 spyderlib/images/actions/1downarrow.png            |  Bin 595 -> 652 bytes
 spyderlib/images/actions/1uparrow.png              |  Bin 599 -> 656 bytes
 spyderlib/images/actions/2downarrow.png            |  Bin 846 -> 903 bytes
 spyderlib/images/actions/2uparrow.png              |  Bin 845 -> 902 bytes
 spyderlib/images/actions/arrow-continue.png        |  Bin 1266 -> 1368 bytes
 spyderlib/images/actions/arrow-step-in.png         |  Bin 644 -> 722 bytes
 spyderlib/images/actions/arrow-step-out.png        |  Bin 410 -> 488 bytes
 spyderlib/images/actions/arrow-step-over.png       |  Bin 710 -> 767 bytes
 spyderlib/images/actions/auto_reload.png           |  Bin 735 -> 813 bytes
 spyderlib/images/actions/browse_tab.png            |  Bin 762 -> 819 bytes
 spyderlib/images/actions/check.png                 |  Bin 978 -> 1035 bytes
 spyderlib/images/actions/cmdprompt.png             |  Bin 642 -> 720 bytes
 spyderlib/images/actions/collapse.png              |  Bin 602 -> 662 bytes
 spyderlib/images/actions/collapse_selection.png    |  Bin 724 -> 784 bytes
 spyderlib/images/actions/configure.png             |  Bin 1367 -> 1429 bytes
 spyderlib/images/actions/copywop.png               |  Bin 893 -> 971 bytes
 spyderlib/images/actions/delete.png                |  Bin 690 -> 768 bytes
 spyderlib/images/actions/edit.png                  |  Bin 657 -> 735 bytes
 spyderlib/images/actions/edit24.png                |  Bin 691 -> 769 bytes
 spyderlib/images/actions/edit_add.png              |  Bin 717 -> 798 bytes
 spyderlib/images/actions/edit_remove.png           |  Bin 432 -> 510 bytes
 spyderlib/images/actions/editcopy.png              |  Bin 768 -> 846 bytes
 spyderlib/images/actions/editcut.png               |  Bin 897 -> 978 bytes
 spyderlib/images/actions/editdelete.png            |  Bin 1137 -> 1218 bytes
 spyderlib/images/actions/editpaste.png             |  Bin 940 -> 1018 bytes
 spyderlib/images/actions/eraser.png                |  Bin 648 -> 729 bytes
 spyderlib/images/actions/exit.png                  |  Bin 895 -> 952 bytes
 spyderlib/images/actions/expand.png                |  Bin 611 -> 671 bytes
 spyderlib/images/actions/expand_selection.png      |  Bin 739 -> 799 bytes
 spyderlib/images/actions/filter.png                |  Bin 982 -> 1060 bytes
 spyderlib/images/actions/find.png                  |  Bin 1104 -> 1166 bytes
 spyderlib/images/actions/findf.png                 |  Bin 897 -> 975 bytes
 spyderlib/images/actions/findnext.png              |  Bin 1129 -> 1189 bytes
 spyderlib/images/actions/findprevious.png          |  Bin 1134 -> 1194 bytes
 spyderlib/images/actions/folder_new.png            |  Bin 750 -> 828 bytes
 spyderlib/images/actions/hide.png                  |  Bin 190 -> 269 bytes
 spyderlib/images/actions/hist.png                  |  Bin 267 -> 348 bytes
 spyderlib/images/actions/home.png                  |  Bin 833 -> 893 bytes
 spyderlib/images/actions/imshow.png                |  Bin 432 -> 510 bytes
 spyderlib/images/actions/insert.png                |  Bin 314 -> 392 bytes
 spyderlib/images/actions/lock.png                  |  Bin 777 -> 855 bytes
 spyderlib/images/actions/lock_open.png             |  Bin 307 -> 386 bytes
 spyderlib/images/actions/magnifier.png             |  Bin 656 -> 734 bytes
 spyderlib/images/actions/maximize.png              |  Bin 1068 -> 1151 bytes
 spyderlib/images/actions/next.png                  |  Bin 668 -> 749 bytes
 spyderlib/images/actions/options_less.png          |  Bin 755 -> 833 bytes
 spyderlib/images/actions/options_more.png          |  Bin 798 -> 876 bytes
 spyderlib/images/actions/plot.png                  |  Bin 304 -> 382 bytes
 spyderlib/images/actions/previous.png              |  Bin 662 -> 743 bytes
 spyderlib/images/actions/redo.png                  |  Bin 953 -> 1031 bytes
 spyderlib/images/actions/reload.png                |  Bin 844 -> 922 bytes
 spyderlib/images/actions/rename.png                |  Bin 447 -> 525 bytes
 spyderlib/images/actions/replace.png               |  Bin 1079 -> 1136 bytes
 spyderlib/images/actions/restore.png               |  Bin 396 -> 456 bytes
 spyderlib/images/actions/show.png                  |  Bin 182 -> 261 bytes
 spyderlib/images/actions/special_paste.png         |  Bin 699 -> 777 bytes
 spyderlib/images/actions/stop.png                  |  Bin 393 -> 474 bytes
 spyderlib/images/actions/stop_debug.png            |  Bin 1009 -> 1090 bytes
 spyderlib/images/actions/synchronize.png           |  Bin 575 -> 653 bytes
 spyderlib/images/actions/tooloptions.png           |  Bin 711 -> 789 bytes
 spyderlib/images/actions/undo.png                  |  Bin 1127 -> 1208 bytes
 spyderlib/images/actions/unmaximize.png            |  Bin 1018 -> 1096 bytes
 spyderlib/images/actions/up.png                    |  Bin 893 -> 971 bytes
 spyderlib/images/actions/window_fullscreen.png     |  Bin 218 -> 299 bytes
 spyderlib/images/actions/window_nofullscreen.png   |  Bin 625 -> 703 bytes
 spyderlib/images/actions/zoom_in.png               |  Bin 759 -> 837 bytes
 spyderlib/images/actions/zoom_out.png              |  Bin 759 -> 837 bytes
 spyderlib/images/advanced.png                      |  Bin 814 -> 871 bytes
 spyderlib/images/arredit.png                       |  Bin 826 -> 883 bytes
 spyderlib/images/arrow.png                         |  Bin 229 -> 289 bytes
 spyderlib/images/bold.png                          |  Bin 123 -> 181 bytes
 spyderlib/images/browser.png                       |  Bin 877 -> 955 bytes
 spyderlib/images/console/cmdprompt_t.png           |  Bin 510 -> 591 bytes
 spyderlib/images/console/console.png               |  Bin 535 -> 592 bytes
 .../images/console/{clear.png => editclear.png}    |  Bin 1611 -> 1694 bytes
 spyderlib/images/console/environ.png               |  Bin 418 -> 475 bytes
 spyderlib/images/console/history.png               |  Bin 347 -> 404 bytes
 spyderlib/images/console/history24.png             |  Bin 358 -> 436 bytes
 spyderlib/images/console/ipython_console.png       |  Bin 493 -> 571 bytes
 spyderlib/images/console/ipython_console_t.png     |  Bin 283 -> 357 bytes
 spyderlib/images/console/kill.png                  |  Bin 808 -> 889 bytes
 spyderlib/images/console/loading_sprites.png       |  Bin 4774 -> 4636 bytes
 spyderlib/images/console/prompt.png                |  Bin 217 -> 277 bytes
 spyderlib/images/console/python.png                |  Bin 667 -> 724 bytes
 spyderlib/images/console/python_t.png              |  Bin 345 -> 409 bytes
 spyderlib/images/console/restart.png               |  Bin 821 -> 899 bytes
 spyderlib/images/console/run_small.png             |  Bin 515 -> 593 bytes
 spyderlib/images/console/syspath.png               |  Bin 748 -> 826 bytes
 spyderlib/images/console/terminated.png            |  Bin 423 -> 473 bytes
 spyderlib/images/dictedit.png                      |  Bin 633 -> 693 bytes
 spyderlib/images/editor/attribute.png              |  Bin 0 -> 534 bytes
 spyderlib/images/editor/blockcomment.png           |  Bin 265 -> 320 bytes
 spyderlib/images/editor/breakpoint_big.png         |  Bin 1245 -> 1347 bytes
 spyderlib/images/editor/breakpoint_cond_big.png    |  Bin 1274 -> 1376 bytes
 spyderlib/images/editor/breakpoint_cond_small.png  |  Bin 741 -> 819 bytes
 spyderlib/images/editor/breakpoint_small.png       |  Bin 451 -> 532 bytes
 spyderlib/images/editor/bug.png                    |  Bin 1642 -> 1704 bytes
 spyderlib/images/editor/cell.png                   |  Bin 141 -> 209 bytes
 spyderlib/images/editor/class.png                  |  Bin 323 -> 380 bytes
 spyderlib/images/editor/close_panel.png            |  Bin 1034 -> 1091 bytes
 spyderlib/images/editor/comment.png                |  Bin 792 -> 873 bytes
 spyderlib/images/editor/convention.png             |  Bin 332 -> 410 bytes
 spyderlib/images/editor/debug.png                  |  Bin 1340 -> 1442 bytes
 spyderlib/images/editor/error.png                  |  Bin 393 -> 450 bytes
 spyderlib/images/editor/file.png                   |  Bin 213 -> 261 bytes
 spyderlib/images/editor/filelist.png               |  Bin 490 -> 568 bytes
 spyderlib/images/editor/fromcursor.png             |  Bin 370 -> 448 bytes
 spyderlib/images/editor/function.png               |  Bin 343 -> 403 bytes
 spyderlib/images/editor/gotoline.png               |  Bin 339 -> 399 bytes
 spyderlib/images/editor/highlight.png              |  Bin 524 -> 581 bytes
 spyderlib/images/editor/horsplit.png               |  Bin 1116 -> 1173 bytes
 spyderlib/images/editor/indent.png                 |  Bin 361 -> 439 bytes
 spyderlib/images/editor/last_edit_location.png     |  Bin 849 -> 906 bytes
 spyderlib/images/editor/method.png                 |  Bin 371 -> 431 bytes
 spyderlib/images/editor/module.png                 |  Bin 0 -> 727 bytes
 spyderlib/images/editor/newwindow.png              |  Bin 1006 -> 1063 bytes
 spyderlib/images/editor/next_cursor.png            |  Bin 884 -> 941 bytes
 spyderlib/images/editor/next_wng.png               |  Bin 876 -> 936 bytes
 spyderlib/images/editor/no_match.png               |  Bin 0 -> 161 bytes
 spyderlib/images/editor/outline_explorer.png       |  Bin 718 -> 775 bytes
 spyderlib/images/editor/outline_explorer_vis.png   |  Bin 989 -> 1046 bytes
 spyderlib/images/editor/prev_cursor.png            |  Bin 881 -> 938 bytes
 spyderlib/images/editor/prev_wng.png               |  Bin 870 -> 930 bytes
 spyderlib/images/editor/private1.png               |  Bin 371 -> 431 bytes
 spyderlib/images/editor/private2.png               |  Bin 368 -> 428 bytes
 spyderlib/images/editor/refactor.png               |  Bin 318 -> 396 bytes
 spyderlib/images/editor/run.png                    |  Bin 792 -> 870 bytes
 spyderlib/images/editor/run_again.png              |  Bin 1273 -> 1356 bytes
 spyderlib/images/editor/run_cell.png               |  Bin 896 -> 974 bytes
 spyderlib/images/editor/run_cell_advance.png       |  Bin 879 -> 957 bytes
 spyderlib/images/editor/run_selection.png          |  Bin 941 -> 1019 bytes
 spyderlib/images/editor/run_settings.png           |  Bin 1241 -> 1319 bytes
 spyderlib/images/editor/select.png                 |  Bin 305 -> 365 bytes
 spyderlib/images/editor/selectall.png              |  Bin 1143 -> 1221 bytes
 spyderlib/images/editor/todo.png                   |  Bin 517 -> 577 bytes
 spyderlib/images/editor/todo_list.png              |  Bin 751 -> 829 bytes
 spyderlib/images/editor/uncomment.png              |  Bin 759 -> 840 bytes
 spyderlib/images/editor/unindent.png               |  Bin 366 -> 444 bytes
 spyderlib/images/editor/versplit.png               |  Bin 988 -> 1045 bytes
 spyderlib/images/editor/warning.png                |  Bin 436 -> 496 bytes
 spyderlib/images/editor/wng_list.png               |  Bin 738 -> 816 bytes
 spyderlib/images/eyedropper.png                    |  Bin 0 -> 1363 bytes
 spyderlib/images/file/fileclose.png                |  Bin 1123 -> 1204 bytes
 spyderlib/images/file/filecloseall.png             |  Bin 297 -> 357 bytes
 spyderlib/images/file/fileimport.png               |  Bin 2055 -> 2117 bytes
 spyderlib/images/file/filenew.png                  |  Bin 301 -> 330 bytes
 spyderlib/images/file/fileopen.png                 |  Bin 1219 -> 1276 bytes
 spyderlib/images/file/filesave.png                 |  Bin 967 -> 1029 bytes
 spyderlib/images/file/filesaveas.png               |  Bin 1264 -> 1326 bytes
 spyderlib/images/file/print.png                    |  Bin 1108 -> 1165 bytes
 spyderlib/images/file/save_all.png                 |  Bin 1423 -> 1485 bytes
 spyderlib/images/filetypes/bat.png                 |  Bin 515 -> 593 bytes
 spyderlib/images/filetypes/bmp.png                 |  Bin 432 -> 510 bytes
 spyderlib/images/filetypes/c.png                   |  Bin 301 -> 361 bytes
 spyderlib/images/filetypes/cc.png                  |  Bin 293 -> 356 bytes
 spyderlib/images/filetypes/cfg.png                 |  Bin 402 -> 480 bytes
 spyderlib/images/filetypes/chm.png                 |  Bin 620 -> 698 bytes
 spyderlib/images/filetypes/cl.png                  |  Bin 284 -> 353 bytes
 spyderlib/images/filetypes/cmd.png                 |  Bin 515 -> 593 bytes
 spyderlib/images/filetypes/cpp.png                 |  Bin 293 -> 356 bytes
 spyderlib/images/filetypes/css.png                 |  Bin 325 -> 392 bytes
 spyderlib/images/filetypes/cxx.png                 |  Bin 293 -> 356 bytes
 spyderlib/images/filetypes/diff.png                |  Bin 169 -> 229 bytes
 spyderlib/images/filetypes/doc.png                 |  Bin 574 -> 652 bytes
 spyderlib/images/filetypes/enaml.png               |  Bin 882 -> 963 bytes
 spyderlib/images/filetypes/exe.png                 |  Bin 604 -> 682 bytes
 spyderlib/images/filetypes/f.png                   |  Bin 278 -> 349 bytes
 spyderlib/images/filetypes/f77.png                 |  Bin 278 -> 349 bytes
 spyderlib/images/filetypes/f90.png                 |  Bin 278 -> 349 bytes
 spyderlib/images/filetypes/gif.png                 |  Bin 432 -> 510 bytes
 spyderlib/images/filetypes/h.png                   |  Bin 286 -> 348 bytes
 spyderlib/images/filetypes/hh.png                  |  Bin 293 -> 356 bytes
 spyderlib/images/filetypes/hpp.png                 |  Bin 293 -> 356 bytes
 spyderlib/images/filetypes/htm.png                 |  Bin 480 -> 537 bytes
 spyderlib/images/filetypes/html.png                |  Bin 587 -> 665 bytes
 spyderlib/images/filetypes/hxx.png                 |  Bin 293 -> 356 bytes
 spyderlib/images/filetypes/inf.png                 |  Bin 402 -> 480 bytes
 spyderlib/images/filetypes/ini.png                 |  Bin 402 -> 480 bytes
 spyderlib/images/filetypes/jl.png                  |  Bin 617 -> 698 bytes
 spyderlib/images/filetypes/jpeg.png                |  Bin 432 -> 510 bytes
 spyderlib/images/filetypes/jpg.png                 |  Bin 432 -> 510 bytes
 spyderlib/images/filetypes/js.png                  |  Bin 480 -> 537 bytes
 spyderlib/images/filetypes/log.png                 |  Bin 567 -> 645 bytes
 spyderlib/images/filetypes/nsh.png                 |  Bin 962 -> 1019 bytes
 spyderlib/images/filetypes/nsi.png                 |  Bin 962 -> 1019 bytes
 spyderlib/images/filetypes/nt.png                  |  Bin 515 -> 593 bytes
 spyderlib/images/filetypes/patch.png               |  Bin 169 -> 229 bytes
 spyderlib/images/filetypes/pdf.png                 |  Bin 733 -> 811 bytes
 spyderlib/images/filetypes/png.png                 |  Bin 432 -> 510 bytes
 spyderlib/images/filetypes/po.png                  |  Bin 939 -> 996 bytes
 spyderlib/images/filetypes/pot.png                 |  Bin 895 -> 952 bytes
 spyderlib/images/filetypes/pps.png                 |  Bin 467 -> 545 bytes
 spyderlib/images/filetypes/properties.png          |  Bin 402 -> 480 bytes
 spyderlib/images/filetypes/ps.png                  |  Bin 460 -> 538 bytes
 spyderlib/images/filetypes/pxd.png                 |  Bin 862 -> 922 bytes
 spyderlib/images/filetypes/pxi.png                 |  Bin 862 -> 922 bytes
 spyderlib/images/filetypes/py.png                  |  Bin 769 -> 826 bytes
 spyderlib/images/filetypes/pyc.png                 |  Bin 847 -> 904 bytes
 spyderlib/images/filetypes/pyw.png                 |  Bin 769 -> 826 bytes
 spyderlib/images/filetypes/pyx.png                 |  Bin 862 -> 922 bytes
 spyderlib/images/filetypes/rar.png                 |  Bin 553 -> 631 bytes
 spyderlib/images/filetypes/readme.png              |  Bin 577 -> 655 bytes
 spyderlib/images/filetypes/reg.png                 |  Bin 402 -> 480 bytes
 spyderlib/images/filetypes/rej.png                 |  Bin 169 -> 229 bytes
 spyderlib/images/filetypes/scss.png                |  Bin 0 -> 392 bytes
 spyderlib/images/filetypes/session.png             |  Bin 402 -> 480 bytes
 spyderlib/images/filetypes/tar.png                 |  Bin 553 -> 631 bytes
 spyderlib/images/filetypes/tex.png                 |  Bin 427 -> 505 bytes
 spyderlib/images/filetypes/tgz.png                 |  Bin 553 -> 631 bytes
 spyderlib/images/filetypes/tif.png                 |  Bin 432 -> 510 bytes
 spyderlib/images/filetypes/tiff.png                |  Bin 432 -> 510 bytes
 spyderlib/images/filetypes/ts.png                  |  Bin 837 -> 897 bytes
 spyderlib/images/filetypes/txt.png                 |  Bin 544 -> 622 bytes
 spyderlib/images/filetypes/ui.png                  |  Bin 933 -> 993 bytes
 spyderlib/images/filetypes/xls.png                 |  Bin 460 -> 538 bytes
 spyderlib/images/filetypes/xml.png                 |  Bin 533 -> 611 bytes
 spyderlib/images/filetypes/zip.png                 |  Bin 553 -> 631 bytes
 spyderlib/images/font.png                          |  Bin 741 -> 819 bytes
 spyderlib/images/genprefs.png                      |  Bin 1301 -> 1363 bytes
 spyderlib/images/inspector.png                     |  Bin 1169 -> 1231 bytes
 spyderlib/images/italic.png                        |  Bin 128 -> 186 bytes
 spyderlib/images/keyboard.png                      |  Bin 0 -> 1363 bytes
 spyderlib/images/matplotlib.png                    |  Bin 703 -> 763 bytes
 spyderlib/images/none.png                          |  Bin 82 -> 161 bytes
 spyderlib/images/not_found.png                     |  Bin 281 -> 362 bytes
 spyderlib/images/projects/add_to_path.png          |  Bin 750 -> 828 bytes
 spyderlib/images/projects/folder.png               |  Bin 711 -> 768 bytes
 spyderlib/images/projects/package.png              |  Bin 759 -> 816 bytes
 spyderlib/images/projects/pp_folder.png            |  Bin 701 -> 758 bytes
 spyderlib/images/projects/pp_package.png           |  Bin 745 -> 802 bytes
 spyderlib/images/projects/pp_project.png           |  Bin 700 -> 757 bytes
 spyderlib/images/projects/project.png              |  Bin 680 -> 737 bytes
 spyderlib/images/projects/project_closed.png       |  Bin 362 -> 414 bytes
 spyderlib/images/projects/pydev.png                |  Bin 851 -> 911 bytes
 spyderlib/images/projects/pythonpath.png           |  Bin 786 -> 864 bytes
 spyderlib/images/projects/remove_from_path.png     |  Bin 719 -> 776 bytes
 spyderlib/images/projects/show_all.png             |  Bin 327 -> 376 bytes
 .../images/{pythonpath_mgr.png => pythonpath.png}  |  Bin 1265 -> 1327 bytes
 spyderlib/images/pythonxy.png                      |  Bin 1353 -> 1415 bytes
 spyderlib/images/qt.png                            |  Bin 1743 -> 1805 bytes
 spyderlib/images/qtassistant.png                   |  Bin 1880 -> 1942 bytes
 spyderlib/images/qtdesigner.png                    |  Bin 1712 -> 1774 bytes
 spyderlib/images/qtlinguist.png                    |  Bin 1769 -> 1831 bytes
 spyderlib/images/scipy.png                         |  Bin 874 -> 955 bytes
 spyderlib/images/set_workdir.png                   |  Bin 706 -> 784 bytes
 spyderlib/images/splash.png                        |  Bin 166018 -> 166120 bytes
 spyderlib/images/spyder.png                        |  Bin 0 -> 4431 bytes
 spyderlib/images/tour-spyder-logo.png              |  Bin 0 -> 8259 bytes
 spyderlib/images/upper_lower.png                   |  Bin 258 -> 339 bytes
 spyderlib/images/vcs_browse.png                    |  Bin 623 -> 680 bytes
 spyderlib/images/vcs_commit.png                    |  Bin 549 -> 606 bytes
 spyderlib/images/vitables.png                      |  Bin 1350 -> 1412 bytes
 spyderlib/images/whole_words.png                   |  Bin 138 -> 219 bytes
 spyderlib/images/win_env.png                       |  Bin 1018 -> 1078 bytes
 spyderlib/locale/es/LC_MESSAGES/spyderlib.mo       |  Bin 97535 -> 97535 bytes
 spyderlib/locale/es/LC_MESSAGES/spyderlib.po       | 2974 ++++++-----
 spyderlib/locale/fr/LC_MESSAGES/spyderlib.mo       |  Bin 99259 -> 97704 bytes
 spyderlib/locale/fr/LC_MESSAGES/spyderlib.po       | 2973 ++++++-----
 spyderlib/locale/pt_BR/LC_MESSAGES/spyderlib.mo    |  Bin 0 -> 91400 bytes
 spyderlib/locale/pt_BR/LC_MESSAGES/spyderlib.po    | 5520 ++++++++++++++++++++
 spyderlib/locale/spyderlib.pot                     | 2659 +++++-----
 spyderlib/otherplugins.py                          |  186 +-
 spyderlib/plugins/__init__.py                      |  276 +-
 spyderlib/plugins/configdialog.py                  |  380 +-
 spyderlib/plugins/console.py                       |  107 +-
 spyderlib/plugins/editor.py                        |  601 ++-
 spyderlib/plugins/explorer.py                      |   40 +-
 spyderlib/plugins/externalconsole.py               |  342 +-
 spyderlib/plugins/findinfiles.py                   |   32 +-
 spyderlib/plugins/history.py                       |   70 +-
 spyderlib/plugins/inspector.py                     |  313 +-
 spyderlib/plugins/ipythonconsole.py                |  196 +-
 spyderlib/plugins/layoutdialog.py                  |  341 ++
 spyderlib/plugins/onlinehelp.py                    |    3 +-
 spyderlib/plugins/outlineexplorer.py               |   19 +-
 spyderlib/plugins/projectexplorer.py               |   50 +-
 spyderlib/plugins/runconfig.py                     |  107 +-
 spyderlib/plugins/shortcuts.py                     |  907 +++-
 spyderlib/plugins/variableexplorer.py              |   69 +-
 spyderlib/plugins/workingdirectory.py              |   94 +-
 spyderlib/py3compat.py                             |   45 +-
 spyderlib/pygments_patch.py                        |   81 -
 spyderlib/pyplot.py                                |    2 +-
 spyderlib/qt/QtCore.py                             |   31 +-
 spyderlib/qt/QtGui.py                              |   19 +-
 spyderlib/qt/QtNetwork.py                          |   14 +
 spyderlib/qt/QtSvg.py                              |    8 +-
 spyderlib/qt/QtWebKit.py                           |   10 +-
 spyderlib/qt/__init__.py                           |   43 +-
 spyderlib/requirements.py                          |   13 +-
 spyderlib/restart_app.py                           |  274 +
 spyderlib/rope_patch.py                            |   13 +-
 spyderlib/scientific_startup.py                    |    2 +-
 spyderlib/spyder.py                                | 1648 ++++--
 spyderlib/start_app.py                             |   16 +-
 spyderlib/tour.py                                  | 1286 +++++
 spyderlib/utils/bsdsocket.py                       |   69 +-
 spyderlib/utils/codeanalysis.py                    |    8 +-
 spyderlib/utils/debug.py                           |    2 +-
 spyderlib/utils/environ.py                         |   28 +-
 spyderlib/utils/external/__init__.py               |    2 +-
 spyderlib/utils/external/path.py                   | 1047 ----
 spyderlib/utils/external/pickleshare.py            |  370 --
 spyderlib/utils/icon_manager.py                    |  264 +
 spyderlib/utils/inspector/__init__.py              |    2 +-
 spyderlib/utils/inspector/conf.py                  |    2 +-
 spyderlib/utils/inspector/sphinxify.py             |    7 +-
 .../inspector/static/images/collapse_expand.png    |  Bin 274 -> 353 bytes
 .../inspector/static/images/debug-continue.png     |  Bin 1266 -> 1368 bytes
 .../inspector/static/images/debug-step-in.png      |  Bin 644 -> 722 bytes
 .../inspector/static/images/debug-step-out.png     |  Bin 410 -> 488 bytes
 .../inspector/static/images/debug-step-over.png    |  Bin 710 -> 767 bytes
 .../static/images/spyder-hello-docstring.png       |  Bin 5311 -> 5413 bytes
 .../images/spyder-nice-docstring-rendering.png     |  Bin 31481 -> 31643 bytes
 .../static/images/spyder-sympy-example.png         |  Bin 8030 -> 8113 bytes
 spyderlib/utils/inspector/tutorial.rst             |   26 +-
 spyderlib/utils/introspection/__init__.py          |    1 +
 spyderlib/utils/introspection/fallback_plugin.py   |   51 +-
 spyderlib/utils/introspection/jedi_plugin.py       |   15 +-
 spyderlib/utils/introspection/module_completion.py |   19 +-
 spyderlib/utils/introspection/plugin_manager.py    |   96 +-
 spyderlib/utils/introspection/rope_plugin.py       |   43 +-
 spyderlib/utils/iofuncs.py                         |    9 +-
 spyderlib/utils/misc.py                            |   26 +-
 spyderlib/utils/programs.py                        |   51 +-
 spyderlib/utils/qthelpers.py                       |   97 +-
 spyderlib/utils/sourcecode.py                      |   13 +-
 spyderlib/utils/stringmatching.py                  |  280 +
 .../sourcecode => utils}/syntaxhighlighters.py     |  168 +-
 spyderlib/utils/vcs.py                             |   31 +-
 spyderlib/widgets/__init__.py                      |    2 +-
 spyderlib/widgets/arraybuilder.py                  |  373 ++
 spyderlib/widgets/browser.py                       |  111 +-
 spyderlib/widgets/colors.py                        |   18 +-
 spyderlib/widgets/comboboxes.py                    |  230 +-
 spyderlib/widgets/dependencies.py                  |   39 +-
 spyderlib/widgets/editor.py                        | 4753 ++++++++---------
 spyderlib/widgets/editortools.py                   |   65 +-
 spyderlib/widgets/explorer.py                      | 2262 ++++----
 spyderlib/widgets/externalshell/baseshell.py       |  116 +-
 spyderlib/widgets/externalshell/inputhooks.py      |   20 +-
 spyderlib/widgets/externalshell/introspection.py   |   19 +-
 spyderlib/widgets/externalshell/monitor.py         |   15 +-
 spyderlib/widgets/externalshell/pythonshell.py     |  239 +-
 spyderlib/widgets/externalshell/sitecustomize.py   |  415 +-
 .../widgets/externalshell/start_ipython_kernel.py  |   22 +-
 spyderlib/widgets/externalshell/systemshell.py     |   74 +-
 spyderlib/widgets/fileswitcher.py                  |  584 +++
 spyderlib/widgets/findinfiles.py                   |  115 +-
 spyderlib/widgets/findreplace.py                   |   89 +-
 spyderlib/widgets/formlayout.py                    |   58 +-
 spyderlib/widgets/helperwidgets.py                 |  253 +
 spyderlib/widgets/internalshell.py                 |   71 +-
 spyderlib/widgets/ipython.py                       |  119 +-
 spyderlib/widgets/mixins.py                        |   63 +-
 spyderlib/widgets/onecolumntree.py                 |   44 +-
 spyderlib/widgets/pathmanager.py                   |   55 +-
 spyderlib/widgets/projectexplorer.py               |  135 +-
 spyderlib/widgets/pydocgui.py                      |   23 +-
 spyderlib/widgets/shell.py                         |   74 +-
 spyderlib/widgets/sourcecode/base.py               |  149 +-
 spyderlib/widgets/sourcecode/codeeditor.py         |  657 ++-
 spyderlib/widgets/sourcecode/kill_ring.py          |  132 +
 spyderlib/widgets/status.py                        |   15 +-
 spyderlib/widgets/tabs.py                          |   74 +-
 spyderlib/widgets/variableexplorer/__init__.py     |   12 +
 .../widgets/{ => variableexplorer}/arrayeditor.py  |  259 +-
 .../collectionseditor.py}                          |  409 +-
 .../{ => variableexplorer}/dataframeeditor.py      |   93 +-
 .../widgets/{ => variableexplorer}/importwizard.py |   76 +-
 .../namespacebrowser.py                            |  129 +-
 .../widgets/{ => variableexplorer}/objecteditor.py |   38 +-
 .../widgets/{ => variableexplorer}/texteditor.py   |   50 +-
 .../utils.py}                                      |  195 +-
 {spyderplugins => spyderlib/workers}/__init__.py   |    0
 spyderlib/workers/updates.py                       |   96 +
 spyderplugins/images/pylint.png                    |  Bin 1134 -> 0 bytes
 spyderplugins/io_dicom.py                          |   23 -
 .../locale/fr/LC_MESSAGES/p_breakpoints.mo         |  Bin 762 -> 0 bytes
 spyderplugins/locale/fr/LC_MESSAGES/p_profiler.mo  |  Bin 2342 -> 0 bytes
 spyderplugins/locale/fr/LC_MESSAGES/p_pylint.mo    |  Bin 2594 -> 0 bytes
 spyderplugins/widgets/__init__.py                  |   15 -
 spyplugins/__init__.py                             |   12 +
 spyplugins/io/__init__.py                          |   12 +
 spyplugins/io/dcm/__init__.py                      |    9 +
 spyplugins/io/dcm/dcm.py                           |   26 +
 spyplugins/io/hdf5/__init__.py                     |    9 +
 .../io_hdf5.py => spyplugins/io/hdf5/hdf5.py       |    7 -
 spyplugins/ui/__init__.py                          |   12 +
 spyplugins/ui/breakpoints/__init__.py              |    6 +
 .../ui/breakpoints/breakpoints.py                  |   45 +-
 .../locale/es/LC_MESSAGES/breakpoints.mo           |  Bin
 .../locale/fr/LC_MESSAGES/breakpoints.mo           |  Bin 0 -> 835 bytes
 .../locale/pt_BR/LC_MESSAGES/breakpoints.mo        |  Bin 0 -> 863 bytes
 .../ui/breakpoints/widgets}/__init__.py            |    0
 .../ui/breakpoints}/widgets/breakpointsgui.py      |   74 +-
 spyplugins/ui/profiler/__init__.py                 |    6 +
 .../ui/profiler}/images/profiler.png               |  Bin 1392 -> 1454 bytes
 .../ui/profiler/locale/es/LC_MESSAGES/profiler.mo  |  Bin
 .../ui/profiler/locale/fr/LC_MESSAGES/profiler.mo  |  Bin 0 -> 2736 bytes
 .../profiler/locale/pt_BR/LC_MESSAGES/profiler.mo  |  Bin 0 -> 2317 bytes
 .../ui/profiler/profiler.py                        |   55 +-
 .../ui/profiler/widgets}/__init__.py               |    0
 .../ui/profiler}/widgets/profilergui.py            |  312 +-
 spyplugins/ui/pylint/__init__.py                   |    6 +
 spyplugins/ui/pylint/images/pylint.png             |  Bin 0 -> 1196 bytes
 .../ui/pylint/locale/es/LC_MESSAGES/pylint.mo      |  Bin
 .../ui/pylint/locale/fr/LC_MESSAGES/pylint.mo      |  Bin 0 -> 2427 bytes
 .../ui/pylint/locale/pt_BR/LC_MESSAGES/pylint.mo   |  Bin 0 -> 2607 bytes
 .../p_pylint.py => spyplugins/ui/pylint/pylint.py  |   43 +-
 .../ui/pylint/widgets}/__init__.py                 |    0
 .../ui/pylint}/widgets/pylintgui.py                |   77 +-
 468 files changed, 25814 insertions(+), 13777 deletions(-)

diff --git a/LICENSE b/LICENSE
index 5474e76..5a4140c 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,7 +1,7 @@
 Spyder License Agreement (MIT License)
 --------------------------------------
 
-Copyright (c) 2009-2013 Pierre Raybaut
+Copyright (c) 2009- The Spyder Development Team
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
@@ -50,9 +50,12 @@ spyderlib/images/whole_words.png
 spyderlib/images/win_env.png
 spyderlib/images/actions/hist.png
 spyderlib/images/actions/window_nofullscreen.png
+spyderlib/images/editor/attribute.png
 spyderlib/images/editor/filelist.png
 spyderlib/images/editor/function.png
 spyderlib/images/editor/method.png
+spyderlib/images/editor/module.png
+spyderlib/images/editor/no_match.png
 spyderlib/images/editor/private1.png
 spyderlib/images/editor/private2.png
 spyderlib/images/editor/cell.png
diff --git a/MANIFEST.in b/MANIFEST.in
index c2db4f8..cf6ba11 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -2,6 +2,8 @@ recursive-include spyderlib *.pot *.po *.svg *.png *.css *.qss
 recursive-include spyderlibplugins *.pot *.po *.svg *.png
 recursive-include doc *.py *.rst *.png *.ico *.
 recursive-include app_example *.py *.pyw *.bat *.qm *.svg *.png
+include spyderlib/fonts/spyder.ttf
+include spyderlib/fonts/spyder-charmap.json
 include scripts/*
 include img_src/*.ico
 include img_src/spyder.png
diff --git a/PKG-INFO b/PKG-INFO
index daf0484..9a7604a 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,17 +1,17 @@
 Metadata-Version: 1.1
 Name: spyder
-Version: 2.3.8
+Version: 3.0.0b2
 Summary: Scientific PYthon Development EnviRonment
 Home-page: https://github.com/spyder-ide/spyder
 Author: Pierre Raybaut
 Author-email: UNKNOWN
 License: MIT
-Download-URL: https://github.com/spyder-ide/spyder/files/spyder-2.3.8.zip
-Description: Spyder is an interactive Python development environment providing 
+Download-URL: https://github.com/spyder-ide/spyder/files/spyder-3.0.0b2.zip
+Description: Spyder is an interactive Python development environment providing
         MATLAB-like features in a simple and light-weighted software.
-        It also provides ready-to-use pure-Python widgets to your PyQt4 or 
-        PySide application: source code editor with syntax highlighting and 
-        code introspection/analysis features, NumPy array editor, dictionary 
+        It also provides ready-to-use pure-Python widgets to your PyQt4 or
+        PySide application: source code editor with syntax highlighting and
+        code introspection/analysis features, NumPy array editor, dictionary
         editor, Python console, etc.
 Keywords: PyQt4 PySide editor shell console widgets IDE
 Platform: any
@@ -23,9 +23,6 @@ Classifier: Operating System :: POSIX
 Classifier: Operating System :: Unix
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
-Classifier: Development Status :: 5 - Production/Stable
+Classifier: Programming Language :: Python :: 3.3Development Status :: 5 - Production/Stable
 Classifier: Topic :: Scientific/Engineering
 Classifier: Topic :: Software Development :: Widget Sets
-Requires: rope (>=0.9.2)
-Requires: sphinx (>=0.6.0)
-Requires: PyQt4 (>=4.4)
diff --git a/README.md b/README.md
index 1de0ce0..8dbb71f 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,12 @@
 # Spyder - The Scientific PYthon Development EnviRonment
 
-Copyright © 2009-2013 Pierre Raybaut.
-Licensed under the terms of the MIT License
-(see `spyderlib/__init__.py` for details)
+Copyright © 2009- The Spyder Development Team.
 
+[![license](https://img.shields.io/pypi/l/spyder.svg)](./LICENSE)
+[![pypi version](https://img.shields.io/pypi/v/spyder.svg)](https://pypi.python.org/pypi/spyder)
+[![pypi downloads](https://img.shields.io/pypi/dm/spyder.svg)](https://pypi.python.org/pypi/spyder)
+[![Travis status](https://travis-ci.org/spyder-ide/spyder.svg?branch=master)](https://travis-ci.org/spyder-ide/spyder)
+[![AppVeyor status](https://ci.appveyor.com/api/projects/status/awb92if4tl555fuy/branch/master?svg=true)](https://ci.appveyor.com/project/ccordoba12/spyder/branch/master)
 
 ## Overview
 
@@ -11,36 +14,36 @@ Licensed under the terms of the MIT License
 
 Spyder is a Python development environment with a lot of features:
 
-* Editor
+* **Editor**
 
     Multi-language editor with function/class browser, code analysis
     features (pyflakes and pylint are currently supported), code
     completion, horizontal and vertical splitting, and goto definition.
 
-* Interactive console
+* **Interactive console**
 
     Python or IPython consoles with workspace and debugging support to
     instantly evaluate the code written in the Editor. It also comes
     with Matplotlib figures integration. 
 
-* Documentation viewer
+* **Documentation viewer**
 
     Show documentation for any class or function call made either in the
     Editor or a Console.
 
-* Variable explorer
+* **Variable explorer**
 
     Explore variables created during the execution of a file. Editing
     them is also possible with several GUI based editors, like a
     dictionary and Numpy array ones.
 
-* Find in files feature
+* **Find in files**
 
     Supporting regular expressions and mercurial repositories
 
-* File/directories explorer
+* **File explorer**
 
-* History log
+* **History log**
 
 Spyder may also be used as a PyQt4/PySide extension library (module 
 `spyderlib`). For example, the Python interactive shell widget used in
@@ -61,122 +64,110 @@ Spyder. If you prefer testing the development version, please use
 the `bootstrap` script (see next section).
 
 The easiest way to install Spyder is:
-            
-* On Windows:
-
-    - Using one of our executable installers, which can be found
-      [here](https://github.com/spyder-ide/spyder/releases).
-    - Or using one of these scientific Python distributions:
-        1. [Python(x,y)](http://pythonxy.googlecode.com)
-        2. [WinPython](https://winpython.github.io/)
-        3. [Anaconda](http://continuum.io/downloads)
-
-* On Mac OSX:
-
-    - Using our DMG installer, which can be found
-      [here](https://github.com/spyder-ide/spyder/releases).
-    - Using the [Anaconda Distribution](http://continuum.io/downloads).
-    - Through [MacPorts](http://www.macports.org/).
-            
-* On GNU/Linux
-
-    - Through your distribution package manager (i.e. `apt-get`, `yum`,
-    etc).
-    - Using the [Anaconda Distribution](http://continuum.io/downloads).
-    - Installing from source (see below).
-
-### Installing from source
-
-You can also install Spyder from its zip source package. For that you need to
-download and uncompress the file called `spyder-x.y.z.zip`, which can be
-found [here](https://github.com/spyder-ide/spyder/releases). Then you need to
-use the integrated `setup.py` script that comes with it and which is based
-on the Python standard library `distutils` module, with the following command:
-
-    python setup.py install
-
-Note that `distutils` does *not* uninstall previous versions of Python 
-packages: it simply copies files on top of an existing installation. 
-When using this command, it is thus highly recommended to uninstall 
-manually any previous version of Spyder by removing the associated 
-directories ('spyderlib' and 'spyderplugins') from your site-packages 
-directory).
-
-From the [Python package index](http://pypi.python.org/pypi), you also
-may install Spyder *and* upgrade an existing installation using `pip`
-with this command
 
-    pip install --upgrade spyder
+### On Windows:
 
-For more details on supported platforms, please go to
-<http://pythonhosted.org/spyder/installation.html>.
+- Or using one of these scientific Python distributions:
+  1. [Anaconda](http://continuum.io/downloads)
+  2. [WinPython](https://winpython.github.io/)
+  3. [Python(x,y)](http://pythonxy.googlecode.com)
+- Using one of our executable installers, which can be found
+  [here](https://github.com/spyder-ide/spyder/releases).
 
+### On Mac OSX:
 
-## Dependencies
+- Using our DMG installer, which can be found
+  [here](https://github.com/spyder-ide/spyder/releases).
+- Using the [Anaconda Distribution](http://continuum.io/downloads).
+- Through [MacPorts](http://www.macports.org/).
 
-*Imnportant note*: Most if not all the dependencies listed below come
-with Python(x,y), WinPython and Anaconda, so you don't need to install
-them separately when installing one of these scientific Python
-distributions.
+### On GNU/Linux
 
-### Build dependencies
+- Through your distribution package manager (i.e. `apt-get`, `yum`,
+  etc).
+- Using the [Anaconda Distribution](http://continuum.io/downloads).
+- Installing from source (see below).
 
-When installing Spyder from its source package (using the command
-`python setup.py install`), the only requirements is to have a Python version
-greater than 2.6.
+### Cross-platform way from source
 
-### Runtime dependencies
+You can also install Spyder with the `pip` package manager, which comes by
+default with most Python installations. For that you need to use the
+command:
 
-* Python 2.6+
+    pip install spyder
 
-* PyQt4 4.6+ or PySide 1.2.0+ (PyQt4 is recommended)
-            
-### Recommended modules
+To upgrade Spyder to its latest version, if it was installed before, you need
+to run
 
-* Rope v0.9.2+ (editor code completion, calltips and go-to-definition)
+    pip install --upgrade spyder
+
+For more details on supported platforms, please refer to our
+[installation instructions](http://pythonhosted.org/spyder/installation.html).
 
-* Pyflakes v0.5.0+ (real-time code analysis)
+**Important note**: This does not install the graphical Python libraries (i.e.
+PyQt4, PyQt5 or PySide) that Spyder depend on. Those have to be installed
+separately after installing Python.
 
-* Sphinx v0.6+ (object inspector's rich text mode)
 
-* Numpy (N-dimensional arrays)
+## Running from source
 
-* Scipy (signal/image processing)
+The fastest way to run Spyder is to get the source code using git, install
+PyQt4, PyQt5 or PySide, and run these commands:
 
-* Matplotlib (2D/3D plotting)
+1. `pip install qtawesome` or `conda install -c spyder-ide qtawesome`
+2. `cd /your/spyder/git-clone`
+3. `python bootstrap.py`
 
-* IPython 3.0- or qtconsole 4.0+ (enhanced Python interpreter)
+You may want to do this for fixing bugs in Spyder, adding new
+features, learning how Spyder works or just getting a taste of it.
 
-    In Ubuntu you need to install `ipython-qtconsole`, on Fedora
-    `ipython-gui` and on Gentoo `ipython` with the `qt4` USE flag.
 
-### Optional modules
+## Dependencies
 
-* Pygments (syntax highlighting for several file types).
+**Important note**: Most if not all the dependencies listed below come
+with *Anaconda*, *WinPython* and *Python(x,y)*, so you don't need to install
+them separately when installing one of these Scientific Python
+distributions.
 
-* Pylint (static code analysis).
+### Build dependencies
 
-* Pep8 (style analysis).
+When installing Spyder from its source package, the only requirement is to have
+a Python version greater than 2.7 (Python 3.2 is not supported anymore).
 
-## Running from source
+### Runtime dependencies
 
-It is possible to run Spyder directly (i.e. without installation)
-from the unpacked zip folder (see *Installing from source*) using
-Spyder's bootstrap script like this:
+* **Python** 2.7 or 3.3+
+* **PyQt4** 4.6+, **PyQt5** 5.2+ or **PySide** 1.2.0+: PyQt4 is recommended.
+* **IPython** 3.0 or **qtconsole**: Enhanced Python interpreter.
+* **Rope** and/or **Jedi** 0.8.1: Editor code completion, calltips
+  and go-to-definition.
+* **Pyflakes**: Real-time code analysis)
+* **Sphinx**: Object Inspector's rich text mode.
+* **Pygments**: Syntax highlighting for all file types it supports.
+* **Pylint**: Static code analysis.
+* **Pep8**: Style analysis.
+* **Psutil**: CPU and memory usage on the status bar.
+* **Nbconvert**: Manipulation of notebooks in the Editor.
+
+**Note**: To get IPython in Ubuntu you need to install `ipython-qtconsole`,
+on Fedora `ipython-gui` and on Gentoo `ipython` with the `qt4` USE flag.
 
-    python bootstrap.py
+### Optional modules
+
+* **Matplotlib**: 2D/3D plotting.
+* **Pandas**: DataFrame and Series support.
+* **Numpy**: N-dimensional arrays.
+* **SymPy**: Symbolic mathematics.
 
-This is especially useful for beta-testing, troubleshooting 
-and development of Spyder itself.
 
 ## More information
 
-* For code development please go to
+* For code development please go to:
 
     <https://github.com/spyder-ide/spyder>
-    
-* For bug reports and feature requests
-           
+
+* For bug reports and feature requests:
+
     <https://github.com/spyder-ide/spyder/issues>
 
 * For discussions and troubleshooting:
diff --git a/bootstrap.py b/bootstrap.py
index 66db923..9cb64a8 100755
--- a/bootstrap.py
+++ b/bootstrap.py
@@ -32,7 +32,8 @@ symbol (example: `python bootstrap.py -- --show-console`).
 Type `python bootstrap.py -- --help` to read about Spyder
 options.""")
 parser.add_option('--gui', default=None,
-                  help="GUI toolkit: pyqt (for PyQt4) or pyside (for PySide)")
+                  help="GUI toolkit: pyqt5 (for PyQt5), pyqt (for PyQt4) or "
+                       "pyside (for PySide)")
 parser.add_option('--hide-console', action='store_true',
                   default=False, help="Hide parent console window (Windows only)")
 parser.add_option('--test', dest="test", action='store_true', default=False,
@@ -41,9 +42,13 @@ parser.add_option('--no-apport', action='store_true',
                   default=False, help="Disable Apport exception hook (Ubuntu)")
 parser.add_option('--debug', action='store_true',
                   default=False, help="Run Spyder in debug mode")
+
 options, args = parser.parse_args()
 
-assert options.gui in (None, 'pyqt', 'pyside'), \
+# Store variable to be used in self.restart (restart spyder instance)
+os.environ['SPYDER_BOOTSTRAP_ARGS'] = str(sys.argv[1:])
+
+assert options.gui in (None, 'pyqt5', 'pyqt', 'pyside'), \
        "Invalid GUI toolkit option '%s'" % options.gui
 
 # For testing purposes
@@ -92,27 +97,27 @@ if sys.excepthook != sys.__excepthook__:
 
 # --- Continue
 
-from spyderlib.utils.vcs import get_hg_revision
-print("Revision %s:%s, Branch: %s" % get_hg_revision(DEVPATH))
+from spyderlib.utils.vcs import get_git_revision
+print("Revision %s, Branch: %s" % get_git_revision(DEVPATH))
 
 sys.path.insert(0, DEVPATH)
 print("01. Patched sys.path with %s" % DEVPATH)
 
-EXTPATH = osp.join(DEVPATH, 'external-py' + sys.version[0])
-if osp.isdir(EXTPATH):
-    sys.path.insert(0, EXTPATH)
-    print("                      and %s" % EXTPATH)
-
 
-# Selecting the GUI toolkit: PySide if installed, otherwise PyQt4
+# Selecting the GUI toolkit: PyQt5 if installed, otherwise PySide or PyQt4
 # (Note: PyQt4 is still the officially supported GUI toolkit for Spyder)
 if options.gui is None:
     try:
-        import PySide  # analysis:ignore
-        print("02. PySide is detected, selecting (experimental)")
-        os.environ['QT_API'] = 'pyside'
-    except:
-        print("02. No PySide detected, using PyQt4 if available")
+        import PyQt5  # analysis:ignore
+        print("02. PyQt5 is detected, selecting (experimental)")
+        os.environ['QT_API'] = 'pyqt5'
+    except ImportError:
+        try:
+            import PySide  # analysis:ignore
+            print("02. PySide is detected, selecting")
+            os.environ['QT_API'] = 'pyside'
+        except ImportError:
+            print("02. No PyQt5 or PySide detected, using PyQt4 if available")
 else:
     print ("02. Skipping GUI toolkit detection")
     os.environ['QT_API'] = options.gui
@@ -120,7 +125,7 @@ else:
 
 if options.debug:
     # safety check - Spyder config should not be imported at this point
-    if "spyderlib.baseconfig" in sys.modules:
+    if "spyderlib.config.base" in sys.modules:
         sys.exit("ERROR: Can't enable debug mode - Spyder is already imported")
     print("0x. Switching debug mode on")
     os.environ["SPYDER_DEBUG"] = "True"
diff --git a/doc/images/arrayeditor.png b/doc/images/arrayeditor.png
index 3d88aa8..36fd440 100644
Binary files a/doc/images/arrayeditor.png and b/doc/images/arrayeditor.png differ
diff --git a/doc/images/console.png b/doc/images/console.png
index 361a48d..151756c 100644
Binary files a/doc/images/console.png and b/doc/images/console.png differ
diff --git a/doc/images/dicteditor.png b/doc/images/dicteditor.png
index 2193034..83861ce 100644
Binary files a/doc/images/dicteditor.png and b/doc/images/dicteditor.png differ
diff --git a/doc/images/editor1.png b/doc/images/editor1.png
index 930836c..5638e4c 100644
Binary files a/doc/images/editor1.png and b/doc/images/editor1.png differ
diff --git a/doc/images/editor2.png b/doc/images/editor2.png
index 1ac5bc8..07383d9 100644
Binary files a/doc/images/editor2.png and b/doc/images/editor2.png differ
diff --git a/doc/images/editor3.png b/doc/images/editor3.png
index 0e4f28c..36e4a39 100644
Binary files a/doc/images/editor3.png and b/doc/images/editor3.png differ
diff --git a/doc/images/explorer.png b/doc/images/explorer.png
index b81bb05..5171466 100644
Binary files a/doc/images/explorer.png and b/doc/images/explorer.png differ
diff --git a/doc/images/explorer_menu1.png b/doc/images/explorer_menu1.png
index 6ed43c9..cd8e3bc 100644
Binary files a/doc/images/explorer_menu1.png and b/doc/images/explorer_menu1.png differ
diff --git a/doc/images/explorer_menu2.png b/doc/images/explorer_menu2.png
index 2a425e2..68f1c04 100644
Binary files a/doc/images/explorer_menu2.png and b/doc/images/explorer_menu2.png differ
diff --git a/doc/images/findinfiles.png b/doc/images/findinfiles.png
index 8e5b39f..dc94943 100644
Binary files a/doc/images/findinfiles.png and b/doc/images/findinfiles.png differ
diff --git a/doc/images/git_install_dialog.png b/doc/images/git_install_dialog.png
index f9b834b..65e63a3 100644
Binary files a/doc/images/git_install_dialog.png and b/doc/images/git_install_dialog.png differ
diff --git a/doc/images/historylog.png b/doc/images/historylog.png
index 9b30687..3965106 100644
Binary files a/doc/images/historylog.png and b/doc/images/historylog.png differ
diff --git a/doc/images/inspector_plain.png b/doc/images/inspector_plain.png
index b5af47f..a9ca61d 100644
Binary files a/doc/images/inspector_plain.png and b/doc/images/inspector_plain.png differ
diff --git a/doc/images/inspector_rich.png b/doc/images/inspector_rich.png
index 2e36e51..69ab608 100644
Binary files a/doc/images/inspector_rich.png and b/doc/images/inspector_rich.png differ
diff --git a/doc/images/inspector_source.png b/doc/images/inspector_source.png
index 46f97b7..a5b3178 100644
Binary files a/doc/images/inspector_source.png and b/doc/images/inspector_source.png differ
diff --git a/doc/images/internalconsole.png b/doc/images/internalconsole.png
index e0a5de2..cf81ad8 100644
Binary files a/doc/images/internalconsole.png and b/doc/images/internalconsole.png differ
diff --git a/doc/images/ipythonconsole.png b/doc/images/ipythonconsole.png
index 517db97..13ac0f0 100644
Binary files a/doc/images/ipythonconsole.png and b/doc/images/ipythonconsole.png differ
diff --git a/doc/images/ipythonconsolemenu.png b/doc/images/ipythonconsolemenu.png
index 66ead5b..1034ae4 100644
Binary files a/doc/images/ipythonconsolemenu.png and b/doc/images/ipythonconsolemenu.png differ
diff --git a/doc/images/ipythonkernelconnect.png b/doc/images/ipythonkernelconnect.png
index b7a7b8f..48179fb 100644
Binary files a/doc/images/ipythonkernelconnect.png and b/doc/images/ipythonkernelconnect.png differ
diff --git a/doc/images/lightmode.png b/doc/images/lightmode.png
index 0d4806b..1f4bd14 100644
Binary files a/doc/images/lightmode.png and b/doc/images/lightmode.png differ
diff --git a/doc/images/listeditor.png b/doc/images/listeditor.png
index 36c1793..87dd9a4 100644
Binary files a/doc/images/listeditor.png and b/doc/images/listeditor.png differ
diff --git a/doc/images/onlinehelp.png b/doc/images/onlinehelp.png
index 4b1086d..f8455ed 100644
Binary files a/doc/images/onlinehelp.png and b/doc/images/onlinehelp.png differ
diff --git a/doc/images/projectexplorer.png b/doc/images/projectexplorer.png
index 5c9bfd6..1d7d540 100644
Binary files a/doc/images/projectexplorer.png and b/doc/images/projectexplorer.png differ
diff --git a/doc/images/projectexplorer2.png b/doc/images/projectexplorer2.png
index e5f3d3f..69fabde 100644
Binary files a/doc/images/projectexplorer2.png and b/doc/images/projectexplorer2.png differ
diff --git a/doc/images/pylint.png b/doc/images/pylint.png
index bbf41cf..e186afa 100644
Binary files a/doc/images/pylint.png and b/doc/images/pylint.png differ
diff --git a/doc/images/texteditor.png b/doc/images/texteditor.png
index b599114..70cbe30 100644
Binary files a/doc/images/texteditor.png and b/doc/images/texteditor.png differ
diff --git a/doc/images/variableexplorer-imshow.png b/doc/images/variableexplorer-imshow.png
index e615383..a1b91cf 100644
Binary files a/doc/images/variableexplorer-imshow.png and b/doc/images/variableexplorer-imshow.png differ
diff --git a/doc/images/variableexplorer-plot.png b/doc/images/variableexplorer-plot.png
index c0db7ad..6b6d6df 100644
Binary files a/doc/images/variableexplorer-plot.png and b/doc/images/variableexplorer-plot.png differ
diff --git a/doc/images/variableexplorer1.png b/doc/images/variableexplorer1.png
index 4ff5ba1..3415ecc 100644
Binary files a/doc/images/variableexplorer1.png and b/doc/images/variableexplorer1.png differ
diff --git a/doc/images/variableexplorer2.png b/doc/images/variableexplorer2.png
index 3db422f..4e63b77 100644
Binary files a/doc/images/variableexplorer2.png and b/doc/images/variableexplorer2.png differ
diff --git a/doc/options.rst b/doc/options.rst
index b31e11f..9de51b6 100644
--- a/doc/options.rst
+++ b/doc/options.rst
@@ -7,16 +7,17 @@ Spyder's command line options are the following:
 Options:
   -h, --help            show this help message and exit
   -l, --light           Light version (all add-ons are disabled)
+  --new-instance        Run a new instance of Spyder, even if the single
+                        instance mode has been turned on (default)
   --session=STARTUP_SESSION
                         Startup session
-  --defaults            Reset to configuration settings to defaults
+  --defaults            Reset configuration settings to defaults
   --reset               Remove all configuration files!
   --optimize            Optimize Spyder bytecode (this may require
                         administrative privileges)
   -w WORKING_DIRECTORY, --workdir=WORKING_DIRECTORY
                         Default working directory
-  -d, --debug           Debug mode (stds are not redirected)
+  --show-console        Do not hide parent console window (Windows)
   --multithread         Internal console is executed in another thread
                         (separate from main application thread)
-  --profile             Profile mode (internal test, not related with Python
-                        profiling)
\ No newline at end of file
+  --profile             Profile mode (internal test, not related with Python
\ No newline at end of file
diff --git a/doc/spyder_bbg.png b/doc/spyder_bbg.png
index bb961d8..e01a4ee 100644
Binary files a/doc/spyder_bbg.png and b/doc/spyder_bbg.png differ
diff --git a/img_src/spyder.png b/img_src/spyder.png
index 581fdb8..82d9508 100644
Binary files a/img_src/spyder.png and b/img_src/spyder.png differ
diff --git a/img_src/spyder3.png b/img_src/spyder3.png
index 581fdb8..82d9508 100644
Binary files a/img_src/spyder3.png and b/img_src/spyder3.png differ
diff --git a/scripts/spyder_win_post_install.py b/scripts/spyder_win_post_install.py
index 153ebbb..527936b 100644
--- a/scripts/spyder_win_post_install.py
+++ b/scripts/spyder_win_post_install.py
@@ -95,7 +95,7 @@ except NameError:
                   file=sys.stderr)
             sys.exit(1)
         from win32com.shell import shell, shellcon
-        
+
         path_names = ['CSIDL_COMMON_STARTMENU', 'CSIDL_STARTMENU',
                       'CSIDL_COMMON_APPDATA', 'CSIDL_LOCAL_APPDATA',
                       'CSIDL_APPDATA', 'CSIDL_COMMON_DESKTOPDIRECTORY',
@@ -131,6 +131,8 @@ def install():
     python = osp.abspath(osp.join(sys.prefix, 'python.exe'))
     pythonw = osp.abspath(osp.join(sys.prefix, 'pythonw.exe'))
     script = osp.abspath(osp.join(sys.prefix, 'scripts', 'spyder'))
+    if not osp.exists(script): # if not installed to the site scripts dir
+        script = osp.abspath(osp.join(osp.dirname(osp.abspath(__file__)), 'spyder'))
     workdir = "%HOMEDRIVE%%HOMEPATH%"
     import distutils.sysconfig
     lib_dir = distutils.sysconfig.get_python_lib(plat_specific=1)
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 00bb0ae..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-[egg_info]
-tag_date = 0
-tag_svn_revision = 0
-tag_build = 
-
diff --git a/setup.py b/setup.py
index f23b187..1112060 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -22,26 +22,38 @@ import shutil
 
 from distutils.core import setup
 from distutils.command.build import build
+from distutils.command.install import install
 from distutils.command.install_data import install_data
 
+
+#==============================================================================
 # Check for Python 3
+#==============================================================================
 PY3 = sys.version_info[0] == 3
 
-# This is necessary to prevent an error while installing Spyder with pip
-# See http://stackoverflow.com/a/18961843/438386
-with_setuptools = False
-if 'USE_SETUPTOOLS' in os.environ or 'pip' in __file__ or \
-  'VIRTUAL_ENV' in os.environ:
-    try:
-        from setuptools.command.install import install
-        with_setuptools = True
-    except:
-        with_setuptools = False
 
-if not with_setuptools:
-    from distutils.command.install import install  # analysis:ignore
+#==============================================================================
+# Minimal Python version sanity check
+# Taken from the notebook setup.py -- Modified BSD License
+#==============================================================================
+v = sys.version_info
+if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)):
+    error = "ERROR: Spyder requires Python version 2.7 or 3.3 or above."
+    print(error, file=sys.stderr)
+    sys.exit(1)
 
 
+#==============================================================================
+# Constants
+#==============================================================================
+NAME = 'spyder'
+LIBNAME = 'spyderlib'
+from spyderlib import __version__, __project_url__
+
+
+#==============================================================================
+# Auxiliary functions
+#==============================================================================
 def get_package_data(name, extlist):
     """Return data files for package *name* with extensions in *extlist*"""
     flist = []
@@ -80,6 +92,15 @@ def get_data_files():
     return data_files
 
 
+def get_packages():
+    """Return package list"""
+    packages = get_subpackages(LIBNAME) + get_subpackages('spyplugins')
+    return packages
+
+
+#==============================================================================
+# Make Linux detect Spyder desktop file
+#==============================================================================
 class MyInstallData(install_data):
     def run(self):
         install_data.run(self)
@@ -92,7 +113,9 @@ class MyInstallData(install_data):
 CMDCLASS = {'install_data': MyInstallData}
 
 
+#==============================================================================
 # Sphinx build (documentation)
+#==============================================================================
 def get_html_help_exe():
     """Return HTML Help Workshop executable path (Windows only)"""
     if os.name == 'nt':
@@ -136,7 +159,7 @@ try:
             sys.path.insert(0, os.path.abspath(build.build_lib))
             dirname = self.distribution.get_command_obj('build').build_purelib
             self.builder_target_dir = osp.join(dirname, 'spyderlib', 'doc')
-            
+
             if not osp.exists(self.builder_target_dir):
                 os.mkdir(self.builder_target_dir)
 
@@ -152,7 +175,7 @@ try:
                       "location (path with *only* ASCII characters).",
                       file=sys.stderr)
             sys.path.pop(0)
-            
+
             # Building chm doc, if HTML Help Workshop is installed
             if hhc_exe is not None:
                 fname = osp.join(self.builder_target_dir, 'Spyderdoc.chm')
@@ -171,11 +194,9 @@ except ImportError:
           'is not installed', file=sys.stderr)
 
 
-NAME = 'spyder'
-LIBNAME = 'spyderlib'
-from spyderlib import __version__, __project_url__
-
-
+#==============================================================================
+# Windows installer names
+#==============================================================================
 JOINEDARGS = ''.join(sys.argv)
 WINDOWS_INSTALLER = 'bdist_wininst' in JOINEDARGS or 'bdist_msi' in JOINEDARGS
 TARGET_MATCH = re.search(r'--target-version=([0-9]*)\.([0-9]*)', JOINEDARGS)
@@ -185,25 +206,9 @@ else:
     TARGET_VERSION = (str(sys.version_info[0]), str(sys.version_info[1]))
 
 
-def get_packages():
-    """Return package list"""
-    if WINDOWS_INSTALLER:
-        # Adding pyflakes and rope to the package if available in the 
-        # repository (this is not conventional but Spyder really need 
-        # those tools and there is not decent package manager on 
-        # Windows platforms, so...)
-        import shutil
-        import atexit
-        extdir = 'external-py' + TARGET_VERSION[0]
-        for name in ('rope', 'pyflakes'):
-            srcdir = osp.join(extdir, name)
-            if osp.isdir(srcdir):
-                dstdir = osp.join(LIBNAME, 'utils', 'external', name)
-                shutil.copytree(srcdir, dstdir)
-                atexit.register(shutil.rmtree, osp.abspath(dstdir))
-    packages = get_subpackages(LIBNAME)+get_subpackages('spyderplugins')
-    return packages
-
+#==============================================================================
+# Main scripts
+#==============================================================================
 # NOTE: the '[...]_win_post_install.py' script is installed even on non-Windows
 # platforms due to a bug in pip installation process (see Issue 1158)
 SCRIPTS = ['%s_win_post_install.py' % NAME]
@@ -211,13 +216,21 @@ if PY3 and sys.platform.startswith('linux'):
     SCRIPTS.append('spyder3')
 else:
     SCRIPTS.append('spyder')
+
+
+#==============================================================================
+# Files added to the package
+#==============================================================================
 EXTLIST = ['.mo', '.svg', '.png', '.css', '.html', '.js', '.chm', '.ini',
-           '.txt', '.rst', '.qss']
+           '.txt', '.rst', '.qss', '.ttf', '.json']
 if os.name == 'nt':
     SCRIPTS += ['spyder.bat']
     EXTLIST += ['.ico']
 
+
+#==============================================================================
 # Adding a message for the Windows installers
+#==============================================================================
 WININST_MSG = ""
 if WINDOWS_INSTALLER:
     WININST_MSG = \
@@ -226,15 +239,18 @@ if WINDOWS_INSTALLER:
 """
 
 
-setup(name=NAME,
+#==============================================================================
+# Setup arguments
+#==============================================================================
+setup_args = dict(name=NAME,
       version=__version__,
       description='Scientific PYthon Development EnviRonment',
       long_description=WININST_MSG + \
-"""Spyder is an interactive Python development environment providing 
+"""Spyder is an interactive Python development environment providing
 MATLAB-like features in a simple and light-weighted software.
-It also provides ready-to-use pure-Python widgets to your PyQt4 or 
-PySide application: source code editor with syntax highlighting and 
-code introspection/analysis features, NumPy array editor, dictionary 
+It also provides ready-to-use pure-Python widgets to your PyQt4 or
+PySide application: source code editor with syntax highlighting and
+code introspection/analysis features, NumPy array editor, dictionary
 editor, Python console, etc.""",
       download_url='%s/files/%s-%s.zip' % (__project_url__, NAME, __version__),
       author="Pierre Raybaut",
@@ -244,9 +260,8 @@ editor, Python console, etc.""",
       platforms=['any'],
       packages=get_packages(),
       package_data={LIBNAME: get_package_data(LIBNAME, EXTLIST),
-                    'spyderplugins':
-                    get_package_data('spyderplugins', EXTLIST)},
-      requires=["rope (>=0.9.2)", "sphinx (>=0.6.0)", "PyQt4 (>=4.4)"],
+                    'spyplugins': get_package_data('spyplugins', EXTLIST),
+                    },
       scripts=[osp.join('scripts', fname) for fname in SCRIPTS],
       data_files=get_data_files(),
       options={"bdist_wininst":
@@ -265,7 +280,46 @@ editor, Python console, etc.""",
                    'Operating System :: Unix',
                    'Programming Language :: Python :: 2.7',
                    'Programming Language :: Python :: 3',
+                   'Programming Language :: Python :: 3.3'
                    'Development Status :: 5 - Production/Stable',
                    'Topic :: Scientific/Engineering',
                    'Topic :: Software Development :: Widget Sets'],
       cmdclass=CMDCLASS)
+
+
+#==============================================================================
+# Setuptools deps
+#==============================================================================
+if any(arg == 'bdist_wheel' for arg in sys.argv):
+    import setuptools     # analysis:ignore
+
+install_requires = [
+    'rope_py3k' if PY3 else 'rope>=0.9.4',
+    'jedi==0.8.1',
+    'pyflakes',
+    'pygments',
+    'qtconsole',
+    'nbconvert',
+    'sphinx',
+    'pep8',
+    'pylint',
+    'psutil',
+    'qtawesome'
+]
+
+if 'setuptools' in sys.modules:
+    setup_args['install_requires'] = install_requires
+
+    setup_args['entry_points'] = {
+        'gui_scripts': [
+            'spyder = spyderlib.start_app:main'
+        ]
+    }
+
+    setup_args.pop('scripts', None)
+
+
+#==============================================================================
+# Main setup
+#==============================================================================
+setup(**setup_args)
diff --git a/spyder.egg-info/PKG-INFO b/spyder.egg-info/PKG-INFO
deleted file mode 100644
index daf0484..0000000
--- a/spyder.egg-info/PKG-INFO
+++ /dev/null
@@ -1,31 +0,0 @@
-Metadata-Version: 1.1
-Name: spyder
-Version: 2.3.8
-Summary: Scientific PYthon Development EnviRonment
-Home-page: https://github.com/spyder-ide/spyder
-Author: Pierre Raybaut
-Author-email: UNKNOWN
-License: MIT
-Download-URL: https://github.com/spyder-ide/spyder/files/spyder-2.3.8.zip
-Description: Spyder is an interactive Python development environment providing 
-        MATLAB-like features in a simple and light-weighted software.
-        It also provides ready-to-use pure-Python widgets to your PyQt4 or 
-        PySide application: source code editor with syntax highlighting and 
-        code introspection/analysis features, NumPy array editor, dictionary 
-        editor, Python console, etc.
-Keywords: PyQt4 PySide editor shell console widgets IDE
-Platform: any
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Operating System :: MacOS
-Classifier: Operating System :: Microsoft :: Windows
-Classifier: Operating System :: OS Independent
-Classifier: Operating System :: POSIX
-Classifier: Operating System :: Unix
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Topic :: Scientific/Engineering
-Classifier: Topic :: Software Development :: Widget Sets
-Requires: rope (>=0.9.2)
-Requires: sphinx (>=0.6.0)
-Requires: PyQt4 (>=4.4)
diff --git a/spyder.egg-info/SOURCES.txt b/spyder.egg-info/SOURCES.txt
deleted file mode 100644
index e2c609e..0000000
--- a/spyder.egg-info/SOURCES.txt
+++ /dev/null
@@ -1,692 +0,0 @@
-LICENSE
-MANIFEST.in
-README.md
-bootstrap.py
-setup.py
-app_example/create_exe.py
-app_example/example.pyw
-doc/conf.py
-doc/console.rst
-doc/debugging.rst
-doc/editor.rst
-doc/explorer.rst
-doc/findinfiles.rst
-doc/historylog.rst
-doc/index.rst
-doc/inspector.rst
-doc/installation.rst
-doc/internalconsole.rst
-doc/ipythonconsole.rst
-doc/lightmode.rst
-doc/onlinehelp.rst
-doc/options.rst
-doc/overview.rst
-doc/projectexplorer.rst
-doc/pylint.rst
-doc/spyder_bbg.png
-doc/variableexplorer.rst
-doc/_static/favicon.ico
-doc/images/arrayeditor.png
-doc/images/console.png
-doc/images/dicteditor.png
-doc/images/editor1.png
-doc/images/editor2.png
-doc/images/editor3.png
-doc/images/explorer.png
-doc/images/explorer_menu1.png
-doc/images/explorer_menu2.png
-doc/images/findinfiles.png
-doc/images/git_install_dialog.png
-doc/images/historylog.png
-doc/images/inspector_plain.png
-doc/images/inspector_rich.png
-doc/images/inspector_source.png
-doc/images/internalconsole.png
-doc/images/ipythonconsole.png
-doc/images/ipythonconsolemenu.png
-doc/images/ipythonkernelconnect.png
-doc/images/lightmode.png
-doc/images/listeditor.png
-doc/images/onlinehelp.png
-doc/images/projectexplorer.png
-doc/images/projectexplorer2.png
-doc/images/pylint.png
-doc/images/texteditor.png
-doc/images/variableexplorer-imshow.png
-doc/images/variableexplorer-plot.png
-doc/images/variableexplorer1.png
-doc/images/variableexplorer2.png
-img_src/spyder.ico
-img_src/spyder.png
-img_src/spyder3.png
-img_src/spyder_light.ico
-scripts/spyder
-scripts/spyder.bat
-scripts/spyder.desktop
-scripts/spyder3
-scripts/spyder3.desktop
-scripts/spyder_win_post_install.py
-spyder.egg-info/PKG-INFO
-spyder.egg-info/SOURCES.txt
-spyder.egg-info/dependency_links.txt
-spyder.egg-info/top_level.txt
-spyderlib/__init__.py
-spyderlib/baseconfig.py
-spyderlib/cli_options.py
-spyderlib/config.py
-spyderlib/dependencies.py
-spyderlib/guiconfig.py
-spyderlib/interpreter.py
-spyderlib/ipythonconfig.py
-spyderlib/mac_stylesheet.qss
-spyderlib/otherplugins.py
-spyderlib/pil_patch.py
-spyderlib/py3compat.py
-spyderlib/pygments_patch.py
-spyderlib/pyplot.py
-spyderlib/requirements.py
-spyderlib/rope_patch.py
-spyderlib/scientific_startup.py
-spyderlib/spyder.py
-spyderlib/start_app.py
-spyderlib/userconfig.py
-spyderlib/defaults/Readme.txt
-spyderlib/defaults/defaults-2.4.0.ini
-spyderlib/defaults/defaults-3.0.0.ini
-spyderlib/images/advanced.png
-spyderlib/images/arredit.png
-spyderlib/images/arrow.png
-spyderlib/images/bold.png
-spyderlib/images/browser.png
-spyderlib/images/chevron-left.png
-spyderlib/images/chevron-right.png
-spyderlib/images/dictedit.png
-spyderlib/images/font.png
-spyderlib/images/genprefs.png
-spyderlib/images/inspector.png
-spyderlib/images/italic.png
-spyderlib/images/matplotlib.png
-spyderlib/images/none.png
-spyderlib/images/not_found.png
-spyderlib/images/options.svg
-spyderlib/images/pythonpath_mgr.png
-spyderlib/images/pythonxy.png
-spyderlib/images/qt.png
-spyderlib/images/qtassistant.png
-spyderlib/images/qtdesigner.png
-spyderlib/images/qtlinguist.png
-spyderlib/images/scipy.png
-spyderlib/images/set_workdir.png
-spyderlib/images/splash.png
-spyderlib/images/spyder.svg
-spyderlib/images/spyder_light.svg
-spyderlib/images/upper_lower.png
-spyderlib/images/vcs_browse.png
-spyderlib/images/vcs_commit.png
-spyderlib/images/vitables.png
-spyderlib/images/whole_words.png
-spyderlib/images/win_env.png
-spyderlib/images/winpython.svg
-spyderlib/images/actions/1downarrow.png
-spyderlib/images/actions/1uparrow.png
-spyderlib/images/actions/2downarrow.png
-spyderlib/images/actions/2uparrow.png
-spyderlib/images/actions/arrow-continue.png
-spyderlib/images/actions/arrow-step-in.png
-spyderlib/images/actions/arrow-step-out.png
-spyderlib/images/actions/arrow-step-over.png
-spyderlib/images/actions/auto_reload.png
-spyderlib/images/actions/browse_tab.png
-spyderlib/images/actions/check.png
-spyderlib/images/actions/cmdprompt.png
-spyderlib/images/actions/collapse.png
-spyderlib/images/actions/collapse_selection.png
-spyderlib/images/actions/configure.png
-spyderlib/images/actions/copywop.png
-spyderlib/images/actions/delete.png
-spyderlib/images/actions/edit.png
-spyderlib/images/actions/edit24.png
-spyderlib/images/actions/edit_add.png
-spyderlib/images/actions/edit_remove.png
-spyderlib/images/actions/editcopy.png
-spyderlib/images/actions/editcut.png
-spyderlib/images/actions/editdelete.png
-spyderlib/images/actions/editpaste.png
-spyderlib/images/actions/eraser.png
-spyderlib/images/actions/exit.png
-spyderlib/images/actions/expand.png
-spyderlib/images/actions/expand_selection.png
-spyderlib/images/actions/filter.png
-spyderlib/images/actions/find.png
-spyderlib/images/actions/findf.png
-spyderlib/images/actions/findnext.png
-spyderlib/images/actions/findprevious.png
-spyderlib/images/actions/folder_new.png
-spyderlib/images/actions/hide.png
-spyderlib/images/actions/hist.png
-spyderlib/images/actions/home.png
-spyderlib/images/actions/imshow.png
-spyderlib/images/actions/insert.png
-spyderlib/images/actions/lock.png
-spyderlib/images/actions/lock_open.png
-spyderlib/images/actions/magnifier.png
-spyderlib/images/actions/maximize.png
-spyderlib/images/actions/next.png
-spyderlib/images/actions/options_less.png
-spyderlib/images/actions/options_more.png
-spyderlib/images/actions/plot.png
-spyderlib/images/actions/previous.png
-spyderlib/images/actions/redo.png
-spyderlib/images/actions/reload.png
-spyderlib/images/actions/rename.png
-spyderlib/images/actions/replace.png
-spyderlib/images/actions/restore.png
-spyderlib/images/actions/show.png
-spyderlib/images/actions/special_paste.png
-spyderlib/images/actions/stop.png
-spyderlib/images/actions/stop_debug.png
-spyderlib/images/actions/synchronize.png
-spyderlib/images/actions/tooloptions.png
-spyderlib/images/actions/undo.png
-spyderlib/images/actions/unmaximize.png
-spyderlib/images/actions/up.png
-spyderlib/images/actions/window_fullscreen.png
-spyderlib/images/actions/window_nofullscreen.png
-spyderlib/images/actions/zoom_in.png
-spyderlib/images/actions/zoom_out.png
-spyderlib/images/console/clear.png
-spyderlib/images/console/cmdprompt_t.png
-spyderlib/images/console/console.png
-spyderlib/images/console/environ.png
-spyderlib/images/console/history.png
-spyderlib/images/console/history24.png
-spyderlib/images/console/ipython_console.png
-spyderlib/images/console/ipython_console_t.png
-spyderlib/images/console/kill.png
-spyderlib/images/console/loading_sprites.png
-spyderlib/images/console/prompt.png
-spyderlib/images/console/python.png
-spyderlib/images/console/python_t.png
-spyderlib/images/console/restart.png
-spyderlib/images/console/run_small.png
-spyderlib/images/console/syspath.png
-spyderlib/images/console/terminated.png
-spyderlib/images/editor/blockcomment.png
-spyderlib/images/editor/breakpoint_big.png
-spyderlib/images/editor/breakpoint_cond_big.png
-spyderlib/images/editor/breakpoint_cond_small.png
-spyderlib/images/editor/breakpoint_small.png
-spyderlib/images/editor/bug.png
-spyderlib/images/editor/cell.png
-spyderlib/images/editor/class.png
-spyderlib/images/editor/close_panel.png
-spyderlib/images/editor/comment.png
-spyderlib/images/editor/convention.png
-spyderlib/images/editor/debug.png
-spyderlib/images/editor/error.png
-spyderlib/images/editor/file.png
-spyderlib/images/editor/filelist.png
-spyderlib/images/editor/fromcursor.png
-spyderlib/images/editor/function.png
-spyderlib/images/editor/gotoline.png
-spyderlib/images/editor/highlight.png
-spyderlib/images/editor/horsplit.png
-spyderlib/images/editor/indent.png
-spyderlib/images/editor/last_edit_location.png
-spyderlib/images/editor/method.png
-spyderlib/images/editor/newwindow.png
-spyderlib/images/editor/next_cursor.png
-spyderlib/images/editor/next_wng.png
-spyderlib/images/editor/outline_explorer.png
-spyderlib/images/editor/outline_explorer_vis.png
-spyderlib/images/editor/prev_cursor.png
-spyderlib/images/editor/prev_wng.png
-spyderlib/images/editor/private1.png
-spyderlib/images/editor/private2.png
-spyderlib/images/editor/refactor.png
-spyderlib/images/editor/run.png
-spyderlib/images/editor/run_again.png
-spyderlib/images/editor/run_cell.png
-spyderlib/images/editor/run_cell_advance.png
-spyderlib/images/editor/run_selection.png
-spyderlib/images/editor/run_settings.png
-spyderlib/images/editor/select.png
-spyderlib/images/editor/selectall.png
-spyderlib/images/editor/todo.png
-spyderlib/images/editor/todo_list.png
-spyderlib/images/editor/uncomment.png
-spyderlib/images/editor/unindent.png
-spyderlib/images/editor/versplit.png
-spyderlib/images/editor/warning.png
-spyderlib/images/editor/wng_list.png
-spyderlib/images/file/fileclose.png
-spyderlib/images/file/filecloseall.png
-spyderlib/images/file/fileimport.png
-spyderlib/images/file/filenew.png
-spyderlib/images/file/fileopen.png
-spyderlib/images/file/filesave.png
-spyderlib/images/file/filesaveas.png
-spyderlib/images/file/print.png
-spyderlib/images/file/save_all.png
-spyderlib/images/filetypes/bat.png
-spyderlib/images/filetypes/bmp.png
-spyderlib/images/filetypes/c.png
-spyderlib/images/filetypes/cc.png
-spyderlib/images/filetypes/cfg.png
-spyderlib/images/filetypes/chm.png
-spyderlib/images/filetypes/cl.png
-spyderlib/images/filetypes/cmd.png
-spyderlib/images/filetypes/cpp.png
-spyderlib/images/filetypes/css.png
-spyderlib/images/filetypes/cxx.png
-spyderlib/images/filetypes/diff.png
-spyderlib/images/filetypes/doc.png
-spyderlib/images/filetypes/enaml.png
-spyderlib/images/filetypes/exe.png
-spyderlib/images/filetypes/f.png
-spyderlib/images/filetypes/f77.png
-spyderlib/images/filetypes/f90.png
-spyderlib/images/filetypes/gif.png
-spyderlib/images/filetypes/h.png
-spyderlib/images/filetypes/hh.png
-spyderlib/images/filetypes/hpp.png
-spyderlib/images/filetypes/htm.png
-spyderlib/images/filetypes/html.png
-spyderlib/images/filetypes/hxx.png
-spyderlib/images/filetypes/inf.png
-spyderlib/images/filetypes/ini.png
-spyderlib/images/filetypes/jl.png
-spyderlib/images/filetypes/jpeg.png
-spyderlib/images/filetypes/jpg.png
-spyderlib/images/filetypes/js.png
-spyderlib/images/filetypes/log.png
-spyderlib/images/filetypes/nsh.png
-spyderlib/images/filetypes/nsi.png
-spyderlib/images/filetypes/nt.png
-spyderlib/images/filetypes/patch.png
-spyderlib/images/filetypes/pdf.png
-spyderlib/images/filetypes/png.png
-spyderlib/images/filetypes/po.png
-spyderlib/images/filetypes/pot.png
-spyderlib/images/filetypes/pps.png
-spyderlib/images/filetypes/properties.png
-spyderlib/images/filetypes/ps.png
-spyderlib/images/filetypes/pxd.png
-spyderlib/images/filetypes/pxi.png
-spyderlib/images/filetypes/py.png
-spyderlib/images/filetypes/pyc.png
-spyderlib/images/filetypes/pyw.png
-spyderlib/images/filetypes/pyx.png
-spyderlib/images/filetypes/rar.png
-spyderlib/images/filetypes/readme.png
-spyderlib/images/filetypes/reg.png
-spyderlib/images/filetypes/rej.png
-spyderlib/images/filetypes/session.png
-spyderlib/images/filetypes/tar.png
-spyderlib/images/filetypes/tex.png
-spyderlib/images/filetypes/tgz.png
-spyderlib/images/filetypes/tif.png
-spyderlib/images/filetypes/tiff.png
-spyderlib/images/filetypes/ts.png
-spyderlib/images/filetypes/txt.png
-spyderlib/images/filetypes/ui.png
-spyderlib/images/filetypes/xls.png
-spyderlib/images/filetypes/xml.png
-spyderlib/images/filetypes/zip.png
-spyderlib/images/projects/add_to_path.png
-spyderlib/images/projects/folder.png
-spyderlib/images/projects/package.png
-spyderlib/images/projects/pp_folder.png
-spyderlib/images/projects/pp_package.png
-spyderlib/images/projects/pp_project.png
-spyderlib/images/projects/project.png
-spyderlib/images/projects/project_closed.png
-spyderlib/images/projects/pydev.png
-spyderlib/images/projects/pythonpath.png
-spyderlib/images/projects/remove_from_path.png
-spyderlib/images/projects/show_all.png
-spyderlib/locale/spyderlib.pot
-spyderlib/locale/es/LC_MESSAGES/spyderlib.mo
-spyderlib/locale/es/LC_MESSAGES/spyderlib.po
-spyderlib/locale/fr/LC_MESSAGES/spyderlib.mo
-spyderlib/locale/fr/LC_MESSAGES/spyderlib.po
-spyderlib/plugins/__init__.py
-spyderlib/plugins/configdialog.py
-spyderlib/plugins/console.py
-spyderlib/plugins/editor.py
-spyderlib/plugins/explorer.py
-spyderlib/plugins/externalconsole.py
-spyderlib/plugins/findinfiles.py
-spyderlib/plugins/history.py
-spyderlib/plugins/inspector.py
-spyderlib/plugins/ipythonconsole.py
-spyderlib/plugins/onlinehelp.py
-spyderlib/plugins/outlineexplorer.py
-spyderlib/plugins/projectexplorer.py
-spyderlib/plugins/runconfig.py
-spyderlib/plugins/shortcuts.py
-spyderlib/plugins/variableexplorer.py
-spyderlib/plugins/workingdirectory.py
-spyderlib/qt/QtCore.py
-spyderlib/qt/QtGui.py
-spyderlib/qt/QtSvg.py
-spyderlib/qt/QtWebKit.py
-spyderlib/qt/__init__.py
-spyderlib/qt/compat.py
-spyderlib/utils/__init__.py
-spyderlib/utils/bsdsocket.py
-spyderlib/utils/codeanalysis.py
-spyderlib/utils/debug.py
-spyderlib/utils/dochelpers.py
-spyderlib/utils/encoding.py
-spyderlib/utils/environ.py
-spyderlib/utils/iofuncs.py
-spyderlib/utils/misc.py
-spyderlib/utils/programs.py
-spyderlib/utils/qthelpers.py
-spyderlib/utils/sourcecode.py
-spyderlib/utils/system.py
-spyderlib/utils/vcs.py
-spyderlib/utils/windows.py
-spyderlib/utils/external/__init__.py
-spyderlib/utils/external/lockfile.py
-spyderlib/utils/external/path.py
-spyderlib/utils/external/pickleshare.py
-spyderlib/utils/inspector/__init__.py
-spyderlib/utils/inspector/conf.py
-spyderlib/utils/inspector/sphinxify.py
-spyderlib/utils/inspector/tutorial.rst
-spyderlib/utils/inspector/js/collapse_sections.js
-spyderlib/utils/inspector/js/copy_button.js
-spyderlib/utils/inspector/js/fix_image_paths.js
-spyderlib/utils/inspector/js/jquery.js
-spyderlib/utils/inspector/js/math_config.js
-spyderlib/utils/inspector/js/move_outline.js
-spyderlib/utils/inspector/js/utils.js
-spyderlib/utils/inspector/js/mathjax/MathJax.js
-spyderlib/utils/inspector/js/mathjax/config/TeX-AMS-MML_HTMLorMML-full.js
-spyderlib/utils/inspector/js/mathjax/config/TeX-AMS-MML_HTMLorMML.js
-spyderlib/utils/inspector/js/mathjax/config/TeX-AMS-MML_SVG-full.js
-spyderlib/utils/inspector/js/mathjax/config/TeX-AMS-MML_SVG.js
-spyderlib/utils/inspector/js/mathjax/config/TeX-MML-AM_HTMLorMML-full.js
-spyderlib/utils/inspector/js/mathjax/config/TeX-MML-AM_HTMLorMML.js
-spyderlib/utils/inspector/js/mathjax/config/default.js
-spyderlib/utils/inspector/js/mathjax/config/local/local.js
-spyderlib/utils/inspector/js/mathjax/extensions/FontWarnings.js
-spyderlib/utils/inspector/js/mathjax/extensions/MathEvents.js
-spyderlib/utils/inspector/js/mathjax/extensions/MathMenu.js
-spyderlib/utils/inspector/js/mathjax/extensions/MathZoom.js
-spyderlib/utils/inspector/js/mathjax/extensions/asciimath2jax.js
-spyderlib/utils/inspector/js/mathjax/extensions/jsMath2jax.js
-spyderlib/utils/inspector/js/mathjax/extensions/mml2jax.js
-spyderlib/utils/inspector/js/mathjax/extensions/tex2jax.js
-spyderlib/utils/inspector/js/mathjax/extensions/toMathML.js
-spyderlib/utils/inspector/js/mathjax/extensions/v1.0-warning.js
-spyderlib/utils/inspector/js/mathjax/extensions/HTML-CSS/handle-floats.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/AMSmath.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/AMSsymbols.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/HTML.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/action.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/autobold.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/autoload-all.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/bbox.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/begingroup.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/boldsymbol.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/cancel.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/color.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/enclose.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/extpfeil.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/mathchoice.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/mhchem.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/newcommand.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/noErrors.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/noUndefined.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/unicode.js
-spyderlib/utils/inspector/js/mathjax/extensions/TeX/verb.js
-spyderlib/utils/inspector/js/mathjax/images/CloseX-31.png
-spyderlib/utils/inspector/js/mathjax/images/MenuArrow-15.png
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/jax.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/Arrows.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/BasicLatin.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/CombDiacritMarks.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/CombDiactForSymbols.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/Dingbats.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/GeneralPunctuation.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/GeometricShapes.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/GreekAndCoptic.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/Latin1Supplement.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/LetterlikeSymbols.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/MathOperators.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/MiscMathSymbolsA.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/MiscMathSymbolsB.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/MiscSymbolsAndArrows.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/MiscTechnical.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/SpacingModLetters.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/SuppMathOperators.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/SupplementalArrowsA.js
-spyderlib/utils/inspector/js/mathjax/jax/element/mml/optable/SupplementalArrowsB.js
-spyderlib/utils/inspector/js/mathjax/jax/input/AsciiMath/config.js
-spyderlib/utils/inspector/js/mathjax/jax/input/AsciiMath/jax.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/config.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/jax.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/a.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/b.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/c.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/d.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/e.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/f.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/fr.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/g.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/h.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/i.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/j.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/k.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/l.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/m.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/n.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/o.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/opf.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/p.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/q.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/r.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/s.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/scr.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/t.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/u.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/v.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/w.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/x.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/y.js
-spyderlib/utils/inspector/js/mathjax/jax/input/MathML/entities/z.js
-spyderlib/utils/inspector/js/mathjax/jax/input/TeX/config.js
-spyderlib/utils/inspector/js/mathjax/jax/input/TeX/jax.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/config.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/jax.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/autoload/annotation-xml.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/autoload/maction.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/autoload/menclose.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/autoload/mglyph.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/autoload/mmultiscripts.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/autoload/ms.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/autoload/mtable.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/autoload/multiline.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/fontdata-extra.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/fontdata.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/Arrows.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/BoxDrawing.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/CombDiacritMarks.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/Dingbats.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/EnclosedAlphanum.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/GeneralPunctuation.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/GeometricShapes.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/GreekAndCoptic.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/Latin1Supplement.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/LatinExtendedA.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/LetterlikeSymbols.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/MathOperators.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/MiscMathSymbolsB.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/MiscSymbols.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/MiscTechnical.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/PUA.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/SpacingModLetters.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/AMS/Regular/SuppMathOperators.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Caligraphic/Bold/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Caligraphic/Regular/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Fraktur/Bold/BasicLatin.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Fraktur/Bold/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Fraktur/Bold/Other.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Fraktur/Bold/PUA.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Fraktur/Regular/BasicLatin.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Fraktur/Regular/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Fraktur/Regular/Other.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Fraktur/Regular/PUA.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/Arrows.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/BasicLatin.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/CombDiacritMarks.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/CombDiactForSymbols.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/GeneralPunctuation.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/GeometricShapes.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/GreekAndCoptic.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/Latin1Supplement.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/LatinExtendedA.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/LatinExtendedB.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/LetterlikeSymbols.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/MathOperators.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/MiscMathSymbolsA.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/MiscSymbols.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/MiscTechnical.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/SpacingModLetters.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/SuppMathOperators.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Bold/SupplementalArrowsA.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Italic/BasicLatin.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Italic/CombDiacritMarks.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Italic/GeneralPunctuation.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Italic/GreekAndCoptic.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Italic/LatinExtendedA.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Italic/LatinExtendedB.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Italic/LetterlikeSymbols.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Italic/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Italic/MathOperators.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Regular/BasicLatin.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Regular/CombDiacritMarks.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Regular/GeometricShapes.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Regular/GreekAndCoptic.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Regular/LatinExtendedA.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Regular/LatinExtendedB.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Regular/LetterlikeSymbols.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Regular/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Regular/MathOperators.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Regular/MiscSymbols.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Regular/SpacingModLetters.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Main/Regular/SuppMathOperators.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Math/BoldItalic/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Math/Italic/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/SansSerif/Bold/BasicLatin.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/SansSerif/Bold/CombDiacritMarks.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/SansSerif/Bold/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/SansSerif/Bold/Other.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/SansSerif/Italic/BasicLatin.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/SansSerif/Italic/CombDiacritMarks.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/SansSerif/Italic/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/SansSerif/Italic/Other.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/SansSerif/Regular/BasicLatin.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/SansSerif/Regular/CombDiacritMarks.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/SansSerif/Regular/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/SansSerif/Regular/Other.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Script/Regular/BasicLatin.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Script/Regular/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Size1/Regular/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Size2/Regular/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Size3/Regular/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Size4/Regular/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Typewriter/Regular/BasicLatin.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Typewriter/Regular/CombDiacritMarks.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Typewriter/Regular/Main.js
-spyderlib/utils/inspector/js/mathjax/jax/output/SVG/fonts/TeX/Typewriter/Regular/Other.js
-spyderlib/utils/inspector/static/css/default.css
-spyderlib/utils/inspector/static/css/pygments.css
-spyderlib/utils/inspector/static/images/collapse_expand.png
-spyderlib/utils/inspector/static/images/debug-continue.png
-spyderlib/utils/inspector/static/images/debug-step-in.png
-spyderlib/utils/inspector/static/images/debug-step-out.png
-spyderlib/utils/inspector/static/images/debug-step-over.png
-spyderlib/utils/inspector/static/images/spyder-hello-docstring.png
-spyderlib/utils/inspector/static/images/spyder-nice-docstring-rendering.png
-spyderlib/utils/inspector/static/images/spyder-sympy-example.png
-spyderlib/utils/inspector/templates/layout.html
-spyderlib/utils/inspector/templates/usage.html
-spyderlib/utils/inspector/templates/warning.html
-spyderlib/utils/introspection/__init__.py
-spyderlib/utils/introspection/fallback_plugin.py
-spyderlib/utils/introspection/jedi_plugin.py
-spyderlib/utils/introspection/module_completion.py
-spyderlib/utils/introspection/plugin_manager.py
-spyderlib/utils/introspection/rope_plugin.py
-spyderlib/utils/ipython/templates/blank.html
-spyderlib/utils/ipython/templates/kernel_error.html
-spyderlib/utils/ipython/templates/loading.html
-spyderlib/widgets/__init__.py
-spyderlib/widgets/arrayeditor.py
-spyderlib/widgets/browser.py
-spyderlib/widgets/calltip.py
-spyderlib/widgets/colors.py
-spyderlib/widgets/comboboxes.py
-spyderlib/widgets/dataframeeditor.py
-spyderlib/widgets/dependencies.py
-spyderlib/widgets/dicteditor.py
-spyderlib/widgets/dicteditorutils.py
-spyderlib/widgets/editor.py
-spyderlib/widgets/editortools.py
-spyderlib/widgets/explorer.py
-spyderlib/widgets/findinfiles.py
-spyderlib/widgets/findreplace.py
-spyderlib/widgets/formlayout.py
-spyderlib/widgets/importwizard.py
-spyderlib/widgets/internalshell.py
-spyderlib/widgets/ipython.py
-spyderlib/widgets/mixins.py
-spyderlib/widgets/objecteditor.py
-spyderlib/widgets/onecolumntree.py
-spyderlib/widgets/pathmanager.py
-spyderlib/widgets/projectexplorer.py
-spyderlib/widgets/pydocgui.py
-spyderlib/widgets/shell.py
-spyderlib/widgets/status.py
-spyderlib/widgets/tabs.py
-spyderlib/widgets/texteditor.py
-spyderlib/widgets/externalshell/__init__.py
-spyderlib/widgets/externalshell/baseshell.py
-spyderlib/widgets/externalshell/inputhooks.py
-spyderlib/widgets/externalshell/introspection.py
-spyderlib/widgets/externalshell/monitor.py
-spyderlib/widgets/externalshell/namespacebrowser.py
-spyderlib/widgets/externalshell/osx_app_site.py
-spyderlib/widgets/externalshell/pythonshell.py
-spyderlib/widgets/externalshell/sitecustomize.py
-spyderlib/widgets/externalshell/start_ipython_kernel.py
-spyderlib/widgets/externalshell/systemshell.py
-spyderlib/widgets/sourcecode/__init__.py
-spyderlib/widgets/sourcecode/base.py
-spyderlib/widgets/sourcecode/codeeditor.py
-spyderlib/widgets/sourcecode/syntaxhighlighters.py
-spyderlib/widgets/sourcecode/terminal.py
-spyderplugins/__init__.py
-spyderplugins/io_dicom.py
-spyderplugins/io_hdf5.py
-spyderplugins/p_breakpoints.py
-spyderplugins/p_profiler.py
-spyderplugins/p_pylint.py
-spyderplugins/images/profiler.png
-spyderplugins/images/pylint.png
-spyderplugins/locale/es/LC_MESSAGES/p_breakpoints.mo
-spyderplugins/locale/es/LC_MESSAGES/p_profiler.mo
-spyderplugins/locale/es/LC_MESSAGES/p_pylint.mo
-spyderplugins/locale/fr/LC_MESSAGES/p_breakpoints.mo
-spyderplugins/locale/fr/LC_MESSAGES/p_profiler.mo
-spyderplugins/locale/fr/LC_MESSAGES/p_pylint.mo
-spyderplugins/widgets/__init__.py
-spyderplugins/widgets/breakpointsgui.py
-spyderplugins/widgets/profilergui.py
-spyderplugins/widgets/pylintgui.py
\ No newline at end of file
diff --git a/spyder.egg-info/dependency_links.txt b/spyder.egg-info/dependency_links.txt
deleted file mode 100644
index 8b13789..0000000
--- a/spyder.egg-info/dependency_links.txt
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/spyder.egg-info/top_level.txt b/spyder.egg-info/top_level.txt
deleted file mode 100644
index 3562be6..0000000
--- a/spyder.egg-info/top_level.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-spyderlib
-spyderplugins
diff --git a/spyderlib/__init__.py b/spyderlib/__init__.py
index 1bd5023..fc07709 100644
--- a/spyderlib/__init__.py
+++ b/spyderlib/__init__.py
@@ -28,7 +28,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 """
 
-__version__ = '2.3.8'
+__version__ = '3.0.0b2'
 __license__ = __doc__
 __project_url__ = 'https://github.com/spyder-ide/spyder'
 __forum_url__   = 'http://groups.google.com/group/spyderlib'
@@ -68,7 +68,7 @@ def get_versions(reporev=True):
     revision = None
     if reporev:
         from spyderlib.utils import vcs
-        revision = vcs.get_git_revision(os.path.dirname(__dir__))
+        revision, branch = vcs.get_git_revision(os.path.dirname(__dir__))
 
     if not sys.platform == 'darwin':  # To avoid a crash with our Mac app
         system = platform.system()
diff --git a/spyderplugins/__init__.py b/spyderlib/config/__init__.py
similarity index 100%
copy from spyderplugins/__init__.py
copy to spyderlib/config/__init__.py
diff --git a/spyderlib/baseconfig.py b/spyderlib/config/base.py
similarity index 67%
rename from spyderlib/baseconfig.py
rename to spyderlib/config/base.py
index f5f7609..ddeef2e 100644
--- a/spyderlib/baseconfig.py
+++ b/spyderlib/config/base.py
@@ -1,26 +1,26 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2011-2013 Pierre Raybaut
+# Copyright © 2009- The Spyder development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
 """
 Spyder base configuration management
 
-As opposed to spyderlib/config.py, this configuration script deals 
-exclusively with non-GUI features configuration only
-(in other words, we won't import any PyQt object here, avoiding any 
+This file only deals with non-GUI configuration features
+(in other words, we won't import any PyQt object here, avoiding any
 sip API incompatibility issue in spyderlib's non-gui modules)
 """
 
 from __future__ import print_function
 
+import codecs
+import locale
 import os.path as osp
 import os
 import sys
 
 # Local imports
-from spyderlib import __version__
 from spyderlib.utils import encoding
 from spyderlib.py3compat import (is_unicode, TEXT_TYPES, INT_TYPES, PY3,
                                  to_text_string, is_text_string)
@@ -41,7 +41,8 @@ TEST = os.environ.get('SPYDER_TEST')
 #==============================================================================
 # Debug helpers
 #==============================================================================
-STDOUT = sys.stdout
+# This is needed after restarting and using debug_print
+STDOUT = sys.stdout if PY3 else codecs.getwriter('utf-8')(sys.stdout)
 STDERR = sys.stderr
 def _get_debug_env():
     debug_env = os.environ.get('SPYDER_DEBUG', '')
@@ -50,18 +51,28 @@ def _get_debug_env():
     return int(debug_env)    
 DEBUG = _get_debug_env()
 
-def debug_print(message):
+def debug_print(*message):
     """Output debug messages to stdout"""
     if DEBUG:
         ss = STDOUT
-        print(message, file=ss)
+        if PY3:
+            # This is needed after restarting and using debug_print
+            for m in message:
+                ss.buffer.write(str(m).encode('utf-8'))
+            print('', file=ss)
+        else:
+            print(*message, file=ss)
 
 #==============================================================================
 # Configuration paths
 #==============================================================================
 # Spyder settings dir
+# NOTE: During the 2.x.x series this dir was named .spyder2, but
+# since 3.0+ we've reverted back to use .spyder to simplify major
+# updates in version (required when we change APIs by Linux
+# packagers)
 if TEST is None:
-    SUBFOLDER = '.spyder%s' % __version__.split('.')[0]
+    SUBFOLDER = '.spyder'
 else:
     SUBFOLDER = 'spyder_test'
 
@@ -179,16 +190,12 @@ def add_image_path(path):
         return
     global IMG_PATH
     IMG_PATH.append(path)
-    for _root, dirs, _files in os.walk(path):
-        for dir in dirs:
-            IMG_PATH.append(osp.join(path, dir))
+    for dirpath, dirnames, _filenames in os.walk(path):
+        for dirname in dirnames:
+            IMG_PATH.append(osp.join(dirpath, dirname))
 
 add_image_path(get_module_data_path('spyderlib', relpath='images'))
 
-from spyderlib.otherplugins import PLUGIN_PATH
-if PLUGIN_PATH is not None:
-    add_image_path(osp.join(PLUGIN_PATH, 'images'))
-
 def get_image_path(name, default="not_found.png"):
     """Return image absolute path"""
     for img_path in IMG_PATH:
@@ -202,18 +209,107 @@ def get_image_path(name, default="not_found.png"):
 #==============================================================================
 # Translations
 #==============================================================================
+LANG_FILE = get_conf_path('langconfig')
+DEFAULT_LANGUAGE = 'en'
+
+# This needs to be updated every time a new language is added to spyder, and is
+# used by the Preferences configuration to populate the Language QComboBox
+LANGUAGE_CODES = {'en': u'English',
+                  'fr': u'Français',
+                  'es': u'Español',
+                  'pt_BR': u'Português'
+                  }
+
+
+def get_available_translations():
+    """
+    List available translations for spyder based on the folders found in the
+    locale folder. This function checks if LANGUAGE_CODES contain the same
+    information that is found in the 'locale' folder to ensure that when a new
+    language is added, LANGUAGE_CODES is updated.
+    """
+    locale_path = get_module_data_path("spyderlib", relpath="locale",
+                                       attr_name='LOCALEPATH')
+    listdir = os.listdir(locale_path)
+    langs = [d for d in listdir if osp.isdir(osp.join(locale_path, d))]
+    langs = [DEFAULT_LANGUAGE] + langs
+
+    # Check that there is a language code available in case a new translation
+    # is added, to ensure LANGUAGE_CODES is updated.
+    for lang in langs:
+        if lang not in LANGUAGE_CODES:
+            error = _('Update LANGUAGE_CODES (inside config/base.py) if a new '
+                      'translation has been added to Spyder')
+            raise Exception(error)
+    return langs
+
+
+def get_interface_language():
+    """
+    If Spyder has a translation available for the locale language, it will
+    return the version provided by Spyder adjusted for language subdifferences,
+    otherwise it will return DEFAULT_LANGUAGE.
+
+    Example:
+    1.) Spyder provides ('en',  'fr', 'es' and 'pt_BR'), if the locale is
+    either 'en_US' or 'en' or 'en_UK', this function will return 'en'
+
+    2.) Spyder provides ('en',  'fr', 'es' and 'pt_BR'), if the locale is
+    either 'pt' or 'pt_BR', this function will return 'pt_BR'
+    """
+    locale_language = locale.getdefaultlocale()[0]
+
+    language = DEFAULT_LANGUAGE
+
+    if locale_language is not None:
+        spyder_languages = get_available_translations()
+        for lang in spyder_languages:
+            if locale_language == lang:
+                language = locale_language
+                break
+            elif locale_language.startswith(lang) or \
+              lang.startswith(locale_language):
+                language = lang
+                break
+
+    return language
+
+
+def save_lang_conf(value):
+    """Save language setting to language config file"""
+    with open(LANG_FILE, 'w') as f:
+        f.write(value)
+
+
+def load_lang_conf():
+    """
+    Load language setting from language config file if it exists, otherwise
+    try to use the local settings if Spyder provides a translation, or
+    return the default if no translation provided.
+    """
+    if osp.isfile(LANG_FILE):
+        with open(LANG_FILE, 'r') as f:
+            lang = f.read()
+    else:
+        lang = get_interface_language()
+        save_lang_conf(lang)
+    return lang
+
+
 def get_translation(modname, dirname=None):
     """Return translation callback for module *modname*"""
     if dirname is None:
         dirname = modname
     locale_path = get_module_data_path(dirname, relpath="locale",
                                        attr_name='LOCALEPATH')
-    # fixup environment var LANG in case it's unknown
-    if "LANG" not in os.environ:
-        import locale
-        lang = locale.getdefaultlocale()[0]
-        if lang is not None:
-            os.environ["LANG"] = lang
+    # If LANG is defined in ubuntu, a warning message is displayed, so in unix
+    # systems we define the LANGUAGE variable.
+    language = load_lang_conf()
+    if os.name == 'nt':
+        os.environ["LANG"] = language      # Works on Windows
+    else:
+        os.environ["LANGUAGE"] = language  # Works on Linux
+ 
     import gettext
     try:
         _trans = gettext.translation(modname, locale_path, codeset="utf-8")
@@ -279,7 +375,7 @@ def get_supported_types():
 
 # Variable explorer display / check all elements data types for sequences:
 # (when saving the variable explorer contents, check_all is True,
-#  see widgets/externalshell/namespacebrowser.py:NamespaceBrowser.save_data)
+#  see widgets/variableexplorer/namespacebrowser.py:NamespaceBrowser.save_data)
 CHECK_ALL = False #XXX: If True, this should take too much to compute...
 
 EXCLUDED_NAMES = ['nan', 'inf', 'infty', 'little_endian', 'colorbar_doc',
diff --git a/spyderlib/guiconfig.py b/spyderlib/config/gui.py
similarity index 96%
rename from spyderlib/guiconfig.py
rename to spyderlib/config/gui.py
index 7e68d94..3ef5234 100644
--- a/spyderlib/guiconfig.py
+++ b/spyderlib/config/gui.py
@@ -6,7 +6,7 @@
 
 """
 Spyder GUI-related configuration management
-(for non-GUI configuration, see spyderlib/baseconfig.py)
+(for non-GUI configuration, see spyderlib/config/base.py)
 
 Important note regarding shortcuts:
     For compatibility with QWERTZ keyboards, one must avoid using the following
@@ -19,10 +19,10 @@ from collections import namedtuple
 from spyderlib.qt.QtGui import QFont, QFontDatabase, QShortcut, QKeySequence
 from spyderlib.qt.QtCore import Qt
 
-from spyderlib.config import CONF
-from spyderlib.userconfig import NoDefault
-from spyderlib.widgets.sourcecode import syntaxhighlighters as sh
+from spyderlib.config.main import CONF
+from spyderlib.config.user import NoDefault
 from spyderlib.py3compat import to_text_string
+from spyderlib.utils import syntaxhighlighters as sh
 
 
 # To save metadata about widget shortcuts (needed to build our
diff --git a/spyderlib/ipythonconfig.py b/spyderlib/config/ipython.py
similarity index 81%
rename from spyderlib/ipythonconfig.py
rename to spyderlib/config/ipython.py
index 2739f1a..1331fe9 100644
--- a/spyderlib/ipythonconfig.py
+++ b/spyderlib/config/ipython.py
@@ -10,12 +10,12 @@ IPython configuration variables needed by Spyder
 
 from spyderlib.utils import programs
 from spyderlib import dependencies
-from spyderlib.baseconfig import _
+from spyderlib.config.base import _
 
 
 # Constants
-IPYTHON_REQVER = '>=1.0'
-ZMQ_REQVER = '>=2.1.11'
+IPYTHON_REQVER = '>=3.0'
+ZMQ_REQVER = '>=13.0.0'
 QTCONSOLE_REQVER = '>=4.0'
 
 
@@ -35,9 +35,10 @@ if ipy4_installed:
 
 # Auxiliary functions
 def is_qtconsole_installed():
-    pyzmq_installed = programs.is_module_installed('zmq')
+    ipyqt_installed = programs.is_module_installed('IPython.qt',
+                                                   version=IPYTHON_REQVER)
+    pyzmq_installed = programs.is_module_installed('zmq', version=ZMQ_REQVER)
     pygments_installed = programs.is_module_installed('pygments')
-    ipyqt_installed = programs.is_module_installed('IPython.qt')
 
     if ipyqt_installed and pyzmq_installed and pygments_installed:
         if ipy4_installed:
diff --git a/spyderlib/config.py b/spyderlib/config/main.py
similarity index 89%
rename from spyderlib/config.py
rename to spyderlib/config/main.py
index 72cd524..f558a0b 100644
--- a/spyderlib/config.py
+++ b/spyderlib/config/main.py
@@ -16,9 +16,9 @@ import sys
 import os.path as osp
 
 # Local import
-from spyderlib.userconfig import UserConfig
-from spyderlib.baseconfig import (CHECK_ALL, EXCLUDED_NAMES, SUBFOLDER,
-                                  get_home_dir, _)
+from spyderlib.config.user import UserConfig
+from spyderlib.config.base import (CHECK_ALL, EXCLUDED_NAMES, SUBFOLDER,
+                                   get_home_dir, _)
 from spyderlib.utils import iofuncs, codeanalysis
 
 
@@ -42,7 +42,7 @@ EDIT_FILETYPES = (
     (_("reStructured Text files"), ('.txt', '.rst')),
     (_("gettext files"), ('.po', '.pot')),
     (_("NSIS files"), ('.nsi', '.nsh')),
-    (_("Web page files"), ('.css', '.htm', '.html',)),
+    (_("Web page files"), ('.scss', '.css', '.htm', '.html',)),
     (_("XML files"), ('.xml',)),
     (_("Javascript files"), ('.js',)),
     (_("Json files"), ('.json',)),
@@ -111,8 +111,10 @@ NAME_FILTERS = ['*' + _ext for _ext in VALID_EXT + SHOW_EXT if _ext]+\
 # it to open external files
 OPEN_FILES_PORT = 21128
 
-# Ctrl key
-CTRL = "Meta" if sys.platform == 'darwin' else "Ctrl"
+# OS Specific
+WIN = os.name == 'nt'
+MAC = sys.platform == 'darwin'
+CTRL = "Meta" if MAC else "Ctrl"
 
 
 #==============================================================================
@@ -179,12 +181,15 @@ else:
 DEFAULTS = [
             ('main',
              {
+              'icon_theme': 'spyder 2',
               'single_instance': True,
               'open_files_port': OPEN_FILES_PORT,
               'tear_off_menus': False,
               'vertical_dockwidget_titlebars': False,
               'vertical_tabs': False,
               'animated_docks': True,
+              'prompt_on_exit': False,
+              'panes_locked': True,
               'window/size': (1260, 740),
               'window/position': (10, 10),
               'window/is_maximized': True,
@@ -201,17 +206,23 @@ DEFAULTS = [
               # settings within the "light mode")
               'lightwindow/prefs_dialog_size': (745, 411),
 
+              'show_status_bar': True,
               'memory_usage/enable': True,
               'memory_usage/timeout': 2000,
               'cpu_usage/enable': False,
               'cpu_usage/timeout': 2000,
               'use_custom_margin': True,
               'custom_margin': 0,
-              'show_internal_console_if_traceback': True
+              'show_internal_console_if_traceback': True,
+              'check_updates_on_startup': True,
+              'toolbars_visible': True,
               }),
             ('quick_layouts',
              {
               'place_holder': '',
+              'names': ['Matlab layout', 'Rstudio layout', 'Vertical split', 'Horizontal split'],
+              'order': ['Matlab layout', 'Rstudio layout', 'Vertical split', 'Horizontal split'],
+              'active': ['Matlab layout', 'Rstudio layout', 'Vertical split', 'Horizontal split'],
               }),
             ('editor_appearance',
              {
@@ -259,12 +270,7 @@ DEFAULTS = [
               'show_icontext': False,
               'monitor/enabled': True,
               'qt/api': 'default',
-              'pyqt/api_version': 2,
-              'pyqt/ignore_sip_setapi_errors': False,
-              'matplotlib/backend/enabled': True,
-              'matplotlib/backend/value': 'MacOSX' if (sys.platform == 'darwin' \
-                                           and os.environ.get('QT_API') == 'pyside')\
-                                           else 'Qt4Agg',
+              'matplotlib/backend/value': 0,
               'umr/enabled': True,
               'umr/verbose': True,
               'umr/namelist': ['guidata', 'guiqwt'],
@@ -284,7 +290,7 @@ DEFAULTS = [
               'font/italic': False,
               'font/bold': False,
               'show_banner': True,
-              'use_gui_completion': True,
+              'completion_type': 0,
               'use_pager': False,
               'show_calltips': True,
               'ask_before_closing': True,
@@ -483,16 +489,18 @@ DEFAULTS = [
               # ---- Global ----
               # -- In spyder.py
               '_/close pane': "Shift+Ctrl+F4",
+              '_/lock unlock panes': "Shift+Ctrl+F5",
               '_/preferences': "Ctrl+Alt+Shift+P",
               '_/maximize pane': "Ctrl+Alt+Shift+M",
               '_/fullscreen mode': "F11",
+              '_/use next layout': "Shift+Alt+PgDown",
+              '_/use previous layout': "Shift+Alt+PgUp",
+              '_/save current layout': "Shift+Alt+S",
+              '_/toggle default layout': "Shift+Alt+Home",
+              '_/layout preferences': "Shift+Alt+P",
+              '_/show toolbars': "Alt+Shift+T",
+              '_/restart': "Shift+Alt+R",
               '_/quit': "Ctrl+Q",
-              '_/switch to/from layout 1': "Shift+Alt+F1",
-              '_/set layout 1': "Ctrl+Shift+Alt+F1",
-              '_/switch to/from layout 2': "Shift+Alt+F2",
-              '_/set layout 2': "Ctrl+Shift+Alt+F2",
-              '_/switch to/from layout 3': "Shift+Alt+F3",
-              '_/set layout 3': "Ctrl+Shift+Alt+F3",
               # -- In plugins/editor
               '_/debug step over': "Ctrl+F10",
               '_/debug continue': "Ctrl+F12",
@@ -514,9 +522,9 @@ DEFAULTS = [
               # ---- Editor ----
               # -- In codeeditor
               'editor/code completion': CTRL+'+Space',
-              'editor/duplicate line': "Ctrl+Alt+Up" if os.name == 'nt' else \
+              'editor/duplicate line': "Ctrl+Alt+Up" if WIN else \
                                        "Shift+Alt+Up",
-              'editor/copy line': "Ctrl+Alt+Down" if os.name == 'nt' else \
+              'editor/copy line': "Ctrl+Alt+Down" if WIN else \
                                   "Shift+Alt+Down",
               'editor/delete line': 'Ctrl+D',
               'editor/move line up': "Alt+Up",
@@ -525,25 +533,48 @@ DEFAULTS = [
               'editor/toggle comment': "Ctrl+1",
               'editor/blockcomment': "Ctrl+4",
               'editor/unblockcomment': "Ctrl+5",
+              'editor/start of line': "Meta+A",
+              'editor/end of line': "Meta+E",
+              'editor/previous line': "Meta+P",
+              'editor/next line': "Meta+N",
+              'editor/previous char': "Meta+B",
+              'editor/next char': "Meta+F",
+              'editor/previous word': "Meta+Left",
+              'editor/next word': "Meta+Right",
+              'editor/kill to line end': "Meta+K",
+              'editor/kill to line start': "Meta+U",
+              'editor/yank': 'Meta+Y',
+              'editor/rotate kill ring': 'Shift+Meta+Y',
+              'editor/kill previous word': 'Meta+Backspace',
+              'editor/kill next word': 'Meta+D',
+              'editor/start of document': 'Ctrl+Up',
+              'editor/end of document': 'Ctrl+Down',
               # -- In widgets/editor
               'editor/inspect current object': 'Ctrl+I',
               'editor/go to line': 'Ctrl+L',
-              'editor/file list management': 'Ctrl+E',
               'editor/go to previous file': 'Ctrl+Tab',
               'editor/go to next file': 'Ctrl+Shift+Tab',
+              '_/file switcher': 'Ctrl+P',
               # -- In spyder.py
               'editor/find text': "Ctrl+F",
               'editor/find next': "F3",
               'editor/find previous': "Shift+F3",
               'editor/replace text': "Ctrl+H",
+              'editor/undo': 'Ctrl+U',
+              'editor/redo': 'Ctrl+Y',
+              'editor/cut': 'Ctrl+X',
+              'editor/copy': 'Ctrl+C',
+              'editor/paste': 'Ctrl+V',
+              'editor/delete': 'Delete',
+              'editor/select all': "Ctrl+A",
               # -- In plugins/editor
               'editor/show/hide outline': "Ctrl+Alt+O",
               'editor/show/hide project explorer': "Ctrl+Alt+P",
               'editor/new file': "Ctrl+N",
               'editor/open file': "Ctrl+O",
               'editor/save file': "Ctrl+S",
-              'editor/save all': "Ctrl+Shift+S",
-              'editor/print': "Ctrl+P",
+              'editor/save all': "Ctrl+Alt+S",
+              'editor/save as': 'Ctrl+Shift+S',
               'editor/close all': "Ctrl+Shift+W",
               'editor/breakpoint': 'F12',
               'editor/conditional breakpoint': 'Shift+F12',
@@ -728,7 +759,7 @@ DEFAULTS = [
 # 2. If you want to *remove* options that are no longer needed in our codebase,
 #    you need to do a MAJOR update in version, e.g. from 3.0.0 to 4.0.0
 # 3. You don't need to touch this value if you're just adding a new option
-CONF_VERSION = '15.2.0'
+CONF_VERSION = '21.1.0'
 
 # XXX: Previously we had load=(not DEV) here but DEV was set to *False*.
 # Check if it *really* needs to be updated or not
diff --git a/spyderlib/userconfig.py b/spyderlib/config/user.py
similarity index 88%
rename from spyderlib/userconfig.py
rename to spyderlib/config/user.py
index 90f3ecb..6034fec 100644
--- a/spyderlib/userconfig.py
+++ b/spyderlib/config/user.py
@@ -1,53 +1,34 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
-
-#    userconfig License Agreement (MIT License)
-#    ------------------------------------------
-#    
-#    Copyright © 2009-2012 Pierre Raybaut
-#    Copyright © 2014 The Spyder Development Team
-#    
-#    Permission is hereby granted, free of charge, to any person
-#    obtaining a copy of this software and associated documentation
-#    files (the "Software"), to deal in the Software without
-#    restriction, including without limitation the rights to use,
-#    copy, modify, merge, publish, distribute, sublicense, and/or sell
-#    copies of the Software, and to permit persons to whom the
-#    Software is furnished to do so, subject to the following
-#    conditions:
-#    
-#    The above copyright notice and this permission notice shall be
-#    included in all copies or substantial portions of the Software.
-#    
-#    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-#    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-#    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-#    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-#    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-#    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-#    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-#    OTHER DEALINGS IN THE SOFTWARE.
-
+#
+# Copyright © 2009-2013 Pierre Raybaut
+# Copyright © 2014-2015 The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)    
 
 """
-This module provides user configuration file (.ini file) management features
-based on ``ConfigParser`` (present in the standard library).
+This module provides user configuration file management features for Spyder
+
+It's based on the ConfigParser module (present in the standard library).
 """
 
 from __future__ import print_function
 
+# Std imports
 import os
 import re
 import os.path as osp
 import shutil
 import time
 
-from spyderlib.baseconfig import (DEV, TEST, get_module_source_path,
-                                  get_home_dir)
+# Local imports
+from spyderlib import __version__
+from spyderlib.config.base import (DEV, TEST, get_module_source_path,
+                                   get_home_dir)
 from spyderlib.utils.programs import check_version
 from spyderlib.py3compat import configparser as cp
 from spyderlib.py3compat import PY2, is_text_string, to_text_string
 
+# Std imports for Python 2
 if PY2:
     import codecs
 
@@ -77,7 +58,7 @@ class DefaultsConfig(cp.ConfigParser):
         The one from configparser fails for non-ascii Windows accounts
         """
         if self._defaults:
-            fp.write("[%s]\n" % DEFAULTSECT)
+            fp.write("[%s]\n" % cp.DEFAULTSECT)
             for (key, value) in self._defaults.items():
                 fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t')))
             fp.write("\n")
@@ -154,7 +135,21 @@ class DefaultsConfig(cp.ConfigParser):
             if 'defaults' in self.name:
                 folder = osp.join(folder, 'defaults')
             try:
-                os.makedirs(folder)
+                # Copying old config dir for Spyder 3.0. The new config
+                # dir for 3.0+ is going to be simply ~/.spyder{-py3}
+                if __version__.split('.')[0] == '3':
+                    if PY2:
+                        old_confdir = '.spyder2'
+                    else:
+                        old_confdir = '.spyder2-py3'
+                    old_confdir = osp.join(get_home_dir(), old_confdir)
+                    new_confdir = osp.join(get_home_dir(), self.subfolder)
+                    if osp.isdir(old_confdir) and not osp.isdir(new_confdir):
+                        shutil.copytree(old_confdir, new_confdir)
+                    else:
+                        os.makedirs(folder)
+                else:
+                    os.makedirs(folder)
             except os.error:
                 # Folder (or one of its parents) already exists
                 pass
diff --git a/spyderlib/dependencies.py b/spyderlib/dependencies.py
index 0c4ebfa..1b356e6 100644
--- a/spyderlib/dependencies.py
+++ b/spyderlib/dependencies.py
@@ -1,10 +1,10 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2013 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
-"""Module checking Spyder optional runtime dependencies"""
+"""Module checking Spyder runtime dependencies"""
 
 
 import os
@@ -14,7 +14,7 @@ from spyderlib.utils import programs
 
 
 class Dependency(object):
-    """Spyder's optional dependency
+    """Spyder's dependency
 
     version may starts with =, >=, > or < to specify the exact requirement ;
     multiple conditions may be separated by ';' (e.g. '>=0.13;<1.0')"""
@@ -60,7 +60,7 @@ class Dependency(object):
 DEPENDENCIES = []
 
 def add(modname, features, required_version, installed_version=None):
-    """Add Spyder optional dependency"""
+    """Add Spyder dependency"""
     global DEPENDENCIES
     for dependency in DEPENDENCIES:
         if dependency.modname == modname:
@@ -71,7 +71,6 @@ def add(modname, features, required_version, installed_version=None):
 
 def check(modname):
     """Check if required dependency is installed"""
-    global DEPENDENCIES
     for dependency in DEPENDENCIES:
         if dependency.modname == modname:
             return dependency.check()
@@ -79,8 +78,7 @@ def check(modname):
         raise RuntimeError("Unkwown dependency %s" % modname)
 
 def status():
-    """Return a complete status of Optional Dependencies"""
-    global DEPENDENCIES
+    """Return a complete status of Dependencies"""
     maxwidth = 0
     col1 = []
     col2 = []
diff --git a/spyderlib/fonts/spyder-charmap.json b/spyderlib/fonts/spyder-charmap.json
new file mode 100644
index 0000000..2d60254
--- /dev/null
+++ b/spyderlib/fonts/spyder-charmap.json
@@ -0,0 +1,50 @@
+{
+    "continue": "0xE000",
+    "debug": "0xE001",
+    "run-cell": "0xE003",
+    "run-cell-inplace": "0xE004",
+    "step-forward": "0xE005",
+    "step-into": "0xE006",
+    "step-out": "0xE007",
+    "step-over": "0xE008",
+    "stop": "0xE009",
+    "cell": "0xE00A",
+    "cell-page": "0xE03A",
+    "cell-page-shadow": "0xE03F",
+    "cell-code": "0xE03B",
+    "cell-play": "0xE03C",
+    "cell-next": "0xE03D",
+    "cell-border": "0xE03E",
+    "run-one-inplace": "0xE00B",
+    "run-one": "0xE00C",
+    "python-logo": "0xE00D",
+    "python-logo-up": "0xE00E",
+    "python-logo-down": "0xE00F",
+    "spyder-logo-web": "0xE010",
+    "spyder-logo-snake": "0xE011",
+    "spyder-logo-background": "0xE012",
+    "inward": "0xE013",
+    "rows": "0xE014",
+    "window": "0xE015",
+    "maximize-pane": "0xE016",
+    "minimize-pane": "0xE017",
+    "ipython-logo": "0xE018",
+    "ipython-logo-alt": "0xE042",
+    "jupyter-logo": "0xE043",
+    "run-selection": "0xE019",
+    "text-select-all": "0xE01A",
+    "treeview": "0xE01B",
+    "circle-letter-a": "0xE01F",
+    "circle-letter-c": "0xE020",
+    "circle-letter-f": "0xE021",
+    "circle-hash": "0xE022",
+    "circle-letter-m": "0xE023",
+    "circle-percent": "0xE024",
+    "circle-letter-r": "0xE025",
+    "cube-front": "0xE055",
+    "cube-bottom": "0xE056",
+    "cube-right": "0xE057",
+    "cube-left": "0xE058",
+    "cube-rear": "0xE059",
+    "cube-top": "0xE060"
+}
diff --git a/spyderlib/fonts/spyder.ttf b/spyderlib/fonts/spyder.ttf
new file mode 100644
index 0000000..48ef0e3
Binary files /dev/null and b/spyderlib/fonts/spyder.ttf differ
diff --git a/spyderlib/images/actions/1downarrow.png b/spyderlib/images/actions/1downarrow.png
index 391b2b0..c2b7714 100644
Binary files a/spyderlib/images/actions/1downarrow.png and b/spyderlib/images/actions/1downarrow.png differ
diff --git a/spyderlib/images/actions/1uparrow.png b/spyderlib/images/actions/1uparrow.png
index 221a939..36f07ab 100644
Binary files a/spyderlib/images/actions/1uparrow.png and b/spyderlib/images/actions/1uparrow.png differ
diff --git a/spyderlib/images/actions/2downarrow.png b/spyderlib/images/actions/2downarrow.png
index 3866533..96c7192 100644
Binary files a/spyderlib/images/actions/2downarrow.png and b/spyderlib/images/actions/2downarrow.png differ
diff --git a/spyderlib/images/actions/2uparrow.png b/spyderlib/images/actions/2uparrow.png
index 852c192..5d9bae8 100644
Binary files a/spyderlib/images/actions/2uparrow.png and b/spyderlib/images/actions/2uparrow.png differ
diff --git a/spyderlib/images/actions/arrow-continue.png b/spyderlib/images/actions/arrow-continue.png
index 38a87cd..fe021de 100644
Binary files a/spyderlib/images/actions/arrow-continue.png and b/spyderlib/images/actions/arrow-continue.png differ
diff --git a/spyderlib/images/actions/arrow-step-in.png b/spyderlib/images/actions/arrow-step-in.png
index 5978c72..34590bd 100644
Binary files a/spyderlib/images/actions/arrow-step-in.png and b/spyderlib/images/actions/arrow-step-in.png differ
diff --git a/spyderlib/images/actions/arrow-step-out.png b/spyderlib/images/actions/arrow-step-out.png
index a9ddc32..a2f006f 100644
Binary files a/spyderlib/images/actions/arrow-step-out.png and b/spyderlib/images/actions/arrow-step-out.png differ
diff --git a/spyderlib/images/actions/arrow-step-over.png b/spyderlib/images/actions/arrow-step-over.png
index 2310b2e..1686e73 100644
Binary files a/spyderlib/images/actions/arrow-step-over.png and b/spyderlib/images/actions/arrow-step-over.png differ
diff --git a/spyderlib/images/actions/auto_reload.png b/spyderlib/images/actions/auto_reload.png
index 0bf8d44..04edfa3 100644
Binary files a/spyderlib/images/actions/auto_reload.png and b/spyderlib/images/actions/auto_reload.png differ
diff --git a/spyderlib/images/actions/browse_tab.png b/spyderlib/images/actions/browse_tab.png
index c7f606d..b6b42a4 100644
Binary files a/spyderlib/images/actions/browse_tab.png and b/spyderlib/images/actions/browse_tab.png differ
diff --git a/spyderlib/images/actions/check.png b/spyderlib/images/actions/check.png
index 97e875a..a4d3225 100644
Binary files a/spyderlib/images/actions/check.png and b/spyderlib/images/actions/check.png differ
diff --git a/spyderlib/images/actions/cmdprompt.png b/spyderlib/images/actions/cmdprompt.png
index 2f2590e..c4fbfe5 100644
Binary files a/spyderlib/images/actions/cmdprompt.png and b/spyderlib/images/actions/cmdprompt.png differ
diff --git a/spyderlib/images/actions/collapse.png b/spyderlib/images/actions/collapse.png
index ad06020..6b1f434 100644
Binary files a/spyderlib/images/actions/collapse.png and b/spyderlib/images/actions/collapse.png differ
diff --git a/spyderlib/images/actions/collapse_selection.png b/spyderlib/images/actions/collapse_selection.png
index c421665..4575325 100644
Binary files a/spyderlib/images/actions/collapse_selection.png and b/spyderlib/images/actions/collapse_selection.png differ
diff --git a/spyderlib/images/actions/configure.png b/spyderlib/images/actions/configure.png
index 5cbfe32..6c40eae 100644
Binary files a/spyderlib/images/actions/configure.png and b/spyderlib/images/actions/configure.png differ
diff --git a/spyderlib/images/actions/copywop.png b/spyderlib/images/actions/copywop.png
index c781678..2c334cc 100644
Binary files a/spyderlib/images/actions/copywop.png and b/spyderlib/images/actions/copywop.png differ
diff --git a/spyderlib/images/actions/delete.png b/spyderlib/images/actions/delete.png
index 6311feb..11725d5 100644
Binary files a/spyderlib/images/actions/delete.png and b/spyderlib/images/actions/delete.png differ
diff --git a/spyderlib/images/actions/edit.png b/spyderlib/images/actions/edit.png
index c1e2877..362a5f0 100644
Binary files a/spyderlib/images/actions/edit.png and b/spyderlib/images/actions/edit.png differ
diff --git a/spyderlib/images/actions/edit24.png b/spyderlib/images/actions/edit24.png
index af264bc..8781a53 100644
Binary files a/spyderlib/images/actions/edit24.png and b/spyderlib/images/actions/edit24.png differ
diff --git a/spyderlib/images/actions/edit_add.png b/spyderlib/images/actions/edit_add.png
index 1fe4205..da9b61a 100644
Binary files a/spyderlib/images/actions/edit_add.png and b/spyderlib/images/actions/edit_add.png differ
diff --git a/spyderlib/images/actions/edit_remove.png b/spyderlib/images/actions/edit_remove.png
index 45eb438..5d8fecd 100644
Binary files a/spyderlib/images/actions/edit_remove.png and b/spyderlib/images/actions/edit_remove.png differ
diff --git a/spyderlib/images/actions/editcopy.png b/spyderlib/images/actions/editcopy.png
index 549f6d7..6a7614a 100644
Binary files a/spyderlib/images/actions/editcopy.png and b/spyderlib/images/actions/editcopy.png differ
diff --git a/spyderlib/images/actions/editcut.png b/spyderlib/images/actions/editcut.png
index 12d91a4..436fa23 100644
Binary files a/spyderlib/images/actions/editcut.png and b/spyderlib/images/actions/editcut.png differ
diff --git a/spyderlib/images/actions/editdelete.png b/spyderlib/images/actions/editdelete.png
index 3536ef1..eeeaa22 100644
Binary files a/spyderlib/images/actions/editdelete.png and b/spyderlib/images/actions/editdelete.png differ
diff --git a/spyderlib/images/actions/editpaste.png b/spyderlib/images/actions/editpaste.png
index c655582..bba209d 100644
Binary files a/spyderlib/images/actions/editpaste.png and b/spyderlib/images/actions/editpaste.png differ
diff --git a/spyderlib/images/actions/eraser.png b/spyderlib/images/actions/eraser.png
index 7e04abf..d76f3e2 100644
Binary files a/spyderlib/images/actions/eraser.png and b/spyderlib/images/actions/eraser.png differ
diff --git a/spyderlib/images/actions/exit.png b/spyderlib/images/actions/exit.png
index e090aa6..e86fa9c 100644
Binary files a/spyderlib/images/actions/exit.png and b/spyderlib/images/actions/exit.png differ
diff --git a/spyderlib/images/actions/expand.png b/spyderlib/images/actions/expand.png
index b0212eb..1c21751 100644
Binary files a/spyderlib/images/actions/expand.png and b/spyderlib/images/actions/expand.png differ
diff --git a/spyderlib/images/actions/expand_selection.png b/spyderlib/images/actions/expand_selection.png
index dad8af9..32ec296 100644
Binary files a/spyderlib/images/actions/expand_selection.png and b/spyderlib/images/actions/expand_selection.png differ
diff --git a/spyderlib/images/actions/filter.png b/spyderlib/images/actions/filter.png
index 50d9a4c..faef8ba 100644
Binary files a/spyderlib/images/actions/filter.png and b/spyderlib/images/actions/filter.png differ
diff --git a/spyderlib/images/actions/find.png b/spyderlib/images/actions/find.png
index 18a123a..0738c11 100644
Binary files a/spyderlib/images/actions/find.png and b/spyderlib/images/actions/find.png differ
diff --git a/spyderlib/images/actions/findf.png b/spyderlib/images/actions/findf.png
index e4e9b9c..78596aa 100644
Binary files a/spyderlib/images/actions/findf.png and b/spyderlib/images/actions/findf.png differ
diff --git a/spyderlib/images/actions/findnext.png b/spyderlib/images/actions/findnext.png
index 502a44f..5a57a8a 100644
Binary files a/spyderlib/images/actions/findnext.png and b/spyderlib/images/actions/findnext.png differ
diff --git a/spyderlib/images/actions/findprevious.png b/spyderlib/images/actions/findprevious.png
index 93d644c..a1f44b4 100644
Binary files a/spyderlib/images/actions/findprevious.png and b/spyderlib/images/actions/findprevious.png differ
diff --git a/spyderlib/images/actions/folder_new.png b/spyderlib/images/actions/folder_new.png
index 97b2f01..2f3d594 100644
Binary files a/spyderlib/images/actions/folder_new.png and b/spyderlib/images/actions/folder_new.png differ
diff --git a/spyderlib/images/actions/hide.png b/spyderlib/images/actions/hide.png
index f2d031e..09833e8 100644
Binary files a/spyderlib/images/actions/hide.png and b/spyderlib/images/actions/hide.png differ
diff --git a/spyderlib/images/actions/hist.png b/spyderlib/images/actions/hist.png
index 3911347..12798a9 100644
Binary files a/spyderlib/images/actions/hist.png and b/spyderlib/images/actions/hist.png differ
diff --git a/spyderlib/images/actions/home.png b/spyderlib/images/actions/home.png
index c0a0730..e835f92 100644
Binary files a/spyderlib/images/actions/home.png and b/spyderlib/images/actions/home.png differ
diff --git a/spyderlib/images/actions/imshow.png b/spyderlib/images/actions/imshow.png
index 2136210..d837c18 100644
Binary files a/spyderlib/images/actions/imshow.png and b/spyderlib/images/actions/imshow.png differ
diff --git a/spyderlib/images/actions/insert.png b/spyderlib/images/actions/insert.png
index 6ceba98..1715ab2 100644
Binary files a/spyderlib/images/actions/insert.png and b/spyderlib/images/actions/insert.png differ
diff --git a/spyderlib/images/actions/lock.png b/spyderlib/images/actions/lock.png
index f6ef32b..519f2ac 100644
Binary files a/spyderlib/images/actions/lock.png and b/spyderlib/images/actions/lock.png differ
diff --git a/spyderlib/images/actions/lock_open.png b/spyderlib/images/actions/lock_open.png
index d0a0254..31f68f5 100644
Binary files a/spyderlib/images/actions/lock_open.png and b/spyderlib/images/actions/lock_open.png differ
diff --git a/spyderlib/images/actions/magnifier.png b/spyderlib/images/actions/magnifier.png
index 249b4af..db55e94 100644
Binary files a/spyderlib/images/actions/magnifier.png and b/spyderlib/images/actions/magnifier.png differ
diff --git a/spyderlib/images/actions/maximize.png b/spyderlib/images/actions/maximize.png
index 0512107..fa52576 100644
Binary files a/spyderlib/images/actions/maximize.png and b/spyderlib/images/actions/maximize.png differ
diff --git a/spyderlib/images/actions/next.png b/spyderlib/images/actions/next.png
index a0fd2bc..8d3ad83 100644
Binary files a/spyderlib/images/actions/next.png and b/spyderlib/images/actions/next.png differ
diff --git a/spyderlib/images/actions/options_less.png b/spyderlib/images/actions/options_less.png
index a45c492..93a2d8c 100644
Binary files a/spyderlib/images/actions/options_less.png and b/spyderlib/images/actions/options_less.png differ
diff --git a/spyderlib/images/actions/options_more.png b/spyderlib/images/actions/options_more.png
index fcc7cea..e5420cb 100644
Binary files a/spyderlib/images/actions/options_more.png and b/spyderlib/images/actions/options_more.png differ
diff --git a/spyderlib/images/actions/plot.png b/spyderlib/images/actions/plot.png
index 618102c..b935afd 100644
Binary files a/spyderlib/images/actions/plot.png and b/spyderlib/images/actions/plot.png differ
diff --git a/spyderlib/images/actions/previous.png b/spyderlib/images/actions/previous.png
index 6242dd5..9f44b1b 100644
Binary files a/spyderlib/images/actions/previous.png and b/spyderlib/images/actions/previous.png differ
diff --git a/spyderlib/images/actions/redo.png b/spyderlib/images/actions/redo.png
index 1846b0a..7cb3c20 100644
Binary files a/spyderlib/images/actions/redo.png and b/spyderlib/images/actions/redo.png differ
diff --git a/spyderlib/images/actions/reload.png b/spyderlib/images/actions/reload.png
index de5265f..1729212 100644
Binary files a/spyderlib/images/actions/reload.png and b/spyderlib/images/actions/reload.png differ
diff --git a/spyderlib/images/actions/rename.png b/spyderlib/images/actions/rename.png
index b073d66..9c6100c 100644
Binary files a/spyderlib/images/actions/rename.png and b/spyderlib/images/actions/rename.png differ
diff --git a/spyderlib/images/actions/replace.png b/spyderlib/images/actions/replace.png
index a6e1231..fa24c6f 100644
Binary files a/spyderlib/images/actions/replace.png and b/spyderlib/images/actions/replace.png differ
diff --git a/spyderlib/images/actions/restore.png b/spyderlib/images/actions/restore.png
index 1ab9807..05ccd9c 100644
Binary files a/spyderlib/images/actions/restore.png and b/spyderlib/images/actions/restore.png differ
diff --git a/spyderlib/images/actions/show.png b/spyderlib/images/actions/show.png
index 1938b0e..2fa0969 100644
Binary files a/spyderlib/images/actions/show.png and b/spyderlib/images/actions/show.png differ
diff --git a/spyderlib/images/actions/special_paste.png b/spyderlib/images/actions/special_paste.png
index c5fc602..81b1174 100644
Binary files a/spyderlib/images/actions/special_paste.png and b/spyderlib/images/actions/special_paste.png differ
diff --git a/spyderlib/images/actions/stop.png b/spyderlib/images/actions/stop.png
index 6550bb6..6e58f57 100644
Binary files a/spyderlib/images/actions/stop.png and b/spyderlib/images/actions/stop.png differ
diff --git a/spyderlib/images/actions/stop_debug.png b/spyderlib/images/actions/stop_debug.png
index f94f3e7..79ea809 100644
Binary files a/spyderlib/images/actions/stop_debug.png and b/spyderlib/images/actions/stop_debug.png differ
diff --git a/spyderlib/images/actions/synchronize.png b/spyderlib/images/actions/synchronize.png
index f98f086..84bb38d 100644
Binary files a/spyderlib/images/actions/synchronize.png and b/spyderlib/images/actions/synchronize.png differ
diff --git a/spyderlib/images/actions/tooloptions.png b/spyderlib/images/actions/tooloptions.png
index e58b81e..dc321c8 100644
Binary files a/spyderlib/images/actions/tooloptions.png and b/spyderlib/images/actions/tooloptions.png differ
diff --git a/spyderlib/images/actions/undo.png b/spyderlib/images/actions/undo.png
index 817e18d..d7d62fe 100644
Binary files a/spyderlib/images/actions/undo.png and b/spyderlib/images/actions/undo.png differ
diff --git a/spyderlib/images/actions/unmaximize.png b/spyderlib/images/actions/unmaximize.png
index 2a494dd..6b1c21c 100644
Binary files a/spyderlib/images/actions/unmaximize.png and b/spyderlib/images/actions/unmaximize.png differ
diff --git a/spyderlib/images/actions/up.png b/spyderlib/images/actions/up.png
index 5036f3c..bcc3204 100644
Binary files a/spyderlib/images/actions/up.png and b/spyderlib/images/actions/up.png differ
diff --git a/spyderlib/images/actions/window_fullscreen.png b/spyderlib/images/actions/window_fullscreen.png
index c648cf5..3e6593e 100644
Binary files a/spyderlib/images/actions/window_fullscreen.png and b/spyderlib/images/actions/window_fullscreen.png differ
diff --git a/spyderlib/images/actions/window_nofullscreen.png b/spyderlib/images/actions/window_nofullscreen.png
index 4d88f5b..b0869c7 100644
Binary files a/spyderlib/images/actions/window_nofullscreen.png and b/spyderlib/images/actions/window_nofullscreen.png differ
diff --git a/spyderlib/images/actions/zoom_in.png b/spyderlib/images/actions/zoom_in.png
index 030b5e7..e1842d9 100644
Binary files a/spyderlib/images/actions/zoom_in.png and b/spyderlib/images/actions/zoom_in.png differ
diff --git a/spyderlib/images/actions/zoom_out.png b/spyderlib/images/actions/zoom_out.png
index 20be89c..ca5c993 100644
Binary files a/spyderlib/images/actions/zoom_out.png and b/spyderlib/images/actions/zoom_out.png differ
diff --git a/spyderlib/images/advanced.png b/spyderlib/images/advanced.png
index 581c6d4..256c790 100644
Binary files a/spyderlib/images/advanced.png and b/spyderlib/images/advanced.png differ
diff --git a/spyderlib/images/arredit.png b/spyderlib/images/arredit.png
index 7940faf..567b5f8 100644
Binary files a/spyderlib/images/arredit.png and b/spyderlib/images/arredit.png differ
diff --git a/spyderlib/images/arrow.png b/spyderlib/images/arrow.png
index 4005c9b..3ac2481 100644
Binary files a/spyderlib/images/arrow.png and b/spyderlib/images/arrow.png differ
diff --git a/spyderlib/images/bold.png b/spyderlib/images/bold.png
index 1619ff0..c96ce63 100644
Binary files a/spyderlib/images/bold.png and b/spyderlib/images/bold.png differ
diff --git a/spyderlib/images/browser.png b/spyderlib/images/browser.png
index 95dbeac..43e02bb 100644
Binary files a/spyderlib/images/browser.png and b/spyderlib/images/browser.png differ
diff --git a/spyderlib/images/console/cmdprompt_t.png b/spyderlib/images/console/cmdprompt_t.png
index cf6fcb1..1d71328 100644
Binary files a/spyderlib/images/console/cmdprompt_t.png and b/spyderlib/images/console/cmdprompt_t.png differ
diff --git a/spyderlib/images/console/console.png b/spyderlib/images/console/console.png
index 6db158f..dcdfb3e 100644
Binary files a/spyderlib/images/console/console.png and b/spyderlib/images/console/console.png differ
diff --git a/spyderlib/images/console/clear.png b/spyderlib/images/console/editclear.png
similarity index 68%
rename from spyderlib/images/console/clear.png
rename to spyderlib/images/console/editclear.png
index 4b58e65..acd6068 100644
Binary files a/spyderlib/images/console/clear.png and b/spyderlib/images/console/editclear.png differ
diff --git a/spyderlib/images/console/environ.png b/spyderlib/images/console/environ.png
index 1b14d96..e7239df 100644
Binary files a/spyderlib/images/console/environ.png and b/spyderlib/images/console/environ.png differ
diff --git a/spyderlib/images/console/history.png b/spyderlib/images/console/history.png
index a4f0569..8b4feae 100644
Binary files a/spyderlib/images/console/history.png and b/spyderlib/images/console/history.png differ
diff --git a/spyderlib/images/console/history24.png b/spyderlib/images/console/history24.png
index 9c82460..8ce7207 100644
Binary files a/spyderlib/images/console/history24.png and b/spyderlib/images/console/history24.png differ
diff --git a/spyderlib/images/console/ipython_console.png b/spyderlib/images/console/ipython_console.png
index 7f9d4bf..1aca205 100644
Binary files a/spyderlib/images/console/ipython_console.png and b/spyderlib/images/console/ipython_console.png differ
diff --git a/spyderlib/images/console/ipython_console_t.png b/spyderlib/images/console/ipython_console_t.png
index ef4556a..cf88e6d 100644
Binary files a/spyderlib/images/console/ipython_console_t.png and b/spyderlib/images/console/ipython_console_t.png differ
diff --git a/spyderlib/images/console/kill.png b/spyderlib/images/console/kill.png
index 05c60f2..79a1e56 100644
Binary files a/spyderlib/images/console/kill.png and b/spyderlib/images/console/kill.png differ
diff --git a/spyderlib/images/console/loading_sprites.png b/spyderlib/images/console/loading_sprites.png
index eac4d53..4e39d3e 100644
Binary files a/spyderlib/images/console/loading_sprites.png and b/spyderlib/images/console/loading_sprites.png differ
diff --git a/spyderlib/images/console/prompt.png b/spyderlib/images/console/prompt.png
index 45d38d3..dda75d7 100644
Binary files a/spyderlib/images/console/prompt.png and b/spyderlib/images/console/prompt.png differ
diff --git a/spyderlib/images/console/python.png b/spyderlib/images/console/python.png
index b8c47a0..8c22fb6 100644
Binary files a/spyderlib/images/console/python.png and b/spyderlib/images/console/python.png differ
diff --git a/spyderlib/images/console/python_t.png b/spyderlib/images/console/python_t.png
index b32024b..3a31981 100644
Binary files a/spyderlib/images/console/python_t.png and b/spyderlib/images/console/python_t.png differ
diff --git a/spyderlib/images/console/restart.png b/spyderlib/images/console/restart.png
index 5afcc94..0a0335c 100644
Binary files a/spyderlib/images/console/restart.png and b/spyderlib/images/console/restart.png differ
diff --git a/spyderlib/images/console/run_small.png b/spyderlib/images/console/run_small.png
index 68b4171..9039f07 100644
Binary files a/spyderlib/images/console/run_small.png and b/spyderlib/images/console/run_small.png differ
diff --git a/spyderlib/images/console/syspath.png b/spyderlib/images/console/syspath.png
index b718247..4c349fa 100644
Binary files a/spyderlib/images/console/syspath.png and b/spyderlib/images/console/syspath.png differ
diff --git a/spyderlib/images/console/terminated.png b/spyderlib/images/console/terminated.png
index c0e8ff8..3a611b4 100644
Binary files a/spyderlib/images/console/terminated.png and b/spyderlib/images/console/terminated.png differ
diff --git a/spyderlib/images/dictedit.png b/spyderlib/images/dictedit.png
index 7f348c9..06b89b7 100644
Binary files a/spyderlib/images/dictedit.png and b/spyderlib/images/dictedit.png differ
diff --git a/spyderlib/images/editor/attribute.png b/spyderlib/images/editor/attribute.png
new file mode 100644
index 0000000..a8684cc
Binary files /dev/null and b/spyderlib/images/editor/attribute.png differ
diff --git a/spyderlib/images/editor/blockcomment.png b/spyderlib/images/editor/blockcomment.png
index 23958eb..fe8c1be 100644
Binary files a/spyderlib/images/editor/blockcomment.png and b/spyderlib/images/editor/blockcomment.png differ
diff --git a/spyderlib/images/editor/breakpoint_big.png b/spyderlib/images/editor/breakpoint_big.png
index d89ce51..e4b6780 100644
Binary files a/spyderlib/images/editor/breakpoint_big.png and b/spyderlib/images/editor/breakpoint_big.png differ
diff --git a/spyderlib/images/editor/breakpoint_cond_big.png b/spyderlib/images/editor/breakpoint_cond_big.png
index 3b1108b..36e2678 100644
Binary files a/spyderlib/images/editor/breakpoint_cond_big.png and b/spyderlib/images/editor/breakpoint_cond_big.png differ
diff --git a/spyderlib/images/editor/breakpoint_cond_small.png b/spyderlib/images/editor/breakpoint_cond_small.png
index 292acaf..c1a76bf 100644
Binary files a/spyderlib/images/editor/breakpoint_cond_small.png and b/spyderlib/images/editor/breakpoint_cond_small.png differ
diff --git a/spyderlib/images/editor/breakpoint_small.png b/spyderlib/images/editor/breakpoint_small.png
index 5c48597..0ba899c 100644
Binary files a/spyderlib/images/editor/breakpoint_small.png and b/spyderlib/images/editor/breakpoint_small.png differ
diff --git a/spyderlib/images/editor/bug.png b/spyderlib/images/editor/bug.png
index 57c20bd..28a851a 100644
Binary files a/spyderlib/images/editor/bug.png and b/spyderlib/images/editor/bug.png differ
diff --git a/spyderlib/images/editor/cell.png b/spyderlib/images/editor/cell.png
index dbbaeb5..d410ac0 100644
Binary files a/spyderlib/images/editor/cell.png and b/spyderlib/images/editor/cell.png differ
diff --git a/spyderlib/images/editor/class.png b/spyderlib/images/editor/class.png
index 08f4e4b..e1db26a 100644
Binary files a/spyderlib/images/editor/class.png and b/spyderlib/images/editor/class.png differ
diff --git a/spyderlib/images/editor/close_panel.png b/spyderlib/images/editor/close_panel.png
index 369c999..6cab16c 100644
Binary files a/spyderlib/images/editor/close_panel.png and b/spyderlib/images/editor/close_panel.png differ
diff --git a/spyderlib/images/editor/comment.png b/spyderlib/images/editor/comment.png
index e36a7b6..585f7e8 100644
Binary files a/spyderlib/images/editor/comment.png and b/spyderlib/images/editor/comment.png differ
diff --git a/spyderlib/images/editor/convention.png b/spyderlib/images/editor/convention.png
index a582e94..a3b9e02 100644
Binary files a/spyderlib/images/editor/convention.png and b/spyderlib/images/editor/convention.png differ
diff --git a/spyderlib/images/editor/debug.png b/spyderlib/images/editor/debug.png
index 48d5839..2c2ebf7 100644
Binary files a/spyderlib/images/editor/debug.png and b/spyderlib/images/editor/debug.png differ
diff --git a/spyderlib/images/editor/error.png b/spyderlib/images/editor/error.png
index a1ff423..7f25e62 100644
Binary files a/spyderlib/images/editor/error.png and b/spyderlib/images/editor/error.png differ
diff --git a/spyderlib/images/editor/file.png b/spyderlib/images/editor/file.png
index da01ef5..ffa2a48 100644
Binary files a/spyderlib/images/editor/file.png and b/spyderlib/images/editor/file.png differ
diff --git a/spyderlib/images/editor/filelist.png b/spyderlib/images/editor/filelist.png
index 8679c52..d0a308c 100644
Binary files a/spyderlib/images/editor/filelist.png and b/spyderlib/images/editor/filelist.png differ
diff --git a/spyderlib/images/editor/fromcursor.png b/spyderlib/images/editor/fromcursor.png
index d937f7d..45ff527 100644
Binary files a/spyderlib/images/editor/fromcursor.png and b/spyderlib/images/editor/fromcursor.png differ
diff --git a/spyderlib/images/editor/function.png b/spyderlib/images/editor/function.png
index db73ca2..fa59798 100644
Binary files a/spyderlib/images/editor/function.png and b/spyderlib/images/editor/function.png differ
diff --git a/spyderlib/images/editor/gotoline.png b/spyderlib/images/editor/gotoline.png
index c90469b..924f4da 100644
Binary files a/spyderlib/images/editor/gotoline.png and b/spyderlib/images/editor/gotoline.png differ
diff --git a/spyderlib/images/editor/highlight.png b/spyderlib/images/editor/highlight.png
index b7f07ec..be87386 100644
Binary files a/spyderlib/images/editor/highlight.png and b/spyderlib/images/editor/highlight.png differ
diff --git a/spyderlib/images/editor/horsplit.png b/spyderlib/images/editor/horsplit.png
index 93695ed..79f0b4b 100644
Binary files a/spyderlib/images/editor/horsplit.png and b/spyderlib/images/editor/horsplit.png differ
diff --git a/spyderlib/images/editor/indent.png b/spyderlib/images/editor/indent.png
index 7b39799..7b706ff 100644
Binary files a/spyderlib/images/editor/indent.png and b/spyderlib/images/editor/indent.png differ
diff --git a/spyderlib/images/editor/last_edit_location.png b/spyderlib/images/editor/last_edit_location.png
index fef9541..3f73ac5 100644
Binary files a/spyderlib/images/editor/last_edit_location.png and b/spyderlib/images/editor/last_edit_location.png differ
diff --git a/spyderlib/images/editor/method.png b/spyderlib/images/editor/method.png
index 0f37ee1..fc79ebf 100644
Binary files a/spyderlib/images/editor/method.png and b/spyderlib/images/editor/method.png differ
diff --git a/spyderlib/images/editor/module.png b/spyderlib/images/editor/module.png
new file mode 100644
index 0000000..48beb64
Binary files /dev/null and b/spyderlib/images/editor/module.png differ
diff --git a/spyderlib/images/editor/newwindow.png b/spyderlib/images/editor/newwindow.png
index 5bfc691..379373d 100644
Binary files a/spyderlib/images/editor/newwindow.png and b/spyderlib/images/editor/newwindow.png differ
diff --git a/spyderlib/images/editor/next_cursor.png b/spyderlib/images/editor/next_cursor.png
index 446194f..ae79d3d 100644
Binary files a/spyderlib/images/editor/next_cursor.png and b/spyderlib/images/editor/next_cursor.png differ
diff --git a/spyderlib/images/editor/next_wng.png b/spyderlib/images/editor/next_wng.png
index ca973d8..2341d8f 100644
Binary files a/spyderlib/images/editor/next_wng.png and b/spyderlib/images/editor/next_wng.png differ
diff --git a/spyderlib/images/editor/no_match.png b/spyderlib/images/editor/no_match.png
new file mode 100644
index 0000000..690e2f9
Binary files /dev/null and b/spyderlib/images/editor/no_match.png differ
diff --git a/spyderlib/images/editor/outline_explorer.png b/spyderlib/images/editor/outline_explorer.png
index 6a62c98..59bb924 100644
Binary files a/spyderlib/images/editor/outline_explorer.png and b/spyderlib/images/editor/outline_explorer.png differ
diff --git a/spyderlib/images/editor/outline_explorer_vis.png b/spyderlib/images/editor/outline_explorer_vis.png
index b7f7ae6..d6e98fb 100644
Binary files a/spyderlib/images/editor/outline_explorer_vis.png and b/spyderlib/images/editor/outline_explorer_vis.png differ
diff --git a/spyderlib/images/editor/prev_cursor.png b/spyderlib/images/editor/prev_cursor.png
index 075206d..a9b17c6 100644
Binary files a/spyderlib/images/editor/prev_cursor.png and b/spyderlib/images/editor/prev_cursor.png differ
diff --git a/spyderlib/images/editor/prev_wng.png b/spyderlib/images/editor/prev_wng.png
index 1ea2039..ad6391e 100644
Binary files a/spyderlib/images/editor/prev_wng.png and b/spyderlib/images/editor/prev_wng.png differ
diff --git a/spyderlib/images/editor/private1.png b/spyderlib/images/editor/private1.png
index 2c91d85..d49f4a1 100644
Binary files a/spyderlib/images/editor/private1.png and b/spyderlib/images/editor/private1.png differ
diff --git a/spyderlib/images/editor/private2.png b/spyderlib/images/editor/private2.png
index 42df3a3..0a5c196 100644
Binary files a/spyderlib/images/editor/private2.png and b/spyderlib/images/editor/private2.png differ
diff --git a/spyderlib/images/editor/refactor.png b/spyderlib/images/editor/refactor.png
index 5ed704d..783e091 100644
Binary files a/spyderlib/images/editor/refactor.png and b/spyderlib/images/editor/refactor.png differ
diff --git a/spyderlib/images/editor/run.png b/spyderlib/images/editor/run.png
index 7759843..3e84c12 100644
Binary files a/spyderlib/images/editor/run.png and b/spyderlib/images/editor/run.png differ
diff --git a/spyderlib/images/editor/run_again.png b/spyderlib/images/editor/run_again.png
index 5053bfd..6bd59ec 100644
Binary files a/spyderlib/images/editor/run_again.png and b/spyderlib/images/editor/run_again.png differ
diff --git a/spyderlib/images/editor/run_cell.png b/spyderlib/images/editor/run_cell.png
index 0a39849..73dfdc9 100644
Binary files a/spyderlib/images/editor/run_cell.png and b/spyderlib/images/editor/run_cell.png differ
diff --git a/spyderlib/images/editor/run_cell_advance.png b/spyderlib/images/editor/run_cell_advance.png
index 9f29b0f..5405783 100644
Binary files a/spyderlib/images/editor/run_cell_advance.png and b/spyderlib/images/editor/run_cell_advance.png differ
diff --git a/spyderlib/images/editor/run_selection.png b/spyderlib/images/editor/run_selection.png
index be79ffd..4802f60 100644
Binary files a/spyderlib/images/editor/run_selection.png and b/spyderlib/images/editor/run_selection.png differ
diff --git a/spyderlib/images/editor/run_settings.png b/spyderlib/images/editor/run_settings.png
index a9ce293..aa9a6e4 100644
Binary files a/spyderlib/images/editor/run_settings.png and b/spyderlib/images/editor/run_settings.png differ
diff --git a/spyderlib/images/editor/select.png b/spyderlib/images/editor/select.png
index 01c304e..3d61f6e 100644
Binary files a/spyderlib/images/editor/select.png and b/spyderlib/images/editor/select.png differ
diff --git a/spyderlib/images/editor/selectall.png b/spyderlib/images/editor/selectall.png
index 3c63165..c280f08 100644
Binary files a/spyderlib/images/editor/selectall.png and b/spyderlib/images/editor/selectall.png differ
diff --git a/spyderlib/images/editor/todo.png b/spyderlib/images/editor/todo.png
index 53c23a0..7a4b26d 100644
Binary files a/spyderlib/images/editor/todo.png and b/spyderlib/images/editor/todo.png differ
diff --git a/spyderlib/images/editor/todo_list.png b/spyderlib/images/editor/todo_list.png
index 235dc23..e01a303 100644
Binary files a/spyderlib/images/editor/todo_list.png and b/spyderlib/images/editor/todo_list.png differ
diff --git a/spyderlib/images/editor/uncomment.png b/spyderlib/images/editor/uncomment.png
index 63ce7b4..4fb121e 100644
Binary files a/spyderlib/images/editor/uncomment.png and b/spyderlib/images/editor/uncomment.png differ
diff --git a/spyderlib/images/editor/unindent.png b/spyderlib/images/editor/unindent.png
index f9f8468..a367b3d 100644
Binary files a/spyderlib/images/editor/unindent.png and b/spyderlib/images/editor/unindent.png differ
diff --git a/spyderlib/images/editor/versplit.png b/spyderlib/images/editor/versplit.png
index f8d9c07..1695695 100644
Binary files a/spyderlib/images/editor/versplit.png and b/spyderlib/images/editor/versplit.png differ
diff --git a/spyderlib/images/editor/warning.png b/spyderlib/images/editor/warning.png
index 449cbdb..2aecaa3 100644
Binary files a/spyderlib/images/editor/warning.png and b/spyderlib/images/editor/warning.png differ
diff --git a/spyderlib/images/editor/wng_list.png b/spyderlib/images/editor/wng_list.png
index 06745bd..9a71d63 100644
Binary files a/spyderlib/images/editor/wng_list.png and b/spyderlib/images/editor/wng_list.png differ
diff --git a/spyderlib/images/eyedropper.png b/spyderlib/images/eyedropper.png
new file mode 100644
index 0000000..526b8fa
Binary files /dev/null and b/spyderlib/images/eyedropper.png differ
diff --git a/spyderlib/images/file/fileclose.png b/spyderlib/images/file/fileclose.png
index cad282b..a3a7ec1 100644
Binary files a/spyderlib/images/file/fileclose.png and b/spyderlib/images/file/fileclose.png differ
diff --git a/spyderlib/images/file/filecloseall.png b/spyderlib/images/file/filecloseall.png
index b76b0ff..b4d9155 100644
Binary files a/spyderlib/images/file/filecloseall.png and b/spyderlib/images/file/filecloseall.png differ
diff --git a/spyderlib/images/file/fileimport.png b/spyderlib/images/file/fileimport.png
index c93fad5..1fde5dd 100644
Binary files a/spyderlib/images/file/fileimport.png and b/spyderlib/images/file/fileimport.png differ
diff --git a/spyderlib/images/file/filenew.png b/spyderlib/images/file/filenew.png
index 93c2c22..e88f955 100644
Binary files a/spyderlib/images/file/filenew.png and b/spyderlib/images/file/filenew.png differ
diff --git a/spyderlib/images/file/fileopen.png b/spyderlib/images/file/fileopen.png
index f7a76e4..35f7f98 100644
Binary files a/spyderlib/images/file/fileopen.png and b/spyderlib/images/file/fileopen.png differ
diff --git a/spyderlib/images/file/filesave.png b/spyderlib/images/file/filesave.png
index fc92b29..29d1471 100644
Binary files a/spyderlib/images/file/filesave.png and b/spyderlib/images/file/filesave.png differ
diff --git a/spyderlib/images/file/filesaveas.png b/spyderlib/images/file/filesaveas.png
index dfeb87b..b3ad006 100644
Binary files a/spyderlib/images/file/filesaveas.png and b/spyderlib/images/file/filesaveas.png differ
diff --git a/spyderlib/images/file/print.png b/spyderlib/images/file/print.png
index 0389db2..679b9f2 100644
Binary files a/spyderlib/images/file/print.png and b/spyderlib/images/file/print.png differ
diff --git a/spyderlib/images/file/save_all.png b/spyderlib/images/file/save_all.png
index 0a452630..d23eb0f 100644
Binary files a/spyderlib/images/file/save_all.png and b/spyderlib/images/file/save_all.png differ
diff --git a/spyderlib/images/filetypes/bat.png b/spyderlib/images/filetypes/bat.png
index bfdc1ae..8566dcc 100644
Binary files a/spyderlib/images/filetypes/bat.png and b/spyderlib/images/filetypes/bat.png differ
diff --git a/spyderlib/images/filetypes/bmp.png b/spyderlib/images/filetypes/bmp.png
index 2136210..d837c18 100644
Binary files a/spyderlib/images/filetypes/bmp.png and b/spyderlib/images/filetypes/bmp.png differ
diff --git a/spyderlib/images/filetypes/c.png b/spyderlib/images/filetypes/c.png
index 96afdcd..a62d149 100644
Binary files a/spyderlib/images/filetypes/c.png and b/spyderlib/images/filetypes/c.png differ
diff --git a/spyderlib/images/filetypes/cc.png b/spyderlib/images/filetypes/cc.png
index b6a3ca6..beec3eb 100644
Binary files a/spyderlib/images/filetypes/cc.png and b/spyderlib/images/filetypes/cc.png differ
diff --git a/spyderlib/images/filetypes/cfg.png b/spyderlib/images/filetypes/cfg.png
index 992933b..f693913 100644
Binary files a/spyderlib/images/filetypes/cfg.png and b/spyderlib/images/filetypes/cfg.png differ
diff --git a/spyderlib/images/filetypes/chm.png b/spyderlib/images/filetypes/chm.png
index 3d6f320..e7969bc 100644
Binary files a/spyderlib/images/filetypes/chm.png and b/spyderlib/images/filetypes/chm.png differ
diff --git a/spyderlib/images/filetypes/cl.png b/spyderlib/images/filetypes/cl.png
index 70f1314..5c2e7ba 100644
Binary files a/spyderlib/images/filetypes/cl.png and b/spyderlib/images/filetypes/cl.png differ
diff --git a/spyderlib/images/filetypes/cmd.png b/spyderlib/images/filetypes/cmd.png
index bfdc1ae..8566dcc 100644
Binary files a/spyderlib/images/filetypes/cmd.png and b/spyderlib/images/filetypes/cmd.png differ
diff --git a/spyderlib/images/filetypes/cpp.png b/spyderlib/images/filetypes/cpp.png
index b6a3ca6..beec3eb 100644
Binary files a/spyderlib/images/filetypes/cpp.png and b/spyderlib/images/filetypes/cpp.png differ
diff --git a/spyderlib/images/filetypes/css.png b/spyderlib/images/filetypes/css.png
index 0c47094..b8de93f 100644
Binary files a/spyderlib/images/filetypes/css.png and b/spyderlib/images/filetypes/css.png differ
diff --git a/spyderlib/images/filetypes/cxx.png b/spyderlib/images/filetypes/cxx.png
index b6a3ca6..beec3eb 100644
Binary files a/spyderlib/images/filetypes/cxx.png and b/spyderlib/images/filetypes/cxx.png differ
diff --git a/spyderlib/images/filetypes/diff.png b/spyderlib/images/filetypes/diff.png
index 3512ee7..3d34cc9 100644
Binary files a/spyderlib/images/filetypes/diff.png and b/spyderlib/images/filetypes/diff.png differ
diff --git a/spyderlib/images/filetypes/doc.png b/spyderlib/images/filetypes/doc.png
index 18b31a4..270d71e 100644
Binary files a/spyderlib/images/filetypes/doc.png and b/spyderlib/images/filetypes/doc.png differ
diff --git a/spyderlib/images/filetypes/enaml.png b/spyderlib/images/filetypes/enaml.png
index 5afd8c2..7dd127d 100644
Binary files a/spyderlib/images/filetypes/enaml.png and b/spyderlib/images/filetypes/enaml.png differ
diff --git a/spyderlib/images/filetypes/exe.png b/spyderlib/images/filetypes/exe.png
index e92431b..321317c 100644
Binary files a/spyderlib/images/filetypes/exe.png and b/spyderlib/images/filetypes/exe.png differ
diff --git a/spyderlib/images/filetypes/f.png b/spyderlib/images/filetypes/f.png
index 636df7e..8c4cbfa 100644
Binary files a/spyderlib/images/filetypes/f.png and b/spyderlib/images/filetypes/f.png differ
diff --git a/spyderlib/images/filetypes/f77.png b/spyderlib/images/filetypes/f77.png
index 636df7e..8c4cbfa 100644
Binary files a/spyderlib/images/filetypes/f77.png and b/spyderlib/images/filetypes/f77.png differ
diff --git a/spyderlib/images/filetypes/f90.png b/spyderlib/images/filetypes/f90.png
index 636df7e..8c4cbfa 100644
Binary files a/spyderlib/images/filetypes/f90.png and b/spyderlib/images/filetypes/f90.png differ
diff --git a/spyderlib/images/filetypes/gif.png b/spyderlib/images/filetypes/gif.png
index 2136210..d837c18 100644
Binary files a/spyderlib/images/filetypes/gif.png and b/spyderlib/images/filetypes/gif.png differ
diff --git a/spyderlib/images/filetypes/h.png b/spyderlib/images/filetypes/h.png
index e9a0d91..dc03421 100644
Binary files a/spyderlib/images/filetypes/h.png and b/spyderlib/images/filetypes/h.png differ
diff --git a/spyderlib/images/filetypes/hh.png b/spyderlib/images/filetypes/hh.png
index b6a3ca6..beec3eb 100644
Binary files a/spyderlib/images/filetypes/hh.png and b/spyderlib/images/filetypes/hh.png differ
diff --git a/spyderlib/images/filetypes/hpp.png b/spyderlib/images/filetypes/hpp.png
index b6a3ca6..beec3eb 100644
Binary files a/spyderlib/images/filetypes/hpp.png and b/spyderlib/images/filetypes/hpp.png differ
diff --git a/spyderlib/images/filetypes/htm.png b/spyderlib/images/filetypes/htm.png
index b3e81a6..7e6cd49 100644
Binary files a/spyderlib/images/filetypes/htm.png and b/spyderlib/images/filetypes/htm.png differ
diff --git a/spyderlib/images/filetypes/html.png b/spyderlib/images/filetypes/html.png
index a229a76..51f5859 100644
Binary files a/spyderlib/images/filetypes/html.png and b/spyderlib/images/filetypes/html.png differ
diff --git a/spyderlib/images/filetypes/hxx.png b/spyderlib/images/filetypes/hxx.png
index b6a3ca6..beec3eb 100644
Binary files a/spyderlib/images/filetypes/hxx.png and b/spyderlib/images/filetypes/hxx.png differ
diff --git a/spyderlib/images/filetypes/inf.png b/spyderlib/images/filetypes/inf.png
index 992933b..f693913 100644
Binary files a/spyderlib/images/filetypes/inf.png and b/spyderlib/images/filetypes/inf.png differ
diff --git a/spyderlib/images/filetypes/ini.png b/spyderlib/images/filetypes/ini.png
index 992933b..f693913 100644
Binary files a/spyderlib/images/filetypes/ini.png and b/spyderlib/images/filetypes/ini.png differ
diff --git a/spyderlib/images/filetypes/jl.png b/spyderlib/images/filetypes/jl.png
index 611e572..c9488ad 100644
Binary files a/spyderlib/images/filetypes/jl.png and b/spyderlib/images/filetypes/jl.png differ
diff --git a/spyderlib/images/filetypes/jpeg.png b/spyderlib/images/filetypes/jpeg.png
index 2136210..d837c18 100644
Binary files a/spyderlib/images/filetypes/jpeg.png and b/spyderlib/images/filetypes/jpeg.png differ
diff --git a/spyderlib/images/filetypes/jpg.png b/spyderlib/images/filetypes/jpg.png
index 2136210..d837c18 100644
Binary files a/spyderlib/images/filetypes/jpg.png and b/spyderlib/images/filetypes/jpg.png differ
diff --git a/spyderlib/images/filetypes/js.png b/spyderlib/images/filetypes/js.png
index b3e81a6..7e6cd49 100644
Binary files a/spyderlib/images/filetypes/js.png and b/spyderlib/images/filetypes/js.png differ
diff --git a/spyderlib/images/filetypes/log.png b/spyderlib/images/filetypes/log.png
index bb6b165..f272ccf 100644
Binary files a/spyderlib/images/filetypes/log.png and b/spyderlib/images/filetypes/log.png differ
diff --git a/spyderlib/images/filetypes/nsh.png b/spyderlib/images/filetypes/nsh.png
index 3b7869d..8667b2c 100644
Binary files a/spyderlib/images/filetypes/nsh.png and b/spyderlib/images/filetypes/nsh.png differ
diff --git a/spyderlib/images/filetypes/nsi.png b/spyderlib/images/filetypes/nsi.png
index 3b7869d..8667b2c 100644
Binary files a/spyderlib/images/filetypes/nsi.png and b/spyderlib/images/filetypes/nsi.png differ
diff --git a/spyderlib/images/filetypes/nt.png b/spyderlib/images/filetypes/nt.png
index bfdc1ae..8566dcc 100644
Binary files a/spyderlib/images/filetypes/nt.png and b/spyderlib/images/filetypes/nt.png differ
diff --git a/spyderlib/images/filetypes/patch.png b/spyderlib/images/filetypes/patch.png
index 3512ee7..3d34cc9 100644
Binary files a/spyderlib/images/filetypes/patch.png and b/spyderlib/images/filetypes/patch.png differ
diff --git a/spyderlib/images/filetypes/pdf.png b/spyderlib/images/filetypes/pdf.png
index aa57e1d..2011768 100644
Binary files a/spyderlib/images/filetypes/pdf.png and b/spyderlib/images/filetypes/pdf.png differ
diff --git a/spyderlib/images/filetypes/png.png b/spyderlib/images/filetypes/png.png
index 2136210..d837c18 100644
Binary files a/spyderlib/images/filetypes/png.png and b/spyderlib/images/filetypes/png.png differ
diff --git a/spyderlib/images/filetypes/po.png b/spyderlib/images/filetypes/po.png
index 968088a..658177b 100644
Binary files a/spyderlib/images/filetypes/po.png and b/spyderlib/images/filetypes/po.png differ
diff --git a/spyderlib/images/filetypes/pot.png b/spyderlib/images/filetypes/pot.png
index c5d44d1..11a16be 100644
Binary files a/spyderlib/images/filetypes/pot.png and b/spyderlib/images/filetypes/pot.png differ
diff --git a/spyderlib/images/filetypes/pps.png b/spyderlib/images/filetypes/pps.png
index d27ddc8..4c6447f 100644
Binary files a/spyderlib/images/filetypes/pps.png and b/spyderlib/images/filetypes/pps.png differ
diff --git a/spyderlib/images/filetypes/properties.png b/spyderlib/images/filetypes/properties.png
index 992933b..f693913 100644
Binary files a/spyderlib/images/filetypes/properties.png and b/spyderlib/images/filetypes/properties.png differ
diff --git a/spyderlib/images/filetypes/ps.png b/spyderlib/images/filetypes/ps.png
index 653d85b..ba03df2 100644
Binary files a/spyderlib/images/filetypes/ps.png and b/spyderlib/images/filetypes/ps.png differ
diff --git a/spyderlib/images/filetypes/pxd.png b/spyderlib/images/filetypes/pxd.png
index a7b874e..873eee2 100644
Binary files a/spyderlib/images/filetypes/pxd.png and b/spyderlib/images/filetypes/pxd.png differ
diff --git a/spyderlib/images/filetypes/pxi.png b/spyderlib/images/filetypes/pxi.png
index a7b874e..873eee2 100644
Binary files a/spyderlib/images/filetypes/pxi.png and b/spyderlib/images/filetypes/pxi.png differ
diff --git a/spyderlib/images/filetypes/py.png b/spyderlib/images/filetypes/py.png
index b790495..52cc99f 100644
Binary files a/spyderlib/images/filetypes/py.png and b/spyderlib/images/filetypes/py.png differ
diff --git a/spyderlib/images/filetypes/pyc.png b/spyderlib/images/filetypes/pyc.png
index 57767db..3de80d7 100644
Binary files a/spyderlib/images/filetypes/pyc.png and b/spyderlib/images/filetypes/pyc.png differ
diff --git a/spyderlib/images/filetypes/pyw.png b/spyderlib/images/filetypes/pyw.png
index b790495..52cc99f 100644
Binary files a/spyderlib/images/filetypes/pyw.png and b/spyderlib/images/filetypes/pyw.png differ
diff --git a/spyderlib/images/filetypes/pyx.png b/spyderlib/images/filetypes/pyx.png
index a7b874e..873eee2 100644
Binary files a/spyderlib/images/filetypes/pyx.png and b/spyderlib/images/filetypes/pyx.png differ
diff --git a/spyderlib/images/filetypes/rar.png b/spyderlib/images/filetypes/rar.png
index 27b7408..9bf3a0e 100644
Binary files a/spyderlib/images/filetypes/rar.png and b/spyderlib/images/filetypes/rar.png differ
diff --git a/spyderlib/images/filetypes/readme.png b/spyderlib/images/filetypes/readme.png
index 47e1c1a..5fd8404 100644
Binary files a/spyderlib/images/filetypes/readme.png and b/spyderlib/images/filetypes/readme.png differ
diff --git a/spyderlib/images/filetypes/reg.png b/spyderlib/images/filetypes/reg.png
index 992933b..f693913 100644
Binary files a/spyderlib/images/filetypes/reg.png and b/spyderlib/images/filetypes/reg.png differ
diff --git a/spyderlib/images/filetypes/rej.png b/spyderlib/images/filetypes/rej.png
index 3512ee7..3d34cc9 100644
Binary files a/spyderlib/images/filetypes/rej.png and b/spyderlib/images/filetypes/rej.png differ
diff --git a/spyderlib/images/filetypes/scss.png b/spyderlib/images/filetypes/scss.png
new file mode 100644
index 0000000..b8de93f
Binary files /dev/null and b/spyderlib/images/filetypes/scss.png differ
diff --git a/spyderlib/images/filetypes/session.png b/spyderlib/images/filetypes/session.png
index 992933b..f693913 100644
Binary files a/spyderlib/images/filetypes/session.png and b/spyderlib/images/filetypes/session.png differ
diff --git a/spyderlib/images/filetypes/tar.png b/spyderlib/images/filetypes/tar.png
index 27b7408..9bf3a0e 100644
Binary files a/spyderlib/images/filetypes/tar.png and b/spyderlib/images/filetypes/tar.png differ
diff --git a/spyderlib/images/filetypes/tex.png b/spyderlib/images/filetypes/tex.png
index 7fc8ba4..07057d8 100644
Binary files a/spyderlib/images/filetypes/tex.png and b/spyderlib/images/filetypes/tex.png differ
diff --git a/spyderlib/images/filetypes/tgz.png b/spyderlib/images/filetypes/tgz.png
index 27b7408..9bf3a0e 100644
Binary files a/spyderlib/images/filetypes/tgz.png and b/spyderlib/images/filetypes/tgz.png differ
diff --git a/spyderlib/images/filetypes/tif.png b/spyderlib/images/filetypes/tif.png
index 2136210..d837c18 100644
Binary files a/spyderlib/images/filetypes/tif.png and b/spyderlib/images/filetypes/tif.png differ
diff --git a/spyderlib/images/filetypes/tiff.png b/spyderlib/images/filetypes/tiff.png
index 2136210..d837c18 100644
Binary files a/spyderlib/images/filetypes/tiff.png and b/spyderlib/images/filetypes/tiff.png differ
diff --git a/spyderlib/images/filetypes/ts.png b/spyderlib/images/filetypes/ts.png
index 4384030..0afa93b 100644
Binary files a/spyderlib/images/filetypes/ts.png and b/spyderlib/images/filetypes/ts.png differ
diff --git a/spyderlib/images/filetypes/txt.png b/spyderlib/images/filetypes/txt.png
index a7fbac4..1aff38c 100644
Binary files a/spyderlib/images/filetypes/txt.png and b/spyderlib/images/filetypes/txt.png differ
diff --git a/spyderlib/images/filetypes/ui.png b/spyderlib/images/filetypes/ui.png
index b222a34..0727cf8 100644
Binary files a/spyderlib/images/filetypes/ui.png and b/spyderlib/images/filetypes/ui.png differ
diff --git a/spyderlib/images/filetypes/xls.png b/spyderlib/images/filetypes/xls.png
index 42bad74..1152393 100644
Binary files a/spyderlib/images/filetypes/xls.png and b/spyderlib/images/filetypes/xls.png differ
diff --git a/spyderlib/images/filetypes/xml.png b/spyderlib/images/filetypes/xml.png
index b026913..e8ce467 100644
Binary files a/spyderlib/images/filetypes/xml.png and b/spyderlib/images/filetypes/xml.png differ
diff --git a/spyderlib/images/filetypes/zip.png b/spyderlib/images/filetypes/zip.png
index 27b7408..9bf3a0e 100644
Binary files a/spyderlib/images/filetypes/zip.png and b/spyderlib/images/filetypes/zip.png differ
diff --git a/spyderlib/images/font.png b/spyderlib/images/font.png
index 4ca74e0..4ad8670 100644
Binary files a/spyderlib/images/font.png and b/spyderlib/images/font.png differ
diff --git a/spyderlib/images/genprefs.png b/spyderlib/images/genprefs.png
index 118bb5c..526b8fa 100644
Binary files a/spyderlib/images/genprefs.png and b/spyderlib/images/genprefs.png differ
diff --git a/spyderlib/images/inspector.png b/spyderlib/images/inspector.png
index 19e2be9..939918e 100644
Binary files a/spyderlib/images/inspector.png and b/spyderlib/images/inspector.png differ
diff --git a/spyderlib/images/italic.png b/spyderlib/images/italic.png
index 1ae4619..31eef84 100644
Binary files a/spyderlib/images/italic.png and b/spyderlib/images/italic.png differ
diff --git a/spyderlib/images/keyboard.png b/spyderlib/images/keyboard.png
new file mode 100644
index 0000000..526b8fa
Binary files /dev/null and b/spyderlib/images/keyboard.png differ
diff --git a/spyderlib/images/matplotlib.png b/spyderlib/images/matplotlib.png
index e763772..dfaa93f 100644
Binary files a/spyderlib/images/matplotlib.png and b/spyderlib/images/matplotlib.png differ
diff --git a/spyderlib/images/none.png b/spyderlib/images/none.png
index 017d4f9..ecf17ca 100644
Binary files a/spyderlib/images/none.png and b/spyderlib/images/none.png differ
diff --git a/spyderlib/images/not_found.png b/spyderlib/images/not_found.png
index 8125a4d..f2b17f7 100644
Binary files a/spyderlib/images/not_found.png and b/spyderlib/images/not_found.png differ
diff --git a/spyderlib/images/projects/add_to_path.png b/spyderlib/images/projects/add_to_path.png
index 97b2f01..2f3d594 100644
Binary files a/spyderlib/images/projects/add_to_path.png and b/spyderlib/images/projects/add_to_path.png differ
diff --git a/spyderlib/images/projects/folder.png b/spyderlib/images/projects/folder.png
index a37f751..a9467c0 100644
Binary files a/spyderlib/images/projects/folder.png and b/spyderlib/images/projects/folder.png differ
diff --git a/spyderlib/images/projects/package.png b/spyderlib/images/projects/package.png
index d0b85e0..67627bc 100644
Binary files a/spyderlib/images/projects/package.png and b/spyderlib/images/projects/package.png differ
diff --git a/spyderlib/images/projects/pp_folder.png b/spyderlib/images/projects/pp_folder.png
index 6d86b89..7206aa4 100644
Binary files a/spyderlib/images/projects/pp_folder.png and b/spyderlib/images/projects/pp_folder.png differ
diff --git a/spyderlib/images/projects/pp_package.png b/spyderlib/images/projects/pp_package.png
index 00acf3d..3df48a6 100644
Binary files a/spyderlib/images/projects/pp_package.png and b/spyderlib/images/projects/pp_package.png differ
diff --git a/spyderlib/images/projects/pp_project.png b/spyderlib/images/projects/pp_project.png
index 8e85fd5..e5eb566 100644
Binary files a/spyderlib/images/projects/pp_project.png and b/spyderlib/images/projects/pp_project.png differ
diff --git a/spyderlib/images/projects/project.png b/spyderlib/images/projects/project.png
index f5c44a3..f906996 100644
Binary files a/spyderlib/images/projects/project.png and b/spyderlib/images/projects/project.png differ
diff --git a/spyderlib/images/projects/project_closed.png b/spyderlib/images/projects/project_closed.png
index b6c4c32..1044cd5 100644
Binary files a/spyderlib/images/projects/project_closed.png and b/spyderlib/images/projects/project_closed.png differ
diff --git a/spyderlib/images/projects/pydev.png b/spyderlib/images/projects/pydev.png
index 9ab5691..3fcc782 100644
Binary files a/spyderlib/images/projects/pydev.png and b/spyderlib/images/projects/pydev.png differ
diff --git a/spyderlib/images/projects/pythonpath.png b/spyderlib/images/projects/pythonpath.png
index e1f4667..95b8a14 100644
Binary files a/spyderlib/images/projects/pythonpath.png and b/spyderlib/images/projects/pythonpath.png differ
diff --git a/spyderlib/images/projects/remove_from_path.png b/spyderlib/images/projects/remove_from_path.png
index 803070b..eb241d5 100644
Binary files a/spyderlib/images/projects/remove_from_path.png and b/spyderlib/images/projects/remove_from_path.png differ
diff --git a/spyderlib/images/projects/show_all.png b/spyderlib/images/projects/show_all.png
index 8a1d453..1acf62b 100644
Binary files a/spyderlib/images/projects/show_all.png and b/spyderlib/images/projects/show_all.png differ
diff --git a/spyderlib/images/pythonpath_mgr.png b/spyderlib/images/pythonpath.png
similarity index 67%
rename from spyderlib/images/pythonpath_mgr.png
rename to spyderlib/images/pythonpath.png
index c5b4c8c..da88873 100644
Binary files a/spyderlib/images/pythonpath_mgr.png and b/spyderlib/images/pythonpath.png differ
diff --git a/spyderlib/images/pythonxy.png b/spyderlib/images/pythonxy.png
index 05d9c14..dbd1dc0 100644
Binary files a/spyderlib/images/pythonxy.png and b/spyderlib/images/pythonxy.png differ
diff --git a/spyderlib/images/qt.png b/spyderlib/images/qt.png
index 55afdd8..ce0e72d 100644
Binary files a/spyderlib/images/qt.png and b/spyderlib/images/qt.png differ
diff --git a/spyderlib/images/qtassistant.png b/spyderlib/images/qtassistant.png
index a448169..19cec5e 100644
Binary files a/spyderlib/images/qtassistant.png and b/spyderlib/images/qtassistant.png differ
diff --git a/spyderlib/images/qtdesigner.png b/spyderlib/images/qtdesigner.png
index abd8bea..802fdb1 100644
Binary files a/spyderlib/images/qtdesigner.png and b/spyderlib/images/qtdesigner.png differ
diff --git a/spyderlib/images/qtlinguist.png b/spyderlib/images/qtlinguist.png
index 40e1f47..073c906 100644
Binary files a/spyderlib/images/qtlinguist.png and b/spyderlib/images/qtlinguist.png differ
diff --git a/spyderlib/images/scipy.png b/spyderlib/images/scipy.png
index 4944d97..0d829e3 100644
Binary files a/spyderlib/images/scipy.png and b/spyderlib/images/scipy.png differ
diff --git a/spyderlib/images/set_workdir.png b/spyderlib/images/set_workdir.png
index f72a84a..ad3fd4a 100644
Binary files a/spyderlib/images/set_workdir.png and b/spyderlib/images/set_workdir.png differ
diff --git a/spyderlib/images/splash.png b/spyderlib/images/splash.png
index 9462167..f21c390 100644
Binary files a/spyderlib/images/splash.png and b/spyderlib/images/splash.png differ
diff --git a/spyderlib/images/spyder.png b/spyderlib/images/spyder.png
new file mode 100644
index 0000000..63602ce
Binary files /dev/null and b/spyderlib/images/spyder.png differ
diff --git a/spyderlib/images/tour-spyder-logo.png b/spyderlib/images/tour-spyder-logo.png
new file mode 100644
index 0000000..7de5dc2
Binary files /dev/null and b/spyderlib/images/tour-spyder-logo.png differ
diff --git a/spyderlib/images/upper_lower.png b/spyderlib/images/upper_lower.png
index 2e2c586..f36c99b 100644
Binary files a/spyderlib/images/upper_lower.png and b/spyderlib/images/upper_lower.png differ
diff --git a/spyderlib/images/vcs_browse.png b/spyderlib/images/vcs_browse.png
index 06c806c..f1b9076 100644
Binary files a/spyderlib/images/vcs_browse.png and b/spyderlib/images/vcs_browse.png differ
diff --git a/spyderlib/images/vcs_commit.png b/spyderlib/images/vcs_commit.png
index d2216c4..dbecb4e 100644
Binary files a/spyderlib/images/vcs_commit.png and b/spyderlib/images/vcs_commit.png differ
diff --git a/spyderlib/images/vitables.png b/spyderlib/images/vitables.png
index 6188381..c31674f 100644
Binary files a/spyderlib/images/vitables.png and b/spyderlib/images/vitables.png differ
diff --git a/spyderlib/images/whole_words.png b/spyderlib/images/whole_words.png
index 231d6ea..3d39320 100644
Binary files a/spyderlib/images/whole_words.png and b/spyderlib/images/whole_words.png differ
diff --git a/spyderlib/images/win_env.png b/spyderlib/images/win_env.png
index 72f4546..76d925f 100644
Binary files a/spyderlib/images/win_env.png and b/spyderlib/images/win_env.png differ
diff --git a/spyderlib/locale/es/LC_MESSAGES/spyderlib.mo b/spyderlib/locale/es/LC_MESSAGES/spyderlib.mo
index 66efe83..753e6e4 100644
Binary files a/spyderlib/locale/es/LC_MESSAGES/spyderlib.mo and b/spyderlib/locale/es/LC_MESSAGES/spyderlib.mo differ
diff --git a/spyderlib/locale/es/LC_MESSAGES/spyderlib.po b/spyderlib/locale/es/LC_MESSAGES/spyderlib.po
index 9446efd..be6222d 100644
--- a/spyderlib/locale/es/LC_MESSAGES/spyderlib.po
+++ b/spyderlib/locale/es/LC_MESSAGES/spyderlib.po
@@ -5,7 +5,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: 2.1\n"
-"POT-Creation-Date: 2015-11-24 20:56+COT\n"
+"POT-Creation-Date: 2015-08-29 22:49+COT\n"
 "PO-Revision-Date: 2015-08-24 15:13-0500\n"
 "Last-Translator: Carlos Cordoba <ccordoba12 at gmail.com>\n"
 "Language-Team: Python\n"
@@ -18,184 +18,219 @@ msgstr ""
 "X-Poedit-Basepath: ../../../../\n"
 "X-Generator: Poedit 1.5.4\n"
 
-#: spyderlib/config.py:29
+#: spyderlib/config/base.py:241
+msgid ""
+"Update LANGUAGE_CODES (inside config/base.py) if a new translation has been "
+"added to Spyder"
+msgstr ""
+
+#: spyderlib/config/ipython.py:23 spyderlib/config/ipython.py:25
+#: spyderlib/config/ipython.py:32
+msgid "IPython Console integration"
+msgstr "Integración con la terminal de IPython"
+
+#: spyderlib/config/main.py:29
 msgid "Python files"
 msgstr "Archivos Python"
 
-#: spyderlib/config.py:30
+#: spyderlib/config/main.py:30
 msgid "Cython/Pyrex files"
 msgstr "Archivos Cython/Pyrex"
 
-#: spyderlib/config.py:31
+#: spyderlib/config/main.py:31
 msgid "C files"
 msgstr "Archivos C"
 
-#: spyderlib/config.py:32
+#: spyderlib/config/main.py:32
 msgid "C++ files"
 msgstr "Archivos C++"
 
-#: spyderlib/config.py:33
+#: spyderlib/config/main.py:33
 msgid "OpenCL files"
 msgstr "Archivos OpenCL"
 
-#: spyderlib/config.py:34
+#: spyderlib/config/main.py:34
 msgid "Fortran files"
 msgstr "Archivos Fortran"
 
-#: spyderlib/config.py:35
+#: spyderlib/config/main.py:35
 msgid "IDL files"
 msgstr "Archivos IDL"
 
-#: spyderlib/config.py:36
+#: spyderlib/config/main.py:36
 msgid "MATLAB files"
 msgstr "Archivos MATLAB"
 
-#: spyderlib/config.py:37
+#: spyderlib/config/main.py:37
 msgid "Julia files"
 msgstr "Archivos Julia"
 
-#: spyderlib/config.py:38
+#: spyderlib/config/main.py:38
 msgid "Yaml files"
 msgstr "Archivos Yaml"
 
-#: spyderlib/config.py:39
+#: spyderlib/config/main.py:39
 msgid "Patch and diff files"
 msgstr "Archivos Patch y diff"
 
-#: spyderlib/config.py:40
+#: spyderlib/config/main.py:40
 msgid "Batch files"
 msgstr "Archivos Batch"
 
-#: spyderlib/config.py:41 spyderlib/utils/iofuncs.py:514
+#: spyderlib/config/main.py:41 spyderlib/utils/iofuncs.py:500
 msgid "Text files"
 msgstr "Archivos de Texto"
 
-#: spyderlib/config.py:42
+#: spyderlib/config/main.py:42
 msgid "reStructured Text files"
 msgstr "Archivos de Texto reStructurado"
 
-#: spyderlib/config.py:43
+#: spyderlib/config/main.py:43
 msgid "gettext files"
 msgstr "Archivos gettext"
 
-#: spyderlib/config.py:44
+#: spyderlib/config/main.py:44
 msgid "NSIS files"
 msgstr "Archivos NSIS"
 
-#: spyderlib/config.py:45
+#: spyderlib/config/main.py:45
 msgid "Web page files"
 msgstr "Archivos de Páginas web"
 
-#: spyderlib/config.py:46
+#: spyderlib/config/main.py:46
 msgid "XML files"
 msgstr "Archivos XML"
 
-#: spyderlib/config.py:47
+#: spyderlib/config/main.py:47
 msgid "Javascript files"
 msgstr "Archivos Javascript"
 
-#: spyderlib/config.py:48
+#: spyderlib/config/main.py:48
 msgid "Json files"
 msgstr "Archivos Json"
 
-#: spyderlib/config.py:49
+#: spyderlib/config/main.py:49
 msgid "IPython notebooks"
 msgstr "Notebooks de IPython"
 
-#: spyderlib/config.py:50
+#: spyderlib/config/main.py:50
 msgid "Enaml files"
 msgstr "Archivos Enaml"
 
-#: spyderlib/config.py:51
+#: spyderlib/config/main.py:51
 msgid "Configuration files"
 msgstr "Archivos de Configuración"
 
-#: spyderlib/config.py:58 spyderlib/widgets/explorer.py:651
+#: spyderlib/config/main.py:58 spyderlib/widgets/explorer.py:660
 msgid "All files"
 msgstr "Todos los archivos"
 
-#: spyderlib/ipythonconfig.py:23 spyderlib/ipythonconfig.py:25
-#: spyderlib/ipythonconfig.py:32
-msgid "IPython Console integration"
-msgstr "Integración con la terminal de IPython"
-
-#: spyderlib/plugins/__init__.py:318 spyderlib/plugins/editor.py:94
-#: spyderlib/plugins/editor.py:527 spyderlib/plugins/editor.py:1606
-#: spyderlib/plugins/inspector.py:134 spyderlib/plugins/inspector.py:403
-#: spyderlib/widgets/editor.py:434
-#: spyderlib/widgets/sourcecode/codeeditor.py:85
-#: spyderlib/widgets/sourcecode/codeeditor.py:2709
+#: spyderlib/plugins/__init__.py:513 spyderlib/plugins/editor.py:95
+#: spyderlib/plugins/editor.py:551 spyderlib/plugins/editor.py:1600
+#: spyderlib/plugins/inspector.py:139 spyderlib/plugins/inspector.py:419
+#: spyderlib/widgets/editor.py:357
+#: spyderlib/widgets/sourcecode/codeeditor.py:95
+#: spyderlib/widgets/sourcecode/codeeditor.py:2902
 msgid "Editor"
 msgstr "Editor"
 
-#: spyderlib/plugins/configdialog.py:144
+#: spyderlib/plugins/configdialog.py:133
+#, fuzzy
+msgid "Reset to defaults"
+msgstr "Restaurar los valores por defecto"
+
+#: spyderlib/plugins/configdialog.py:145
 msgid "Preferences"
 msgstr "Preferencias"
 
-#: spyderlib/plugins/configdialog.py:429
+#: spyderlib/plugins/configdialog.py:473
 msgid "Invalid directory path"
 msgstr "Ruta de directorio inválida"
 
-#: spyderlib/plugins/configdialog.py:432 spyderlib/plugins/configdialog.py:448
-#: spyderlib/plugins/runconfig.py:172 spyderlib/plugins/runconfig.py:236
-#: spyderlib/plugins/workingdirectory.py:286 spyderlib/widgets/explorer.py:565
-#: spyderlib/widgets/externalshell/pythonshell.py:623
-#: spyderlib/widgets/findinfiles.py:504 spyderlib/widgets/pathmanager.py:218
-#: spyderlib/widgets/projectexplorer.py:890
+#: spyderlib/plugins/configdialog.py:476 spyderlib/plugins/configdialog.py:491
+#: spyderlib/plugins/runconfig.py:176 spyderlib/plugins/runconfig.py:240
+#: spyderlib/plugins/workingdirectory.py:295 spyderlib/widgets/explorer.py:574
+#: spyderlib/widgets/externalshell/pythonshell.py:640
+#: spyderlib/widgets/findinfiles.py:505 spyderlib/widgets/pathmanager.py:223
+#: spyderlib/widgets/projectexplorer.py:899
 msgid "Select directory"
 msgstr "Seleccionar directorio"
 
-#: spyderlib/plugins/configdialog.py:460
+#: spyderlib/plugins/configdialog.py:503
 msgid "Invalid file path"
 msgstr "Ruta de archivo inválida"
 
-#: spyderlib/plugins/configdialog.py:463 spyderlib/plugins/configdialog.py:481
+#: spyderlib/plugins/configdialog.py:506 spyderlib/plugins/configdialog.py:523
 msgid "Select file"
 msgstr "Seleccionar archivo"
 
-#: spyderlib/plugins/configdialog.py:480
+#: spyderlib/plugins/configdialog.py:522
 msgid "All files (*)"
 msgstr "Todos los archivos (*)"
 
-#: spyderlib/plugins/configdialog.py:550 spyderlib/widgets/formlayout.py:216
+#: spyderlib/plugins/configdialog.py:595 spyderlib/widgets/formlayout.py:214
 msgid "Bold"
 msgstr "Negrita"
 
-#: spyderlib/plugins/configdialog.py:553 spyderlib/widgets/formlayout.py:211
+#: spyderlib/plugins/configdialog.py:598 spyderlib/widgets/formlayout.py:209
 msgid "Italic"
 msgstr "Cursiva"
 
-#: spyderlib/plugins/configdialog.py:591
+#: spyderlib/plugins/configdialog.py:640
 msgid "Font: "
 msgstr "Tipo de letra"
 
-#: spyderlib/plugins/configdialog.py:595
+#: spyderlib/plugins/configdialog.py:644
 msgid "Size: "
 msgstr "Tamaño:"
 
-#: spyderlib/plugins/configdialog.py:604 spyderlib/plugins/history.py:47
+#: spyderlib/plugins/configdialog.py:653 spyderlib/plugins/history.py:48
 msgid "Font style"
 msgstr "Fuente"
 
-#: spyderlib/plugins/configdialog.py:657
+#: spyderlib/plugins/configdialog.py:708
+msgid "Spyder needs to restart to change the following setting:"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:711
+msgid "Spyder needs to restart to change the following settings:"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:713
+msgid "Do you wish to restart now?"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:719
+msgid "Information"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:734
 msgid "General"
 msgstr "General"
 
-#: spyderlib/plugins/configdialog.py:664 spyderlib/plugins/editor.py:103
-#: spyderlib/plugins/externalconsole.py:65
-#: spyderlib/plugins/ipythonconsole.py:161
+#: spyderlib/plugins/configdialog.py:741 spyderlib/plugins/editor.py:104
+#: spyderlib/plugins/externalconsole.py:67
+#: spyderlib/plugins/ipythonconsole.py:162
 msgid "Interface"
 msgstr "Interfaz"
 
-#: spyderlib/plugins/configdialog.py:672
+#: spyderlib/plugins/configdialog.py:744
 msgid "Qt windows style"
 msgstr "Estilo de Qt"
 
-#: spyderlib/plugins/configdialog.py:676
+#: spyderlib/plugins/configdialog.py:750
+msgid "Icon theme"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:755
+msgid "Language"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:759
 msgid "Use a single instance"
 msgstr "Utilizar una única instancia"
 
-#: spyderlib/plugins/configdialog.py:678
+#: spyderlib/plugins/configdialog.py:761
 msgid ""
 "Set this to open external<br> Python files in an already running instance "
 "(Requires a restart)"
@@ -203,339 +238,358 @@ msgstr ""
 "Seleccione esta opción<br> para abrir archivos externos de Python en la "
 "ventana actual (Requiere reiniciar)"
 
-#: spyderlib/plugins/configdialog.py:681
-msgid "Vertical dockwidget title bars"
+#: spyderlib/plugins/configdialog.py:764
+#, fuzzy
+msgid "Vertical title bars in panes"
 msgstr "Barras de título verticales para los componentes"
 
-#: spyderlib/plugins/configdialog.py:683
-msgid "Vertical dockwidget tabs"
-msgstr "Componentes en pestañas verticales"
+#: spyderlib/plugins/configdialog.py:766
+msgid "Vertical tabs in panes"
+msgstr ""
 
-#: spyderlib/plugins/configdialog.py:685
-msgid "Animated toolbars and dockwidgets"
+#: spyderlib/plugins/configdialog.py:768
+#, fuzzy
+msgid "Animated toolbars and panes"
 msgstr "Barras de herramientas y componentes animados"
 
-#: spyderlib/plugins/configdialog.py:687
+#: spyderlib/plugins/configdialog.py:770
 msgid "Tear off menus"
 msgstr "Separar los menús"
 
-#: spyderlib/plugins/configdialog.py:688
+#: spyderlib/plugins/configdialog.py:771
 msgid "Set this to detach any<br> menu from the main window"
 msgstr ""
 "Establezca esta opción<br> si desea separar los menús de la ventana principal"
 
-#: spyderlib/plugins/configdialog.py:690
-msgid "Custom dockwidget margin:"
-msgstr "Márgenes de componente personalizadas:"
+#: spyderlib/plugins/configdialog.py:773
+msgid "Custom margin for panes:"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:782
+msgid "Prompt when exiting"
+msgstr ""
 
-#: spyderlib/plugins/configdialog.py:717
+#: spyderlib/plugins/configdialog.py:813
 msgid "Status bar"
 msgstr "Barra de estado"
 
-#: spyderlib/plugins/configdialog.py:718
+#: spyderlib/plugins/configdialog.py:814
+#, fuzzy
+msgid "Show status bar"
+msgstr "Mostrar barra de pestañas"
+
+#: spyderlib/plugins/configdialog.py:816
 msgid "Show memory usage every"
 msgstr "Mostrar la memoria usada cada"
 
-#: spyderlib/plugins/configdialog.py:729
+#: spyderlib/plugins/configdialog.py:825
 msgid "Show CPU usage every"
 msgstr "Mostrar el uso de CPU cada"
 
-#: spyderlib/plugins/configdialog.py:746
+#: spyderlib/plugins/configdialog.py:858
 msgid "Debugging"
 msgstr "Depurar"
 
-#: spyderlib/plugins/configdialog.py:747
+#: spyderlib/plugins/configdialog.py:859
 msgid "Pop up internal console when internal errors appear"
 msgstr "Mostrar la terminal interna cuando se produzcan errores"
 
-#: spyderlib/plugins/configdialog.py:769
+#: spyderlib/plugins/configdialog.py:868
+msgid "Updates"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:869 spyderlib/spyder.py:2872
+msgid "Check for updates on startup"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:902
 msgid "Syntax coloring"
 msgstr "Coloreado de sintaxis"
 
-#: spyderlib/plugins/configdialog.py:778
+#: spyderlib/plugins/configdialog.py:911
 msgid "Background:"
 msgstr "Fondo:"
 
-#: spyderlib/plugins/configdialog.py:779
-#: spyderlib/widgets/sourcecode/codeeditor.py:95
+#: spyderlib/plugins/configdialog.py:912
+#: spyderlib/widgets/sourcecode/codeeditor.py:104
 msgid "Current line:"
 msgstr "Línea seleccionada:"
 
-#: spyderlib/plugins/configdialog.py:780
+#: spyderlib/plugins/configdialog.py:913
 msgid "Current cell:"
 msgstr "Celda seleccionada:"
 
-#: spyderlib/plugins/configdialog.py:781
+#: spyderlib/plugins/configdialog.py:914
 msgid "Occurence:"
 msgstr "Ocurrencia:"
 
-#: spyderlib/plugins/configdialog.py:782
+#: spyderlib/plugins/configdialog.py:915
 msgid "Link:"
 msgstr "Enlace:"
 
-#: spyderlib/plugins/configdialog.py:783
+#: spyderlib/plugins/configdialog.py:916
 msgid "Side areas:"
 msgstr "Áreas laterales:"
 
-#: spyderlib/plugins/configdialog.py:784
+#: spyderlib/plugins/configdialog.py:917
 msgid "Matched parentheses:"
 msgstr "Paréntesis emparejados:"
 
-#: spyderlib/plugins/configdialog.py:785
+#: spyderlib/plugins/configdialog.py:918
 msgid "Unmatched parentheses:"
 msgstr "Paréntesis desemparejados:"
 
-#: spyderlib/plugins/configdialog.py:786
+#: spyderlib/plugins/configdialog.py:919
 msgid "Normal text:"
 msgstr "Texto normal:"
 
-#: spyderlib/plugins/configdialog.py:787
+#: spyderlib/plugins/configdialog.py:920
 msgid "Keyword:"
 msgstr "Palabra clave:"
 
-#: spyderlib/plugins/configdialog.py:788
+#: spyderlib/plugins/configdialog.py:921
 msgid "Builtin:"
 msgstr "Objeto integrado:"
 
-#: spyderlib/plugins/configdialog.py:789
+#: spyderlib/plugins/configdialog.py:922
 msgid "Definition:"
 msgstr "Definición:"
 
-#: spyderlib/plugins/configdialog.py:790
+#: spyderlib/plugins/configdialog.py:923
 msgid "Comment:"
 msgstr "Comentario:"
 
-#: spyderlib/plugins/configdialog.py:791
+#: spyderlib/plugins/configdialog.py:924
 msgid "String:"
 msgstr "Cadena:"
 
-#: spyderlib/plugins/configdialog.py:792
+#: spyderlib/plugins/configdialog.py:925
 msgid "Number:"
 msgstr "Número:"
 
-#: spyderlib/plugins/configdialog.py:793
+#: spyderlib/plugins/configdialog.py:926
 msgid "Instance:"
 msgstr "Instancia:"
 
-#: spyderlib/plugins/configdialog.py:799
+#: spyderlib/plugins/configdialog.py:932
 msgid "Color scheme"
 msgstr "Esquema de coloreado"
 
-#: spyderlib/plugins/configdialog.py:821 spyderlib/plugins/shortcuts.py:344
+#: spyderlib/plugins/configdialog.py:954 spyderlib/plugins/shortcuts.py:776
 msgid "Reset to default values"
 msgstr "Restaurar los valores por defecto"
 
-#: spyderlib/plugins/console.py:105
+#: spyderlib/plugins/console.py:109
 msgid "Internal console"
 msgstr "Terminal interna"
 
-#: spyderlib/plugins/console.py:125 spyderlib/spyder.py:772
-#: spyderlib/widgets/ipython.py:583
+#: spyderlib/plugins/console.py:129 spyderlib/spyder.py:869
+#: spyderlib/widgets/ipython.py:595
 msgid "&Quit"
 msgstr "&Salir"
 
-#: spyderlib/plugins/console.py:126 spyderlib/spyder.py:773
+#: spyderlib/plugins/console.py:131 spyderlib/spyder.py:871
 msgid "Quit"
 msgstr "Salir"
 
-#: spyderlib/plugins/console.py:129 spyderlib/plugins/externalconsole.py:1099
+#: spyderlib/plugins/console.py:134 spyderlib/plugins/externalconsole.py:1039
 msgid "&Run..."
 msgstr "E&jecutar..."
 
-#: spyderlib/plugins/console.py:130 spyderlib/plugins/externalconsole.py:1100
+#: spyderlib/plugins/console.py:136 spyderlib/plugins/externalconsole.py:1040
 msgid "Run a Python script"
 msgstr "Ejecutar un archivo de Python"
 
-#: spyderlib/plugins/console.py:133
+#: spyderlib/plugins/console.py:139
 msgid "Environment variables..."
 msgstr "Variables de entorno..."
 
-#: spyderlib/plugins/console.py:135
+#: spyderlib/plugins/console.py:141
 msgid "Show and edit environment variables (for current session)"
 msgstr "Muestra y edita las variables de entorno (para la sesión actual)"
 
-#: spyderlib/plugins/console.py:139
+#: spyderlib/plugins/console.py:145
 msgid "Show sys.path contents..."
 msgstr "Contenidos del sys.path"
 
-#: spyderlib/plugins/console.py:141
+#: spyderlib/plugins/console.py:147
 msgid "Show (read-only) sys.path"
 msgstr "Muestra los contenidos del sys.path en modo lectura"
 
-#: spyderlib/plugins/console.py:144
+#: spyderlib/plugins/console.py:150
 msgid "Buffer..."
 msgstr "Mostrar líneas..."
 
-#: spyderlib/plugins/console.py:145 spyderlib/plugins/externalconsole.py:85
-#: spyderlib/plugins/history.py:40
+#: spyderlib/plugins/console.py:151 spyderlib/plugins/externalconsole.py:87
+#: spyderlib/plugins/history.py:41
 msgid "Set maximum line count"
 msgstr "Establece el máximo número de líneas a mostrar en la terminal"
 
-#: spyderlib/plugins/console.py:148 spyderlib/plugins/explorer.py:57
-#: spyderlib/plugins/history.py:164 spyderlib/plugins/inspector.py:372
-#: spyderlib/plugins/projectexplorer.py:56
+#: spyderlib/plugins/console.py:154 spyderlib/plugins/explorer.py:67
+#: spyderlib/plugins/history.py:169 spyderlib/plugins/inspector.py:388
+#: spyderlib/plugins/projectexplorer.py:68
 msgid "&Font..."
 msgstr "&Tipo de letra..."
 
-#: spyderlib/plugins/console.py:149 spyderlib/plugins/history.py:165
+#: spyderlib/plugins/console.py:155 spyderlib/plugins/history.py:170
 msgid "Set shell font style"
 msgstr "Establece el tipo de fuente de la terminal"
 
-#: spyderlib/plugins/console.py:152
+#: spyderlib/plugins/console.py:158
 msgid "External editor path..."
 msgstr "Ruta del editor externo..."
 
-#: spyderlib/plugins/console.py:153
+#: spyderlib/plugins/console.py:159
 msgid "Set external editor executable path"
 msgstr "Establece la ruta del editor externo"
 
-#: spyderlib/plugins/console.py:156 spyderlib/plugins/editor.py:144
-#: spyderlib/plugins/externalconsole.py:86 spyderlib/plugins/history.py:43
-#: spyderlib/plugins/history.py:167 spyderlib/plugins/inspector.py:175
-#: spyderlib/plugins/inspector.py:375
+#: spyderlib/plugins/console.py:162 spyderlib/plugins/editor.py:139
+#: spyderlib/plugins/externalconsole.py:88 spyderlib/plugins/history.py:44
+#: spyderlib/plugins/history.py:172 spyderlib/plugins/inspector.py:180
+#: spyderlib/plugins/inspector.py:391
 msgid "Wrap lines"
 msgstr "Ajuste de línea automático"
 
-#: spyderlib/plugins/console.py:159 spyderlib/plugins/editor.py:178
+#: spyderlib/plugins/console.py:165 spyderlib/plugins/editor.py:181
 #: spyderlib/plugins/externalconsole.py:133
-#: spyderlib/plugins/ipythonconsole.py:175
+#: spyderlib/plugins/ipythonconsole.py:172
 msgid "Display balloon tips"
 msgstr "Mostrar globos de sugerencias"
 
-#: spyderlib/plugins/console.py:163 spyderlib/plugins/editor.py:172
+#: spyderlib/plugins/console.py:169 spyderlib/plugins/editor.py:175
 #: spyderlib/plugins/externalconsole.py:127
 msgid "Automatic code completion"
 msgstr "Completar código automáticamente"
 
-#: spyderlib/plugins/console.py:167 spyderlib/plugins/editor.py:176
+#: spyderlib/plugins/console.py:173 spyderlib/plugins/editor.py:179
 #: spyderlib/plugins/externalconsole.py:131
 msgid "Enter key selects completion"
 msgstr "La tecla Enter selecciona el resultado a completar"
 
-#: spyderlib/plugins/console.py:172
+#: spyderlib/plugins/console.py:178
 msgid "Internal console settings"
 msgstr "Opciones"
 
-#: spyderlib/plugins/console.py:223 spyderlib/plugins/externalconsole.py:1285
+#: spyderlib/plugins/console.py:231 spyderlib/plugins/externalconsole.py:1220
 msgid "Run Python script"
 msgstr "Ejecutar archivo de Python"
 
-#: spyderlib/plugins/console.py:224 spyderlib/plugins/externalconsole.py:229
-#: spyderlib/plugins/externalconsole.py:1286 spyderlib/widgets/explorer.py:666
+#: spyderlib/plugins/console.py:232 spyderlib/plugins/externalconsole.py:226
+#: spyderlib/plugins/externalconsole.py:1221 spyderlib/widgets/explorer.py:675
 msgid "Python scripts"
 msgstr "Archivos de Python"
 
-#: spyderlib/plugins/console.py:269 spyderlib/plugins/explorer.py:109
-#: spyderlib/plugins/history.py:282 spyderlib/plugins/inspector.py:651
-#: spyderlib/plugins/projectexplorer.py:118
+#: spyderlib/plugins/console.py:278 spyderlib/plugins/explorer.py:117
+#: spyderlib/plugins/history.py:285 spyderlib/plugins/inspector.py:665
+#: spyderlib/plugins/projectexplorer.py:126
 msgid "Select a new font"
 msgstr "Seleccionar una nueva fuente"
 
-#: spyderlib/plugins/console.py:276
+#: spyderlib/plugins/console.py:286
 msgid "Buffer"
 msgstr "Mostrar"
 
-#: spyderlib/plugins/console.py:277
+#: spyderlib/plugins/console.py:287
 msgid "Maximum line count"
 msgstr "Máximo número de líneas a mostrar"
 
-#: spyderlib/plugins/console.py:286
+#: spyderlib/plugins/console.py:297
 msgid "External editor"
 msgstr "Editor externo"
 
-#: spyderlib/plugins/console.py:287
+#: spyderlib/plugins/console.py:298
 msgid "External editor executable path:"
 msgstr "Ruta ejecutable del editor externo:"
 
-#: spyderlib/plugins/editor.py:100
+#: spyderlib/plugins/editor.py:101
 msgid "Edit template for new modules"
 msgstr "Editar la plantilla para nuevos módulos"
 
-#: spyderlib/plugins/editor.py:105
+#: spyderlib/plugins/editor.py:106
 msgid "Text and margin font style"
 msgstr "Tipo de letra para el texto y las márgenes"
 
-#: spyderlib/plugins/editor.py:108
+#: spyderlib/plugins/editor.py:109
 msgid "Sort files according to full path"
 msgstr "Ordenar archivos según su ruta completa"
 
-#: spyderlib/plugins/editor.py:110
+#: spyderlib/plugins/editor.py:111
 msgid "Show tab bar"
 msgstr "Mostrar barra de pestañas"
 
-#: spyderlib/plugins/editor.py:117 spyderlib/plugins/editor.py:192
-#: spyderlib/plugins/externalconsole.py:81
-#: spyderlib/plugins/externalconsole.py:126 spyderlib/plugins/history.py:42
-#: spyderlib/plugins/inspector.py:174 spyderlib/plugins/ipythonconsole.py:199
+#: spyderlib/plugins/editor.py:118 spyderlib/plugins/editor.py:195
+#: spyderlib/plugins/externalconsole.py:83
+#: spyderlib/plugins/externalconsole.py:126 spyderlib/plugins/history.py:43
+#: spyderlib/plugins/inspector.py:179 spyderlib/plugins/ipythonconsole.py:206
 msgid "Source code"
 msgstr "Código fuente"
 
-#: spyderlib/plugins/editor.py:118
+#: spyderlib/plugins/editor.py:119
 msgid "Show line numbers"
 msgstr "Mostrar números de líneas"
 
-#: spyderlib/plugins/editor.py:119 spyderlib/plugins/editor.py:892
+#: spyderlib/plugins/editor.py:120 spyderlib/plugins/editor.py:916
 msgid "Show blank spaces"
 msgstr "Mostrar espacios en blanco"
 
-#: spyderlib/plugins/editor.py:120
+#: spyderlib/plugins/editor.py:121
 msgid "Show vertical line after"
 msgstr "Mostrar una línea vertical después de"
 
-#: spyderlib/plugins/editor.py:121
+#: spyderlib/plugins/editor.py:122
 msgid "characters"
 msgstr "caracteres"
 
-#: spyderlib/plugins/editor.py:129
+#: spyderlib/plugins/editor.py:127
 msgid "Highlight current line"
 msgstr "Resaltar la línea actual"
 
-#: spyderlib/plugins/editor.py:131
+#: spyderlib/plugins/editor.py:129
 msgid "Highlight current cell"
 msgstr "Resaltar la celda actual"
 
-#: spyderlib/plugins/editor.py:133
+#: spyderlib/plugins/editor.py:131
 msgid "Highlight occurences after"
 msgstr "Resaltar ocurrencias después de"
 
-#: spyderlib/plugins/editor.py:147 spyderlib/plugins/history.py:51
-#: spyderlib/plugins/inspector.py:178
+#: spyderlib/plugins/editor.py:142 spyderlib/plugins/history.py:52
+#: spyderlib/plugins/inspector.py:183
 msgid "Syntax color scheme: "
 msgstr "Esquema de coloreado:"
 
-#: spyderlib/plugins/editor.py:161 spyderlib/plugins/runconfig.py:313
-#: spyderlib/plugins/runconfig.py:435 spyderlib/plugins/runconfig.py:440
-#: spyderlib/spyder.py:1850 spyderlib/utils/programs.py:175
-#: spyderlib/widgets/explorer.py:234
-#: spyderlib/widgets/externalshell/baseshell.py:138
+#: spyderlib/plugins/editor.py:164 spyderlib/plugins/runconfig.py:321
+#: spyderlib/plugins/runconfig.py:443 spyderlib/plugins/runconfig.py:448
+#: spyderlib/spyder.py:2501 spyderlib/utils/programs.py:175
+#: spyderlib/widgets/explorer.py:240
+#: spyderlib/widgets/externalshell/baseshell.py:140
 msgid "Run"
 msgstr "Ejecutar"
 
-#: spyderlib/plugins/editor.py:162
+#: spyderlib/plugins/editor.py:165
 msgid "Save all files before running script"
 msgstr "Guardar todo antes de ejecutar un archivo"
 
-#: spyderlib/plugins/editor.py:165
+#: spyderlib/plugins/editor.py:168
 msgid "Run selection"
 msgstr "Ejecutar selección"
 
-#: spyderlib/plugins/editor.py:166
+#: spyderlib/plugins/editor.py:169
 msgid "Maintain focus in the Editor after running cells or selections"
 msgstr "Mantener el foco en el Editor después de ejecutar celdas o selecciones"
 
-#: spyderlib/plugins/editor.py:169 spyderlib/plugins/externalconsole.py:365
+#: spyderlib/plugins/editor.py:172 spyderlib/plugins/externalconsole.py:334
 msgid "Introspection"
 msgstr "Introspección"
 
-#: spyderlib/plugins/editor.py:174 spyderlib/plugins/externalconsole.py:129
+#: spyderlib/plugins/editor.py:177 spyderlib/plugins/externalconsole.py:129
 msgid "Case sensitive code completion"
 msgstr "Diferenciar entre mayúsculas y minúsculas al completar código"
 
-#: spyderlib/plugins/editor.py:179
+#: spyderlib/plugins/editor.py:182
 msgid "Link to object definition"
 msgstr "Enlazar a la definición de un objeto"
 
-#: spyderlib/plugins/editor.py:181
+#: spyderlib/plugins/editor.py:184
 msgid ""
 "If this option is enabled, clicking on an object\n"
 "name (left-click + Ctrl key) will go this object\n"
@@ -546,7 +600,7 @@ msgstr ""
 "la tecla Ctrl), el Editor se ubicará en la definición\n"
 "del mismo (de poder resolverse el nombre)."
 
-#: spyderlib/plugins/editor.py:185
+#: spyderlib/plugins/editor.py:188
 msgid ""
 "<b>Warning:</b><br>The Python module <i>rope</i> is not installed on this "
 "computer: calltips, code completion and go-to-definition features won't be "
@@ -556,51 +610,51 @@ msgstr ""
 "este computador. Por tanto el completado de código, el ir a la definición de "
 "una función o método y los globos de sugerencias se encontrarán desactivados."
 
-#: spyderlib/plugins/editor.py:193
+#: spyderlib/plugins/editor.py:196
 msgid "Automatic insertion of parentheses, braces and brackets"
 msgstr "Inserción automática de paréntesis, llaves y corchetes"
 
-#: spyderlib/plugins/editor.py:196
+#: spyderlib/plugins/editor.py:199
 msgid "Automatic insertion of closing quotes"
 msgstr "Inserción automática de comillas"
 
-#: spyderlib/plugins/editor.py:198
+#: spyderlib/plugins/editor.py:201
 msgid "Automatic insertion of colons after 'for', 'if', 'def', etc"
 msgstr "Inserción automática de ':' después de 'for', 'if', 'def', etc"
 
-#: spyderlib/plugins/editor.py:201
+#: spyderlib/plugins/editor.py:204
 msgid "Automatic indentation after 'else', 'elif', etc."
 msgstr "Indentación automática después de 'else', 'elif', etc."
 
-#: spyderlib/plugins/editor.py:203
+#: spyderlib/plugins/editor.py:206
 msgid "Indentation characters: "
 msgstr "Caracteres de indentación:"
 
-#: spyderlib/plugins/editor.py:204
+#: spyderlib/plugins/editor.py:207
 msgid "4 spaces"
 msgstr "4 espacios"
 
-#: spyderlib/plugins/editor.py:205
+#: spyderlib/plugins/editor.py:208
 msgid "2 spaces"
 msgstr "2 espacios"
 
-#: spyderlib/plugins/editor.py:206
+#: spyderlib/plugins/editor.py:209
 msgid "tab"
 msgstr "tabulador"
 
-#: spyderlib/plugins/editor.py:207
+#: spyderlib/plugins/editor.py:210
 msgid "Tab stop width:"
 msgstr "Ancho de las tabulaciones:"
 
-#: spyderlib/plugins/editor.py:207
+#: spyderlib/plugins/editor.py:210
 msgid "pixels"
 msgstr "pixels"
 
-#: spyderlib/plugins/editor.py:209
+#: spyderlib/plugins/editor.py:212
 msgid "Tab always indent"
 msgstr "Siempre indentar con la tecla Tab"
 
-#: spyderlib/plugins/editor.py:211
+#: spyderlib/plugins/editor.py:214
 msgid ""
 "If enabled, pressing Tab will always indent,\n"
 "even when the cursor is not at the beginning\n"
@@ -615,79 +669,76 @@ msgstr ""
 "la combinación de teclas Ctrl+Espacio para\n"
 "activar el completado de código)"
 
-#: spyderlib/plugins/editor.py:216
+#: spyderlib/plugins/editor.py:219
 msgid "Intelligent backspace"
 msgstr "Tecla de retroceso (\"backspace\") inteligente"
 
-#: spyderlib/plugins/editor.py:218
+#: spyderlib/plugins/editor.py:221
 msgid "Automatically remove trailing spaces when saving files"
 msgstr "Eliminar automáticamente espacios en blanco al guardar un archivo"
 
-#: spyderlib/plugins/editor.py:222
+#: spyderlib/plugins/editor.py:225
 msgid "Analysis"
 msgstr "Análisis"
 
-#: spyderlib/plugins/editor.py:224
-msgid ""
-"<u>Note</u>: add <b>analysis:ignore</b> in a comment to ignore code/style "
-"analysis warnings. For more informations on style guide for Python code, "
-"please refer to the %s page."
+#: spyderlib/plugins/editor.py:227
+msgid "<i>(Refer to the {} page)</i>"
 msgstr ""
-"<u>Nota</u>: Añada <b>analysis:ignore</b> a un comentario para ignorar "
-"advertencias de análisis de código o estilo. Para más información sobre una "
-"guía de estilo para escribir código en Python, por favor refiérase a la "
-"página de %s (en inglés).<br>"
 
-#: spyderlib/plugins/editor.py:233
-#: spyderlib/widgets/sourcecode/codeeditor.py:1617
-msgid "Code analysis"
-msgstr "Análisis del código"
+#: spyderlib/plugins/editor.py:231
+#, fuzzy
+msgid "Real-time code analysis"
+msgstr "Análisis del código en tiempo real en el Editor"
 
-#: spyderlib/plugins/editor.py:235
+#: spyderlib/plugins/editor.py:233
+#, fuzzy
 msgid ""
-"If enabled, Python source code will be analyzed\n"
-"using pyflakes, lines containing errors or \n"
-"warnings will be highlighted"
+"<p>If enabled, Python source code will be analyzedusing pyflakes, lines "
+"containing errors or warnings will be highlighted.</p><p><u>Note</u>: add "
+"<b>analysis:ignore</b> in a comment to ignore code analysis warnings.</p>"
 msgstr ""
 "Si esta opción está activada, los archivos de Python\n"
 "serán analizados automáticamente y las líneas que\n"
 "contengan errores o advertencias serán resaltadas"
 
-#: spyderlib/plugins/editor.py:240
+#: spyderlib/plugins/editor.py:241
 msgid "Code analysis requires pyflakes %s+"
 msgstr "El análisis del código requiere pyflakes %s+"
 
-#: spyderlib/plugins/editor.py:242
-msgid "Style analysis"
-msgstr "Análisis de estilo"
+#: spyderlib/plugins/editor.py:243
+#, fuzzy
+msgid "Real-time code style analysis"
+msgstr "Análisis de estilo del código en el Editor"
 
-#: spyderlib/plugins/editor.py:244
+#: spyderlib/plugins/editor.py:245
+#, fuzzy
 msgid ""
-"If enabled, Python source code will be analyzed\n"
-"using pep8, lines that are not following PEP8\n"
-"style guide will be highlighted"
+"<p>If enabled, Python source code will be analyzedusing pep8, lines that are "
+"not following PEP8 style guide will be highlighted.</p><p><u>Note</u>: add "
+"<b>analysis:ignore</b> in a comment to ignore style analysis warnings.</p>"
 msgstr ""
 "Si esta opción está activada, los archivos de Python\n"
 "serán analizados con PEP8 y las líneas que no sigan\n"
 "esta guía de estilo serán resaltadas."
 
-#: spyderlib/plugins/editor.py:251
-msgid "Tasks (TODO, FIXME, XXX, HINT, TIP, @todo)"
+#: spyderlib/plugins/editor.py:252
+#, fuzzy
+msgid "Code annotations (TODO, FIXME, XXX, HINT, TIP, @todo)"
 msgstr "Tareas (TODO, FIXME, XXX, HINT, TIP, @todo)"
 
-#: spyderlib/plugins/editor.py:254
+#: spyderlib/plugins/editor.py:255
 msgid "Perform analysis when saving file and every"
 msgstr "Realizar los análisis al guardar el archivo y cada"
 
-#: spyderlib/plugins/editor.py:258
+#: spyderlib/plugins/editor.py:259
 msgid "Perform analysis only when saving file"
 msgstr "Realizar análisis sólo cuando se guarde el archivo"
 
-#: spyderlib/plugins/editor.py:306
+#: spyderlib/plugins/editor.py:318
 msgid "End-of-line characters"
 msgstr "Caracteres de fin de línea"
 
-#: spyderlib/plugins/editor.py:307
+#: spyderlib/plugins/editor.py:319
 msgid ""
 "When opening a text file containing mixed end-of-line characters (this may "
 "raise syntax errors in the consoles on Windows platforms), Spyder may fix "
@@ -697,224 +748,224 @@ msgstr ""
 "de fin de línea (lo cual puede dar lugar a errores en Windows), Spyder puede "
 "arreglar el archivo automáticamente."
 
-#: spyderlib/plugins/editor.py:313
+#: spyderlib/plugins/editor.py:325
 msgid "Fix automatically and show warning message box"
 msgstr "Arreglar automáticamente y mostrar un mensaje de advertencia"
 
-#: spyderlib/plugins/editor.py:324 spyderlib/plugins/externalconsole.py:363
-#: spyderlib/plugins/ipythonconsole.py:444
+#: spyderlib/plugins/editor.py:336 spyderlib/plugins/externalconsole.py:332
+#: spyderlib/plugins/ipythonconsole.py:463
 #: spyderlib/plugins/variableexplorer.py:41
 msgid "Display"
 msgstr "Visualización"
 
-#: spyderlib/plugins/editor.py:326
+#: spyderlib/plugins/editor.py:338
 msgid "Code Introspection/Analysis"
 msgstr "Análisis e introspección de código"
 
-#: spyderlib/plugins/editor.py:329 spyderlib/plugins/externalconsole.py:367
+#: spyderlib/plugins/editor.py:341 spyderlib/plugins/externalconsole.py:336
 msgid "Advanced settings"
 msgstr "Opciones avanzadas"
 
-#: spyderlib/plugins/editor.py:583 spyderlib/widgets/editortools.py:508
+#: spyderlib/plugins/editor.py:607 spyderlib/widgets/editortools.py:510
 msgid "Show/hide outline explorer"
 msgstr ""
 "Mostrar u ocultar el\n"
 "explorador de código"
 
-#: spyderlib/plugins/editor.py:589
+#: spyderlib/plugins/editor.py:613
 msgid "Show/hide project explorer"
 msgstr "Mostrar/cerrar el explorador de proyectos"
 
-#: spyderlib/plugins/editor.py:597
+#: spyderlib/plugins/editor.py:621
 msgid "&New file..."
 msgstr "&Nuevo"
 
-#: spyderlib/plugins/editor.py:598 spyderlib/plugins/workingdirectory.py:82
-#: spyderlib/widgets/explorer.py:643 spyderlib/widgets/explorer.py:650
+#: spyderlib/plugins/editor.py:622 spyderlib/plugins/workingdirectory.py:82
+#: spyderlib/widgets/explorer.py:652 spyderlib/widgets/explorer.py:659
 msgid "New file"
 msgstr "Nuevo archivo"
 
-#: spyderlib/plugins/editor.py:605
+#: spyderlib/plugins/editor.py:629
 msgid "&Open..."
 msgstr "&Abrir"
 
-#: spyderlib/plugins/editor.py:606 spyderlib/plugins/editor.py:1647
+#: spyderlib/plugins/editor.py:630 spyderlib/plugins/editor.py:1643
 #: spyderlib/plugins/workingdirectory.py:69
 msgid "Open file"
 msgstr "Abrir archivo"
 
-#: spyderlib/plugins/editor.py:613
+#: spyderlib/plugins/editor.py:637
 msgid "&Revert"
 msgstr "&Restaurar"
 
-#: spyderlib/plugins/editor.py:614
+#: spyderlib/plugins/editor.py:638
 msgid "Revert file from disk"
 msgstr "Restaurar archivo desde el disco"
 
-#: spyderlib/plugins/editor.py:617
+#: spyderlib/plugins/editor.py:641
 msgid "&Save"
 msgstr "&Guardar"
 
-#: spyderlib/plugins/editor.py:618
+#: spyderlib/plugins/editor.py:642
 msgid "Save file"
 msgstr "Guardar archivo"
 
-#: spyderlib/plugins/editor.py:625
+#: spyderlib/plugins/editor.py:649
 msgid "Sav&e all"
 msgstr "Guardar t&odo"
 
-#: spyderlib/plugins/editor.py:626
+#: spyderlib/plugins/editor.py:650
 msgid "Save all files"
 msgstr "Guardar todos los archivos"
 
-#: spyderlib/plugins/editor.py:633
+#: spyderlib/plugins/editor.py:658
 msgid "Save &as..."
 msgstr "Gu&ardar como..."
 
-#: spyderlib/plugins/editor.py:634
+#: spyderlib/plugins/editor.py:659
 msgid "Save current file as..."
 msgstr "Guardar el archivo actual como..."
 
-#: spyderlib/plugins/editor.py:636 spyderlib/plugins/editor.py:637
+#: spyderlib/plugins/editor.py:663 spyderlib/plugins/editor.py:664
 msgid "Print preview..."
 msgstr "Presentación preliminar..."
 
-#: spyderlib/plugins/editor.py:638
+#: spyderlib/plugins/editor.py:665
 msgid "&Print..."
 msgstr "Im&primir"
 
-#: spyderlib/plugins/editor.py:639
+#: spyderlib/plugins/editor.py:666
 msgid "Print current file..."
 msgstr "Imprimir el archivo actual..."
 
-#: spyderlib/plugins/editor.py:644
+#: spyderlib/plugins/editor.py:669
 msgid "&Close"
 msgstr "&Cerrar"
 
-#: spyderlib/plugins/editor.py:645
+#: spyderlib/plugins/editor.py:670
 msgid "Close current file"
 msgstr "Cerrar el archivo actual"
 
-#: spyderlib/plugins/editor.py:647
+#: spyderlib/plugins/editor.py:673
 msgid "C&lose all"
 msgstr "C&errar todo"
 
-#: spyderlib/plugins/editor.py:648
+#: spyderlib/plugins/editor.py:674
 msgid "Close all opened files"
 msgstr "Cerrar todos los archivos abiertos"
 
-#: spyderlib/plugins/editor.py:655
+#: spyderlib/plugins/editor.py:681
 msgid "Set/Clear breakpoint"
 msgstr "Añadir o eliminar un punto de interrupción"
 
-#: spyderlib/plugins/editor.py:662
+#: spyderlib/plugins/editor.py:688
 msgid "Set/Edit conditional breakpoint"
 msgstr "Añadir o editar un punto de interrupción condicional"
 
-#: spyderlib/plugins/editor.py:669
+#: spyderlib/plugins/editor.py:695
 msgid "Clear breakpoints in all files"
 msgstr "Eliminar los puntos de interrupción de todos los archivos"
 
-#: spyderlib/plugins/editor.py:671
+#: spyderlib/plugins/editor.py:697
 msgid "Breakpoints"
 msgstr "Puntos de interrupción (Breakpoints)"
 
-#: spyderlib/plugins/editor.py:675
+#: spyderlib/plugins/editor.py:701
 msgid "Debug with winpdb"
 msgstr "Depurar con winpdb"
 
-#: spyderlib/plugins/editor.py:682 spyderlib/spyder.py:575
+#: spyderlib/plugins/editor.py:708 spyderlib/spyder.py:659
 msgid "&Debug"
 msgstr "&Depurar"
 
-#: spyderlib/plugins/editor.py:683
+#: spyderlib/plugins/editor.py:709
 msgid "Debug file"
 msgstr "Depurar archivo"
 
-#: spyderlib/plugins/editor.py:688
+#: spyderlib/plugins/editor.py:713
 msgid "Step"
 msgstr "Ejecutar línea"
 
-#: spyderlib/plugins/editor.py:689
+#: spyderlib/plugins/editor.py:714
 msgid "Run current line"
 msgstr "Ejecutar la línea seleccionada"
 
-#: spyderlib/plugins/editor.py:695
+#: spyderlib/plugins/editor.py:720
 msgid "Continue"
 msgstr "Continuar"
 
-#: spyderlib/plugins/editor.py:696
+#: spyderlib/plugins/editor.py:721
 msgid "Continue execution until next breakpoint"
 msgstr "Continuar con la ejecución hasta el siguiente punto de interrupción"
 
-#: spyderlib/plugins/editor.py:703
+#: spyderlib/plugins/editor.py:728
 msgid "Step Into"
 msgstr "Ingresar en la función/método"
 
-#: spyderlib/plugins/editor.py:704
+#: spyderlib/plugins/editor.py:729
 msgid "Step into function or method of current line"
 msgstr "Ingresar en la función o método de la línea actual"
 
-#: spyderlib/plugins/editor.py:711
+#: spyderlib/plugins/editor.py:736
 msgid "Step Return"
 msgstr "Salir de la función/método"
 
-#: spyderlib/plugins/editor.py:712
+#: spyderlib/plugins/editor.py:737
 msgid "Run until current function or method returns"
 msgstr "Ejecutar hasta que la función o método actual termine"
 
-#: spyderlib/plugins/editor.py:719
+#: spyderlib/plugins/editor.py:744
 msgid "Exit"
 msgstr "Terminar"
 
-#: spyderlib/plugins/editor.py:720
+#: spyderlib/plugins/editor.py:745
 msgid "Exit Debug"
 msgstr "Terminar depuración"
 
-#: spyderlib/plugins/editor.py:731
+#: spyderlib/plugins/editor.py:756
 msgid "Debugging control"
 msgstr "Control de depuración"
 
-#: spyderlib/plugins/editor.py:735 spyderlib/plugins/editor.py:1246
-#: spyderlib/spyder.py:570
+#: spyderlib/plugins/editor.py:760 spyderlib/plugins/editor.py:1236
+#: spyderlib/spyder.py:654
 msgid "&Run"
 msgstr "E&jecutar"
 
-#: spyderlib/plugins/editor.py:736
+#: spyderlib/plugins/editor.py:761
 msgid "Run file"
 msgstr "Ejecutar archivo"
 
-#: spyderlib/plugins/editor.py:742
+#: spyderlib/plugins/editor.py:766
 msgid "&Configure..."
 msgstr "&Configurar..."
 
-#: spyderlib/plugins/editor.py:743
-#: spyderlib/widgets/externalshell/pythonshell.py:294
+#: spyderlib/plugins/editor.py:768
+#: spyderlib/widgets/externalshell/pythonshell.py:311
 msgid "Run settings"
 msgstr "Ajustes de ejecución"
 
-#: spyderlib/plugins/editor.py:752
+#: spyderlib/plugins/editor.py:776
 msgid "Re-run &last script"
 msgstr "Ejecutar de &nuevo el último archivo"
 
-#: spyderlib/plugins/editor.py:753
+#: spyderlib/plugins/editor.py:778
 msgid "Run again last file"
 msgstr "Ejecutar de nuevo el mismo archivo"
 
-#: spyderlib/plugins/editor.py:760
-#: spyderlib/widgets/sourcecode/codeeditor.py:2305
+#: spyderlib/plugins/editor.py:785
+#: spyderlib/widgets/sourcecode/codeeditor.py:2462
 msgid "Run &selection or current line"
 msgstr "Ejecutar la &selección o la línea actual"
 
-#: spyderlib/plugins/editor.py:763
+#: spyderlib/plugins/editor.py:788
 msgid "Run selection or current line"
 msgstr "Ejecutar la &selección o línea actual"
 
-#: spyderlib/plugins/editor.py:776
+#: spyderlib/plugins/editor.py:801
 msgid "Run cell"
 msgstr "Ejecutar la celda"
 
-#: spyderlib/plugins/editor.py:778
+#: spyderlib/plugins/editor.py:804
 msgid ""
 "Run current cell (Ctrl+Enter)\n"
 "[Use #%% to create cells]"
@@ -922,166 +973,166 @@ msgstr ""
 "Ejecutar la celda actual (Ctrl+Enter)\n"
 "[Usar #%% para crear celdas]"
 
-#: spyderlib/plugins/editor.py:783
+#: spyderlib/plugins/editor.py:809
 msgid "Run cell and advance"
 msgstr "Ejecutar la celda y avanzar"
 
-#: spyderlib/plugins/editor.py:786
+#: spyderlib/plugins/editor.py:812
 msgid "Run current cell and go to the next one (Shift+Enter)"
 msgstr "Ejecutar la celda actual y avanzar a la siguiente (Shift+Enter)"
 
-#: spyderlib/plugins/editor.py:792
+#: spyderlib/plugins/editor.py:818
 msgid "Show todo list"
 msgstr "Mostrar lista de TODO's"
 
-#: spyderlib/plugins/editor.py:793
+#: spyderlib/plugins/editor.py:819
 msgid "Show TODO/FIXME/XXX/HINT/TIP/@todo comments list"
 msgstr ""
 "Mostrar la lista de comentarios de\n"
 "los TODO/FIXME/XXX/HINT/TIP/@todo"
 
-#: spyderlib/plugins/editor.py:801
+#: spyderlib/plugins/editor.py:826
 msgid "Show warning/error list"
 msgstr ""
 "Mostrar la lista de errores\n"
 "y advertencias"
 
-#: spyderlib/plugins/editor.py:802
+#: spyderlib/plugins/editor.py:827
 msgid "Show code analysis warnings/errors"
 msgstr ""
 "Mostrar errores o advertencias\n"
 "del análisis del código"
 
-#: spyderlib/plugins/editor.py:809
+#: spyderlib/plugins/editor.py:833
 msgid "Previous warning/error"
 msgstr "Anterior advertencia o error"
 
-#: spyderlib/plugins/editor.py:810
+#: spyderlib/plugins/editor.py:834
 msgid "Go to previous code analysis warning/error"
 msgstr ""
 "Ir a la línea anterior de\n"
 "advertencia o error"
 
-#: spyderlib/plugins/editor.py:813
+#: spyderlib/plugins/editor.py:837
 msgid "Next warning/error"
 msgstr "Siguiente advertencia o error"
 
-#: spyderlib/plugins/editor.py:814
+#: spyderlib/plugins/editor.py:838
 msgid "Go to next code analysis warning/error"
 msgstr ""
 "Ir a la próxima línea de\n"
 "advertencia o error"
 
-#: spyderlib/plugins/editor.py:818
+#: spyderlib/plugins/editor.py:842
 msgid "Last edit location"
 msgstr "Última posición de edición"
 
-#: spyderlib/plugins/editor.py:819
+#: spyderlib/plugins/editor.py:843
 msgid "Go to last edit location"
 msgstr ""
 "Ir a la anterior posición\n"
 "de edición"
 
-#: spyderlib/plugins/editor.py:825
+#: spyderlib/plugins/editor.py:849
 msgid "Previous cursor position"
 msgstr "Anterior posición del cursor"
 
-#: spyderlib/plugins/editor.py:826
+#: spyderlib/plugins/editor.py:850
 msgid "Go to previous cursor position"
 msgstr "Ir a la anterior posición del cursor"
 
-#: spyderlib/plugins/editor.py:832
+#: spyderlib/plugins/editor.py:856
 msgid "Next cursor position"
 msgstr "Siguiente posición del cursor"
 
-#: spyderlib/plugins/editor.py:833
+#: spyderlib/plugins/editor.py:857
 msgid "Go to next cursor position"
 msgstr "Ir a la siguiente posición del cursor"
 
-#: spyderlib/plugins/editor.py:840
-#: spyderlib/widgets/sourcecode/codeeditor.py:2292
+#: spyderlib/plugins/editor.py:864
+#: spyderlib/widgets/sourcecode/codeeditor.py:2449
 msgid "Comment"
 msgstr "Comentar"
 
-#: spyderlib/plugins/editor.py:840
-#: spyderlib/widgets/sourcecode/codeeditor.py:2292
+#: spyderlib/plugins/editor.py:864
+#: spyderlib/widgets/sourcecode/codeeditor.py:2449
 msgid "Uncomment"
 msgstr "Descomentar"
 
-#: spyderlib/plugins/editor.py:841
+#: spyderlib/plugins/editor.py:865
 msgid "Comment current line or selection"
 msgstr "Comentar la línea o selección actual"
 
-#: spyderlib/plugins/editor.py:845
+#: spyderlib/plugins/editor.py:869
 msgid "Add &block comment"
 msgstr "Añadir comentario de &bloque"
 
-#: spyderlib/plugins/editor.py:846
+#: spyderlib/plugins/editor.py:870
 msgid "Add block comment around current line or selection"
 msgstr ""
 "Añadir un comentario de bloque alrededor de la línea o selección actual"
 
-#: spyderlib/plugins/editor.py:852
+#: spyderlib/plugins/editor.py:876
 msgid "R&emove block comment"
 msgstr "&Eliminar comentario de bloque"
 
-#: spyderlib/plugins/editor.py:853
+#: spyderlib/plugins/editor.py:877
 msgid "Remove comment block around current line or selection"
 msgstr "Eliminar comentario de bloque alrededor de la línea o selección actual"
 
-#: spyderlib/plugins/editor.py:864
+#: spyderlib/plugins/editor.py:888
 msgid "Indent"
 msgstr "Indentar"
 
-#: spyderlib/plugins/editor.py:865
+#: spyderlib/plugins/editor.py:889
 msgid "Indent current line or selection"
 msgstr "Indentar la línea o selección actual"
 
-#: spyderlib/plugins/editor.py:868
+#: spyderlib/plugins/editor.py:892
 msgid "Unindent"
 msgstr "Quitar indentación"
 
-#: spyderlib/plugins/editor.py:869
+#: spyderlib/plugins/editor.py:893
 msgid "Unindent current line or selection"
 msgstr "Quitar indentación de la línea o selección actual"
 
-#: spyderlib/plugins/editor.py:874
+#: spyderlib/plugins/editor.py:898
 msgid "Carriage return and line feed (Windows)"
 msgstr "Retorno de carro y salto de línea (Windows)"
 
-#: spyderlib/plugins/editor.py:877
+#: spyderlib/plugins/editor.py:901
 msgid "Line feed (UNIX)"
 msgstr "Salto de línea (UNIX)"
 
-#: spyderlib/plugins/editor.py:880
+#: spyderlib/plugins/editor.py:904
 msgid "Carriage return (Mac)"
 msgstr "Retorno de carro (Mac)"
 
-#: spyderlib/plugins/editor.py:886
+#: spyderlib/plugins/editor.py:910
 msgid "Convert end-of-line characters"
 msgstr "Convertir caracteres de fin de línea"
 
-#: spyderlib/plugins/editor.py:890
+#: spyderlib/plugins/editor.py:914
 msgid "Remove trailing spaces"
 msgstr "Eliminar espacios en blanco"
 
-#: spyderlib/plugins/editor.py:894
+#: spyderlib/plugins/editor.py:918
 msgid "Fix indentation"
 msgstr "Corregir la indentación"
 
-#: spyderlib/plugins/editor.py:895
+#: spyderlib/plugins/editor.py:919
 msgid "Replace tab characters by space characters"
 msgstr "Reemplazar caracteres de tabulación por espacios"
 
-#: spyderlib/plugins/editor.py:898
+#: spyderlib/plugins/editor.py:922
 msgid "Go to line..."
 msgstr "Ir a la línea..."
 
-#: spyderlib/plugins/editor.py:906
+#: spyderlib/plugins/editor.py:930
 msgid "Set console working directory"
 msgstr "Establecer directorio de trabajo"
 
-#: spyderlib/plugins/editor.py:908
+#: spyderlib/plugins/editor.py:932
 msgid ""
 "Set current console (and file explorer) working directory to current script "
 "directory"
@@ -1089,139 +1140,139 @@ msgstr ""
 "Fija el directorio de trabajo para la terminal actual como el directorio del "
 "archivo actual"
 
-#: spyderlib/plugins/editor.py:913
+#: spyderlib/plugins/editor.py:937
 msgid "Maximum number of recent files..."
 msgstr "Máximo número de archivos recientes..."
 
-#: spyderlib/plugins/editor.py:916
+#: spyderlib/plugins/editor.py:940
 msgid "Clear recent files list"
 msgstr "Limpiar la lista de archivos recientes"
 
-#: spyderlib/plugins/editor.py:916
+#: spyderlib/plugins/editor.py:940
 msgid "Clear this list"
 msgstr "Limpiar esta lista"
 
-#: spyderlib/plugins/editor.py:918
+#: spyderlib/plugins/editor.py:942
 msgid "Open &recent"
 msgstr "Abrir &reciente"
 
-#: spyderlib/plugins/editor.py:1234 spyderlib/spyder.py:551
+#: spyderlib/plugins/editor.py:1224 spyderlib/spyder.py:635
 msgid "File toolbar"
 msgstr "Barra de archivo"
 
-#: spyderlib/plugins/editor.py:1235 spyderlib/spyder.py:561
+#: spyderlib/plugins/editor.py:1225 spyderlib/spyder.py:645
 msgid "Search toolbar"
 msgstr "Barra de búsqueda"
 
-#: spyderlib/plugins/editor.py:1236 spyderlib/spyder.py:566
+#: spyderlib/plugins/editor.py:1226 spyderlib/spyder.py:650
 msgid "Source toolbar"
 msgstr "Barra de código fuente"
 
-#: spyderlib/plugins/editor.py:1237 spyderlib/spyder.py:571
+#: spyderlib/plugins/editor.py:1227 spyderlib/spyder.py:655
 msgid "Run toolbar"
 msgstr "Barra de ejecución"
 
-#: spyderlib/plugins/editor.py:1238 spyderlib/spyder.py:576
+#: spyderlib/plugins/editor.py:1228 spyderlib/spyder.py:660
 msgid "Debug toolbar"
 msgstr "Barra de depuración"
 
-#: spyderlib/plugins/editor.py:1239 spyderlib/spyder.py:556
+#: spyderlib/plugins/editor.py:1229 spyderlib/spyder.py:640
 msgid "Edit toolbar"
 msgstr "Barra de edición"
 
-#: spyderlib/plugins/editor.py:1242 spyderlib/spyder.py:548
+#: spyderlib/plugins/editor.py:1232 spyderlib/spyder.py:633
 msgid "&File"
 msgstr "&Archivo"
 
-#: spyderlib/plugins/editor.py:1243 spyderlib/spyder.py:555
+#: spyderlib/plugins/editor.py:1233 spyderlib/spyder.py:639
 msgid "&Edit"
 msgstr "&Editar"
 
-#: spyderlib/plugins/editor.py:1244 spyderlib/spyder.py:560
+#: spyderlib/plugins/editor.py:1234 spyderlib/spyder.py:644
 msgid "&Search"
 msgstr "&Buscar"
 
-#: spyderlib/plugins/editor.py:1245 spyderlib/spyder.py:565
+#: spyderlib/plugins/editor.py:1235 spyderlib/spyder.py:649
 msgid "Sour&ce"
 msgstr "&Código fuente"
 
-#: spyderlib/plugins/editor.py:1247 spyderlib/spyder.py:583
+#: spyderlib/plugins/editor.py:1237 spyderlib/spyder.py:667
 msgid "&Tools"
 msgstr "&Herramientas"
 
-#: spyderlib/plugins/editor.py:1248
+#: spyderlib/plugins/editor.py:1238
 msgid "?"
 msgstr "?"
 
-#: spyderlib/plugins/editor.py:1469
+#: spyderlib/plugins/editor.py:1458
 msgid "Spyder Editor"
 msgstr "Editor de Spyder"
 
-#: spyderlib/plugins/editor.py:1470
+#: spyderlib/plugins/editor.py:1459
 msgid "This is a temporary script file."
 msgstr "Este es un archivo temporal"
 
-#: spyderlib/plugins/editor.py:1536
+#: spyderlib/plugins/editor.py:1527
 msgid "untitled"
 msgstr "Sin título "
 
-#: spyderlib/plugins/editor.py:1607
+#: spyderlib/plugins/editor.py:1601
 msgid "Maximum number of recent files"
 msgstr "Máximo número de archivos recientes"
 
-#: spyderlib/plugins/editor.py:1729
+#: spyderlib/plugins/editor.py:1726
 msgid "Printing..."
 msgstr "Imprimir..."
 
-#: spyderlib/plugins/explorer.py:45
+#: spyderlib/plugins/explorer.py:55
 msgid "File explorer"
 msgstr "Explorador de archivos"
 
-#: spyderlib/plugins/explorer.py:58 spyderlib/plugins/inspector.py:373
-#: spyderlib/plugins/projectexplorer.py:57
+#: spyderlib/plugins/explorer.py:68 spyderlib/plugins/inspector.py:389
+#: spyderlib/plugins/projectexplorer.py:69
 msgid "Set font style"
 msgstr "Establece el tipo de fuente"
 
-#: spyderlib/plugins/externalconsole.py:46
+#: spyderlib/plugins/externalconsole.py:49
 msgid "Interactive data plotting in the consoles"
 msgstr "Graficar datos interactivamente en la terminal"
 
-#: spyderlib/plugins/externalconsole.py:53
-#: spyderlib/plugins/externalconsole.py:1066
-#: spyderlib/plugins/inspector.py:403 spyderlib/plugins/runconfig.py:178
-#: spyderlib/plugins/runconfig.py:447
-#: spyderlib/widgets/externalshell/baseshell.py:106
-#: spyderlib/widgets/ipython.py:509
+#: spyderlib/plugins/externalconsole.py:57
+#: spyderlib/plugins/externalconsole.py:1005
+#: spyderlib/plugins/inspector.py:419 spyderlib/plugins/runconfig.py:185
+#: spyderlib/plugins/runconfig.py:455
+#: spyderlib/widgets/externalshell/baseshell.py:107
+#: spyderlib/widgets/ipython.py:521
 msgid "Console"
 msgstr "Terminal"
 
-#: spyderlib/plugins/externalconsole.py:69
+#: spyderlib/plugins/externalconsole.py:71
 msgid "One tab per script"
 msgstr "Una pestaña por archivo"
 
-#: spyderlib/plugins/externalconsole.py:70
-#: spyderlib/widgets/externalshell/baseshell.py:171
+#: spyderlib/plugins/externalconsole.py:72
+#: spyderlib/widgets/externalshell/baseshell.py:173
 msgid "Show elapsed time"
 msgstr "Mostrar el tiempo transcurrido"
 
-#: spyderlib/plugins/externalconsole.py:71 spyderlib/widgets/explorer.py:988
+#: spyderlib/plugins/externalconsole.py:73 spyderlib/widgets/explorer.py:1016
 msgid "Show icons and text"
 msgstr "Mostrar iconos y texto "
 
-#: spyderlib/plugins/externalconsole.py:83
+#: spyderlib/plugins/externalconsole.py:85
 msgid "Buffer: "
 msgstr "Mostrar:"
 
-#: spyderlib/plugins/externalconsole.py:83
-#: spyderlib/plugins/ipythonconsole.py:201
+#: spyderlib/plugins/externalconsole.py:85
+#: spyderlib/plugins/ipythonconsole.py:208
 msgid " lines"
 msgstr "líneas"
 
-#: spyderlib/plugins/externalconsole.py:88
+#: spyderlib/plugins/externalconsole.py:90
 msgid "Merge process standard output/error channels"
 msgstr "Combinar los canales de salida y error estándar del proceso"
 
-#: spyderlib/plugins/externalconsole.py:90
+#: spyderlib/plugins/externalconsole.py:92
 msgid ""
 "Merging the output channels of the process means that\n"
 "the standard error won't be written in red anymore,\n"
@@ -1231,11 +1282,11 @@ msgstr ""
 "el error estándar no será escrito en rojo , pero esto ayuda a\n"
 "mejorar la velocidad en que aparece el texto en la terminal."
 
-#: spyderlib/plugins/externalconsole.py:94
+#: spyderlib/plugins/externalconsole.py:96
 msgid "Colorize standard error channel using ANSI escape codes"
 msgstr "Colorear el canal de error estándar usando códigos de escape ANSI "
 
-#: spyderlib/plugins/externalconsole.py:96
+#: spyderlib/plugins/externalconsole.py:98
 msgid ""
 "This method is the only way to have colorized standard\n"
 "error channel when the output channels have been merged."
@@ -1244,9 +1295,9 @@ msgstr ""
 "estándar cuando los canales de salida han sido combinados."
 
 #: spyderlib/plugins/externalconsole.py:114
-#: spyderlib/plugins/ipythonconsole.py:188
-#: spyderlib/widgets/arrayeditor.py:460
-#: spyderlib/widgets/dataframeeditor.py:515
+#: spyderlib/plugins/ipythonconsole.py:195
+#: spyderlib/widgets/arrayeditor.py:461
+#: spyderlib/widgets/dataframeeditor.py:516
 msgid "Background color"
 msgstr "Color de fondo"
 
@@ -1316,33 +1367,33 @@ msgstr ""
 msgid "Set UMR excluded (not reloaded) modules"
 msgstr "Establecer la lista de módulos excluidos por el RMU"
 
-#: spyderlib/plugins/externalconsole.py:181
+#: spyderlib/plugins/externalconsole.py:180
 msgid "Python executable"
 msgstr "Archivo ejecutable de Python"
 
-#: spyderlib/plugins/externalconsole.py:183
+#: spyderlib/plugins/externalconsole.py:182
 msgid ""
 "Select the Python interpreter executable binary in which Spyder will run "
 "scripts:"
 msgstr "Seleccionar la ruta al intérprete de Python que desee usar:"
 
-#: spyderlib/plugins/externalconsole.py:186
+#: spyderlib/plugins/externalconsole.py:185
 msgid "Default (i.e. the same as Spyder's)"
 msgstr "Por defecto (es decir, el mismo de Spyder)"
 
-#: spyderlib/plugins/externalconsole.py:190
+#: spyderlib/plugins/externalconsole.py:189
 msgid "Use the following Python interpreter:"
 msgstr "Usar el siguiente intérprete:"
 
-#: spyderlib/plugins/externalconsole.py:194
+#: spyderlib/plugins/externalconsole.py:193
 msgid "Executables"
 msgstr "Ejecutables"
 
-#: spyderlib/plugins/externalconsole.py:214
+#: spyderlib/plugins/externalconsole.py:211
 msgid "PYTHONSTARTUP replacement"
 msgstr "Reemplazo de PYTHONSTARTUP"
 
-#: spyderlib/plugins/externalconsole.py:216
+#: spyderlib/plugins/externalconsole.py:213
 msgid ""
 "This option will override the PYTHONSTARTUP environment variable which\n"
 "defines the script to be executed during the Python console startup."
@@ -1351,19 +1402,19 @@ msgstr ""
 "define el archivo que es ejecutado durante el arranque de la terminal de\n"
 "Python."
 
-#: spyderlib/plugins/externalconsole.py:221
+#: spyderlib/plugins/externalconsole.py:218
 msgid "Default PYTHONSTARTUP script"
 msgstr "Utilizar el archivo por defecto de PYTHONSTARTUP"
 
-#: spyderlib/plugins/externalconsole.py:225
+#: spyderlib/plugins/externalconsole.py:222
 msgid "Use the following startup script:"
 msgstr "Utilizar el siguiente archivo de arranque:"
 
-#: spyderlib/plugins/externalconsole.py:244
+#: spyderlib/plugins/externalconsole.py:239
 msgid "Monitor"
 msgstr "Monitor"
 
-#: spyderlib/plugins/externalconsole.py:245
+#: spyderlib/plugins/externalconsole.py:240
 msgid ""
 "The monitor provides introspection features to console: code completion, "
 "calltips and variable explorer. Because it relies on several modules, "
@@ -1374,91 +1425,57 @@ msgstr ""
 "Dado que depende de varios módulos adicionales, desactivar el monitor puede "
 "acelerar el arranque de la terminal."
 
-#: spyderlib/plugins/externalconsole.py:252
+#: spyderlib/plugins/externalconsole.py:247
 msgid "Enable monitor"
 msgstr "Activar el monitor"
 
-#: spyderlib/plugins/externalconsole.py:264
+#: spyderlib/plugins/externalconsole.py:260
 msgid "Default library"
 msgstr "Librería por defecto"
 
-#: spyderlib/plugins/externalconsole.py:266
-msgid "Qt (PyQt/PySide)"
-msgstr "Qt (PyQt/PySide)"
-
-#: spyderlib/plugins/externalconsole.py:268
-msgid "Qt-Python bindings library selection:"
+#: spyderlib/plugins/externalconsole.py:265
+#, fuzzy
+msgid "Qt-Python Bindings"
 msgstr "Selección de la librería de enlace entre Qt y Python:"
 
-#: spyderlib/plugins/externalconsole.py:270
-msgid ""
-"This option will act on<br> libraries such as Matplotlib, guidata or ETS"
+#: spyderlib/plugins/externalconsole.py:267
+msgid "Library:"
 msgstr ""
-"Esta opción tendrá efecto<br> en librerías como Matplotlib, guidata o ETS"
-
-#: spyderlib/plugins/externalconsole.py:291
-msgid "PyQt"
-msgstr "PyQt"
-
-#: spyderlib/plugins/externalconsole.py:293
-msgid "API selection for QString and QVariant objects:"
-msgstr "Selección del API para objetos QString and QVariant:"
-
-#: spyderlib/plugins/externalconsole.py:294
-msgid "API #1"
-msgstr "API #1"
-
-#: spyderlib/plugins/externalconsole.py:294
-msgid "API #2"
-msgstr "API #2"
 
-#: spyderlib/plugins/externalconsole.py:294
-msgid "Default API"
-msgstr "API por defecto"
-
-#: spyderlib/plugins/externalconsole.py:296
+#: spyderlib/plugins/externalconsole.py:269
 msgid ""
-"PyQt API #1 is the default <br>API for Python 2. PyQt API #2 is the default "
-"API for Python 3 and is compatible with PySide."
+"This option will act on<br> libraries such as Matplotlib, guidata or ETS"
 msgstr ""
-"El API #1 de PyQt es el API por<br>defecto para Python 2. El API #2 de PyQt "
-"es el API por defecto para Python 3 y es compatible con PySide."
+"Esta opción tendrá efecto<br> en librerías como Matplotlib, guidata o ETS"
 
-#: spyderlib/plugins/externalconsole.py:300
-msgid "Ignore API change errors (sip.setapi)"
-msgstr "Ignorar los errores de cambio de API (sip.setapi)"
+#: spyderlib/plugins/externalconsole.py:278
+#: spyderlib/plugins/ipythonconsole.py:465
+msgid "Graphics"
+msgstr "Gráficas"
 
-#: spyderlib/plugins/externalconsole.py:302
+#: spyderlib/plugins/externalconsole.py:279
 msgid ""
-"Enabling this option will ignore <br>errors when changing PyQt API. As PyQt "
-"does not support dynamic API changes, it is strongly recommended to use this "
-"feature wisely, e.g. for debugging purpose."
+"Decide which backend to use to display graphics. If unsure, please select "
+"the <b>Automatic</b> backend.<br><br><b>Note:</b> We support a very limited "
+"number of backends in our Python consoles. If you prefer to work with a "
+"different one, please use an IPython console."
 msgstr ""
-"Al activar esta opción se ignorarán <br>los errores generados al cambiar de "
-"API de PyQt. Dado que PyQt no soporta los cambios dinámicos de API, se "
-"recomienda usar esta característica con sumo cuidado, por ejemplo, para "
-"propósitos de depuración."
-
-#: spyderlib/plugins/externalconsole.py:321
-msgid "Matplotlib"
-msgstr "Matplotlib"
 
-#: spyderlib/plugins/externalconsole.py:323
-msgid "GUI backend:"
-msgstr "Salida gráfica:"
+#: spyderlib/plugins/externalconsole.py:295
+#: spyderlib/plugins/ipythonconsole.py:270
+msgid "Backend:"
+msgstr "Salida:"
 
-#: spyderlib/plugins/externalconsole.py:325
-msgid ""
-"Set the GUI toolkit used by <br>Matplotlib to show figures (default: Qt4Agg)"
-msgstr ""
-"Establecer la librería gráfica <br>utilizada para generar las gráficas de "
-"Matplotlib (por defecto: Qt4Agg)"
+#: spyderlib/plugins/externalconsole.py:297
+#: spyderlib/plugins/ipythonconsole.py:272
+msgid "This option will be applied the next time a console is opened."
+msgstr "Esta opción será aplicada la próxima vez que una terminal sea abierta."
 
-#: spyderlib/plugins/externalconsole.py:344
+#: spyderlib/plugins/externalconsole.py:308
 msgid "Enthought Tool Suite"
 msgstr "Enthought Tool Suite"
 
-#: spyderlib/plugins/externalconsole.py:345
+#: spyderlib/plugins/externalconsole.py:309
 msgid ""
 "Enthought Tool Suite (ETS) supports PyQt4 (qt4) and wxPython (wx) graphical "
 "user interfaces."
@@ -1467,24 +1484,25 @@ msgstr ""
 "y \n"
 "wxPython (wx). Esta opción establece cual desea utilizar el usuario."
 
-#: spyderlib/plugins/externalconsole.py:349
+#: spyderlib/plugins/externalconsole.py:313
 msgid "ETS_TOOLKIT:"
 msgstr "ETS_TOOLKIT:"
 
-#: spyderlib/plugins/externalconsole.py:369
+#: spyderlib/plugins/externalconsole.py:338
 msgid "External modules"
 msgstr "Módulos externos"
 
-#: spyderlib/plugins/externalconsole.py:426
-#: spyderlib/plugins/externalconsole.py:666
-#: spyderlib/plugins/ipythonconsole.py:113
-#: spyderlib/plugins/ipythonconsole.py:808 spyderlib/spyder.py:1331
-#: spyderlib/spyder.py:1349 spyderlib/utils/environ.py:94
-#: spyderlib/utils/environ.py:107 spyderlib/widgets/dicteditor.py:449
+#: spyderlib/plugins/externalconsole.py:374
+#: spyderlib/plugins/externalconsole.py:617
+#: spyderlib/plugins/ipythonconsole.py:114
+#: spyderlib/plugins/ipythonconsole.py:832 spyderlib/spyder.py:1803
+#: spyderlib/spyder.py:1825 spyderlib/spyder.py:1888 spyderlib/spyder.py:2774
+#: spyderlib/utils/environ.py:95 spyderlib/utils/environ.py:108
+#: spyderlib/widgets/dicteditor.py:452
 msgid "Warning"
 msgstr "Advertencia"
 
-#: spyderlib/plugins/externalconsole.py:427
+#: spyderlib/plugins/externalconsole.py:375
 msgid ""
 "You selected a <b>Python %d</b> interpreter for the console but Spyder is "
 "running on <b>Python %d</b>!.<br><br>Although this is possible, we recommend "
@@ -1498,11 +1516,11 @@ msgstr ""
 "seleccionado, para evitar ver falsos errores y alarmas en el Editor debido a "
 "la sintaxis incompatible entre estas dos versiones de Python."
 
-#: spyderlib/plugins/externalconsole.py:590
+#: spyderlib/plugins/externalconsole.py:538
 msgid "Trying to kill a kernel?"
 msgstr "Desea cerrar un núcleo?"
 
-#: spyderlib/plugins/externalconsole.py:591
+#: spyderlib/plugins/externalconsole.py:539
 msgid ""
 "You can't close this kernel because it has one or more consoles connected to "
 "it.<br><br>You need to close them instead or you can kill the kernel using "
@@ -1512,7 +1530,7 @@ msgstr ""
 "él.<br><br>Debe cerrarlas previamente o puede terminar el proceso usando el "
 "segundo botón ubicado de derecha a izquierda."
 
-#: spyderlib/plugins/externalconsole.py:667
+#: spyderlib/plugins/externalconsole.py:618
 msgid ""
 "No Python console is currently selected to run <b>%s</b>.<br><br>Please "
 "select or open a new Python console and try again."
@@ -1520,7 +1538,7 @@ msgstr ""
 "No existe una terminal de Python para ejecutar <b>%s</b>.<br><br>Por favor "
 "abra una nueva y pruebe otra vez."
 
-#: spyderlib/plugins/externalconsole.py:748
+#: spyderlib/plugins/externalconsole.py:698
 msgid ""
 "%s is already running in a separate process.\n"
 "Do you want to kill the process before starting a new one?"
@@ -1528,11 +1546,11 @@ msgstr ""
 "%s ya se está ejecutando en proceso aparte.\n"
 "¿Desea terminar este proceso antes de empezar uno nuevo?"
 
-#: spyderlib/plugins/externalconsole.py:917
+#: spyderlib/plugins/externalconsole.py:858
 msgid "Kernel"
 msgstr "Núcleo"
 
-#: spyderlib/plugins/externalconsole.py:929
+#: spyderlib/plugins/externalconsole.py:868
 msgid ""
 "Either:<ol><li>Your IPython frontend and kernel versions are "
 "<b>incompatible</b> or</li><li>You <b>don't have</b> IPython installed in "
@@ -1544,43 +1562,43 @@ msgstr ""
 "intérprete externo.</li></ol>Lo lamentamos, pero en cualquier caso no "
 "podemos crear una terminal de IPython para usted."
 
-#: spyderlib/plugins/externalconsole.py:953
+#: spyderlib/plugins/externalconsole.py:892
 msgid "Command Window"
 msgstr "Símbolo"
 
-#: spyderlib/plugins/externalconsole.py:955
+#: spyderlib/plugins/externalconsole.py:894
 msgid "Terminal"
 msgstr "Terminal"
 
-#: spyderlib/plugins/externalconsole.py:1008
+#: spyderlib/plugins/externalconsole.py:947
 msgid "Kernel %s"
 msgstr "Núcleo %s"
 
-#: spyderlib/plugins/externalconsole.py:1088
+#: spyderlib/plugins/externalconsole.py:1027
 msgid "Open a &Python console"
 msgstr "Abrir una terminal de Python"
 
-#: spyderlib/plugins/externalconsole.py:1091
+#: spyderlib/plugins/externalconsole.py:1031
 msgid "Open &command prompt"
 msgstr "Abrir &símbolo del sistema"
 
-#: spyderlib/plugins/externalconsole.py:1092
+#: spyderlib/plugins/externalconsole.py:1032
 msgid "Open a Windows command prompt"
 msgstr "Abre el símbolo del sistema de Windows"
 
-#: spyderlib/plugins/externalconsole.py:1094
+#: spyderlib/plugins/externalconsole.py:1034
 msgid "Open a &terminal"
 msgstr "Abrir &terminal de comandos"
 
-#: spyderlib/plugins/externalconsole.py:1095
+#: spyderlib/plugins/externalconsole.py:1035
 msgid "Open a terminal window"
 msgstr "Abre una terminal del sistema"
 
-#: spyderlib/plugins/externalconsole.py:1263
+#: spyderlib/plugins/externalconsole.py:1196
 msgid "Open an IPython console"
 msgstr "Abrir una terminal de IPython"
 
-#: spyderlib/plugins/externalconsole.py:1264
+#: spyderlib/plugins/externalconsole.py:1197
 msgid ""
 "The console monitor was disabled: the IPython kernel will be started as "
 "expected, but an IPython console will have to be connected manually to the "
@@ -1589,13 +1607,13 @@ msgstr ""
 "El monitor está desactivado, por tanto se creará un kernel de IPython pero "
 "usted deberá conectar manualmente un intérprete al mismo."
 
-#: spyderlib/plugins/externalconsole.py:1294
-#: spyderlib/plugins/externalconsole.py:1307
-#: spyderlib/plugins/externalconsole.py:1311
+#: spyderlib/plugins/externalconsole.py:1229
+#: spyderlib/plugins/externalconsole.py:1242
+#: spyderlib/plugins/externalconsole.py:1246
 msgid "UMR"
 msgstr "RMU"
 
-#: spyderlib/plugins/externalconsole.py:1295
+#: spyderlib/plugins/externalconsole.py:1230
 msgid ""
 "UMR excluded modules:\n"
 "(example: guidata, guiqwt)"
@@ -1603,7 +1621,7 @@ msgstr ""
 "Módulos excluidos del RMU:\n"
 "(por ejemplo: guidata, guiqwt)"
 
-#: spyderlib/plugins/externalconsole.py:1308
+#: spyderlib/plugins/externalconsole.py:1243
 msgid ""
 "The following modules are not installed on your machine:\n"
 "%s"
@@ -1611,7 +1629,7 @@ msgstr ""
 "Los siguientes módulos no están instalados en su computador:\n"
 "%s"
 
-#: spyderlib/plugins/externalconsole.py:1312
+#: spyderlib/plugins/externalconsole.py:1247
 msgid ""
 "Please note that these changes will be applied only to new Python/IPython "
 "consoles"
@@ -1619,79 +1637,79 @@ msgstr ""
 "Por favor tenga en cuenta que estos cambios sólo se aplicarán a nuevas "
 "terminales de IPython y Python"
 
-#: spyderlib/plugins/findinfiles.py:90 spyderlib/widgets/findinfiles.py:691
+#: spyderlib/plugins/findinfiles.py:96 spyderlib/widgets/findinfiles.py:690
 msgid "Find in files"
 msgstr "Buscar en archivos"
 
-#: spyderlib/plugins/findinfiles.py:114
+#: spyderlib/plugins/findinfiles.py:117
 msgid "&Find in files"
 msgstr "Bus&car en archivos"
 
-#: spyderlib/plugins/findinfiles.py:117
+#: spyderlib/plugins/findinfiles.py:120
 msgid "Search text in multiple files"
 msgstr "Buscar en varios archivos a la vez"
 
-#: spyderlib/plugins/history.py:36
+#: spyderlib/plugins/history.py:37
 msgid "Settings"
 msgstr "Ajustes"
 
-#: spyderlib/plugins/history.py:38
+#: spyderlib/plugins/history.py:39
 msgid " entries"
 msgstr "entradas"
 
-#: spyderlib/plugins/history.py:38
+#: spyderlib/plugins/history.py:39
 msgid "History depth: "
 msgstr "Longitud del historial"
 
-#: spyderlib/plugins/history.py:45
+#: spyderlib/plugins/history.py:46
 msgid "Scroll automatically to last entry"
 msgstr "Desplazarse automáticamente a la última entrada"
 
-#: spyderlib/plugins/history.py:113 spyderlib/plugins/inspector.py:458
-#: spyderlib/widgets/editor.py:540 spyderlib/widgets/explorer.py:1018
-#: spyderlib/widgets/externalshell/baseshell.py:151
-#: spyderlib/widgets/externalshell/namespacebrowser.py:226
-#: spyderlib/widgets/ipython.py:556
+#: spyderlib/plugins/history.py:118 spyderlib/plugins/inspector.py:472
+#: spyderlib/widgets/editor.py:459 spyderlib/widgets/explorer.py:1027
+#: spyderlib/widgets/externalshell/baseshell.py:153
+#: spyderlib/widgets/externalshell/namespacebrowser.py:139
+#: spyderlib/widgets/ipython.py:568
 msgid "Options"
 msgstr "Opciones"
 
-#: spyderlib/plugins/history.py:133
+#: spyderlib/plugins/history.py:138
 msgid "History log"
 msgstr "Historial de comandos"
 
-#: spyderlib/plugins/history.py:160
+#: spyderlib/plugins/history.py:165
 msgid "History..."
 msgstr "Historial..."
 
-#: spyderlib/plugins/history.py:162
+#: spyderlib/plugins/history.py:167
 msgid "Set history maximum entries"
 msgstr "Establece el máximo número de entradas a almacenar"
 
-#: spyderlib/plugins/history.py:272
+#: spyderlib/plugins/history.py:274
 msgid "History"
 msgstr "Historial"
 
-#: spyderlib/plugins/history.py:273
+#: spyderlib/plugins/history.py:275
 msgid "Maximum entries"
 msgstr "Máximo número de entradas"
 
-#: spyderlib/plugins/inspector.py:56
+#: spyderlib/plugins/inspector.py:58
 msgid "Rich text help on the Object Inspector"
 msgstr "Ayuda en texto enriquecido en el Inspector de Objetos"
 
-#: spyderlib/plugins/inspector.py:120
+#: spyderlib/plugins/inspector.py:125
 msgid "Plain text font style"
 msgstr "Fuente para el texto plano"
 
-#: spyderlib/plugins/inspector.py:123
+#: spyderlib/plugins/inspector.py:128
 msgid "Rich text font style"
 msgstr "Fuente para el texto enriquecido"
 
-#: spyderlib/plugins/inspector.py:126
+#: spyderlib/plugins/inspector.py:131
 msgid "Automatic connections"
 msgstr "Conexiones automáticas"
 
-#: spyderlib/plugins/inspector.py:127
+#: spyderlib/plugins/inspector.py:132
 msgid ""
 "The Object Inspector can automatically show an object's help information "
 "after a left parenthesis is written next to it. Below you can decide to "
@@ -1701,7 +1719,7 @@ msgstr ""
 "después de escribir un paréntesis junto al mismo. A continuación puede "
 "decidir a que panel desea conectarlo para activar esta característica."
 
-#: spyderlib/plugins/inspector.py:139
+#: spyderlib/plugins/inspector.py:144
 msgid ""
 "This feature requires the Rope or Jedi libraries.\n"
 "It seems you don't have either installed."
@@ -1709,63 +1727,63 @@ msgstr ""
 "Esta característica requiere las librerías Rope o Jedi.\n"
 "Al parecer no tiene ninguna instalada."
 
-#: spyderlib/plugins/inspector.py:142
+#: spyderlib/plugins/inspector.py:147
 msgid "Python Console"
 msgstr "Terminal de IPython"
 
-#: spyderlib/plugins/inspector.py:144
+#: spyderlib/plugins/inspector.py:149
 msgid "IPython Console"
 msgstr "Terminal de IPython"
 
-#: spyderlib/plugins/inspector.py:156
+#: spyderlib/plugins/inspector.py:161
 msgid "Additional features"
 msgstr "Características adicionales"
 
-#: spyderlib/plugins/inspector.py:157
+#: spyderlib/plugins/inspector.py:162
 msgid "Render mathematical equations"
 msgstr "Renderizar ecuaciones matemáticas"
 
-#: spyderlib/plugins/inspector.py:163
+#: spyderlib/plugins/inspector.py:168
 msgid "This feature requires Sphinx 1.1 or superior."
 msgstr "Esta característica requiere Sphinx 1.1 o superior."
 
-#: spyderlib/plugins/inspector.py:165
+#: spyderlib/plugins/inspector.py:170
 msgid "Sphinx %s is currently installed."
 msgstr "Sphinx %s está instalado actualmente."
 
-#: spyderlib/plugins/inspector.py:357
+#: spyderlib/plugins/inspector.py:373
 msgid "No further documentation available"
 msgstr "No existe más documentación disponible"
 
-#: spyderlib/plugins/inspector.py:396
+#: spyderlib/plugins/inspector.py:412
 msgid "Source"
 msgstr "Origen"
 
-#: spyderlib/plugins/inspector.py:412 spyderlib/widgets/dicteditor.py:173
+#: spyderlib/plugins/inspector.py:427 spyderlib/widgets/dicteditor.py:173
 msgid "Object"
 msgstr "Objeto"
 
-#: spyderlib/plugins/inspector.py:428
+#: spyderlib/plugins/inspector.py:442
 msgid "Plain Text"
 msgstr "Texto plano"
 
-#: spyderlib/plugins/inspector.py:432
+#: spyderlib/plugins/inspector.py:446
 msgid "Show Source"
 msgstr "Mostrar código fuente"
 
-#: spyderlib/plugins/inspector.py:436
+#: spyderlib/plugins/inspector.py:450
 msgid "Rich Text"
 msgstr "Texto enriquecido"
 
-#: spyderlib/plugins/inspector.py:446
+#: spyderlib/plugins/inspector.py:460
 msgid "Automatic import"
 msgstr "Importar automáticamente"
 
-#: spyderlib/plugins/inspector.py:506 spyderlib/plugins/inspector.py:954
+#: spyderlib/plugins/inspector.py:520 spyderlib/plugins/inspector.py:983
 msgid "Object inspector"
 msgstr "Inspector de objetos"
 
-#: spyderlib/plugins/inspector.py:725
+#: spyderlib/plugins/inspector.py:740
 msgid ""
 "Here you can get help of any object by pressing %s in front of it, either on "
 "the Editor or the Console.%sHelp can also be shown automatically after "
@@ -1777,38 +1795,38 @@ msgstr ""
 "ayuda también se puede mostrar automáticamente después de escribir un "
 "paréntesis junto a un objeto. Este comportamiento puede activarse en %s."
 
-#: spyderlib/plugins/inspector.py:731
+#: spyderlib/plugins/inspector.py:746
 msgid "Preferences > Object Inspector"
 msgstr "Preferencias > Inspector de objetos"
 
-#: spyderlib/plugins/inspector.py:733
+#: spyderlib/plugins/inspector.py:753
 msgid "Usage"
 msgstr "Uso"
 
-#: spyderlib/plugins/inspector.py:734
+#: spyderlib/plugins/inspector.py:754
 msgid "New to Spyder? Read our"
 msgstr "Nuevo en Spyder? Lee nuestro"
 
-#: spyderlib/plugins/inspector.py:735
+#: spyderlib/plugins/inspector.py:755
 msgid "tutorial"
 msgstr "tutorial"
 
-#: spyderlib/plugins/inspector.py:742
+#: spyderlib/plugins/inspector.py:762
 msgid ""
 "Please consider installing Sphinx to get documentation rendered in rich text."
 msgstr ""
 "Por favor considere instalar Sphinx para obtener la documentación en texto "
 "enriquecido "
 
-#: spyderlib/plugins/inspector.py:913
+#: spyderlib/plugins/inspector.py:939
 msgid "Lock"
 msgstr "Bloquear"
 
-#: spyderlib/plugins/inspector.py:913
+#: spyderlib/plugins/inspector.py:939
 msgid "Unlock"
 msgstr "Desbloquear"
 
-#: spyderlib/plugins/inspector.py:955
+#: spyderlib/plugins/inspector.py:984
 msgid ""
 "The following error occured when calling <b>Sphinx %s</b>. <br>Incompatible "
 "Sphinx version or doc string decoding failed.<br><br>Error message:<br>%s"
@@ -1817,15 +1835,15 @@ msgstr ""
 "<br>Ello se debe a una versión incompatible de Sphinx o bien a que no fue "
 "posible leer la documentación solicitada.<br><br>Mensaje de error:<br>%s"
 
-#: spyderlib/plugins/inspector.py:999
+#: spyderlib/plugins/inspector.py:1028
 msgid "No source code available."
 msgstr "No está disponible el código fuente"
 
-#: spyderlib/plugins/ipythonconsole.py:61
+#: spyderlib/plugins/ipythonconsole.py:62
 msgid "Symbolic mathematics in the IPython Console"
 msgstr "Matemática simbólica en la terminal de IPython"
 
-#: spyderlib/plugins/ipythonconsole.py:110
+#: spyderlib/plugins/ipythonconsole.py:111
 msgid ""
 "The authenticity of host <b>%s</b> can't be established. Are you sure you "
 "want to continue connecting?"
@@ -1833,28 +1851,28 @@ msgstr ""
 "La autenticidad del servidor <b>%s</b> no puede ser establecida. ¿Está "
 "seguro de que desea continuar conectándose?"
 
-#: spyderlib/plugins/ipythonconsole.py:122
+#: spyderlib/plugins/ipythonconsole.py:123
 msgid "The authenticity of the host can't be established"
 msgstr "La autenticidad del servidor no puede ser establecida"
 
-#: spyderlib/plugins/ipythonconsole.py:129
+#: spyderlib/plugins/ipythonconsole.py:130
 msgid "Tunnel '%s' failed to start"
 msgstr "El túnel '%s' falló en ser iniciado"
 
-#: spyderlib/plugins/ipythonconsole.py:134
+#: spyderlib/plugins/ipythonconsole.py:135
 msgid "Could not connect to remote host"
 msgstr "No fue posible conectarse al servidor remoto"
 
-#: spyderlib/plugins/ipythonconsole.py:150
-#: spyderlib/plugins/ipythonconsole.py:665
+#: spyderlib/plugins/ipythonconsole.py:151
+#: spyderlib/plugins/ipythonconsole.py:689
 msgid "IPython console"
 msgstr "Terminal de IPython"
 
-#: spyderlib/plugins/ipythonconsole.py:162
+#: spyderlib/plugins/ipythonconsole.py:163
 msgid "Display initial banner"
 msgstr "Mostrar el banner inicial"
 
-#: spyderlib/plugins/ipythonconsole.py:163
+#: spyderlib/plugins/ipythonconsole.py:164
 msgid ""
 "This option lets you hide the message shown at\n"
 "the top of the console when it's opened."
@@ -1863,22 +1881,11 @@ msgstr ""
 "aparece al principio de la terminal cuando se abre\n"
 "por primera vez."
 
-#: spyderlib/plugins/ipythonconsole.py:165
-msgid "Use a completion widget"
-msgstr "Usar un widget para completar texto"
-
-#: spyderlib/plugins/ipythonconsole.py:167
-msgid "Use a widget instead of plain text output for tab completion"
-msgstr ""
-"Puede decidir si usar un widget en lugar de texto plano \n"
-"para mostrar las posibilidades de completado usando la\n"
-"tecla Tab."
-
-#: spyderlib/plugins/ipythonconsole.py:169
+#: spyderlib/plugins/ipythonconsole.py:166
 msgid "Use a pager to display additional text inside the console"
 msgstr "Usar un paginador para mostrar textos dentro de la terminal"
 
-#: spyderlib/plugins/ipythonconsole.py:171
+#: spyderlib/plugins/ipythonconsole.py:168
 msgid ""
 "Useful if you don't want to fill the console with long help or completion "
 "texts.\n"
@@ -1887,23 +1894,36 @@ msgstr ""
 "Es útil si no desea llenar la terminal con largos textos de ayuda.\n"
 "Nota: Debe usar la tecla Q para salir del paginador"
 
-#: spyderlib/plugins/ipythonconsole.py:176
+#: spyderlib/plugins/ipythonconsole.py:173
 msgid "Ask for confirmation before closing"
 msgstr "Mostrar un diálogo de confirmación antes de cerrar una terminal"
 
-#: spyderlib/plugins/ipythonconsole.py:189
+#: spyderlib/plugins/ipythonconsole.py:183
+msgid "Completion Type"
+msgstr ""
+
+#: spyderlib/plugins/ipythonconsole.py:184
+msgid "Decide what type of completion to use"
+msgstr ""
+
+#: spyderlib/plugins/ipythonconsole.py:187
+#, fuzzy
+msgid "Completion:"
+msgstr "Condición:"
+
+#: spyderlib/plugins/ipythonconsole.py:196
 msgid "Light background"
 msgstr "Fondo claro"
 
-#: spyderlib/plugins/ipythonconsole.py:191
+#: spyderlib/plugins/ipythonconsole.py:198
 msgid "Dark background"
 msgstr "Fondo oscuro"
 
-#: spyderlib/plugins/ipythonconsole.py:201
+#: spyderlib/plugins/ipythonconsole.py:208
 msgid "Buffer:  "
 msgstr "Mostrar"
 
-#: spyderlib/plugins/ipythonconsole.py:203
+#: spyderlib/plugins/ipythonconsole.py:210
 msgid ""
 "Set the maximum number of lines of text shown in the\n"
 "console before truncation. Specifying -1 disables it\n"
@@ -1913,19 +1933,19 @@ msgstr ""
 "en la terminal en cualquier momento. Si se introduce -1 se\n"
 "mostrarán todas las líneas (no se recomienda!)"
 
-#: spyderlib/plugins/ipythonconsole.py:212
+#: spyderlib/plugins/ipythonconsole.py:219
 msgid "Support for graphics (Matplotlib)"
 msgstr "Soporte para crear gráficas (Matplotlib)"
 
-#: spyderlib/plugins/ipythonconsole.py:213
+#: spyderlib/plugins/ipythonconsole.py:220
 msgid "Activate support"
 msgstr "Activar el soporte"
 
-#: spyderlib/plugins/ipythonconsole.py:214
+#: spyderlib/plugins/ipythonconsole.py:221
 msgid "Automatically load Pylab and NumPy modules"
 msgstr "Cargar automáticamente los módulos de Pylab y NumPy"
 
-#: spyderlib/plugins/ipythonconsole.py:217
+#: spyderlib/plugins/ipythonconsole.py:224
 msgid ""
 "This lets you load graphics support without importing \n"
 "the commands to do plots. Useful to work with other\n"
@@ -1937,7 +1957,7 @@ msgstr ""
 "otras librerías gráficas diferentes a Matplotlib o para\n"
 "desarrollar interfaces gráficas con Spyder."
 
-#: spyderlib/plugins/ipythonconsole.py:236
+#: spyderlib/plugins/ipythonconsole.py:242
 msgid ""
 "This feature requires the Matplotlib library.\n"
 "It seems you don't have it installed."
@@ -1945,19 +1965,19 @@ msgstr ""
 "Esta característica requiere la librería Matplotlib.\n"
 "Al parecer no la tiene instalada."
 
-#: spyderlib/plugins/ipythonconsole.py:241
+#: spyderlib/plugins/ipythonconsole.py:247
 msgid "Inline"
 msgstr "En línea"
 
-#: spyderlib/plugins/ipythonconsole.py:242
+#: spyderlib/plugins/ipythonconsole.py:248
 msgid "Automatic"
 msgstr "Automático"
 
-#: spyderlib/plugins/ipythonconsole.py:243
+#: spyderlib/plugins/ipythonconsole.py:249
 msgid "Graphics backend"
 msgstr "Salida gráfica:"
 
-#: spyderlib/plugins/ipythonconsole.py:244
+#: spyderlib/plugins/ipythonconsole.py:250
 msgid ""
 "Decide how graphics are going to be displayed in the console. If unsure, "
 "please select <b>%s</b> to put graphics inside the console or <b>%s</b> to "
@@ -1968,65 +1988,57 @@ msgstr ""
 "%s</b> para interactuar con ellas (a través de acercamientos y paneos) en "
 "una ventana aparte."
 
-#: spyderlib/plugins/ipythonconsole.py:264
-msgid "Backend:"
-msgstr "Salida:"
-
-#: spyderlib/plugins/ipythonconsole.py:266
-msgid "This option will be applied the next time a console is opened."
-msgstr "Esta opción será aplicada la próxima vez que una terminal sea abierta."
-
-#: spyderlib/plugins/ipythonconsole.py:278
+#: spyderlib/plugins/ipythonconsole.py:283
 msgid "Inline backend"
 msgstr "Salida en línea:"
 
-#: spyderlib/plugins/ipythonconsole.py:279
+#: spyderlib/plugins/ipythonconsole.py:284
 msgid "Decide how to render the figures created by this backend"
 msgstr ""
 "Decida como renderizar las figuras creadas por este tipo de salida gráfica"
 
-#: spyderlib/plugins/ipythonconsole.py:283
+#: spyderlib/plugins/ipythonconsole.py:288
 msgid "Format:"
 msgstr "Formato:"
 
-#: spyderlib/plugins/ipythonconsole.py:286
+#: spyderlib/plugins/ipythonconsole.py:291
 msgid "Resolution:"
 msgstr "Resolución:"
 
-#: spyderlib/plugins/ipythonconsole.py:286
+#: spyderlib/plugins/ipythonconsole.py:291
 msgid "dpi"
 msgstr "dpi"
 
-#: spyderlib/plugins/ipythonconsole.py:288
+#: spyderlib/plugins/ipythonconsole.py:293
 msgid "Only used when the format is PNG. Default is 72"
 msgstr "Sólo se usa cuando el formato es PNG. Por defecto es 72."
 
-#: spyderlib/plugins/ipythonconsole.py:291
+#: spyderlib/plugins/ipythonconsole.py:296
 msgid "Width:"
 msgstr "Ancho:"
 
-#: spyderlib/plugins/ipythonconsole.py:291
-#: spyderlib/plugins/ipythonconsole.py:295
+#: spyderlib/plugins/ipythonconsole.py:296
+#: spyderlib/plugins/ipythonconsole.py:300
 msgid "inches"
 msgstr "pulgadas"
 
-#: spyderlib/plugins/ipythonconsole.py:293
+#: spyderlib/plugins/ipythonconsole.py:298
 msgid "Default is 6"
 msgstr "Por defecto es 6"
 
-#: spyderlib/plugins/ipythonconsole.py:295
+#: spyderlib/plugins/ipythonconsole.py:300
 msgid "Height:"
 msgstr "Alto:"
 
-#: spyderlib/plugins/ipythonconsole.py:297
+#: spyderlib/plugins/ipythonconsole.py:302
 msgid "Default is 4"
 msgstr "Por defecto es 4"
 
-#: spyderlib/plugins/ipythonconsole.py:312
+#: spyderlib/plugins/ipythonconsole.py:328 spyderlib/tour.py:552
 msgid "Run code"
 msgstr "Ejecutar código"
 
-#: spyderlib/plugins/ipythonconsole.py:313
+#: spyderlib/plugins/ipythonconsole.py:329
 msgid ""
 "You can run several lines of code when a console is started. Please "
 "introduce each one separated by commas, for example:<br><i>import os, import "
@@ -2036,15 +2048,15 @@ msgstr ""
 "introduzca cada una separada por comas, por ejemplo:<br><i>import os, import "
 "sys</i>"
 
-#: spyderlib/plugins/ipythonconsole.py:319
+#: spyderlib/plugins/ipythonconsole.py:335
 msgid "Lines:"
 msgstr "Líneas:"
 
-#: spyderlib/plugins/ipythonconsole.py:328
+#: spyderlib/plugins/ipythonconsole.py:344
 msgid "Run a file"
 msgstr "Ejecutar un archivo"
 
-#: spyderlib/plugins/ipythonconsole.py:329
+#: spyderlib/plugins/ipythonconsole.py:345
 msgid ""
 "You can also run a whole file at startup instead of just some lines (This is "
 "similar to have a PYTHONSTARTUP file)."
@@ -2052,15 +2064,15 @@ msgstr ""
 "También se puede ejecutar un archivo completo al inicio, en lugar de unas "
 "pocas líneas (Esto es similar a tener un archivo PYTHONSTARTUP)."
 
-#: spyderlib/plugins/ipythonconsole.py:333
+#: spyderlib/plugins/ipythonconsole.py:349
 msgid "Use the following file:"
 msgstr "Usar el siguiente archivo:"
 
-#: spyderlib/plugins/ipythonconsole.py:348
+#: spyderlib/plugins/ipythonconsole.py:363
 msgid "Greedy completion"
 msgstr "Completado ambicioso"
 
-#: spyderlib/plugins/ipythonconsole.py:349
+#: spyderlib/plugins/ipythonconsole.py:364
 msgid ""
 "Enable <tt>Tab</tt> completion on elements of lists, results of function "
 "calls, etc, <i>without</i> assigning them to a variable.<br>For example, you "
@@ -2072,15 +2084,15 @@ msgstr ""
 "variable.<br>De esta forma se pueden obtener sugerencias de completado en "
 "cosas como <tt>li[0].<Tab></tt> o <tt>ins.meth().<Tab></tt>"
 
-#: spyderlib/plugins/ipythonconsole.py:357
+#: spyderlib/plugins/ipythonconsole.py:372
 msgid "Use the greedy completer"
 msgstr "Usar el completado ambicioso"
 
-#: spyderlib/plugins/ipythonconsole.py:368
+#: spyderlib/plugins/ipythonconsole.py:383
 msgid "Autocall"
 msgstr "Autollamar"
 
-#: spyderlib/plugins/ipythonconsole.py:369
+#: spyderlib/plugins/ipythonconsole.py:384
 msgid ""
 "Autocall makes IPython automatically call any callable object even if you "
 "didn't type explicit parentheses.<br>For example, if you type <i>str 43</i> "
@@ -2091,23 +2103,23 @@ msgstr ""
 "<br>Por ejemplo, al escribir <i>str 43</i>, se convertirá automáticamente en "
 "<i>str(43)</i>."
 
-#: spyderlib/plugins/ipythonconsole.py:376
+#: spyderlib/plugins/ipythonconsole.py:391
 msgid "Smart"
 msgstr "Inteligente"
 
-#: spyderlib/plugins/ipythonconsole.py:377
+#: spyderlib/plugins/ipythonconsole.py:392
 msgid "Full"
 msgstr "Total"
 
-#: spyderlib/plugins/ipythonconsole.py:378
+#: spyderlib/plugins/ipythonconsole.py:393
 msgid "Off"
 msgstr "Desactivado"
 
-#: spyderlib/plugins/ipythonconsole.py:380
+#: spyderlib/plugins/ipythonconsole.py:395
 msgid "Autocall:  "
 msgstr "Autollamar:"
 
-#: spyderlib/plugins/ipythonconsole.py:381
+#: spyderlib/plugins/ipythonconsole.py:396
 msgid ""
 "On <b>%s</b> mode, Autocall is not applied if there are no arguments after "
 "the callable. On <b>%s</b> mode, all callable objects are automatically "
@@ -2117,11 +2129,11 @@ msgstr ""
 "objeto llamable. En modo <b>%s</b>, todos los objetos llamables son llamados "
 "automáticamente (aún si no hay argumentos presentes)."
 
-#: spyderlib/plugins/ipythonconsole.py:393
+#: spyderlib/plugins/ipythonconsole.py:408
 msgid "Symbolic Mathematics"
 msgstr "Matemática simbólica"
 
-#: spyderlib/plugins/ipythonconsole.py:394
+#: spyderlib/plugins/ipythonconsole.py:409
 msgid ""
 "Perfom symbolic operations in the console (e.g. integrals, derivatives, "
 "vector calculus, etc) and get the outputs in a beautifully printed style."
@@ -2129,11 +2141,11 @@ msgstr ""
 "Realice operaciones simbólicas en la terminal (integrales, derivadas o "
 "cálculo vectorial) y obtenga los resultados en un bello estilo impreso."
 
-#: spyderlib/plugins/ipythonconsole.py:399
+#: spyderlib/plugins/ipythonconsole.py:414
 msgid "Use symbolic math"
 msgstr "Usar matemática simbólica"
 
-#: spyderlib/plugins/ipythonconsole.py:400
+#: spyderlib/plugins/ipythonconsole.py:415
 msgid ""
 "This option loads the Sympy library to work with.<br>Please refer to its "
 "documentation to learn how to use it."
@@ -2141,7 +2153,7 @@ msgstr ""
 "Esta opción carga la librería Sympy para trabajar<br>con ella. Por favor lea "
 "su documentación para aprender como usarla."
 
-#: spyderlib/plugins/ipythonconsole.py:413
+#: spyderlib/plugins/ipythonconsole.py:428
 msgid ""
 "This feature requires the Sympy library.\n"
 "It seems you don't have it installed."
@@ -2149,56 +2161,52 @@ msgstr ""
 "Esta característica requiere la librería Sympy.\n"
 "Al parecer no la tiene instalada."
 
-#: spyderlib/plugins/ipythonconsole.py:418
+#: spyderlib/plugins/ipythonconsole.py:433
 msgid "Prompts"
 msgstr "Prompts"
 
-#: spyderlib/plugins/ipythonconsole.py:419
+#: spyderlib/plugins/ipythonconsole.py:434
 msgid "Modify how Input and Output prompts are shown in the console."
 msgstr ""
 "Modifique como se muestran los prompts de entrada y salida en la terminal."
 
-#: spyderlib/plugins/ipythonconsole.py:422
+#: spyderlib/plugins/ipythonconsole.py:437
 msgid "Input prompt:"
 msgstr "Prompt de entrada:"
 
-#: spyderlib/plugins/ipythonconsole.py:424
+#: spyderlib/plugins/ipythonconsole.py:439
 msgid ""
 "Default is<br>In [<span class=\"in-prompt-number\">%i</span>]:"
 msgstr ""
 "Por defecto es<br>In [<span class=\"in-prompt-number\">%i</"
 "span>]:"
 
-#: spyderlib/plugins/ipythonconsole.py:428
+#: spyderlib/plugins/ipythonconsole.py:443
 msgid "Output prompt:"
 msgstr "Prompt de salida:"
 
-#: spyderlib/plugins/ipythonconsole.py:430
+#: spyderlib/plugins/ipythonconsole.py:445
 msgid ""
 "Default is<br>Out[<span class=\"out-prompt-number\">%i</span>]:"
 msgstr ""
 "Por defecto es<br>Out[<span class=\"out-prompt-number\">%i</"
 "span>]:"
 
-#: spyderlib/plugins/ipythonconsole.py:446
-msgid "Graphics"
-msgstr "Gráficas"
-
-#: spyderlib/plugins/ipythonconsole.py:448
-#: spyderlib/plugins/workingdirectory.py:42
+#: spyderlib/plugins/ipythonconsole.py:467
+#: spyderlib/plugins/workingdirectory.py:44
 msgid "Startup"
 msgstr "Inicialización"
 
-#: spyderlib/plugins/ipythonconsole.py:450
+#: spyderlib/plugins/ipythonconsole.py:469
 msgid "Advanced Settings"
 msgstr "Opciones avanzadas"
 
-#: spyderlib/plugins/ipythonconsole.py:462
-#: spyderlib/plugins/ipythonconsole.py:725
+#: spyderlib/plugins/ipythonconsole.py:481
+#: spyderlib/plugins/ipythonconsole.py:749
 msgid "Connect to an existing kernel"
 msgstr "Conectarse a un núcleo existente"
 
-#: spyderlib/plugins/ipythonconsole.py:464
+#: spyderlib/plugins/ipythonconsole.py:483
 msgid ""
 "Please enter the connection info of the kernel you want to connect to. For "
 "that you can either select its JSON connection file using the <tt>Browse</"
@@ -2211,72 +2219,72 @@ msgstr ""
 "sea un núcleo local (por ejemplo, <tt>kernel-3764.json</tt> o sólo <tt>3764</"
 "tt>)"
 
-#: spyderlib/plugins/ipythonconsole.py:475
+#: spyderlib/plugins/ipythonconsole.py:494
 msgid "Connection info:"
 msgstr "Información de conexión:"
 
-#: spyderlib/plugins/ipythonconsole.py:477
+#: spyderlib/plugins/ipythonconsole.py:496
 msgid "Path to connection file or kernel id"
 msgstr "Ruta al archivo de conexión o id del núcleo"
 
-#: spyderlib/plugins/ipythonconsole.py:479
-#: spyderlib/plugins/ipythonconsole.py:497
+#: spyderlib/plugins/ipythonconsole.py:498
+#: spyderlib/plugins/ipythonconsole.py:515
 msgid "Browse"
 msgstr "Seleccionar"
 
-#: spyderlib/plugins/ipythonconsole.py:489
+#: spyderlib/plugins/ipythonconsole.py:507
 msgid "This is a remote kernel"
 msgstr "Este es un núcleo remoto"
 
-#: spyderlib/plugins/ipythonconsole.py:493
+#: spyderlib/plugins/ipythonconsole.py:511
 msgid "username at hostname:port"
 msgstr "usuario at servidor:puerto"
 
-#: spyderlib/plugins/ipythonconsole.py:496
+#: spyderlib/plugins/ipythonconsole.py:514
 msgid "Path to ssh key file"
 msgstr "Ruta al archivo de clave ssh"
 
-#: spyderlib/plugins/ipythonconsole.py:505
+#: spyderlib/plugins/ipythonconsole.py:523
 msgid "Password or ssh key passphrase"
 msgstr "Contraseña o frase de contraseña de la clave ssh"
 
-#: spyderlib/plugins/ipythonconsole.py:509
+#: spyderlib/plugins/ipythonconsole.py:527
 msgid "Host name"
 msgstr "Servidor"
 
-#: spyderlib/plugins/ipythonconsole.py:510
+#: spyderlib/plugins/ipythonconsole.py:528
 msgid "Ssh key"
 msgstr "Clave ssh"
 
-#: spyderlib/plugins/ipythonconsole.py:511
+#: spyderlib/plugins/ipythonconsole.py:529
 msgid "Password"
 msgstr "Contraseña"
 
-#: spyderlib/plugins/ipythonconsole.py:540
+#: spyderlib/plugins/ipythonconsole.py:558
 msgid "Open IPython connection file"
 msgstr "Abrir un archivo de conexión de IPython"
 
-#: spyderlib/plugins/ipythonconsole.py:546
+#: spyderlib/plugins/ipythonconsole.py:564
 msgid "Select ssh key"
 msgstr "Seleccionar clave ssh"
 
-#: spyderlib/plugins/ipythonconsole.py:713
+#: spyderlib/plugins/ipythonconsole.py:737
 msgid "Open an &IPython console"
 msgstr "Abrir una terminal de IPython"
 
-#: spyderlib/plugins/ipythonconsole.py:716
+#: spyderlib/plugins/ipythonconsole.py:740
 msgid "Use %s+T when the console is selected to open a new one"
 msgstr "Usar %s+T para abrir una nueva terminal"
 
-#: spyderlib/plugins/ipythonconsole.py:719
+#: spyderlib/plugins/ipythonconsole.py:743
 msgid "Open a new console"
 msgstr "Abrir una nueva terminal"
 
-#: spyderlib/plugins/ipythonconsole.py:726
+#: spyderlib/plugins/ipythonconsole.py:750
 msgid "Open a new IPython console connected to an existing kernel"
 msgstr "Abrir una nueva terminal de IPython conectada a un núcleo existente"
 
-#: spyderlib/plugins/ipythonconsole.py:809
+#: spyderlib/plugins/ipythonconsole.py:833
 msgid ""
 "No IPython console is currently available to run <b>%s</b>.<br><br>Please "
 "open a new one and try again."
@@ -2284,18 +2292,18 @@ msgstr ""
 "No existe un intérprete de IPython para ejecutar <b>%s</b>.<br><br>Por favor "
 "abra uno nuevo e intente otra vez."
 
-#: spyderlib/plugins/ipythonconsole.py:950
+#: spyderlib/plugins/ipythonconsole.py:968
 msgid ""
 "Do you want to close all other consoles connected to the same kernel as this "
 "one?"
 msgstr ""
 "¿Desea cerrar todas las otras terminales conectadas al mismo núcleo que ésta?"
 
-#: spyderlib/plugins/ipythonconsole.py:1032
+#: spyderlib/plugins/ipythonconsole.py:1050
 msgid "Connection error"
 msgstr "Error de conexión"
 
-#: spyderlib/plugins/ipythonconsole.py:1033
+#: spyderlib/plugins/ipythonconsole.py:1051
 msgid ""
 "Could not open ssh tunnel. The error was:\n"
 "\n"
@@ -2303,39 +2311,58 @@ msgstr ""
 "No fue posible crear un túnel ssh. El error fue:\n"
 "\n"
 
-#: spyderlib/plugins/ipythonconsole.py:1069
+#: spyderlib/plugins/ipythonconsole.py:1088
 msgid "IPython"
 msgstr "IPython"
 
-#: spyderlib/plugins/ipythonconsole.py:1070
+#: spyderlib/plugins/ipythonconsole.py:1089
 msgid "Unable to connect to IPython <b>%s"
 msgstr "No se pudo establecer conexión con el núcleo <b>`%s`"
 
-#: spyderlib/plugins/ipythonconsole.py:1121
+#: spyderlib/plugins/ipythonconsole.py:1140
 msgid "Are you sure you want to restart the kernel?"
 msgstr "Está seguro de que desea reiniciar el núcleo?"
 
-#: spyderlib/plugins/ipythonconsole.py:1123
+#: spyderlib/plugins/ipythonconsole.py:1142
 msgid "Restart kernel?"
 msgstr "Reiniciar el núcleo?"
 
-#: spyderlib/plugins/onlinehelp.py:67
+#: spyderlib/plugins/layoutdialog.py:174
+#, fuzzy
+msgid "Move Up"
+msgstr "Mover arriba"
+
+#: spyderlib/plugins/layoutdialog.py:175
+#, fuzzy
+msgid "Move Down"
+msgstr "Mover abajo"
+
+#: spyderlib/plugins/layoutdialog.py:176
+#, fuzzy
+msgid "Delete Layout"
+msgstr "Eliminar"
+
+#: spyderlib/plugins/layoutdialog.py:180
+msgid "Layout Dispay and Order"
+msgstr ""
+
+#: spyderlib/plugins/onlinehelp.py:68
 msgid "Online help"
 msgstr "Ayuda en línea"
 
-#: spyderlib/plugins/outlineexplorer.py:47
-#: spyderlib/widgets/editortools.py:194
+#: spyderlib/plugins/outlineexplorer.py:48
+#: spyderlib/widgets/editortools.py:195
 msgid "Outline"
 msgstr "Explorador de código"
 
-#: spyderlib/plugins/projectexplorer.py:41
-#: spyderlib/widgets/projectexplorer.py:1137
-#: spyderlib/widgets/projectexplorer.py:1151
+#: spyderlib/plugins/projectexplorer.py:53
+#: spyderlib/widgets/projectexplorer.py:1150
+#: spyderlib/widgets/projectexplorer.py:1164
 msgid "Project explorer"
 msgstr "Explorador de proyectos"
 
-#: spyderlib/plugins/projectexplorer.py:52
-#: spyderlib/widgets/projectexplorer.py:545
+#: spyderlib/plugins/projectexplorer.py:64
+#: spyderlib/widgets/projectexplorer.py:549
 msgid "New project..."
 msgstr "Nuevo proyecto..."
 
@@ -2355,59 +2382,63 @@ msgstr "Ejecutar en una terminal de comandos del sistema"
 msgid "Always show %s on a first file run"
 msgstr "Siempre muestre %s en una primera ejecución"
 
-#: spyderlib/plugins/runconfig.py:153
+#: spyderlib/plugins/runconfig.py:159
 msgid "General settings"
 msgstr "Ajustes generales"
 
-#: spyderlib/plugins/runconfig.py:156 spyderlib/plugins/runconfig.py:201
+#: spyderlib/plugins/runconfig.py:162 spyderlib/plugins/runconfig.py:208
 msgid "Command line options:"
 msgstr "Opciones de línea de comandos:"
 
-#: spyderlib/plugins/runconfig.py:163
+#: spyderlib/plugins/runconfig.py:168
 msgid "Working directory:"
 msgstr "Directorio de trabajo:"
 
-#: spyderlib/plugins/runconfig.py:189
+#: spyderlib/plugins/runconfig.py:180 spyderlib/plugins/runconfig.py:491
+msgid "Enter debugging mode when errors appear during execution"
+msgstr ""
+
+#: spyderlib/plugins/runconfig.py:196 spyderlib/plugins/runconfig.py:501
 msgid "Dedicated Python console"
 msgstr "Terminal de Python dedicada"
 
-#: spyderlib/plugins/runconfig.py:194
+#: spyderlib/plugins/runconfig.py:200 spyderlib/plugins/runconfig.py:503
 msgid "Interact with the Python console after execution"
 msgstr "Interactuar con la terminal después de la ejecución"
 
-#: spyderlib/plugins/runconfig.py:198
+#: spyderlib/plugins/runconfig.py:204
 msgid "Show warning when killing running process"
 msgstr "Mostrar una advertencia cuando se termine el proceso"
 
-#: spyderlib/plugins/runconfig.py:207
+#: spyderlib/plugins/runconfig.py:213
 msgid "<b>-u</b> is added to the other options you set here"
 msgstr "La opción <b>-u</b> se añade a estas opciones"
 
-#: spyderlib/plugins/runconfig.py:218
+#: spyderlib/plugins/runconfig.py:223
 msgid "this dialog"
 msgstr "este diálogo"
 
-#: spyderlib/plugins/runconfig.py:276
+#: spyderlib/plugins/runconfig.py:282
 msgid "Run configuration"
 msgstr "Opciones de ejecución"
 
-#: spyderlib/plugins/runconfig.py:277
+#: spyderlib/plugins/runconfig.py:283
 msgid "The following working directory is not valid:<br><b>%s</b>"
 msgstr "El siguiente directorio de trabajo no es válido:<br><b>%s</b>"
 
-#: spyderlib/plugins/runconfig.py:353
+#: spyderlib/plugins/runconfig.py:361
 msgid "Run settings for %s"
 msgstr "Ajustes de ejecución para %s"
 
-#: spyderlib/plugins/runconfig.py:384
+#: spyderlib/plugins/runconfig.py:393
 msgid "Select a run configuration:"
 msgstr "Seleccionar una configuración de ejecución:"
 
-#: spyderlib/plugins/runconfig.py:414 spyderlib/plugins/runconfig.py:439
+#: spyderlib/plugins/runconfig.py:422 spyderlib/plugins/runconfig.py:447
 msgid "Run Settings"
 msgstr "Ajustes de ejecución"
 
-#: spyderlib/plugins/runconfig.py:441
+#: spyderlib/plugins/runconfig.py:449
 msgid ""
 "The following are the default <i>%s</i>. These options may be overriden "
 "using the <b>%s</b> dialog box (see the <b>%s</b> menu)"
@@ -2415,62 +2446,98 @@ msgstr ""
 "Las siguientes son los <i>%s</i> por defecto. Estos ajustes pueden "
 "modificarse usando el diálogo <b>%s</b> (ver el menú <b>%s</b>)"
 
-#: spyderlib/plugins/runconfig.py:465
-#: spyderlib/widgets/externalshell/pythonshell.py:297
-msgid "Working directory"
-msgstr "Directorio de trabajo"
-
-#: spyderlib/plugins/runconfig.py:467
+#: spyderlib/plugins/runconfig.py:475
 msgid "Default working directory is:"
 msgstr "Directorio de trabajo:"
 
-#: spyderlib/plugins/runconfig.py:469
+#: spyderlib/plugins/runconfig.py:477
 msgid "the script directory"
 msgstr "El directorio en  el que se encuentra el archivo actual"
 
-#: spyderlib/plugins/runconfig.py:472 spyderlib/plugins/workingdirectory.py:54
+#: spyderlib/plugins/runconfig.py:480 spyderlib/plugins/workingdirectory.py:56
 msgid "the following directory:"
 msgstr "el siguiente directorio:"
 
-#: spyderlib/plugins/runconfig.py:491
+#: spyderlib/plugins/runconfig.py:506
+#, fuzzy
+msgid "Show warning when killing running processes"
+msgstr "Mostrar una advertencia cuando se termine el proceso"
+
+#: spyderlib/plugins/runconfig.py:515
 msgid "Run Settings dialog"
 msgstr "Ajustes de ejecución"
 
-#: spyderlib/plugins/shortcuts.py:178
-msgid "Context"
-msgstr "Contexto"
+#: spyderlib/plugins/shortcuts.py:134
+msgid ""
+"Press the new shortcut and select 'Ok': \n"
+"(Press 'Tab' once to switch focus between the shortcut entry \n"
+"and the buttons below it)"
+msgstr ""
 
-#: spyderlib/plugins/shortcuts.py:180 spyderlib/widgets/dicteditor.py:158
-msgid "Name"
-msgstr "Nombre"
+#: spyderlib/plugins/shortcuts.py:137
+#, fuzzy
+msgid "Current shortcut:"
+msgstr "Celda seleccionada:"
 
-#: spyderlib/plugins/shortcuts.py:182
-msgid "Mod1"
-msgstr "Mod1"
+#: spyderlib/plugins/shortcuts.py:139
+#, fuzzy
+msgid "New shortcut:"
+msgstr "Atajos de teclado"
 
-#: spyderlib/plugins/shortcuts.py:184
-msgid "Mod2"
-msgstr "Mod2"
+#: spyderlib/plugins/shortcuts.py:152
+msgid "Shortcut: {0}"
+msgstr ""
 
-#: spyderlib/plugins/shortcuts.py:186
-msgid "Mod3"
-msgstr "Mod3"
+#: spyderlib/plugins/shortcuts.py:273
+msgid "Please introduce a different shortcut"
+msgstr ""
 
-#: spyderlib/plugins/shortcuts.py:188 spyderlib/widgets/dicteditor.py:169
-msgid "Key"
-msgstr "Clave/Tecla"
+#: spyderlib/plugins/shortcuts.py:310
+msgid "The new shorcut conflicts with:"
+msgstr ""
 
 #: spyderlib/plugins/shortcuts.py:321
-msgid "Conflicts"
-msgstr "Conflicto con"
+msgid ""
+"A compound sequence can have {break} a maximum of 4 subsequences.{break}"
+msgstr ""
 
-#: spyderlib/plugins/shortcuts.py:322
-msgid "The following conflicts have been detected:"
-msgstr "Los siguientes conflictos han sido detectados:"
+#: spyderlib/plugins/shortcuts.py:326
+#, fuzzy
+msgid "Invalid key entered"
+msgstr "Ruta de archivo inválida"
 
-#: spyderlib/plugins/shortcuts.py:334
-msgid "Keyboard shortcuts"
-msgstr "Atajos de teclado"
+#: spyderlib/plugins/shortcuts.py:515
+msgid "Context"
+msgstr "Contexto"
+
+#: spyderlib/plugins/shortcuts.py:517 spyderlib/widgets/dicteditor.py:158
+msgid "Name"
+msgstr "Nombre"
+
+#: spyderlib/plugins/shortcuts.py:519
+msgid "Shortcut"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:521
+msgid "Score"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:681
+msgid "Conflicts"
+msgstr "Conflicto con"
+
+#: spyderlib/plugins/shortcuts.py:682
+msgid "The following conflicts have been detected:"
+msgstr "Los siguientes conflictos han sido detectados:"
+
+#: spyderlib/plugins/shortcuts.py:767
+msgid "Keyboard shortcuts"
+msgstr "Atajos de teclado"
+
+#: spyderlib/plugins/shortcuts.py:775
+#, fuzzy
+msgid "Search: "
+msgstr "Buscar"
 
 #: spyderlib/plugins/variableexplorer.py:24
 msgid "Autorefresh"
@@ -2493,32 +2560,32 @@ msgid "Filter"
 msgstr "Filtrar"
 
 #: spyderlib/plugins/variableexplorer.py:33
-#: spyderlib/widgets/externalshell/namespacebrowser.py:196
+#: spyderlib/widgets/externalshell/namespacebrowser.py:214
 msgid "Exclude private references"
 msgstr "Excluir variables privadas"
 
 #: spyderlib/plugins/variableexplorer.py:34
-#: spyderlib/widgets/externalshell/namespacebrowser.py:211
+#: spyderlib/widgets/externalshell/namespacebrowser.py:229
 msgid "Exclude capitalized references"
 msgstr "Excluir variables que comienzan en mayúsculas"
 
 #: spyderlib/plugins/variableexplorer.py:35
-#: spyderlib/widgets/externalshell/namespacebrowser.py:204
+#: spyderlib/widgets/externalshell/namespacebrowser.py:222
 msgid "Exclude all-uppercase references"
 msgstr "Excluir variables en mayúsculas"
 
 #: spyderlib/plugins/variableexplorer.py:36
-#: spyderlib/widgets/externalshell/namespacebrowser.py:219
+#: spyderlib/widgets/externalshell/namespacebrowser.py:237
 msgid "Exclude unsupported data types"
 msgstr "Excluir tipos de datos no soportados"
 
 #: spyderlib/plugins/variableexplorer.py:42
-#: spyderlib/widgets/dicteditor.py:702
+#: spyderlib/widgets/dicteditor.py:708
 msgid "Truncate values"
 msgstr "Abreviar valores"
 
 #: spyderlib/plugins/variableexplorer.py:44
-#: spyderlib/widgets/dicteditor.py:706
+#: spyderlib/widgets/dicteditor.py:712
 msgid "Show arrays min/max"
 msgstr "Mostrar el máximo y mínimo de arreglos"
 
@@ -2538,11 +2605,11 @@ msgstr ""
 "proceso remoto. Esto impide transferir grandes cantidades de\n"
 "datos entre el proceso remoto y Spyder."
 
-#: spyderlib/plugins/variableexplorer.py:158
+#: spyderlib/plugins/variableexplorer.py:183
 msgid "Variable explorer"
 msgstr "Explorador de variables"
 
-#: spyderlib/plugins/workingdirectory.py:35
+#: spyderlib/plugins/workingdirectory.py:37
 msgid ""
 "The <b>global working directory</b> is the working directory for newly "
 "opened <i>consoles</i> (Python/IPython consoles and terminals), for the "
@@ -2554,19 +2621,19 @@ msgstr ""
 "terminales de comandos), para el <i>Explorador de archivos</i> y <i>Buscar "
 "en archivos</i> y para los nuevos archivos creados en el <i>Editor</i>."
 
-#: spyderlib/plugins/workingdirectory.py:44
+#: spyderlib/plugins/workingdirectory.py:46
 msgid "At startup, the global working directory is:"
 msgstr "Al inicio, el directorio de trabajo global es:"
 
-#: spyderlib/plugins/workingdirectory.py:48
+#: spyderlib/plugins/workingdirectory.py:50
 msgid "the same as in last session"
 msgstr "El mismo de la última sesión"
 
-#: spyderlib/plugins/workingdirectory.py:50
+#: spyderlib/plugins/workingdirectory.py:52
 msgid "At startup, Spyder will restore the global directory from last session"
 msgstr "Al inicio Spyder restaurará el directorio global de la última sesión"
 
-#: spyderlib/plugins/workingdirectory.py:56
+#: spyderlib/plugins/workingdirectory.py:58
 msgid "At startup, the global working directory will be the specified path"
 msgstr "Al inicio el directorio de trabajo global será el siguiente"
 
@@ -2600,16 +2667,16 @@ msgstr "Cuando se abra un archivo"
 msgid "When saving a file"
 msgstr "Cuando se guarde un archivo"
 
-#: spyderlib/plugins/workingdirectory.py:160
+#: spyderlib/plugins/workingdirectory.py:171
 msgid "Back"
 msgstr "Anterior"
 
-#: spyderlib/plugins/workingdirectory.py:168
-#: spyderlib/widgets/explorer.py:1004 spyderlib/widgets/importwizard.py:523
+#: spyderlib/plugins/workingdirectory.py:179
+#: spyderlib/widgets/explorer.py:1021 spyderlib/widgets/importwizard.py:529
 msgid "Next"
 msgstr "Siguiente"
 
-#: spyderlib/plugins/workingdirectory.py:181
+#: spyderlib/plugins/workingdirectory.py:190
 msgid ""
 "This is the working directory for newly\n"
 "opened consoles (Python/IPython consoles and\n"
@@ -2624,170 +2691,246 @@ msgstr ""
 "y Buscar en archivos y para los nuevos\n"
 "archivos creados en el Editor"
 
-#: spyderlib/plugins/workingdirectory.py:207
+#: spyderlib/plugins/workingdirectory.py:216
 msgid "Browse a working directory"
 msgstr "Seleccionar un directorio de trabajo"
 
-#: spyderlib/plugins/workingdirectory.py:213
+#: spyderlib/plugins/workingdirectory.py:222
 msgid "Set as current console's working directory"
 msgstr "Establece el directorio de trabajo para la terminal actual"
 
-#: spyderlib/plugins/workingdirectory.py:221
+#: spyderlib/plugins/workingdirectory.py:230
 msgid "Change to parent directory"
 msgstr "Moverse al directorio superior"
 
-#: spyderlib/plugins/workingdirectory.py:228
+#: spyderlib/plugins/workingdirectory.py:237
 msgid "Global working directory"
 msgstr "Directorio de trabajo global"
 
-#: spyderlib/spyder.py:120
+#: spyderlib/restart_app.py:129
+#, fuzzy
+msgid ""
+"It was not possible to close the previous Spyder instance.\n"
+"Restart aborted."
+msgstr "No fue posible ejecutar este archivo en una terminal del sistema"
+
+#: spyderlib/restart_app.py:131
+msgid ""
+"Spyder could not reset to factory defaults.\n"
+"Restart aborted."
+msgstr ""
+
+#: spyderlib/restart_app.py:133
+msgid ""
+"It was not possible to restart Spyder.\n"
+"Operation aborted."
+msgstr ""
+
+#: spyderlib/restart_app.py:135
+#, fuzzy
+msgid "Spyder exit error"
+msgstr "Editor de Spyder"
+
+#: spyderlib/restart_app.py:136
+#, fuzzy
+msgid "Spyder reset error"
+msgstr "Editor de Spyder"
+
+#: spyderlib/restart_app.py:137
+#, fuzzy
+msgid "Spyder restart error"
+msgstr "Tutorial de Spyder"
+
+#: spyderlib/restart_app.py:161
+msgid "Closing Spyder"
+msgstr ""
+
+#: spyderlib/restart_app.py:234
+#, fuzzy
+msgid "Resetting Spyder to defaults"
+msgstr "Restaurar los valores por defecto"
+
+#: spyderlib/restart_app.py:266
+#, fuzzy
+msgid "Restarting"
+msgstr "Restaurar"
+
+#: spyderlib/spyder.py:124
 msgid "Initializing..."
 msgstr "Inicializando..."
 
-#: spyderlib/spyder.py:244
+#: spyderlib/spyder.py:247
 msgid "Numpy and Scipy documentation"
 msgstr "Documentación de Numpy y Scipy"
 
-#: spyderlib/spyder.py:246 spyderlib/spyder.py:949
+#: spyderlib/spyder.py:249 spyderlib/spyder.py:1084
 msgid "Matplotlib documentation"
 msgstr "Documentación de Matplotlib"
 
-#: spyderlib/spyder.py:249
+#: spyderlib/spyder.py:252
 msgid "PyQt4 Reference Guide"
 msgstr "Manual de referencia de PyQt4"
 
-#: spyderlib/spyder.py:252
+#: spyderlib/spyder.py:255
 msgid "PyQt4 API Reference"
 msgstr "Referencia del API de PyQt4"
 
-#: spyderlib/spyder.py:254
+#: spyderlib/spyder.py:257
 msgid "Python(x,y)"
 msgstr "Python(x,y)"
 
-#: spyderlib/spyder.py:256
+#: spyderlib/spyder.py:259
 msgid "WinPython"
 msgstr "WinPython"
 
-#: spyderlib/spyder.py:293
+#: spyderlib/spyder.py:305
 msgid "Reload last session"
 msgstr "Recargar la última sesión"
 
-#: spyderlib/spyder.py:297
+#: spyderlib/spyder.py:309
 msgid "Load session..."
 msgstr "Cargar sesión..."
 
-#: spyderlib/spyder.py:300
+#: spyderlib/spyder.py:312
 msgid "Load Spyder session"
 msgstr "Cargar sesión de Spyder"
 
-#: spyderlib/spyder.py:302
+#: spyderlib/spyder.py:314
 msgid "Save session and quit..."
 msgstr "Guardar sesión y salir..."
 
-#: spyderlib/spyder.py:305
+#: spyderlib/spyder.py:317
 msgid "Save current session and quit application"
 msgstr "Guardar sesión actual y salir de la aplicación"
 
-#: spyderlib/spyder.py:483
+#: spyderlib/spyder.py:530
 msgid "Close current pane"
 msgstr "Cerrar panel actual"
 
-#: spyderlib/spyder.py:489
+#: spyderlib/spyder.py:535
+msgid "Lock panes"
+msgstr ""
+
+#: spyderlib/spyder.py:542
+#, fuzzy
+msgid "Use next layout"
+msgstr "Restablecer la disposición de componentes"
+
+#: spyderlib/spyder.py:546
+#, fuzzy
+msgid "Use previous layout"
+msgstr "Restablecer la disposición de componentes"
+
+#: spyderlib/spyder.py:555
 msgid "&Find text"
 msgstr "&Buscar texto"
 
-#: spyderlib/spyder.py:494
+#: spyderlib/spyder.py:560
 msgid "Find &next"
 msgstr "Buscar &siguiente"
 
-#: spyderlib/spyder.py:500
+#: spyderlib/spyder.py:567
 msgid "Find &previous"
 msgstr "Buscar &anterior"
 
-#: spyderlib/spyder.py:505
+#: spyderlib/spyder.py:573
 msgid "&Replace text"
 msgstr "&Reemplazar texto"
 
-#: spyderlib/spyder.py:520 spyderlib/widgets/sourcecode/codeeditor.py:2268
+#: spyderlib/spyder.py:580 spyderlib/widgets/editor.py:339
+#, fuzzy
+msgid "File switcher..."
+msgstr "Archivo..."
+
+#: spyderlib/spyder.py:582
+msgid "Fast switch between files"
+msgstr ""
+
+#: spyderlib/spyder.py:600 spyderlib/widgets/sourcecode/codeeditor.py:2425
 msgid "Undo"
 msgstr "Deshacer"
 
-#: spyderlib/spyder.py:522 spyderlib/widgets/sourcecode/codeeditor.py:2271
+#: spyderlib/spyder.py:602 spyderlib/widgets/sourcecode/codeeditor.py:2428
 msgid "Redo"
 msgstr "Rehacer"
 
-#: spyderlib/spyder.py:523 spyderlib/widgets/arrayeditor.py:392
+#: spyderlib/spyder.py:604 spyderlib/widgets/arrayeditor.py:392
 #: spyderlib/widgets/dataframeeditor.py:418
-#: spyderlib/widgets/dicteditor.py:674 spyderlib/widgets/shell.py:118
-#: spyderlib/widgets/sourcecode/codeeditor.py:2277
+#: spyderlib/widgets/dicteditor.py:680 spyderlib/widgets/shell.py:126
+#: spyderlib/widgets/sourcecode/codeeditor.py:2434
 msgid "Copy"
 msgstr "Copiar"
 
-#: spyderlib/spyder.py:525 spyderlib/widgets/shell.py:114
-#: spyderlib/widgets/sourcecode/codeeditor.py:2274
+#: spyderlib/spyder.py:606 spyderlib/widgets/shell.py:122
+#: spyderlib/widgets/sourcecode/codeeditor.py:2431
 msgid "Cut"
 msgstr "Cortar"
 
-#: spyderlib/spyder.py:526 spyderlib/widgets/dicteditor.py:671
-#: spyderlib/widgets/shell.py:122
-#: spyderlib/widgets/sourcecode/codeeditor.py:2280
+#: spyderlib/spyder.py:608 spyderlib/widgets/dicteditor.py:677
+#: spyderlib/widgets/shell.py:130
+#: spyderlib/widgets/sourcecode/codeeditor.py:2437
 msgid "Paste"
 msgstr "Pegar"
 
-#: spyderlib/spyder.py:528 spyderlib/widgets/explorer.py:461
-#: spyderlib/widgets/projectexplorer.py:1003 spyderlib/widgets/shell.py:131
-#: spyderlib/widgets/sourcecode/codeeditor.py:2283
+#: spyderlib/spyder.py:610 spyderlib/widgets/explorer.py:470
+#: spyderlib/widgets/projectexplorer.py:1015 spyderlib/widgets/shell.py:139
+#: spyderlib/widgets/sourcecode/codeeditor.py:2440
 msgid "Delete"
 msgstr "Eliminar"
 
-#: spyderlib/spyder.py:531 spyderlib/widgets/shell.py:135
-#: spyderlib/widgets/sourcecode/codeeditor.py:2287
+#: spyderlib/spyder.py:614 spyderlib/widgets/shell.py:143
+#: spyderlib/widgets/sourcecode/codeeditor.py:2444
 msgid "Select All"
 msgstr "Seleccionar todo"
 
-#: spyderlib/spyder.py:580
+#: spyderlib/spyder.py:664
 msgid "C&onsoles"
 msgstr "&Terminales"
 
-#: spyderlib/spyder.py:586
+#: spyderlib/spyder.py:670
 msgid "&View"
 msgstr "&Ver"
 
-#: spyderlib/spyder.py:589
+#: spyderlib/spyder.py:673
 msgid "&Help"
 msgstr "A&yuda"
 
-#: spyderlib/spyder.py:594
+#: spyderlib/spyder.py:678
 msgid "Welcome to Spyder!"
 msgstr "Bienvenido a Spyder!"
 
-#: spyderlib/spyder.py:599
+#: spyderlib/spyder.py:683
 msgid "Pre&ferences"
 msgstr "Pre&ferencias"
 
-#: spyderlib/spyder.py:606 spyderlib/widgets/pathmanager.py:45
-#: spyderlib/widgets/projectexplorer.py:594
+#: spyderlib/spyder.py:690 spyderlib/widgets/pathmanager.py:48
+#: spyderlib/widgets/projectexplorer.py:598
 msgid "PYTHONPATH manager"
 msgstr "Administrador del PYTHONPATH"
 
-#: spyderlib/spyder.py:609
+#: spyderlib/spyder.py:693
 msgid "Python Path Manager"
 msgstr "Manejador de rutas de Python"
 
-#: spyderlib/spyder.py:612
+#: spyderlib/spyder.py:696
 msgid "Update module names list"
 msgstr "Actualizar la lista de nombres de módulos"
 
-#: spyderlib/spyder.py:614
+#: spyderlib/spyder.py:699
 msgid "Refresh list of module names available in PYTHONPATH"
 msgstr ""
 "Actualiza la lista de nombres de los módulos disponibles en su PYTHONPATH"
 
-#: spyderlib/spyder.py:619
+#: spyderlib/spyder.py:702
+#, fuzzy
+msgid "Reset Spyder to factory defaults"
+msgstr "Restaurar los valores por defecto"
+
+#: spyderlib/spyder.py:707
 msgid "Current user environment variables..."
 msgstr "Variables de entorno del usuario actual..."
 
-#: spyderlib/spyder.py:621
+#: spyderlib/spyder.py:709
 msgid ""
 "Show and edit current user environment variables in Windows registry (i.e. "
 "for all sessions)"
@@ -2797,55 +2940,55 @@ msgstr ""
 "registro de Windows (es decir,\n"
 "para todas las sesiones)"
 
-#: spyderlib/spyder.py:629 spyderlib/spyder.py:1043
+#: spyderlib/spyder.py:718 spyderlib/spyder.py:1178
 msgid "External Tools"
 msgstr "Herramientas externas"
 
-#: spyderlib/spyder.py:633
+#: spyderlib/spyder.py:722
 msgid "Python(x,y) launcher"
 msgstr "Lanzador de Python(x,y)"
 
-#: spyderlib/spyder.py:640
+#: spyderlib/spyder.py:729
 msgid "WinPython control panel"
 msgstr "Panel de control de WinPython"
 
-#: spyderlib/spyder.py:649
+#: spyderlib/spyder.py:738
 msgid "Qt Designer"
 msgstr "Diseñador de interfaces de Qt"
 
-#: spyderlib/spyder.py:654
+#: spyderlib/spyder.py:743
 msgid "Qt Linguist"
 msgstr "Traductor de aplicaciones de Qt"
 
-#: spyderlib/spyder.py:660
+#: spyderlib/spyder.py:749
 msgid "Qt examples"
 msgstr "Ejemplos de Qt"
 
-#: spyderlib/spyder.py:678
+#: spyderlib/spyder.py:770
 msgid "guidata examples"
 msgstr "Ejemplos de guidata"
 
-#: spyderlib/spyder.py:686
+#: spyderlib/spyder.py:781
 msgid "guiqwt examples"
 msgstr "Ejemplos de guiqwt"
 
-#: spyderlib/spyder.py:691
+#: spyderlib/spyder.py:786
 msgid "Sift"
 msgstr "Sift"
 
-#: spyderlib/spyder.py:699
+#: spyderlib/spyder.py:796
 msgid "ViTables"
 msgstr "ViTables"
 
-#: spyderlib/spyder.py:713
+#: spyderlib/spyder.py:810
 msgid "Fullscreen mode"
 msgstr "Modo a pantalla completa"
 
-#: spyderlib/spyder.py:725
+#: spyderlib/spyder.py:822
 msgid "Main toolbar"
 msgstr "Barra principal"
 
-#: spyderlib/spyder.py:734
+#: spyderlib/spyder.py:831
 msgid ""
 "Spyder Internal Console\n"
 "\n"
@@ -2866,163 +3009,195 @@ msgstr ""
 "\n"
 "Por favor no ejecuta su código en esta terminal\n"
 
-#: spyderlib/spyder.py:751
+#: spyderlib/spyder.py:848
 msgid "Loading object inspector..."
 msgstr "Cargando el inspector de objetos..."
 
-#: spyderlib/spyder.py:758
+#: spyderlib/spyder.py:855
 msgid "Loading outline explorer..."
 msgstr "Cargando el explorador de código..."
 
-#: spyderlib/spyder.py:766
+#: spyderlib/spyder.py:863
 msgid "Loading editor..."
 msgstr "Cargando el editor..."
 
-#: spyderlib/spyder.py:791
+#: spyderlib/spyder.py:874
+#, fuzzy
+msgid "&Restart"
+msgstr "Restaurar"
+
+#: spyderlib/spyder.py:876
+#, fuzzy
+msgid "Restart"
+msgstr "Restaurar"
+
+#: spyderlib/spyder.py:895
 msgid "Loading file explorer..."
 msgstr "Cargando el explorador de archivos..."
 
-#: spyderlib/spyder.py:798
+#: spyderlib/spyder.py:902
 msgid "Loading history plugin..."
 msgstr "Cargando el historial..."
 
-#: spyderlib/spyder.py:809
+#: spyderlib/spyder.py:913
 msgid "Loading online help..."
 msgstr "Cargando la ayuda en línea..."
 
-#: spyderlib/spyder.py:815
+#: spyderlib/spyder.py:919
 msgid "Loading project explorer..."
 msgstr "Cargando el explorador de proyectos..."
 
-#: spyderlib/spyder.py:826
+#: spyderlib/spyder.py:930
 msgid "Loading external console..."
 msgstr "Cargando la terminal externa..."
 
-#: spyderlib/spyder.py:835
+#: spyderlib/spyder.py:939
 msgid "Loading namespace browser..."
 msgstr "Cargando el explorador de variables..."
 
-#: spyderlib/spyder.py:842
+#: spyderlib/spyder.py:946
 msgid "Loading IPython console..."
 msgstr "Cargando la terminal de IPython..."
 
-#: spyderlib/spyder.py:853
+#: spyderlib/spyder.py:956
 msgid "Setting up main window..."
 msgstr "Construyendo la ventana principal..."
 
-#: spyderlib/spyder.py:856
+#: spyderlib/spyder.py:959
 msgid "Optional dependencies..."
 msgstr "Dependencias opcionales..."
 
-#: spyderlib/spyder.py:860
+#: spyderlib/spyder.py:963
 msgid "Report issue..."
 msgstr "Reportar un problema..."
 
-#: spyderlib/spyder.py:864
+#: spyderlib/spyder.py:967
 msgid "Spyder support..."
 msgstr "Obtener soporte para Spyder"
 
-#: spyderlib/spyder.py:887
+#: spyderlib/spyder.py:970
+msgid "Check for updates..."
+msgstr ""
+
+#: spyderlib/spyder.py:993
 msgid "Spyder documentation"
 msgstr "Documentación de Spyder"
 
-#: spyderlib/spyder.py:889
+#: spyderlib/spyder.py:997
 msgid "Spyder tutorial"
 msgstr "Tutorial de Spyder"
 
-#: spyderlib/spyder.py:896
+#: spyderlib/spyder.py:1002
+#, fuzzy
+msgid "Interactive tours"
+msgstr "Introspección"
+
+#: spyderlib/spyder.py:1031
 msgid "Python documentation"
 msgstr "Documentación de Python"
 
-#: spyderlib/spyder.py:902 spyderlib/spyder.py:941
+#: spyderlib/spyder.py:1037 spyderlib/spyder.py:1076
 msgid "IPython documentation"
 msgstr "Documentación de IPython"
 
-#: spyderlib/spyder.py:903
+#: spyderlib/spyder.py:1038
 msgid "Intro to IPython"
 msgstr "Ayuda básica"
 
-#: spyderlib/spyder.py:905
+#: spyderlib/spyder.py:1040
 msgid "Quick reference"
 msgstr "Referencia rápida"
 
-#: spyderlib/spyder.py:907
+#: spyderlib/spyder.py:1042
 msgid "Console help"
 msgstr "Ayuda de la terminal"
 
-#: spyderlib/spyder.py:939
+#: spyderlib/spyder.py:1074
 msgid "Python(x,y) documentation folder"
 msgstr "Carpeta de documentación de Python(x,y)"
 
-#: spyderlib/spyder.py:943
+#: spyderlib/spyder.py:1078
 msgid "guidata documentation"
 msgstr "Documentación de guidata"
 
-#: spyderlib/spyder.py:946
+#: spyderlib/spyder.py:1081
 msgid "guiqwt documentation"
 msgstr "Documentación de guiqwt"
 
-#: spyderlib/spyder.py:952
+#: spyderlib/spyder.py:1087
 msgid "NumPy documentation"
 msgstr "Documentación de NumPy"
 
-#: spyderlib/spyder.py:954
+#: spyderlib/spyder.py:1089
 msgid "NumPy reference guide"
 msgstr "Manual de referencia de NumPy"
 
-#: spyderlib/spyder.py:956
+#: spyderlib/spyder.py:1091
 msgid "NumPy user guide"
 msgstr "Guía del usuario de Numpy"
 
-#: spyderlib/spyder.py:958
+#: spyderlib/spyder.py:1093
 msgid "SciPy documentation"
 msgstr "Documentación de SciPy"
 
-#: spyderlib/spyder.py:965
+#: spyderlib/spyder.py:1100
 msgid "Installed Python modules"
 msgstr "Módulos instalados de Python"
 
-#: spyderlib/spyder.py:969
+#: spyderlib/spyder.py:1104
 msgid "Online documentation"
 msgstr "Documentación en línea"
 
-#: spyderlib/spyder.py:979
+#: spyderlib/spyder.py:1116
 msgid "Qt documentation"
 msgstr "Documentación de Qt"
 
-#: spyderlib/spyder.py:985
+#: spyderlib/spyder.py:1122
 msgid "About %s..."
 msgstr "Acerca de %s..."
 
-#: spyderlib/spyder.py:1006
+#: spyderlib/spyder.py:1146
 msgid "Panes"
 msgstr "Paneles"
 
-#: spyderlib/spyder.py:1007
+#: spyderlib/spyder.py:1147
 msgid "Toolbars"
 msgstr "Barras de herramientas"
 
-#: spyderlib/spyder.py:1010
-msgid "Reset window layout"
-msgstr "Restablecer la disposición de componentes"
-
-#: spyderlib/spyder.py:1012
-msgid "Custom window layouts"
+#: spyderlib/spyder.py:1148
+#, fuzzy
+msgid "Window layouts"
 msgstr "Disposiciones personalizadas de componentes"
 
-#: spyderlib/spyder.py:1018
-msgid "Switch to/from layout %d"
-msgstr "Cambiarse a la disposición %d"
-
-#: spyderlib/spyder.py:1023
-msgid "Set layout %d"
-msgstr "Establecer la disposición %d"
+#: spyderlib/spyder.py:1157 spyderlib/spyder.py:1910 spyderlib/spyder.py:1911
+#, fuzzy
+msgid "Show toolbars"
+msgstr "Mostrar barra de herramientas"
 
-#: spyderlib/spyder.py:1031
+#: spyderlib/spyder.py:1171
 msgid "Attached console window (debugging)"
 msgstr "Ventana de terminal anexa (para depuración)"
 
-#: spyderlib/spyder.py:1332
+#: spyderlib/spyder.py:1756
+msgid "Spyder Default Layout"
+msgstr ""
+
+#: spyderlib/spyder.py:1774 spyderlib/spyder.py:1785
+#, fuzzy
+msgid "Save current layout"
+msgstr "Guardar el archivo actual"
+
+#: spyderlib/spyder.py:1778 spyderlib/spyder.py:1787
+#, fuzzy
+msgid "Layout preferences"
+msgstr "Preferencias"
+
+#: spyderlib/spyder.py:1782
+#, fuzzy
+msgid "Reset to spyder default"
+msgstr "Restaurar los valores por defecto"
+
+#: spyderlib/spyder.py:1804
 msgid ""
 "Window layout will be reset to default settings: this affects window "
 "position, size and dockwidgets.\n"
@@ -3032,44 +3207,211 @@ msgstr ""
 "Esto afecta a la posición y tamaño de la ventana y los componentes.\n"
 "¿Desea continuar?"
 
-#: spyderlib/spyder.py:1350
-msgid "Quick switch layout #%d has not yet been defined."
+#: spyderlib/spyder.py:1826
+msgid ""
+"Layout <b>%s</b> will be                                                "
+"overwritten. Do you want to                                                "
+"continue?"
+msgstr ""
+
+#: spyderlib/spyder.py:1889
+#, fuzzy
+msgid "Quick switch layout #%s has not yet been defined."
 msgstr "Aún no se ha definido la disposición de componentes #%d"
 
-#: spyderlib/spyder.py:1602 spyderlib/spyder.py:1603
+#: spyderlib/spyder.py:1907 spyderlib/spyder.py:1908
+#, fuzzy
+msgid "Hide toolbars"
+msgstr "Barra de archivo"
+
+#: spyderlib/spyder.py:2229 spyderlib/spyder.py:2230
 msgid "Maximize current pane"
 msgstr "Maximizar el panel actual"
 
-#: spyderlib/spyder.py:1606
+#: spyderlib/spyder.py:2233
 msgid "Restore current pane"
 msgstr "Restaurar el panel actual"
 
-#: spyderlib/spyder.py:1607
+#: spyderlib/spyder.py:2234
 msgid "Restore pane to its original size"
 msgstr "Restaurar el panel a su tamaño original"
 
-#: spyderlib/spyder.py:1686
+#: spyderlib/spyder.py:2318
 msgid "About %s"
 msgstr "Acerca de %s"
 
-#: spyderlib/spyder.py:1851
+#: spyderlib/spyder.py:2502
 msgid "Running an external system terminal is not supported on platform %s."
 msgstr ""
 "Ejecutar en una terminal externa del sistema no está soportado en la "
 "plataforma %s."
 
-#: spyderlib/spyder.py:2066
+#: spyderlib/spyder.py:2721
 msgid "Open session"
 msgstr "Abrir sesión"
 
-#: spyderlib/spyder.py:2067 spyderlib/spyder.py:2078
+#: spyderlib/spyder.py:2722 spyderlib/spyder.py:2734
 msgid "Spyder sessions"
 msgstr "Sesiones de Spyder"
 
-#: spyderlib/spyder.py:2077
+#: spyderlib/spyder.py:2733
 msgid "Save session"
 msgstr "Guardar sesión"
 
+#: spyderlib/spyder.py:2775
+#, fuzzy
+msgid ""
+"Spyder will restart and reset to default settings: <br><br>Do you want to "
+"continue?"
+msgstr ""
+"El siguiente directorio no está vacío:<br><b>%s</b><br><br>¿Desear continuar?"
+
+#: spyderlib/spyder.py:2871 spyderlib/widgets/helperwidgets.py:144
+#, fuzzy
+msgid "Spyder updates"
+msgstr "Archivos de datos de Spyder"
+
+#: spyderlib/spyder.py:2890
+msgid ""
+"<b>Spyder %s is available!</b> <br><br>Please use your package manager to "
+"update Spyder or go to our <a href=\"%s\">Releases</a> page to download this "
+"new version. <br><br>If you are not sure how to proceed to update Spyder "
+"please refer to our  <a href=\"%s\">Installation</a> instructions."
+msgstr ""
+
+#: spyderlib/spyder.py:2902
+#, fuzzy
+msgid "Spyder is up to date."
+msgstr "Obtener soporte para Spyder"
+
+#: spyderlib/tour.py:121
+#, fuzzy
+msgid "Welcome to the Introduction tour"
+msgstr "Bienvenido a Spyder!"
+
+#: spyderlib/tour.py:122
+msgid ""
+"<b>Spyder</b> is a powerful Interactive Development Environment (or IDE) for "
+"the Python programming language.<br><br>Here we are going to guide you "
+"through its most important features.<br><br>Please use the arrow keys or "
+"click on the buttons below to move along the tour."
+msgstr ""
+
+#: spyderlib/tour.py:131
+#, fuzzy
+msgid "The Editor"
+msgstr "Editor de texto"
+
+#: spyderlib/tour.py:132
+msgid ""
+"This is the pane where you write Python code before evaluating it. You can "
+"get automatic suggestions and completions while writing, by pressing the "
+"<b>Tab</b> key next to a given text.<br><br>The Editor comes with a line "
+"number area (highlighted here in red), where Spyder shows warnings and "
+"syntax errors. They can help you to detect potential problems before running "
+"the code.<br><br>You can also set debug breakpoints in the line number area, "
+"by doing a double click next to a non-empty line."
+msgstr ""
+
+#: spyderlib/tour.py:147
+#, fuzzy
+msgid "The IPython console"
+msgstr "Terminal de IPython"
+
+#: spyderlib/tour.py:164
+#, fuzzy
+msgid "The Variable Explorer"
+msgstr "Explorador de variables"
+
+#: spyderlib/tour.py:165
+msgid ""
+"In this pane you can view and edit the variables generated during the "
+"execution of a program, or those entered directly in one of Spyder consoles."
+"<br><br>As you can see, the Variable Explorer is showing the variables "
+"generated during the last step of this tour. By doing a double-click on any "
+"of them, a new window will be opened, where you can inspect and modify their "
+"contents."
+msgstr ""
+
+#: spyderlib/tour.py:177
+#, fuzzy
+msgid "The Python console"
+msgstr "Terminal de IPython"
+
+#: spyderlib/tour.py:178
+msgid ""
+"You can also run your code on a Python console. These consoles are useful "
+"because they let you run a file in a console dedicated only to it.To select "
+"this behavior, please press the <b>F6</b> key.<br><br>By pressing the button "
+"below and then focusing the Variable Explorer, you will notice that Python "
+"consoles are also connected to that pane, and that the Variable Explorer "
+"only shows the variables of the currently focused console."
+msgstr ""
+
+#: spyderlib/tour.py:192
+#, fuzzy
+msgid "The Object Inspector"
+msgstr "Inspector de objetos"
+
+#: spyderlib/tour.py:193
+msgid ""
+"This pane displays documentation of the functions, classes, methods or "
+"modules you are currently using in the Editor or the Consoles.<br><br>To use "
+"it, you need to press <b>Ctrl+I</b> in front of an object. If that object "
+"has some documentation associated with it, it will be displayed here."
+msgstr ""
+
+#: spyderlib/tour.py:203
+#, fuzzy
+msgid "The File Explorer"
+msgstr "Explorador de archivos"
+
+#: spyderlib/tour.py:204
+msgid ""
+"This pane lets you navigate through the directories and files present in "
+"your computer.<br><br>You can also open any of these files with its "
+"corresponding application, by doing a double click on it.<br><br>There is "
+"one exception to this rule: plain-text files will always be opened in the "
+"Spyder Editor."
+msgstr ""
+
+#: spyderlib/tour.py:214
+#, fuzzy
+msgid "The History Log"
+msgstr "Historial de comandos"
+
+#: spyderlib/tour.py:215
+msgid ""
+"This pane records all commands introduced in the Python and IPython consoles."
+msgstr ""
+
+#: spyderlib/tour.py:263
+msgid "<b>Spyder</b> is an interactive development environment based on bla"
+msgstr ""
+
+#: spyderlib/tour.py:267
+#, fuzzy
+msgid "Welcome to Spyder introduction tour"
+msgstr "Bienvenido a Spyder!"
+
+#: spyderlib/tour.py:268
+msgid "Spyder is an interactive development environment based on bla"
+msgstr ""
+
+#: spyderlib/tour.py:273
+#, fuzzy
+msgid "Introduction tour"
+msgstr "Introspección"
+
+#: spyderlib/tour.py:274
+msgid "New features in version 3.0"
+msgstr ""
+
+#: spyderlib/tour.py:821
+#, fuzzy
+msgid "Go to step: "
+msgstr "Ir a la línea"
+
 #: spyderlib/utils/codeanalysis.py:92
 msgid "Real-time code analysis on the Editor"
 msgstr "Análisis del código en tiempo real en el Editor"
@@ -3078,7 +3420,7 @@ msgstr "Análisis del código en tiempo real en el Editor"
 msgid "Real-time code style analysis on the Editor"
 msgstr "Análisis de estilo del código en el Editor"
 
-#: spyderlib/utils/environ.py:95
+#: spyderlib/utils/environ.py:96
 msgid ""
 "Module <b>pywin32 was not found</b>.<br>Please restart this Windows "
 "<i>session</i> (not the computer) for changes to take effect."
@@ -3087,7 +3429,7 @@ msgstr ""
 "<i>sesión</i> de Windows (no el computador) para que los cambios surtan "
 "efecto."
 
-#: spyderlib/utils/environ.py:108
+#: spyderlib/utils/environ.py:109
 msgid ""
 "If you accept changes, this will modify the current user environment "
 "variables directly <b>in Windows registry</b>. Use it with precautions, at "
@@ -3105,8 +3447,8 @@ msgstr ""
 "forma reinicie la aplicación desde la cual lo inició, como por ejemplo "
 "<i>Python(x,y) Home</i>)"
 
-#: spyderlib/utils/inspector/sphinxify.py:209
-#: spyderlib/utils/inspector/sphinxify.py:219
+#: spyderlib/utils/inspector/sphinxify.py:212
+#: spyderlib/utils/inspector/sphinxify.py:222
 msgid ""
 "It was not possible to generate rich text help for this object.</br>Please "
 "see it in plain text."
@@ -3122,59 +3464,59 @@ msgstr "(Experimental) Completado del código y ayuda en el Editor"
 msgid "Editor's code completion, go-to-definition and help"
 msgstr "Completado del código y ayuda en el Editor"
 
-#: spyderlib/utils/iofuncs.py:496
+#: spyderlib/utils/iofuncs.py:482
 msgid "Supported files"
 msgstr "Archivos soportados"
 
-#: spyderlib/utils/iofuncs.py:498
+#: spyderlib/utils/iofuncs.py:484
 msgid "All files (*.*)"
 msgstr "Todos los archivos (*.*)"
 
-#: spyderlib/utils/iofuncs.py:508
+#: spyderlib/utils/iofuncs.py:494
 msgid "Spyder data files"
 msgstr "Archivos de datos de Spyder"
 
-#: spyderlib/utils/iofuncs.py:510 spyderlib/widgets/dicteditor.py:1041
+#: spyderlib/utils/iofuncs.py:496 spyderlib/widgets/dicteditor.py:1056
 msgid "NumPy arrays"
 msgstr "Arreglos de NumPy"
 
-#: spyderlib/utils/iofuncs.py:511
+#: spyderlib/utils/iofuncs.py:497
 msgid "NumPy zip arrays"
 msgstr "Arreglos comprimidos de NumPy"
 
-#: spyderlib/utils/iofuncs.py:512
+#: spyderlib/utils/iofuncs.py:498
 msgid "Matlab files"
 msgstr "Archivos de Matlab"
 
-#: spyderlib/utils/iofuncs.py:513
+#: spyderlib/utils/iofuncs.py:499
 msgid "CSV text files"
 msgstr "Archivos de texto CSV"
 
-#: spyderlib/utils/iofuncs.py:515
+#: spyderlib/utils/iofuncs.py:501
 msgid "JPEG images"
 msgstr "Imágenes JPEG"
 
-#: spyderlib/utils/iofuncs.py:516
+#: spyderlib/utils/iofuncs.py:502
 msgid "PNG images"
 msgstr "Imágenes PNG"
 
-#: spyderlib/utils/iofuncs.py:517
+#: spyderlib/utils/iofuncs.py:503
 msgid "GIF images"
 msgstr "Imágenes GIF"
 
-#: spyderlib/utils/iofuncs.py:518
+#: spyderlib/utils/iofuncs.py:504
 msgid "TIFF images"
 msgstr "Imágenes TIFF"
 
-#: spyderlib/utils/iofuncs.py:519 spyderlib/utils/iofuncs.py:520
+#: spyderlib/utils/iofuncs.py:505 spyderlib/utils/iofuncs.py:506
 msgid "Pickle files"
 msgstr "Archivos pickle"
 
-#: spyderlib/utils/iofuncs.py:521
+#: spyderlib/utils/iofuncs.py:507
 msgid "JSON files"
 msgstr "Archivos JSON"
 
-#: spyderlib/utils/iofuncs.py:540 spyderlib/utils/iofuncs.py:547
+#: spyderlib/utils/iofuncs.py:526 spyderlib/utils/iofuncs.py:533
 msgid "<b>Unsupported file type '%s'</b>"
 msgstr "<b>Tipo de archivo no soportado '%s'</b>"
 
@@ -3182,40 +3524,72 @@ msgstr "<b>Tipo de archivo no soportado '%s'</b>"
 msgid "It was not possible to run this file in an external terminal"
 msgstr "No fue posible ejecutar este archivo en una terminal del sistema"
 
-#: spyderlib/widgets/arrayeditor.py:452 spyderlib/widgets/arrayeditor.py:485
-#: spyderlib/widgets/dataframeeditor.py:507
-#: spyderlib/widgets/dataframeeditor.py:549
+#: spyderlib/widgets/arraybuilder.py:162
+msgid ""
+"\n"
+"           <b>Numpy Array/Matrix Helper</b><br>\n"
+"           Type an array in Matlab    : <code>[1 2;3 4]</code><br>\n"
+"           or Spyder simplified syntax : <code>1 2;3 4</code>\n"
+"           <br><br>\n"
+"           Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n"
+"           <br><br>\n"
+"           <b>Hint:</b><br>\n"
+"           Use two spaces or two tabs to generate a ';'.\n"
+"           "
+msgstr ""
+
+#: spyderlib/widgets/arraybuilder.py:173
+msgid ""
+"\n"
+"           <b>Numpy Array/Matrix Helper</b><br>\n"
+"           Enter an array in the table. <br>\n"
+"           Use Tab to move between cells.\n"
+"           <br><br>\n"
+"           Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n"
+"           <br><br>\n"
+"           <b>Hint:</b><br>\n"
+"           Use two tabs at the end of a row to move to the next row.\n"
+"           "
+msgstr ""
+
+#: spyderlib/widgets/arraybuilder.py:337
+msgid "Array dimensions not valid"
+msgstr ""
+
+#: spyderlib/widgets/arrayeditor.py:453 spyderlib/widgets/arrayeditor.py:486
+#: spyderlib/widgets/dataframeeditor.py:508
+#: spyderlib/widgets/dataframeeditor.py:548
 msgid "Format"
 msgstr "Formato"
 
-#: spyderlib/widgets/arrayeditor.py:457
-#: spyderlib/widgets/dataframeeditor.py:511
+#: spyderlib/widgets/arrayeditor.py:458
+#: spyderlib/widgets/dataframeeditor.py:512
 msgid "Resize"
 msgstr "Redimensionar"
 
-#: spyderlib/widgets/arrayeditor.py:486
-#: spyderlib/widgets/dataframeeditor.py:550
+#: spyderlib/widgets/arrayeditor.py:487
+#: spyderlib/widgets/dataframeeditor.py:549
 msgid "Float formatting"
 msgstr "Formato de punto flotante"
 
-#: spyderlib/widgets/arrayeditor.py:493
-#: spyderlib/widgets/dataframeeditor.py:558 spyderlib/widgets/explorer.py:578
-#: spyderlib/widgets/explorer.py:681
-#: spyderlib/widgets/externalshell/pythonshell.py:537
-#: spyderlib/widgets/externalshell/systemshell.py:93
+#: spyderlib/widgets/arrayeditor.py:494
+#: spyderlib/widgets/dataframeeditor.py:557 spyderlib/widgets/explorer.py:587
+#: spyderlib/widgets/explorer.py:689
+#: spyderlib/widgets/externalshell/pythonshell.py:553
+#: spyderlib/widgets/externalshell/systemshell.py:99
 msgid "Error"
 msgstr "Error"
 
-#: spyderlib/widgets/arrayeditor.py:494
-#: spyderlib/widgets/dataframeeditor.py:559
+#: spyderlib/widgets/arrayeditor.py:495
+#: spyderlib/widgets/dataframeeditor.py:558
 msgid "Format (%s) is incorrect"
 msgstr "El formato (%s) es incorrecto"
 
-#: spyderlib/widgets/arrayeditor.py:528
+#: spyderlib/widgets/arrayeditor.py:529
 msgid "Array is empty"
 msgstr "El arreglo está vacío"
 
-#: spyderlib/widgets/arrayeditor.py:531
+#: spyderlib/widgets/arrayeditor.py:532
 msgid "Arrays with more than 3 dimensions are not supported"
 msgstr "Los arreglos de más de tres dimensiones no están soportados"
 
@@ -3240,10 +3614,11 @@ msgid "%s are currently not supported"
 msgstr "%s no están soportados por el momento"
 
 #: spyderlib/widgets/arrayeditor.py:554
+#, fuzzy
 msgid "NumPy array"
 msgstr "Arreglos de NumPy"
 
-#: spyderlib/widgets/arrayeditor.py:556 spyderlib/widgets/arrayeditor.py:713
+#: spyderlib/widgets/arrayeditor.py:556 spyderlib/widgets/arrayeditor.py:710
 msgid "Array editor"
 msgstr "Editor de arreglos"
 
@@ -3251,35 +3626,35 @@ msgstr "Editor de arreglos"
 msgid "read only"
 msgstr "sólo lectura"
 
-#: spyderlib/widgets/arrayeditor.py:589
+#: spyderlib/widgets/arrayeditor.py:588
 msgid "Record array fields:"
 msgstr "Campos del arreglo de records:"
 
-#: spyderlib/widgets/arrayeditor.py:601
+#: spyderlib/widgets/arrayeditor.py:600
 msgid "Data"
 msgstr "Datos"
 
-#: spyderlib/widgets/arrayeditor.py:601
+#: spyderlib/widgets/arrayeditor.py:600
 msgid "Mask"
 msgstr "Máscara"
 
-#: spyderlib/widgets/arrayeditor.py:601
+#: spyderlib/widgets/arrayeditor.py:600
 msgid "Masked data"
 msgstr "Datos enmascarados"
 
-#: spyderlib/widgets/arrayeditor.py:614
+#: spyderlib/widgets/arrayeditor.py:611
 msgid "Axis:"
 msgstr "Eje:"
 
-#: spyderlib/widgets/arrayeditor.py:619
+#: spyderlib/widgets/arrayeditor.py:616
 msgid "Index:"
 msgstr "Índice:"
 
-#: spyderlib/widgets/arrayeditor.py:633
+#: spyderlib/widgets/arrayeditor.py:629
 msgid "<u>Warning</u>: changes are applied separately"
 msgstr "<u>Advertencia</u>: los cambios son aplicados de forma separada"
 
-#: spyderlib/widgets/arrayeditor.py:634
+#: spyderlib/widgets/arrayeditor.py:630
 msgid ""
 "For performance reasons, changes applied to masked array won't be reflected "
 "in array's data (and vice-versa)."
@@ -3289,13 +3664,13 @@ msgstr ""
 "verán reflejados en los datos del arreglo\n"
 "(y viceversa)."
 
-#: spyderlib/widgets/browser.py:30
-#: spyderlib/widgets/sourcecode/codeeditor.py:2311
+#: spyderlib/widgets/browser.py:31
+#: spyderlib/widgets/sourcecode/codeeditor.py:2468
 msgid "Zoom out"
 msgstr "Alejar"
 
-#: spyderlib/widgets/browser.py:33
-#: spyderlib/widgets/sourcecode/codeeditor.py:2308
+#: spyderlib/widgets/browser.py:34
+#: spyderlib/widgets/sourcecode/codeeditor.py:2465
 msgid "Zoom in"
 msgstr "Acercar"
 
@@ -3303,31 +3678,31 @@ msgstr "Acercar"
 msgid "Home"
 msgstr "Página de inicio"
 
-#: spyderlib/widgets/browser.py:171
+#: spyderlib/widgets/browser.py:166
 msgid "Find text"
 msgstr "Encontrar texto"
 
-#: spyderlib/widgets/browser.py:190
+#: spyderlib/widgets/browser.py:184
 msgid "Address:"
 msgstr "Dirección:"
 
-#: spyderlib/widgets/browser.py:225
+#: spyderlib/widgets/browser.py:220
 msgid "Unable to load page"
 msgstr "No fue posible cargar la página"
 
-#: spyderlib/widgets/comboboxes.py:117
+#: spyderlib/widgets/comboboxes.py:118
 msgid "Press enter to validate this entry"
 msgstr "Presione Enter para validar esta entrada"
 
-#: spyderlib/widgets/comboboxes.py:118
+#: spyderlib/widgets/comboboxes.py:119
 msgid "This entry is incorrect"
 msgstr "Esta entrada es incorrecta"
 
-#: spyderlib/widgets/comboboxes.py:171
+#: spyderlib/widgets/comboboxes.py:174
 msgid "Press enter to validate this path"
 msgstr "Presione Enter para validar esta ruta"
 
-#: spyderlib/widgets/comboboxes.py:172
+#: spyderlib/widgets/comboboxes.py:175
 msgid ""
 "This path is incorrect.\n"
 "Enter a correct directory path,\n"
@@ -3358,7 +3733,7 @@ msgstr "A entero"
 msgid "To str"
 msgstr "A cadena"
 
-#: spyderlib/widgets/dataframeeditor.py:489
+#: spyderlib/widgets/dataframeeditor.py:490
 msgid "%s editor"
 msgstr "Editor de %s"
 
@@ -3366,27 +3741,27 @@ msgstr "Editor de %s"
 msgid "Column min/max"
 msgstr "Min/max de columna"
 
-#: spyderlib/widgets/dependencies.py:60
+#: spyderlib/widgets/dependencies.py:59
 msgid " Required "
 msgstr "Requerido"
 
-#: spyderlib/widgets/dependencies.py:60
+#: spyderlib/widgets/dependencies.py:59
 msgid "Module"
 msgstr "Módulo"
 
-#: spyderlib/widgets/dependencies.py:61
+#: spyderlib/widgets/dependencies.py:60
 msgid " Installed "
 msgstr "Instalado"
 
-#: spyderlib/widgets/dependencies.py:61
+#: spyderlib/widgets/dependencies.py:60
 msgid "Provided features"
 msgstr "Características proporcionadas"
 
-#: spyderlib/widgets/dependencies.py:127
+#: spyderlib/widgets/dependencies.py:130
 msgid "Optional Dependencies"
 msgstr "Dependencias opcionales"
 
-#: spyderlib/widgets/dependencies.py:134
+#: spyderlib/widgets/dependencies.py:137
 msgid ""
 "Spyder depends on several Python modules to provide additional functionality "
 "for its plugins. The table below shows the required and installed versions "
@@ -3401,7 +3776,7 @@ msgstr ""
 "recomienda al menos instalar <b>%s</b> y <b>%s</b> para tener una mejor "
 "experiencia."
 
-#: spyderlib/widgets/dependencies.py:149
+#: spyderlib/widgets/dependencies.py:152
 msgid "Copy to clipboard"
 msgstr "Copiar al portapapeles"
 
@@ -3421,6 +3796,10 @@ msgstr "Lista"
 msgid "Dictionary"
 msgstr "Diccionario"
 
+#: spyderlib/widgets/dicteditor.py:169
+msgid "Key"
+msgstr "Clave/Tecla"
+
 #: spyderlib/widgets/dicteditor.py:175
 msgid "Attribute"
 msgstr "Atributo"
@@ -3429,19 +3808,19 @@ msgstr "Atributo"
 msgid "elements"
 msgstr "elementos"
 
-#: spyderlib/widgets/dicteditor.py:355
+#: spyderlib/widgets/dicteditor.py:356
 msgid "Size"
 msgstr "Tamaño"
 
-#: spyderlib/widgets/dicteditor.py:355
+#: spyderlib/widgets/dicteditor.py:356
 msgid "Type"
 msgstr "Tipo"
 
-#: spyderlib/widgets/dicteditor.py:355
+#: spyderlib/widgets/dicteditor.py:356
 msgid "Value"
 msgstr "Valor"
 
-#: spyderlib/widgets/dicteditor.py:450
+#: spyderlib/widgets/dicteditor.py:453
 msgid ""
 "Opening this variable can be slow\n"
 "\n"
@@ -3451,202 +3830,178 @@ msgstr ""
 "\n"
 "¿Desea continuar de todas formas?"
 
-#: spyderlib/widgets/dicteditor.py:458 spyderlib/widgets/dicteditor.py:607
+#: spyderlib/widgets/dicteditor.py:461 spyderlib/widgets/dicteditor.py:612
 msgid "Edit item"
 msgstr "Editar ítem"
 
-#: spyderlib/widgets/dicteditor.py:459
+#: spyderlib/widgets/dicteditor.py:462
 msgid "<b>Unable to retrieve data.</b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>No fue posible obtener los datos.</b><br><br>Mensaje de error:<br>%s"
 
-#: spyderlib/widgets/dicteditor.py:608
+#: spyderlib/widgets/dicteditor.py:613
 msgid "<b>Unable to assign data to item.</b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>No fue posible asignarle los datos al ítem.</b><br><br>Mensaje de error:"
 "<br>%s"
 
-#: spyderlib/widgets/dicteditor.py:669
+#: spyderlib/widgets/dicteditor.py:675
 msgid "Resize rows to contents"
 msgstr "Ajustar filas a los contenidos"
 
-#: spyderlib/widgets/dicteditor.py:677 spyderlib/widgets/explorer.py:236
+#: spyderlib/widgets/dicteditor.py:683 spyderlib/widgets/explorer.py:242
 msgid "Edit"
 msgstr "Editar"
 
-#: spyderlib/widgets/dicteditor.py:680 spyderlib/widgets/dicteditor.py:1012
-#: spyderlib/widgets/dicteditor.py:1028
+#: spyderlib/widgets/dicteditor.py:686 spyderlib/widgets/dicteditor.py:1025
+#: spyderlib/widgets/dicteditor.py:1042
 msgid "Plot"
 msgstr "Graficar"
 
-#: spyderlib/widgets/dicteditor.py:684
+#: spyderlib/widgets/dicteditor.py:690
 msgid "Histogram"
 msgstr "Histograma"
 
-#: spyderlib/widgets/dicteditor.py:688
+#: spyderlib/widgets/dicteditor.py:694
 msgid "Show image"
 msgstr "Mostrar como imagen"
 
-#: spyderlib/widgets/dicteditor.py:692 spyderlib/widgets/dicteditor.py:1035
+#: spyderlib/widgets/dicteditor.py:698 spyderlib/widgets/dicteditor.py:1050
 msgid "Save array"
 msgstr "Guardar arreglo"
 
-#: spyderlib/widgets/dicteditor.py:696 spyderlib/widgets/dicteditor.py:976
-#: spyderlib/widgets/dicteditor.py:984
+#: spyderlib/widgets/dicteditor.py:702 spyderlib/widgets/dicteditor.py:989
+#: spyderlib/widgets/dicteditor.py:997
 msgid "Insert"
 msgstr "Insertar"
 
-#: spyderlib/widgets/dicteditor.py:699 spyderlib/widgets/dicteditor.py:929
+#: spyderlib/widgets/dicteditor.py:705 spyderlib/widgets/dicteditor.py:939
 msgid "Remove"
 msgstr "Eliminar"
 
-#: spyderlib/widgets/dicteditor.py:710 spyderlib/widgets/dicteditor.py:946
-#: spyderlib/widgets/explorer.py:524 spyderlib/widgets/explorer.py:532
-#: spyderlib/widgets/explorer.py:544
+#: spyderlib/widgets/dicteditor.py:716 spyderlib/widgets/dicteditor.py:956
+#: spyderlib/widgets/explorer.py:532 spyderlib/widgets/explorer.py:540
+#: spyderlib/widgets/explorer.py:551
 msgid "Rename"
 msgstr "Renombrar"
 
-#: spyderlib/widgets/dicteditor.py:713
+#: spyderlib/widgets/dicteditor.py:719
 msgid "Duplicate"
 msgstr "Duplicar"
 
-#: spyderlib/widgets/dicteditor.py:927
+#: spyderlib/widgets/dicteditor.py:937
 msgid "Do you want to remove selected item?"
 msgstr "¿Desea eliminar la variable seleccionada?"
 
-#: spyderlib/widgets/dicteditor.py:928
+#: spyderlib/widgets/dicteditor.py:938
 msgid "Do you want to remove all selected items?"
 msgstr "¿Desea eliminar todas las variables seleccionadas?"
 
-#: spyderlib/widgets/dicteditor.py:946 spyderlib/widgets/dicteditor.py:976
+#: spyderlib/widgets/dicteditor.py:956 spyderlib/widgets/dicteditor.py:989
 msgid "Key:"
 msgstr "Nombre:"
 
-#: spyderlib/widgets/dicteditor.py:984
+#: spyderlib/widgets/dicteditor.py:997
 msgid "Value:"
 msgstr "Valor:"
 
-#: spyderlib/widgets/dicteditor.py:1000
+#: spyderlib/widgets/dicteditor.py:1013
 msgid "Import error"
 msgstr "Error de importación"
 
-#: spyderlib/widgets/dicteditor.py:1001
+#: spyderlib/widgets/dicteditor.py:1014
 msgid "Please install <b>matplotlib</b> or <b>guiqwt</b>."
 msgstr "Por favor instale <b>Matplotlib</b> o <b>guiqwt</b>."
 
-#: spyderlib/widgets/dicteditor.py:1013
+#: spyderlib/widgets/dicteditor.py:1026
 msgid "<b>Unable to plot data.</b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>No fue posible graficar los datos.</b><br><br>Mensaje de error:<br>%s"
 
-#: spyderlib/widgets/dicteditor.py:1029
+#: spyderlib/widgets/dicteditor.py:1043
 msgid "<b>Unable to show image.</b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>No fue posible generar la gráfica.</b><br><br>Mensaje de error:<br>%s"
 
-#: spyderlib/widgets/dicteditor.py:1051
+#: spyderlib/widgets/dicteditor.py:1066
 msgid "<b>Unable to save array</b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>No fue posible guardar el arreglo</b><br><br>Mensaje de error:<br>%s"
 
-#: spyderlib/widgets/dicteditor.py:1068
+#: spyderlib/widgets/dicteditor.py:1085
 msgid "Clipboard contents"
 msgstr "Contenidos del portapapeles"
 
-#: spyderlib/widgets/dicteditor.py:1082
+#: spyderlib/widgets/dicteditor.py:1100
 msgid "Import from clipboard"
 msgstr "Importar desde el portapapeles"
 
-#: spyderlib/widgets/dicteditor.py:1084
+#: spyderlib/widgets/dicteditor.py:1102
 msgid "Empty clipboard"
 msgstr "Vaciar el portapapeles"
 
-#: spyderlib/widgets/dicteditor.py:1085
+#: spyderlib/widgets/dicteditor.py:1103
 msgid "Nothing to be imported from clipboard."
 msgstr "No hay nada para importar desde el portapapeles."
 
-#: spyderlib/widgets/dicteditorutils.py:59
+#: spyderlib/widgets/dicteditorutils.py:60
 msgid "View and edit DataFrames and Series in the Variable Explorer"
 msgstr "Ver y editar DataFrames y Series en el Explorador de Variables"
 
-#: spyderlib/widgets/editor.py:67 spyderlib/widgets/editor.py:417
-msgid "File list management"
-msgstr "Gestión de la lista de archivos"
-
-#: spyderlib/widgets/editor.py:71
-msgid "Filter:"
-msgstr "Filtro:"
-
-#: spyderlib/widgets/editor.py:76
-msgid "(press <b>Enter</b> to edit file)"
-msgstr "(Oprimir <b>Enter</b> para editar)"
-
-#: spyderlib/widgets/editor.py:91
-msgid "&Edit file"
-msgstr "Editar"
-
-#: spyderlib/widgets/editor.py:100
-msgid "&Close file"
-msgstr "Cerrar"
-
-#: spyderlib/widgets/editor.py:108
-msgid "Hint: press <b>Alt</b> to show accelerators"
-msgstr "Sugerencia: oprimir <b>Alt</b> para mostrar aceleradores"
-
-#: spyderlib/widgets/editor.py:420
+#: spyderlib/widgets/editor.py:342
 msgid "Copy path to clipboard"
 msgstr "Copiar la ruta al portapapeles"
 
-#: spyderlib/widgets/editor.py:990
+#: spyderlib/widgets/editor.py:906
 msgid "Temporary file"
 msgstr "Archivo temporal"
 
-#: spyderlib/widgets/editor.py:1087
+#: spyderlib/widgets/editor.py:1003
 msgid "New window"
 msgstr "Nueva ventana"
 
-#: spyderlib/widgets/editor.py:1088
+#: spyderlib/widgets/editor.py:1004
 msgid "Create a new editor window"
 msgstr "Crear una nueva ventana de edición"
 
-#: spyderlib/widgets/editor.py:1091
+#: spyderlib/widgets/editor.py:1007
 msgid "Split vertically"
 msgstr "Dividir verticalmente"
 
-#: spyderlib/widgets/editor.py:1093
+#: spyderlib/widgets/editor.py:1009
 msgid "Split vertically this editor window"
 msgstr "Dividir verticalmente esta panel o ventana de edición"
 
-#: spyderlib/widgets/editor.py:1095
+#: spyderlib/widgets/editor.py:1011
 msgid "Split horizontally"
 msgstr "Dividir horizontalmente"
 
-#: spyderlib/widgets/editor.py:1097
+#: spyderlib/widgets/editor.py:1013
 msgid "Split horizontally this editor window"
 msgstr "Dividir horizontalmente esta ventana o panel de edición"
 
-#: spyderlib/widgets/editor.py:1099
+#: spyderlib/widgets/editor.py:1015
 msgid "Close this panel"
 msgstr "Cerrar este panel"
 
-#: spyderlib/widgets/editor.py:1237
+#: spyderlib/widgets/editor.py:1153
 msgid "<b>%s</b> has been modified.<br>Do you want to save changes?"
 msgstr "<b>%s</b> ha sido modificado.<br>¿Desea guardar los cambios?"
 
-#: spyderlib/widgets/editor.py:1300
+#: spyderlib/widgets/editor.py:1215
 msgid "Save"
 msgstr "Guardar"
 
-#: spyderlib/widgets/editor.py:1301
+#: spyderlib/widgets/editor.py:1216
 msgid "<b>Unable to save script '%s'</b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>No fue posible guardar el archivo '%s'</b><br><br>Mensaje de error:<br>%s"
 
-#: spyderlib/widgets/editor.py:1323
+#: spyderlib/widgets/editor.py:1238
 msgid "Save Python script"
 msgstr "Guardar archivo de Python"
 
-#: spyderlib/widgets/editor.py:1539
+#: spyderlib/widgets/editor.py:1452
 msgid ""
 "<b>%s</b> is unavailable (this file may have been removed, moved or renamed "
 "outside Spyder).<br>Do you want to close it?"
@@ -3654,7 +4009,7 @@ msgstr ""
 "<b>%s</b> no está disponible (el archivo puede haber sido eliminado, movido "
 "o renombrado por fuera de Spyder).<br>¿Desea cerrarlo?"
 
-#: spyderlib/widgets/editor.py:1559
+#: spyderlib/widgets/editor.py:1472
 msgid ""
 "<b>%s</b> has been modified outside Spyder.<br>Do you want to reload it and "
 "lose all your changes?"
@@ -3662,7 +4017,7 @@ msgstr ""
 "<b>%s</b> fue modificado por fuera de Spyder.<br>¿Desea recargarlo y perder "
 "todos sus cambios?"
 
-#: spyderlib/widgets/editor.py:1655
+#: spyderlib/widgets/editor.py:1568
 msgid ""
 "All changes to <b>%s</b> will be lost.<br>Do you want to revert file from "
 "disk?"
@@ -3670,11 +4025,11 @@ msgstr ""
 "Todos los cambios a <b>%s</b> se perderán.<br>Desea revertir el archivo del "
 "disco?"
 
-#: spyderlib/widgets/editor.py:1811
+#: spyderlib/widgets/editor.py:1708
 msgid "Loading %s..."
 msgstr "Cargando %s..."
 
-#: spyderlib/widgets/editor.py:1821
+#: spyderlib/widgets/editor.py:1718
 msgid ""
 "<b>%s</b> contains mixed end-of-line characters.<br>Spyder will fix this "
 "automatically."
@@ -3682,154 +4037,154 @@ msgstr ""
 "<b>%s</b> contiene varios tipos de caracteres de fin de línea.<br>Spyder lo "
 "arreglará automáticamente."
 
-#: spyderlib/widgets/editor.py:2192
+#: spyderlib/widgets/editor.py:2083
 msgid "Close window"
 msgstr "Cerrar ventana"
 
-#: spyderlib/widgets/editor.py:2194
+#: spyderlib/widgets/editor.py:2085
 msgid "Close this window"
 msgstr "Cierra esta ventana"
 
-#: spyderlib/widgets/editortools.py:93 spyderlib/widgets/editortools.py:129
+#: spyderlib/widgets/editortools.py:94 spyderlib/widgets/editortools.py:130
 msgid "Line %s"
 msgstr "Línea %s"
 
-#: spyderlib/widgets/editortools.py:98
+#: spyderlib/widgets/editortools.py:99
 msgid "Class defined at line %s"
 msgstr "Clase definida en la línea %s"
 
-#: spyderlib/widgets/editortools.py:106
+#: spyderlib/widgets/editortools.py:107
 msgid "Method defined at line %s"
 msgstr "Método definido en la línea %s"
 
-#: spyderlib/widgets/editortools.py:116
+#: spyderlib/widgets/editortools.py:117
 msgid "Function defined at line %s"
 msgstr "Función definida en la línea %s"
 
-#: spyderlib/widgets/editortools.py:148
+#: spyderlib/widgets/editortools.py:149
 msgid "Cell starts at line %s"
 msgstr "La celda empieza en la línea %s"
 
-#: spyderlib/widgets/editortools.py:201 spyderlib/widgets/editortools.py:536
+#: spyderlib/widgets/editortools.py:202 spyderlib/widgets/editortools.py:539
 msgid "Go to cursor position"
 msgstr "Ir a la posición del cursor"
 
-#: spyderlib/widgets/editortools.py:204
+#: spyderlib/widgets/editortools.py:205
 msgid "Show absolute path"
 msgstr "Mostrar la ruta completa"
 
-#: spyderlib/widgets/editortools.py:207 spyderlib/widgets/explorer.py:177
+#: spyderlib/widgets/editortools.py:208 spyderlib/widgets/explorer.py:179
 msgid "Show all files"
 msgstr "Mostrar todos los archivos"
 
-#: spyderlib/widgets/editortools.py:210
+#: spyderlib/widgets/editortools.py:211
 msgid "Show special comments"
 msgstr "Mostrar comentarios especiales"
 
-#: spyderlib/widgets/explorer.py:173
+#: spyderlib/widgets/explorer.py:175
 msgid "Edit filename filters..."
 msgstr "Editar filtros..."
 
-#: spyderlib/widgets/explorer.py:186
+#: spyderlib/widgets/explorer.py:189
 msgid "Edit filename filters"
 msgstr "Editar los filtros para nombres de archivo"
 
-#: spyderlib/widgets/explorer.py:187
+#: spyderlib/widgets/explorer.py:190
 msgid "Name filters:"
 msgstr "Nombres de los filtros:"
 
-#: spyderlib/widgets/explorer.py:205
+#: spyderlib/widgets/explorer.py:209
 msgid "File..."
 msgstr "Archivo..."
 
-#: spyderlib/widgets/explorer.py:208
+#: spyderlib/widgets/explorer.py:213
 msgid "Module..."
 msgstr "Módulo"
 
-#: spyderlib/widgets/explorer.py:211
+#: spyderlib/widgets/explorer.py:217
 msgid "Folder..."
 msgstr "Carpeta..."
 
-#: spyderlib/widgets/explorer.py:215
+#: spyderlib/widgets/explorer.py:221
 msgid "Package..."
 msgstr "Paquete..."
 
-#: spyderlib/widgets/explorer.py:238
+#: spyderlib/widgets/explorer.py:244
 msgid "Move..."
 msgstr "Mover a..."
 
-#: spyderlib/widgets/explorer.py:241
+#: spyderlib/widgets/explorer.py:247
 msgid "Delete..."
 msgstr "Eliminar..."
 
-#: spyderlib/widgets/explorer.py:244
+#: spyderlib/widgets/explorer.py:250
 msgid "Rename..."
 msgstr "Renombrar..."
 
-#: spyderlib/widgets/explorer.py:247
+#: spyderlib/widgets/explorer.py:253
 msgid "Open"
 msgstr "Abrir"
 
-#: spyderlib/widgets/explorer.py:248
-#: spyderlib/widgets/sourcecode/codeeditor.py:2299
+#: spyderlib/widgets/explorer.py:254
+#: spyderlib/widgets/sourcecode/codeeditor.py:2456
 msgid "Convert to Python script"
 msgstr "Convertir a un archivo de Python"
 
-#: spyderlib/widgets/explorer.py:271
+#: spyderlib/widgets/explorer.py:277
 msgid "Commit"
 msgstr "Consignar"
 
-#: spyderlib/widgets/explorer.py:275
+#: spyderlib/widgets/explorer.py:281
 msgid "Browse repository"
 msgstr "Explorar repositorio "
 
-#: spyderlib/widgets/explorer.py:287
+#: spyderlib/widgets/explorer.py:293
 msgid "Open command prompt here"
 msgstr "Abrir símbolo del sistema aquí"
 
-#: spyderlib/widgets/explorer.py:289
+#: spyderlib/widgets/explorer.py:295
 msgid "Open terminal here"
 msgstr "Abrir terminal del sistema aquí"
 
-#: spyderlib/widgets/explorer.py:294
+#: spyderlib/widgets/explorer.py:300
 msgid "Open Python console here"
 msgstr "Abrir una terminal de Python aquí"
 
-#: spyderlib/widgets/explorer.py:308
+#: spyderlib/widgets/explorer.py:314
 msgid "New"
 msgstr "Crear nuevo"
 
-#: spyderlib/widgets/explorer.py:316
+#: spyderlib/widgets/explorer.py:322
 msgid "Import"
 msgstr "Importar"
 
-#: spyderlib/widgets/explorer.py:462
+#: spyderlib/widgets/explorer.py:471
 msgid "Do you really want to delete <b>%s</b>?"
 msgstr "¿Realmente desea eliminar <b>%s</b>?"
 
-#: spyderlib/widgets/explorer.py:482
+#: spyderlib/widgets/explorer.py:489
 msgid "delete"
 msgstr "eliminar"
 
-#: spyderlib/widgets/explorer.py:483 spyderlib/widgets/projectexplorer.py:815
-#: spyderlib/widgets/projectexplorer.py:822
-#: spyderlib/widgets/projectexplorer.py:1089
-#: spyderlib/widgets/projectexplorer.py:1173
+#: spyderlib/widgets/explorer.py:490 spyderlib/widgets/projectexplorer.py:823
+#: spyderlib/widgets/projectexplorer.py:830
+#: spyderlib/widgets/projectexplorer.py:1101
+#: spyderlib/widgets/projectexplorer.py:1186
 msgid "Project Explorer"
 msgstr "Explorador de proyectos"
 
-#: spyderlib/widgets/explorer.py:484 spyderlib/widgets/projectexplorer.py:762
-#: spyderlib/widgets/projectexplorer.py:1174
+#: spyderlib/widgets/explorer.py:491 spyderlib/widgets/projectexplorer.py:770
+#: spyderlib/widgets/projectexplorer.py:1187
 msgid "<b>Unable to %s <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr "<b>No fue posible %s <i>%s</i></b><br><br>Mensaje de error:<br>%s"
 
-#: spyderlib/widgets/explorer.py:506
-#: spyderlib/widgets/sourcecode/codeeditor.py:1906
+#: spyderlib/widgets/explorer.py:514
+#: spyderlib/widgets/sourcecode/codeeditor.py:1987
 msgid "Conversion error"
 msgstr "Error de conversión"
 
-#: spyderlib/widgets/explorer.py:507
-#: spyderlib/widgets/sourcecode/codeeditor.py:1907
+#: spyderlib/widgets/explorer.py:515
+#: spyderlib/widgets/sourcecode/codeeditor.py:1988
 msgid ""
 "It was not possible to convert this notebook. The error is:\n"
 "\n"
@@ -3837,11 +4192,11 @@ msgstr ""
 "No fue posible convertir este notebook. El error es:\n"
 "\n"
 
-#: spyderlib/widgets/explorer.py:525
+#: spyderlib/widgets/explorer.py:533
 msgid "New name:"
 msgstr "Nuevo nombre:"
 
-#: spyderlib/widgets/explorer.py:533
+#: spyderlib/widgets/explorer.py:541
 msgid ""
 "Do you really want to rename <b>%s</b> and overwrite the existing file <b>"
 "%s</b>?"
@@ -3849,145 +4204,149 @@ msgstr ""
 "¿Realmente desea renombrar <b>%s</b> y sobrescribir el archivo existente <b>"
 "%s</b>?"
 
-#: spyderlib/widgets/explorer.py:545
+#: spyderlib/widgets/explorer.py:552
 msgid "<b>Unable to rename file <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>No fue posible renombrar el archivo <i>%s</i></b><br><br>Mensaje de error:"
 "<br>%s"
 
-#: spyderlib/widgets/explorer.py:579
+#: spyderlib/widgets/explorer.py:588
 msgid "<b>Unable to move <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr "<b>No fue posible mover <i>%s</i></b><br><br>Mensaje de error:<br>%s"
 
-#: spyderlib/widgets/explorer.py:597
+#: spyderlib/widgets/explorer.py:606
 msgid "<b>Unable to create folder <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>No fue posible crear la carpeta <i>%s</i></b><br><br>Mensaje de error:<br>"
 "%s"
 
-#: spyderlib/widgets/explorer.py:610 spyderlib/widgets/explorer.py:644
+#: spyderlib/widgets/explorer.py:619 spyderlib/widgets/explorer.py:653
 msgid "<b>Unable to create file <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>No fue posible crear el archivo <i>%s</i></b><br><br>Mensaje de error:<br>"
 "%s"
 
-#: spyderlib/widgets/explorer.py:618
+#: spyderlib/widgets/explorer.py:627
 msgid "New folder"
 msgstr "Nueva carpeta"
 
-#: spyderlib/widgets/explorer.py:619
+#: spyderlib/widgets/explorer.py:628
 msgid "Folder name:"
 msgstr "Nombre de la carpeta:"
 
-#: spyderlib/widgets/explorer.py:624
+#: spyderlib/widgets/explorer.py:633
 msgid "New package"
 msgstr "Nuevo paquete"
 
-#: spyderlib/widgets/explorer.py:625
+#: spyderlib/widgets/explorer.py:634
 msgid "Package name:"
 msgstr "Nombre del paquete:"
 
-#: spyderlib/widgets/explorer.py:665
+#: spyderlib/widgets/explorer.py:674
 msgid "New module"
 msgstr "Nuevo módulo"
 
-#: spyderlib/widgets/explorer.py:678
+#: spyderlib/widgets/explorer.py:686
 msgid ""
 "For %s support, please install one of the<br/> following tools:<br/><br/>  %s"
 msgstr ""
 "Para contar con soporte de %s, por favor instale una de<br/> las siguientes "
 "herramientas:<br/><br/>  %s"
 
-#: spyderlib/widgets/explorer.py:682
+#: spyderlib/widgets/explorer.py:690
 msgid "<b>Unable to find external program.</b><br><br>%s"
 msgstr "<b>No fue posible encontrar el programa externo.</b><br><br>%s"
 
-#: spyderlib/widgets/explorer.py:882
+#: spyderlib/widgets/explorer.py:893
 msgid "Show current directory only"
 msgstr "Mostrar sólo el directorio actual"
 
-#: spyderlib/widgets/explorer.py:996 spyderlib/widgets/importwizard.py:518
+#: spyderlib/widgets/explorer.py:989
+msgid "You don't have the right permissions to open this directory"
+msgstr ""
+
+#: spyderlib/widgets/explorer.py:1018 spyderlib/widgets/importwizard.py:525
 msgid "Previous"
 msgstr "Anterior"
 
-#: spyderlib/widgets/explorer.py:1012
+#: spyderlib/widgets/explorer.py:1024
 msgid "Parent"
 msgstr "Directorio superior"
 
-#: spyderlib/widgets/externalshell/baseshell.py:140
+#: spyderlib/widgets/externalshell/baseshell.py:142
 msgid "Run again this program"
 msgstr "Ejecutar de nuevo este programa"
 
-#: spyderlib/widgets/externalshell/baseshell.py:143
+#: spyderlib/widgets/externalshell/baseshell.py:145
 msgid "Kill"
 msgstr "Terminar"
 
-#: spyderlib/widgets/externalshell/baseshell.py:145
+#: spyderlib/widgets/externalshell/baseshell.py:147
 msgid "Kills the current process, causing it to exit immediately"
 msgstr ""
 "Termina el proceso actual, provocando\n"
 "que culmine inmediatamente"
 
-#: spyderlib/widgets/externalshell/baseshell.py:213
+#: spyderlib/widgets/externalshell/baseshell.py:219
 msgid "<span style='color: #44AA44'><b>Running...</b></span>"
 msgstr "<span style='color: #44AA44'><b>Corriendo...</b></span>"
 
-#: spyderlib/widgets/externalshell/baseshell.py:220
+#: spyderlib/widgets/externalshell/baseshell.py:226
 msgid "Terminated."
 msgstr "Terminado."
 
-#: spyderlib/widgets/externalshell/baseshell.py:242
-#: spyderlib/widgets/ipython.py:342 spyderlib/widgets/ipython.py:359
-#: spyderlib/widgets/mixins.py:608
+#: spyderlib/widgets/externalshell/baseshell.py:251
+#: spyderlib/widgets/ipython.py:351 spyderlib/widgets/ipython.py:368
+#: spyderlib/widgets/mixins.py:656
 msgid "Arguments"
 msgstr "Argumentos"
 
-#: spyderlib/widgets/externalshell/baseshell.py:243
+#: spyderlib/widgets/externalshell/baseshell.py:252
 msgid "Command line arguments:"
 msgstr "Argumentos de la línea de comandos:"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:173
+#: spyderlib/widgets/externalshell/namespacebrowser.py:191
 msgid "Refresh"
 msgstr "Actualizar"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:177
+#: spyderlib/widgets/externalshell/namespacebrowser.py:195
 msgid "Refresh periodically"
 msgstr ""
 "Actualizar\n"
 "periódicamente"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:181
-#: spyderlib/widgets/externalshell/namespacebrowser.py:446
+#: spyderlib/widgets/externalshell/namespacebrowser.py:199
+#: spyderlib/widgets/externalshell/namespacebrowser.py:453
 msgid "Import data"
 msgstr "Importar datos"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:184
-#: spyderlib/widgets/externalshell/namespacebrowser.py:536
-#: spyderlib/widgets/externalshell/namespacebrowser.py:557
+#: spyderlib/widgets/externalshell/namespacebrowser.py:202
+#: spyderlib/widgets/externalshell/namespacebrowser.py:541
+#: spyderlib/widgets/externalshell/namespacebrowser.py:562
 msgid "Save data"
 msgstr "Guardar datos"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:189
+#: spyderlib/widgets/externalshell/namespacebrowser.py:207
 msgid "Save data as..."
 msgstr "Guardar datos como..."
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:197
+#: spyderlib/widgets/externalshell/namespacebrowser.py:215
 msgid "Exclude references which name starts with an underscore"
 msgstr ""
 "Excluir variables cuyo nombre comienza\n"
 "con un guión abajo"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:205
+#: spyderlib/widgets/externalshell/namespacebrowser.py:223
 msgid "Exclude references which name is uppercase"
 msgstr ""
 "Excluir variables cuyo nombre está\n"
 "por completo en mayúsculas"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:212
+#: spyderlib/widgets/externalshell/namespacebrowser.py:230
 msgid "Exclude references which name starts with an uppercase character"
 msgstr "Excluir variables cuyo nombre comienza en mayúsculas"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:220
+#: spyderlib/widgets/externalshell/namespacebrowser.py:238
 msgid ""
 "Exclude references to unsupported data types (i.e. which won't be handled/"
 "saved correctly)"
@@ -3996,11 +4355,11 @@ msgstr ""
 "(es decir aquellos que no pueden manejarse y guardarse\n"
 "correctamente)"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:342
+#: spyderlib/widgets/externalshell/namespacebrowser.py:347
 msgid "Object <b>%s</b> is not picklable"
 msgstr "El objeto <b>%s</b> no es picklable"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:468
+#: spyderlib/widgets/externalshell/namespacebrowser.py:473
 msgid ""
 "<b>Unsupported file extension '%s'</b><br><br>Would you like to import it "
 "anyway (by selecting a known file format)?"
@@ -4008,35 +4367,35 @@ msgstr ""
 "<b>Extensión de archivo no soportada: '%s'</b><br><br>¿Desea importar el "
 "archivo de todas formas (seleccionando un formato conocido)?"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:476
+#: spyderlib/widgets/externalshell/namespacebrowser.py:481
 msgid "Open file as:"
 msgstr "Abrir archivo como:"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:524
+#: spyderlib/widgets/externalshell/namespacebrowser.py:529
 msgid "<b>Unable to load '%s'</b><br><br>Error message:<br>%s"
 msgstr "<b>No fue posible cargar '%s'</b><br><br>Mensaje de error:<br>%s"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:558
+#: spyderlib/widgets/externalshell/namespacebrowser.py:563
 msgid "<b>Unable to save current workspace</b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>No fue posible guardar el espacio de trabajo actual</b><br><br>Mensaje de "
 "error:<br>%s"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:269
+#: spyderlib/widgets/externalshell/pythonshell.py:284
 msgid "Variables"
 msgstr "Variables"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:270
+#: spyderlib/widgets/externalshell/pythonshell.py:285
 msgid "Show/hide global variables explorer"
 msgstr ""
 "Mostrar u ocultar el\n"
 "explorador de variables"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:274
+#: spyderlib/widgets/externalshell/pythonshell.py:289
 msgid "Terminate"
 msgstr "Interrumpir"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:275
+#: spyderlib/widgets/externalshell/pythonshell.py:290
 msgid ""
 "Attempts to stop the process. The process\n"
 "may not exit as a result of clicking this\n"
@@ -4048,40 +4407,48 @@ msgstr ""
 "(pues es posible que se le pida al usuario\n"
 "guardar archivos sin salvar, etc)."
 
-#: spyderlib/widgets/externalshell/pythonshell.py:288
+#: spyderlib/widgets/externalshell/pythonshell.py:303
 msgid "Interact"
 msgstr "Interactuar"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:290
+#: spyderlib/widgets/externalshell/pythonshell.py:305
 msgid "Debug"
 msgstr "Depurar"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:292
-#: spyderlib/widgets/externalshell/pythonshell.py:355
+#: spyderlib/widgets/externalshell/pythonshell.py:307
+#: spyderlib/widgets/externalshell/pythonshell.py:373
 msgid "Arguments..."
 msgstr "Argumentos..."
 
-#: spyderlib/widgets/externalshell/pythonshell.py:299
+#: spyderlib/widgets/externalshell/pythonshell.py:309
+msgid "Post Mortem Debug"
+msgstr ""
+
+#: spyderlib/widgets/externalshell/pythonshell.py:315
+msgid "Working directory"
+msgstr "Directorio de trabajo"
+
+#: spyderlib/widgets/externalshell/pythonshell.py:317
 msgid "Set current working directory"
 msgstr "Establece el directorio de trabajo"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:301
+#: spyderlib/widgets/externalshell/pythonshell.py:319
 msgid "Environment variables"
 msgstr "Variables de entorno"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:305
+#: spyderlib/widgets/externalshell/pythonshell.py:323
 msgid "Show sys.path contents"
 msgstr "Contenidos del sys.path"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:351
+#: spyderlib/widgets/externalshell/pythonshell.py:369
 msgid "Arguments: %s"
 msgstr "Argumentos: %s"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:353
+#: spyderlib/widgets/externalshell/pythonshell.py:371
 msgid "No argument"
 msgstr "Sin argumentos"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:534
+#: spyderlib/widgets/externalshell/pythonshell.py:550
 msgid ""
 "The kernel failed to start!! That's all we know... Please close this console "
 "and open a new one."
@@ -4089,77 +4456,96 @@ msgstr ""
 "No fue posible crear un núcleo!! Es todo lo que sabemos... Por favor cierre "
 "esta terminal y abra una nueva."
 
-#: spyderlib/widgets/externalshell/pythonshell.py:538
+#: spyderlib/widgets/externalshell/pythonshell.py:554
 msgid "A Python console failed to start!"
 msgstr "No se pudo iniciar una terminal de Python!"
 
-#: spyderlib/widgets/externalshell/systemshell.py:94
+#: spyderlib/widgets/externalshell/systemshell.py:100
 msgid "Process failed to start"
 msgstr "El proceso falló al empezar"
 
-#: spyderlib/widgets/findinfiles.py:155
+#: spyderlib/widgets/file_switcher.py:109
+#, fuzzy
+msgid "unsaved file"
+msgstr "Guardar archivo"
+
+#: spyderlib/widgets/file_switcher.py:229
+msgid ""
+"Press <b>Enter</b> to switch files or <b>Esc</b> to cancel.<br><br>Type to "
+"filter filenames.<br><br>Use <b>:number</b> to go to a line, e.g. "
+"<b><code>main:42</code></b><br>Use <b>@symbol_text</b> to go to a symbol, e."
+"g. <b><code>@init</code></b><br><br> Press <b>Ctrl+W</b> to close current "
+"tab.<br>"
+msgstr ""
+
+#: spyderlib/widgets/file_switcher.py:481
+#, fuzzy
+msgid "lines"
+msgstr "líneas"
+
+#: spyderlib/widgets/findinfiles.py:158
 msgid "Unexpected error: see internal console"
 msgstr "Error inesperado. Por favor vea la terminal interna."
 
-#: spyderlib/widgets/findinfiles.py:207 spyderlib/widgets/findinfiles.py:231
-#: spyderlib/widgets/findinfiles.py:278
+#: spyderlib/widgets/findinfiles.py:210 spyderlib/widgets/findinfiles.py:234
+#: spyderlib/widgets/findinfiles.py:281
 msgid "invalid regular expression"
 msgstr "expresión regular inválida"
 
-#: spyderlib/widgets/findinfiles.py:276
+#: spyderlib/widgets/findinfiles.py:279
 msgid "permission denied errors were encountered"
 msgstr "permiso denegado, se encontraron errores"
 
-#: spyderlib/widgets/findinfiles.py:310
+#: spyderlib/widgets/findinfiles.py:316
 msgid "Search pattern"
 msgstr "Patrón de búsqueda"
 
-#: spyderlib/widgets/findinfiles.py:313 spyderlib/widgets/findinfiles.py:347
-#: spyderlib/widgets/findinfiles.py:359 spyderlib/widgets/findreplace.py:82
+#: spyderlib/widgets/findinfiles.py:319 spyderlib/widgets/findinfiles.py:353
+#: spyderlib/widgets/findinfiles.py:365 spyderlib/widgets/findreplace.py:77
 msgid "Regular expression"
 msgstr "Expresión regular"
 
-#: spyderlib/widgets/findinfiles.py:322
+#: spyderlib/widgets/findinfiles.py:328
 msgid "Search"
 msgstr "Buscar"
 
-#: spyderlib/widgets/findinfiles.py:325
+#: spyderlib/widgets/findinfiles.py:331
 msgid "Start search"
 msgstr "Comenzar la búsqueda"
 
-#: spyderlib/widgets/findinfiles.py:328 spyderlib/widgets/ipython.py:543
+#: spyderlib/widgets/findinfiles.py:334 spyderlib/widgets/ipython.py:555
 msgid "Stop"
 msgstr "Detener"
 
-#: spyderlib/widgets/findinfiles.py:331
+#: spyderlib/widgets/findinfiles.py:337
 msgid "Stop search"
 msgstr "Detener la búsqueda"
 
-#: spyderlib/widgets/findinfiles.py:341
+#: spyderlib/widgets/findinfiles.py:347
 msgid "Included filenames pattern"
 msgstr ""
 "Patrones de nombres de\n"
 "archivo a incluir"
 
-#: spyderlib/widgets/findinfiles.py:350
+#: spyderlib/widgets/findinfiles.py:356
 msgid "Include:"
 msgstr "Incluir:"
 
-#: spyderlib/widgets/findinfiles.py:353
+#: spyderlib/widgets/findinfiles.py:359
 msgid "Excluded filenames pattern"
 msgstr ""
 "Patrones de nombres de\n"
 "archivo a excluir"
 
-#: spyderlib/widgets/findinfiles.py:362
+#: spyderlib/widgets/findinfiles.py:368
 msgid "Exclude:"
 msgstr "Excluir:"
 
-#: spyderlib/widgets/findinfiles.py:372
+#: spyderlib/widgets/findinfiles.py:378
 msgid "PYTHONPATH"
 msgstr "PYTHONPATH"
 
-#: spyderlib/widgets/findinfiles.py:374
+#: spyderlib/widgets/findinfiles.py:380
 msgid ""
 "Search in all directories listed in sys.path which are outside the Python "
 "installation directory"
@@ -4168,27 +4554,27 @@ msgstr ""
 "sys.path que están por fuera del\n"
 "directorio de instalación de Python"
 
-#: spyderlib/widgets/findinfiles.py:377
+#: spyderlib/widgets/findinfiles.py:383
 msgid "Hg repository"
 msgstr "Repositorio Hg"
 
-#: spyderlib/widgets/findinfiles.py:380
+#: spyderlib/widgets/findinfiles.py:386
 msgid "Search in current directory hg repository"
 msgstr ""
 "Buscar en el repositorio\n"
 "actual de Mercurial"
 
-#: spyderlib/widgets/findinfiles.py:381
+#: spyderlib/widgets/findinfiles.py:387
 msgid "Here:"
 msgstr "Aquí"
 
-#: spyderlib/widgets/findinfiles.py:385
+#: spyderlib/widgets/findinfiles.py:391
 msgid "Search recursively in this directory"
 msgstr ""
 "Buscar recursivamente\n"
 "en este directorio"
 
-#: spyderlib/widgets/findinfiles.py:393
+#: spyderlib/widgets/findinfiles.py:396
 msgid "Browse a search directory"
 msgstr ""
 "Seleccionar el directorio\n"
@@ -4202,159 +4588,159 @@ msgstr "Ocultar opciones avanzadas"
 msgid "Show advanced options"
 msgstr "Mostrar opciones avanzadas"
 
-#: spyderlib/widgets/findinfiles.py:571
+#: spyderlib/widgets/findinfiles.py:570
 msgid "Search canceled"
 msgstr "Búsqueda cancelada"
 
-#: spyderlib/widgets/findinfiles.py:575
+#: spyderlib/widgets/findinfiles.py:574
 msgid "String not found"
 msgstr "Texto no encontrado"
 
-#: spyderlib/widgets/findinfiles.py:577
+#: spyderlib/widgets/findinfiles.py:576
 msgid "matches in"
 msgstr "coincidencias en"
 
-#: spyderlib/widgets/findinfiles.py:578
+#: spyderlib/widgets/findinfiles.py:577
 msgid "file"
 msgstr "archivo"
 
-#: spyderlib/widgets/findinfiles.py:586
+#: spyderlib/widgets/findinfiles.py:585
 msgid "interrupted"
 msgstr "interrumpido"
 
-#: spyderlib/widgets/findreplace.py:62
+#: spyderlib/widgets/findreplace.py:59
 msgid "Search string"
 msgstr "Buscar texto"
 
-#: spyderlib/widgets/findreplace.py:89
+#: spyderlib/widgets/findreplace.py:83
 msgid "Case Sensitive"
 msgstr ""
 "Distinguir mayúsculas\n"
 "de minúsculas"
 
-#: spyderlib/widgets/findreplace.py:96
+#: spyderlib/widgets/findreplace.py:89
 msgid "Whole words"
 msgstr ""
 "Solamente palabras\n"
 "completas"
 
-#: spyderlib/widgets/findreplace.py:103
+#: spyderlib/widgets/findreplace.py:95
 msgid "Highlight matches"
 msgstr "Resaltar coincidencias"
 
-#: spyderlib/widgets/findreplace.py:118
+#: spyderlib/widgets/findreplace.py:109
 msgid "Replace with:"
 msgstr "Reemplazar con:"
 
-#: spyderlib/widgets/findreplace.py:120
+#: spyderlib/widgets/findreplace.py:111
 msgid "Replace string"
 msgstr "Reemplazar texto"
 
-#: spyderlib/widgets/findreplace.py:123
+#: spyderlib/widgets/findreplace.py:114
 msgid "Replace/find"
 msgstr "Buscar/reemplazar"
 
-#: spyderlib/widgets/findreplace.py:132
+#: spyderlib/widgets/findreplace.py:121
 msgid "Replace all"
 msgstr "Reemplazar todo"
 
-#: spyderlib/widgets/importwizard.py:111 spyderlib/widgets/importwizard.py:425
+#: spyderlib/widgets/importwizard.py:116 spyderlib/widgets/importwizard.py:431
 msgid "Import as"
 msgstr "Importar como"
 
-#: spyderlib/widgets/importwizard.py:113
+#: spyderlib/widgets/importwizard.py:118
 msgid "data"
 msgstr "datos"
 
-#: spyderlib/widgets/importwizard.py:117
+#: spyderlib/widgets/importwizard.py:122
 msgid "code"
 msgstr "código"
 
-#: spyderlib/widgets/importwizard.py:120 spyderlib/widgets/importwizard.py:497
+#: spyderlib/widgets/importwizard.py:125 spyderlib/widgets/importwizard.py:504
 msgid "text"
 msgstr "texto"
 
-#: spyderlib/widgets/importwizard.py:133
+#: spyderlib/widgets/importwizard.py:138
 msgid "Column separator:"
 msgstr "Separador de columnas:"
 
-#: spyderlib/widgets/importwizard.py:137
+#: spyderlib/widgets/importwizard.py:142
 msgid "Tab"
 msgstr "Tabulación"
 
-#: spyderlib/widgets/importwizard.py:140 spyderlib/widgets/importwizard.py:159
+#: spyderlib/widgets/importwizard.py:145 spyderlib/widgets/importwizard.py:163
 msgid "other"
 msgstr "otro"
 
-#: spyderlib/widgets/importwizard.py:152
+#: spyderlib/widgets/importwizard.py:156
 msgid "Row separator:"
 msgstr "Separador de filas:"
 
-#: spyderlib/widgets/importwizard.py:156
+#: spyderlib/widgets/importwizard.py:160
 msgid "EOL"
 msgstr "Fin de línea"
 
-#: spyderlib/widgets/importwizard.py:172
+#: spyderlib/widgets/importwizard.py:175
 msgid "Additional options"
 msgstr "Opciones adicionales"
 
-#: spyderlib/widgets/importwizard.py:176
+#: spyderlib/widgets/importwizard.py:179
 msgid "Skip rows:"
 msgstr "Saltar filas:"
 
-#: spyderlib/widgets/importwizard.py:187
+#: spyderlib/widgets/importwizard.py:190
 msgid "Comments:"
 msgstr "Comentarios:"
 
-#: spyderlib/widgets/importwizard.py:193
+#: spyderlib/widgets/importwizard.py:196
 msgid "Transpose"
 msgstr "Trasponer"
 
-#: spyderlib/widgets/importwizard.py:428
+#: spyderlib/widgets/importwizard.py:434
 msgid "array"
 msgstr "arreglo"
 
-#: spyderlib/widgets/importwizard.py:433
+#: spyderlib/widgets/importwizard.py:439
 msgid "list"
 msgstr "lista"
 
-#: spyderlib/widgets/importwizard.py:438
+#: spyderlib/widgets/importwizard.py:444
 msgid "DataFrame"
 msgstr "DataFrame"
 
-#: spyderlib/widgets/importwizard.py:480 spyderlib/widgets/importwizard.py:567
+#: spyderlib/widgets/importwizard.py:487 spyderlib/widgets/importwizard.py:569
 msgid "Import wizard"
 msgstr "Asistente de importación"
 
-#: spyderlib/widgets/importwizard.py:485
+#: spyderlib/widgets/importwizard.py:492
 msgid "Raw text"
 msgstr "Texto sin formato"
 
-#: spyderlib/widgets/importwizard.py:488
+#: spyderlib/widgets/importwizard.py:495
 msgid "variable_name"
 msgstr "nombre_de_variable"
 
-#: spyderlib/widgets/importwizard.py:499
+#: spyderlib/widgets/importwizard.py:506
 msgid "table"
 msgstr "tabla"
 
-#: spyderlib/widgets/importwizard.py:500
+#: spyderlib/widgets/importwizard.py:507
 msgid "Preview"
 msgstr "Vista previa"
 
-#: spyderlib/widgets/importwizard.py:504
+#: spyderlib/widgets/importwizard.py:511
 msgid "Variable Name"
 msgstr "Nombre de variable"
 
-#: spyderlib/widgets/importwizard.py:512
+#: spyderlib/widgets/importwizard.py:519
 msgid "Cancel"
 msgstr "Cancelar"
 
-#: spyderlib/widgets/importwizard.py:527
+#: spyderlib/widgets/importwizard.py:532
 msgid "Done"
 msgstr "Hecho"
 
-#: spyderlib/widgets/importwizard.py:568
+#: spyderlib/widgets/importwizard.py:570
 msgid ""
 "<b>Unable to proceed to next step</b><br><br>Please check your entries."
 "<br><br>Error message:<br>%s"
@@ -4362,71 +4748,71 @@ msgstr ""
 "<b>No fue posible pasar al siguiente paso</b><br><br>Por favor revise sus "
 "daros.<br><br>Mensaje de error:<br>%s"
 
-#: spyderlib/widgets/internalshell.py:252
+#: spyderlib/widgets/internalshell.py:258
 msgid "Help..."
 msgstr "Ayuda..."
 
-#: spyderlib/widgets/internalshell.py:259
+#: spyderlib/widgets/internalshell.py:266
 msgid "Help"
 msgstr "Ayuda"
 
-#: spyderlib/widgets/internalshell.py:268
+#: spyderlib/widgets/internalshell.py:275
 msgid "Shell special commands:"
 msgstr "Comandos especiales:"
 
-#: spyderlib/widgets/internalshell.py:269
+#: spyderlib/widgets/internalshell.py:276
 msgid "Internal editor:"
 msgstr "Editor interno:"
 
-#: spyderlib/widgets/internalshell.py:270
+#: spyderlib/widgets/internalshell.py:277
 msgid "External editor:"
 msgstr "Editor externo:"
 
-#: spyderlib/widgets/internalshell.py:271
+#: spyderlib/widgets/internalshell.py:278
 msgid "Run script:"
 msgstr "Ejecutar un archivo:"
 
-#: spyderlib/widgets/internalshell.py:272
+#: spyderlib/widgets/internalshell.py:279
 msgid "Remove references:"
 msgstr "Eliminar referencias:"
 
-#: spyderlib/widgets/internalshell.py:273
+#: spyderlib/widgets/internalshell.py:280
 msgid "System commands:"
 msgstr "Comandos del sistema:"
 
-#: spyderlib/widgets/internalshell.py:274
+#: spyderlib/widgets/internalshell.py:281
 msgid "Python help:"
 msgstr "Ayuda de Python:"
 
-#: spyderlib/widgets/internalshell.py:275
+#: spyderlib/widgets/internalshell.py:282
 msgid "GUI-based editor:"
 msgstr "Editor gráfico:"
 
-#: spyderlib/widgets/ipython.py:495
+#: spyderlib/widgets/ipython.py:506
 msgid "An error ocurred while starting the kernel"
 msgstr "Ocurrió un error mientras iniciaba el núcleo"
 
-#: spyderlib/widgets/ipython.py:523
+#: spyderlib/widgets/ipython.py:535
 msgid "Restart kernel"
 msgstr "Reiniciar el núcleo"
 
-#: spyderlib/widgets/ipython.py:545
+#: spyderlib/widgets/ipython.py:557
 msgid "Stop the current command"
 msgstr "Detener el comando actual"
 
-#: spyderlib/widgets/ipython.py:569
+#: spyderlib/widgets/ipython.py:581
 msgid "Inspect current object"
 msgstr "Inspeccionar objeto"
 
-#: spyderlib/widgets/ipython.py:574
+#: spyderlib/widgets/ipython.py:586
 msgid "Clear line or block"
 msgstr "Limpiar línea o bloque"
 
-#: spyderlib/widgets/ipython.py:578
+#: spyderlib/widgets/ipython.py:590
 msgid "Clear console"
 msgstr "Limpiar la terminal"
 
-#: spyderlib/widgets/ipython.py:623
+#: spyderlib/widgets/ipython.py:640
 msgid ""
 "It seems the kernel died unexpectedly. Use 'Restart kernel' to continue "
 "using this console."
@@ -4434,87 +4820,87 @@ msgstr ""
 "Al parecer el núcleo murió de forma inesperada. Use 'Reiniciar el núcleo' "
 "para continuar usando esta terminal."
 
-#: spyderlib/widgets/ipython.py:639
+#: spyderlib/widgets/ipython.py:660
 msgid "Changing backend to Qt for Mayavi"
 msgstr "Cambiando la salida gráfica a Qt por Mayavi"
 
-#: spyderlib/widgets/ipython.py:648
+#: spyderlib/widgets/ipython.py:669
 msgid "Kernel process is either remote or unspecified. Cannot interrupt"
 msgstr ""
 "El núcleo es remoto o no está especificado. Por ello no se puede interrumpir."
 
-#: spyderlib/widgets/ipython.py:657
+#: spyderlib/widgets/ipython.py:678
 msgid "Kernel process is either remote or unspecified. Cannot restart."
 msgstr ""
 "El núcleo es remoto o no está especificado. Por ello no se puede reiniciar."
 
-#: spyderlib/widgets/ipython.py:734
+#: spyderlib/widgets/ipython.py:757
 msgid "Connecting to kernel..."
 msgstr "Conectándose al núcleo..."
 
-#: spyderlib/widgets/onecolumntree.py:63
+#: spyderlib/widgets/onecolumntree.py:60
 msgid "Collapse all"
 msgstr "Colapsar resultados"
 
-#: spyderlib/widgets/onecolumntree.py:67
+#: spyderlib/widgets/onecolumntree.py:64
 msgid "Expand all"
 msgstr "Expandir resultados"
 
-#: spyderlib/widgets/onecolumntree.py:71
+#: spyderlib/widgets/onecolumntree.py:68
 msgid "Restore"
 msgstr "Restaurar"
 
-#: spyderlib/widgets/onecolumntree.py:72
+#: spyderlib/widgets/onecolumntree.py:69
 msgid "Restore original tree layout"
 msgstr "Restaurar la disposición original"
 
-#: spyderlib/widgets/onecolumntree.py:76
+#: spyderlib/widgets/onecolumntree.py:73
 msgid "Collapse selection"
 msgstr "Colapsar selección"
 
-#: spyderlib/widgets/onecolumntree.py:80
+#: spyderlib/widgets/onecolumntree.py:77
 msgid "Expand selection"
 msgstr "Expandir selección"
 
-#: spyderlib/widgets/pathmanager.py:84
+#: spyderlib/widgets/pathmanager.py:86
 msgid "Move to top"
 msgstr "Mover al principio"
 
-#: spyderlib/widgets/pathmanager.py:90
+#: spyderlib/widgets/pathmanager.py:92
 msgid "Move up"
 msgstr "Mover arriba"
 
-#: spyderlib/widgets/pathmanager.py:96
+#: spyderlib/widgets/pathmanager.py:98
 msgid "Move down"
 msgstr "Mover abajo"
 
-#: spyderlib/widgets/pathmanager.py:102
+#: spyderlib/widgets/pathmanager.py:104
 msgid "Move to bottom"
 msgstr "Mover al final"
 
-#: spyderlib/widgets/pathmanager.py:113 spyderlib/widgets/pathmanager.py:225
+#: spyderlib/widgets/pathmanager.py:115 spyderlib/widgets/pathmanager.py:230
 msgid "Add path"
 msgstr "Añadir ruta"
 
-#: spyderlib/widgets/pathmanager.py:118 spyderlib/widgets/pathmanager.py:209
+#: spyderlib/widgets/pathmanager.py:120 spyderlib/widgets/pathmanager.py:213
 msgid "Remove path"
 msgstr "Eliminar ruta"
 
-#: spyderlib/widgets/pathmanager.py:128
+#: spyderlib/widgets/pathmanager.py:130
 msgid "Synchronize..."
 msgstr "Sincronizar..."
 
-#: spyderlib/widgets/pathmanager.py:130
+#: spyderlib/widgets/pathmanager.py:132
 msgid "Synchronize Spyder's path list with PYTHONPATH environment variable"
 msgstr ""
 "Sincronizar la lista de rutas de Spyder con la variable\n"
 "de entorno PYTHONPATH"
 
-#: spyderlib/widgets/pathmanager.py:141
+#: spyderlib/widgets/pathmanager.py:144
 msgid "Synchronize"
 msgstr "Sincronizar"
 
-#: spyderlib/widgets/pathmanager.py:142
+#: spyderlib/widgets/pathmanager.py:145
 msgid ""
 "This will synchronize Spyder's path list with <b>PYTHONPATH</b> environment "
 "variable for current user, allowing you to run your Python modules outside "
@@ -4527,11 +4913,11 @@ msgstr ""
 "<br>¿Desea borrar los contenidos del PYTHONPATH antes de añadir la lista de "
 "rutas de Spyder?"
 
-#: spyderlib/widgets/pathmanager.py:210
+#: spyderlib/widgets/pathmanager.py:214
 msgid "Do you really want to remove selected path?"
 msgstr "¿Realmente desea eliminar la ruta seleccionada?"
 
-#: spyderlib/widgets/pathmanager.py:226
+#: spyderlib/widgets/pathmanager.py:231
 msgid ""
 "This directory is already included in Spyder path list.<br>Do you want to "
 "move it to the top of the list?"
@@ -4539,71 +4925,71 @@ msgstr ""
 "Este directorio ya está incluido en la lista de rutas de Spyder.<br>¿Desea "
 "moverlo al principio de la lista?"
 
-#: spyderlib/widgets/projectexplorer.py:333
+#: spyderlib/widgets/projectexplorer.py:335
 msgid "its own configuration file"
 msgstr "su propio archivo de configuración"
 
-#: spyderlib/widgets/projectexplorer.py:335
+#: spyderlib/widgets/projectexplorer.py:337
 msgid " and "
 msgstr " y"
 
-#: spyderlib/widgets/projectexplorer.py:339
+#: spyderlib/widgets/projectexplorer.py:341
 msgid "the following projects:<br>%s"
 msgstr "los siguientes proyectos:<br>%s"
 
-#: spyderlib/widgets/projectexplorer.py:541
+#: spyderlib/widgets/projectexplorer.py:545
 msgid "Project..."
 msgstr "Proyecto..."
 
-#: spyderlib/widgets/projectexplorer.py:554
+#: spyderlib/widgets/projectexplorer.py:558
 msgid "Existing directory"
 msgstr "Un directorio existente"
 
-#: spyderlib/widgets/projectexplorer.py:558
+#: spyderlib/widgets/projectexplorer.py:562
 msgid "Existing Spyder project"
 msgstr "Un proyecto de Spyder existente"
 
-#: spyderlib/widgets/projectexplorer.py:562
+#: spyderlib/widgets/projectexplorer.py:566
 msgid "Existing Pydev project"
 msgstr "Un proyecto de Pydev existente"
 
-#: spyderlib/widgets/projectexplorer.py:579
+#: spyderlib/widgets/projectexplorer.py:583
 msgid "Open project"
 msgstr "Abrir proyecto"
 
-#: spyderlib/widgets/projectexplorer.py:584
+#: spyderlib/widgets/projectexplorer.py:588
 msgid "Close project"
 msgstr "Cerrar proyecto"
 
-#: spyderlib/widgets/projectexplorer.py:589
+#: spyderlib/widgets/projectexplorer.py:593
 msgid "Close unrelated projects"
 msgstr "Cerrar proyectos no relacionados"
 
-#: spyderlib/widgets/projectexplorer.py:598
+#: spyderlib/widgets/projectexplorer.py:602
 msgid "Edit related projects"
 msgstr "Editar proyectos relacionados"
 
-#: spyderlib/widgets/projectexplorer.py:606
+#: spyderlib/widgets/projectexplorer.py:610
 msgid "Add to PYTHONPATH"
 msgstr "Añadir al PYTHONPATH"
 
-#: spyderlib/widgets/projectexplorer.py:611
+#: spyderlib/widgets/projectexplorer.py:615
 msgid "Remove from PYTHONPATH"
 msgstr "Eliminar del PYTHONPATH"
 
-#: spyderlib/widgets/projectexplorer.py:616
+#: spyderlib/widgets/projectexplorer.py:620
 msgid "Properties"
 msgstr "Propiedades"
 
-#: spyderlib/widgets/projectexplorer.py:651
+#: spyderlib/widgets/projectexplorer.py:655
 msgid "Show horizontal scrollbar"
 msgstr "Mostrar una barra de desplazamiento horizontal"
 
-#: spyderlib/widgets/projectexplorer.py:684
+#: spyderlib/widgets/projectexplorer.py:692
 msgid "Workspace"
 msgstr "Espacio de trabajo"
 
-#: spyderlib/widgets/projectexplorer.py:685
+#: spyderlib/widgets/projectexplorer.py:693
 msgid ""
 "The workspace was unable to load or save %s<br><br>Please check if you have "
 "the permission to write the associated configuration files."
@@ -4612,11 +4998,11 @@ msgstr ""
 "verifique si cuenta con los permisos necesarios para escribir los archivos "
 "de configuración del proyecto al disco."
 
-#: spyderlib/widgets/projectexplorer.py:744
+#: spyderlib/widgets/projectexplorer.py:752
 msgid "Import directory"
 msgstr "Importar directorio"
 
-#: spyderlib/widgets/projectexplorer.py:746
+#: spyderlib/widgets/projectexplorer.py:754
 msgid ""
 "The following directory is not in workspace:<br><b>%s</b><br><br>Do you want "
 "to continue (and copy the directory to workspace)?"
@@ -4624,16 +5010,16 @@ msgstr ""
 "El siguiente directorio no está en el espacio de trabajo:<br><b>%s</"
 "b><br><br>¿Desea continuar (y copiar el directorio al espacio de trabajo)?"
 
-#: spyderlib/widgets/projectexplorer.py:764
-#: spyderlib/widgets/projectexplorer.py:1170
+#: spyderlib/widgets/projectexplorer.py:772
+#: spyderlib/widgets/projectexplorer.py:1183
 msgid "copy"
 msgstr "copiar"
 
-#: spyderlib/widgets/projectexplorer.py:816
+#: spyderlib/widgets/projectexplorer.py:824
 msgid "The project <b>%s</b> is already opened!"
 msgstr "El proyecto <b>%s</b> ya está abierto!"
 
-#: spyderlib/widgets/projectexplorer.py:823
+#: spyderlib/widgets/projectexplorer.py:831
 msgid ""
 "The project root path directory is inside the workspace but not as the "
 "expected tree level. It is not a directory of the workspace:<br><b>%s</b>"
@@ -4642,15 +5028,15 @@ msgstr ""
 "no al nivel esperado de profundidad, pues no es un directorio sino un "
 "subdirectorio del espacio de trabajo:<br><b>%s</b>"
 
-#: spyderlib/widgets/projectexplorer.py:834
+#: spyderlib/widgets/projectexplorer.py:842
 msgid "Project name:"
 msgstr "Nombre del proyecto:"
 
-#: spyderlib/widgets/projectexplorer.py:843
+#: spyderlib/widgets/projectexplorer.py:851
 msgid "A project named <b>%s</b> already exists"
 msgstr "Un proyecto llamado <b>%s</b> ya existe"
 
-#: spyderlib/widgets/projectexplorer.py:848
+#: spyderlib/widgets/projectexplorer.py:856
 msgid ""
 "Invalid project name.<br><br>Name must match the following regular "
 "expression:<br><b>%s</b>"
@@ -4658,18 +5044,18 @@ msgstr ""
 "Nombre de proyecto inválido.<br><br>El nombre debe ajustarse a una expresión "
 "del tipo:<br><b>%s</b>"
 
-#: spyderlib/widgets/projectexplorer.py:855
+#: spyderlib/widgets/projectexplorer.py:863
 msgid ""
 "The following directory is not empty:<br><b>%s</b><br><br>Do you want to "
 "continue?"
 msgstr ""
 "El siguiente directorio no está vacío:<br><b>%s</b><br><br>¿Desear continuar?"
 
-#: spyderlib/widgets/projectexplorer.py:867
+#: spyderlib/widgets/projectexplorer.py:876
 msgid "New project"
 msgstr "Nuevo proyecto"
 
-#: spyderlib/widgets/projectexplorer.py:875
+#: spyderlib/widgets/projectexplorer.py:884
 msgid ""
 "The current workspace has not been configured yet.\n"
 "Do you want to do this now?"
@@ -4677,30 +5063,30 @@ msgstr ""
 "El siguiente espacio de trabajo no ha sido configurado.\n"
 "¿Desea hacerlo ahora?"
 
-#: spyderlib/widgets/projectexplorer.py:912
+#: spyderlib/widgets/projectexplorer.py:922
 msgid "Import existing project"
 msgstr "Importar proyecto existente"
 
-#: spyderlib/widgets/projectexplorer.py:925
+#: spyderlib/widgets/projectexplorer.py:935
 msgid "Select projects to import"
 msgstr "Seleccionar proyectos a importar"
 
-#: spyderlib/widgets/projectexplorer.py:937
+#: spyderlib/widgets/projectexplorer.py:947
 msgid "The folder <i>%s</i> does not contain a valid %s project"
 msgstr "La carpeta <i>%s</i> no contiene un proyecto de %s válido"
 
-#: spyderlib/widgets/projectexplorer.py:965
+#: spyderlib/widgets/projectexplorer.py:977
 msgid "Import existing Pydev project"
 msgstr "Importar un proyecto existente de Pydev"
 
-#: spyderlib/widgets/projectexplorer.py:966
+#: spyderlib/widgets/projectexplorer.py:978
 msgid ""
 "<b>Unable to read Pydev project <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>No fue posible cargar el proyecto de Pydev <i>%s</i></b><br><br>Mensaje "
 "de error:<br>%s"
 
-#: spyderlib/widgets/projectexplorer.py:1004
+#: spyderlib/widgets/projectexplorer.py:1016
 msgid ""
 "Do you really want to delete project <b>%s</b>?<br><br>Note: project files "
 "won't be deleted from disk."
@@ -4708,41 +5094,42 @@ msgstr ""
 "¿Realmente desea eliminar el proyecto <b>%s</b>?<br><br>Nota: Los archivos "
 "del proyecto no serán eliminados del disco."
 
-#: spyderlib/widgets/projectexplorer.py:1057
+#: spyderlib/widgets/projectexplorer.py:1069
 msgid "Related projects"
 msgstr "Proyectos relacionados"
 
-#: spyderlib/widgets/projectexplorer.py:1065
+#: spyderlib/widgets/projectexplorer.py:1077
 msgid "Select projects which are related to <b>%s</b>"
 msgstr "Seleccionar los proyectos que están relacionados a <b>%s</b>"
 
-#: spyderlib/widgets/projectexplorer.py:1090
+#: spyderlib/widgets/projectexplorer.py:1102
+#, fuzzy
 msgid ""
-"Statistics on source files only:<br>(Python, C/C++, Fortran)<br><br><b>%s</"
-"b> files.<br><b>%s</b> lines of code."
+"Statistics on source files only:<br>(Python, Cython, IPython, Enaml,C/C++, "
+"Fortran)<br><br><b>%s</b> files.<br><b>%s</b> lines of code."
 msgstr ""
 "Estadísticas para los archivos de código únicamente:<br>(Python, C/C++, "
 "Fortran)<br><br><b>%s</b> archivos.<br><b>%s</b> líneas de código."
 
-#: spyderlib/widgets/projectexplorer.py:1138
+#: spyderlib/widgets/projectexplorer.py:1151
 msgid "File <b>%s</b> already exists.<br>Do you want to overwrite it?"
 msgstr "El archivo <b>%s</b> ya existe.<br>¿Desea sobrescribirlo?"
 
-#: spyderlib/widgets/projectexplorer.py:1152
+#: spyderlib/widgets/projectexplorer.py:1165
 msgid "Folder <b>%s</b> already exists."
 msgstr "La carpeta <b>%s</b> ya existe."
 
-#: spyderlib/widgets/projectexplorer.py:1172
+#: spyderlib/widgets/projectexplorer.py:1185
 msgid "move"
 msgstr "mover"
 
-#: spyderlib/widgets/projectexplorer.py:1182
+#: spyderlib/widgets/projectexplorer.py:1195
 msgid "Select an existing workspace directory, or create a new one"
 msgstr ""
 "Seleccionar un directorio existente para que\n"
 "sea el espacio de trabajo, o crear uno nuevo"
 
-#: spyderlib/widgets/projectexplorer.py:1183
+#: spyderlib/widgets/projectexplorer.py:1196
 msgid ""
 "<u><b>What is the workspace?</b></u><br><br>A <b>Spyder workspace</b> is a "
 "directory on your filesystem that contains Spyder projects and <b>."
@@ -4759,11 +5146,11 @@ msgstr ""
 "spyderproject</b>) con los ajustes del proyecto (PYTHONPATH, proyectos "
 "referenciados, etc).<br>"
 
-#: spyderlib/widgets/projectexplorer.py:1210
+#: spyderlib/widgets/projectexplorer.py:1225
 msgid "This is the current workspace directory"
 msgstr "Este es el directorio actual del espacio de trabajo"
 
-#: spyderlib/widgets/projectexplorer.py:1241
+#: spyderlib/widgets/projectexplorer.py:1255
 msgid ""
 "The following directory is not a Spyder workspace:<br>%s<br><br>Do you want "
 "to create a new workspace in this directory?"
@@ -4775,71 +5162,75 @@ msgstr ""
 msgid "Module or package:"
 msgstr "Módulo o paquete:"
 
-#: spyderlib/widgets/shell.py:126
+#: spyderlib/widgets/shell.py:134
 msgid "Save history log..."
 msgstr "Guardar el historial..."
 
-#: spyderlib/widgets/shell.py:128
+#: spyderlib/widgets/shell.py:136
 msgid "Save current history log (i.e. all inputs and outputs) in a text file"
 msgstr ""
 "Guardar el historial actual (es decir\n"
 "todas las entradas y salidas) en un\n"
 "archivo de texto"
 
-#: spyderlib/widgets/shell.py:248
+#: spyderlib/widgets/shell.py:262
 msgid "Save history log"
 msgstr "Guardar el historial"
 
-#: spyderlib/widgets/shell.py:251
+#: spyderlib/widgets/shell.py:265
 msgid "History logs"
 msgstr "Historiales"
 
-#: spyderlib/widgets/shell.py:262
+#: spyderlib/widgets/shell.py:276
 msgid "<b>Unable to save file '%s'</b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>No fue posible guardar el archivo '%s'</b><br><br>Mensaje de error:<br>%s"
 
-#: spyderlib/widgets/shell.py:701
+#: spyderlib/widgets/shell.py:718
 msgid "Copy without prompts"
 msgstr "Copiar sin los prompts"
 
-#: spyderlib/widgets/shell.py:704 spyderlib/widgets/shell.py:708
+#: spyderlib/widgets/shell.py:721 spyderlib/widgets/shell.py:725
 msgid "Clear line"
 msgstr "Limpiar línea"
 
-#: spyderlib/widgets/shell.py:710
+#: spyderlib/widgets/shell.py:727
 msgid "Clear shell"
 msgstr "Limpiar la terminal"
 
-#: spyderlib/widgets/shell.py:714
+#: spyderlib/widgets/shell.py:731
 msgid "Clear shell contents ('cls' command)"
 msgstr "Limpia los contenidos de la terminal (equivalente al comando 'cls')"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:88
+#: spyderlib/widgets/sourcecode/codeeditor.py:98
 msgid "Go to line:"
 msgstr "Ir a la línea"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:97
+#: spyderlib/widgets/sourcecode/codeeditor.py:106
 msgid "Line count:"
 msgstr "Número total de líneas:"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:1210
+#: spyderlib/widgets/sourcecode/codeeditor.py:1270
 msgid "Breakpoint"
 msgstr "Punto de interrupción"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:1211
+#: spyderlib/widgets/sourcecode/codeeditor.py:1271
 msgid "Condition:"
 msgstr "Condición:"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:1671
+#: spyderlib/widgets/sourcecode/codeeditor.py:1679
+msgid "Code analysis"
+msgstr "Análisis del código"
+
+#: spyderlib/widgets/sourcecode/codeeditor.py:1733
 msgid "To do"
 msgstr "To do"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:1880
+#: spyderlib/widgets/sourcecode/codeeditor.py:1974
 msgid "Removal error"
 msgstr "Error de remoción"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:1881
+#: spyderlib/widgets/sourcecode/codeeditor.py:1975
 msgid ""
 "It was not possible to remove outputs from this notebook. The error is:\n"
 "\n"
@@ -4847,19 +5238,19 @@ msgstr ""
 "No fue posible remover las outputs de este notebook. El error es:\n"
 "\n"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:2296
+#: spyderlib/widgets/sourcecode/codeeditor.py:2453
 msgid "Clear all ouput"
 msgstr "Eliminar todas las salidas"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:2302
+#: spyderlib/widgets/sourcecode/codeeditor.py:2459
 msgid "Go to definition"
 msgstr "Ir a la definición"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:2314
+#: spyderlib/widgets/sourcecode/codeeditor.py:2471
 msgid "Zoom reset"
 msgstr "Restaurar"
 
-#: spyderlib/widgets/sourcecode/syntaxhighlighters.py:30
+#: spyderlib/widgets/sourcecode/syntaxhighlighters.py:32
 msgid "Syntax highlighting for Matlab, Julia and other file types"
 msgstr ""
 "Coloreado del código para archivos tipo Matlab, Julia y varios otros tipos"
@@ -4911,13 +5302,13 @@ msgstr "Línea:"
 msgid "Column:"
 msgstr "Columna:"
 
-#: spyderlib/widgets/tabs.py:137
+#: spyderlib/widgets/tabs.py:142
 msgid "Browse tabs"
 msgstr ""
 "Navegar por\n"
 "las pestañas"
 
-#: spyderlib/widgets/tabs.py:260
+#: spyderlib/widgets/tabs.py:270
 msgid "Close current tab"
 msgstr "Cerrar pestaña actual"
 
@@ -4925,6 +5316,137 @@ msgstr "Cerrar pestaña actual"
 msgid "Text editor"
 msgstr "Editor de texto"
 
+#: spyderlib/workers/updates.py:79 spyderlib/workers/updates.py:81
+msgid "Unable to retrieve information."
+msgstr ""
+
+#: spyderlib/workers/updates.py:83
+msgid ""
+"Unable to connect to the internet. <br><br>Make sure the connection is "
+"working properly."
+msgstr ""
+
+#: spyderlib/workers/updates.py:86
+#, fuzzy
+msgid "Unable to check for updates."
+msgstr "No fue posible cargar la página"
+
+#~ msgid "PyQt"
+#~ msgstr "PyQt"
+
+#~ msgid "API selection for QString and QVariant objects:"
+#~ msgstr "Selección del API para objetos QString and QVariant:"
+
+#~ msgid "API #1"
+#~ msgstr "API #1"
+
+#~ msgid "API #2"
+#~ msgstr "API #2"
+
+#~ msgid "Default API"
+#~ msgstr "API por defecto"
+
+#~ msgid ""
+#~ "PyQt API #1 is the default <br>API for Python 2. PyQt API #2 is the "
+#~ "default API for Python 3 and is compatible with PySide."
+#~ msgstr ""
+#~ "El API #1 de PyQt es el API por<br>defecto para Python 2. El API #2 de "
+#~ "PyQt es el API por defecto para Python 3 y es compatible con PySide."
+
+#~ msgid "Ignore API change errors (sip.setapi)"
+#~ msgstr "Ignorar los errores de cambio de API (sip.setapi)"
+
+#~ msgid ""
+#~ "Enabling this option will ignore <br>errors when changing PyQt API. As "
+#~ "PyQt does not support dynamic API changes, it is strongly recommended to "
+#~ "use this feature wisely, e.g. for debugging purpose."
+#~ msgstr ""
+#~ "Al activar esta opción se ignorarán <br>los errores generados al cambiar "
+#~ "de API de PyQt. Dado que PyQt no soporta los cambios dinámicos de API, se "
+#~ "recomienda usar esta característica con sumo cuidado, por ejemplo, para "
+#~ "propósitos de depuración."
+
+#~ msgid "Matplotlib"
+#~ msgstr "Matplotlib"
+
+#~ msgid "GUI backend:"
+#~ msgstr "Salida gráfica:"
+
+#~ msgid ""
+#~ "Set the GUI toolkit used by <br>Matplotlib to show figures (default: "
+#~ "Qt4Agg)"
+#~ msgstr ""
+#~ "Establecer la librería gráfica <br>utilizada para generar las gráficas de "
+#~ "Matplotlib (por defecto: Qt4Agg)"
+
+#~ msgid "Mod1"
+#~ msgstr "Mod1"
+
+#~ msgid "Mod2"
+#~ msgstr "Mod2"
+
+#~ msgid "Mod3"
+#~ msgstr "Mod3"
+
+#, fuzzy
+#~ msgid "The Internal Console"
+#~ msgstr "Terminal interna"
+
+#~ msgid "File list management"
+#~ msgstr "Gestión de la lista de archivos"
+
+#~ msgid "Filter:"
+#~ msgstr "Filtro:"
+
+#~ msgid "(press <b>Enter</b> to edit file)"
+#~ msgstr "(Oprimir <b>Enter</b> para editar)"
+
+#~ msgid "&Edit file"
+#~ msgstr "Editar"
+
+#~ msgid "&Close file"
+#~ msgstr "Cerrar"
+
+#~ msgid "Hint: press <b>Alt</b> to show accelerators"
+#~ msgstr "Sugerencia: oprimir <b>Alt</b> para mostrar aceleradores"
+
+#~ msgid "Vertical dockwidget tabs"
+#~ msgstr "Componentes en pestañas verticales"
+
+#~ msgid "Custom dockwidget margin:"
+#~ msgstr "Márgenes de componente personalizadas:"
+
+#~ msgid ""
+#~ "<u>Note</u>: add <b>analysis:ignore</b> in a comment to ignore code/style "
+#~ "analysis warnings. For more informations on style guide for Python code, "
+#~ "please refer to the %s page."
+#~ msgstr ""
+#~ "<u>Nota</u>: Añada <b>analysis:ignore</b> a un comentario para ignorar "
+#~ "advertencias de análisis de código o estilo. Para más información sobre "
+#~ "una guía de estilo para escribir código en Python, por favor refiérase a "
+#~ "la página de %s (en inglés).<br>"
+
+#~ msgid "Style analysis"
+#~ msgstr "Análisis de estilo"
+
+#~ msgid "Qt (PyQt/PySide)"
+#~ msgstr "Qt (PyQt/PySide)"
+
+#~ msgid "Use a completion widget"
+#~ msgstr "Usar un widget para completar texto"
+
+#~ msgid "Use a widget instead of plain text output for tab completion"
+#~ msgstr ""
+#~ "Puede decidir si usar un widget en lugar de texto plano \n"
+#~ "para mostrar las posibilidades de completado usando la\n"
+#~ "tecla Tab."
+
+#~ msgid "Switch to/from layout %d"
+#~ msgstr "Cambiarse a la disposición %d"
+
+#~ msgid "Set layout %d"
+#~ msgstr "Establecer la disposición %d"
+
 #~ msgid ""
 #~ "%s will be closed.\n"
 #~ "Do you want to kill the associated kernel and all of its clients?"
@@ -4970,9 +5492,6 @@ msgstr "Editor de texto"
 #~ msgid "Show collection contents"
 #~ msgstr "Mostrar contenidos de listas"
 
-#~ msgid "Show toolbar"
-#~ msgstr "Mostrar barra de herramientas"
-
 #~ msgid ""
 #~ "Resizing cells of a table of such size could take a long time.\n"
 #~ "Do you want to continue anyway?"
@@ -5109,9 +5628,6 @@ msgstr "Editor de texto"
 #~ msgid "Open text file"
 #~ msgstr "Abrir archivo de texto"
 
-#~ msgid "Save current file"
-#~ msgstr "Guardar el archivo actual"
-
 #~ msgid ""
 #~ "Run selection or current \n"
 #~ "block of lines"
diff --git a/spyderlib/locale/fr/LC_MESSAGES/spyderlib.mo b/spyderlib/locale/fr/LC_MESSAGES/spyderlib.mo
index 703ba58..9f51156 100644
Binary files a/spyderlib/locale/fr/LC_MESSAGES/spyderlib.mo and b/spyderlib/locale/fr/LC_MESSAGES/spyderlib.mo differ
diff --git a/spyderlib/locale/fr/LC_MESSAGES/spyderlib.po b/spyderlib/locale/fr/LC_MESSAGES/spyderlib.po
index 405bd54..4fbaa71 100644
--- a/spyderlib/locale/fr/LC_MESSAGES/spyderlib.po
+++ b/spyderlib/locale/fr/LC_MESSAGES/spyderlib.po
@@ -5,7 +5,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: 2.1\n"
-"POT-Creation-Date: 2015-11-24 20:56+COT\n"
+"POT-Creation-Date: 2015-08-29 22:49+COT\n"
 "PO-Revision-Date: 2015-03-16 22:59-0500\n"
 "Last-Translator: Sylvain Corlay <sylvain.corlay at gmail.com>\n"
 "Language-Team: Python\n"
@@ -16,184 +16,219 @@ msgstr ""
 "Generated-By: pygettext.py 1.5\n"
 "X-Generator: Poedit 1.5.4\n"
 
-#: spyderlib/config.py:29
+#: spyderlib/config/base.py:241
+msgid ""
+"Update LANGUAGE_CODES (inside config/base.py) if a new translation has been "
+"added to Spyder"
+msgstr ""
+
+#: spyderlib/config/ipython.py:23 spyderlib/config/ipython.py:25
+#: spyderlib/config/ipython.py:32
+msgid "IPython Console integration"
+msgstr "Intégration de la console IPython"
+
+#: spyderlib/config/main.py:29
 msgid "Python files"
 msgstr "Fichiers Python"
 
-#: spyderlib/config.py:30
+#: spyderlib/config/main.py:30
 msgid "Cython/Pyrex files"
 msgstr "Fichiers Cython/Pyrex"
 
-#: spyderlib/config.py:31
+#: spyderlib/config/main.py:31
 msgid "C files"
 msgstr "Fichiers C"
 
-#: spyderlib/config.py:32
+#: spyderlib/config/main.py:32
 msgid "C++ files"
 msgstr "Fichiers C++"
 
-#: spyderlib/config.py:33
+#: spyderlib/config/main.py:33
 msgid "OpenCL files"
 msgstr "Fichiers OpenCL"
 
-#: spyderlib/config.py:34
+#: spyderlib/config/main.py:34
 msgid "Fortran files"
 msgstr "Fichiers Fortran"
 
-#: spyderlib/config.py:35
+#: spyderlib/config/main.py:35
 msgid "IDL files"
 msgstr "Fichiers IDL"
 
-#: spyderlib/config.py:36
+#: spyderlib/config/main.py:36
 msgid "MATLAB files"
 msgstr "Fichiers MATLAB"
 
-#: spyderlib/config.py:37
+#: spyderlib/config/main.py:37
 msgid "Julia files"
 msgstr "Fichiers Julia"
 
-#: spyderlib/config.py:38
+#: spyderlib/config/main.py:38
 msgid "Yaml files"
 msgstr "Fichiers Yaml"
 
-#: spyderlib/config.py:39
+#: spyderlib/config/main.py:39
 msgid "Patch and diff files"
 msgstr "Fichiers patch et diff"
 
-#: spyderlib/config.py:40
+#: spyderlib/config/main.py:40
 msgid "Batch files"
 msgstr "Fichiers Batch"
 
-#: spyderlib/config.py:41 spyderlib/utils/iofuncs.py:514
+#: spyderlib/config/main.py:41 spyderlib/utils/iofuncs.py:500
 msgid "Text files"
 msgstr "Fichiers texte"
 
-#: spyderlib/config.py:42
+#: spyderlib/config/main.py:42
 msgid "reStructured Text files"
 msgstr "Fichiers reST"
 
-#: spyderlib/config.py:43
+#: spyderlib/config/main.py:43
 msgid "gettext files"
 msgstr "Fichiers gettext"
 
-#: spyderlib/config.py:44
+#: spyderlib/config/main.py:44
 msgid "NSIS files"
 msgstr "Fichiers NSIS"
 
-#: spyderlib/config.py:45
+#: spyderlib/config/main.py:45
 msgid "Web page files"
 msgstr "Fichiers web"
 
-#: spyderlib/config.py:46
+#: spyderlib/config/main.py:46
 msgid "XML files"
 msgstr "Fichiers XML"
 
-#: spyderlib/config.py:47
+#: spyderlib/config/main.py:47
 msgid "Javascript files"
 msgstr "Fichiers Javascript"
 
-#: spyderlib/config.py:48
+#: spyderlib/config/main.py:48
 msgid "Json files"
 msgstr "Fichiers Json"
 
-#: spyderlib/config.py:49
+#: spyderlib/config/main.py:49
 msgid "IPython notebooks"
 msgstr "Documents IPython "
 
-#: spyderlib/config.py:50
+#: spyderlib/config/main.py:50
 msgid "Enaml files"
 msgstr "Fichiers Enaml"
 
-#: spyderlib/config.py:51
+#: spyderlib/config/main.py:51
 msgid "Configuration files"
 msgstr "Configurations"
 
-#: spyderlib/config.py:58 spyderlib/widgets/explorer.py:651
+#: spyderlib/config/main.py:58 spyderlib/widgets/explorer.py:660
 msgid "All files"
 msgstr "Tous les fichiers"
 
-#: spyderlib/ipythonconfig.py:23 spyderlib/ipythonconfig.py:25
-#: spyderlib/ipythonconfig.py:32
-msgid "IPython Console integration"
-msgstr "Intégration de la console IPython"
-
-#: spyderlib/plugins/__init__.py:318 spyderlib/plugins/editor.py:94
-#: spyderlib/plugins/editor.py:527 spyderlib/plugins/editor.py:1606
-#: spyderlib/plugins/inspector.py:134 spyderlib/plugins/inspector.py:403
-#: spyderlib/widgets/editor.py:434
-#: spyderlib/widgets/sourcecode/codeeditor.py:85
-#: spyderlib/widgets/sourcecode/codeeditor.py:2709
+#: spyderlib/plugins/__init__.py:513 spyderlib/plugins/editor.py:95
+#: spyderlib/plugins/editor.py:551 spyderlib/plugins/editor.py:1600
+#: spyderlib/plugins/inspector.py:139 spyderlib/plugins/inspector.py:419
+#: spyderlib/widgets/editor.py:357
+#: spyderlib/widgets/sourcecode/codeeditor.py:95
+#: spyderlib/widgets/sourcecode/codeeditor.py:2902
 msgid "Editor"
 msgstr "Éditeur"
 
-#: spyderlib/plugins/configdialog.py:144
+#: spyderlib/plugins/configdialog.py:133
+#, fuzzy
+msgid "Reset to defaults"
+msgstr "Rétablir les valeurs par défaut"
+
+#: spyderlib/plugins/configdialog.py:145
 msgid "Preferences"
 msgstr "Préférences"
 
-#: spyderlib/plugins/configdialog.py:429
+#: spyderlib/plugins/configdialog.py:473
 msgid "Invalid directory path"
 msgstr "Chemin d'accès de répertoire incorrect"
 
-#: spyderlib/plugins/configdialog.py:432 spyderlib/plugins/configdialog.py:448
-#: spyderlib/plugins/runconfig.py:172 spyderlib/plugins/runconfig.py:236
-#: spyderlib/plugins/workingdirectory.py:286 spyderlib/widgets/explorer.py:565
-#: spyderlib/widgets/externalshell/pythonshell.py:623
-#: spyderlib/widgets/findinfiles.py:504 spyderlib/widgets/pathmanager.py:218
-#: spyderlib/widgets/projectexplorer.py:890
+#: spyderlib/plugins/configdialog.py:476 spyderlib/plugins/configdialog.py:491
+#: spyderlib/plugins/runconfig.py:176 spyderlib/plugins/runconfig.py:240
+#: spyderlib/plugins/workingdirectory.py:295 spyderlib/widgets/explorer.py:574
+#: spyderlib/widgets/externalshell/pythonshell.py:640
+#: spyderlib/widgets/findinfiles.py:505 spyderlib/widgets/pathmanager.py:223
+#: spyderlib/widgets/projectexplorer.py:899
 msgid "Select directory"
 msgstr "Sélectionner un répertoire"
 
-#: spyderlib/plugins/configdialog.py:460
+#: spyderlib/plugins/configdialog.py:503
 msgid "Invalid file path"
 msgstr "Chemin d'accès de fichier incorrect"
 
-#: spyderlib/plugins/configdialog.py:463 spyderlib/plugins/configdialog.py:481
+#: spyderlib/plugins/configdialog.py:506 spyderlib/plugins/configdialog.py:523
 msgid "Select file"
 msgstr "Sélectionner un fichier"
 
-#: spyderlib/plugins/configdialog.py:480
+#: spyderlib/plugins/configdialog.py:522
 msgid "All files (*)"
 msgstr "Tous les fichiers (*)"
 
-#: spyderlib/plugins/configdialog.py:550 spyderlib/widgets/formlayout.py:216
+#: spyderlib/plugins/configdialog.py:595 spyderlib/widgets/formlayout.py:214
 msgid "Bold"
 msgstr "Gras"
 
-#: spyderlib/plugins/configdialog.py:553 spyderlib/widgets/formlayout.py:211
+#: spyderlib/plugins/configdialog.py:598 spyderlib/widgets/formlayout.py:209
 msgid "Italic"
 msgstr "Italique"
 
-#: spyderlib/plugins/configdialog.py:591
+#: spyderlib/plugins/configdialog.py:640
 msgid "Font: "
 msgstr "Police : "
 
-#: spyderlib/plugins/configdialog.py:595
+#: spyderlib/plugins/configdialog.py:644
 msgid "Size: "
 msgstr "Taille : "
 
-#: spyderlib/plugins/configdialog.py:604 spyderlib/plugins/history.py:47
+#: spyderlib/plugins/configdialog.py:653 spyderlib/plugins/history.py:48
 msgid "Font style"
 msgstr "Police d'écriture"
 
-#: spyderlib/plugins/configdialog.py:657
+#: spyderlib/plugins/configdialog.py:708
+msgid "Spyder needs to restart to change the following setting:"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:711
+msgid "Spyder needs to restart to change the following settings:"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:713
+msgid "Do you wish to restart now?"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:719
+msgid "Information"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:734
 msgid "General"
 msgstr "Général"
 
-#: spyderlib/plugins/configdialog.py:664 spyderlib/plugins/editor.py:103
-#: spyderlib/plugins/externalconsole.py:65
-#: spyderlib/plugins/ipythonconsole.py:161
+#: spyderlib/plugins/configdialog.py:741 spyderlib/plugins/editor.py:104
+#: spyderlib/plugins/externalconsole.py:67
+#: spyderlib/plugins/ipythonconsole.py:162
 msgid "Interface"
 msgstr "Interface"
 
-#: spyderlib/plugins/configdialog.py:672
+#: spyderlib/plugins/configdialog.py:744
 msgid "Qt windows style"
 msgstr "Style de fenêtres Qt"
 
-#: spyderlib/plugins/configdialog.py:676
+#: spyderlib/plugins/configdialog.py:750
+msgid "Icon theme"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:755
+msgid "Language"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:759
 msgid "Use a single instance"
 msgstr "Ouvrir une seule instance de Spyder"
 
-#: spyderlib/plugins/configdialog.py:678
+#: spyderlib/plugins/configdialog.py:761
 msgid ""
 "Set this to open external<br> Python files in an already running instance "
 "(Requires a restart)"
@@ -201,342 +236,362 @@ msgstr ""
 "Activer cette option afin que les fichiers ouverts<br>depuis l'extérieur "
 "soit affichés dans une instance unique de Spyder<br>(redémarrage requis)"
 
-#: spyderlib/plugins/configdialog.py:681
-msgid "Vertical dockwidget title bars"
+#: spyderlib/plugins/configdialog.py:764
+#, fuzzy
+msgid "Vertical title bars in panes"
 msgstr "Barres de titre orientées verticalement"
 
-#: spyderlib/plugins/configdialog.py:683
-msgid "Vertical dockwidget tabs"
-msgstr "Onglets distribués verticalement"
+#: spyderlib/plugins/configdialog.py:766
+msgid "Vertical tabs in panes"
+msgstr ""
 
-#: spyderlib/plugins/configdialog.py:685
-msgid "Animated toolbars and dockwidgets"
+#: spyderlib/plugins/configdialog.py:768
+#, fuzzy
+msgid "Animated toolbars and panes"
 msgstr "Panneaux et barres d'outils animés"
 
-#: spyderlib/plugins/configdialog.py:687
+#: spyderlib/plugins/configdialog.py:770
 msgid "Tear off menus"
 msgstr "Menus détachables"
 
-#: spyderlib/plugins/configdialog.py:688
+#: spyderlib/plugins/configdialog.py:771
 msgid "Set this to detach any<br> menu from the main window"
 msgstr ""
 "Activer cette option rend détachables tous les menus de la fenêtre principale"
 
-#: spyderlib/plugins/configdialog.py:690
-msgid "Custom dockwidget margin:"
-msgstr "Marges personnalisées :"
+#: spyderlib/plugins/configdialog.py:773
+msgid "Custom margin for panes:"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:782
+#, fuzzy
+msgid "Prompt when exiting"
+msgstr "Éditeurs dans le processus distant"
 
-#: spyderlib/plugins/configdialog.py:717
+#: spyderlib/plugins/configdialog.py:813
 msgid "Status bar"
 msgstr "Barre d'état"
 
-#: spyderlib/plugins/configdialog.py:718
+#: spyderlib/plugins/configdialog.py:814
+#, fuzzy
+msgid "Show status bar"
+msgstr "Afficher la barre d'onglets"
+
+#: spyderlib/plugins/configdialog.py:816
 msgid "Show memory usage every"
 msgstr "Afficher l'occupation mémoire toutes les"
 
-#: spyderlib/plugins/configdialog.py:729
+#: spyderlib/plugins/configdialog.py:825
 msgid "Show CPU usage every"
 msgstr "Afficher la charge du CPU toutes les"
 
-#: spyderlib/plugins/configdialog.py:746
+#: spyderlib/plugins/configdialog.py:858
 msgid "Debugging"
 msgstr "Débogage"
 
-#: spyderlib/plugins/configdialog.py:747
+#: spyderlib/plugins/configdialog.py:859
 msgid "Pop up internal console when internal errors appear"
 msgstr "Afficher la console interne en cas d'erreur inattendue"
 
-#: spyderlib/plugins/configdialog.py:769
+#: spyderlib/plugins/configdialog.py:868
+msgid "Updates"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:869 spyderlib/spyder.py:2872
+msgid "Check for updates on startup"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:902
 msgid "Syntax coloring"
 msgstr "Coloration syntaxique"
 
-#: spyderlib/plugins/configdialog.py:778
+#: spyderlib/plugins/configdialog.py:911
 msgid "Background:"
 msgstr "Fond :"
 
-#: spyderlib/plugins/configdialog.py:779
-#: spyderlib/widgets/sourcecode/codeeditor.py:95
+#: spyderlib/plugins/configdialog.py:912
+#: spyderlib/widgets/sourcecode/codeeditor.py:104
 msgid "Current line:"
 msgstr "Ligne actuelle :"
 
-#: spyderlib/plugins/configdialog.py:780
+#: spyderlib/plugins/configdialog.py:913
 msgid "Current cell:"
 msgstr "Cellule actuelle :"
 
-#: spyderlib/plugins/configdialog.py:781
+#: spyderlib/plugins/configdialog.py:914
 msgid "Occurence:"
 msgstr "Occurence :"
 
-#: spyderlib/plugins/configdialog.py:782
+#: spyderlib/plugins/configdialog.py:915
 msgid "Link:"
 msgstr "Lien :"
 
-#: spyderlib/plugins/configdialog.py:783
+#: spyderlib/plugins/configdialog.py:916
 msgid "Side areas:"
 msgstr "Zones latérales :"
 
-#: spyderlib/plugins/configdialog.py:784
+#: spyderlib/plugins/configdialog.py:917
 msgid "Matched parentheses:"
 msgstr "Parenthèse fermée :"
 
-#: spyderlib/plugins/configdialog.py:785
+#: spyderlib/plugins/configdialog.py:918
 msgid "Unmatched parentheses:"
 msgstr "Parenthèse non fermée :"
 
-#: spyderlib/plugins/configdialog.py:786
+#: spyderlib/plugins/configdialog.py:919
 msgid "Normal text:"
 msgstr "Texte normal :"
 
-#: spyderlib/plugins/configdialog.py:787
+#: spyderlib/plugins/configdialog.py:920
 msgid "Keyword:"
 msgstr "Mot-clé :"
 
-#: spyderlib/plugins/configdialog.py:788
+#: spyderlib/plugins/configdialog.py:921
 msgid "Builtin:"
 msgstr "Objet intégré :"
 
-#: spyderlib/plugins/configdialog.py:789
+#: spyderlib/plugins/configdialog.py:922
 msgid "Definition:"
 msgstr "Définition :"
 
-#: spyderlib/plugins/configdialog.py:790
+#: spyderlib/plugins/configdialog.py:923
 msgid "Comment:"
 msgstr "Commentaire :"
 
-#: spyderlib/plugins/configdialog.py:791
+#: spyderlib/plugins/configdialog.py:924
 msgid "String:"
 msgstr "Chaîne :"
 
-#: spyderlib/plugins/configdialog.py:792
+#: spyderlib/plugins/configdialog.py:925
 msgid "Number:"
 msgstr "Nombre :"
 
-#: spyderlib/plugins/configdialog.py:793
+#: spyderlib/plugins/configdialog.py:926
 msgid "Instance:"
 msgstr "Instance :"
 
-#: spyderlib/plugins/configdialog.py:799
+#: spyderlib/plugins/configdialog.py:932
 msgid "Color scheme"
 msgstr "Paramètres de coloration syntaxique"
 
-#: spyderlib/plugins/configdialog.py:821 spyderlib/plugins/shortcuts.py:344
+#: spyderlib/plugins/configdialog.py:954 spyderlib/plugins/shortcuts.py:776
 msgid "Reset to default values"
 msgstr "Rétablir les valeurs par défaut"
 
-#: spyderlib/plugins/console.py:105
+#: spyderlib/plugins/console.py:109
 msgid "Internal console"
 msgstr "Console interne"
 
-#: spyderlib/plugins/console.py:125 spyderlib/spyder.py:772
-#: spyderlib/widgets/ipython.py:583
+#: spyderlib/plugins/console.py:129 spyderlib/spyder.py:869
+#: spyderlib/widgets/ipython.py:595
 msgid "&Quit"
 msgstr "&Quitter"
 
-#: spyderlib/plugins/console.py:126 spyderlib/spyder.py:773
+#: spyderlib/plugins/console.py:131 spyderlib/spyder.py:871
 msgid "Quit"
 msgstr "Quitter"
 
-#: spyderlib/plugins/console.py:129 spyderlib/plugins/externalconsole.py:1099
+#: spyderlib/plugins/console.py:134 spyderlib/plugins/externalconsole.py:1039
 msgid "&Run..."
 msgstr "Exécute&r..."
 
-#: spyderlib/plugins/console.py:130 spyderlib/plugins/externalconsole.py:1100
+#: spyderlib/plugins/console.py:136 spyderlib/plugins/externalconsole.py:1040
 msgid "Run a Python script"
 msgstr "Exécuter un script Python"
 
-#: spyderlib/plugins/console.py:133
+#: spyderlib/plugins/console.py:139
 msgid "Environment variables..."
 msgstr "Variables d'environnement..."
 
-#: spyderlib/plugins/console.py:135
+#: spyderlib/plugins/console.py:141
 msgid "Show and edit environment variables (for current session)"
 msgstr ""
 "Afficher et modifier les variables d'environnement (pour la session en cours)"
 
-#: spyderlib/plugins/console.py:139
+#: spyderlib/plugins/console.py:145
 msgid "Show sys.path contents..."
 msgstr "Afficher le contenu de sys.path..."
 
-#: spyderlib/plugins/console.py:141
+#: spyderlib/plugins/console.py:147
 msgid "Show (read-only) sys.path"
 msgstr "Afficher le contenu de sys.path (lecture seule)"
 
-#: spyderlib/plugins/console.py:144
+#: spyderlib/plugins/console.py:150
 msgid "Buffer..."
 msgstr "Tampon..."
 
-#: spyderlib/plugins/console.py:145 spyderlib/plugins/externalconsole.py:85
-#: spyderlib/plugins/history.py:40
+#: spyderlib/plugins/console.py:151 spyderlib/plugins/externalconsole.py:87
+#: spyderlib/plugins/history.py:41
 msgid "Set maximum line count"
 msgstr "Modifier le nombre maximum de lignes"
 
-#: spyderlib/plugins/console.py:148 spyderlib/plugins/explorer.py:57
-#: spyderlib/plugins/history.py:164 spyderlib/plugins/inspector.py:372
-#: spyderlib/plugins/projectexplorer.py:56
+#: spyderlib/plugins/console.py:154 spyderlib/plugins/explorer.py:67
+#: spyderlib/plugins/history.py:169 spyderlib/plugins/inspector.py:388
+#: spyderlib/plugins/projectexplorer.py:68
 msgid "&Font..."
 msgstr "&Police..."
 
-#: spyderlib/plugins/console.py:149 spyderlib/plugins/history.py:165
+#: spyderlib/plugins/console.py:155 spyderlib/plugins/history.py:170
 msgid "Set shell font style"
 msgstr "Changer la police d'écriture de la console"
 
-#: spyderlib/plugins/console.py:152
+#: spyderlib/plugins/console.py:158
 msgid "External editor path..."
 msgstr "Éditeur externe..."
 
-#: spyderlib/plugins/console.py:153
+#: spyderlib/plugins/console.py:159
 msgid "Set external editor executable path"
 msgstr "Modifier le chemin d'accès de l'éditeur externe"
 
-#: spyderlib/plugins/console.py:156 spyderlib/plugins/editor.py:144
-#: spyderlib/plugins/externalconsole.py:86 spyderlib/plugins/history.py:43
-#: spyderlib/plugins/history.py:167 spyderlib/plugins/inspector.py:175
-#: spyderlib/plugins/inspector.py:375
+#: spyderlib/plugins/console.py:162 spyderlib/plugins/editor.py:139
+#: spyderlib/plugins/externalconsole.py:88 spyderlib/plugins/history.py:44
+#: spyderlib/plugins/history.py:172 spyderlib/plugins/inspector.py:180
+#: spyderlib/plugins/inspector.py:391
 msgid "Wrap lines"
 msgstr "Retour à la ligne automatique"
 
-#: spyderlib/plugins/console.py:159 spyderlib/plugins/editor.py:178
+#: spyderlib/plugins/console.py:165 spyderlib/plugins/editor.py:181
 #: spyderlib/plugins/externalconsole.py:133
-#: spyderlib/plugins/ipythonconsole.py:175
+#: spyderlib/plugins/ipythonconsole.py:172
 msgid "Display balloon tips"
 msgstr "Afficher des info-bulles"
 
-#: spyderlib/plugins/console.py:163 spyderlib/plugins/editor.py:172
+#: spyderlib/plugins/console.py:169 spyderlib/plugins/editor.py:175
 #: spyderlib/plugins/externalconsole.py:127
 msgid "Automatic code completion"
 msgstr "Complétion de code automatique"
 
-#: spyderlib/plugins/console.py:167 spyderlib/plugins/editor.py:176
+#: spyderlib/plugins/console.py:173 spyderlib/plugins/editor.py:179
 #: spyderlib/plugins/externalconsole.py:131
 msgid "Enter key selects completion"
 msgstr "Entrée valide la complétion de code"
 
-#: spyderlib/plugins/console.py:172
+#: spyderlib/plugins/console.py:178
 msgid "Internal console settings"
 msgstr "Options de la console interne"
 
-#: spyderlib/plugins/console.py:223 spyderlib/plugins/externalconsole.py:1285
+#: spyderlib/plugins/console.py:231 spyderlib/plugins/externalconsole.py:1220
 msgid "Run Python script"
 msgstr "Exécuter un script Python"
 
-#: spyderlib/plugins/console.py:224 spyderlib/plugins/externalconsole.py:229
-#: spyderlib/plugins/externalconsole.py:1286 spyderlib/widgets/explorer.py:666
+#: spyderlib/plugins/console.py:232 spyderlib/plugins/externalconsole.py:226
+#: spyderlib/plugins/externalconsole.py:1221 spyderlib/widgets/explorer.py:675
 msgid "Python scripts"
 msgstr "Scripts Python"
 
-#: spyderlib/plugins/console.py:269 spyderlib/plugins/explorer.py:109
-#: spyderlib/plugins/history.py:282 spyderlib/plugins/inspector.py:651
-#: spyderlib/plugins/projectexplorer.py:118
+#: spyderlib/plugins/console.py:278 spyderlib/plugins/explorer.py:117
+#: spyderlib/plugins/history.py:285 spyderlib/plugins/inspector.py:665
+#: spyderlib/plugins/projectexplorer.py:126
 msgid "Select a new font"
 msgstr "Sélectionner une police d'écriture"
 
-#: spyderlib/plugins/console.py:276
+#: spyderlib/plugins/console.py:286
 msgid "Buffer"
 msgstr "Tampon"
 
-#: spyderlib/plugins/console.py:277
+#: spyderlib/plugins/console.py:287
 msgid "Maximum line count"
 msgstr "Nombre maximum de lignes"
 
-#: spyderlib/plugins/console.py:286
+#: spyderlib/plugins/console.py:297
 msgid "External editor"
 msgstr "Éditeur externe"
 
-#: spyderlib/plugins/console.py:287
+#: spyderlib/plugins/console.py:298
 msgid "External editor executable path:"
 msgstr "Chemin d'accès de l'exécutable :"
 
-#: spyderlib/plugins/editor.py:100
+#: spyderlib/plugins/editor.py:101
 msgid "Edit template for new modules"
 msgstr "Modifier le modèle (nouveaux modules)"
 
-#: spyderlib/plugins/editor.py:105
+#: spyderlib/plugins/editor.py:106
 msgid "Text and margin font style"
 msgstr "Police d'écriture du texte et de la marge"
 
-#: spyderlib/plugins/editor.py:108
+#: spyderlib/plugins/editor.py:109
 msgid "Sort files according to full path"
 msgstr "Classer les fichiers suivant leur chemin complet"
 
-#: spyderlib/plugins/editor.py:110
+#: spyderlib/plugins/editor.py:111
 msgid "Show tab bar"
 msgstr "Afficher la barre d'onglets"
 
-#: spyderlib/plugins/editor.py:117 spyderlib/plugins/editor.py:192
-#: spyderlib/plugins/externalconsole.py:81
-#: spyderlib/plugins/externalconsole.py:126 spyderlib/plugins/history.py:42
-#: spyderlib/plugins/inspector.py:174 spyderlib/plugins/ipythonconsole.py:199
+#: spyderlib/plugins/editor.py:118 spyderlib/plugins/editor.py:195
+#: spyderlib/plugins/externalconsole.py:83
+#: spyderlib/plugins/externalconsole.py:126 spyderlib/plugins/history.py:43
+#: spyderlib/plugins/inspector.py:179 spyderlib/plugins/ipythonconsole.py:206
 msgid "Source code"
 msgstr "Code source"
 
-#: spyderlib/plugins/editor.py:118
+#: spyderlib/plugins/editor.py:119
 msgid "Show line numbers"
 msgstr "Afficher les numéros de ligne"
 
-#: spyderlib/plugins/editor.py:119 spyderlib/plugins/editor.py:892
+#: spyderlib/plugins/editor.py:120 spyderlib/plugins/editor.py:916
 msgid "Show blank spaces"
 msgstr "Afficher les espaces"
 
-#: spyderlib/plugins/editor.py:120
+#: spyderlib/plugins/editor.py:121
 msgid "Show vertical line after"
 msgstr "Afficher une ligne verticale après"
 
-#: spyderlib/plugins/editor.py:121
+#: spyderlib/plugins/editor.py:122
 msgid "characters"
 msgstr "caractères"
 
-#: spyderlib/plugins/editor.py:129
+#: spyderlib/plugins/editor.py:127
 msgid "Highlight current line"
 msgstr "Surligner la ligne en cours d'édition"
 
-#: spyderlib/plugins/editor.py:131
+#: spyderlib/plugins/editor.py:129
 msgid "Highlight current cell"
 msgstr "Surligner la cellule en cours d'édition"
 
-#: spyderlib/plugins/editor.py:133
+#: spyderlib/plugins/editor.py:131
 msgid "Highlight occurences after"
 msgstr "Surligner les occurences après"
 
-#: spyderlib/plugins/editor.py:147 spyderlib/plugins/history.py:51
-#: spyderlib/plugins/inspector.py:178
+#: spyderlib/plugins/editor.py:142 spyderlib/plugins/history.py:52
+#: spyderlib/plugins/inspector.py:183
 msgid "Syntax color scheme: "
 msgstr "Thème de coloration syntaxique : "
 
-#: spyderlib/plugins/editor.py:161 spyderlib/plugins/runconfig.py:313
-#: spyderlib/plugins/runconfig.py:435 spyderlib/plugins/runconfig.py:440
-#: spyderlib/spyder.py:1850 spyderlib/utils/programs.py:175
-#: spyderlib/widgets/explorer.py:234
-#: spyderlib/widgets/externalshell/baseshell.py:138
+#: spyderlib/plugins/editor.py:164 spyderlib/plugins/runconfig.py:321
+#: spyderlib/plugins/runconfig.py:443 spyderlib/plugins/runconfig.py:448
+#: spyderlib/spyder.py:2501 spyderlib/utils/programs.py:175
+#: spyderlib/widgets/explorer.py:240
+#: spyderlib/widgets/externalshell/baseshell.py:140
 msgid "Run"
 msgstr "Exécuter"
 
-#: spyderlib/plugins/editor.py:162
+#: spyderlib/plugins/editor.py:165
 msgid "Save all files before running script"
 msgstr "Enregistrer tous les fichiers avant l'exécution d'un script"
 
-#: spyderlib/plugins/editor.py:165
+#: spyderlib/plugins/editor.py:168
 msgid "Run selection"
 msgstr "Exécuter la sélection"
 
-#: spyderlib/plugins/editor.py:166
+#: spyderlib/plugins/editor.py:169
 msgid "Maintain focus in the Editor after running cells or selections"
 msgstr ""
 "Garder le focus dans l'éditeur après l'exécution d'une cellule ou d'une "
 "sélection"
 
-#: spyderlib/plugins/editor.py:169 spyderlib/plugins/externalconsole.py:365
+#: spyderlib/plugins/editor.py:172 spyderlib/plugins/externalconsole.py:334
 msgid "Introspection"
 msgstr "Introspection"
 
-#: spyderlib/plugins/editor.py:174 spyderlib/plugins/externalconsole.py:129
+#: spyderlib/plugins/editor.py:177 spyderlib/plugins/externalconsole.py:129
 msgid "Case sensitive code completion"
 msgstr "Complétion de code sensible à la casse"
 
-#: spyderlib/plugins/editor.py:179
+#: spyderlib/plugins/editor.py:182
 msgid "Link to object definition"
 msgstr "Lien vers la définition d'un objet"
 
-#: spyderlib/plugins/editor.py:181
+#: spyderlib/plugins/editor.py:184
 msgid ""
 "If this option is enabled, clicking on an object\n"
 "name (left-click + Ctrl key) will go this object\n"
@@ -546,7 +601,7 @@ msgstr ""
 "d'un objet (click gauche + touche Ctrl) ira à la\n"
 "définition de cet objet (si celle-ci est trouvée)."
 
-#: spyderlib/plugins/editor.py:185
+#: spyderlib/plugins/editor.py:188
 msgid ""
 "<b>Warning:</b><br>The Python module <i>rope</i> is not installed on this "
 "computer: calltips, code completion and go-to-definition features won't be "
@@ -556,51 +611,51 @@ msgstr ""
 "sur cet ordinateur : les fonctionnalités telles que la complétion de code ou "
 "le lien vers la définition d'un objet ne sont donc pas accessibles."
 
-#: spyderlib/plugins/editor.py:193
+#: spyderlib/plugins/editor.py:196
 msgid "Automatic insertion of parentheses, braces and brackets"
 msgstr "Insertion automatique des parenthèses, crochets et accolades"
 
-#: spyderlib/plugins/editor.py:196
+#: spyderlib/plugins/editor.py:199
 msgid "Automatic insertion of closing quotes"
 msgstr "Insertion automatique de guillemets de clôture"
 
-#: spyderlib/plugins/editor.py:198
+#: spyderlib/plugins/editor.py:201
 msgid "Automatic insertion of colons after 'for', 'if', 'def', etc"
 msgstr "Insertion automatique de ':' après 'for', 'if', 'def', etc."
 
-#: spyderlib/plugins/editor.py:201
+#: spyderlib/plugins/editor.py:204
 msgid "Automatic indentation after 'else', 'elif', etc."
 msgstr "Indentation automatique après 'else', 'elif', etc."
 
-#: spyderlib/plugins/editor.py:203
+#: spyderlib/plugins/editor.py:206
 msgid "Indentation characters: "
 msgstr "Caractères d'indentation : "
 
-#: spyderlib/plugins/editor.py:204
+#: spyderlib/plugins/editor.py:207
 msgid "4 spaces"
 msgstr "4 espaces"
 
-#: spyderlib/plugins/editor.py:205
+#: spyderlib/plugins/editor.py:208
 msgid "2 spaces"
 msgstr "2 espaces"
 
-#: spyderlib/plugins/editor.py:206
+#: spyderlib/plugins/editor.py:209
 msgid "tab"
 msgstr "tabulation"
 
-#: spyderlib/plugins/editor.py:207
+#: spyderlib/plugins/editor.py:210
 msgid "Tab stop width:"
 msgstr "Largeur des tabulations :"
 
-#: spyderlib/plugins/editor.py:207
+#: spyderlib/plugins/editor.py:210
 msgid "pixels"
 msgstr "pixels"
 
-#: spyderlib/plugins/editor.py:209
+#: spyderlib/plugins/editor.py:212
 msgid "Tab always indent"
 msgstr "Toujours indenter avec la touche Tab"
 
-#: spyderlib/plugins/editor.py:211
+#: spyderlib/plugins/editor.py:214
 msgid ""
 "If enabled, pressing Tab will always indent,\n"
 "even when the cursor is not at the beginning\n"
@@ -614,81 +669,78 @@ msgstr ""
 "option est activée, la complétion de code reste \n"
 "accessible via le raccourci Ctrl+Espace)"
 
-#: spyderlib/plugins/editor.py:216
+#: spyderlib/plugins/editor.py:219
 msgid "Intelligent backspace"
 msgstr "Retour arrière (\"backspace\") intelligent"
 
-#: spyderlib/plugins/editor.py:218
+#: spyderlib/plugins/editor.py:221
 msgid "Automatically remove trailing spaces when saving files"
 msgstr ""
 "Supprimer automatiquement les espaces en fin de ligne lors de "
 "l'enregistrement"
 
-#: spyderlib/plugins/editor.py:222
+#: spyderlib/plugins/editor.py:225
 msgid "Analysis"
 msgstr "Analyse"
 
-#: spyderlib/plugins/editor.py:224
-msgid ""
-"<u>Note</u>: add <b>analysis:ignore</b> in a comment to ignore code/style "
-"analysis warnings. For more informations on style guide for Python code, "
-"please refer to the %s page."
+#: spyderlib/plugins/editor.py:227
+msgid "<i>(Refer to the {} page)</i>"
 msgstr ""
-"<u>Note</u>: ajouter <b>analysis:ignore</b> dans un commentaire pour ignorer "
-"les résultats de l'analyse de code ou de style. Pour plus d'informations sur "
-"les recommandations officielles de style d'écriture avec le langage Python, "
-"veuillez visiter la page de la %s."
 
-#: spyderlib/plugins/editor.py:233
-#: spyderlib/widgets/sourcecode/codeeditor.py:1617
-msgid "Code analysis"
-msgstr "Analyse de code"
+#: spyderlib/plugins/editor.py:231
+#, fuzzy
+msgid "Real-time code analysis"
+msgstr "Analyse de code temps réel dans l'éditeur"
 
-#: spyderlib/plugins/editor.py:235
+#: spyderlib/plugins/editor.py:233
+#, fuzzy
 msgid ""
-"If enabled, Python source code will be analyzed\n"
-"using pyflakes, lines containing errors or \n"
-"warnings will be highlighted"
+"<p>If enabled, Python source code will be analyzedusing pyflakes, lines "
+"containing errors or warnings will be highlighted.</p><p><u>Note</u>: add "
+"<b>analysis:ignore</b> in a comment to ignore code analysis warnings.</p>"
 msgstr ""
 "Si cette option est activée, le code source Python sera analysé\n"
 "avec des outils l'outil d'introspection de code pyflakes\n"
 "et les lignes contenant des erreurs seront indiquées"
 
-#: spyderlib/plugins/editor.py:240
+#: spyderlib/plugins/editor.py:241
 msgid "Code analysis requires pyflakes %s+"
 msgstr "L'analyse de code requiert pyflakes %s+"
 
-#: spyderlib/plugins/editor.py:242
-msgid "Style analysis"
-msgstr "Analyse de style"
+#: spyderlib/plugins/editor.py:243
+#, fuzzy
+msgid "Real-time code style analysis"
+msgstr "Analyse de code temps réel dans l'éditeur"
 
-#: spyderlib/plugins/editor.py:244
+#: spyderlib/plugins/editor.py:245
+#, fuzzy
 msgid ""
-"If enabled, Python source code will be analyzed\n"
-"using pep8, lines that are not following PEP8\n"
-"style guide will be highlighted"
+"<p>If enabled, Python source code will be analyzedusing pep8, lines that are "
+"not following PEP8 style guide will be highlighted.</p><p><u>Note</u>: add "
+"<b>analysis:ignore</b> in a comment to ignore style analysis warnings.</p>"
 msgstr ""
 "Si cette option est activée, le style du code source Python sera analysé\n"
 "avec l'outil d'introspection de code pep8 et les lignes ne suivant pas\n"
 "les recommandations officielles seront indiquées"
 
-#: spyderlib/plugins/editor.py:251
-msgid "Tasks (TODO, FIXME, XXX, HINT, TIP, @todo)"
+#: spyderlib/plugins/editor.py:252
+#, fuzzy
+msgid "Code annotations (TODO, FIXME, XXX, HINT, TIP, @todo)"
 msgstr "Tâches (TODO, FIXME, XXX, HINT, TIP, @todo)"
 
-#: spyderlib/plugins/editor.py:254
+#: spyderlib/plugins/editor.py:255
 msgid "Perform analysis when saving file and every"
 msgstr "Analyser lors de l'enregistrement et toutes les"
 
-#: spyderlib/plugins/editor.py:258
+#: spyderlib/plugins/editor.py:259
 msgid "Perform analysis only when saving file"
 msgstr "Analyser uniquement lors de l'enregistrement"
 
-#: spyderlib/plugins/editor.py:306
+#: spyderlib/plugins/editor.py:318
 msgid "End-of-line characters"
 msgstr "Caractères de fin de ligne"
 
-#: spyderlib/plugins/editor.py:307
+#: spyderlib/plugins/editor.py:319
 msgid ""
 "When opening a text file containing mixed end-of-line characters (this may "
 "raise syntax errors in the consoles on Windows platforms), Spyder may fix "
@@ -699,224 +751,224 @@ msgstr ""
 "consoles Python sous Windows), Spyder peut réparer le fichier "
 "automatiquement."
 
-#: spyderlib/plugins/editor.py:313
+#: spyderlib/plugins/editor.py:325
 msgid "Fix automatically and show warning message box"
 msgstr "Réparer automatiquement et afficher un message d'avertissement"
 
-#: spyderlib/plugins/editor.py:324 spyderlib/plugins/externalconsole.py:363
-#: spyderlib/plugins/ipythonconsole.py:444
+#: spyderlib/plugins/editor.py:336 spyderlib/plugins/externalconsole.py:332
+#: spyderlib/plugins/ipythonconsole.py:463
 #: spyderlib/plugins/variableexplorer.py:41
 msgid "Display"
 msgstr "Affichage"
 
-#: spyderlib/plugins/editor.py:326
+#: spyderlib/plugins/editor.py:338
 msgid "Code Introspection/Analysis"
 msgstr "Introspection et analyse de code"
 
-#: spyderlib/plugins/editor.py:329 spyderlib/plugins/externalconsole.py:367
+#: spyderlib/plugins/editor.py:341 spyderlib/plugins/externalconsole.py:336
 msgid "Advanced settings"
 msgstr "Options avancées"
 
-#: spyderlib/plugins/editor.py:583 spyderlib/widgets/editortools.py:508
+#: spyderlib/plugins/editor.py:607 spyderlib/widgets/editortools.py:510
 msgid "Show/hide outline explorer"
 msgstr "Afficher/masquer l'explorateur de structure"
 
-#: spyderlib/plugins/editor.py:589
+#: spyderlib/plugins/editor.py:613
 msgid "Show/hide project explorer"
 msgstr "Afficher/masquer l'explorateur de projets"
 
-#: spyderlib/plugins/editor.py:597
+#: spyderlib/plugins/editor.py:621
 msgid "&New file..."
 msgstr "&Nouveau fichier..."
 
-#: spyderlib/plugins/editor.py:598 spyderlib/plugins/workingdirectory.py:82
-#: spyderlib/widgets/explorer.py:643 spyderlib/widgets/explorer.py:650
+#: spyderlib/plugins/editor.py:622 spyderlib/plugins/workingdirectory.py:82
+#: spyderlib/widgets/explorer.py:652 spyderlib/widgets/explorer.py:659
 msgid "New file"
 msgstr "Nouveau fichier"
 
-#: spyderlib/plugins/editor.py:605
+#: spyderlib/plugins/editor.py:629
 msgid "&Open..."
 msgstr "&Ouvrir..."
 
-#: spyderlib/plugins/editor.py:606 spyderlib/plugins/editor.py:1647
+#: spyderlib/plugins/editor.py:630 spyderlib/plugins/editor.py:1643
 #: spyderlib/plugins/workingdirectory.py:69
 msgid "Open file"
 msgstr "Ouvrir un fichier"
 
-#: spyderlib/plugins/editor.py:613
+#: spyderlib/plugins/editor.py:637
 msgid "&Revert"
 msgstr "&Réinitialiser"
 
-#: spyderlib/plugins/editor.py:614
+#: spyderlib/plugins/editor.py:638
 msgid "Revert file from disk"
 msgstr "Revenir à la version du fichier enregistrée sur le disque"
 
-#: spyderlib/plugins/editor.py:617
+#: spyderlib/plugins/editor.py:641
 msgid "&Save"
 msgstr "&Enregistrer"
 
-#: spyderlib/plugins/editor.py:618
+#: spyderlib/plugins/editor.py:642
 msgid "Save file"
 msgstr "Enregitrer un fichier"
 
-#: spyderlib/plugins/editor.py:625
+#: spyderlib/plugins/editor.py:649
 msgid "Sav&e all"
 msgstr "Enregistrer &tout"
 
-#: spyderlib/plugins/editor.py:626
+#: spyderlib/plugins/editor.py:650
 msgid "Save all files"
 msgstr "Enregistrer tous les fichiers"
 
-#: spyderlib/plugins/editor.py:633
+#: spyderlib/plugins/editor.py:658
 msgid "Save &as..."
 msgstr "Enregistrer &sous..."
 
-#: spyderlib/plugins/editor.py:634
+#: spyderlib/plugins/editor.py:659
 msgid "Save current file as..."
 msgstr "Enregistrer le fichier en cours d'édition sous un autre nom..."
 
-#: spyderlib/plugins/editor.py:636 spyderlib/plugins/editor.py:637
+#: spyderlib/plugins/editor.py:663 spyderlib/plugins/editor.py:664
 msgid "Print preview..."
 msgstr "Aperçu avant impression..."
 
-#: spyderlib/plugins/editor.py:638
+#: spyderlib/plugins/editor.py:665
 msgid "&Print..."
 msgstr "Im&primer..."
 
-#: spyderlib/plugins/editor.py:639
+#: spyderlib/plugins/editor.py:666
 msgid "Print current file..."
 msgstr "Imprimer le fichier en cours d'édition..."
 
-#: spyderlib/plugins/editor.py:644
+#: spyderlib/plugins/editor.py:669
 msgid "&Close"
 msgstr "&Fermer"
 
-#: spyderlib/plugins/editor.py:645
+#: spyderlib/plugins/editor.py:670
 msgid "Close current file"
 msgstr "Fermer le fichier en cours d'édition"
 
-#: spyderlib/plugins/editor.py:647
+#: spyderlib/plugins/editor.py:673
 msgid "C&lose all"
 msgstr "Fermer t&out"
 
-#: spyderlib/plugins/editor.py:648
+#: spyderlib/plugins/editor.py:674
 msgid "Close all opened files"
 msgstr "Fermer tous les fichiers ouverts"
 
-#: spyderlib/plugins/editor.py:655
+#: spyderlib/plugins/editor.py:681
 msgid "Set/Clear breakpoint"
 msgstr "Ajouter/supprimer un point d'arrêt"
 
-#: spyderlib/plugins/editor.py:662
+#: spyderlib/plugins/editor.py:688
 msgid "Set/Edit conditional breakpoint"
 msgstr "Ajouter/modifier un point d'arrêt conditionnel"
 
-#: spyderlib/plugins/editor.py:669
+#: spyderlib/plugins/editor.py:695
 msgid "Clear breakpoints in all files"
 msgstr "Supprimer les points d'arrêt dans tous les fichiers"
 
-#: spyderlib/plugins/editor.py:671
+#: spyderlib/plugins/editor.py:697
 msgid "Breakpoints"
 msgstr "Points d'arrêt"
 
-#: spyderlib/plugins/editor.py:675
+#: spyderlib/plugins/editor.py:701
 msgid "Debug with winpdb"
 msgstr "Déboguer avec winpdb"
 
-#: spyderlib/plugins/editor.py:682 spyderlib/spyder.py:575
+#: spyderlib/plugins/editor.py:708 spyderlib/spyder.py:659
 msgid "&Debug"
 msgstr "&Déboguer"
 
-#: spyderlib/plugins/editor.py:683
+#: spyderlib/plugins/editor.py:709
 msgid "Debug file"
 msgstr "Déboguer le script"
 
-#: spyderlib/plugins/editor.py:688
+#: spyderlib/plugins/editor.py:713
 msgid "Step"
 msgstr "Pas"
 
-#: spyderlib/plugins/editor.py:689
+#: spyderlib/plugins/editor.py:714
 msgid "Run current line"
 msgstr "Exécuter la ligne en cours"
 
-#: spyderlib/plugins/editor.py:695
+#: spyderlib/plugins/editor.py:720
 msgid "Continue"
 msgstr "Continuer"
 
-#: spyderlib/plugins/editor.py:696
+#: spyderlib/plugins/editor.py:721
 msgid "Continue execution until next breakpoint"
 msgstr "Continuer l'exécution jusqu'au prochain point d'arrêt"
 
-#: spyderlib/plugins/editor.py:703
+#: spyderlib/plugins/editor.py:728
 msgid "Step Into"
 msgstr "Pas vers l'intérieur"
 
-#: spyderlib/plugins/editor.py:704
+#: spyderlib/plugins/editor.py:729
 msgid "Step into function or method of current line"
 msgstr ""
 "Avancer dans la fonction, méthode \n"
 "ou classe de la ligne en cours"
 
-#: spyderlib/plugins/editor.py:711
+#: spyderlib/plugins/editor.py:736
 msgid "Step Return"
 msgstr "Pas vers l'extérieur"
 
-#: spyderlib/plugins/editor.py:712
+#: spyderlib/plugins/editor.py:737
 msgid "Run until current function or method returns"
 msgstr "Exécuter jusqu'au retour de la fonction ou méthode"
 
-#: spyderlib/plugins/editor.py:719
+#: spyderlib/plugins/editor.py:744
 msgid "Exit"
 msgstr "Sortir"
 
-#: spyderlib/plugins/editor.py:720
+#: spyderlib/plugins/editor.py:745
 msgid "Exit Debug"
 msgstr "Quitter le débogage"
 
-#: spyderlib/plugins/editor.py:731
+#: spyderlib/plugins/editor.py:756
 msgid "Debugging control"
 msgstr "Contrôle du débogage"
 
-#: spyderlib/plugins/editor.py:735 spyderlib/plugins/editor.py:1246
-#: spyderlib/spyder.py:570
+#: spyderlib/plugins/editor.py:760 spyderlib/plugins/editor.py:1236
+#: spyderlib/spyder.py:654
 msgid "&Run"
 msgstr "E&xécution"
 
-#: spyderlib/plugins/editor.py:736
+#: spyderlib/plugins/editor.py:761
 msgid "Run file"
 msgstr "Exécuter le fichier"
 
-#: spyderlib/plugins/editor.py:742
+#: spyderlib/plugins/editor.py:766
 msgid "&Configure..."
 msgstr "&Configurer..."
 
-#: spyderlib/plugins/editor.py:743
-#: spyderlib/widgets/externalshell/pythonshell.py:294
+#: spyderlib/plugins/editor.py:768
+#: spyderlib/widgets/externalshell/pythonshell.py:311
 msgid "Run settings"
 msgstr "Options d'exécution"
 
-#: spyderlib/plugins/editor.py:752
+#: spyderlib/plugins/editor.py:776
 msgid "Re-run &last script"
 msgstr "Exécuter de nouveau le &dernier script"
 
-#: spyderlib/plugins/editor.py:753
+#: spyderlib/plugins/editor.py:778
 msgid "Run again last file"
 msgstr "Exécuter de nouveau le dernier fichier"
 
-#: spyderlib/plugins/editor.py:760
-#: spyderlib/widgets/sourcecode/codeeditor.py:2305
+#: spyderlib/plugins/editor.py:785
+#: spyderlib/widgets/sourcecode/codeeditor.py:2462
 msgid "Run &selection or current line"
 msgstr "Exécuter la &sélection ou la ligne courante"
 
-#: spyderlib/plugins/editor.py:763
+#: spyderlib/plugins/editor.py:788
 msgid "Run selection or current line"
 msgstr "Exécuter la sélection ou le bloc de lignes"
 
-#: spyderlib/plugins/editor.py:776
+#: spyderlib/plugins/editor.py:801
 msgid "Run cell"
 msgstr "Exécuter la cellule"
 
-#: spyderlib/plugins/editor.py:778
+#: spyderlib/plugins/editor.py:804
 msgid ""
 "Run current cell (Ctrl+Enter)\n"
 "[Use #%% to create cells]"
@@ -924,160 +976,160 @@ msgstr ""
 "Exécuter la cellule courante \n"
 "[Utiliser #%% pour délimiter les cellules]"
 
-#: spyderlib/plugins/editor.py:783
+#: spyderlib/plugins/editor.py:809
 msgid "Run cell and advance"
 msgstr "Exécuter la cellule et avancer"
 
-#: spyderlib/plugins/editor.py:786
+#: spyderlib/plugins/editor.py:812
 msgid "Run current cell and go to the next one (Shift+Enter)"
 msgstr ""
 "Exécuter la cellule en cours d'édition et aller à la suivante\n"
 "(voir la documentation de l'Editeur, pour plus de détails sur les cellules)"
 
-#: spyderlib/plugins/editor.py:792
+#: spyderlib/plugins/editor.py:818
 msgid "Show todo list"
 msgstr "Afficher la liste des tâches"
 
-#: spyderlib/plugins/editor.py:793
+#: spyderlib/plugins/editor.py:819
 msgid "Show TODO/FIXME/XXX/HINT/TIP/@todo comments list"
 msgstr ""
 "Afficher la liste des commentaires du type TODO/FIXME/XXX/HINT/TIP/@todo"
 
-#: spyderlib/plugins/editor.py:801
+#: spyderlib/plugins/editor.py:826
 msgid "Show warning/error list"
 msgstr "Afficher la liste des avertissements/erreurs"
 
-#: spyderlib/plugins/editor.py:802
+#: spyderlib/plugins/editor.py:827
 msgid "Show code analysis warnings/errors"
 msgstr ""
 "Afficher la liste des avertissements/erreurs provenant de l'analyse de code"
 
-#: spyderlib/plugins/editor.py:809
+#: spyderlib/plugins/editor.py:833
 msgid "Previous warning/error"
 msgstr "Avertissement suivant"
 
-#: spyderlib/plugins/editor.py:810
+#: spyderlib/plugins/editor.py:834
 msgid "Go to previous code analysis warning/error"
 msgstr "Afficher le message d'avertissement ou d'erreur suivant"
 
-#: spyderlib/plugins/editor.py:813
+#: spyderlib/plugins/editor.py:837
 msgid "Next warning/error"
 msgstr "Avertissement précédent"
 
-#: spyderlib/plugins/editor.py:814
+#: spyderlib/plugins/editor.py:838
 msgid "Go to next code analysis warning/error"
 msgstr "Afficher le message d'avertissement ou d'erreur précédent"
 
-#: spyderlib/plugins/editor.py:818
+#: spyderlib/plugins/editor.py:842
 msgid "Last edit location"
 msgstr "Dernière position d'édition"
 
-#: spyderlib/plugins/editor.py:819
+#: spyderlib/plugins/editor.py:843
 msgid "Go to last edit location"
 msgstr "Aller à la dernière position d'édition"
 
-#: spyderlib/plugins/editor.py:825
+#: spyderlib/plugins/editor.py:849
 msgid "Previous cursor position"
 msgstr "Position suivante du curseur"
 
-#: spyderlib/plugins/editor.py:826
+#: spyderlib/plugins/editor.py:850
 msgid "Go to previous cursor position"
 msgstr "Aller à la position précédente du curseur"
 
-#: spyderlib/plugins/editor.py:832
+#: spyderlib/plugins/editor.py:856
 msgid "Next cursor position"
 msgstr "Position suivante du curseur"
 
-#: spyderlib/plugins/editor.py:833
+#: spyderlib/plugins/editor.py:857
 msgid "Go to next cursor position"
 msgstr "Aller à la position suivante du curseur"
 
-#: spyderlib/plugins/editor.py:840
-#: spyderlib/widgets/sourcecode/codeeditor.py:2292
+#: spyderlib/plugins/editor.py:864
+#: spyderlib/widgets/sourcecode/codeeditor.py:2449
 msgid "Comment"
 msgstr "Commenter"
 
-#: spyderlib/plugins/editor.py:840
-#: spyderlib/widgets/sourcecode/codeeditor.py:2292
+#: spyderlib/plugins/editor.py:864
+#: spyderlib/widgets/sourcecode/codeeditor.py:2449
 msgid "Uncomment"
 msgstr "Décommenter"
 
-#: spyderlib/plugins/editor.py:841
+#: spyderlib/plugins/editor.py:865
 msgid "Comment current line or selection"
 msgstr "Commenter la sélection ou la ligne en cours d'édition"
 
-#: spyderlib/plugins/editor.py:845
+#: spyderlib/plugins/editor.py:869
 msgid "Add &block comment"
 msgstr "Ajouter un &bloc de commentaires"
 
-#: spyderlib/plugins/editor.py:846
+#: spyderlib/plugins/editor.py:870
 msgid "Add block comment around current line or selection"
 msgstr ""
 "Ajouter un bloc de commentaires autour de la sélection ou de la ligne en "
 "cours d'édition"
 
-#: spyderlib/plugins/editor.py:852
+#: spyderlib/plugins/editor.py:876
 msgid "R&emove block comment"
 msgstr "&Supprimer un bloc de commentaires"
 
-#: spyderlib/plugins/editor.py:853
+#: spyderlib/plugins/editor.py:877
 msgid "Remove comment block around current line or selection"
 msgstr ""
 "Supprimer le bloc de commentaires autour de la ligne en cours d'édition"
 
-#: spyderlib/plugins/editor.py:864
+#: spyderlib/plugins/editor.py:888
 msgid "Indent"
 msgstr "Indenter"
 
-#: spyderlib/plugins/editor.py:865
+#: spyderlib/plugins/editor.py:889
 msgid "Indent current line or selection"
 msgstr "Indenter la sélection ou la ligne en cours d'édition"
 
-#: spyderlib/plugins/editor.py:868
+#: spyderlib/plugins/editor.py:892
 msgid "Unindent"
 msgstr "Désindenter"
 
-#: spyderlib/plugins/editor.py:869
+#: spyderlib/plugins/editor.py:893
 msgid "Unindent current line or selection"
 msgstr "Désindenter la sélection ou la ligne en cours d'édition"
 
-#: spyderlib/plugins/editor.py:874
+#: spyderlib/plugins/editor.py:898
 msgid "Carriage return and line feed (Windows)"
 msgstr "Retour chariot et retour à la ligne (Windows)"
 
-#: spyderlib/plugins/editor.py:877
+#: spyderlib/plugins/editor.py:901
 msgid "Line feed (UNIX)"
 msgstr "Retour à la ligne (UNIX)"
 
-#: spyderlib/plugins/editor.py:880
+#: spyderlib/plugins/editor.py:904
 msgid "Carriage return (Mac)"
 msgstr "Retour chariot (Mac)"
 
-#: spyderlib/plugins/editor.py:886
+#: spyderlib/plugins/editor.py:910
 msgid "Convert end-of-line characters"
 msgstr "Convertir les caractères de fin de ligne"
 
-#: spyderlib/plugins/editor.py:890
+#: spyderlib/plugins/editor.py:914
 msgid "Remove trailing spaces"
 msgstr "Supprimer les espaces en fin de ligne"
 
-#: spyderlib/plugins/editor.py:894
+#: spyderlib/plugins/editor.py:918
 msgid "Fix indentation"
 msgstr "Corriger l'indentation"
 
-#: spyderlib/plugins/editor.py:895
+#: spyderlib/plugins/editor.py:919
 msgid "Replace tab characters by space characters"
 msgstr "Remplacer les caractères de tabulation par des espaces"
 
-#: spyderlib/plugins/editor.py:898
+#: spyderlib/plugins/editor.py:922
 msgid "Go to line..."
 msgstr "Aller à la ligne..."
 
-#: spyderlib/plugins/editor.py:906
+#: spyderlib/plugins/editor.py:930
 msgid "Set console working directory"
 msgstr "Répertoire de travail de la console"
 
-#: spyderlib/plugins/editor.py:908
+#: spyderlib/plugins/editor.py:932
 msgid ""
 "Set current console (and file explorer) working directory to current script "
 "directory"
@@ -1085,139 +1137,139 @@ msgstr ""
 "Choisir le répertoire du script comme répertoire de travail de la console "
 "courante (et de l'explorateur de fichier)"
 
-#: spyderlib/plugins/editor.py:913
+#: spyderlib/plugins/editor.py:937
 msgid "Maximum number of recent files..."
 msgstr "Nombre maximum de fichiers récents..."
 
-#: spyderlib/plugins/editor.py:916
+#: spyderlib/plugins/editor.py:940
 msgid "Clear recent files list"
 msgstr "Effacer la liste des fichiers récents"
 
-#: spyderlib/plugins/editor.py:916
+#: spyderlib/plugins/editor.py:940
 msgid "Clear this list"
 msgstr "Effacer cette liste"
 
-#: spyderlib/plugins/editor.py:918
+#: spyderlib/plugins/editor.py:942
 msgid "Open &recent"
 msgstr "Fichiers &récents"
 
-#: spyderlib/plugins/editor.py:1234 spyderlib/spyder.py:551
+#: spyderlib/plugins/editor.py:1224 spyderlib/spyder.py:635
 msgid "File toolbar"
 msgstr "Barre d'outil fichiers"
 
-#: spyderlib/plugins/editor.py:1235 spyderlib/spyder.py:561
+#: spyderlib/plugins/editor.py:1225 spyderlib/spyder.py:645
 msgid "Search toolbar"
 msgstr "Barre d'outil de recherche"
 
-#: spyderlib/plugins/editor.py:1236 spyderlib/spyder.py:566
+#: spyderlib/plugins/editor.py:1226 spyderlib/spyder.py:650
 msgid "Source toolbar"
 msgstr "Barre d'outils code source"
 
-#: spyderlib/plugins/editor.py:1237 spyderlib/spyder.py:571
+#: spyderlib/plugins/editor.py:1227 spyderlib/spyder.py:655
 msgid "Run toolbar"
 msgstr "Barre d'outil exécution"
 
-#: spyderlib/plugins/editor.py:1238 spyderlib/spyder.py:576
+#: spyderlib/plugins/editor.py:1228 spyderlib/spyder.py:660
 msgid "Debug toolbar"
 msgstr "Barre d'outil de débogage"
 
-#: spyderlib/plugins/editor.py:1239 spyderlib/spyder.py:556
+#: spyderlib/plugins/editor.py:1229 spyderlib/spyder.py:640
 msgid "Edit toolbar"
 msgstr "Barre d'outil édition"
 
-#: spyderlib/plugins/editor.py:1242 spyderlib/spyder.py:548
+#: spyderlib/plugins/editor.py:1232 spyderlib/spyder.py:633
 msgid "&File"
 msgstr "&Fichier"
 
-#: spyderlib/plugins/editor.py:1243 spyderlib/spyder.py:555
+#: spyderlib/plugins/editor.py:1233 spyderlib/spyder.py:639
 msgid "&Edit"
 msgstr "&Édition"
 
-#: spyderlib/plugins/editor.py:1244 spyderlib/spyder.py:560
+#: spyderlib/plugins/editor.py:1234 spyderlib/spyder.py:644
 msgid "&Search"
 msgstr "&Recherche"
 
-#: spyderlib/plugins/editor.py:1245 spyderlib/spyder.py:565
+#: spyderlib/plugins/editor.py:1235 spyderlib/spyder.py:649
 msgid "Sour&ce"
 msgstr "Sour&ce"
 
-#: spyderlib/plugins/editor.py:1247 spyderlib/spyder.py:583
+#: spyderlib/plugins/editor.py:1237 spyderlib/spyder.py:667
 msgid "&Tools"
 msgstr "Ou&tils"
 
-#: spyderlib/plugins/editor.py:1248
+#: spyderlib/plugins/editor.py:1238
 msgid "?"
 msgstr "?"
 
-#: spyderlib/plugins/editor.py:1469
+#: spyderlib/plugins/editor.py:1458
 msgid "Spyder Editor"
 msgstr "Éditeur de Spyder"
 
-#: spyderlib/plugins/editor.py:1470
+#: spyderlib/plugins/editor.py:1459
 msgid "This is a temporary script file."
 msgstr "Ceci est un script temporaire."
 
-#: spyderlib/plugins/editor.py:1536
+#: spyderlib/plugins/editor.py:1527
 msgid "untitled"
 msgstr "sanstitre"
 
-#: spyderlib/plugins/editor.py:1607
+#: spyderlib/plugins/editor.py:1601
 msgid "Maximum number of recent files"
 msgstr "Nombre maximum de fichiers récents"
 
-#: spyderlib/plugins/editor.py:1729
+#: spyderlib/plugins/editor.py:1726
 msgid "Printing..."
 msgstr "Impression en cours..."
 
-#: spyderlib/plugins/explorer.py:45
+#: spyderlib/plugins/explorer.py:55
 msgid "File explorer"
 msgstr "Explorateur de fichiers"
 
-#: spyderlib/plugins/explorer.py:58 spyderlib/plugins/inspector.py:373
-#: spyderlib/plugins/projectexplorer.py:57
+#: spyderlib/plugins/explorer.py:68 spyderlib/plugins/inspector.py:389
+#: spyderlib/plugins/projectexplorer.py:69
 msgid "Set font style"
 msgstr "Changer la police d'écriture"
 
-#: spyderlib/plugins/externalconsole.py:46
+#: spyderlib/plugins/externalconsole.py:49
 msgid "Interactive data plotting in the consoles"
 msgstr "Visualisation interactive de données"
 
-#: spyderlib/plugins/externalconsole.py:53
-#: spyderlib/plugins/externalconsole.py:1066
-#: spyderlib/plugins/inspector.py:403 spyderlib/plugins/runconfig.py:178
-#: spyderlib/plugins/runconfig.py:447
-#: spyderlib/widgets/externalshell/baseshell.py:106
-#: spyderlib/widgets/ipython.py:509
+#: spyderlib/plugins/externalconsole.py:57
+#: spyderlib/plugins/externalconsole.py:1005
+#: spyderlib/plugins/inspector.py:419 spyderlib/plugins/runconfig.py:185
+#: spyderlib/plugins/runconfig.py:455
+#: spyderlib/widgets/externalshell/baseshell.py:107
+#: spyderlib/widgets/ipython.py:521
 msgid "Console"
 msgstr "Console"
 
-#: spyderlib/plugins/externalconsole.py:69
+#: spyderlib/plugins/externalconsole.py:71
 msgid "One tab per script"
 msgstr "Un onglet par script"
 
-#: spyderlib/plugins/externalconsole.py:70
-#: spyderlib/widgets/externalshell/baseshell.py:171
+#: spyderlib/plugins/externalconsole.py:72
+#: spyderlib/widgets/externalshell/baseshell.py:173
 msgid "Show elapsed time"
 msgstr "Afficher le temps écoulé"
 
-#: spyderlib/plugins/externalconsole.py:71 spyderlib/widgets/explorer.py:988
+#: spyderlib/plugins/externalconsole.py:73 spyderlib/widgets/explorer.py:1016
 msgid "Show icons and text"
 msgstr "Afficher icônes et textes"
 
-#: spyderlib/plugins/externalconsole.py:83
+#: spyderlib/plugins/externalconsole.py:85
 msgid "Buffer: "
 msgstr "Tampon : "
 
-#: spyderlib/plugins/externalconsole.py:83
-#: spyderlib/plugins/ipythonconsole.py:201
+#: spyderlib/plugins/externalconsole.py:85
+#: spyderlib/plugins/ipythonconsole.py:208
 msgid " lines"
 msgstr " lignes"
 
-#: spyderlib/plugins/externalconsole.py:88
+#: spyderlib/plugins/externalconsole.py:90
 msgid "Merge process standard output/error channels"
 msgstr "Fusionner les canaux de sortie et d'erreur du processus"
 
-#: spyderlib/plugins/externalconsole.py:90
+#: spyderlib/plugins/externalconsole.py:92
 msgid ""
 "Merging the output channels of the process means that\n"
 "the standard error won't be written in red anymore,\n"
@@ -1228,11 +1280,11 @@ msgstr ""
 "mais cela entraînera également une amélioration des performances\n"
 "d'affichage et une meilleure réactivité de la console."
 
-#: spyderlib/plugins/externalconsole.py:94
+#: spyderlib/plugins/externalconsole.py:96
 msgid "Colorize standard error channel using ANSI escape codes"
 msgstr "Coloriser le canal d'erreur standard (codes d'échappement ANSI)"
 
-#: spyderlib/plugins/externalconsole.py:96
+#: spyderlib/plugins/externalconsole.py:98
 msgid ""
 "This method is the only way to have colorized standard\n"
 "error channel when the output channels have been merged."
@@ -1241,9 +1293,9 @@ msgstr ""
 "d'erreur standard lorsque les canaux de sorties ont été fusionnés."
 
 #: spyderlib/plugins/externalconsole.py:114
-#: spyderlib/plugins/ipythonconsole.py:188
-#: spyderlib/widgets/arrayeditor.py:460
-#: spyderlib/widgets/dataframeeditor.py:515
+#: spyderlib/plugins/ipythonconsole.py:195
+#: spyderlib/widgets/arrayeditor.py:461
+#: spyderlib/widgets/dataframeeditor.py:516
 msgid "Background color"
 msgstr "Couleur de fond"
 
@@ -1315,34 +1367,34 @@ msgstr ""
 msgid "Set UMR excluded (not reloaded) modules"
 msgstr "Définir la liste des modules non rechargés par l'UMR"
 
-#: spyderlib/plugins/externalconsole.py:181
+#: spyderlib/plugins/externalconsole.py:180
 msgid "Python executable"
 msgstr "Exécutable Python"
 
-#: spyderlib/plugins/externalconsole.py:183
+#: spyderlib/plugins/externalconsole.py:182
 msgid ""
 "Select the Python interpreter executable binary in which Spyder will run "
 "scripts:"
 msgstr "Sélectionner l'interpréteur Python utilisé pour exécuter des scripts:"
 
-#: spyderlib/plugins/externalconsole.py:186
+#: spyderlib/plugins/externalconsole.py:185
 msgid "Default (i.e. the same as Spyder's)"
 msgstr ""
 "Par défaut (interpréteur identique à celui dans lequel Spyder est exécuté)"
 
-#: spyderlib/plugins/externalconsole.py:190
+#: spyderlib/plugins/externalconsole.py:189
 msgid "Use the following Python interpreter:"
 msgstr "Utiliser l'interpréteur Python suivant :"
 
-#: spyderlib/plugins/externalconsole.py:194
+#: spyderlib/plugins/externalconsole.py:193
 msgid "Executables"
 msgstr "Exécutables"
 
-#: spyderlib/plugins/externalconsole.py:214
+#: spyderlib/plugins/externalconsole.py:211
 msgid "PYTHONSTARTUP replacement"
 msgstr "Substitution de PYTHONSTARTUP"
 
-#: spyderlib/plugins/externalconsole.py:216
+#: spyderlib/plugins/externalconsole.py:213
 msgid ""
 "This option will override the PYTHONSTARTUP environment variable which\n"
 "defines the script to be executed during the Python console startup."
@@ -1351,19 +1403,19 @@ msgstr ""
 "défini par la\n"
 "variable d'environnement PYTHONSTARTUP."
 
-#: spyderlib/plugins/externalconsole.py:221
+#: spyderlib/plugins/externalconsole.py:218
 msgid "Default PYTHONSTARTUP script"
 msgstr "Script PYTHONSTARTUP par défaut"
 
-#: spyderlib/plugins/externalconsole.py:225
+#: spyderlib/plugins/externalconsole.py:222
 msgid "Use the following startup script:"
 msgstr "Utiliser le script de démarrage suivant :"
 
-#: spyderlib/plugins/externalconsole.py:244
+#: spyderlib/plugins/externalconsole.py:239
 msgid "Monitor"
 msgstr "Moniteur"
 
-#: spyderlib/plugins/externalconsole.py:245
+#: spyderlib/plugins/externalconsole.py:240
 msgid ""
 "The monitor provides introspection features to console: code completion, "
 "calltips and variable explorer. Because it relies on several modules, "
@@ -1374,94 +1426,59 @@ msgstr ""
 "Parce qu'il nécessite l'import de nombreux modules, désactiver le moniteur "
 "permet d'accélérer le démarrage de la console."
 
-#: spyderlib/plugins/externalconsole.py:252
+#: spyderlib/plugins/externalconsole.py:247
 msgid "Enable monitor"
 msgstr "Activer le moniteur"
 
-#: spyderlib/plugins/externalconsole.py:264
+#: spyderlib/plugins/externalconsole.py:260
 msgid "Default library"
 msgstr "Bibliothèque par défaut"
 
-#: spyderlib/plugins/externalconsole.py:266
-msgid "Qt (PyQt/PySide)"
-msgstr "Qt (PyQt/PySide)"
-
-#: spyderlib/plugins/externalconsole.py:268
-msgid "Qt-Python bindings library selection:"
+#: spyderlib/plugins/externalconsole.py:265
+#, fuzzy
+msgid "Qt-Python Bindings"
 msgstr "Sélection de la bibliothèque d'interfaçage Qt :"
 
-#: spyderlib/plugins/externalconsole.py:270
+#: spyderlib/plugins/externalconsole.py:267
+msgid "Library:"
+msgstr ""
+
+#: spyderlib/plugins/externalconsole.py:269
 msgid ""
 "This option will act on<br> libraries such as Matplotlib, guidata or ETS"
 msgstr ""
 "Cette option est prise en charge par les bibliothèques telles que "
 "Matplotlib, guidata ou ETS"
 
-#: spyderlib/plugins/externalconsole.py:291
-msgid "PyQt"
-msgstr "PyQt"
-
-#: spyderlib/plugins/externalconsole.py:293
-msgid "API selection for QString and QVariant objects:"
-msgstr "Sélection de l'API des objets QString et QVariant :"
-
-#: spyderlib/plugins/externalconsole.py:294
-msgid "API #1"
-msgstr "API n°1"
-
-#: spyderlib/plugins/externalconsole.py:294
-msgid "API #2"
-msgstr "API n°2"
-
-#: spyderlib/plugins/externalconsole.py:294
-msgid "Default API"
-msgstr "API par défaut"
+#: spyderlib/plugins/externalconsole.py:278
+#: spyderlib/plugins/ipythonconsole.py:465
+msgid "Graphics"
+msgstr "Graphiques"
 
-#: spyderlib/plugins/externalconsole.py:296
+#: spyderlib/plugins/externalconsole.py:279
 msgid ""
-"PyQt API #1 is the default <br>API for Python 2. PyQt API #2 is the default "
-"API for Python 3 and is compatible with PySide."
+"Decide which backend to use to display graphics. If unsure, please select "
+"the <b>Automatic</b> backend.<br><br><b>Note:</b> We support a very limited "
+"number of backends in our Python consoles. If you prefer to work with a "
+"different one, please use an IPython console."
 msgstr ""
-"L'API n°1 de PyQt est l'API par défaut pour Python 2. L'API n°2 est l'API "
-"par défaut pour Python 3 : c'est l'API qui est compatible avec PySide."
 
-#: spyderlib/plugins/externalconsole.py:300
-msgid "Ignore API change errors (sip.setapi)"
-msgstr "Ignorer les erreurs de changement d'API (sip.setapi)"
+#: spyderlib/plugins/externalconsole.py:295
+#: spyderlib/plugins/ipythonconsole.py:270
+msgid "Backend:"
+msgstr "Sortie :"
 
-#: spyderlib/plugins/externalconsole.py:302
-msgid ""
-"Enabling this option will ignore <br>errors when changing PyQt API. As PyQt "
-"does not support dynamic API changes, it is strongly recommended to use this "
-"feature wisely, e.g. for debugging purpose."
-msgstr ""
-"L'activation de cette option permet d'ignorer les erreurs liées aux "
-"changements\n"
-"d'API de PyQt. Vu que PyQt ne prend pas en charge le changement dynamique\n"
-" d'API, il est fortement recommandé d'utiliser cette fonctionnalité "
-"exceptionnellement,\n"
-"par exemple pour du débogage."
-
-#: spyderlib/plugins/externalconsole.py:321
-msgid "Matplotlib"
-msgstr "Matplotlib"
-
-#: spyderlib/plugins/externalconsole.py:323
-msgid "GUI backend:"
-msgstr "Backend graphique :"
-
-#: spyderlib/plugins/externalconsole.py:325
-msgid ""
-"Set the GUI toolkit used by <br>Matplotlib to show figures (default: Qt4Agg)"
+#: spyderlib/plugins/externalconsole.py:297
+#: spyderlib/plugins/ipythonconsole.py:272
+msgid "This option will be applied the next time a console is opened."
 msgstr ""
-"Spécifie la bibliothèque d'interfaces graphiques à utiliser pour l'affichage "
-"des figures Matplotlib (par défaut : Qt4Agg)"
+"Cette option sera prise en compte lors de la prochaine ouverture de console."
 
-#: spyderlib/plugins/externalconsole.py:344
+#: spyderlib/plugins/externalconsole.py:308
 msgid "Enthought Tool Suite"
 msgstr "Enthought Tool Suite"
 
-#: spyderlib/plugins/externalconsole.py:345
+#: spyderlib/plugins/externalconsole.py:309
 msgid ""
 "Enthought Tool Suite (ETS) supports PyQt4 (qt4) and wxPython (wx) graphical "
 "user interfaces."
@@ -1469,24 +1486,25 @@ msgstr ""
 "Le logiciel Enthought Tool Suite (ETS) prend en charge les interfaces "
 "graphiques PyQt4 (qt4) et wxPython (wx)."
 
-#: spyderlib/plugins/externalconsole.py:349
+#: spyderlib/plugins/externalconsole.py:313
 msgid "ETS_TOOLKIT:"
 msgstr "ETS_TOOLKIT:"
 
-#: spyderlib/plugins/externalconsole.py:369
+#: spyderlib/plugins/externalconsole.py:338
 msgid "External modules"
 msgstr "Modules externes"
 
-#: spyderlib/plugins/externalconsole.py:426
-#: spyderlib/plugins/externalconsole.py:666
-#: spyderlib/plugins/ipythonconsole.py:113
-#: spyderlib/plugins/ipythonconsole.py:808 spyderlib/spyder.py:1331
-#: spyderlib/spyder.py:1349 spyderlib/utils/environ.py:94
-#: spyderlib/utils/environ.py:107 spyderlib/widgets/dicteditor.py:449
+#: spyderlib/plugins/externalconsole.py:374
+#: spyderlib/plugins/externalconsole.py:617
+#: spyderlib/plugins/ipythonconsole.py:114
+#: spyderlib/plugins/ipythonconsole.py:832 spyderlib/spyder.py:1803
+#: spyderlib/spyder.py:1825 spyderlib/spyder.py:1888 spyderlib/spyder.py:2774
+#: spyderlib/utils/environ.py:95 spyderlib/utils/environ.py:108
+#: spyderlib/widgets/dicteditor.py:452
 msgid "Warning"
 msgstr "Attention"
 
-#: spyderlib/plugins/externalconsole.py:427
+#: spyderlib/plugins/externalconsole.py:375
 msgid ""
 "You selected a <b>Python %d</b> interpreter for the console but Spyder is "
 "running on <b>Python %d</b>!.<br><br>Although this is possible, we recommend "
@@ -1501,11 +1519,11 @@ msgstr ""
 "d'éviter l'apparition d'avertissements ou d'erreurs liées à une syntaxe "
 "incompatible entre ces deux versions de Python"
 
-#: spyderlib/plugins/externalconsole.py:590
+#: spyderlib/plugins/externalconsole.py:538
 msgid "Trying to kill a kernel?"
 msgstr "Tentative d'arrêt d'un noyau"
 
-#: spyderlib/plugins/externalconsole.py:591
+#: spyderlib/plugins/externalconsole.py:539
 msgid ""
 "You can't close this kernel because it has one or more consoles connected to "
 "it.<br><br>You need to close them instead or you can kill the kernel using "
@@ -1515,7 +1533,7 @@ msgstr ""
 "<br><br> Veuillez soit fermer toutes les consoles connectées ou appuyer sur "
 "le second bouton en partant de la droite pour tuer le processus du noyau."
 
-#: spyderlib/plugins/externalconsole.py:667
+#: spyderlib/plugins/externalconsole.py:618
 msgid ""
 "No Python console is currently selected to run <b>%s</b>.<br><br>Please "
 "select or open a new Python console and try again."
@@ -1524,7 +1542,7 @@ msgstr ""
 "b>.<br><br>Merci de sélectionner ou d'ouvrir une nouvelle console Python et "
 "de réessayer."
 
-#: spyderlib/plugins/externalconsole.py:748
+#: spyderlib/plugins/externalconsole.py:698
 msgid ""
 "%s is already running in a separate process.\n"
 "Do you want to kill the process before starting a new one?"
@@ -1532,11 +1550,11 @@ msgstr ""
 "%s est déjà en cours d'exécution dans un processus séparé.\n"
 "Souhaitez-vous tuer ce processus avant d'en démarrer un autre ?"
 
-#: spyderlib/plugins/externalconsole.py:917
+#: spyderlib/plugins/externalconsole.py:858
 msgid "Kernel"
 msgstr "Noyau"
 
-#: spyderlib/plugins/externalconsole.py:929
+#: spyderlib/plugins/externalconsole.py:868
 msgid ""
 "Either:<ol><li>Your IPython frontend and kernel versions are "
 "<b>incompatible</b> or</li><li>You <b>don't have</b> IPython installed in "
@@ -1548,43 +1566,43 @@ msgstr ""
 "votre interpréteur externe.</li></ol>Dans tous les cas nous sommes désolés "
 "mais nous ne pouvons ouvrir une console pour vous."
 
-#: spyderlib/plugins/externalconsole.py:953
+#: spyderlib/plugins/externalconsole.py:892
 msgid "Command Window"
 msgstr "Invite de commandes"
 
-#: spyderlib/plugins/externalconsole.py:955
+#: spyderlib/plugins/externalconsole.py:894
 msgid "Terminal"
 msgstr "Terminal"
 
-#: spyderlib/plugins/externalconsole.py:1008
+#: spyderlib/plugins/externalconsole.py:947
 msgid "Kernel %s"
 msgstr "Noyau %s"
 
-#: spyderlib/plugins/externalconsole.py:1088
+#: spyderlib/plugins/externalconsole.py:1027
 msgid "Open a &Python console"
 msgstr "Ouvrir une console &Python"
 
-#: spyderlib/plugins/externalconsole.py:1091
+#: spyderlib/plugins/externalconsole.py:1031
 msgid "Open &command prompt"
 msgstr "Ouvrir un invite de &commandes"
 
-#: spyderlib/plugins/externalconsole.py:1092
+#: spyderlib/plugins/externalconsole.py:1032
 msgid "Open a Windows command prompt"
 msgstr "Ouvrir un invite de commandes Windows"
 
-#: spyderlib/plugins/externalconsole.py:1094
+#: spyderlib/plugins/externalconsole.py:1034
 msgid "Open a &terminal"
 msgstr "Ouvrir un &terminal"
 
-#: spyderlib/plugins/externalconsole.py:1095
+#: spyderlib/plugins/externalconsole.py:1035
 msgid "Open a terminal window"
 msgstr "Ouvrir un terminal de commandes dans Spyder"
 
-#: spyderlib/plugins/externalconsole.py:1263
+#: spyderlib/plugins/externalconsole.py:1196
 msgid "Open an IPython console"
 msgstr "Ouvrir une console IPython"
 
-#: spyderlib/plugins/externalconsole.py:1264
+#: spyderlib/plugins/externalconsole.py:1197
 msgid ""
 "The console monitor was disabled: the IPython kernel will be started as "
 "expected, but an IPython console will have to be connected manually to the "
@@ -1593,13 +1611,13 @@ msgstr ""
 "Le moniteur (console) a été désactivé. Par conséquent, le noyau IPython sera "
 "démarré mais la console IPython devra y être connectée manuellement."
 
-#: spyderlib/plugins/externalconsole.py:1294
-#: spyderlib/plugins/externalconsole.py:1307
-#: spyderlib/plugins/externalconsole.py:1311
+#: spyderlib/plugins/externalconsole.py:1229
+#: spyderlib/plugins/externalconsole.py:1242
+#: spyderlib/plugins/externalconsole.py:1246
 msgid "UMR"
 msgstr "UMR"
 
-#: spyderlib/plugins/externalconsole.py:1295
+#: spyderlib/plugins/externalconsole.py:1230
 msgid ""
 "UMR excluded modules:\n"
 "(example: guidata, guiqwt)"
@@ -1607,7 +1625,7 @@ msgstr ""
 "Modules non rechargés par l'UMR :\n"
 "(exemple: guidata, guiqwt)"
 
-#: spyderlib/plugins/externalconsole.py:1308
+#: spyderlib/plugins/externalconsole.py:1243
 msgid ""
 "The following modules are not installed on your machine:\n"
 "%s"
@@ -1615,7 +1633,7 @@ msgstr ""
 "Les modules suivants ne sont pas installés sur votre ordinateur :\n"
 "%s"
 
-#: spyderlib/plugins/externalconsole.py:1312
+#: spyderlib/plugins/externalconsole.py:1247
 msgid ""
 "Please note that these changes will be applied only to new Python/IPython "
 "consoles"
@@ -1623,79 +1641,79 @@ msgstr ""
 "Veuillez noter que ces changements ne seront pris en compte que dans les "
 "nouvelles consoles Python/IPython"
 
-#: spyderlib/plugins/findinfiles.py:90 spyderlib/widgets/findinfiles.py:691
+#: spyderlib/plugins/findinfiles.py:96 spyderlib/widgets/findinfiles.py:690
 msgid "Find in files"
 msgstr "Recherche dans des fichiers"
 
-#: spyderlib/plugins/findinfiles.py:114
+#: spyderlib/plugins/findinfiles.py:117
 msgid "&Find in files"
 msgstr "Rechercher dans des &fichiers"
 
-#: spyderlib/plugins/findinfiles.py:117
+#: spyderlib/plugins/findinfiles.py:120
 msgid "Search text in multiple files"
 msgstr "Rechercher une chaîne de caractères dans plusieurs fichiers à la fois"
 
-#: spyderlib/plugins/history.py:36
+#: spyderlib/plugins/history.py:37
 msgid "Settings"
 msgstr "Options"
 
-#: spyderlib/plugins/history.py:38
+#: spyderlib/plugins/history.py:39
 msgid " entries"
 msgstr " lignes"
 
-#: spyderlib/plugins/history.py:38
+#: spyderlib/plugins/history.py:39
 msgid "History depth: "
 msgstr "Taille de l'historique : "
 
-#: spyderlib/plugins/history.py:45
+#: spyderlib/plugins/history.py:46
 msgid "Scroll automatically to last entry"
 msgstr "Défiler automatiquement jusqu'à la dernière ligne"
 
-#: spyderlib/plugins/history.py:113 spyderlib/plugins/inspector.py:458
-#: spyderlib/widgets/editor.py:540 spyderlib/widgets/explorer.py:1018
-#: spyderlib/widgets/externalshell/baseshell.py:151
-#: spyderlib/widgets/externalshell/namespacebrowser.py:226
-#: spyderlib/widgets/ipython.py:556
+#: spyderlib/plugins/history.py:118 spyderlib/plugins/inspector.py:472
+#: spyderlib/widgets/editor.py:459 spyderlib/widgets/explorer.py:1027
+#: spyderlib/widgets/externalshell/baseshell.py:153
+#: spyderlib/widgets/externalshell/namespacebrowser.py:139
+#: spyderlib/widgets/ipython.py:568
 msgid "Options"
 msgstr "Options"
 
-#: spyderlib/plugins/history.py:133
+#: spyderlib/plugins/history.py:138
 msgid "History log"
 msgstr "Historique"
 
-#: spyderlib/plugins/history.py:160
+#: spyderlib/plugins/history.py:165
 msgid "History..."
 msgstr "Historique..."
 
-#: spyderlib/plugins/history.py:162
+#: spyderlib/plugins/history.py:167
 msgid "Set history maximum entries"
 msgstr "Modifier le nombre d'entrées maximum de l'historique"
 
-#: spyderlib/plugins/history.py:272
+#: spyderlib/plugins/history.py:274
 msgid "History"
 msgstr "Historique"
 
-#: spyderlib/plugins/history.py:273
+#: spyderlib/plugins/history.py:275
 msgid "Maximum entries"
 msgstr "Nombre maximum d'entrées"
 
-#: spyderlib/plugins/inspector.py:56
+#: spyderlib/plugins/inspector.py:58
 msgid "Rich text help on the Object Inspector"
 msgstr "Texte enrichi dans l'inspecteur d'objets"
 
-#: spyderlib/plugins/inspector.py:120
+#: spyderlib/plugins/inspector.py:125
 msgid "Plain text font style"
 msgstr "Police d'écriture du texte brut"
 
-#: spyderlib/plugins/inspector.py:123
+#: spyderlib/plugins/inspector.py:128
 msgid "Rich text font style"
 msgstr "Police d'écriture du texte enrichi"
 
-#: spyderlib/plugins/inspector.py:126
+#: spyderlib/plugins/inspector.py:131
 msgid "Automatic connections"
 msgstr "Connexions automatiques"
 
-#: spyderlib/plugins/inspector.py:127
+#: spyderlib/plugins/inspector.py:132
 msgid ""
 "The Object Inspector can automatically show an object's help information "
 "after a left parenthesis is written next to it. Below you can decide to "
@@ -1704,7 +1722,7 @@ msgstr ""
 "L'inspecteur d'objet peut automatiquement afficher l'aide sur un objet dès "
 "l'ouverture d'une parenthèse."
 
-#: spyderlib/plugins/inspector.py:139
+#: spyderlib/plugins/inspector.py:144
 msgid ""
 "This feature requires the Rope or Jedi libraries.\n"
 "It seems you don't have either installed."
@@ -1712,63 +1730,63 @@ msgstr ""
 "Cette fonctionnalité nécessite Rope ou Jedi.\n"
 "Il semble qu'aucun de ces modules ne soit présent."
 
-#: spyderlib/plugins/inspector.py:142
+#: spyderlib/plugins/inspector.py:147
 msgid "Python Console"
 msgstr "Console Python"
 
-#: spyderlib/plugins/inspector.py:144
+#: spyderlib/plugins/inspector.py:149
 msgid "IPython Console"
 msgstr "Console IPython"
 
-#: spyderlib/plugins/inspector.py:156
+#: spyderlib/plugins/inspector.py:161
 msgid "Additional features"
 msgstr "Options supplémentaires"
 
-#: spyderlib/plugins/inspector.py:157
+#: spyderlib/plugins/inspector.py:162
 msgid "Render mathematical equations"
 msgstr "Styliser les équations mathématiques"
 
-#: spyderlib/plugins/inspector.py:163
+#: spyderlib/plugins/inspector.py:168
 msgid "This feature requires Sphinx 1.1 or superior."
 msgstr "Cette fonctionnalité nécessite l'installation de Sphinx 1.1+."
 
-#: spyderlib/plugins/inspector.py:165
+#: spyderlib/plugins/inspector.py:170
 msgid "Sphinx %s is currently installed."
 msgstr "Sphinx %s n'est pas installé."
 
-#: spyderlib/plugins/inspector.py:357
+#: spyderlib/plugins/inspector.py:373
 msgid "No further documentation available"
 msgstr "Aucune documentation disponible"
 
-#: spyderlib/plugins/inspector.py:396
+#: spyderlib/plugins/inspector.py:412
 msgid "Source"
 msgstr "Source"
 
-#: spyderlib/plugins/inspector.py:412 spyderlib/widgets/dicteditor.py:173
+#: spyderlib/plugins/inspector.py:427 spyderlib/widgets/dicteditor.py:173
 msgid "Object"
 msgstr "Objet"
 
-#: spyderlib/plugins/inspector.py:428
+#: spyderlib/plugins/inspector.py:442
 msgid "Plain Text"
 msgstr "Texte brut"
 
-#: spyderlib/plugins/inspector.py:432
+#: spyderlib/plugins/inspector.py:446
 msgid "Show Source"
 msgstr "Afficher les sources"
 
-#: spyderlib/plugins/inspector.py:436
+#: spyderlib/plugins/inspector.py:450
 msgid "Rich Text"
 msgstr "Texte enrichi"
 
-#: spyderlib/plugins/inspector.py:446
+#: spyderlib/plugins/inspector.py:460
 msgid "Automatic import"
 msgstr "Import automatique"
 
-#: spyderlib/plugins/inspector.py:506 spyderlib/plugins/inspector.py:954
+#: spyderlib/plugins/inspector.py:520 spyderlib/plugins/inspector.py:983
 msgid "Object inspector"
 msgstr "Inspecteur d'objets"
 
-#: spyderlib/plugins/inspector.py:725
+#: spyderlib/plugins/inspector.py:740
 msgid ""
 "Here you can get help of any object by pressing %s in front of it, either on "
 "the Editor or the Console.%sHelp can also be shown automatically after "
@@ -1780,37 +1798,37 @@ msgstr ""
 "automatiquement après la saisie d'une parenthèse gauche après un objet si "
 "l'option correspondante est activée dans %s."
 
-#: spyderlib/plugins/inspector.py:731
+#: spyderlib/plugins/inspector.py:746
 msgid "Preferences > Object Inspector"
 msgstr "Préférences > Inspecteur d'objets"
 
-#: spyderlib/plugins/inspector.py:733
+#: spyderlib/plugins/inspector.py:753
 msgid "Usage"
 msgstr "Utilisation"
 
-#: spyderlib/plugins/inspector.py:734
+#: spyderlib/plugins/inspector.py:754
 msgid "New to Spyder? Read our"
 msgstr "Vous découvrez Spyder ? Lisez notre"
 
-#: spyderlib/plugins/inspector.py:735
+#: spyderlib/plugins/inspector.py:755
 msgid "tutorial"
 msgstr "Tutoriel"
 
-#: spyderlib/plugins/inspector.py:742
+#: spyderlib/plugins/inspector.py:762
 msgid ""
 "Please consider installing Sphinx to get documentation rendered in rich text."
 msgstr ""
 "Merci d'installer Sphinx pour obtenir la documentation en texte enrichi."
 
-#: spyderlib/plugins/inspector.py:913
+#: spyderlib/plugins/inspector.py:939
 msgid "Lock"
 msgstr "Verrouiller"
 
-#: spyderlib/plugins/inspector.py:913
+#: spyderlib/plugins/inspector.py:939
 msgid "Unlock"
 msgstr "Déverrouiller"
 
-#: spyderlib/plugins/inspector.py:955
+#: spyderlib/plugins/inspector.py:984
 msgid ""
 "The following error occured when calling <b>Sphinx %s</b>. <br>Incompatible "
 "Sphinx version or doc string decoding failed.<br><br>Error message:<br>%s"
@@ -1819,15 +1837,15 @@ msgstr ""
 "<br>Veuillez vérifier si cette version de Sphinx est bien prise en charge "
 "par Spyder. <br><br>Message d'erreur :<br>%s"
 
-#: spyderlib/plugins/inspector.py:999
+#: spyderlib/plugins/inspector.py:1028
 msgid "No source code available."
 msgstr "Aucun code source disponible."
 
-#: spyderlib/plugins/ipythonconsole.py:61
+#: spyderlib/plugins/ipythonconsole.py:62
 msgid "Symbolic mathematics in the IPython Console"
 msgstr "Mathématiques symboliques pour la console IPython"
 
-#: spyderlib/plugins/ipythonconsole.py:110
+#: spyderlib/plugins/ipythonconsole.py:111
 msgid ""
 "The authenticity of host <b>%s</b> can't be established. Are you sure you "
 "want to continue connecting?"
@@ -1835,28 +1853,28 @@ msgstr ""
 "L'identité du serveur <b>%s</b> ne peut pas être confirmée. Êtes-vous sûr de "
 "vouloir poursuivre ?"
 
-#: spyderlib/plugins/ipythonconsole.py:122
+#: spyderlib/plugins/ipythonconsole.py:123
 msgid "The authenticity of the host can't be established"
 msgstr "L'identité du serveur ne peut pas être confirmée"
 
-#: spyderlib/plugins/ipythonconsole.py:129
+#: spyderlib/plugins/ipythonconsole.py:130
 msgid "Tunnel '%s' failed to start"
 msgstr "Impossible d'ouvrir le tunnel '%s'"
 
-#: spyderlib/plugins/ipythonconsole.py:134
+#: spyderlib/plugins/ipythonconsole.py:135
 msgid "Could not connect to remote host"
 msgstr "Impossible d'établir la connection au serveur distant"
 
-#: spyderlib/plugins/ipythonconsole.py:150
-#: spyderlib/plugins/ipythonconsole.py:665
+#: spyderlib/plugins/ipythonconsole.py:151
+#: spyderlib/plugins/ipythonconsole.py:689
 msgid "IPython console"
 msgstr "Console IPython"
 
-#: spyderlib/plugins/ipythonconsole.py:162
+#: spyderlib/plugins/ipythonconsole.py:163
 msgid "Display initial banner"
 msgstr "Afficher le message d'accueil"
 
-#: spyderlib/plugins/ipythonconsole.py:163
+#: spyderlib/plugins/ipythonconsole.py:164
 msgid ""
 "This option lets you hide the message shown at\n"
 "the top of the console when it's opened."
@@ -1864,19 +1882,11 @@ msgstr ""
 "Cette option permet de masquer la message d'accueil\n"
 "qui s'affiche à l'ouverture de la console."
 
-#: spyderlib/plugins/ipythonconsole.py:165
-msgid "Use a completion widget"
-msgstr "Utiliser un widget de complétion de code"
-
-#: spyderlib/plugins/ipythonconsole.py:167
-msgid "Use a widget instead of plain text output for tab completion"
-msgstr "Utiliser un widget de complétion au lieu d'une liste en texte brut"
-
-#: spyderlib/plugins/ipythonconsole.py:169
+#: spyderlib/plugins/ipythonconsole.py:166
 msgid "Use a pager to display additional text inside the console"
 msgstr "Utiliser un pager pour afficher l'aide"
 
-#: spyderlib/plugins/ipythonconsole.py:171
+#: spyderlib/plugins/ipythonconsole.py:168
 msgid ""
 "Useful if you don't want to fill the console with long help or completion "
 "texts.\n"
@@ -1885,23 +1895,36 @@ msgstr ""
 "Le pager permet d'éviter de remplir la console de texte d'aide.\n"
 "Note : utiliser la touche Q pour quitter le pager."
 
-#: spyderlib/plugins/ipythonconsole.py:176
+#: spyderlib/plugins/ipythonconsole.py:173
 msgid "Ask for confirmation before closing"
 msgstr "Demander confirmation avant de fermer une console"
 
-#: spyderlib/plugins/ipythonconsole.py:189
+#: spyderlib/plugins/ipythonconsole.py:183
+msgid "Completion Type"
+msgstr ""
+
+#: spyderlib/plugins/ipythonconsole.py:184
+msgid "Decide what type of completion to use"
+msgstr ""
+
+#: spyderlib/plugins/ipythonconsole.py:187
+#, fuzzy
+msgid "Completion:"
+msgstr "Condition :"
+
+#: spyderlib/plugins/ipythonconsole.py:196
 msgid "Light background"
 msgstr "Fond blanc"
 
-#: spyderlib/plugins/ipythonconsole.py:191
+#: spyderlib/plugins/ipythonconsole.py:198
 msgid "Dark background"
 msgstr "Fond noir"
 
-#: spyderlib/plugins/ipythonconsole.py:201
+#: spyderlib/plugins/ipythonconsole.py:208
 msgid "Buffer:  "
 msgstr "Tampon :  "
 
-#: spyderlib/plugins/ipythonconsole.py:203
+#: spyderlib/plugins/ipythonconsole.py:210
 msgid ""
 "Set the maximum number of lines of text shown in the\n"
 "console before truncation. Specifying -1 disables it\n"
@@ -1910,19 +1933,19 @@ msgstr ""
 "Nombre maximum de lignes de texte affichées dans la console avant troncature "
 "(saisir -1 désactive cette dernière, ce qui est fortement déconseillé)."
 
-#: spyderlib/plugins/ipythonconsole.py:212
+#: spyderlib/plugins/ipythonconsole.py:219
 msgid "Support for graphics (Matplotlib)"
 msgstr "Prise en charge des graphes (Matplotlib)"
 
-#: spyderlib/plugins/ipythonconsole.py:213
+#: spyderlib/plugins/ipythonconsole.py:220
 msgid "Activate support"
 msgstr "Activer"
 
-#: spyderlib/plugins/ipythonconsole.py:214
+#: spyderlib/plugins/ipythonconsole.py:221
 msgid "Automatically load Pylab and NumPy modules"
 msgstr "Importer automatiquement Pylab et NumPy"
 
-#: spyderlib/plugins/ipythonconsole.py:217
+#: spyderlib/plugins/ipythonconsole.py:224
 msgid ""
 "This lets you load graphics support without importing \n"
 "the commands to do plots. Useful to work with other\n"
@@ -1932,7 +1955,7 @@ msgstr ""
 "Import automatique de toutes les fonctions de représentation graphique et de "
 "calcul numérique"
 
-#: spyderlib/plugins/ipythonconsole.py:236
+#: spyderlib/plugins/ipythonconsole.py:242
 msgid ""
 "This feature requires the Matplotlib library.\n"
 "It seems you don't have it installed."
@@ -1940,19 +1963,19 @@ msgstr ""
 "Cette fonctionnalité nécessite l'installation du module Matplotlib.\n"
 "Ce dernier n'est apparemment pas installé."
 
-#: spyderlib/plugins/ipythonconsole.py:241
+#: spyderlib/plugins/ipythonconsole.py:247
 msgid "Inline"
 msgstr "En ligne"
 
-#: spyderlib/plugins/ipythonconsole.py:242
+#: spyderlib/plugins/ipythonconsole.py:248
 msgid "Automatic"
 msgstr "Automatique"
 
-#: spyderlib/plugins/ipythonconsole.py:243
+#: spyderlib/plugins/ipythonconsole.py:249
 msgid "Graphics backend"
 msgstr "Sortie graphique"
 
-#: spyderlib/plugins/ipythonconsole.py:244
+#: spyderlib/plugins/ipythonconsole.py:250
 msgid ""
 "Decide how graphics are going to be displayed in the console. If unsure, "
 "please select <b>%s</b> to put graphics inside the console or <b>%s</b> to "
@@ -1963,65 +1986,56 @@ msgstr ""
 "des graphes tandis que le mode <b>%s</b> permet d'interagir avec (zoom/pan) "
 "dans une fenêtre séparée."
 
-#: spyderlib/plugins/ipythonconsole.py:264
-msgid "Backend:"
-msgstr "Sortie :"
-
-#: spyderlib/plugins/ipythonconsole.py:266
-msgid "This option will be applied the next time a console is opened."
-msgstr ""
-"Cette option sera prise en compte lors de la prochaine ouverture de console."
-
-#: spyderlib/plugins/ipythonconsole.py:278
+#: spyderlib/plugins/ipythonconsole.py:283
 msgid "Inline backend"
 msgstr "Backend intégré"
 
-#: spyderlib/plugins/ipythonconsole.py:279
+#: spyderlib/plugins/ipythonconsole.py:284
 msgid "Decide how to render the figures created by this backend"
 msgstr "Option relative au rendu des figures dans ce backend"
 
-#: spyderlib/plugins/ipythonconsole.py:283
+#: spyderlib/plugins/ipythonconsole.py:288
 msgid "Format:"
 msgstr "Format :"
 
-#: spyderlib/plugins/ipythonconsole.py:286
+#: spyderlib/plugins/ipythonconsole.py:291
 msgid "Resolution:"
 msgstr "Résolution :"
 
-#: spyderlib/plugins/ipythonconsole.py:286
+#: spyderlib/plugins/ipythonconsole.py:291
 msgid "dpi"
 msgstr "ppp"
 
-#: spyderlib/plugins/ipythonconsole.py:288
+#: spyderlib/plugins/ipythonconsole.py:293
 msgid "Only used when the format is PNG. Default is 72"
 msgstr "Utilisé uniquement dans le cas du format PNG. Par défaut: 72"
 
-#: spyderlib/plugins/ipythonconsole.py:291
+#: spyderlib/plugins/ipythonconsole.py:296
 msgid "Width:"
 msgstr "Largeur :"
 
-#: spyderlib/plugins/ipythonconsole.py:291
-#: spyderlib/plugins/ipythonconsole.py:295
+#: spyderlib/plugins/ipythonconsole.py:296
+#: spyderlib/plugins/ipythonconsole.py:300
 msgid "inches"
 msgstr "pouces"
 
-#: spyderlib/plugins/ipythonconsole.py:293
+#: spyderlib/plugins/ipythonconsole.py:298
 msgid "Default is 6"
 msgstr "Par défaut : 6"
 
-#: spyderlib/plugins/ipythonconsole.py:295
+#: spyderlib/plugins/ipythonconsole.py:300
 msgid "Height:"
 msgstr "Hauteur :"
 
-#: spyderlib/plugins/ipythonconsole.py:297
+#: spyderlib/plugins/ipythonconsole.py:302
 msgid "Default is 4"
 msgstr "Par défaut : 4"
 
-#: spyderlib/plugins/ipythonconsole.py:312
+#: spyderlib/plugins/ipythonconsole.py:328 spyderlib/tour.py:552
 msgid "Run code"
 msgstr "Exécuter du code"
 
-#: spyderlib/plugins/ipythonconsole.py:313
+#: spyderlib/plugins/ipythonconsole.py:329
 msgid ""
 "You can run several lines of code when a console is started. Please "
 "introduce each one separated by commas, for example:<br><i>import os, import "
@@ -2031,29 +2045,29 @@ msgstr ""
 "console. Veuillez séparer deux lignes consécutives par une virgule - par "
 "exemple :<br><i>import os, import sys</i>"
 
-#: spyderlib/plugins/ipythonconsole.py:319
+#: spyderlib/plugins/ipythonconsole.py:335
 msgid "Lines:"
 msgstr "Lignes :"
 
-#: spyderlib/plugins/ipythonconsole.py:328
+#: spyderlib/plugins/ipythonconsole.py:344
 msgid "Run a file"
 msgstr "Exécuter un fichier"
 
-#: spyderlib/plugins/ipythonconsole.py:329
+#: spyderlib/plugins/ipythonconsole.py:345
 msgid ""
 "You can also run a whole file at startup instead of just some lines (This is "
 "similar to have a PYTHONSTARTUP file)."
 msgstr "Option similaire à PYTHONSTARTUP pour un interpréteur standard"
 
-#: spyderlib/plugins/ipythonconsole.py:333
+#: spyderlib/plugins/ipythonconsole.py:349
 msgid "Use the following file:"
 msgstr "Utiliser le fichier suivant :"
 
-#: spyderlib/plugins/ipythonconsole.py:348
+#: spyderlib/plugins/ipythonconsole.py:363
 msgid "Greedy completion"
 msgstr "Complétion avancée"
 
-#: spyderlib/plugins/ipythonconsole.py:349
+#: spyderlib/plugins/ipythonconsole.py:364
 msgid ""
 "Enable <tt>Tab</tt> completion on elements of lists, results of function "
 "calls, etc, <i>without</i> assigning them to a variable.<br>For example, you "
@@ -2065,15 +2079,15 @@ msgstr ""
 "<br>Par exemple vous pourrez avoir la complétion pour des expressions du "
 "type <tt>li[0].<Tab></tt> ou <tt>ins.meth().<Tab></tt>."
 
-#: spyderlib/plugins/ipythonconsole.py:357
+#: spyderlib/plugins/ipythonconsole.py:372
 msgid "Use the greedy completer"
 msgstr "Utiliser la complétion avancée"
 
-#: spyderlib/plugins/ipythonconsole.py:368
+#: spyderlib/plugins/ipythonconsole.py:383
 msgid "Autocall"
 msgstr "Appel automatique"
 
-#: spyderlib/plugins/ipythonconsole.py:369
+#: spyderlib/plugins/ipythonconsole.py:384
 msgid ""
 "Autocall makes IPython automatically call any callable object even if you "
 "didn't type explicit parentheses.<br>For example, if you type <i>str 43</i> "
@@ -2083,23 +2097,23 @@ msgstr ""
 "appelables même sans parenthèses explicites.<br>Par exemple <tt>str 43</tt> "
 "deviendra automatiquement <tt>str(43)</tt>."
 
-#: spyderlib/plugins/ipythonconsole.py:376
+#: spyderlib/plugins/ipythonconsole.py:391
 msgid "Smart"
 msgstr "Intelligent"
 
-#: spyderlib/plugins/ipythonconsole.py:377
+#: spyderlib/plugins/ipythonconsole.py:392
 msgid "Full"
 msgstr "Toujours"
 
-#: spyderlib/plugins/ipythonconsole.py:378
+#: spyderlib/plugins/ipythonconsole.py:393
 msgid "Off"
 msgstr "Désactivé"
 
-#: spyderlib/plugins/ipythonconsole.py:380
+#: spyderlib/plugins/ipythonconsole.py:395
 msgid "Autocall:  "
 msgstr "Appel automatique :"
 
-#: spyderlib/plugins/ipythonconsole.py:381
+#: spyderlib/plugins/ipythonconsole.py:396
 msgid ""
 "On <b>%s</b> mode, Autocall is not applied if there are no arguments after "
 "the callable. On <b>%s</b> mode, all callable objects are automatically "
@@ -2109,11 +2123,11 @@ msgstr ""
 "d'arguments. En mode <b>%s</b>, tous les objets appelables sont "
 "automatiquement appelés (même s'il n'y a pas d'arguments)"
 
-#: spyderlib/plugins/ipythonconsole.py:393
+#: spyderlib/plugins/ipythonconsole.py:408
 msgid "Symbolic Mathematics"
 msgstr "Calcul formel"
 
-#: spyderlib/plugins/ipythonconsole.py:394
+#: spyderlib/plugins/ipythonconsole.py:409
 msgid ""
 "Perfom symbolic operations in the console (e.g. integrals, derivatives, "
 "vector calculus, etc) and get the outputs in a beautifully printed style."
@@ -2122,11 +2136,11 @@ msgstr ""
 "exemple intégrales, dérivées, calcul vectoriel, etc...) et affiche les "
 "résultats de manière élégante."
 
-#: spyderlib/plugins/ipythonconsole.py:399
+#: spyderlib/plugins/ipythonconsole.py:414
 msgid "Use symbolic math"
 msgstr "Utiliser le calcul formel"
 
-#: spyderlib/plugins/ipythonconsole.py:400
+#: spyderlib/plugins/ipythonconsole.py:415
 msgid ""
 "This option loads the Sympy library to work with.<br>Please refer to its "
 "documentation to learn how to use it."
@@ -2134,7 +2148,7 @@ msgstr ""
 "Activer cette option permet de travailler avec la bibliothèque Sympy."
 "<br>Merci de consulter la documentation pour savoir comment l'utiliser."
 
-#: spyderlib/plugins/ipythonconsole.py:413
+#: spyderlib/plugins/ipythonconsole.py:428
 msgid ""
 "This feature requires the Sympy library.\n"
 "It seems you don't have it installed."
@@ -2142,55 +2156,51 @@ msgstr ""
 "Cette fonctionnalité nécessite l'installation du module Sympy.\n"
 "Ce dernier n'est apparemment pas installé."
 
-#: spyderlib/plugins/ipythonconsole.py:418
+#: spyderlib/plugins/ipythonconsole.py:433
 msgid "Prompts"
 msgstr "Invites de commande"
 
-#: spyderlib/plugins/ipythonconsole.py:419
+#: spyderlib/plugins/ipythonconsole.py:434
 msgid "Modify how Input and Output prompts are shown in the console."
 msgstr ""
 "Change l'affichage des invites de commande d'entrée et de sortie de la "
 "console."
 
-#: spyderlib/plugins/ipythonconsole.py:422
+#: spyderlib/plugins/ipythonconsole.py:437
 msgid "Input prompt:"
 msgstr "En entrée :"
 
-#: spyderlib/plugins/ipythonconsole.py:424
+#: spyderlib/plugins/ipythonconsole.py:439
 msgid ""
 "Default is<br>In [<span class=\"in-prompt-number\">%i</span>]:"
 msgstr ""
 "Par défaut :<br>In [<span class=\"in-prompt-number\">%i</span>]:"
 
-#: spyderlib/plugins/ipythonconsole.py:428
+#: spyderlib/plugins/ipythonconsole.py:443
 msgid "Output prompt:"
 msgstr "En sortie :"
 
-#: spyderlib/plugins/ipythonconsole.py:430
+#: spyderlib/plugins/ipythonconsole.py:445
 msgid ""
 "Default is<br>Out[<span class=\"out-prompt-number\">%i</span>]:"
 msgstr ""
 "Par défaut :<br>Out[<span class=\"out-prompt-number\">%i</span>]:"
 
-#: spyderlib/plugins/ipythonconsole.py:446
-msgid "Graphics"
-msgstr "Graphiques"
-
-#: spyderlib/plugins/ipythonconsole.py:448
-#: spyderlib/plugins/workingdirectory.py:42
+#: spyderlib/plugins/ipythonconsole.py:467
+#: spyderlib/plugins/workingdirectory.py:44
 msgid "Startup"
 msgstr "Démarrage"
 
-#: spyderlib/plugins/ipythonconsole.py:450
+#: spyderlib/plugins/ipythonconsole.py:469
 msgid "Advanced Settings"
 msgstr "Options avancées"
 
-#: spyderlib/plugins/ipythonconsole.py:462
-#: spyderlib/plugins/ipythonconsole.py:725
+#: spyderlib/plugins/ipythonconsole.py:481
+#: spyderlib/plugins/ipythonconsole.py:749
 msgid "Connect to an existing kernel"
 msgstr "Connecter à un noyau existant"
 
-#: spyderlib/plugins/ipythonconsole.py:464
+#: spyderlib/plugins/ipythonconsole.py:483
 msgid ""
 "Please enter the connection info of the kernel you want to connect to. For "
 "that you can either select its JSON connection file using the <tt>Browse</"
@@ -2203,75 +2213,75 @@ msgstr ""
 "identifiant si c'est un noyau local (Exemple : <tt>kernel-3764.json</tt> ou "
 "juste <tt>3764</tt>)."
 
-#: spyderlib/plugins/ipythonconsole.py:475
+#: spyderlib/plugins/ipythonconsole.py:494
 msgid "Connection info:"
 msgstr "Information de connexion :"
 
-#: spyderlib/plugins/ipythonconsole.py:477
+#: spyderlib/plugins/ipythonconsole.py:496
 msgid "Path to connection file or kernel id"
 msgstr "Chemin vers un fichier de connexion ou identifiant de noyau"
 
-#: spyderlib/plugins/ipythonconsole.py:479
-#: spyderlib/plugins/ipythonconsole.py:497
+#: spyderlib/plugins/ipythonconsole.py:498
+#: spyderlib/plugins/ipythonconsole.py:515
 msgid "Browse"
 msgstr "Parcourir"
 
-#: spyderlib/plugins/ipythonconsole.py:489
+#: spyderlib/plugins/ipythonconsole.py:507
 msgid "This is a remote kernel"
 msgstr "Noyau distant"
 
-#: spyderlib/plugins/ipythonconsole.py:493
+#: spyderlib/plugins/ipythonconsole.py:511
 msgid "username at hostname:port"
 msgstr "utilisateur at hôte:port"
 
-#: spyderlib/plugins/ipythonconsole.py:496
+#: spyderlib/plugins/ipythonconsole.py:514
 msgid "Path to ssh key file"
 msgstr "Chemin vers la clé ssh"
 
-#: spyderlib/plugins/ipythonconsole.py:505
+#: spyderlib/plugins/ipythonconsole.py:523
 msgid "Password or ssh key passphrase"
 msgstr "Mot de passe ou passphrase de clé ssh"
 
-#: spyderlib/plugins/ipythonconsole.py:509
+#: spyderlib/plugins/ipythonconsole.py:527
 msgid "Host name"
 msgstr "Nom d'hôte"
 
-#: spyderlib/plugins/ipythonconsole.py:510
+#: spyderlib/plugins/ipythonconsole.py:528
 msgid "Ssh key"
 msgstr "Clé ssh"
 
-#: spyderlib/plugins/ipythonconsole.py:511
+#: spyderlib/plugins/ipythonconsole.py:529
 msgid "Password"
 msgstr "Mot de passe"
 
-#: spyderlib/plugins/ipythonconsole.py:540
+#: spyderlib/plugins/ipythonconsole.py:558
 msgid "Open IPython connection file"
 msgstr "Ouvrir un fichier de connexion IPython"
 
-#: spyderlib/plugins/ipythonconsole.py:546
+#: spyderlib/plugins/ipythonconsole.py:564
 msgid "Select ssh key"
 msgstr "Sélectionner une clé ssh"
 
-#: spyderlib/plugins/ipythonconsole.py:713
+#: spyderlib/plugins/ipythonconsole.py:737
 msgid "Open an &IPython console"
 msgstr "Ouvrir une console &IPython"
 
-#: spyderlib/plugins/ipythonconsole.py:716
+#: spyderlib/plugins/ipythonconsole.py:740
 msgid "Use %s+T when the console is selected to open a new one"
 msgstr ""
 "Quand la console est sélectionnée, utiliser %s+T pour ouvrir une nouvelle "
 "console"
 
-#: spyderlib/plugins/ipythonconsole.py:719
+#: spyderlib/plugins/ipythonconsole.py:743
 #, fuzzy
 msgid "Open a new console"
 msgstr "Ouvrir une nouvelle console"
 
-#: spyderlib/plugins/ipythonconsole.py:726
+#: spyderlib/plugins/ipythonconsole.py:750
 msgid "Open a new IPython console connected to an existing kernel"
 msgstr "Ouvrir une nouvelle console IPython connecté à un noyau existant"
 
-#: spyderlib/plugins/ipythonconsole.py:809
+#: spyderlib/plugins/ipythonconsole.py:833
 msgid ""
 "No IPython console is currently available to run <b>%s</b>.<br><br>Please "
 "open a new one and try again."
@@ -2279,7 +2289,7 @@ msgstr ""
 "Aucun client IPython n'est actuellement sélectionné pour exécuter <b>%s</b>."
 "<br><br>Merci d'ouvrir un nouveau client IPython et de réessayer."
 
-#: spyderlib/plugins/ipythonconsole.py:950
+#: spyderlib/plugins/ipythonconsole.py:968
 msgid ""
 "Do you want to close all other consoles connected to the same kernel as this "
 "one?"
@@ -2287,11 +2297,11 @@ msgstr ""
 "Voulez-vous fermer les toutes les autres consoles connectées au même noyau "
 "que celle-ci ?"
 
-#: spyderlib/plugins/ipythonconsole.py:1032
+#: spyderlib/plugins/ipythonconsole.py:1050
 msgid "Connection error"
 msgstr "Erreur de connexion"
 
-#: spyderlib/plugins/ipythonconsole.py:1033
+#: spyderlib/plugins/ipythonconsole.py:1051
 msgid ""
 "Could not open ssh tunnel. The error was:\n"
 "\n"
@@ -2299,39 +2309,58 @@ msgstr ""
 "Impossible d'ouvrir un tunnel ssh. L'erreur rencontrée est:\n"
 "\n"
 
-#: spyderlib/plugins/ipythonconsole.py:1069
+#: spyderlib/plugins/ipythonconsole.py:1088
 msgid "IPython"
 msgstr "IPython"
 
-#: spyderlib/plugins/ipythonconsole.py:1070
+#: spyderlib/plugins/ipythonconsole.py:1089
 msgid "Unable to connect to IPython <b>%s"
 msgstr "Impossible de se connecter au noyau IPython <b>`%s`"
 
-#: spyderlib/plugins/ipythonconsole.py:1121
+#: spyderlib/plugins/ipythonconsole.py:1140
 msgid "Are you sure you want to restart the kernel?"
 msgstr "Souhaitez-vous vraiment redémarrer le noyau ?"
 
-#: spyderlib/plugins/ipythonconsole.py:1123
+#: spyderlib/plugins/ipythonconsole.py:1142
 msgid "Restart kernel?"
 msgstr "Redémarrer le noyau"
 
-#: spyderlib/plugins/onlinehelp.py:67
+#: spyderlib/plugins/layoutdialog.py:174
+#, fuzzy
+msgid "Move Up"
+msgstr "Monter"
+
+#: spyderlib/plugins/layoutdialog.py:175
+#, fuzzy
+msgid "Move Down"
+msgstr "Descendre"
+
+#: spyderlib/plugins/layoutdialog.py:176
+#, fuzzy
+msgid "Delete Layout"
+msgstr "Supprimer"
+
+#: spyderlib/plugins/layoutdialog.py:180
+msgid "Layout Dispay and Order"
+msgstr ""
+
+#: spyderlib/plugins/onlinehelp.py:68
 msgid "Online help"
 msgstr "Aide en ligne"
 
-#: spyderlib/plugins/outlineexplorer.py:47
-#: spyderlib/widgets/editortools.py:194
+#: spyderlib/plugins/outlineexplorer.py:48
+#: spyderlib/widgets/editortools.py:195
 msgid "Outline"
 msgstr "Structure"
 
-#: spyderlib/plugins/projectexplorer.py:41
-#: spyderlib/widgets/projectexplorer.py:1137
-#: spyderlib/widgets/projectexplorer.py:1151
+#: spyderlib/plugins/projectexplorer.py:53
+#: spyderlib/widgets/projectexplorer.py:1150
+#: spyderlib/widgets/projectexplorer.py:1164
 msgid "Project explorer"
 msgstr "Explorateur de projets"
 
-#: spyderlib/plugins/projectexplorer.py:52
-#: spyderlib/widgets/projectexplorer.py:545
+#: spyderlib/plugins/projectexplorer.py:64
+#: spyderlib/widgets/projectexplorer.py:549
 msgid "New project..."
 msgstr "Nouveau projet..."
 
@@ -2351,59 +2380,63 @@ msgstr "Exécuter dans un terminal système externe"
 msgid "Always show %s on a first file run"
 msgstr "Toujours afficher %s lors de la première exécution d'un script"
 
-#: spyderlib/plugins/runconfig.py:153
+#: spyderlib/plugins/runconfig.py:159
 msgid "General settings"
 msgstr "Options générales"
 
-#: spyderlib/plugins/runconfig.py:156 spyderlib/plugins/runconfig.py:201
+#: spyderlib/plugins/runconfig.py:162 spyderlib/plugins/runconfig.py:208
 msgid "Command line options:"
 msgstr "Options en ligne de commande :"
 
-#: spyderlib/plugins/runconfig.py:163
+#: spyderlib/plugins/runconfig.py:168
 msgid "Working directory:"
 msgstr "Répertoire de travail :"
 
-#: spyderlib/plugins/runconfig.py:189
+#: spyderlib/plugins/runconfig.py:180 spyderlib/plugins/runconfig.py:491
+msgid "Enter debugging mode when errors appear during execution"
+msgstr ""
+
+#: spyderlib/plugins/runconfig.py:196 spyderlib/plugins/runconfig.py:501
 msgid "Dedicated Python console"
 msgstr "Console Python dédiée"
 
-#: spyderlib/plugins/runconfig.py:194
+#: spyderlib/plugins/runconfig.py:200 spyderlib/plugins/runconfig.py:503
 msgid "Interact with the Python console after execution"
 msgstr "Interagir avec la console Python après l'exécution"
 
-#: spyderlib/plugins/runconfig.py:198
+#: spyderlib/plugins/runconfig.py:204
 msgid "Show warning when killing running process"
 msgstr "Afficher un avertissement à l'interruption d'un processus"
 
-#: spyderlib/plugins/runconfig.py:207
+#: spyderlib/plugins/runconfig.py:213
 msgid "<b>-u</b> is added to the other options you set here"
 msgstr "L'option <b>-u</b> est ajoutée aux autres options spécifiées ici"
 
-#: spyderlib/plugins/runconfig.py:218
+#: spyderlib/plugins/runconfig.py:223
 msgid "this dialog"
 msgstr "cette fenêtre"
 
-#: spyderlib/plugins/runconfig.py:276
+#: spyderlib/plugins/runconfig.py:282
 msgid "Run configuration"
 msgstr "Configuration d'exécution"
 
-#: spyderlib/plugins/runconfig.py:277
+#: spyderlib/plugins/runconfig.py:283
 msgid "The following working directory is not valid:<br><b>%s</b>"
 msgstr "Le répertoire de travail suivant n'est pas valide :<br><b>%s</b>"
 
-#: spyderlib/plugins/runconfig.py:353
+#: spyderlib/plugins/runconfig.py:361
 msgid "Run settings for %s"
 msgstr "Options d'exécution pour %s"
 
-#: spyderlib/plugins/runconfig.py:384
+#: spyderlib/plugins/runconfig.py:393
 msgid "Select a run configuration:"
 msgstr "Sélectionner une configuration d'exécution :"
 
-#: spyderlib/plugins/runconfig.py:414 spyderlib/plugins/runconfig.py:439
+#: spyderlib/plugins/runconfig.py:422 spyderlib/plugins/runconfig.py:447
 msgid "Run Settings"
 msgstr "Options d'exécution"
 
-#: spyderlib/plugins/runconfig.py:441
+#: spyderlib/plugins/runconfig.py:449
 msgid ""
 "The following are the default <i>%s</i>. These options may be overriden "
 "using the <b>%s</b> dialog box (see the <b>%s</b> menu)"
@@ -2412,63 +2445,99 @@ msgstr ""
 "réglages peuvent être remplacés à tout moment en utilisant la boîte de "
 "dialogue <b>%s</b> (voir le menu <b>%s</b>)"
 
-#: spyderlib/plugins/runconfig.py:465
-#: spyderlib/widgets/externalshell/pythonshell.py:297
-msgid "Working directory"
-msgstr "Répertoire de travail"
-
-#: spyderlib/plugins/runconfig.py:467
+#: spyderlib/plugins/runconfig.py:475
 msgid "Default working directory is:"
 msgstr "Le répertoire de travail par défaut est :"
 
-#: spyderlib/plugins/runconfig.py:469
+#: spyderlib/plugins/runconfig.py:477
 msgid "the script directory"
 msgstr "le répertoire du fichier à exécuter"
 
-#: spyderlib/plugins/runconfig.py:472 spyderlib/plugins/workingdirectory.py:54
+#: spyderlib/plugins/runconfig.py:480 spyderlib/plugins/workingdirectory.py:56
 msgid "the following directory:"
 msgstr "le répertoire suivant :"
 
-#: spyderlib/plugins/runconfig.py:491
+#: spyderlib/plugins/runconfig.py:506
+#, fuzzy
+msgid "Show warning when killing running processes"
+msgstr "Afficher un avertissement à l'interruption d'un processus"
+
+#: spyderlib/plugins/runconfig.py:515
 msgid "Run Settings dialog"
 msgstr "la fenêtre Options d'exécution"
 
-#: spyderlib/plugins/shortcuts.py:178
+#: spyderlib/plugins/shortcuts.py:134
+msgid ""
+"Press the new shortcut and select 'Ok': \n"
+"(Press 'Tab' once to switch focus between the shortcut entry \n"
+"and the buttons below it)"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:137
+#, fuzzy
+msgid "Current shortcut:"
+msgstr "Cellule actuelle :"
+
+#: spyderlib/plugins/shortcuts.py:139
+#, fuzzy
+msgid "New shortcut:"
+msgstr "Raccourcis clavier"
+
+#: spyderlib/plugins/shortcuts.py:152
+msgid "Shortcut: {0}"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:273
+msgid "Please introduce a different shortcut"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:310
+msgid "The new shorcut conflicts with:"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:321
+msgid ""
+"A compound sequence can have {break} a maximum of 4 subsequences.{break}"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:326
+#, fuzzy
+msgid "Invalid key entered"
+msgstr "Chemin d'accès de fichier incorrect"
+
+#: spyderlib/plugins/shortcuts.py:515
 msgid "Context"
 msgstr "Contexte"
 
-#: spyderlib/plugins/shortcuts.py:180 spyderlib/widgets/dicteditor.py:158
+#: spyderlib/plugins/shortcuts.py:517 spyderlib/widgets/dicteditor.py:158
 msgid "Name"
 msgstr "Nom"
 
-#: spyderlib/plugins/shortcuts.py:182
-msgid "Mod1"
-msgstr "Mod1"
-
-#: spyderlib/plugins/shortcuts.py:184
-msgid "Mod2"
-msgstr "Mod2"
-
-#: spyderlib/plugins/shortcuts.py:186
-msgid "Mod3"
-msgstr "Mod3"
+#: spyderlib/plugins/shortcuts.py:519
+msgid "Shortcut"
+msgstr ""
 
-#: spyderlib/plugins/shortcuts.py:188 spyderlib/widgets/dicteditor.py:169
-msgid "Key"
-msgstr "Clé"
+#: spyderlib/plugins/shortcuts.py:521
+msgid "Score"
+msgstr ""
 
-#: spyderlib/plugins/shortcuts.py:321
+#: spyderlib/plugins/shortcuts.py:681
 msgid "Conflicts"
 msgstr "Conflits"
 
-#: spyderlib/plugins/shortcuts.py:322
+#: spyderlib/plugins/shortcuts.py:682
 msgid "The following conflicts have been detected:"
 msgstr "Les conflits suivants ont été détectés :"
 
-#: spyderlib/plugins/shortcuts.py:334
+#: spyderlib/plugins/shortcuts.py:767
 msgid "Keyboard shortcuts"
 msgstr "Raccourcis clavier"
 
+#: spyderlib/plugins/shortcuts.py:775
+#, fuzzy
+msgid "Search: "
+msgstr "Rechercher"
+
 #: spyderlib/plugins/variableexplorer.py:24
 msgid "Autorefresh"
 msgstr "Rafraîchissement automatique"
@@ -2490,32 +2559,32 @@ msgid "Filter"
 msgstr "Filtre"
 
 #: spyderlib/plugins/variableexplorer.py:33
-#: spyderlib/widgets/externalshell/namespacebrowser.py:196
+#: spyderlib/widgets/externalshell/namespacebrowser.py:214
 msgid "Exclude private references"
 msgstr "Exclure les références privées"
 
 #: spyderlib/plugins/variableexplorer.py:34
-#: spyderlib/widgets/externalshell/namespacebrowser.py:211
+#: spyderlib/widgets/externalshell/namespacebrowser.py:229
 msgid "Exclude capitalized references"
 msgstr "Exclure les références commençant par une majuscule"
 
 #: spyderlib/plugins/variableexplorer.py:35
-#: spyderlib/widgets/externalshell/namespacebrowser.py:204
+#: spyderlib/widgets/externalshell/namespacebrowser.py:222
 msgid "Exclude all-uppercase references"
 msgstr "Exclure les références en lettres capitales"
 
 #: spyderlib/plugins/variableexplorer.py:36
-#: spyderlib/widgets/externalshell/namespacebrowser.py:219
+#: spyderlib/widgets/externalshell/namespacebrowser.py:237
 msgid "Exclude unsupported data types"
 msgstr "Exclure les types non supportés"
 
 #: spyderlib/plugins/variableexplorer.py:42
-#: spyderlib/widgets/dicteditor.py:702
+#: spyderlib/widgets/dicteditor.py:708
 msgid "Truncate values"
 msgstr "Tronquer les valeurs"
 
 #: spyderlib/plugins/variableexplorer.py:44
-#: spyderlib/widgets/dicteditor.py:706
+#: spyderlib/widgets/dicteditor.py:712
 msgid "Show arrays min/max"
 msgstr "Afficher les min/max des tableaux"
 
@@ -2535,11 +2604,11 @@ msgstr ""
 "Cela permet d'éviter de transférer de gros volumes de données entre le "
 "processus distant et Spyder (à travers le socket)."
 
-#: spyderlib/plugins/variableexplorer.py:158
+#: spyderlib/plugins/variableexplorer.py:183
 msgid "Variable explorer"
 msgstr "Explorateur de variables"
 
-#: spyderlib/plugins/workingdirectory.py:35
+#: spyderlib/plugins/workingdirectory.py:37
 msgid ""
 "The <b>global working directory</b> is the working directory for newly "
 "opened <i>consoles</i> (Python/IPython consoles and terminals), for the "
@@ -2551,21 +2620,21 @@ msgstr ""
 "pour l'<i>explorateur de fichiers</i>, pour la <i>recherche dans les "
 "fichiers</i> et pour les fichiers créés dans l'<i>éditeur</i>."
 
-#: spyderlib/plugins/workingdirectory.py:44
+#: spyderlib/plugins/workingdirectory.py:46
 msgid "At startup, the global working directory is:"
 msgstr "Au démarrage, le répertoire de travail global est :"
 
-#: spyderlib/plugins/workingdirectory.py:48
+#: spyderlib/plugins/workingdirectory.py:50
 msgid "the same as in last session"
 msgstr "celui utilisé lors de la dernière session"
 
-#: spyderlib/plugins/workingdirectory.py:50
+#: spyderlib/plugins/workingdirectory.py:52
 msgid "At startup, Spyder will restore the global directory from last session"
 msgstr ""
 "Au démarrage, Spyder reprendra le répertoire de travail global de la "
 "dernière session"
 
-#: spyderlib/plugins/workingdirectory.py:56
+#: spyderlib/plugins/workingdirectory.py:58
 msgid "At startup, the global working directory will be the specified path"
 msgstr ""
 "Au démarrage, le répertoire de travail global sera le chemin d'accès "
@@ -2601,16 +2670,16 @@ msgstr "Lors de l'ouverture d'un fichier"
 msgid "When saving a file"
 msgstr "Lors de l'enregistrement d'un fichier"
 
-#: spyderlib/plugins/workingdirectory.py:160
+#: spyderlib/plugins/workingdirectory.py:171
 msgid "Back"
 msgstr "Retour"
 
-#: spyderlib/plugins/workingdirectory.py:168
-#: spyderlib/widgets/explorer.py:1004 spyderlib/widgets/importwizard.py:523
+#: spyderlib/plugins/workingdirectory.py:179
+#: spyderlib/widgets/explorer.py:1021 spyderlib/widgets/importwizard.py:529
 msgid "Next"
 msgstr "Suivant"
 
-#: spyderlib/plugins/workingdirectory.py:181
+#: spyderlib/plugins/workingdirectory.py:190
 msgid ""
 "This is the working directory for newly\n"
 "opened consoles (Python/IPython consoles and\n"
@@ -2624,171 +2693,248 @@ msgstr ""
 "de fichiers, pour la recherche dans les fichiers\n"
 "et pour les fichiers créés dans l'éditeur"
 
-#: spyderlib/plugins/workingdirectory.py:207
+#: spyderlib/plugins/workingdirectory.py:216
 msgid "Browse a working directory"
 msgstr "Sélectionner un répertoire de travail"
 
-#: spyderlib/plugins/workingdirectory.py:213
+#: spyderlib/plugins/workingdirectory.py:222
 msgid "Set as current console's working directory"
 msgstr "Changer le répertoire de travail de la console actuelle"
 
-#: spyderlib/plugins/workingdirectory.py:221
+#: spyderlib/plugins/workingdirectory.py:230
 msgid "Change to parent directory"
 msgstr "Aller au répertoire parent"
 
-#: spyderlib/plugins/workingdirectory.py:228
+#: spyderlib/plugins/workingdirectory.py:237
 msgid "Global working directory"
 msgstr "Répertoire de travail global"
 
-#: spyderlib/spyder.py:120
+#: spyderlib/restart_app.py:129
+#, fuzzy
+msgid ""
+"It was not possible to close the previous Spyder instance.\n"
+"Restart aborted."
+msgstr "Impossible d'exécuter ce fichier dans un terminal externe"
+
+#: spyderlib/restart_app.py:131
+msgid ""
+"Spyder could not reset to factory defaults.\n"
+"Restart aborted."
+msgstr ""
+
+#: spyderlib/restart_app.py:133
+msgid ""
+"It was not possible to restart Spyder.\n"
+"Operation aborted."
+msgstr ""
+
+#: spyderlib/restart_app.py:135
+#, fuzzy
+msgid "Spyder exit error"
+msgstr "Éditeur de Spyder"
+
+#: spyderlib/restart_app.py:136
+#, fuzzy
+msgid "Spyder reset error"
+msgstr "Éditeur de Spyder"
+
+#: spyderlib/restart_app.py:137
+#, fuzzy
+msgid "Spyder restart error"
+msgstr "Démarrage de Spyder"
+
+#: spyderlib/restart_app.py:161
+#, fuzzy
+msgid "Closing Spyder"
+msgstr "Ouvrir en dehors de Spyder"
+
+#: spyderlib/restart_app.py:234
+#, fuzzy
+msgid "Resetting Spyder to defaults"
+msgstr "Rétablir les valeurs par défaut"
+
+#: spyderlib/restart_app.py:266
+#, fuzzy
+msgid "Restarting"
+msgstr "Restaurer"
+
+#: spyderlib/spyder.py:124
 msgid "Initializing..."
 msgstr "Initialisation..."
 
-#: spyderlib/spyder.py:244
+#: spyderlib/spyder.py:247
 msgid "Numpy and Scipy documentation"
 msgstr "Documentation de Numpy et Scipy"
 
-#: spyderlib/spyder.py:246 spyderlib/spyder.py:949
+#: spyderlib/spyder.py:249 spyderlib/spyder.py:1084
 msgid "Matplotlib documentation"
 msgstr "Documentation de Matplotlib"
 
-#: spyderlib/spyder.py:249
+#: spyderlib/spyder.py:252
 msgid "PyQt4 Reference Guide"
 msgstr "Guide de référence de PyQt4"
 
-#: spyderlib/spyder.py:252
+#: spyderlib/spyder.py:255
 msgid "PyQt4 API Reference"
 msgstr "Documentation de l'API de PyQt4"
 
-#: spyderlib/spyder.py:254
+#: spyderlib/spyder.py:257
 msgid "Python(x,y)"
 msgstr "Python(x,y)"
 
-#: spyderlib/spyder.py:256
+#: spyderlib/spyder.py:259
 msgid "WinPython"
 msgstr "WinPython"
 
-#: spyderlib/spyder.py:293
+#: spyderlib/spyder.py:305
 msgid "Reload last session"
 msgstr "Recharger la session précédente"
 
-#: spyderlib/spyder.py:297
+#: spyderlib/spyder.py:309
 msgid "Load session..."
 msgstr "Charger une session..."
 
-#: spyderlib/spyder.py:300
+#: spyderlib/spyder.py:312
 msgid "Load Spyder session"
 msgstr "Charger une session Spyder"
 
-#: spyderlib/spyder.py:302
+#: spyderlib/spyder.py:314
 msgid "Save session and quit..."
 msgstr "Enregistrer la session et quitter..."
 
-#: spyderlib/spyder.py:305
+#: spyderlib/spyder.py:317
 msgid "Save current session and quit application"
 msgstr "Enregistrer la session en cours et quitter l'application"
 
-#: spyderlib/spyder.py:483
+#: spyderlib/spyder.py:530
 msgid "Close current pane"
 msgstr "Fermer le volet courant"
 
-#: spyderlib/spyder.py:489
+#: spyderlib/spyder.py:535
+msgid "Lock panes"
+msgstr ""
+
+#: spyderlib/spyder.py:542
+#, fuzzy
+msgid "Use next layout"
+msgstr "Réinitialiser la disposition des fenêtres"
+
+#: spyderlib/spyder.py:546
+#, fuzzy
+msgid "Use previous layout"
+msgstr "Réinitialiser la disposition des fenêtres"
+
+#: spyderlib/spyder.py:555
 msgid "&Find text"
 msgstr "Rec&hercher"
 
-#: spyderlib/spyder.py:494
+#: spyderlib/spyder.py:560
 msgid "Find &next"
 msgstr "Rechercher le &suivant"
 
-#: spyderlib/spyder.py:500
+#: spyderlib/spyder.py:567
 msgid "Find &previous"
 msgstr "Rechercher le &précédent"
 
-#: spyderlib/spyder.py:505
+#: spyderlib/spyder.py:573
 msgid "&Replace text"
 msgstr "&Remplacer"
 
-#: spyderlib/spyder.py:520 spyderlib/widgets/sourcecode/codeeditor.py:2268
+#: spyderlib/spyder.py:580 spyderlib/widgets/editor.py:339
+#, fuzzy
+msgid "File switcher..."
+msgstr "Fichier..."
+
+#: spyderlib/spyder.py:582
+msgid "Fast switch between files"
+msgstr ""
+
+#: spyderlib/spyder.py:600 spyderlib/widgets/sourcecode/codeeditor.py:2425
 msgid "Undo"
 msgstr "Annuler"
 
-#: spyderlib/spyder.py:522 spyderlib/widgets/sourcecode/codeeditor.py:2271
+#: spyderlib/spyder.py:602 spyderlib/widgets/sourcecode/codeeditor.py:2428
 msgid "Redo"
 msgstr "Répéter"
 
-#: spyderlib/spyder.py:523 spyderlib/widgets/arrayeditor.py:392
+#: spyderlib/spyder.py:604 spyderlib/widgets/arrayeditor.py:392
 #: spyderlib/widgets/dataframeeditor.py:418
-#: spyderlib/widgets/dicteditor.py:674 spyderlib/widgets/shell.py:118
-#: spyderlib/widgets/sourcecode/codeeditor.py:2277
+#: spyderlib/widgets/dicteditor.py:680 spyderlib/widgets/shell.py:126
+#: spyderlib/widgets/sourcecode/codeeditor.py:2434
 msgid "Copy"
 msgstr "Copier"
 
-#: spyderlib/spyder.py:525 spyderlib/widgets/shell.py:114
-#: spyderlib/widgets/sourcecode/codeeditor.py:2274
+#: spyderlib/spyder.py:606 spyderlib/widgets/shell.py:122
+#: spyderlib/widgets/sourcecode/codeeditor.py:2431
 msgid "Cut"
 msgstr "Couper"
 
-#: spyderlib/spyder.py:526 spyderlib/widgets/dicteditor.py:671
-#: spyderlib/widgets/shell.py:122
-#: spyderlib/widgets/sourcecode/codeeditor.py:2280
+#: spyderlib/spyder.py:608 spyderlib/widgets/dicteditor.py:677
+#: spyderlib/widgets/shell.py:130
+#: spyderlib/widgets/sourcecode/codeeditor.py:2437
 msgid "Paste"
 msgstr "Coller"
 
-#: spyderlib/spyder.py:528 spyderlib/widgets/explorer.py:461
-#: spyderlib/widgets/projectexplorer.py:1003 spyderlib/widgets/shell.py:131
-#: spyderlib/widgets/sourcecode/codeeditor.py:2283
+#: spyderlib/spyder.py:610 spyderlib/widgets/explorer.py:470
+#: spyderlib/widgets/projectexplorer.py:1015 spyderlib/widgets/shell.py:139
+#: spyderlib/widgets/sourcecode/codeeditor.py:2440
 msgid "Delete"
 msgstr "Supprimer"
 
-#: spyderlib/spyder.py:531 spyderlib/widgets/shell.py:135
-#: spyderlib/widgets/sourcecode/codeeditor.py:2287
+#: spyderlib/spyder.py:614 spyderlib/widgets/shell.py:143
+#: spyderlib/widgets/sourcecode/codeeditor.py:2444
 msgid "Select All"
 msgstr "Sélectionner tout"
 
-#: spyderlib/spyder.py:580
+#: spyderlib/spyder.py:664
 msgid "C&onsoles"
 msgstr "C&onsoles"
 
-#: spyderlib/spyder.py:586
+#: spyderlib/spyder.py:670
 msgid "&View"
 msgstr "&Affichage"
 
-#: spyderlib/spyder.py:589
+#: spyderlib/spyder.py:673
 msgid "&Help"
 msgstr "A&ide"
 
-#: spyderlib/spyder.py:594
+#: spyderlib/spyder.py:678
 msgid "Welcome to Spyder!"
 msgstr "Bienvenue dans Spyder !"
 
-#: spyderlib/spyder.py:599
+#: spyderlib/spyder.py:683
 msgid "Pre&ferences"
 msgstr "Pré&férences"
 
-#: spyderlib/spyder.py:606 spyderlib/widgets/pathmanager.py:45
-#: spyderlib/widgets/projectexplorer.py:594
+#: spyderlib/spyder.py:690 spyderlib/widgets/pathmanager.py:48
+#: spyderlib/widgets/projectexplorer.py:598
 msgid "PYTHONPATH manager"
 msgstr "Gestionnaire de PYTHONPATH"
 
-#: spyderlib/spyder.py:609
+#: spyderlib/spyder.py:693
 msgid "Python Path Manager"
 msgstr "Gestionnaire de chemins d'accès Python"
 
-#: spyderlib/spyder.py:612
+#: spyderlib/spyder.py:696
 msgid "Update module names list"
 msgstr "Mise à jour de la liste des modules"
 
-#: spyderlib/spyder.py:614
+#: spyderlib/spyder.py:699
 msgid "Refresh list of module names available in PYTHONPATH"
 msgstr ""
 "Mise à jour de la liste des modules disponibles notamment à travers "
 "PYTHONPATH"
 
-#: spyderlib/spyder.py:619
+#: spyderlib/spyder.py:702
+#, fuzzy
+msgid "Reset Spyder to factory defaults"
+msgstr "Rétablir les valeurs par défaut"
+
+#: spyderlib/spyder.py:707
 msgid "Current user environment variables..."
 msgstr "Variables d'environnement de l'utilisateur..."
 
-#: spyderlib/spyder.py:621
+#: spyderlib/spyder.py:709
 msgid ""
 "Show and edit current user environment variables in Windows registry (i.e. "
 "for all sessions)"
@@ -2796,55 +2942,55 @@ msgstr ""
 "Afficher et modifier les variables d'environnement de l'utilisateur courant "
 "dans Windows (c'est-à-dire directement dans la base de registre)"
 
-#: spyderlib/spyder.py:629 spyderlib/spyder.py:1043
+#: spyderlib/spyder.py:718 spyderlib/spyder.py:1178
 msgid "External Tools"
 msgstr "Outils externes"
 
-#: spyderlib/spyder.py:633
+#: spyderlib/spyder.py:722
 msgid "Python(x,y) launcher"
 msgstr "Accueil de Python(x,y)"
 
-#: spyderlib/spyder.py:640
+#: spyderlib/spyder.py:729
 msgid "WinPython control panel"
 msgstr "Panneau de contrôle WinPython"
 
-#: spyderlib/spyder.py:649
+#: spyderlib/spyder.py:738
 msgid "Qt Designer"
 msgstr "Qt Designer"
 
-#: spyderlib/spyder.py:654
+#: spyderlib/spyder.py:743
 msgid "Qt Linguist"
 msgstr "Qt Linguist"
 
-#: spyderlib/spyder.py:660
+#: spyderlib/spyder.py:749
 msgid "Qt examples"
 msgstr "Exemples Qt"
 
-#: spyderlib/spyder.py:678
+#: spyderlib/spyder.py:770
 msgid "guidata examples"
 msgstr "Exemples guidata"
 
-#: spyderlib/spyder.py:686
+#: spyderlib/spyder.py:781
 msgid "guiqwt examples"
 msgstr "Exemples guiqwt"
 
-#: spyderlib/spyder.py:691
+#: spyderlib/spyder.py:786
 msgid "Sift"
 msgstr "Sift"
 
-#: spyderlib/spyder.py:699
+#: spyderlib/spyder.py:796
 msgid "ViTables"
 msgstr "ViTables"
 
-#: spyderlib/spyder.py:713
+#: spyderlib/spyder.py:810
 msgid "Fullscreen mode"
 msgstr "Mode plein écran"
 
-#: spyderlib/spyder.py:725
+#: spyderlib/spyder.py:822
 msgid "Main toolbar"
 msgstr "Barre d'outil principale"
 
-#: spyderlib/spyder.py:734
+#: spyderlib/spyder.py:831
 msgid ""
 "Spyder Internal Console\n"
 "\n"
@@ -2867,163 +3013,195 @@ msgstr ""
 "Ne l'utilisez pas pour exécuter votre propre code.\n"
 "\n"
 
-#: spyderlib/spyder.py:751
+#: spyderlib/spyder.py:848
 msgid "Loading object inspector..."
 msgstr "Chargement de l'inspecteur d'objet..."
 
-#: spyderlib/spyder.py:758
+#: spyderlib/spyder.py:855
 msgid "Loading outline explorer..."
 msgstr "Chargement de l'explorateur de structure..."
 
-#: spyderlib/spyder.py:766
+#: spyderlib/spyder.py:863
 msgid "Loading editor..."
 msgstr "Chargement de l'éditeur..."
 
-#: spyderlib/spyder.py:791
+#: spyderlib/spyder.py:874
+#, fuzzy
+msgid "&Restart"
+msgstr "Restaurer"
+
+#: spyderlib/spyder.py:876
+#, fuzzy
+msgid "Restart"
+msgstr "Restaurer"
+
+#: spyderlib/spyder.py:895
 msgid "Loading file explorer..."
 msgstr "Chargement de l'explorateur de fichiers..."
 
-#: spyderlib/spyder.py:798
+#: spyderlib/spyder.py:902
 msgid "Loading history plugin..."
 msgstr "Chargement du journal d'historique..."
 
-#: spyderlib/spyder.py:809
+#: spyderlib/spyder.py:913
 msgid "Loading online help..."
 msgstr "Chargement de l'aide en ligne..."
 
-#: spyderlib/spyder.py:815
+#: spyderlib/spyder.py:919
 msgid "Loading project explorer..."
 msgstr "Chargement de l'explorateur de projet..."
 
-#: spyderlib/spyder.py:826
+#: spyderlib/spyder.py:930
 msgid "Loading external console..."
 msgstr "Chargement de la console externe..."
 
-#: spyderlib/spyder.py:835
+#: spyderlib/spyder.py:939
 msgid "Loading namespace browser..."
 msgstr "Chargement de l'explorateur d'espace de noms..."
 
-#: spyderlib/spyder.py:842
+#: spyderlib/spyder.py:946
 msgid "Loading IPython console..."
 msgstr "Chargement de la console IPython..."
 
-#: spyderlib/spyder.py:853
+#: spyderlib/spyder.py:956
 msgid "Setting up main window..."
 msgstr "Configuration de la fenêtre principale..."
 
-#: spyderlib/spyder.py:856
+#: spyderlib/spyder.py:959
 msgid "Optional dependencies..."
 msgstr "Dépendances optionnelles..."
 
-#: spyderlib/spyder.py:860
+#: spyderlib/spyder.py:963
 msgid "Report issue..."
 msgstr "Rapport d'erreur..."
 
-#: spyderlib/spyder.py:864
+#: spyderlib/spyder.py:967
 msgid "Spyder support..."
 msgstr "Support technique de Spyder..."
 
-#: spyderlib/spyder.py:887
+#: spyderlib/spyder.py:970
+msgid "Check for updates..."
+msgstr ""
+
+#: spyderlib/spyder.py:993
 msgid "Spyder documentation"
 msgstr "Documentation de Spyder"
 
-#: spyderlib/spyder.py:889
+#: spyderlib/spyder.py:997
 msgid "Spyder tutorial"
 msgstr "Tutoriel de Spyder"
 
-#: spyderlib/spyder.py:896
+#: spyderlib/spyder.py:1002
+#, fuzzy
+msgid "Interactive tours"
+msgstr "Barre d'outil d'interaction"
+
+#: spyderlib/spyder.py:1031
 msgid "Python documentation"
 msgstr "Documentation de Python"
 
-#: spyderlib/spyder.py:902 spyderlib/spyder.py:941
+#: spyderlib/spyder.py:1037 spyderlib/spyder.py:1076
 msgid "IPython documentation"
 msgstr "Documentation de IPython"
 
-#: spyderlib/spyder.py:903
+#: spyderlib/spyder.py:1038
 msgid "Intro to IPython"
 msgstr "Introduction à IPython"
 
-#: spyderlib/spyder.py:905
+#: spyderlib/spyder.py:1040
 msgid "Quick reference"
 msgstr "Référence rapide"
 
-#: spyderlib/spyder.py:907
+#: spyderlib/spyder.py:1042
 msgid "Console help"
 msgstr "Aide sur la console"
 
-#: spyderlib/spyder.py:939
+#: spyderlib/spyder.py:1074
 msgid "Python(x,y) documentation folder"
 msgstr "Dossier de documentation Python(x,y)"
 
-#: spyderlib/spyder.py:943
+#: spyderlib/spyder.py:1078
 msgid "guidata documentation"
 msgstr "Documentation de guidata"
 
-#: spyderlib/spyder.py:946
+#: spyderlib/spyder.py:1081
 msgid "guiqwt documentation"
 msgstr "Documentation de guiqwt"
 
-#: spyderlib/spyder.py:952
+#: spyderlib/spyder.py:1087
 msgid "NumPy documentation"
 msgstr "Documentation de NumPy"
 
-#: spyderlib/spyder.py:954
+#: spyderlib/spyder.py:1089
 msgid "NumPy reference guide"
 msgstr "Manuel de référence de NumPy"
 
-#: spyderlib/spyder.py:956
+#: spyderlib/spyder.py:1091
 msgid "NumPy user guide"
 msgstr "Manuel de l'utilisateur de NumPy"
 
-#: spyderlib/spyder.py:958
+#: spyderlib/spyder.py:1093
 msgid "SciPy documentation"
 msgstr "Documentation de SciPy"
 
-#: spyderlib/spyder.py:965
+#: spyderlib/spyder.py:1100
 msgid "Installed Python modules"
 msgstr "Modules Python installés"
 
-#: spyderlib/spyder.py:969
+#: spyderlib/spyder.py:1104
 msgid "Online documentation"
 msgstr "Documentation en ligne"
 
-#: spyderlib/spyder.py:979
+#: spyderlib/spyder.py:1116
 msgid "Qt documentation"
 msgstr "Documentation de Qt"
 
-#: spyderlib/spyder.py:985
+#: spyderlib/spyder.py:1122
 msgid "About %s..."
 msgstr "À propos de %s..."
 
-#: spyderlib/spyder.py:1006
+#: spyderlib/spyder.py:1146
 msgid "Panes"
 msgstr "Volets"
 
-#: spyderlib/spyder.py:1007
+#: spyderlib/spyder.py:1147
 msgid "Toolbars"
 msgstr "Barres d'outils"
 
-#: spyderlib/spyder.py:1010
-msgid "Reset window layout"
-msgstr "Réinitialiser la disposition des fenêtres"
-
-#: spyderlib/spyder.py:1012
-msgid "Custom window layouts"
+#: spyderlib/spyder.py:1148
+#, fuzzy
+msgid "Window layouts"
 msgstr "Dispositions de fenêtres personnalisées"
 
-#: spyderlib/spyder.py:1018
-msgid "Switch to/from layout %d"
-msgstr "Basculer vers/depuis la disposition %d"
-
-#: spyderlib/spyder.py:1023
-msgid "Set layout %d"
-msgstr "Définir la disposition %d"
+#: spyderlib/spyder.py:1157 spyderlib/spyder.py:1910 spyderlib/spyder.py:1911
+#, fuzzy
+msgid "Show toolbars"
+msgstr "Afficher la barre d'outils"
 
-#: spyderlib/spyder.py:1031
+#: spyderlib/spyder.py:1171
 msgid "Attached console window (debugging)"
 msgstr "Invite de commandes attaché (débogage)"
 
-#: spyderlib/spyder.py:1332
+#: spyderlib/spyder.py:1756
+msgid "Spyder Default Layout"
+msgstr ""
+
+#: spyderlib/spyder.py:1774 spyderlib/spyder.py:1785
+#, fuzzy
+msgid "Save current layout"
+msgstr "Enregistrer le fichier en cours d'édition"
+
+#: spyderlib/spyder.py:1778 spyderlib/spyder.py:1787
+#, fuzzy
+msgid "Layout preferences"
+msgstr "Préférences"
+
+#: spyderlib/spyder.py:1782
+#, fuzzy
+msgid "Reset to spyder default"
+msgstr "Rétablir les valeurs par défaut"
+
+#: spyderlib/spyder.py:1804
 msgid ""
 "Window layout will be reset to default settings: this affects window "
 "position, size and dockwidgets.\n"
@@ -3033,45 +3211,213 @@ msgstr ""
 "défaut.\n"
 "Souhaitez-vous continuer ?"
 
-#: spyderlib/spyder.py:1350
-msgid "Quick switch layout #%d has not yet been defined."
+#: spyderlib/spyder.py:1826
+msgid ""
+"Layout <b>%s</b> will be                                                "
+"overwritten. Do you want to                                                "
+"continue?"
+msgstr ""
+
+#: spyderlib/spyder.py:1889
+#, fuzzy
+msgid "Quick switch layout #%s has not yet been defined."
 msgstr ""
 "La disposition de fenêtre personnalisée n°%d n'a pas encore été définie."
 
-#: spyderlib/spyder.py:1602 spyderlib/spyder.py:1603
+#: spyderlib/spyder.py:1907 spyderlib/spyder.py:1908
+#, fuzzy
+msgid "Hide toolbars"
+msgstr "Barre d'outil fichiers"
+
+#: spyderlib/spyder.py:2229 spyderlib/spyder.py:2230
 msgid "Maximize current pane"
 msgstr "Agrandir le volet courant"
 
-#: spyderlib/spyder.py:1606
+#: spyderlib/spyder.py:2233
 msgid "Restore current pane"
 msgstr "Restaurer le volet courant"
 
-#: spyderlib/spyder.py:1607
+#: spyderlib/spyder.py:2234
 msgid "Restore pane to its original size"
 msgstr "Restaurer le volet à sa taille d'origine"
 
-#: spyderlib/spyder.py:1686
+#: spyderlib/spyder.py:2318
 msgid "About %s"
 msgstr "À propos de %s"
 
-#: spyderlib/spyder.py:1851
+#: spyderlib/spyder.py:2502
 msgid "Running an external system terminal is not supported on platform %s."
 msgstr ""
 "L'exécution dans un terminal système externe n'est pas prise en charge sur "
 "la plateforme %s."
 
-#: spyderlib/spyder.py:2066
+#: spyderlib/spyder.py:2721
 msgid "Open session"
 msgstr "Ouvrir une session"
 
-#: spyderlib/spyder.py:2067 spyderlib/spyder.py:2078
+#: spyderlib/spyder.py:2722 spyderlib/spyder.py:2734
 msgid "Spyder sessions"
 msgstr "Sessions Spyder"
 
-#: spyderlib/spyder.py:2077
+#: spyderlib/spyder.py:2733
 msgid "Save session"
 msgstr "Enregistrer la session"
 
+#: spyderlib/spyder.py:2775
+#, fuzzy
+msgid ""
+"Spyder will restart and reset to default settings: <br><br>Do you want to "
+"continue?"
+msgstr ""
+"Le répertoire suivant n'est pas vide :<br><b>%s</b><br><br>Souhaitez-vous "
+"néanmoins continuer ?"
+
+#: spyderlib/spyder.py:2871 spyderlib/widgets/helperwidgets.py:144
+#, fuzzy
+msgid "Spyder updates"
+msgstr "Fichiers Spyder"
+
+#: spyderlib/spyder.py:2890
+msgid ""
+"<b>Spyder %s is available!</b> <br><br>Please use your package manager to "
+"update Spyder or go to our <a href=\"%s\">Releases</a> page to download this "
+"new version. <br><br>If you are not sure how to proceed to update Spyder "
+"please refer to our  <a href=\"%s\">Installation</a> instructions."
+msgstr ""
+
+#: spyderlib/spyder.py:2902
+#, fuzzy
+msgid "Spyder is up to date."
+msgstr "Support technique de Spyder..."
+
+#: spyderlib/tour.py:121
+#, fuzzy
+msgid "Welcome to the Introduction tour"
+msgstr "Bienvenue dans Spyder !"
+
+#: spyderlib/tour.py:122
+msgid ""
+"<b>Spyder</b> is a powerful Interactive Development Environment (or IDE) for "
+"the Python programming language.<br><br>Here we are going to guide you "
+"through its most important features.<br><br>Please use the arrow keys or "
+"click on the buttons below to move along the tour."
+msgstr ""
+
+#: spyderlib/tour.py:131
+#, fuzzy
+msgid "The Editor"
+msgstr "Éditeur de texte"
+
+#: spyderlib/tour.py:132
+msgid ""
+"This is the pane where you write Python code before evaluating it. You can "
+"get automatic suggestions and completions while writing, by pressing the "
+"<b>Tab</b> key next to a given text.<br><br>The Editor comes with a line "
+"number area (highlighted here in red), where Spyder shows warnings and "
+"syntax errors. They can help you to detect potential problems before running "
+"the code.<br><br>You can also set debug breakpoints in the line number area, "
+"by doing a double click next to a non-empty line."
+msgstr ""
+
+#: spyderlib/tour.py:147
+#, fuzzy
+msgid "The IPython console"
+msgstr "Console IPython"
+
+#: spyderlib/tour.py:164
+#, fuzzy
+msgid "The Variable Explorer"
+msgstr "Explorateur de variables"
+
+#: spyderlib/tour.py:165
+msgid ""
+"In this pane you can view and edit the variables generated during the "
+"execution of a program, or those entered directly in one of Spyder consoles."
+"<br><br>As you can see, the Variable Explorer is showing the variables "
+"generated during the last step of this tour. By doing a double-click on any "
+"of them, a new window will be opened, where you can inspect and modify their "
+"contents."
+msgstr ""
+
+#: spyderlib/tour.py:177
+#, fuzzy
+msgid "The Python console"
+msgstr "Console IPython"
+
+#: spyderlib/tour.py:178
+msgid ""
+"You can also run your code on a Python console. These consoles are useful "
+"because they let you run a file in a console dedicated only to it.To select "
+"this behavior, please press the <b>F6</b> key.<br><br>By pressing the button "
+"below and then focusing the Variable Explorer, you will notice that Python "
+"consoles are also connected to that pane, and that the Variable Explorer "
+"only shows the variables of the currently focused console."
+msgstr ""
+
+#: spyderlib/tour.py:192
+#, fuzzy
+msgid "The Object Inspector"
+msgstr "Inspecteur d'objets"
+
+#: spyderlib/tour.py:193
+msgid ""
+"This pane displays documentation of the functions, classes, methods or "
+"modules you are currently using in the Editor or the Consoles.<br><br>To use "
+"it, you need to press <b>Ctrl+I</b> in front of an object. If that object "
+"has some documentation associated with it, it will be displayed here."
+msgstr ""
+
+#: spyderlib/tour.py:203
+#, fuzzy
+msgid "The File Explorer"
+msgstr "Explorateur de fichiers"
+
+#: spyderlib/tour.py:204
+msgid ""
+"This pane lets you navigate through the directories and files present in "
+"your computer.<br><br>You can also open any of these files with its "
+"corresponding application, by doing a double click on it.<br><br>There is "
+"one exception to this rule: plain-text files will always be opened in the "
+"Spyder Editor."
+msgstr ""
+
+#: spyderlib/tour.py:214
+#, fuzzy
+msgid "The History Log"
+msgstr "Historique"
+
+#: spyderlib/tour.py:215
+msgid ""
+"This pane records all commands introduced in the Python and IPython consoles."
+msgstr ""
+
+#: spyderlib/tour.py:263
+msgid "<b>Spyder</b> is an interactive development environment based on bla"
+msgstr ""
+
+#: spyderlib/tour.py:267
+#, fuzzy
+msgid "Welcome to Spyder introduction tour"
+msgstr "Bienvenue dans Spyder !"
+
+#: spyderlib/tour.py:268
+msgid "Spyder is an interactive development environment based on bla"
+msgstr ""
+
+#: spyderlib/tour.py:273
+#, fuzzy
+msgid "Introduction tour"
+msgstr "Introspection"
+
+#: spyderlib/tour.py:274
+msgid "New features in version 3.0"
+msgstr ""
+
+#: spyderlib/tour.py:821
+#, fuzzy
+msgid "Go to step: "
+msgstr "Aller à la ligne :"
+
 #: spyderlib/utils/codeanalysis.py:92
 msgid "Real-time code analysis on the Editor"
 msgstr "Analyse de code temps réel dans l'éditeur"
@@ -3080,7 +3426,7 @@ msgstr "Analyse de code temps réel dans l'éditeur"
 msgid "Real-time code style analysis on the Editor"
 msgstr "Analyse de code temps réel dans l'éditeur"
 
-#: spyderlib/utils/environ.py:95
+#: spyderlib/utils/environ.py:96
 msgid ""
 "Module <b>pywin32 was not found</b>.<br>Please restart this Windows "
 "<i>session</i> (not the computer) for changes to take effect."
@@ -3089,7 +3435,7 @@ msgstr ""
 "<i>session</i> en cours (et non l'ordinateur) pour que les changements "
 "effectués prennent effet."
 
-#: spyderlib/utils/environ.py:108
+#: spyderlib/utils/environ.py:109
 msgid ""
 "If you accept changes, this will modify the current user environment "
 "variables directly <b>in Windows registry</b>. Use it with precautions, at "
@@ -3109,8 +3455,8 @@ msgstr ""
 "servie à exécuter Spyder : <i>Python(x,y) Home</i> ou un invite de commandes "
 "par exemple)"
 
-#: spyderlib/utils/inspector/sphinxify.py:209
-#: spyderlib/utils/inspector/sphinxify.py:219
+#: spyderlib/utils/inspector/sphinxify.py:212
+#: spyderlib/utils/inspector/sphinxify.py:222
 msgid ""
 "It was not possible to generate rich text help for this object.</br>Please "
 "see it in plain text."
@@ -3126,59 +3472,59 @@ msgstr "(Expérimental) : autocomplétion, aller à la définition, aide."
 msgid "Editor's code completion, go-to-definition and help"
 msgstr "Editeur : complétion de code, aller à la définition, etc."
 
-#: spyderlib/utils/iofuncs.py:496
+#: spyderlib/utils/iofuncs.py:482
 msgid "Supported files"
 msgstr "Fichiers compatibles"
 
-#: spyderlib/utils/iofuncs.py:498
+#: spyderlib/utils/iofuncs.py:484
 msgid "All files (*.*)"
 msgstr "Tous les fichiers (*.*)"
 
-#: spyderlib/utils/iofuncs.py:508
+#: spyderlib/utils/iofuncs.py:494
 msgid "Spyder data files"
 msgstr "Fichiers Spyder"
 
-#: spyderlib/utils/iofuncs.py:510 spyderlib/widgets/dicteditor.py:1041
+#: spyderlib/utils/iofuncs.py:496 spyderlib/widgets/dicteditor.py:1056
 msgid "NumPy arrays"
 msgstr "Tableaux NumPy"
 
-#: spyderlib/utils/iofuncs.py:511
+#: spyderlib/utils/iofuncs.py:497
 msgid "NumPy zip arrays"
 msgstr "Tableaux NumPy compressés"
 
-#: spyderlib/utils/iofuncs.py:512
+#: spyderlib/utils/iofuncs.py:498
 msgid "Matlab files"
 msgstr "Fichiers Matlab"
 
-#: spyderlib/utils/iofuncs.py:513
+#: spyderlib/utils/iofuncs.py:499
 msgid "CSV text files"
 msgstr "Fichiers texte CSV"
 
-#: spyderlib/utils/iofuncs.py:515
+#: spyderlib/utils/iofuncs.py:501
 msgid "JPEG images"
 msgstr "Images JPEG"
 
-#: spyderlib/utils/iofuncs.py:516
+#: spyderlib/utils/iofuncs.py:502
 msgid "PNG images"
 msgstr "Images PNG"
 
-#: spyderlib/utils/iofuncs.py:517
+#: spyderlib/utils/iofuncs.py:503
 msgid "GIF images"
 msgstr "Images GIF"
 
-#: spyderlib/utils/iofuncs.py:518
+#: spyderlib/utils/iofuncs.py:504
 msgid "TIFF images"
 msgstr "Images TIFF"
 
-#: spyderlib/utils/iofuncs.py:519 spyderlib/utils/iofuncs.py:520
+#: spyderlib/utils/iofuncs.py:505 spyderlib/utils/iofuncs.py:506
 msgid "Pickle files"
 msgstr "Fichiers pickle"
 
-#: spyderlib/utils/iofuncs.py:521
+#: spyderlib/utils/iofuncs.py:507
 msgid "JSON files"
 msgstr "Fichiers JSON"
 
-#: spyderlib/utils/iofuncs.py:540 spyderlib/utils/iofuncs.py:547
+#: spyderlib/utils/iofuncs.py:526 spyderlib/utils/iofuncs.py:533
 msgid "<b>Unsupported file type '%s'</b>"
 msgstr "<b>Type de fichier non pris en charge '%s'</b>"
 
@@ -3186,40 +3532,72 @@ msgstr "<b>Type de fichier non pris en charge '%s'</b>"
 msgid "It was not possible to run this file in an external terminal"
 msgstr "Impossible d'exécuter ce fichier dans un terminal externe"
 
-#: spyderlib/widgets/arrayeditor.py:452 spyderlib/widgets/arrayeditor.py:485
-#: spyderlib/widgets/dataframeeditor.py:507
-#: spyderlib/widgets/dataframeeditor.py:549
+#: spyderlib/widgets/arraybuilder.py:162
+msgid ""
+"\n"
+"           <b>Numpy Array/Matrix Helper</b><br>\n"
+"           Type an array in Matlab    : <code>[1 2;3 4]</code><br>\n"
+"           or Spyder simplified syntax : <code>1 2;3 4</code>\n"
+"           <br><br>\n"
+"           Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n"
+"           <br><br>\n"
+"           <b>Hint:</b><br>\n"
+"           Use two spaces or two tabs to generate a ';'.\n"
+"           "
+msgstr ""
+
+#: spyderlib/widgets/arraybuilder.py:173
+msgid ""
+"\n"
+"           <b>Numpy Array/Matrix Helper</b><br>\n"
+"           Enter an array in the table. <br>\n"
+"           Use Tab to move between cells.\n"
+"           <br><br>\n"
+"           Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n"
+"           <br><br>\n"
+"           <b>Hint:</b><br>\n"
+"           Use two tabs at the end of a row to move to the next row.\n"
+"           "
+msgstr ""
+
+#: spyderlib/widgets/arraybuilder.py:337
+msgid "Array dimensions not valid"
+msgstr ""
+
+#: spyderlib/widgets/arrayeditor.py:453 spyderlib/widgets/arrayeditor.py:486
+#: spyderlib/widgets/dataframeeditor.py:508
+#: spyderlib/widgets/dataframeeditor.py:548
 msgid "Format"
 msgstr "Format"
 
-#: spyderlib/widgets/arrayeditor.py:457
-#: spyderlib/widgets/dataframeeditor.py:511
+#: spyderlib/widgets/arrayeditor.py:458
+#: spyderlib/widgets/dataframeeditor.py:512
 msgid "Resize"
 msgstr "Ajuster"
 
-#: spyderlib/widgets/arrayeditor.py:486
-#: spyderlib/widgets/dataframeeditor.py:550
+#: spyderlib/widgets/arrayeditor.py:487
+#: spyderlib/widgets/dataframeeditor.py:549
 msgid "Float formatting"
 msgstr "Format de flottant"
 
-#: spyderlib/widgets/arrayeditor.py:493
-#: spyderlib/widgets/dataframeeditor.py:558 spyderlib/widgets/explorer.py:578
-#: spyderlib/widgets/explorer.py:681
-#: spyderlib/widgets/externalshell/pythonshell.py:537
-#: spyderlib/widgets/externalshell/systemshell.py:93
+#: spyderlib/widgets/arrayeditor.py:494
+#: spyderlib/widgets/dataframeeditor.py:557 spyderlib/widgets/explorer.py:587
+#: spyderlib/widgets/explorer.py:689
+#: spyderlib/widgets/externalshell/pythonshell.py:553
+#: spyderlib/widgets/externalshell/systemshell.py:99
 msgid "Error"
 msgstr "Erreur"
 
-#: spyderlib/widgets/arrayeditor.py:494
-#: spyderlib/widgets/dataframeeditor.py:559
+#: spyderlib/widgets/arrayeditor.py:495
+#: spyderlib/widgets/dataframeeditor.py:558
 msgid "Format (%s) is incorrect"
 msgstr "Le format (%s) n'est pas valide"
 
-#: spyderlib/widgets/arrayeditor.py:528
+#: spyderlib/widgets/arrayeditor.py:529
 msgid "Array is empty"
 msgstr "Ce tableau est vide"
 
-#: spyderlib/widgets/arrayeditor.py:531
+#: spyderlib/widgets/arrayeditor.py:532
 msgid "Arrays with more than 3 dimensions are not supported"
 msgstr "Les tableaux de plus de trois dimensions ne sont pas pris en charge"
 
@@ -3246,7 +3624,7 @@ msgstr "%s ne sont actuellement pas pris en charge"
 msgid "NumPy array"
 msgstr "Tableaux NumPy"
 
-#: spyderlib/widgets/arrayeditor.py:556 spyderlib/widgets/arrayeditor.py:713
+#: spyderlib/widgets/arrayeditor.py:556 spyderlib/widgets/arrayeditor.py:710
 msgid "Array editor"
 msgstr "Éditeur de tableaux"
 
@@ -3254,35 +3632,35 @@ msgstr "Éditeur de tableaux"
 msgid "read only"
 msgstr "lecture seule"
 
-#: spyderlib/widgets/arrayeditor.py:589
+#: spyderlib/widgets/arrayeditor.py:588
 msgid "Record array fields:"
 msgstr "Champs du tableau : "
 
-#: spyderlib/widgets/arrayeditor.py:601
+#: spyderlib/widgets/arrayeditor.py:600
 msgid "Data"
 msgstr "Données"
 
-#: spyderlib/widgets/arrayeditor.py:601
+#: spyderlib/widgets/arrayeditor.py:600
 msgid "Mask"
 msgstr "Masque"
 
-#: spyderlib/widgets/arrayeditor.py:601
+#: spyderlib/widgets/arrayeditor.py:600
 msgid "Masked data"
 msgstr "Données masquées"
 
-#: spyderlib/widgets/arrayeditor.py:614
+#: spyderlib/widgets/arrayeditor.py:611
 msgid "Axis:"
 msgstr "Axe :"
 
-#: spyderlib/widgets/arrayeditor.py:619
+#: spyderlib/widgets/arrayeditor.py:616
 msgid "Index:"
 msgstr "Indice :"
 
-#: spyderlib/widgets/arrayeditor.py:633
+#: spyderlib/widgets/arrayeditor.py:629
 msgid "<u>Warning</u>: changes are applied separately"
 msgstr "<u>Attention</u>: les changements seront pris en compte séparément"
 
-#: spyderlib/widgets/arrayeditor.py:634
+#: spyderlib/widgets/arrayeditor.py:630
 msgid ""
 "For performance reasons, changes applied to masked array won't be reflected "
 "in array's data (and vice-versa)."
@@ -3291,13 +3669,13 @@ msgstr ""
 "masquées ne seront pas reflétées sur les données du tableau (et "
 "réciproquement)."
 
-#: spyderlib/widgets/browser.py:30
-#: spyderlib/widgets/sourcecode/codeeditor.py:2311
+#: spyderlib/widgets/browser.py:31
+#: spyderlib/widgets/sourcecode/codeeditor.py:2468
 msgid "Zoom out"
 msgstr "Réduire"
 
-#: spyderlib/widgets/browser.py:33
-#: spyderlib/widgets/sourcecode/codeeditor.py:2308
+#: spyderlib/widgets/browser.py:34
+#: spyderlib/widgets/sourcecode/codeeditor.py:2465
 msgid "Zoom in"
 msgstr "Agrandir"
 
@@ -3305,31 +3683,31 @@ msgstr "Agrandir"
 msgid "Home"
 msgstr "Accueil"
 
-#: spyderlib/widgets/browser.py:171
+#: spyderlib/widgets/browser.py:166
 msgid "Find text"
 msgstr "Rechercher"
 
-#: spyderlib/widgets/browser.py:190
+#: spyderlib/widgets/browser.py:184
 msgid "Address:"
 msgstr "Adresse :"
 
-#: spyderlib/widgets/browser.py:225
+#: spyderlib/widgets/browser.py:220
 msgid "Unable to load page"
 msgstr "Impossible de charger la page"
 
-#: spyderlib/widgets/comboboxes.py:117
+#: spyderlib/widgets/comboboxes.py:118
 msgid "Press enter to validate this entry"
 msgstr "Appuyer sur Entrée pour valider cette saisie"
 
-#: spyderlib/widgets/comboboxes.py:118
+#: spyderlib/widgets/comboboxes.py:119
 msgid "This entry is incorrect"
 msgstr "Cette saisie n'est pas correcte"
 
-#: spyderlib/widgets/comboboxes.py:171
+#: spyderlib/widgets/comboboxes.py:174
 msgid "Press enter to validate this path"
 msgstr "Appuyez sur Entrée pour valider ce chemin d'accès"
 
-#: spyderlib/widgets/comboboxes.py:172
+#: spyderlib/widgets/comboboxes.py:175
 msgid ""
 "This path is incorrect.\n"
 "Enter a correct directory path,\n"
@@ -3359,7 +3737,7 @@ msgstr "Entier"
 msgid "To str"
 msgstr "Caractères"
 
-#: spyderlib/widgets/dataframeeditor.py:489
+#: spyderlib/widgets/dataframeeditor.py:490
 msgid "%s editor"
 msgstr "Éditeur de %s"
 
@@ -3367,27 +3745,27 @@ msgstr "Éditeur de %s"
 msgid "Column min/max"
 msgstr "Colonne min/max"
 
-#: spyderlib/widgets/dependencies.py:60
+#: spyderlib/widgets/dependencies.py:59
 msgid " Required "
 msgstr "  Requis  "
 
-#: spyderlib/widgets/dependencies.py:60
+#: spyderlib/widgets/dependencies.py:59
 msgid "Module"
 msgstr "Module"
 
-#: spyderlib/widgets/dependencies.py:61
+#: spyderlib/widgets/dependencies.py:60
 msgid " Installed "
 msgstr "  Installé  "
 
-#: spyderlib/widgets/dependencies.py:61
+#: spyderlib/widgets/dependencies.py:60
 msgid "Provided features"
 msgstr "Fonctionnalités associées"
 
-#: spyderlib/widgets/dependencies.py:127
+#: spyderlib/widgets/dependencies.py:130
 msgid "Optional Dependencies"
 msgstr "Dépendances optionnelles"
 
-#: spyderlib/widgets/dependencies.py:134
+#: spyderlib/widgets/dependencies.py:137
 msgid ""
 "Spyder depends on several Python modules to provide additional functionality "
 "for its plugins. The table below shows the required and installed versions "
@@ -3402,7 +3780,7 @@ msgstr ""
 "ces modules, il est néanmoins fortement recommandé d'installer au minimum <b>"
 "%s</b> et <b>%s</b> afin de bénéficier des fonctionnalités les plus avancées."
 
-#: spyderlib/widgets/dependencies.py:149
+#: spyderlib/widgets/dependencies.py:152
 msgid "Copy to clipboard"
 msgstr "Copier dans le presse-papier"
 
@@ -3422,6 +3800,10 @@ msgstr "Liste"
 msgid "Dictionary"
 msgstr "Dictionnaire"
 
+#: spyderlib/widgets/dicteditor.py:169
+msgid "Key"
+msgstr "Clé"
+
 #: spyderlib/widgets/dicteditor.py:175
 msgid "Attribute"
 msgstr "Attribut"
@@ -3430,19 +3812,19 @@ msgstr "Attribut"
 msgid "elements"
 msgstr "éléments"
 
-#: spyderlib/widgets/dicteditor.py:355
+#: spyderlib/widgets/dicteditor.py:356
 msgid "Size"
 msgstr "Taille"
 
-#: spyderlib/widgets/dicteditor.py:355
+#: spyderlib/widgets/dicteditor.py:356
 msgid "Type"
 msgstr "Type"
 
-#: spyderlib/widgets/dicteditor.py:355
+#: spyderlib/widgets/dicteditor.py:356
 msgid "Value"
 msgstr "Valeur"
 
-#: spyderlib/widgets/dicteditor.py:450
+#: spyderlib/widgets/dicteditor.py:453
 msgid ""
 "Opening this variable can be slow\n"
 "\n"
@@ -3452,204 +3834,180 @@ msgstr ""
 "\n"
 "Souhaitez-vous néanmoins continuer ?"
 
-#: spyderlib/widgets/dicteditor.py:458 spyderlib/widgets/dicteditor.py:607
+#: spyderlib/widgets/dicteditor.py:461 spyderlib/widgets/dicteditor.py:612
 msgid "Edit item"
 msgstr "Modifier"
 
-#: spyderlib/widgets/dicteditor.py:459
+#: spyderlib/widgets/dicteditor.py:462
 msgid "<b>Unable to retrieve data.</b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>Impossible d'accéder aux données</b><br><br>Message d'erreur :<br>%s"
 
-#: spyderlib/widgets/dicteditor.py:608
+#: spyderlib/widgets/dicteditor.py:613
 msgid "<b>Unable to assign data to item.</b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>Impossible d'assigner la valeur de l'objet.</b><br><br>Message d'erreur :"
 "<br>%s"
 
-#: spyderlib/widgets/dicteditor.py:669
+#: spyderlib/widgets/dicteditor.py:675
 msgid "Resize rows to contents"
 msgstr "Ajuster la hauteur des lignes"
 
-#: spyderlib/widgets/dicteditor.py:677 spyderlib/widgets/explorer.py:236
+#: spyderlib/widgets/dicteditor.py:683 spyderlib/widgets/explorer.py:242
 msgid "Edit"
 msgstr "Modifier"
 
-#: spyderlib/widgets/dicteditor.py:680 spyderlib/widgets/dicteditor.py:1012
-#: spyderlib/widgets/dicteditor.py:1028
+#: spyderlib/widgets/dicteditor.py:686 spyderlib/widgets/dicteditor.py:1025
+#: spyderlib/widgets/dicteditor.py:1042
 msgid "Plot"
 msgstr "Tracer"
 
-#: spyderlib/widgets/dicteditor.py:684
+#: spyderlib/widgets/dicteditor.py:690
 msgid "Histogram"
 msgstr "Histogramme"
 
-#: spyderlib/widgets/dicteditor.py:688
+#: spyderlib/widgets/dicteditor.py:694
 msgid "Show image"
 msgstr "Afficher l'image"
 
-#: spyderlib/widgets/dicteditor.py:692 spyderlib/widgets/dicteditor.py:1035
+#: spyderlib/widgets/dicteditor.py:698 spyderlib/widgets/dicteditor.py:1050
 msgid "Save array"
 msgstr "Enregistrer le tableau"
 
-#: spyderlib/widgets/dicteditor.py:696 spyderlib/widgets/dicteditor.py:976
-#: spyderlib/widgets/dicteditor.py:984
+#: spyderlib/widgets/dicteditor.py:702 spyderlib/widgets/dicteditor.py:989
+#: spyderlib/widgets/dicteditor.py:997
 msgid "Insert"
 msgstr "Insérer"
 
-#: spyderlib/widgets/dicteditor.py:699 spyderlib/widgets/dicteditor.py:929
+#: spyderlib/widgets/dicteditor.py:705 spyderlib/widgets/dicteditor.py:939
 msgid "Remove"
 msgstr "Supprimer"
 
-#: spyderlib/widgets/dicteditor.py:710 spyderlib/widgets/dicteditor.py:946
-#: spyderlib/widgets/explorer.py:524 spyderlib/widgets/explorer.py:532
-#: spyderlib/widgets/explorer.py:544
+#: spyderlib/widgets/dicteditor.py:716 spyderlib/widgets/dicteditor.py:956
+#: spyderlib/widgets/explorer.py:532 spyderlib/widgets/explorer.py:540
+#: spyderlib/widgets/explorer.py:551
 msgid "Rename"
 msgstr "Renommer"
 
-#: spyderlib/widgets/dicteditor.py:713
+#: spyderlib/widgets/dicteditor.py:719
 msgid "Duplicate"
 msgstr "Dupliquer"
 
-#: spyderlib/widgets/dicteditor.py:927
+#: spyderlib/widgets/dicteditor.py:937
 msgid "Do you want to remove selected item?"
 msgstr "Souhaitez-vous supprimer l'élément sélectionné ?"
 
-#: spyderlib/widgets/dicteditor.py:928
+#: spyderlib/widgets/dicteditor.py:938
 msgid "Do you want to remove all selected items?"
 msgstr "Souhaitez-vous supprimer les éléments sélectionnés ?"
 
-#: spyderlib/widgets/dicteditor.py:946 spyderlib/widgets/dicteditor.py:976
+#: spyderlib/widgets/dicteditor.py:956 spyderlib/widgets/dicteditor.py:989
 msgid "Key:"
 msgstr "Clé :"
 
-#: spyderlib/widgets/dicteditor.py:984
+#: spyderlib/widgets/dicteditor.py:997
 msgid "Value:"
 msgstr "Valeur :"
 
-#: spyderlib/widgets/dicteditor.py:1000
+#: spyderlib/widgets/dicteditor.py:1013
 msgid "Import error"
 msgstr "Erreur d'import"
 
-#: spyderlib/widgets/dicteditor.py:1001
+#: spyderlib/widgets/dicteditor.py:1014
 msgid "Please install <b>matplotlib</b> or <b>guiqwt</b>."
 msgstr "Merci d'installer <b>matplotlib</b> ou <b>guiqwt</b>."
 
-#: spyderlib/widgets/dicteditor.py:1013
+#: spyderlib/widgets/dicteditor.py:1026
 msgid "<b>Unable to plot data.</b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>Impossible d'afficher les données</b><br><br>Message d'erreur :<br>%s"
 
-#: spyderlib/widgets/dicteditor.py:1029
+#: spyderlib/widgets/dicteditor.py:1043
 msgid "<b>Unable to show image.</b><br><br>Error message:<br>%s"
 msgstr "<b>Impossible d'afficher l'image</b><br><br>Message d'erreur :<br>%s"
 
-#: spyderlib/widgets/dicteditor.py:1051
+#: spyderlib/widgets/dicteditor.py:1066
 msgid "<b>Unable to save array</b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>Impossible d'enregistrer le tableau</b><br><br>Message d'erreur :<br>%s"
 
-#: spyderlib/widgets/dicteditor.py:1068
+#: spyderlib/widgets/dicteditor.py:1085
 msgid "Clipboard contents"
 msgstr "Contenu du presse-papiers"
 
-#: spyderlib/widgets/dicteditor.py:1082
+#: spyderlib/widgets/dicteditor.py:1100
 msgid "Import from clipboard"
 msgstr "Importer depuis le presse-papiers"
 
-#: spyderlib/widgets/dicteditor.py:1084
+#: spyderlib/widgets/dicteditor.py:1102
 msgid "Empty clipboard"
 msgstr "Presse-papiers vide"
 
-#: spyderlib/widgets/dicteditor.py:1085
+#: spyderlib/widgets/dicteditor.py:1103
 msgid "Nothing to be imported from clipboard."
 msgstr "Aucune donnée ne peut être importée depuis le presse-papiers."
 
-#: spyderlib/widgets/dicteditorutils.py:59
+#: spyderlib/widgets/dicteditorutils.py:60
 msgid "View and edit DataFrames and Series in the Variable Explorer"
 msgstr ""
 "Voir et éditer les Dataframes et les Series dans l'explorateur de variables"
 
-#: spyderlib/widgets/editor.py:67 spyderlib/widgets/editor.py:417
-msgid "File list management"
-msgstr "Gestionnaire de fichiers"
-
-#: spyderlib/widgets/editor.py:71
-msgid "Filter:"
-msgstr "Filtre :"
-
-#: spyderlib/widgets/editor.py:76
-msgid "(press <b>Enter</b> to edit file)"
-msgstr "(appuyer sur <b>Entrée</b> pour modifier le fichier)"
-
-#: spyderlib/widgets/editor.py:91
-msgid "&Edit file"
-msgstr "Modifi&er le fichier"
-
-#: spyderlib/widgets/editor.py:100
-msgid "&Close file"
-msgstr "&Fermer le fichier"
-
-#: spyderlib/widgets/editor.py:108
-msgid "Hint: press <b>Alt</b> to show accelerators"
-msgstr "Astuce : la touche <b>Alt</b> affiche les accélérateurs"
-
-#: spyderlib/widgets/editor.py:420
+#: spyderlib/widgets/editor.py:342
 msgid "Copy path to clipboard"
 msgstr "Copier le chemin d'accès dans le presse-papier"
 
-#: spyderlib/widgets/editor.py:990
+#: spyderlib/widgets/editor.py:906
 msgid "Temporary file"
 msgstr "Fichier temporaire"
 
-#: spyderlib/widgets/editor.py:1087
+#: spyderlib/widgets/editor.py:1003
 msgid "New window"
 msgstr "Nouvelle fenêtre"
 
-#: spyderlib/widgets/editor.py:1088
+#: spyderlib/widgets/editor.py:1004
 msgid "Create a new editor window"
 msgstr "Créer une nouvelle fenêtre d'édition"
 
-#: spyderlib/widgets/editor.py:1091
+#: spyderlib/widgets/editor.py:1007
 msgid "Split vertically"
 msgstr "Séparation verticale"
 
-#: spyderlib/widgets/editor.py:1093
+#: spyderlib/widgets/editor.py:1009
 msgid "Split vertically this editor window"
 msgstr "Séparer en deux verticalement cette fenêtre d'édition"
 
-#: spyderlib/widgets/editor.py:1095
+#: spyderlib/widgets/editor.py:1011
 msgid "Split horizontally"
 msgstr "Séparation horizontale"
 
-#: spyderlib/widgets/editor.py:1097
+#: spyderlib/widgets/editor.py:1013
 msgid "Split horizontally this editor window"
 msgstr "Séparer en deux horizontalement cette fenêtre d'édition"
 
-#: spyderlib/widgets/editor.py:1099
+#: spyderlib/widgets/editor.py:1015
 msgid "Close this panel"
 msgstr "Fermer ce panneau"
 
-#: spyderlib/widgets/editor.py:1237
+#: spyderlib/widgets/editor.py:1153
 msgid "<b>%s</b> has been modified.<br>Do you want to save changes?"
 msgstr ""
 "<b>%s</b> a été modifié.<br>Souhaitez-vous enregistrer ces changements ?"
 
-#: spyderlib/widgets/editor.py:1300
+#: spyderlib/widgets/editor.py:1215
 msgid "Save"
 msgstr "Enregistrer"
 
-#: spyderlib/widgets/editor.py:1301
+#: spyderlib/widgets/editor.py:1216
 msgid "<b>Unable to save script '%s'</b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>Impossible d'enregistrer le script '%s'</b><br><br>Message d'erreur :<br>"
 "%s"
 
-#: spyderlib/widgets/editor.py:1323
+#: spyderlib/widgets/editor.py:1238
 msgid "Save Python script"
 msgstr "Enregistrer le script Python"
 
-#: spyderlib/widgets/editor.py:1539
+#: spyderlib/widgets/editor.py:1452
 msgid ""
 "<b>%s</b> is unavailable (this file may have been removed, moved or renamed "
 "outside Spyder).<br>Do you want to close it?"
@@ -3657,7 +4015,7 @@ msgstr ""
 "<b>%s</b> n'est pas accessible (ce fichier a peut-être été supprimé, déplacé "
 "ou renommé en dehors de Spyder).<br>Souhaitez-vous le fermer ?"
 
-#: spyderlib/widgets/editor.py:1559
+#: spyderlib/widgets/editor.py:1472
 msgid ""
 "<b>%s</b> has been modified outside Spyder.<br>Do you want to reload it and "
 "lose all your changes?"
@@ -3665,7 +4023,7 @@ msgstr ""
 "<b>%s</b> a été modifié en dehors de Spyder.<br>Souhaitez-vous le recharger "
 "et perdre ainsi vos modifications ?"
 
-#: spyderlib/widgets/editor.py:1655
+#: spyderlib/widgets/editor.py:1568
 msgid ""
 "All changes to <b>%s</b> will be lost.<br>Do you want to revert file from "
 "disk?"
@@ -3674,11 +4032,11 @@ msgstr ""
 "<br>Souhaitez-vous revenir à la version du fichier enregistrée sur le "
 "disque ?"
 
-#: spyderlib/widgets/editor.py:1811
+#: spyderlib/widgets/editor.py:1708
 msgid "Loading %s..."
 msgstr "Chargement de \"%s\" en cours..."
 
-#: spyderlib/widgets/editor.py:1821
+#: spyderlib/widgets/editor.py:1718
 msgid ""
 "<b>%s</b> contains mixed end-of-line characters.<br>Spyder will fix this "
 "automatically."
@@ -3686,154 +4044,154 @@ msgstr ""
 "<b>%s</b> contient des caractères de fin de ligne mélangés.<br>Spyder va "
 "corriger ceci automatiquement."
 
-#: spyderlib/widgets/editor.py:2192
+#: spyderlib/widgets/editor.py:2083
 msgid "Close window"
 msgstr "Fermer la fenêtre"
 
-#: spyderlib/widgets/editor.py:2194
+#: spyderlib/widgets/editor.py:2085
 msgid "Close this window"
 msgstr "Fermer cette fenêtre d'édition"
 
-#: spyderlib/widgets/editortools.py:93 spyderlib/widgets/editortools.py:129
+#: spyderlib/widgets/editortools.py:94 spyderlib/widgets/editortools.py:130
 msgid "Line %s"
 msgstr "Ligne %s"
 
-#: spyderlib/widgets/editortools.py:98
+#: spyderlib/widgets/editortools.py:99
 msgid "Class defined at line %s"
 msgstr "Classe déclarée ligne %s"
 
-#: spyderlib/widgets/editortools.py:106
+#: spyderlib/widgets/editortools.py:107
 msgid "Method defined at line %s"
 msgstr "Méthode déclarée ligne %s"
 
-#: spyderlib/widgets/editortools.py:116
+#: spyderlib/widgets/editortools.py:117
 msgid "Function defined at line %s"
 msgstr "Fonction déclarée ligne %s"
 
-#: spyderlib/widgets/editortools.py:148
+#: spyderlib/widgets/editortools.py:149
 msgid "Cell starts at line %s"
 msgstr "Cellule commençant ligne %s"
 
-#: spyderlib/widgets/editortools.py:201 spyderlib/widgets/editortools.py:536
+#: spyderlib/widgets/editortools.py:202 spyderlib/widgets/editortools.py:539
 msgid "Go to cursor position"
 msgstr "Aller à la position du curseur"
 
-#: spyderlib/widgets/editortools.py:204
+#: spyderlib/widgets/editortools.py:205
 msgid "Show absolute path"
 msgstr "Afficher les chemins complets"
 
-#: spyderlib/widgets/editortools.py:207 spyderlib/widgets/explorer.py:177
+#: spyderlib/widgets/editortools.py:208 spyderlib/widgets/explorer.py:179
 msgid "Show all files"
 msgstr "Afficher tous les fichiers"
 
-#: spyderlib/widgets/editortools.py:210
+#: spyderlib/widgets/editortools.py:211
 msgid "Show special comments"
 msgstr "Afficher les commentaires spéciaux"
 
-#: spyderlib/widgets/explorer.py:173
+#: spyderlib/widgets/explorer.py:175
 msgid "Edit filename filters..."
 msgstr "Modifier les filtres..."
 
-#: spyderlib/widgets/explorer.py:186
+#: spyderlib/widgets/explorer.py:189
 msgid "Edit filename filters"
 msgstr "Modifier les filtres"
 
-#: spyderlib/widgets/explorer.py:187
+#: spyderlib/widgets/explorer.py:190
 msgid "Name filters:"
 msgstr "Filtres sur les noms de fichiers :"
 
-#: spyderlib/widgets/explorer.py:205
+#: spyderlib/widgets/explorer.py:209
 msgid "File..."
 msgstr "Fichier..."
 
-#: spyderlib/widgets/explorer.py:208
+#: spyderlib/widgets/explorer.py:213
 msgid "Module..."
 msgstr "Module..."
 
-#: spyderlib/widgets/explorer.py:211
+#: spyderlib/widgets/explorer.py:217
 msgid "Folder..."
 msgstr "Dossier..."
 
-#: spyderlib/widgets/explorer.py:215
+#: spyderlib/widgets/explorer.py:221
 msgid "Package..."
 msgstr "Paquet..."
 
-#: spyderlib/widgets/explorer.py:238
+#: spyderlib/widgets/explorer.py:244
 msgid "Move..."
 msgstr "Déplacer..."
 
-#: spyderlib/widgets/explorer.py:241
+#: spyderlib/widgets/explorer.py:247
 msgid "Delete..."
 msgstr "Supprimer..."
 
-#: spyderlib/widgets/explorer.py:244
+#: spyderlib/widgets/explorer.py:250
 msgid "Rename..."
 msgstr "Renommer..."
 
-#: spyderlib/widgets/explorer.py:247
+#: spyderlib/widgets/explorer.py:253
 msgid "Open"
 msgstr "Ouvrir"
 
-#: spyderlib/widgets/explorer.py:248
-#: spyderlib/widgets/sourcecode/codeeditor.py:2299
+#: spyderlib/widgets/explorer.py:254
+#: spyderlib/widgets/sourcecode/codeeditor.py:2456
 msgid "Convert to Python script"
 msgstr "Convertir en fichier Python"
 
-#: spyderlib/widgets/explorer.py:271
+#: spyderlib/widgets/explorer.py:277
 msgid "Commit"
 msgstr "Commiter"
 
-#: spyderlib/widgets/explorer.py:275
+#: spyderlib/widgets/explorer.py:281
 msgid "Browse repository"
 msgstr "Explorer le dépôt"
 
-#: spyderlib/widgets/explorer.py:287
+#: spyderlib/widgets/explorer.py:293
 msgid "Open command prompt here"
 msgstr "Ouvrir un invite de commandes ici"
 
-#: spyderlib/widgets/explorer.py:289
+#: spyderlib/widgets/explorer.py:295
 msgid "Open terminal here"
 msgstr "Ouvrir un terminal ici"
 
-#: spyderlib/widgets/explorer.py:294
+#: spyderlib/widgets/explorer.py:300
 msgid "Open Python console here"
 msgstr "Ouvrir une console &Python ici"
 
-#: spyderlib/widgets/explorer.py:308
+#: spyderlib/widgets/explorer.py:314
 msgid "New"
 msgstr "Nouveau"
 
-#: spyderlib/widgets/explorer.py:316
+#: spyderlib/widgets/explorer.py:322
 msgid "Import"
 msgstr "Import"
 
-#: spyderlib/widgets/explorer.py:462
+#: spyderlib/widgets/explorer.py:471
 msgid "Do you really want to delete <b>%s</b>?"
 msgstr "Souhaitez-vous réellement supprimer <b>%s</b> ?"
 
-#: spyderlib/widgets/explorer.py:482
+#: spyderlib/widgets/explorer.py:489
 msgid "delete"
 msgstr "supprimer"
 
-#: spyderlib/widgets/explorer.py:483 spyderlib/widgets/projectexplorer.py:815
-#: spyderlib/widgets/projectexplorer.py:822
-#: spyderlib/widgets/projectexplorer.py:1089
-#: spyderlib/widgets/projectexplorer.py:1173
+#: spyderlib/widgets/explorer.py:490 spyderlib/widgets/projectexplorer.py:823
+#: spyderlib/widgets/projectexplorer.py:830
+#: spyderlib/widgets/projectexplorer.py:1101
+#: spyderlib/widgets/projectexplorer.py:1186
 msgid "Project Explorer"
 msgstr "Explorateur de projets"
 
-#: spyderlib/widgets/explorer.py:484 spyderlib/widgets/projectexplorer.py:762
-#: spyderlib/widgets/projectexplorer.py:1174
+#: spyderlib/widgets/explorer.py:491 spyderlib/widgets/projectexplorer.py:770
+#: spyderlib/widgets/projectexplorer.py:1187
 msgid "<b>Unable to %s <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr "<b>Impossible de %s <i>%s</i></b><br><br>Message d'erreur :<br>%s"
 
-#: spyderlib/widgets/explorer.py:506
-#: spyderlib/widgets/sourcecode/codeeditor.py:1906
+#: spyderlib/widgets/explorer.py:514
+#: spyderlib/widgets/sourcecode/codeeditor.py:1987
 msgid "Conversion error"
 msgstr "Erreur de conversion"
 
-#: spyderlib/widgets/explorer.py:507
-#: spyderlib/widgets/sourcecode/codeeditor.py:1907
+#: spyderlib/widgets/explorer.py:515
+#: spyderlib/widgets/sourcecode/codeeditor.py:1988
 msgid ""
 "It was not possible to convert this notebook. The error is:\n"
 "\n"
@@ -3841,11 +4199,11 @@ msgstr ""
 "Impossible de convertir ce notebook. Message d'erreur:\n"
 "\n"
 
-#: spyderlib/widgets/explorer.py:525
+#: spyderlib/widgets/explorer.py:533
 msgid "New name:"
 msgstr "Nouveau nom :"
 
-#: spyderlib/widgets/explorer.py:533
+#: spyderlib/widgets/explorer.py:541
 msgid ""
 "Do you really want to rename <b>%s</b> and overwrite the existing file <b>"
 "%s</b>?"
@@ -3853,139 +4211,143 @@ msgstr ""
 "Souhaitez-vous réellement renommer <b>%s</b> et remplacer le ficher existant "
 "<b>%s</b> ?"
 
-#: spyderlib/widgets/explorer.py:545
+#: spyderlib/widgets/explorer.py:552
 msgid "<b>Unable to rename file <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>Impossible de renommer l'élément <i>%s</i></b><br><br>Message d'erreur :"
 "<br>%s"
 
-#: spyderlib/widgets/explorer.py:579
+#: spyderlib/widgets/explorer.py:588
 msgid "<b>Unable to move <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>Impossible de déplacer <i>%s</i></b><br><br>Message d'erreur :<br>%s"
 
-#: spyderlib/widgets/explorer.py:597
+#: spyderlib/widgets/explorer.py:606
 msgid "<b>Unable to create folder <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>Impossible de créer le répertoire <i>%s</i></b><br><br>Message d'erreur :"
 "<br>%s"
 
-#: spyderlib/widgets/explorer.py:610 spyderlib/widgets/explorer.py:644
+#: spyderlib/widgets/explorer.py:619 spyderlib/widgets/explorer.py:653
 msgid "<b>Unable to create file <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>Impossible de créer le fichier <i>%s</i></b><br><br>Message d'erreur :<br>"
 "%s"
 
-#: spyderlib/widgets/explorer.py:618
+#: spyderlib/widgets/explorer.py:627
 msgid "New folder"
 msgstr "Nouveau répertoire"
 
-#: spyderlib/widgets/explorer.py:619
+#: spyderlib/widgets/explorer.py:628
 msgid "Folder name:"
 msgstr "Nom du dossier :"
 
-#: spyderlib/widgets/explorer.py:624
+#: spyderlib/widgets/explorer.py:633
 msgid "New package"
 msgstr "Nouveau paquet"
 
-#: spyderlib/widgets/explorer.py:625
+#: spyderlib/widgets/explorer.py:634
 msgid "Package name:"
 msgstr "Nom du paquet :"
 
-#: spyderlib/widgets/explorer.py:665
+#: spyderlib/widgets/explorer.py:674
 msgid "New module"
 msgstr "Nouveau module"
 
-#: spyderlib/widgets/explorer.py:678
+#: spyderlib/widgets/explorer.py:686
 msgid ""
 "For %s support, please install one of the<br/> following tools:<br/><br/>  %s"
 msgstr ""
 "Pour ajouter la prise en charge de %s, merci d'installer <br/>l'un des "
 "outils suivants :<br/><br/>  %s"
 
-#: spyderlib/widgets/explorer.py:682
+#: spyderlib/widgets/explorer.py:690
 msgid "<b>Unable to find external program.</b><br><br>%s"
 msgstr "<b>Impossible de trouver un programme externe.</b><br><br>%s"
 
-#: spyderlib/widgets/explorer.py:882
+#: spyderlib/widgets/explorer.py:893
 msgid "Show current directory only"
 msgstr "Afficher uniquement le répertoire courant"
 
-#: spyderlib/widgets/explorer.py:996 spyderlib/widgets/importwizard.py:518
+#: spyderlib/widgets/explorer.py:989
+msgid "You don't have the right permissions to open this directory"
+msgstr ""
+
+#: spyderlib/widgets/explorer.py:1018 spyderlib/widgets/importwizard.py:525
 msgid "Previous"
 msgstr "Précédent"
 
-#: spyderlib/widgets/explorer.py:1012
+#: spyderlib/widgets/explorer.py:1024
 msgid "Parent"
 msgstr "Parent"
 
-#: spyderlib/widgets/externalshell/baseshell.py:140
+#: spyderlib/widgets/externalshell/baseshell.py:142
 msgid "Run again this program"
 msgstr "Exécuter de nouveau ce programme"
 
-#: spyderlib/widgets/externalshell/baseshell.py:143
+#: spyderlib/widgets/externalshell/baseshell.py:145
 msgid "Kill"
 msgstr "Terminer"
 
-#: spyderlib/widgets/externalshell/baseshell.py:145
+#: spyderlib/widgets/externalshell/baseshell.py:147
 msgid "Kills the current process, causing it to exit immediately"
 msgstr ""
 "Tue le processus, entraînant une sortie brutale et immédiate du programme"
 
-#: spyderlib/widgets/externalshell/baseshell.py:213
+#: spyderlib/widgets/externalshell/baseshell.py:219
 msgid "<span style='color: #44AA44'><b>Running...</b></span>"
 msgstr "<span style='color: #44AA44'><b>En cours d'exécution...</b></span>"
 
-#: spyderlib/widgets/externalshell/baseshell.py:220
+#: spyderlib/widgets/externalshell/baseshell.py:226
 msgid "Terminated."
 msgstr "Terminé."
 
-#: spyderlib/widgets/externalshell/baseshell.py:242
-#: spyderlib/widgets/ipython.py:342 spyderlib/widgets/ipython.py:359
-#: spyderlib/widgets/mixins.py:608
+#: spyderlib/widgets/externalshell/baseshell.py:251
+#: spyderlib/widgets/ipython.py:351 spyderlib/widgets/ipython.py:368
+#: spyderlib/widgets/mixins.py:656
 msgid "Arguments"
 msgstr "Arguments"
 
-#: spyderlib/widgets/externalshell/baseshell.py:243
+#: spyderlib/widgets/externalshell/baseshell.py:252
 msgid "Command line arguments:"
 msgstr "Arguments en ligne de commande :"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:173
+#: spyderlib/widgets/externalshell/namespacebrowser.py:191
 msgid "Refresh"
 msgstr "Rafraîchir"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:177
+#: spyderlib/widgets/externalshell/namespacebrowser.py:195
 msgid "Refresh periodically"
 msgstr "Rafraîchir périodiquement"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:181
-#: spyderlib/widgets/externalshell/namespacebrowser.py:446
+#: spyderlib/widgets/externalshell/namespacebrowser.py:199
+#: spyderlib/widgets/externalshell/namespacebrowser.py:453
 msgid "Import data"
 msgstr "Importer des données"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:184
-#: spyderlib/widgets/externalshell/namespacebrowser.py:536
-#: spyderlib/widgets/externalshell/namespacebrowser.py:557
+#: spyderlib/widgets/externalshell/namespacebrowser.py:202
+#: spyderlib/widgets/externalshell/namespacebrowser.py:541
+#: spyderlib/widgets/externalshell/namespacebrowser.py:562
 msgid "Save data"
 msgstr "Enregistrer les données"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:189
+#: spyderlib/widgets/externalshell/namespacebrowser.py:207
 msgid "Save data as..."
 msgstr "Enregistrer les données sous..."
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:197
+#: spyderlib/widgets/externalshell/namespacebrowser.py:215
 msgid "Exclude references which name starts with an underscore"
 msgstr "Exclure les références dont le nom commence par un tiret bas"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:205
+#: spyderlib/widgets/externalshell/namespacebrowser.py:223
 msgid "Exclude references which name is uppercase"
 msgstr "Exclure les références dont le nom s'écrit en lettres capitales"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:212
+#: spyderlib/widgets/externalshell/namespacebrowser.py:230
 msgid "Exclude references which name starts with an uppercase character"
 msgstr "Exclure les références dont le nom commence par une lettre majuscule"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:220
+#: spyderlib/widgets/externalshell/namespacebrowser.py:238
 msgid ""
 "Exclude references to unsupported data types (i.e. which won't be handled/"
 "saved correctly)"
@@ -3993,13 +4355,13 @@ msgstr ""
 "Exclure les références dont le type n'est pas supporté par l'espace de "
 "travail (en particulier, l'enregistrement ne fonctionnera pas)"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:342
+#: spyderlib/widgets/externalshell/namespacebrowser.py:347
 msgid "Object <b>%s</b> is not picklable"
 msgstr ""
 "L'objet <b>%s</b> n'est pas pris en charge par le protocole de sérialisation "
 "de <i>Pickle</i>"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:468
+#: spyderlib/widgets/externalshell/namespacebrowser.py:473
 msgid ""
 "<b>Unsupported file extension '%s'</b><br><br>Would you like to import it "
 "anyway (by selecting a known file format)?"
@@ -4007,33 +4369,33 @@ msgstr ""
 "<b>Extension de fichier non pris en charge '%s'</b><br><br>Souhaitez-vous "
 "néanmoins ouvrir ce fichier (en choisissant un format de fichier connu) ?"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:476
+#: spyderlib/widgets/externalshell/namespacebrowser.py:481
 msgid "Open file as:"
 msgstr "Ouvrir le fichier en tant que :"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:524
+#: spyderlib/widgets/externalshell/namespacebrowser.py:529
 msgid "<b>Unable to load '%s'</b><br><br>Error message:<br>%s"
 msgstr "<b>Impossible d'ouvrir '%s'</b><br><br>Message d'erreur :<br>%s"
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:558
+#: spyderlib/widgets/externalshell/namespacebrowser.py:563
 msgid "<b>Unable to save current workspace</b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>Impossible d'enregistrer l'espace de travail</b><br><br>Message d'erreur :"
 "<br>%s"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:269
+#: spyderlib/widgets/externalshell/pythonshell.py:284
 msgid "Variables"
 msgstr "Variables"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:270
+#: spyderlib/widgets/externalshell/pythonshell.py:285
 msgid "Show/hide global variables explorer"
 msgstr "Afficher/masquer l'explorateur de variables globales"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:274
+#: spyderlib/widgets/externalshell/pythonshell.py:289
 msgid "Terminate"
 msgstr "Quitter"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:275
+#: spyderlib/widgets/externalshell/pythonshell.py:290
 msgid ""
 "Attempts to stop the process. The process\n"
 "may not exit as a result of clicking this\n"
@@ -4045,40 +4407,48 @@ msgstr ""
 "et propose à l'utilisateur de sauvegarder\n"
 "les fichiers non-enregistrés, etc..."
 
-#: spyderlib/widgets/externalshell/pythonshell.py:288
+#: spyderlib/widgets/externalshell/pythonshell.py:303
 msgid "Interact"
 msgstr "Interagir"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:290
+#: spyderlib/widgets/externalshell/pythonshell.py:305
 msgid "Debug"
 msgstr "Déboguer"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:292
-#: spyderlib/widgets/externalshell/pythonshell.py:355
+#: spyderlib/widgets/externalshell/pythonshell.py:307
+#: spyderlib/widgets/externalshell/pythonshell.py:373
 msgid "Arguments..."
 msgstr "Arguments..."
 
-#: spyderlib/widgets/externalshell/pythonshell.py:299
+#: spyderlib/widgets/externalshell/pythonshell.py:309
+msgid "Post Mortem Debug"
+msgstr ""
+
+#: spyderlib/widgets/externalshell/pythonshell.py:315
+msgid "Working directory"
+msgstr "Répertoire de travail"
+
+#: spyderlib/widgets/externalshell/pythonshell.py:317
 msgid "Set current working directory"
 msgstr "Changer le répertoire de travail"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:301
+#: spyderlib/widgets/externalshell/pythonshell.py:319
 msgid "Environment variables"
 msgstr "Variables d'environnement"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:305
+#: spyderlib/widgets/externalshell/pythonshell.py:323
 msgid "Show sys.path contents"
 msgstr "Afficher le contenu de sys.path"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:351
+#: spyderlib/widgets/externalshell/pythonshell.py:369
 msgid "Arguments: %s"
 msgstr "Arguments : %s"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:353
+#: spyderlib/widgets/externalshell/pythonshell.py:371
 msgid "No argument"
 msgstr "Aucun argument"
 
-#: spyderlib/widgets/externalshell/pythonshell.py:534
+#: spyderlib/widgets/externalshell/pythonshell.py:550
 msgid ""
 "The kernel failed to start!! That's all we know... Please close this console "
 "and open a new one."
@@ -4086,73 +4456,92 @@ msgstr ""
 "Le démarrage du noyau a échoué ! C'est malheureusement tout ce que nous "
 "savons... Merci de fermer cette console et d'en ouvrir une nouvelle."
 
-#: spyderlib/widgets/externalshell/pythonshell.py:538
+#: spyderlib/widgets/externalshell/pythonshell.py:554
 msgid "A Python console failed to start!"
 msgstr "Le démarrage d'une console Python a échoué !"
 
-#: spyderlib/widgets/externalshell/systemshell.py:94
+#: spyderlib/widgets/externalshell/systemshell.py:100
 msgid "Process failed to start"
 msgstr "Le processus n'a pas pu démarrer"
 
-#: spyderlib/widgets/findinfiles.py:155
+#: spyderlib/widgets/file_switcher.py:109
+#, fuzzy
+msgid "unsaved file"
+msgstr "Enregitrer un fichier"
+
+#: spyderlib/widgets/file_switcher.py:229
+msgid ""
+"Press <b>Enter</b> to switch files or <b>Esc</b> to cancel.<br><br>Type to "
+"filter filenames.<br><br>Use <b>:number</b> to go to a line, e.g. "
+"<b><code>main:42</code></b><br>Use <b>@symbol_text</b> to go to a symbol, e."
+"g. <b><code>@init</code></b><br><br> Press <b>Ctrl+W</b> to close current "
+"tab.<br>"
+msgstr ""
+
+#: spyderlib/widgets/file_switcher.py:481
+#, fuzzy
+msgid "lines"
+msgstr " lignes"
+
+#: spyderlib/widgets/findinfiles.py:158
 msgid "Unexpected error: see internal console"
 msgstr "Erreur inattendue : voir console interne"
 
-#: spyderlib/widgets/findinfiles.py:207 spyderlib/widgets/findinfiles.py:231
-#: spyderlib/widgets/findinfiles.py:278
+#: spyderlib/widgets/findinfiles.py:210 spyderlib/widgets/findinfiles.py:234
+#: spyderlib/widgets/findinfiles.py:281
 msgid "invalid regular expression"
 msgstr "expression régulière incorrecte"
 
-#: spyderlib/widgets/findinfiles.py:276
+#: spyderlib/widgets/findinfiles.py:279
 msgid "permission denied errors were encountered"
 msgstr "des erreurs d'autorisation d'accès ont été rencontrées"
 
-#: spyderlib/widgets/findinfiles.py:310
+#: spyderlib/widgets/findinfiles.py:316
 msgid "Search pattern"
 msgstr "Expression recherchée"
 
-#: spyderlib/widgets/findinfiles.py:313 spyderlib/widgets/findinfiles.py:347
-#: spyderlib/widgets/findinfiles.py:359 spyderlib/widgets/findreplace.py:82
+#: spyderlib/widgets/findinfiles.py:319 spyderlib/widgets/findinfiles.py:353
+#: spyderlib/widgets/findinfiles.py:365 spyderlib/widgets/findreplace.py:77
 msgid "Regular expression"
 msgstr "Expression régulière"
 
-#: spyderlib/widgets/findinfiles.py:322
+#: spyderlib/widgets/findinfiles.py:328
 msgid "Search"
 msgstr "Rechercher"
 
-#: spyderlib/widgets/findinfiles.py:325
+#: spyderlib/widgets/findinfiles.py:331
 msgid "Start search"
 msgstr "Démarrer la recherche"
 
-#: spyderlib/widgets/findinfiles.py:328 spyderlib/widgets/ipython.py:543
+#: spyderlib/widgets/findinfiles.py:334 spyderlib/widgets/ipython.py:555
 msgid "Stop"
 msgstr "Arrêter"
 
-#: spyderlib/widgets/findinfiles.py:331
+#: spyderlib/widgets/findinfiles.py:337
 msgid "Stop search"
 msgstr "Arrêter la recherche"
 
-#: spyderlib/widgets/findinfiles.py:341
+#: spyderlib/widgets/findinfiles.py:347
 msgid "Included filenames pattern"
 msgstr "Expression des noms de fichier à inclure"
 
-#: spyderlib/widgets/findinfiles.py:350
+#: spyderlib/widgets/findinfiles.py:356
 msgid "Include:"
 msgstr "Inclure :"
 
-#: spyderlib/widgets/findinfiles.py:353
+#: spyderlib/widgets/findinfiles.py:359
 msgid "Excluded filenames pattern"
 msgstr "Expression des noms de fichier à exclure"
 
-#: spyderlib/widgets/findinfiles.py:362
+#: spyderlib/widgets/findinfiles.py:368
 msgid "Exclude:"
 msgstr "Exclure :"
 
-#: spyderlib/widgets/findinfiles.py:372
+#: spyderlib/widgets/findinfiles.py:378
 msgid "PYTHONPATH"
 msgstr "PYTHONPATH"
 
-#: spyderlib/widgets/findinfiles.py:374
+#: spyderlib/widgets/findinfiles.py:380
 msgid ""
 "Search in all directories listed in sys.path which are outside the Python "
 "installation directory"
@@ -4160,23 +4549,23 @@ msgstr ""
 "Rechercher dans tous les répertoires listés dans sys.path qui sont situés en "
 "dehors du répertoire d'installation de Python"
 
-#: spyderlib/widgets/findinfiles.py:377
+#: spyderlib/widgets/findinfiles.py:383
 msgid "Hg repository"
 msgstr "Dépôt Mercurial"
 
-#: spyderlib/widgets/findinfiles.py:380
+#: spyderlib/widgets/findinfiles.py:386
 msgid "Search in current directory hg repository"
 msgstr "Rechercher dans le dépôt Mercurial du répertoire courant"
 
-#: spyderlib/widgets/findinfiles.py:381
+#: spyderlib/widgets/findinfiles.py:387
 msgid "Here:"
 msgstr "Ici :"
 
-#: spyderlib/widgets/findinfiles.py:385
+#: spyderlib/widgets/findinfiles.py:391
 msgid "Search recursively in this directory"
 msgstr "Rechercher de manière récursive dans ce répertoire"
 
-#: spyderlib/widgets/findinfiles.py:393
+#: spyderlib/widgets/findinfiles.py:396
 msgid "Browse a search directory"
 msgstr "Sélectionner un répertoire de recherche"
 
@@ -4188,155 +4577,155 @@ msgstr "Masquer les options avancées"
 msgid "Show advanced options"
 msgstr "Afficher les options avancées"
 
-#: spyderlib/widgets/findinfiles.py:571
+#: spyderlib/widgets/findinfiles.py:570
 msgid "Search canceled"
 msgstr "Recherche annulée"
 
-#: spyderlib/widgets/findinfiles.py:575
+#: spyderlib/widgets/findinfiles.py:574
 msgid "String not found"
 msgstr "Chaîne de caractères non trouvée"
 
-#: spyderlib/widgets/findinfiles.py:577
+#: spyderlib/widgets/findinfiles.py:576
 msgid "matches in"
 msgstr "correspondances trouvées dans"
 
-#: spyderlib/widgets/findinfiles.py:578
+#: spyderlib/widgets/findinfiles.py:577
 msgid "file"
 msgstr "fichier"
 
-#: spyderlib/widgets/findinfiles.py:586
+#: spyderlib/widgets/findinfiles.py:585
 msgid "interrupted"
 msgstr "interrompu"
 
-#: spyderlib/widgets/findreplace.py:62
+#: spyderlib/widgets/findreplace.py:59
 msgid "Search string"
 msgstr "Chaîne de caractères à rechercher"
 
-#: spyderlib/widgets/findreplace.py:89
+#: spyderlib/widgets/findreplace.py:83
 msgid "Case Sensitive"
 msgstr "Respecter la casse"
 
-#: spyderlib/widgets/findreplace.py:96
+#: spyderlib/widgets/findreplace.py:89
 msgid "Whole words"
 msgstr "Mots entiers"
 
-#: spyderlib/widgets/findreplace.py:103
+#: spyderlib/widgets/findreplace.py:95
 msgid "Highlight matches"
 msgstr "Surligner les résultats"
 
-#: spyderlib/widgets/findreplace.py:118
+#: spyderlib/widgets/findreplace.py:109
 msgid "Replace with:"
 msgstr "Remplacer par :"
 
-#: spyderlib/widgets/findreplace.py:120
+#: spyderlib/widgets/findreplace.py:111
 msgid "Replace string"
 msgstr "Chaîne de caractères de remplacement"
 
-#: spyderlib/widgets/findreplace.py:123
+#: spyderlib/widgets/findreplace.py:114
 msgid "Replace/find"
 msgstr "Remplacer/rechercher"
 
-#: spyderlib/widgets/findreplace.py:132
+#: spyderlib/widgets/findreplace.py:121
 msgid "Replace all"
 msgstr "Remplacer tout"
 
-#: spyderlib/widgets/importwizard.py:111 spyderlib/widgets/importwizard.py:425
+#: spyderlib/widgets/importwizard.py:116 spyderlib/widgets/importwizard.py:431
 msgid "Import as"
 msgstr "Importer en tant que"
 
-#: spyderlib/widgets/importwizard.py:113
+#: spyderlib/widgets/importwizard.py:118
 msgid "data"
 msgstr "données"
 
-#: spyderlib/widgets/importwizard.py:117
+#: spyderlib/widgets/importwizard.py:122
 msgid "code"
 msgstr "code"
 
-#: spyderlib/widgets/importwizard.py:120 spyderlib/widgets/importwizard.py:497
+#: spyderlib/widgets/importwizard.py:125 spyderlib/widgets/importwizard.py:504
 msgid "text"
 msgstr "texte"
 
-#: spyderlib/widgets/importwizard.py:133
+#: spyderlib/widgets/importwizard.py:138
 msgid "Column separator:"
 msgstr "Séparateur de colonne :"
 
-#: spyderlib/widgets/importwizard.py:137
+#: spyderlib/widgets/importwizard.py:142
 msgid "Tab"
 msgstr "Tab"
 
-#: spyderlib/widgets/importwizard.py:140 spyderlib/widgets/importwizard.py:159
+#: spyderlib/widgets/importwizard.py:145 spyderlib/widgets/importwizard.py:163
 msgid "other"
 msgstr "autre"
 
-#: spyderlib/widgets/importwizard.py:152
+#: spyderlib/widgets/importwizard.py:156
 msgid "Row separator:"
 msgstr "Séparateur de ligne :"
 
-#: spyderlib/widgets/importwizard.py:156
+#: spyderlib/widgets/importwizard.py:160
 msgid "EOL"
 msgstr "EOL"
 
-#: spyderlib/widgets/importwizard.py:172
+#: spyderlib/widgets/importwizard.py:175
 msgid "Additional options"
 msgstr "Options supplémentaires"
 
-#: spyderlib/widgets/importwizard.py:176
+#: spyderlib/widgets/importwizard.py:179
 msgid "Skip rows:"
 msgstr "Sauter des lignes :"
 
-#: spyderlib/widgets/importwizard.py:187
+#: spyderlib/widgets/importwizard.py:190
 msgid "Comments:"
 msgstr "Commentaires :"
 
-#: spyderlib/widgets/importwizard.py:193
+#: spyderlib/widgets/importwizard.py:196
 msgid "Transpose"
 msgstr "Transposer"
 
-#: spyderlib/widgets/importwizard.py:428
+#: spyderlib/widgets/importwizard.py:434
 msgid "array"
 msgstr "tableau"
 
-#: spyderlib/widgets/importwizard.py:433
+#: spyderlib/widgets/importwizard.py:439
 msgid "list"
 msgstr "liste"
 
-#: spyderlib/widgets/importwizard.py:438
+#: spyderlib/widgets/importwizard.py:444
 msgid "DataFrame"
 msgstr "DataFrame"
 
-#: spyderlib/widgets/importwizard.py:480 spyderlib/widgets/importwizard.py:567
+#: spyderlib/widgets/importwizard.py:487 spyderlib/widgets/importwizard.py:569
 msgid "Import wizard"
 msgstr "Assistant d'importation"
 
-#: spyderlib/widgets/importwizard.py:485
+#: spyderlib/widgets/importwizard.py:492
 msgid "Raw text"
 msgstr "Text brut"
 
-#: spyderlib/widgets/importwizard.py:488
+#: spyderlib/widgets/importwizard.py:495
 msgid "variable_name"
 msgstr "nom_de_variable"
 
-#: spyderlib/widgets/importwizard.py:499
+#: spyderlib/widgets/importwizard.py:506
 msgid "table"
 msgstr "tableau"
 
-#: spyderlib/widgets/importwizard.py:500
+#: spyderlib/widgets/importwizard.py:507
 msgid "Preview"
 msgstr "Aperçu"
 
-#: spyderlib/widgets/importwizard.py:504
+#: spyderlib/widgets/importwizard.py:511
 msgid "Variable Name"
 msgstr "Nom de variable"
 
-#: spyderlib/widgets/importwizard.py:512
+#: spyderlib/widgets/importwizard.py:519
 msgid "Cancel"
 msgstr "Annuler"
 
-#: spyderlib/widgets/importwizard.py:527
+#: spyderlib/widgets/importwizard.py:532
 msgid "Done"
 msgstr "Terminer"
 
-#: spyderlib/widgets/importwizard.py:568
+#: spyderlib/widgets/importwizard.py:570
 msgid ""
 "<b>Unable to proceed to next step</b><br><br>Please check your entries."
 "<br><br>Error message:<br>%s"
@@ -4344,71 +4733,71 @@ msgstr ""
 "<b>Impossible de passer à l'étape suivante</b><br><br>Merci de vérifier "
 "votre saisie.<br><br>Message d'erreur :<br>%s"
 
-#: spyderlib/widgets/internalshell.py:252
+#: spyderlib/widgets/internalshell.py:258
 msgid "Help..."
 msgstr "Aide..."
 
-#: spyderlib/widgets/internalshell.py:259
+#: spyderlib/widgets/internalshell.py:266
 msgid "Help"
 msgstr "Aide"
 
-#: spyderlib/widgets/internalshell.py:268
+#: spyderlib/widgets/internalshell.py:275
 msgid "Shell special commands:"
 msgstr "Commandes spéciales de la console :"
 
-#: spyderlib/widgets/internalshell.py:269
+#: spyderlib/widgets/internalshell.py:276
 msgid "Internal editor:"
 msgstr "Éditeur interne :"
 
-#: spyderlib/widgets/internalshell.py:270
+#: spyderlib/widgets/internalshell.py:277
 msgid "External editor:"
 msgstr "Éditeur externe :"
 
-#: spyderlib/widgets/internalshell.py:271
+#: spyderlib/widgets/internalshell.py:278
 msgid "Run script:"
 msgstr "Exécuter un script :"
 
-#: spyderlib/widgets/internalshell.py:272
+#: spyderlib/widgets/internalshell.py:279
 msgid "Remove references:"
 msgstr "Supprimer des références :"
 
-#: spyderlib/widgets/internalshell.py:273
+#: spyderlib/widgets/internalshell.py:280
 msgid "System commands:"
 msgstr "Commandes systèmes :"
 
-#: spyderlib/widgets/internalshell.py:274
+#: spyderlib/widgets/internalshell.py:281
 msgid "Python help:"
 msgstr "Aide Python :"
 
-#: spyderlib/widgets/internalshell.py:275
+#: spyderlib/widgets/internalshell.py:282
 msgid "GUI-based editor:"
 msgstr "Éditeur graphique :"
 
-#: spyderlib/widgets/ipython.py:495
+#: spyderlib/widgets/ipython.py:506
 msgid "An error ocurred while starting the kernel"
 msgstr "Une erreur est survenue lors du démarrage du noyau."
 
-#: spyderlib/widgets/ipython.py:523
+#: spyderlib/widgets/ipython.py:535
 msgid "Restart kernel"
 msgstr "Redémarrer le noyau"
 
-#: spyderlib/widgets/ipython.py:545
+#: spyderlib/widgets/ipython.py:557
 msgid "Stop the current command"
 msgstr "Interrompre la commande en cours"
 
-#: spyderlib/widgets/ipython.py:569
+#: spyderlib/widgets/ipython.py:581
 msgid "Inspect current object"
 msgstr "Inspecter l'onglet courant"
 
-#: spyderlib/widgets/ipython.py:574
+#: spyderlib/widgets/ipython.py:586
 msgid "Clear line or block"
 msgstr "Effacer la ligne ou le bloc"
 
-#: spyderlib/widgets/ipython.py:578
+#: spyderlib/widgets/ipython.py:590
 msgid "Clear console"
 msgstr "Effacer la console"
 
-#: spyderlib/widgets/ipython.py:623
+#: spyderlib/widgets/ipython.py:640
 msgid ""
 "It seems the kernel died unexpectedly. Use 'Restart kernel' to continue "
 "using this console."
@@ -4416,89 +4805,89 @@ msgstr ""
 "Le noyau a été arrêté de façon inattendue. Redémarrez le noyau pour "
 "continuer d'utiliser cette console."
 
-#: spyderlib/widgets/ipython.py:639
+#: spyderlib/widgets/ipython.py:660
 msgid "Changing backend to Qt for Mayavi"
 msgstr "Utilisation du backend Qt pour Mayavi"
 
-#: spyderlib/widgets/ipython.py:648
+#: spyderlib/widgets/ipython.py:669
 msgid "Kernel process is either remote or unspecified. Cannot interrupt"
 msgstr ""
 "Le processus du noyau est soit distant, soit non spécifié : impossible "
 "d'arrêter le noyau."
 
-#: spyderlib/widgets/ipython.py:657
+#: spyderlib/widgets/ipython.py:678
 msgid "Kernel process is either remote or unspecified. Cannot restart."
 msgstr ""
 "Le processus du noyau est soit distant, soit non spécifié : impossible de "
 "redémarrer le noyau."
 
-#: spyderlib/widgets/ipython.py:734
+#: spyderlib/widgets/ipython.py:757
 msgid "Connecting to kernel..."
 msgstr "Connexion au noyau..."
 
-#: spyderlib/widgets/onecolumntree.py:63
+#: spyderlib/widgets/onecolumntree.py:60
 msgid "Collapse all"
 msgstr "Replier tout"
 
-#: spyderlib/widgets/onecolumntree.py:67
+#: spyderlib/widgets/onecolumntree.py:64
 msgid "Expand all"
 msgstr "Déplier tout"
 
-#: spyderlib/widgets/onecolumntree.py:71
+#: spyderlib/widgets/onecolumntree.py:68
 msgid "Restore"
 msgstr "Restaurer"
 
-#: spyderlib/widgets/onecolumntree.py:72
+#: spyderlib/widgets/onecolumntree.py:69
 msgid "Restore original tree layout"
 msgstr "Restaurer l'organisation initiale de l'arbre"
 
-#: spyderlib/widgets/onecolumntree.py:76
+#: spyderlib/widgets/onecolumntree.py:73
 msgid "Collapse selection"
 msgstr "Replier la sélection"
 
-#: spyderlib/widgets/onecolumntree.py:80
+#: spyderlib/widgets/onecolumntree.py:77
 msgid "Expand selection"
 msgstr "Déplier la sélection"
 
-#: spyderlib/widgets/pathmanager.py:84
+#: spyderlib/widgets/pathmanager.py:86
 msgid "Move to top"
 msgstr "Placer en premier"
 
-#: spyderlib/widgets/pathmanager.py:90
+#: spyderlib/widgets/pathmanager.py:92
 msgid "Move up"
 msgstr "Monter"
 
-#: spyderlib/widgets/pathmanager.py:96
+#: spyderlib/widgets/pathmanager.py:98
 msgid "Move down"
 msgstr "Descendre"
 
-#: spyderlib/widgets/pathmanager.py:102
+#: spyderlib/widgets/pathmanager.py:104
 msgid "Move to bottom"
 msgstr "Placer en dernier"
 
-#: spyderlib/widgets/pathmanager.py:113 spyderlib/widgets/pathmanager.py:225
+#: spyderlib/widgets/pathmanager.py:115 spyderlib/widgets/pathmanager.py:230
 msgid "Add path"
 msgstr "Ajouter un chemin"
 
-#: spyderlib/widgets/pathmanager.py:118 spyderlib/widgets/pathmanager.py:209
+#: spyderlib/widgets/pathmanager.py:120 spyderlib/widgets/pathmanager.py:213
 msgid "Remove path"
 msgstr "Supprimer"
 
-#: spyderlib/widgets/pathmanager.py:128
+#: spyderlib/widgets/pathmanager.py:130
 msgid "Synchronize..."
 msgstr "Synchroniser..."
 
-#: spyderlib/widgets/pathmanager.py:130
+#: spyderlib/widgets/pathmanager.py:132
 msgid "Synchronize Spyder's path list with PYTHONPATH environment variable"
 msgstr ""
 "Synchronise la liste des chemins d'accès de Spyder avec celle de la variable "
 "d'environnement PYTHONPATH"
 
-#: spyderlib/widgets/pathmanager.py:141
+#: spyderlib/widgets/pathmanager.py:144
 msgid "Synchronize"
 msgstr "Synchroniser"
 
-#: spyderlib/widgets/pathmanager.py:142
+#: spyderlib/widgets/pathmanager.py:145
 msgid ""
 "This will synchronize Spyder's path list with <b>PYTHONPATH</b> environment "
 "variable for current user, allowing you to run your Python modules outside "
@@ -4511,11 +4900,11 @@ msgstr ""
 "avoir besoin de configurer sys.path. <br>Souhaitez-vous effacer le contenu "
 "de PYTHONPATH avant d'y ajouter la liste des chemins d'accès de Spyder ?"
 
-#: spyderlib/widgets/pathmanager.py:210
+#: spyderlib/widgets/pathmanager.py:214
 msgid "Do you really want to remove selected path?"
 msgstr "Souhaitez-vous vraiment supprimer le chemin sélectionné ?"
 
-#: spyderlib/widgets/pathmanager.py:226
+#: spyderlib/widgets/pathmanager.py:231
 msgid ""
 "This directory is already included in Spyder path list.<br>Do you want to "
 "move it to the top of the list?"
@@ -4523,71 +4912,71 @@ msgstr ""
 "Ce répertoire est déjà inclus dans la liste des chemins d'accès de Spyder."
 "<br>Souhaitez-vous le placer en début de liste ?"
 
-#: spyderlib/widgets/projectexplorer.py:333
+#: spyderlib/widgets/projectexplorer.py:335
 msgid "its own configuration file"
 msgstr "son propre fichier de configuration"
 
-#: spyderlib/widgets/projectexplorer.py:335
+#: spyderlib/widgets/projectexplorer.py:337
 msgid " and "
 msgstr " et "
 
-#: spyderlib/widgets/projectexplorer.py:339
+#: spyderlib/widgets/projectexplorer.py:341
 msgid "the following projects:<br>%s"
 msgstr "les projets suivants :<br>%s"
 
-#: spyderlib/widgets/projectexplorer.py:541
+#: spyderlib/widgets/projectexplorer.py:545
 msgid "Project..."
 msgstr "Projet..."
 
-#: spyderlib/widgets/projectexplorer.py:554
+#: spyderlib/widgets/projectexplorer.py:558
 msgid "Existing directory"
 msgstr "Répertoire existant"
 
-#: spyderlib/widgets/projectexplorer.py:558
+#: spyderlib/widgets/projectexplorer.py:562
 msgid "Existing Spyder project"
 msgstr "Projet Spyder existant"
 
-#: spyderlib/widgets/projectexplorer.py:562
+#: spyderlib/widgets/projectexplorer.py:566
 msgid "Existing Pydev project"
 msgstr "Projet Pydev existant"
 
-#: spyderlib/widgets/projectexplorer.py:579
+#: spyderlib/widgets/projectexplorer.py:583
 msgid "Open project"
 msgstr "Ouvrir le projet"
 
-#: spyderlib/widgets/projectexplorer.py:584
+#: spyderlib/widgets/projectexplorer.py:588
 msgid "Close project"
 msgstr "Fermer le projet"
 
-#: spyderlib/widgets/projectexplorer.py:589
+#: spyderlib/widgets/projectexplorer.py:593
 msgid "Close unrelated projects"
 msgstr "Fermer les projets non associés"
 
-#: spyderlib/widgets/projectexplorer.py:598
+#: spyderlib/widgets/projectexplorer.py:602
 msgid "Edit related projects"
 msgstr "Modifier les projets associés"
 
-#: spyderlib/widgets/projectexplorer.py:606
+#: spyderlib/widgets/projectexplorer.py:610
 msgid "Add to PYTHONPATH"
 msgstr "Ajouter à PYTHONPATH"
 
-#: spyderlib/widgets/projectexplorer.py:611
+#: spyderlib/widgets/projectexplorer.py:615
 msgid "Remove from PYTHONPATH"
 msgstr "Retirer de PYTHONPATH"
 
-#: spyderlib/widgets/projectexplorer.py:616
+#: spyderlib/widgets/projectexplorer.py:620
 msgid "Properties"
 msgstr "Propriétés"
 
-#: spyderlib/widgets/projectexplorer.py:651
+#: spyderlib/widgets/projectexplorer.py:655
 msgid "Show horizontal scrollbar"
 msgstr "Barre de défilement horizontal"
 
-#: spyderlib/widgets/projectexplorer.py:684
+#: spyderlib/widgets/projectexplorer.py:692
 msgid "Workspace"
 msgstr "Espace de travail"
 
-#: spyderlib/widgets/projectexplorer.py:685
+#: spyderlib/widgets/projectexplorer.py:693
 msgid ""
 "The workspace was unable to load or save %s<br><br>Please check if you have "
 "the permission to write the associated configuration files."
@@ -4596,11 +4985,11 @@ msgstr ""
 "%s<br><br>Veuillez vérifier que vous disposez bien des droits d'écriture sur "
 "les fichiers de configuration associés."
 
-#: spyderlib/widgets/projectexplorer.py:744
+#: spyderlib/widgets/projectexplorer.py:752
 msgid "Import directory"
 msgstr "Importer un répertoire"
 
-#: spyderlib/widgets/projectexplorer.py:746
+#: spyderlib/widgets/projectexplorer.py:754
 msgid ""
 "The following directory is not in workspace:<br><b>%s</b><br><br>Do you want "
 "to continue (and copy the directory to workspace)?"
@@ -4609,16 +4998,16 @@ msgstr ""
 "b><br><br>Souhaitez-vous continuer (et copier ce répertoire dans l'espace de "
 "travail) ?"
 
-#: spyderlib/widgets/projectexplorer.py:764
-#: spyderlib/widgets/projectexplorer.py:1170
+#: spyderlib/widgets/projectexplorer.py:772
+#: spyderlib/widgets/projectexplorer.py:1183
 msgid "copy"
 msgstr "copier"
 
-#: spyderlib/widgets/projectexplorer.py:816
+#: spyderlib/widgets/projectexplorer.py:824
 msgid "The project <b>%s</b> is already opened!"
 msgstr "Le projet <b>%s</b> est déjà ouvert !"
 
-#: spyderlib/widgets/projectexplorer.py:823
+#: spyderlib/widgets/projectexplorer.py:831
 msgid ""
 "The project root path directory is inside the workspace but not as the "
 "expected tree level. It is not a directory of the workspace:<br><b>%s</b>"
@@ -4627,15 +5016,15 @@ msgstr ""
 "mais pas au niveau d'arborescence attendu. Ce n'est pas un répertoire de "
 "l'espace de travail :<br><b>%s</b>"
 
-#: spyderlib/widgets/projectexplorer.py:834
+#: spyderlib/widgets/projectexplorer.py:842
 msgid "Project name:"
 msgstr "Nom du projet :"
 
-#: spyderlib/widgets/projectexplorer.py:843
+#: spyderlib/widgets/projectexplorer.py:851
 msgid "A project named <b>%s</b> already exists"
 msgstr "Un projet nommé <b>%s</b> existe déjà"
 
-#: spyderlib/widgets/projectexplorer.py:848
+#: spyderlib/widgets/projectexplorer.py:856
 msgid ""
 "Invalid project name.<br><br>Name must match the following regular "
 "expression:<br><b>%s</b>"
@@ -4643,7 +5032,7 @@ msgstr ""
 "Nom de projet incorrect.<br><br>Le nom doit respecter l'expression régulière "
 "suivante :<br><b>%s</b>"
 
-#: spyderlib/widgets/projectexplorer.py:855
+#: spyderlib/widgets/projectexplorer.py:863
 msgid ""
 "The following directory is not empty:<br><b>%s</b><br><br>Do you want to "
 "continue?"
@@ -4651,11 +5040,11 @@ msgstr ""
 "Le répertoire suivant n'est pas vide :<br><b>%s</b><br><br>Souhaitez-vous "
 "néanmoins continuer ?"
 
-#: spyderlib/widgets/projectexplorer.py:867
+#: spyderlib/widgets/projectexplorer.py:876
 msgid "New project"
 msgstr "Nouveau projet"
 
-#: spyderlib/widgets/projectexplorer.py:875
+#: spyderlib/widgets/projectexplorer.py:884
 msgid ""
 "The current workspace has not been configured yet.\n"
 "Do you want to do this now?"
@@ -4663,30 +5052,30 @@ msgstr ""
 "L'espace de travail n'a pas encore été défini.\n"
 "Souhaitez-vous le faire maintenant ?"
 
-#: spyderlib/widgets/projectexplorer.py:912
+#: spyderlib/widgets/projectexplorer.py:922
 msgid "Import existing project"
 msgstr "Importer un projet existant"
 
-#: spyderlib/widgets/projectexplorer.py:925
+#: spyderlib/widgets/projectexplorer.py:935
 msgid "Select projects to import"
 msgstr "Sélectionner les projets à importer"
 
-#: spyderlib/widgets/projectexplorer.py:937
+#: spyderlib/widgets/projectexplorer.py:947
 msgid "The folder <i>%s</i> does not contain a valid %s project"
 msgstr "Le dossier <i>%s</i> ne contient pas de projet %s valide"
 
-#: spyderlib/widgets/projectexplorer.py:965
+#: spyderlib/widgets/projectexplorer.py:977
 msgid "Import existing Pydev project"
 msgstr "Importer un projet Pydev"
 
-#: spyderlib/widgets/projectexplorer.py:966
+#: spyderlib/widgets/projectexplorer.py:978
 msgid ""
 "<b>Unable to read Pydev project <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>Impossible d'ouvrir le projet Pydev <i>%s</i></b><br><br>Message "
 "d'erreur :<br>%s"
 
-#: spyderlib/widgets/projectexplorer.py:1004
+#: spyderlib/widgets/projectexplorer.py:1016
 msgid ""
 "Do you really want to delete project <b>%s</b>?<br><br>Note: project files "
 "won't be deleted from disk."
@@ -4694,39 +5083,40 @@ msgstr ""
 "Souhaitez-vous réellement supprimer le projet <b>%s</b> ?<br><br>Notez que "
 "les fichiers et répertoires du projet ne seront pas supprimés du disque."
 
-#: spyderlib/widgets/projectexplorer.py:1057
+#: spyderlib/widgets/projectexplorer.py:1069
 msgid "Related projects"
 msgstr "Projets associés"
 
-#: spyderlib/widgets/projectexplorer.py:1065
+#: spyderlib/widgets/projectexplorer.py:1077
 msgid "Select projects which are related to <b>%s</b>"
 msgstr "Sélectionner les projets à associer à <b>%s</b>"
 
-#: spyderlib/widgets/projectexplorer.py:1090
+#: spyderlib/widgets/projectexplorer.py:1102
+#, fuzzy
 msgid ""
-"Statistics on source files only:<br>(Python, C/C++, Fortran)<br><br><b>%s</"
-"b> files.<br><b>%s</b> lines of code."
+"Statistics on source files only:<br>(Python, Cython, IPython, Enaml,C/C++, "
+"Fortran)<br><br><b>%s</b> files.<br><b>%s</b> lines of code."
 msgstr ""
 "Statistique sur les fichiers source uniquement:<br>(Python, C/C++, "
 "Fortran)<br><br><b>%s</b> fichiers.<br><b>%s</b> lignes de code."
 
-#: spyderlib/widgets/projectexplorer.py:1138
+#: spyderlib/widgets/projectexplorer.py:1151
 msgid "File <b>%s</b> already exists.<br>Do you want to overwrite it?"
 msgstr "Le fichier <b>%s</b> existe déjà.<br>Souhaitez-vous le remplacer ?"
 
-#: spyderlib/widgets/projectexplorer.py:1152
+#: spyderlib/widgets/projectexplorer.py:1165
 msgid "Folder <b>%s</b> already exists."
 msgstr "Le dossier <b>%s</b> existe déjà."
 
-#: spyderlib/widgets/projectexplorer.py:1172
+#: spyderlib/widgets/projectexplorer.py:1185
 msgid "move"
 msgstr "déplacer"
 
-#: spyderlib/widgets/projectexplorer.py:1182
+#: spyderlib/widgets/projectexplorer.py:1195
 msgid "Select an existing workspace directory, or create a new one"
 msgstr "Sélectionner un espace de travail existant, ou en créer un nouveau"
 
-#: spyderlib/widgets/projectexplorer.py:1183
+#: spyderlib/widgets/projectexplorer.py:1196
 msgid ""
 "<u><b>What is the workspace?</b></u><br><br>A <b>Spyder workspace</b> is a "
 "directory on your filesystem that contains Spyder projects and <b>."
@@ -4743,11 +5133,11 @@ msgstr ""
 "configuration (nommé <b>.spyderproject</b>) dans lequel sont stockés les "
 "réglages du projet (PYTHONPATH, projets liés, ...).<br>"
 
-#: spyderlib/widgets/projectexplorer.py:1210
+#: spyderlib/widgets/projectexplorer.py:1225
 msgid "This is the current workspace directory"
 msgstr "Ceci est l'espace de travail actif"
 
-#: spyderlib/widgets/projectexplorer.py:1241
+#: spyderlib/widgets/projectexplorer.py:1255
 msgid ""
 "The following directory is not a Spyder workspace:<br>%s<br><br>Do you want "
 "to create a new workspace in this directory?"
@@ -4760,71 +5150,75 @@ msgstr ""
 msgid "Module or package:"
 msgstr "Module ou paquet :"
 
-#: spyderlib/widgets/shell.py:126
+#: spyderlib/widgets/shell.py:134
 msgid "Save history log..."
 msgstr "Enregistrer l'historique..."
 
-#: spyderlib/widgets/shell.py:128
+#: spyderlib/widgets/shell.py:136
 msgid "Save current history log (i.e. all inputs and outputs) in a text file"
 msgstr ""
 "Enregistrer l'historique complet (toutes les entrées et sorties) dans un "
 "fichier texte"
 
-#: spyderlib/widgets/shell.py:248
+#: spyderlib/widgets/shell.py:262
 msgid "Save history log"
 msgstr "Enregistrer l'historique"
 
-#: spyderlib/widgets/shell.py:251
+#: spyderlib/widgets/shell.py:265
 msgid "History logs"
 msgstr "Fichiers d'historique"
 
-#: spyderlib/widgets/shell.py:262
+#: spyderlib/widgets/shell.py:276
 msgid "<b>Unable to save file '%s'</b><br><br>Error message:<br>%s"
 msgstr ""
 "<b>Impossible d'enregistrer le fichier '%s'</b><br><br>Message d'erreur :<br>"
 "%s"
 
-#: spyderlib/widgets/shell.py:701
+#: spyderlib/widgets/shell.py:718
 msgid "Copy without prompts"
 msgstr "Copier sans les préfixes"
 
-#: spyderlib/widgets/shell.py:704 spyderlib/widgets/shell.py:708
+#: spyderlib/widgets/shell.py:721 spyderlib/widgets/shell.py:725
 msgid "Clear line"
 msgstr "Effacer la ligne"
 
-#: spyderlib/widgets/shell.py:710
+#: spyderlib/widgets/shell.py:727
 msgid "Clear shell"
 msgstr "Effacer la console"
 
-#: spyderlib/widgets/shell.py:714
+#: spyderlib/widgets/shell.py:731
 msgid "Clear shell contents ('cls' command)"
 msgstr "Effacer le contenu de la console"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:88
+#: spyderlib/widgets/sourcecode/codeeditor.py:98
 msgid "Go to line:"
 msgstr "Aller à la ligne :"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:97
+#: spyderlib/widgets/sourcecode/codeeditor.py:106
 msgid "Line count:"
 msgstr "Nombre de lignes :"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:1210
+#: spyderlib/widgets/sourcecode/codeeditor.py:1270
 msgid "Breakpoint"
 msgstr "Point d'arrêt"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:1211
+#: spyderlib/widgets/sourcecode/codeeditor.py:1271
 msgid "Condition:"
 msgstr "Condition :"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:1671
+#: spyderlib/widgets/sourcecode/codeeditor.py:1679
+msgid "Code analysis"
+msgstr "Analyse de code"
+
+#: spyderlib/widgets/sourcecode/codeeditor.py:1733
 msgid "To do"
 msgstr "À faire"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:1880
+#: spyderlib/widgets/sourcecode/codeeditor.py:1974
 msgid "Removal error"
 msgstr "Erreur de suppression"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:1881
+#: spyderlib/widgets/sourcecode/codeeditor.py:1975
 msgid ""
 "It was not possible to remove outputs from this notebook. The error is:\n"
 "\n"
@@ -4832,19 +5226,19 @@ msgstr ""
 "Impossible d'effacer les résultats de ce notebook:\n"
 "\n"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:2296
+#: spyderlib/widgets/sourcecode/codeeditor.py:2453
 msgid "Clear all ouput"
 msgstr "Effacer tous les résultats"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:2302
+#: spyderlib/widgets/sourcecode/codeeditor.py:2459
 msgid "Go to definition"
 msgstr "Aller à la définition de l'objet"
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:2314
+#: spyderlib/widgets/sourcecode/codeeditor.py:2471
 msgid "Zoom reset"
 msgstr "Réinitialisation du zoom"
 
-#: spyderlib/widgets/sourcecode/syntaxhighlighters.py:30
+#: spyderlib/widgets/sourcecode/syntaxhighlighters.py:32
 msgid "Syntax highlighting for Matlab, Julia and other file types"
 msgstr "Coloration syntaxique pour Matlab, Julia et d'autres types de fichier"
 
@@ -4893,11 +5287,11 @@ msgstr "Ligne :"
 msgid "Column:"
 msgstr "Colonne :"
 
-#: spyderlib/widgets/tabs.py:137
+#: spyderlib/widgets/tabs.py:142
 msgid "Browse tabs"
 msgstr "Naviguer dans les onglets"
 
-#: spyderlib/widgets/tabs.py:260
+#: spyderlib/widgets/tabs.py:270
 msgid "Close current tab"
 msgstr "Fermer l'onglet"
 
@@ -4905,6 +5299,137 @@ msgstr "Fermer l'onglet"
 msgid "Text editor"
 msgstr "Éditeur de texte"
 
+#: spyderlib/workers/updates.py:79 spyderlib/workers/updates.py:81
+msgid "Unable to retrieve information."
+msgstr ""
+
+#: spyderlib/workers/updates.py:83
+msgid ""
+"Unable to connect to the internet. <br><br>Make sure the connection is "
+"working properly."
+msgstr ""
+
+#: spyderlib/workers/updates.py:86
+#, fuzzy
+msgid "Unable to check for updates."
+msgstr "Impossible de charger la page"
+
+#~ msgid "PyQt"
+#~ msgstr "PyQt"
+
+#~ msgid "API selection for QString and QVariant objects:"
+#~ msgstr "Sélection de l'API des objets QString et QVariant :"
+
+#~ msgid "API #1"
+#~ msgstr "API n°1"
+
+#~ msgid "API #2"
+#~ msgstr "API n°2"
+
+#~ msgid "Default API"
+#~ msgstr "API par défaut"
+
+#~ msgid ""
+#~ "PyQt API #1 is the default <br>API for Python 2. PyQt API #2 is the "
+#~ "default API for Python 3 and is compatible with PySide."
+#~ msgstr ""
+#~ "L'API n°1 de PyQt est l'API par défaut pour Python 2. L'API n°2 est l'API "
+#~ "par défaut pour Python 3 : c'est l'API qui est compatible avec PySide."
+
+#~ msgid "Ignore API change errors (sip.setapi)"
+#~ msgstr "Ignorer les erreurs de changement d'API (sip.setapi)"
+
+#~ msgid ""
+#~ "Enabling this option will ignore <br>errors when changing PyQt API. As "
+#~ "PyQt does not support dynamic API changes, it is strongly recommended to "
+#~ "use this feature wisely, e.g. for debugging purpose."
+#~ msgstr ""
+#~ "L'activation de cette option permet d'ignorer les erreurs liées aux "
+#~ "changements\n"
+#~ "d'API de PyQt. Vu que PyQt ne prend pas en charge le changement "
+#~ "dynamique\n"
+#~ " d'API, il est fortement recommandé d'utiliser cette fonctionnalité "
+#~ "exceptionnellement,\n"
+#~ "par exemple pour du débogage."
+
+#~ msgid "Matplotlib"
+#~ msgstr "Matplotlib"
+
+#~ msgid "GUI backend:"
+#~ msgstr "Backend graphique :"
+
+#~ msgid ""
+#~ "Set the GUI toolkit used by <br>Matplotlib to show figures (default: "
+#~ "Qt4Agg)"
+#~ msgstr ""
+#~ "Spécifie la bibliothèque d'interfaces graphiques à utiliser pour "
+#~ "l'affichage des figures Matplotlib (par défaut : Qt4Agg)"
+
+#~ msgid "Mod1"
+#~ msgstr "Mod1"
+
+#~ msgid "Mod2"
+#~ msgstr "Mod2"
+
+#~ msgid "Mod3"
+#~ msgstr "Mod3"
+
+#, fuzzy
+#~ msgid "The Internal Console"
+#~ msgstr "Console interne"
+
+#~ msgid "File list management"
+#~ msgstr "Gestionnaire de fichiers"
+
+#~ msgid "Filter:"
+#~ msgstr "Filtre :"
+
+#~ msgid "(press <b>Enter</b> to edit file)"
+#~ msgstr "(appuyer sur <b>Entrée</b> pour modifier le fichier)"
+
+#~ msgid "&Edit file"
+#~ msgstr "Modifi&er le fichier"
+
+#~ msgid "&Close file"
+#~ msgstr "&Fermer le fichier"
+
+#~ msgid "Hint: press <b>Alt</b> to show accelerators"
+#~ msgstr "Astuce : la touche <b>Alt</b> affiche les accélérateurs"
+
+#~ msgid "Vertical dockwidget tabs"
+#~ msgstr "Onglets distribués verticalement"
+
+#~ msgid "Custom dockwidget margin:"
+#~ msgstr "Marges personnalisées :"
+
+#~ msgid ""
+#~ "<u>Note</u>: add <b>analysis:ignore</b> in a comment to ignore code/style "
+#~ "analysis warnings. For more informations on style guide for Python code, "
+#~ "please refer to the %s page."
+#~ msgstr ""
+#~ "<u>Note</u>: ajouter <b>analysis:ignore</b> dans un commentaire pour "
+#~ "ignorer les résultats de l'analyse de code ou de style. Pour plus "
+#~ "d'informations sur les recommandations officielles de style d'écriture "
+#~ "avec le langage Python, veuillez visiter la page de la %s."
+
+#~ msgid "Style analysis"
+#~ msgstr "Analyse de style"
+
+#~ msgid "Qt (PyQt/PySide)"
+#~ msgstr "Qt (PyQt/PySide)"
+
+#~ msgid "Use a completion widget"
+#~ msgstr "Utiliser un widget de complétion de code"
+
+#~ msgid "Use a widget instead of plain text output for tab completion"
+#~ msgstr "Utiliser un widget de complétion au lieu d'une liste en texte brut"
+
+#~ msgid "Switch to/from layout %d"
+#~ msgstr "Basculer vers/depuis la disposition %d"
+
+#~ msgid "Set layout %d"
+#~ msgstr "Définir la disposition %d"
+
 #~ msgid ""
 #~ "%s will be closed.\n"
 #~ "Do you want to kill the associated kernel and all of its clients?"
@@ -4951,9 +5476,6 @@ msgstr "Éditeur de texte"
 #~ msgid "Show collection contents"
 #~ msgstr "Afficher le contenu des séquences"
 
-#~ msgid "Show toolbar"
-#~ msgstr "Afficher la barre d'outils"
-
 #~ msgid ""
 #~ "Resizing cells of a table of such size could take a long time.\n"
 #~ "Do you want to continue anyway?"
@@ -5006,9 +5528,6 @@ msgstr "Éditeur de texte"
 #~ msgid "Open a Python interpreter at startup"
 #~ msgstr "Ouvrir un interpréteur Python au démarrage"
 
-#~ msgid "Spyder startup"
-#~ msgstr "Démarrage de Spyder"
-
 #~ msgid "Open an IPython console at startup"
 #~ msgstr "Ouvrir une console IPython au démarrage"
 
@@ -5069,9 +5588,6 @@ msgstr "Éditeur de texte"
 #~ msgid "Open text file"
 #~ msgstr "Ouvrir un fichier texte"
 
-#~ msgid "Save current file"
-#~ msgstr "Enregistrer le fichier en cours d'édition"
-
 #~ msgid ""
 #~ "Run current cell \n"
 #~ "(see Editor documentation \n"
@@ -5328,9 +5844,6 @@ msgstr "Éditeur de texte"
 #~ msgid "&Interact"
 #~ msgstr "&Interagir"
 
-#~ msgid "Interact toolbar"
-#~ msgstr "Barre d'outil d'interaction"
-
 #~ msgid ""
 #~ "The project explorer shows a tree view of projects: the root of this tree "
 #~ "is called the workspace.<br><br>Each project is associated to a simple "
@@ -5364,9 +5877,6 @@ msgstr "Éditeur de texte"
 #~ msgid "New file..."
 #~ msgstr "Nouveau fichier..."
 
-#~ msgid "Open outside Spyder"
-#~ msgstr "Ouvrir en dehors de Spyder"
-
 #~ msgid "<b>Unable to delete selected file</b><br><br>Error message:<br>%s"
 #~ msgstr ""
 #~ "<b>Impossible de supprimer le fichier sélectionné</b><br><br>Message "
@@ -5452,9 +5962,6 @@ msgstr "Éditeur de texte"
 #~ msgid "Please install <b>matplotlib</b>."
 #~ msgstr "Merci d'installer <b>matplotlib</b>."
 
-#~ msgid "Remote editing"
-#~ msgstr "Éditeurs dans le processus distant"
-
 #~ msgid ""
 #~ "Remote editing for NumPy arrays, PIL images, lists, tuples and "
 #~ "dictionaries"
diff --git a/spyderlib/locale/pt_BR/LC_MESSAGES/spyderlib.mo b/spyderlib/locale/pt_BR/LC_MESSAGES/spyderlib.mo
new file mode 100644
index 0000000..c7c130a
Binary files /dev/null and b/spyderlib/locale/pt_BR/LC_MESSAGES/spyderlib.mo differ
diff --git a/spyderlib/locale/pt_BR/LC_MESSAGES/spyderlib.po b/spyderlib/locale/pt_BR/LC_MESSAGES/spyderlib.po
new file mode 100644
index 0000000..373ad20
--- /dev/null
+++ b/spyderlib/locale/pt_BR/LC_MESSAGES/spyderlib.po
@@ -0,0 +1,5520 @@
+# -*- coding: utf-8 -*-
+# Spyder's brazilian portuguese translation file
+# Valter Nazianzeno <manipuladordedados at gmail.com>, 2014.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: 2.3\n"
+"POT-Creation-Date: 2015-08-29 22:49+COT\n"
+"PO-Revision-Date: 2015-02-26 03:04-0400\n"
+"Last-Translator: Valter Nazianzeno <manipuladordedados at gmail.com>\n"
+"Language-Team: pt_BR\n"
+"Language: pt_BR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: pygettext.py 1.5\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"X-Generator: Poedit 1.7.4\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+
+#: spyderlib/config/base.py:241
+msgid ""
+"Update LANGUAGE_CODES (inside config/base.py) if a new translation has been "
+"added to Spyder"
+msgstr ""
+
+#: spyderlib/config/ipython.py:23 spyderlib/config/ipython.py:25
+#: spyderlib/config/ipython.py:32
+msgid "IPython Console integration"
+msgstr "Integração com console IPython"
+
+#: spyderlib/config/main.py:29
+msgid "Python files"
+msgstr "Arquivos Python"
+
+#: spyderlib/config/main.py:30
+msgid "Cython/Pyrex files"
+msgstr "Arquivos Cython/Pyrex"
+
+#: spyderlib/config/main.py:31
+msgid "C files"
+msgstr "Arquivos C"
+
+#: spyderlib/config/main.py:32
+msgid "C++ files"
+msgstr "Arquivos C++"
+
+#: spyderlib/config/main.py:33
+msgid "OpenCL files"
+msgstr "Arquivos OpenCL"
+
+#: spyderlib/config/main.py:34
+msgid "Fortran files"
+msgstr "Arquivos Fortran"
+
+#: spyderlib/config/main.py:35
+msgid "IDL files"
+msgstr "Arquivos IDL"
+
+#: spyderlib/config/main.py:36
+msgid "MATLAB files"
+msgstr "Arquivos MATLAB"
+
+#: spyderlib/config/main.py:37
+msgid "Julia files"
+msgstr "Arquivos Julia"
+
+#: spyderlib/config/main.py:38
+msgid "Yaml files"
+msgstr "Arquivos Yaml"
+
+#: spyderlib/config/main.py:39
+msgid "Patch and diff files"
+msgstr "Arquivos Patch e diff"
+
+#: spyderlib/config/main.py:40
+msgid "Batch files"
+msgstr "Arquivos Batch"
+
+#: spyderlib/config/main.py:41 spyderlib/utils/iofuncs.py:500
+msgid "Text files"
+msgstr "Arquivos de texto"
+
+#: spyderlib/config/main.py:42
+msgid "reStructured Text files"
+msgstr "Arquivos de texto reeStruturado"
+
+#: spyderlib/config/main.py:43
+msgid "gettext files"
+msgstr "Arquivos gettext "
+
+#: spyderlib/config/main.py:44
+msgid "NSIS files"
+msgstr "Arquivos NSIS "
+
+#: spyderlib/config/main.py:45
+msgid "Web page files"
+msgstr "Arquivos de Páginas web"
+
+#: spyderlib/config/main.py:46
+msgid "XML files"
+msgstr "Arquivos XML"
+
+#: spyderlib/config/main.py:47
+msgid "Javascript files"
+msgstr "Arquivos Javascript"
+
+#: spyderlib/config/main.py:48
+msgid "Json files"
+msgstr "Arquivos Json"
+
+#: spyderlib/config/main.py:49
+msgid "IPython notebooks"
+msgstr "Notebooks do IPython"
+
+#: spyderlib/config/main.py:50
+msgid "Enaml files"
+msgstr "Arquivos Enaml"
+
+#: spyderlib/config/main.py:51
+msgid "Configuration files"
+msgstr "Arquivos de Configuração"
+
+#: spyderlib/config/main.py:58 spyderlib/widgets/explorer.py:660
+msgid "All files"
+msgstr "Todos os arquivos"
+
+#: spyderlib/plugins/__init__.py:513 spyderlib/plugins/editor.py:95
+#: spyderlib/plugins/editor.py:551 spyderlib/plugins/editor.py:1600
+#: spyderlib/plugins/inspector.py:139 spyderlib/plugins/inspector.py:419
+#: spyderlib/widgets/editor.py:357
+#: spyderlib/widgets/sourcecode/codeeditor.py:95
+#: spyderlib/widgets/sourcecode/codeeditor.py:2902
+msgid "Editor"
+msgstr "Editor"
+
+#: spyderlib/plugins/configdialog.py:133
+#, fuzzy
+msgid "Reset to defaults"
+msgstr "Restaurar os valores padrões."
+
+#: spyderlib/plugins/configdialog.py:145
+msgid "Preferences"
+msgstr "Preferências"
+
+#: spyderlib/plugins/configdialog.py:473
+msgid "Invalid directory path"
+msgstr "Caminho de diretório inválido"
+
+#: spyderlib/plugins/configdialog.py:476 spyderlib/plugins/configdialog.py:491
+#: spyderlib/plugins/runconfig.py:176 spyderlib/plugins/runconfig.py:240
+#: spyderlib/plugins/workingdirectory.py:295 spyderlib/widgets/explorer.py:574
+#: spyderlib/widgets/externalshell/pythonshell.py:640
+#: spyderlib/widgets/findinfiles.py:505 spyderlib/widgets/pathmanager.py:223
+#: spyderlib/widgets/projectexplorer.py:899
+msgid "Select directory"
+msgstr "Selecionar diretório"
+
+#: spyderlib/plugins/configdialog.py:503
+msgid "Invalid file path"
+msgstr "Caminho de arquivo inválido "
+
+#: spyderlib/plugins/configdialog.py:506 spyderlib/plugins/configdialog.py:523
+msgid "Select file"
+msgstr "Selecionar arquivo"
+
+#: spyderlib/plugins/configdialog.py:522
+msgid "All files (*)"
+msgstr "Todos os arquivos (*)"
+
+#: spyderlib/plugins/configdialog.py:595 spyderlib/widgets/formlayout.py:214
+msgid "Bold"
+msgstr "Negrito"
+
+#: spyderlib/plugins/configdialog.py:598 spyderlib/widgets/formlayout.py:209
+msgid "Italic"
+msgstr "Itálico"
+
+#: spyderlib/plugins/configdialog.py:640
+msgid "Font: "
+msgstr "Fonte:"
+
+#: spyderlib/plugins/configdialog.py:644
+msgid "Size: "
+msgstr "Tamanho:"
+
+#: spyderlib/plugins/configdialog.py:653 spyderlib/plugins/history.py:48
+msgid "Font style"
+msgstr "Estilo de fonte"
+
+#: spyderlib/plugins/configdialog.py:708
+msgid "Spyder needs to restart to change the following setting:"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:711
+msgid "Spyder needs to restart to change the following settings:"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:713
+msgid "Do you wish to restart now?"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:719
+msgid "Information"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:734
+msgid "General"
+msgstr "Geral"
+
+#: spyderlib/plugins/configdialog.py:741 spyderlib/plugins/editor.py:104
+#: spyderlib/plugins/externalconsole.py:67
+#: spyderlib/plugins/ipythonconsole.py:162
+msgid "Interface"
+msgstr "Interface"
+
+#: spyderlib/plugins/configdialog.py:744
+msgid "Qt windows style"
+msgstr "Tema do Qt"
+
+#: spyderlib/plugins/configdialog.py:750
+msgid "Icon theme"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:755
+msgid "Language"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:759
+msgid "Use a single instance"
+msgstr "Usar uma única instância "
+
+#: spyderlib/plugins/configdialog.py:761
+msgid ""
+"Set this to open external<br> Python files in an already running instance "
+"(Requires a restart)"
+msgstr ""
+"Selecione esta opção<br> para abrir arquivos externos de Python nessa "
+"instância atual (Requer que seja reiniciado)"
+
+#: spyderlib/plugins/configdialog.py:764
+#, fuzzy
+msgid "Vertical title bars in panes"
+msgstr "Abas de título verticais para os componentes"
+
+#: spyderlib/plugins/configdialog.py:766
+msgid "Vertical tabs in panes"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:768
+#, fuzzy
+msgid "Animated toolbars and panes"
+msgstr "Aba de ferramentas e componentes animados"
+
+#: spyderlib/plugins/configdialog.py:770
+msgid "Tear off menus"
+msgstr "Separar os menus"
+
+#: spyderlib/plugins/configdialog.py:771
+msgid "Set this to detach any<br> menu from the main window"
+msgstr "Habilite esta opção<br> se deseja separar os menus da janela principal"
+
+#: spyderlib/plugins/configdialog.py:773
+msgid "Custom margin for panes:"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:782
+msgid "Prompt when exiting"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:813
+msgid "Status bar"
+msgstr "Barra de status"
+
+#: spyderlib/plugins/configdialog.py:814
+#, fuzzy
+msgid "Show status bar"
+msgstr "Mostrar barra de abas"
+
+#: spyderlib/plugins/configdialog.py:816
+msgid "Show memory usage every"
+msgstr "Mostrar uso da memória a cada"
+
+#: spyderlib/plugins/configdialog.py:825
+msgid "Show CPU usage every"
+msgstr "Mostrar uso da CPU a cada"
+
+#: spyderlib/plugins/configdialog.py:858
+msgid "Debugging"
+msgstr "Depuração"
+
+#: spyderlib/plugins/configdialog.py:859
+msgid "Pop up internal console when internal errors appear"
+msgstr "Mostrar o terminal interno quando houver erros"
+
+#: spyderlib/plugins/configdialog.py:868
+msgid "Updates"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:869 spyderlib/spyder.py:2872
+msgid "Check for updates on startup"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:902
+msgid "Syntax coloring"
+msgstr "Sintaxe colorida"
+
+#: spyderlib/plugins/configdialog.py:911
+msgid "Background:"
+msgstr "Fundo:"
+
+#: spyderlib/plugins/configdialog.py:912
+#: spyderlib/widgets/sourcecode/codeeditor.py:104
+msgid "Current line:"
+msgstr "Linha atual:"
+
+#: spyderlib/plugins/configdialog.py:913
+msgid "Current cell:"
+msgstr "Célula selecionada:"
+
+#: spyderlib/plugins/configdialog.py:914
+msgid "Occurence:"
+msgstr "Ocorrência:"
+
+#: spyderlib/plugins/configdialog.py:915
+msgid "Link:"
+msgstr "Link:"
+
+#: spyderlib/plugins/configdialog.py:916
+msgid "Side areas:"
+msgstr "Áreas laterais:"
+
+#: spyderlib/plugins/configdialog.py:917
+msgid "Matched parentheses:"
+msgstr "Parênteses fechados:"
+
+#: spyderlib/plugins/configdialog.py:918
+msgid "Unmatched parentheses:"
+msgstr "Parênteses abertos:"
+
+#: spyderlib/plugins/configdialog.py:919
+msgid "Normal text:"
+msgstr "Texto normal:"
+
+#: spyderlib/plugins/configdialog.py:920
+msgid "Keyword:"
+msgstr "Palavra chave:"
+
+#: spyderlib/plugins/configdialog.py:921
+msgid "Builtin:"
+msgstr "Objeto integrado:"
+
+#: spyderlib/plugins/configdialog.py:922
+msgid "Definition:"
+msgstr "Definição:"
+
+#: spyderlib/plugins/configdialog.py:923
+msgid "Comment:"
+msgstr "Comentário:"
+
+#: spyderlib/plugins/configdialog.py:924
+msgid "String:"
+msgstr "String:"
+
+#: spyderlib/plugins/configdialog.py:925
+msgid "Number:"
+msgstr "Número:"
+
+#: spyderlib/plugins/configdialog.py:926
+msgid "Instance:"
+msgstr "Instância:"
+
+#: spyderlib/plugins/configdialog.py:932
+msgid "Color scheme"
+msgstr "Esquema de cores"
+
+#: spyderlib/plugins/configdialog.py:954 spyderlib/plugins/shortcuts.py:776
+msgid "Reset to default values"
+msgstr "Restaurar os valores padrões."
+
+#: spyderlib/plugins/console.py:109
+msgid "Internal console"
+msgstr "Console interno"
+
+#: spyderlib/plugins/console.py:129 spyderlib/spyder.py:869
+#: spyderlib/widgets/ipython.py:595
+msgid "&Quit"
+msgstr "&Sair"
+
+#: spyderlib/plugins/console.py:131 spyderlib/spyder.py:871
+msgid "Quit"
+msgstr "Sair"
+
+#: spyderlib/plugins/console.py:134 spyderlib/plugins/externalconsole.py:1039
+msgid "&Run..."
+msgstr "E&xecutar"
+
+#: spyderlib/plugins/console.py:136 spyderlib/plugins/externalconsole.py:1040
+msgid "Run a Python script"
+msgstr "Executar um script Python"
+
+#: spyderlib/plugins/console.py:139
+msgid "Environment variables..."
+msgstr "Variáveis de ambiente..."
+
+#: spyderlib/plugins/console.py:141
+msgid "Show and edit environment variables (for current session)"
+msgstr "Mostrar e editar as variáveis de ambiente (para a sessão atual)"
+
+#: spyderlib/plugins/console.py:145
+msgid "Show sys.path contents..."
+msgstr "Mostrar conteúdo da sys.path..."
+
+#: spyderlib/plugins/console.py:147
+msgid "Show (read-only) sys.path"
+msgstr "Mostrar conteúdo da sys.path em modo de leitura"
+
+#: spyderlib/plugins/console.py:150
+msgid "Buffer..."
+msgstr "Buffer..."
+
+#: spyderlib/plugins/console.py:151 spyderlib/plugins/externalconsole.py:87
+#: spyderlib/plugins/history.py:41
+msgid "Set maximum line count"
+msgstr "Definir número máximo de linhas"
+
+#: spyderlib/plugins/console.py:154 spyderlib/plugins/explorer.py:67
+#: spyderlib/plugins/history.py:169 spyderlib/plugins/inspector.py:388
+#: spyderlib/plugins/projectexplorer.py:68
+msgid "&Font..."
+msgstr "&Fonte..."
+
+#: spyderlib/plugins/console.py:155 spyderlib/plugins/history.py:170
+msgid "Set shell font style"
+msgstr "Definir tipo de fonte do shell"
+
+#: spyderlib/plugins/console.py:158
+msgid "External editor path..."
+msgstr "Caminho de editor externo:"
+
+#: spyderlib/plugins/console.py:159
+msgid "Set external editor executable path"
+msgstr "Definir caminho de editor externo"
+
+#: spyderlib/plugins/console.py:162 spyderlib/plugins/editor.py:139
+#: spyderlib/plugins/externalconsole.py:88 spyderlib/plugins/history.py:44
+#: spyderlib/plugins/history.py:172 spyderlib/plugins/inspector.py:180
+#: spyderlib/plugins/inspector.py:391
+msgid "Wrap lines"
+msgstr "Ajuste de linha automático"
+
+#: spyderlib/plugins/console.py:165 spyderlib/plugins/editor.py:181
+#: spyderlib/plugins/externalconsole.py:133
+#: spyderlib/plugins/ipythonconsole.py:172
+msgid "Display balloon tips"
+msgstr "Mostrar sugestões"
+
+#: spyderlib/plugins/console.py:169 spyderlib/plugins/editor.py:175
+#: spyderlib/plugins/externalconsole.py:127
+msgid "Automatic code completion"
+msgstr "Completar código automáticamente"
+
+#: spyderlib/plugins/console.py:173 spyderlib/plugins/editor.py:179
+#: spyderlib/plugins/externalconsole.py:131
+msgid "Enter key selects completion"
+msgstr "A tecla Enter seleciona o resultado a completar"
+
+#: spyderlib/plugins/console.py:178
+msgid "Internal console settings"
+msgstr "Configurações do console interno"
+
+#: spyderlib/plugins/console.py:231 spyderlib/plugins/externalconsole.py:1220
+msgid "Run Python script"
+msgstr "Executar script Python"
+
+#: spyderlib/plugins/console.py:232 spyderlib/plugins/externalconsole.py:226
+#: spyderlib/plugins/externalconsole.py:1221 spyderlib/widgets/explorer.py:675
+msgid "Python scripts"
+msgstr "Scripts Python"
+
+#: spyderlib/plugins/console.py:278 spyderlib/plugins/explorer.py:117
+#: spyderlib/plugins/history.py:285 spyderlib/plugins/inspector.py:665
+#: spyderlib/plugins/projectexplorer.py:126
+msgid "Select a new font"
+msgstr "Selecionar uma nova fonte"
+
+#: spyderlib/plugins/console.py:286
+msgid "Buffer"
+msgstr "Buffer"
+
+#: spyderlib/plugins/console.py:287
+msgid "Maximum line count"
+msgstr "Número máximo de linhas"
+
+#: spyderlib/plugins/console.py:297
+msgid "External editor"
+msgstr "Editor externo"
+
+#: spyderlib/plugins/console.py:298
+msgid "External editor executable path:"
+msgstr "Caminho do executável do editor externo:"
+
+#: spyderlib/plugins/editor.py:101
+msgid "Edit template for new modules"
+msgstr "Editar template para novos módulos"
+
+#: spyderlib/plugins/editor.py:106
+msgid "Text and margin font style"
+msgstr "Estilo de fonte para o texto e margens"
+
+#: spyderlib/plugins/editor.py:109
+msgid "Sort files according to full path"
+msgstr "Ordenar arquivos seguindo seu caminho completo"
+
+#: spyderlib/plugins/editor.py:111
+msgid "Show tab bar"
+msgstr "Mostrar barra de abas"
+
+#: spyderlib/plugins/editor.py:118 spyderlib/plugins/editor.py:195
+#: spyderlib/plugins/externalconsole.py:83
+#: spyderlib/plugins/externalconsole.py:126 spyderlib/plugins/history.py:43
+#: spyderlib/plugins/inspector.py:179 spyderlib/plugins/ipythonconsole.py:206
+msgid "Source code"
+msgstr "Código fonte"
+
+#: spyderlib/plugins/editor.py:119
+msgid "Show line numbers"
+msgstr "Mostrar número de linhas"
+
+#: spyderlib/plugins/editor.py:120 spyderlib/plugins/editor.py:916
+msgid "Show blank spaces"
+msgstr ""
+
+#: spyderlib/plugins/editor.py:121
+msgid "Show vertical line after"
+msgstr "Mostrar uma linha vertical depois de"
+
+#: spyderlib/plugins/editor.py:122
+msgid "characters"
+msgstr "caracteres"
+
+#: spyderlib/plugins/editor.py:127
+msgid "Highlight current line"
+msgstr "Realçar linha atual"
+
+#: spyderlib/plugins/editor.py:129
+msgid "Highlight current cell"
+msgstr "Realçar célula atual"
+
+#: spyderlib/plugins/editor.py:131
+msgid "Highlight occurences after"
+msgstr "Realçar ocorrências depois de"
+
+#: spyderlib/plugins/editor.py:142 spyderlib/plugins/history.py:52
+#: spyderlib/plugins/inspector.py:183
+msgid "Syntax color scheme: "
+msgstr "Esquema de cores da sintaxe:"
+
+#: spyderlib/plugins/editor.py:164 spyderlib/plugins/runconfig.py:321
+#: spyderlib/plugins/runconfig.py:443 spyderlib/plugins/runconfig.py:448
+#: spyderlib/spyder.py:2501 spyderlib/utils/programs.py:175
+#: spyderlib/widgets/explorer.py:240
+#: spyderlib/widgets/externalshell/baseshell.py:140
+msgid "Run"
+msgstr "Executar"
+
+#: spyderlib/plugins/editor.py:165
+msgid "Save all files before running script"
+msgstr "Salvar tudo antes de executar um script"
+
+#: spyderlib/plugins/editor.py:168
+msgid "Run selection"
+msgstr "Executar seleção"
+
+#: spyderlib/plugins/editor.py:169
+msgid "Maintain focus in the Editor after running cells or selections"
+msgstr "Manter o foco no editor depois de executar células ou seleções"
+
+#: spyderlib/plugins/editor.py:172 spyderlib/plugins/externalconsole.py:334
+msgid "Introspection"
+msgstr "Introspecção"
+
+#: spyderlib/plugins/editor.py:177 spyderlib/plugins/externalconsole.py:129
+msgid "Case sensitive code completion"
+msgstr "Diferenciar entre maiúsculas e minusculas ao completar código"
+
+#: spyderlib/plugins/editor.py:182
+msgid "Link to object definition"
+msgstr "Link para a definição do objeto"
+
+#: spyderlib/plugins/editor.py:184
+msgid ""
+"If this option is enabled, clicking on an object\n"
+"name (left-click + Ctrl key) will go this object\n"
+"definition (if resolved)."
+msgstr ""
+"Se esta opção estiver ativada, clicando no nome\n"
+"de um objeto (clique-esquerdo + Ctrl) o editor irá\n"
+"mostrar a definição do mesmo."
+
+#: spyderlib/plugins/editor.py:188
+msgid ""
+"<b>Warning:</b><br>The Python module <i>rope</i> is not installed on this "
+"computer: calltips, code completion and go-to-definition features won't be "
+"available."
+msgstr ""
+"<b>Aviso:</b><br>O módulo <i>rope</i> não está instalado neste computador: "
+"Por tanto a completação de código, balões de dicas e o método ir para função "
+"não estão disponíveis."
+
+#: spyderlib/plugins/editor.py:196
+msgid "Automatic insertion of parentheses, braces and brackets"
+msgstr "Inserção automática de parênteses, chaves e colchetes"
+
+#: spyderlib/plugins/editor.py:199
+msgid "Automatic insertion of closing quotes"
+msgstr "Inserção automática de aspas"
+
+#: spyderlib/plugins/editor.py:201
+msgid "Automatic insertion of colons after 'for', 'if', 'def', etc"
+msgstr "Inserção automática de \":\" depois de 'for', 'if', 'def', etc"
+
+#: spyderlib/plugins/editor.py:204
+msgid "Automatic indentation after 'else', 'elif', etc."
+msgstr "Indentação automática depois do 'else', 'elif', etc."
+
+#: spyderlib/plugins/editor.py:206
+msgid "Indentation characters: "
+msgstr "Caracteres de indentação:"
+
+#: spyderlib/plugins/editor.py:207
+msgid "4 spaces"
+msgstr "4 espaços"
+
+#: spyderlib/plugins/editor.py:208
+msgid "2 spaces"
+msgstr "2 espaços"
+
+#: spyderlib/plugins/editor.py:209
+msgid "tab"
+msgstr "tabulador"
+
+#: spyderlib/plugins/editor.py:210
+msgid "Tab stop width:"
+msgstr "Largura da tabulação:"
+
+#: spyderlib/plugins/editor.py:210
+msgid "pixels"
+msgstr "pixels"
+
+#: spyderlib/plugins/editor.py:212
+msgid "Tab always indent"
+msgstr "Sempre indentar com a tecla Tab"
+
+#: spyderlib/plugins/editor.py:214
+msgid ""
+"If enabled, pressing Tab will always indent,\n"
+"even when the cursor is not at the beginning\n"
+"of a line (when this option is enabled, code\n"
+"completion may be triggered using the alternate\n"
+"shortcut: Ctrl+Space)"
+msgstr ""
+"Se ativada, pressionando Tab o código\n"
+"será indentado, mesmo se o cursor não estiver\n"
+"no inicio da linha (se essa opção for ativada a\n"
+"completação de código poderá ser usada\n"
+"pressionando Ctrl+Espaço)"
+
+#: spyderlib/plugins/editor.py:219
+msgid "Intelligent backspace"
+msgstr "Tecla de retorno (\"backspace\") inteligente"
+
+#: spyderlib/plugins/editor.py:221
+msgid "Automatically remove trailing spaces when saving files"
+msgstr "Remover automaticamente espaços em branco ao salvar arquivos"
+
+#: spyderlib/plugins/editor.py:225
+msgid "Analysis"
+msgstr "Análise"
+
+#: spyderlib/plugins/editor.py:227
+msgid "<i>(Refer to the {} page)</i>"
+msgstr ""
+
+#: spyderlib/plugins/editor.py:231
+#, fuzzy
+msgid "Real-time code analysis"
+msgstr "Análise de código em tempo real no editor"
+
+#: spyderlib/plugins/editor.py:233
+#, fuzzy
+msgid ""
+"<p>If enabled, Python source code will be analyzedusing pyflakes, lines "
+"containing errors or warnings will be highlighted.</p><p><u>Note</u>: add "
+"<b>analysis:ignore</b> in a comment to ignore code analysis warnings.</p>"
+msgstr ""
+"Se ativado, o  código fonte será analisado\n"
+"usando o pyflakes, linhas contendo erros ou\n"
+"avisos serão realçadas"
+
+#: spyderlib/plugins/editor.py:241
+msgid "Code analysis requires pyflakes %s+"
+msgstr "A análise de código requer pyflakes %s+"
+
+#: spyderlib/plugins/editor.py:243
+#, fuzzy
+msgid "Real-time code style analysis"
+msgstr "Análise de estilo em tempo real no editor."
+
+#: spyderlib/plugins/editor.py:245
+#, fuzzy
+msgid ""
+"<p>If enabled, Python source code will be analyzedusing pep8, lines that are "
+"not following PEP8 style guide will be highlighted.</p><p><u>Note</u>: add "
+"<b>analysis:ignore</b> in a comment to ignore style analysis warnings.</p>"
+msgstr ""
+"Se ativado, o  código fonte será analisado\n"
+"usando o pep8, linhas que não seguem o guia de estilo\n"
+"PEP8 serão realçadas"
+
+#: spyderlib/plugins/editor.py:252
+#, fuzzy
+msgid "Code annotations (TODO, FIXME, XXX, HINT, TIP, @todo)"
+msgstr "Tarefas (TODO, FIXME, XXX, HINT, TIP, @todo)"
+
+#: spyderlib/plugins/editor.py:255
+msgid "Perform analysis when saving file and every"
+msgstr "Fazer análise de código ao guardar arquivo e a cada"
+
+#: spyderlib/plugins/editor.py:259
+msgid "Perform analysis only when saving file"
+msgstr "Fazer análise só quando o arquivo for salvo"
+
+#: spyderlib/plugins/editor.py:318
+msgid "End-of-line characters"
+msgstr "Caracteres de fim de linha"
+
+#: spyderlib/plugins/editor.py:319
+msgid ""
+"When opening a text file containing mixed end-of-line characters (this may "
+"raise syntax errors in the consoles on Windows platforms), Spyder may fix "
+"the file automatically."
+msgstr ""
+"Quando for aberto um arquivo de texto que contenha vários tipos de "
+"caracteres de fim de linha (o qual pode dar erros no Windows). O Spyder pode "
+"consertar o arquivo automaticamente."
+
+#: spyderlib/plugins/editor.py:325
+msgid "Fix automatically and show warning message box"
+msgstr "Corrigir automaticamente e exibir uma mensagem de aviso"
+
+#: spyderlib/plugins/editor.py:336 spyderlib/plugins/externalconsole.py:332
+#: spyderlib/plugins/ipythonconsole.py:463
+#: spyderlib/plugins/variableexplorer.py:41
+msgid "Display"
+msgstr "Visualização"
+
+#: spyderlib/plugins/editor.py:338
+msgid "Code Introspection/Analysis"
+msgstr "Análise e introspecção de código"
+
+#: spyderlib/plugins/editor.py:341 spyderlib/plugins/externalconsole.py:336
+msgid "Advanced settings"
+msgstr "Configurações avançadas"
+
+#: spyderlib/plugins/editor.py:607 spyderlib/widgets/editortools.py:510
+msgid "Show/hide outline explorer"
+msgstr "Mostrar/esconder o explorador de código"
+
+#: spyderlib/plugins/editor.py:613
+msgid "Show/hide project explorer"
+msgstr "Mostrar/esconder o explorador de projetos"
+
+#: spyderlib/plugins/editor.py:621
+msgid "&New file..."
+msgstr "&Novo arquivo..."
+
+#: spyderlib/plugins/editor.py:622 spyderlib/plugins/workingdirectory.py:82
+#: spyderlib/widgets/explorer.py:652 spyderlib/widgets/explorer.py:659
+msgid "New file"
+msgstr "Novo arquivo"
+
+#: spyderlib/plugins/editor.py:629
+msgid "&Open..."
+msgstr "&Abrir..."
+
+#: spyderlib/plugins/editor.py:630 spyderlib/plugins/editor.py:1643
+#: spyderlib/plugins/workingdirectory.py:69
+msgid "Open file"
+msgstr "Abrir arquivo"
+
+#: spyderlib/plugins/editor.py:637
+msgid "&Revert"
+msgstr "Resta&urar"
+
+#: spyderlib/plugins/editor.py:638
+msgid "Revert file from disk"
+msgstr "Reverter arquivo do disco"
+
+#: spyderlib/plugins/editor.py:641
+msgid "&Save"
+msgstr "&Salvar"
+
+#: spyderlib/plugins/editor.py:642
+msgid "Save file"
+msgstr "Salvar arquivo"
+
+#: spyderlib/plugins/editor.py:649
+msgid "Sav&e all"
+msgstr "Sal&var tudo"
+
+#: spyderlib/plugins/editor.py:650
+msgid "Save all files"
+msgstr "Salvar todos os arquivos"
+
+#: spyderlib/plugins/editor.py:658
+msgid "Save &as..."
+msgstr "Salvar c&omo..."
+
+#: spyderlib/plugins/editor.py:659
+msgid "Save current file as..."
+msgstr "Salvar arquivo atual como..."
+
+#: spyderlib/plugins/editor.py:663 spyderlib/plugins/editor.py:664
+msgid "Print preview..."
+msgstr "Pré-visualizar impressão..."
+
+#: spyderlib/plugins/editor.py:665
+msgid "&Print..."
+msgstr "&Imprimir..."
+
+#: spyderlib/plugins/editor.py:666
+msgid "Print current file..."
+msgstr "Imprimir o arquivo atual..."
+
+#: spyderlib/plugins/editor.py:669
+msgid "&Close"
+msgstr "&Fechar"
+
+#: spyderlib/plugins/editor.py:670
+msgid "Close current file"
+msgstr "Fechar arquivo atual"
+
+#: spyderlib/plugins/editor.py:673
+msgid "C&lose all"
+msgstr "Fechar &tudo"
+
+#: spyderlib/plugins/editor.py:674
+msgid "Close all opened files"
+msgstr "Fechar todos os arquivos abertos"
+
+#: spyderlib/plugins/editor.py:681
+msgid "Set/Clear breakpoint"
+msgstr "Adicionar ou limpar um ponto de interrupção"
+
+#: spyderlib/plugins/editor.py:688
+msgid "Set/Edit conditional breakpoint"
+msgstr "Adicionar ou editar um ponto de interrupção condicional"
+
+#: spyderlib/plugins/editor.py:695
+msgid "Clear breakpoints in all files"
+msgstr "Limpar pontos de interrupção em todos os arquivos"
+
+#: spyderlib/plugins/editor.py:697
+msgid "Breakpoints"
+msgstr "Pontos de interrupção (Breakpoints)"
+
+#: spyderlib/plugins/editor.py:701
+msgid "Debug with winpdb"
+msgstr "Depurar com winpdb"
+
+#: spyderlib/plugins/editor.py:708 spyderlib/spyder.py:659
+msgid "&Debug"
+msgstr "&Depurar"
+
+#: spyderlib/plugins/editor.py:709
+msgid "Debug file"
+msgstr "Depurar arquivo"
+
+#: spyderlib/plugins/editor.py:713
+msgid "Step"
+msgstr "Executar linha"
+
+#: spyderlib/plugins/editor.py:714
+msgid "Run current line"
+msgstr "Executar linha selecionada"
+
+#: spyderlib/plugins/editor.py:720
+msgid "Continue"
+msgstr "Continuar"
+
+#: spyderlib/plugins/editor.py:721
+msgid "Continue execution until next breakpoint"
+msgstr "Continuar a execução até o próximo ponto de interrupção"
+
+#: spyderlib/plugins/editor.py:728
+msgid "Step Into"
+msgstr "Ingressar na função/método"
+
+#: spyderlib/plugins/editor.py:729
+msgid "Step into function or method of current line"
+msgstr "Ingressar na função ou método da linha atual"
+
+#: spyderlib/plugins/editor.py:736
+msgid "Step Return"
+msgstr "Sair da função/método"
+
+#: spyderlib/plugins/editor.py:737
+msgid "Run until current function or method returns"
+msgstr "Executar até que a função ou método atual terminem"
+
+#: spyderlib/plugins/editor.py:744
+msgid "Exit"
+msgstr "Sair"
+
+#: spyderlib/plugins/editor.py:745
+msgid "Exit Debug"
+msgstr "Terminar depuração"
+
+#: spyderlib/plugins/editor.py:756
+msgid "Debugging control"
+msgstr "Controle de depuração"
+
+#: spyderlib/plugins/editor.py:760 spyderlib/plugins/editor.py:1236
+#: spyderlib/spyder.py:654
+msgid "&Run"
+msgstr "E&xecutar"
+
+#: spyderlib/plugins/editor.py:761
+msgid "Run file"
+msgstr "Executar arquivo"
+
+#: spyderlib/plugins/editor.py:766
+msgid "&Configure..."
+msgstr "&Configurar..."
+
+#: spyderlib/plugins/editor.py:768
+#: spyderlib/widgets/externalshell/pythonshell.py:311
+msgid "Run settings"
+msgstr "Executar configurações"
+
+#: spyderlib/plugins/editor.py:776
+msgid "Re-run &last script"
+msgstr "Executar &novamente o último script"
+
+#: spyderlib/plugins/editor.py:778
+msgid "Run again last file"
+msgstr "Executar novamente o mesmo arquivo"
+
+#: spyderlib/plugins/editor.py:785
+#: spyderlib/widgets/sourcecode/codeeditor.py:2462
+msgid "Run &selection or current line"
+msgstr "Executar &seleção ou linha atual"
+
+#: spyderlib/plugins/editor.py:788
+msgid "Run selection or current line"
+msgstr "Executar seleção ou linha atual"
+
+#: spyderlib/plugins/editor.py:801
+msgid "Run cell"
+msgstr "Executar célula"
+
+#: spyderlib/plugins/editor.py:804
+msgid ""
+"Run current cell (Ctrl+Enter)\n"
+"[Use #%% to create cells]"
+msgstr ""
+"Executar a célula atual (Ctrl+Enter)\n"
+"[Usar #%% para criar células]"
+
+#: spyderlib/plugins/editor.py:809
+msgid "Run cell and advance"
+msgstr "Executar célula e avançar"
+
+#: spyderlib/plugins/editor.py:812
+msgid "Run current cell and go to the next one (Shift+Enter)"
+msgstr "Executar célula atual e ir para a próxima (Shift+Enter)"
+
+#: spyderlib/plugins/editor.py:818
+msgid "Show todo list"
+msgstr "Mostrar lista de tarefas"
+
+#: spyderlib/plugins/editor.py:819
+msgid "Show TODO/FIXME/XXX/HINT/TIP/@todo comments list"
+msgstr ""
+"Mostrar a lista de comentários dos\n"
+"TODO/FIXME/XXX/HINT/TIP/@todo"
+
+#: spyderlib/plugins/editor.py:826
+msgid "Show warning/error list"
+msgstr "Mostrar lista de erros e avisos"
+
+#: spyderlib/plugins/editor.py:827
+msgid "Show code analysis warnings/errors"
+msgstr "Mostrar erros e avisos da análise de código"
+
+#: spyderlib/plugins/editor.py:833
+msgid "Previous warning/error"
+msgstr "Aviso ou erro anterior"
+
+#: spyderlib/plugins/editor.py:834
+msgid "Go to previous code analysis warning/error"
+msgstr "Ir para linha anterior de aviso ou erro"
+
+#: spyderlib/plugins/editor.py:837
+msgid "Next warning/error"
+msgstr "Próximo aviso ou erro"
+
+#: spyderlib/plugins/editor.py:838
+msgid "Go to next code analysis warning/error"
+msgstr "Ir para próxima linha de aviso ou erro"
+
+#: spyderlib/plugins/editor.py:842
+msgid "Last edit location"
+msgstr "Última posição da edição"
+
+#: spyderlib/plugins/editor.py:843
+msgid "Go to last edit location"
+msgstr "Ir para posição anterior da edição"
+
+#: spyderlib/plugins/editor.py:849
+msgid "Previous cursor position"
+msgstr "Posição anterior do cursor"
+
+#: spyderlib/plugins/editor.py:850
+msgid "Go to previous cursor position"
+msgstr "Ir a posição anterior do cursor"
+
+#: spyderlib/plugins/editor.py:856
+msgid "Next cursor position"
+msgstr "Próxima posição do cursor"
+
+#: spyderlib/plugins/editor.py:857
+msgid "Go to next cursor position"
+msgstr "Ir para a próxima posição do cursor"
+
+#: spyderlib/plugins/editor.py:864
+#: spyderlib/widgets/sourcecode/codeeditor.py:2449
+msgid "Comment"
+msgstr "Comentar"
+
+#: spyderlib/plugins/editor.py:864
+#: spyderlib/widgets/sourcecode/codeeditor.py:2449
+msgid "Uncomment"
+msgstr "Descomentar"
+
+#: spyderlib/plugins/editor.py:865
+msgid "Comment current line or selection"
+msgstr "Comentar linha ou seleção atual"
+
+#: spyderlib/plugins/editor.py:869
+msgid "Add &block comment"
+msgstr "Adicionar &bloco de comentário "
+
+#: spyderlib/plugins/editor.py:870
+msgid "Add block comment around current line or selection"
+msgstr "Adicionar bloco de comentário ao redor da linha ou seleção atual"
+
+#: spyderlib/plugins/editor.py:876
+msgid "R&emove block comment"
+msgstr "R&emover bloco de comentário"
+
+#: spyderlib/plugins/editor.py:877
+msgid "Remove comment block around current line or selection"
+msgstr "Remover bloco de comentário ao redor da linha ou seleção atual"
+
+#: spyderlib/plugins/editor.py:888
+msgid "Indent"
+msgstr "Indentar"
+
+#: spyderlib/plugins/editor.py:889
+msgid "Indent current line or selection"
+msgstr "Indentar a linha ou seleção atual"
+
+#: spyderlib/plugins/editor.py:892
+msgid "Unindent"
+msgstr "Desfazer indentação"
+
+#: spyderlib/plugins/editor.py:893
+msgid "Unindent current line or selection"
+msgstr "Desfazer indentação da linha ou seleção atual"
+
+#: spyderlib/plugins/editor.py:898
+msgid "Carriage return and line feed (Windows)"
+msgstr "Carriage return e salto de linha (Windows)"
+
+#: spyderlib/plugins/editor.py:901
+msgid "Line feed (UNIX)"
+msgstr "Salto de linha (UNIX)"
+
+#: spyderlib/plugins/editor.py:904
+msgid "Carriage return (Mac)"
+msgstr "Carriage return (Mac)"
+
+#: spyderlib/plugins/editor.py:910
+msgid "Convert end-of-line characters"
+msgstr "Converter caracteres de fim de linha"
+
+#: spyderlib/plugins/editor.py:914
+msgid "Remove trailing spaces"
+msgstr "Remover espaços em branco"
+
+#: spyderlib/plugins/editor.py:918
+msgid "Fix indentation"
+msgstr "Consertar indentação"
+
+#: spyderlib/plugins/editor.py:919
+msgid "Replace tab characters by space characters"
+msgstr "Substituir caracteres de tabulação por espaços"
+
+#: spyderlib/plugins/editor.py:922
+msgid "Go to line..."
+msgstr "Ir para linha..."
+
+#: spyderlib/plugins/editor.py:930
+msgid "Set console working directory"
+msgstr "Definir diretório de trabalho"
+
+#: spyderlib/plugins/editor.py:932
+msgid ""
+"Set current console (and file explorer) working directory to current script "
+"directory"
+msgstr ""
+"Definir o diretório de trabalho do console (e do explorador de arquivos) "
+"para o diretório do script atual."
+
+#: spyderlib/plugins/editor.py:937
+msgid "Maximum number of recent files..."
+msgstr "Número máximo de arquivos recentes..."
+
+#: spyderlib/plugins/editor.py:940
+msgid "Clear recent files list"
+msgstr "Limpar lista de arquivos recentes"
+
+#: spyderlib/plugins/editor.py:940
+msgid "Clear this list"
+msgstr "Limpar esta lista"
+
+#: spyderlib/plugins/editor.py:942
+msgid "Open &recent"
+msgstr "Abrir &recente"
+
+#: spyderlib/plugins/editor.py:1224 spyderlib/spyder.py:635
+msgid "File toolbar"
+msgstr "Barra de arquivo"
+
+#: spyderlib/plugins/editor.py:1225 spyderlib/spyder.py:645
+msgid "Search toolbar"
+msgstr "Barra de pesquisa"
+
+#: spyderlib/plugins/editor.py:1226 spyderlib/spyder.py:650
+msgid "Source toolbar"
+msgstr "Barra de código"
+
+#: spyderlib/plugins/editor.py:1227 spyderlib/spyder.py:655
+msgid "Run toolbar"
+msgstr "Barra de execução "
+
+#: spyderlib/plugins/editor.py:1228 spyderlib/spyder.py:660
+msgid "Debug toolbar"
+msgstr "Barra de depuração"
+
+#: spyderlib/plugins/editor.py:1229 spyderlib/spyder.py:640
+msgid "Edit toolbar"
+msgstr "Barra de edição"
+
+#: spyderlib/plugins/editor.py:1232 spyderlib/spyder.py:633
+msgid "&File"
+msgstr "&Arquivo"
+
+#: spyderlib/plugins/editor.py:1233 spyderlib/spyder.py:639
+msgid "&Edit"
+msgstr "&Editar"
+
+#: spyderlib/plugins/editor.py:1234 spyderlib/spyder.py:644
+msgid "&Search"
+msgstr "&Pesquisar"
+
+#: spyderlib/plugins/editor.py:1235 spyderlib/spyder.py:649
+msgid "Sour&ce"
+msgstr "Códi&go"
+
+#: spyderlib/plugins/editor.py:1237 spyderlib/spyder.py:667
+msgid "&Tools"
+msgstr "&Ferramentas"
+
+#: spyderlib/plugins/editor.py:1238
+msgid "?"
+msgstr "?"
+
+#: spyderlib/plugins/editor.py:1458
+msgid "Spyder Editor"
+msgstr "Spyder Editor"
+
+#: spyderlib/plugins/editor.py:1459
+msgid "This is a temporary script file."
+msgstr "Este é um arquivo de script temporário."
+
+#: spyderlib/plugins/editor.py:1527
+msgid "untitled"
+msgstr "Sem título"
+
+#: spyderlib/plugins/editor.py:1601
+msgid "Maximum number of recent files"
+msgstr "Número máximo de arquivos recentes"
+
+#: spyderlib/plugins/editor.py:1726
+msgid "Printing..."
+msgstr "Imprimindo..."
+
+#: spyderlib/plugins/explorer.py:55
+msgid "File explorer"
+msgstr "Explorador de arquivos"
+
+#: spyderlib/plugins/explorer.py:68 spyderlib/plugins/inspector.py:389
+#: spyderlib/plugins/projectexplorer.py:69
+msgid "Set font style"
+msgstr "Definir estilo da fonte"
+
+#: spyderlib/plugins/externalconsole.py:49
+msgid "Interactive data plotting in the consoles"
+msgstr "Mostrar dados interativos no console"
+
+#: spyderlib/plugins/externalconsole.py:57
+#: spyderlib/plugins/externalconsole.py:1005
+#: spyderlib/plugins/inspector.py:419 spyderlib/plugins/runconfig.py:185
+#: spyderlib/plugins/runconfig.py:455
+#: spyderlib/widgets/externalshell/baseshell.py:107
+#: spyderlib/widgets/ipython.py:521
+msgid "Console"
+msgstr "Console"
+
+#: spyderlib/plugins/externalconsole.py:71
+msgid "One tab per script"
+msgstr "Uma aba por script"
+
+#: spyderlib/plugins/externalconsole.py:72
+#: spyderlib/widgets/externalshell/baseshell.py:173
+msgid "Show elapsed time"
+msgstr "Mostrar tempo de execução"
+
+#: spyderlib/plugins/externalconsole.py:73 spyderlib/widgets/explorer.py:1016
+msgid "Show icons and text"
+msgstr "Mostrar ícones e texto"
+
+#: spyderlib/plugins/externalconsole.py:85
+msgid "Buffer: "
+msgstr "Buffer:"
+
+#: spyderlib/plugins/externalconsole.py:85
+#: spyderlib/plugins/ipythonconsole.py:208
+msgid " lines"
+msgstr "linhas"
+
+#: spyderlib/plugins/externalconsole.py:90
+msgid "Merge process standard output/error channels"
+msgstr "Combinar os canais de saída/erro do processo"
+
+#: spyderlib/plugins/externalconsole.py:92
+msgid ""
+"Merging the output channels of the process means that\n"
+"the standard error won't be written in red anymore,\n"
+"but this has the effect of speeding up display."
+msgstr ""
+"Combinar os canais de saída do processo significa que\n"
+"o erro padrão não será escrito em vermelho, mas isso ajuda a\n"
+"melhorar a velocidade em que aparece o texto no console."
+
+#: spyderlib/plugins/externalconsole.py:96
+msgid "Colorize standard error channel using ANSI escape codes"
+msgstr "Colorir o canal de error padrão utilizando códigos de escape ANSI "
+
+#: spyderlib/plugins/externalconsole.py:98
+msgid ""
+"This method is the only way to have colorized standard\n"
+"error channel when the output channels have been merged."
+msgstr ""
+"Este método é a única forma de ter cor no canal de erro\n"
+"padrão quando os canais de saída forem combinados."
+
+#: spyderlib/plugins/externalconsole.py:114
+#: spyderlib/plugins/ipythonconsole.py:195
+#: spyderlib/widgets/arrayeditor.py:461
+#: spyderlib/widgets/dataframeeditor.py:516
+msgid "Background color"
+msgstr "Cor de fundo"
+
+#: spyderlib/plugins/externalconsole.py:115
+msgid ""
+"This option will be applied the next time a Python console or a terminal is "
+"opened."
+msgstr ""
+"Esta opção será ativada na próxima vez que um console Python ou um terminal "
+"for aberto."
+
+#: spyderlib/plugins/externalconsole.py:118
+msgid "Light background (white color)"
+msgstr "Fundo claro (cor branca)"
+
+#: spyderlib/plugins/externalconsole.py:143
+msgid "User Module Reloader (UMR)"
+msgstr "Recarregador de Módulos do Usuário (RMU)"
+
+#: spyderlib/plugins/externalconsole.py:144
+msgid ""
+"UMR forces Python to reload modules which were imported when executing a \n"
+"script in the external console with the 'runfile' function."
+msgstr ""
+"O RMU força o Python a recarregar os módulos que foram importados\n"
+"durante a execução de um arquivo no console com a função 'runfile'."
+
+#: spyderlib/plugins/externalconsole.py:147
+msgid "Enable UMR"
+msgstr "Ativar RMU"
+
+#: spyderlib/plugins/externalconsole.py:148
+msgid ""
+"This option will enable the User Module Reloader (UMR) in Python/IPython "
+"consoles. UMR forces Python to reload deeply modules during import when "
+"running a Python script using the Spyder's builtin function <b>runfile</b>."
+"<br><br><b>1.</b> UMR may require to restart the console in which it will be "
+"called (otherwise only newly imported modules will be reloaded when "
+"executing scripts).<br><br><b>2.</b> If errors occur when re-running a PyQt-"
+"based program, please check that the Qt objects are properly destroyed (e.g. "
+"you may have to use the attribute <b>Qt.WA_DeleteOnClose</b> on your main "
+"window, using the <b>setAttribute</b> method)"
+msgstr ""
+"Esta opção ativará o Recarregador de Módulos do Usuário (RMU) nos consoles "
+"do Python/IPython. O RMU força o Python a recarregar profundamente os "
+"módulos que foram importados ao executar um arquivo do Python, usando a "
+"função incorporada do Spyder chamada <b>runfile</b>.<br><br><b>1.</b> O RMU "
+"pode necessitar que se reinicie o terminal em o qual será utilizado (de "
+"outra forma, só os módulos que foram importados em último lugar serão "
+"recarregados ao executar um arquivo).<br><br><b>2.</b> Se ocorrer algum erro "
+"ao re-executar programas baseados no PyQt ou PySide, por favor verifique se "
+"os objetos do Qt foram destruídos apropriadamente (por exemplo, você pode "
+"ter que utilizar o atributo <b>Qt.WA_DeleteOnClose</b> em sua janela "
+"principal, utilizando o método <b>setAttribute</b>)."
+
+#: spyderlib/plugins/externalconsole.py:164
+msgid "Show reloaded modules list"
+msgstr "Mostrar lista de módulos que foram recarregados"
+
+#: spyderlib/plugins/externalconsole.py:165
+msgid "Please note that these changes will be applied only to new consoles"
+msgstr ""
+"Por favor tenha em nota que as mudanças só serão aplicadas em novos consoles"
+
+#: spyderlib/plugins/externalconsole.py:169
+msgid "Set UMR excluded (not reloaded) modules"
+msgstr "Definir lista de módulos excluídos pelo RMU"
+
+#: spyderlib/plugins/externalconsole.py:180
+msgid "Python executable"
+msgstr "Executável Python"
+
+#: spyderlib/plugins/externalconsole.py:182
+msgid ""
+"Select the Python interpreter executable binary in which Spyder will run "
+"scripts:"
+msgstr "Selecione o caminho do interpretador Python que deseja utilizar:"
+
+#: spyderlib/plugins/externalconsole.py:185
+msgid "Default (i.e. the same as Spyder's)"
+msgstr "Padrão (o mesmo do Spyder)"
+
+#: spyderlib/plugins/externalconsole.py:189
+msgid "Use the following Python interpreter:"
+msgstr "Usar o seguinte interpretador:"
+
+#: spyderlib/plugins/externalconsole.py:193
+msgid "Executables"
+msgstr "Executáveis "
+
+#: spyderlib/plugins/externalconsole.py:211
+msgid "PYTHONSTARTUP replacement"
+msgstr "Substituto do PYTHONSTARTUP"
+
+#: spyderlib/plugins/externalconsole.py:213
+msgid ""
+"This option will override the PYTHONSTARTUP environment variable which\n"
+"defines the script to be executed during the Python console startup."
+msgstr ""
+"Esta opção modificará a variável de ambiente PYTHONSTARTUP, a qual\n"
+"define o script que é executado durante a inicialização do console\n"
+"Python."
+
+#: spyderlib/plugins/externalconsole.py:218
+msgid "Default PYTHONSTARTUP script"
+msgstr "Script PYTHONSTARTUP padrão"
+
+#: spyderlib/plugins/externalconsole.py:222
+msgid "Use the following startup script:"
+msgstr "Usar o seguinte script de inicialização:"
+
+#: spyderlib/plugins/externalconsole.py:239
+msgid "Monitor"
+msgstr "Monitor"
+
+#: spyderlib/plugins/externalconsole.py:240
+msgid ""
+"The monitor provides introspection features to console: code completion, "
+"calltips and variable explorer. Because it relies on several modules, "
+"disabling the monitor may be useful to accelerate console startup."
+msgstr ""
+"O monitor fornece características de introspecção para o console: "
+"completador de código, sugestões e o explorador de variáveis. Porque ele "
+"depende de vários módulos adicionais, desativando o monitor é possível "
+"acelerar a inicialização do console."
+
+#: spyderlib/plugins/externalconsole.py:247
+msgid "Enable monitor"
+msgstr "Ativar monitor"
+
+#: spyderlib/plugins/externalconsole.py:260
+msgid "Default library"
+msgstr "Biblioteca padrão"
+
+#: spyderlib/plugins/externalconsole.py:265
+#, fuzzy
+msgid "Qt-Python Bindings"
+msgstr "Seleção da biblioteca de ligação entre o Qt e Python:"
+
+#: spyderlib/plugins/externalconsole.py:267
+msgid "Library:"
+msgstr ""
+
+#: spyderlib/plugins/externalconsole.py:269
+msgid ""
+"This option will act on<br> libraries such as Matplotlib, guidata or ETS"
+msgstr ""
+"Esta opção trará efeitos <br> em bibliotecas como Matplotlib, guidata ou ETS"
+
+#: spyderlib/plugins/externalconsole.py:278
+#: spyderlib/plugins/ipythonconsole.py:465
+msgid "Graphics"
+msgstr "Gráficos"
+
+#: spyderlib/plugins/externalconsole.py:279
+msgid ""
+"Decide which backend to use to display graphics. If unsure, please select "
+"the <b>Automatic</b> backend.<br><br><b>Note:</b> We support a very limited "
+"number of backends in our Python consoles. If you prefer to work with a "
+"different one, please use an IPython console."
+msgstr ""
+
+#: spyderlib/plugins/externalconsole.py:295
+#: spyderlib/plugins/ipythonconsole.py:270
+msgid "Backend:"
+msgstr "Saída:"
+
+#: spyderlib/plugins/externalconsole.py:297
+#: spyderlib/plugins/ipythonconsole.py:272
+msgid "This option will be applied the next time a console is opened."
+msgstr "Esta opção será aplicada na próxima vez que um console for aberto."
+
+#: spyderlib/plugins/externalconsole.py:308
+msgid "Enthought Tool Suite"
+msgstr "Enthought Tool Suite"
+
+#: spyderlib/plugins/externalconsole.py:309
+msgid ""
+"Enthought Tool Suite (ETS) supports PyQt4 (qt4) and wxPython (wx) graphical "
+"user interfaces."
+msgstr ""
+"Enthought Tool Suite (ETS) suporta as bibliotecas gráficas PyQt4 (qt4) e \n"
+"wxPython (wx)."
+
+#: spyderlib/plugins/externalconsole.py:313
+msgid "ETS_TOOLKIT:"
+msgstr "ETS_TOOLKIT:"
+
+#: spyderlib/plugins/externalconsole.py:338
+msgid "External modules"
+msgstr "Módulos externos"
+
+#: spyderlib/plugins/externalconsole.py:374
+#: spyderlib/plugins/externalconsole.py:617
+#: spyderlib/plugins/ipythonconsole.py:114
+#: spyderlib/plugins/ipythonconsole.py:832 spyderlib/spyder.py:1803
+#: spyderlib/spyder.py:1825 spyderlib/spyder.py:1888 spyderlib/spyder.py:2774
+#: spyderlib/utils/environ.py:95 spyderlib/utils/environ.py:108
+#: spyderlib/widgets/dicteditor.py:452
+msgid "Warning"
+msgstr "Aviso"
+
+#: spyderlib/plugins/externalconsole.py:375
+msgid ""
+"You selected a <b>Python %d</b> interpreter for the console but Spyder is "
+"running on <b>Python %d</b>!.<br><br>Although this is possible, we recommend "
+"you to install and run Spyder directly with your selected interpreter, to "
+"avoid seeing false warnings and errors due to the incompatible syntax "
+"between these two Python versions."
+msgstr ""
+"Você selecionou um interpretador <b>Python %d</b> para o console, mas o "
+"Spyder está sendo executado em <b>Python %d</b>!.<br><br>Embora isso seja "
+"possível, nós recomendamos instalar e executar o Spyder diretamente com o "
+"interpretador selecionado, para evitar ver falsos erros e avisos no Editor "
+"devido a sintaxe incompatível entre estas duas versões do Python."
+
+#: spyderlib/plugins/externalconsole.py:538
+msgid "Trying to kill a kernel?"
+msgstr "Tentando matar um kernel?"
+
+#: spyderlib/plugins/externalconsole.py:539
+msgid ""
+"You can't close this kernel because it has one or more consoles connected to "
+"it.<br><br>You need to close them instead or you can kill the kernel using "
+"the second button from right to left."
+msgstr ""
+"Você não pode fechar este kernel porque tem um ou mais consoles conectados a "
+"ele.<br><br>Você deve fechá-lo previamente ou pode terminar o processo "
+"usando o segundo botão da direita para esquerda."
+
+#: spyderlib/plugins/externalconsole.py:618
+msgid ""
+"No Python console is currently selected to run <b>%s</b>.<br><br>Please "
+"select or open a new Python console and try again."
+msgstr ""
+"Nenhum console Python foi selecionado para executar <b>%s</b>.<br><br>Por "
+"favor selecione ou abra um novo console Python e tente novamente."
+
+#: spyderlib/plugins/externalconsole.py:698
+msgid ""
+"%s is already running in a separate process.\n"
+"Do you want to kill the process before starting a new one?"
+msgstr ""
+"%s já está sendo executado em um processo separado.\n"
+"Você deseja matar o processo antes de iniciar um novo?"
+
+#: spyderlib/plugins/externalconsole.py:858
+msgid "Kernel"
+msgstr "Kernel"
+
+#: spyderlib/plugins/externalconsole.py:868
+msgid ""
+"Either:<ol><li>Your IPython frontend and kernel versions are "
+"<b>incompatible</b> or</li><li>You <b>don't have</b> IPython installed in "
+"your external interpreter.</li></ol>In any case, we're sorry but we can't "
+"create a console for you."
+msgstr ""
+"Ou:<ol><li>Suas versões de kernel e da interface gráfica do IPython são "
+"<b>incompatíveis</b> ou</li><li>Você <b>não possui</b> o IPython instalado "
+"em seu interpretador externo.</li></ol>Nós lamentamos, mas não podemos criar "
+"um console do IPython para você."
+
+#: spyderlib/plugins/externalconsole.py:892
+msgid "Command Window"
+msgstr "Janela de comando"
+
+#: spyderlib/plugins/externalconsole.py:894
+msgid "Terminal"
+msgstr "Terminal"
+
+#: spyderlib/plugins/externalconsole.py:947
+#, fuzzy
+msgid "Kernel %s"
+msgstr "Kernel"
+
+#: spyderlib/plugins/externalconsole.py:1027
+msgid "Open a &Python console"
+msgstr "Abrir um console &Python"
+
+#: spyderlib/plugins/externalconsole.py:1031
+msgid "Open &command prompt"
+msgstr "Abrir &prompt de comando"
+
+#: spyderlib/plugins/externalconsole.py:1032
+msgid "Open a Windows command prompt"
+msgstr "Abrir o prompt de comando do Windows"
+
+#: spyderlib/plugins/externalconsole.py:1034
+msgid "Open a &terminal"
+msgstr "Abrir um &terminal"
+
+#: spyderlib/plugins/externalconsole.py:1035
+msgid "Open a terminal window"
+msgstr "Abrir uma janela de terminal"
+
+#: spyderlib/plugins/externalconsole.py:1196
+msgid "Open an IPython console"
+msgstr "Abrir um console IPython"
+
+#: spyderlib/plugins/externalconsole.py:1197
+msgid ""
+"The console monitor was disabled: the IPython kernel will be started as "
+"expected, but an IPython console will have to be connected manually to the "
+"kernel."
+msgstr ""
+"O monitor está desativado, por tanto será criado um kernel do IPython, mas "
+"você deverá conectar manualmente um interpretador ao mesmo."
+
+#: spyderlib/plugins/externalconsole.py:1229
+#: spyderlib/plugins/externalconsole.py:1242
+#: spyderlib/plugins/externalconsole.py:1246
+msgid "UMR"
+msgstr "RMU"
+
+#: spyderlib/plugins/externalconsole.py:1230
+msgid ""
+"UMR excluded modules:\n"
+"(example: guidata, guiqwt)"
+msgstr ""
+"Módulos excluídos pelo RMU:\n"
+"(Exemplo: guidata, guiqwt)"
+
+#: spyderlib/plugins/externalconsole.py:1243
+msgid ""
+"The following modules are not installed on your machine:\n"
+"%s"
+msgstr ""
+"Os seguintes módulos não estão instalados no seu computador:\n"
+"%s"
+
+#: spyderlib/plugins/externalconsole.py:1247
+msgid ""
+"Please note that these changes will be applied only to new Python/IPython "
+"consoles"
+msgstr ""
+"Por favor, note que estas mudanças só serão aplicadas apenas aos novos "
+"consoles do Python/IPython"
+
+#: spyderlib/plugins/findinfiles.py:96 spyderlib/widgets/findinfiles.py:690
+msgid "Find in files"
+msgstr "Procurar em arquivos"
+
+#: spyderlib/plugins/findinfiles.py:117
+msgid "&Find in files"
+msgstr "Procurar em arqui&vos"
+
+#: spyderlib/plugins/findinfiles.py:120
+msgid "Search text in multiple files"
+msgstr "Buscar em vários arquivos"
+
+#: spyderlib/plugins/history.py:37
+msgid "Settings"
+msgstr "Configurações"
+
+#: spyderlib/plugins/history.py:39
+msgid " entries"
+msgstr "entradas"
+
+#: spyderlib/plugins/history.py:39
+msgid "History depth: "
+msgstr "Profundidade do histórico: "
+
+#: spyderlib/plugins/history.py:46
+msgid "Scroll automatically to last entry"
+msgstr "Ir automaticamente para a última entrada"
+
+#: spyderlib/plugins/history.py:118 spyderlib/plugins/inspector.py:472
+#: spyderlib/widgets/editor.py:459 spyderlib/widgets/explorer.py:1027
+#: spyderlib/widgets/externalshell/baseshell.py:153
+#: spyderlib/widgets/externalshell/namespacebrowser.py:139
+#: spyderlib/widgets/ipython.py:568
+msgid "Options"
+msgstr "Opções"
+
+#: spyderlib/plugins/history.py:138
+msgid "History log"
+msgstr "Log do histórico "
+
+#: spyderlib/plugins/history.py:165
+msgid "History..."
+msgstr "Histórico..."
+
+#: spyderlib/plugins/history.py:167
+msgid "Set history maximum entries"
+msgstr "Definir número máximo de entradas para armazenar"
+
+#: spyderlib/plugins/history.py:274
+msgid "History"
+msgstr "Histórico"
+
+#: spyderlib/plugins/history.py:275
+msgid "Maximum entries"
+msgstr "Número máximo de entradas"
+
+#: spyderlib/plugins/inspector.py:58
+msgid "Rich text help on the Object Inspector"
+msgstr "Ajuda em texto formatado no Explorador de Objetos"
+
+#: spyderlib/plugins/inspector.py:125
+msgid "Plain text font style"
+msgstr "Estilo de fonte para o texto normal"
+
+#: spyderlib/plugins/inspector.py:128
+msgid "Rich text font style"
+msgstr "Estilo de fonte para o texto formatado"
+
+#: spyderlib/plugins/inspector.py:131
+msgid "Automatic connections"
+msgstr "Conexões automáticas "
+
+#: spyderlib/plugins/inspector.py:132
+msgid ""
+"The Object Inspector can automatically show an object's help information "
+"after a left parenthesis is written next to it. Below you can decide to "
+"which plugin you want to connect it to turn on this feature."
+msgstr ""
+"O Inspetor de Objetos pode mostrar automaticamente a ajuda de um objeto "
+"depois de escrever um parênteses no mesmo. A seguir você pode decidir a que "
+"painel/componente você deseja conectar para ativar esta característica."
+
+#: spyderlib/plugins/inspector.py:144
+#, fuzzy
+msgid ""
+"This feature requires the Rope or Jedi libraries.\n"
+"It seems you don't have either installed."
+msgstr ""
+"Esta funcionalidade requer a biblioteca Rope.\n"
+"Parece que ela não está instalada."
+
+#: spyderlib/plugins/inspector.py:147
+msgid "Python Console"
+msgstr "Console Python"
+
+#: spyderlib/plugins/inspector.py:149
+msgid "IPython Console"
+msgstr "Console IPython"
+
+#: spyderlib/plugins/inspector.py:161
+msgid "Additional features"
+msgstr "Funcionalidades adicionais"
+
+#: spyderlib/plugins/inspector.py:162
+msgid "Render mathematical equations"
+msgstr "Renderizar equações matemáticas"
+
+#: spyderlib/plugins/inspector.py:168
+msgid "This feature requires Sphinx 1.1 or superior."
+msgstr "Esta funcionalidade requer Sphinx 1.1 ou superior."
+
+#: spyderlib/plugins/inspector.py:170
+msgid "Sphinx %s is currently installed."
+msgstr "Sphinx %s está instalado atualmente."
+
+#: spyderlib/plugins/inspector.py:373
+#, fuzzy
+msgid "No further documentation available"
+msgstr "Não existe documentação disponível"
+
+#: spyderlib/plugins/inspector.py:412
+msgid "Source"
+msgstr "Origem"
+
+#: spyderlib/plugins/inspector.py:427 spyderlib/widgets/dicteditor.py:173
+msgid "Object"
+msgstr "Objeto"
+
+#: spyderlib/plugins/inspector.py:442
+msgid "Plain Text"
+msgstr "Texto Normal"
+
+#: spyderlib/plugins/inspector.py:446
+msgid "Show Source"
+msgstr "Mostrar código fonte"
+
+#: spyderlib/plugins/inspector.py:450
+msgid "Rich Text"
+msgstr "Texto Formatado "
+
+#: spyderlib/plugins/inspector.py:460
+msgid "Automatic import"
+msgstr "Importar automaticamente"
+
+#: spyderlib/plugins/inspector.py:520 spyderlib/plugins/inspector.py:983
+msgid "Object inspector"
+msgstr "Inspetor de objetos"
+
+#: spyderlib/plugins/inspector.py:740
+msgid ""
+"Here you can get help of any object by pressing %s in front of it, either on "
+"the Editor or the Console.%sHelp can also be shown automatically after "
+"writing a left parenthesis next to an object. You can activate this behavior "
+"in %s."
+msgstr ""
+"Neste painel é possível obter a ajuda de qualquer objeto ao pressionar %s "
+"estando na frente do mesmo, tanto no Editor quanto no Console.%sEssa ajuda "
+"também pode ser mostrada automaticamente depois de escrever um parênteses "
+"junto a um objeto. Você pode ativar este comportamento em %s."
+
+#: spyderlib/plugins/inspector.py:746
+msgid "Preferences > Object Inspector"
+msgstr "Preferências > Inspetor de objetos"
+
+#: spyderlib/plugins/inspector.py:753
+msgid "Usage"
+msgstr "Uso"
+
+#: spyderlib/plugins/inspector.py:754
+msgid "New to Spyder? Read our"
+msgstr "Novo no Spyder? Leia nosso"
+
+#: spyderlib/plugins/inspector.py:755
+msgid "tutorial"
+msgstr "tutorial"
+
+#: spyderlib/plugins/inspector.py:762
+msgid ""
+"Please consider installing Sphinx to get documentation rendered in rich text."
+msgstr ""
+"Por favor considere instalar o Sphinx para obter a documentação em texto "
+"formatado."
+
+#: spyderlib/plugins/inspector.py:939
+msgid "Lock"
+msgstr "Trancar"
+
+#: spyderlib/plugins/inspector.py:939
+msgid "Unlock"
+msgstr "Destrancar"
+
+#: spyderlib/plugins/inspector.py:984
+msgid ""
+"The following error occured when calling <b>Sphinx %s</b>. <br>Incompatible "
+"Sphinx version or doc string decoding failed.<br><br>Error message:<br>%s"
+msgstr ""
+"Ocorreu o seguinte erro quando o <b>Sphinx %s</b> tentou ser utilizado. "
+"<br>Isso se deve a uma versão incompatível do Sphinx ou não foi possível ler "
+"a documentação solicitada.<br><br>Mensagem de erro:<br>%s"
+
+#: spyderlib/plugins/inspector.py:1028
+msgid "No source code available."
+msgstr "O código fonte não está disponível"
+
+#: spyderlib/plugins/ipythonconsole.py:62
+msgid "Symbolic mathematics in the IPython Console"
+msgstr "Matemática simbólica no console IPython"
+
+#: spyderlib/plugins/ipythonconsole.py:111
+msgid ""
+"The authenticity of host <b>%s</b> can't be established. Are you sure you "
+"want to continue connecting?"
+msgstr ""
+"A autenticidade do servidor <b>%s</b> não pode ser estabelecida. Você tem "
+"certeza que deseja continuar conectando?"
+
+#: spyderlib/plugins/ipythonconsole.py:123
+msgid "The authenticity of the host can't be established"
+msgstr "A autenticidade do servidor não pode ser estabelecida"
+
+#: spyderlib/plugins/ipythonconsole.py:130
+msgid "Tunnel '%s' failed to start"
+msgstr "O túnel '%s' falhou ao ser iniciado"
+
+#: spyderlib/plugins/ipythonconsole.py:135
+msgid "Could not connect to remote host"
+msgstr "Não foi possível conectar ao servidor remoto"
+
+#: spyderlib/plugins/ipythonconsole.py:151
+#: spyderlib/plugins/ipythonconsole.py:689
+msgid "IPython console"
+msgstr "Console IPython"
+
+#: spyderlib/plugins/ipythonconsole.py:163
+msgid "Display initial banner"
+msgstr "Mostrar o banner inicial"
+
+#: spyderlib/plugins/ipythonconsole.py:164
+msgid ""
+"This option lets you hide the message shown at\n"
+"the top of the console when it's opened."
+msgstr ""
+"Esta opção permite ocultar a mensagem que \n"
+"aparece no topo do console quando se abre\n"
+"ele pela primeira vez."
+
+#: spyderlib/plugins/ipythonconsole.py:166
+msgid "Use a pager to display additional text inside the console"
+msgstr "Usar um paginador para mostrar textos dentro do console"
+
+#: spyderlib/plugins/ipythonconsole.py:168
+msgid ""
+"Useful if you don't want to fill the console with long help or completion "
+"texts.\n"
+"Note: Use the Q key to get out of the pager."
+msgstr ""
+"Isso é útil se não deseja preencher o console com grandes textos de ajuda.\n"
+"Nota: Use a tecla Q para sair do paginador."
+
+#: spyderlib/plugins/ipythonconsole.py:173
+msgid "Ask for confirmation before closing"
+msgstr "Mostrar janela de confirmação antes de fechar"
+
+#: spyderlib/plugins/ipythonconsole.py:183
+msgid "Completion Type"
+msgstr ""
+
+#: spyderlib/plugins/ipythonconsole.py:184
+msgid "Decide what type of completion to use"
+msgstr ""
+
+#: spyderlib/plugins/ipythonconsole.py:187
+#, fuzzy
+msgid "Completion:"
+msgstr "Condição:"
+
+#: spyderlib/plugins/ipythonconsole.py:196
+msgid "Light background"
+msgstr "Fundo claro"
+
+#: spyderlib/plugins/ipythonconsole.py:198
+msgid "Dark background"
+msgstr "Fundo escuro"
+
+#: spyderlib/plugins/ipythonconsole.py:208
+msgid "Buffer:  "
+msgstr "Buffer: "
+
+#: spyderlib/plugins/ipythonconsole.py:210
+msgid ""
+"Set the maximum number of lines of text shown in the\n"
+"console before truncation. Specifying -1 disables it\n"
+"(not recommended!)"
+msgstr ""
+"Define o número máximo de linhas que serão mostradas\n"
+"no console em qualquer momento. Especificando -1 serão\n"
+"mostradas todas as linhas (não é recomendável!)"
+
+#: spyderlib/plugins/ipythonconsole.py:219
+msgid "Support for graphics (Matplotlib)"
+msgstr "Suporte para criação de gráficos (Matplotlib)"
+
+#: spyderlib/plugins/ipythonconsole.py:220
+msgid "Activate support"
+msgstr "Ativar suporte"
+
+#: spyderlib/plugins/ipythonconsole.py:221
+msgid "Automatically load Pylab and NumPy modules"
+msgstr "Carregar automaticamente os módulos do Pylab e do NumPy"
+
+#: spyderlib/plugins/ipythonconsole.py:224
+msgid ""
+"This lets you load graphics support without importing \n"
+"the commands to do plots. Useful to work with other\n"
+"plotting libraries different to Matplotlib or to develop \n"
+"GUIs with Spyder."
+msgstr ""
+"Isso lhe permite carregar o suporte gráfico sem importar\n"
+"os comandos para criar imagens. É útil para trabalhar com\n"
+"outras bibliotecas gráficas diferentes da Matplotlib ou para\n"
+"desenvolver interfaces gráficas com o Spyder."
+
+#: spyderlib/plugins/ipythonconsole.py:242
+msgid ""
+"This feature requires the Matplotlib library.\n"
+"It seems you don't have it installed."
+msgstr ""
+"Esta funcionalidade requer a biblioteca Matplotlb.\n"
+"parece que você não tem ela instalada."
+
+#: spyderlib/plugins/ipythonconsole.py:247
+msgid "Inline"
+msgstr "Em linha"
+
+#: spyderlib/plugins/ipythonconsole.py:248
+msgid "Automatic"
+msgstr "Automático"
+
+#: spyderlib/plugins/ipythonconsole.py:249
+msgid "Graphics backend"
+msgstr "Saída gráfica"
+
+#: spyderlib/plugins/ipythonconsole.py:250
+msgid ""
+"Decide how graphics are going to be displayed in the console. If unsure, "
+"please select <b>%s</b> to put graphics inside the console or <b>%s</b> to "
+"interact with them (through zooming and panning) in a separate window."
+msgstr ""
+"Decidir como serão mostrados os gráficos no console. Se está inseguro, por "
+"favor selecione <b>%s</b> para colocar os gráficos no console ou <b>%s</b> "
+"para interagir com eles (através de zoom) em uma janela separada."
+
+#: spyderlib/plugins/ipythonconsole.py:283
+msgid "Inline backend"
+msgstr "Saída em linha"
+
+#: spyderlib/plugins/ipythonconsole.py:284
+msgid "Decide how to render the figures created by this backend"
+msgstr ""
+"Decida como renderizar as imagens criados por este tipo de saída gráfica"
+
+#: spyderlib/plugins/ipythonconsole.py:288
+msgid "Format:"
+msgstr "Formato:"
+
+#: spyderlib/plugins/ipythonconsole.py:291
+msgid "Resolution:"
+msgstr "Resolução:"
+
+#: spyderlib/plugins/ipythonconsole.py:291
+msgid "dpi"
+msgstr "dpi"
+
+#: spyderlib/plugins/ipythonconsole.py:293
+msgid "Only used when the format is PNG. Default is 72"
+msgstr "Só se usa quando o formato for PNG. O padrão é 72"
+
+#: spyderlib/plugins/ipythonconsole.py:296
+msgid "Width:"
+msgstr "Largura:"
+
+#: spyderlib/plugins/ipythonconsole.py:296
+#: spyderlib/plugins/ipythonconsole.py:300
+msgid "inches"
+msgstr "polegadas"
+
+#: spyderlib/plugins/ipythonconsole.py:298
+msgid "Default is 6"
+msgstr "O padrão é 6"
+
+#: spyderlib/plugins/ipythonconsole.py:300
+msgid "Height:"
+msgstr "Altura:"
+
+#: spyderlib/plugins/ipythonconsole.py:302
+msgid "Default is 4"
+msgstr "O padrão é 4"
+
+#: spyderlib/plugins/ipythonconsole.py:328 spyderlib/tour.py:552
+msgid "Run code"
+msgstr "Executar código"
+
+#: spyderlib/plugins/ipythonconsole.py:329
+msgid ""
+"You can run several lines of code when a console is started. Please "
+"introduce each one separated by commas, for example:<br><i>import os, import "
+"sys</i>"
+msgstr ""
+"Você pode executar várias linhas de código ao abrir um terminal. Por favor "
+"introduza cada uma separada por vírgulas, por exemplo:<br><i>import os, "
+"import sys</i>"
+
+#: spyderlib/plugins/ipythonconsole.py:335
+msgid "Lines:"
+msgstr "Linhas:"
+
+#: spyderlib/plugins/ipythonconsole.py:344
+msgid "Run a file"
+msgstr "Executar arquivo"
+
+#: spyderlib/plugins/ipythonconsole.py:345
+msgid ""
+"You can also run a whole file at startup instead of just some lines (This is "
+"similar to have a PYTHONSTARTUP file)."
+msgstr ""
+"Você também pode executar um arquivo por inteiro ao inicializar, em vez de "
+"poucas linhas (Isso é similar a ter um arquivo PYTHONSTARTUP)."
+
+#: spyderlib/plugins/ipythonconsole.py:349
+msgid "Use the following file:"
+msgstr "Use o seguinte arquivo:"
+
+#: spyderlib/plugins/ipythonconsole.py:363
+msgid "Greedy completion"
+msgstr "Completação gulosa"
+
+#: spyderlib/plugins/ipythonconsole.py:364
+msgid ""
+"Enable <tt>Tab</tt> completion on elements of lists, results of function "
+"calls, etc, <i>without</i> assigning them to a variable.<br>For example, you "
+"can get completions on things like <tt>li[0].<Tab></tt> or <tt>ins."
+"meth().<Tab></tt>"
+msgstr ""
+"Habilita o completador usando a tecla <tt>Tab</tt> em elementos de listas, "
+"resultados de chamadas de funções, etc, <i>sem</i> atribuí-los a uma "
+"variável.<br>Dessa forma pode-se obter sugestões de completação em coisas "
+"como <tt>li[0].<Tab></tt> ou <tt>ins.meth().<Tab></tt>"
+
+#: spyderlib/plugins/ipythonconsole.py:372
+msgid "Use the greedy completer"
+msgstr "Usar o completador guloso"
+
+#: spyderlib/plugins/ipythonconsole.py:383
+msgid "Autocall"
+msgstr "Autocall"
+
+#: spyderlib/plugins/ipythonconsole.py:384
+msgid ""
+"Autocall makes IPython automatically call any callable object even if you "
+"didn't type explicit parentheses.<br>For example, if you type <i>str 43</i> "
+"it becomes <i>str(43)</i> automatically."
+msgstr ""
+"Esta opção faz com que o Python chame automaticamente qualquer objeto mesmo "
+"se você não tenha digitado os parenteses ao seu redor.<br>Por exemplo, ao "
+"escrever <i>str 43</i>, irá virar automaticamente <i>str(43)</i>."
+
+#: spyderlib/plugins/ipythonconsole.py:391
+msgid "Smart"
+msgstr "Inteligente"
+
+#: spyderlib/plugins/ipythonconsole.py:392
+msgid "Full"
+msgstr "Total"
+
+#: spyderlib/plugins/ipythonconsole.py:393
+msgid "Off"
+msgstr "Desativado"
+
+#: spyderlib/plugins/ipythonconsole.py:395
+msgid "Autocall:  "
+msgstr "Autocall: "
+
+#: spyderlib/plugins/ipythonconsole.py:396
+msgid ""
+"On <b>%s</b> mode, Autocall is not applied if there are no arguments after "
+"the callable. On <b>%s</b> mode, all callable objects are automatically "
+"called (even if no arguments are present)."
+msgstr ""
+"No modo <b>%s</b>, Auto-chamada não é aplicada se não houver argumentos "
+"depois do objeto clamável. No modo <b>%s</b>, todos os objetos chamáveis são "
+"chamados automaticamente (mesmo se não houver argumentos presentes)."
+
+#: spyderlib/plugins/ipythonconsole.py:408
+msgid "Symbolic Mathematics"
+msgstr "Matemática simbólica"
+
+#: spyderlib/plugins/ipythonconsole.py:409
+msgid ""
+"Perfom symbolic operations in the console (e.g. integrals, derivatives, "
+"vector calculus, etc) and get the outputs in a beautifully printed style."
+msgstr ""
+"Realiza operações simbólicas no console (integrais, derivadas, cálculo "
+"vetorial) e tenha os resultados em um belo estilo impresso."
+
+#: spyderlib/plugins/ipythonconsole.py:414
+msgid "Use symbolic math"
+msgstr "Usar matemática simbólica"
+
+#: spyderlib/plugins/ipythonconsole.py:415
+msgid ""
+"This option loads the Sympy library to work with.<br>Please refer to its "
+"documentation to learn how to use it."
+msgstr ""
+"Esta opção carrega a biblioteca Sympy para trabalhar<br>com ela. Por favor "
+"leia sua documentação para aprender a usá-la. "
+
+#: spyderlib/plugins/ipythonconsole.py:428
+msgid ""
+"This feature requires the Sympy library.\n"
+"It seems you don't have it installed."
+msgstr ""
+"Esta funcionalidade requer a biblioteca Sympy .\n"
+"Parece que você não tem ela instalada."
+
+#: spyderlib/plugins/ipythonconsole.py:433
+msgid "Prompts"
+msgstr "Prompts"
+
+#: spyderlib/plugins/ipythonconsole.py:434
+msgid "Modify how Input and Output prompts are shown in the console."
+msgstr "Modifique como são mostradas as saídas e entradas no console."
+
+#: spyderlib/plugins/ipythonconsole.py:437
+msgid "Input prompt:"
+msgstr "Prompt de entrada:"
+
+#: spyderlib/plugins/ipythonconsole.py:439
+msgid ""
+"Default is<br>In [<span class=\"in-prompt-number\">%i</span>]:"
+msgstr ""
+"O Padrão é<br>In [<span class=\"in-prompt-number\">%i</span>]:"
+
+#: spyderlib/plugins/ipythonconsole.py:443
+msgid "Output prompt:"
+msgstr "Prompt de saída:"
+
+#: spyderlib/plugins/ipythonconsole.py:445
+msgid ""
+"Default is<br>Out[<span class=\"out-prompt-number\">%i</span>]:"
+msgstr ""
+"O Padrão é<br>Out[<span class=\"out-prompt-number\">%i</span>]: "
+
+#: spyderlib/plugins/ipythonconsole.py:467
+#: spyderlib/plugins/workingdirectory.py:44
+msgid "Startup"
+msgstr "Inicialização"
+
+#: spyderlib/plugins/ipythonconsole.py:469
+msgid "Advanced Settings"
+msgstr "Configurações avançadas"
+
+#: spyderlib/plugins/ipythonconsole.py:481
+#: spyderlib/plugins/ipythonconsole.py:749
+msgid "Connect to an existing kernel"
+msgstr "Conectando a um kernel já existente"
+
+#: spyderlib/plugins/ipythonconsole.py:483
+msgid ""
+"Please enter the connection info of the kernel you want to connect to. For "
+"that you can either select its JSON connection file using the <tt>Browse</"
+"tt> button, or write directly its id, in case it's a local kernel (for "
+"example <tt>kernel-3764.json</tt> or just <tt>3764</tt>)."
+msgstr ""
+"Por favor introduza a informação de conexão do kernel ao qual deseja se "
+"conectar. Para isso você pode selecionar seu arquivo de conexão JSON, usando "
+"o botão <tt>Selecionar</tt>, ou escrever diretamente seu id, em caso de que "
+"seja um kernel local (por exemplo, <tt>kernel-3764.json</tt> ou só <tt>3764</"
+"tt>)."
+
+#: spyderlib/plugins/ipythonconsole.py:494
+msgid "Connection info:"
+msgstr "Informação da conexão:"
+
+#: spyderlib/plugins/ipythonconsole.py:496
+msgid "Path to connection file or kernel id"
+msgstr "Caminho para arquivo de conexão ou id do kernel"
+
+#: spyderlib/plugins/ipythonconsole.py:498
+#: spyderlib/plugins/ipythonconsole.py:515
+msgid "Browse"
+msgstr "Navegar"
+
+#: spyderlib/plugins/ipythonconsole.py:507
+msgid "This is a remote kernel"
+msgstr "Este é um kernel remoto"
+
+#: spyderlib/plugins/ipythonconsole.py:511
+msgid "username at hostname:port"
+msgstr "usuário at servidor:porta"
+
+#: spyderlib/plugins/ipythonconsole.py:514
+msgid "Path to ssh key file"
+msgstr "Caminho do arquivo de chave ssh"
+
+#: spyderlib/plugins/ipythonconsole.py:523
+msgid "Password or ssh key passphrase"
+msgstr "Senha"
+
+#: spyderlib/plugins/ipythonconsole.py:527
+msgid "Host name"
+msgstr "Nome do host "
+
+#: spyderlib/plugins/ipythonconsole.py:528
+msgid "Ssh key"
+msgstr "Chave ssh"
+
+#: spyderlib/plugins/ipythonconsole.py:529
+msgid "Password"
+msgstr "Senha"
+
+#: spyderlib/plugins/ipythonconsole.py:558
+msgid "Open IPython connection file"
+msgstr "Abrir arquivo de conexão do IPython"
+
+#: spyderlib/plugins/ipythonconsole.py:564
+msgid "Select ssh key"
+msgstr "Selecionar chave ssh"
+
+#: spyderlib/plugins/ipythonconsole.py:737
+msgid "Open an &IPython console"
+msgstr "Abrir um console &IPython "
+
+#: spyderlib/plugins/ipythonconsole.py:740
+msgid "Use %s+T when the console is selected to open a new one"
+msgstr ""
+
+#: spyderlib/plugins/ipythonconsole.py:743
+#, fuzzy
+msgid "Open a new console"
+msgstr "Abrir um console &Python"
+
+#: spyderlib/plugins/ipythonconsole.py:750
+msgid "Open a new IPython console connected to an existing kernel"
+msgstr "Abrir um novo console do IPython conectado a um kernel existente."
+
+#: spyderlib/plugins/ipythonconsole.py:833
+msgid ""
+"No IPython console is currently available to run <b>%s</b>.<br><br>Please "
+"open a new one and try again."
+msgstr ""
+"Não existe um console IPython para ser executado <b>%s</b>.<br><br>Por favor "
+"abra um novo e tente novamente."
+
+#: spyderlib/plugins/ipythonconsole.py:968
+msgid ""
+"Do you want to close all other consoles connected to the same kernel as this "
+"one?"
+msgstr ""
+
+#: spyderlib/plugins/ipythonconsole.py:1050
+msgid "Connection error"
+msgstr "Erro de conexão"
+
+#: spyderlib/plugins/ipythonconsole.py:1051
+msgid ""
+"Could not open ssh tunnel. The error was:\n"
+"\n"
+msgstr ""
+"Não foi possível criar um túnel ssh. O erro foi:\n"
+"\n"
+
+#: spyderlib/plugins/ipythonconsole.py:1088
+msgid "IPython"
+msgstr "IPython"
+
+#: spyderlib/plugins/ipythonconsole.py:1089
+msgid "Unable to connect to IPython <b>%s"
+msgstr "Não foi possível conectar ao IPython <b>%s"
+
+#: spyderlib/plugins/ipythonconsole.py:1140
+msgid "Are you sure you want to restart the kernel?"
+msgstr "Deseja mesmo reiniciar o kernel?"
+
+#: spyderlib/plugins/ipythonconsole.py:1142
+msgid "Restart kernel?"
+msgstr "Reiniciar kernel?"
+
+#: spyderlib/plugins/layoutdialog.py:174
+#, fuzzy
+msgid "Move Up"
+msgstr "Mover para cima"
+
+#: spyderlib/plugins/layoutdialog.py:175
+#, fuzzy
+msgid "Move Down"
+msgstr "Mover para baixo"
+
+#: spyderlib/plugins/layoutdialog.py:176
+#, fuzzy
+msgid "Delete Layout"
+msgstr "Deletar"
+
+#: spyderlib/plugins/layoutdialog.py:180
+msgid "Layout Dispay and Order"
+msgstr ""
+
+#: spyderlib/plugins/onlinehelp.py:68
+msgid "Online help"
+msgstr "Ajuda online"
+
+#: spyderlib/plugins/outlineexplorer.py:48
+#: spyderlib/widgets/editortools.py:195
+msgid "Outline"
+msgstr "Explorador de código"
+
+#: spyderlib/plugins/projectexplorer.py:53
+#: spyderlib/widgets/projectexplorer.py:1150
+#: spyderlib/widgets/projectexplorer.py:1164
+msgid "Project explorer"
+msgstr "Explorador de projetos"
+
+#: spyderlib/plugins/projectexplorer.py:64
+#: spyderlib/widgets/projectexplorer.py:549
+msgid "New project..."
+msgstr "Novo projeto..."
+
+#: spyderlib/plugins/runconfig.py:28
+msgid "Execute in current Python or IPython console"
+msgstr "Executar no console atual do Python ou IPython"
+
+#: spyderlib/plugins/runconfig.py:29
+msgid "Execute in a new dedicated Python console"
+msgstr "Executar em um novo console dedicado do Python"
+
+#: spyderlib/plugins/runconfig.py:30
+msgid "Execute in an external System terminal"
+msgstr "Executar em um terminal externo do Sistema"
+
+#: spyderlib/plugins/runconfig.py:40
+msgid "Always show %s on a first file run"
+msgstr "Sempre mostrar %s na primeira execução"
+
+#: spyderlib/plugins/runconfig.py:159
+msgid "General settings"
+msgstr "Configurações gerais"
+
+#: spyderlib/plugins/runconfig.py:162 spyderlib/plugins/runconfig.py:208
+msgid "Command line options:"
+msgstr "Opções de linha de comando: "
+
+#: spyderlib/plugins/runconfig.py:168
+msgid "Working directory:"
+msgstr "Diretório de trabalho:"
+
+#: spyderlib/plugins/runconfig.py:180 spyderlib/plugins/runconfig.py:491
+msgid "Enter debugging mode when errors appear during execution"
+msgstr ""
+
+#: spyderlib/plugins/runconfig.py:196 spyderlib/plugins/runconfig.py:501
+msgid "Dedicated Python console"
+msgstr "Console do Python dedicado"
+
+#: spyderlib/plugins/runconfig.py:200 spyderlib/plugins/runconfig.py:503
+msgid "Interact with the Python console after execution"
+msgstr "Interagir com o console depois da execução"
+
+#: spyderlib/plugins/runconfig.py:204
+msgid "Show warning when killing running process"
+msgstr "Mostrar um aviso quando matar o processo"
+
+#: spyderlib/plugins/runconfig.py:213
+msgid "<b>-u</b> is added to the other options you set here"
+msgstr "A opção <b>-u</b> foi adicionada a essas opções"
+
+#: spyderlib/plugins/runconfig.py:223
+msgid "this dialog"
+msgstr "este dialogo "
+
+#: spyderlib/plugins/runconfig.py:282
+msgid "Run configuration"
+msgstr "Opções de execução"
+
+#: spyderlib/plugins/runconfig.py:283
+msgid "The following working directory is not valid:<br><b>%s</b>"
+msgstr "O seguinte diretório de trabalho não é válido:<br><b>%s</b>"
+
+#: spyderlib/plugins/runconfig.py:361
+msgid "Run settings for %s"
+msgstr "Ajustar configuração para %s"
+
+#: spyderlib/plugins/runconfig.py:393
+msgid "Select a run configuration:"
+msgstr "Selecionar um arquivo de execução:"
+
+#: spyderlib/plugins/runconfig.py:422 spyderlib/plugins/runconfig.py:447
+msgid "Run Settings"
+msgstr "Opções de execução"
+
+#: spyderlib/plugins/runconfig.py:449
+msgid ""
+"The following are the default <i>%s</i>. These options may be overriden "
+"using the <b>%s</b> dialog box (see the <b>%s</b> menu)"
+msgstr ""
+"As seguintes <i>%s</i> são padrões. Estas opções podem ser modificadas "
+"usando o diálogo <b>%s</b> (ver o menu <b>%s</b>)"
+
+#: spyderlib/plugins/runconfig.py:475
+msgid "Default working directory is:"
+msgstr "O diretório de trabalho padrão é:"
+
+#: spyderlib/plugins/runconfig.py:477
+msgid "the script directory"
+msgstr "Diretório do script atual"
+
+#: spyderlib/plugins/runconfig.py:480 spyderlib/plugins/workingdirectory.py:56
+msgid "the following directory:"
+msgstr "O seguinte diretório:"
+
+#: spyderlib/plugins/runconfig.py:506
+#, fuzzy
+msgid "Show warning when killing running processes"
+msgstr "Mostrar um aviso quando matar o processo"
+
+#: spyderlib/plugins/runconfig.py:515
+msgid "Run Settings dialog"
+msgstr "Configurações de execução"
+
+#: spyderlib/plugins/shortcuts.py:134
+msgid ""
+"Press the new shortcut and select 'Ok': \n"
+"(Press 'Tab' once to switch focus between the shortcut entry \n"
+"and the buttons below it)"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:137
+#, fuzzy
+msgid "Current shortcut:"
+msgstr "Célula selecionada:"
+
+#: spyderlib/plugins/shortcuts.py:139
+#, fuzzy
+msgid "New shortcut:"
+msgstr "Teclas de atalho"
+
+#: spyderlib/plugins/shortcuts.py:152
+msgid "Shortcut: {0}"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:273
+msgid "Please introduce a different shortcut"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:310
+msgid "The new shorcut conflicts with:"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:321
+msgid ""
+"A compound sequence can have {break} a maximum of 4 subsequences.{break}"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:326
+#, fuzzy
+msgid "Invalid key entered"
+msgstr "Caminho de arquivo inválido "
+
+#: spyderlib/plugins/shortcuts.py:515
+msgid "Context"
+msgstr "Contexto"
+
+#: spyderlib/plugins/shortcuts.py:517 spyderlib/widgets/dicteditor.py:158
+msgid "Name"
+msgstr "Nome"
+
+#: spyderlib/plugins/shortcuts.py:519
+msgid "Shortcut"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:521
+msgid "Score"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:681
+msgid "Conflicts"
+msgstr "Conflitos"
+
+#: spyderlib/plugins/shortcuts.py:682
+msgid "The following conflicts have been detected:"
+msgstr "Os seguintes conflitos foram detectados:"
+
+#: spyderlib/plugins/shortcuts.py:767
+msgid "Keyboard shortcuts"
+msgstr "Teclas de atalho"
+
+#: spyderlib/plugins/shortcuts.py:775
+#, fuzzy
+msgid "Search: "
+msgstr "Procurar"
+
+#: spyderlib/plugins/variableexplorer.py:24
+msgid "Autorefresh"
+msgstr "Atualizar automaticamente"
+
+#: spyderlib/plugins/variableexplorer.py:25
+msgid "Enable autorefresh"
+msgstr "Ativar atualização automatica"
+
+#: spyderlib/plugins/variableexplorer.py:27
+msgid "Refresh interval: "
+msgstr "Intervalo de atualização"
+
+#: spyderlib/plugins/variableexplorer.py:28
+msgid " ms"
+msgstr "ms"
+
+#: spyderlib/plugins/variableexplorer.py:31
+msgid "Filter"
+msgstr "Filtro"
+
+#: spyderlib/plugins/variableexplorer.py:33
+#: spyderlib/widgets/externalshell/namespacebrowser.py:214
+msgid "Exclude private references"
+msgstr "Excluir variáveis privadas"
+
+#: spyderlib/plugins/variableexplorer.py:34
+#: spyderlib/widgets/externalshell/namespacebrowser.py:229
+msgid "Exclude capitalized references"
+msgstr "Excluir variáveis que começam em maiúsculas"
+
+#: spyderlib/plugins/variableexplorer.py:35
+#: spyderlib/widgets/externalshell/namespacebrowser.py:222
+msgid "Exclude all-uppercase references"
+msgstr "Excluir variáveis em maiúscula "
+
+#: spyderlib/plugins/variableexplorer.py:36
+#: spyderlib/widgets/externalshell/namespacebrowser.py:237
+msgid "Exclude unsupported data types"
+msgstr "Excluir tipos de dados não suportados"
+
+#: spyderlib/plugins/variableexplorer.py:42
+#: spyderlib/widgets/dicteditor.py:708
+msgid "Truncate values"
+msgstr "Abreviar valores"
+
+#: spyderlib/plugins/variableexplorer.py:44
+#: spyderlib/widgets/dicteditor.py:712
+msgid "Show arrays min/max"
+msgstr "Mostrar o minimo e máximo de matrizes"
+
+#: spyderlib/plugins/variableexplorer.py:46
+msgid "Edit data in the remote process"
+msgstr "Editar dados em um processo remoto"
+
+#: spyderlib/plugins/variableexplorer.py:47
+msgid ""
+"Editors are opened in the remote process for NumPy arrays, PIL images, "
+"lists, tuples and dictionaries.\n"
+"This avoids transfering large amount of data between the remote process and "
+"Spyder (through the socket)."
+msgstr ""
+"Esta opção permite modificar matrizes do NumPY, imagens do PIL, listas, "
+"tuplas e\n"
+"dicionários em um processo remoto. Isto impede a transferência de grandes "
+"quantidades de dados\n"
+"entre o processo remoto e o Spyder."
+
+#: spyderlib/plugins/variableexplorer.py:183
+msgid "Variable explorer"
+msgstr "Explorador de variáveis"
+
+#: spyderlib/plugins/workingdirectory.py:37
+msgid ""
+"The <b>global working directory</b> is the working directory for newly "
+"opened <i>consoles</i> (Python/IPython consoles and terminals), for the "
+"<i>file explorer</i>, for the <i>find in files</i> plugin and for new files "
+"created in the <i>editor</i>."
+msgstr ""
+"O <b>diretório de trabalho global</b> é o diretório de trabalho para os "
+"<i>consoles</i> recém abertos (do IPython/Python e dos terminais), para o "
+"<i>Explorador de arquivos</i>, <i>Buscar em arquivos</i> e para os novos "
+"arquivos criados no <i>Editor</i>."
+
+#: spyderlib/plugins/workingdirectory.py:46
+msgid "At startup, the global working directory is:"
+msgstr "Ao iniciar, o diretório de trabalho global é:"
+
+#: spyderlib/plugins/workingdirectory.py:50
+msgid "the same as in last session"
+msgstr "O mesmo da última sessão"
+
+#: spyderlib/plugins/workingdirectory.py:52
+msgid "At startup, Spyder will restore the global directory from last session"
+msgstr "Ao iniciar o Spyder irá restaurar o diretório global da última sessão"
+
+#: spyderlib/plugins/workingdirectory.py:58
+msgid "At startup, the global working directory will be the specified path"
+msgstr "Ao iniciar o diretório de trabalho será o seguinte"
+
+#: spyderlib/plugins/workingdirectory.py:70
+msgid "Files are opened from:"
+msgstr "Os arquivos são abertos de:"
+
+#: spyderlib/plugins/workingdirectory.py:74
+#: spyderlib/plugins/workingdirectory.py:87
+msgid "the current file directory"
+msgstr "O diretório do arquivo atual"
+
+#: spyderlib/plugins/workingdirectory.py:78
+#: spyderlib/plugins/workingdirectory.py:91
+msgid "the global working directory"
+msgstr "O diretório de trabalho global"
+
+#: spyderlib/plugins/workingdirectory.py:83
+msgid "Files are created in:"
+msgstr "Os arquivos são criados em:"
+
+#: spyderlib/plugins/workingdirectory.py:97
+msgid "Change to file base directory"
+msgstr "Mudar para diretório base do arquivo"
+
+#: spyderlib/plugins/workingdirectory.py:99
+msgid "When opening a file"
+msgstr "Ao abrir um arquivo"
+
+#: spyderlib/plugins/workingdirectory.py:101
+msgid "When saving a file"
+msgstr "Ao salvar um arquivo"
+
+#: spyderlib/plugins/workingdirectory.py:171
+msgid "Back"
+msgstr "Anterior"
+
+#: spyderlib/plugins/workingdirectory.py:179
+#: spyderlib/widgets/explorer.py:1021 spyderlib/widgets/importwizard.py:529
+msgid "Next"
+msgstr "Próximo"
+
+#: spyderlib/plugins/workingdirectory.py:190
+msgid ""
+"This is the working directory for newly\n"
+"opened consoles (Python/IPython consoles and\n"
+"terminals), for the file explorer, for the\n"
+"find in files plugin and for new files\n"
+"created in the editor"
+msgstr ""
+"Este é o diretório de trabalho para os\n"
+"consoles recém abertos \n"
+"(do IPython/Python e terminais), \n"
+"para o Explorador de arquivos,\n"
+"Buscar em arquivos e para os novos\n"
+"arquivos criados no Editor"
+
+#: spyderlib/plugins/workingdirectory.py:216
+msgid "Browse a working directory"
+msgstr "Selecionar um diretório de trabalho"
+
+#: spyderlib/plugins/workingdirectory.py:222
+msgid "Set as current console's working directory"
+msgstr "Definir como diretório de trabalho para o console atual"
+
+#: spyderlib/plugins/workingdirectory.py:230
+msgid "Change to parent directory"
+msgstr "Mudar para diretório superior"
+
+#: spyderlib/plugins/workingdirectory.py:237
+msgid "Global working directory"
+msgstr "Diretório de trabalho global"
+
+#: spyderlib/restart_app.py:129
+msgid ""
+"It was not possible to close the previous Spyder instance.\n"
+"Restart aborted."
+msgstr ""
+
+#: spyderlib/restart_app.py:131
+msgid ""
+"Spyder could not reset to factory defaults.\n"
+"Restart aborted."
+msgstr ""
+
+#: spyderlib/restart_app.py:133
+msgid ""
+"It was not possible to restart Spyder.\n"
+"Operation aborted."
+msgstr ""
+
+#: spyderlib/restart_app.py:135
+#, fuzzy
+msgid "Spyder exit error"
+msgstr "Spyder Editor"
+
+#: spyderlib/restart_app.py:136
+#, fuzzy
+msgid "Spyder reset error"
+msgstr "Spyder Editor"
+
+#: spyderlib/restart_app.py:137
+#, fuzzy
+msgid "Spyder restart error"
+msgstr "Tutorial do Spyder"
+
+#: spyderlib/restart_app.py:161
+msgid "Closing Spyder"
+msgstr ""
+
+#: spyderlib/restart_app.py:234
+#, fuzzy
+msgid "Resetting Spyder to defaults"
+msgstr "Restaurar os valores padrões."
+
+#: spyderlib/restart_app.py:266
+#, fuzzy
+msgid "Restarting"
+msgstr "Restaurar"
+
+#: spyderlib/spyder.py:124
+msgid "Initializing..."
+msgstr "Inicializando..."
+
+#: spyderlib/spyder.py:247
+msgid "Numpy and Scipy documentation"
+msgstr "Documentação do Numpy e Scipy"
+
+#: spyderlib/spyder.py:249 spyderlib/spyder.py:1084
+msgid "Matplotlib documentation"
+msgstr "Documentação do Matplotlib"
+
+#: spyderlib/spyder.py:252
+msgid "PyQt4 Reference Guide"
+msgstr "Guia de referência do PyQt4"
+
+#: spyderlib/spyder.py:255
+msgid "PyQt4 API Reference"
+msgstr "Referência da API do PyQt4"
+
+#: spyderlib/spyder.py:257
+msgid "Python(x,y)"
+msgstr "Python(x,y)"
+
+#: spyderlib/spyder.py:259
+msgid "WinPython"
+msgstr "WinPython"
+
+#: spyderlib/spyder.py:305
+msgid "Reload last session"
+msgstr "Recarregar última sessão"
+
+#: spyderlib/spyder.py:309
+msgid "Load session..."
+msgstr "Carregar sessão..."
+
+#: spyderlib/spyder.py:312
+msgid "Load Spyder session"
+msgstr "Carregar sessão do Spyder"
+
+#: spyderlib/spyder.py:314
+msgid "Save session and quit..."
+msgstr "Salvar sessão e sair..."
+
+#: spyderlib/spyder.py:317
+msgid "Save current session and quit application"
+msgstr "Salvar sessão atual e sair do aplicativo"
+
+#: spyderlib/spyder.py:530
+msgid "Close current pane"
+msgstr "Fechar painel atual"
+
+#: spyderlib/spyder.py:535
+msgid "Lock panes"
+msgstr ""
+
+#: spyderlib/spyder.py:542
+#, fuzzy
+msgid "Use next layout"
+msgstr "Reiniciar esquema dos componentes"
+
+#: spyderlib/spyder.py:546
+#, fuzzy
+msgid "Use previous layout"
+msgstr "Reiniciar esquema dos componentes"
+
+#: spyderlib/spyder.py:555
+msgid "&Find text"
+msgstr "&Procurar"
+
+#: spyderlib/spyder.py:560
+msgid "Find &next"
+msgstr "P&rocurar próximo"
+
+#: spyderlib/spyder.py:567
+msgid "Find &previous"
+msgstr "Procurar &anterior"
+
+#: spyderlib/spyder.py:573
+msgid "&Replace text"
+msgstr "&Substituir"
+
+#: spyderlib/spyder.py:580 spyderlib/widgets/editor.py:339
+#, fuzzy
+msgid "File switcher..."
+msgstr "Arquivo..."
+
+#: spyderlib/spyder.py:582
+msgid "Fast switch between files"
+msgstr ""
+
+#: spyderlib/spyder.py:600 spyderlib/widgets/sourcecode/codeeditor.py:2425
+msgid "Undo"
+msgstr "Desfazer"
+
+#: spyderlib/spyder.py:602 spyderlib/widgets/sourcecode/codeeditor.py:2428
+msgid "Redo"
+msgstr "Refazer"
+
+#: spyderlib/spyder.py:604 spyderlib/widgets/arrayeditor.py:392
+#: spyderlib/widgets/dataframeeditor.py:418
+#: spyderlib/widgets/dicteditor.py:680 spyderlib/widgets/shell.py:126
+#: spyderlib/widgets/sourcecode/codeeditor.py:2434
+msgid "Copy"
+msgstr "Copiar"
+
+#: spyderlib/spyder.py:606 spyderlib/widgets/shell.py:122
+#: spyderlib/widgets/sourcecode/codeeditor.py:2431
+msgid "Cut"
+msgstr "Recortar"
+
+#: spyderlib/spyder.py:608 spyderlib/widgets/dicteditor.py:677
+#: spyderlib/widgets/shell.py:130
+#: spyderlib/widgets/sourcecode/codeeditor.py:2437
+msgid "Paste"
+msgstr "Colar"
+
+#: spyderlib/spyder.py:610 spyderlib/widgets/explorer.py:470
+#: spyderlib/widgets/projectexplorer.py:1015 spyderlib/widgets/shell.py:139
+#: spyderlib/widgets/sourcecode/codeeditor.py:2440
+msgid "Delete"
+msgstr "Deletar"
+
+#: spyderlib/spyder.py:614 spyderlib/widgets/shell.py:143
+#: spyderlib/widgets/sourcecode/codeeditor.py:2444
+msgid "Select All"
+msgstr "Selecionar tudo"
+
+#: spyderlib/spyder.py:664
+msgid "C&onsoles"
+msgstr "C&onsoles"
+
+#: spyderlib/spyder.py:670
+msgid "&View"
+msgstr "&Ver"
+
+#: spyderlib/spyder.py:673
+msgid "&Help"
+msgstr "A&juda"
+
+#: spyderlib/spyder.py:678
+msgid "Welcome to Spyder!"
+msgstr "Bem-vindo ao Spyder!"
+
+#: spyderlib/spyder.py:683
+msgid "Pre&ferences"
+msgstr "Pre&ferências"
+
+#: spyderlib/spyder.py:690 spyderlib/widgets/pathmanager.py:48
+#: spyderlib/widgets/projectexplorer.py:598
+msgid "PYTHONPATH manager"
+msgstr "Gerenciar PYTHONPATH"
+
+#: spyderlib/spyder.py:693
+msgid "Python Path Manager"
+msgstr "Gerenciador de caminhos do Python"
+
+#: spyderlib/spyder.py:696
+msgid "Update module names list"
+msgstr "Atualizar a lista de nomes dos módulos"
+
+#: spyderlib/spyder.py:699
+msgid "Refresh list of module names available in PYTHONPATH"
+msgstr "Atualizar a lista de nomes dos módulos disponíveis no PYTHONPATH"
+
+#: spyderlib/spyder.py:702
+#, fuzzy
+msgid "Reset Spyder to factory defaults"
+msgstr "Restaurar os valores padrões."
+
+#: spyderlib/spyder.py:707
+msgid "Current user environment variables..."
+msgstr "Variáveis de ambiente do usuário atual..."
+
+#: spyderlib/spyder.py:709
+msgid ""
+"Show and edit current user environment variables in Windows registry (i.e. "
+"for all sessions)"
+msgstr ""
+"Mostrar e editar as variáveis de\n"
+"ambiente do usuário atual no\n"
+"registro do Windows (para todas\n"
+"as sessões)"
+
+#: spyderlib/spyder.py:718 spyderlib/spyder.py:1178
+msgid "External Tools"
+msgstr "Ferramentas externas"
+
+#: spyderlib/spyder.py:722
+msgid "Python(x,y) launcher"
+msgstr "Lançador do Python(x,y)"
+
+#: spyderlib/spyder.py:729
+msgid "WinPython control panel"
+msgstr "Painel de controle WinPython"
+
+#: spyderlib/spyder.py:738
+msgid "Qt Designer"
+msgstr "Qt Designer"
+
+#: spyderlib/spyder.py:743
+msgid "Qt Linguist"
+msgstr "Qt Linguist"
+
+#: spyderlib/spyder.py:749
+msgid "Qt examples"
+msgstr "Exemplos do Qt"
+
+#: spyderlib/spyder.py:770
+msgid "guidata examples"
+msgstr "Exemplos do guidata"
+
+#: spyderlib/spyder.py:781
+msgid "guiqwt examples"
+msgstr "Exemplos do guiqwt"
+
+#: spyderlib/spyder.py:786
+msgid "Sift"
+msgstr "Sift"
+
+#: spyderlib/spyder.py:796
+msgid "ViTables"
+msgstr "ViTables"
+
+#: spyderlib/spyder.py:810
+msgid "Fullscreen mode"
+msgstr "Modo tela cheia"
+
+#: spyderlib/spyder.py:822
+msgid "Main toolbar"
+msgstr "Barra principal"
+
+#: spyderlib/spyder.py:831
+msgid ""
+"Spyder Internal Console\n"
+"\n"
+"This console is used to report application\n"
+"internal errors and to inspect Spyder\n"
+"internals with the following commands:\n"
+"  spy.app, spy.window, dir(spy)\n"
+"\n"
+"Please don't use it to run your code\n"
+"\n"
+msgstr ""
+"Console interno do Spyder!\n"
+"\n"
+"Este console é usado para reportar erros\n"
+"internos do aplicativo e para inspecionar\n"
+"as características internas do Spyder com\n"
+"os seguintes comandos:\n"
+"  spy.app, spy.window, dir(spy)\n"
+"\n"
+"Por favor não execute seu código neste console\n"
+
+#: spyderlib/spyder.py:848
+msgid "Loading object inspector..."
+msgstr "Carregando inspetor de objetos..."
+
+#: spyderlib/spyder.py:855
+msgid "Loading outline explorer..."
+msgstr "Carregando o explorador de código..."
+
+#: spyderlib/spyder.py:863
+msgid "Loading editor..."
+msgstr "Carregando editor..."
+
+#: spyderlib/spyder.py:874
+#, fuzzy
+msgid "&Restart"
+msgstr "Restaurar"
+
+#: spyderlib/spyder.py:876
+#, fuzzy
+msgid "Restart"
+msgstr "Restaurar"
+
+#: spyderlib/spyder.py:895
+msgid "Loading file explorer..."
+msgstr "Carregando explorador de arquivos..."
+
+#: spyderlib/spyder.py:902
+msgid "Loading history plugin..."
+msgstr "Carregando histórico..."
+
+#: spyderlib/spyder.py:913
+msgid "Loading online help..."
+msgstr "Carregando ajuda online..."
+
+#: spyderlib/spyder.py:919
+msgid "Loading project explorer..."
+msgstr "Carregando explorador de projetos..."
+
+#: spyderlib/spyder.py:930
+msgid "Loading external console..."
+msgstr "Carregando console externo..."
+
+#: spyderlib/spyder.py:939
+msgid "Loading namespace browser..."
+msgstr "Carregando explorador de variáveis..."
+
+#: spyderlib/spyder.py:946
+msgid "Loading IPython console..."
+msgstr "Carregando console IPython..."
+
+#: spyderlib/spyder.py:956
+msgid "Setting up main window..."
+msgstr "Configurando tela principal..."
+
+#: spyderlib/spyder.py:959
+msgid "Optional dependencies..."
+msgstr "Dependências opcionais... "
+
+#: spyderlib/spyder.py:963
+msgid "Report issue..."
+msgstr "Reportar problema..."
+
+#: spyderlib/spyder.py:967
+msgid "Spyder support..."
+msgstr "Suporte do Spyder..."
+
+#: spyderlib/spyder.py:970
+msgid "Check for updates..."
+msgstr ""
+
+#: spyderlib/spyder.py:993
+msgid "Spyder documentation"
+msgstr "Documentação do Spyder"
+
+#: spyderlib/spyder.py:997
+msgid "Spyder tutorial"
+msgstr "Tutorial do Spyder"
+
+#: spyderlib/spyder.py:1002
+#, fuzzy
+msgid "Interactive tours"
+msgstr "Introspecção"
+
+#: spyderlib/spyder.py:1031
+msgid "Python documentation"
+msgstr "Documentação do Python"
+
+#: spyderlib/spyder.py:1037 spyderlib/spyder.py:1076
+msgid "IPython documentation"
+msgstr "Documentação do IPython"
+
+#: spyderlib/spyder.py:1038
+msgid "Intro to IPython"
+msgstr "Introdução ao IPython"
+
+#: spyderlib/spyder.py:1040
+msgid "Quick reference"
+msgstr "Referência rápida"
+
+#: spyderlib/spyder.py:1042
+msgid "Console help"
+msgstr "Ajuda do console"
+
+#: spyderlib/spyder.py:1074
+msgid "Python(x,y) documentation folder"
+msgstr "Pasta de documentação do Python(x,y)"
+
+#: spyderlib/spyder.py:1078
+msgid "guidata documentation"
+msgstr "Documentação do guidata "
+
+#: spyderlib/spyder.py:1081
+msgid "guiqwt documentation"
+msgstr "Documentação do guiqwt"
+
+#: spyderlib/spyder.py:1087
+msgid "NumPy documentation"
+msgstr "Documentação do NumPy"
+
+#: spyderlib/spyder.py:1089
+msgid "NumPy reference guide"
+msgstr "Guia de referência do NumPy"
+
+#: spyderlib/spyder.py:1091
+msgid "NumPy user guide"
+msgstr "Guia do usuário do NumPy"
+
+#: spyderlib/spyder.py:1093
+msgid "SciPy documentation"
+msgstr "Documentação do SciPy"
+
+#: spyderlib/spyder.py:1100
+msgid "Installed Python modules"
+msgstr "Módulos instalados do Python"
+
+#: spyderlib/spyder.py:1104
+msgid "Online documentation"
+msgstr "Documentação online"
+
+#: spyderlib/spyder.py:1116
+msgid "Qt documentation"
+msgstr "Documentação do Qt"
+
+#: spyderlib/spyder.py:1122
+msgid "About %s..."
+msgstr "Sobre o %s..."
+
+#: spyderlib/spyder.py:1146
+msgid "Panes"
+msgstr "Painéis"
+
+#: spyderlib/spyder.py:1147
+msgid "Toolbars"
+msgstr "Barra de ferramentas"
+
+#: spyderlib/spyder.py:1148
+#, fuzzy
+msgid "Window layouts"
+msgstr "Esquema personalizado dos componentes"
+
+#: spyderlib/spyder.py:1157 spyderlib/spyder.py:1910 spyderlib/spyder.py:1911
+#, fuzzy
+msgid "Show toolbars"
+msgstr "Mostrar barra de ferramentas"
+
+#: spyderlib/spyder.py:1171
+msgid "Attached console window (debugging)"
+msgstr "Janela do console anexada (depuração)"
+
+#: spyderlib/spyder.py:1756
+msgid "Spyder Default Layout"
+msgstr ""
+
+#: spyderlib/spyder.py:1774 spyderlib/spyder.py:1785
+#, fuzzy
+msgid "Save current layout"
+msgstr "Salvar arquivo atual como..."
+
+#: spyderlib/spyder.py:1778 spyderlib/spyder.py:1787
+#, fuzzy
+msgid "Layout preferences"
+msgstr "Preferências"
+
+#: spyderlib/spyder.py:1782
+#, fuzzy
+msgid "Reset to spyder default"
+msgstr "Restaurar os valores padrões."
+
+#: spyderlib/spyder.py:1804
+msgid ""
+"Window layout will be reset to default settings: this affects window "
+"position, size and dockwidgets.\n"
+"Do you want to continue?"
+msgstr ""
+"O esquema das janelas será reiniciado para as configurações padrões: isso "
+"afeta a posição, tamanho e componentes da janela.\n"
+"Deseja continuar?"
+
+#: spyderlib/spyder.py:1826
+msgid ""
+"Layout <b>%s</b> will be                                                "
+"overwritten. Do you want to                                                "
+"continue?"
+msgstr ""
+
+#: spyderlib/spyder.py:1889
+#, fuzzy
+msgid "Quick switch layout #%s has not yet been defined."
+msgstr "Ainda não foi definido o esquema do componente #%d."
+
+#: spyderlib/spyder.py:1907 spyderlib/spyder.py:1908
+#, fuzzy
+msgid "Hide toolbars"
+msgstr "Barra de arquivo"
+
+#: spyderlib/spyder.py:2229 spyderlib/spyder.py:2230
+msgid "Maximize current pane"
+msgstr "Maximizar painel atual"
+
+#: spyderlib/spyder.py:2233
+msgid "Restore current pane"
+msgstr "Restaurar painel atual"
+
+#: spyderlib/spyder.py:2234
+msgid "Restore pane to its original size"
+msgstr "Restaurar painel ao seu tamanho original"
+
+#: spyderlib/spyder.py:2318
+msgid "About %s"
+msgstr "Sobre o %s"
+
+#: spyderlib/spyder.py:2502
+msgid "Running an external system terminal is not supported on platform %s."
+msgstr "Executar um terminal externo não é suportado na plataforma %s."
+
+#: spyderlib/spyder.py:2721
+msgid "Open session"
+msgstr "Abrir sessão"
+
+#: spyderlib/spyder.py:2722 spyderlib/spyder.py:2734
+msgid "Spyder sessions"
+msgstr "Sessões do Spyder"
+
+#: spyderlib/spyder.py:2733
+msgid "Save session"
+msgstr "Salvar sessão"
+
+#: spyderlib/spyder.py:2775
+#, fuzzy
+msgid ""
+"Spyder will restart and reset to default settings: <br><br>Do you want to "
+"continue?"
+msgstr ""
+"O seguinte diretório não está vazio:<br><b>%s</b><br><br>Deseja continuar?"
+
+#: spyderlib/spyder.py:2871 spyderlib/widgets/helperwidgets.py:144
+#, fuzzy
+msgid "Spyder updates"
+msgstr "Arquivos data do Spyder"
+
+#: spyderlib/spyder.py:2890
+msgid ""
+"<b>Spyder %s is available!</b> <br><br>Please use your package manager to "
+"update Spyder or go to our <a href=\"%s\">Releases</a> page to download this "
+"new version. <br><br>If you are not sure how to proceed to update Spyder "
+"please refer to our  <a href=\"%s\">Installation</a> instructions."
+msgstr ""
+
+#: spyderlib/spyder.py:2902
+#, fuzzy
+msgid "Spyder is up to date."
+msgstr "Suporte do Spyder..."
+
+#: spyderlib/tour.py:121
+#, fuzzy
+msgid "Welcome to the Introduction tour"
+msgstr "Bem-vindo ao Spyder!"
+
+#: spyderlib/tour.py:122
+msgid ""
+"<b>Spyder</b> is a powerful Interactive Development Environment (or IDE) for "
+"the Python programming language.<br><br>Here we are going to guide you "
+"through its most important features.<br><br>Please use the arrow keys or "
+"click on the buttons below to move along the tour."
+msgstr ""
+
+#: spyderlib/tour.py:131
+#, fuzzy
+msgid "The Editor"
+msgstr "Editor de texto"
+
+#: spyderlib/tour.py:132
+msgid ""
+"This is the pane where you write Python code before evaluating it. You can "
+"get automatic suggestions and completions while writing, by pressing the "
+"<b>Tab</b> key next to a given text.<br><br>The Editor comes with a line "
+"number area (highlighted here in red), where Spyder shows warnings and "
+"syntax errors. They can help you to detect potential problems before running "
+"the code.<br><br>You can also set debug breakpoints in the line number area, "
+"by doing a double click next to a non-empty line."
+msgstr ""
+
+#: spyderlib/tour.py:147
+#, fuzzy
+msgid "The IPython console"
+msgstr "Console IPython"
+
+#: spyderlib/tour.py:164
+#, fuzzy
+msgid "The Variable Explorer"
+msgstr "Explorador de variáveis"
+
+#: spyderlib/tour.py:165
+msgid ""
+"In this pane you can view and edit the variables generated during the "
+"execution of a program, or those entered directly in one of Spyder consoles."
+"<br><br>As you can see, the Variable Explorer is showing the variables "
+"generated during the last step of this tour. By doing a double-click on any "
+"of them, a new window will be opened, where you can inspect and modify their "
+"contents."
+msgstr ""
+
+#: spyderlib/tour.py:177
+#, fuzzy
+msgid "The Python console"
+msgstr "Console IPython"
+
+#: spyderlib/tour.py:178
+msgid ""
+"You can also run your code on a Python console. These consoles are useful "
+"because they let you run a file in a console dedicated only to it.To select "
+"this behavior, please press the <b>F6</b> key.<br><br>By pressing the button "
+"below and then focusing the Variable Explorer, you will notice that Python "
+"consoles are also connected to that pane, and that the Variable Explorer "
+"only shows the variables of the currently focused console."
+msgstr ""
+
+#: spyderlib/tour.py:192
+#, fuzzy
+msgid "The Object Inspector"
+msgstr "Inspetor de objetos"
+
+#: spyderlib/tour.py:193
+msgid ""
+"This pane displays documentation of the functions, classes, methods or "
+"modules you are currently using in the Editor or the Consoles.<br><br>To use "
+"it, you need to press <b>Ctrl+I</b> in front of an object. If that object "
+"has some documentation associated with it, it will be displayed here."
+msgstr ""
+
+#: spyderlib/tour.py:203
+#, fuzzy
+msgid "The File Explorer"
+msgstr "Explorador de arquivos"
+
+#: spyderlib/tour.py:204
+msgid ""
+"This pane lets you navigate through the directories and files present in "
+"your computer.<br><br>You can also open any of these files with its "
+"corresponding application, by doing a double click on it.<br><br>There is "
+"one exception to this rule: plain-text files will always be opened in the "
+"Spyder Editor."
+msgstr ""
+
+#: spyderlib/tour.py:214
+#, fuzzy
+msgid "The History Log"
+msgstr "Log do histórico "
+
+#: spyderlib/tour.py:215
+msgid ""
+"This pane records all commands introduced in the Python and IPython consoles."
+msgstr ""
+
+#: spyderlib/tour.py:263
+msgid "<b>Spyder</b> is an interactive development environment based on bla"
+msgstr ""
+
+#: spyderlib/tour.py:267
+#, fuzzy
+msgid "Welcome to Spyder introduction tour"
+msgstr "Bem-vindo ao Spyder!"
+
+#: spyderlib/tour.py:268
+msgid "Spyder is an interactive development environment based on bla"
+msgstr ""
+
+#: spyderlib/tour.py:273
+#, fuzzy
+msgid "Introduction tour"
+msgstr "Introspecção"
+
+#: spyderlib/tour.py:274
+msgid "New features in version 3.0"
+msgstr ""
+
+#: spyderlib/tour.py:821
+#, fuzzy
+msgid "Go to step: "
+msgstr "Ir para a linha:"
+
+#: spyderlib/utils/codeanalysis.py:92
+msgid "Real-time code analysis on the Editor"
+msgstr "Análise de código em tempo real no editor"
+
+#: spyderlib/utils/codeanalysis.py:96
+msgid "Real-time code style analysis on the Editor"
+msgstr "Análise de estilo em tempo real no editor."
+
+#: spyderlib/utils/environ.py:96
+msgid ""
+"Module <b>pywin32 was not found</b>.<br>Please restart this Windows "
+"<i>session</i> (not the computer) for changes to take effect."
+msgstr ""
+"O módulo <b>pywin32 não foi encontrado</b>.<br>Por favor reinicie esta "
+"<i>sessão</i> do Windows (não do computador) para que as mudanças tenham "
+"efeito."
+
+#: spyderlib/utils/environ.py:109
+msgid ""
+"If you accept changes, this will modify the current user environment "
+"variables directly <b>in Windows registry</b>. Use it with precautions, at "
+"your own risks.<br><br>Note that for changes to take effect, you will need "
+"to restart the parent process of this application (simply restart Spyder if "
+"you have executed it from a Windows shortcut, otherwise restart any "
+"application from which you may have executed it, like <i>Python(x,y) Home</"
+"i> for example)"
+msgstr ""
+"Se você aceitar, as variáveis de ambiente atuais serão modificadas <b>no "
+"registro do Windows</b>. Use com precaução, em seu próprio risco."
+"<br><br>Tenha em mente que para que as mudanças tenham efeito, você deverá "
+"reiniciar o processo pai deste aplicativo (simplesmente reinicie o Spyder se "
+"você executou ele de um atalho, caso contrário reinicie qualquer aplicativo "
+"pelo qual você você executou ele, como o <i>Python(x,y) Home</i>)"
+
+#: spyderlib/utils/inspector/sphinxify.py:212
+#: spyderlib/utils/inspector/sphinxify.py:222
+msgid ""
+"It was not possible to generate rich text help for this object.</br>Please "
+"see it in plain text."
+msgstr ""
+"Não foi possível gerar ajuda em texto formatado para este objeto.</br>Por "
+"favor veja em texto normal."
+
+#: spyderlib/utils/introspection/jedi_plugin.py:32
+#, fuzzy
+msgid "(Experimental) Editor's code completion, go-to-definition and help"
+msgstr "Completador de código e ajuda no Editor"
+
+#: spyderlib/utils/introspection/rope_plugin.py:37
+msgid "Editor's code completion, go-to-definition and help"
+msgstr "Completador de código e ajuda no Editor"
+
+#: spyderlib/utils/iofuncs.py:482
+msgid "Supported files"
+msgstr "Arquivos suportados"
+
+#: spyderlib/utils/iofuncs.py:484
+msgid "All files (*.*)"
+msgstr "Todos os arquivos (*.*)"
+
+#: spyderlib/utils/iofuncs.py:494
+msgid "Spyder data files"
+msgstr "Arquivos data do Spyder"
+
+#: spyderlib/utils/iofuncs.py:496 spyderlib/widgets/dicteditor.py:1056
+msgid "NumPy arrays"
+msgstr "Matrizes do NumPy"
+
+#: spyderlib/utils/iofuncs.py:497
+msgid "NumPy zip arrays"
+msgstr "Matrizes comprimidas do NumPy"
+
+#: spyderlib/utils/iofuncs.py:498
+msgid "Matlab files"
+msgstr "Arquivos do Matlab"
+
+#: spyderlib/utils/iofuncs.py:499
+msgid "CSV text files"
+msgstr "Arquivos de texto CSV"
+
+#: spyderlib/utils/iofuncs.py:501
+msgid "JPEG images"
+msgstr "Imagens JPEG"
+
+#: spyderlib/utils/iofuncs.py:502
+msgid "PNG images"
+msgstr "Imagens PNG"
+
+#: spyderlib/utils/iofuncs.py:503
+msgid "GIF images"
+msgstr "Imagens GIF"
+
+#: spyderlib/utils/iofuncs.py:504
+msgid "TIFF images"
+msgstr "Imagens TIFF"
+
+#: spyderlib/utils/iofuncs.py:505 spyderlib/utils/iofuncs.py:506
+msgid "Pickle files"
+msgstr "Arquivos Pickle"
+
+#: spyderlib/utils/iofuncs.py:507
+msgid "JSON files"
+msgstr "Arquivos JSON"
+
+#: spyderlib/utils/iofuncs.py:526 spyderlib/utils/iofuncs.py:533
+msgid "<b>Unsupported file type '%s'</b>"
+msgstr "<b>Tipo de arquivo não suportado '%s'</b>"
+
+#: spyderlib/utils/programs.py:176
+msgid "It was not possible to run this file in an external terminal"
+msgstr ""
+
+#: spyderlib/widgets/arraybuilder.py:162
+msgid ""
+"\n"
+"           <b>Numpy Array/Matrix Helper</b><br>\n"
+"           Type an array in Matlab    : <code>[1 2;3 4]</code><br>\n"
+"           or Spyder simplified syntax : <code>1 2;3 4</code>\n"
+"           <br><br>\n"
+"           Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n"
+"           <br><br>\n"
+"           <b>Hint:</b><br>\n"
+"           Use two spaces or two tabs to generate a ';'.\n"
+"           "
+msgstr ""
+
+#: spyderlib/widgets/arraybuilder.py:173
+msgid ""
+"\n"
+"           <b>Numpy Array/Matrix Helper</b><br>\n"
+"           Enter an array in the table. <br>\n"
+"           Use Tab to move between cells.\n"
+"           <br><br>\n"
+"           Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n"
+"           <br><br>\n"
+"           <b>Hint:</b><br>\n"
+"           Use two tabs at the end of a row to move to the next row.\n"
+"           "
+msgstr ""
+
+#: spyderlib/widgets/arraybuilder.py:337
+msgid "Array dimensions not valid"
+msgstr ""
+
+#: spyderlib/widgets/arrayeditor.py:453 spyderlib/widgets/arrayeditor.py:486
+#: spyderlib/widgets/dataframeeditor.py:508
+#: spyderlib/widgets/dataframeeditor.py:548
+msgid "Format"
+msgstr "Formato"
+
+#: spyderlib/widgets/arrayeditor.py:458
+#: spyderlib/widgets/dataframeeditor.py:512
+msgid "Resize"
+msgstr "Redimensionar"
+
+#: spyderlib/widgets/arrayeditor.py:487
+#: spyderlib/widgets/dataframeeditor.py:549
+msgid "Float formatting"
+msgstr "Formatação de ponto flutuante"
+
+#: spyderlib/widgets/arrayeditor.py:494
+#: spyderlib/widgets/dataframeeditor.py:557 spyderlib/widgets/explorer.py:587
+#: spyderlib/widgets/explorer.py:689
+#: spyderlib/widgets/externalshell/pythonshell.py:553
+#: spyderlib/widgets/externalshell/systemshell.py:99
+msgid "Error"
+msgstr "Error"
+
+#: spyderlib/widgets/arrayeditor.py:495
+#: spyderlib/widgets/dataframeeditor.py:558
+msgid "Format (%s) is incorrect"
+msgstr "O formato (%s) está incorreto"
+
+#: spyderlib/widgets/arrayeditor.py:529
+msgid "Array is empty"
+msgstr "A matriz está vazia"
+
+#: spyderlib/widgets/arrayeditor.py:532
+msgid "Arrays with more than 3 dimensions are not supported"
+msgstr "Matrizes com mais de 3 dimensões não são suportadas"
+
+#: spyderlib/widgets/arrayeditor.py:535
+msgid "The 'xlabels' argument length do no match array column number"
+msgstr ""
+"O argumento de comprimento 'xlabels' não corresponde com o número de colunas "
+"da matriz"
+
+#: spyderlib/widgets/arrayeditor.py:539
+msgid "The 'ylabels' argument length do no match array row number"
+msgstr ""
+"O argumento de comprimento 'ylabels' não corresponde com o número de linhas "
+"da matriz"
+
+#: spyderlib/widgets/arrayeditor.py:546
+msgid "%s arrays"
+msgstr "%s matrizes"
+
+#: spyderlib/widgets/arrayeditor.py:547
+msgid "%s are currently not supported"
+msgstr "%s não é suportado no momento"
+
+#: spyderlib/widgets/arrayeditor.py:554
+#, fuzzy
+msgid "NumPy array"
+msgstr "Matrizes do NumPy"
+
+#: spyderlib/widgets/arrayeditor.py:556 spyderlib/widgets/arrayeditor.py:710
+msgid "Array editor"
+msgstr "Editor de matrizes"
+
+#: spyderlib/widgets/arrayeditor.py:558
+msgid "read only"
+msgstr "somente leitura"
+
+#: spyderlib/widgets/arrayeditor.py:588
+msgid "Record array fields:"
+msgstr "Campos de matrizes registradas:"
+
+#: spyderlib/widgets/arrayeditor.py:600
+msgid "Data"
+msgstr "Dados"
+
+#: spyderlib/widgets/arrayeditor.py:600
+msgid "Mask"
+msgstr "Máscara"
+
+#: spyderlib/widgets/arrayeditor.py:600
+msgid "Masked data"
+msgstr "Dados mascarados"
+
+#: spyderlib/widgets/arrayeditor.py:611
+msgid "Axis:"
+msgstr "Eixo:"
+
+#: spyderlib/widgets/arrayeditor.py:616
+msgid "Index:"
+msgstr "Índice:"
+
+#: spyderlib/widgets/arrayeditor.py:629
+msgid "<u>Warning</u>: changes are applied separately"
+msgstr "<u>Aviso</u>: mudanças são aplicadas de forma separada"
+
+#: spyderlib/widgets/arrayeditor.py:630
+msgid ""
+"For performance reasons, changes applied to masked array won't be reflected "
+"in array's data (and vice-versa)."
+msgstr ""
+"Por motivos de desempenho, as mudanças\n"
+"aplicadas a matrizes mascaradas não serão\n"
+"refletidas nos dados da matriz\n"
+"(e vice-versa)."
+
+#: spyderlib/widgets/browser.py:31
+#: spyderlib/widgets/sourcecode/codeeditor.py:2468
+msgid "Zoom out"
+msgstr "Menos zoom"
+
+#: spyderlib/widgets/browser.py:34
+#: spyderlib/widgets/sourcecode/codeeditor.py:2465
+msgid "Zoom in"
+msgstr "Mais zoom"
+
+#: spyderlib/widgets/browser.py:131
+msgid "Home"
+msgstr "Página inicial"
+
+#: spyderlib/widgets/browser.py:166
+msgid "Find text"
+msgstr "Buscar texto"
+
+#: spyderlib/widgets/browser.py:184
+msgid "Address:"
+msgstr "Endereço:"
+
+#: spyderlib/widgets/browser.py:220
+msgid "Unable to load page"
+msgstr "Não foi possível carregar a página"
+
+#: spyderlib/widgets/comboboxes.py:118
+msgid "Press enter to validate this entry"
+msgstr "Aperte enter para validar esta entrada"
+
+#: spyderlib/widgets/comboboxes.py:119
+msgid "This entry is incorrect"
+msgstr "Esta entrada é incorreta"
+
+#: spyderlib/widgets/comboboxes.py:174
+msgid "Press enter to validate this path"
+msgstr "Aperte enter para validar esse caminho"
+
+#: spyderlib/widgets/comboboxes.py:175
+msgid ""
+"This path is incorrect.\n"
+"Enter a correct directory path,\n"
+"then press enter to validate"
+msgstr ""
+"Este caminho está incorreto.\n"
+"Digite um caminho correto,\n"
+"depois aperte enter para validar"
+
+#: spyderlib/widgets/dataframeeditor.py:423
+msgid "To bool"
+msgstr "Para booleano"
+
+#: spyderlib/widgets/dataframeeditor.py:423
+msgid "To complex"
+msgstr "Para complexo"
+
+#: spyderlib/widgets/dataframeeditor.py:424
+msgid "To float"
+msgstr "Para flutuante"
+
+#: spyderlib/widgets/dataframeeditor.py:424
+msgid "To int"
+msgstr "Para inteiro"
+
+#: spyderlib/widgets/dataframeeditor.py:425
+msgid "To str"
+msgstr "Para string"
+
+#: spyderlib/widgets/dataframeeditor.py:490
+msgid "%s editor"
+msgstr "Editor de %s"
+
+#: spyderlib/widgets/dataframeeditor.py:522
+msgid "Column min/max"
+msgstr "Min/max de coluna"
+
+#: spyderlib/widgets/dependencies.py:59
+msgid " Required "
+msgstr "Requerido"
+
+#: spyderlib/widgets/dependencies.py:59
+msgid "Module"
+msgstr "Módulo "
+
+#: spyderlib/widgets/dependencies.py:60
+msgid " Installed "
+msgstr "Instalado"
+
+#: spyderlib/widgets/dependencies.py:60
+msgid "Provided features"
+msgstr "Características proporcionadas"
+
+#: spyderlib/widgets/dependencies.py:130
+msgid "Optional Dependencies"
+msgstr "Dependências Opcionais"
+
+#: spyderlib/widgets/dependencies.py:137
+msgid ""
+"Spyder depends on several Python modules to provide additional functionality "
+"for its plugins. The table below shows the required and installed versions "
+"(if any) of all of them.<br><br>Although Spyder can work without any of "
+"these modules, it's strongly recommended that at least you try to install <b>"
+"%s</b> and <b>%s</b> to have a much better experience."
+msgstr ""
+"O Spyder depende de vários módulos do Python para oferecer funcionalidade "
+"adicional para seus componentes. A tabela que apareçe abaixo mostra as "
+"versões requeridas e instaladas (se existir) de todos eles.<br><br>Embora o "
+"Spyder possa funcionar sem nenhum destes módulos, é recomendado ao menos "
+"instalar <b>%s</b> e <b>%s</b> para ter uma melhor experiência."
+
+#: spyderlib/widgets/dependencies.py:152
+msgid "Copy to clipboard"
+msgstr "Copiar para área transferência "
+
+#: spyderlib/widgets/dicteditor.py:156
+msgid "Index"
+msgstr "Índice"
+
+#: spyderlib/widgets/dicteditor.py:161
+msgid "Tuple"
+msgstr "Tupla"
+
+#: spyderlib/widgets/dicteditor.py:164
+msgid "List"
+msgstr "Lista"
+
+#: spyderlib/widgets/dicteditor.py:167
+msgid "Dictionary"
+msgstr "Dicionário "
+
+#: spyderlib/widgets/dicteditor.py:169
+msgid "Key"
+msgstr "Chave"
+
+#: spyderlib/widgets/dicteditor.py:175
+msgid "Attribute"
+msgstr "Atributo"
+
+#: spyderlib/widgets/dicteditor.py:177
+msgid "elements"
+msgstr "elementos"
+
+#: spyderlib/widgets/dicteditor.py:356
+msgid "Size"
+msgstr "Tamanho"
+
+#: spyderlib/widgets/dicteditor.py:356
+msgid "Type"
+msgstr "Tipo"
+
+#: spyderlib/widgets/dicteditor.py:356
+msgid "Value"
+msgstr "Valor"
+
+#: spyderlib/widgets/dicteditor.py:453
+#, fuzzy
+msgid ""
+"Opening this variable can be slow\n"
+"\n"
+"Do you want to continue anyway?"
+msgstr ""
+"Abrir e inspecionar esse %s pode ser lento\n"
+"\n"
+"Deseja continuar mesmo assim?"
+
+#: spyderlib/widgets/dicteditor.py:461 spyderlib/widgets/dicteditor.py:612
+msgid "Edit item"
+msgstr "Editar item"
+
+#: spyderlib/widgets/dicteditor.py:462
+msgid "<b>Unable to retrieve data.</b><br><br>Error message:<br>%s"
+msgstr "<b>Não foi possível obter os dados.</b><br><br>Mensagem de erro:<br>%s"
+
+#: spyderlib/widgets/dicteditor.py:613
+msgid "<b>Unable to assign data to item.</b><br><br>Error message:<br>%s"
+msgstr ""
+"<b>Não foi possível atribuir dados ao item.</b><br><br>Mensagem de erro:<br>"
+"%s"
+
+#: spyderlib/widgets/dicteditor.py:675
+msgid "Resize rows to contents"
+msgstr "Redimensionar linhas para o conteúdo "
+
+#: spyderlib/widgets/dicteditor.py:683 spyderlib/widgets/explorer.py:242
+msgid "Edit"
+msgstr "Editar"
+
+#: spyderlib/widgets/dicteditor.py:686 spyderlib/widgets/dicteditor.py:1025
+#: spyderlib/widgets/dicteditor.py:1042
+msgid "Plot"
+msgstr "Gráfico"
+
+#: spyderlib/widgets/dicteditor.py:690
+msgid "Histogram"
+msgstr "Histograma"
+
+#: spyderlib/widgets/dicteditor.py:694
+msgid "Show image"
+msgstr "Mostrar imagem"
+
+#: spyderlib/widgets/dicteditor.py:698 spyderlib/widgets/dicteditor.py:1050
+msgid "Save array"
+msgstr "Salvar matriz"
+
+#: spyderlib/widgets/dicteditor.py:702 spyderlib/widgets/dicteditor.py:989
+#: spyderlib/widgets/dicteditor.py:997
+msgid "Insert"
+msgstr "Inserir"
+
+#: spyderlib/widgets/dicteditor.py:705 spyderlib/widgets/dicteditor.py:939
+msgid "Remove"
+msgstr "Remover"
+
+#: spyderlib/widgets/dicteditor.py:716 spyderlib/widgets/dicteditor.py:956
+#: spyderlib/widgets/explorer.py:532 spyderlib/widgets/explorer.py:540
+#: spyderlib/widgets/explorer.py:551
+msgid "Rename"
+msgstr "Renomear"
+
+#: spyderlib/widgets/dicteditor.py:719
+msgid "Duplicate"
+msgstr "Duplicar"
+
+#: spyderlib/widgets/dicteditor.py:937
+msgid "Do you want to remove selected item?"
+msgstr "Você deseja remover o item selecionado?"
+
+#: spyderlib/widgets/dicteditor.py:938
+msgid "Do you want to remove all selected items?"
+msgstr "Você deseja remover todos os itens selecionados?"
+
+#: spyderlib/widgets/dicteditor.py:956 spyderlib/widgets/dicteditor.py:989
+msgid "Key:"
+msgstr "Chave:"
+
+#: spyderlib/widgets/dicteditor.py:997
+msgid "Value:"
+msgstr "Valor:"
+
+#: spyderlib/widgets/dicteditor.py:1013
+msgid "Import error"
+msgstr "Erro de importação"
+
+#: spyderlib/widgets/dicteditor.py:1014
+msgid "Please install <b>matplotlib</b> or <b>guiqwt</b>."
+msgstr "Por favor instale <b>matplotlib</b> ou <b>guiqwt</b>."
+
+#: spyderlib/widgets/dicteditor.py:1026
+msgid "<b>Unable to plot data.</b><br><br>Error message:<br>%s"
+msgstr ""
+"<b>Não foi possível mostrar os dados.</b><br><br>Mensagem de erro:<br>%s"
+
+#: spyderlib/widgets/dicteditor.py:1043
+msgid "<b>Unable to show image.</b><br><br>Error message:<br>%s"
+msgstr ""
+"<b>Não foi possível mostrar o gráfico.</b><br><br>Mensagem de erro:<br>%s"
+
+#: spyderlib/widgets/dicteditor.py:1066
+msgid "<b>Unable to save array</b><br><br>Error message:<br>%s"
+msgstr "<b>Não foi possível salvar matriz</b><br><br>Mensagem de erro:<br>%s"
+
+#: spyderlib/widgets/dicteditor.py:1085
+msgid "Clipboard contents"
+msgstr "Conteúdo da área de transferência "
+
+#: spyderlib/widgets/dicteditor.py:1100
+msgid "Import from clipboard"
+msgstr "Importar da área de transferência "
+
+#: spyderlib/widgets/dicteditor.py:1102
+msgid "Empty clipboard"
+msgstr "Área de transferência vazia"
+
+#: spyderlib/widgets/dicteditor.py:1103
+msgid "Nothing to be imported from clipboard."
+msgstr "Não há nada para ser importado da área de transferência."
+
+#: spyderlib/widgets/dicteditorutils.py:60
+msgid "View and edit DataFrames and Series in the Variable Explorer"
+msgstr "Ver e editar DataFrames e Series no Explorador de Variáveis"
+
+#: spyderlib/widgets/editor.py:342
+msgid "Copy path to clipboard"
+msgstr "Copiar caminho para área de transferência"
+
+#: spyderlib/widgets/editor.py:906
+msgid "Temporary file"
+msgstr "Arquivo temporário "
+
+#: spyderlib/widgets/editor.py:1003
+msgid "New window"
+msgstr "Nova janela"
+
+#: spyderlib/widgets/editor.py:1004
+msgid "Create a new editor window"
+msgstr "Criar uma nova janela de edição"
+
+#: spyderlib/widgets/editor.py:1007
+msgid "Split vertically"
+msgstr "Dividir verticalmente"
+
+#: spyderlib/widgets/editor.py:1009
+msgid "Split vertically this editor window"
+msgstr "Dividir verticalmente esta janela de edição"
+
+#: spyderlib/widgets/editor.py:1011
+msgid "Split horizontally"
+msgstr "Dividir horizontalmente"
+
+#: spyderlib/widgets/editor.py:1013
+msgid "Split horizontally this editor window"
+msgstr "Dividir horizontalmente esta janela de edição"
+
+#: spyderlib/widgets/editor.py:1015
+msgid "Close this panel"
+msgstr "Fechar este painel"
+
+#: spyderlib/widgets/editor.py:1153
+msgid "<b>%s</b> has been modified.<br>Do you want to save changes?"
+msgstr "<b>%s</b> foi modificado.<br>Deseja salvar as mudanças?"
+
+#: spyderlib/widgets/editor.py:1215
+msgid "Save"
+msgstr "Salvar"
+
+#: spyderlib/widgets/editor.py:1216
+msgid "<b>Unable to save script '%s'</b><br><br>Error message:<br>%s"
+msgstr ""
+"<b>Não foi possível salvar o script '%s'</b><br><br>Mensagem de erro:<br>%s"
+
+#: spyderlib/widgets/editor.py:1238
+msgid "Save Python script"
+msgstr "Salvar script Python"
+
+#: spyderlib/widgets/editor.py:1452
+msgid ""
+"<b>%s</b> is unavailable (this file may have been removed, moved or renamed "
+"outside Spyder).<br>Do you want to close it?"
+msgstr ""
+"<b>%s</b> está indisponível (o arquivo pode ter sido removido, movido ou "
+"renomeado fora do Spyder).<br>Deseja fechar?"
+
+#: spyderlib/widgets/editor.py:1472
+msgid ""
+"<b>%s</b> has been modified outside Spyder.<br>Do you want to reload it and "
+"lose all your changes?"
+msgstr ""
+"<b>%s</b> foi modificado fora do Spyder.<br>Você deseja recarregar ele e "
+"perder todas as modificações?"
+
+#: spyderlib/widgets/editor.py:1568
+msgid ""
+"All changes to <b>%s</b> will be lost.<br>Do you want to revert file from "
+"disk?"
+msgstr ""
+"Todas as modificações do <b>%s</b> foram perdidas.<br>Você deseja reverter o "
+"arquivo do disco?"
+
+#: spyderlib/widgets/editor.py:1708
+msgid "Loading %s..."
+msgstr "Carregando %s..."
+
+#: spyderlib/widgets/editor.py:1718
+msgid ""
+"<b>%s</b> contains mixed end-of-line characters.<br>Spyder will fix this "
+"automatically."
+msgstr ""
+"<b>%s</b> contém vários tipos de caracteres de fim de linha.<br>O Spyder irá "
+"corrigir automaticamente."
+
+#: spyderlib/widgets/editor.py:2083
+msgid "Close window"
+msgstr "Fechar janela"
+
+#: spyderlib/widgets/editor.py:2085
+msgid "Close this window"
+msgstr "Fechar esta janela"
+
+#: spyderlib/widgets/editortools.py:94 spyderlib/widgets/editortools.py:130
+msgid "Line %s"
+msgstr "Linha %s"
+
+#: spyderlib/widgets/editortools.py:99
+msgid "Class defined at line %s"
+msgstr "Classe definida na linha %s"
+
+#: spyderlib/widgets/editortools.py:107
+msgid "Method defined at line %s"
+msgstr "Método definido na linha %s"
+
+#: spyderlib/widgets/editortools.py:117
+msgid "Function defined at line %s"
+msgstr "Função definida na linha %s"
+
+#: spyderlib/widgets/editortools.py:149
+msgid "Cell starts at line %s"
+msgstr "A célula inicia na linha %s"
+
+#: spyderlib/widgets/editortools.py:202 spyderlib/widgets/editortools.py:539
+msgid "Go to cursor position"
+msgstr "Ir para a posição do cursor "
+
+#: spyderlib/widgets/editortools.py:205
+msgid "Show absolute path"
+msgstr "Mostrar o caminho completo"
+
+#: spyderlib/widgets/editortools.py:208 spyderlib/widgets/explorer.py:179
+msgid "Show all files"
+msgstr "Mostrar todos os arquivos"
+
+#: spyderlib/widgets/editortools.py:211
+msgid "Show special comments"
+msgstr "Mostrar comentários especiais"
+
+#: spyderlib/widgets/explorer.py:175
+msgid "Edit filename filters..."
+msgstr "Editar filtros para nomes de arquivos..."
+
+#: spyderlib/widgets/explorer.py:189
+msgid "Edit filename filters"
+msgstr "Editar filtros para nomes de arquivos"
+
+#: spyderlib/widgets/explorer.py:190
+msgid "Name filters:"
+msgstr "Nome dos filtros:"
+
+#: spyderlib/widgets/explorer.py:209
+msgid "File..."
+msgstr "Arquivo..."
+
+#: spyderlib/widgets/explorer.py:213
+msgid "Module..."
+msgstr "Módulo..."
+
+#: spyderlib/widgets/explorer.py:217
+msgid "Folder..."
+msgstr "Pasta..."
+
+#: spyderlib/widgets/explorer.py:221
+msgid "Package..."
+msgstr "Pacote..."
+
+#: spyderlib/widgets/explorer.py:244
+msgid "Move..."
+msgstr "Mover..."
+
+#: spyderlib/widgets/explorer.py:247
+msgid "Delete..."
+msgstr "Deletar..."
+
+#: spyderlib/widgets/explorer.py:250
+msgid "Rename..."
+msgstr "Renomear..."
+
+#: spyderlib/widgets/explorer.py:253
+msgid "Open"
+msgstr "Abrir"
+
+#: spyderlib/widgets/explorer.py:254
+#: spyderlib/widgets/sourcecode/codeeditor.py:2456
+msgid "Convert to Python script"
+msgstr "Converter para um script Python"
+
+#: spyderlib/widgets/explorer.py:277
+msgid "Commit"
+msgstr "Enviar"
+
+#: spyderlib/widgets/explorer.py:281
+msgid "Browse repository"
+msgstr "Explorar repositório "
+
+#: spyderlib/widgets/explorer.py:293
+msgid "Open command prompt here"
+msgstr "Abrir prompt de comando aqui"
+
+#: spyderlib/widgets/explorer.py:295
+msgid "Open terminal here"
+msgstr "Abrir terminal aqui"
+
+#: spyderlib/widgets/explorer.py:300
+msgid "Open Python console here"
+msgstr "Abrir console Python aqui"
+
+#: spyderlib/widgets/explorer.py:314
+msgid "New"
+msgstr "Novo"
+
+#: spyderlib/widgets/explorer.py:322
+msgid "Import"
+msgstr "Importar"
+
+#: spyderlib/widgets/explorer.py:471
+msgid "Do you really want to delete <b>%s</b>?"
+msgstr "Deseja mesmo deletar <b>%s</b>?"
+
+#: spyderlib/widgets/explorer.py:489
+msgid "delete"
+msgstr "deletar"
+
+#: spyderlib/widgets/explorer.py:490 spyderlib/widgets/projectexplorer.py:823
+#: spyderlib/widgets/projectexplorer.py:830
+#: spyderlib/widgets/projectexplorer.py:1101
+#: spyderlib/widgets/projectexplorer.py:1186
+msgid "Project Explorer"
+msgstr "Explorador de projetos"
+
+#: spyderlib/widgets/explorer.py:491 spyderlib/widgets/projectexplorer.py:770
+#: spyderlib/widgets/projectexplorer.py:1187
+msgid "<b>Unable to %s <i>%s</i></b><br><br>Error message:<br>%s"
+msgstr "<b>Não foi possível %s <i>%s</i></b><br><br>Mensagem de erro:<br>%s"
+
+#: spyderlib/widgets/explorer.py:514
+#: spyderlib/widgets/sourcecode/codeeditor.py:1987
+#, fuzzy
+msgid "Conversion error"
+msgstr "Erro de conexão"
+
+#: spyderlib/widgets/explorer.py:515
+#: spyderlib/widgets/sourcecode/codeeditor.py:1988
+msgid ""
+"It was not possible to convert this notebook. The error is:\n"
+"\n"
+msgstr ""
+
+#: spyderlib/widgets/explorer.py:533
+msgid "New name:"
+msgstr "Novo nome:"
+
+#: spyderlib/widgets/explorer.py:541
+msgid ""
+"Do you really want to rename <b>%s</b> and overwrite the existing file <b>"
+"%s</b>?"
+msgstr ""
+"Você deseja mesmo renomear <b>%s</b> e sobrescrever o arquivo já existente "
+"<b>%s</b>? "
+
+#: spyderlib/widgets/explorer.py:552
+msgid "<b>Unable to rename file <i>%s</i></b><br><br>Error message:<br>%s"
+msgstr ""
+"<b>Não foi possível renomear arquivo <i>%s</i></b><br><br>Mensagem de erro:"
+"<br>%s"
+
+#: spyderlib/widgets/explorer.py:588
+msgid "<b>Unable to move <i>%s</i></b><br><br>Error message:<br>%s"
+msgstr "<b>Não foi possível mover <i>%s</i></b><br><br>Mensagem de erro:<br>%s"
+
+#: spyderlib/widgets/explorer.py:606
+msgid "<b>Unable to create folder <i>%s</i></b><br><br>Error message:<br>%s"
+msgstr ""
+"<b>Não foi possível criar pasta <i>%s</i></b><br><br>Mensagem de erro:<br>%s"
+
+#: spyderlib/widgets/explorer.py:619 spyderlib/widgets/explorer.py:653
+msgid "<b>Unable to create file <i>%s</i></b><br><br>Error message:<br>%s"
+msgstr ""
+"<b>Não foi possível criar arquivo <i>%s</i></b><br><br>Mensagem de erro:<br>"
+"%s"
+
+#: spyderlib/widgets/explorer.py:627
+msgid "New folder"
+msgstr "Nova pasta"
+
+#: spyderlib/widgets/explorer.py:628
+msgid "Folder name:"
+msgstr "Nome da pasta:"
+
+#: spyderlib/widgets/explorer.py:633
+msgid "New package"
+msgstr "Novo pacote"
+
+#: spyderlib/widgets/explorer.py:634
+msgid "Package name:"
+msgstr "Nome do pacote:"
+
+#: spyderlib/widgets/explorer.py:674
+msgid "New module"
+msgstr "Novo módulo "
+
+#: spyderlib/widgets/explorer.py:686
+msgid ""
+"For %s support, please install one of the<br/> following tools:<br/><br/>  %s"
+msgstr ""
+"Para ter suporte ao %s, por favor instale as<br/> seguintes ferramentas:<br/"
+"><br/>  %s"
+
+#: spyderlib/widgets/explorer.py:690
+msgid "<b>Unable to find external program.</b><br><br>%s"
+msgstr "<b>Não foi possível encontrar o programa externo.</b><br><br>%s"
+
+#: spyderlib/widgets/explorer.py:893
+msgid "Show current directory only"
+msgstr "Mostrar somente o diretório atual"
+
+#: spyderlib/widgets/explorer.py:989
+msgid "You don't have the right permissions to open this directory"
+msgstr ""
+
+#: spyderlib/widgets/explorer.py:1018 spyderlib/widgets/importwizard.py:525
+msgid "Previous"
+msgstr "Anterior"
+
+#: spyderlib/widgets/explorer.py:1024
+msgid "Parent"
+msgstr "Superior"
+
+#: spyderlib/widgets/externalshell/baseshell.py:142
+msgid "Run again this program"
+msgstr "Executar novamente este programa"
+
+#: spyderlib/widgets/externalshell/baseshell.py:145
+msgid "Kill"
+msgstr "Matar"
+
+#: spyderlib/widgets/externalshell/baseshell.py:147
+msgid "Kills the current process, causing it to exit immediately"
+msgstr "Matar o processo atual, fazendo ele fechar imediatamente"
+
+#: spyderlib/widgets/externalshell/baseshell.py:219
+msgid "<span style='color: #44AA44'><b>Running...</b></span>"
+msgstr "<span style='color: #44AA44'><b>Executando...</b></span>"
+
+#: spyderlib/widgets/externalshell/baseshell.py:226
+msgid "Terminated."
+msgstr "Finalizado."
+
+#: spyderlib/widgets/externalshell/baseshell.py:251
+#: spyderlib/widgets/ipython.py:351 spyderlib/widgets/ipython.py:368
+#: spyderlib/widgets/mixins.py:656
+msgid "Arguments"
+msgstr "Argumentos"
+
+#: spyderlib/widgets/externalshell/baseshell.py:252
+msgid "Command line arguments:"
+msgstr "Argumentos da linha de comando:"
+
+#: spyderlib/widgets/externalshell/namespacebrowser.py:191
+msgid "Refresh"
+msgstr "Atualizar"
+
+#: spyderlib/widgets/externalshell/namespacebrowser.py:195
+msgid "Refresh periodically"
+msgstr "Atualizar periodicamente"
+
+#: spyderlib/widgets/externalshell/namespacebrowser.py:199
+#: spyderlib/widgets/externalshell/namespacebrowser.py:453
+msgid "Import data"
+msgstr "Importar data"
+
+#: spyderlib/widgets/externalshell/namespacebrowser.py:202
+#: spyderlib/widgets/externalshell/namespacebrowser.py:541
+#: spyderlib/widgets/externalshell/namespacebrowser.py:562
+msgid "Save data"
+msgstr "Salvar data"
+
+#: spyderlib/widgets/externalshell/namespacebrowser.py:207
+msgid "Save data as..."
+msgstr "Salvar data como..."
+
+#: spyderlib/widgets/externalshell/namespacebrowser.py:215
+msgid "Exclude references which name starts with an underscore"
+msgstr "Excluir variáveis cujo nomes comecem com sublinhado"
+
+#: spyderlib/widgets/externalshell/namespacebrowser.py:223
+msgid "Exclude references which name is uppercase"
+msgstr ""
+"Excluir variáveis cujo nome esteja\n"
+"completamente em maiúsculas"
+
+#: spyderlib/widgets/externalshell/namespacebrowser.py:230
+msgid "Exclude references which name starts with an uppercase character"
+msgstr "Excluir variáveis cujo nome comece com maiúsculas. "
+
+#: spyderlib/widgets/externalshell/namespacebrowser.py:238
+msgid ""
+"Exclude references to unsupported data types (i.e. which won't be handled/"
+"saved correctly)"
+msgstr ""
+"Excluir variáveis que guardam tipos de dados não suportados\n"
+"(aqueles que não podem ser manipulados e armazenados\n"
+" corretamente)"
+
+#: spyderlib/widgets/externalshell/namespacebrowser.py:347
+msgid "Object <b>%s</b> is not picklable"
+msgstr "O objeto <b>%s</b> não é picklable"
+
+#: spyderlib/widgets/externalshell/namespacebrowser.py:473
+msgid ""
+"<b>Unsupported file extension '%s'</b><br><br>Would you like to import it "
+"anyway (by selecting a known file format)?"
+msgstr ""
+"<b>Tipo de arquivo não suportado '%s'</b><br><br>Deseja importar mesmo assim "
+"(selecionando um formato conhecido)?"
+
+#: spyderlib/widgets/externalshell/namespacebrowser.py:481
+msgid "Open file as:"
+msgstr "Abrir arquivo como:"
+
+#: spyderlib/widgets/externalshell/namespacebrowser.py:529
+msgid "<b>Unable to load '%s'</b><br><br>Error message:<br>%s"
+msgstr "<b>Não foi possível carregar '%s'</b><br><br>Mensagem de erro:<br>%s"
+
+#: spyderlib/widgets/externalshell/namespacebrowser.py:563
+msgid "<b>Unable to save current workspace</b><br><br>Error message:<br>%s"
+msgstr ""
+"<b>Não foi possível salvar o espaço de trabalho atual</b><br><br>Mensagem de "
+"erro:<br>%s"
+
+#: spyderlib/widgets/externalshell/pythonshell.py:284
+msgid "Variables"
+msgstr "Variáveis"
+
+#: spyderlib/widgets/externalshell/pythonshell.py:285
+msgid "Show/hide global variables explorer"
+msgstr "Mostrar/esconder o explorador de variáveis "
+
+#: spyderlib/widgets/externalshell/pythonshell.py:289
+msgid "Terminate"
+msgstr "Finalizar"
+
+#: spyderlib/widgets/externalshell/pythonshell.py:290
+msgid ""
+"Attempts to stop the process. The process\n"
+"may not exit as a result of clicking this\n"
+"button (it is given the chance to prompt\n"
+"the user for any unsaved files, etc)."
+msgstr ""
+"Tentativa de parar este processo, mas este\n"
+"pode não ser concluído se esse botão for pressionado\n"
+"(pode ser possível que se peça ao usuário\n"
+"para guardar arquivos ainda não salvos, etc)."
+
+#: spyderlib/widgets/externalshell/pythonshell.py:303
+msgid "Interact"
+msgstr "Interagir"
+
+#: spyderlib/widgets/externalshell/pythonshell.py:305
+msgid "Debug"
+msgstr "Depurar"
+
+#: spyderlib/widgets/externalshell/pythonshell.py:307
+#: spyderlib/widgets/externalshell/pythonshell.py:373
+msgid "Arguments..."
+msgstr "Argumentos..."
+
+#: spyderlib/widgets/externalshell/pythonshell.py:309
+msgid "Post Mortem Debug"
+msgstr ""
+
+#: spyderlib/widgets/externalshell/pythonshell.py:315
+msgid "Working directory"
+msgstr "Diretório de trabalho"
+
+#: spyderlib/widgets/externalshell/pythonshell.py:317
+msgid "Set current working directory"
+msgstr "Definir diretório de trabalho"
+
+#: spyderlib/widgets/externalshell/pythonshell.py:319
+msgid "Environment variables"
+msgstr "Variáveis de ambiente"
+
+#: spyderlib/widgets/externalshell/pythonshell.py:323
+msgid "Show sys.path contents"
+msgstr "Mostrar conteúdo do sys.path"
+
+#: spyderlib/widgets/externalshell/pythonshell.py:369
+msgid "Arguments: %s"
+msgstr "Argumentos: %s"
+
+#: spyderlib/widgets/externalshell/pythonshell.py:371
+msgid "No argument"
+msgstr "Sem argumento"
+
+#: spyderlib/widgets/externalshell/pythonshell.py:550
+msgid ""
+"The kernel failed to start!! That's all we know... Please close this console "
+"and open a new one."
+msgstr ""
+"O kernel falhou ao iniciar!! Isso é tudo que sabemos... Por favor feche este "
+"console e abra um novo."
+
+#: spyderlib/widgets/externalshell/pythonshell.py:554
+msgid "A Python console failed to start!"
+msgstr "Não foi possível iniciar um console Python!"
+
+#: spyderlib/widgets/externalshell/systemshell.py:100
+msgid "Process failed to start"
+msgstr "O processo falhou ao iniciar."
+
+#: spyderlib/widgets/file_switcher.py:109
+#, fuzzy
+msgid "unsaved file"
+msgstr "Salvar arquivo"
+
+#: spyderlib/widgets/file_switcher.py:229
+msgid ""
+"Press <b>Enter</b> to switch files or <b>Esc</b> to cancel.<br><br>Type to "
+"filter filenames.<br><br>Use <b>:number</b> to go to a line, e.g. "
+"<b><code>main:42</code></b><br>Use <b>@symbol_text</b> to go to a symbol, e."
+"g. <b><code>@init</code></b><br><br> Press <b>Ctrl+W</b> to close current "
+"tab.<br>"
+msgstr ""
+
+#: spyderlib/widgets/file_switcher.py:481
+#, fuzzy
+msgid "lines"
+msgstr "linhas"
+
+#: spyderlib/widgets/findinfiles.py:158
+msgid "Unexpected error: see internal console"
+msgstr "Erro inesperado: veja o console interno"
+
+#: spyderlib/widgets/findinfiles.py:210 spyderlib/widgets/findinfiles.py:234
+#: spyderlib/widgets/findinfiles.py:281
+msgid "invalid regular expression"
+msgstr "expressão regular inválida"
+
+#: spyderlib/widgets/findinfiles.py:279
+msgid "permission denied errors were encountered"
+msgstr "permissão negada, foram encontrados erros"
+
+#: spyderlib/widgets/findinfiles.py:316
+msgid "Search pattern"
+msgstr "Padrão de pesquisa "
+
+#: spyderlib/widgets/findinfiles.py:319 spyderlib/widgets/findinfiles.py:353
+#: spyderlib/widgets/findinfiles.py:365 spyderlib/widgets/findreplace.py:77
+msgid "Regular expression"
+msgstr "Expressão regular"
+
+#: spyderlib/widgets/findinfiles.py:328
+msgid "Search"
+msgstr "Procurar"
+
+#: spyderlib/widgets/findinfiles.py:331
+msgid "Start search"
+msgstr "Iniciar busca"
+
+#: spyderlib/widgets/findinfiles.py:334 spyderlib/widgets/ipython.py:555
+msgid "Stop"
+msgstr "Parar"
+
+#: spyderlib/widgets/findinfiles.py:337
+msgid "Stop search"
+msgstr "Parar busca"
+
+#: spyderlib/widgets/findinfiles.py:347
+msgid "Included filenames pattern"
+msgstr ""
+"Incluir padrões de nomes\n"
+"do arquivo"
+
+#: spyderlib/widgets/findinfiles.py:356
+msgid "Include:"
+msgstr "Incluir:"
+
+#: spyderlib/widgets/findinfiles.py:359
+msgid "Excluded filenames pattern"
+msgstr ""
+"Excluir padrões de nomes\n"
+"do arquivo"
+
+#: spyderlib/widgets/findinfiles.py:368
+msgid "Exclude:"
+msgstr "Excluir:"
+
+#: spyderlib/widgets/findinfiles.py:378
+msgid "PYTHONPATH"
+msgstr "PYTHONPATH"
+
+#: spyderlib/widgets/findinfiles.py:380
+msgid ""
+"Search in all directories listed in sys.path which are outside the Python "
+"installation directory"
+msgstr ""
+"Procurar em todos diretórios listados na sys.path\n"
+"que estão fora do diretório de instalação do Python"
+
+#: spyderlib/widgets/findinfiles.py:383
+msgid "Hg repository"
+msgstr "Repositório Hg"
+
+#: spyderlib/widgets/findinfiles.py:386
+msgid "Search in current directory hg repository"
+msgstr "Buscar no repositório"
+
+#: spyderlib/widgets/findinfiles.py:387
+msgid "Here:"
+msgstr "Aqui:"
+
+#: spyderlib/widgets/findinfiles.py:391
+msgid "Search recursively in this directory"
+msgstr "Buscar recursivamente neste diretório"
+
+#: spyderlib/widgets/findinfiles.py:396
+msgid "Browse a search directory"
+msgstr "Selecionar um diretório de busca"
+
+#: spyderlib/widgets/findinfiles.py:426
+msgid "Hide advanced options"
+msgstr "Esconder opções avançadas"
+
+#: spyderlib/widgets/findinfiles.py:429
+msgid "Show advanced options"
+msgstr "Mostrar opções avançadas "
+
+#: spyderlib/widgets/findinfiles.py:570
+msgid "Search canceled"
+msgstr "Busca cancelada"
+
+#: spyderlib/widgets/findinfiles.py:574
+msgid "String not found"
+msgstr "String não encontrada"
+
+#: spyderlib/widgets/findinfiles.py:576
+msgid "matches in"
+msgstr "correspondências em"
+
+#: spyderlib/widgets/findinfiles.py:577
+msgid "file"
+msgstr "arquivo"
+
+#: spyderlib/widgets/findinfiles.py:585
+msgid "interrupted"
+msgstr "interrompido"
+
+#: spyderlib/widgets/findreplace.py:59
+msgid "Search string"
+msgstr "Procurar string"
+
+#: spyderlib/widgets/findreplace.py:83
+msgid "Case Sensitive"
+msgstr ""
+"Diferenciar maiúsculas\n"
+"de minúsculas"
+
+#: spyderlib/widgets/findreplace.py:89
+msgid "Whole words"
+msgstr "Palavras inteiras"
+
+#: spyderlib/widgets/findreplace.py:95
+msgid "Highlight matches"
+msgstr "Destacar correspondências "
+
+#: spyderlib/widgets/findreplace.py:109
+msgid "Replace with:"
+msgstr "Substituir com:"
+
+#: spyderlib/widgets/findreplace.py:111
+msgid "Replace string"
+msgstr "Substituir string"
+
+#: spyderlib/widgets/findreplace.py:114
+msgid "Replace/find"
+msgstr "Substituir/buscar"
+
+#: spyderlib/widgets/findreplace.py:121
+msgid "Replace all"
+msgstr "Substituir tudo"
+
+#: spyderlib/widgets/importwizard.py:116 spyderlib/widgets/importwizard.py:431
+msgid "Import as"
+msgstr "Importar como"
+
+#: spyderlib/widgets/importwizard.py:118
+msgid "data"
+msgstr "dados"
+
+#: spyderlib/widgets/importwizard.py:122
+msgid "code"
+msgstr "código"
+
+#: spyderlib/widgets/importwizard.py:125 spyderlib/widgets/importwizard.py:504
+msgid "text"
+msgstr "texto"
+
+#: spyderlib/widgets/importwizard.py:138
+msgid "Column separator:"
+msgstr "Separador de colunas:"
+
+#: spyderlib/widgets/importwizard.py:142
+msgid "Tab"
+msgstr "Tabulação"
+
+#: spyderlib/widgets/importwizard.py:145 spyderlib/widgets/importwizard.py:163
+msgid "other"
+msgstr "outro"
+
+#: spyderlib/widgets/importwizard.py:156
+msgid "Row separator:"
+msgstr "Separador de linha:"
+
+#: spyderlib/widgets/importwizard.py:160
+msgid "EOL"
+msgstr "Fim de linha"
+
+#: spyderlib/widgets/importwizard.py:175
+msgid "Additional options"
+msgstr "Opções adicionais"
+
+#: spyderlib/widgets/importwizard.py:179
+msgid "Skip rows:"
+msgstr "Pular linhas:"
+
+#: spyderlib/widgets/importwizard.py:190
+msgid "Comments:"
+msgstr "Comentários:"
+
+#: spyderlib/widgets/importwizard.py:196
+msgid "Transpose"
+msgstr "Transpor"
+
+#: spyderlib/widgets/importwizard.py:434
+msgid "array"
+msgstr "matriz"
+
+#: spyderlib/widgets/importwizard.py:439
+msgid "list"
+msgstr "lista"
+
+#: spyderlib/widgets/importwizard.py:444
+msgid "DataFrame"
+msgstr "DataFrame"
+
+#: spyderlib/widgets/importwizard.py:487 spyderlib/widgets/importwizard.py:569
+msgid "Import wizard"
+msgstr "Assistente de importação"
+
+#: spyderlib/widgets/importwizard.py:492
+msgid "Raw text"
+msgstr "Texto sem formatação"
+
+#: spyderlib/widgets/importwizard.py:495
+msgid "variable_name"
+msgstr "nome_da_variável"
+
+#: spyderlib/widgets/importwizard.py:506
+msgid "table"
+msgstr "tabela"
+
+#: spyderlib/widgets/importwizard.py:507
+msgid "Preview"
+msgstr "Pré-Visualização"
+
+#: spyderlib/widgets/importwizard.py:511
+msgid "Variable Name"
+msgstr "Nome da variável"
+
+#: spyderlib/widgets/importwizard.py:519
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: spyderlib/widgets/importwizard.py:532
+msgid "Done"
+msgstr "Feito"
+
+#: spyderlib/widgets/importwizard.py:570
+msgid ""
+"<b>Unable to proceed to next step</b><br><br>Please check your entries."
+"<br><br>Error message:<br>%s"
+msgstr ""
+"<b>Não foi possível prosseguir para o próximo passo</b><br><br>Por favor "
+"revise seus dados<br><br>Mensagem de erro:<br>%s"
+
+#: spyderlib/widgets/internalshell.py:258
+msgid "Help..."
+msgstr "Ajuda..."
+
+#: spyderlib/widgets/internalshell.py:266
+msgid "Help"
+msgstr "Ajuda"
+
+#: spyderlib/widgets/internalshell.py:275
+msgid "Shell special commands:"
+msgstr "Comando especiais: "
+
+#: spyderlib/widgets/internalshell.py:276
+msgid "Internal editor:"
+msgstr "Editor interno:"
+
+#: spyderlib/widgets/internalshell.py:277
+msgid "External editor:"
+msgstr "Editor externo:"
+
+#: spyderlib/widgets/internalshell.py:278
+msgid "Run script:"
+msgstr "Executar script:"
+
+#: spyderlib/widgets/internalshell.py:279
+msgid "Remove references:"
+msgstr "Remover referências:"
+
+#: spyderlib/widgets/internalshell.py:280
+msgid "System commands:"
+msgstr "Comandos do sistema:"
+
+#: spyderlib/widgets/internalshell.py:281
+msgid "Python help:"
+msgstr "Ajuda do Python:"
+
+#: spyderlib/widgets/internalshell.py:282
+msgid "GUI-based editor:"
+msgstr "Editor gráfico:"
+
+#: spyderlib/widgets/ipython.py:506
+msgid "An error ocurred while starting the kernel"
+msgstr "Um erro ocorreu enquanto o kernel era inicializado"
+
+#: spyderlib/widgets/ipython.py:535
+msgid "Restart kernel"
+msgstr "Reiniciar kernel"
+
+#: spyderlib/widgets/ipython.py:557
+msgid "Stop the current command"
+msgstr "Parar o comando atual"
+
+#: spyderlib/widgets/ipython.py:581
+msgid "Inspect current object"
+msgstr "Inspecionar objeto"
+
+#: spyderlib/widgets/ipython.py:586
+msgid "Clear line or block"
+msgstr "Limpar linha ou bloco"
+
+#: spyderlib/widgets/ipython.py:590
+msgid "Clear console"
+msgstr "Limpar console"
+
+#: spyderlib/widgets/ipython.py:640
+msgid ""
+"It seems the kernel died unexpectedly. Use 'Restart kernel' to continue "
+"using this console."
+msgstr ""
+"Parece que o kernel morreu inesperadamente. Use 'Reiniciar kernel\" para "
+"continuar usando o console."
+
+#: spyderlib/widgets/ipython.py:660
+msgid "Changing backend to Qt for Mayavi"
+msgstr "Mudando a saída gráfica do Qt para Mayavi"
+
+#: spyderlib/widgets/ipython.py:669
+msgid "Kernel process is either remote or unspecified. Cannot interrupt"
+msgstr "O kernel é remoto ou não está especificado. Não é possível interromper"
+
+#: spyderlib/widgets/ipython.py:678
+msgid "Kernel process is either remote or unspecified. Cannot restart."
+msgstr "O kernel é remoto ou não está especificado. Não é possível reiniciar."
+
+#: spyderlib/widgets/ipython.py:757
+msgid "Connecting to kernel..."
+msgstr "Conectando ao kernel..."
+
+#: spyderlib/widgets/onecolumntree.py:60
+msgid "Collapse all"
+msgstr "Reduzir tudo"
+
+#: spyderlib/widgets/onecolumntree.py:64
+msgid "Expand all"
+msgstr "Expandir tudo"
+
+#: spyderlib/widgets/onecolumntree.py:68
+msgid "Restore"
+msgstr "Restaurar"
+
+#: spyderlib/widgets/onecolumntree.py:69
+msgid "Restore original tree layout"
+msgstr "Restaurar a disposição original"
+
+#: spyderlib/widgets/onecolumntree.py:73
+msgid "Collapse selection"
+msgstr "Reduzir seleção"
+
+#: spyderlib/widgets/onecolumntree.py:77
+msgid "Expand selection"
+msgstr "Expandir seleção"
+
+#: spyderlib/widgets/pathmanager.py:86
+msgid "Move to top"
+msgstr "Mover para o inicio"
+
+#: spyderlib/widgets/pathmanager.py:92
+msgid "Move up"
+msgstr "Mover para cima"
+
+#: spyderlib/widgets/pathmanager.py:98
+msgid "Move down"
+msgstr "Mover para baixo"
+
+#: spyderlib/widgets/pathmanager.py:104
+msgid "Move to bottom"
+msgstr "Mover para o final"
+
+#: spyderlib/widgets/pathmanager.py:115 spyderlib/widgets/pathmanager.py:230
+msgid "Add path"
+msgstr "Adicionar caminho"
+
+#: spyderlib/widgets/pathmanager.py:120 spyderlib/widgets/pathmanager.py:213
+msgid "Remove path"
+msgstr "Remover caminho"
+
+#: spyderlib/widgets/pathmanager.py:130
+msgid "Synchronize..."
+msgstr "Sincronizar"
+
+#: spyderlib/widgets/pathmanager.py:132
+msgid "Synchronize Spyder's path list with PYTHONPATH environment variable"
+msgstr ""
+"Sincronizar a lista de caminhos do Spyder com a variável\n"
+"de ambiente PYTHONPATH"
+
+#: spyderlib/widgets/pathmanager.py:144
+msgid "Synchronize"
+msgstr "Sincronizar"
+
+#: spyderlib/widgets/pathmanager.py:145
+msgid ""
+"This will synchronize Spyder's path list with <b>PYTHONPATH</b> environment "
+"variable for current user, allowing you to run your Python modules outside "
+"Spyder without having to configure sys.path. <br>Do you want to clear "
+"contents of PYTHONPATH before adding Spyder's path list?"
+msgstr ""
+"Isso irá sincronizar a lista de caminhos do Spyder com a variável de "
+"ambiente <b>PYTHONPATH</b>para o usuário atual, permitindo executar seus "
+"módulos de Python fora do Spyder sem precisar configurar o sys.path. "
+"<br>Deseja limpar o conteúdo da PYTHONPATH antes de adicionar a lista de "
+"caminhos do Spyder?"
+
+#: spyderlib/widgets/pathmanager.py:214
+msgid "Do you really want to remove selected path?"
+msgstr "Você deseja mesmo remover o caminho selecionado?"
+
+#: spyderlib/widgets/pathmanager.py:231
+msgid ""
+"This directory is already included in Spyder path list.<br>Do you want to "
+"move it to the top of the list?"
+msgstr ""
+"Este diretório já está incluído na lista de caminhos do Spyder.<br>Deseja "
+"mover ele para o topo da lista?"
+
+#: spyderlib/widgets/projectexplorer.py:335
+msgid "its own configuration file"
+msgstr "seu próprio arquivo de configuração"
+
+#: spyderlib/widgets/projectexplorer.py:337
+msgid " and "
+msgstr " e"
+
+#: spyderlib/widgets/projectexplorer.py:341
+msgid "the following projects:<br>%s"
+msgstr "Os seguintes projetos:<br>%s"
+
+#: spyderlib/widgets/projectexplorer.py:545
+msgid "Project..."
+msgstr "Projeto..."
+
+#: spyderlib/widgets/projectexplorer.py:558
+msgid "Existing directory"
+msgstr "Diretório existente"
+
+#: spyderlib/widgets/projectexplorer.py:562
+msgid "Existing Spyder project"
+msgstr "Projeto existente do Spyder"
+
+#: spyderlib/widgets/projectexplorer.py:566
+msgid "Existing Pydev project"
+msgstr "Projeto existente do Pydev"
+
+#: spyderlib/widgets/projectexplorer.py:583
+msgid "Open project"
+msgstr "Abrir projeto"
+
+#: spyderlib/widgets/projectexplorer.py:588
+msgid "Close project"
+msgstr "Fechar projeto"
+
+#: spyderlib/widgets/projectexplorer.py:593
+msgid "Close unrelated projects"
+msgstr "Fechar projetos não relacionados"
+
+#: spyderlib/widgets/projectexplorer.py:602
+msgid "Edit related projects"
+msgstr "Editar projetos relacionados"
+
+#: spyderlib/widgets/projectexplorer.py:610
+msgid "Add to PYTHONPATH"
+msgstr "Adicionar para a PYTHONPATH"
+
+#: spyderlib/widgets/projectexplorer.py:615
+msgid "Remove from PYTHONPATH"
+msgstr "Remover da PYTHONPATH"
+
+#: spyderlib/widgets/projectexplorer.py:620
+msgid "Properties"
+msgstr "Propriedades"
+
+#: spyderlib/widgets/projectexplorer.py:655
+msgid "Show horizontal scrollbar"
+msgstr "Mostrar barra de rolagem horizontal"
+
+#: spyderlib/widgets/projectexplorer.py:692
+msgid "Workspace"
+msgstr "Espaço de trabalho"
+
+#: spyderlib/widgets/projectexplorer.py:693
+msgid ""
+"The workspace was unable to load or save %s<br><br>Please check if you have "
+"the permission to write the associated configuration files."
+msgstr ""
+"Não foi possível carregar ou salvar o espaço de trabalho %s<br><br>Verifique "
+"se você tem permissão para escrever os arquivos de configuração."
+
+#: spyderlib/widgets/projectexplorer.py:752
+msgid "Import directory"
+msgstr "Importar diretório"
+
+#: spyderlib/widgets/projectexplorer.py:754
+msgid ""
+"The following directory is not in workspace:<br><b>%s</b><br><br>Do you want "
+"to continue (and copy the directory to workspace)?"
+msgstr ""
+"O seguinte diretório não está em um espaço de trabalho:<br><b>%s</"
+"b><br><br>Deseja continuar (e copiar o diretório para o espaço de trabalho)?"
+
+#: spyderlib/widgets/projectexplorer.py:772
+#: spyderlib/widgets/projectexplorer.py:1183
+msgid "copy"
+msgstr "copiar"
+
+#: spyderlib/widgets/projectexplorer.py:824
+msgid "The project <b>%s</b> is already opened!"
+msgstr "O projeto <b>%s</b> já está aberto!"
+
+#: spyderlib/widgets/projectexplorer.py:831
+msgid ""
+"The project root path directory is inside the workspace but not as the "
+"expected tree level. It is not a directory of the workspace:<br><b>%s</b>"
+msgstr ""
+"O caminho do diretório do projeto está dentro do espaço de trabalho porém "
+"não em um nível de profundidade esperado, pois é um subdiretório do espaço "
+"de trabalho:<br><b>%s</b>"
+
+#: spyderlib/widgets/projectexplorer.py:842
+msgid "Project name:"
+msgstr "Nome do projeto:"
+
+#: spyderlib/widgets/projectexplorer.py:851
+msgid "A project named <b>%s</b> already exists"
+msgstr "Um projeto chamado <b>%s</b> já existe"
+
+#: spyderlib/widgets/projectexplorer.py:856
+msgid ""
+"Invalid project name.<br><br>Name must match the following regular "
+"expression:<br><b>%s</b>"
+msgstr ""
+"Nome de projeto inválido.<br><br>O nome deve coincidir com a seguinte "
+"expressão:<br><b>%s</b>"
+
+#: spyderlib/widgets/projectexplorer.py:863
+msgid ""
+"The following directory is not empty:<br><b>%s</b><br><br>Do you want to "
+"continue?"
+msgstr ""
+"O seguinte diretório não está vazio:<br><b>%s</b><br><br>Deseja continuar?"
+
+#: spyderlib/widgets/projectexplorer.py:876
+msgid "New project"
+msgstr "Novo projeto"
+
+#: spyderlib/widgets/projectexplorer.py:884
+msgid ""
+"The current workspace has not been configured yet.\n"
+"Do you want to do this now?"
+msgstr ""
+"O espaço de trabalho atual ainda não foi configurado.\n"
+"Deseja fazer agora?"
+
+#: spyderlib/widgets/projectexplorer.py:922
+msgid "Import existing project"
+msgstr "Importar um projeto existente"
+
+#: spyderlib/widgets/projectexplorer.py:935
+msgid "Select projects to import"
+msgstr "Selecione projetos para importar"
+
+#: spyderlib/widgets/projectexplorer.py:947
+msgid "The folder <i>%s</i> does not contain a valid %s project"
+msgstr "A pasta <i>%s</i> não possui um projeto de %s válido"
+
+#: spyderlib/widgets/projectexplorer.py:977
+msgid "Import existing Pydev project"
+msgstr "Importar projeto existente do Pydev"
+
+#: spyderlib/widgets/projectexplorer.py:978
+msgid ""
+"<b>Unable to read Pydev project <i>%s</i></b><br><br>Error message:<br>%s"
+msgstr ""
+"<b>Não foi possível ler o projeto <i>%s</i> do Pydev</b><br><br>Mensagem de "
+"erro:<br>%s"
+
+#: spyderlib/widgets/projectexplorer.py:1016
+msgid ""
+"Do you really want to delete project <b>%s</b>?<br><br>Note: project files "
+"won't be deleted from disk."
+msgstr ""
+"Você deseja deletar o projeto <b>%s</b>?<br><br>Nota: Os arquivos do projeto "
+"não serão eliminados do disco."
+
+#: spyderlib/widgets/projectexplorer.py:1069
+msgid "Related projects"
+msgstr "Projetos relacionados"
+
+#: spyderlib/widgets/projectexplorer.py:1077
+msgid "Select projects which are related to <b>%s</b>"
+msgstr "Selecionar os projetos que estão relacionados a <b>%s</b>"
+
+#: spyderlib/widgets/projectexplorer.py:1102
+#, fuzzy
+msgid ""
+"Statistics on source files only:<br>(Python, Cython, IPython, Enaml,C/C++, "
+"Fortran)<br><br><b>%s</b> files.<br><b>%s</b> lines of code."
+msgstr ""
+"Estatísticas para os arquivos de código:<br>(Python, C/C++, "
+"Fortran)<br><br><b>%s</b> arquivos.<br><b>%s</b> linhas de código."
+
+#: spyderlib/widgets/projectexplorer.py:1151
+msgid "File <b>%s</b> already exists.<br>Do you want to overwrite it?"
+msgstr "O arquivo <b>%s</b> já existe<br>Deseja sobrescrever ele?"
+
+#: spyderlib/widgets/projectexplorer.py:1165
+msgid "Folder <b>%s</b> already exists."
+msgstr "A Pasta <b>%s</b> já existe."
+
+#: spyderlib/widgets/projectexplorer.py:1185
+msgid "move"
+msgstr "mover"
+
+#: spyderlib/widgets/projectexplorer.py:1195
+msgid "Select an existing workspace directory, or create a new one"
+msgstr "Selecione um espaço de trabalho existente, ou crie um novo"
+
+#: spyderlib/widgets/projectexplorer.py:1196
+msgid ""
+"<u><b>What is the workspace?</b></u><br><br>A <b>Spyder workspace</b> is a "
+"directory on your filesystem that contains Spyder projects and <b>."
+"spyderworkspace</b> configuration file.<br><br>A <b>Spyder project</b> is a "
+"directory with source code (and other related files) and a configuration "
+"file (named <b>.spyderproject</b>) with project settings (PYTHONPATH, linked "
+"projects, ...).<br>"
+msgstr ""
+"<u><b>O que é um espaço de trabalho?</b></u><br><br>Um <b>espaço de trabalho "
+"do Spyder</b> é um diretório no seu sistema de arquivos que contem projetos "
+"do Spyder e um arquivo de configuração </b>.spyderworkspace.<br><br>Um "
+"<b>projeto do Spyder</b> é um diretório com código fonte (e outros arquivos "
+"relacionados) e um arquivo de configuração (chamado <b>.spyderproject</b>) "
+"com configurações do projeto (PYTHONPATH, projetos vinculados).<br>"
+
+#: spyderlib/widgets/projectexplorer.py:1225
+msgid "This is the current workspace directory"
+msgstr "Este é o diretório atual do espaço de trabalho"
+
+#: spyderlib/widgets/projectexplorer.py:1255
+msgid ""
+"The following directory is not a Spyder workspace:<br>%s<br><br>Do you want "
+"to create a new workspace in this directory?"
+msgstr ""
+"O seguinte diretório não é um espaço de trabalho do Spyder:<br>"
+"%s<br><br>Você deseja criar um novo espaço de trabalho neste diretório?"
+
+#: spyderlib/widgets/pydocgui.py:107
+msgid "Module or package:"
+msgstr "Módulo ou pacote:"
+
+#: spyderlib/widgets/shell.py:134
+msgid "Save history log..."
+msgstr "Salvar histórico..."
+
+#: spyderlib/widgets/shell.py:136
+msgid "Save current history log (i.e. all inputs and outputs) in a text file"
+msgstr ""
+"Salvar o histórico atual (todas entradas e saídas) em um arquivo de texto"
+
+#: spyderlib/widgets/shell.py:262
+msgid "Save history log"
+msgstr "Salvar histórico"
+
+#: spyderlib/widgets/shell.py:265
+msgid "History logs"
+msgstr "Histórico de comandos"
+
+#: spyderlib/widgets/shell.py:276
+msgid "<b>Unable to save file '%s'</b><br><br>Error message:<br>%s"
+msgstr ""
+"<b>Não foi possível salvar arquivo '%s'</b><br><br>Mensagem de erro:<br>%s"
+
+#: spyderlib/widgets/shell.py:718
+msgid "Copy without prompts"
+msgstr "Copiar sem os prompts"
+
+#: spyderlib/widgets/shell.py:721 spyderlib/widgets/shell.py:725
+msgid "Clear line"
+msgstr "Limpar linha"
+
+#: spyderlib/widgets/shell.py:727
+msgid "Clear shell"
+msgstr "Limpar shell"
+
+#: spyderlib/widgets/shell.py:731
+msgid "Clear shell contents ('cls' command)"
+msgstr "Limpar conteúdo do shell (comando 'cls')"
+
+#: spyderlib/widgets/sourcecode/codeeditor.py:98
+msgid "Go to line:"
+msgstr "Ir para a linha:"
+
+#: spyderlib/widgets/sourcecode/codeeditor.py:106
+msgid "Line count:"
+msgstr "Número de linhas:"
+
+#: spyderlib/widgets/sourcecode/codeeditor.py:1270
+msgid "Breakpoint"
+msgstr "Ponto de interrupção"
+
+#: spyderlib/widgets/sourcecode/codeeditor.py:1271
+msgid "Condition:"
+msgstr "Condição:"
+
+#: spyderlib/widgets/sourcecode/codeeditor.py:1679
+msgid "Code analysis"
+msgstr "Análise de código"
+
+#: spyderlib/widgets/sourcecode/codeeditor.py:1733
+msgid "To do"
+msgstr "To do"
+
+#: spyderlib/widgets/sourcecode/codeeditor.py:1974
+#, fuzzy
+msgid "Removal error"
+msgstr "Erro de importação"
+
+#: spyderlib/widgets/sourcecode/codeeditor.py:1975
+msgid ""
+"It was not possible to remove outputs from this notebook. The error is:\n"
+"\n"
+msgstr ""
+
+#: spyderlib/widgets/sourcecode/codeeditor.py:2453
+msgid "Clear all ouput"
+msgstr "Limpar todas as saídas "
+
+#: spyderlib/widgets/sourcecode/codeeditor.py:2459
+msgid "Go to definition"
+msgstr "Ver definição"
+
+#: spyderlib/widgets/sourcecode/codeeditor.py:2471
+#, fuzzy
+msgid "Zoom reset"
+msgstr "Menos zoom"
+
+#: spyderlib/widgets/sourcecode/syntaxhighlighters.py:32
+msgid "Syntax highlighting for Matlab, Julia and other file types"
+msgstr "Sintaxe colorida para arquivos do tipo Matlab, Julia e outros tipos"
+
+#: spyderlib/widgets/status.py:23
+msgid "CPU and memory usage info in the status bar"
+msgstr "Uso de CPU e memória na barra de status"
+
+#: spyderlib/widgets/status.py:92
+msgid "Memory:"
+msgstr "Memória:"
+
+#: spyderlib/widgets/status.py:93
+msgid ""
+"Memory usage status: requires the `psutil` (>=v0.3) library on non-Windows "
+"platforms"
+msgstr ""
+"Status de uso da memória: requer a biblioteca `psutil` (>=v0.3) em outras "
+"plataformas"
+
+#: spyderlib/widgets/status.py:105
+msgid "CPU:"
+msgstr "CPU:"
+
+#: spyderlib/widgets/status.py:106
+msgid "CPU usage status: requires the `psutil` (>=v0.3) library"
+msgstr "Status de uso da CPU: requer a biblioteca `psutil` (>=v0.3)"
+
+#: spyderlib/widgets/status.py:128
+msgid "Permissions:"
+msgstr "Permissões:"
+
+#: spyderlib/widgets/status.py:142
+msgid "End-of-lines:"
+msgstr "Fim de linha:"
+
+#: spyderlib/widgets/status.py:156
+msgid "Encoding:"
+msgstr "Codificação:"
+
+#: spyderlib/widgets/status.py:169
+msgid "Line:"
+msgstr "Linha:"
+
+#: spyderlib/widgets/status.py:173
+msgid "Column:"
+msgstr "Coluna:"
+
+#: spyderlib/widgets/tabs.py:142
+msgid "Browse tabs"
+msgstr "Navegar pelas abas"
+
+#: spyderlib/widgets/tabs.py:270
+msgid "Close current tab"
+msgstr "Fechar aba atual"
+
+#: spyderlib/widgets/texteditor.py:72
+msgid "Text editor"
+msgstr "Editor de texto"
+
+#: spyderlib/workers/updates.py:79 spyderlib/workers/updates.py:81
+msgid "Unable to retrieve information."
+msgstr ""
+
+#: spyderlib/workers/updates.py:83
+msgid ""
+"Unable to connect to the internet. <br><br>Make sure the connection is "
+"working properly."
+msgstr ""
+
+#: spyderlib/workers/updates.py:86
+#, fuzzy
+msgid "Unable to check for updates."
+msgstr "Não foi possível carregar a página"
+
+#~ msgid "PyQt"
+#~ msgstr "PyQt"
+
+#~ msgid "API selection for QString and QVariant objects:"
+#~ msgstr "Seleção da API para objetos QString e QVariant:"
+
+#~ msgid "API #1"
+#~ msgstr "API #1"
+
+#~ msgid "API #2"
+#~ msgstr "API #1"
+
+#~ msgid "Default API"
+#~ msgstr "API Padrão"
+
+#~ msgid ""
+#~ "PyQt API #1 is the default <br>API for Python 2. PyQt API #2 is the "
+#~ "default API for Python 3 and is compatible with PySide."
+#~ msgstr ""
+#~ "A API #1 de PyQt é a API padrão <br>para o Python 2. A API #2 do PyQt é a "
+#~ "API padrão para o Python 3 e é compatível com o PySide."
+
+#~ msgid "Ignore API change errors (sip.setapi)"
+#~ msgstr "Ignorar erros de mudança de API (sip.setapi)"
+
+#~ msgid ""
+#~ "Enabling this option will ignore <br>errors when changing PyQt API. As "
+#~ "PyQt does not support dynamic API changes, it is strongly recommended to "
+#~ "use this feature wisely, e.g. for debugging purpose."
+#~ msgstr ""
+#~ "Ativando esta opção serão ignorados <br>os erros gerados ao mudar a API "
+#~ "do PyQt. Dado que o PyQt não suporta mudanças dinâmicas da API, é "
+#~ "recomendável usar essa funcionalidade com certo cuidado, por exemplo, "
+#~ "para propósitos de depuração."
+
+#~ msgid "Matplotlib"
+#~ msgstr "Matplotlib"
+
+#~ msgid "GUI backend:"
+#~ msgstr "Saída gráfica:"
+
+#~ msgid ""
+#~ "Set the GUI toolkit used by <br>Matplotlib to show figures (default: "
+#~ "Qt4Agg)"
+#~ msgstr ""
+#~ "Definir interface gráfica usada pelo <br>Matplotlib para mostrar imagens "
+#~ "(padrão: Qt4Agg)"
+
+#~ msgid "Mod1"
+#~ msgstr "Mod1"
+
+#~ msgid "Mod2"
+#~ msgstr "Mod2"
+
+#~ msgid "Mod3"
+#~ msgstr "Mod3"
+
+#, fuzzy
+#~ msgid "The Internal Console"
+#~ msgstr "Console interno"
+
+#~ msgid "File list management"
+#~ msgstr "Gerenciador da lista de arquivos"
+
+#~ msgid "Filter:"
+#~ msgstr "Filtro:"
+
+#~ msgid "(press <b>Enter</b> to edit file)"
+#~ msgstr "(Aperte <b>Enter</b> para editar)"
+
+#~ msgid "&Edit file"
+#~ msgstr "&Editar arrquivo"
+
+#~ msgid "&Close file"
+#~ msgstr "&Fechar arquivo"
+
+#~ msgid "Hint: press <b>Alt</b> to show accelerators"
+#~ msgstr "Sugestão: aperte <b>Alt</b> para mostrar aceleradores"
+
+#~ msgid "Vertical dockwidget tabs"
+#~ msgstr "Componentes em abas verticais"
+
+#~ msgid "Custom dockwidget margin:"
+#~ msgstr "Margem de componente personalizada:"
+
+#~ msgid ""
+#~ "<u>Note</u>: add <b>analysis:ignore</b> in a comment to ignore code/style "
+#~ "analysis warnings. For more informations on style guide for Python code, "
+#~ "please refer to the %s page."
+#~ msgstr ""
+#~ "<u>Nota</u>: Adicione <b>analysis:ignore</b> a um comentário para ignorar "
+#~ "avisos de análise de código ou estilo. Para mais informações sobre um "
+#~ "guia de estilo para escrever código em Python, por favor visite a página "
+#~ "%s (em inglês).<br>"
+
+#~ msgid "Style analysis"
+#~ msgstr "Análise de estilo"
+
+#~ msgid "Qt (PyQt/PySide)"
+#~ msgstr "Qt (PyQt/PySide)"
+
+#~ msgid "Install Spyder's input hook for Qt"
+#~ msgstr "Instalar o \"input hook\" do Spyder para o Qt"
+
+#~ msgid ""
+#~ "PyQt installs an input hook that allows<br> creating and interacting with "
+#~ "Qt widgets in an interactive console without blocking it. On Windows "
+#~ "platforms, it is strongly recommended to replace it by Spyder's. "
+#~ "Regarding PySide, note that it does not install an input hook, so it is "
+#~ "required to enable this feature in order to be able to manipulate PySide/"
+#~ "Qtobjects interactively."
+#~ msgstr ""
+#~ "PyQt instala um mecanismo de \"input hook\"<br> que permite criar e "
+#~ "interagir com widgets do Qt em um console sem bloqueá-lo. No Windows é "
+#~ "altamente recomendável substituir este mecanismo pelo do Spyder. A "
+#~ "respeito do PySide, ele não instala um \"inputhook\", Então é necessário "
+#~ "ativar esta característica para poder manipular objetos do PySide/Qt "
+#~ "interativamente."
+
+#~ msgid "Use a completion widget"
+#~ msgstr "Usar um widget para completar texto"
+
+#~ msgid "Use a widget instead of plain text output for tab completion"
+#~ msgstr ""
+#~ "Usar um widget no lugar da saída de texto plano para \n"
+#~ "mostrar as possibilidades do completador usando a tecla\n"
+#~ "Tab."
+
+#~ msgid ""
+#~ "%s will be closed.\n"
+#~ "Do you want to kill the associated kernel and all of its clients?"
+#~ msgstr ""
+#~ "%s será fechado.\n"
+#~ "Deseja matar o kernel associado e todos seus clientes?"
+
+#~ msgid "Could not open ssh tunnel\n"
+#~ msgstr "não foi possível criar um túnel ssh\n"
+
+#~ msgid "Mismatch between kernel and frontend"
+#~ msgstr "Incompatibilidade entre o kernel e a interface gráfica"
+
+#~ msgid ""
+#~ "Your IPython frontend and kernel versions are <b>incompatible!!</"
+#~ "b><br><br>We're sorry but we can't create an IPython console for you."
+#~ msgstr ""
+#~ "Suas versões do kernel e da interface gráfica do IPython são "
+#~ "<b>incompativeis!!</b><br><br>Desculpe mas não podemos criar um console "
+#~ "IPython para você."
+
+#~ msgid "Always edit in-place"
+#~ msgstr "Sempre editar em linha"
+
+#~ msgid "Show collection contents"
+#~ msgstr "Mostrar conteúdo de listas"
+
+#~ msgid "Switch to/from layout %d"
+#~ msgstr "Mudar para esquema %d"
+
+#~ msgid "Set layout %d"
+#~ msgstr "Definir esquema %d"
+
+#~ msgid "User Module Deleter (UMD)"
+#~ msgstr "Eliminador de Módulos do Usuário (EMU)"
+
+#~ msgid ""
+#~ "UMD forces Python to reload modules which were imported when executing "
+#~ "a \n"
+#~ "script in the external console with the 'runfile' function."
+#~ msgstr ""
+#~ "O EMU obriga o Python a recarregar os módulos que foram importados\n"
+#~ "durante a execução de um arquivo no console com a função 'runfile'."
+
+#~ msgid "Enable UMD"
+#~ msgstr "Ativar UMD"
+
+#~ msgid ""
+#~ "This option will enable the User Module Deleter (UMD) in Python/IPython "
+#~ "consoles. UMD forces Python to reload deeply modules during import when "
+#~ "running a Python script using the Spyder's builtin function <b>runfile</"
+#~ "b>.<br><br><b>1.</b> UMD may require to restart the console in which it "
+#~ "will be called (otherwise only newly imported modules will be reloaded "
+#~ "when executing scripts).<br><br><b>2.</b> If errors occur when re-running "
+#~ "a PyQt-based program, please check that the Qt objects are properly "
+#~ "destroyed (e.g. you may have to use the attribute <b>Qt.WA_DeleteOnClose</"
+#~ "b> on your main window, using the <b>setAttribute</b> method)"
+#~ msgstr ""
+#~ "Essa opção irá ativar o Eliminador de módulos do usuário (EMU) nos "
+#~ "consoles do Python e IPython. O EMU obriga o Python a recarregar "
+#~ "profundamente os módulos que foram importados durante a execução de um "
+#~ "script, usando a função incorporada do Spyder chamada <b>runfile</b>."
+#~ "<br><br><b>1.</b> O EMU pode precisar que o console no qual será "
+#~ "utilizado (de outra forma, só os módulos que foram importados em último "
+#~ "lugar serão recarregados ao executar um arquivo).<br><br><b>2.</b> se "
+#~ "ocorrer algum erro ao executar novamente programas baseados no PyQt ou "
+#~ "PySide, por favor verifique se os objetos do Qt foram  apropriadamente "
+#~ "destruídos (por exemplo, talvez você precise usar o atributo <b>Qt."
+#~ "WA_DeleteOnClose</b> na sua janela principal, usando o método "
+#~ "<b>setAttribute</b>)."
+
+#~ msgid "Set UMD excluded (not reloaded) modules"
+#~ msgstr "Definir lista de módulos excluídos pelo EMU"
+
+#~ msgid ""
+#~ "You can't close this kernel because it has one or more consoles connected "
+#~ "to it.<br><br>You need to close them instead or you can kill the kernel "
+#~ "using the button far to the right."
+#~ msgstr ""
+#~ "Você não pode fechar esse kernel porque existem um ou mais consoles "
+#~ "conectados a ele.<br><br>Você precisa fechá-lo ou matar o processo usando "
+#~ "o botão direito."
+
+#~ msgid "UMD"
+#~ msgstr "UMD"
+
+#~ msgid ""
+#~ "UMD excluded modules:\n"
+#~ "(example: guidata, guiqwt)"
+#~ msgstr ""
+#~ "Módulos excluídos do EMU:\n"
+#~ "(Exemplo: guidata, guiqwt)"
+
+#~ msgid ""
+#~ "Resizing cells of a table of such size could take a long time.\n"
+#~ "Do you want to continue anyway?"
+#~ msgstr ""
+#~ "Redimensionar as células de uma tabela desse tamanho pode\n"
+#~ " demorar muito tempo.\n"
+#~ "\n"
+#~ "Deseja continuar mesmo assim?"
+
+#~ msgid ""
+#~ "Attempts to terminate the process.\n"
+#~ "The process may not exit as a result of clicking this button\n"
+#~ "(it is given the chance to prompt the user for any unsaved files, etc)."
+#~ msgstr ""
+#~ "Intenta interrumpir este proceso, pero éste\n"
+#~ "puede no concluir tras oprimir este botón\n"
+#~ "(pues es posible que se le pida al usuario\n"
+#~ "guardar archivos sin salvar, etc)."
+
+#~ msgid "Additionnal options"
+#~ msgstr "Opções adcionais"
+
+#~ msgid "Interrupt kernel"
+#~ msgstr "Interromper kernel "
diff --git a/spyderlib/locale/spyderlib.pot b/spyderlib/locale/spyderlib.pot
old mode 100755
new mode 100644
index 78b490f..f5f2f8d
--- a/spyderlib/locale/spyderlib.pot
+++ b/spyderlib/locale/spyderlib.pot
@@ -5,7 +5,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2015-11-24 20:56+COT\n"
+"POT-Creation-Date: 2015-08-29 22:49+COT\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
 "Language-Team: LANGUAGE <LL at li.org>\n"
@@ -15,574 +15,622 @@ msgstr ""
 "Generated-By: pygettext.py 1.5\n"
 
 
-#: spyderlib/config.py:29
+#: spyderlib/config/base.py:241
+msgid "Update LANGUAGE_CODES (inside config/base.py) if a new translation has been added to Spyder"
+msgstr ""
+
+#: spyderlib/config/ipython.py:23 spyderlib/config/ipython.py:25
+#: spyderlib/config/ipython.py:32
+msgid "IPython Console integration"
+msgstr ""
+
+#: spyderlib/config/main.py:29
 msgid "Python files"
 msgstr ""
 
-#: spyderlib/config.py:30
+#: spyderlib/config/main.py:30
 msgid "Cython/Pyrex files"
 msgstr ""
 
-#: spyderlib/config.py:31
+#: spyderlib/config/main.py:31
 msgid "C files"
 msgstr ""
 
-#: spyderlib/config.py:32
+#: spyderlib/config/main.py:32
 msgid "C++ files"
 msgstr ""
 
-#: spyderlib/config.py:33
+#: spyderlib/config/main.py:33
 msgid "OpenCL files"
 msgstr ""
 
-#: spyderlib/config.py:34
+#: spyderlib/config/main.py:34
 msgid "Fortran files"
 msgstr ""
 
-#: spyderlib/config.py:35
+#: spyderlib/config/main.py:35
 msgid "IDL files"
 msgstr ""
 
-#: spyderlib/config.py:36
+#: spyderlib/config/main.py:36
 msgid "MATLAB files"
 msgstr ""
 
-#: spyderlib/config.py:37
+#: spyderlib/config/main.py:37
 msgid "Julia files"
 msgstr ""
 
-#: spyderlib/config.py:38
+#: spyderlib/config/main.py:38
 msgid "Yaml files"
 msgstr ""
 
-#: spyderlib/config.py:39
+#: spyderlib/config/main.py:39
 msgid "Patch and diff files"
 msgstr ""
 
-#: spyderlib/config.py:40
+#: spyderlib/config/main.py:40
 msgid "Batch files"
 msgstr ""
 
-#: spyderlib/config.py:41 spyderlib/utils/iofuncs.py:514
+#: spyderlib/config/main.py:41 spyderlib/utils/iofuncs.py:500
 msgid "Text files"
 msgstr ""
 
-#: spyderlib/config.py:42
+#: spyderlib/config/main.py:42
 msgid "reStructured Text files"
 msgstr ""
 
-#: spyderlib/config.py:43
+#: spyderlib/config/main.py:43
 msgid "gettext files"
 msgstr ""
 
-#: spyderlib/config.py:44
+#: spyderlib/config/main.py:44
 msgid "NSIS files"
 msgstr ""
 
-#: spyderlib/config.py:45
+#: spyderlib/config/main.py:45
 msgid "Web page files"
 msgstr ""
 
-#: spyderlib/config.py:46
+#: spyderlib/config/main.py:46
 msgid "XML files"
 msgstr ""
 
-#: spyderlib/config.py:47
+#: spyderlib/config/main.py:47
 msgid "Javascript files"
 msgstr ""
 
-#: spyderlib/config.py:48
+#: spyderlib/config/main.py:48
 msgid "Json files"
 msgstr ""
 
-#: spyderlib/config.py:49
+#: spyderlib/config/main.py:49
 msgid "IPython notebooks"
 msgstr ""
 
-#: spyderlib/config.py:50
+#: spyderlib/config/main.py:50
 msgid "Enaml files"
 msgstr ""
 
-#: spyderlib/config.py:51
+#: spyderlib/config/main.py:51
 msgid "Configuration files"
 msgstr ""
 
-#: spyderlib/config.py:58 spyderlib/widgets/explorer.py:651
+#: spyderlib/config/main.py:58 spyderlib/widgets/explorer.py:660
 msgid "All files"
 msgstr ""
 
-#: spyderlib/ipythonconfig.py:23 spyderlib/ipythonconfig.py:25
-#: spyderlib/ipythonconfig.py:32
-msgid "IPython Console integration"
+#: spyderlib/plugins/__init__.py:513 spyderlib/plugins/editor.py:95
+#: spyderlib/plugins/editor.py:551 spyderlib/plugins/editor.py:1600
+#: spyderlib/plugins/inspector.py:139 spyderlib/plugins/inspector.py:419
+#: spyderlib/widgets/editor.py:357
+#: spyderlib/widgets/sourcecode/codeeditor.py:95
+#: spyderlib/widgets/sourcecode/codeeditor.py:2902
+msgid "Editor"
 msgstr ""
 
-#: spyderlib/plugins/__init__.py:318 spyderlib/plugins/editor.py:94
-#: spyderlib/plugins/editor.py:527 spyderlib/plugins/editor.py:1606
-#: spyderlib/plugins/inspector.py:134 spyderlib/plugins/inspector.py:403
-#: spyderlib/widgets/editor.py:434
-#: spyderlib/widgets/sourcecode/codeeditor.py:85
-#: spyderlib/widgets/sourcecode/codeeditor.py:2709
-msgid "Editor"
+#: spyderlib/plugins/configdialog.py:133
+msgid "Reset to defaults"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:144
+#: spyderlib/plugins/configdialog.py:145
 msgid "Preferences"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:429
+#: spyderlib/plugins/configdialog.py:473
 msgid "Invalid directory path"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:432 spyderlib/plugins/configdialog.py:448
-#: spyderlib/plugins/runconfig.py:172 spyderlib/plugins/runconfig.py:236
-#: spyderlib/plugins/workingdirectory.py:286 spyderlib/widgets/explorer.py:565
-#: spyderlib/widgets/externalshell/pythonshell.py:623
-#: spyderlib/widgets/findinfiles.py:504 spyderlib/widgets/pathmanager.py:218
-#: spyderlib/widgets/projectexplorer.py:890
+#: spyderlib/plugins/configdialog.py:476 spyderlib/plugins/configdialog.py:491
+#: spyderlib/plugins/runconfig.py:176 spyderlib/plugins/runconfig.py:240
+#: spyderlib/plugins/workingdirectory.py:295 spyderlib/widgets/explorer.py:574
+#: spyderlib/widgets/externalshell/pythonshell.py:640
+#: spyderlib/widgets/findinfiles.py:505 spyderlib/widgets/pathmanager.py:223
+#: spyderlib/widgets/projectexplorer.py:899
 msgid "Select directory"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:460
+#: spyderlib/plugins/configdialog.py:503
 msgid "Invalid file path"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:463 spyderlib/plugins/configdialog.py:481
+#: spyderlib/plugins/configdialog.py:506 spyderlib/plugins/configdialog.py:523
 msgid "Select file"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:480
+#: spyderlib/plugins/configdialog.py:522
 msgid "All files (*)"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:550 spyderlib/widgets/formlayout.py:216
+#: spyderlib/plugins/configdialog.py:595 spyderlib/widgets/formlayout.py:214
 msgid "Bold"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:553 spyderlib/widgets/formlayout.py:211
+#: spyderlib/plugins/configdialog.py:598 spyderlib/widgets/formlayout.py:209
 msgid "Italic"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:591
+#: spyderlib/plugins/configdialog.py:640
 msgid "Font: "
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:595
+#: spyderlib/plugins/configdialog.py:644
 msgid "Size: "
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:604 spyderlib/plugins/history.py:47
+#: spyderlib/plugins/configdialog.py:653 spyderlib/plugins/history.py:48
 msgid "Font style"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:657
+#: spyderlib/plugins/configdialog.py:708
+msgid "Spyder needs to restart to change the following setting:"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:711
+msgid "Spyder needs to restart to change the following settings:"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:713
+msgid "Do you wish to restart now?"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:719
+msgid "Information"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:734
 msgid "General"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:664 spyderlib/plugins/editor.py:103
-#: spyderlib/plugins/externalconsole.py:65
-#: spyderlib/plugins/ipythonconsole.py:161
+#: spyderlib/plugins/configdialog.py:741 spyderlib/plugins/editor.py:104
+#: spyderlib/plugins/externalconsole.py:67
+#: spyderlib/plugins/ipythonconsole.py:162
 msgid "Interface"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:672
+#: spyderlib/plugins/configdialog.py:744
 msgid "Qt windows style"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:676
+#: spyderlib/plugins/configdialog.py:750
+msgid "Icon theme"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:755
+msgid "Language"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:759
 msgid "Use a single instance"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:678
+#: spyderlib/plugins/configdialog.py:761
 msgid "Set this to open external<br> Python files in an already running instance (Requires a restart)"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:681
-msgid "Vertical dockwidget title bars"
+#: spyderlib/plugins/configdialog.py:764
+msgid "Vertical title bars in panes"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:683
-msgid "Vertical dockwidget tabs"
+#: spyderlib/plugins/configdialog.py:766
+msgid "Vertical tabs in panes"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:685
-msgid "Animated toolbars and dockwidgets"
+#: spyderlib/plugins/configdialog.py:768
+msgid "Animated toolbars and panes"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:687
+#: spyderlib/plugins/configdialog.py:770
 msgid "Tear off menus"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:688
+#: spyderlib/plugins/configdialog.py:771
 msgid "Set this to detach any<br> menu from the main window"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:690
-msgid "Custom dockwidget margin:"
+#: spyderlib/plugins/configdialog.py:773
+msgid "Custom margin for panes:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:717
+#: spyderlib/plugins/configdialog.py:782
+msgid "Prompt when exiting"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:813
 msgid "Status bar"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:718
+#: spyderlib/plugins/configdialog.py:814
+msgid "Show status bar"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:816
 msgid "Show memory usage every"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:729
+#: spyderlib/plugins/configdialog.py:825
 msgid "Show CPU usage every"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:746
+#: spyderlib/plugins/configdialog.py:858
 msgid "Debugging"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:747
+#: spyderlib/plugins/configdialog.py:859
 msgid "Pop up internal console when internal errors appear"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:769
+#: spyderlib/plugins/configdialog.py:868
+msgid "Updates"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:869 spyderlib/spyder.py:2872
+msgid "Check for updates on startup"
+msgstr ""
+
+#: spyderlib/plugins/configdialog.py:902
 msgid "Syntax coloring"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:778
+#: spyderlib/plugins/configdialog.py:911
 msgid "Background:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:779
-#: spyderlib/widgets/sourcecode/codeeditor.py:95
+#: spyderlib/plugins/configdialog.py:912
+#: spyderlib/widgets/sourcecode/codeeditor.py:104
 msgid "Current line:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:780
+#: spyderlib/plugins/configdialog.py:913
 msgid "Current cell:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:781
+#: spyderlib/plugins/configdialog.py:914
 msgid "Occurence:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:782
+#: spyderlib/plugins/configdialog.py:915
 msgid "Link:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:783
+#: spyderlib/plugins/configdialog.py:916
 msgid "Side areas:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:784
+#: spyderlib/plugins/configdialog.py:917
 msgid "Matched parentheses:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:785
+#: spyderlib/plugins/configdialog.py:918
 msgid "Unmatched parentheses:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:786
+#: spyderlib/plugins/configdialog.py:919
 msgid "Normal text:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:787
+#: spyderlib/plugins/configdialog.py:920
 msgid "Keyword:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:788
+#: spyderlib/plugins/configdialog.py:921
 msgid "Builtin:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:789
+#: spyderlib/plugins/configdialog.py:922
 msgid "Definition:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:790
+#: spyderlib/plugins/configdialog.py:923
 msgid "Comment:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:791
+#: spyderlib/plugins/configdialog.py:924
 msgid "String:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:792
+#: spyderlib/plugins/configdialog.py:925
 msgid "Number:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:793
+#: spyderlib/plugins/configdialog.py:926
 msgid "Instance:"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:799
+#: spyderlib/plugins/configdialog.py:932
 msgid "Color scheme"
 msgstr ""
 
-#: spyderlib/plugins/configdialog.py:821 spyderlib/plugins/shortcuts.py:344
+#: spyderlib/plugins/configdialog.py:954 spyderlib/plugins/shortcuts.py:776
 msgid "Reset to default values"
 msgstr ""
 
-#: spyderlib/plugins/console.py:105
+#: spyderlib/plugins/console.py:109
 msgid "Internal console"
 msgstr ""
 
-#: spyderlib/plugins/console.py:125 spyderlib/spyder.py:772
-#: spyderlib/widgets/ipython.py:583
+#: spyderlib/plugins/console.py:129 spyderlib/spyder.py:869
+#: spyderlib/widgets/ipython.py:595
 msgid "&Quit"
 msgstr ""
 
-#: spyderlib/plugins/console.py:126 spyderlib/spyder.py:773
+#: spyderlib/plugins/console.py:131 spyderlib/spyder.py:871
 msgid "Quit"
 msgstr ""
 
-#: spyderlib/plugins/console.py:129 spyderlib/plugins/externalconsole.py:1099
+#: spyderlib/plugins/console.py:134 spyderlib/plugins/externalconsole.py:1039
 msgid "&Run..."
 msgstr ""
 
-#: spyderlib/plugins/console.py:130 spyderlib/plugins/externalconsole.py:1100
+#: spyderlib/plugins/console.py:136 spyderlib/plugins/externalconsole.py:1040
 msgid "Run a Python script"
 msgstr ""
 
-#: spyderlib/plugins/console.py:133
+#: spyderlib/plugins/console.py:139
 msgid "Environment variables..."
 msgstr ""
 
-#: spyderlib/plugins/console.py:135
+#: spyderlib/plugins/console.py:141
 msgid "Show and edit environment variables (for current session)"
 msgstr ""
 
-#: spyderlib/plugins/console.py:139
+#: spyderlib/plugins/console.py:145
 msgid "Show sys.path contents..."
 msgstr ""
 
-#: spyderlib/plugins/console.py:141
+#: spyderlib/plugins/console.py:147
 msgid "Show (read-only) sys.path"
 msgstr ""
 
-#: spyderlib/plugins/console.py:144
+#: spyderlib/plugins/console.py:150
 msgid "Buffer..."
 msgstr ""
 
-#: spyderlib/plugins/console.py:145 spyderlib/plugins/externalconsole.py:85
-#: spyderlib/plugins/history.py:40
+#: spyderlib/plugins/console.py:151 spyderlib/plugins/externalconsole.py:87
+#: spyderlib/plugins/history.py:41
 msgid "Set maximum line count"
 msgstr ""
 
-#: spyderlib/plugins/console.py:148 spyderlib/plugins/explorer.py:57
-#: spyderlib/plugins/history.py:164 spyderlib/plugins/inspector.py:372
-#: spyderlib/plugins/projectexplorer.py:56
+#: spyderlib/plugins/console.py:154 spyderlib/plugins/explorer.py:67
+#: spyderlib/plugins/history.py:169 spyderlib/plugins/inspector.py:388
+#: spyderlib/plugins/projectexplorer.py:68
 msgid "&Font..."
 msgstr ""
 
-#: spyderlib/plugins/console.py:149 spyderlib/plugins/history.py:165
+#: spyderlib/plugins/console.py:155 spyderlib/plugins/history.py:170
 msgid "Set shell font style"
 msgstr ""
 
-#: spyderlib/plugins/console.py:152
+#: spyderlib/plugins/console.py:158
 msgid "External editor path..."
 msgstr ""
 
-#: spyderlib/plugins/console.py:153
+#: spyderlib/plugins/console.py:159
 msgid "Set external editor executable path"
 msgstr ""
 
-#: spyderlib/plugins/console.py:156 spyderlib/plugins/editor.py:144
-#: spyderlib/plugins/externalconsole.py:86 spyderlib/plugins/history.py:43
-#: spyderlib/plugins/history.py:167 spyderlib/plugins/inspector.py:175
-#: spyderlib/plugins/inspector.py:375
+#: spyderlib/plugins/console.py:162 spyderlib/plugins/editor.py:139
+#: spyderlib/plugins/externalconsole.py:88 spyderlib/plugins/history.py:44
+#: spyderlib/plugins/history.py:172 spyderlib/plugins/inspector.py:180
+#: spyderlib/plugins/inspector.py:391
 msgid "Wrap lines"
 msgstr ""
 
-#: spyderlib/plugins/console.py:159 spyderlib/plugins/editor.py:178
+#: spyderlib/plugins/console.py:165 spyderlib/plugins/editor.py:181
 #: spyderlib/plugins/externalconsole.py:133
-#: spyderlib/plugins/ipythonconsole.py:175
+#: spyderlib/plugins/ipythonconsole.py:172
 msgid "Display balloon tips"
 msgstr ""
 
-#: spyderlib/plugins/console.py:163 spyderlib/plugins/editor.py:172
+#: spyderlib/plugins/console.py:169 spyderlib/plugins/editor.py:175
 #: spyderlib/plugins/externalconsole.py:127
 msgid "Automatic code completion"
 msgstr ""
 
-#: spyderlib/plugins/console.py:167 spyderlib/plugins/editor.py:176
+#: spyderlib/plugins/console.py:173 spyderlib/plugins/editor.py:179
 #: spyderlib/plugins/externalconsole.py:131
 msgid "Enter key selects completion"
 msgstr ""
 
-#: spyderlib/plugins/console.py:172
+#: spyderlib/plugins/console.py:178
 msgid "Internal console settings"
 msgstr ""
 
-#: spyderlib/plugins/console.py:223 spyderlib/plugins/externalconsole.py:1285
+#: spyderlib/plugins/console.py:231 spyderlib/plugins/externalconsole.py:1220
 msgid "Run Python script"
 msgstr ""
 
-#: spyderlib/plugins/console.py:224 spyderlib/plugins/externalconsole.py:229
-#: spyderlib/plugins/externalconsole.py:1286 spyderlib/widgets/explorer.py:666
+#: spyderlib/plugins/console.py:232 spyderlib/plugins/externalconsole.py:226
+#: spyderlib/plugins/externalconsole.py:1221 spyderlib/widgets/explorer.py:675
 msgid "Python scripts"
 msgstr ""
 
-#: spyderlib/plugins/console.py:269 spyderlib/plugins/explorer.py:109
-#: spyderlib/plugins/history.py:282 spyderlib/plugins/inspector.py:651
-#: spyderlib/plugins/projectexplorer.py:118
+#: spyderlib/plugins/console.py:278 spyderlib/plugins/explorer.py:117
+#: spyderlib/plugins/history.py:285 spyderlib/plugins/inspector.py:665
+#: spyderlib/plugins/projectexplorer.py:126
 msgid "Select a new font"
 msgstr ""
 
-#: spyderlib/plugins/console.py:276
+#: spyderlib/plugins/console.py:286
 msgid "Buffer"
 msgstr ""
 
-#: spyderlib/plugins/console.py:277
+#: spyderlib/plugins/console.py:287
 msgid "Maximum line count"
 msgstr ""
 
-#: spyderlib/plugins/console.py:286
+#: spyderlib/plugins/console.py:297
 msgid "External editor"
 msgstr ""
 
-#: spyderlib/plugins/console.py:287
+#: spyderlib/plugins/console.py:298
 msgid "External editor executable path:"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:100
+#: spyderlib/plugins/editor.py:101
 msgid "Edit template for new modules"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:105
+#: spyderlib/plugins/editor.py:106
 msgid "Text and margin font style"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:108
+#: spyderlib/plugins/editor.py:109
 msgid "Sort files according to full path"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:110
+#: spyderlib/plugins/editor.py:111
 msgid "Show tab bar"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:117 spyderlib/plugins/editor.py:192
-#: spyderlib/plugins/externalconsole.py:81
-#: spyderlib/plugins/externalconsole.py:126 spyderlib/plugins/history.py:42
-#: spyderlib/plugins/inspector.py:174 spyderlib/plugins/ipythonconsole.py:199
+#: spyderlib/plugins/editor.py:118 spyderlib/plugins/editor.py:195
+#: spyderlib/plugins/externalconsole.py:83
+#: spyderlib/plugins/externalconsole.py:126 spyderlib/plugins/history.py:43
+#: spyderlib/plugins/inspector.py:179 spyderlib/plugins/ipythonconsole.py:206
 msgid "Source code"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:118
+#: spyderlib/plugins/editor.py:119
 msgid "Show line numbers"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:119 spyderlib/plugins/editor.py:892
+#: spyderlib/plugins/editor.py:120 spyderlib/plugins/editor.py:916
 msgid "Show blank spaces"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:120
+#: spyderlib/plugins/editor.py:121
 msgid "Show vertical line after"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:121
+#: spyderlib/plugins/editor.py:122
 msgid "characters"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:129
+#: spyderlib/plugins/editor.py:127
 msgid "Highlight current line"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:131
+#: spyderlib/plugins/editor.py:129
 msgid "Highlight current cell"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:133
+#: spyderlib/plugins/editor.py:131
 msgid "Highlight occurences after"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:147 spyderlib/plugins/history.py:51
-#: spyderlib/plugins/inspector.py:178
+#: spyderlib/plugins/editor.py:142 spyderlib/plugins/history.py:52
+#: spyderlib/plugins/inspector.py:183
 msgid "Syntax color scheme: "
 msgstr ""
 
-#: spyderlib/plugins/editor.py:161 spyderlib/plugins/runconfig.py:313
-#: spyderlib/plugins/runconfig.py:435 spyderlib/plugins/runconfig.py:440
-#: spyderlib/spyder.py:1850 spyderlib/utils/programs.py:175
-#: spyderlib/widgets/explorer.py:234
-#: spyderlib/widgets/externalshell/baseshell.py:138
+#: spyderlib/plugins/editor.py:164 spyderlib/plugins/runconfig.py:321
+#: spyderlib/plugins/runconfig.py:443 spyderlib/plugins/runconfig.py:448
+#: spyderlib/spyder.py:2501 spyderlib/utils/programs.py:175
+#: spyderlib/widgets/explorer.py:240
+#: spyderlib/widgets/externalshell/baseshell.py:140
 msgid "Run"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:162
+#: spyderlib/plugins/editor.py:165
 msgid "Save all files before running script"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:165
+#: spyderlib/plugins/editor.py:168
 msgid "Run selection"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:166
+#: spyderlib/plugins/editor.py:169
 msgid "Maintain focus in the Editor after running cells or selections"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:169 spyderlib/plugins/externalconsole.py:365
+#: spyderlib/plugins/editor.py:172 spyderlib/plugins/externalconsole.py:334
 msgid "Introspection"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:174 spyderlib/plugins/externalconsole.py:129
+#: spyderlib/plugins/editor.py:177 spyderlib/plugins/externalconsole.py:129
 msgid "Case sensitive code completion"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:179
+#: spyderlib/plugins/editor.py:182
 msgid "Link to object definition"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:181
+#: spyderlib/plugins/editor.py:184
 msgid ""
 "If this option is enabled, clicking on an object\n"
 "name (left-click + Ctrl key) will go this object\n"
 "definition (if resolved)."
 msgstr ""
 
-#: spyderlib/plugins/editor.py:185
+#: spyderlib/plugins/editor.py:188
 msgid "<b>Warning:</b><br>The Python module <i>rope</i> is not installed on this computer: calltips, code completion and go-to-definition features won't be available."
 msgstr ""
 
-#: spyderlib/plugins/editor.py:193
+#: spyderlib/plugins/editor.py:196
 msgid "Automatic insertion of parentheses, braces and brackets"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:196
+#: spyderlib/plugins/editor.py:199
 msgid "Automatic insertion of closing quotes"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:198
+#: spyderlib/plugins/editor.py:201
 msgid "Automatic insertion of colons after 'for', 'if', 'def', etc"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:201
+#: spyderlib/plugins/editor.py:204
 msgid "Automatic indentation after 'else', 'elif', etc."
 msgstr ""
 
-#: spyderlib/plugins/editor.py:203
+#: spyderlib/plugins/editor.py:206
 msgid "Indentation characters: "
 msgstr ""
 
-#: spyderlib/plugins/editor.py:204
+#: spyderlib/plugins/editor.py:207
 msgid "4 spaces"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:205
+#: spyderlib/plugins/editor.py:208
 msgid "2 spaces"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:206
+#: spyderlib/plugins/editor.py:209
 msgid "tab"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:207
+#: spyderlib/plugins/editor.py:210
 msgid "Tab stop width:"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:207
+#: spyderlib/plugins/editor.py:210
 msgid "pixels"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:209
+#: spyderlib/plugins/editor.py:212
 msgid "Tab always indent"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:211
+#: spyderlib/plugins/editor.py:214
 msgid ""
 "If enabled, pressing Tab will always indent,\n"
 "even when the cursor is not at the beginning\n"
@@ -591,593 +639,586 @@ msgid ""
 "shortcut: Ctrl+Space)"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:216
+#: spyderlib/plugins/editor.py:219
 msgid "Intelligent backspace"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:218
+#: spyderlib/plugins/editor.py:221
 msgid "Automatically remove trailing spaces when saving files"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:222
+#: spyderlib/plugins/editor.py:225
 msgid "Analysis"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:224
-msgid "<u>Note</u>: add <b>analysis:ignore</b> in a comment to ignore code/style analysis warnings. For more informations on style guide for Python code, please refer to the %s page."
+#: spyderlib/plugins/editor.py:227
+msgid "<i>(Refer to the {} page)</i>"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:233
-#: spyderlib/widgets/sourcecode/codeeditor.py:1617
-msgid "Code analysis"
+#: spyderlib/plugins/editor.py:231
+msgid "Real-time code analysis"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:235
-msgid ""
-"If enabled, Python source code will be analyzed\n"
-"using pyflakes, lines containing errors or \n"
-"warnings will be highlighted"
+#: spyderlib/plugins/editor.py:233
+msgid "<p>If enabled, Python source code will be analyzedusing pyflakes, lines containing errors or warnings will be highlighted.</p><p><u>Note</u>: add <b>analysis:ignore</b> in a comment to ignore code analysis warnings.</p>"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:240
+#: spyderlib/plugins/editor.py:241
 msgid "Code analysis requires pyflakes %s+"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:242
-msgid "Style analysis"
+#: spyderlib/plugins/editor.py:243
+msgid "Real-time code style analysis"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:244
-msgid ""
-"If enabled, Python source code will be analyzed\n"
-"using pep8, lines that are not following PEP8\n"
-"style guide will be highlighted"
+#: spyderlib/plugins/editor.py:245
+msgid "<p>If enabled, Python source code will be analyzedusing pep8, lines that are not following PEP8 style guide will be highlighted.</p><p><u>Note</u>: add <b>analysis:ignore</b> in a comment to ignore style analysis warnings.</p>"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:251
-msgid "Tasks (TODO, FIXME, XXX, HINT, TIP, @todo)"
+#: spyderlib/plugins/editor.py:252
+msgid "Code annotations (TODO, FIXME, XXX, HINT, TIP, @todo)"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:254
+#: spyderlib/plugins/editor.py:255
 msgid "Perform analysis when saving file and every"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:258
+#: spyderlib/plugins/editor.py:259
 msgid "Perform analysis only when saving file"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:306
+#: spyderlib/plugins/editor.py:318
 msgid "End-of-line characters"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:307
+#: spyderlib/plugins/editor.py:319
 msgid "When opening a text file containing mixed end-of-line characters (this may raise syntax errors in the consoles on Windows platforms), Spyder may fix the file automatically."
 msgstr ""
 
-#: spyderlib/plugins/editor.py:313
+#: spyderlib/plugins/editor.py:325
 msgid "Fix automatically and show warning message box"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:324 spyderlib/plugins/externalconsole.py:363
-#: spyderlib/plugins/ipythonconsole.py:444
+#: spyderlib/plugins/editor.py:336 spyderlib/plugins/externalconsole.py:332
+#: spyderlib/plugins/ipythonconsole.py:463
 #: spyderlib/plugins/variableexplorer.py:41
 msgid "Display"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:326
+#: spyderlib/plugins/editor.py:338
 msgid "Code Introspection/Analysis"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:329 spyderlib/plugins/externalconsole.py:367
+#: spyderlib/plugins/editor.py:341 spyderlib/plugins/externalconsole.py:336
 msgid "Advanced settings"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:583 spyderlib/widgets/editortools.py:508
+#: spyderlib/plugins/editor.py:607 spyderlib/widgets/editortools.py:510
 msgid "Show/hide outline explorer"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:589
+#: spyderlib/plugins/editor.py:613
 msgid "Show/hide project explorer"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:597
+#: spyderlib/plugins/editor.py:621
 msgid "&New file..."
 msgstr ""
 
-#: spyderlib/plugins/editor.py:598 spyderlib/plugins/workingdirectory.py:82
-#: spyderlib/widgets/explorer.py:643 spyderlib/widgets/explorer.py:650
+#: spyderlib/plugins/editor.py:622 spyderlib/plugins/workingdirectory.py:82
+#: spyderlib/widgets/explorer.py:652 spyderlib/widgets/explorer.py:659
 msgid "New file"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:605
+#: spyderlib/plugins/editor.py:629
 msgid "&Open..."
 msgstr ""
 
-#: spyderlib/plugins/editor.py:606 spyderlib/plugins/editor.py:1647
+#: spyderlib/plugins/editor.py:630 spyderlib/plugins/editor.py:1643
 #: spyderlib/plugins/workingdirectory.py:69
 msgid "Open file"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:613
+#: spyderlib/plugins/editor.py:637
 msgid "&Revert"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:614
+#: spyderlib/plugins/editor.py:638
 msgid "Revert file from disk"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:617
+#: spyderlib/plugins/editor.py:641
 msgid "&Save"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:618
+#: spyderlib/plugins/editor.py:642
 msgid "Save file"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:625
+#: spyderlib/plugins/editor.py:649
 msgid "Sav&e all"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:626
+#: spyderlib/plugins/editor.py:650
 msgid "Save all files"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:633
+#: spyderlib/plugins/editor.py:658
 msgid "Save &as..."
 msgstr ""
 
-#: spyderlib/plugins/editor.py:634
+#: spyderlib/plugins/editor.py:659
 msgid "Save current file as..."
 msgstr ""
 
-#: spyderlib/plugins/editor.py:636 spyderlib/plugins/editor.py:637
+#: spyderlib/plugins/editor.py:663 spyderlib/plugins/editor.py:664
 msgid "Print preview..."
 msgstr ""
 
-#: spyderlib/plugins/editor.py:638
+#: spyderlib/plugins/editor.py:665
 msgid "&Print..."
 msgstr ""
 
-#: spyderlib/plugins/editor.py:639
+#: spyderlib/plugins/editor.py:666
 msgid "Print current file..."
 msgstr ""
 
-#: spyderlib/plugins/editor.py:644
+#: spyderlib/plugins/editor.py:669
 msgid "&Close"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:645
+#: spyderlib/plugins/editor.py:670
 msgid "Close current file"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:647
+#: spyderlib/plugins/editor.py:673
 msgid "C&lose all"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:648
+#: spyderlib/plugins/editor.py:674
 msgid "Close all opened files"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:655
+#: spyderlib/plugins/editor.py:681
 msgid "Set/Clear breakpoint"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:662
+#: spyderlib/plugins/editor.py:688
 msgid "Set/Edit conditional breakpoint"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:669
+#: spyderlib/plugins/editor.py:695
 msgid "Clear breakpoints in all files"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:671
+#: spyderlib/plugins/editor.py:697
 msgid "Breakpoints"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:675
+#: spyderlib/plugins/editor.py:701
 msgid "Debug with winpdb"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:682 spyderlib/spyder.py:575
+#: spyderlib/plugins/editor.py:708 spyderlib/spyder.py:659
 msgid "&Debug"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:683
+#: spyderlib/plugins/editor.py:709
 msgid "Debug file"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:688
+#: spyderlib/plugins/editor.py:713
 msgid "Step"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:689
+#: spyderlib/plugins/editor.py:714
 msgid "Run current line"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:695
+#: spyderlib/plugins/editor.py:720
 msgid "Continue"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:696
+#: spyderlib/plugins/editor.py:721
 msgid "Continue execution until next breakpoint"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:703
+#: spyderlib/plugins/editor.py:728
 msgid "Step Into"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:704
+#: spyderlib/plugins/editor.py:729
 msgid "Step into function or method of current line"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:711
+#: spyderlib/plugins/editor.py:736
 msgid "Step Return"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:712
+#: spyderlib/plugins/editor.py:737
 msgid "Run until current function or method returns"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:719
+#: spyderlib/plugins/editor.py:744
 msgid "Exit"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:720
+#: spyderlib/plugins/editor.py:745
 msgid "Exit Debug"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:731
+#: spyderlib/plugins/editor.py:756
 msgid "Debugging control"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:735 spyderlib/plugins/editor.py:1246
-#: spyderlib/spyder.py:570
+#: spyderlib/plugins/editor.py:760 spyderlib/plugins/editor.py:1236
+#: spyderlib/spyder.py:654
 msgid "&Run"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:736
+#: spyderlib/plugins/editor.py:761
 msgid "Run file"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:742
+#: spyderlib/plugins/editor.py:766
 msgid "&Configure..."
 msgstr ""
 
-#: spyderlib/plugins/editor.py:743
-#: spyderlib/widgets/externalshell/pythonshell.py:294
+#: spyderlib/plugins/editor.py:768
+#: spyderlib/widgets/externalshell/pythonshell.py:311
 msgid "Run settings"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:752
+#: spyderlib/plugins/editor.py:776
 msgid "Re-run &last script"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:753
+#: spyderlib/plugins/editor.py:778
 msgid "Run again last file"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:760
-#: spyderlib/widgets/sourcecode/codeeditor.py:2305
+#: spyderlib/plugins/editor.py:785
+#: spyderlib/widgets/sourcecode/codeeditor.py:2462
 msgid "Run &selection or current line"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:763
+#: spyderlib/plugins/editor.py:788
 msgid "Run selection or current line"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:776
+#: spyderlib/plugins/editor.py:801
 msgid "Run cell"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:778
+#: spyderlib/plugins/editor.py:804
 msgid ""
 "Run current cell (Ctrl+Enter)\n"
 "[Use #%% to create cells]"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:783
+#: spyderlib/plugins/editor.py:809
 msgid "Run cell and advance"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:786
+#: spyderlib/plugins/editor.py:812
 msgid "Run current cell and go to the next one (Shift+Enter)"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:792
+#: spyderlib/plugins/editor.py:818
 msgid "Show todo list"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:793
+#: spyderlib/plugins/editor.py:819
 msgid "Show TODO/FIXME/XXX/HINT/TIP/@todo comments list"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:801
+#: spyderlib/plugins/editor.py:826
 msgid "Show warning/error list"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:802
+#: spyderlib/plugins/editor.py:827
 msgid "Show code analysis warnings/errors"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:809
+#: spyderlib/plugins/editor.py:833
 msgid "Previous warning/error"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:810
+#: spyderlib/plugins/editor.py:834
 msgid "Go to previous code analysis warning/error"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:813
+#: spyderlib/plugins/editor.py:837
 msgid "Next warning/error"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:814
+#: spyderlib/plugins/editor.py:838
 msgid "Go to next code analysis warning/error"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:818
+#: spyderlib/plugins/editor.py:842
 msgid "Last edit location"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:819
+#: spyderlib/plugins/editor.py:843
 msgid "Go to last edit location"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:825
+#: spyderlib/plugins/editor.py:849
 msgid "Previous cursor position"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:826
+#: spyderlib/plugins/editor.py:850
 msgid "Go to previous cursor position"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:832
+#: spyderlib/plugins/editor.py:856
 msgid "Next cursor position"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:833
+#: spyderlib/plugins/editor.py:857
 msgid "Go to next cursor position"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:840
-#: spyderlib/widgets/sourcecode/codeeditor.py:2292
+#: spyderlib/plugins/editor.py:864
+#: spyderlib/widgets/sourcecode/codeeditor.py:2449
 msgid "Comment"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:840
-#: spyderlib/widgets/sourcecode/codeeditor.py:2292
+#: spyderlib/plugins/editor.py:864
+#: spyderlib/widgets/sourcecode/codeeditor.py:2449
 msgid "Uncomment"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:841
+#: spyderlib/plugins/editor.py:865
 msgid "Comment current line or selection"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:845
+#: spyderlib/plugins/editor.py:869
 msgid "Add &block comment"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:846
+#: spyderlib/plugins/editor.py:870
 msgid "Add block comment around current line or selection"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:852
+#: spyderlib/plugins/editor.py:876
 msgid "R&emove block comment"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:853
+#: spyderlib/plugins/editor.py:877
 msgid "Remove comment block around current line or selection"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:864
+#: spyderlib/plugins/editor.py:888
 msgid "Indent"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:865
+#: spyderlib/plugins/editor.py:889
 msgid "Indent current line or selection"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:868
+#: spyderlib/plugins/editor.py:892
 msgid "Unindent"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:869
+#: spyderlib/plugins/editor.py:893
 msgid "Unindent current line or selection"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:874
+#: spyderlib/plugins/editor.py:898
 msgid "Carriage return and line feed (Windows)"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:877
+#: spyderlib/plugins/editor.py:901
 msgid "Line feed (UNIX)"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:880
+#: spyderlib/plugins/editor.py:904
 msgid "Carriage return (Mac)"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:886
+#: spyderlib/plugins/editor.py:910
 msgid "Convert end-of-line characters"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:890
+#: spyderlib/plugins/editor.py:914
 msgid "Remove trailing spaces"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:894
+#: spyderlib/plugins/editor.py:918
 msgid "Fix indentation"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:895
+#: spyderlib/plugins/editor.py:919
 msgid "Replace tab characters by space characters"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:898
+#: spyderlib/plugins/editor.py:922
 msgid "Go to line..."
 msgstr ""
 
-#: spyderlib/plugins/editor.py:906
+#: spyderlib/plugins/editor.py:930
 msgid "Set console working directory"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:908
+#: spyderlib/plugins/editor.py:932
 msgid "Set current console (and file explorer) working directory to current script directory"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:913
+#: spyderlib/plugins/editor.py:937
 msgid "Maximum number of recent files..."
 msgstr ""
 
-#: spyderlib/plugins/editor.py:916
+#: spyderlib/plugins/editor.py:940
 msgid "Clear recent files list"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:916
+#: spyderlib/plugins/editor.py:940
 msgid "Clear this list"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:918
+#: spyderlib/plugins/editor.py:942
 msgid "Open &recent"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1234 spyderlib/spyder.py:551
+#: spyderlib/plugins/editor.py:1224 spyderlib/spyder.py:635
 msgid "File toolbar"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1235 spyderlib/spyder.py:561
+#: spyderlib/plugins/editor.py:1225 spyderlib/spyder.py:645
 msgid "Search toolbar"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1236 spyderlib/spyder.py:566
+#: spyderlib/plugins/editor.py:1226 spyderlib/spyder.py:650
 msgid "Source toolbar"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1237 spyderlib/spyder.py:571
+#: spyderlib/plugins/editor.py:1227 spyderlib/spyder.py:655
 msgid "Run toolbar"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1238 spyderlib/spyder.py:576
+#: spyderlib/plugins/editor.py:1228 spyderlib/spyder.py:660
 msgid "Debug toolbar"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1239 spyderlib/spyder.py:556
+#: spyderlib/plugins/editor.py:1229 spyderlib/spyder.py:640
 msgid "Edit toolbar"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1242 spyderlib/spyder.py:548
+#: spyderlib/plugins/editor.py:1232 spyderlib/spyder.py:633
 msgid "&File"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1243 spyderlib/spyder.py:555
+#: spyderlib/plugins/editor.py:1233 spyderlib/spyder.py:639
 msgid "&Edit"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1244 spyderlib/spyder.py:560
+#: spyderlib/plugins/editor.py:1234 spyderlib/spyder.py:644
 msgid "&Search"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1245 spyderlib/spyder.py:565
+#: spyderlib/plugins/editor.py:1235 spyderlib/spyder.py:649
 msgid "Sour&ce"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1247 spyderlib/spyder.py:583
+#: spyderlib/plugins/editor.py:1237 spyderlib/spyder.py:667
 msgid "&Tools"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1248
+#: spyderlib/plugins/editor.py:1238
 msgid "?"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1469
+#: spyderlib/plugins/editor.py:1458
 msgid "Spyder Editor"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1470
+#: spyderlib/plugins/editor.py:1459
 msgid "This is a temporary script file."
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1536
+#: spyderlib/plugins/editor.py:1527
 msgid "untitled"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1607
+#: spyderlib/plugins/editor.py:1601
 msgid "Maximum number of recent files"
 msgstr ""
 
-#: spyderlib/plugins/editor.py:1729
+#: spyderlib/plugins/editor.py:1726
 msgid "Printing..."
 msgstr ""
 
-#: spyderlib/plugins/explorer.py:45
+#: spyderlib/plugins/explorer.py:55
 msgid "File explorer"
 msgstr ""
 
-#: spyderlib/plugins/explorer.py:58 spyderlib/plugins/inspector.py:373
-#: spyderlib/plugins/projectexplorer.py:57
+#: spyderlib/plugins/explorer.py:68 spyderlib/plugins/inspector.py:389
+#: spyderlib/plugins/projectexplorer.py:69
 msgid "Set font style"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:46
+#: spyderlib/plugins/externalconsole.py:49
 msgid "Interactive data plotting in the consoles"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:53
-#: spyderlib/plugins/externalconsole.py:1066
-#: spyderlib/plugins/inspector.py:403 spyderlib/plugins/runconfig.py:178
-#: spyderlib/plugins/runconfig.py:447
-#: spyderlib/widgets/externalshell/baseshell.py:106
-#: spyderlib/widgets/ipython.py:509
+#: spyderlib/plugins/externalconsole.py:57
+#: spyderlib/plugins/externalconsole.py:1005
+#: spyderlib/plugins/inspector.py:419 spyderlib/plugins/runconfig.py:185
+#: spyderlib/plugins/runconfig.py:455
+#: spyderlib/widgets/externalshell/baseshell.py:107
+#: spyderlib/widgets/ipython.py:521
 msgid "Console"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:69
+#: spyderlib/plugins/externalconsole.py:71
 msgid "One tab per script"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:70
-#: spyderlib/widgets/externalshell/baseshell.py:171
+#: spyderlib/plugins/externalconsole.py:72
+#: spyderlib/widgets/externalshell/baseshell.py:173
 msgid "Show elapsed time"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:71 spyderlib/widgets/explorer.py:988
+#: spyderlib/plugins/externalconsole.py:73 spyderlib/widgets/explorer.py:1016
 msgid "Show icons and text"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:83
+#: spyderlib/plugins/externalconsole.py:85
 msgid "Buffer: "
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:83
-#: spyderlib/plugins/ipythonconsole.py:201
+#: spyderlib/plugins/externalconsole.py:85
+#: spyderlib/plugins/ipythonconsole.py:208
 msgid " lines"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:88
+#: spyderlib/plugins/externalconsole.py:90
 msgid "Merge process standard output/error channels"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:90
+#: spyderlib/plugins/externalconsole.py:92
 msgid ""
 "Merging the output channels of the process means that\n"
 "the standard error won't be written in red anymore,\n"
 "but this has the effect of speeding up display."
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:94
+#: spyderlib/plugins/externalconsole.py:96
 msgid "Colorize standard error channel using ANSI escape codes"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:96
+#: spyderlib/plugins/externalconsole.py:98
 msgid ""
 "This method is the only way to have colorized standard\n"
 "error channel when the output channels have been merged."
 msgstr ""
 
 #: spyderlib/plugins/externalconsole.py:114
-#: spyderlib/plugins/ipythonconsole.py:188
-#: spyderlib/widgets/arrayeditor.py:460
-#: spyderlib/widgets/dataframeeditor.py:515
+#: spyderlib/plugins/ipythonconsole.py:195
+#: spyderlib/widgets/arrayeditor.py:461
+#: spyderlib/widgets/dataframeeditor.py:516
 msgid "Background color"
 msgstr ""
 
@@ -1219,500 +1260,480 @@ msgstr ""
 msgid "Set UMR excluded (not reloaded) modules"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:181
+#: spyderlib/plugins/externalconsole.py:180
 msgid "Python executable"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:183
+#: spyderlib/plugins/externalconsole.py:182
 msgid "Select the Python interpreter executable binary in which Spyder will run scripts:"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:186
+#: spyderlib/plugins/externalconsole.py:185
 msgid "Default (i.e. the same as Spyder's)"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:190
+#: spyderlib/plugins/externalconsole.py:189
 msgid "Use the following Python interpreter:"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:194
+#: spyderlib/plugins/externalconsole.py:193
 msgid "Executables"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:214
+#: spyderlib/plugins/externalconsole.py:211
 msgid "PYTHONSTARTUP replacement"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:216
+#: spyderlib/plugins/externalconsole.py:213
 msgid ""
 "This option will override the PYTHONSTARTUP environment variable which\n"
 "defines the script to be executed during the Python console startup."
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:221
+#: spyderlib/plugins/externalconsole.py:218
 msgid "Default PYTHONSTARTUP script"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:225
+#: spyderlib/plugins/externalconsole.py:222
 msgid "Use the following startup script:"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:244
+#: spyderlib/plugins/externalconsole.py:239
 msgid "Monitor"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:245
+#: spyderlib/plugins/externalconsole.py:240
 msgid "The monitor provides introspection features to console: code completion, calltips and variable explorer. Because it relies on several modules, disabling the monitor may be useful to accelerate console startup."
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:252
+#: spyderlib/plugins/externalconsole.py:247
 msgid "Enable monitor"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:264
+#: spyderlib/plugins/externalconsole.py:260
 msgid "Default library"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:266
-msgid "Qt (PyQt/PySide)"
+#: spyderlib/plugins/externalconsole.py:265
+msgid "Qt-Python Bindings"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:268
-msgid "Qt-Python bindings library selection:"
+#: spyderlib/plugins/externalconsole.py:267
+msgid "Library:"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:270
+#: spyderlib/plugins/externalconsole.py:269
 msgid "This option will act on<br> libraries such as Matplotlib, guidata or ETS"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:291
-msgid "PyQt"
-msgstr ""
-
-#: spyderlib/plugins/externalconsole.py:293
-msgid "API selection for QString and QVariant objects:"
-msgstr ""
-
-#: spyderlib/plugins/externalconsole.py:294
-msgid "API #1"
-msgstr ""
-
-#: spyderlib/plugins/externalconsole.py:294
-msgid "API #2"
-msgstr ""
-
-#: spyderlib/plugins/externalconsole.py:294
-msgid "Default API"
-msgstr ""
-
-#: spyderlib/plugins/externalconsole.py:296
-msgid "PyQt API #1 is the default <br>API for Python 2. PyQt API #2 is the default API for Python 3 and is compatible with PySide."
-msgstr ""
-
-#: spyderlib/plugins/externalconsole.py:300
-msgid "Ignore API change errors (sip.setapi)"
-msgstr ""
-
-#: spyderlib/plugins/externalconsole.py:302
-msgid "Enabling this option will ignore <br>errors when changing PyQt API. As PyQt does not support dynamic API changes, it is strongly recommended to use this feature wisely, e.g. for debugging purpose."
+#: spyderlib/plugins/externalconsole.py:278
+#: spyderlib/plugins/ipythonconsole.py:465
+msgid "Graphics"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:321
-msgid "Matplotlib"
+#: spyderlib/plugins/externalconsole.py:279
+msgid "Decide which backend to use to display graphics. If unsure, please select the <b>Automatic</b> backend.<br><br><b>Note:</b> We support a very limited number of backends in our Python consoles. If you prefer to work with a different one, please use an IPython console."
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:323
-msgid "GUI backend:"
+#: spyderlib/plugins/externalconsole.py:295
+#: spyderlib/plugins/ipythonconsole.py:270
+msgid "Backend:"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:325
-msgid "Set the GUI toolkit used by <br>Matplotlib to show figures (default: Qt4Agg)"
+#: spyderlib/plugins/externalconsole.py:297
+#: spyderlib/plugins/ipythonconsole.py:272
+msgid "This option will be applied the next time a console is opened."
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:344
+#: spyderlib/plugins/externalconsole.py:308
 msgid "Enthought Tool Suite"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:345
+#: spyderlib/plugins/externalconsole.py:309
 msgid "Enthought Tool Suite (ETS) supports PyQt4 (qt4) and wxPython (wx) graphical user interfaces."
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:349
+#: spyderlib/plugins/externalconsole.py:313
 msgid "ETS_TOOLKIT:"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:369
+#: spyderlib/plugins/externalconsole.py:338
 msgid "External modules"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:426
-#: spyderlib/plugins/externalconsole.py:666
-#: spyderlib/plugins/ipythonconsole.py:113
-#: spyderlib/plugins/ipythonconsole.py:808 spyderlib/spyder.py:1331
-#: spyderlib/spyder.py:1349 spyderlib/utils/environ.py:94
-#: spyderlib/utils/environ.py:107 spyderlib/widgets/dicteditor.py:449
+#: spyderlib/plugins/externalconsole.py:374
+#: spyderlib/plugins/externalconsole.py:617
+#: spyderlib/plugins/ipythonconsole.py:114
+#: spyderlib/plugins/ipythonconsole.py:832 spyderlib/spyder.py:1803
+#: spyderlib/spyder.py:1825 spyderlib/spyder.py:1888 spyderlib/spyder.py:2774
+#: spyderlib/utils/environ.py:95 spyderlib/utils/environ.py:108
+#: spyderlib/widgets/dicteditor.py:452
 msgid "Warning"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:427
+#: spyderlib/plugins/externalconsole.py:375
 msgid "You selected a <b>Python %d</b> interpreter for the console but Spyder is running on <b>Python %d</b>!.<br><br>Although this is possible, we recommend you to install and run Spyder directly with your selected interpreter, to avoid seeing false warnings and errors due to the incompatible syntax between these two Python versions."
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:590
+#: spyderlib/plugins/externalconsole.py:538
 msgid "Trying to kill a kernel?"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:591
+#: spyderlib/plugins/externalconsole.py:539
 msgid "You can't close this kernel because it has one or more consoles connected to it.<br><br>You need to close them instead or you can kill the kernel using the second button from right to left."
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:667
+#: spyderlib/plugins/externalconsole.py:618
 msgid "No Python console is currently selected to run <b>%s</b>.<br><br>Please select or open a new Python console and try again."
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:748
+#: spyderlib/plugins/externalconsole.py:698
 msgid ""
 "%s is already running in a separate process.\n"
 "Do you want to kill the process before starting a new one?"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:917
+#: spyderlib/plugins/externalconsole.py:858
 msgid "Kernel"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:929
+#: spyderlib/plugins/externalconsole.py:868
 msgid "Either:<ol><li>Your IPython frontend and kernel versions are <b>incompatible</b> or</li><li>You <b>don't have</b> IPython installed in your external interpreter.</li></ol>In any case, we're sorry but we can't create a console for you."
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:953
+#: spyderlib/plugins/externalconsole.py:892
 msgid "Command Window"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:955
+#: spyderlib/plugins/externalconsole.py:894
 msgid "Terminal"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:1008
+#: spyderlib/plugins/externalconsole.py:947
 msgid "Kernel %s"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:1088
+#: spyderlib/plugins/externalconsole.py:1027
 msgid "Open a &Python console"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:1091
+#: spyderlib/plugins/externalconsole.py:1031
 msgid "Open &command prompt"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:1092
+#: spyderlib/plugins/externalconsole.py:1032
 msgid "Open a Windows command prompt"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:1094
+#: spyderlib/plugins/externalconsole.py:1034
 msgid "Open a &terminal"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:1095
+#: spyderlib/plugins/externalconsole.py:1035
 msgid "Open a terminal window"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:1263
+#: spyderlib/plugins/externalconsole.py:1196
 msgid "Open an IPython console"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:1264
+#: spyderlib/plugins/externalconsole.py:1197
 msgid "The console monitor was disabled: the IPython kernel will be started as expected, but an IPython console will have to be connected manually to the kernel."
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:1294
-#: spyderlib/plugins/externalconsole.py:1307
-#: spyderlib/plugins/externalconsole.py:1311
+#: spyderlib/plugins/externalconsole.py:1229
+#: spyderlib/plugins/externalconsole.py:1242
+#: spyderlib/plugins/externalconsole.py:1246
 msgid "UMR"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:1295
+#: spyderlib/plugins/externalconsole.py:1230
 msgid ""
 "UMR excluded modules:\n"
 "(example: guidata, guiqwt)"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:1308
+#: spyderlib/plugins/externalconsole.py:1243
 msgid ""
 "The following modules are not installed on your machine:\n"
 "%s"
 msgstr ""
 
-#: spyderlib/plugins/externalconsole.py:1312
+#: spyderlib/plugins/externalconsole.py:1247
 msgid "Please note that these changes will be applied only to new Python/IPython consoles"
 msgstr ""
 
-#: spyderlib/plugins/findinfiles.py:90 spyderlib/widgets/findinfiles.py:691
+#: spyderlib/plugins/findinfiles.py:96 spyderlib/widgets/findinfiles.py:690
 msgid "Find in files"
 msgstr ""
 
-#: spyderlib/plugins/findinfiles.py:114
+#: spyderlib/plugins/findinfiles.py:117
 msgid "&Find in files"
 msgstr ""
 
-#: spyderlib/plugins/findinfiles.py:117
+#: spyderlib/plugins/findinfiles.py:120
 msgid "Search text in multiple files"
 msgstr ""
 
-#: spyderlib/plugins/history.py:36
+#: spyderlib/plugins/history.py:37
 msgid "Settings"
 msgstr ""
 
-#: spyderlib/plugins/history.py:38
+#: spyderlib/plugins/history.py:39
 msgid " entries"
 msgstr ""
 
-#: spyderlib/plugins/history.py:38
+#: spyderlib/plugins/history.py:39
 msgid "History depth: "
 msgstr ""
 
-#: spyderlib/plugins/history.py:45
+#: spyderlib/plugins/history.py:46
 msgid "Scroll automatically to last entry"
 msgstr ""
 
-#: spyderlib/plugins/history.py:113 spyderlib/plugins/inspector.py:458
-#: spyderlib/widgets/editor.py:540 spyderlib/widgets/explorer.py:1018
-#: spyderlib/widgets/externalshell/baseshell.py:151
-#: spyderlib/widgets/externalshell/namespacebrowser.py:226
-#: spyderlib/widgets/ipython.py:556
+#: spyderlib/plugins/history.py:118 spyderlib/plugins/inspector.py:472
+#: spyderlib/widgets/editor.py:459 spyderlib/widgets/explorer.py:1027
+#: spyderlib/widgets/externalshell/baseshell.py:153
+#: spyderlib/widgets/externalshell/namespacebrowser.py:139
+#: spyderlib/widgets/ipython.py:568
 msgid "Options"
 msgstr ""
 
-#: spyderlib/plugins/history.py:133
+#: spyderlib/plugins/history.py:138
 msgid "History log"
 msgstr ""
 
-#: spyderlib/plugins/history.py:160
+#: spyderlib/plugins/history.py:165
 msgid "History..."
 msgstr ""
 
-#: spyderlib/plugins/history.py:162
+#: spyderlib/plugins/history.py:167
 msgid "Set history maximum entries"
 msgstr ""
 
-#: spyderlib/plugins/history.py:272
+#: spyderlib/plugins/history.py:274
 msgid "History"
 msgstr ""
 
-#: spyderlib/plugins/history.py:273
+#: spyderlib/plugins/history.py:275
 msgid "Maximum entries"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:56
+#: spyderlib/plugins/inspector.py:58
 msgid "Rich text help on the Object Inspector"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:120
+#: spyderlib/plugins/inspector.py:125
 msgid "Plain text font style"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:123
+#: spyderlib/plugins/inspector.py:128
 msgid "Rich text font style"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:126
+#: spyderlib/plugins/inspector.py:131
 msgid "Automatic connections"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:127
+#: spyderlib/plugins/inspector.py:132
 msgid "The Object Inspector can automatically show an object's help information after a left parenthesis is written next to it. Below you can decide to which plugin you want to connect it to turn on this feature."
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:139
+#: spyderlib/plugins/inspector.py:144
 msgid ""
 "This feature requires the Rope or Jedi libraries.\n"
 "It seems you don't have either installed."
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:142
+#: spyderlib/plugins/inspector.py:147
 msgid "Python Console"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:144
+#: spyderlib/plugins/inspector.py:149
 msgid "IPython Console"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:156
+#: spyderlib/plugins/inspector.py:161
 msgid "Additional features"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:157
+#: spyderlib/plugins/inspector.py:162
 msgid "Render mathematical equations"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:163
+#: spyderlib/plugins/inspector.py:168
 msgid "This feature requires Sphinx 1.1 or superior."
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:165
+#: spyderlib/plugins/inspector.py:170
 msgid "Sphinx %s is currently installed."
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:357
+#: spyderlib/plugins/inspector.py:373
 msgid "No further documentation available"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:396
+#: spyderlib/plugins/inspector.py:412
 msgid "Source"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:412 spyderlib/widgets/dicteditor.py:173
+#: spyderlib/plugins/inspector.py:427 spyderlib/widgets/dicteditor.py:173
 msgid "Object"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:428
+#: spyderlib/plugins/inspector.py:442
 msgid "Plain Text"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:432
+#: spyderlib/plugins/inspector.py:446
 msgid "Show Source"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:436
+#: spyderlib/plugins/inspector.py:450
 msgid "Rich Text"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:446
+#: spyderlib/plugins/inspector.py:460
 msgid "Automatic import"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:506 spyderlib/plugins/inspector.py:954
+#: spyderlib/plugins/inspector.py:520 spyderlib/plugins/inspector.py:983
 msgid "Object inspector"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:725
+#: spyderlib/plugins/inspector.py:740
 msgid "Here you can get help of any object by pressing %s in front of it, either on the Editor or the Console.%sHelp can also be shown automatically after writing a left parenthesis next to an object. You can activate this behavior in %s."
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:731
+#: spyderlib/plugins/inspector.py:746
 msgid "Preferences > Object Inspector"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:733
+#: spyderlib/plugins/inspector.py:753
 msgid "Usage"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:734
+#: spyderlib/plugins/inspector.py:754
 msgid "New to Spyder? Read our"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:735
+#: spyderlib/plugins/inspector.py:755
 msgid "tutorial"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:742
+#: spyderlib/plugins/inspector.py:762
 msgid "Please consider installing Sphinx to get documentation rendered in rich text."
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:913
+#: spyderlib/plugins/inspector.py:939
 msgid "Lock"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:913
+#: spyderlib/plugins/inspector.py:939
 msgid "Unlock"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:955
+#: spyderlib/plugins/inspector.py:984
 msgid "The following error occured when calling <b>Sphinx %s</b>. <br>Incompatible Sphinx version or doc string decoding failed.<br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/plugins/inspector.py:999
+#: spyderlib/plugins/inspector.py:1028
 msgid "No source code available."
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:61
+#: spyderlib/plugins/ipythonconsole.py:62
 msgid "Symbolic mathematics in the IPython Console"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:110
+#: spyderlib/plugins/ipythonconsole.py:111
 msgid "The authenticity of host <b>%s</b> can't be established. Are you sure you want to continue connecting?"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:122
+#: spyderlib/plugins/ipythonconsole.py:123
 msgid "The authenticity of the host can't be established"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:129
+#: spyderlib/plugins/ipythonconsole.py:130
 msgid "Tunnel '%s' failed to start"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:134
+#: spyderlib/plugins/ipythonconsole.py:135
 msgid "Could not connect to remote host"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:150
-#: spyderlib/plugins/ipythonconsole.py:665
+#: spyderlib/plugins/ipythonconsole.py:151
+#: spyderlib/plugins/ipythonconsole.py:689
 msgid "IPython console"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:162
+#: spyderlib/plugins/ipythonconsole.py:163
 msgid "Display initial banner"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:163
+#: spyderlib/plugins/ipythonconsole.py:164
 msgid ""
 "This option lets you hide the message shown at\n"
 "the top of the console when it's opened."
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:165
-msgid "Use a completion widget"
-msgstr ""
-
-#: spyderlib/plugins/ipythonconsole.py:167
-msgid "Use a widget instead of plain text output for tab completion"
-msgstr ""
-
-#: spyderlib/plugins/ipythonconsole.py:169
+#: spyderlib/plugins/ipythonconsole.py:166
 msgid "Use a pager to display additional text inside the console"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:171
+#: spyderlib/plugins/ipythonconsole.py:168
 msgid ""
 "Useful if you don't want to fill the console with long help or completion texts.\n"
 "Note: Use the Q key to get out of the pager."
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:176
+#: spyderlib/plugins/ipythonconsole.py:173
 msgid "Ask for confirmation before closing"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:189
+#: spyderlib/plugins/ipythonconsole.py:183
+msgid "Completion Type"
+msgstr ""
+
+#: spyderlib/plugins/ipythonconsole.py:184
+msgid "Decide what type of completion to use"
+msgstr ""
+
+#: spyderlib/plugins/ipythonconsole.py:187
+msgid "Completion:"
+msgstr ""
+
+#: spyderlib/plugins/ipythonconsole.py:196
 msgid "Light background"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:191
+#: spyderlib/plugins/ipythonconsole.py:198
 msgid "Dark background"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:201
+#: spyderlib/plugins/ipythonconsole.py:208
 msgid "Buffer:  "
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:203
+#: spyderlib/plugins/ipythonconsole.py:210
 msgid ""
 "Set the maximum number of lines of text shown in the\n"
 "console before truncation. Specifying -1 disables it\n"
 "(not recommended!)"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:212
+#: spyderlib/plugins/ipythonconsole.py:219
 msgid "Support for graphics (Matplotlib)"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:213
+#: spyderlib/plugins/ipythonconsole.py:220
 msgid "Activate support"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:214
+#: spyderlib/plugins/ipythonconsole.py:221
 msgid "Automatically load Pylab and NumPy modules"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:217
+#: spyderlib/plugins/ipythonconsole.py:224
 msgid ""
 "This lets you load graphics support without importing \n"
 "the commands to do plots. Useful to work with other\n"
@@ -1720,329 +1741,333 @@ msgid ""
 "GUIs with Spyder."
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:236
+#: spyderlib/plugins/ipythonconsole.py:242
 msgid ""
 "This feature requires the Matplotlib library.\n"
 "It seems you don't have it installed."
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:241
+#: spyderlib/plugins/ipythonconsole.py:247
 msgid "Inline"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:242
+#: spyderlib/plugins/ipythonconsole.py:248
 msgid "Automatic"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:243
+#: spyderlib/plugins/ipythonconsole.py:249
 msgid "Graphics backend"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:244
+#: spyderlib/plugins/ipythonconsole.py:250
 msgid "Decide how graphics are going to be displayed in the console. If unsure, please select <b>%s</b> to put graphics inside the console or <b>%s</b> to interact with them (through zooming and panning) in a separate window."
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:264
-msgid "Backend:"
-msgstr ""
-
-#: spyderlib/plugins/ipythonconsole.py:266
-msgid "This option will be applied the next time a console is opened."
-msgstr ""
-
-#: spyderlib/plugins/ipythonconsole.py:278
+#: spyderlib/plugins/ipythonconsole.py:283
 msgid "Inline backend"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:279
+#: spyderlib/plugins/ipythonconsole.py:284
 msgid "Decide how to render the figures created by this backend"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:283
+#: spyderlib/plugins/ipythonconsole.py:288
 msgid "Format:"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:286
+#: spyderlib/plugins/ipythonconsole.py:291
 msgid "Resolution:"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:286
+#: spyderlib/plugins/ipythonconsole.py:291
 msgid "dpi"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:288
+#: spyderlib/plugins/ipythonconsole.py:293
 msgid "Only used when the format is PNG. Default is 72"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:291
+#: spyderlib/plugins/ipythonconsole.py:296
 msgid "Width:"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:291
-#: spyderlib/plugins/ipythonconsole.py:295
+#: spyderlib/plugins/ipythonconsole.py:296
+#: spyderlib/plugins/ipythonconsole.py:300
 msgid "inches"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:293
+#: spyderlib/plugins/ipythonconsole.py:298
 msgid "Default is 6"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:295
+#: spyderlib/plugins/ipythonconsole.py:300
 msgid "Height:"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:297
+#: spyderlib/plugins/ipythonconsole.py:302
 msgid "Default is 4"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:312
+#: spyderlib/plugins/ipythonconsole.py:328 spyderlib/tour.py:552
 msgid "Run code"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:313
+#: spyderlib/plugins/ipythonconsole.py:329
 msgid "You can run several lines of code when a console is started. Please introduce each one separated by commas, for example:<br><i>import os, import sys</i>"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:319
+#: spyderlib/plugins/ipythonconsole.py:335
 msgid "Lines:"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:328
+#: spyderlib/plugins/ipythonconsole.py:344
 msgid "Run a file"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:329
+#: spyderlib/plugins/ipythonconsole.py:345
 msgid "You can also run a whole file at startup instead of just some lines (This is similar to have a PYTHONSTARTUP file)."
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:333
+#: spyderlib/plugins/ipythonconsole.py:349
 msgid "Use the following file:"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:348
+#: spyderlib/plugins/ipythonconsole.py:363
 msgid "Greedy completion"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:349
+#: spyderlib/plugins/ipythonconsole.py:364
 msgid "Enable <tt>Tab</tt> completion on elements of lists, results of function calls, etc, <i>without</i> assigning them to a variable.<br>For example, you can get completions on things like <tt>li[0].<Tab></tt> or <tt>ins.meth().<Tab></tt>"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:357
+#: spyderlib/plugins/ipythonconsole.py:372
 msgid "Use the greedy completer"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:368
+#: spyderlib/plugins/ipythonconsole.py:383
 msgid "Autocall"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:369
+#: spyderlib/plugins/ipythonconsole.py:384
 msgid "Autocall makes IPython automatically call any callable object even if you didn't type explicit parentheses.<br>For example, if you type <i>str 43</i> it becomes <i>str(43)</i> automatically."
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:376
+#: spyderlib/plugins/ipythonconsole.py:391
 msgid "Smart"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:377
+#: spyderlib/plugins/ipythonconsole.py:392
 msgid "Full"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:378
+#: spyderlib/plugins/ipythonconsole.py:393
 msgid "Off"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:380
+#: spyderlib/plugins/ipythonconsole.py:395
 msgid "Autocall:  "
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:381
+#: spyderlib/plugins/ipythonconsole.py:396
 msgid "On <b>%s</b> mode, Autocall is not applied if there are no arguments after the callable. On <b>%s</b> mode, all callable objects are automatically called (even if no arguments are present)."
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:393
+#: spyderlib/plugins/ipythonconsole.py:408
 msgid "Symbolic Mathematics"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:394
+#: spyderlib/plugins/ipythonconsole.py:409
 msgid "Perfom symbolic operations in the console (e.g. integrals, derivatives, vector calculus, etc) and get the outputs in a beautifully printed style."
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:399
+#: spyderlib/plugins/ipythonconsole.py:414
 msgid "Use symbolic math"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:400
+#: spyderlib/plugins/ipythonconsole.py:415
 msgid "This option loads the Sympy library to work with.<br>Please refer to its documentation to learn how to use it."
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:413
+#: spyderlib/plugins/ipythonconsole.py:428
 msgid ""
 "This feature requires the Sympy library.\n"
 "It seems you don't have it installed."
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:418
+#: spyderlib/plugins/ipythonconsole.py:433
 msgid "Prompts"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:419
+#: spyderlib/plugins/ipythonconsole.py:434
 msgid "Modify how Input and Output prompts are shown in the console."
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:422
+#: spyderlib/plugins/ipythonconsole.py:437
 msgid "Input prompt:"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:424
+#: spyderlib/plugins/ipythonconsole.py:439
 msgid "Default is<br>In [<span class=\"in-prompt-number\">%i</span>]:"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:428
+#: spyderlib/plugins/ipythonconsole.py:443
 msgid "Output prompt:"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:430
+#: spyderlib/plugins/ipythonconsole.py:445
 msgid "Default is<br>Out[<span class=\"out-prompt-number\">%i</span>]:"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:446
-msgid "Graphics"
-msgstr ""
-
-#: spyderlib/plugins/ipythonconsole.py:448
-#: spyderlib/plugins/workingdirectory.py:42
+#: spyderlib/plugins/ipythonconsole.py:467
+#: spyderlib/plugins/workingdirectory.py:44
 msgid "Startup"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:450
+#: spyderlib/plugins/ipythonconsole.py:469
 msgid "Advanced Settings"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:462
-#: spyderlib/plugins/ipythonconsole.py:725
+#: spyderlib/plugins/ipythonconsole.py:481
+#: spyderlib/plugins/ipythonconsole.py:749
 msgid "Connect to an existing kernel"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:464
+#: spyderlib/plugins/ipythonconsole.py:483
 msgid "Please enter the connection info of the kernel you want to connect to. For that you can either select its JSON connection file using the <tt>Browse</tt> button, or write directly its id, in case it's a local kernel (for example <tt>kernel-3764.json</tt> or just <tt>3764</tt>)."
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:475
+#: spyderlib/plugins/ipythonconsole.py:494
 msgid "Connection info:"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:477
+#: spyderlib/plugins/ipythonconsole.py:496
 msgid "Path to connection file or kernel id"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:479
-#: spyderlib/plugins/ipythonconsole.py:497
+#: spyderlib/plugins/ipythonconsole.py:498
+#: spyderlib/plugins/ipythonconsole.py:515
 msgid "Browse"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:489
+#: spyderlib/plugins/ipythonconsole.py:507
 msgid "This is a remote kernel"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:493
+#: spyderlib/plugins/ipythonconsole.py:511
 msgid "username at hostname:port"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:496
+#: spyderlib/plugins/ipythonconsole.py:514
 msgid "Path to ssh key file"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:505
+#: spyderlib/plugins/ipythonconsole.py:523
 msgid "Password or ssh key passphrase"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:509
+#: spyderlib/plugins/ipythonconsole.py:527
 msgid "Host name"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:510
+#: spyderlib/plugins/ipythonconsole.py:528
 msgid "Ssh key"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:511
+#: spyderlib/plugins/ipythonconsole.py:529
 msgid "Password"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:540
+#: spyderlib/plugins/ipythonconsole.py:558
 msgid "Open IPython connection file"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:546
+#: spyderlib/plugins/ipythonconsole.py:564
 msgid "Select ssh key"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:713
+#: spyderlib/plugins/ipythonconsole.py:737
 msgid "Open an &IPython console"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:716
+#: spyderlib/plugins/ipythonconsole.py:740
 msgid "Use %s+T when the console is selected to open a new one"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:719
+#: spyderlib/plugins/ipythonconsole.py:743
 msgid "Open a new console"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:726
+#: spyderlib/plugins/ipythonconsole.py:750
 msgid "Open a new IPython console connected to an existing kernel"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:809
+#: spyderlib/plugins/ipythonconsole.py:833
 msgid "No IPython console is currently available to run <b>%s</b>.<br><br>Please open a new one and try again."
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:950
+#: spyderlib/plugins/ipythonconsole.py:968
 msgid "Do you want to close all other consoles connected to the same kernel as this one?"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:1032
+#: spyderlib/plugins/ipythonconsole.py:1050
 msgid "Connection error"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:1033
+#: spyderlib/plugins/ipythonconsole.py:1051
 msgid ""
 "Could not open ssh tunnel. The error was:\n"
 "\n"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:1069
+#: spyderlib/plugins/ipythonconsole.py:1088
 msgid "IPython"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:1070
+#: spyderlib/plugins/ipythonconsole.py:1089
 msgid "Unable to connect to IPython <b>%s"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:1121
+#: spyderlib/plugins/ipythonconsole.py:1140
 msgid "Are you sure you want to restart the kernel?"
 msgstr ""
 
-#: spyderlib/plugins/ipythonconsole.py:1123
+#: spyderlib/plugins/ipythonconsole.py:1142
 msgid "Restart kernel?"
 msgstr ""
 
-#: spyderlib/plugins/onlinehelp.py:67
+#: spyderlib/plugins/layoutdialog.py:174
+msgid "Move Up"
+msgstr ""
+
+#: spyderlib/plugins/layoutdialog.py:175
+msgid "Move Down"
+msgstr ""
+
+#: spyderlib/plugins/layoutdialog.py:176
+msgid "Delete Layout"
+msgstr ""
+
+#: spyderlib/plugins/layoutdialog.py:180
+msgid "Layout Dispay and Order"
+msgstr ""
+
+#: spyderlib/plugins/onlinehelp.py:68
 msgid "Online help"
 msgstr ""
 
-#: spyderlib/plugins/outlineexplorer.py:47
-#: spyderlib/widgets/editortools.py:194
+#: spyderlib/plugins/outlineexplorer.py:48
+#: spyderlib/widgets/editortools.py:195
 msgid "Outline"
 msgstr ""
 
-#: spyderlib/plugins/projectexplorer.py:41
-#: spyderlib/widgets/projectexplorer.py:1137
-#: spyderlib/widgets/projectexplorer.py:1151
+#: spyderlib/plugins/projectexplorer.py:53
+#: spyderlib/widgets/projectexplorer.py:1150
+#: spyderlib/widgets/projectexplorer.py:1164
 msgid "Project explorer"
 msgstr ""
 
-#: spyderlib/plugins/projectexplorer.py:52
-#: spyderlib/widgets/projectexplorer.py:545
+#: spyderlib/plugins/projectexplorer.py:64
+#: spyderlib/widgets/projectexplorer.py:549
 msgid "New project..."
 msgstr ""
 
@@ -2062,119 +2087,153 @@ msgstr ""
 msgid "Always show %s on a first file run"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:153
+#: spyderlib/plugins/runconfig.py:159
 msgid "General settings"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:156 spyderlib/plugins/runconfig.py:201
+#: spyderlib/plugins/runconfig.py:162 spyderlib/plugins/runconfig.py:208
 msgid "Command line options:"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:163
+#: spyderlib/plugins/runconfig.py:168
 msgid "Working directory:"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:189
+#: spyderlib/plugins/runconfig.py:180 spyderlib/plugins/runconfig.py:491
+msgid "Enter debugging mode when errors appear during execution"
+msgstr ""
+
+#: spyderlib/plugins/runconfig.py:196 spyderlib/plugins/runconfig.py:501
 msgid "Dedicated Python console"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:194
+#: spyderlib/plugins/runconfig.py:200 spyderlib/plugins/runconfig.py:503
 msgid "Interact with the Python console after execution"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:198
+#: spyderlib/plugins/runconfig.py:204
 msgid "Show warning when killing running process"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:207
+#: spyderlib/plugins/runconfig.py:213
 msgid "<b>-u</b> is added to the other options you set here"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:218
+#: spyderlib/plugins/runconfig.py:223
 msgid "this dialog"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:276
+#: spyderlib/plugins/runconfig.py:282
 msgid "Run configuration"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:277
+#: spyderlib/plugins/runconfig.py:283
 msgid "The following working directory is not valid:<br><b>%s</b>"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:353
+#: spyderlib/plugins/runconfig.py:361
 msgid "Run settings for %s"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:384
+#: spyderlib/plugins/runconfig.py:393
 msgid "Select a run configuration:"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:414 spyderlib/plugins/runconfig.py:439
+#: spyderlib/plugins/runconfig.py:422 spyderlib/plugins/runconfig.py:447
 msgid "Run Settings"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:441
+#: spyderlib/plugins/runconfig.py:449
 msgid "The following are the default <i>%s</i>. These options may be overriden using the <b>%s</b> dialog box (see the <b>%s</b> menu)"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:465
-#: spyderlib/widgets/externalshell/pythonshell.py:297
-msgid "Working directory"
-msgstr ""
-
-#: spyderlib/plugins/runconfig.py:467
+#: spyderlib/plugins/runconfig.py:475
 msgid "Default working directory is:"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:469
+#: spyderlib/plugins/runconfig.py:477
 msgid "the script directory"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:472 spyderlib/plugins/workingdirectory.py:54
+#: spyderlib/plugins/runconfig.py:480 spyderlib/plugins/workingdirectory.py:56
 msgid "the following directory:"
 msgstr ""
 
-#: spyderlib/plugins/runconfig.py:491
+#: spyderlib/plugins/runconfig.py:506
+msgid "Show warning when killing running processes"
+msgstr ""
+
+#: spyderlib/plugins/runconfig.py:515
 msgid "Run Settings dialog"
 msgstr ""
 
-#: spyderlib/plugins/shortcuts.py:178
-msgid "Context"
+#: spyderlib/plugins/shortcuts.py:134
+msgid ""
+"Press the new shortcut and select 'Ok': \n"
+"(Press 'Tab' once to switch focus between the shortcut entry \n"
+"and the buttons below it)"
 msgstr ""
 
-#: spyderlib/plugins/shortcuts.py:180 spyderlib/widgets/dicteditor.py:158
-msgid "Name"
+#: spyderlib/plugins/shortcuts.py:137
+msgid "Current shortcut:"
 msgstr ""
 
-#: spyderlib/plugins/shortcuts.py:182
-msgid "Mod1"
+#: spyderlib/plugins/shortcuts.py:139
+msgid "New shortcut:"
 msgstr ""
 
-#: spyderlib/plugins/shortcuts.py:184
-msgid "Mod2"
+#: spyderlib/plugins/shortcuts.py:152
+msgid "Shortcut: {0}"
 msgstr ""
 
-#: spyderlib/plugins/shortcuts.py:186
-msgid "Mod3"
+#: spyderlib/plugins/shortcuts.py:273
+msgid "Please introduce a different shortcut"
 msgstr ""
 
-#: spyderlib/plugins/shortcuts.py:188 spyderlib/widgets/dicteditor.py:169
-msgid "Key"
+#: spyderlib/plugins/shortcuts.py:310
+msgid "The new shorcut conflicts with:"
 msgstr ""
 
 #: spyderlib/plugins/shortcuts.py:321
+msgid "A compound sequence can have {break} a maximum of 4 subsequences.{break}"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:326
+msgid "Invalid key entered"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:515
+msgid "Context"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:517 spyderlib/widgets/dicteditor.py:158
+msgid "Name"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:519
+msgid "Shortcut"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:521
+msgid "Score"
+msgstr ""
+
+#: spyderlib/plugins/shortcuts.py:681
 msgid "Conflicts"
 msgstr ""
 
-#: spyderlib/plugins/shortcuts.py:322
+#: spyderlib/plugins/shortcuts.py:682
 msgid "The following conflicts have been detected:"
 msgstr ""
 
-#: spyderlib/plugins/shortcuts.py:334
+#: spyderlib/plugins/shortcuts.py:767
 msgid "Keyboard shortcuts"
 msgstr ""
 
+#: spyderlib/plugins/shortcuts.py:775
+msgid "Search: "
+msgstr ""
+
 #: spyderlib/plugins/variableexplorer.py:24
 msgid "Autorefresh"
 msgstr ""
@@ -2196,32 +2255,32 @@ msgid "Filter"
 msgstr ""
 
 #: spyderlib/plugins/variableexplorer.py:33
-#: spyderlib/widgets/externalshell/namespacebrowser.py:196
+#: spyderlib/widgets/externalshell/namespacebrowser.py:214
 msgid "Exclude private references"
 msgstr ""
 
 #: spyderlib/plugins/variableexplorer.py:34
-#: spyderlib/widgets/externalshell/namespacebrowser.py:211
+#: spyderlib/widgets/externalshell/namespacebrowser.py:229
 msgid "Exclude capitalized references"
 msgstr ""
 
 #: spyderlib/plugins/variableexplorer.py:35
-#: spyderlib/widgets/externalshell/namespacebrowser.py:204
+#: spyderlib/widgets/externalshell/namespacebrowser.py:222
 msgid "Exclude all-uppercase references"
 msgstr ""
 
 #: spyderlib/plugins/variableexplorer.py:36
-#: spyderlib/widgets/externalshell/namespacebrowser.py:219
+#: spyderlib/widgets/externalshell/namespacebrowser.py:237
 msgid "Exclude unsupported data types"
 msgstr ""
 
 #: spyderlib/plugins/variableexplorer.py:42
-#: spyderlib/widgets/dicteditor.py:702
+#: spyderlib/widgets/dicteditor.py:708
 msgid "Truncate values"
 msgstr ""
 
 #: spyderlib/plugins/variableexplorer.py:44
-#: spyderlib/widgets/dicteditor.py:706
+#: spyderlib/widgets/dicteditor.py:712
 msgid "Show arrays min/max"
 msgstr ""
 
@@ -2235,27 +2294,27 @@ msgid ""
 "This avoids transfering large amount of data between the remote process and Spyder (through the socket)."
 msgstr ""
 
-#: spyderlib/plugins/variableexplorer.py:158
+#: spyderlib/plugins/variableexplorer.py:183
 msgid "Variable explorer"
 msgstr ""
 
-#: spyderlib/plugins/workingdirectory.py:35
+#: spyderlib/plugins/workingdirectory.py:37
 msgid "The <b>global working directory</b> is the working directory for newly opened <i>consoles</i> (Python/IPython consoles and terminals), for the <i>file explorer</i>, for the <i>find in files</i> plugin and for new files created in the <i>editor</i>."
 msgstr ""
 
-#: spyderlib/plugins/workingdirectory.py:44
+#: spyderlib/plugins/workingdirectory.py:46
 msgid "At startup, the global working directory is:"
 msgstr ""
 
-#: spyderlib/plugins/workingdirectory.py:48
+#: spyderlib/plugins/workingdirectory.py:50
 msgid "the same as in last session"
 msgstr ""
 
-#: spyderlib/plugins/workingdirectory.py:50
+#: spyderlib/plugins/workingdirectory.py:52
 msgid "At startup, Spyder will restore the global directory from last session"
 msgstr ""
 
-#: spyderlib/plugins/workingdirectory.py:56
+#: spyderlib/plugins/workingdirectory.py:58
 msgid "At startup, the global working directory will be the specified path"
 msgstr ""
 
@@ -2289,16 +2348,16 @@ msgstr ""
 msgid "When saving a file"
 msgstr ""
 
-#: spyderlib/plugins/workingdirectory.py:160
+#: spyderlib/plugins/workingdirectory.py:171
 msgid "Back"
 msgstr ""
 
-#: spyderlib/plugins/workingdirectory.py:168
-#: spyderlib/widgets/explorer.py:1004 spyderlib/widgets/importwizard.py:523
+#: spyderlib/plugins/workingdirectory.py:179
+#: spyderlib/widgets/explorer.py:1021 spyderlib/widgets/importwizard.py:529
 msgid "Next"
 msgstr ""
 
-#: spyderlib/plugins/workingdirectory.py:181
+#: spyderlib/plugins/workingdirectory.py:190
 msgid ""
 "This is the working directory for newly\n"
 "opened consoles (Python/IPython consoles and\n"
@@ -2307,221 +2366,287 @@ msgid ""
 "created in the editor"
 msgstr ""
 
-#: spyderlib/plugins/workingdirectory.py:207
+#: spyderlib/plugins/workingdirectory.py:216
 msgid "Browse a working directory"
 msgstr ""
 
-#: spyderlib/plugins/workingdirectory.py:213
+#: spyderlib/plugins/workingdirectory.py:222
 msgid "Set as current console's working directory"
 msgstr ""
 
-#: spyderlib/plugins/workingdirectory.py:221
+#: spyderlib/plugins/workingdirectory.py:230
 msgid "Change to parent directory"
 msgstr ""
 
-#: spyderlib/plugins/workingdirectory.py:228
+#: spyderlib/plugins/workingdirectory.py:237
 msgid "Global working directory"
 msgstr ""
 
-#: spyderlib/spyder.py:120
+#: spyderlib/restart_app.py:129
+msgid ""
+"It was not possible to close the previous Spyder instance.\n"
+"Restart aborted."
+msgstr ""
+
+#: spyderlib/restart_app.py:131
+msgid ""
+"Spyder could not reset to factory defaults.\n"
+"Restart aborted."
+msgstr ""
+
+#: spyderlib/restart_app.py:133
+msgid ""
+"It was not possible to restart Spyder.\n"
+"Operation aborted."
+msgstr ""
+
+#: spyderlib/restart_app.py:135
+msgid "Spyder exit error"
+msgstr ""
+
+#: spyderlib/restart_app.py:136
+msgid "Spyder reset error"
+msgstr ""
+
+#: spyderlib/restart_app.py:137
+msgid "Spyder restart error"
+msgstr ""
+
+#: spyderlib/restart_app.py:161
+msgid "Closing Spyder"
+msgstr ""
+
+#: spyderlib/restart_app.py:234
+msgid "Resetting Spyder to defaults"
+msgstr ""
+
+#: spyderlib/restart_app.py:266
+msgid "Restarting"
+msgstr ""
+
+#: spyderlib/spyder.py:124
 msgid "Initializing..."
 msgstr ""
 
-#: spyderlib/spyder.py:244
+#: spyderlib/spyder.py:247
 msgid "Numpy and Scipy documentation"
 msgstr ""
 
-#: spyderlib/spyder.py:246 spyderlib/spyder.py:949
+#: spyderlib/spyder.py:249 spyderlib/spyder.py:1084
 msgid "Matplotlib documentation"
 msgstr ""
 
-#: spyderlib/spyder.py:249
+#: spyderlib/spyder.py:252
 msgid "PyQt4 Reference Guide"
 msgstr ""
 
-#: spyderlib/spyder.py:252
+#: spyderlib/spyder.py:255
 msgid "PyQt4 API Reference"
 msgstr ""
 
-#: spyderlib/spyder.py:254
+#: spyderlib/spyder.py:257
 msgid "Python(x,y)"
 msgstr ""
 
-#: spyderlib/spyder.py:256
+#: spyderlib/spyder.py:259
 msgid "WinPython"
 msgstr ""
 
-#: spyderlib/spyder.py:293
+#: spyderlib/spyder.py:305
 msgid "Reload last session"
 msgstr ""
 
-#: spyderlib/spyder.py:297
+#: spyderlib/spyder.py:309
 msgid "Load session..."
 msgstr ""
 
-#: spyderlib/spyder.py:300
+#: spyderlib/spyder.py:312
 msgid "Load Spyder session"
 msgstr ""
 
-#: spyderlib/spyder.py:302
+#: spyderlib/spyder.py:314
 msgid "Save session and quit..."
 msgstr ""
 
-#: spyderlib/spyder.py:305
+#: spyderlib/spyder.py:317
 msgid "Save current session and quit application"
 msgstr ""
 
-#: spyderlib/spyder.py:483
+#: spyderlib/spyder.py:530
 msgid "Close current pane"
 msgstr ""
 
-#: spyderlib/spyder.py:489
+#: spyderlib/spyder.py:535
+msgid "Lock panes"
+msgstr ""
+
+#: spyderlib/spyder.py:542
+msgid "Use next layout"
+msgstr ""
+
+#: spyderlib/spyder.py:546
+msgid "Use previous layout"
+msgstr ""
+
+#: spyderlib/spyder.py:555
 msgid "&Find text"
 msgstr ""
 
-#: spyderlib/spyder.py:494
+#: spyderlib/spyder.py:560
 msgid "Find &next"
 msgstr ""
 
-#: spyderlib/spyder.py:500
+#: spyderlib/spyder.py:567
 msgid "Find &previous"
 msgstr ""
 
-#: spyderlib/spyder.py:505
+#: spyderlib/spyder.py:573
 msgid "&Replace text"
 msgstr ""
 
-#: spyderlib/spyder.py:520 spyderlib/widgets/sourcecode/codeeditor.py:2268
+#: spyderlib/spyder.py:580 spyderlib/widgets/editor.py:339
+msgid "File switcher..."
+msgstr ""
+
+#: spyderlib/spyder.py:582
+msgid "Fast switch between files"
+msgstr ""
+
+#: spyderlib/spyder.py:600 spyderlib/widgets/sourcecode/codeeditor.py:2425
 msgid "Undo"
 msgstr ""
 
-#: spyderlib/spyder.py:522 spyderlib/widgets/sourcecode/codeeditor.py:2271
+#: spyderlib/spyder.py:602 spyderlib/widgets/sourcecode/codeeditor.py:2428
 msgid "Redo"
 msgstr ""
 
-#: spyderlib/spyder.py:523 spyderlib/widgets/arrayeditor.py:392
+#: spyderlib/spyder.py:604 spyderlib/widgets/arrayeditor.py:392
 #: spyderlib/widgets/dataframeeditor.py:418
-#: spyderlib/widgets/dicteditor.py:674 spyderlib/widgets/shell.py:118
-#: spyderlib/widgets/sourcecode/codeeditor.py:2277
+#: spyderlib/widgets/dicteditor.py:680 spyderlib/widgets/shell.py:126
+#: spyderlib/widgets/sourcecode/codeeditor.py:2434
 msgid "Copy"
 msgstr ""
 
-#: spyderlib/spyder.py:525 spyderlib/widgets/shell.py:114
-#: spyderlib/widgets/sourcecode/codeeditor.py:2274
+#: spyderlib/spyder.py:606 spyderlib/widgets/shell.py:122
+#: spyderlib/widgets/sourcecode/codeeditor.py:2431
 msgid "Cut"
 msgstr ""
 
-#: spyderlib/spyder.py:526 spyderlib/widgets/dicteditor.py:671
-#: spyderlib/widgets/shell.py:122
-#: spyderlib/widgets/sourcecode/codeeditor.py:2280
+#: spyderlib/spyder.py:608 spyderlib/widgets/dicteditor.py:677
+#: spyderlib/widgets/shell.py:130
+#: spyderlib/widgets/sourcecode/codeeditor.py:2437
 msgid "Paste"
 msgstr ""
 
-#: spyderlib/spyder.py:528 spyderlib/widgets/explorer.py:461
-#: spyderlib/widgets/projectexplorer.py:1003 spyderlib/widgets/shell.py:131
-#: spyderlib/widgets/sourcecode/codeeditor.py:2283
+#: spyderlib/spyder.py:610 spyderlib/widgets/explorer.py:470
+#: spyderlib/widgets/projectexplorer.py:1015 spyderlib/widgets/shell.py:139
+#: spyderlib/widgets/sourcecode/codeeditor.py:2440
 msgid "Delete"
 msgstr ""
 
-#: spyderlib/spyder.py:531 spyderlib/widgets/shell.py:135
-#: spyderlib/widgets/sourcecode/codeeditor.py:2287
+#: spyderlib/spyder.py:614 spyderlib/widgets/shell.py:143
+#: spyderlib/widgets/sourcecode/codeeditor.py:2444
 msgid "Select All"
 msgstr ""
 
-#: spyderlib/spyder.py:580
+#: spyderlib/spyder.py:664
 msgid "C&onsoles"
 msgstr ""
 
-#: spyderlib/spyder.py:586
+#: spyderlib/spyder.py:670
 msgid "&View"
 msgstr ""
 
-#: spyderlib/spyder.py:589
+#: spyderlib/spyder.py:673
 msgid "&Help"
 msgstr ""
 
-#: spyderlib/spyder.py:594
+#: spyderlib/spyder.py:678
 msgid "Welcome to Spyder!"
 msgstr ""
 
-#: spyderlib/spyder.py:599
+#: spyderlib/spyder.py:683
 msgid "Pre&ferences"
 msgstr ""
 
-#: spyderlib/spyder.py:606 spyderlib/widgets/pathmanager.py:45
-#: spyderlib/widgets/projectexplorer.py:594
+#: spyderlib/spyder.py:690 spyderlib/widgets/pathmanager.py:48
+#: spyderlib/widgets/projectexplorer.py:598
 msgid "PYTHONPATH manager"
 msgstr ""
 
-#: spyderlib/spyder.py:609
+#: spyderlib/spyder.py:693
 msgid "Python Path Manager"
 msgstr ""
 
-#: spyderlib/spyder.py:612
+#: spyderlib/spyder.py:696
 msgid "Update module names list"
 msgstr ""
 
-#: spyderlib/spyder.py:614
+#: spyderlib/spyder.py:699
 msgid "Refresh list of module names available in PYTHONPATH"
 msgstr ""
 
-#: spyderlib/spyder.py:619
+#: spyderlib/spyder.py:702
+msgid "Reset Spyder to factory defaults"
+msgstr ""
+
+#: spyderlib/spyder.py:707
 msgid "Current user environment variables..."
 msgstr ""
 
-#: spyderlib/spyder.py:621
+#: spyderlib/spyder.py:709
 msgid "Show and edit current user environment variables in Windows registry (i.e. for all sessions)"
 msgstr ""
 
-#: spyderlib/spyder.py:629 spyderlib/spyder.py:1043
+#: spyderlib/spyder.py:718 spyderlib/spyder.py:1178
 msgid "External Tools"
 msgstr ""
 
-#: spyderlib/spyder.py:633
+#: spyderlib/spyder.py:722
 msgid "Python(x,y) launcher"
 msgstr ""
 
-#: spyderlib/spyder.py:640
+#: spyderlib/spyder.py:729
 msgid "WinPython control panel"
 msgstr ""
 
-#: spyderlib/spyder.py:649
+#: spyderlib/spyder.py:738
 msgid "Qt Designer"
 msgstr ""
 
-#: spyderlib/spyder.py:654
+#: spyderlib/spyder.py:743
 msgid "Qt Linguist"
 msgstr ""
 
-#: spyderlib/spyder.py:660
+#: spyderlib/spyder.py:749
 msgid "Qt examples"
 msgstr ""
 
-#: spyderlib/spyder.py:678
+#: spyderlib/spyder.py:770
 msgid "guidata examples"
 msgstr ""
 
-#: spyderlib/spyder.py:686
+#: spyderlib/spyder.py:781
 msgid "guiqwt examples"
 msgstr ""
 
-#: spyderlib/spyder.py:691
+#: spyderlib/spyder.py:786
 msgid "Sift"
 msgstr ""
 
-#: spyderlib/spyder.py:699
+#: spyderlib/spyder.py:796
 msgid "ViTables"
 msgstr ""
 
-#: spyderlib/spyder.py:713
+#: spyderlib/spyder.py:810
 msgid "Fullscreen mode"
 msgstr ""
 
-#: spyderlib/spyder.py:725
+#: spyderlib/spyder.py:822
 msgid "Main toolbar"
 msgstr ""
 
-#: spyderlib/spyder.py:734
+#: spyderlib/spyder.py:831
 msgid ""
 "Spyder Internal Console\n"
 "\n"
@@ -2534,204 +2659,336 @@ msgid ""
 "\n"
 msgstr ""
 
-#: spyderlib/spyder.py:751
+#: spyderlib/spyder.py:848
 msgid "Loading object inspector..."
 msgstr ""
 
-#: spyderlib/spyder.py:758
+#: spyderlib/spyder.py:855
 msgid "Loading outline explorer..."
 msgstr ""
 
-#: spyderlib/spyder.py:766
+#: spyderlib/spyder.py:863
 msgid "Loading editor..."
 msgstr ""
 
-#: spyderlib/spyder.py:791
+#: spyderlib/spyder.py:874
+msgid "&Restart"
+msgstr ""
+
+#: spyderlib/spyder.py:876
+msgid "Restart"
+msgstr ""
+
+#: spyderlib/spyder.py:895
 msgid "Loading file explorer..."
 msgstr ""
 
-#: spyderlib/spyder.py:798
+#: spyderlib/spyder.py:902
 msgid "Loading history plugin..."
 msgstr ""
 
-#: spyderlib/spyder.py:809
+#: spyderlib/spyder.py:913
 msgid "Loading online help..."
 msgstr ""
 
-#: spyderlib/spyder.py:815
+#: spyderlib/spyder.py:919
 msgid "Loading project explorer..."
 msgstr ""
 
-#: spyderlib/spyder.py:826
+#: spyderlib/spyder.py:930
 msgid "Loading external console..."
 msgstr ""
 
-#: spyderlib/spyder.py:835
+#: spyderlib/spyder.py:939
 msgid "Loading namespace browser..."
 msgstr ""
 
-#: spyderlib/spyder.py:842
+#: spyderlib/spyder.py:946
 msgid "Loading IPython console..."
 msgstr ""
 
-#: spyderlib/spyder.py:853
+#: spyderlib/spyder.py:956
 msgid "Setting up main window..."
 msgstr ""
 
-#: spyderlib/spyder.py:856
+#: spyderlib/spyder.py:959
 msgid "Optional dependencies..."
 msgstr ""
 
-#: spyderlib/spyder.py:860
+#: spyderlib/spyder.py:963
 msgid "Report issue..."
 msgstr ""
 
-#: spyderlib/spyder.py:864
+#: spyderlib/spyder.py:967
 msgid "Spyder support..."
 msgstr ""
 
-#: spyderlib/spyder.py:887
+#: spyderlib/spyder.py:970
+msgid "Check for updates..."
+msgstr ""
+
+#: spyderlib/spyder.py:993
 msgid "Spyder documentation"
 msgstr ""
 
-#: spyderlib/spyder.py:889
+#: spyderlib/spyder.py:997
 msgid "Spyder tutorial"
 msgstr ""
 
-#: spyderlib/spyder.py:896
+#: spyderlib/spyder.py:1002
+msgid "Interactive tours"
+msgstr ""
+
+#: spyderlib/spyder.py:1031
 msgid "Python documentation"
 msgstr ""
 
-#: spyderlib/spyder.py:902 spyderlib/spyder.py:941
+#: spyderlib/spyder.py:1037 spyderlib/spyder.py:1076
 msgid "IPython documentation"
 msgstr ""
 
-#: spyderlib/spyder.py:903
+#: spyderlib/spyder.py:1038
 msgid "Intro to IPython"
 msgstr ""
 
-#: spyderlib/spyder.py:905
+#: spyderlib/spyder.py:1040
 msgid "Quick reference"
 msgstr ""
 
-#: spyderlib/spyder.py:907
+#: spyderlib/spyder.py:1042
 msgid "Console help"
 msgstr ""
 
-#: spyderlib/spyder.py:939
+#: spyderlib/spyder.py:1074
 msgid "Python(x,y) documentation folder"
 msgstr ""
 
-#: spyderlib/spyder.py:943
+#: spyderlib/spyder.py:1078
 msgid "guidata documentation"
 msgstr ""
 
-#: spyderlib/spyder.py:946
+#: spyderlib/spyder.py:1081
 msgid "guiqwt documentation"
 msgstr ""
 
-#: spyderlib/spyder.py:952
+#: spyderlib/spyder.py:1087
 msgid "NumPy documentation"
 msgstr ""
 
-#: spyderlib/spyder.py:954
+#: spyderlib/spyder.py:1089
 msgid "NumPy reference guide"
 msgstr ""
 
-#: spyderlib/spyder.py:956
+#: spyderlib/spyder.py:1091
 msgid "NumPy user guide"
 msgstr ""
 
-#: spyderlib/spyder.py:958
+#: spyderlib/spyder.py:1093
 msgid "SciPy documentation"
 msgstr ""
 
-#: spyderlib/spyder.py:965
+#: spyderlib/spyder.py:1100
 msgid "Installed Python modules"
 msgstr ""
 
-#: spyderlib/spyder.py:969
+#: spyderlib/spyder.py:1104
 msgid "Online documentation"
 msgstr ""
 
-#: spyderlib/spyder.py:979
+#: spyderlib/spyder.py:1116
 msgid "Qt documentation"
 msgstr ""
 
-#: spyderlib/spyder.py:985
+#: spyderlib/spyder.py:1122
 msgid "About %s..."
 msgstr ""
 
-#: spyderlib/spyder.py:1006
+#: spyderlib/spyder.py:1146
 msgid "Panes"
 msgstr ""
 
-#: spyderlib/spyder.py:1007
+#: spyderlib/spyder.py:1147
 msgid "Toolbars"
 msgstr ""
 
-#: spyderlib/spyder.py:1010
-msgid "Reset window layout"
+#: spyderlib/spyder.py:1148
+msgid "Window layouts"
+msgstr ""
+
+#: spyderlib/spyder.py:1157 spyderlib/spyder.py:1910 spyderlib/spyder.py:1911
+msgid "Show toolbars"
 msgstr ""
 
-#: spyderlib/spyder.py:1012
-msgid "Custom window layouts"
+#: spyderlib/spyder.py:1171
+msgid "Attached console window (debugging)"
 msgstr ""
 
-#: spyderlib/spyder.py:1018
-msgid "Switch to/from layout %d"
+#: spyderlib/spyder.py:1756
+msgid "Spyder Default Layout"
 msgstr ""
 
-#: spyderlib/spyder.py:1023
-msgid "Set layout %d"
+#: spyderlib/spyder.py:1774 spyderlib/spyder.py:1785
+msgid "Save current layout"
 msgstr ""
 
-#: spyderlib/spyder.py:1031
-msgid "Attached console window (debugging)"
+#: spyderlib/spyder.py:1778 spyderlib/spyder.py:1787
+msgid "Layout preferences"
 msgstr ""
 
-#: spyderlib/spyder.py:1332
+#: spyderlib/spyder.py:1782
+msgid "Reset to spyder default"
+msgstr ""
+
+#: spyderlib/spyder.py:1804
 msgid ""
 "Window layout will be reset to default settings: this affects window position, size and dockwidgets.\n"
 "Do you want to continue?"
 msgstr ""
 
-#: spyderlib/spyder.py:1350
-msgid "Quick switch layout #%d has not yet been defined."
+#: spyderlib/spyder.py:1826
+msgid "Layout <b>%s</b> will be                                                overwritten. Do you want to                                                continue?"
+msgstr ""
+
+#: spyderlib/spyder.py:1889
+msgid "Quick switch layout #%s has not yet been defined."
+msgstr ""
+
+#: spyderlib/spyder.py:1907 spyderlib/spyder.py:1908
+msgid "Hide toolbars"
 msgstr ""
 
-#: spyderlib/spyder.py:1602 spyderlib/spyder.py:1603
+#: spyderlib/spyder.py:2229 spyderlib/spyder.py:2230
 msgid "Maximize current pane"
 msgstr ""
 
-#: spyderlib/spyder.py:1606
+#: spyderlib/spyder.py:2233
 msgid "Restore current pane"
 msgstr ""
 
-#: spyderlib/spyder.py:1607
+#: spyderlib/spyder.py:2234
 msgid "Restore pane to its original size"
 msgstr ""
 
-#: spyderlib/spyder.py:1686
+#: spyderlib/spyder.py:2318
 msgid "About %s"
 msgstr ""
 
-#: spyderlib/spyder.py:1851
+#: spyderlib/spyder.py:2502
 msgid "Running an external system terminal is not supported on platform %s."
 msgstr ""
 
-#: spyderlib/spyder.py:2066
+#: spyderlib/spyder.py:2721
 msgid "Open session"
 msgstr ""
 
-#: spyderlib/spyder.py:2067 spyderlib/spyder.py:2078
+#: spyderlib/spyder.py:2722 spyderlib/spyder.py:2734
 msgid "Spyder sessions"
 msgstr ""
 
-#: spyderlib/spyder.py:2077
+#: spyderlib/spyder.py:2733
 msgid "Save session"
 msgstr ""
 
+#: spyderlib/spyder.py:2775
+msgid "Spyder will restart and reset to default settings: <br><br>Do you want to continue?"
+msgstr ""
+
+#: spyderlib/spyder.py:2871 spyderlib/widgets/helperwidgets.py:144
+msgid "Spyder updates"
+msgstr ""
+
+#: spyderlib/spyder.py:2890
+msgid "<b>Spyder %s is available!</b> <br><br>Please use your package manager to update Spyder or go to our <a href=\"%s\">Releases</a> page to download this new version. <br><br>If you are not sure how to proceed to update Spyder please refer to our  <a href=\"%s\">Installation</a> instructions."
+msgstr ""
+
+#: spyderlib/spyder.py:2902
+msgid "Spyder is up to date."
+msgstr ""
+
+#: spyderlib/tour.py:121
+msgid "Welcome to the Introduction tour"
+msgstr ""
+
+#: spyderlib/tour.py:122
+msgid "<b>Spyder</b> is a powerful Interactive Development Environment (or IDE) for the Python programming language.<br><br>Here we are going to guide you through its most important features.<br><br>Please use the arrow keys or click on the buttons below to move along the tour."
+msgstr ""
+
+#: spyderlib/tour.py:131
+msgid "The Editor"
+msgstr ""
+
+#: spyderlib/tour.py:132
+msgid "This is the pane where you write Python code before evaluating it. You can get automatic suggestions and completions while writing, by pressing the <b>Tab</b> key next to a given text.<br><br>The Editor comes with a line number area (highlighted here in red), where Spyder shows warnings and syntax errors. They can help you to detect potential problems before running the code.<br><br>You can also set debug breakpoints in the line number area, by doing a double click next to a non-e [...]
+msgstr ""
+
+#: spyderlib/tour.py:147
+msgid "The IPython console"
+msgstr ""
+
+#: spyderlib/tour.py:164
+msgid "The Variable Explorer"
+msgstr ""
+
+#: spyderlib/tour.py:165
+msgid "In this pane you can view and edit the variables generated during the execution of a program, or those entered directly in one of Spyder consoles.<br><br>As you can see, the Variable Explorer is showing the variables generated during the last step of this tour. By doing a double-click on any of them, a new window will be opened, where you can inspect and modify their contents."
+msgstr ""
+
+#: spyderlib/tour.py:177
+msgid "The Python console"
+msgstr ""
+
+#: spyderlib/tour.py:178
+msgid "You can also run your code on a Python console. These consoles are useful because they let you run a file in a console dedicated only to it.To select this behavior, please press the <b>F6</b> key.<br><br>By pressing the button below and then focusing the Variable Explorer, you will notice that Python consoles are also connected to that pane, and that the Variable Explorer only shows the variables of the currently focused console."
+msgstr ""
+
+#: spyderlib/tour.py:192
+msgid "The Object Inspector"
+msgstr ""
+
+#: spyderlib/tour.py:193
+msgid "This pane displays documentation of the functions, classes, methods or modules you are currently using in the Editor or the Consoles.<br><br>To use it, you need to press <b>Ctrl+I</b> in front of an object. If that object has some documentation associated with it, it will be displayed here."
+msgstr ""
+
+#: spyderlib/tour.py:203
+msgid "The File Explorer"
+msgstr ""
+
+#: spyderlib/tour.py:204
+msgid "This pane lets you navigate through the directories and files present in your computer.<br><br>You can also open any of these files with its corresponding application, by doing a double click on it.<br><br>There is one exception to this rule: plain-text files will always be opened in the Spyder Editor."
+msgstr ""
+
+#: spyderlib/tour.py:214
+msgid "The History Log"
+msgstr ""
+
+#: spyderlib/tour.py:215
+msgid "This pane records all commands introduced in the Python and IPython consoles."
+msgstr ""
+
+#: spyderlib/tour.py:263
+msgid "<b>Spyder</b> is an interactive development environment based on bla"
+msgstr ""
+
+#: spyderlib/tour.py:267
+msgid "Welcome to Spyder introduction tour"
+msgstr ""
+
+#: spyderlib/tour.py:268
+msgid "Spyder is an interactive development environment based on bla"
+msgstr ""
+
+#: spyderlib/tour.py:273
+msgid "Introduction tour"
+msgstr ""
+
+#: spyderlib/tour.py:274
+msgid "New features in version 3.0"
+msgstr ""
+
+#: spyderlib/tour.py:821
+msgid "Go to step: "
+msgstr ""
+
 #: spyderlib/utils/codeanalysis.py:92
 msgid "Real-time code analysis on the Editor"
 msgstr ""
@@ -2740,16 +2997,16 @@ msgstr ""
 msgid "Real-time code style analysis on the Editor"
 msgstr ""
 
-#: spyderlib/utils/environ.py:95
+#: spyderlib/utils/environ.py:96
 msgid "Module <b>pywin32 was not found</b>.<br>Please restart this Windows <i>session</i> (not the computer) for changes to take effect."
 msgstr ""
 
-#: spyderlib/utils/environ.py:108
+#: spyderlib/utils/environ.py:109
 msgid "If you accept changes, this will modify the current user environment variables directly <b>in Windows registry</b>. Use it with precautions, at your own risks.<br><br>Note that for changes to take effect, you will need to restart the parent process of this application (simply restart Spyder if you have executed it from a Windows shortcut, otherwise restart any application from which you may have executed it, like <i>Python(x,y) Home</i> for example)"
 msgstr ""
 
-#: spyderlib/utils/inspector/sphinxify.py:209
-#: spyderlib/utils/inspector/sphinxify.py:219
+#: spyderlib/utils/inspector/sphinxify.py:212
+#: spyderlib/utils/inspector/sphinxify.py:222
 msgid "It was not possible to generate rich text help for this object.</br>Please see it in plain text."
 msgstr ""
 
@@ -2761,59 +3018,59 @@ msgstr ""
 msgid "Editor's code completion, go-to-definition and help"
 msgstr ""
 
-#: spyderlib/utils/iofuncs.py:496
+#: spyderlib/utils/iofuncs.py:482
 msgid "Supported files"
 msgstr ""
 
-#: spyderlib/utils/iofuncs.py:498
+#: spyderlib/utils/iofuncs.py:484
 msgid "All files (*.*)"
 msgstr ""
 
-#: spyderlib/utils/iofuncs.py:508
+#: spyderlib/utils/iofuncs.py:494
 msgid "Spyder data files"
 msgstr ""
 
-#: spyderlib/utils/iofuncs.py:510 spyderlib/widgets/dicteditor.py:1041
+#: spyderlib/utils/iofuncs.py:496 spyderlib/widgets/dicteditor.py:1056
 msgid "NumPy arrays"
 msgstr ""
 
-#: spyderlib/utils/iofuncs.py:511
+#: spyderlib/utils/iofuncs.py:497
 msgid "NumPy zip arrays"
 msgstr ""
 
-#: spyderlib/utils/iofuncs.py:512
+#: spyderlib/utils/iofuncs.py:498
 msgid "Matlab files"
 msgstr ""
 
-#: spyderlib/utils/iofuncs.py:513
+#: spyderlib/utils/iofuncs.py:499
 msgid "CSV text files"
 msgstr ""
 
-#: spyderlib/utils/iofuncs.py:515
+#: spyderlib/utils/iofuncs.py:501
 msgid "JPEG images"
 msgstr ""
 
-#: spyderlib/utils/iofuncs.py:516
+#: spyderlib/utils/iofuncs.py:502
 msgid "PNG images"
 msgstr ""
 
-#: spyderlib/utils/iofuncs.py:517
+#: spyderlib/utils/iofuncs.py:503
 msgid "GIF images"
 msgstr ""
 
-#: spyderlib/utils/iofuncs.py:518
+#: spyderlib/utils/iofuncs.py:504
 msgid "TIFF images"
 msgstr ""
 
-#: spyderlib/utils/iofuncs.py:519 spyderlib/utils/iofuncs.py:520
+#: spyderlib/utils/iofuncs.py:505 spyderlib/utils/iofuncs.py:506
 msgid "Pickle files"
 msgstr ""
 
-#: spyderlib/utils/iofuncs.py:521
+#: spyderlib/utils/iofuncs.py:507
 msgid "JSON files"
 msgstr ""
 
-#: spyderlib/utils/iofuncs.py:540 spyderlib/utils/iofuncs.py:547
+#: spyderlib/utils/iofuncs.py:526 spyderlib/utils/iofuncs.py:533
 msgid "<b>Unsupported file type '%s'</b>"
 msgstr ""
 
@@ -2821,40 +3078,72 @@ msgstr ""
 msgid "It was not possible to run this file in an external terminal"
 msgstr ""
 
-#: spyderlib/widgets/arrayeditor.py:452 spyderlib/widgets/arrayeditor.py:485
-#: spyderlib/widgets/dataframeeditor.py:507
-#: spyderlib/widgets/dataframeeditor.py:549
+#: spyderlib/widgets/arraybuilder.py:162
+msgid ""
+"\n"
+"           <b>Numpy Array/Matrix Helper</b><br>\n"
+"           Type an array in Matlab    : <code>[1 2;3 4]</code><br>\n"
+"           or Spyder simplified syntax : <code>1 2;3 4</code>\n"
+"           <br><br>\n"
+"           Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n"
+"           <br><br>\n"
+"           <b>Hint:</b><br>\n"
+"           Use two spaces or two tabs to generate a ';'.\n"
+"           "
+msgstr ""
+
+#: spyderlib/widgets/arraybuilder.py:173
+msgid ""
+"\n"
+"           <b>Numpy Array/Matrix Helper</b><br>\n"
+"           Enter an array in the table. <br>\n"
+"           Use Tab to move between cells.\n"
+"           <br><br>\n"
+"           Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n"
+"           <br><br>\n"
+"           <b>Hint:</b><br>\n"
+"           Use two tabs at the end of a row to move to the next row.\n"
+"           "
+msgstr ""
+
+#: spyderlib/widgets/arraybuilder.py:337
+msgid "Array dimensions not valid"
+msgstr ""
+
+#: spyderlib/widgets/arrayeditor.py:453 spyderlib/widgets/arrayeditor.py:486
+#: spyderlib/widgets/dataframeeditor.py:508
+#: spyderlib/widgets/dataframeeditor.py:548
 msgid "Format"
 msgstr ""
 
-#: spyderlib/widgets/arrayeditor.py:457
-#: spyderlib/widgets/dataframeeditor.py:511
+#: spyderlib/widgets/arrayeditor.py:458
+#: spyderlib/widgets/dataframeeditor.py:512
 msgid "Resize"
 msgstr ""
 
-#: spyderlib/widgets/arrayeditor.py:486
-#: spyderlib/widgets/dataframeeditor.py:550
+#: spyderlib/widgets/arrayeditor.py:487
+#: spyderlib/widgets/dataframeeditor.py:549
 msgid "Float formatting"
 msgstr ""
 
-#: spyderlib/widgets/arrayeditor.py:493
-#: spyderlib/widgets/dataframeeditor.py:558 spyderlib/widgets/explorer.py:578
-#: spyderlib/widgets/explorer.py:681
-#: spyderlib/widgets/externalshell/pythonshell.py:537
-#: spyderlib/widgets/externalshell/systemshell.py:93
+#: spyderlib/widgets/arrayeditor.py:494
+#: spyderlib/widgets/dataframeeditor.py:557 spyderlib/widgets/explorer.py:587
+#: spyderlib/widgets/explorer.py:689
+#: spyderlib/widgets/externalshell/pythonshell.py:553
+#: spyderlib/widgets/externalshell/systemshell.py:99
 msgid "Error"
 msgstr ""
 
-#: spyderlib/widgets/arrayeditor.py:494
-#: spyderlib/widgets/dataframeeditor.py:559
+#: spyderlib/widgets/arrayeditor.py:495
+#: spyderlib/widgets/dataframeeditor.py:558
 msgid "Format (%s) is incorrect"
 msgstr ""
 
-#: spyderlib/widgets/arrayeditor.py:528
+#: spyderlib/widgets/arrayeditor.py:529
 msgid "Array is empty"
 msgstr ""
 
-#: spyderlib/widgets/arrayeditor.py:531
+#: spyderlib/widgets/arrayeditor.py:532
 msgid "Arrays with more than 3 dimensions are not supported"
 msgstr ""
 
@@ -2878,7 +3167,7 @@ msgstr ""
 msgid "NumPy array"
 msgstr ""
 
-#: spyderlib/widgets/arrayeditor.py:556 spyderlib/widgets/arrayeditor.py:713
+#: spyderlib/widgets/arrayeditor.py:556 spyderlib/widgets/arrayeditor.py:710
 msgid "Array editor"
 msgstr ""
 
@@ -2886,45 +3175,45 @@ msgstr ""
 msgid "read only"
 msgstr ""
 
-#: spyderlib/widgets/arrayeditor.py:589
+#: spyderlib/widgets/arrayeditor.py:588
 msgid "Record array fields:"
 msgstr ""
 
-#: spyderlib/widgets/arrayeditor.py:601
+#: spyderlib/widgets/arrayeditor.py:600
 msgid "Data"
 msgstr ""
 
-#: spyderlib/widgets/arrayeditor.py:601
+#: spyderlib/widgets/arrayeditor.py:600
 msgid "Mask"
 msgstr ""
 
-#: spyderlib/widgets/arrayeditor.py:601
+#: spyderlib/widgets/arrayeditor.py:600
 msgid "Masked data"
 msgstr ""
 
-#: spyderlib/widgets/arrayeditor.py:614
+#: spyderlib/widgets/arrayeditor.py:611
 msgid "Axis:"
 msgstr ""
 
-#: spyderlib/widgets/arrayeditor.py:619
+#: spyderlib/widgets/arrayeditor.py:616
 msgid "Index:"
 msgstr ""
 
-#: spyderlib/widgets/arrayeditor.py:633
+#: spyderlib/widgets/arrayeditor.py:629
 msgid "<u>Warning</u>: changes are applied separately"
 msgstr ""
 
-#: spyderlib/widgets/arrayeditor.py:634
+#: spyderlib/widgets/arrayeditor.py:630
 msgid "For performance reasons, changes applied to masked array won't be reflected in array's data (and vice-versa)."
 msgstr ""
 
-#: spyderlib/widgets/browser.py:30
-#: spyderlib/widgets/sourcecode/codeeditor.py:2311
+#: spyderlib/widgets/browser.py:31
+#: spyderlib/widgets/sourcecode/codeeditor.py:2468
 msgid "Zoom out"
 msgstr ""
 
-#: spyderlib/widgets/browser.py:33
-#: spyderlib/widgets/sourcecode/codeeditor.py:2308
+#: spyderlib/widgets/browser.py:34
+#: spyderlib/widgets/sourcecode/codeeditor.py:2465
 msgid "Zoom in"
 msgstr ""
 
@@ -2932,31 +3221,31 @@ msgstr ""
 msgid "Home"
 msgstr ""
 
-#: spyderlib/widgets/browser.py:171
+#: spyderlib/widgets/browser.py:166
 msgid "Find text"
 msgstr ""
 
-#: spyderlib/widgets/browser.py:190
+#: spyderlib/widgets/browser.py:184
 msgid "Address:"
 msgstr ""
 
-#: spyderlib/widgets/browser.py:225
+#: spyderlib/widgets/browser.py:220
 msgid "Unable to load page"
 msgstr ""
 
-#: spyderlib/widgets/comboboxes.py:117
+#: spyderlib/widgets/comboboxes.py:118
 msgid "Press enter to validate this entry"
 msgstr ""
 
-#: spyderlib/widgets/comboboxes.py:118
+#: spyderlib/widgets/comboboxes.py:119
 msgid "This entry is incorrect"
 msgstr ""
 
-#: spyderlib/widgets/comboboxes.py:171
+#: spyderlib/widgets/comboboxes.py:174
 msgid "Press enter to validate this path"
 msgstr ""
 
-#: spyderlib/widgets/comboboxes.py:172
+#: spyderlib/widgets/comboboxes.py:175
 msgid ""
 "This path is incorrect.\n"
 "Enter a correct directory path,\n"
@@ -2983,7 +3272,7 @@ msgstr ""
 msgid "To str"
 msgstr ""
 
-#: spyderlib/widgets/dataframeeditor.py:489
+#: spyderlib/widgets/dataframeeditor.py:490
 msgid "%s editor"
 msgstr ""
 
@@ -2991,31 +3280,31 @@ msgstr ""
 msgid "Column min/max"
 msgstr ""
 
-#: spyderlib/widgets/dependencies.py:60
+#: spyderlib/widgets/dependencies.py:59
 msgid " Required "
 msgstr ""
 
-#: spyderlib/widgets/dependencies.py:60
+#: spyderlib/widgets/dependencies.py:59
 msgid "Module"
 msgstr ""
 
-#: spyderlib/widgets/dependencies.py:61
+#: spyderlib/widgets/dependencies.py:60
 msgid " Installed "
 msgstr ""
 
-#: spyderlib/widgets/dependencies.py:61
+#: spyderlib/widgets/dependencies.py:60
 msgid "Provided features"
 msgstr ""
 
-#: spyderlib/widgets/dependencies.py:127
+#: spyderlib/widgets/dependencies.py:130
 msgid "Optional Dependencies"
 msgstr ""
 
-#: spyderlib/widgets/dependencies.py:134
+#: spyderlib/widgets/dependencies.py:137
 msgid "Spyder depends on several Python modules to provide additional functionality for its plugins. The table below shows the required and installed versions (if any) of all of them.<br><br>Although Spyder can work without any of these modules, it's strongly recommended that at least you try to install <b>%s</b> and <b>%s</b> to have a much better experience."
 msgstr ""
 
-#: spyderlib/widgets/dependencies.py:149
+#: spyderlib/widgets/dependencies.py:152
 msgid "Copy to clipboard"
 msgstr ""
 
@@ -3035,6 +3324,10 @@ msgstr ""
 msgid "Dictionary"
 msgstr ""
 
+#: spyderlib/widgets/dicteditor.py:169
+msgid "Key"
+msgstr ""
+
 #: spyderlib/widgets/dicteditor.py:175
 msgid "Attribute"
 msgstr ""
@@ -3043,552 +3336,532 @@ msgstr ""
 msgid "elements"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:355
+#: spyderlib/widgets/dicteditor.py:356
 msgid "Size"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:355
+#: spyderlib/widgets/dicteditor.py:356
 msgid "Type"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:355
+#: spyderlib/widgets/dicteditor.py:356
 msgid "Value"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:450
+#: spyderlib/widgets/dicteditor.py:453
 msgid ""
 "Opening this variable can be slow\n"
 "\n"
 "Do you want to continue anyway?"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:458 spyderlib/widgets/dicteditor.py:607
+#: spyderlib/widgets/dicteditor.py:461 spyderlib/widgets/dicteditor.py:612
 msgid "Edit item"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:459
+#: spyderlib/widgets/dicteditor.py:462
 msgid "<b>Unable to retrieve data.</b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:608
+#: spyderlib/widgets/dicteditor.py:613
 msgid "<b>Unable to assign data to item.</b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:669
+#: spyderlib/widgets/dicteditor.py:675
 msgid "Resize rows to contents"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:677 spyderlib/widgets/explorer.py:236
+#: spyderlib/widgets/dicteditor.py:683 spyderlib/widgets/explorer.py:242
 msgid "Edit"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:680 spyderlib/widgets/dicteditor.py:1012
-#: spyderlib/widgets/dicteditor.py:1028
+#: spyderlib/widgets/dicteditor.py:686 spyderlib/widgets/dicteditor.py:1025
+#: spyderlib/widgets/dicteditor.py:1042
 msgid "Plot"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:684
+#: spyderlib/widgets/dicteditor.py:690
 msgid "Histogram"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:688
+#: spyderlib/widgets/dicteditor.py:694
 msgid "Show image"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:692 spyderlib/widgets/dicteditor.py:1035
+#: spyderlib/widgets/dicteditor.py:698 spyderlib/widgets/dicteditor.py:1050
 msgid "Save array"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:696 spyderlib/widgets/dicteditor.py:976
-#: spyderlib/widgets/dicteditor.py:984
+#: spyderlib/widgets/dicteditor.py:702 spyderlib/widgets/dicteditor.py:989
+#: spyderlib/widgets/dicteditor.py:997
 msgid "Insert"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:699 spyderlib/widgets/dicteditor.py:929
+#: spyderlib/widgets/dicteditor.py:705 spyderlib/widgets/dicteditor.py:939
 msgid "Remove"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:710 spyderlib/widgets/dicteditor.py:946
-#: spyderlib/widgets/explorer.py:524 spyderlib/widgets/explorer.py:532
-#: spyderlib/widgets/explorer.py:544
+#: spyderlib/widgets/dicteditor.py:716 spyderlib/widgets/dicteditor.py:956
+#: spyderlib/widgets/explorer.py:532 spyderlib/widgets/explorer.py:540
+#: spyderlib/widgets/explorer.py:551
 msgid "Rename"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:713
+#: spyderlib/widgets/dicteditor.py:719
 msgid "Duplicate"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:927
+#: spyderlib/widgets/dicteditor.py:937
 msgid "Do you want to remove selected item?"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:928
+#: spyderlib/widgets/dicteditor.py:938
 msgid "Do you want to remove all selected items?"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:946 spyderlib/widgets/dicteditor.py:976
+#: spyderlib/widgets/dicteditor.py:956 spyderlib/widgets/dicteditor.py:989
 msgid "Key:"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:984
+#: spyderlib/widgets/dicteditor.py:997
 msgid "Value:"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:1000
+#: spyderlib/widgets/dicteditor.py:1013
 msgid "Import error"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:1001
+#: spyderlib/widgets/dicteditor.py:1014
 msgid "Please install <b>matplotlib</b> or <b>guiqwt</b>."
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:1013
+#: spyderlib/widgets/dicteditor.py:1026
 msgid "<b>Unable to plot data.</b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:1029
+#: spyderlib/widgets/dicteditor.py:1043
 msgid "<b>Unable to show image.</b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:1051
+#: spyderlib/widgets/dicteditor.py:1066
 msgid "<b>Unable to save array</b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:1068
+#: spyderlib/widgets/dicteditor.py:1085
 msgid "Clipboard contents"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:1082
+#: spyderlib/widgets/dicteditor.py:1100
 msgid "Import from clipboard"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:1084
+#: spyderlib/widgets/dicteditor.py:1102
 msgid "Empty clipboard"
 msgstr ""
 
-#: spyderlib/widgets/dicteditor.py:1085
+#: spyderlib/widgets/dicteditor.py:1103
 msgid "Nothing to be imported from clipboard."
 msgstr ""
 
-#: spyderlib/widgets/dicteditorutils.py:59
+#: spyderlib/widgets/dicteditorutils.py:60
 msgid "View and edit DataFrames and Series in the Variable Explorer"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:67 spyderlib/widgets/editor.py:417
-msgid "File list management"
-msgstr ""
-
-#: spyderlib/widgets/editor.py:71
-msgid "Filter:"
-msgstr ""
-
-#: spyderlib/widgets/editor.py:76
-msgid "(press <b>Enter</b> to edit file)"
-msgstr ""
-
-#: spyderlib/widgets/editor.py:91
-msgid "&Edit file"
-msgstr ""
-
-#: spyderlib/widgets/editor.py:100
-msgid "&Close file"
-msgstr ""
-
-#: spyderlib/widgets/editor.py:108
-msgid "Hint: press <b>Alt</b> to show accelerators"
-msgstr ""
-
-#: spyderlib/widgets/editor.py:420
+#: spyderlib/widgets/editor.py:342
 msgid "Copy path to clipboard"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:990
+#: spyderlib/widgets/editor.py:906
 msgid "Temporary file"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:1087
+#: spyderlib/widgets/editor.py:1003
 msgid "New window"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:1088
+#: spyderlib/widgets/editor.py:1004
 msgid "Create a new editor window"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:1091
+#: spyderlib/widgets/editor.py:1007
 msgid "Split vertically"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:1093
+#: spyderlib/widgets/editor.py:1009
 msgid "Split vertically this editor window"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:1095
+#: spyderlib/widgets/editor.py:1011
 msgid "Split horizontally"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:1097
+#: spyderlib/widgets/editor.py:1013
 msgid "Split horizontally this editor window"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:1099
+#: spyderlib/widgets/editor.py:1015
 msgid "Close this panel"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:1237
+#: spyderlib/widgets/editor.py:1153
 msgid "<b>%s</b> has been modified.<br>Do you want to save changes?"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:1300
+#: spyderlib/widgets/editor.py:1215
 msgid "Save"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:1301
+#: spyderlib/widgets/editor.py:1216
 msgid "<b>Unable to save script '%s'</b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:1323
+#: spyderlib/widgets/editor.py:1238
 msgid "Save Python script"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:1539
+#: spyderlib/widgets/editor.py:1452
 msgid "<b>%s</b> is unavailable (this file may have been removed, moved or renamed outside Spyder).<br>Do you want to close it?"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:1559
+#: spyderlib/widgets/editor.py:1472
 msgid "<b>%s</b> has been modified outside Spyder.<br>Do you want to reload it and lose all your changes?"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:1655
+#: spyderlib/widgets/editor.py:1568
 msgid "All changes to <b>%s</b> will be lost.<br>Do you want to revert file from disk?"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:1811
+#: spyderlib/widgets/editor.py:1708
 msgid "Loading %s..."
 msgstr ""
 
-#: spyderlib/widgets/editor.py:1821
+#: spyderlib/widgets/editor.py:1718
 msgid "<b>%s</b> contains mixed end-of-line characters.<br>Spyder will fix this automatically."
 msgstr ""
 
-#: spyderlib/widgets/editor.py:2192
+#: spyderlib/widgets/editor.py:2083
 msgid "Close window"
 msgstr ""
 
-#: spyderlib/widgets/editor.py:2194
+#: spyderlib/widgets/editor.py:2085
 msgid "Close this window"
 msgstr ""
 
-#: spyderlib/widgets/editortools.py:93 spyderlib/widgets/editortools.py:129
+#: spyderlib/widgets/editortools.py:94 spyderlib/widgets/editortools.py:130
 msgid "Line %s"
 msgstr ""
 
-#: spyderlib/widgets/editortools.py:98
+#: spyderlib/widgets/editortools.py:99
 msgid "Class defined at line %s"
 msgstr ""
 
-#: spyderlib/widgets/editortools.py:106
+#: spyderlib/widgets/editortools.py:107
 msgid "Method defined at line %s"
 msgstr ""
 
-#: spyderlib/widgets/editortools.py:116
+#: spyderlib/widgets/editortools.py:117
 msgid "Function defined at line %s"
 msgstr ""
 
-#: spyderlib/widgets/editortools.py:148
+#: spyderlib/widgets/editortools.py:149
 msgid "Cell starts at line %s"
 msgstr ""
 
-#: spyderlib/widgets/editortools.py:201 spyderlib/widgets/editortools.py:536
+#: spyderlib/widgets/editortools.py:202 spyderlib/widgets/editortools.py:539
 msgid "Go to cursor position"
 msgstr ""
 
-#: spyderlib/widgets/editortools.py:204
+#: spyderlib/widgets/editortools.py:205
 msgid "Show absolute path"
 msgstr ""
 
-#: spyderlib/widgets/editortools.py:207 spyderlib/widgets/explorer.py:177
+#: spyderlib/widgets/editortools.py:208 spyderlib/widgets/explorer.py:179
 msgid "Show all files"
 msgstr ""
 
-#: spyderlib/widgets/editortools.py:210
+#: spyderlib/widgets/editortools.py:211
 msgid "Show special comments"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:173
+#: spyderlib/widgets/explorer.py:175
 msgid "Edit filename filters..."
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:186
+#: spyderlib/widgets/explorer.py:189
 msgid "Edit filename filters"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:187
+#: spyderlib/widgets/explorer.py:190
 msgid "Name filters:"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:205
+#: spyderlib/widgets/explorer.py:209
 msgid "File..."
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:208
+#: spyderlib/widgets/explorer.py:213
 msgid "Module..."
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:211
+#: spyderlib/widgets/explorer.py:217
 msgid "Folder..."
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:215
+#: spyderlib/widgets/explorer.py:221
 msgid "Package..."
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:238
+#: spyderlib/widgets/explorer.py:244
 msgid "Move..."
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:241
+#: spyderlib/widgets/explorer.py:247
 msgid "Delete..."
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:244
+#: spyderlib/widgets/explorer.py:250
 msgid "Rename..."
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:247
+#: spyderlib/widgets/explorer.py:253
 msgid "Open"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:248
-#: spyderlib/widgets/sourcecode/codeeditor.py:2299
+#: spyderlib/widgets/explorer.py:254
+#: spyderlib/widgets/sourcecode/codeeditor.py:2456
 msgid "Convert to Python script"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:271
+#: spyderlib/widgets/explorer.py:277
 msgid "Commit"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:275
+#: spyderlib/widgets/explorer.py:281
 msgid "Browse repository"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:287
+#: spyderlib/widgets/explorer.py:293
 msgid "Open command prompt here"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:289
+#: spyderlib/widgets/explorer.py:295
 msgid "Open terminal here"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:294
+#: spyderlib/widgets/explorer.py:300
 msgid "Open Python console here"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:308
+#: spyderlib/widgets/explorer.py:314
 msgid "New"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:316
+#: spyderlib/widgets/explorer.py:322
 msgid "Import"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:462
+#: spyderlib/widgets/explorer.py:471
 msgid "Do you really want to delete <b>%s</b>?"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:482
+#: spyderlib/widgets/explorer.py:489
 msgid "delete"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:483 spyderlib/widgets/projectexplorer.py:815
-#: spyderlib/widgets/projectexplorer.py:822
-#: spyderlib/widgets/projectexplorer.py:1089
-#: spyderlib/widgets/projectexplorer.py:1173
+#: spyderlib/widgets/explorer.py:490 spyderlib/widgets/projectexplorer.py:823
+#: spyderlib/widgets/projectexplorer.py:830
+#: spyderlib/widgets/projectexplorer.py:1101
+#: spyderlib/widgets/projectexplorer.py:1186
 msgid "Project Explorer"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:484 spyderlib/widgets/projectexplorer.py:762
-#: spyderlib/widgets/projectexplorer.py:1174
+#: spyderlib/widgets/explorer.py:491 spyderlib/widgets/projectexplorer.py:770
+#: spyderlib/widgets/projectexplorer.py:1187
 msgid "<b>Unable to %s <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:506
-#: spyderlib/widgets/sourcecode/codeeditor.py:1906
+#: spyderlib/widgets/explorer.py:514
+#: spyderlib/widgets/sourcecode/codeeditor.py:1987
 msgid "Conversion error"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:507
-#: spyderlib/widgets/sourcecode/codeeditor.py:1907
+#: spyderlib/widgets/explorer.py:515
+#: spyderlib/widgets/sourcecode/codeeditor.py:1988
 msgid ""
 "It was not possible to convert this notebook. The error is:\n"
 "\n"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:525
+#: spyderlib/widgets/explorer.py:533
 msgid "New name:"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:533
+#: spyderlib/widgets/explorer.py:541
 msgid "Do you really want to rename <b>%s</b> and overwrite the existing file <b>%s</b>?"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:545
+#: spyderlib/widgets/explorer.py:552
 msgid "<b>Unable to rename file <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:579
+#: spyderlib/widgets/explorer.py:588
 msgid "<b>Unable to move <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:597
+#: spyderlib/widgets/explorer.py:606
 msgid "<b>Unable to create folder <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:610 spyderlib/widgets/explorer.py:644
+#: spyderlib/widgets/explorer.py:619 spyderlib/widgets/explorer.py:653
 msgid "<b>Unable to create file <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:618
+#: spyderlib/widgets/explorer.py:627
 msgid "New folder"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:619
+#: spyderlib/widgets/explorer.py:628
 msgid "Folder name:"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:624
+#: spyderlib/widgets/explorer.py:633
 msgid "New package"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:625
+#: spyderlib/widgets/explorer.py:634
 msgid "Package name:"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:665
+#: spyderlib/widgets/explorer.py:674
 msgid "New module"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:678
+#: spyderlib/widgets/explorer.py:686
 msgid "For %s support, please install one of the<br/> following tools:<br/><br/>  %s"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:682
+#: spyderlib/widgets/explorer.py:690
 msgid "<b>Unable to find external program.</b><br><br>%s"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:882
+#: spyderlib/widgets/explorer.py:893
 msgid "Show current directory only"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:996 spyderlib/widgets/importwizard.py:518
+#: spyderlib/widgets/explorer.py:989
+msgid "You don't have the right permissions to open this directory"
+msgstr ""
+
+#: spyderlib/widgets/explorer.py:1018 spyderlib/widgets/importwizard.py:525
 msgid "Previous"
 msgstr ""
 
-#: spyderlib/widgets/explorer.py:1012
+#: spyderlib/widgets/explorer.py:1024
 msgid "Parent"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/baseshell.py:140
+#: spyderlib/widgets/externalshell/baseshell.py:142
 msgid "Run again this program"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/baseshell.py:143
+#: spyderlib/widgets/externalshell/baseshell.py:145
 msgid "Kill"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/baseshell.py:145
+#: spyderlib/widgets/externalshell/baseshell.py:147
 msgid "Kills the current process, causing it to exit immediately"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/baseshell.py:213
+#: spyderlib/widgets/externalshell/baseshell.py:219
 msgid "<span style='color: #44AA44'><b>Running...</b></span>"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/baseshell.py:220
+#: spyderlib/widgets/externalshell/baseshell.py:226
 msgid "Terminated."
 msgstr ""
 
-#: spyderlib/widgets/externalshell/baseshell.py:242
-#: spyderlib/widgets/ipython.py:342 spyderlib/widgets/ipython.py:359
-#: spyderlib/widgets/mixins.py:608
+#: spyderlib/widgets/externalshell/baseshell.py:251
+#: spyderlib/widgets/ipython.py:351 spyderlib/widgets/ipython.py:368
+#: spyderlib/widgets/mixins.py:656
 msgid "Arguments"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/baseshell.py:243
+#: spyderlib/widgets/externalshell/baseshell.py:252
 msgid "Command line arguments:"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:173
+#: spyderlib/widgets/externalshell/namespacebrowser.py:191
 msgid "Refresh"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:177
+#: spyderlib/widgets/externalshell/namespacebrowser.py:195
 msgid "Refresh periodically"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:181
-#: spyderlib/widgets/externalshell/namespacebrowser.py:446
+#: spyderlib/widgets/externalshell/namespacebrowser.py:199
+#: spyderlib/widgets/externalshell/namespacebrowser.py:453
 msgid "Import data"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:184
-#: spyderlib/widgets/externalshell/namespacebrowser.py:536
-#: spyderlib/widgets/externalshell/namespacebrowser.py:557
+#: spyderlib/widgets/externalshell/namespacebrowser.py:202
+#: spyderlib/widgets/externalshell/namespacebrowser.py:541
+#: spyderlib/widgets/externalshell/namespacebrowser.py:562
 msgid "Save data"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:189
+#: spyderlib/widgets/externalshell/namespacebrowser.py:207
 msgid "Save data as..."
 msgstr ""
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:197
+#: spyderlib/widgets/externalshell/namespacebrowser.py:215
 msgid "Exclude references which name starts with an underscore"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:205
+#: spyderlib/widgets/externalshell/namespacebrowser.py:223
 msgid "Exclude references which name is uppercase"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:212
+#: spyderlib/widgets/externalshell/namespacebrowser.py:230
 msgid "Exclude references which name starts with an uppercase character"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:220
+#: spyderlib/widgets/externalshell/namespacebrowser.py:238
 msgid "Exclude references to unsupported data types (i.e. which won't be handled/saved correctly)"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:342
+#: spyderlib/widgets/externalshell/namespacebrowser.py:347
 msgid "Object <b>%s</b> is not picklable"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:468
+#: spyderlib/widgets/externalshell/namespacebrowser.py:473
 msgid "<b>Unsupported file extension '%s'</b><br><br>Would you like to import it anyway (by selecting a known file format)?"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:476
+#: spyderlib/widgets/externalshell/namespacebrowser.py:481
 msgid "Open file as:"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:524
+#: spyderlib/widgets/externalshell/namespacebrowser.py:529
 msgid "<b>Unable to load '%s'</b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/namespacebrowser.py:558
+#: spyderlib/widgets/externalshell/namespacebrowser.py:563
 msgid "<b>Unable to save current workspace</b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/pythonshell.py:269
+#: spyderlib/widgets/externalshell/pythonshell.py:284
 msgid "Variables"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/pythonshell.py:270
+#: spyderlib/widgets/externalshell/pythonshell.py:285
 msgid "Show/hide global variables explorer"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/pythonshell.py:274
+#: spyderlib/widgets/externalshell/pythonshell.py:289
 msgid "Terminate"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/pythonshell.py:275
+#: spyderlib/widgets/externalshell/pythonshell.py:290
 msgid ""
 "Attempts to stop the process. The process\n"
 "may not exit as a result of clicking this\n"
@@ -3596,130 +3869,150 @@ msgid ""
 "the user for any unsaved files, etc)."
 msgstr ""
 
-#: spyderlib/widgets/externalshell/pythonshell.py:288
+#: spyderlib/widgets/externalshell/pythonshell.py:303
 msgid "Interact"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/pythonshell.py:290
+#: spyderlib/widgets/externalshell/pythonshell.py:305
 msgid "Debug"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/pythonshell.py:292
-#: spyderlib/widgets/externalshell/pythonshell.py:355
+#: spyderlib/widgets/externalshell/pythonshell.py:307
+#: spyderlib/widgets/externalshell/pythonshell.py:373
 msgid "Arguments..."
 msgstr ""
 
-#: spyderlib/widgets/externalshell/pythonshell.py:299
+#: spyderlib/widgets/externalshell/pythonshell.py:309
+msgid "Post Mortem Debug"
+msgstr ""
+
+#: spyderlib/widgets/externalshell/pythonshell.py:315
+msgid "Working directory"
+msgstr ""
+
+#: spyderlib/widgets/externalshell/pythonshell.py:317
 msgid "Set current working directory"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/pythonshell.py:301
+#: spyderlib/widgets/externalshell/pythonshell.py:319
 msgid "Environment variables"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/pythonshell.py:305
+#: spyderlib/widgets/externalshell/pythonshell.py:323
 msgid "Show sys.path contents"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/pythonshell.py:351
+#: spyderlib/widgets/externalshell/pythonshell.py:369
 msgid "Arguments: %s"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/pythonshell.py:353
+#: spyderlib/widgets/externalshell/pythonshell.py:371
 msgid "No argument"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/pythonshell.py:534
+#: spyderlib/widgets/externalshell/pythonshell.py:550
 msgid "The kernel failed to start!! That's all we know... Please close this console and open a new one."
 msgstr ""
 
-#: spyderlib/widgets/externalshell/pythonshell.py:538
+#: spyderlib/widgets/externalshell/pythonshell.py:554
 msgid "A Python console failed to start!"
 msgstr ""
 
-#: spyderlib/widgets/externalshell/systemshell.py:94
+#: spyderlib/widgets/externalshell/systemshell.py:100
 msgid "Process failed to start"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:155
+#: spyderlib/widgets/file_switcher.py:109
+msgid "unsaved file"
+msgstr ""
+
+#: spyderlib/widgets/file_switcher.py:229
+msgid "Press <b>Enter</b> to switch files or <b>Esc</b> to cancel.<br><br>Type to filter filenames.<br><br>Use <b>:number</b> to go to a line, e.g. <b><code>main:42</code></b><br>Use <b>@symbol_text</b> to go to a symbol, e.g. <b><code>@init</code></b><br><br> Press <b>Ctrl+W</b> to close current tab.<br>"
+msgstr ""
+
+#: spyderlib/widgets/file_switcher.py:481
+msgid "lines"
+msgstr ""
+
+#: spyderlib/widgets/findinfiles.py:158
 msgid "Unexpected error: see internal console"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:207 spyderlib/widgets/findinfiles.py:231
-#: spyderlib/widgets/findinfiles.py:278
+#: spyderlib/widgets/findinfiles.py:210 spyderlib/widgets/findinfiles.py:234
+#: spyderlib/widgets/findinfiles.py:281
 msgid "invalid regular expression"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:276
+#: spyderlib/widgets/findinfiles.py:279
 msgid "permission denied errors were encountered"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:310
+#: spyderlib/widgets/findinfiles.py:316
 msgid "Search pattern"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:313 spyderlib/widgets/findinfiles.py:347
-#: spyderlib/widgets/findinfiles.py:359 spyderlib/widgets/findreplace.py:82
+#: spyderlib/widgets/findinfiles.py:319 spyderlib/widgets/findinfiles.py:353
+#: spyderlib/widgets/findinfiles.py:365 spyderlib/widgets/findreplace.py:77
 msgid "Regular expression"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:322
+#: spyderlib/widgets/findinfiles.py:328
 msgid "Search"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:325
+#: spyderlib/widgets/findinfiles.py:331
 msgid "Start search"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:328 spyderlib/widgets/ipython.py:543
+#: spyderlib/widgets/findinfiles.py:334 spyderlib/widgets/ipython.py:555
 msgid "Stop"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:331
+#: spyderlib/widgets/findinfiles.py:337
 msgid "Stop search"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:341
+#: spyderlib/widgets/findinfiles.py:347
 msgid "Included filenames pattern"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:350
+#: spyderlib/widgets/findinfiles.py:356
 msgid "Include:"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:353
+#: spyderlib/widgets/findinfiles.py:359
 msgid "Excluded filenames pattern"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:362
+#: spyderlib/widgets/findinfiles.py:368
 msgid "Exclude:"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:372
+#: spyderlib/widgets/findinfiles.py:378
 msgid "PYTHONPATH"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:374
+#: spyderlib/widgets/findinfiles.py:380
 msgid "Search in all directories listed in sys.path which are outside the Python installation directory"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:377
+#: spyderlib/widgets/findinfiles.py:383
 msgid "Hg repository"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:380
+#: spyderlib/widgets/findinfiles.py:386
 msgid "Search in current directory hg repository"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:381
+#: spyderlib/widgets/findinfiles.py:387
 msgid "Here:"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:385
+#: spyderlib/widgets/findinfiles.py:391
 msgid "Search recursively in this directory"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:393
+#: spyderlib/widgets/findinfiles.py:396
 msgid "Browse a search directory"
 msgstr ""
 
@@ -3731,490 +4024,490 @@ msgstr ""
 msgid "Show advanced options"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:571
+#: spyderlib/widgets/findinfiles.py:570
 msgid "Search canceled"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:575
+#: spyderlib/widgets/findinfiles.py:574
 msgid "String not found"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:577
+#: spyderlib/widgets/findinfiles.py:576
 msgid "matches in"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:578
+#: spyderlib/widgets/findinfiles.py:577
 msgid "file"
 msgstr ""
 
-#: spyderlib/widgets/findinfiles.py:586
+#: spyderlib/widgets/findinfiles.py:585
 msgid "interrupted"
 msgstr ""
 
-#: spyderlib/widgets/findreplace.py:62
+#: spyderlib/widgets/findreplace.py:59
 msgid "Search string"
 msgstr ""
 
-#: spyderlib/widgets/findreplace.py:89
+#: spyderlib/widgets/findreplace.py:83
 msgid "Case Sensitive"
 msgstr ""
 
-#: spyderlib/widgets/findreplace.py:96
+#: spyderlib/widgets/findreplace.py:89
 msgid "Whole words"
 msgstr ""
 
-#: spyderlib/widgets/findreplace.py:103
+#: spyderlib/widgets/findreplace.py:95
 msgid "Highlight matches"
 msgstr ""
 
-#: spyderlib/widgets/findreplace.py:118
+#: spyderlib/widgets/findreplace.py:109
 msgid "Replace with:"
 msgstr ""
 
-#: spyderlib/widgets/findreplace.py:120
+#: spyderlib/widgets/findreplace.py:111
 msgid "Replace string"
 msgstr ""
 
-#: spyderlib/widgets/findreplace.py:123
+#: spyderlib/widgets/findreplace.py:114
 msgid "Replace/find"
 msgstr ""
 
-#: spyderlib/widgets/findreplace.py:132
+#: spyderlib/widgets/findreplace.py:121
 msgid "Replace all"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:111 spyderlib/widgets/importwizard.py:425
+#: spyderlib/widgets/importwizard.py:116 spyderlib/widgets/importwizard.py:431
 msgid "Import as"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:113
+#: spyderlib/widgets/importwizard.py:118
 msgid "data"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:117
+#: spyderlib/widgets/importwizard.py:122
 msgid "code"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:120 spyderlib/widgets/importwizard.py:497
+#: spyderlib/widgets/importwizard.py:125 spyderlib/widgets/importwizard.py:504
 msgid "text"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:133
+#: spyderlib/widgets/importwizard.py:138
 msgid "Column separator:"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:137
+#: spyderlib/widgets/importwizard.py:142
 msgid "Tab"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:140 spyderlib/widgets/importwizard.py:159
+#: spyderlib/widgets/importwizard.py:145 spyderlib/widgets/importwizard.py:163
 msgid "other"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:152
+#: spyderlib/widgets/importwizard.py:156
 msgid "Row separator:"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:156
+#: spyderlib/widgets/importwizard.py:160
 msgid "EOL"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:172
+#: spyderlib/widgets/importwizard.py:175
 msgid "Additional options"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:176
+#: spyderlib/widgets/importwizard.py:179
 msgid "Skip rows:"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:187
+#: spyderlib/widgets/importwizard.py:190
 msgid "Comments:"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:193
+#: spyderlib/widgets/importwizard.py:196
 msgid "Transpose"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:428
+#: spyderlib/widgets/importwizard.py:434
 msgid "array"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:433
+#: spyderlib/widgets/importwizard.py:439
 msgid "list"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:438
+#: spyderlib/widgets/importwizard.py:444
 msgid "DataFrame"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:480 spyderlib/widgets/importwizard.py:567
+#: spyderlib/widgets/importwizard.py:487 spyderlib/widgets/importwizard.py:569
 msgid "Import wizard"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:485
+#: spyderlib/widgets/importwizard.py:492
 msgid "Raw text"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:488
+#: spyderlib/widgets/importwizard.py:495
 msgid "variable_name"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:499
+#: spyderlib/widgets/importwizard.py:506
 msgid "table"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:500
+#: spyderlib/widgets/importwizard.py:507
 msgid "Preview"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:504
+#: spyderlib/widgets/importwizard.py:511
 msgid "Variable Name"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:512
+#: spyderlib/widgets/importwizard.py:519
 msgid "Cancel"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:527
+#: spyderlib/widgets/importwizard.py:532
 msgid "Done"
 msgstr ""
 
-#: spyderlib/widgets/importwizard.py:568
+#: spyderlib/widgets/importwizard.py:570
 msgid "<b>Unable to proceed to next step</b><br><br>Please check your entries.<br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/internalshell.py:252
+#: spyderlib/widgets/internalshell.py:258
 msgid "Help..."
 msgstr ""
 
-#: spyderlib/widgets/internalshell.py:259
+#: spyderlib/widgets/internalshell.py:266
 msgid "Help"
 msgstr ""
 
-#: spyderlib/widgets/internalshell.py:268
+#: spyderlib/widgets/internalshell.py:275
 msgid "Shell special commands:"
 msgstr ""
 
-#: spyderlib/widgets/internalshell.py:269
+#: spyderlib/widgets/internalshell.py:276
 msgid "Internal editor:"
 msgstr ""
 
-#: spyderlib/widgets/internalshell.py:270
+#: spyderlib/widgets/internalshell.py:277
 msgid "External editor:"
 msgstr ""
 
-#: spyderlib/widgets/internalshell.py:271
+#: spyderlib/widgets/internalshell.py:278
 msgid "Run script:"
 msgstr ""
 
-#: spyderlib/widgets/internalshell.py:272
+#: spyderlib/widgets/internalshell.py:279
 msgid "Remove references:"
 msgstr ""
 
-#: spyderlib/widgets/internalshell.py:273
+#: spyderlib/widgets/internalshell.py:280
 msgid "System commands:"
 msgstr ""
 
-#: spyderlib/widgets/internalshell.py:274
+#: spyderlib/widgets/internalshell.py:281
 msgid "Python help:"
 msgstr ""
 
-#: spyderlib/widgets/internalshell.py:275
+#: spyderlib/widgets/internalshell.py:282
 msgid "GUI-based editor:"
 msgstr ""
 
-#: spyderlib/widgets/ipython.py:495
+#: spyderlib/widgets/ipython.py:506
 msgid "An error ocurred while starting the kernel"
 msgstr ""
 
-#: spyderlib/widgets/ipython.py:523
+#: spyderlib/widgets/ipython.py:535
 msgid "Restart kernel"
 msgstr ""
 
-#: spyderlib/widgets/ipython.py:545
+#: spyderlib/widgets/ipython.py:557
 msgid "Stop the current command"
 msgstr ""
 
-#: spyderlib/widgets/ipython.py:569
+#: spyderlib/widgets/ipython.py:581
 msgid "Inspect current object"
 msgstr ""
 
-#: spyderlib/widgets/ipython.py:574
+#: spyderlib/widgets/ipython.py:586
 msgid "Clear line or block"
 msgstr ""
 
-#: spyderlib/widgets/ipython.py:578
+#: spyderlib/widgets/ipython.py:590
 msgid "Clear console"
 msgstr ""
 
-#: spyderlib/widgets/ipython.py:623
+#: spyderlib/widgets/ipython.py:640
 msgid "It seems the kernel died unexpectedly. Use 'Restart kernel' to continue using this console."
 msgstr ""
 
-#: spyderlib/widgets/ipython.py:639
+#: spyderlib/widgets/ipython.py:660
 msgid "Changing backend to Qt for Mayavi"
 msgstr ""
 
-#: spyderlib/widgets/ipython.py:648
+#: spyderlib/widgets/ipython.py:669
 msgid "Kernel process is either remote or unspecified. Cannot interrupt"
 msgstr ""
 
-#: spyderlib/widgets/ipython.py:657
+#: spyderlib/widgets/ipython.py:678
 msgid "Kernel process is either remote or unspecified. Cannot restart."
 msgstr ""
 
-#: spyderlib/widgets/ipython.py:734
+#: spyderlib/widgets/ipython.py:757
 msgid "Connecting to kernel..."
 msgstr ""
 
-#: spyderlib/widgets/onecolumntree.py:63
+#: spyderlib/widgets/onecolumntree.py:60
 msgid "Collapse all"
 msgstr ""
 
-#: spyderlib/widgets/onecolumntree.py:67
+#: spyderlib/widgets/onecolumntree.py:64
 msgid "Expand all"
 msgstr ""
 
-#: spyderlib/widgets/onecolumntree.py:71
+#: spyderlib/widgets/onecolumntree.py:68
 msgid "Restore"
 msgstr ""
 
-#: spyderlib/widgets/onecolumntree.py:72
+#: spyderlib/widgets/onecolumntree.py:69
 msgid "Restore original tree layout"
 msgstr ""
 
-#: spyderlib/widgets/onecolumntree.py:76
+#: spyderlib/widgets/onecolumntree.py:73
 msgid "Collapse selection"
 msgstr ""
 
-#: spyderlib/widgets/onecolumntree.py:80
+#: spyderlib/widgets/onecolumntree.py:77
 msgid "Expand selection"
 msgstr ""
 
-#: spyderlib/widgets/pathmanager.py:84
+#: spyderlib/widgets/pathmanager.py:86
 msgid "Move to top"
 msgstr ""
 
-#: spyderlib/widgets/pathmanager.py:90
+#: spyderlib/widgets/pathmanager.py:92
 msgid "Move up"
 msgstr ""
 
-#: spyderlib/widgets/pathmanager.py:96
+#: spyderlib/widgets/pathmanager.py:98
 msgid "Move down"
 msgstr ""
 
-#: spyderlib/widgets/pathmanager.py:102
+#: spyderlib/widgets/pathmanager.py:104
 msgid "Move to bottom"
 msgstr ""
 
-#: spyderlib/widgets/pathmanager.py:113 spyderlib/widgets/pathmanager.py:225
+#: spyderlib/widgets/pathmanager.py:115 spyderlib/widgets/pathmanager.py:230
 msgid "Add path"
 msgstr ""
 
-#: spyderlib/widgets/pathmanager.py:118 spyderlib/widgets/pathmanager.py:209
+#: spyderlib/widgets/pathmanager.py:120 spyderlib/widgets/pathmanager.py:213
 msgid "Remove path"
 msgstr ""
 
-#: spyderlib/widgets/pathmanager.py:128
+#: spyderlib/widgets/pathmanager.py:130
 msgid "Synchronize..."
 msgstr ""
 
-#: spyderlib/widgets/pathmanager.py:130
+#: spyderlib/widgets/pathmanager.py:132
 msgid "Synchronize Spyder's path list with PYTHONPATH environment variable"
 msgstr ""
 
-#: spyderlib/widgets/pathmanager.py:141
+#: spyderlib/widgets/pathmanager.py:144
 msgid "Synchronize"
 msgstr ""
 
-#: spyderlib/widgets/pathmanager.py:142
+#: spyderlib/widgets/pathmanager.py:145
 msgid "This will synchronize Spyder's path list with <b>PYTHONPATH</b> environment variable for current user, allowing you to run your Python modules outside Spyder without having to configure sys.path. <br>Do you want to clear contents of PYTHONPATH before adding Spyder's path list?"
 msgstr ""
 
-#: spyderlib/widgets/pathmanager.py:210
+#: spyderlib/widgets/pathmanager.py:214
 msgid "Do you really want to remove selected path?"
 msgstr ""
 
-#: spyderlib/widgets/pathmanager.py:226
+#: spyderlib/widgets/pathmanager.py:231
 msgid "This directory is already included in Spyder path list.<br>Do you want to move it to the top of the list?"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:333
+#: spyderlib/widgets/projectexplorer.py:335
 msgid "its own configuration file"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:335
+#: spyderlib/widgets/projectexplorer.py:337
 msgid " and "
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:339
+#: spyderlib/widgets/projectexplorer.py:341
 msgid "the following projects:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:541
+#: spyderlib/widgets/projectexplorer.py:545
 msgid "Project..."
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:554
+#: spyderlib/widgets/projectexplorer.py:558
 msgid "Existing directory"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:558
+#: spyderlib/widgets/projectexplorer.py:562
 msgid "Existing Spyder project"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:562
+#: spyderlib/widgets/projectexplorer.py:566
 msgid "Existing Pydev project"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:579
+#: spyderlib/widgets/projectexplorer.py:583
 msgid "Open project"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:584
+#: spyderlib/widgets/projectexplorer.py:588
 msgid "Close project"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:589
+#: spyderlib/widgets/projectexplorer.py:593
 msgid "Close unrelated projects"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:598
+#: spyderlib/widgets/projectexplorer.py:602
 msgid "Edit related projects"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:606
+#: spyderlib/widgets/projectexplorer.py:610
 msgid "Add to PYTHONPATH"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:611
+#: spyderlib/widgets/projectexplorer.py:615
 msgid "Remove from PYTHONPATH"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:616
+#: spyderlib/widgets/projectexplorer.py:620
 msgid "Properties"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:651
+#: spyderlib/widgets/projectexplorer.py:655
 msgid "Show horizontal scrollbar"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:684
+#: spyderlib/widgets/projectexplorer.py:692
 msgid "Workspace"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:685
+#: spyderlib/widgets/projectexplorer.py:693
 msgid "The workspace was unable to load or save %s<br><br>Please check if you have the permission to write the associated configuration files."
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:744
+#: spyderlib/widgets/projectexplorer.py:752
 msgid "Import directory"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:746
+#: spyderlib/widgets/projectexplorer.py:754
 msgid "The following directory is not in workspace:<br><b>%s</b><br><br>Do you want to continue (and copy the directory to workspace)?"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:764
-#: spyderlib/widgets/projectexplorer.py:1170
+#: spyderlib/widgets/projectexplorer.py:772
+#: spyderlib/widgets/projectexplorer.py:1183
 msgid "copy"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:816
+#: spyderlib/widgets/projectexplorer.py:824
 msgid "The project <b>%s</b> is already opened!"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:823
+#: spyderlib/widgets/projectexplorer.py:831
 msgid "The project root path directory is inside the workspace but not as the expected tree level. It is not a directory of the workspace:<br><b>%s</b>"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:834
+#: spyderlib/widgets/projectexplorer.py:842
 msgid "Project name:"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:843
+#: spyderlib/widgets/projectexplorer.py:851
 msgid "A project named <b>%s</b> already exists"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:848
+#: spyderlib/widgets/projectexplorer.py:856
 msgid "Invalid project name.<br><br>Name must match the following regular expression:<br><b>%s</b>"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:855
+#: spyderlib/widgets/projectexplorer.py:863
 msgid "The following directory is not empty:<br><b>%s</b><br><br>Do you want to continue?"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:867
+#: spyderlib/widgets/projectexplorer.py:876
 msgid "New project"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:875
+#: spyderlib/widgets/projectexplorer.py:884
 msgid ""
 "The current workspace has not been configured yet.\n"
 "Do you want to do this now?"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:912
+#: spyderlib/widgets/projectexplorer.py:922
 msgid "Import existing project"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:925
+#: spyderlib/widgets/projectexplorer.py:935
 msgid "Select projects to import"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:937
+#: spyderlib/widgets/projectexplorer.py:947
 msgid "The folder <i>%s</i> does not contain a valid %s project"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:965
+#: spyderlib/widgets/projectexplorer.py:977
 msgid "Import existing Pydev project"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:966
+#: spyderlib/widgets/projectexplorer.py:978
 msgid "<b>Unable to read Pydev project <i>%s</i></b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:1004
+#: spyderlib/widgets/projectexplorer.py:1016
 msgid "Do you really want to delete project <b>%s</b>?<br><br>Note: project files won't be deleted from disk."
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:1057
+#: spyderlib/widgets/projectexplorer.py:1069
 msgid "Related projects"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:1065
+#: spyderlib/widgets/projectexplorer.py:1077
 msgid "Select projects which are related to <b>%s</b>"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:1090
-msgid "Statistics on source files only:<br>(Python, C/C++, Fortran)<br><br><b>%s</b> files.<br><b>%s</b> lines of code."
+#: spyderlib/widgets/projectexplorer.py:1102
+msgid "Statistics on source files only:<br>(Python, Cython, IPython, Enaml,C/C++, Fortran)<br><br><b>%s</b> files.<br><b>%s</b> lines of code."
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:1138
+#: spyderlib/widgets/projectexplorer.py:1151
 msgid "File <b>%s</b> already exists.<br>Do you want to overwrite it?"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:1152
+#: spyderlib/widgets/projectexplorer.py:1165
 msgid "Folder <b>%s</b> already exists."
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:1172
+#: spyderlib/widgets/projectexplorer.py:1185
 msgid "move"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:1182
+#: spyderlib/widgets/projectexplorer.py:1195
 msgid "Select an existing workspace directory, or create a new one"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:1183
+#: spyderlib/widgets/projectexplorer.py:1196
 msgid "<u><b>What is the workspace?</b></u><br><br>A <b>Spyder workspace</b> is a directory on your filesystem that contains Spyder projects and <b>.spyderworkspace</b> configuration file.<br><br>A <b>Spyder project</b> is a directory with source code (and other related files) and a configuration file (named <b>.spyderproject</b>) with project settings (PYTHONPATH, linked projects, ...).<br>"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:1210
+#: spyderlib/widgets/projectexplorer.py:1225
 msgid "This is the current workspace directory"
 msgstr ""
 
-#: spyderlib/widgets/projectexplorer.py:1241
+#: spyderlib/widgets/projectexplorer.py:1255
 msgid "The following directory is not a Spyder workspace:<br>%s<br><br>Do you want to create a new workspace in this directory?"
 msgstr ""
 
@@ -4222,85 +4515,89 @@ msgstr ""
 msgid "Module or package:"
 msgstr ""
 
-#: spyderlib/widgets/shell.py:126
+#: spyderlib/widgets/shell.py:134
 msgid "Save history log..."
 msgstr ""
 
-#: spyderlib/widgets/shell.py:128
+#: spyderlib/widgets/shell.py:136
 msgid "Save current history log (i.e. all inputs and outputs) in a text file"
 msgstr ""
 
-#: spyderlib/widgets/shell.py:248
+#: spyderlib/widgets/shell.py:262
 msgid "Save history log"
 msgstr ""
 
-#: spyderlib/widgets/shell.py:251
+#: spyderlib/widgets/shell.py:265
 msgid "History logs"
 msgstr ""
 
-#: spyderlib/widgets/shell.py:262
+#: spyderlib/widgets/shell.py:276
 msgid "<b>Unable to save file '%s'</b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib/widgets/shell.py:701
+#: spyderlib/widgets/shell.py:718
 msgid "Copy without prompts"
 msgstr ""
 
-#: spyderlib/widgets/shell.py:704 spyderlib/widgets/shell.py:708
+#: spyderlib/widgets/shell.py:721 spyderlib/widgets/shell.py:725
 msgid "Clear line"
 msgstr ""
 
-#: spyderlib/widgets/shell.py:710
+#: spyderlib/widgets/shell.py:727
 msgid "Clear shell"
 msgstr ""
 
-#: spyderlib/widgets/shell.py:714
+#: spyderlib/widgets/shell.py:731
 msgid "Clear shell contents ('cls' command)"
 msgstr ""
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:88
+#: spyderlib/widgets/sourcecode/codeeditor.py:98
 msgid "Go to line:"
 msgstr ""
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:97
+#: spyderlib/widgets/sourcecode/codeeditor.py:106
 msgid "Line count:"
 msgstr ""
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:1210
+#: spyderlib/widgets/sourcecode/codeeditor.py:1270
 msgid "Breakpoint"
 msgstr ""
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:1211
+#: spyderlib/widgets/sourcecode/codeeditor.py:1271
 msgid "Condition:"
 msgstr ""
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:1671
+#: spyderlib/widgets/sourcecode/codeeditor.py:1679
+msgid "Code analysis"
+msgstr ""
+
+#: spyderlib/widgets/sourcecode/codeeditor.py:1733
 msgid "To do"
 msgstr ""
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:1880
+#: spyderlib/widgets/sourcecode/codeeditor.py:1974
 msgid "Removal error"
 msgstr ""
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:1881
+#: spyderlib/widgets/sourcecode/codeeditor.py:1975
 msgid ""
 "It was not possible to remove outputs from this notebook. The error is:\n"
 "\n"
 msgstr ""
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:2296
+#: spyderlib/widgets/sourcecode/codeeditor.py:2453
 msgid "Clear all ouput"
 msgstr ""
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:2302
+#: spyderlib/widgets/sourcecode/codeeditor.py:2459
 msgid "Go to definition"
 msgstr ""
 
-#: spyderlib/widgets/sourcecode/codeeditor.py:2314
+#: spyderlib/widgets/sourcecode/codeeditor.py:2471
 msgid "Zoom reset"
 msgstr ""
 
-#: spyderlib/widgets/sourcecode/syntaxhighlighters.py:30
+#: spyderlib/widgets/sourcecode/syntaxhighlighters.py:32
 msgid "Syntax highlighting for Matlab, Julia and other file types"
 msgstr ""
 
@@ -4344,11 +4641,11 @@ msgstr ""
 msgid "Column:"
 msgstr ""
 
-#: spyderlib/widgets/tabs.py:137
+#: spyderlib/widgets/tabs.py:142
 msgid "Browse tabs"
 msgstr ""
 
-#: spyderlib/widgets/tabs.py:260
+#: spyderlib/widgets/tabs.py:270
 msgid "Close current tab"
 msgstr ""
 
@@ -4356,3 +4653,15 @@ msgstr ""
 msgid "Text editor"
 msgstr ""
 
+#: spyderlib/workers/updates.py:79 spyderlib/workers/updates.py:81
+msgid "Unable to retrieve information."
+msgstr ""
+
+#: spyderlib/workers/updates.py:83
+msgid "Unable to connect to the internet. <br><br>Make sure the connection is working properly."
+msgstr ""
+
+#: spyderlib/workers/updates.py:86
+msgid "Unable to check for updates."
+msgstr ""
+
diff --git a/spyderlib/otherplugins.py b/spyderlib/otherplugins.py
index dc822b8..30ce2d5 100644
--- a/spyderlib/otherplugins.py
+++ b/spyderlib/otherplugins.py
@@ -8,52 +8,154 @@
 Spyder third-party plugins configuration management
 """
 
+import importlib
 import os
 import os.path as osp
 import sys
 import traceback
 
 # Local imports
-from spyderlib.utils import programs
-
-
-# Calculate path to `spyderplugins` package, where Spyder looks for all 3rd
-# party plugin modules
-PLUGIN_PATH = None
-if programs.is_module_installed("spyderplugins"):
-    import spyderplugins
-    PLUGIN_PATH = osp.abspath(spyderplugins.__path__[0])
-    if not osp.isdir(PLUGIN_PATH):
-        # py2exe/cx_Freeze distribution: ignoring extra plugins
-        PLUGIN_PATH = None
-
-
-def get_spyderplugins(prefix, extension):
-    """Scan directory of `spyderplugins` package and
-    return the list of module names matching *prefix* and *extension*"""
-    plist = []
-    if PLUGIN_PATH is not None:
-        for name in os.listdir(PLUGIN_PATH):
-            modname, ext = osp.splitext(name)
-            if prefix is not None and not name.startswith(prefix):
-                continue
-            if extension is not None and ext != extension:
-                continue
-            plist.append(modname)
-    return plist
-
-
-def get_spyderplugins_mods(prefix, extension):
-    """Import modules that match *prefix* and *extension* from
-    `spyderplugins` package and return the list"""
-    modlist = []
-    for modname in get_spyderplugins(prefix, extension):
-        name = 'spyderplugins.%s' % modname
-        try:
-            __import__(name)
-            modlist.append(sys.modules[name])
-        except Exception:
-            sys.stderr.write(
-                "ERROR: 3rd party plugin import failed for `%s`\n" % modname)
-            traceback.print_exc(file=sys.stderr)
+from spyderlib.config.base import get_conf_path
+from spyderlib.py3compat import PY2, PY3, PY33
+
+if PY2:
+    import imp
+
+
+def _get_spyderplugins(plugin_path, base_namespace, plugins_namespace,
+                       modnames, modlist):
+    """Scan the directory `plugin_path` for plugins_namespace package and
+    loads its submodules."""
+    namespace_path = osp.join(plugin_path, base_namespace, plugins_namespace)
+
+    if not osp.exists(namespace_path):
+        return
+
+    dirs = []
+    for d in os.listdir(namespace_path):
+        path = osp.join(namespace_path, d)
+        if osp.isdir(path):
+            dirs.append(path)
+            
+    for dirname in dirs:
+        name = osp.basename(dirname)
+        if name == "__pycache__":
+            continue
+        _import_plugin(name, base_namespace, plugins_namespace,
+                       namespace_path, modnames, modlist)
+
+
+class _ModuleMock():
+    """This mock module is added to sys.modules on plugin load to add the
+    location of the LOCALEDATA so that the module loads succesfully.
+    Once loaded the module is replaced by the actual loaded module object.
+    """
+    pass
+
+
+def _import_plugin(name, base_namespace, plugin_namespace, namespace_path,
+                   modnames, modlist):
+    """Import the plugin `plugins_namsepace`.`name`, add it to `modlist` and
+    adds its name to `modnames`."""
+    module_name = "{0}.{1}.{2}".format(base_namespace, plugin_namespace, name)
+
+    if module_name in modnames:
+        return
+    try:
+        # First add a mock module with the LOCALEPATH attribute so that the
+        # helper method can find the locale on import
+        mock = _ModuleMock()
+        mock.LOCALEPATH = osp.join(namespace_path, name, 'locale')
+        sys.modules[module_name] = mock
+        module = None
+        if PY33:
+            loader = importlib.machinery.PathFinder.find_module(
+                name, [namespace_path])
+            if loader:
+                module = loader.load_module(name)
+        elif PY3:
+            spec = importlib.machinery.PathFinder.find_spec(name,
+                                                            [namespace_path])
+            if spec:
+                module = spec.loader.load_module(name)
+        else:
+            info = imp.find_module(name, [namespace_path])
+            if info:
+                module = imp.load_module(module_name, *info)
+
+        # Then restore the actual loaded module instead of the mock
+        if module:
+            sys.modules[module_name] = module
+            modlist.append(module)
+            modnames.append(module_name)
+    except Exception:
+        sys.stderr.write("ERROR: 3rd party plugin import failed for "
+                         "`{0}`\n".format(module_name))
+        traceback.print_exc(file=sys.stderr)
+
+
+def create_userplugins_files(path):
+    """
+    Create userplugins namespace dirs and files if not present in .spyder* dir
+    """
+    if not osp.isdir(path):
+        os.makedirs(path)
+
+    init_file = "__init__.py"
+    init_file_content = """# -*- coding: utf-8 -*-
+'''
+'spyplugins' makes uses of namespace packages to keep different plugins
+organized in the sitepackages directory and in the user directory.
+
+Spyder plugins can be of 'io' type or 'ui' type. Each type also makes use
+of namespace packages.
+
+For more information on namespace packages visit:
+- https://www.python.org/dev/peps/pep-0382/
+- https://www.python.org/dev/peps/pep-0420/
+'''
+
+# Declare as a namespace package
+__import__('pkg_resources').declare_namespace(__name__)
+"""
+    data = ""
+    new_path = osp.join(path, init_file)
+    if osp.isfile(new_path):
+        with open(new_path, "r") as f:
+            data = f.read()
+
+    if not (osp.isfile(new_path) and data == init_file_content):
+        with open(new_path, "w") as f:
+            f.write(init_file_content)
+
+
+def get_spyderplugins_mods(io=False):
+    """Import modules from plugins package and return the list"""
+    base_namespace = "spyplugins"
+
+    if io:
+        plugins_namespace = "io"
+    else:
+        plugins_namespace = "ui"
+
+    namespace = '.'.join([base_namespace, plugins_namespace])
+
+    # Import parent module
+    importlib.import_module(namespace)
+
+    # Create user directory
+    user_conf_path = get_conf_path()
+    user_plugin_basepath = osp.join(user_conf_path, base_namespace)
+    user_plugin_path = osp.join(user_conf_path, base_namespace,
+                                plugins_namespace)
+
+    create_userplugins_files(user_plugin_basepath)
+    create_userplugins_files(user_plugin_path)
+
+    modlist, modnames = [], []
+
+    # The user plugins directory is given the priority when looking for modules
+    for plugin_path in [user_conf_path] + sys.path:
+        _get_spyderplugins(plugin_path, base_namespace, plugins_namespace,
+                           modnames, modlist)
     return modlist
diff --git a/spyderlib/plugins/__init__.py b/spyderlib/plugins/__init__.py
index 0cec5c7..8602e14 100644
--- a/spyderlib/plugins/__init__.py
+++ b/spyderlib/plugins/__init__.py
@@ -18,20 +18,26 @@ These plugins inherit the following classes
 # pylint: disable=R0911
 # pylint: disable=R0201
 
-from spyderlib.qt.QtGui import (QDockWidget, QWidget, QShortcut, QCursor,
-                                QKeySequence, QMainWindow, QApplication)
-from spyderlib.qt.QtCore import SIGNAL, Qt, QObject, Signal
+# Standard library imports
+import inspect
+import os
 
-import sys
+# Third party imports
+from spyderlib.qt import PYQT5
+from spyderlib.qt.QtCore import Qt, Signal, QObject, QEvent, QPoint
+from spyderlib.qt.QtGui import (QDockWidget, QWidget, QShortcut, QCursor,
+                                QKeySequence, QMainWindow, QApplication,
+                                QTabBar)
 
 # Local imports
-from spyderlib.utils.qthelpers import toggle_actions, get_icon, create_action
-from spyderlib.baseconfig import _
-from spyderlib.config import CONF
-from spyderlib.userconfig import NoDefault
-from spyderlib.guiconfig import get_font, set_font
+from spyderlib.utils.qthelpers import create_action, toggle_actions
+from spyderlib.config.base import _
+from spyderlib.config.gui import get_font, set_font
+from spyderlib.config.main import CONF
+from spyderlib.config.user import NoDefault
 from spyderlib.plugins.configdialog import SpyderConfigPage
 from spyderlib.py3compat import configparser, is_text_string
+from spyderlib.utils import icon_manager as ima
 
 
 class PluginConfigPage(SpyderConfigPage):
@@ -52,15 +58,187 @@ class PluginConfigPage(SpyderConfigPage):
         return self.plugin.get_plugin_icon()
 
 
+class TabFilter(QObject):
+    """
+    Filter event attached to each QTabBar that holds 2 or more dockwidgets in
+    charge of handling tab rearangement.
+
+    This filter also holds the methods needed for the detection of a drag and
+    the movement of tabs.
+    """
+    def __init__(self, dock_tabbar, main):
+        QObject.__init__(self)
+        self.dock_tabbar = dock_tabbar
+        self.main = main
+        self.moving = False
+        self.from_index = None
+        self.to_index = None
+
+    # Helper methods
+    def _get_plugin(self, index):
+        """Get plugin reference based on tab index."""
+        for plugin in self.main.widgetlist:
+            if plugin.get_plugin_title() == self.dock_tabbar.tabText(index):
+                return plugin
+
+    def _get_plugins(self):
+        """
+        Get a list of all plugin references in the QTabBar to which this
+        event filter is attached.
+        """
+        plugins = []
+        for index in range(self.dock_tabbar.count()):
+            plugin = self._get_plugin(index)
+            plugins.append(plugin)
+        return plugins
+
+    def _fix_cursor(self, from_index, to_index):
+        """Fix mouse cursor position to adjust for different tab sizes."""
+        # The direction is +1 (moving to the right) or -1 (moving to the left)
+        direction = abs(to_index - from_index)/(to_index - from_index)
+
+        tab_width = self.dock_tabbar.tabRect(to_index).width()
+        tab_x_min = self.dock_tabbar.tabRect(to_index).x()
+        tab_x_max = tab_x_min + tab_width
+        previous_width = self.dock_tabbar.tabRect(to_index - direction).width()
+
+        delta = previous_width - tab_width
+        if delta > 0:
+            delta = delta * direction
+        else:
+            delta = 0
+        cursor = QCursor()
+        pos = self.dock_tabbar.mapFromGlobal(cursor.pos())
+        x, y = pos.x(), pos.y()
+        if x < tab_x_min or x > tab_x_max:
+            new_pos = self.dock_tabbar.mapToGlobal(QPoint(x + delta, y))
+            cursor.setPos(new_pos)
+
+    def eventFilter(self,  obj,  event):
+        """Filter mouse press events.
+
+        Events that are captured and not propagated return True. Events that
+        are not captured and are propagated return False.
+        """
+        event_type = event.type()
+        if event_type == QEvent.MouseButtonPress:
+            self.tab_pressed(event)
+            return False
+        if event_type == QEvent.MouseMove:
+            self.tab_moved(event)
+            return True
+        if event_type == QEvent.MouseButtonRelease:
+            self.tab_released(event)
+            return True
+        return False
+
+    def tab_pressed(self, event):
+        """Method called when a tab from a QTabBar has been pressed."""
+        self.from_index = self.dock_tabbar.tabAt(event.pos())
+        self.dock_tabbar.setCurrentIndex(self.from_index)
+
+        if event.button() == Qt.RightButton:
+            if self.from_index == -1:
+                self.show_nontab_menu(event)
+            else:
+                self.show_tab_menu(event)
+
+    def tab_moved(self, event):
+        """Method called when a tab from a QTabBar has been moved."""
+        # If the left button isn't pressed anymore then return
+        if not event.buttons() & Qt.LeftButton:
+            self.to_index = None
+            return
+
+        self.to_index = self.dock_tabbar.tabAt(event.pos())
+
+        if not self.moving and self.from_index != -1 and self.to_index != -1:
+            QApplication.setOverrideCursor(Qt.ClosedHandCursor)
+            self.moving = True
+
+        if self.to_index == -1:
+            self.to_index = self.from_index
+
+        from_index, to_index = self.from_index, self.to_index
+        if from_index != to_index and from_index != -1 and to_index != -1:
+            self.move_tab(from_index, to_index)
+            self._fix_cursor(from_index, to_index)
+            self.from_index = to_index
+
+    def tab_released(self, event):
+        """Method called when a tab from a QTabBar has been released."""
+        QApplication.restoreOverrideCursor()
+        self.moving = False
+
+    def move_tab(self, from_index, to_index):
+        """Move a tab from a given index to a given index position."""
+        plugins = self._get_plugins()
+        from_plugin = self._get_plugin(from_index)
+        to_plugin = self._get_plugin(to_index)
+
+        from_idx = plugins.index(from_plugin)
+        to_idx = plugins.index(to_plugin)
+
+        plugins[from_idx], plugins[to_idx] = plugins[to_idx], plugins[from_idx]
+
+        for i in range(len(plugins)-1):
+            self.main.tabify_plugins(plugins[i], plugins[i+1])
+        from_plugin.dockwidget.raise_()
+
+    def show_tab_menu(self, event):
+        """Show the context menu assigned to tabs."""
+        self.show_nontab_menu(event)
+
+    def show_nontab_menu(self, event):
+        """Show the context menu assigned to nontabs section."""
+        menu = self.main.createPopupMenu()
+        menu.exec_(self.dock_tabbar.mapToGlobal(event.pos()))
+
+
 class SpyderDockWidget(QDockWidget):
     """Subclass to override needed methods"""
+    plugin_closed = Signal()
+
+    def __init__(self, title, parent):
+        super(SpyderDockWidget, self).__init__(title, parent)
+
+        # Needed for the installation of the event filter
+        self.title = title
+        self.main = parent
+        self.dock_tabbar = None
+
+        # To track dockwidget changes the filter is installed when dockwidget
+        # visibility changes. This installs the filter on startup and also
+        # on dockwidgets that are undocked and then docked to a new location.
+        self.visibilityChanged.connect(self.install_tab_event_filter)
 
     def closeEvent(self, event):
         """
         Reimplement Qt method to send a signal on close so that "Panes" main
         window menu can be updated correctly
         """
-        self.emit(SIGNAL('plugin_closed()'))
+        self.plugin_closed.emit()
+
+    def install_tab_event_filter(self, value):
+        """
+        Install an event filter to capture mouse events in the tabs of a
+        QTabBar holding tabified dockwidgets.
+        """
+        dock_tabbar = None
+        tabbars = self.main.findChildren(QTabBar)
+        for tabbar in tabbars:
+            for tab in range(tabbar.count()):
+                title = tabbar.tabText(tab)
+                if title == self.title:
+                    dock_tabbar = tabbar
+                    break
+        if dock_tabbar is not None:
+            self.dock_tabbar = dock_tabbar
+            # Install filter only once per QTabBar
+            if getattr(self.dock_tabbar, 'filter', None) is None:
+                self.dock_tabbar.filter = TabFilter(self.dock_tabbar,
+                                                    self.main)
+                self.dock_tabbar.installEventFilter(self.dock_tabbar.filter)
 
 
 class SpyderPluginMixin(object):
@@ -69,24 +247,30 @@ class SpyderPluginMixin(object):
     See SpyderPluginWidget class for required widget interface
     
     Signals:
-        sig_option_changed
-            Example:
-            plugin.sig_option_changed.emit('show_all', checked)
-        'show_message(QString,int)'
+        * sig_option_changed
+             Example:
+             plugin.sig_option_changed.emit('show_all', checked)
+        * show_message
+        * update_plugin_title
     """
     CONF_SECTION = None
     CONFIGWIDGET_CLASS = None
+    IMG_PATH = 'images'
     ALLOWED_AREAS = Qt.AllDockWidgetAreas
     LOCATION = Qt.LeftDockWidgetArea
-    FEATURES = QDockWidget.DockWidgetClosable | \
-               QDockWidget.DockWidgetFloatable | \
-               QDockWidget.DockWidgetMovable
+    FEATURES = QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable
     DISABLE_ACTIONS_WHEN_HIDDEN = True
+
+    # Signals
     sig_option_changed = None
-    def __init__(self, main):
+    show_message = None
+    update_plugin_title = None
+
+    def __init__(self, main=None, **kwds):
         """Bind widget to a QMainWindow instance"""
-        super(SpyderPluginMixin, self).__init__()
+        super(SpyderPluginMixin, self).__init__(**kwds)
         assert self.CONF_SECTION is not None
+        self.PLUGIN_PATH = os.path.dirname(inspect.getfile(self.__class__))
         self.main = main
         self.default_margins = None
         self.plugin_actions = None
@@ -107,15 +291,15 @@ class SpyderPluginMixin(object):
         # We decided to create our own toggle action instead of using
         # the one that comes with dockwidget because it's not possible
         # to raise and focus the plugin with it.
-        self.toggle_view_action = None
+        self.toggle_view_action = None 
         
     def initialize_plugin(self):
         """Initialize plugin: connect signals, setup actions, ..."""
         self.plugin_actions = self.get_plugin_actions()
-        QObject.connect(self, SIGNAL('show_message(QString,int)'),
-                        self.show_message)
-        QObject.connect(self, SIGNAL('update_plugin_title()'),
-                        self.__update_plugin_title)
+        if self.show_message is not None:
+            self.show_message.connect(self.__show_message)
+        if self.update_plugin_title is not None:
+            self.update_plugin_title.connect(self.__update_plugin_title)
         if self.sig_option_changed is not None:
             self.sig_option_changed.connect(self.set_option)
         self.setWindowTitle(self.get_plugin_title())
@@ -178,10 +362,8 @@ class SpyderPluginMixin(object):
         dock.setFeatures(self.FEATURES)
         dock.setWidget(self)
         self.update_margins()
-        self.connect(dock, SIGNAL('visibilityChanged(bool)'),
-                     self.visibility_changed)
-        self.connect(dock, SIGNAL('plugin_closed()'),
-                     self.plugin_closed)
+        dock.visibilityChanged.connect(self.visibility_changed)
+        dock.plugin_closed.connect(self.plugin_closed)
         self.dockwidget = dock
         if self.shortcut is not None:
             sc = QShortcut(QKeySequence(self.shortcut), self.main,
@@ -196,9 +378,9 @@ class SpyderPluginMixin(object):
         """
         self.mainwindow = mainwindow = QMainWindow()
         mainwindow.setAttribute(Qt.WA_DeleteOnClose)
-        icon = self.get_widget_icon()
+        icon = self.get_plugin_icon()
         if is_text_string(icon):
-            icon = get_icon(icon)
+            icon = self.get_icon(icon)
         mainwindow.setWindowIcon(icon)
         mainwindow.setWindowTitle(self.get_plugin_title())
         mainwindow.setCentralWidget(self)
@@ -279,8 +461,8 @@ class SpyderPluginMixin(object):
     def set_plugin_font(self, font, option=None):
         """Set plugin font option"""
         set_font(font, self.CONF_SECTION, option)
-        
-    def show_message(self, message, timeout=0):
+
+    def __show_message(self, message, timeout=0):
         """Show message in main window's status bar"""
         self.main.statusBar().showMessage(message, timeout)
 
@@ -289,7 +471,7 @@ class SpyderPluginMixin(object):
         Showing message in main window's status bar
         and changing mouse cursor to Qt.WaitCursor
         """
-        self.show_message(message)
+        self.__show_message(message)
         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
         QApplication.processEvents()
         
@@ -299,7 +481,7 @@ class SpyderPluginMixin(object):
         and restoring mouse cursor
         """
         QApplication.restoreOverrideCursor()
-        self.show_message(message, timeout=2000)
+        self.__show_message(message, timeout=2000)
         QApplication.processEvents()
         
     def set_default_color_scheme(self, name='Spyder'):
@@ -317,11 +499,13 @@ class SpyderPluginMixin(object):
         if self.CONF_SECTION == 'editor':
             title = _('Editor')
         if self.shortcut is not None:
-            action = create_action(self, title, toggled=self.toggle_view,
-                                   shortcut=QKeySequence(self.shortcut))
+            action = create_action(self, title,
+                             toggled=lambda checked: self.toggle_view(checked),
+                             shortcut=QKeySequence(self.shortcut))
             action.setShortcutContext(Qt.WidgetWithChildrenShortcut)
         else:
-            action = create_action(self, title, toggled=self.toggle_view)
+            action = create_action(self, title, toggled=lambda checked:
+                                                self.toggle_view(checked))
         self.toggle_view_action = action
     
     def toggle_view(self, checked):
@@ -339,10 +523,16 @@ class SpyderPluginWidget(QWidget, SpyderPluginMixin):
     Spyder's widgets either inherit this class or reimplement its interface
     """
     sig_option_changed = Signal(str, object)
-    
-    def __init__(self, parent):
-        QWidget.__init__(self, parent)
-        SpyderPluginMixin.__init__(self, parent)
+    show_message = Signal(str, int)
+    update_plugin_title = Signal()
+
+    if PYQT5:
+        def __init__(self, parent, **kwds):
+            super(SpyderPluginWidget, self).__init__(parent, **kwds)
+    else:
+        def __init__(self, parent):
+            QWidget.__init__(self, parent)
+            SpyderPluginMixin.__init__(self, parent)
         
     def get_plugin_title(self):
         """
@@ -359,7 +549,7 @@ class SpyderPluginWidget(QWidget, SpyderPluginMixin):
               (see SpyderPluginMixin.create_mainwindow)
               and for configuration dialog widgets creation
         """
-        return get_icon('qt.png')
+        return ima.icon('outline_explorer')
     
     def get_focus_widget(self):
         """
@@ -374,7 +564,7 @@ class SpyderPluginWidget(QWidget, SpyderPluginMixin):
         Return True or False whether the plugin may be closed immediately or not
         Note: returned value is ignored if *cancelable* is False
         """
-        raise NotImplementedError
+        return True
         
     def refresh_plugin(self):
         """Refresh widget"""
diff --git a/spyderlib/plugins/configdialog.py b/spyderlib/plugins/configdialog.py
index 6f54fa8..a35008a 100644
--- a/spyderlib/plugins/configdialog.py
+++ b/spyderlib/plugins/configdialog.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -8,15 +8,7 @@
 
 import os.path as osp
 
-from spyderlib.baseconfig import _, running_in_mac_app
-from spyderlib.config import CONF, is_gtk_desktop
-from spyderlib.guiconfig import (CUSTOM_COLOR_SCHEME_NAME,
-                                 set_default_color_scheme)
-from spyderlib.utils.qthelpers import get_icon, get_std_icon
-from spyderlib.userconfig import NoDefault
-from spyderlib.widgets.colors import ColorLayout
-from spyderlib.widgets.sourcecode import syntaxhighlighters as sh
-
+from spyderlib.qt import API
 from spyderlib.qt.QtGui import (QWidget, QDialog, QListWidget, QListWidgetItem,
                                 QVBoxLayout, QStackedWidget, QListView,
                                 QHBoxLayout, QDialogButtonBox, QCheckBox,
@@ -25,9 +17,19 @@ from spyderlib.qt.QtGui import (QWidget, QDialog, QListWidget, QListWidgetItem,
                                 QComboBox, QColor, QGridLayout, QTabWidget,
                                 QRadioButton, QButtonGroup, QSplitter,
                                 QStyleFactory, QScrollArea, QDoubleSpinBox)
-from spyderlib.qt.QtCore import Qt, QSize, SIGNAL, SLOT, Slot
+from spyderlib.qt.QtCore import Qt, QSize, Signal, Slot
 from spyderlib.qt.compat import (to_qvariant, from_qvariant,
                                  getexistingdirectory, getopenfilename)
+import spyderlib.utils.icon_manager as ima
+
+from spyderlib.config.base import (_, running_in_mac_app, LANGUAGE_CODES,
+                                   save_lang_conf, load_lang_conf)
+from spyderlib.config.main import CONF, is_gtk_desktop
+from spyderlib.config.gui import (CUSTOM_COLOR_SCHEME_NAME,
+                                  set_default_color_scheme)
+from spyderlib.config.user import NoDefault
+from spyderlib.utils import syntaxhighlighters as sh
+from spyderlib.widgets.colors import ColorLayout
 from spyderlib.py3compat import to_text_string, is_text_string, getcwd
 
 
@@ -45,6 +47,10 @@ class ConfigAccessMixin(object):
 class ConfigPage(QWidget):
     """Base class for configuration page in Preferences"""
 
+    # Signals
+    apply_button_enabled = Signal(bool)
+    show_this_page = Signal()
+
     def __init__(self, parent, apply_callback=None):
         QWidget.__init__(self, parent)
         self.apply_callback = apply_callback
@@ -73,8 +79,8 @@ class ConfigPage(QWidget):
         
     def set_modified(self, state):
         self.is_modified = state
-        self.emit(SIGNAL("apply_button_enabled(bool)"), state)
-        
+        self.apply_button_enabled.emit(state)
+    
     def is_valid(self):
         """Return True if all widget contents are valid"""
         raise NotImplementedError
@@ -85,8 +91,21 @@ class ConfigPage(QWidget):
             self.save_to_conf()
             if self.apply_callback is not None:
                 self.apply_callback()
+
+            # Since the language cannot be retrieved by CONF and the language
+            # is needed before loading CONF, this is an extra method needed to
+            # ensure that when changes are applied, they are copied to a
+            # specific file storing the language value. This only applies to
+            # the main section config.
+            if self.CONF_SECTION == u'main':
+                self._save_lang()
+
+            for restart_option in self.restart_options:
+                if restart_option in self.changed_options:
+                    self.prompt_restart_required()
+                    break  # Ensure a single popup is displayed
             self.set_modified(False)
-    
+
     def load_from_conf(self):
         """Load settings from configuration file"""
         raise NotImplementedError
@@ -98,40 +117,44 @@ class ConfigPage(QWidget):
 
 class ConfigDialog(QDialog):
     """Spyder configuration ('Preferences') dialog box"""
+    
+    # Signals
+    check_settings = Signal()
+    size_change = Signal(QSize)
+    
     def __init__(self, parent=None):
         QDialog.__init__(self, parent)
-        
+
+        self.main = parent
+
+        # Widgets
+        self.pages_widget = QStackedWidget()
+        self.contents_widget = QListWidget()
+        self.button_reset = QPushButton(_('Reset to defaults'))
+
+        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Apply |
+                                QDialogButtonBox.Cancel)
+        self.apply_btn = bbox.button(QDialogButtonBox.Apply)
+
+        # Widgets setup
         # Destroying the C++ object right after closing the dialog box,
         # otherwise it may be garbage-collected in another QThread
         # (e.g. the editor's analysis thread in Spyder), thus leading to
         # a segmentation fault on UNIX or an application crash on Windows
         self.setAttribute(Qt.WA_DeleteOnClose)
-
-        self.contents_widget = QListWidget()
+        self.setWindowTitle(_('Preferences'))
+        self.setWindowIcon(ima.icon('configure'))
         self.contents_widget.setMovement(QListView.Static)
         self.contents_widget.setSpacing(1)
-
-        bbox = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Apply
-                                |QDialogButtonBox.Cancel)
-        self.apply_btn = bbox.button(QDialogButtonBox.Apply)
-        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
-        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
-        self.connect(bbox, SIGNAL("clicked(QAbstractButton*)"),
-                     self.button_clicked)
-
-        self.pages_widget = QStackedWidget()
-        self.connect(self.pages_widget, SIGNAL("currentChanged(int)"),
-                     self.current_page_changed)
-
-        self.connect(self.contents_widget, SIGNAL("currentRowChanged(int)"),
-                     self.pages_widget.setCurrentIndex)
         self.contents_widget.setCurrentRow(0)
 
+        # Layout
         hsplitter = QSplitter()
         hsplitter.addWidget(self.contents_widget)
         hsplitter.addWidget(self.pages_widget)
 
         btnlayout = QHBoxLayout()
+        btnlayout.addWidget(self.button_reset)
         btnlayout.addStretch(1)
         btnlayout.addWidget(bbox)
 
@@ -141,9 +164,18 @@ class ConfigDialog(QDialog):
 
         self.setLayout(vlayout)
 
-        self.setWindowTitle(_("Preferences"))
-        self.setWindowIcon(get_icon("configure.png"))
-        
+        # Signals and slots
+        self.button_reset.clicked.connect(self.main.reset_spyder)
+        self.pages_widget.currentChanged.connect(self.current_page_changed)
+        self.contents_widget.currentRowChanged.connect(
+                                             self.pages_widget.setCurrentIndex)
+        bbox.accepted.connect(self.accept)
+        bbox.rejected.connect(self.reject)
+        bbox.clicked.connect(self.button_clicked)
+
+        # Ensures that the config is present on spyder first run
+        CONF.set('main', 'interface_language', load_lang_conf())
+
     def get_current_index(self):
         """Return current page index"""
         return self.contents_widget.currentRow()
@@ -159,7 +191,8 @@ class ConfigDialog(QDialog):
         else:
             widget = self.pages_widget.widget(index)
         return widget.widget()
-        
+    
+    @Slot()
     def accept(self):
         """Reimplement Qt method"""
         for index in range(self.pages_widget.count()):
@@ -183,12 +216,10 @@ class ConfigDialog(QDialog):
         self.apply_btn.setEnabled(widget.is_modified)
         
     def add_page(self, widget):
-        self.connect(self, SIGNAL('check_settings()'), widget.check_settings)
-        self.connect(widget, SIGNAL('show_this_page()'),
-                     lambda row=self.contents_widget.count():
-                     self.contents_widget.setCurrentRow(row))
-        self.connect(widget, SIGNAL("apply_button_enabled(bool)"),
-                     self.apply_btn.setEnabled)
+        self.check_settings.connect(widget.check_settings)
+        widget.show_this_page.connect(lambda row=self.contents_widget.count():
+                                      self.contents_widget.setCurrentRow(row))
+        widget.apply_button_enabled.connect(self.apply_btn.setEnabled)
         scrollarea = QScrollArea(self)
         scrollarea.setWidgetResizable(True)
         scrollarea.setWidget(widget)
@@ -202,7 +233,7 @@ class ConfigDialog(QDialog):
     def check_all_settings(self):
         """This method is called to check all configuration page settings
         after configuration dialog has been shown"""
-        self.emit(SIGNAL('check_settings()'))
+        self.check_settings.emit()
     
     def resizeEvent(self, event):
         """
@@ -210,7 +241,7 @@ class ConfigDialog(QDialog):
         main application
         """
         QDialog.resizeEvent(self, event)
-        self.emit(SIGNAL("size_change(QSize)"), self.size())
+        self.size_change.emit(self.size())
 
 
 class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
@@ -231,6 +262,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
         self.coloredits = {}
         self.scedits = {}
         self.changed_options = set()
+        self.restart_options = dict()  # Dict to store name and localized text
         self.default_button_group = None
         
     def apply_settings(self, options):
@@ -263,24 +295,25 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
         """Load settings from configuration file"""
         for checkbox, (option, default) in list(self.checkboxes.items()):
             checkbox.setChecked(self.get_option(option, default))
-            self.connect(checkbox, SIGNAL("clicked(bool)"),
-                         lambda _foo, opt=option: self.has_been_modified(opt))
+            # Checkboxes work differently for PySide and PyQt
+            if API == 'pyqt':
+                checkbox.clicked.connect(lambda _foo, opt=option:
+                                         self.has_been_modified(opt))
+            else:
+                checkbox.clicked.connect(lambda opt=option:
+                                         self.has_been_modified(opt))
         for radiobutton, (option, default) in list(self.radiobuttons.items()):
             radiobutton.setChecked(self.get_option(option, default))
-            self.connect(radiobutton, SIGNAL("toggled(bool)"),
-                         lambda _foo, opt=option: self.has_been_modified(opt))
+            radiobutton.toggled.connect(lambda _foo, opt=option:
+                                        self.has_been_modified(opt))
         for lineedit, (option, default) in list(self.lineedits.items()):
             lineedit.setText(self.get_option(option, default))
-            self.connect(lineedit, SIGNAL("textChanged(QString)"),
-                         lambda _foo, opt=option: self.has_been_modified(opt))
+            lineedit.textChanged.connect(lambda _foo, opt=option:
+                                         self.has_been_modified(opt))
         for spinbox, (option, default) in list(self.spinboxes.items()):
             spinbox.setValue(self.get_option(option, default))
-            if type(spinbox) is QSpinBox:
-                self.connect(spinbox, SIGNAL('valueChanged(int)'),
-                             lambda _foo, opt=option: self.has_been_modified(opt))
-            else:
-                self.connect(spinbox, SIGNAL('valueChanged(double)'),
-                             lambda _foo, opt=option: self.has_been_modified(opt))
+            spinbox.valueChanged.connect(lambda _foo, opt=option:
+                                         self.has_been_modified(opt))
         for combobox, (option, default) in list(self.comboboxes.items()):
             value = self.get_option(option, default)
             for index in range(combobox.count()):
@@ -291,8 +324,11 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
                 if to_text_string(data) == to_text_string(value):
                     break
             combobox.setCurrentIndex(index)
-            self.connect(combobox, SIGNAL('currentIndexChanged(int)'),
-                         lambda _foo, opt=option: self.has_been_modified(opt))
+            combobox.currentIndexChanged.connect(lambda _foo, opt=option:
+                                                 self.has_been_modified(opt))
+            if combobox.restart_required:
+                self.restart_options[option] = combobox.label_text
+
         for (fontbox, sizebox), option in list(self.fontboxes.items()):
             font = self.get_font(option)
             fontbox.setCurrentFont(font)
@@ -301,19 +337,18 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
                 property = 'plugin_font'
             else:
                 property = option
-            self.connect(fontbox, SIGNAL('currentIndexChanged(int)'),
-                         lambda _foo, opt=property: self.has_been_modified(opt))
-            self.connect(sizebox, SIGNAL('valueChanged(int)'),
-                         lambda _foo, opt=property: self.has_been_modified(opt))
+            fontbox.currentIndexChanged.connect(lambda _foo, opt=property:
+                                                self.has_been_modified(opt))
+            sizebox.valueChanged.connect(lambda _foo, opt=property:
+                                         self.has_been_modified(opt))
         for clayout, (option, default) in list(self.coloredits.items()):
             property = to_qvariant(option)
             edit = clayout.lineedit
             btn = clayout.colorbtn
             edit.setText(self.get_option(option, default))
-            self.connect(btn, SIGNAL('clicked()'),
-                         lambda opt=option: self.has_been_modified(opt))
-            self.connect(edit, SIGNAL("textChanged(QString)"),
-                         lambda _foo, opt=option: self.has_been_modified(opt))
+            btn.clicked.connect(lambda opt=option: self.has_been_modified(opt))
+            edit.textChanged.connect(lambda _foo, opt=option:
+                                     self.has_been_modified(opt))
         for (clayout, cb_bold, cb_italic
              ), (option, default) in list(self.scedits.items()):
             edit = clayout.lineedit
@@ -322,15 +357,22 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
             edit.setText(color)
             cb_bold.setChecked(bold)
             cb_italic.setChecked(italic)
-            self.connect(btn, SIGNAL('clicked()'),
-                         lambda opt=option: self.has_been_modified(opt))
-            self.connect(edit, SIGNAL("textChanged(QString)"),
-                         lambda _foo, opt=option: self.has_been_modified(opt))
-            self.connect(cb_bold, SIGNAL("clicked(bool)"),
-                         lambda _foo, opt=option: self.has_been_modified(opt))
-            self.connect(cb_italic, SIGNAL("clicked(bool)"),
-                         lambda _foo, opt=option: self.has_been_modified(opt))
-    
+            btn.clicked.connect(lambda opt=option: self.has_been_modified(opt))
+            edit.textChanged.connect(lambda _foo, opt=option:
+                                     self.has_been_modified(opt))
+            if API == 'pyqt':
+                cb_bold.clicked.connect(lambda _foo, opt=option:
+                                        self.has_been_modified(opt))
+            else:
+                cb_bold.clicked.connect(lambda opt=option:
+                                        self.has_been_modified(opt))
+            if API == 'pyqt':
+                cb_italic.clicked.connect(lambda _foo, opt=option:
+                                          self.has_been_modified(opt))
+            else:
+                cb_italic.clicked.connect(lambda opt=option:
+                                          self.has_been_modified(opt))
+
     def save_to_conf(self):
         """Save settings to configuration file"""
         for checkbox, (option, _default) in list(self.checkboxes.items()):
@@ -360,7 +402,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
     def has_been_modified(self, option):
         self.set_modified(True)
         self.changed_options.add(option)
-    
+
     def create_checkbox(self, text, option, default=NoDefault,
                         tip=None, msg_warning=None, msg_info=None,
                         msg_if_enabled=False):
@@ -377,7 +419,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
                     if msg_info is not None:
                         QMessageBox.information(self, self.get_name(),
                                                 msg_info, QMessageBox.Ok)
-            self.connect(checkbox, SIGNAL("clicked(bool)"), show_message)
+            checkbox.clicked.connect(show_message)
         return checkbox
     
     def create_radiobutton(self, text, option, default=NoDefault,
@@ -401,7 +443,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
                     if msg_info is not None:
                         QMessageBox.information(self, self.get_name(),
                                                 msg_info, QMessageBox.Ok)
-            self.connect(radiobutton, SIGNAL("toggled(bool)"), show_message)
+            radiobutton.toggled.connect(show_message)
         return radiobutton
     
     def create_lineedit(self, text, option, default=NoDefault,
@@ -417,6 +459,8 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
             edit.setToolTip(tip)
         self.lineedits[edit] = (option, default)
         widget = QWidget(self)
+        widget.label = label
+        widget.textbox = edit 
         widget.setLayout(layout)
         return widget
     
@@ -428,10 +472,9 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
                 break
         msg = _("Invalid directory path")
         self.validate_data[edit] = (osp.isdir, msg)
-        browse_btn = QPushButton(get_std_icon('DirOpenIcon'), "", self)
+        browse_btn = QPushButton(ima.icon('DirOpenIcon'), '', self)
         browse_btn.setToolTip(_("Select directory"))
-        self.connect(browse_btn, SIGNAL("clicked()"),
-                     lambda: self.select_directory(edit))
+        browse_btn.clicked.connect(lambda: self.select_directory(edit))
         layout = QHBoxLayout()
         layout.addWidget(widget)
         layout.addWidget(browse_btn)
@@ -457,12 +500,11 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
         for edit in self.lineedits:
             if widget.isAncestorOf(edit):
                 break
-        msg = _("Invalid file path")
+        msg = _('Invalid file path')
         self.validate_data[edit] = (osp.isfile, msg)
-        browse_btn = QPushButton(get_std_icon('FileIcon'), "", self)
+        browse_btn = QPushButton(ima.icon('FileIcon'), '', self)
         browse_btn.setToolTip(_("Select file"))
-        self.connect(browse_btn, SIGNAL("clicked()"),
-                     lambda: self.select_file(edit, filters))
+        browse_btn.clicked.connect(lambda: self.select_file(edit, filters))
         layout = QHBoxLayout()
         layout.addWidget(widget)
         layout.addWidget(browse_btn)
@@ -485,12 +527,15 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
     
     def create_spinbox(self, prefix, suffix, option, default=NoDefault,
                        min_=None, max_=None, step=None, tip=None):
+        widget = QWidget(self)
         if prefix:
             plabel = QLabel(prefix)
+            widget.plabel = plabel
         else:
             plabel = None
         if suffix:
             slabel = QLabel(suffix)
+            widget.slabel = slabel
         else:
             slabel = None
         if step is not None:
@@ -515,7 +560,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
                 layout.addWidget(subwidget)
         layout.addStretch(1)
         layout.setContentsMargins(0, 0, 0, 0)
-        widget = QWidget(self)
+        widget.spinbox = spinbox
         widget.setLayout(layout)
         return widget
     
@@ -546,10 +591,10 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
         if tip is not None:
             clayout.setToolTip(tip)
         cb_bold = QCheckBox()
-        cb_bold.setIcon(get_icon("bold.png"))
+        cb_bold.setIcon(ima.icon('bold'))
         cb_bold.setToolTip(_("Bold"))
         cb_italic = QCheckBox()
-        cb_italic.setIcon(get_icon("italic.png"))
+        cb_italic.setIcon(ima.icon('italic'))
         cb_italic.setToolTip(_("Italic"))
         self.scedits[(clayout, cb_bold, cb_italic)] = (option, default)
         if without_layout:
@@ -567,7 +612,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
         return widget
     
     def create_combobox(self, text, choices, option, default=NoDefault,
-                        tip=None):
+                        tip=None, restart=False):
         """choices: couples (name, key)"""
         label = QLabel(text)
         combobox = QComboBox()
@@ -577,12 +622,16 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
             combobox.addItem(name, to_qvariant(key))
         self.comboboxes[combobox] = (option, default)
         layout = QHBoxLayout()
-        for subwidget in (label, combobox):
-            layout.addWidget(subwidget)
+        layout.addWidget(label)
+        layout.addWidget(combobox)
         layout.addStretch(1)
         layout.setContentsMargins(0, 0, 0, 0)
         widget = QWidget(self)
+        widget.label = label
+        widget.combobox = combobox
         widget.setLayout(layout)
+        combobox.restart_required = restart
+        combobox.label_text = text
         return widget
     
     def create_fontgroup(self, option=None, text=None,
@@ -610,9 +659,8 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
     
     def create_button(self, text, callback):
         btn = QPushButton(text)
-        self.connect(btn, SIGNAL('clicked()'), callback)
-        self.connect(btn, SIGNAL('clicked()'),
-                     lambda opt='': self.has_been_modified(opt))
+        btn.clicked.connect(callback)
+        btn.clicked.connect(lambda opt='': self.has_been_modified(opt))
         return btn
     
     def create_tab(self, *widgets):
@@ -645,18 +693,47 @@ class GeneralConfigPage(SpyderConfigPage):
     
     def get_icon(self):
         """Loads page icon named by self.ICON"""
-        return get_icon(self.ICON)
+        return self.ICON
 
     def apply_settings(self, options):
         raise NotImplementedError
 
+    def prompt_restart_required(self):
+        """Prompt the user with a request to restart."""
+        restart_opts = self.restart_options
+        changed_opts = self.changed_options
+        options = [restart_opts[o] for o in changed_opts if o in restart_opts]
+
+        if len(options) == 1:
+            msg_start = _("Spyder needs to restart to change the following "
+                          "setting:")
+        else:
+            msg_start = _("Spyder needs to restart to change the following "
+                          "settings:")
+        msg_end = _("Do you wish to restart now?")
+
+        msg_options = ""
+        for option in options:
+            msg_options += "<li>{0}</li>".format(option)
+
+        msg_title = _("Information")
+        msg = "{0}<ul>{1}</ul><br>{2}".format(msg_start, msg_options, msg_end)
+        answer = QMessageBox.information(self, msg_title, msg,
+                                         QMessageBox.Yes | QMessageBox.No)
+        if answer == QMessageBox.Yes:
+            self.restart()
+
+    def restart(self):
+        """Restart Spyder."""
+        self.main.restart()
+
 
 class MainConfigPage(GeneralConfigPage):
     CONF_SECTION = "main"
     
     NAME = _("General")
-    ICON = "genprefs.png"
-    
+    ICON = ima.icon('genprefs')
+
     def setup_page(self):
         newcb = self.create_checkbox
 
@@ -673,73 +750,113 @@ class MainConfigPage(GeneralConfigPage):
                                            'windows_style',
                                            default=self.main.default_style)
 
+        themes = ['Spyder 2', 'Spyder 3']
+        icon_choices = list(zip(themes, [theme.lower() for theme in themes]))
+        icons_combo = self.create_combobox(_('Icon theme'), icon_choices,
+                                           'icon_theme', restart=True)
+
+        languages = LANGUAGE_CODES.items()
+        language_choices = sorted([(val, key) for key, val in languages])
+        language_combo = self.create_combobox(_('Language'), language_choices,
+                                              'interface_language',
+                                              restart=True)
+
         single_instance_box = newcb(_("Use a single instance"),
                                     'single_instance',
                                     tip=_("Set this to open external<br> "
                                           "Python files in an already running "
                                           "instance (Requires a restart)"))
-        vertdock_box = newcb(_("Vertical dockwidget title bars"),
+        vertdock_box = newcb(_("Vertical title bars in panes"),
                              'vertical_dockwidget_titlebars')
-        verttabs_box = newcb(_("Vertical dockwidget tabs"),
+        verttabs_box = newcb(_("Vertical tabs in panes"),
                              'vertical_tabs')
-        animated_box = newcb(_("Animated toolbars and dockwidgets"),
+        animated_box = newcb(_("Animated toolbars and panes"),
                              'animated_docks')
         tear_off_box = newcb(_("Tear off menus"), 'tear_off_menus',
                              tip=_("Set this to detach any<br> "
                                    "menu from the main window"))
-        margin_box = newcb(_("Custom dockwidget margin:"),
+        margin_box = newcb(_("Custom margin for panes:"),
                            'use_custom_margin')
         margin_spin = self.create_spinbox("", "pixels", 'custom_margin',
                                           0, 0, 30)
-        self.connect(margin_box, SIGNAL("toggled(bool)"),
-                     margin_spin.setEnabled)
+        margin_box.toggled.connect(margin_spin.setEnabled)
         margin_spin.setEnabled(self.get_option('use_custom_margin'))
         margins_layout = QHBoxLayout()
         margins_layout.addWidget(margin_box)
         margins_layout.addWidget(margin_spin)
+        prompt_box = newcb(_("Prompt when exiting"), 'prompt_on_exit')
 
-        # Decide if it's possible to activate or not singie instance mode
+        # Decide if it's possible to activate or not single instance mode
         if running_in_mac_app():
             self.set_option("single_instance", True)
             single_instance_box.setEnabled(False)
+
+        # Layout interface
+        comboboxes_layout = QHBoxLayout()
+        cbs_layout = QGridLayout()
+        cbs_layout.addWidget(style_combo.label, 0, 0)
+        cbs_layout.addWidget(style_combo.combobox, 0, 1)
+        cbs_layout.addWidget(icons_combo.label, 1, 0)
+        cbs_layout.addWidget(icons_combo.combobox, 1, 1)
+        cbs_layout.addWidget(language_combo.label, 2, 0)
+        cbs_layout.addWidget(language_combo.combobox, 2, 1)
+        comboboxes_layout.addLayout(cbs_layout)
+        comboboxes_layout.addStretch(1)
         
         interface_layout = QVBoxLayout()
-        interface_layout.addWidget(style_combo)
+        interface_layout.addLayout(comboboxes_layout)
         interface_layout.addWidget(single_instance_box)
         interface_layout.addWidget(vertdock_box)
         interface_layout.addWidget(verttabs_box)
         interface_layout.addWidget(animated_box)
         interface_layout.addWidget(tear_off_box)
         interface_layout.addLayout(margins_layout)
+        interface_layout.addWidget(prompt_box)
         interface_group.setLayout(interface_layout)
 
         # --- Status bar
         sbar_group = QGroupBox(_("Status bar"))
+        show_status_bar = newcb(_("Show status bar"), 'show_status_bar')
+
         memory_box = newcb(_("Show memory usage every"), 'memory_usage/enable',
                            tip=self.main.mem_status.toolTip())
         memory_spin = self.create_spinbox("", " ms", 'memory_usage/timeout',
                                           min_=100, max_=1000000, step=100)
-        self.connect(memory_box, SIGNAL("toggled(bool)"),
-                     memory_spin.setEnabled)
+        memory_box.toggled.connect(memory_spin.setEnabled)
         memory_spin.setEnabled(self.get_option('memory_usage/enable'))
-        memory_layout = QHBoxLayout()
-        memory_layout.addWidget(memory_box)
-        memory_layout.addWidget(memory_spin)
-        memory_layout.setEnabled(self.main.mem_status.is_supported())
+        memory_box.setEnabled(self.main.mem_status.is_supported())
+        memory_spin.setEnabled(self.main.mem_status.is_supported())
+
         cpu_box = newcb(_("Show CPU usage every"), 'cpu_usage/enable',
                         tip=self.main.cpu_status.toolTip())
         cpu_spin = self.create_spinbox("", " ms", 'cpu_usage/timeout',
                                        min_=100, max_=1000000, step=100)
-        self.connect(cpu_box, SIGNAL("toggled(bool)"), cpu_spin.setEnabled)
+        cpu_box.toggled.connect(cpu_spin.setEnabled)
         cpu_spin.setEnabled(self.get_option('cpu_usage/enable'))
-        cpu_layout = QHBoxLayout()
-        cpu_layout.addWidget(cpu_box)
-        cpu_layout.addWidget(cpu_spin)
-        cpu_layout.setEnabled(self.main.cpu_status.is_supported())
+
+        cpu_box.setEnabled(self.main.cpu_status.is_supported())
+        cpu_spin.setEnabled(self.main.cpu_status.is_supported())
         
+        status_bar_o = self.get_option('show_status_bar')
+        show_status_bar.toggled.connect(memory_box.setEnabled)
+        show_status_bar.toggled.connect(memory_spin.setEnabled)
+        show_status_bar.toggled.connect(cpu_box.setEnabled)
+        show_status_bar.toggled.connect(cpu_spin.setEnabled)
+        memory_box.setEnabled(status_bar_o)
+        memory_spin.setEnabled(status_bar_o)
+        cpu_box.setEnabled(status_bar_o)
+        cpu_spin.setEnabled(status_bar_o)
+
+        # Layout status bar
+        cpu_memory_layout = QGridLayout()
+        cpu_memory_layout.addWidget(memory_box, 0, 0)
+        cpu_memory_layout.addWidget(memory_spin, 0, 1)
+        cpu_memory_layout.addWidget(cpu_box, 1, 0)
+        cpu_memory_layout.addWidget(cpu_spin, 1, 1)
+
         sbar_layout = QVBoxLayout()
-        sbar_layout.addLayout(memory_layout)
-        sbar_layout.addLayout(cpu_layout)
+        sbar_layout.addWidget(show_status_bar)
+        sbar_layout.addLayout(cpu_memory_layout)
         sbar_group.setLayout(sbar_layout)
 
         # --- Debugging
@@ -751,23 +868,44 @@ class MainConfigPage(GeneralConfigPage):
         debug_layout = QVBoxLayout()
         debug_layout.addWidget(popup_console_box)
         debug_group.setLayout(debug_layout)
+
+        # --- Spyder updates
+        update_group = QGroupBox(_("Updates"))
+        check_updates = newcb(_("Check for updates on startup"),
+                              'check_updates_on_startup')
+        update_layout = QVBoxLayout()
+        update_layout.addWidget(check_updates)
+        update_group.setLayout(update_layout)
         
         vlayout = QVBoxLayout()
         vlayout.addWidget(interface_group)
         vlayout.addWidget(sbar_group)
         vlayout.addWidget(debug_group)
+        vlayout.addWidget(update_group)
         vlayout.addStretch(1)
         self.setLayout(vlayout)
-        
+
     def apply_settings(self, options):
         self.main.apply_settings()
 
+    def _save_lang(self):
+        """
+        Get selected language setting and save to language configuration file.
+        """
+        for combobox, (option, _default) in list(self.comboboxes.items()):
+            if option == 'interface_language':
+                data = combobox.itemData(combobox.currentIndex())
+                value = from_qvariant(data, to_text_string)
+                break
+        save_lang_conf(value)
+        self.set_option('interface_language', value)
+
 
 class ColorSchemeConfigPage(GeneralConfigPage):
     CONF_SECTION = "color_schemes"
     
     NAME = _("Syntax coloring")
-    ICON = "genprefs.png"
+    ICON = ima.icon('eyedropper')
     
     def setup_page(self):
         tabs = QTabWidget()
@@ -792,7 +930,7 @@ class ColorSchemeConfigPage(GeneralConfigPage):
                       "number":         _("Number:"),
                       "instance":       _("Instance:"),
                       }
-        from spyderlib.widgets.sourcecode import syntaxhighlighters
+        from spyderlib.utils import syntaxhighlighters
         assert all([key in fieldnames
                     for key in syntaxhighlighters.COLOR_SCHEME_KEYS])
         for tabname in names:
diff --git a/spyderlib/plugins/console.py b/spyderlib/plugins/console.py
index 20a937b..cf5ed9e 100644
--- a/spyderlib/plugins/console.py
+++ b/spyderlib/plugins/console.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -11,10 +11,12 @@
 # pylint: disable=R0911
 # pylint: disable=R0201
 
+from spyderlib.qt import PYQT5
 from spyderlib.qt.QtGui import (QVBoxLayout, QFontDialog, QInputDialog,
                                 QLineEdit, QMenu)
-from spyderlib.qt.QtCore import SIGNAL
+from spyderlib.qt.QtCore import Signal, Slot
 from spyderlib.qt.compat import getopenfilename
+import spyderlib.utils.icon_manager as ima
 
 import os
 import sys
@@ -22,27 +24,34 @@ import os.path as osp
 
 
 # Local imports
-from spyderlib.baseconfig import _, debug_print
-from spyderlib.config import CONF
+from spyderlib.config.base import _, debug_print
+from spyderlib.config.main import CONF
 from spyderlib.utils.misc import get_error_match, remove_backslashes
-from spyderlib.utils.qthelpers import (get_icon, create_action, add_actions,
+from spyderlib.utils.qthelpers import (create_action, add_actions,
                                        mimedata2url, DialogManager)
 from spyderlib.utils.environ import EnvDialog
 from spyderlib.widgets.internalshell import InternalShell
 from spyderlib.widgets.findreplace import FindReplace
-from spyderlib.widgets.dicteditor import DictEditor
+from spyderlib.widgets.variableexplorer.collectionseditor import CollectionsEditor
 from spyderlib.plugins import SpyderPluginWidget
 from spyderlib.py3compat import to_text_string, getcwd
 
-    
+
 class Console(SpyderPluginWidget):
     """
     Console widget
     """
     CONF_SECTION = 'internal_console'
+    focus_changed = Signal()
+    redirect_stdio = Signal(bool)
+    edit_goto = Signal(str, int, str)
+    
     def __init__(self, parent=None, namespace=None, commands=[], message=None,
                  exitfunc=None, profile=False, multithreaded=False):
-        SpyderPluginWidget.__init__(self, parent)
+        if PYQT5:
+            SpyderPluginWidget.__init__(self, parent, main = parent)
+        else:
+            SpyderPluginWidget.__init__(self, parent)
         
         debug_print("    ..internal console: initializing")
         self.dialog_manager = DialogManager()
@@ -54,21 +63,17 @@ class Console(SpyderPluginWidget):
                                    self.get_plugin_font(), exitfunc, profile,
                                    multithreaded,
                                    light_background=light_background)
-        self.connect(self.shell, SIGNAL('status(QString)'),
-                     lambda msg:
-                     self.emit(SIGNAL('show_message(QString,int)'), msg, 0))
-        self.connect(self.shell, SIGNAL("go_to_error(QString)"),
-                     self.go_to_error)
-        self.connect(self.shell, SIGNAL("focus_changed()"),
-                     lambda: self.emit(SIGNAL("focus_changed()")))
-        # Redirecting some SIGNALs:
-        self.connect(self.shell, SIGNAL('redirect_stdio(bool)'),
-                     lambda state: self.emit(SIGNAL('redirect_stdio(bool)'),
-                                             state))
+        self.shell.status.connect(lambda msg: self.show_message.emit(msg, 0))
+        self.shell.go_to_error.connect(self.go_to_error)
+        self.shell.focus_changed.connect(lambda: self.focus_changed.emit())
+
+        # Redirecting some signals:
+        self.shell.redirect_stdio.connect(lambda state:
+                                          self.redirect_stdio.emit(state))
         
         # Initialize plugin
         self.initialize_plugin()
-                
+
         # Find/replace widget
         self.find_widget = FindReplace(self)
         self.find_widget.set_editor(self.shell)
@@ -92,8 +97,7 @@ class Console(SpyderPluginWidget):
         """Bind historylog instance to this console
         Not used anymore since v2.0"""
         historylog.add_history(self.shell.history_filename)
-        self.connect(self.shell, SIGNAL('append_to_history(QString,QString)'),
-                     historylog.append_to_history)
+        self.shell.append_to_history.connect(historylog.append_to_history)
         
     def set_inspector(self, inspector):
         """Bind inspector instance to this console"""
@@ -123,21 +127,23 @@ class Console(SpyderPluginWidget):
     def get_plugin_actions(self):
         """Return a list of actions related to plugin"""
         quit_action = create_action(self, _("&Quit"),
-                                    icon='exit.png', tip=_("Quit"),
+                                    icon=ima.icon('exit'), 
+                                    tip=_("Quit"),
                                     triggered=self.quit)
         self.register_shortcut(quit_action, "_", "Quit", "Ctrl+Q")
         run_action = create_action(self, _("&Run..."), None,
-                            'run_small.png', _("Run a Python script"),
+                            ima.icon('run_small'),
+                            _("Run a Python script"),
                             triggered=self.run_script)
         environ_action = create_action(self,
                             _("Environment variables..."),
-                            icon = 'environ.png',
+                            icon=ima.icon('environ'),
                             tip=_("Show and edit environment variables"
                                         " (for current session)"),
                             triggered=self.show_env)
         syspath_action = create_action(self,
                             _("Show sys.path contents..."),
-                            icon = 'syspath.png',
+                            icon=ima.icon('syspath'),
                             tip=_("Show (read-only) sys.path"),
                             triggered=self.show_syspath)
         buffer_action = create_action(self,
@@ -146,7 +152,7 @@ class Console(SpyderPluginWidget):
                             triggered=self.change_max_line_count)
         font_action = create_action(self,
                             _("&Font..."), None,
-                            'font.png', _("Set shell font style"),
+                            ima.icon('font'), _("Set shell font style"),
                             triggered=self.change_font)
         exteditor_action = create_action(self,
                             _("External editor path..."), None, None,
@@ -169,8 +175,8 @@ class Console(SpyderPluginWidget):
         codecompenter_action.setChecked(self.get_option(
                                                     'codecompletion/enter_key'))
         
-        option_menu = QMenu(_("Internal console settings"), self)
-        option_menu.setIcon(get_icon('tooloptions.png'))
+        option_menu = QMenu(_('Internal console settings'), self)
+        option_menu.setIcon(ima.icon('tooloptions'))
         add_actions(option_menu, (buffer_action, font_action, wrap_action,
                                   calltips_action, codecompletion_action,
                                   codecompenter_action, exteditor_action))
@@ -185,12 +191,10 @@ class Console(SpyderPluginWidget):
     
     def register_plugin(self):
         """Register plugin in Spyder's main window"""
-        self.connect(self, SIGNAL('focus_changed()'),
-                     self.main.plugin_focus_changed)
+        self.focus_changed.connect(self.main.plugin_focus_changed)
         self.main.add_dockwidget(self)
         # Connecting the following signal once the dockwidget has been created:
-        self.connect(self.shell, SIGNAL('traceback_available()'),
-                     self.traceback_available)
+        self.shell.traceback_available.connect(self.traceback_available)
     
     def traceback_available(self):
         """Traceback is available in the internal console: showing the 
@@ -200,21 +204,25 @@ class Console(SpyderPluginWidget):
             self.dockwidget.raise_()
         
     #------ Public API ---------------------------------------------------------
+    @Slot()
     def quit(self):
         """Quit mainwindow"""
         self.main.close()
-        
+    
+    @Slot()
     def show_env(self):
         """Show environment variables"""
         self.dialog_manager.show(EnvDialog())
-
+    
+    @Slot()
     def show_syspath(self):
         """Show sys.path"""
-        editor = DictEditor()
+        editor = CollectionsEditor()
         editor.setup(sys.path, title="sys.path", readonly=True,
-                     width=600, icon='syspath.png')
+                     width=600, icon=ima.icon('syspath'))
         self.dialog_manager.show(editor)
-        
+    
+    @Slot()
     def run_script(self, filename=None, silent=False, set_focus=False,
                    args=None):
         """Run a Python script"""
@@ -228,6 +236,7 @@ class Console(SpyderPluginWidget):
                 filename = osp.basename(filename)
             else:
                 return
+        debug_print(args)
         filename = osp.abspath(filename)
         rbs = remove_backslashes
         command = "runfile('%s', args='%s')" % (rbs(filename), rbs(args))
@@ -255,14 +264,14 @@ class Console(SpyderPluginWidget):
             self.shell.external_editor(filename, goto)
             return
         if filename is not None:
-            self.emit(SIGNAL("edit_goto(QString,int,QString)"),
-                      osp.abspath(filename), goto, '')
+            self.edit_goto.emit(osp.abspath(filename), goto, '')
         
     def execute_lines(self, lines):
         """Execute lines and give focus to shell"""
         self.shell.execute_lines(to_text_string(lines))
         self.shell.setFocus()
-        
+    
+    @Slot()
     def change_font(self):
         """Change console font"""
         font, valid = QFontDialog.getFont(self.get_plugin_font(),
@@ -270,7 +279,8 @@ class Console(SpyderPluginWidget):
         if valid:
             self.shell.set_font(font)
             self.set_plugin_font(font)
-        
+    
+    @Slot()
     def change_max_line_count(self):
         "Change maximum line count"""
         mlc, valid = QInputDialog.getInteger(self, _('Buffer'),
@@ -281,6 +291,7 @@ class Console(SpyderPluginWidget):
             self.shell.setMaximumBlockCount(mlc)
             self.set_option('max_line_count', mlc)
 
+    @Slot()
     def change_exteditor(self):
         """Change external editor path"""
         path, valid = QInputDialog.getText(self, _('External editor'),
@@ -289,22 +300,26 @@ class Console(SpyderPluginWidget):
                           self.get_option('external_editor/path'))
         if valid:
             self.set_option('external_editor/path', to_text_string(path))
-            
+    
+    @Slot(bool)
     def toggle_wrap_mode(self, checked):
         """Toggle wrap mode"""
         self.shell.toggle_wrap_mode(checked)
         self.set_option('wrap', checked)
-            
+    
+    @Slot(bool)
     def toggle_calltips(self, checked):
         """Toggle calltips"""
         self.shell.set_calltips(checked)
         self.set_option('calltips', checked)
-            
+    
+    @Slot(bool)
     def toggle_codecompletion(self, checked):
         """Toggle automatic code completion"""
         self.shell.set_codecompletion_auto(checked)
         self.set_option('codecompletion/auto', checked)
-            
+    
+    @Slot(bool)
     def toggle_codecompletion_enter(self, checked):
         """Toggle Enter key for code completion"""
         self.shell.set_codecompletion_enter(checked)
diff --git a/spyderlib/plugins/editor.py b/spyderlib/plugins/editor.py
index 5149b15..8b5f802 100644
--- a/spyderlib/plugins/editor.py
+++ b/spyderlib/plugins/editor.py
@@ -11,14 +11,16 @@
 # pylint: disable=R0911
 # pylint: disable=R0201
 
+from spyderlib.qt import PYQT5
 from spyderlib.qt.QtGui import (QVBoxLayout, QPrintDialog, QSplitter, QToolBar,
                                 QAction, QApplication, QDialog, QWidget,
                                 QPrinter, QActionGroup, QInputDialog, QMenu,
                                 QAbstractPrintDialog, QGroupBox, QTabWidget,
                                 QLabel, QFontComboBox, QHBoxLayout,
-                                QKeySequence)
-from spyderlib.qt.QtCore import SIGNAL, QByteArray, Qt, Slot
+                                QKeySequence, QGridLayout)
+from spyderlib.qt.QtCore import Signal, QByteArray, Qt, Slot
 from spyderlib.qt.compat import to_qvariant, from_qvariant, getopenfilenames
+import spyderlib.utils.icon_manager as ima
 
 import os
 import re
@@ -28,13 +30,12 @@ import os.path as osp
 
 # Local imports
 from spyderlib.utils import encoding, sourcecode, codeanalysis
-from spyderlib.baseconfig import get_conf_path, _
-from spyderlib.config import CONF, EDIT_FILTERS, get_filter, EDIT_FILETYPES
-from spyderlib.guiconfig import get_color_scheme
+from spyderlib.config.base import get_conf_path, _
+from spyderlib.config.main import CONF, EDIT_FILTERS, get_filter, EDIT_FILETYPES
+from spyderlib.config.gui import get_color_scheme
 from spyderlib.utils import programs
-from spyderlib.utils.qthelpers import (get_icon, create_action, add_actions,
-                                       get_std_icon, get_filetype_icon,
-                                       add_shortcut_to_tooltip)
+from spyderlib.utils.qthelpers import (create_action, add_actions,
+                                       get_filetype_icon, add_shortcut_to_tooltip)
 from spyderlib.widgets.findreplace import FindReplace
 from spyderlib.widgets.status import (ReadWriteStatus, EOLStatus,
                                       EncodingStatus, CursorPositionStatus)
@@ -94,7 +95,7 @@ class EditorConfigPage(PluginConfigPage):
         return _("Editor")
         
     def get_icon(self):
-        return get_icon("edit24.png")
+        return ima.icon('edit')
     
     def setup_page(self):
         template_btn = self.create_button(_("Edit template for new modules"),
@@ -120,12 +121,9 @@ class EditorConfigPage(PluginConfigPage):
         edgeline_box = newcb(_("Show vertical line after"), 'edge_line')
         edgeline_spin = self.create_spinbox("", _("characters"),
                                             'edge_line_column', 79, 1, 500)
-        self.connect(edgeline_box, SIGNAL("toggled(bool)"),
-                     edgeline_spin.setEnabled)
+        edgeline_box.toggled.connect(edgeline_spin.setEnabled)
         edgeline_spin.setEnabled(self.get_option('edge_line'))
-        edgeline_layout = QHBoxLayout()
-        edgeline_layout.addWidget(edgeline_box)
-        edgeline_layout.addWidget(edgeline_spin)
+
         currentline_box = newcb(_("Highlight current line"),
                                 'highlight_current_line')
         currentcell_box = newcb(_("Highlight current cell"),
@@ -135,28 +133,33 @@ class EditorConfigPage(PluginConfigPage):
         occurence_spin = self.create_spinbox("", " ms",
                                              'occurence_highlighting/timeout',
                                              min_=100, max_=1000000, step=100)
-        self.connect(occurence_box, SIGNAL("toggled(bool)"),
-                     occurence_spin.setEnabled)
+        occurence_box.toggled.connect(occurence_spin.setEnabled)
         occurence_spin.setEnabled(self.get_option('occurence_highlighting'))
-        occurence_layout = QHBoxLayout()
-        occurence_layout.addWidget(occurence_box)
-        occurence_layout.addWidget(occurence_spin)
+
         wrap_mode_box = newcb(_("Wrap lines"), 'wrap')
         names = CONF.get('color_schemes', 'names')
         choices = list(zip(names, names))
         cs_combo = self.create_combobox(_("Syntax color scheme: "),
                                         choices, 'color_scheme_name')
         
-        display_layout = QVBoxLayout()
-        display_layout.addWidget(linenumbers_box)
-        display_layout.addWidget(blanks_box)
-        display_layout.addLayout(edgeline_layout)
-        display_layout.addWidget(currentline_box)
-        display_layout.addWidget(currentcell_box)
-        display_layout.addLayout(occurence_layout)
-        display_layout.addWidget(wrap_mode_box)
-        display_layout.addWidget(cs_combo)
-        display_group.setLayout(display_layout)
+        display_layout = QGridLayout()
+        display_layout.addWidget(linenumbers_box, 0, 0)
+        display_layout.addWidget(blanks_box, 1, 0)
+        display_layout.addWidget(edgeline_box, 2, 0)
+        display_layout.addWidget(edgeline_spin.spinbox, 2, 1)
+        display_layout.addWidget(edgeline_spin.slabel, 2, 2)
+        display_layout.addWidget(currentline_box, 3, 0)
+        display_layout.addWidget(currentcell_box, 4, 0)
+        display_layout.addWidget(occurence_box, 5, 0)
+        display_layout.addWidget(occurence_spin.spinbox, 5, 1)
+        display_layout.addWidget(occurence_spin.slabel, 5, 2)
+        display_layout.addWidget(wrap_mode_box, 6, 0)
+        display_layout.addWidget(cs_combo.label, 7, 0)
+        display_layout.addWidget(cs_combo.combobox, 7, 1)
+        display_h_layout = QHBoxLayout()
+        display_h_layout.addLayout(display_layout)
+        display_h_layout.addStretch(1)
+        display_group.setLayout(display_h_layout)
 
         run_group = QGroupBox(_("Run"))
         saveall_box = newcb(_("Save all files before running script"),
@@ -220,35 +223,33 @@ class EditorConfigPage(PluginConfigPage):
                                'always_remove_trailing_spaces', default=False)
         
         analysis_group = QGroupBox(_("Analysis"))
-        pep8_url = '<a href="http://www.python.org/dev/peps/pep-0008/">PEP8</a>'
-        analysis_label = QLabel(_("<u>Note</u>: add <b>analysis:ignore</b> in "
-                                  "a comment to ignore code/style analysis "
-                                  "warnings. For more informations on style "
-                                  "guide for Python code, please refer to the "
-                                  "%s page.") % pep8_url)
-        analysis_label.setWordWrap(True)
+        pep_url = '<a href="http://www.python.org/dev/peps/pep-0008/">PEP8</a>'
+        pep8_label = QLabel(_("<i>(Refer to the {} page)</i>").format(pep_url))
+        pep8_label.setOpenExternalLinks(True)
         is_pyflakes = codeanalysis.is_pyflakes_installed()
         is_pep8 = codeanalysis.get_checker_executable('pep8') is not None
-        analysis_label.setEnabled(is_pyflakes or is_pep8)
-        pyflakes_box = newcb(_("Code analysis")+" (pyflakes)",
+        pyflakes_box = newcb(_("Real-time code analysis"),
                       'code_analysis/pyflakes', default=True,
-                      tip=_("If enabled, Python source code will be analyzed\n"
-                            "using pyflakes, lines containing errors or \n"
-                            "warnings will be highlighted"))
+                      tip=_("<p>If enabled, Python source code will be analyzed "
+                            "using pyflakes, lines containing errors or "
+                            "warnings will be highlighted.</p>"
+                            "<p><u>Note</u>: add <b>analysis:ignore</b> in "
+                            "a comment to ignore code analysis "
+                            "warnings.</p>"))
         pyflakes_box.setEnabled(is_pyflakes)
         if not is_pyflakes:
             pyflakes_box.setToolTip(_("Code analysis requires pyflakes %s+") %
                                     codeanalysis.PYFLAKES_REQVER)
-        pep8_box = newcb(_("Style analysis")+' (pep8)',
+        pep8_box = newcb(_("Real-time code style analysis"),
                       'code_analysis/pep8', default=False,
-                      tip=_('If enabled, Python source code will be analyzed\n'
-                            'using pep8, lines that are not following PEP8\n'
-                            'style guide will be highlighted'))
+                      tip=_("<p>If enabled, Python source code will be analyzed"
+                            "using pep8, lines that are not following PEP8 "
+                            "style guide will be highlighted.</p>"
+                            "<p><u>Note</u>: add <b>analysis:ignore</b> in "
+                            "a comment to ignore style analysis "
+                            "warnings.</p>"))
         pep8_box.setEnabled(is_pep8)
-        ancb_layout = QHBoxLayout()
-        ancb_layout.addWidget(pyflakes_box)
-        ancb_layout.addWidget(pep8_box)
-        todolist_box = newcb(_("Tasks (TODO, FIXME, XXX, HINT, TIP, @todo)"),
+        todolist_box = newcb(_("Code annotations (TODO, FIXME, XXX, HINT, TIP, @todo)"),
                              'todo_list', default=True)
         realtime_radio = self.create_radiobutton(
                                             _("Perform analysis when "
@@ -284,8 +285,11 @@ class EditorConfigPage(PluginConfigPage):
         introspection_group.setLayout(introspection_layout)
         
         analysis_layout = QVBoxLayout()
-        analysis_layout.addWidget(analysis_label)
-        analysis_layout.addLayout(ancb_layout)
+        analysis_layout.addWidget(pyflakes_box)
+        analysis_pep_layout = QHBoxLayout() 
+        analysis_pep_layout.addWidget(pep8_box)
+        analysis_pep_layout.addWidget(pep8_label)
+        analysis_layout.addLayout(analysis_pep_layout)
         analysis_layout.addWidget(todolist_box)
         analysis_layout.addLayout(af_layout)
         analysis_layout.addWidget(saveonly_radio)
@@ -296,8 +300,16 @@ class EditorConfigPage(PluginConfigPage):
         sourcecode_layout.addWidget(autounindent_box)
         sourcecode_layout.addWidget(add_colons_box)
         sourcecode_layout.addWidget(close_quotes_box)
-        sourcecode_layout.addWidget(indent_chars_box)
-        sourcecode_layout.addWidget(tabwidth_spin)
+        indent_tab_layout = QHBoxLayout()
+        indent_tab_grid_layout = QGridLayout()
+        indent_tab_grid_layout.addWidget(indent_chars_box.label, 0, 0)
+        indent_tab_grid_layout.addWidget(indent_chars_box.combobox, 0, 1)
+        indent_tab_grid_layout.addWidget(tabwidth_spin.plabel, 1, 0)
+        indent_tab_grid_layout.addWidget(tabwidth_spin.spinbox, 1, 1)
+        indent_tab_grid_layout.addWidget(tabwidth_spin.slabel, 1, 2)
+        indent_tab_layout.addLayout(indent_tab_grid_layout)
+        indent_tab_layout.addStretch(1)
+        sourcecode_layout.addLayout(indent_tab_layout)
         sourcecode_layout.addWidget(tab_mode_box)
         sourcecode_layout.addWidget(ibackspace_box)
         sourcecode_layout.addWidget(removetrail_box)
@@ -342,8 +354,20 @@ class Editor(SpyderPluginWidget):
     TEMPFILE_PATH = get_conf_path('temp.py')
     TEMPLATE_PATH = get_conf_path('template.py')
     DISABLE_ACTIONS_WHEN_HIDDEN = False # SpyderPluginWidget class attribute
+    
+    # Signals
+    run_in_current_ipyclient = Signal(str, str, str, bool, bool)
+    exec_in_extconsole = Signal(str, bool)
+    redirect_stdio = Signal(bool)
+    open_dir = Signal(str)
+    breakpoints_saved = Signal()
+    run_in_current_extconsole = Signal(str, str, str, bool, bool)
+    
     def __init__(self, parent, ignore_last_opened_files=False):
-        SpyderPluginWidget.__init__(self, parent)
+        if PYQT5:
+            SpyderPluginWidget.__init__(self, parent, main=parent)
+        else:
+            SpyderPluginWidget.__init__(self, parent)
         
         self.__set_eol_chars = True
         
@@ -401,18 +425,16 @@ class Editor(SpyderPluginWidget):
         self.menu_list = None
         
         # Setup new windows:
-        self.connect(self.main, SIGNAL('all_actions_defined()'),
-                     self.setup_other_windows)
+        self.main.all_actions_defined.connect(self.setup_other_windows)
 
         # Change module completions when PYTHONPATH changes
-        self.connect(self.main, SIGNAL("pythonpath_changed()"),
-                     self.set_path)
+        self.main.sig_pythonpath_changed.connect(self.set_path)
 
         # Find widget
         self.find_widget = FindReplace(self, enable_replace=True)
         self.find_widget.hide()
-        self.connect(self.find_widget, SIGNAL("visibility_changed(bool)"),
-                     lambda vs: self.rehighlight_cells())
+        self.find_widget.visibility_changed.connect(
+                                          lambda vs: self.rehighlight_cells())
         self.register_widget_shortcuts("Editor", self.find_widget)
 
         # Tabbed editor widget + Find/Replace widget
@@ -437,7 +459,8 @@ class Editor(SpyderPluginWidget):
         # Editor's splitter state
         state = self.get_option('splitter_state', None)
         if state is not None:
-            self.splitter.restoreState( QByteArray().fromHex(str(state)) )
+            self.splitter.restoreState( QByteArray().fromHex(
+                    str(state).encode('utf-8')) )
         
         self.recent_files = self.get_option('recent_files', [])
         
@@ -472,7 +495,8 @@ class Editor(SpyderPluginWidget):
         
     def set_projectexplorer(self, projectexplorer):
         self.projectexplorer = projectexplorer
-        
+
+    @Slot()
     def show_hide_project_explorer(self):
         if self.projectexplorer is not None:
             dw = self.projectexplorer.dockwidget
@@ -488,15 +512,15 @@ class Editor(SpyderPluginWidget):
         for editorstack in self.editorstacks:
             editorstack.set_outlineexplorer(self.outlineexplorer)
         self.editorstacks[0].initialize_outlineexplorer()
-        self.connect(self.outlineexplorer,
-                     SIGNAL("edit_goto(QString,int,QString)"),
-                     lambda filenames, goto, word:
-                     self.load(filenames=filenames, goto=goto, word=word,
-                               editorwindow=self))
-        self.connect(self.outlineexplorer, SIGNAL("edit(QString)"),
-                     lambda filenames:
-                     self.load(filenames=filenames, editorwindow=self))
-            
+        self.outlineexplorer.edit_goto.connect(
+                           lambda filenames, goto, word:
+                           self.load(filenames=filenames, goto=goto, word=word,
+                                     editorwindow=self))
+        self.outlineexplorer.edit.connect(
+                             lambda filenames:
+                             self.load(filenames=filenames, editorwindow=self))
+
+    @Slot()
     def show_hide_outline_explorer(self):
         if self.outlineexplorer is not None:
             dw = self.outlineexplorer.dockwidget
@@ -532,7 +556,7 @@ class Editor(SpyderPluginWidget):
     
     def get_plugin_icon(self):
         """Return widget icon"""
-        return get_icon('edit.png')
+        return ima.icon('edit')
     
     def get_focus_widget(self):
         """
@@ -570,11 +594,14 @@ class Editor(SpyderPluginWidget):
                     [win.get_layout_settings() for win in self.editorwindows])
         self.set_option('filenames', filenames)
         self.set_option('recent_files', self.recent_files)
-        if not editorstack.save_if_changed(cancelable) and cancelable:
-            return False
-        else:
-            for win in self.editorwindows[:]:
-                win.close()
+        try:
+            if not editorstack.save_if_changed(cancelable) and cancelable:
+                return False
+            else:
+                for win in self.editorwindows[:]:
+                    win.close()
+                return True
+        except IndexError:
             return True
 
     def get_plugin_actions(self):
@@ -595,7 +622,7 @@ class Editor(SpyderPluginWidget):
         
         # ---- File menu and toolbar ----
         self.new_action = create_action(self, _("&New file..."),
-                icon='filenew.png', tip=_("New file"),
+                icon=ima.icon('filenew'), tip=_("New file"),
                 triggered=self.new)
         self.register_shortcut(self.new_action, context="Editor",
                                name="New file")
@@ -603,19 +630,26 @@ class Editor(SpyderPluginWidget):
                                 name="New file")
         
         self.open_action = create_action(self, _("&Open..."),
-                icon='fileopen.png', tip=_("Open file"),
+                icon=ima.icon('fileopen'), tip=_("Open file"),
                 triggered=self.load)
         self.register_shortcut(self.open_action, context="Editor",
                                name="Open file")
         add_shortcut_to_tooltip(self.open_action, context="Editor",
                                 name="Open file")
-        
+
+        self.file_switcher_action = create_action(self, _('File switcher...'),
+                                            icon=ima.icon('filelist'),
+                                            tip=_('Fast switch between files'),
+                                            triggered=self.call_file_switcher,
+                                            context=Qt.ApplicationShortcut)
+        self.register_shortcut(self.file_switcher_action, "_", "file switcher")
+
         self.revert_action = create_action(self, _("&Revert"),
-                icon='revert.png', tip=_("Revert file from disk"),
+                icon=ima.icon('revert'), tip=_("Revert file from disk"),
                 triggered=self.revert)
         
         self.save_action = create_action(self, _("&Save"),
-                icon='filesave.png', tip=_("Save file"),
+                icon=ima.icon('filesave'), tip=_("Save file"),
                 triggered=self.save)
         self.register_shortcut(self.save_action, context="Editor",
                                name="Save file")
@@ -623,7 +657,8 @@ class Editor(SpyderPluginWidget):
                                 name="Save file")
         
         self.save_all_action = create_action(self, _("Sav&e all"),
-                icon='save_all.png', tip=_("Save all files"),
+                icon=ima.icon('save_all'), tip=_("Save all files"),
+                                             
                 triggered=self.save_all)
         self.register_shortcut(self.save_all_action, context="Editor",
                                name="Save all")
@@ -631,21 +666,22 @@ class Editor(SpyderPluginWidget):
                                 name="Save all")
         
         save_as_action = create_action(self, _("Save &as..."), None,
-                'filesaveas.png', _("Save current file as..."),
+                ima.icon('filesaveas'), tip=_("Save current file as..."),
                 triggered=self.save_as)
+        self.register_shortcut(save_as_action, "Editor", "Save As")
+
         print_preview_action = create_action(self, _("Print preview..."),
                 tip=_("Print preview..."), triggered=self.print_preview)
         self.print_action = create_action(self, _("&Print..."),
-                icon='print.png', tip=_("Print current file..."),
+                icon=ima.icon('print'), tip=_("Print current file..."),
                 triggered=self.print_file)
-        self.register_shortcut(self.print_action, context="Editor",
-                               name="Print")
         # Shortcut for close_action is defined in widgets/editor.py
         self.close_action = create_action(self, _("&Close"),
-                icon='fileclose.png', tip=_("Close current file"),
+                icon=ima.icon('fileclose'), tip=_("Close current file"),
                 triggered=self.close_file)
+
         self.close_all_action = create_action(self, _("C&lose all"),
-                icon='filecloseall.png', tip=_("Close all opened files"),
+                icon=ima.icon('filecloseall'), tip=_("Close all opened files"),
                 triggered=self.close_all_files)
         self.register_shortcut(self.close_all_action, context="Editor",
                                name="Close all")
@@ -653,20 +689,20 @@ class Editor(SpyderPluginWidget):
         # ---- Debug menu ----
         set_clear_breakpoint_action = create_action(self,
                                     _("Set/Clear breakpoint"),
-                                    icon=get_icon("breakpoint_big.png"),
+                                    icon=ima.icon('breakpoint_big'),
                                     triggered=self.set_or_clear_breakpoint,
                                     context=Qt.WidgetShortcut)
         self.register_shortcut(set_clear_breakpoint_action, context="Editor",
                                name="Breakpoint")
         set_cond_breakpoint_action = create_action(self,
                             _("Set/Edit conditional breakpoint"),
-                            icon=get_icon("breakpoint_cond_big.png"),
+                            icon=ima.icon('breakpoint_cond_big'),
                             triggered=self.set_or_edit_conditional_breakpoint,
                             context=Qt.WidgetShortcut)
         self.register_shortcut(set_cond_breakpoint_action, context="Editor",
                                name="Conditional breakpoint")
         clear_all_breakpoints_action = create_action(self,
-                                    _("Clear breakpoints in all files"),
+                                    _('Clear breakpoints in all files'),
                                     triggered=self.clear_all_breakpoints)
         breakpoints_menu = QMenu(_("Breakpoints"), self)
         add_actions(breakpoints_menu, (set_clear_breakpoint_action,
@@ -679,45 +715,44 @@ class Editor(SpyderPluginWidget):
                                name="Debug with winpdb")
         
         # --- Debug toolbar ---
-        debug_action = create_action(self, _("&Debug"), icon='debug.png',
-                                     tip=_("Debug file"),
-                                     triggered=self.debug_file)
+        debug_action = create_action(self, _("&Debug"), icon=ima.icon('debug'),
+                                     tip=_("Debug file"), triggered=self.debug_file)
         self.register_shortcut(debug_action, context="Editor", name="Debug")
         add_shortcut_to_tooltip(debug_action, context="Editor", name="Debug")
         
         debug_next_action = create_action(self, _("Step"), 
-               icon='arrow-step-over.png', tip=_("Run current line"), 
+               icon=ima.icon('arrow-step-over'), tip=_("Run current line"), 
                triggered=lambda: self.debug_command("next")) 
         self.register_shortcut(debug_next_action, "_", "Debug Step Over")
         add_shortcut_to_tooltip(debug_next_action, context="_",
                                 name="Debug Step Over")
 
         debug_continue_action = create_action(self, _("Continue"),
-               icon='arrow-continue.png', tip=_("Continue execution until "
-                                                "next breakpoint"), 
+               icon=ima.icon('arrow-continue'), tip=_("Continue execution until "
+                                                      "next breakpoint"), 
                triggered=lambda: self.debug_command("continue"))                                                 
         self.register_shortcut(debug_continue_action, "_", "Debug Continue")
         add_shortcut_to_tooltip(debug_continue_action, context="_",
                                 name="Debug Continue")
 
         debug_step_action = create_action(self, _("Step Into"), 
-               icon='arrow-step-in.png', tip=_("Step into function or method "
-                                               "of current line"), 
+               icon=ima.icon('arrow-step-in'), tip=_("Step into function or method "
+                                                     "of current line"), 
                triggered=lambda: self.debug_command("step"))                
         self.register_shortcut(debug_step_action, "_", "Debug Step Into")
         add_shortcut_to_tooltip(debug_step_action, context="_",
                                 name="Debug Step Into")
 
         debug_return_action = create_action(self, _("Step Return"), 
-               icon='arrow-step-out.png', tip=_("Run until current function "
-                                                "or method returns"), 
+               icon=ima.icon('arrow-step-out'), tip=_("Run until current function "
+                                                      "or method returns"), 
                triggered=lambda: self.debug_command("return"))               
         self.register_shortcut(debug_return_action, "_", "Debug Step Return")
         add_shortcut_to_tooltip(debug_return_action, context="_",
                                 name="Debug Step Return")
 
         debug_exit_action = create_action(self, _("Exit"),
-               icon='stop_debug.png', tip=_("Exit Debug"), 
+               icon=ima.icon('stop_debug'), tip=_("Exit Debug"), 
                triggered=lambda: self.debug_command("exit"))                                       
         self.register_shortcut(debug_exit_action, "_", "Debug Exit")
         add_shortcut_to_tooltip(debug_exit_action, context="_",
@@ -732,14 +767,14 @@ class Editor(SpyderPluginWidget):
         add_actions(debug_control_menu, debug_control_menu_actions)   
         
         # --- Run toolbar ---
-        run_action = create_action(self, _("&Run"), icon='run.png',
+        run_action = create_action(self, _("&Run"), icon=ima.icon('run'),
                                    tip=_("Run file"),
                                    triggered=self.run_file)
         self.register_shortcut(run_action, context="Editor", name="Run")
         add_shortcut_to_tooltip(run_action, context="Editor", name="Run")
 
-        configure_action = create_action(self,
-                               _("&Configure..."), icon='run_settings.png',
+        configure_action = create_action(self, _("&Configure..."), 
+                                         icon=ima.icon('run_settings'),
                                tip=_("Run settings"),
                                menurole=QAction.NoRole,
                                triggered=self.edit_run_configurations)
@@ -748,8 +783,8 @@ class Editor(SpyderPluginWidget):
         add_shortcut_to_tooltip(configure_action, context="Editor",
                                 name="Configure")
         
-        re_run_action = create_action(self,
-                            _("Re-run &last script"), icon='run_again.png',
+        re_run_action = create_action(self, _("Re-run &last script"), 
+                                      icon=ima.icon('run_again'),
                             tip=_("Run again last file"),
                             triggered=self.re_run_file)
         self.register_shortcut(re_run_action, context="Editor",
@@ -759,7 +794,7 @@ class Editor(SpyderPluginWidget):
 
         run_selected_action = create_action(self, _("Run &selection or "
                                                     "current line"),
-                                            icon='run_selection.png',
+                                            icon=ima.icon('run_selection'),
                                             tip=_("Run selection or "
                                                   "current line"),
                                             triggered=self.run_selection)
@@ -773,7 +808,8 @@ class Editor(SpyderPluginWidget):
         run_cell_advance_sc = Qt.SHIFT + Qt.Key_Enter
 
         run_cell_action = create_action(self,
-                            _("Run cell"), icon='run_cell.png',
+                            _("Run cell"),
+                            icon=ima.icon('run_cell'),
                             shortcut=QKeySequence(run_cell_sc),
                             tip=_("Run current cell (Ctrl+Enter)\n"
                                   "[Use #%% to create cells]"),
@@ -781,7 +817,7 @@ class Editor(SpyderPluginWidget):
 
         run_cell_advance_action = create_action(self,
                             _("Run cell and advance"),
-                            icon='run_cell_advance.png',
+                            icon=ima.icon('run_cell_advance'),
                             shortcut=QKeySequence(run_cell_advance_sc),
                             tip=_("Run current cell and go to "
                                   "the next one (Shift+Enter)"),
@@ -789,47 +825,45 @@ class Editor(SpyderPluginWidget):
         
         # --- Source code Toolbar ---
         self.todo_list_action = create_action(self,
-                _("Show todo list"), icon='todo_list.png',
+                _("Show todo list"), icon=ima.icon('todo_list'),
                 tip=_("Show TODO/FIXME/XXX/HINT/TIP/@todo comments list"),
                 triggered=self.go_to_next_todo)
         self.todo_menu = QMenu(self)
         self.todo_list_action.setMenu(self.todo_menu)
-        self.connect(self.todo_menu, SIGNAL("aboutToShow()"),
-                     self.update_todo_menu)
+        self.todo_menu.aboutToShow.connect(self.update_todo_menu)
         
         self.warning_list_action = create_action(self,
-                _("Show warning/error list"), icon='wng_list.png',
+                _("Show warning/error list"), icon=ima.icon('wng_list'),
                 tip=_("Show code analysis warnings/errors"),
                 triggered=self.go_to_next_warning)
         self.warning_menu = QMenu(self)
         self.warning_list_action.setMenu(self.warning_menu)
-        self.connect(self.warning_menu, SIGNAL("aboutToShow()"),
-                     self.update_warning_menu)
+        self.warning_menu.aboutToShow.connect(self.update_warning_menu)
         self.previous_warning_action = create_action(self,
-                _("Previous warning/error"), icon='prev_wng.png',
+                _("Previous warning/error"), icon=ima.icon('prev_wng'),
                 tip=_("Go to previous code analysis warning/error"),
                 triggered=self.go_to_previous_warning)
         self.next_warning_action = create_action(self,
-                _("Next warning/error"), icon='next_wng.png',
+                _("Next warning/error"), icon=ima.icon('next_wng'),
                 tip=_("Go to next code analysis warning/error"),
                 triggered=self.go_to_next_warning)
         
         self.previous_edit_cursor_action = create_action(self,
-                _("Last edit location"), icon='last_edit_location.png',
+                _("Last edit location"), icon=ima.icon('last_edit_location'),
                 tip=_("Go to last edit location"),
                 triggered=self.go_to_last_edit_location)
         self.register_shortcut(self.previous_edit_cursor_action,
                                context="Editor",
                                name="Last edit location")
         self.previous_cursor_action = create_action(self,
-                _("Previous cursor position"), icon='prev_cursor.png',
+                _("Previous cursor position"), icon=ima.icon('prev_cursor'),
                 tip=_("Go to previous cursor position"),
                 triggered=self.go_to_previous_cursor_position)
         self.register_shortcut(self.previous_cursor_action,
                                context="Editor",
                                name="Previous cursor position")
         self.next_cursor_action = create_action(self,
-                _("Next cursor position"), icon='next_cursor.png',
+                _("Next cursor position"), icon=ima.icon('next_cursor'),
                 tip=_("Go to next cursor position"),
                 triggered=self.go_to_next_cursor_position)
         self.register_shortcut(self.next_cursor_action,
@@ -837,7 +871,7 @@ class Editor(SpyderPluginWidget):
         
         # --- Edit Toolbar ---
         self.toggle_comment_action = create_action(self,
-                _("Comment")+"/"+_("Uncomment"), icon='comment.png',
+                _("Comment")+"/"+_("Uncomment"), icon=ima.icon('comment'),
                 tip=_("Comment current line or selection"),
                 triggered=self.toggle_comment, context=Qt.WidgetShortcut)
         self.register_shortcut(self.toggle_comment_action, context="Editor",
@@ -861,11 +895,11 @@ class Editor(SpyderPluginWidget):
         # keyPressEvent handler (the shortcut is here only to inform user):
         # (context=Qt.WidgetShortcut -> disable shortcut for other widgets)
         self.indent_action = create_action(self,
-                _("Indent"), "Tab", icon='indent.png',
+                _("Indent"), "Tab", icon=ima.icon('indent'),
                 tip=_("Indent current line or selection"),
                 triggered=self.indent, context=Qt.WidgetShortcut)
         self.unindent_action = create_action(self,
-                _("Unindent"), "Shift+Tab", icon='unindent.png',
+                _("Unindent"), "Shift+Tab", icon=ima.icon('unindent'),
                 tip=_("Unindent current line or selection"),
                 triggered=self.unindent, context=Qt.WidgetShortcut)
         # ----------------------------------------------------------------------
@@ -896,7 +930,7 @@ class Editor(SpyderPluginWidget):
                       triggered=self.fix_indentation)
 
         gotoline_action = create_action(self, _("Go to line..."),
-                                        icon=get_icon("gotoline.png"),
+                                        icon=ima.icon('gotoline'),
                                         triggered=self.go_to_line,
                                         context=Qt.WidgetShortcut)
         self.register_shortcut(gotoline_action, context="Editor",
@@ -904,7 +938,7 @@ class Editor(SpyderPluginWidget):
 
         workdir_action = create_action(self,
                 _("Set console working directory"),
-                icon=get_std_icon('DirOpenIcon'),
+                icon=ima.icon('DirOpenIcon'),
                 tip=_("Set current console (and file explorer) working "
                             "directory to current script directory"),
                 triggered=self.__set_workdir)
@@ -916,21 +950,21 @@ class Editor(SpyderPluginWidget):
             _("Clear this list"), tip=_("Clear recent files list"),
             triggered=self.clear_recent_files)
         self.recent_file_menu = QMenu(_("Open &recent"), self)
-        self.connect(self.recent_file_menu, SIGNAL("aboutToShow()"),
-                     self.update_recent_file_menu)
+        self.recent_file_menu.aboutToShow.connect(self.update_recent_file_menu)
 
         file_menu_actions = [self.new_action, self.open_action,
                              self.recent_file_menu, self.save_action,
                              self.save_all_action, save_as_action,
-                             self.revert_action, 
+                             self.file_switcher_action, self.revert_action,
                              None, print_preview_action, self.print_action,
                              None, self.close_action,
                              self.close_all_action, None]
         self.main.file_menu_actions += file_menu_actions
         file_toolbar_actions = [self.new_action, self.open_action,
-                                self.save_action, self.save_all_action]
+                                self.save_action, self.save_all_action,
+                                self.file_switcher_action]
         self.main.file_toolbar_actions += file_toolbar_actions
-        
+
         self.edit_menu_actions = [self.toggle_comment_action,
                                   blockcomment_action, unblockcomment_action,
                                   self.indent_action, self.unindent_action]
@@ -999,16 +1033,12 @@ class Editor(SpyderPluginWidget):
     
     def register_plugin(self):
         """Register plugin in Spyder's main window"""
-        self.connect(self.main, SIGNAL('restore_scrollbar_position()'),
-                     self.restore_scrollbar_position)
-        self.connect(self.main.console,
-                     SIGNAL("edit_goto(QString,int,QString)"), self.load)
-        self.connect(self, SIGNAL('exec_in_extconsole(QString,bool)'),
-                     self.main.execute_in_external_console)
-        self.connect(self, SIGNAL('redirect_stdio(bool)'),
-                     self.main.redirect_internalshell_stdio)
-        self.connect(self, SIGNAL("open_dir(QString)"),
-                     self.main.workingdirectory.chdir)
+        self.main.restore_scrollbar_position.connect(
+                                               self.restore_scrollbar_position)
+        self.main.console.edit_goto.connect(self.load)
+        self.exec_in_extconsole.connect(self.main.execute_in_external_console)
+        self.redirect_stdio.connect(self.main.redirect_internalshell_stdio)
+        self.open_dir.connect(self.main.workingdirectory.chdir)
         self.set_inspector(self.main.inspector)
         if self.main.outlineexplorer is not None:
             self.set_outlineexplorer(self.main.outlineexplorer)
@@ -1060,21 +1090,16 @@ class Editor(SpyderPluginWidget):
             if self.outlineexplorer is not None:
                 editorstack.set_outlineexplorer(self.outlineexplorer)
             editorstack.set_find_widget(self.find_widget)
-            self.connect(editorstack, SIGNAL('reset_statusbar()'),
-                         self.readwrite_status.hide)
-            self.connect(editorstack, SIGNAL('reset_statusbar()'),
-                         self.encoding_status.hide)
-            self.connect(editorstack, SIGNAL('reset_statusbar()'),
-                         self.cursorpos_status.hide)
-            self.connect(editorstack, SIGNAL('readonly_changed(bool)'),
-                         self.readwrite_status.readonly_changed)
-            self.connect(editorstack, SIGNAL('encoding_changed(QString)'),
-                         self.encoding_status.encoding_changed)
-            self.connect(editorstack,
-                         SIGNAL('editor_cursor_position_changed(int,int)'),
-                         self.cursorpos_status.cursor_position_changed)
-            self.connect(editorstack, SIGNAL('refresh_eol_chars(QString)'),
-                         self.eol_status.eol_changed)
+            editorstack.reset_statusbar.connect(self.readwrite_status.hide)
+            editorstack.reset_statusbar.connect(self.encoding_status.hide)
+            editorstack.reset_statusbar.connect(self.cursorpos_status.hide)
+            editorstack.readonly_changed.connect(
+                                        self.readwrite_status.readonly_changed)
+            editorstack.encoding_changed.connect(
+                                         self.encoding_status.encoding_changed)
+            editorstack.sig_editor_cursor_position_changed.connect(
+                                 self.cursorpos_status.cursor_position_changed)
+            editorstack.refresh_eol_chars.connect(self.eol_status.eol_changed)
             
         editorstack.set_inspector(self.inspector)
         editorstack.set_io_actions(self.new_action, self.open_action,
@@ -1121,71 +1146,47 @@ class Editor(SpyderPluginWidget):
         color_scheme = get_color_scheme(self.get_option('color_scheme_name'))
         editorstack.set_default_font(self.get_plugin_font(), color_scheme)
         
-        self.connect(editorstack, SIGNAL('starting_long_process(QString)'),
-                     self.starting_long_process)
-        self.connect(editorstack, SIGNAL('ending_long_process(QString)'),
-                     self.ending_long_process)
+        editorstack.starting_long_process.connect(self.starting_long_process)
+        editorstack.ending_long_process.connect(self.ending_long_process)
         
         # Redirect signals
-        self.connect(editorstack, SIGNAL('redirect_stdio(bool)'),
-                     lambda state:
-                     self.emit(SIGNAL('redirect_stdio(bool)'), state))
-        self.connect(editorstack, SIGNAL('exec_in_extconsole(QString,bool)'),
-                     lambda text, option: self.emit(
-                     SIGNAL('exec_in_extconsole(QString,bool)'), text, option))
-        self.connect(editorstack, SIGNAL("update_plugin_title()"),
-                     lambda: self.emit(SIGNAL("update_plugin_title()")))
-
-        self.connect(editorstack, SIGNAL("editor_focus_changed()"),
-                     self.save_focus_editorstack)
-        self.connect(editorstack, SIGNAL('editor_focus_changed()'),
-                     self.main.plugin_focus_changed)
-
-        self.connect(editorstack, SIGNAL('zoom_in()'), lambda: self.zoom(1))
-        self.connect(editorstack, SIGNAL('zoom_out()'), lambda: self.zoom(-1))
-        self.connect(editorstack, SIGNAL('zoom_reset()'), lambda: self.zoom(0))
-        self.connect(editorstack, SIGNAL('sig_new_file()'), self.new)
-
-        self.connect(editorstack, SIGNAL('close_file(QString,int)'),
-                     self.close_file_in_all_editorstacks)
-        self.connect(editorstack, SIGNAL('file_saved(QString,int,QString)'),
-                     self.file_saved_in_editorstack)
-        self.connect(editorstack,
-                     SIGNAL('file_renamed_in_data(QString,int,QString)'),
-                     self.file_renamed_in_data_in_editorstack)
-        
-        self.connect(editorstack, SIGNAL("create_new_window()"),
-                     self.create_new_window)
-        
-        self.connect(editorstack, SIGNAL('opened_files_list_changed()'),
-                     self.opened_files_list_changed)
-        self.connect(editorstack, SIGNAL('analysis_results_changed()'),
-                     self.analysis_results_changed)
-        self.connect(editorstack, SIGNAL('todo_results_changed()'),
-                     self.todo_results_changed)
-        self.connect(editorstack, SIGNAL('update_code_analysis_actions()'),
-                     self.update_code_analysis_actions)
-        self.connect(editorstack, SIGNAL('update_code_analysis_actions()'),
-                     self.update_todo_actions)
-        self.connect(editorstack,
-                     SIGNAL('refresh_file_dependent_actions()'),
-                     self.refresh_file_dependent_actions)
-        self.connect(editorstack, SIGNAL('refresh_save_all_action()'),
-                     self.refresh_save_all_action)
-        self.connect(editorstack, SIGNAL('refresh_eol_chars(QString)'),
-                     self.refresh_eol_chars)
-        
-        self.connect(editorstack, SIGNAL("save_breakpoints(QString,QString)"),
-                     self.save_breakpoints)
-        
-        self.connect(editorstack, SIGNAL('text_changed_at(QString,int)'),
-                     self.text_changed_at)
-        self.connect(editorstack, SIGNAL('current_file_changed(QString,int)'),
-                     self.current_file_changed)
-        
-        self.connect(editorstack, SIGNAL('plugin_load(QString)'), self.load)
-        self.connect(editorstack, SIGNAL("edit_goto(QString,int,QString)"),
-                     self.load)
+        editorstack.redirect_stdio.connect(
+                                 lambda state: self.redirect_stdio.emit(state))
+        editorstack.exec_in_extconsole.connect(
+                                    lambda text, option:
+                                    self.exec_in_extconsole.emit(text, option))
+        editorstack.update_plugin_title.connect(
+                                       lambda: self.update_plugin_title.emit())
+        editorstack.editor_focus_changed.connect(self.save_focus_editorstack)
+        editorstack.editor_focus_changed.connect(self.main.plugin_focus_changed)
+        editorstack.zoom_in.connect(lambda: self.zoom(1))
+        editorstack.zoom_out.connect(lambda: self.zoom(-1))
+        editorstack.zoom_reset.connect(lambda: self.zoom(0))
+        editorstack.sig_new_file.connect(lambda s: self.new(text=s))
+        editorstack.sig_new_file[()].connect(self.new)
+        editorstack.sig_close_file.connect(self.close_file_in_all_editorstacks)
+        editorstack.file_saved.connect(self.file_saved_in_editorstack)
+        editorstack.file_renamed_in_data.connect(
+                                      self.file_renamed_in_data_in_editorstack)
+        editorstack.create_new_window.connect(self.create_new_window)
+        editorstack.opened_files_list_changed.connect(
+                                                self.opened_files_list_changed)
+        editorstack.analysis_results_changed.connect(
+                                                 self.analysis_results_changed)
+        editorstack.todo_results_changed.connect(self.todo_results_changed)
+        editorstack.update_code_analysis_actions.connect(
+                                             self.update_code_analysis_actions)
+        editorstack.update_code_analysis_actions.connect(
+                                                      self.update_todo_actions)
+        editorstack.refresh_file_dependent_actions.connect(
+                                           self.refresh_file_dependent_actions)
+        editorstack.refresh_save_all_action.connect(self.refresh_save_all_action)
+        editorstack.refresh_eol_chars.connect(self.refresh_eol_chars)
+        editorstack.save_breakpoints.connect(self.save_breakpoints)
+        editorstack.text_changed_at.connect(self.text_changed_at)
+        editorstack.current_file_changed.connect(self.current_file_changed)
+        editorstack.plugin_load.connect(self.load)
+        editorstack.edit_goto.connect(self.load)
         
     def unregister_editorstack(self, editorstack):
         """Removing editorstack only if it's not the last remaining"""
@@ -1264,8 +1265,7 @@ class Editor(SpyderPluginWidget):
         window.resize(self.size())
         window.show()
         self.register_editorwindow(window)
-        self.connect(window, SIGNAL("destroyed()"),
-                     lambda win=window: self.unregister_editorwindow(win))
+        window.destroyed.connect(lambda: self.unregister_editorwindow(window))
         return window
     
     def register_editorwindow(self, window):
@@ -1346,7 +1346,7 @@ class Editor(SpyderPluginWidget):
         for message, line_number in check_results:
             error = 'syntax' in message
             text = message[:1].upper()+message[1:]
-            icon = get_icon('error.png' if error else 'warning.png')
+            icon = ima.icon('error') if error else ima.icon('warning')
             slot = lambda _l=line_number: self.load(filename, goto=_l)
             action = create_action(self, text=text, icon=icon, triggered=slot)
             self.warning_menu.addAction(action)
@@ -1372,7 +1372,7 @@ class Editor(SpyderPluginWidget):
         self.todo_menu.clear()
         filename = self.get_current_filename()
         for text, line0 in results:
-            icon = get_icon('todo.png')
+            icon = ima.icon('todo')
             slot = lambda _l=line0: self.load(filename, goto=_l)
             action = create_action(self, text=text, icon=icon, triggered=slot)
             self.todo_menu.addAction(action)
@@ -1458,7 +1458,7 @@ class Editor(SpyderPluginWidget):
         else:
             breakpoints = []
         save_breakpoints(filename, breakpoints)
-        self.emit(SIGNAL("breakpoints_saved()"))
+        self.breakpoints_saved.emit()
         
     #------ File I/O
     def __load_temp_file(self):
@@ -1474,12 +1474,13 @@ class Editor(SpyderPluginWidget):
             encoding.write(to_text_string(text), self.TEMPFILE_PATH, 'utf-8')
         self.load(self.TEMPFILE_PATH)
 
+    @Slot()
     def __set_workdir(self):
         """Set current script directory as working directory"""
         fname = self.get_current_filename()
         if fname is not None:
             directory = osp.dirname(osp.abspath(fname))
-            self.emit(SIGNAL("open_dir(QString)"), directory)
+            self.open_dir.emit(directory)
                 
     def __add_recent_file(self, fname):
         """Add to recent file list"""
@@ -1499,6 +1500,7 @@ class Editor(SpyderPluginWidget):
             editor = editorstack.clone_editor_from(finfo, set_current=False)
             self.register_widget_shortcuts("Editor", editor)
     
+    @Slot()
     def new(self, fname=None, editorstack=None, text=None):
         """
         Create a new file - Untitled
@@ -1573,7 +1575,11 @@ class Editor(SpyderPluginWidget):
     def edit_template(self):
         """Edit new file template"""
         self.load(self.TEMPLATE_PATH)
-        
+
+    def call_file_switcher(self):
+        if self.editorstacks:
+            self.get_current_editorstack().open_fileswitcher_dlg()
+
     def update_recent_file_menu(self):
         """Update recent file menu"""
         recent_files = []
@@ -1595,11 +1601,13 @@ class Editor(SpyderPluginWidget):
         self.clear_recent_action.setEnabled(len(recent_files) > 0)
         add_actions(self.recent_file_menu, (None, self.max_recent_action,
                                             self.clear_recent_action))
-        
+
+    @Slot()
     def clear_recent_files(self):
         """Clear recent files list"""
         self.recent_files = []
-        
+
+    @Slot()
     def change_max_recent_files(self):
         "Change max recent files entries"""
         editorstack = self.get_current_editorstack()
@@ -1608,7 +1616,9 @@ class Editor(SpyderPluginWidget):
                                self.get_option('max_recent_files'), 1, 35)
         if valid:
             self.set_option('max_recent_files', mrf)
-        
+    
+
+    @Slot(str, int, str, object)
     def load(self, filenames=None, goto=None, word='', editorwindow=None,
              processevents=True):
         """
@@ -1636,7 +1646,7 @@ class Editor(SpyderPluginWidget):
                 c_fname = self.get_current_filename()
                 if c_fname is not None and c_fname != self.TEMPFILE_PATH:
                     basedir = osp.dirname(c_fname)
-            self.emit(SIGNAL('redirect_stdio(bool)'), False)
+            self.redirect_stdio.emit(False)
             parent_widget = self.get_current_editorstack()
             if filename0 is not None:
                 selectedfilter = get_filter(EDIT_FILETYPES,
@@ -1646,12 +1656,12 @@ class Editor(SpyderPluginWidget):
             filenames, _selfilter = getopenfilenames(parent_widget,
                                          _("Open file"), basedir, EDIT_FILTERS,
                                          selectedfilter=selectedfilter)
-            self.emit(SIGNAL('redirect_stdio(bool)'), True)
+            self.redirect_stdio.emit(True)
             if filenames:
                 filenames = [osp.normpath(fname) for fname in filenames]
                 if CONF.get('workingdir', 'editor/open/auto_set_to_basedir'):
                     directory = osp.dirname(filenames[0])
-                    self.emit(SIGNAL("open_dir(QString)"), directory)
+                    self.open_dir.emit(directory)
             else:
                 return
             
@@ -1713,6 +1723,7 @@ class Editor(SpyderPluginWidget):
             if processevents:
                 QApplication.processEvents()
 
+    @Slot()
     def print_file(self):
         """Print current file"""
         editor = self.get_current_editor()
@@ -1722,15 +1733,16 @@ class Editor(SpyderPluginWidget):
         printDialog = QPrintDialog(printer, editor)
         if editor.has_selected_text():
             printDialog.addEnabledOption(QAbstractPrintDialog.PrintSelection)
-        self.emit(SIGNAL('redirect_stdio(bool)'), False)
+        self.redirect_stdio.emit(False)
         answer = printDialog.exec_()
-        self.emit(SIGNAL('redirect_stdio(bool)'), True)
+        self.redirect_stdio.emit(True)
         if answer == QDialog.Accepted:
             self.starting_long_process(_("Printing..."))
             printer.setDocName(filename)
             editor.print_(printer)
             self.ending_long_process()
 
+    @Slot()
     def print_preview(self):
         """Print preview for current file"""
         from spyderlib.qt.QtGui import QPrintPreviewDialog
@@ -1739,39 +1751,44 @@ class Editor(SpyderPluginWidget):
                           header_font=self.get_plugin_font('printer_header'))
         preview = QPrintPreviewDialog(printer, self)
         preview.setWindowFlags(Qt.Window)
-        self.connect(preview, SIGNAL("paintRequested(QPrinter*)"),
-                     lambda printer: editor.print_(printer))
-        self.emit(SIGNAL('redirect_stdio(bool)'), False)
+        preview.paintRequested.connect(lambda printer: editor.print_(printer))
+        self.redirect_stdio.emit(False)
         preview.exec_()
-        self.emit(SIGNAL('redirect_stdio(bool)'), True)
+        self.redirect_stdio.emit(True)
 
+    @Slot()
     def close_file(self):
         """Close current file"""
         editorstack = self.get_current_editorstack()
         editorstack.close_file()
 
+    @Slot()
     def close_all_files(self):
         """Close all opened scripts"""
         self.editorstacks[0].close_all_files()
-                
+    
+    @Slot()
     def save(self, index=None, force=False):
         """Save file"""
         editorstack = self.get_current_editorstack()
         return editorstack.save(index=index, force=force)
-                
+    
+    @Slot()
     def save_as(self):
         """Save *as* the currently edited file"""
         editorstack = self.get_current_editorstack()
         if editorstack.save_as():
             fname = editorstack.get_current_filename()
             if CONF.get('workingdir', 'editor/save/auto_set_to_basedir'):
-                self.emit(SIGNAL("open_dir(QString)"), osp.dirname(fname))
+                self.open_dir.emit(osp.dirname(fname))
             self.__add_recent_file(fname)
-        
+    
+    @Slot()
     def save_all(self):
         """Save all opened files"""
         self.get_current_editorstack().save_all()
-        
+    
+    @Slot()
     def revert(self):
         """Revert the currently edited file from disk"""
         editorstack = self.get_current_editorstack()
@@ -1808,54 +1825,63 @@ class Editor(SpyderPluginWidget):
         
     
     #------ Source code
+    @Slot()
     def indent(self):
         """Indent current line or selection"""
         editor = self.get_current_editor()
         if editor is not None:
             editor.indent()
 
+    @Slot()
     def unindent(self):
         """Unindent current line or selection"""
         editor = self.get_current_editor()
         if editor is not None:
             editor.unindent()
-    
+
+    @Slot()
     def toggle_comment(self):
         """Comment current line or selection"""
         editor = self.get_current_editor()
         if editor is not None:
             editor.toggle_comment()
-    
+
+    @Slot()
     def blockcomment(self):
         """Block comment current line or selection"""
         editor = self.get_current_editor()
         if editor is not None:
             editor.blockcomment()
 
+    @Slot()
     def unblockcomment(self):
         """Un-block comment current line or selection"""
         editor = self.get_current_editor()
         if editor is not None:
             editor.unblockcomment()
-    
+
+    @Slot()
     def go_to_next_todo(self):
         editor = self.get_current_editor()
         position = editor.go_to_next_todo()
         filename = self.get_current_filename()
         self.add_cursor_position_to_history(filename, position)
-    
+
+    @Slot()
     def go_to_next_warning(self):
         editor = self.get_current_editor()
         position = editor.go_to_next_warning()
         filename = self.get_current_filename()
         self.add_cursor_position_to_history(filename, position)
-    
+
+    @Slot()
     def go_to_previous_warning(self):
         editor = self.get_current_editor()
         position = editor.go_to_previous_warning()
         filename = self.get_current_filename()
         self.add_cursor_position_to_history(filename, position)
-                
+
+    @Slot()
     def run_winpdb(self):
         """Run winpdb to debug current file"""
         if self.save():
@@ -1877,15 +1903,18 @@ class Editor(SpyderPluginWidget):
         editor = self.get_current_editor()
         if self.__set_eol_chars:
             editor.set_eol_chars(sourcecode.get_eol_chars_from_os_name(os_name))
-    
+
+    @Slot(bool)
     def toggle_show_blanks(self, checked):
         editor = self.get_current_editor()
         editor.set_blanks_enabled(checked)
-        
+
+    @Slot()
     def remove_trailing_spaces(self):
         editorstack = self.get_current_editorstack()
         editorstack.remove_trailing_spaces()
-        
+
+    @Slot()
     def fix_indentation(self):
         editorstack = self.get_current_editorstack()
         editorstack.fix_indentation()
@@ -1934,7 +1963,8 @@ class Editor(SpyderPluginWidget):
     def current_file_changed(self, filename, position):
         self.add_cursor_position_to_history(to_text_string(filename), position,
                                             fc=True)
-        
+
+    @Slot()
     def go_to_last_edit_location(self):
         if self.last_edit_cursor_pos is not None:
             filename, position = self.last_edit_cursor_pos
@@ -1972,35 +2002,41 @@ class Editor(SpyderPluginWidget):
                 editor.set_cursor_position(position)
         self.__ignore_cursor_position = False
         self.update_cursorpos_actions()
-            
+
+    @Slot()
     def go_to_previous_cursor_position(self):
         self.__move_cursor_position(-1)
-            
+
+    @Slot()
     def go_to_next_cursor_position(self):
         self.__move_cursor_position(1)
-        
+
+    @Slot()
     def go_to_line(self):
         """Open 'go to line' dialog"""
         editorstack = self.get_current_editorstack()
         if editorstack is not None:
             editorstack.go_to_line()
-            
+
+    @Slot()
     def set_or_clear_breakpoint(self):
         """Set/Clear breakpoint"""
         editorstack = self.get_current_editorstack()
         if editorstack is not None:
             editorstack.set_or_clear_breakpoint()
-            
+
+    @Slot()
     def set_or_edit_conditional_breakpoint(self):
         """Set/Edit conditional breakpoint"""
         editorstack = self.get_current_editorstack()
         if editorstack is not None:
             editorstack.set_or_edit_conditional_breakpoint()
-            
+
+    @Slot()
     def clear_all_breakpoints(self):
         """Clear breakpoints in all files"""
         clear_all_breakpoints()
-        self.emit(SIGNAL("breakpoints_saved()"))
+        self.breakpoints_saved.emit()
         editorstack = self.get_current_editorstack()
         if editorstack is not None:
             for data in editorstack.data:
@@ -2010,7 +2046,7 @@ class Editor(SpyderPluginWidget):
     def clear_breakpoint(self, filename, lineno):
         """Remove a single breakpoint"""
         clear_breakpoint(filename, lineno)
-        self.emit(SIGNAL("breakpoints_saved()"))
+        self.breakpoints_saved.emit()
         editorstack = self.get_current_editorstack()
         if editorstack is not None:
             index = self.is_file_opened(filename)
@@ -2031,10 +2067,10 @@ class Editor(SpyderPluginWidget):
             self.main.extconsole.execute_python_code(command)
     
     #------ Run Python script
+    @Slot()
     def edit_run_configurations(self):
         dialog = RunConfigDialog(self)
-        self.connect(dialog, SIGNAL("size_change(QSize)"),
-                     lambda s: self.set_dialog_size(s))
+        dialog.size_change.connect(lambda s: self.set_dialog_size(s))
         if self.dialog_size is not None:
             dialog.resize(self.dialog_size)
         fname = osp.abspath(self.get_current_filename())
@@ -2044,7 +2080,8 @@ class Editor(SpyderPluginWidget):
             if fname is not None:
                 self.load(fname)
                 self.run_file()
-        
+
+    @Slot()
     def run_file(self, debug=False):
         """Run script inside current interpreter or in a new one"""
         editorstack = self.get_current_editorstack()
@@ -2059,8 +2096,7 @@ class Editor(SpyderPluginWidget):
             runconf = get_run_configuration(fname)
             if runconf is None:
                 dialog = RunConfigOneDialog(self)
-                self.connect(dialog, SIGNAL("size_change(QSize)"),
-                             lambda s: self.set_dialog_size(s))
+                dialog.size_change.connect(lambda s: self.set_dialog_size(s))
                 if self.dialog_size is not None:
                     dialog.resize(self.dialog_size)
                 dialog.setup(fname)
@@ -2082,13 +2118,14 @@ class Editor(SpyderPluginWidget):
             args = runconf.get_arguments()
             python_args = runconf.get_python_arguments()
             interact = runconf.interact
+            post_mortem = runconf.post_mortem
             current = runconf.current
             systerm = runconf.systerm
             
             python = True # Note: in the future, it may be useful to run
             # something in a terminal instead of a Python interp.
             self.__last_ec_exec = (fname, wdir, args, interact, debug,
-                                   python, python_args, current, systerm)
+                                   python, python_args, current, systerm, post_mortem)
             self.re_run_file()
             if not interact and not debug:
                 # If external console dockwidget is hidden, it will be
@@ -2100,6 +2137,7 @@ class Editor(SpyderPluginWidget):
     def set_dialog_size(self, size):
         self.dialog_size = size
 
+    @Slot()
     def debug_file(self):
         """Debug current script"""
         self.run_file(debug=True)
@@ -2107,7 +2145,8 @@ class Editor(SpyderPluginWidget):
         if editor.get_breakpoints():
             time.sleep(0.5)
             self.debug_command('continue')
-        
+
+    @Slot()
     def re_run_file(self):
         """Re-run last script"""
         if self.get_option('save_all_before_run'):
@@ -2115,36 +2154,36 @@ class Editor(SpyderPluginWidget):
         if self.__last_ec_exec is None:
             return
         (fname, wdir, args, interact, debug,
-         python, python_args, current, systerm) = self.__last_ec_exec
+         python, python_args, current, systerm, post_mortem) = self.__last_ec_exec
         if current:
             if self.main.ipyconsole is not None:
                 if self.main.last_console_plugin_focus_was_python:
-                    self.emit(
-                      SIGNAL('run_in_current_extconsole(QString,QString,QString,bool)'),
-                      fname, wdir, args, debug)
+                    self.run_in_current_extconsole.emit(fname, wdir, args,
+                                                        debug, post_mortem)
                 else:
-                    self.emit(
-                      SIGNAL('run_in_current_ipyclient(QString,QString,QString,bool)'),
-                      fname, wdir, args, debug)
+                    self.run_in_current_ipyclient.emit(fname, wdir, args,
+                                                       debug, post_mortem)
             else:
-                self.emit(
-                  SIGNAL('run_in_current_extconsole(QString,QString,QString,bool)'),
-                  fname, wdir, args, debug)
+                self.run_in_current_extconsole.emit(fname, wdir, args, debug,
+                                                    post_mortem)
         else:
             self.main.open_external_console(fname, wdir, args, interact,
                                             debug, python, python_args,
-                                            systerm)
+                                            systerm, post_mortem)
 
+    @Slot()
     def run_selection(self):
         """Run selection or current line in external console"""
         editorstack = self.get_current_editorstack()
         editorstack.run_selection()
-    
+
+    @Slot()
     def run_cell(self):
         """Run current cell"""
         editorstack = self.get_current_editorstack()
         editorstack.run_cell()
 
+    @Slot()
     def run_cell_and_advance(self):
         """Run current cell and advance to the next one"""
         editorstack = self.get_current_editorstack()
diff --git a/spyderlib/plugins/explorer.py b/spyderlib/plugins/explorer.py
index ec6d6c2..4a92f1b 100644
--- a/spyderlib/plugins/explorer.py
+++ b/spyderlib/plugins/explorer.py
@@ -12,12 +12,13 @@
 # pylint: disable=R0201
 
 from spyderlib.qt.QtGui import QFontDialog
-from spyderlib.qt.QtCore import SIGNAL
+from spyderlib.qt.QtCore import Signal, Slot
+import spyderlib.utils.icon_manager as ima
 
 import os.path as osp
 
 # Local imports
-from spyderlib.baseconfig import _
+from spyderlib.config.base import _
 from spyderlib.utils.qthelpers import create_action
 from spyderlib.widgets.explorer import ExplorerWidget
 from spyderlib.plugins import SpyderPluginMixin
@@ -27,6 +28,15 @@ from spyderlib.py3compat import to_text_string
 class Explorer(ExplorerWidget, SpyderPluginMixin):
     """File and Directories Explorer DockWidget"""
     CONF_SECTION = 'explorer'
+    open_terminal = Signal(str)
+    open_interpreter = Signal(str)
+    edit = Signal(str)
+    removed = Signal(str)
+    renamed = Signal(str, str)
+    create_module = Signal(str)
+    run = Signal(str)
+    open_dir = Signal(str)
+    
     def __init__(self, parent=None):
         ExplorerWidget.__init__(self, parent=parent,
                                 name_filters=self.get_option('name_filters'),
@@ -54,7 +64,7 @@ class Explorer(ExplorerWidget, SpyderPluginMixin):
     def get_plugin_actions(self):
         """Return a list of actions related to plugin"""
         # Font
-        font_action = create_action(self, _("&Font..."), None, 'font.png',
+        font_action = create_action(self, _("&Font..."), None, ima.icon('font'),
                                     _("Set font style"),
                                     triggered=self.change_font)
         self.treewidget.common_actions.append(font_action)
@@ -63,31 +73,28 @@ class Explorer(ExplorerWidget, SpyderPluginMixin):
     def register_plugin(self):
         """Register plugin in Spyder's main window"""
         self.main.add_dockwidget(self)
-        self.connect(self, SIGNAL("edit(QString)"), self.main.editor.load)
-        self.connect(self, SIGNAL("removed(QString)"), self.main.editor.removed)
-        self.connect(self, SIGNAL("renamed(QString,QString)"),
-                     self.main.editor.renamed)
-        self.connect(self.main.editor, SIGNAL("open_dir(QString)"), self.chdir)
-        self.connect(self, SIGNAL("create_module(QString)"),
-                     self.main.editor.new)
-        self.connect(self, SIGNAL("run(QString)"),
+        self.edit.connect(self.main.editor.load)
+        self.removed.connect(self.main.editor.removed)
+        self.renamed.connect(self.main.editor.renamed)
+        self.main.editor.open_dir.connect(self.chdir)
+        self.create_module.connect(self.main.editor.new)
+        self.run.connect(
                      lambda fname:
                      self.main.open_external_console(to_text_string(fname),
                                          osp.dirname(to_text_string(fname)),
                                          '', False, False, True, '', False))
         # Signal "set_explorer_cwd(QString)" will refresh only the
         # contents of path passed by the signal in explorer:
-        self.connect(self.main.workingdirectory,
-                     SIGNAL("set_explorer_cwd(QString)"),
+        self.main.workingdirectory.set_explorer_cwd.connect(
                      lambda directory: self.refresh_plugin(new_path=directory,
                                                            force_current=True))
-        self.connect(self, SIGNAL("open_dir(QString)"),
+        self.open_dir.connect(
                      lambda dirname:
                      self.main.workingdirectory.chdir(dirname,
                                                       refresh_explorer=False))
 
         self.sig_open_file.connect(self.main.open_file)
-        self.sig_new_file.connect(self.main.new_file)
+        self.sig_new_file.connect(lambda t: self.main.editor.new(text=t))
         
     def refresh_plugin(self, new_path=None, force_current=True):
         """Refresh explorer widget"""
@@ -102,7 +109,8 @@ class Explorer(ExplorerWidget, SpyderPluginMixin):
     def chdir(self, directory):
         """Set working directory"""
         self.treewidget.chdir(directory)
-        
+    
+    @Slot()
     def change_font(self):
         """Change font"""
         font, valid = QFontDialog.getFont(self.get_plugin_font(), self,
diff --git a/spyderlib/plugins/externalconsole.py b/spyderlib/plugins/externalconsole.py
index 9996ef2..b0b5c24 100644
--- a/spyderlib/plugins/externalconsole.py
+++ b/spyderlib/plugins/externalconsole.py
@@ -12,12 +12,14 @@
 # pylint: disable=R0201
 
 # Qt imports
+from spyderlib.qt import PYQT5
 from spyderlib.qt.QtGui import (QVBoxLayout, QMessageBox, QInputDialog,
                                 QLineEdit, QPushButton, QGroupBox, QLabel,
                                 QTabWidget, QFontComboBox, QHBoxLayout,
                                 QButtonGroup, QWidget)
-from spyderlib.qt.QtCore import SIGNAL, Qt
+from spyderlib.qt.QtCore import Signal, Slot, Qt
 from spyderlib.qt.compat import getopenfilename
+import spyderlib.utils.icon_manager as ima
 
 # Stdlib imports
 import atexit
@@ -27,12 +29,12 @@ import sys
 import subprocess
 
 # Local imports
-from spyderlib.baseconfig import SCIENTIFIC_STARTUP, running_in_mac_app, _
-from spyderlib.config import CONF
+from spyderlib.config.base import SCIENTIFIC_STARTUP, running_in_mac_app, _
+from spyderlib.config.main import CONF
 from spyderlib.utils import encoding, programs
 from spyderlib.utils.misc import (get_error_match, get_python_executable,
                                   remove_backslashes, is_python_script)
-from spyderlib.utils.qthelpers import get_icon, create_action, mimedata2url
+from spyderlib.utils.qthelpers import create_action, mimedata2url
 from spyderlib.widgets.tabs import Tabs
 from spyderlib.widgets.externalshell.pythonshell import ExternalPythonShell
 from spyderlib.widgets.externalshell.systemshell import ExternalSystemShell
@@ -42,12 +44,14 @@ from spyderlib.plugins.runconfig import get_run_configuration
 from spyderlib.py3compat import to_text_string, is_text_string, getcwd
 from spyderlib import dependencies
 
+
 MPL_REQVER = '>=1.0'
 dependencies.add("matplotlib", _("Interactive data plotting in the consoles"),
                  required_version=MPL_REQVER)
 
 
 class ExternalConsoleConfigPage(PluginConfigPage):
+
     def __init__(self, plugin, parent):
         PluginConfigPage.__init__(self, plugin, parent)
         self.get_name = lambda: _("Console")
@@ -56,10 +60,8 @@ class ExternalConsoleConfigPage(PluginConfigPage):
 
     def initialize(self):
         PluginConfigPage.initialize(self)
-        self.connect(self.pyexec_edit, SIGNAL("textChanged(QString)"),
-                     self.python_executable_changed)
-        self.connect(self.cus_exec_radio, SIGNAL("toggled(bool)"),
-                     self.python_executable_switched)
+        self.pyexec_edit.textChanged.connect(self.python_executable_changed)
+        self.cus_exec_radio.toggled.connect(self.python_executable_switched)
 
     def setup_page(self):
         interface_group = QGroupBox(_("Interface"))
@@ -96,10 +98,8 @@ class ExternalConsoleConfigPage(PluginConfigPage):
                tip=_("This method is the only way to have colorized standard\n"
                      "error channel when the output channels have been "
                      "merged."))
-        self.connect(merge_channels_box, SIGNAL("toggled(bool)"),
-                     colorize_sys_stderr_box.setEnabled)
-        self.connect(merge_channels_box, SIGNAL("toggled(bool)"),
-                     colorize_sys_stderr_box.setChecked)
+        merge_channels_box.toggled.connect(colorize_sys_stderr_box.setEnabled)
+        merge_channels_box.toggled.connect(colorize_sys_stderr_box.setChecked)
         colorize_sys_stderr_box.setEnabled(
                                     self.get_option('merge_output_channels'))
         
@@ -167,8 +167,7 @@ class ExternalConsoleConfigPage(PluginConfigPage):
                                 "be applied only to new consoles"))
         umr_namelist_btn = QPushButton(
                             _("Set UMR excluded (not reloaded) modules"))
-        self.connect(umr_namelist_btn, SIGNAL('clicked()'),
-                     self.plugin.set_umr_namelist)
+        umr_namelist_btn.clicked.connect(self.plugin.set_umr_namelist)
         
         umr_layout = QVBoxLayout()
         umr_layout.addWidget(umr_label)
@@ -199,10 +198,8 @@ class ExternalConsoleConfigPage(PluginConfigPage):
         for le in self.lineedits:
             if self.lineedits[le][0] == 'pythonexecutable':
                 self.pyexec_edit = le
-        self.connect(def_exec_radio, SIGNAL("toggled(bool)"),
-                     pyexec_file.setDisabled)
-        self.connect(self.cus_exec_radio, SIGNAL("toggled(bool)"),
-                     pyexec_file.setEnabled)
+        def_exec_radio.toggled.connect(pyexec_file.setDisabled)
+        self.cus_exec_radio.toggled.connect(pyexec_file.setEnabled)
         pyexec_layout = QVBoxLayout()
         pyexec_layout.addWidget(pyexec_label)
         pyexec_layout.addWidget(def_exec_radio)
@@ -228,10 +225,8 @@ class ExternalConsoleConfigPage(PluginConfigPage):
         pystartup_file = self.create_browsefile('', 'pythonstartup', '',
                                                 filters=_("Python scripts")+\
                                                 " (*.py)")
-        self.connect(def_startup_radio, SIGNAL("toggled(bool)"),
-                     pystartup_file.setDisabled)
-        self.connect(cus_startup_radio, SIGNAL("toggled(bool)"),
-                     pystartup_file.setEnabled)
+        def_startup_radio.toggled.connect(pystartup_file.setDisabled)
+        cus_startup_radio.toggled.connect(pystartup_file.setEnabled)
         
         pystartup_layout = QVBoxLayout()
         pystartup_layout.addWidget(pystartup_label)
@@ -252,7 +247,7 @@ class ExternalConsoleConfigPage(PluginConfigPage):
         monitor_box = newcb(_("Enable monitor"), 'monitor/enabled')
         for obj in (completion_box, case_comp_box, comp_enter_box,
                     calltips_box):
-            self.connect(monitor_box, SIGNAL("toggled(bool)"), obj.setEnabled)
+            monitor_box.toggled.connect(obj.setEnabled)
             obj.setEnabled(self.get_option('monitor/enabled'))
         
         monitor_layout = QVBoxLayout()
@@ -261,85 +256,52 @@ class ExternalConsoleConfigPage(PluginConfigPage):
         monitor_group.setLayout(monitor_layout)
         
         # Qt Group
-        opts = [(_("Default library"), 'default'), ('PyQt4', 'pyqt'),
-                ('PySide', 'pyside')]
-        qt_group = QGroupBox(_("Qt (PyQt/PySide)"))
+        opts = [
+            (_("Default library"), 'default'),
+            ('PyQt5', 'pyqt5'),
+            ('PyQt4', 'pyqt'),
+            ('PySide', 'pyside'),
+        ]
+        qt_group = QGroupBox(_("Qt-Python Bindings"))
         qt_setapi_box = self.create_combobox(
-                         _("Qt-Python bindings library selection:"), opts,
+                         _("Library:") + "   ", opts,
                          'qt/api', default='default',
                          tip=_("This option will act on<br> "
                                "libraries such as Matplotlib, guidata "
                                "or ETS"))
-        if self.get_option('pythonexecutable/default'):
-            interpreter = get_python_executable()
-        else:
-            interpreter = self.get_option('pythonexecutable')
-        has_pyqt4 = programs.is_module_installed('PyQt4',
-                                                 interpreter=interpreter)
-        has_pyside = programs.is_module_installed('PySide',
-                                                  interpreter=interpreter)
-        if has_pyside and not has_pyqt4:
-            self.set_option('qt/api', 'pyside')
-        
+
         qt_layout = QVBoxLayout()
         qt_layout.addWidget(qt_setapi_box)
         qt_group.setLayout(qt_layout)
-        qt_group.setEnabled(has_pyqt4 or has_pyside)
-        
-        # PyQt Group
-        if has_pyqt4:
-            pyqt_group = QGroupBox(_("PyQt"))
-            setapi_box = self.create_combobox(
-                _("API selection for QString and QVariant objects:"),
-                ((_("Default API"), 0), (_("API #1"), 1), (_("API #2"), 2)),
-                'pyqt/api_version', default=0,
-                tip=_("PyQt API #1 is the default <br>"
-                      "API for Python 2. PyQt API #2 is "
-                      "the default API for Python 3 and "
-                      "is compatible with PySide."))
-            ignore_api_box = newcb(_("Ignore API change errors (sip.setapi)"),
-                                     'pyqt/ignore_sip_setapi_errors',
-                               tip=_("Enabling this option will ignore <br>"
-                                     "errors when changing PyQt API. As "
-                                     "PyQt does not support dynamic API "
-                                     "changes, it is strongly recommended "
-                                     "to use this feature wisely, e.g. "
-                                     "for debugging purpose."))
-            try:
-                from sip import setapi #analysis:ignore
-            except ImportError:
-                setapi_box.setDisabled(True)
-                ignore_api_box.setDisabled(True)
-            
-            pyqt_layout = QVBoxLayout()
-            pyqt_layout.addWidget(setapi_box)
-            pyqt_layout.addWidget(ignore_api_box)
-            pyqt_group.setLayout(pyqt_layout)
-            qt_layout.addWidget(pyqt_group)
-        
+
         # Matplotlib Group
-        mpl_group = QGroupBox(_("Matplotlib"))
-        mpl_backend_box = newcb('', 'matplotlib/backend/enabled', True)
-        mpl_backend_edit = self.create_lineedit(_("GUI backend:"),
-                                'matplotlib/backend/value', "Qt4Agg",
-                                tip=_("Set the GUI toolkit used by <br>"
-                                      "Matplotlib to show figures "
-                                      "(default: Qt4Agg)"),
-                                alignment=Qt.Horizontal)
-        self.connect(mpl_backend_box, SIGNAL("toggled(bool)"),
-                     mpl_backend_edit.setEnabled)
-        mpl_backend_layout = QHBoxLayout()
-        mpl_backend_layout.addWidget(mpl_backend_box)
-        mpl_backend_layout.addWidget(mpl_backend_edit)
-        mpl_backend_edit.setEnabled(
-                                self.get_option('matplotlib/backend/enabled'))
+        mpl_group = QGroupBox(_("Graphics"))
+        mpl_label = QLabel(_("Decide which backend to use to display graphics. "
+                              "If unsure, please select the <b>Automatic</b> "
+                              "backend.<br><br>"
+                              "<b>Note:</b> We support a very limited number "
+                              "of backends in our Python consoles. If you "
+                              "prefer to work with a different one, please use "
+                              "an IPython console."))
+        mpl_label.setWordWrap(True)
+
+        backends = [("Automatic", 0), ("None", 1)]
+        if not os.name == 'nt' and programs.is_module_installed('_tkinter'):
+            backends.append( ("Tkinter", 2) )
+        backends = tuple(backends)
+
+        mpl_backend_box = self.create_combobox( _("Backend:")+"   ", backends,
+                                       'matplotlib/backend/value',
+                                       tip=_("This option will be applied the "
+                                             "next time a console is opened."))
+
         mpl_installed = programs.is_module_installed('matplotlib')
-        
         mpl_layout = QVBoxLayout()
-        mpl_layout.addLayout(mpl_backend_layout)
+        mpl_layout.addWidget(mpl_label)
+        mpl_layout.addWidget(mpl_backend_box)
         mpl_group.setLayout(mpl_layout)
         mpl_group.setEnabled(mpl_installed)
-        
+
         # ETS Group
         ets_group = QGroupBox(_("Enthought Tool Suite"))
         ets_label = QLabel(_("Enthought Tool Suite (ETS) supports "
@@ -348,15 +310,20 @@ class ExternalConsoleConfigPage(PluginConfigPage):
         ets_label.setWordWrap(True)
         ets_edit = self.create_lineedit(_("ETS_TOOLKIT:"), 'ets_backend',
                                         alignment=Qt.Horizontal)
-        
+
         ets_layout = QVBoxLayout()
         ets_layout.addWidget(ets_label)
         ets_layout.addWidget(ets_edit)
         ets_group.setLayout(ets_layout)
+
+        if self.get_option('pythonexecutable/default'):
+            interpreter = get_python_executable()
+        else:
+            interpreter = self.get_option('pythonexecutable')
         ets_group.setEnabled(programs.is_module_installed(
                                                     "enthought.etsconfig.api",
                                                     interpreter=interpreter))
-        
+
         tabs = QTabWidget()
         tabs.addTab(self.create_tab(font_group, interface_group, display_group,
                                     bg_group),
@@ -372,31 +339,12 @@ class ExternalConsoleConfigPage(PluginConfigPage):
         vlayout.addWidget(tabs)
         self.setLayout(vlayout)
 
-    def _auto_change_qt_api(self, pyexec):
-        """Change automatically Qt API depending on
-        selected Python executable"""
-        has_pyqt4 = programs.is_module_installed('PyQt4', interpreter=pyexec)
-        has_pyside = programs.is_module_installed('PySide', interpreter=pyexec)
-        for cb in self.comboboxes:
-            if self.comboboxes[cb][0] == 'qt/api':
-                qt_setapi_cb = cb
-        if has_pyside and not has_pyqt4:
-            qt_setapi_cb.setCurrentIndex(2)
-        elif has_pyqt4 and not has_pyside:
-            qt_setapi_cb.setCurrentIndex(1)
-        else:
-            qt_setapi_cb.setCurrentIndex(0)
-
     def python_executable_changed(self, pyexec):
         """Custom Python executable value has been changed"""
         if not self.cus_exec_radio.isChecked():
             return
         if not is_text_string(pyexec):
             pyexec = to_text_string(pyexec.toUtf8(), 'utf-8')
-        old_pyexec = self.get_option("pythonexecutable",
-                                     get_python_executable())
-        if pyexec != old_pyexec:
-            self._auto_change_qt_api(pyexec)
         self.warn_python_compatibility(pyexec)
 
     def python_executable_switched(self, custom):
@@ -406,8 +354,6 @@ class ExternalConsoleConfigPage(PluginConfigPage):
         if not is_text_string(cust_pyexec):
             cust_pyexec = to_text_string(cust_pyexec.toUtf8(), 'utf-8')
         if def_pyexec != cust_pyexec:
-            pyexec = cust_pyexec if custom else def_pyexec
-            self._auto_change_qt_api(pyexec)
             if custom:
                 self.warn_python_compatibility(cust_pyexec)
 
@@ -440,8 +386,16 @@ class ExternalConsole(SpyderPluginWidget):
     CONF_SECTION = 'console'
     CONFIGWIDGET_CLASS = ExternalConsoleConfigPage
     DISABLE_ACTIONS_WHEN_HIDDEN = False
+
+    edit_goto = Signal((str, int, str), (str, int, str, bool))
+    focus_changed = Signal()
+    redirect_stdio = Signal(bool)
+    
     def __init__(self, parent, light_mode):
-        SpyderPluginWidget.__init__(self, parent)
+        if PYQT5:
+            SpyderPluginWidget.__init__(self, parent, main = parent)
+        else:
+            SpyderPluginWidget.__init__(self, parent)
         self.light_mode = light_mode
         self.tabwidget = None
         self.menu_actions = None
@@ -449,15 +403,10 @@ class ExternalConsole(SpyderPluginWidget):
         self.inspector = None # Object inspector plugin
         self.historylog = None # History log plugin
         self.variableexplorer = None # Variable explorer plugin
-        
+
         self.python_count = 0
         self.terminal_count = 0
 
-        try:
-            from sip import setapi #analysis:ignore
-        except ImportError:
-            self.set_option('pyqt/ignore_sip_setapi_errors', False)
-        
         # Python executable selection (initializing default values as well)
         executable = self.get_option('pythonexecutable',
                                      get_python_executable())
@@ -500,12 +449,9 @@ class ExternalConsole(SpyderPluginWidget):
             # a crash when the console is detached from the main window
             # Fixes Issue 561
             self.tabwidget.setDocumentMode(True)
-        self.connect(self.tabwidget, SIGNAL('currentChanged(int)'),
-                     self.refresh_plugin)
-        self.connect(self.tabwidget, SIGNAL('move_data(int,int)'),
-                     self.move_tab)
-        self.connect(self.main, SIGNAL("pythonpath_changed()"),
-                     self.set_path)
+        self.tabwidget.currentChanged.connect(self.refresh_plugin)
+        self.tabwidget.move_data.connect(self.move_tab)
+        self.main.sig_pythonpath_changed.connect(self.set_path)
                      
         self.tabwidget.set_close_function(self.close_console)
 
@@ -542,7 +488,7 @@ class ExternalConsole(SpyderPluginWidget):
         self.filenames.insert(index_to, filename)
         self.shellwidgets.insert(index_to, shell)
         self.icons.insert(index_to, icons)
-        self.emit(SIGNAL('update_plugin_title()'))
+        self.update_plugin_title.emit()
 
     def get_shell_index_from_id(self, shell_id):
         """Return shellwidget index from id"""
@@ -585,7 +531,7 @@ class ExternalConsole(SpyderPluginWidget):
             self.filenames.pop(index)
             self.shellwidgets.pop(index)
             self.icons.pop(index)
-            self.emit(SIGNAL('update_plugin_title()'))
+            self.update_plugin_title.emit()
         else:
             QMessageBox.question(self, _('Trying to kill a kernel?'),
                 _("You can't close this kernel because it has one or more "
@@ -652,7 +598,8 @@ class ExternalConsole(SpyderPluginWidget):
             else:
                 return shellwidgets[0].shell
         
-    def run_script_in_current_shell(self, filename, wdir, args, debug):
+    def run_script_in_current_shell(self, filename, wdir, args, debug, 
+                  post_mortem):
         """Run script in current shell, if any"""
         norm = lambda text: remove_backslashes(to_text_string(text))
         line = "%s('%s'" % ('debugfile' if debug else 'runfile',
@@ -661,6 +608,8 @@ class ExternalConsole(SpyderPluginWidget):
             line += ", args='%s'" % norm(args)
         if wdir:
             line += ", wdir='%s'" % norm(wdir)
+        if post_mortem:
+            line += ', post_mortem=True'
         line += ")"
         if not self.execute_python_code(line, interpreter_only=True):
             QMessageBox.warning(self, _('Warning'),
@@ -696,8 +645,7 @@ class ExternalConsole(SpyderPluginWidget):
         # This is a unique form of the edit_goto signal that is intended to 
         # prevent keyboard input from accidentally entering the editor
         # during repeated, rapid entry of debugging commands.    
-        self.emit(SIGNAL("edit_goto(QString,int,QString,bool)"),
-                  fname, lineno, '', False)
+        self.edit_goto[str, int, str, bool].emit(fname, lineno, '', False)
         if shellwidget.is_ipykernel:
             # Focus client widget, not kernel
             ipw = self.main.ipyconsole.get_focus_widget()
@@ -706,7 +654,7 @@ class ExternalConsole(SpyderPluginWidget):
         else:
             self.activateWindow()
             shellwidget.shell.setFocus()
-        
+    
     def set_spyder_breakpoints(self):
         """Set all Spyder breakpoints into all shells"""
         for shellwidget in self.shellwidgets:
@@ -714,7 +662,7 @@ class ExternalConsole(SpyderPluginWidget):
     
     def start(self, fname, wdir=None, args='', interact=False, debug=False,
               python=True, ipykernel=False, ipyclient=None,
-              give_ipyclient_focus=True, python_args=''):
+              give_ipyclient_focus=True, python_args='', post_mortem=True):
         """
         Start new console
         
@@ -768,24 +716,20 @@ class ExternalConsole(SpyderPluginWidget):
         if python:
             if self.get_option('pythonexecutable/default'):
                 pythonexecutable = get_python_executable()
+                external_interpreter = False
             else:
                 pythonexecutable = self.get_option('pythonexecutable')
+                external_interpreter = True
             if self.get_option('pythonstartup/default') or ipykernel:
                 pythonstartup = None
             else:
                 pythonstartup = self.get_option('pythonstartup', None)
             monitor_enabled = self.get_option('monitor/enabled')
-            if self.get_option('matplotlib/backend/enabled'):
-                mpl_backend = self.get_option('matplotlib/backend/value')
-            else:
-                mpl_backend = None
+            mpl_backend = self.get_option('matplotlib/backend/value')
             ets_backend = self.get_option('ets_backend')
             qt_api = self.get_option('qt/api')
-            if qt_api not in ('pyqt', 'pyside'):
+            if qt_api not in ('pyqt', 'pyside', 'pyqt5'):
                 qt_api = None
-            pyqt_api = self.get_option('pyqt/api_version')
-            ignore_sip_setapi_errors = self.get_option(
-                                            'pyqt/ignore_sip_setapi_errors')
             merge_output_channels = self.get_option('merge_output_channels')
             colorize_sys_stderr = self.get_option('colorize_sys_stderr')
             umr_enabled = self.get_option('umr/enabled')
@@ -810,18 +754,18 @@ class ExternalConsole(SpyderPluginWidget):
             else:
                 sa_settings = None
             shellwidget = ExternalPythonShell(self, fname, wdir,
-                           interact, debug, path=pythonpath,
+                           interact, debug, post_mortem=post_mortem, 
+                           path=pythonpath,
                            python_args=python_args,
                            ipykernel=ipykernel,
                            arguments=args, stand_alone=sa_settings,
                            pythonstartup=pythonstartup,
                            pythonexecutable=pythonexecutable,
+                           external_interpreter=external_interpreter,
                            umr_enabled=umr_enabled, umr_namelist=umr_namelist,
                            umr_verbose=umr_verbose, ets_backend=ets_backend,
                            monitor_enabled=monitor_enabled,
-                           mpl_backend=mpl_backend,
-                           qt_api=qt_api, pyqt_api=pyqt_api,
-                           ignore_sip_setapi_errors=ignore_sip_setapi_errors,
+                           mpl_backend=mpl_backend, qt_api=qt_api,
                            merge_output_channels=merge_output_channels,
                            colorize_sys_stderr=colorize_sys_stderr,
                            autorefresh_timeout=ar_timeout,
@@ -830,9 +774,9 @@ class ExternalConsole(SpyderPluginWidget):
                            menu_actions=self.menu_actions,
                            show_buttons_inside=False,
                            show_elapsed_time=show_elapsed_time)
-            self.connect(shellwidget, SIGNAL('pdb(QString,int)'),
-                         lambda fname, lineno, shellwidget=shellwidget:
-                         self.pdb_has_stopped(fname, lineno, shellwidget))
+            shellwidget.sig_pdb.connect(
+                              lambda fname, lineno, shellwidget=shellwidget:
+                              self.pdb_has_stopped(fname, lineno, shellwidget))
             self.register_widget_shortcuts("Console", shellwidget.shell)
         else:
             if os.name == 'posix':
@@ -873,23 +817,19 @@ class ExternalConsole(SpyderPluginWidget):
                                CONF.get('inspector', 'connect/python_console'))
         if self.historylog is not None:
             self.historylog.add_history(shellwidget.shell.history_filename)
-            self.connect(shellwidget.shell,
-                         SIGNAL('append_to_history(QString,QString)'),
-                         self.historylog.append_to_history)
-        self.connect(shellwidget.shell, SIGNAL("go_to_error(QString)"),
-                     self.go_to_error)
-        self.connect(shellwidget.shell, SIGNAL("focus_changed()"),
-                     lambda: self.emit(SIGNAL("focus_changed()")))
+            shellwidget.shell.append_to_history.connect(
+                                             self.historylog.append_to_history)
+            shellwidget.shell.go_to_error.connect(self.go_to_error)
+            shellwidget.shell.focus_changed.connect(        
+                                             lambda: self.focus_changed.emit())
         if python:
             if self.main.editor is not None:
-                self.connect(shellwidget, SIGNAL('open_file(QString,int)'),
-                             self.open_file_in_spyder)
+                shellwidget.open_file.connect(self.open_file_in_spyder)
             if fname is None:
                 if ipykernel:
                     # Connect client to any possible error while starting the
                     # kernel
-                    ipyclient.connect(shellwidget,
-                              SIGNAL("ipython_kernel_start_error(QString)"),
+                    shellwidget.ipython_kernel_start_error.connect(
                               lambda error: ipyclient.show_kernel_error(error))
                     
                     # Detect if kernel and frontend match or not
@@ -903,29 +843,26 @@ class ExternalConsole(SpyderPluginWidget):
                             frontend_ver = '<3.0'
                         else:
                             frontend_ver = '>=3.0'
-                        pyexec = self.get_option('pythonexecutable')
                         kernel_and_frontend_match = \
                           programs.is_module_installed('IPython',
-                                                       version=frontend_ver,
-                                                       interpreter=pyexec)
+                                                  version=frontend_ver,
+                                                  interpreter=pythonexecutable)
                     else:
                         kernel_and_frontend_match = True
-                    
+
                     # Create a a kernel tab only if frontend and kernel
                     # versions match
                     if kernel_and_frontend_match:
                         tab_name = _("Kernel")
-                        tab_icon1 = get_icon('ipython_console.png')
-                        tab_icon2 = get_icon('ipython_console_t.png')
-                        self.connect(shellwidget,
-                                     SIGNAL('create_ipython_client(QString)'),
+                        tab_icon1 = ima.icon('ipython_console')
+                        tab_icon2 = ima.icon('ipython_console_t')
+                        shellwidget.create_ipython_client.connect(
                                      lambda cf: self.register_ipyclient(cf,
                                               ipyclient,
                                               shellwidget,
                                               give_focus=give_ipyclient_focus))
                     else:
-                        shellwidget.emit(
-                          SIGNAL("ipython_kernel_start_error(QString)"),
+                        shellwidget.ipython_kernel_start_error.emit(
                           _("Either:"
                             "<ol>"
                             "<li>Your IPython frontend and kernel versions "
@@ -941,12 +878,12 @@ class ExternalConsole(SpyderPluginWidget):
                 else:
                     self.python_count += 1
                     tab_name = "Python %d" % self.python_count
-                    tab_icon1 = get_icon('python.png')
-                    tab_icon2 = get_icon('python_t.png')
+                    tab_icon1 = ima.icon('python')
+                    tab_icon2 = ima.icon('python_t')
             else:
                 tab_name = osp.basename(fname)
-                tab_icon1 = get_icon('run.png')
-                tab_icon2 = get_icon('terminated.png')
+                tab_icon1 = ima.icon('run')
+                tab_icon2 = ima.icon('terminated')
         else:
             fname = id(shellwidget)
             if os.name == 'nt':
@@ -955,8 +892,8 @@ class ExternalConsole(SpyderPluginWidget):
                 tab_name = _("Terminal")
             self.terminal_count += 1
             tab_name += (" %d" % self.terminal_count)
-            tab_icon1 = get_icon('cmdprompt.png')
-            tab_icon2 = get_icon('cmdprompt_t.png')
+            tab_icon1 = ima.icon('cmdprompt')
+            tab_icon2 = ima.icon('cmdprompt_t')
         self.shellwidgets.insert(index, shellwidget)
         self.filenames.insert(index, fname)
         self.icons.insert(index, (tab_icon1, tab_icon2))
@@ -965,9 +902,9 @@ class ExternalConsole(SpyderPluginWidget):
         else:
             self.tabwidget.insertTab(index, shellwidget, tab_name)
         
-        self.connect(shellwidget, SIGNAL("started()"),
+        shellwidget.started.connect(
                      lambda sid=id(shellwidget): self.process_started(sid))
-        self.connect(shellwidget, SIGNAL("finished()"),
+        shellwidget.sig_finished.connect(
                      lambda sid=id(shellwidget): self.process_finished(sid))
         self.find_widget.set_editor(shellwidget.shell)
         self.tabwidget.setTabToolTip(index, fname if wdir is None else wdir)
@@ -1073,7 +1010,7 @@ class ExternalConsole(SpyderPluginWidget):
     
     def get_plugin_icon(self):
         """Return widget icon"""
-        return get_icon('console.png')
+        return ima.icon('console')
     
     def get_focus_widget(self):
         """
@@ -1086,7 +1023,8 @@ class ExternalConsole(SpyderPluginWidget):
         """Return a list of actions related to plugin"""
         interpreter_action = create_action(self,
                             _("Open a &Python console"), None,
-                            'python.png', triggered=self.open_interpreter)
+                            ima.icon('python'),
+                            triggered=self.open_interpreter)
         if os.name == 'nt':
             text = _("Open &command prompt")
             tip = _("Open a Windows command prompt")
@@ -1097,7 +1035,7 @@ class ExternalConsole(SpyderPluginWidget):
                                         triggered=self.open_terminal)
         run_action = create_action(self,
                             _("&Run..."), None,
-                            'run_small.png', _("Run a Python script"),
+                            ima.icon('run_small'), _("Run a Python script"),
                             triggered=self.run_script)
 
         consoles_menu_actions = [interpreter_action]
@@ -1120,39 +1058,31 @@ class ExternalConsole(SpyderPluginWidget):
             if self.inspector is not None:
                 self.inspector.set_external_console(self)
             self.historylog = self.main.historylog
-            self.connect(self, SIGNAL("edit_goto(QString,int,QString)"),
-                         self.main.editor.load)
-            self.connect(self, SIGNAL("edit_goto(QString,int,QString,bool)"),
+            self.edit_goto.connect(self.main.editor.load)
+            self.edit_goto[str, int, str, bool].connect(
                          lambda fname, lineno, word, processevents:
                          self.main.editor.load(fname, lineno, word,
                                                processevents=processevents))
-            self.connect(self.main.editor,
-                         SIGNAL('run_in_current_extconsole(QString,QString,QString,bool)'),
+            self.main.editor.run_in_current_extconsole.connect(
                          self.run_script_in_current_shell)
-            self.connect(self.main.editor,
-                         SIGNAL("breakpoints_saved()"),
+            self.main.editor.breakpoints_saved.connect(
                          self.set_spyder_breakpoints)
-            self.connect(self.main.editor, SIGNAL("open_dir(QString)"),
+            self.main.editor.open_dir.connect(
                          self.set_current_shell_working_directory)
-            self.connect(self.main.workingdirectory,
-                         SIGNAL("set_current_console_wd(QString)"),
+            self.main.workingdirectory.set_current_console_wd.connect(
                          self.set_current_shell_working_directory)
-            self.connect(self, SIGNAL('focus_changed()'),
+            self.focus_changed.connect(
                          self.main.plugin_focus_changed)
-            self.connect(self, SIGNAL('redirect_stdio(bool)'),
+            self.redirect_stdio.connect(
                          self.main.redirect_internalshell_stdio)
             expl = self.main.explorer
             if expl is not None:
-                self.connect(expl, SIGNAL("open_terminal(QString)"),
-                             self.open_terminal)
-                self.connect(expl, SIGNAL("open_interpreter(QString)"),
-                             self.open_interpreter)
+                expl.open_terminal.connect(self.open_terminal)
+                expl.open_interpreter.connect(self.open_interpreter)
             pexpl = self.main.projectexplorer
             if pexpl is not None:
-                self.connect(pexpl, SIGNAL("open_terminal(QString)"),
-                             self.open_terminal)
-                self.connect(pexpl, SIGNAL("open_interpreter(QString)"),
-                             self.open_interpreter)
+                pexpl.open_terminal.connect(self.open_terminal)
+                pexpl.open_interpreter.connect(self.open_interpreter)
         
     def closing_plugin(self, cancelable=False):
         """Perform actions before parent main window is closed"""
@@ -1177,7 +1107,7 @@ class ExternalConsole(SpyderPluginWidget):
         if shellwidget:
             shellwidget.update_time_label_visibility()
         self.main.last_console_plugin_focus_was_python = True
-        self.emit(SIGNAL('update_plugin_title()'))
+        self.update_plugin_title.emit()
     
     def apply_plugin_settings(self, options):
         """Apply configuration file's plugin settings"""
@@ -1248,6 +1178,7 @@ class ExternalConsole(SpyderPluginWidget):
             self.dockwidget.hide()
     
     #------ Public API ---------------------------------------------------------
+    @Slot(str)
     def open_interpreter(self, wdir=None):
         """Open interpreter"""
         if wdir is None:
@@ -1272,19 +1203,21 @@ class ExternalConsole(SpyderPluginWidget):
                    interact=True, debug=False, python=True, ipykernel=True,
                    ipyclient=client, give_ipyclient_focus=give_focus)
 
+    @Slot(str)
     def open_terminal(self, wdir=None):
         """Open terminal"""
         if wdir is None:
             wdir = getcwd()
         self.start(fname=None, wdir=to_text_string(wdir), args='',
                    interact=True, debug=False, python=False)
-        
+
+    @Slot()
     def run_script(self):
         """Run a Python script"""
-        self.emit(SIGNAL('redirect_stdio(bool)'), False)
+        self.redirect_stdio.emit(False)
         filename, _selfilter = getopenfilename(self, _("Run Python script"),
                 getcwd(), _("Python scripts")+" (*.py ; *.pyw ; *.ipy)")
-        self.emit(SIGNAL('redirect_stdio(bool)'), True)
+        self.redirect_stdio.emit(True)
         if filename:
             self.start(fname=filename, wdir=None, args='',
                        interact=False, debug=False)
@@ -1321,8 +1254,7 @@ class ExternalConsole(SpyderPluginWidget):
         match = get_error_match(to_text_string(text))
         if match:
             fname, lnb = match.groups()
-            self.emit(SIGNAL("edit_goto(QString,int,QString)"),
-                      osp.abspath(fname), int(lnb), '')
+            self.edit_goto.emit(osp.abspath(fname), int(lnb), '')
             
     #----Drag and drop
     def dragEnterEvent(self, event):
diff --git a/spyderlib/plugins/findinfiles.py b/spyderlib/plugins/findinfiles.py
index d5ffc81..5e4f1aa 100644
--- a/spyderlib/plugins/findinfiles.py
+++ b/spyderlib/plugins/findinfiles.py
@@ -12,10 +12,11 @@
 # pylint: disable=R0201
 
 from spyderlib.qt.QtGui import QApplication
-from spyderlib.qt.QtCore import SIGNAL, Signal
+from spyderlib.qt.QtCore import Signal, Slot
+import spyderlib.utils.icon_manager as ima
 
 # Local imports
-from spyderlib.baseconfig import _
+from spyderlib.config.base import _
 from spyderlib.utils.qthelpers import create_action
 from spyderlib.widgets.findinfiles import FindInFilesWidget
 from spyderlib.plugins import SpyderPluginMixin
@@ -26,6 +27,10 @@ class FindInFiles(FindInFilesWidget, SpyderPluginMixin):
     """Find in files DockWidget"""
     CONF_SECTION = 'find_in_files'
     sig_option_changed = Signal(str, object)
+    toggle_visibility = Signal(bool)
+    edit_goto = Signal(str, int, str)
+    redirect_stdio = Signal(bool)
+    
     def __init__(self, parent=None):
         supported_encodings = self.get_option('supported_encodings')
         
@@ -56,7 +61,7 @@ class FindInFiles(FindInFilesWidget, SpyderPluginMixin):
         # Initialize plugin
         self.initialize_plugin()
         
-        self.connect(self, SIGNAL('toggle_visibility(bool)'), self.toggle)
+        self.toggle_visibility.connect(self.toggle)
         
     def toggle(self, state):
         """Toggle widget visibility"""
@@ -67,6 +72,7 @@ class FindInFiles(FindInFilesWidget, SpyderPluginMixin):
         """Refresh search directory"""
         self.find_options.set_directory(getcwd())
 
+    @Slot()
     def findinfiles_callback(self):
         """Find in files callback"""
         widget = QApplication.focusWidget()
@@ -84,7 +90,14 @@ class FindInFiles(FindInFilesWidget, SpyderPluginMixin):
         if text:
             self.find()
         
-    #------ SpyderPluginWidget API ---------------------------------------------    
+    #------ SpyderPluginMixin API ---------------------------------------------    
+    def switch_to_plugin(self):
+        """Switch to plugin
+        This method is called when pressing plugin's shortcut key"""
+        self.findinfiles_callback()  # Necessary at least with PyQt5 on Windows
+        SpyderPluginMixin.switch_to_plugin(self)
+
+    #------ SpyderPluginWidget API --------------------------------------------    
     def get_plugin_title(self):
         """Return widget title"""
         return _("Find in files")
@@ -104,15 +117,12 @@ class FindInFiles(FindInFilesWidget, SpyderPluginMixin):
         """Register plugin in Spyder's main window"""
         self.get_pythonpath_callback = self.main.get_spyder_pythonpath
         self.main.add_dockwidget(self)
-        self.connect(self, SIGNAL("edit_goto(QString,int,QString)"),
-                     self.main.editor.load)
-        self.connect(self, SIGNAL('redirect_stdio(bool)'),
-                     self.main.redirect_internalshell_stdio)
-        self.connect(self.main.workingdirectory,
-                     SIGNAL("refresh_findinfiles()"), self.refreshdir)
+        self.edit_goto.connect(self.main.editor.load)
+        self.redirect_stdio.connect(self.main.redirect_internalshell_stdio)
+        self.main.workingdirectory.refresh_findinfiles.connect(self.refreshdir)
         
         findinfiles_action = create_action(self, _("&Find in files"),
-                                   icon='findf.png',
+                                   icon=ima.icon('findf'),
                                    triggered=self.findinfiles_callback,
                                    tip=_("Search text in multiple files"))        
         
diff --git a/spyderlib/plugins/history.py b/spyderlib/plugins/history.py
index 9a0bc70..9422d4f 100644
--- a/spyderlib/plugins/history.py
+++ b/spyderlib/plugins/history.py
@@ -6,21 +6,22 @@
 
 """Console History Plugin"""
 
+from spyderlib.qt import PYQT5
 from spyderlib.qt.QtGui import (QVBoxLayout, QFontDialog, QInputDialog,
                                 QToolButton, QMenu, QFontComboBox, QGroupBox,
                                 QHBoxLayout, QWidget)
-from spyderlib.qt.QtCore import SIGNAL
+from spyderlib.qt.QtCore import Signal, Slot
+import spyderlib.utils.icon_manager as ima
 
 import os.path as osp
 import sys
 
 # Local imports
 from spyderlib.utils import encoding
-from spyderlib.baseconfig import _
-from spyderlib.config import CONF
-from spyderlib.guiconfig import get_color_scheme
-from spyderlib.utils.qthelpers import (get_icon, create_action,
-                                       create_toolbutton, add_actions)
+from spyderlib.config.base import _
+from spyderlib.config.main import CONF
+from spyderlib.config.gui import get_color_scheme
+from spyderlib.utils.qthelpers import (create_action, create_toolbutton, add_actions)
 from spyderlib.widgets.tabs import Tabs
 from spyderlib.widgets.sourcecode import codeeditor
 from spyderlib.widgets.findreplace import FindReplace
@@ -30,7 +31,7 @@ from spyderlib.py3compat import to_text_string, is_text_string
 
 class HistoryConfigPage(PluginConfigPage):
     def get_icon(self):
-        return get_icon('history24.png')
+        return ima.icon('history')
     
     def setup_page(self):
         settings_group = QGroupBox(_("Settings"))
@@ -62,8 +63,8 @@ class HistoryConfigPage(PluginConfigPage):
         sourcecode_group.setLayout(sourcecode_layout)
         
         vlayout = QVBoxLayout()
-        vlayout.addWidget(settings_group)
         vlayout.addWidget(font_group)
+        vlayout.addWidget(settings_group)
         vlayout.addWidget(sourcecode_group)
         vlayout.addStretch(1)
         self.setLayout(vlayout)
@@ -75,6 +76,8 @@ class HistoryLog(SpyderPluginWidget):
     """
     CONF_SECTION = 'historylog'
     CONFIGWIDGET_CLASS = HistoryConfigPage
+    focus_changed = Signal()
+    
     def __init__(self, parent):
         self.tabwidget = None
         self.menu_actions = None
@@ -84,8 +87,10 @@ class HistoryLog(SpyderPluginWidget):
         self.editors = []
         self.filenames = []
         self.icons = []
-        
-        SpyderPluginWidget.__init__(self, parent)
+        if PYQT5:        
+            SpyderPluginWidget.__init__(self, parent, main = parent)
+        else:
+            SpyderPluginWidget.__init__(self, parent)
 
         # Initialize plugin
         self.initialize_plugin()
@@ -94,10 +99,8 @@ class HistoryLog(SpyderPluginWidget):
         
         layout = QVBoxLayout()
         self.tabwidget = Tabs(self, self.menu_actions)
-        self.connect(self.tabwidget, SIGNAL('currentChanged(int)'),
-                     self.refresh_plugin)
-        self.connect(self.tabwidget, SIGNAL('move_data(int,int)'),
-                     self.move_tab)
+        self.tabwidget.currentChanged.connect(self.refresh_plugin)
+        self.tabwidget.move_data.connect(self.move_tab)
 
         if sys.platform == 'darwin':
             tab_container = QWidget()
@@ -109,9 +112,11 @@ class HistoryLog(SpyderPluginWidget):
         else:
             layout.addWidget(self.tabwidget)
 
+        self.tabwidget.setStyleSheet("QTabWidget::pane {border: 0;}")
+
         # Menu as corner widget
-        options_button = create_toolbutton(self, text=_("Options"),
-                                           icon=get_icon('tooloptions.png'))
+        options_button = create_toolbutton(self, text=_('Options'),
+                                           icon=ima.icon('tooloptions'))
         options_button.setPopupMode(QToolButton.InstantPopup)
         menu = QMenu(self)
         add_actions(menu, self.menu_actions)
@@ -134,7 +139,7 @@ class HistoryLog(SpyderPluginWidget):
     
     def get_plugin_icon(self):
         """Return widget icon"""
-        return get_icon('history.png')
+        return ima.icon('history')
     
     def get_focus_widget(self):
         """
@@ -158,11 +163,11 @@ class HistoryLog(SpyderPluginWidget):
     def get_plugin_actions(self):
         """Return a list of actions related to plugin"""
         history_action = create_action(self, _("History..."),
-                                       None, 'history.png',
+                                       None, ima.icon('history'),
                                        _("Set history maximum entries"),
                                        triggered=self.change_history_depth)
         font_action = create_action(self, _("&Font..."), None,
-                                    'font.png', _("Set shell font style"),
+                                    ima.icon('font'), _("Set shell font style"),
                                     triggered=self.change_font)
         self.wrap_action = create_action(self, _("Wrap lines"),
                                     toggled=self.toggle_wrap_mode)
@@ -176,12 +181,10 @@ class HistoryLog(SpyderPluginWidget):
     
     def register_plugin(self):
         """Register plugin in Spyder's main window"""
-        self.connect(self, SIGNAL('focus_changed()'),
-                     self.main.plugin_focus_changed)
+        self.focus_changed.connect(self.main.plugin_focus_changed)
         self.main.add_dockwidget(self)
 #        self.main.console.set_historylog(self)
-        self.connect(self.main.console.shell, SIGNAL("refresh()"),
-                     self.refresh_plugin)
+        self.main.console.shell.refresh.connect(self.refresh_plugin)
 
     def apply_plugin_settings(self, options):
         """Apply configuration file's plugin settings"""
@@ -218,7 +221,7 @@ class HistoryLog(SpyderPluginWidget):
     def add_history(self, filename):
         """
         Add new history tab
-        Slot for SIGNAL('add_history(QString)') emitted by shell instance
+        Slot for add_history signal emitted by shell instance
         """
         filename = encoding.to_unicode_from_fs(filename)
         if filename in self.filenames:
@@ -226,14 +229,13 @@ class HistoryLog(SpyderPluginWidget):
         editor = codeeditor.CodeEditor(self)
         if osp.splitext(filename)[1] == '.py':
             language = 'py'
-            icon = get_icon('python.png')
+            icon = ima.icon('python')
         else:
             language = 'bat'
-            icon = get_icon('cmdprompt.png')
+            icon = ima.icon('cmdprompt')
         editor.setup_editor(linenumbers=False, language=language,
                             scrollflagarea=False)
-        self.connect(editor, SIGNAL("focus_changed()"),
-                     lambda: self.emit(SIGNAL("focus_changed()")))
+        editor.focus_changed.connect(lambda: self.focus_changed.emit())
         editor.setReadOnly(True)
         color_scheme = get_color_scheme(self.get_option('color_scheme_name'))
         editor.set_font( self.get_plugin_font(), color_scheme )
@@ -255,8 +257,7 @@ class HistoryLog(SpyderPluginWidget):
     def append_to_history(self, filename, command):
         """
         Append an entry to history filename
-        Slot for SIGNAL('append_to_history(QString,QString)')
-        emitted by shell instance
+        Slot for append_to_history signal emitted by shell instance
         """
         if not is_text_string(filename): # filename is a QString
             filename = to_text_string(filename.toUtf8(), 'utf-8')
@@ -266,7 +267,8 @@ class HistoryLog(SpyderPluginWidget):
         if self.get_option('go_to_eof'):
             self.editors[index].set_cursor_position('eof')
         self.tabwidget.setCurrentIndex(index)
-        
+    
+    @Slot()
     def change_history_depth(self):
         "Change history max entries"""
         depth, valid = QInputDialog.getInteger(self, _('History'),
@@ -275,7 +277,8 @@ class HistoryLog(SpyderPluginWidget):
                                        10, 10000)
         if valid:
             self.set_option('max_entries', depth)
-        
+    
+    @Slot()
     def change_font(self):
         """Change console font"""
         font, valid = QFontDialog.getFont(self.get_plugin_font(),
@@ -284,7 +287,8 @@ class HistoryLog(SpyderPluginWidget):
             for editor in self.editors:
                 editor.set_font(font)
             self.set_plugin_font(font)
-            
+    
+    @Slot(bool)
     def toggle_wrap_mode(self, checked):
         """Toggle wrap mode"""
         if self.tabwidget is None:
diff --git a/spyderlib/plugins/inspector.py b/spyderlib/plugins/inspector.py
index 2453e7f..d859558 100644
--- a/spyderlib/plugins/inspector.py
+++ b/spyderlib/plugins/inspector.py
@@ -6,12 +6,14 @@
 
 """Object Inspector Plugin"""
 
+from spyderlib.qt import PYQT5
 from spyderlib.qt.QtGui import (QHBoxLayout, QVBoxLayout, QLabel, QSizePolicy,
                                 QMenu, QToolButton, QGroupBox, QFontComboBox,
                                 QActionGroup, QFontDialog, QWidget, QComboBox,
                                 QLineEdit, QMessageBox)
-from spyderlib.qt.QtCore import SIGNAL, QUrl, QThread
+from spyderlib.qt.QtCore import Signal, Slot, QUrl, QThread
 from spyderlib.qt.QtWebKit import QWebPage
+import spyderlib.utils.icon_manager as ima
 
 import re
 import os.path as osp
@@ -20,17 +22,17 @@ import sys
 
 # Local imports
 from spyderlib import dependencies
-from spyderlib.baseconfig import get_conf_path, get_module_source_path, _
-from spyderlib.ipythonconfig import IPYTHON_QT_INSTALLED
-from spyderlib.config import CONF
-from spyderlib.guiconfig import get_color_scheme, get_font, set_font
+from spyderlib.config.base import get_conf_path, get_module_source_path, _
+from spyderlib.config.ipython import IPYTHON_QT_INSTALLED
+from spyderlib.config.main import CONF
+from spyderlib.config.gui import get_color_scheme, get_font, set_font
 from spyderlib.utils import programs
-from spyderlib.utils.qthelpers import (get_icon, create_toolbutton,
-                                       add_actions, create_action)
+from spyderlib.utils.qthelpers import (create_toolbutton, add_actions,
+                                       create_action)
 from spyderlib.widgets.comboboxes import EditableComboBox
 from spyderlib.widgets.sourcecode import codeeditor
 from spyderlib.widgets.findreplace import FindReplace
-from spyderlib.widgets.browser import WebView
+from spyderlib.widgets.browser import FrameWebView
 from spyderlib.widgets.externalshell.pythonshell import ExtPythonShellWidget
 from spyderlib.plugins import SpyderPluginWidget, PluginConfigPage
 from spyderlib.py3compat import to_text_string, get_meth_class_inst
@@ -61,12 +63,15 @@ class ObjectComboBox(EditableComboBox):
     """
     QComboBox handling object names
     """
+    # Signals
+    valid = Signal(bool, bool)
+
     def __init__(self, parent):
         EditableComboBox.__init__(self, parent)
         self.object_inspector = parent
         self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
         self.tips = {True: '', False: ''}
-        
+
     def is_valid(self, qstr=None):
         """Return True if string is valid"""
         if not self.object_inspector.source_is_console():
@@ -91,10 +96,10 @@ class ObjectComboBox(EditableComboBox):
                 except socket.error:
                     # Well... too bad!
                     pass
-        
+
     def validate_current_text(self):
         self.validate(self.currentText())
-    
+
     def validate(self, qstr, editing=True):
         """Reimplemented to avoid formatting actions"""
         valid = self.is_valid(qstr)
@@ -102,26 +107,24 @@ class ObjectComboBox(EditableComboBox):
             if editing:
                 # Combo box text is being modified: invalidate the entry
                 self.show_tip(self.tips[valid])
-                self.emit(SIGNAL('valid(bool)'), False)
+                self.valid.emit(False, False)
             else:
                 # A new item has just been selected
                 if valid:
                     self.selected()
                 else:
-                    self.emit(SIGNAL('valid(bool)'), False)
-        else:
-            self.set_default_style()
+                    self.valid.emit(False, False)
 
 
 class ObjectInspectorConfigPage(PluginConfigPage):
     def setup_page(self):
-        # Fonts group        
+        # Fonts group
         plain_text_font_group = self.create_fontgroup(option=None,
                                     text=_("Plain text font style"),
                                     fontfilters=QFontComboBox.MonospacedFonts)
         rich_text_font_group = self.create_fontgroup(option='rich_text',
                                 text=_("Rich text font style"))
-        
+
         # Connections group
         connections_group = QGroupBox(_("Automatic connections"))
         connections_label = QLabel(_("The Object Inspector can automatically "
@@ -144,14 +147,14 @@ class ObjectInspectorConfigPage(PluginConfigPage):
         ipython_box = self.create_checkbox(_("IPython Console"),
                                            'connect/ipython_console')
         ipython_box.setEnabled(IPYTHON_QT_INSTALLED)
-        
+
         connections_layout = QVBoxLayout()
         connections_layout.addWidget(connections_label)
         connections_layout.addWidget(editor_box)
         connections_layout.addWidget(python_box)
         connections_layout.addWidget(ipython_box)
         connections_group.setLayout(connections_layout)
-        
+
         # Features group
         features_group = QGroupBox(_("Additional features"))
         math_box = self.create_checkbox(_("Render mathematical equations"),
@@ -165,11 +168,11 @@ class ObjectInspectorConfigPage(PluginConfigPage):
                 sphinx_tip += "\n" + _("Sphinx %s is currently installed."
                                        ) % sphinx_version
             math_box.setToolTip(sphinx_tip)
-        
+
         features_layout = QVBoxLayout()
         features_layout.addWidget(math_box)
         features_group.setLayout(features_layout)
-        
+
         # Source code group
         sourcecode_group = QGroupBox(_("Source code"))
         wrap_mode_box = self.create_checkbox(_("Wrap lines"), 'wrap')
@@ -182,7 +185,7 @@ class ObjectInspectorConfigPage(PluginConfigPage):
         sourcecode_layout.addWidget(wrap_mode_box)
         sourcecode_layout.addWidget(cs_combo)
         sourcecode_group.setLayout(sourcecode_layout)
-        
+
         # Final layout
         vlayout = QVBoxLayout()
         vlayout.addWidget(rich_text_font_group)
@@ -200,34 +203,37 @@ class RichText(QWidget):
     """
     def __init__(self, parent):
         QWidget.__init__(self, parent)
-        
-        self.webview = WebView(self)
+
+        self.webview = FrameWebView(self)
         self.find_widget = FindReplace(self)
         self.find_widget.set_editor(self.webview)
         self.find_widget.hide()
-        
+
         layout = QVBoxLayout()
         layout.setContentsMargins(0, 0, 0, 0)
         layout.addWidget(self.webview)
         layout.addWidget(self.find_widget)
         self.setLayout(layout)
-        
+
     def set_font(self, font, fixed_font=None):
         """Set font"""
         self.webview.set_font(font, fixed_font=fixed_font)
-        
+
     def set_html(self, html_text, base_url):
         """Set html text"""
         self.webview.setHtml(html_text, base_url)
-        
+
     def clear(self):
         self.set_html('', self.webview.url())
-        
-        
+
+
 class PlainText(QWidget):
     """
     Read-only editor widget with find dialog
     """
+    # Signals
+    focus_changed = Signal()
+
     def __init__(self, parent):
         QWidget.__init__(self, parent)
         self.editor = None
@@ -236,29 +242,28 @@ class PlainText(QWidget):
         self.editor = codeeditor.CodeEditor(self)
         self.editor.setup_editor(linenumbers=False, language='py',
                                  scrollflagarea=False, edge_line=False)
-        self.connect(self.editor, SIGNAL("focus_changed()"),
-                     lambda: self.emit(SIGNAL("focus_changed()")))
+        self.editor.focus_changed.connect(lambda: self.focus_changed.emit())
         self.editor.setReadOnly(True)
-        
+
         # Find/replace widget
         self.find_widget = FindReplace(self)
         self.find_widget.set_editor(self.editor)
         self.find_widget.hide()
-        
+
         layout = QVBoxLayout()
         layout.setContentsMargins(0, 0, 0, 0)
         layout.addWidget(self.editor)
         layout.addWidget(self.find_widget)
         self.setLayout(layout)
-        
+
     def set_font(self, font, color_scheme=None):
         """Set font"""
         self.editor.set_font(font, color_scheme=color_scheme)
-        
+
     def set_color_scheme(self, color_scheme):
         """Set color scheme"""
         self.editor.set_color_scheme(color_scheme)
-        
+
     def set_text(self, text, is_code):
         self.editor.set_highlight_current_line(is_code)
         self.editor.set_occurence_highlighting(is_code)
@@ -268,7 +273,7 @@ class PlainText(QWidget):
             self.editor.set_language(None)
         self.editor.set_text(text)
         self.editor.set_cursor_position('sof')
-        
+
     def clear(self):
         self.editor.clear()
 
@@ -276,7 +281,7 @@ class PlainText(QWidget):
 class SphinxThread(QThread):
     """
     A worker thread for handling rich text rendering.
-    
+
     Parameters
     ----------
     doc : str or dict
@@ -290,16 +295,20 @@ class SphinxThread(QThread):
         Text to be rendered if doc string cannot be extracted.
     math_option : bool
         Use LaTeX math rendering.
-        
+
     """
+    # Signals
+    error_msg = Signal(str)
+    html_ready = Signal(str)
+
     def __init__(self, html_text_no_doc=''):
         super(SphinxThread, self).__init__()
         self.doc = None
         self.context = None
         self.html_text_no_doc = html_text_no_doc
         self.math_option = False
-        
-    def render(self, doc, context=None, math_option=False):
+
+    def render(self, doc, context=None, math_option=False, img_path=''):
         """Start thread to render a given documentation"""
         # If the thread is already running wait for it to finish before
         # starting it again.
@@ -307,6 +316,7 @@ class SphinxThread(QThread):
             self.doc = doc
             self.context = context
             self.math_option = math_option
+            self.img_path = img_path
             # This causes run() to be executed in separate thread
             self.start()
 
@@ -319,24 +329,23 @@ class SphinxThread(QThread):
                     context = generate_context(name=doc['name'],
                                                argspec=doc['argspec'],
                                                note=doc['note'],
-                                               math=self.math_option)
+                                               math=self.math_option,
+                                               img_path=self.img_path)
                     html_text = sphinxify(doc['docstring'], context)
                     if doc['docstring'] == '':
                         html_text += '<div class="hr"></div>'
                         html_text += self.html_text_no_doc
 
                 except Exception as error:
-                    self.emit(SIGNAL('error_msg(QString)'),
-                              to_text_string(error))
+                    self.error_msg.emit(to_text_string(error))
                     return
             elif self.context is not None:
                 try:
                     html_text = sphinxify(doc, self.context)
                 except Exception as error:
-                    self.emit(SIGNAL('error_msg(QString)'),
-                              to_text_string(error))
+                    self.error_msg.emit(to_text_string(error))
                     return
-        self.emit(SIGNAL('html_ready(QString)'), html_text)
+        self.html_ready.emit(html_text)
 
 
 class ObjectInspector(SpyderPluginWidget):
@@ -346,16 +355,21 @@ class ObjectInspector(SpyderPluginWidget):
     CONF_SECTION = 'inspector'
     CONFIGWIDGET_CLASS = ObjectInspectorConfigPage
     LOG_PATH = get_conf_path(CONF_SECTION)
+    focus_changed = Signal()
+
     def __init__(self, parent):
-        SpyderPluginWidget.__init__(self, parent)
-        
+        if PYQT5:
+            SpyderPluginWidget.__init__(self, parent, main = parent)
+        else:
+            SpyderPluginWidget.__init__(self, parent)
+
         self.internal_shell = None
 
         # Initialize plugin
         self.initialize_plugin()
 
         self.no_doc_string = _("No further documentation available")
-        
+
         self._last_console_cb = None
         self._last_editor_cb = None
 
@@ -363,14 +377,14 @@ class ObjectInspector(SpyderPluginWidget):
 
         self.plain_text = PlainText(self)
         self.rich_text = RichText(self)
-        
+
         color_scheme = get_color_scheme(self.get_option('color_scheme_name'))
         self.set_plain_text_font(self.get_plugin_font(), color_scheme)
         self.plain_text.editor.toggle_wrap_mode(self.get_option('wrap'))
-        
+
         # Add entries to read-only editor context-menu
         font_action = create_action(self, _("&Font..."), None,
-                                    'font.png', _("Set font style"),
+                                    ima.icon('font'), _("Set font style"),
                                     triggered=self.change_font)
         self.wrap_action = create_action(self, _("Wrap lines"),
                                          toggled=self.toggle_wrap_mode)
@@ -380,16 +394,16 @@ class ObjectInspector(SpyderPluginWidget):
                     (font_action, self.wrap_action))
 
         self.set_rich_text_font(self.get_plugin_font('rich_text'))
-        
+
         self.shell = None
-        
+
         self.external_console = None
-        
+
         # locked = disable link with Console
         self.locked = False
         self._last_texts = [None, None]
         self._last_editor_doc = None
-        
+
         # Object name
         layout_edit = QHBoxLayout()
         layout_edit.setContentsMargins(0, 0, 0, 0)
@@ -401,9 +415,8 @@ class ObjectInspector(SpyderPluginWidget):
         layout_edit.addWidget(source_label)
         self.source_combo = QComboBox(self)
         self.source_combo.addItems([_("Console"), _("Editor")])
-        self.connect(self.source_combo, SIGNAL('currentIndexChanged(int)'),
-                     self.source_changed)
-        if (not programs.is_module_installed('rope') and 
+        self.source_combo.currentIndexChanged.connect(self.source_changed)
+        if (not programs.is_module_installed('rope') and
                 not programs.is_module_installed('jedi', '>=0.8.1')):
             self.source_combo.hide()
             source_label.hide()
@@ -418,45 +431,44 @@ class ObjectInspector(SpyderPluginWidget):
         self.combo.setMaxCount(self.get_option('max_history_entries'))
         self.combo.addItems( self.load_history() )
         self.combo.setItemText(0, '')
-        self.connect(self.combo, SIGNAL("valid(bool)"),
-                     lambda valid: self.force_refresh())
-        
+        self.combo.valid.connect(lambda valid: self.force_refresh())
+
         # Plain text docstring option
         self.docstring = True
         self.rich_help = sphinxify is not None \
                          and self.get_option('rich_mode', True)
         self.plain_text_action = create_action(self, _("Plain Text"),
                                                toggled=self.toggle_plain_text)
-        
+
         # Source code option
         self.show_source_action = create_action(self, _("Show Source"),
                                                 toggled=self.toggle_show_source)
-        
+
         # Rich text option
         self.rich_text_action = create_action(self, _("Rich Text"),
                                          toggled=self.toggle_rich_text)
-                        
+
         # Add the help actions to an exclusive QActionGroup
         help_actions = QActionGroup(self)
         help_actions.setExclusive(True)
         help_actions.addAction(self.plain_text_action)
         help_actions.addAction(self.rich_text_action)
-        
+
         # Automatic import option
         self.auto_import_action = create_action(self, _("Automatic import"),
                                                 toggled=self.toggle_auto_import)
         auto_import_state = self.get_option('automatic_import')
         self.auto_import_action.setChecked(auto_import_state)
-        
+
         # Lock checkbox
         self.locked_button = create_toolbutton(self,
                                                triggered=self.toggle_locked)
         layout_edit.addWidget(self.locked_button)
         self._update_lock_icon()
-        
+
         # Option menu
-        options_button = create_toolbutton(self, text=_("Options"),
-                                           icon=get_icon('tooloptions.png'))
+        options_button = create_toolbutton(self, text=_('Options'),
+                                           icon=ima.icon('tooloptions'))
         options_button.setPopupMode(QToolButton.InstantPopup)
         menu = QMenu(self)
         add_actions(menu, [self.rich_text_action, self.plain_text_action,
@@ -481,34 +493,34 @@ class ObjectInspector(SpyderPluginWidget):
         layout.addWidget(self.plain_text)
         layout.addWidget(self.rich_text)
         self.setLayout(layout)
-        
+
         # Add worker thread for handling rich text rendering
         if sphinxify is None:
             self._sphinx_thread = None
         else:
             self._sphinx_thread = SphinxThread(
                                   html_text_no_doc=warning(self.no_doc_string))
-            self.connect(self._sphinx_thread, SIGNAL('html_ready(QString)'), 
-                         self._on_sphinx_thread_html_ready)
-            self.connect(self._sphinx_thread, SIGNAL('error_msg(QString)'),
-                         self._on_sphinx_thread_error_msg)
-        
+            self._sphinx_thread.html_ready.connect(
+                                             self._on_sphinx_thread_html_ready)
+            self._sphinx_thread.error_msg.connect(
+                                              self._on_sphinx_thread_error_msg)
+
         # Render internal links
         view = self.rich_text.webview
         view.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
         view.linkClicked.connect(self.handle_link_clicks)
 
         self._starting_up = True
-            
-    #------ SpyderPluginWidget API ---------------------------------------------    
+
+    #------ SpyderPluginWidget API ---------------------------------------------
     def get_plugin_title(self):
         """Return widget title"""
         return _('Object inspector')
-    
+
     def get_plugin_icon(self):
         """Return widget icon"""
-        return get_icon('inspector.png')
-    
+        return ima.icon('inspector')
+
     def get_focus_widget(self):
         """
         Return the widget to give focus to when
@@ -516,23 +528,22 @@ class ObjectInspector(SpyderPluginWidget):
         """
         self.combo.lineEdit().selectAll()
         return self.combo
-    
+
     def get_plugin_actions(self):
         """Return a list of actions related to plugin"""
         return []
-    
+
     def register_plugin(self):
         """Register plugin in Spyder's main window"""
-        self.connect(self, SIGNAL('focus_changed()'),
-                     self.main.plugin_focus_changed)
+        self.focus_changed.connect(self.main.plugin_focus_changed)
         self.main.add_dockwidget(self)
         self.main.console.set_inspector(self)
         self.internal_shell = self.main.console.shell
-        
+
     def closing_plugin(self, cancelable=False):
         """Perform actions before parent main window is closed"""
         return True
-        
+
     def refresh_plugin(self):
         """Refresh widget"""
         if self._starting_up:
@@ -555,7 +566,7 @@ class ObjectInspector(SpyderPluginWidget):
         self.wrap_action.setChecked(wrap_o)
         math_n = 'math'
         math_o = self.get_option(math_n)
-        
+
         if font_n in options:
             scs = color_scheme_o if color_scheme_n in options else None
             self.set_plain_text_font(font_o, color_scheme=scs)
@@ -573,18 +584,18 @@ class ObjectInspector(SpyderPluginWidget):
         self.main.extconsole.apply_plugin_settings(options=[connect_n])
         if self.main.ipyconsole is not None:
             self.main.ipyconsole.apply_plugin_settings(options=[connect_n])
-        
+
     #------ Public API (related to inspector's source) -------------------------
     def source_is_console(self):
         """Return True if source is Console"""
         return self.source_combo.currentIndex() == 0
-    
+
     def switch_to_editor_source(self):
         self.source_combo.setCurrentIndex(1)
-        
+
     def switch_to_console_source(self):
         self.source_combo.setCurrentIndex(0)
-        
+
     def source_changed(self, index=None):
         if self.source_is_console():
             # Console
@@ -599,13 +610,13 @@ class ObjectInspector(SpyderPluginWidget):
             self.show_source_action.setDisabled(True)
             self.auto_import_action.setDisabled(True)
         self.restore_text()
-            
+
     def save_text(self, callback):
         if self.source_is_console():
             self._last_console_cb = callback
         else:
             self._last_editor_cb = callback
-            
+
     def restore_text(self):
         if self.source_is_console():
             cb = self._last_console_cb
@@ -624,7 +635,7 @@ class ObjectInspector(SpyderPluginWidget):
                 self.switch_to_rich_text()
             else:
                 self.switch_to_plain_text()
-        
+
     #------ Public API (related to rich/plain text widgets) --------------------
     @property
     def find_widget(self):
@@ -632,11 +643,11 @@ class ObjectInspector(SpyderPluginWidget):
             return self.plain_text.find_widget
         else:
             return self.rich_text.find_widget
-    
+
     def set_rich_text_font(self, font):
         """Set rich text mode font"""
         self.rich_text.set_font(font, fixed_font=self.get_plugin_font())
-        
+
     def set_plain_text_font(self, font, color_scheme=None):
         """Set plain text mode font"""
         self.plain_text.set_font(font, color_scheme=color_scheme)
@@ -644,7 +655,8 @@ class ObjectInspector(SpyderPluginWidget):
     def set_plain_text_color_scheme(self, color_scheme):
         """Set plain text mode color scheme"""
         self.plain_text.set_color_scheme(color_scheme)
-        
+
+    @Slot()
     def change_font(self):
         """Change console font"""
         font, valid = QFontDialog.getFont(get_font(self.CONF_SECTION), self,
@@ -652,16 +664,17 @@ class ObjectInspector(SpyderPluginWidget):
         if valid:
             self.set_plain_text_font(font)
             set_font(font, self.CONF_SECTION)
-            
+
+    @Slot(bool)
     def toggle_wrap_mode(self, checked):
         """Toggle wrap mode"""
         self.plain_text.editor.toggle_wrap_mode(checked)
         self.set_option('wrap', checked)
-    
+
     def toggle_math_mode(self, checked):
         """Toggle math mode"""
         self.set_option('math', checked)
-    
+
     def is_plain_text_mode(self):
         """Return True if plain text mode is active"""
         return self.plain_text.isVisible()
@@ -676,7 +689,7 @@ class ObjectInspector(SpyderPluginWidget):
         self.plain_text.show()
         self.rich_text.hide()
         self.plain_text_action.setChecked(True)
-        
+
     def switch_to_rich_text(self):
         """Switch to rich text mode"""
         self.rich_help = True
@@ -684,10 +697,10 @@ class ObjectInspector(SpyderPluginWidget):
         self.rich_text.show()
         self.rich_text_action.setChecked(True)
         self.show_source_action.setChecked(False)
-            
+
     def set_plain_text(self, text, is_code):
         """Set plain text docs"""
-        
+
         # text is coming from utils.dochelpers.getdoc
         if type(text) is dict:
             name = text['name']
@@ -696,13 +709,13 @@ class ObjectInspector(SpyderPluginWidget):
                                     '='*len(name), '\n\n'])
             else:
                 rst_title = ''
-            
+
             if text['argspec']:
                 definition = ''.join(['Definition: ', name, text['argspec'],
                                       '\n'])
             else:
                 definition = ''
-            
+
             if text['note']:
                 note = ''.join(['Type: ', text['note'], '\n\n----\n\n'])
             else:
@@ -712,15 +725,15 @@ class ObjectInspector(SpyderPluginWidget):
                                  text['docstring']])
         else:
             full_text = text
-        
+
         self.plain_text.set_text(full_text, is_code)
         self.save_text([self.plain_text.set_text, full_text, is_code])
-        
+
     def set_rich_text_html(self, html_text, base_url):
         """Set rich text"""
         self.rich_text.set_html(html_text, base_url)
         self.save_text([self.rich_text.set_html, html_text, base_url])
-    
+
     def show_intro_message(self):
         intro_message = _("Here you can get help of any object by pressing "
                           "%s in front of it, either on the Editor or the "
@@ -729,11 +742,16 @@ class ObjectInspector(SpyderPluginWidget):
                           "a left parenthesis next to an object. You can "
                           "activate this behavior in %s.")
         prefs = _("Preferences > Object Inspector")
+        if sys.platform == 'darwin':
+            shortcut = "Cmd+I"
+        else:
+            shortcut = "Ctrl+I"
+
         if self.is_rich_text_mode():
             title = _("Usage")
             tutorial_message = _("New to Spyder? Read our")
             tutorial = _("tutorial")
-            intro_message = intro_message % ("<b>Ctrl+I</b>", "<br><br>",
+            intro_message = intro_message % ("<b>"+shortcut+"</b>", "<br><br>",
                                              "<i>"+prefs+"</i>")
             self.set_rich_text_html(usage(title, intro_message,
                                           tutorial_message, tutorial),
@@ -742,10 +760,10 @@ class ObjectInspector(SpyderPluginWidget):
             install_sphinx = "\n\n%s" % _("Please consider installing Sphinx "
                                           "to get documentation rendered in "
                                           "rich text.")
-            intro_message = intro_message % ("Ctrl+I", "\n\n", prefs)
+            intro_message = intro_message % (shortcut, "\n\n", prefs)
             intro_message += install_sphinx
             self.set_plain_text(intro_message, is_code=False)
-    
+
     def show_rich_text(self, text, collapse=False, img_path=''):
         """Show text in rich mode"""
         self.visibility_changed(True)
@@ -753,14 +771,15 @@ class ObjectInspector(SpyderPluginWidget):
         self.switch_to_rich_text()
         context = generate_context(collapse=collapse, img_path=img_path)
         self.render_sphinx_doc(text, context)
-    
+
     def show_plain_text(self, text):
         """Show text in plain mode"""
         self.visibility_changed(True)
         self.raise_()
         self.switch_to_plain_text()
         self.set_plain_text(text, is_code=False)
-    
+
+    @Slot()
     def show_tutorial(self):
         tutorial_path = get_module_source_path('spyderlib.utils.inspector')
         img_path = osp.join(tutorial_path, 'static', 'images')
@@ -779,17 +798,17 @@ class ObjectInspector(SpyderPluginWidget):
             programs.start_file(url)
         else:
             self.rich_text.webview.load(QUrl(url))
-        
+
     #------ Public API ---------------------------------------------------------
     def set_external_console(self, external_console):
         self.external_console = external_console
-    
+
     def force_refresh(self):
         if self.source_is_console():
             self.set_object_text(None, force_refresh=True)
         elif self._last_editor_doc is not None:
             self.set_editor_doc(self._last_editor_doc, force_refresh=True)
-    
+
     def set_object_text(self, text, force_refresh=False, ignore_unknown=False):
         """Set object analyzed by Object Inspector"""
         if (self.locked and not force_refresh):
@@ -800,22 +819,22 @@ class ObjectInspector(SpyderPluginWidget):
         if text is None:
             text = to_text_string(self.combo.currentText())
             add_to_combo = False
-            
+
         found = self.show_help(text, ignore_unknown=ignore_unknown)
         if ignore_unknown and not found:
             return
-        
+
         if add_to_combo:
             self.combo.add_text(text)
         if found:
             self.save_history()
-        
+
         if self.dockwidget is not None:
             self.dockwidget.blockSignals(True)
         self.__eventually_raise_inspector(text, force=force_refresh)
         if self.dockwidget is not None:
             self.dockwidget.blockSignals(False)
-        
+
     def set_editor_doc(self, doc, force_refresh=False):
         """
         Use the object inspector to show docstring dictionary computed
@@ -831,14 +850,14 @@ class ObjectInspector(SpyderPluginWidget):
             self.render_sphinx_doc(doc)
         else:
             self.set_plain_text(doc, is_code=False)
-        
+
         if self.dockwidget is not None:
             self.dockwidget.blockSignals(True)
         self.__eventually_raise_inspector(doc['docstring'],
                                           force=force_refresh)
         if self.dockwidget is not None:
             self.dockwidget.blockSignals(False)
-            
+
     def __eventually_raise_inspector(self, text, force=False):
         index = self.source_combo.currentIndex()
         if hasattr(self.main, 'tabifiedDockWidgets'):
@@ -853,7 +872,7 @@ class ObjectInspector(SpyderPluginWidget):
                     self.dockwidget.show()
                     self.dockwidget.raise_()
         self._last_texts[index] = text
-    
+
     def load_history(self, obj=None):
         """Load history from a text file in user home directory"""
         if osp.isfile(self.LOG_PATH):
@@ -862,13 +881,14 @@ class ObjectInspector(SpyderPluginWidget):
         else:
             history = []
         return history
-    
+
     def save_history(self):
         """Save history to a text file in user home directory"""
         open(self.LOG_PATH, 'w').write("\n".join( \
                 [to_text_string(self.combo.itemText(index))
                  for index in range(self.combo.count())] ))
-        
+
+    @Slot(bool)
     def toggle_plain_text(self, checked):
         """Toggle plain text docstring"""
         if checked:
@@ -876,7 +896,8 @@ class ObjectInspector(SpyderPluginWidget):
             self.switch_to_plain_text()
             self.force_refresh()
         self.set_option('rich_mode', not checked)
-        
+
+    @Slot(bool)
     def toggle_show_source(self, checked):
         """Toggle show source code"""
         if checked:
@@ -884,20 +905,23 @@ class ObjectInspector(SpyderPluginWidget):
         self.docstring = not checked
         self.force_refresh()
         self.set_option('rich_mode', not checked)
-        
+
+    @Slot(bool)
     def toggle_rich_text(self, checked):
         """Toggle between sphinxified docstrings or plain ones"""
         if checked:
             self.docstring = not checked
             self.switch_to_rich_text()
         self.set_option('rich_mode', checked)
-        
+
+    @Slot(bool)
     def toggle_auto_import(self, checked):
         """Toggle automatic import feature"""
         self.combo.validate_current_text()
         self.set_option('automatic_import', checked)
         self.force_refresh()
-        
+
+    @Slot()
     def toggle_locked(self):
         """
         Toggle locked state
@@ -905,14 +929,14 @@ class ObjectInspector(SpyderPluginWidget):
         """
         self.locked = not self.locked
         self._update_lock_icon()
-        
+
     def _update_lock_icon(self):
         """Update locked state icon"""
-        icon = get_icon("lock.png" if self.locked else "lock_open.png")
+        icon = ima.icon('lock') if self.locked else ima.icon('lock_open')
         self.locked_button.setIcon(icon)
         tip = _("Unlock") if self.locked else _("Lock")
         self.locked_button.setToolTip(tip)
-        
+
     def set_shell(self, shell):
         """Bind to shell"""
         if IPythonControlWidget is not None:
@@ -923,7 +947,7 @@ class ObjectInspector(SpyderPluginWidget):
                 self.shell = self.external_console.get_current_shell()
         else:
             self.shell = shell
-    
+
     def get_shell(self):
         """Return shell which is currently bound to object inspector,
         or another running shell if it has been terminated"""
@@ -935,12 +959,15 @@ class ObjectInspector(SpyderPluginWidget):
             if self.shell is None:
                 self.shell = self.internal_shell
         return self.shell
-        
+
     def render_sphinx_doc(self, doc, context=None):
         """Transform doc string dictionary to HTML and show it"""
         # Math rendering option could have changed
-        self._sphinx_thread.render(doc, context, self.get_option('math'))
-        
+        fname = self.parent().parent().editor.get_current_filename()
+        dname = osp.dirname(fname)
+        self._sphinx_thread.render(doc, context, self.get_option('math'),
+                                   dname)
+
     def _on_sphinx_thread_html_ready(self, html_text):
         """Set our sphinx documentation based on thread result"""
         self._sphinx_thread.wait()
@@ -964,7 +991,7 @@ class ObjectInspector(SpyderPluginWidget):
         if shell is None:
             return
         obj_text = to_text_string(obj_text)
-        
+
         if not shell.is_defined(obj_text):
             if self.get_option('automatic_import') and\
                self.internal_shell.is_defined(obj_text, force_import=True):
@@ -973,13 +1000,13 @@ class ObjectInspector(SpyderPluginWidget):
                 shell = None
                 doc = None
                 source_text = None
-            
+
         if shell is not None:
             doc = shell.get_doc(obj_text)
             source_text = shell.get_source(obj_text)
-            
+
         is_code = False
-        
+
         if self.rich_help:
             self.render_sphinx_doc(doc)
             return doc is not None
diff --git a/spyderlib/plugins/ipythonconsole.py b/spyderlib/plugins/ipythonconsole.py
index 402440d..f6997d1 100644
--- a/spyderlib/plugins/ipythonconsole.py
+++ b/spyderlib/plugins/ipythonconsole.py
@@ -21,35 +21,36 @@ import os.path as osp
 import sys
 
 # Qt imports
+from spyderlib.qt import PYQT5
 from spyderlib.qt.QtGui import (QVBoxLayout, QHBoxLayout, QFormLayout, 
                                 QMessageBox, QGroupBox, QDialogButtonBox,
                                 QDialog, QTabWidget, QFontComboBox, 
                                 QCheckBox, QApplication, QLabel,QLineEdit,
-                                QPushButton, QKeySequence, QWidget)
+                                QPushButton, QKeySequence, QWidget,
+                                QGridLayout)
 from spyderlib.qt.compat import getopenfilename
-from spyderlib.qt.QtCore import SIGNAL, Qt
+from spyderlib.qt.QtCore import Signal, Slot, Qt
+import spyderlib.utils.icon_manager as ima
 
 # IPython imports
 from IPython.core.application import get_ipython_dir
 from IPython.kernel.connect import find_connection_file
 from IPython.qt.manager import QtKernelManager
-try: # IPython = "<=2.0"
-    from IPython.external.ssh import tunnel as zmqtunnel
-    import IPython.external.pexpect as pexpect
+
+# Ssh imports
+from zmq.ssh import tunnel as zmqtunnel
+try:
+    import pexpect
 except ImportError:
-    from zmq.ssh import tunnel as zmqtunnel      # analysis:ignore
-    try:
-        import pexpect                           # analysis:ignore
-    except ImportError:
-        pexpect = None                           # analysis:ignore
+    pexpect = None
 
 # Local imports
 from spyderlib import dependencies
-from spyderlib.baseconfig import _
-from spyderlib.config import CONF
+from spyderlib.config.base import _
+from spyderlib.config.main import CONF
 from spyderlib.utils.misc import get_error_match, remove_backslashes
 from spyderlib.utils import programs
-from spyderlib.utils.qthelpers import get_icon, create_action
+from spyderlib.utils.qthelpers import create_action
 from spyderlib.widgets.tabs import Tabs
 from spyderlib.widgets.ipython import IPythonClient
 from spyderlib.widgets.findreplace import FindReplace
@@ -162,10 +163,6 @@ class IPythonConsoleConfigPage(PluginConfigPage):
         banner_box = newcb(_("Display initial banner"), 'show_banner',
                       tip=_("This option lets you hide the message shown at\n"
                             "the top of the console when it's opened."))
-        gui_comp_box = newcb(_("Use a completion widget"),
-                             'use_gui_completion',
-                             tip=_("Use a widget instead of plain text "
-                                   "output for tab completion"))
         pager_box = newcb(_("Use a pager to display additional text inside "
                             "the console"), 'use_pager',
                             tip=_("Useful if you don't want to fill the "
@@ -178,12 +175,22 @@ class IPythonConsoleConfigPage(PluginConfigPage):
 
         interface_layout = QVBoxLayout()
         interface_layout.addWidget(banner_box)
-        interface_layout.addWidget(gui_comp_box)
         interface_layout.addWidget(pager_box)
         interface_layout.addWidget(calltips_box)
         interface_layout.addWidget(ask_box)
         interface_group.setLayout(interface_layout)
 
+        comp_group = QGroupBox(_("Completion Type"))
+        comp_label = QLabel(_("Decide what type of completion to use"))
+        comp_label.setWordWrap(True)
+        completers = [("Graphical", 0), ("Terminal", 1), ("Plain", 2)]
+        comp_box = self.create_combobox(_("Completion:")+"   ", completers,
+                                        'completion_type')
+        comp_layout = QVBoxLayout()
+        comp_layout.addWidget(comp_label)
+        comp_layout.addWidget(comp_box)
+        comp_group.setLayout(comp_layout)
+
         # Background Color Group
         bg_group = QGroupBox(_("Background color"))
         light_radio = self.create_radiobutton(_("Light background"),
@@ -221,8 +228,7 @@ class IPythonConsoleConfigPage(PluginConfigPage):
                                      "Matplotlib or to develop \nGUIs with "
                                      "Spyder."))
         autoload_pylab_box.setEnabled(self.get_option('pylab') and mpl_present)
-        self.connect(pylab_box, SIGNAL("toggled(bool)"),
-                     autoload_pylab_box.setEnabled)
+        pylab_box.toggled.connect(autoload_pylab_box.setEnabled)
         
         pylab_layout = QVBoxLayout()
         pylab_layout.addWidget(pylab_box)
@@ -271,8 +277,7 @@ class IPythonConsoleConfigPage(PluginConfigPage):
         backend_layout.addWidget(backend_box)
         backend_group.setLayout(backend_layout)
         backend_group.setEnabled(self.get_option('pylab') and mpl_present)
-        self.connect(pylab_box, SIGNAL("toggled(bool)"),
-                     backend_group.setEnabled)
+        pylab_box.toggled.connect(backend_group.setEnabled)
         
         # Inline backend Group
         inline_group = QGroupBox(_("Inline backend"))
@@ -296,16 +301,27 @@ class IPythonConsoleConfigPage(PluginConfigPage):
                           'pylab/inline/height', min_=1, max_=20, step=1,
                           tip=_("Default is 4"))
         
-        inline_layout = QVBoxLayout()
-        inline_layout.addWidget(inline_label)
-        inline_layout.addWidget(format_box)
-        inline_layout.addWidget(resolution_spin)
-        inline_layout.addWidget(width_spin)
-        inline_layout.addWidget(height_spin)
-        inline_group.setLayout(inline_layout)
+        inline_v_layout = QVBoxLayout()
+        inline_v_layout.addWidget(inline_label)
+        inline_layout = QGridLayout()
+        inline_layout.addWidget(format_box.label, 1, 0)
+        inline_layout.addWidget(format_box.combobox, 1, 1)
+        inline_layout.addWidget(resolution_spin.plabel, 2, 0)
+        inline_layout.addWidget(resolution_spin.spinbox, 2, 1)
+        inline_layout.addWidget(resolution_spin.slabel, 2, 2)
+        inline_layout.addWidget(width_spin.plabel, 3, 0)
+        inline_layout.addWidget(width_spin.spinbox, 3, 1)
+        inline_layout.addWidget(width_spin.slabel, 3, 2)
+        inline_layout.addWidget(height_spin.plabel, 4, 0)
+        inline_layout.addWidget(height_spin.spinbox, 4, 1)
+        inline_layout.addWidget(height_spin.slabel, 4, 2)
+        inline_h_layout = QHBoxLayout()
+        inline_h_layout.addLayout(inline_layout)
+        inline_h_layout.addStretch(1)
+        inline_v_layout.addLayout(inline_h_layout)
+        inline_group.setLayout(inline_v_layout)
         inline_group.setEnabled(self.get_option('pylab') and mpl_present)
-        self.connect(pylab_box, SIGNAL("toggled(bool)"),
-                     inline_group.setEnabled)
+        pylab_box.toggled.connect(inline_group.setEnabled)
 
         # --- Startup ---
         # Run lines Group
@@ -334,8 +350,7 @@ class IPythonConsoleConfigPage(PluginConfigPage):
                            'startup/use_run_file', False)
         run_file_browser = self.create_browsefile('', 'startup/run_file', '')
         run_file_browser.setEnabled(False)
-        self.connect(file_radio, SIGNAL("toggled(bool)"),
-                     run_file_browser.setEnabled)
+        file_radio.toggled.connect(run_file_browser.setEnabled)
         
         run_file_layout = QVBoxLayout()
         run_file_layout.addWidget(run_file_label)
@@ -434,14 +449,18 @@ class IPythonConsoleConfigPage(PluginConfigPage):
         
         prompts_layout = QVBoxLayout()
         prompts_layout.addWidget(prompts_label)
-        prompts_layout.addWidget(in_prompt_edit)
-        prompts_layout.addWidget(out_prompt_edit)
+        prompts_g_layout  = QGridLayout()
+        prompts_g_layout.addWidget(in_prompt_edit.label, 0, 0)
+        prompts_g_layout.addWidget(in_prompt_edit.textbox, 0, 1)
+        prompts_g_layout.addWidget(out_prompt_edit.label, 1, 0)
+        prompts_g_layout.addWidget(out_prompt_edit.textbox, 1, 1)
+        prompts_layout.addLayout(prompts_g_layout)
         prompts_group.setLayout(prompts_layout)
 
         # --- Tabs organization ---
         tabs = QTabWidget()
-        tabs.addTab(self.create_tab(font_group, interface_group, bg_group,
-                                    source_code_group), _("Display"))
+        tabs.addTab(self.create_tab(font_group, interface_group, comp_group,
+                                    bg_group, source_code_group), _("Display"))
         tabs.addTab(self.create_tab(pylab_group, backend_group, inline_group),
                                     _("Graphics"))
         tabs.addTab(self.create_tab(run_lines_group, run_file_group),
@@ -477,8 +496,7 @@ class KernelConnectionDialog(QDialog):
         self.cf.setPlaceholderText(_('Path to connection file or kernel id'))
         self.cf.setMinimumWidth(250)
         cf_open_btn = QPushButton(_('Browse'))
-        self.connect(cf_open_btn, SIGNAL('clicked()'),
-                     self.select_connection_file)
+        cf_open_btn.clicked.connect(self.select_connection_file)
 
         cf_layout = QHBoxLayout()
         cf_layout.addWidget(cf_label)
@@ -495,7 +513,7 @@ class KernelConnectionDialog(QDialog):
         self.kf = QLineEdit()
         self.kf.setPlaceholderText(_('Path to ssh key file'))
         kf_open_btn = QPushButton(_('Browse'))
-        self.connect(kf_open_btn, SIGNAL('clicked()'), self.select_ssh_key)
+        kf_open_btn.clicked.connect(self.select_ssh_key)
 
         kf_layout = QHBoxLayout()
         kf_layout.addWidget(self.kf)
@@ -515,8 +533,8 @@ class KernelConnectionDialog(QDialog):
             QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
             Qt.Horizontal, self)
 
-        self.connect(accept_btns, SIGNAL('accepted()'), self.accept)
-        self.connect(accept_btns, SIGNAL('rejected()'), self.reject)
+        accept_btns.accepted.connect(self.accept)
+        accept_btns.rejected.connect(self.reject)
 
         # Dialog layout
         layout = QVBoxLayout(self)
@@ -534,7 +552,7 @@ class KernelConnectionDialog(QDialog):
                 ssh_form.itemAt(2 * i).widget().setEnabled(state)
        
         ssh_set_enabled(self.rm_cb.checkState())
-        self.connect(self.rm_cb, SIGNAL('stateChanged(int)'), ssh_set_enabled)
+        self.rm_cb.stateChanged.connect(ssh_set_enabled)
 
     def select_connection_file(self):
         cf = getopenfilename(self, _('Open IPython connection file'),
@@ -573,9 +591,16 @@ class IPythonConsole(SpyderPluginWidget):
     CONF_SECTION = 'ipython_console'
     CONFIGWIDGET_CLASS = IPythonConsoleConfigPage
     DISABLE_ACTIONS_WHEN_HIDDEN = False
+    
+    # Signals
+    focus_changed = Signal()
+    edit_goto = Signal(str, int, str)
 
     def __init__(self, parent):
-        SpyderPluginWidget.__init__(self, parent)
+        if PYQT5:
+            SpyderPluginWidget.__init__(self, parent, main = parent)
+        else:
+            SpyderPluginWidget.__init__(self, parent)
 
         self.tabwidget = None
         self.menu_actions = None
@@ -584,6 +609,7 @@ class IPythonConsole(SpyderPluginWidget):
         self.inspector = None          # Object inspector plugin
         self.historylog = None         # History log plugin
         self.variableexplorer = None   # Variable explorer plugin
+        self.editor = None             # Editor plugin
 
         self.master_clients = 0
         self.clients = []
@@ -599,10 +625,8 @@ class IPythonConsole(SpyderPluginWidget):
             # a crash when the console is detached from the main window
             # Fixes Issue 561
             self.tabwidget.setDocumentMode(True)
-        self.connect(self.tabwidget, SIGNAL('currentChanged(int)'),
-                     self.refresh_plugin)
-        self.connect(self.tabwidget, SIGNAL('move_data(int,int)'),
-                     self.move_tab)
+        self.tabwidget.currentChanged.connect(self.refresh_plugin)
+        self.tabwidget.move_data.connect(self.move_tab)
                      
         self.tabwidget.set_close_function(self.close_client)
 
@@ -666,7 +690,7 @@ class IPythonConsole(SpyderPluginWidget):
     
     def get_plugin_icon(self):
         """Return widget icon"""
-        return get_icon('ipython_console.png')
+        return ima.icon('ipython_console')
     
     def get_focus_widget(self):
         """
@@ -704,20 +728,20 @@ class IPythonConsole(SpyderPluginWidget):
         self.find_widget.set_editor(control)
         self.tabwidget.set_corner_widgets({Qt.TopRightCorner: widgets})
         self.main.last_console_plugin_focus_was_python = False
-        self.emit(SIGNAL('update_plugin_title()'))
+        self.update_plugin_title.emit()
 
     def get_plugin_actions(self):
         """Return a list of actions related to plugin"""
         ctrl = "Cmd" if sys.platform == "darwin" else "Ctrl"
         main_create_client_action = create_action(self,
                                 _("Open an &IPython console"),
-                                None, 'ipython_console.png',
+                                None, ima.icon('ipython_console'),
                                 triggered=self.create_new_client,
                                 tip=_("Use %s+T when the console is selected "
                                       "to open a new one") % ctrl)
         create_client_action = create_action(self,
                                 _("Open a new console"),
-                                QKeySequence("Ctrl+T"), 'ipython_console.png',
+                                QKeySequence("Ctrl+T"), ima.icon('ipython_console'),
                                 triggered=self.create_new_client)
         create_client_action.setShortcutContext(Qt.WidgetWithChildrenShortcut)
 
@@ -744,16 +768,13 @@ class IPythonConsole(SpyderPluginWidget):
         self.inspector = self.main.inspector
         self.historylog = self.main.historylog
         self.variableexplorer = self.main.variableexplorer
-
-        self.connect(self, SIGNAL('focus_changed()'),
-                     self.main.plugin_focus_changed)
-
-        if self.main.editor is not None:
-            self.connect(self, SIGNAL("edit_goto(QString,int,QString)"),
-                         self.main.editor.load)
-            self.connect(self.main.editor,
-                         SIGNAL('run_in_current_ipyclient(QString,QString,QString,bool)'),
-                         self.run_script_in_current_client)
+        self.editor = self.main.editor
+        
+        self.focus_changed.connect(self.main.plugin_focus_changed)
+        if self.editor is not None:
+            self.edit_goto.connect(self.editor.load)
+            self.editor.run_in_current_ipyclient.connect(
+                                             self.run_script_in_current_client)
 
     #------ Public API (for clients) ------------------------------------------
     def get_clients(self):
@@ -779,7 +800,8 @@ class IPythonConsole(SpyderPluginWidget):
         if client is not None:
             return client
 
-    def run_script_in_current_client(self, filename, wdir, args, debug):
+    def run_script_in_current_client(self, filename, wdir, args, debug,
+            post_mortem):
         """Run script in current client, if any"""
         norm = lambda text: remove_backslashes(to_text_string(text))
         client = self.get_current_client()
@@ -792,6 +814,8 @@ class IPythonConsole(SpyderPluginWidget):
                     line += ", args='%s'" % norm(args)
                 if wdir:
                     line += ", wdir='%s'" % norm(wdir)
+                if post_mortem:
+                    line += ", post_mortem=True"
                 line += ")"
             else: # External kernels, use %run
                 line = "%run "
@@ -822,6 +846,7 @@ class IPythonConsole(SpyderPluginWidget):
         if client is not None:
             client.shellwidget.write_to_stdin(line)
 
+    @Slot()
     def create_new_client(self, give_focus=True):
         """Create a new client"""
         self.master_clients += 1
@@ -842,8 +867,7 @@ class IPythonConsole(SpyderPluginWidget):
         page_control = shellwidget._page_control
 
         # Create new clients with Ctrl+T shortcut
-        self.connect(shellwidget, SIGNAL('new_ipyclient()'),
-                     self.create_new_client)
+        shellwidget.new_client.connect(self.create_new_client)
         
         # Handle kernel interrupts
         extconsoles = self.extconsole.shellwidgets
@@ -861,7 +885,7 @@ class IPythonConsole(SpyderPluginWidget):
 
         # Connect to our variable explorer
         if kernel_widget is not None and self.variableexplorer is not None:
-            nsb = self.variableexplorer.currentWidget()
+            nsb = self.variableexplorer.current_widget()
             # When the autorefresh button is active, our kernels
             # start to consume more and more CPU during time
             # Fix Issue 1450
@@ -882,7 +906,7 @@ class IPythonConsole(SpyderPluginWidget):
             return
         
         # For tracebacks
-        self.connect(control, SIGNAL("go_to_error(QString)"), self.go_to_error)
+        control.go_to_error.connect(self.go_to_error)
         
         # Handle kernel restarts asked by the user
         if kernel_widget is not None:
@@ -904,28 +928,22 @@ class IPythonConsole(SpyderPluginWidget):
         # Connect client to our history log
         if self.historylog is not None:
             self.historylog.add_history(client.history_filename)
-            self.connect(client, SIGNAL('append_to_history(QString,QString)'),
-                         self.historylog.append_to_history)
+            client.append_to_history.connect(self.historylog.append_to_history)
         
         # Set font for client
         client.set_font( self.get_plugin_font() )
         
         # Connect focus signal to client's control widget
-        self.connect(control, SIGNAL('focus_changed()'),
-                     lambda: self.emit(SIGNAL('focus_changed()')))
+        control.focus_changed.connect(lambda: self.focus_changed.emit())
         
         # Update the find widget if focus changes between control and
         # page_control
         self.find_widget.set_editor(control)
         if page_control:
-            self.connect(page_control, SIGNAL('focus_changed()'),
-                         lambda: self.emit(SIGNAL('focus_changed()')))
-            self.connect(control, SIGNAL('visibility_changed(bool)'),
-                         self.refresh_plugin)
-            self.connect(page_control, SIGNAL('visibility_changed(bool)'),
-                         self.refresh_plugin)
-            self.connect(page_control, SIGNAL('show_find_widget()'),
-                         self.find_widget.show)
+            page_control.focus_changed.connect(lambda: self.focus_changed.emit())
+            control.visibility_changed.connect(self.refresh_plugin)
+            page_control.visibility_changed.connect(self.refresh_plugin)
+            page_control.show_find_widget.connect(self.find_widget.show)
 
     def close_client(self, index=None, client=None, force=False):
         """Close client tab from index or widget (or close current tab)"""
@@ -963,7 +981,7 @@ class IPythonConsole(SpyderPluginWidget):
         # Note: client index may have changed after closing related widgets
         self.tabwidget.removeTab(self.tabwidget.indexOf(client))
         self.clients.remove(client)
-        self.emit(SIGNAL('update_plugin_title()'))
+        self.update_plugin_title.emit()
 
     def get_client_index_from_id(self, client_id):
         """Return client index from id"""
@@ -1051,6 +1069,7 @@ class IPythonConsole(SpyderPluginWidget):
             widget.kernel_manager = km
             widget.kernel_client = kc
 
+    @Slot()
     def create_client_for_kernel(self):
         """Create a client connected to an existing kernel"""
         (cf, hostname,
@@ -1143,7 +1162,7 @@ class IPythonConsole(SpyderPluginWidget):
     def add_tab(self, widget, name):
         """Add tab"""
         self.clients.append(widget)
-        index = self.tabwidget.addTab(widget, get_icon('ipython_console.png'),
+        index = self.tabwidget.addTab(widget, ima.icon('ipython_console'),
                                       name)
         self.tabwidget.setCurrentIndex(index)
         if self.dockwidget and not self.ismaximized:
@@ -1158,7 +1177,7 @@ class IPythonConsole(SpyderPluginWidget):
         """
         client = self.clients.pop(index_from)
         self.clients.insert(index_to, client)
-        self.emit(SIGNAL('update_plugin_title()'))
+        self.update_plugin_title.emit()
 
     #------ Public API (for help) ---------------------------------------------
     def go_to_error(self, text):
@@ -1166,19 +1185,21 @@ class IPythonConsole(SpyderPluginWidget):
         match = get_error_match(to_text_string(text))
         if match:
             fname, lnb = match.groups()
-            self.emit(SIGNAL("edit_goto(QString,int,QString)"),
-                      osp.abspath(fname), int(lnb), '')
-    
+            self.edit_goto.emit(osp.abspath(fname), int(lnb), '')
+
+    @Slot()
     def show_intro(self):
         """Show intro to IPython help"""
         from IPython.core.usage import interactive_usage
         self.inspector.show_rich_text(interactive_usage)
-    
+
+    @Slot()
     def show_guiref(self):
         """Show qtconsole help"""
         from IPython.core.usage import gui_reference
         self.inspector.show_rich_text(gui_reference, collapse=True)
-    
+
+    @Slot()
     def show_quickref(self):
         """Show IPython Cheat Sheet"""
         from IPython.core.usage import quick_reference
@@ -1225,4 +1246,3 @@ class IPythonConsole(SpyderPluginWidget):
 #            elif shellwidget:
 #                shellwidget.shell.drop_pathlist(pathlist)
 #        event.acceptProposedAction()
-
diff --git a/spyderlib/plugins/layoutdialog.py b/spyderlib/plugins/layoutdialog.py
new file mode 100644
index 0000000..1e06d2e
--- /dev/null
+++ b/spyderlib/plugins/layoutdialog.py
@@ -0,0 +1,341 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2014 Gonzalo Peña (@goanpeca)
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+"""Layout dialogs"""
+
+import sys
+
+from spyderlib.config.base import _
+
+from spyderlib.qt.QtGui import (QVBoxLayout, QHBoxLayout, QDialogButtonBox,
+                                QGroupBox, QComboBox, QPushButton, QDialog,
+                                QAbstractItemView, QTableView)
+from spyderlib.qt.QtCore import Qt, QSize, QAbstractTableModel, QModelIndex
+from spyderlib.qt.compat import to_qvariant, from_qvariant
+from spyderlib.py3compat import to_text_string
+
+
+class LayoutModel(QAbstractTableModel):
+    """ """
+    def __init__(self, parent, order, active):
+        super(LayoutModel, self).__init__(parent)
+
+        # variables
+        self._parent = parent
+        self.order = order
+        self.active = active
+        self._rows = []
+        self.set_data(order, active)
+
+    def set_data(self, order, active):
+        """ """
+        self._rows = []
+        self.order = order
+        self.active = active
+        for name in order:
+            if name in active:
+                row = [name, True]
+            else:
+                row = [name, False]
+            self._rows.append(row)
+
+    def flags(self, index):
+        """Override Qt method"""
+        if not index.isValid():
+            return Qt.ItemIsEnabled
+        column = index.column()
+        if column in [0]:
+            return Qt.ItemFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable |
+                                Qt.ItemIsUserCheckable | Qt.ItemIsEditable)
+        else:
+            return Qt.ItemFlags(Qt.ItemIsEnabled)
+
+    def data(self, index, role=Qt.DisplayRole):
+        """Override Qt method"""
+        if not index.isValid() or not 0 <= index.row() < len(self._rows):
+            return to_qvariant()
+        row = index.row()
+        column = index.column()
+
+        name, state = self.row(row)
+
+        if role == Qt.DisplayRole or role == Qt.EditRole:
+            if column == 0:
+                return to_qvariant(name)
+        elif role == Qt.CheckStateRole:
+            if column == 0:
+                if state:
+                    return Qt.Checked
+                else:
+                    return Qt.Unchecked
+            if column == 1:
+                return to_qvariant(state)
+        return to_qvariant()
+
+    def setData(self, index, value, role):
+        """Override Qt method"""
+        row = index.row()
+        name, state = self.row(row)
+
+        if role == Qt.CheckStateRole:
+            self.set_row(row, [name, not state])
+            self._parent.setCurrentIndex(index)
+            self._parent.setFocus()
+            self.dataChanged.emit(index, index)
+            return True
+        elif role == Qt.EditRole:
+            self.set_row(row, [from_qvariant(value, to_text_string), state])
+            self.dataChanged.emit(index, index)
+            return True
+        return True
+
+    def rowCount(self, index=QModelIndex()):
+        """Override Qt method"""
+        return len(self._rows)
+
+    def columnCount(self, index=QModelIndex()):
+        """Override Qt method"""
+        return 2
+
+    def row(self, rownum):
+        """ """
+        if self._rows == []:
+            return [None, None]
+        else:
+            return self._rows[rownum]
+
+    def set_row(self, rownum, value):
+        """ """
+        self._rows[rownum] = value
+
+
+class LayoutSaveDialog(QDialog):
+    """ """
+    def __init__(self, parent, order):
+        super(LayoutSaveDialog, self).__init__(parent)
+
+        # variables
+        self._parent = parent
+
+        # widgets
+        self.combo_box = QComboBox(self)
+        self.combo_box.addItems(order)
+        self.combo_box.setEditable(True)
+        self.combo_box.clearEditText()
+        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok |
+                                           QDialogButtonBox.Cancel,
+                                           Qt.Horizontal, self)
+        self.button_ok = self.button_box.button(QDialogButtonBox.Ok)
+        self.button_cancel = self.button_box.button(QDialogButtonBox.Cancel)
+
+        # widget setup
+        self.button_ok.setEnabled(False)
+        self.dialog_size = QSize(300, 100)
+        self.setWindowTitle('Save layout as')
+        self.setModal(True)
+        self.setMinimumSize(self.dialog_size)
+        self.setFixedSize(self.dialog_size)
+
+        # layouts
+        self.layout = QVBoxLayout()
+        self.layout.addWidget(self.combo_box)
+        self.layout.addWidget(self.button_box)
+        self.setLayout(self.layout)
+
+        # signals and slots
+        self.button_box.accepted.connect(self.accept)
+        self.button_box.rejected.connect(self.close)
+        self.combo_box.editTextChanged.connect(self.check_text)
+
+    def check_text(self, text):
+        """Disable empty layout name possibility"""
+        if to_text_string(text) == u'':
+            self.button_ok.setEnabled(False)
+        else:
+            self.button_ok.setEnabled(True)
+
+
+class LayoutSettingsDialog(QDialog):
+    """Layout settings dialog"""
+    def __init__(self, parent, names, order, active):
+        super(LayoutSettingsDialog, self).__init__(parent)
+
+        # variables
+        self._parent = parent
+        self._selection_model = None
+        self.names = names
+        self.order = order
+        self.active = active
+
+        # widgets
+        self.button_move_up = QPushButton(_('Move Up'))
+        self.button_move_down = QPushButton(_('Move Down'))
+        self.button_delete = QPushButton(_('Delete Layout'))
+        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok |
+                                           QDialogButtonBox.Cancel,
+                                           Qt.Horizontal, self)
+        self.group_box = QGroupBox(_("Layout Display and Order"))
+        self.table = QTableView(self)
+        self.ok_button = self.button_box.button(QDialogButtonBox.Ok)
+        self.cancel_button = self.button_box.button(QDialogButtonBox.Cancel)
+        self.cancel_button.setDefault(True)
+        self.cancel_button.setAutoDefault(True)
+
+        # widget setup
+        self.dialog_size = QSize(300, 200)
+        self.setMinimumSize(self.dialog_size)
+        self.setFixedSize(self.dialog_size)
+        self.setWindowTitle('Layout Settings')
+
+        self.table.setModel(LayoutModel(self.table, order, active))
+        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
+        self.table.setSelectionMode(QAbstractItemView.SingleSelection)
+        self.table.verticalHeader().hide()
+        self.table.horizontalHeader().hide()
+        self.table.setAlternatingRowColors(True)
+        self.table.setShowGrid(False)
+        self.table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+        self.table.horizontalHeader().setStretchLastSection(True)
+        self.table.setColumnHidden(1, True)
+        
+        # need to keep a reference for pyside not to segfault!
+        self._selection_model = self.table.selectionModel()
+
+        # layout
+        buttons_layout = QVBoxLayout()
+        buttons_layout.addWidget(self.button_move_up)
+        buttons_layout.addWidget(self.button_move_down)
+        buttons_layout.addStretch()
+        buttons_layout.addWidget(self.button_delete)
+
+        group_layout = QHBoxLayout()
+        group_layout.addWidget(self.table)
+        group_layout.addLayout(buttons_layout)
+        self.group_box.setLayout(group_layout)
+
+        layout = QVBoxLayout()
+        layout.addWidget(self.group_box)
+        layout.addWidget(self.button_box)
+
+        self.setLayout(layout)
+
+        # signals and slots
+        self.button_box.accepted.connect(self.accept)
+        self.button_box.rejected.connect(self.close)
+        self.button_delete.clicked.connect(self.delete_layout)
+        self.button_move_up.clicked.connect(lambda: self.move_layout(True))
+        self.button_move_down.clicked.connect(lambda: self.move_layout(False))
+        self.table.model().dataChanged.connect(
+           lambda: self.selection_changed(None, None))
+        self._selection_model.selectionChanged.connect(
+           lambda: self.selection_changed(None, None))
+
+        # focus table
+        index = self.table.model().index(0, 0)
+        self.table.setCurrentIndex(index)
+        self.table.setFocus()
+
+    def delete_layout(self):
+        """ """
+        names, order, active = self.names, self.order, self.order
+        name = from_qvariant(self.table.selectionModel().currentIndex().data(),
+                             to_text_string)
+
+        if name in names:
+            index = names.index(name)
+            # In case nothing has focus in the table
+        if index != -1:
+            order.remove(name)
+            names[index] = None
+            if name in active:
+                active.remove(name)
+            self.names, self.order, self.active = names, order, active
+            self.table.model().set_data(order, active)
+            index = self.table.model().index(0, 0)
+            self.table.setCurrentIndex(index)
+            self.table.setFocus()
+            self.selection_changed(None, None)
+            if len(order) == 0:
+                self.button_move_up.setDisabled(True)
+                self.button_move_down.setDisabled(True)
+                self.button_delete.setDisabled(True)
+
+    def move_layout(self, up=True):
+        """ """
+        names, order, active = self.names, self.order, self.active
+        row = self.table.selectionModel().currentIndex().row()
+        row_new = row
+
+        if up:
+            row_new -= 1
+        else:
+            row_new += 1
+
+        order[row], order[row_new] = order[row_new], order[row]
+
+        self.order = order
+        self.table.model().set_data(order, active)
+        index = self.table.model().index(row_new, 0)
+        self.table.setCurrentIndex(index)
+        self.table.setFocus()
+        self.selection_changed(None, None)
+
+    def selection_changed(self, selection, deselection):
+        """ """
+        model = self.table.model()
+        index = self.table.currentIndex()
+        row = index.row()
+        order, names, active = self.order, self.names, self.active
+
+        state = model.row(row)[1]
+        name = model.row(row)[0]
+
+        # Check if name changed
+        if name not in names:  # Did changed
+            if row != -1:  # row == -1, means no items left to delete
+                old_name = order[row]
+                order[row] = name
+                names[names.index(old_name)] = name
+                if old_name in active:
+                    active[active.index(old_name)] = name
+
+        # Check if checbox clicked
+        if state:
+            if name not in active:
+                active.append(name)
+        else:
+            if name in active:
+                active.remove(name)
+
+        self.active = active
+        self.button_move_up.setDisabled(False)
+        self.button_move_down.setDisabled(False)
+
+        if row == 0:
+            self.button_move_up.setDisabled(True)
+        if row == len(names) - 1:
+            self.button_move_down.setDisabled(True)
+        if len(names) == 0:
+            self.button_move_up.setDisabled(True)
+            self.button_move_down.setDisabled(True)
+
+
+def test():
+    """Run layout test widget test"""
+    from spyderlib.utils.qthelpers import qapplication
+
+    app = qapplication()
+    names = ['test', 'tester', '20', '30', '40']
+    order = ['test', 'tester', '20', '30', '40']
+    active = ['test', 'tester']
+    widget_1 = LayoutSettingsDialog(None, names, order, active)
+    widget_2 = LayoutSaveDialog(None, order)
+    widget_1.show()
+    widget_2.show()
+    sys.exit(app.exec_())
+
+if __name__ == '__main__':
+    test()
diff --git a/spyderlib/plugins/onlinehelp.py b/spyderlib/plugins/onlinehelp.py
index b07c28d..5f9bd05 100644
--- a/spyderlib/plugins/onlinehelp.py
+++ b/spyderlib/plugins/onlinehelp.py
@@ -11,7 +11,7 @@ from spyderlib.qt.QtCore import Signal
 import os.path as osp
 
 # Local imports
-from spyderlib.baseconfig import get_conf_path, _
+from spyderlib.config.base import get_conf_path, _
 from spyderlib.widgets.pydocgui import PydocBrowser
 from spyderlib.plugins import SpyderPluginMixin
 from spyderlib.py3compat import to_text_string
@@ -24,6 +24,7 @@ class OnlineHelp(PydocBrowser, SpyderPluginMixin):
     sig_option_changed = Signal(str, object)
     CONF_SECTION = 'onlinehelp'
     LOG_PATH = get_conf_path(CONF_SECTION)
+
     def __init__(self, parent):
         self.main = parent
         PydocBrowser.__init__(self, parent)
diff --git a/spyderlib/plugins/outlineexplorer.py b/spyderlib/plugins/outlineexplorer.py
index 98f03ce..2af6b69 100644
--- a/spyderlib/plugins/outlineexplorer.py
+++ b/spyderlib/plugins/outlineexplorer.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2011 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -8,22 +8,23 @@
 
 Data for outline are provided by method .get_outlineexplorer_data() of
 highlighter of assigned editor. For example, for Python files code editor uses
-highlighter spyderlib.widgets.sourcecode.syntaxhighlighters.PythonSH
+highlighter spyderlib.utils.syntaxhighlighters.PythonSH
 """
 
-from spyderlib.qt.QtCore import SIGNAL, Signal
+from spyderlib.qt.QtCore import Signal
 
 # Local imports
-from spyderlib.baseconfig import _
-from spyderlib.utils.qthelpers import get_icon
+from spyderlib.config.base import _
 from spyderlib.widgets.editortools import OutlineExplorerWidget
 from spyderlib.plugins import SpyderPluginMixin
 from spyderlib.py3compat import is_text_string
+import spyderlib.utils.icon_manager as ima
 
 
 class OutlineExplorer(OutlineExplorerWidget, SpyderPluginMixin):
     CONF_SECTION = 'outline_explorer'
     sig_option_changed = Signal(str, object)
+    
     def __init__(self, parent=None, fullpath_sorting=True):
         show_fullpath = self.get_option('show_fullpath')
         show_all_files = self.get_option('show_all_files')
@@ -48,7 +49,7 @@ class OutlineExplorer(OutlineExplorerWidget, SpyderPluginMixin):
 
     def get_plugin_icon(self):
         """Return widget icon"""
-        return get_icon('outline_explorer.png')
+        return ima.icon('outline_explorer')
     
     def get_focus_widget(self):
         """
@@ -63,8 +64,8 @@ class OutlineExplorer(OutlineExplorerWidget, SpyderPluginMixin):
     
     def register_plugin(self):
         """Register plugin in Spyder's main window"""
-        self.connect(self.main, SIGNAL('restore_scrollbar_position()'),
-                     self.restore_scrollbar_position)
+        self.main.restore_scrollbar_position.connect(
+                                               self.restore_scrollbar_position)
         self.main.add_dockwidget(self)
         
     def refresh_plugin(self):
@@ -81,7 +82,7 @@ class OutlineExplorer(OutlineExplorerWidget, SpyderPluginMixin):
         """DockWidget visibility has changed"""
         SpyderPluginMixin.visibility_changed(self, enable)
         if enable:
-            self.emit(SIGNAL("outlineexplorer_is_visible()"))
+            self.outlineexplorer_is_visible.emit()
             
     #------ Public API ---------------------------------------------------------
     def restore_scrollbar_position(self):
diff --git a/spyderlib/plugins/projectexplorer.py b/spyderlib/plugins/projectexplorer.py
index 45209b1..83b93da 100644
--- a/spyderlib/plugins/projectexplorer.py
+++ b/spyderlib/plugins/projectexplorer.py
@@ -7,11 +7,12 @@
 """Project Explorer Plugin"""
 
 from spyderlib.qt.QtGui import QFontDialog
-from spyderlib.qt.QtCore import SIGNAL
+from spyderlib.qt.QtCore import Signal, Slot
+import spyderlib.utils.icon_manager as ima
 
 # Local imports
-from spyderlib.baseconfig import _
-from spyderlib.utils.qthelpers import get_icon, create_action
+from spyderlib.config.base import _
+from spyderlib.utils.qthelpers import create_action
 from spyderlib.widgets.projectexplorer import ProjectExplorerWidget
 from spyderlib.plugins import SpyderPluginMixin
 from spyderlib.py3compat import is_text_string
@@ -20,6 +21,17 @@ from spyderlib.py3compat import is_text_string
 class ProjectExplorer(ProjectExplorerWidget, SpyderPluginMixin):
     """Project explorer plugin"""
     CONF_SECTION = 'project_explorer'
+
+    open_terminal = Signal(str)
+    open_interpreter = Signal(str)
+    pythonpath_changed = Signal()
+    sig_projects_were_closed = Signal()
+    create_module = Signal(str)
+    edit = Signal(str)
+    removed = Signal(str)
+    removed_tree = Signal(str)
+    renamed = Signal(str, str)
+    redirect_stdio = Signal(bool)
     
     def __init__(self, parent=None):
         ProjectExplorerWidget.__init__(self, parent=parent,
@@ -50,11 +62,11 @@ class ProjectExplorer(ProjectExplorerWidget, SpyderPluginMixin):
     def get_plugin_actions(self):
         """Return a list of actions related to plugin"""
         new_project_act = create_action(self, text=_('New project...'),
-                                        icon=get_icon('project_expanded.png'),
+                                        icon=ima.icon('project_expanded'),
                                         triggered=self.create_new_project)
 
         font_action = create_action(self, _("&Font..."),
-                                    None, 'font.png', _("Set font style"),
+                                    None, ima.icon('font'), _("Set font style"),
                                     triggered=self.change_font)
         self.treewidget.common_actions += (None, font_action)
         
@@ -65,21 +77,15 @@ class ProjectExplorer(ProjectExplorerWidget, SpyderPluginMixin):
     def register_plugin(self):
         """Register plugin in Spyder's main window"""
         self.main.pythonpath_changed()
-        self.connect(self.main, SIGNAL('restore_scrollbar_position()'),
-                     self.restore_scrollbar_position)
-        self.connect(self, SIGNAL("pythonpath_changed()"),
-                     self.main.pythonpath_changed)
-        self.connect(self, SIGNAL("projects_were_closed()"),
-                     self.projects_were_closed)
-        self.connect(self, SIGNAL("create_module(QString)"),
-                     self.main.editor.new)
-        self.connect(self, SIGNAL("edit(QString)"), self.main.editor.load)
-        self.connect(self, SIGNAL("removed(QString)"),
-                     self.main.editor.removed)
-        self.connect(self, SIGNAL("removed_tree(QString)"),
-                     self.main.editor.removed_tree)
-        self.connect(self, SIGNAL("renamed(QString,QString)"),
-                     self.main.editor.renamed)
+        self.main.restore_scrollbar_position.connect(
+                                               self.restore_scrollbar_position)
+        self.pythonpath_changed.connect(self.main.pythonpath_changed)
+        self.sig_projects_were_closed.connect(self.projects_were_closed)
+        self.create_module.connect(self.main.editor.new)
+        self.edit.connect(self.main.editor.load)
+        self.removed.connect(self.main.editor.removed)
+        self.removed_tree.connect(self.main.editor.removed_tree)
+        self.renamed.connect(self.main.editor.renamed)
         self.main.editor.set_projectexplorer(self)
         self.main.add_dockwidget(self)
 
@@ -96,6 +102,7 @@ class ProjectExplorer(ProjectExplorerWidget, SpyderPluginMixin):
         return True
         
     #------ Public API ---------------------------------------------------------
+    @Slot()
     def create_new_project(self):
         """Create new project"""
         if self.dockwidget.isHidden():
@@ -111,7 +118,8 @@ class ProjectExplorer(ProjectExplorerWidget, SpyderPluginMixin):
         for fname in self.main.editor.get_filenames():
             if self.treewidget.workspace.is_file_in_closed_project(fname):
                 self.main.editor.close_file_from_name(fname)
-        
+
+    @Slot()    
     def change_font(self):
         """Change font"""
         font, valid = QFontDialog.getFont(self.get_plugin_font(), self,
diff --git a/spyderlib/plugins/runconfig.py b/spyderlib/plugins/runconfig.py
index 4f7eb08..568bef0 100644
--- a/spyderlib/plugins/runconfig.py
+++ b/spyderlib/plugins/runconfig.py
@@ -12,15 +12,15 @@ from spyderlib.qt.QtGui import (QVBoxLayout, QDialog, QWidget, QGroupBox,
                                 QStackedWidget, QGridLayout, QSizePolicy,
                                 QRadioButton, QMessageBox, QFrame,
                                 QButtonGroup)
-from spyderlib.qt.QtCore import SIGNAL, SLOT, Qt
+from spyderlib.qt.QtCore import Signal, Slot, Qt, QSize
 from spyderlib.qt.compat import getexistingdirectory
+import spyderlib.utils.icon_manager as ima
 
 import os.path as osp
 
 # Local imports
-from spyderlib.baseconfig import _
-from spyderlib.config import CONF
-from spyderlib.utils.qthelpers import get_icon, get_std_icon
+from spyderlib.config.base import _
+from spyderlib.config.main import CONF
 from spyderlib.plugins.configdialog import GeneralConfigPage
 from spyderlib.py3compat import to_text_string, getcwd
 
@@ -51,7 +51,8 @@ class RunConfiguration(object):
         self.current = None
         self.systerm = None
         self.interact = None
-        self.show_kill_warning = None
+        self.show_kill_warning =None
+        self.post_mortem = None
         self.python_args = None
         self.python_args_enabled = None
         self.set(CONF.get('run', 'defaultconfiguration', default={}))
@@ -74,8 +75,12 @@ class RunConfiguration(object):
                            CONF.get('run', CURRENT_INTERPRETER_OPTION, True))
         self.systerm = options.get('systerm',
                            CONF.get('run', SYSTERM_INTERPRETER_OPTION, False))
-        self.interact = options.get('interact', False)
-        self.show_kill_warning = options.get('show_kill_warning', True)
+        self.interact = options.get('interact',
+                           CONF.get('run', 'interact', False))
+        self.show_kill_warning = options.get('show_kill_warning', 
+                           CONF.get('run', 'show_kill_warning', False))
+        self.post_mortem = options.get('post_mortem',
+                           CONF.get('run', 'post_mortem', False))
         self.python_args = options.get('python_args', '')
         self.python_args_enabled = options.get('python_args/enabled', False)
         
@@ -89,6 +94,7 @@ class RunConfiguration(object):
                 'systerm': self.systerm,
                 'interact': self.interact,
                 'show_kill_warning': self.show_kill_warning,
+                'post_mortem': self.post_mortem,
                 'python_args/enabled': self.python_args_enabled,
                 'python_args': self.python_args,
                 }
@@ -156,23 +162,24 @@ class RunConfigOptions(QWidget):
         self.clo_cb = QCheckBox(_("Command line options:"))
         common_layout.addWidget(self.clo_cb, 0, 0)
         self.clo_edit = QLineEdit()
-        self.connect(self.clo_cb, SIGNAL("toggled(bool)"),
-                     self.clo_edit.setEnabled)
+        self.clo_cb.toggled.connect(self.clo_edit.setEnabled)
         self.clo_edit.setEnabled(False)
         common_layout.addWidget(self.clo_edit, 0, 1)
         self.wd_cb = QCheckBox(_("Working directory:"))
         common_layout.addWidget(self.wd_cb, 1, 0)
         wd_layout = QHBoxLayout()
         self.wd_edit = QLineEdit()
-        self.connect(self.wd_cb, SIGNAL("toggled(bool)"),
-                     self.wd_edit.setEnabled)
+        self.wd_cb.toggled.connect(self.wd_edit.setEnabled)
         self.wd_edit.setEnabled(False)
         wd_layout.addWidget(self.wd_edit)
-        browse_btn = QPushButton(get_std_icon('DirOpenIcon'), "", self)
+        browse_btn = QPushButton(ima.icon('DirOpenIcon'), '', self)
         browse_btn.setToolTip(_("Select directory"))
-        self.connect(browse_btn, SIGNAL("clicked()"), self.select_directory)
+        browse_btn.clicked.connect(self.select_directory)
         wd_layout.addWidget(browse_btn)
         common_layout.addLayout(wd_layout, 1, 1)
+        self.post_mortem_cb = QCheckBox(_("Enter debugging mode when "
+                                          "errors appear during execution"))
+        common_layout.addWidget(self.post_mortem_cb)
         
         # --- Interpreter ---
         interpreter_group = QGroupBox(_("Console"))
@@ -187,8 +194,7 @@ class RunConfigOptions(QWidget):
         
         # --- Dedicated interpreter ---
         new_group = QGroupBox(_("Dedicated Python console"))
-        self.connect(self.current_radio, SIGNAL("toggled(bool)"),
-                     new_group.setDisabled)
+        self.current_radio.toggled.connect(new_group.setDisabled)
         new_layout = QGridLayout()
         new_group.setLayout(new_layout)
         self.interact_cb = QCheckBox(_("Interact with the Python "
@@ -197,18 +203,17 @@ class RunConfigOptions(QWidget):
         
         self.show_kill_warning_cb = QCheckBox(_("Show warning when killing"
                                                 " running process"))
+
         new_layout.addWidget(self.show_kill_warning_cb, 2, 0, 1, -1)
         self.pclo_cb = QCheckBox(_("Command line options:"))
         new_layout.addWidget(self.pclo_cb, 3, 0)
         self.pclo_edit = QLineEdit()
-        self.connect(self.pclo_cb, SIGNAL("toggled(bool)"),
-                     self.pclo_edit.setEnabled)
+        self.pclo_cb.toggled.connect(self.pclo_edit.setEnabled)
         self.pclo_edit.setEnabled(False)
         self.pclo_edit.setToolTip(_("<b>-u</b> is added to the "
                                     "other options you set here"))
         new_layout.addWidget(self.pclo_edit, 3, 1)
         
-        #TODO: Add option for "Post-mortem debugging"
 
         # Checkbox to preserve the old behavior, i.e. always open the dialog
         # on first run
@@ -216,8 +221,7 @@ class RunConfigOptions(QWidget):
         hline.setFrameShape(QFrame.HLine)
         hline.setFrameShadow(QFrame.Sunken)
         self.firstrun_cb = QCheckBox(ALWAYS_OPEN_FIRST_RUN % _("this dialog"))
-        self.connect(self.firstrun_cb, SIGNAL("clicked(bool)"),
-                     self.set_firstrun_o)
+        self.firstrun_cb.clicked.connect(self.set_firstrun_o)
         self.firstrun_cb.setChecked(firstrun_o)
         
         layout = QVBoxLayout()
@@ -252,6 +256,7 @@ class RunConfigOptions(QWidget):
             self.dedicated_radio.setChecked(True)
         self.interact_cb.setChecked(self.runconf.interact)
         self.show_kill_warning_cb.setChecked(self.runconf.show_kill_warning)
+        self.post_mortem_cb.setChecked(self.runconf.post_mortem)
         self.pclo_cb.setChecked(self.runconf.python_args_enabled)
         self.pclo_edit.setText(self.runconf.python_args)
     
@@ -264,6 +269,7 @@ class RunConfigOptions(QWidget):
         self.runconf.systerm = self.systerm_radio.isChecked()
         self.runconf.interact = self.interact_cb.isChecked()
         self.runconf.show_kill_warning = self.show_kill_warning_cb.isChecked()
+        self.runconf.post_mortem = self.post_mortem_cb.isChecked()
         self.runconf.python_args_enabled = self.pclo_cb.isChecked()
         self.runconf.python_args = to_text_string(self.pclo_edit.text())
         return self.runconf.get()
@@ -285,6 +291,8 @@ class RunConfigOptions(QWidget):
 
 class BaseRunConfigDialog(QDialog):
     """Run configuration dialog box, base widget"""
+    size_change = Signal(QSize)
+    
     def __init__(self, parent=None):
         QDialog.__init__(self, parent)
         
@@ -294,7 +302,7 @@ class BaseRunConfigDialog(QDialog):
         # a segmentation fault on UNIX or an application crash on Windows
         self.setAttribute(Qt.WA_DeleteOnClose)
 
-        self.setWindowIcon(get_icon("run_settings.png"))
+        self.setWindowIcon(ima.icon('run_settings'))
         layout = QVBoxLayout()
         self.setLayout(layout)
     
@@ -311,9 +319,9 @@ class BaseRunConfigDialog(QDialog):
         """Create dialog button box and add it to the dialog layout"""
         bbox = QDialogButtonBox(stdbtns)
         run_btn = bbox.addButton(_("Run"), QDialogButtonBox.AcceptRole)
-        self.connect(run_btn, SIGNAL('clicked()'), self.run_btn_clicked)
-        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
-        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
+        run_btn.clicked.connect(self.run_btn_clicked)
+        bbox.accepted.connect(self.accept)
+        bbox.rejected.connect(self.reject)
         btnlayout = QHBoxLayout()
         btnlayout.addStretch(1)
         btnlayout.addWidget(bbox)
@@ -325,7 +333,7 @@ class BaseRunConfigDialog(QDialog):
         main application
         """
         QDialog.resizeEvent(self, event)
-        self.emit(SIGNAL("size_change(QSize)"), self.size())
+        self.size_change.emit(self.size())
     
     def run_btn_clicked(self):
         """Run button was just clicked"""
@@ -351,7 +359,8 @@ class RunConfigOneDialog(BaseRunConfigDialog):
         self.add_widgets(self.runconfigoptions)
         self.add_button_box(QDialogButtonBox.Cancel)
         self.setWindowTitle(_("Run settings for %s") % osp.basename(fname))
-            
+    
+    @Slot()
     def accept(self):
         """Reimplement Qt method"""
         if not self.runconfigoptions.is_valid():
@@ -404,8 +413,7 @@ class RunConfigDialog(BaseRunConfigDialog):
             widget.set(options)
             self.combo.addItem(filename)
             self.stack.addWidget(widget)
-        self.connect(self.combo, SIGNAL("currentIndexChanged(int)"),
-                     self.stack.setCurrentIndex)
+        self.combo.currentIndexChanged.connect(self.stack.setCurrentIndex)
         self.combo.setCurrentIndex(index)
 
         self.add_widgets(combo_label, self.combo, 10, self.stack)
@@ -433,7 +441,7 @@ class RunConfigPage(GeneralConfigPage):
     CONF_SECTION = "run"
 
     NAME = _("Run")
-    ICON = "run.png"
+    ICON = ima.icon('run')
     
     def setup_page(self):
         run_dlg = _("Run Settings")
@@ -462,8 +470,8 @@ class RunConfigPage(GeneralConfigPage):
         interpreter_layout.addWidget(self.dedicated_radio)
         interpreter_layout.addWidget(self.systerm_radio)
         
-        wdir_group = QGroupBox(_("Working directory"))
-        wdir_bg = QButtonGroup(wdir_group)
+        general_group = QGroupBox("General settings")
+        wdir_bg = QButtonGroup(general_group)
         wdir_label = QLabel(_("Default working directory is:"))
         wdir_label.setWordWrap(True)
         dirname_radio = self.create_radiobutton(_("the script directory"),
@@ -473,19 +481,35 @@ class RunConfigPage(GeneralConfigPage):
                                 WDIR_USE_FIXED_DIR_OPTION, False,
                                 button_group=wdir_bg)
         thisdir_bd = self.create_browsedir("", WDIR_FIXED_DIR_OPTION, getcwd())
-        self.connect(thisdir_radio, SIGNAL("toggled(bool)"),
-                     thisdir_bd.setEnabled)
-        self.connect(dirname_radio, SIGNAL("toggled(bool)"),
-                     thisdir_bd.setDisabled)
+        thisdir_radio.toggled.connect(thisdir_bd.setEnabled)
+        dirname_radio.toggled.connect(thisdir_bd.setDisabled)
         thisdir_layout = QHBoxLayout()
         thisdir_layout.addWidget(thisdir_radio)
         thisdir_layout.addWidget(thisdir_bd)
 
-        wdir_layout = QVBoxLayout()
-        wdir_layout.addWidget(wdir_label)
-        wdir_layout.addWidget(dirname_radio)
-        wdir_layout.addLayout(thisdir_layout)
-        wdir_group.setLayout(wdir_layout)
+        post_mortem = self.create_checkbox(
+             _("Enter debugging mode when errors appear during execution"),
+             'post_mortem', False)
+
+        general_layout = QVBoxLayout()
+        general_layout.addWidget(wdir_label)
+        general_layout.addWidget(dirname_radio)
+        general_layout.addLayout(thisdir_layout)
+        general_layout.addWidget(post_mortem)
+        general_group.setLayout(general_layout)
+
+        dedicated_group = QGroupBox(_("Dedicated Python console"))
+        interact_after = self.create_checkbox(
+            _("Interact with the Python console after execution"),
+            'interact', False)
+        show_warning = self.create_checkbox(
+            _("Show warning when killing running processes"),
+            'show_kill_warning', True)
+
+        dedicated_layout = QVBoxLayout()
+        dedicated_layout.addWidget(interact_after)
+        dedicated_layout.addWidget(show_warning)
+        dedicated_group.setLayout(dedicated_layout)
 
         firstrun_cb = self.create_checkbox(
                             ALWAYS_OPEN_FIRST_RUN % _("Run Settings dialog"),
@@ -495,7 +519,8 @@ class RunConfigPage(GeneralConfigPage):
         vlayout.addWidget(about_label)
         vlayout.addSpacing(10)
         vlayout.addWidget(interpreter_group)
-        vlayout.addWidget(wdir_group)
+        vlayout.addWidget(general_group)
+        vlayout.addWidget(dedicated_group)
         vlayout.addWidget(firstrun_cb)
         vlayout.addStretch(1)
         self.setLayout(vlayout)
diff --git a/spyderlib/plugins/shortcuts.py b/spyderlib/plugins/shortcuts.py
index 762fc2b..0621a0b 100644
--- a/spyderlib/plugins/shortcuts.py
+++ b/spyderlib/plugins/shortcuts.py
@@ -7,170 +7,507 @@
 """Shortcut management"""
 
 from __future__ import print_function
+import os
+import re
+import sys
 
-from spyderlib.qt.QtGui import (QVBoxLayout, QComboBox, QItemDelegate,
-                                QTableView, QMessageBox, QPushButton)
-from spyderlib.qt.QtCore import (Qt, QSize, QAbstractTableModel, QModelIndex,
-                                 SIGNAL)
+from spyderlib.qt.QtGui import (QVBoxLayout, QTableView, QMessageBox,
+                                QPushButton, QKeySequence, QDialog,
+                                QDialogButtonBox, QLabel, QGridLayout,
+                                QLineEdit, QAbstractItemView,
+                                QSortFilterProxyModel, QApplication,
+                                QSpacerItem, QRegExpValidator, QHBoxLayout)
+from spyderlib.qt.QtCore import Qt, QAbstractTableModel, QModelIndex, QRegExp
 from spyderlib.qt.compat import to_qvariant, from_qvariant
 
-import sys
-
 # Local imports
-from spyderlib.baseconfig import _
-from spyderlib.guiconfig import (get_shortcut, set_shortcut,
-                                 iter_shortcuts, reset_shortcuts)
+from spyderlib.config.base import _, debug_print
+from spyderlib.config.gui import (get_shortcut, set_shortcut,
+                                  iter_shortcuts, reset_shortcuts)
 from spyderlib.plugins.configdialog import GeneralConfigPage
-from spyderlib.py3compat import to_text_string, is_text_string
-
-
-KEYSTRINGS = ["Escape", "Tab", "Backtab", "Backspace", "Return", "Enter",
-              "Delete", "Pause", "Print", "Clear", "Home", "End", "Left",
+from spyderlib.utils import icon_manager as ima
+from spyderlib.utils.qthelpers import get_std_icon
+from spyderlib.utils.stringmatching import get_search_regex, get_search_scores
+from spyderlib.widgets.helperwidgets import HTMLDelegate
+from spyderlib.widgets.helperwidgets import HelperToolButton
+
+
+MODIFIERS = {Qt.Key_Shift: Qt.SHIFT,
+             Qt.Key_Control: Qt.CTRL,
+             Qt.Key_Alt: Qt.ALT,
+             Qt.Key_Meta: Qt.META}
+
+# Valid shortcut keys
+SINGLE_KEYS = ["F{}".format(_i) for _i in range(1, 36)] + ["Delete", "Escape"]
+KEYSTRINGS = ["Tab", "Backtab", "Backspace", "Return", "Enter",
+              "Pause", "Print", "Clear", "Home", "End", "Left",
               "Up", "Right", "Down", "PageUp", "PageDown"] + \
-             ["F%d" % _i for _i in range(1, 36)] + \
-             ["Space", "Exclam", "QuoteDbl", "NumberSign", "Dollar", "Percent",
-              "Ampersand", "Apostrophe", "ParenLeft", "ParenRight", "Asterisk",
-              "Plus", "Comma", "Minus", "Period", "Slash"] + \
+             ["Space", "Exclam", "QuoteDbl", "NumberSign", "Dollar",
+              "Percent", "Ampersand", "Apostrophe", "ParenLeft",
+              "ParenRight", "Asterisk", "Plus", "Comma", "Minus",
+              "Period", "Slash"] + \
              [str(_i) for _i in range(10)] + \
-             ["Colon", "Semicolon", "Less", "Equal", "Greater", "Question",
-              "At"] + [chr(_i) for _i in range(65, 91)] + \
-             ["BracketLeft", "Backslash", "BracketRight", "Underscore"]
-
-
-class Key(object):
-    MODIFIERS = {Qt.NoModifier: "", Qt.ShiftModifier: "Shift",
-                 Qt.ControlModifier: "Ctrl", Qt.AltModifier: "Alt",
-                 Qt.MetaModifier: "Meta"}
-    if sys.platform == 'darwin':
-        MODIFIERNAMES = {Qt.NoModifier: "", Qt.ShiftModifier: "Shift",
-                         Qt.ControlModifier: "Cmd", Qt.AltModifier: "Alt",
-                         Qt.MetaModifier: "Ctrl"}
-    elif sys.platform == 'win32':
-        MODIFIERNAMES = {Qt.NoModifier: "", Qt.ShiftModifier: "Shift",
-                         Qt.ControlModifier: "Ctrl", Qt.AltModifier: "Alt",
-                         Qt.MetaModifier: "Win"}
-    else:
-        MODIFIERNAMES = {Qt.NoModifier: "", Qt.ShiftModifier: "Shift",
-                         Qt.ControlModifier: "Ctrl", Qt.AltModifier: "Alt",
-                         Qt.MetaModifier: "Meta"}
-    KEYS = {}
-    for attr in KEYSTRINGS:
-        KEYS[getattr(Qt, "Key_"+attr)] = attr
-
-    def __init__(self, key, mod1=Qt.NoModifier, mod2=Qt.NoModifier,
-                 mod3=Qt.NoModifier):
-        modifiers = [mod1, mod2, mod3]
-        assert all([mod in self.MODIFIERS for mod in modifiers])
-        self.modifiers = sorted(modifiers)
-        assert key in self.KEYS
-        self.key = key
-        
-    def __str__(self):
-        tlist = []
-        for mod in sorted(list(set(self.modifiers))):
-            if mod != Qt.NoModifier:
-                tlist.append(self.MODIFIERS[mod])
-        tlist.append(self.KEYS[self.key])
-        return "+".join(tlist)
-    
-    def __unicode__(self):
-        return to_text_string(self.__str__())
-    
-    @staticmethod
-    def modifier_from_str(modstr):
-        for k, v in list(Key.MODIFIERS.items()):
-            if v.lower() == modstr.lower():
-                return k
-    
-    @staticmethod
-    def key_from_str(keystr):
-        for k, v in list(Key.KEYS.items()):
-            if v.lower() == keystr.lower():
-                return k
-
-    @staticmethod
-    def modifier_from_name(modname):
-        for k, v in list(Key.MODIFIERNAMES.items()):
-            if v.lower() == modname.lower():
-                return k        
-
-def keystr2key(keystr):
-    keylist = keystr.split("+")
-    mods = []
-    if len(keylist) > 1:
-        for modstr in keylist[:-1]:
-            mods.append(Key.modifier_from_str(modstr))
-    return Key(Key.key_from_str(keylist[-1]), *mods)
+             ["Colon", "Semicolon", "Less", "Equal", "Greater",
+              "Question", "At"] + [chr(_i) for _i in range(65, 91)] + \
+             ["BracketLeft", "Backslash", "BracketRight", "Underscore",
+              "Control", "Alt", "Shift", "Meta"]
+VALID_SINGLE_KEYS = [getattr(Qt, 'Key_{0}'.format(k)) for k in SINGLE_KEYS]
+VALID_KEYS = [getattr(Qt, 'Key_{0}'.format(k)) for k in KEYSTRINGS+SINGLE_KEYS]
+
+# Valid finder chars. To be improved
+VALID_ACCENT_CHARS = "ÁÉÍOÚáéíúóàèìòùÀÈÌÒÙâêîôûÂÊÎÔÛäëïöüÄËÏÖÜñÑ"
+VALID_FINDER_CHARS = "[A-Za-z\s{0}]".format(VALID_ACCENT_CHARS)
+
+
+class CustomLineEdit(QLineEdit):
+    """QLineEdit that filters its key press and release events."""
+    def __init__(self, parent):
+        super(CustomLineEdit, self).__init__(parent)
+        self.setReadOnly(True)
+        self.setFocusPolicy(Qt.NoFocus)
+
+    def keyPressEvent(self, e):
+        """Qt Override"""
+        self.parent().keyPressEvent(e)
+
+    def keyReleaseEvent(self, e):
+        """Qt Override"""
+        self.parent().keyReleaseEvent(e)
+
+
+class ShortcutFinder(QLineEdit):
+    """Textbox for filtering listed shortcuts in the table."""
+    def __init__(self, parent, callback=None):
+        super(ShortcutFinder, self).__init__(parent)
+        self._parent = parent
+
+        # Widget setup
+        regex = QRegExp(VALID_FINDER_CHARS + "{100}")
+        self.setValidator(QRegExpValidator(regex))
+
+        # Signals
+        if callback:
+            self.textChanged.connect(callback)
+
+    def set_text(self, text):
+        """Set the filter text."""
+        text = text.strip()
+        new_text = self.text() + text
+        self.setText(new_text)
+
+    def keyPressEvent(self, event):
+        """Qt Override."""
+        key = event.key()
+        if key in [Qt.Key_Up]:
+            self._parent.previous_row()
+        elif key in [Qt.Key_Down]:
+            self._parent.next_row()
+        elif key in [Qt.Key_Enter, Qt.Key_Return]:
+            self._parent.show_editor()
+        else:
+            super(ShortcutFinder, self).keyPressEvent(event)
+
+
+# Error codes for the shortcut editor dialog
+NO_WARNING, SEQUENCE_LENGTH, SEQUENCE_CONFLICT, INVALID_KEY = [0, 1, 2, 3]
+
+
+class ShortcutEditor(QDialog):
+    """A dialog for entering key sequences."""
+    def __init__(self, parent, context, name, sequence, shortcuts):
+        super(ShortcutEditor, self).__init__(parent)
+        self._parent = parent
+
+        self.context = context
+        self.npressed = 0
+        self.keys = set()
+        self.key_modifiers = set()
+        self.key_non_modifiers = list()
+        self.key_text = list()
+        self.sequence = sequence
+        self.new_sequence = None
+        self.edit_state = True
+        self.shortcuts = shortcuts
+
+        # Widgets
+        self.label_info = QLabel()
+        self.label_info.setText(_("Press the new shortcut and select 'Ok': \n"
+             "(Press 'Tab' once to switch focus between the shortcut entry \n"
+             "and the buttons below it)"))
+        self.label_current_sequence = QLabel(_("Current shortcut:"))
+        self.text_current_sequence = QLabel(sequence)
+        self.label_new_sequence = QLabel(_("New shortcut:"))
+        self.text_new_sequence = CustomLineEdit(self)
+        self.text_new_sequence.setPlaceholderText(sequence)
+        self.helper_button = HelperToolButton()
+        self.helper_button.hide()
+        self.label_warning = QLabel()
+        self.label_warning.hide()
+
+        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
+        self.button_ok = bbox.button(QDialogButtonBox.Ok)
+        self.button_cancel = bbox.button(QDialogButtonBox.Cancel)
+
+        # Setup widgets
+        self.setWindowTitle(_('Shortcut: {0}').format(name))
+        self.button_ok.setFocusPolicy(Qt.NoFocus)
+        self.button_ok.setEnabled(False)
+        self.button_cancel.setFocusPolicy(Qt.NoFocus)
+        self.helper_button.setToolTip('')
+        self.helper_button.setFocusPolicy(Qt.NoFocus)
+        style = """
+            QToolButton {
+              margin:1px;
+              border: 0px solid grey;
+              padding:0px;
+              border-radius: 0px;
+            }"""
+        self.helper_button.setStyleSheet(style)
+        self.text_new_sequence.setFocusPolicy(Qt.NoFocus)
+        self.label_warning.setFocusPolicy(Qt.NoFocus)
+
+        # Layout
+        spacing = 5
+        layout_sequence = QGridLayout()
+        layout_sequence.addWidget(self.label_info, 0, 0, 1, 3)
+        layout_sequence.addItem(QSpacerItem(spacing, spacing), 1, 0, 1, 2)
+        layout_sequence.addWidget(self.label_current_sequence, 2, 0)
+        layout_sequence.addWidget(self.text_current_sequence, 2, 2)
+        layout_sequence.addWidget(self.label_new_sequence, 3, 0)
+        layout_sequence.addWidget(self.helper_button, 3, 1)
+        layout_sequence.addWidget(self.text_new_sequence, 3, 2)
+        layout_sequence.addWidget(self.label_warning, 4, 2, 1, 2)
+
+        layout = QVBoxLayout()
+        layout.addLayout(layout_sequence)
+        layout.addSpacing(spacing)
+        layout.addWidget(bbox)
+        self.setLayout(layout)
+
+        # Signals
+        bbox.accepted.connect(self.accept)
+        bbox.rejected.connect(self.reject)
+
+    def keyPressEvent(self, e):
+        """Qt override."""
+        key = e.key()
+        # Check if valid keys
+        if key not in VALID_KEYS:
+            self.invalid_key_flag = True
+            return
+
+        self.npressed += 1
+        self.key_non_modifiers.append(key)
+        self.key_modifiers.add(key)
+        self.key_text.append(e.text())
+        self.invalid_key_flag = False
+
+        debug_print('key {0}, npressed: {1}'.format(key, self.npressed))
+
+        if key == Qt.Key_unknown:
+            return
+
+        # The user clicked just and only the special keys
+        # Ctrl, Shift, Alt, Meta.
+        if (key == Qt.Key_Control or
+                key == Qt.Key_Shift or
+                key == Qt.Key_Alt or
+                key == Qt.Key_Meta):
+            return
+
+        modifiers = e.modifiers()
+        if modifiers & Qt.ShiftModifier:
+            key += Qt.SHIFT
+        if modifiers & Qt.ControlModifier:
+            key += Qt.CTRL
+            if sys.platform == 'darwin':
+                self.npressed -= 1
+            debug_print('decrementing')
+        if modifiers & Qt.AltModifier:
+            key += Qt.ALT
+        if modifiers & Qt.MetaModifier:
+            key += Qt.META
+
+        self.keys.add(key)
+
+    def toggle_state(self):
+        """Switch between shortcut entry and Accept/Cancel shortcut mode."""
+        self.edit_state = not self.edit_state
+
+        if not self.edit_state:
+            self.text_new_sequence.setEnabled(False)
+            if self.button_ok.isEnabled():
+                self.button_ok.setFocus()
+            else:
+                self.button_cancel.setFocus()
+        else:
+            self.text_new_sequence.setEnabled(True)
+            self.text_new_sequence.setFocus()
+
+    def nonedit_keyrelease(self, e):
+        """Key release event for non-edit state."""
+        key = e.key()
+        if key in [Qt.Key_Escape]:
+            self.close()
+            return
+
+        if key in [Qt.Key_Left, Qt.Key_Right, Qt.Key_Up,
+                   Qt.Key_Down]:
+            if self.button_ok.hasFocus():
+                self.button_cancel.setFocus()
+            else:
+                self.button_ok.setFocus()
+
+    def keyReleaseEvent(self, e):
+        """Qt override."""
+        self.npressed -= 1
+        if self.npressed <= 0:
+            key = e.key()
+
+            if len(self.keys) == 1 and key == Qt.Key_Tab:
+                self.toggle_state()
+                return
+
+            if len(self.keys) == 1 and key == Qt.Key_Escape:
+                self.set_sequence('')
+                self.label_warning.setText(_("Please introduce a different "
+                                             "shortcut"))
+
+            if len(self.keys) == 1 and key in [Qt.Key_Return, Qt.Key_Enter]:
+                self.toggle_state()
+                return
+
+            if not self.edit_state:
+                self.nonedit_keyrelease(e)
+            else:
+                debug_print('keys: {}'.format(self.keys))
+                if self.keys and key != Qt.Key_Escape:
+                    self.validate_sequence()
+                self.keys = set()
+                self.key_modifiers = set()
+                self.key_non_modifiers = list()
+                self.key_text = list()
+                self.npressed = 0
+
+    def check_conflicts(self):
+        """Check shortcuts for conflicts."""
+        conflicts = []
+        for index, shortcut in enumerate(self.shortcuts):
+            sequence = str(shortcut.key)
+            if sequence == self.new_sequence and \
+                (shortcut.context == self.context or shortcut.context == '_' or
+                 self.context == '_'):
+                conflicts.append(shortcut)
+        return conflicts
+
+    def update_warning(self, warning_type=NO_WARNING, conflicts=[]):
+        """Update warning label to reflect conflict status of new shortcut"""
+        if warning_type == NO_WARNING:
+            warn = False
+            tip = 'This shortcut is correct!'
+        elif warning_type == SEQUENCE_CONFLICT:
+            template = '<i>{0}<b>{1}</b></i>'
+            tip_title = _('The new shorcut conflicts with:') + '<br>'
+            tip_body = ''
+            for s in conflicts:
+                tip_body += ' - {0}: {1}<br>'.format(s.context, s.name)
+            tip_body = tip_body[:-4]  # Removing last <br>
+            tip = template.format(tip_title, tip_body)
+            warn = True
+        elif warning_type == SEQUENCE_LENGTH:
+            # Sequences with 5 keysequences (i.e. Ctrl+1, Ctrl+2, Ctrl+3,
+            # Ctrl+4, Ctrl+5) are invalid
+            template = '<i>{0}</i>'
+            tip = _('A compound sequence can have {break} a maximum of '
+                    '4 subsequences.{break}').format(**{'break': '<br>'})
+            warn = True
+        elif warning_type == INVALID_KEY:
+            template = '<i>{0}</i>'
+            tip = _('Invalid key entered') + '<br>'
+            warn = True
+
+        self.helper_button.show()
+        if warn:
+            self.label_warning.show()
+            self.helper_button.setIcon(get_std_icon('MessageBoxWarning'))
+            self.button_ok.setEnabled(False)
+        else:
+            self.helper_button.setIcon(get_std_icon('DialogApplyButton'))
+
+        self.label_warning.setText(tip)
+
+    def set_sequence(self, sequence):
+        """Set the new shortcut and update buttons."""
+        if not sequence or self.sequence == sequence:
+            self.button_ok.setEnabled(False)
+            different_sequence = False
+        else:
+            self.button_ok.setEnabled(True)
+            different_sequence = True
+
+        self.text_new_sequence.setText(sequence)
+        self.new_sequence = sequence
+
+        conflicts = self.check_conflicts()
+        if conflicts and different_sequence:
+            warning_type = SEQUENCE_CONFLICT
+        else:
+            warning_type = NO_WARNING
+
+        self.update_warning(warning_type=warning_type, conflicts=conflicts)
+
+    def validate_sequence(self):
+        """Provide additional checks for accepting or rejecting shortcuts."""
+        if self.invalid_key_flag:
+            self.update_warning(warning_type=INVALID_KEY)
+            return
+
+        for mod in MODIFIERS:
+            non_mod = set(self.key_non_modifiers)
+            non_mod.discard(mod)
+            if mod in self.key_non_modifiers:
+                self.key_non_modifiers.remove(mod)
+
+        self.key_modifiers = self.key_modifiers - non_mod
+
+        while u'' in self.key_text:
+            self.key_text.remove(u'')
+
+        self.key_text = [k.upper() for k in self.key_text]
+
+        # Fix Backtab, Tab issue
+        if os.name == 'nt':
+            if Qt.Key_Backtab in self.key_non_modifiers:
+                idx = self.key_non_modifiers.index(Qt.Key_Backtab)
+                self.key_non_modifiers[idx] = Qt.Key_Tab
+
+        if len(self.key_modifiers) == 0:
+            # Filter single key allowed
+            if self.key_non_modifiers[0] not in VALID_SINGLE_KEYS:
+                return
+            # Filter
+            elif len(self.key_non_modifiers) > 1:
+                return
+
+        # QKeySequence accepts a maximum of 4 different sequences
+        if len(self.keys) > 4:
+            # Update warning
+            self.update_warning(warning_type=SEQUENCE_LENGTH)
+            return
+
+        keys = []
+        for i in range(len(self.keys)):
+            key_seq = 0
+            for m in self.key_modifiers:
+                key_seq += MODIFIERS[m]
+            key_seq += self.key_non_modifiers[i]
+            keys.append(key_seq)
+
+        sequence = QKeySequence(*keys)
+
+        self.set_sequence(sequence.toString())
+
 
 class Shortcut(object):
+    """Shortcut convenience class for holding shortcut context, name,
+    original ordering index, key sequence for the shortcut and localized text.
+    """
     def __init__(self, context, name, key=None):
+        self.index = 0  # Sorted index. Populated when loading shortcuts
         self.context = context
         self.name = name
-        if is_text_string(key):
-            key = keystr2key(key)
         self.key = key
-        
+
     def __str__(self):
-        return "%s/%s: %s" % (self.context, self.name, self.key)
-    
+        return "{0}/{1}: {2}".format(self.context, self.name, self.key)
+
     def load(self):
-        self.key = keystr2key(get_shortcut(self.context, self.name))
-    
+        self.key = get_shortcut(self.context, self.name)
+
     def save(self):
-        set_shortcut(self.context, self.name, str(self.key))
+        set_shortcut(self.context, self.name, self.key)
 
 
-CONTEXT, NAME, MOD1, MOD2, MOD3, KEY = list(range(6))
+CONTEXT, NAME, SEQUENCE, SEARCH_SCORE = [0, 1, 2, 3]
+
 
 class ShortcutsModel(QAbstractTableModel):
-    def __init__(self):
+    def __init__(self, parent):
         QAbstractTableModel.__init__(self)
+        self._parent = parent
+
         self.shortcuts = []
+        self.scores = []
+        self.rich_text = []
+        self.normal_text = []
+        self.letters = ''
+        self.label = QLabel()
+        self.widths = []
+
+        # Needed to compensate for the HTMLDelegate color selection unawarness
+        palette = parent.palette()
+        self.text_color = palette.text().color().name()
+        self.text_color_highlight = palette.highlightedText().color().name()
+
+    def current_index(self):
+        """Get the currently selected index in the parent table view."""
+        i = self._parent.proxy_model.mapToSource(self._parent.currentIndex())
+        return i
 
     def sortByName(self):
+        """Qt Override."""
         self.shortcuts = sorted(self.shortcuts,
                                 key=lambda x: x.context+'/'+x.name)
         self.reset()
 
     def flags(self, index):
+        """Qt Override."""
         if not index.isValid():
             return Qt.ItemIsEnabled
-        column = index.column()
-        if column in (MOD1, MOD2, MOD3, KEY):
-            return Qt.ItemFlags(QAbstractTableModel.flags(self, index)|
-                                Qt.ItemIsEditable)
-        else:
-            return Qt.ItemFlags(QAbstractTableModel.flags(self, index))
+        return Qt.ItemFlags(QAbstractTableModel.flags(self, index))
 
     def data(self, index, role=Qt.DisplayRole):
-        if not index.isValid() or \
-           not (0 <= index.row() < len(self.shortcuts)):
+        """Qt Override."""
+        row = index.row()
+        if not index.isValid() or not (0 <= row < len(self.shortcuts)):
             return to_qvariant()
-        shortcut = self.shortcuts[index.row()]
+
+        shortcut = self.shortcuts[row]
         key = shortcut.key
         column = index.column()
+
         if role == Qt.DisplayRole:
             if column == CONTEXT:
                 return to_qvariant(shortcut.context)
             elif column == NAME:
-                return to_qvariant(shortcut.name)
-            elif column == MOD1:
-                return to_qvariant(Key.MODIFIERNAMES[key.modifiers[0]])
-            elif column == MOD2:
-                return to_qvariant(Key.MODIFIERNAMES[key.modifiers[1]])
-            elif column == MOD3:
-                return to_qvariant(Key.MODIFIERNAMES[key.modifiers[2]])
-            elif column == KEY:
-                return to_qvariant(Key.KEYS[key.key])
+                color = self.text_color
+                if self._parent == QApplication.focusWidget():
+                    if self.current_index().row() == row:
+                        color = self.text_color_highlight
+                    else:
+                        color = self.text_color
+                text = self.rich_text[row]
+                text = '<p style="color:{0}">{1}</p>'.format(color, text)
+                return to_qvariant(text)
+            elif column == SEQUENCE:
+                text = QKeySequence(key).toString(QKeySequence.NativeText)
+                return to_qvariant(text)
+            elif column == SEARCH_SCORE:
+                # Treating search scores as a table column simplifies the
+                # sorting once a score for a specific string in the finder
+                # has been defined. This column however should always remain
+                # hidden.
+                return to_qvariant(self.scores[row])
         elif role == Qt.TextAlignmentRole:
-            return to_qvariant(int(Qt.AlignHCenter|Qt.AlignVCenter))
+            return to_qvariant(int(Qt.AlignHCenter | Qt.AlignVCenter))
         return to_qvariant()
 
     def headerData(self, section, orientation, role=Qt.DisplayRole):
+        """Qt Override."""
         if role == Qt.TextAlignmentRole:
             if orientation == Qt.Horizontal:
-                return to_qvariant(int(Qt.AlignHCenter|Qt.AlignVCenter))
-            return to_qvariant(int(Qt.AlignRight|Qt.AlignVCenter))
+                return to_qvariant(int(Qt.AlignHCenter | Qt.AlignVCenter))
+            return to_qvariant(int(Qt.AlignRight | Qt.AlignVCenter))
         if role != Qt.DisplayRole:
             return to_qvariant()
         if orientation == Qt.Horizontal:
@@ -178,184 +515,294 @@ class ShortcutsModel(QAbstractTableModel):
                 return to_qvariant(_("Context"))
             elif section == NAME:
                 return to_qvariant(_("Name"))
-            elif section == MOD1:
-                return to_qvariant(_("Mod1"))
-            elif section == MOD2:
-                return to_qvariant(_("Mod2"))
-            elif section == MOD3:
-                return to_qvariant(_("Mod3"))
-            elif section == KEY:
-                return to_qvariant(_("Key"))
+            elif section == SEQUENCE:
+                return to_qvariant(_("Shortcut"))
+            elif section == SEARCH_SCORE:
+                return to_qvariant(_("Score"))
         return to_qvariant()
 
     def rowCount(self, index=QModelIndex()):
+        """Qt Override."""
         return len(self.shortcuts)
 
     def columnCount(self, index=QModelIndex()):
-        return 6
-    
+        """Qt Override."""
+        return 4
+
     def setData(self, index, value, role=Qt.EditRole):
+        """Qt Override."""
         if index.isValid() and 0 <= index.row() < len(self.shortcuts):
             shortcut = self.shortcuts[index.row()]
-            key = shortcut.key
             column = index.column()
             text = from_qvariant(value, str)
-            if column == MOD1:
-                key.modifiers[0] = Key.modifier_from_name(text)
-            elif column == MOD2:
-                key.modifiers[1] = Key.modifier_from_name(text)
-            elif column == MOD3:
-                key.modifiers[2] = Key.modifier_from_name(text)
-            elif column == KEY:
-                key.key = Key.key_from_str(text)
-            self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
-                      index, index)
+            if column == SEQUENCE:
+                shortcut.key = text
+            self.dataChanged.emit(index, index)
             return True
         return False
 
+    def update_search_letters(self, text):
+        """Update search letters with text input in search box."""
+        self.letters = text
+        names = [shortcut.name for shortcut in self.shortcuts]
+        results = get_search_scores(text, names, template='<b>{0}</b>')
+        self.normal_text, self.rich_text, self.scores = zip(*results)
+        self.reset()
+
+    def update_active_row(self):
+        """Update active row to update color in selected text."""
+        self.data(self.current_index())
+
+    def row(self, row_num):
+        """Get row based on model index. Needed for the custom proxy model."""
+        return self.shortcuts[row_num]
+
+    def reset(self):
+        """"Reset model to take into account new search letters."""
+        self.beginResetModel()
+        self.endResetModel()
 
-class ShortcutsDelegate(QItemDelegate):
+
+class CustomSortFilterProxy(QSortFilterProxyModel):
+    """Custom column filter based on regex."""
     def __init__(self, parent=None):
-        QItemDelegate.__init__(self, parent)
-        self.modifiers = sorted(Key.MODIFIERNAMES.values())
-        self.mod = None
-        self.keys = sorted(Key.KEYS.values())
-        self.key = None
-        
-    def sizeHint(self, option, index):
-        fm = option.fontMetrics
-        if index.column() in (MOD1, MOD2, MOD3):
-            if self.mod is None:
-                w = 0
-                for mod in self.modifiers:
-                    cw = fm.width(mod)
-                    if cw > w:
-                        w = cw
-                        self.mod = mod
-            else:
-                w = fm.width(self.mod)
-            return QSize(w+20, fm.height())
-        elif index.column() == KEY:
-            if self.key is None:
-                w = 0
-                for key in self.keys:
-                    cw = fm.width(key)
-                    if cw > w:
-                        w = cw
-                        self.key = key
-            else:
-                w = fm.width(self.key)
-            return QSize(w+20, fm.height())
-        return QItemDelegate.sizeHint(self, option, index)
-
-    def createEditor(self, parent, option, index):
-        if index.column() in (MOD1, MOD2, MOD3):
-            combobox = QComboBox(parent)
-            combobox.addItems(self.modifiers)
-            return combobox
-        elif index.column() == KEY:
-            combobox = QComboBox(parent)
-            combobox.addItems(self.keys)
-            return combobox
+        super(CustomSortFilterProxy, self).__init__(parent)
+        self._parent = parent
+        self.pattern = re.compile(u'')
+
+    def set_filter(self, text):
+        """Set regular expression for filter."""
+        self.pattern = get_search_regex(text)
+        if self.pattern:
+            self._parent.setSortingEnabled(False)
         else:
-            return QItemDelegate.createEditor(self, parent, option,
-                                              index)
-
-    def setEditorData(self, editor, index):
-        text = from_qvariant(index.model().data(index, Qt.DisplayRole), str)
-        if index.column() in (MOD1, MOD2, MOD3, KEY):
-            i = editor.findText(text)
-            if i == -1:
-                i = 0
-            editor.setCurrentIndex(i)
-        else:
-            QItemDelegate.setEditorData(self, editor, index)
+            self._parent.setSortingEnabled(True)
+        self.invalidateFilter()
+
+    def filterAcceptsRow(self, row_num, parent):
+        """Qt override.
+
+        Reimplemented from base class to allow the use of custom filtering.
+        """
+        model = self.sourceModel()
+        name = model.row(row_num).name
+        r = re.search(self.pattern, name)
 
-    def setModelData(self, editor, model, index):
-        if index.column() in (MOD1, MOD2, MOD3, KEY):
-            model.setData(index, to_qvariant(editor.currentText()))
+        if r is None:
+            return False
         else:
-            QItemDelegate.setModelData(self, editor, model, index)
+            return True
 
 
 class ShortcutsTable(QTableView):
     def __init__(self, parent=None):
         QTableView.__init__(self, parent)
-        self.model = ShortcutsModel()
-        self.setModel(self.model)
-        self.setItemDelegate(ShortcutsDelegate(self))
+        self._parent = parent
+        self.finder = None
+
+        self.source_model = ShortcutsModel(self)
+        self.proxy_model = CustomSortFilterProxy(self)
+        self.last_regex = ''
+
+        self.proxy_model.setSourceModel(self.source_model)
+        self.proxy_model.setDynamicSortFilter(True)
+        self.proxy_model.setFilterKeyColumn(NAME)
+        self.proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
+        self.setModel(self.proxy_model)
+
+        self.hideColumn(SEARCH_SCORE)
+        self.setItemDelegateForColumn(NAME, HTMLDelegate(self, margin=9))
+        self.setSelectionBehavior(QAbstractItemView.SelectRows)
+        self.setSelectionMode(QAbstractItemView.SingleSelection)
+        self.setSortingEnabled(True)
+        self.setEditTriggers(QAbstractItemView.AllEditTriggers)
+        self.selectionModel().selectionChanged.connect(self.selection)
+
+        self.verticalHeader().hide()
         self.load_shortcuts()
-                     
+
+    def focusOutEvent(self, e):
+        """Qt Override."""
+        self.source_model.update_active_row()
+        super(ShortcutsTable, self).focusOutEvent(e)
+
+    def focusInEvent(self, e):
+        """Qt Override."""
+        super(ShortcutsTable, self).focusInEvent(e)
+        self.selectRow(self.currentIndex().row())
+
+    def selection(self, index):
+        """Update selected row."""
+        self.update()
+        self.isActiveWindow()
+
     def adjust_cells(self):
+        """Adjust column size based on contents."""
         self.resizeColumnsToContents()
-#        self.resizeRowsToContents()
+        fm = self.horizontalHeader().fontMetrics()
+        names = [fm.width(s.name + ' '*9) for s in self.source_model.shortcuts]
+        self.setColumnWidth(NAME, max(names))
         self.horizontalHeader().setStretchLastSection(True)
-        
+
     def load_shortcuts(self):
+        """Load shortcuts and assign to table model."""
         shortcuts = []
         for context, name, keystr in iter_shortcuts():
             shortcut = Shortcut(context, name, keystr)
             shortcuts.append(shortcut)
         shortcuts = sorted(shortcuts, key=lambda x: x.context+x.name)
-        self.model.shortcuts = shortcuts
-        self.model.reset()
+        # Store the original order of shortcuts
+        for i, shortcut in enumerate(shortcuts):
+            shortcut.index = i
+        self.source_model.shortcuts = shortcuts
+        self.source_model.scores = [0]*len(shortcuts)
+        self.source_model.rich_text = [s.name for s in shortcuts]
+        self.source_model.reset()
         self.adjust_cells()
+        self.sortByColumn(CONTEXT, Qt.AscendingOrder)
 
     def check_shortcuts(self):
-        """Check shortcuts for conflicts"""
+        """Check shortcuts for conflicts."""
         conflicts = []
-        for index, sh1 in enumerate(self.model.shortcuts):
-            if index == len(self.model.shortcuts)-1:
+        for index, sh1 in enumerate(self.source_model.shortcuts):
+            if index == len(self.source_model.shortcuts)-1:
                 break
-            for sh2 in self.model.shortcuts[index+1:]:
+            for sh2 in self.source_model.shortcuts[index+1:]:
                 if sh2 is sh1:
                     continue
                 if str(sh2.key) == str(sh1.key) \
-                   and (sh1.context == sh2.context or sh1.context == '_'
-                        or sh2.context == '_'):
+                   and (sh1.context == sh2.context or sh1.context == '_' or
+                        sh2.context == '_'):
                     conflicts.append((sh1, sh2))
         if conflicts:
-            self.parent().emit(SIGNAL('show_this_page()'))
+            self.parent().show_this_page.emit()
             cstr = "\n".join(['%s <---> %s' % (sh1, sh2)
                               for sh1, sh2 in conflicts])
-            QMessageBox.warning(self, _( "Conflicts"),
+            QMessageBox.warning(self, _("Conflicts"),
                                 _("The following conflicts have been "
                                   "detected:")+"\n"+cstr, QMessageBox.Ok)
-        
+
     def save_shortcuts(self):
+        """Save shortcuts from table model."""
         self.check_shortcuts()
-        for shortcut in self.model.shortcuts:
+        for shortcut in self.source_model.shortcuts:
             shortcut.save()
-        
+
+    def show_editor(self):
+        """Create, setup and display the shortcut editor dialog."""
+        index = self.proxy_model.mapToSource(self.currentIndex())
+        row, column = index.row(), index.column()
+        shortcuts = self.source_model.shortcuts
+        context = shortcuts[row].context
+        name = shortcuts[row].name
+
+        sequence_index = self.source_model.index(row, SEQUENCE)
+        sequence = sequence_index.data()
+
+        dialog = ShortcutEditor(self, context, name, sequence, shortcuts)
+
+        if dialog.exec_():
+            new_sequence = dialog.new_sequence
+            self.source_model.setData(sequence_index, new_sequence)
+
+    def set_regex(self, regex=None, reset=False):
+        """Update the regex text for the shortcut finder."""
+        if reset:
+            text = ''
+        else:
+            text = self.finder.text().replace(' ', '').lower()
+
+        self.proxy_model.set_filter(text)
+        self.source_model.update_search_letters(text)
+        self.sortByColumn(SEARCH_SCORE, Qt.AscendingOrder)
+
+        if self.last_regex != regex:
+            self.selectRow(0)
+        self.last_regex = regex
+
+    def next_row(self):
+        """Move to next row from currently selected row."""
+        row = self.currentIndex().row()
+        rows = self.proxy_model.rowCount()
+        if row + 1 == rows:
+            row = -1
+        self.selectRow(row + 1)
+
+    def previous_row(self):
+        """Move to previous row from currently selected row."""
+        row = self.currentIndex().row()
+        rows = self.proxy_model.rowCount()
+        if row == 0:
+            row = rows
+        self.selectRow(row - 1)
+
+    def keyPressEvent(self, event):
+        """Qt Override."""
+        key = event.key()
+        if key in [Qt.Key_Enter, Qt.Key_Return]:
+            self.show_editor()
+        elif key in [Qt.Key_Tab]:
+            self.finder.setFocus()
+        elif key in [Qt.Key_Backtab]:
+            self.parent().reset_btn.setFocus()
+        elif key in [Qt.Key_Up, Qt.Key_Down, Qt.Key_Left, Qt.Key_Right]:
+            super(ShortcutsTable, self).keyPressEvent(event)
+        elif key not in [Qt.Key_Escape, Qt.Key_Space]:
+            text = event.text()
+            if text:
+                if re.search(VALID_FINDER_CHARS, text) is not None:
+                    self.finder.setFocus()
+                    self.finder.set_text(text)
+        elif key in [Qt.Key_Escape]:
+            self.finder.keyPressEvent(event)
+
+    def mouseDoubleClickEvent(self, event):
+        """Qt Override."""
+        self.show_editor()
+
 
 class ShortcutsConfigPage(GeneralConfigPage):
     CONF_SECTION = "shortcuts"
-    
+
     NAME = _("Keyboard shortcuts")
-    ICON = "genprefs.png"
-    
+    ICON = ima.icon('keyboard')
+
     def setup_page(self):
+        # Widgets
         self.table = ShortcutsTable(self)
-        self.connect(self.table.model,
-                     SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
-                     lambda i1, i2, opt='': self.has_been_modified(opt))
+        self.finder = ShortcutFinder(self.table, self.table.set_regex)
+        self.table.finder = self.finder
+        self.label_finder = QLabel(_('Search: '))
+        self.reset_btn = QPushButton(_("Reset to default values"))
+
+        # Layout
+        hlayout = QHBoxLayout()
         vlayout = QVBoxLayout()
+        hlayout.addWidget(self.label_finder)
+        hlayout.addWidget(self.finder)
         vlayout.addWidget(self.table)
-        reset_btn = QPushButton(_("Reset to default values"))
-        self.connect(reset_btn, SIGNAL('clicked()'), self.reset_to_default)
-        vlayout.addWidget(reset_btn)
+        vlayout.addLayout(hlayout)
+        vlayout.addWidget(self.reset_btn)
         self.setLayout(vlayout)
-        
+
+        self.setTabOrder(self.table, self.finder)
+        self.setTabOrder(self.finder, self.reset_btn)
+
+        # Signals and slots
+        self.table.proxy_model.dataChanged.connect(
+                     lambda i1, i2, opt='': self.has_been_modified(opt))
+        self.reset_btn.clicked.connect(self.reset_to_default)
+
     def check_settings(self):
         self.table.check_shortcuts()
-        
+
     def reset_to_default(self):
         reset_shortcuts()
         self.main.apply_shortcuts()
         self.table.load_shortcuts()
         self.load_from_conf()
         self.set_modified(False)
-            
+
     def apply_settings(self, options):
         self.table.save_shortcuts()
         self.main.apply_shortcuts()
@@ -367,8 +814,8 @@ def test():
     table = ShortcutsTable()
     table.show()
     app.exec_()
-    print([str(s) for s in table.model.shortcuts])
+    print([str(s) for s in table.source_model.shortcuts])
     table.check_shortcuts()
 
 if __name__ == '__main__':
-    test()
\ No newline at end of file
+    test()
diff --git a/spyderlib/plugins/variableexplorer.py b/spyderlib/plugins/variableexplorer.py
index d77ccbd..b11f815 100644
--- a/spyderlib/plugins/variableexplorer.py
+++ b/spyderlib/plugins/variableexplorer.py
@@ -1,22 +1,22 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
-"""Namespace Browser Plugin"""
+"""Variable Explorer Plugin"""
 
-from spyderlib.qt.QtGui import QStackedWidget, QGroupBox, QVBoxLayout
+from spyderlib.qt.QtGui import QGroupBox, QStackedWidget, QVBoxLayout, QWidget
 from spyderlib.qt.QtCore import Signal
+import spyderlib.utils.icon_manager as ima
 
 # Local imports
-from spyderlib.baseconfig import _
-from spyderlib.config import CONF
-from spyderlib.utils.qthelpers import get_icon
+from spyderlib.config.base import _
+from spyderlib.config.main import CONF
 from spyderlib.utils import programs
 from spyderlib.plugins import SpyderPluginMixin, PluginConfigPage
 from spyderlib.widgets.externalshell.monitor import REMOTE_SETTINGS
-from spyderlib.widgets.externalshell.namespacebrowser import NamespaceBrowser
+from spyderlib.widgets.variableexplorer.namespacebrowser import NamespaceBrowser
 
 
 class VariableExplorerConfigPage(PluginConfigPage):
@@ -75,18 +75,27 @@ class VariableExplorerConfigPage(PluginConfigPage):
         self.setLayout(vlayout)
 
 
-class VariableExplorer(QStackedWidget, SpyderPluginMixin):
+class VariableExplorer(QWidget, SpyderPluginMixin):
     """
     Variable Explorer Plugin
     """
     CONF_SECTION = 'variable_explorer'
     CONFIGWIDGET_CLASS = VariableExplorerConfigPage
     sig_option_changed = Signal(str, object)
+
     def __init__(self, parent):
-        QStackedWidget.__init__(self, parent)
+        QWidget.__init__(self, parent)
         SpyderPluginMixin.__init__(self, parent)
+
+        # Widgets
+        self.stack = QStackedWidget(self)
         self.shellwidgets = {}
 
+        # Layout
+        layout = QVBoxLayout()
+        layout.addWidget(self.stack)
+        self.setLayout(layout)
+
         # Initialize plugin
         self.initialize_plugin()
 
@@ -101,11 +110,27 @@ class VariableExplorer(QStackedWidget, SpyderPluginMixin):
         for name in REMOTE_SETTINGS:
             settings[name] = CONF.get(VariableExplorer.CONF_SECTION, name)
         return settings
-        
-    #------ Public API ---------------------------------------------------------
+
+    # ----- Stack accesors ----------------------------------------------------
+    def set_current_widget(self, nsb):
+        self.stack.setCurrentWidget(nsb)
+
+    def current_widget(self):
+        return self.stack.currentWidget()
+
+    def count(self):
+        return self.stack.count()
+
+    def remove_widget(self, nsb):
+        self.stack.removeWidget(nsb)
+
+    def add_widget(self, nsb):
+        self.stack.addWidget(nsb)
+
+    # ----- Public API --------------------------------------------------------
     def add_shellwidget(self, shellwidget):
         shellwidget_id = id(shellwidget)
-        # Add shell only once: this method may be called two times in a row 
+        # Add shell only once: this method may be called two times in a row
         # by the External console plugin (dev. convenience)
         from spyderlib.widgets.externalshell import systemshell
         if isinstance(shellwidget, systemshell.ExternalSystemShell):
@@ -115,7 +140,7 @@ class VariableExplorer(QStackedWidget, SpyderPluginMixin):
             nsb.set_shellwidget(shellwidget)
             nsb.setup(**VariableExplorer.get_settings())
             nsb.sig_option_changed.connect(self.sig_option_changed.emit)
-            self.addWidget(nsb)
+            self.add_widget(nsb)
             self.shellwidgets[shellwidget_id] = nsb
             self.set_shellwidget_from_id(shellwidget_id)
             return nsb
@@ -125,22 +150,22 @@ class VariableExplorer(QStackedWidget, SpyderPluginMixin):
         # that shell was not a Python-based console (it was a terminal)
         if shellwidget_id in self.shellwidgets:
             nsb = self.shellwidgets.pop(shellwidget_id)
-            self.removeWidget(nsb)
+            self.remove_widget(nsb)
             nsb.close()
     
     def set_shellwidget_from_id(self, shellwidget_id):
         if shellwidget_id in self.shellwidgets:
             nsb = self.shellwidgets[shellwidget_id]
-            self.setCurrentWidget(nsb)
+            self.set_current_widget(nsb)
             if self.isvisible:
                 nsb.visibility_changed(True)
-            
+
     def import_data(self, fname):
         """Import data in current namespace"""
         if self.count():
-            nsb = self.currentWidget()
+            nsb = self.current_widget()
             nsb.refresh_table()
-            nsb.import_data(fname)
+            nsb.import_data(filename=fname)
             if self.dockwidget and not self.ismaximized:
                 self.dockwidget.setVisible(True)
                 self.dockwidget.raise_()
@@ -150,7 +175,7 @@ class VariableExplorer(QStackedWidget, SpyderPluginMixin):
         """DockWidget visibility has changed"""
         SpyderPluginMixin.visibility_changed(self, enable)
         for nsb in list(self.shellwidgets.values()):
-            nsb.visibility_changed(enable and nsb is self.currentWidget())
+            nsb.visibility_changed(enable and nsb is self.current_widget())
     
     #------ SpyderPluginWidget API ---------------------------------------------
     def get_plugin_title(self):
@@ -159,14 +184,14 @@ class VariableExplorer(QStackedWidget, SpyderPluginMixin):
 
     def get_plugin_icon(self):
         """Return plugin icon"""
-        return get_icon('dictedit.png')
+        return ima.icon('dictedit')
     
     def get_focus_widget(self):
         """
         Return the widget to give focus to when
         this plugin's dockwidget is raised on top-level
         """
-        return self.currentWidget()
+        return self.current_widget()
         
     def closing_plugin(self, cancelable=False):
         """Perform actions before parent main window is closed"""
@@ -191,4 +216,4 @@ class VariableExplorer(QStackedWidget, SpyderPluginMixin):
             nsb.setup(**VariableExplorer.get_settings())
         ar_timeout = self.get_option('autorefresh/timeout')
         for shellwidget in self.main.extconsole.shellwidgets:
-            shellwidget.set_autorefresh_timeout(ar_timeout)
\ No newline at end of file
+            shellwidget.set_autorefresh_timeout(ar_timeout)
diff --git a/spyderlib/plugins/workingdirectory.py b/spyderlib/plugins/workingdirectory.py
index 2808a4c..e8ef4b2 100644
--- a/spyderlib/plugins/workingdirectory.py
+++ b/spyderlib/plugins/workingdirectory.py
@@ -11,18 +11,20 @@
 # pylint: disable=R0911
 # pylint: disable=R0201
 
+from spyderlib.qt import PYQT5
 from spyderlib.qt.QtGui import (QToolBar, QLabel, QGroupBox, QVBoxLayout,
                                 QHBoxLayout, QButtonGroup)
-from spyderlib.qt.QtCore import SIGNAL, Signal
+from spyderlib.qt.QtCore import Signal, Slot, QSize
 from spyderlib.qt.compat import getexistingdirectory
+import spyderlib.utils.icon_manager as ima
 
 import os
 import os.path as osp
 
 # Local imports
 from spyderlib.utils import encoding
-from spyderlib.baseconfig import get_conf_path, _
-from spyderlib.utils.qthelpers import get_icon, get_std_icon, create_action
+from spyderlib.config.base import get_conf_path, _
+from spyderlib.utils.qthelpers import create_action
 
 # Package local imports
 from spyderlib.widgets.comboboxes import PathComboBox
@@ -58,10 +60,8 @@ class WorkingDirectoryConfigPage(PluginConfigPage):
                                 button_group=startup_bg)
         thisdir_bd = self.create_browsedir("", 'startup/fixed_directory',
                                            getcwd())
-        self.connect(thisdir_radio, SIGNAL("toggled(bool)"),
-                     thisdir_bd.setEnabled)
-        self.connect(lastdir_radio, SIGNAL("toggled(bool)"),
-                     thisdir_bd.setDisabled)
+        thisdir_radio.toggled.connect(thisdir_bd.setEnabled)
+        lastdir_radio.toggled.connect(thisdir_bd.setDisabled)
         thisdir_layout = QHBoxLayout()
         thisdir_layout.addWidget(thisdir_radio)
         thisdir_layout.addWidget(thisdir_bd)
@@ -142,10 +142,21 @@ class WorkingDirectory(QToolBar, SpyderPluginMixin):
     CONF_SECTION = 'workingdir'
     CONFIGWIDGET_CLASS = WorkingDirectoryConfigPage
     LOG_PATH = get_conf_path(CONF_SECTION)
+
     sig_option_changed = Signal(str, object)
-    def __init__(self, parent, workdir=None):
-        QToolBar.__init__(self, parent)
-        SpyderPluginMixin.__init__(self, parent)
+    set_previous_enabled = Signal(bool)
+    set_next_enabled = Signal(bool)
+    redirect_stdio = Signal(bool)
+    set_explorer_cwd = Signal(str)
+    refresh_findinfiles = Signal()
+    set_current_console_wd = Signal(str)
+    
+    def __init__(self, parent, workdir=None, **kwds):
+        if PYQT5:
+            super(WorkingDirectory, self).__init__(parent, **kwds)
+        else:
+            QToolBar.__init__(self, parent)
+            SpyderPluginMixin.__init__(self, parent)
 
         # Initialize plugin
         self.initialize_plugin()
@@ -157,7 +168,7 @@ class WorkingDirectory(QToolBar, SpyderPluginMixin):
         self.history = []
         self.histindex = None
         self.previous_action = create_action(self, "previous", None,
-                                     get_icon('previous.png'), _('Back'),
+                                     ima.icon('previous'), _('Back'),
                                      triggered=self.previous_directory)
         self.addAction(self.previous_action)
         
@@ -165,15 +176,13 @@ class WorkingDirectory(QToolBar, SpyderPluginMixin):
         self.history = []
         self.histindex = None
         self.next_action = create_action(self, "next", None,
-                                     get_icon('next.png'), _('Next'),
+                                     ima.icon('next'), _('Next'),
                                      triggered=self.next_directory)
         self.addAction(self.next_action)
         
         # Enable/disable previous/next actions
-        self.connect(self, SIGNAL("set_previous_enabled(bool)"),
-                     self.previous_action.setEnabled)
-        self.connect(self, SIGNAL("set_next_enabled(bool)"),
-                     self.next_action.setEnabled)
+        self.set_previous_enabled.connect(self.previous_action.setEnabled)
+        self.set_next_enabled.connect(self.next_action.setEnabled)
         
         # Path combo box
         adjust = self.get_option('working_dir_adjusttocontents')
@@ -183,7 +192,7 @@ class WorkingDirectory(QToolBar, SpyderPluginMixin):
                                "terminals), for the file explorer, for the\n"
                                "find in files plugin and for new files\n"
                                "created in the editor"))
-        self.connect(self.pathedit, SIGNAL("open_dir(QString)"), self.chdir)
+        self.pathedit.open_dir.connect(self.chdir)
         self.pathedit.setMaxCount(self.get_option('working_dir_history'))
         wdhistory = self.load_wdhistory( workdir )
         if workdir is None:
@@ -198,18 +207,19 @@ class WorkingDirectory(QToolBar, SpyderPluginMixin):
                     workdir = "."
         self.chdir(workdir)
         self.pathedit.addItems( wdhistory )
+        self.pathedit.selected_text = self.pathedit.currentText()
         self.refresh_plugin()
         self.addWidget(self.pathedit)
         
         # Browse action
         browse_action = create_action(self, "browse", None,
-                                      get_std_icon('DirOpenIcon'),
+                                      ima.icon('DirOpenIcon'),
                                       _('Browse a working directory'),
                                       triggered=self.select_directory)
         self.addAction(browse_action)
         
         # Set current console working directory action
-        setwd_action = create_action(self, icon=get_icon('set_workdir.png'),
+        setwd_action = create_action(self, icon=ima.icon('set_workdir'),
                                      text=_("Set as current console's "
                                                   "working directory"),
                                      triggered=self.set_as_current_console_wd)
@@ -217,7 +227,7 @@ class WorkingDirectory(QToolBar, SpyderPluginMixin):
         
         # Parent dir action
         parent_action = create_action(self, "parent", None,
-                                      get_icon('up.png'),
+                                      ima.icon('up'),
                                       _('Change to parent directory'),
                                       triggered=self.parent_directory)
         self.addAction(parent_action)
@@ -229,7 +239,7 @@ class WorkingDirectory(QToolBar, SpyderPluginMixin):
     
     def get_plugin_icon(self):
         """Return widget icon"""
-        return get_std_icon('DirOpenIcon')
+        return ima.icon('DirOpenIcon')
         
     def get_plugin_actions(self):
         """Setup actions"""
@@ -237,10 +247,10 @@ class WorkingDirectory(QToolBar, SpyderPluginMixin):
     
     def register_plugin(self):
         """Register plugin in Spyder's main window"""
-        self.connect(self, SIGNAL('redirect_stdio(bool)'),
-                     self.main.redirect_internalshell_stdio)
-        self.connect(self.main.console.shell, SIGNAL("refresh()"),
-                     self.refresh_plugin)
+        self.redirect_stdio.connect(self.main.redirect_internalshell_stdio)
+        self.main.console.shell.refresh.connect(self.refresh_plugin)
+        iconsize = 24 
+        self.setIconSize(QSize(iconsize, iconsize))
         self.main.addToolBar(self)
         
     def refresh_plugin(self):
@@ -248,11 +258,10 @@ class WorkingDirectory(QToolBar, SpyderPluginMixin):
         curdir = getcwd()
         self.pathedit.add_text(curdir)
         self.save_wdhistory()
-        self.emit(SIGNAL("set_previous_enabled(bool)"),
-                  self.histindex is not None and self.histindex > 0)
-        self.emit(SIGNAL("set_next_enabled(bool)"),
-                  self.histindex is not None and \
-                  self.histindex < len(self.history)-1)
+        self.set_previous_enabled.emit(
+                             self.histindex is not None and self.histindex > 0)
+        self.set_next_enabled.emit(self.histindex is not None and \
+                                   self.histindex < len(self.history)-1)
 
     def apply_plugin_settings(self, options):
         """Apply configuration file's plugin settings"""
@@ -279,26 +288,30 @@ class WorkingDirectory(QToolBar, SpyderPluginMixin):
         text = [ to_text_string( self.pathedit.itemText(index) ) \
                  for index in range(self.pathedit.count()) ]
         encoding.writelines(text, self.LOG_PATH)
-        
+    
+    @Slot()
     def select_directory(self):
         """Select directory"""
-        self.emit(SIGNAL('redirect_stdio(bool)'), False)
+        self.redirect_stdio.emit(False)
         directory = getexistingdirectory(self.main, _("Select directory"),
                                          getcwd())
         if directory:
             self.chdir(directory)
-        self.emit(SIGNAL('redirect_stdio(bool)'), True)
-        
+        self.redirect_stdio.emit(True)
+    
+    @Slot()
     def previous_directory(self):
         """Back to previous directory"""
         self.histindex -= 1
         self.chdir(browsing_history=True)
-        
+    
+    @Slot()
     def next_directory(self):
         """Return to next directory"""
         self.histindex += 1
         self.chdir(browsing_history=True)
-        
+    
+    @Slot()
     def parent_directory(self):
         """Change working directory to parent directory"""
         self.chdir(os.path.join(getcwd(), os.path.pardir))
@@ -325,9 +338,10 @@ class WorkingDirectory(QToolBar, SpyderPluginMixin):
         os.chdir( to_text_string(directory) )
         self.refresh_plugin()
         if refresh_explorer:
-            self.emit(SIGNAL("set_explorer_cwd(QString)"), directory)
-        self.emit(SIGNAL("refresh_findinfiles()"))
-        
+            self.set_explorer_cwd.emit(directory)
+        self.refresh_findinfiles.emit()
+    
+    @Slot()
     def set_as_current_console_wd(self):
         """Set as current console working directory"""
-        self.emit(SIGNAL("set_current_console_wd(QString)"), getcwd())
+        self.set_current_console_wd.emit(getcwd())
diff --git a/spyderlib/py3compat.py b/spyderlib/py3compat.py
index a7f9550..ba5b918 100644
--- a/spyderlib/py3compat.py
+++ b/spyderlib/py3compat.py
@@ -18,12 +18,13 @@ This module should be fully compatible with:
 
 from __future__ import print_function
 
-import sys
+import operator
 import os
+import sys
 
 PY2 = sys.version[0] == '2'
 PY3 = sys.version[0] == '3'
-
+PY33 = sys.version_info[0:2] >= (3, 3)
 
 #==============================================================================
 # Data types
@@ -243,6 +244,46 @@ def qbytearray_to_str(qba):
     """Convert QByteArray object to str in a way compatible with Python 2/3"""
     return str(bytes(qba.toHex().data()).decode())
 
+# =============================================================================
+# Dict funcs
+# =============================================================================
+if PY3:
+    def iterkeys(d, **kw):
+        return iter(d.keys(**kw))
+
+    def itervalues(d, **kw):
+        return iter(d.values(**kw))
+
+    def iteritems(d, **kw):
+        return iter(d.items(**kw))
+
+    def iterlists(d, **kw):
+        return iter(d.lists(**kw))
+
+    viewkeys = operator.methodcaller("keys")
+
+    viewvalues = operator.methodcaller("values")
+
+    viewitems = operator.methodcaller("items")
+else:
+    def iterkeys(d, **kw):
+        return d.iterkeys(**kw)
+
+    def itervalues(d, **kw):
+        return d.itervalues(**kw)
+
+    def iteritems(d, **kw):
+        return d.iteritems(**kw)
+
+    def iterlists(d, **kw):
+        return d.iterlists(**kw)
+
+    viewkeys = operator.methodcaller("viewkeys")
+
+    viewvalues = operator.methodcaller("viewvalues")
+
+    viewitems = operator.methodcaller("viewitems")
+
 
 if __name__ == '__main__':
     pass
diff --git a/spyderlib/pygments_patch.py b/spyderlib/pygments_patch.py
deleted file mode 100644
index 6ff994b..0000000
--- a/spyderlib/pygments_patch.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright © 2014 The Spyder development team
-# Licensed under the terms of the MIT License
-# (see spyderlib/__init__.py for details)
-
-"""
-Patching pygments to avoid errors with IPython console
-"""
-
-def apply():
-    """
-    Monkey patching pygments
-    See Issue 2042 and https://github.com/ipython/ipython/pull/6878
-    """
-    from spyderlib.utils.programs import is_module_installed
-    if is_module_installed('pygments', '<2.0') and \
-      is_module_installed('IPython', '>3.0'):
-          return
-    
-    # Patching IPython's patch of RegLexer (Oh God!!)
-    from pygments.lexer import _TokenType, Text, Error
-    from spyderlib.py3compat import to_text_string
-    try:
-        from IPython.qt.console.pygments_highlighter import RegexLexer
-    except ImportError:
-        from IPython.frontend.qt.console.pygments_highlighter import RegexLexer
-    def get_tokens_unprocessed(self, text, stack=('root',)):
-        pos = 0
-        tokendefs = self._tokens
-        if hasattr(self, '_saved_state_stack'):
-            statestack = list(self._saved_state_stack)
-        else:
-            statestack = list(stack)
-        statetokens = tokendefs[statestack[-1]]
-        while 1:
-            for rexmatch, action, new_state in statetokens:
-                m = rexmatch(text, pos)
-                if m:
-                    if action is not None:
-                        if type(action) is _TokenType:
-                            yield pos, action, m.group()
-                        else:
-                            for item in action(self, m):
-                                yield item
-                    pos = m.end()
-                    if new_state is not None:
-                        # state transition
-                        if isinstance(new_state, tuple):
-                            for state in new_state:
-                                if state == '#pop':
-                                    statestack.pop()
-                                elif state == '#push':
-                                    statestack.append(statestack[-1])
-                                else:
-                                    statestack.append(state)
-                        elif isinstance(new_state, int):
-                            # pop
-                            del statestack[new_state:]
-                        elif new_state == '#push':
-                            statestack.append(statestack[-1])
-                        else:
-                            assert False, "wrong state def: %r" % new_state
-                        statetokens = tokendefs[statestack[-1]]
-                    break
-            else:
-                try:
-                    if text[pos] == '\n':
-                        # at EOL, reset state to "root"
-                        pos += 1
-                        statestack = ['root']
-                        statetokens = tokendefs['root']
-                        yield pos, Text, to_text_string('\n')
-                        continue
-                    yield pos, Error, text[pos]
-                    pos += 1
-                except IndexError:
-                    break
-        self._saved_state_stack = list(statestack)
-
-    RegexLexer.get_tokens_unprocessed = get_tokens_unprocessed
diff --git a/spyderlib/pyplot.py b/spyderlib/pyplot.py
index 64696c3..affd277 100644
--- a/spyderlib/pyplot.py
+++ b/spyderlib/pyplot.py
@@ -5,5 +5,5 @@ Importing guiqwt's pyplot module or matplotlib's pyplot
 
 try:
     from guiqwt.pyplot import *
-except ImportError:
+except (ImportError, AssertionError):
     from matplotlib.pyplot import *
diff --git a/spyderlib/qt/QtCore.py b/spyderlib/qt/QtCore.py
index c4c1f6f..c1989af 100644
--- a/spyderlib/qt/QtCore.py
+++ b/spyderlib/qt/QtCore.py
@@ -6,15 +6,26 @@
 
 import os
 
-if os.environ['QT_API'] == 'pyqt':
-    from PyQt4.QtCore import *  # analysis:ignore
-    from PyQt4.QtCore import QCoreApplication  # analysis:ignore
-    from PyQt4.QtCore import Qt  # analysis:ignore
-    from PyQt4.QtCore import pyqtSignal as Signal  # analysis:ignore
-    from PyQt4.QtCore import pyqtSlot as Slot  # analysis:ignore
-    from PyQt4.QtCore import pyqtProperty as Property  # analysis:ignore
-    from PyQt4.QtCore import QT_VERSION_STR as __version__
+if os.environ['QT_API'] == 'pyqt5':
+    from PyQt5.QtCore import *                                # analysis:ignore
+    from PyQt5.QtCore import QCoreApplication
+    from PyQt5.QtCore import pyqtSignal as Signal
+    from PyQt5.QtCore import pyqtSlot as Slot
+    from PyQt5.QtCore import pyqtProperty as Property
+    from PyQt5.QtCore import QT_VERSION_STR as __version__
+elif os.environ['QT_API'] == 'pyqt':
+    from PyQt4.QtCore import *                                # analysis:ignore
+    from PyQt4.QtCore import QCoreApplication                 # analysis:ignore
+    from PyQt4.QtCore import Qt                               # analysis:ignore
+    from PyQt4.QtCore import pyqtSignal as Signal             # analysis:ignore
+    from PyQt4.QtCore import pyqtSlot as Slot                 # analysis:ignore
+    from PyQt4.QtCore import pyqtProperty as Property         # analysis:ignore
+    from PyQt4.QtCore import QT_VERSION_STR as __version__    # analysis:ignore
+
+    from PyQt4.QtGui import QItemSelection, QItemSelectionRange  # analysis:ignore
 else:
     import PySide.QtCore
-    __version__ = PySide.QtCore.__version__  # analysis:ignore
-    from PySide.QtCore import *  # analysis:ignore
+    __version__ = PySide.QtCore.__version__                   # analysis:ignore
+    from PySide.QtCore import *                               # analysis:ignore
+
+    from PySide.QtGui import QItemSelection, QItemSelectionRange  # analysis:ignore
diff --git a/spyderlib/qt/QtGui.py b/spyderlib/qt/QtGui.py
index 2eae128..17dd18d 100644
--- a/spyderlib/qt/QtGui.py
+++ b/spyderlib/qt/QtGui.py
@@ -6,8 +6,19 @@
 
 import os
 
-if os.environ['QT_API'] == 'pyqt':
-    from PyQt4.Qt import QKeySequence, QTextCursor  # analysis:ignore
-    from PyQt4.QtGui import *  # analysis:ignore
+if os.environ['QT_API'] == 'pyqt5':
+    from PyQt5.QtCore import QSortFilterProxyModel            # analysis:ignore
+    from PyQt5.QtPrintSupport import (QPrinter, QPrintDialog, # analysis:ignore
+                                      QAbstractPrintDialog)
+    from PyQt5.QtPrintSupport import QPrintPreviewDialog      # analysis:ignore
+    from PyQt5.QtGui import *                                 # analysis:ignore
+    from PyQt5.QtWidgets import *                             # analysis:ignore
+elif os.environ['QT_API'] == 'pyqt':
+    from PyQt4.Qt import QKeySequence, QTextCursor            # analysis:ignore
+    from PyQt4.QtGui import *                                 # analysis:ignore
+    QStyleOptionViewItem = QStyleOptionViewItemV4             # analysis:ignore
+    del QItemSelection, QItemSelectionRange                   # analysis:ignore
 else:
-    from PySide.QtGui import *  # analysis:ignore
+    from PySide.QtGui import *                                # analysis:ignore
+    QStyleOptionViewItem = QStyleOptionViewItemV4             # analysis:ignore
+    del QItemSelection, QItemSelectionRange                   # analysis:ignore
diff --git a/spyderlib/qt/QtNetwork.py b/spyderlib/qt/QtNetwork.py
new file mode 100644
index 0000000..763c8f6
--- /dev/null
+++ b/spyderlib/qt/QtNetwork.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2011 Pierre Raybaut
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+import os
+
+if os.environ['QT_API'] == 'pyqt5':
+    from PyQt5.QtNetwork import *  # analysis:ignore
+elif os.environ['QT_API'] == 'pyqt':
+    from PyQt4.QtNetwork import *  # analysis:ignore
+else:
+    from PySide.QtNetwork import *  # analysis:ignore
diff --git a/spyderlib/qt/QtSvg.py b/spyderlib/qt/QtSvg.py
index 46d5a48..f4443b6 100644
--- a/spyderlib/qt/QtSvg.py
+++ b/spyderlib/qt/QtSvg.py
@@ -6,7 +6,9 @@
 
 import os
 
-if os.environ['QT_API'] == 'pyqt':
-    from PyQt4.QtSvg import *  # analysis:ignore
+if os.environ['QT_API'] == 'pyqt5':
+    from PyQt5.QtSvg import *                                 # analysis:ignore
+elif os.environ['QT_API'] == 'pyqt':
+    from PyQt4.QtSvg import *                                 # analysis:ignore
 else:
-    from PySide.QtSvg import *  # analysis:ignore
\ No newline at end of file
+    from PySide.QtSvg import *                                # analysis:ignore
diff --git a/spyderlib/qt/QtWebKit.py b/spyderlib/qt/QtWebKit.py
index 3f133d8..60c6dca 100644
--- a/spyderlib/qt/QtWebKit.py
+++ b/spyderlib/qt/QtWebKit.py
@@ -6,7 +6,11 @@
 
 import os
 
-if os.environ['QT_API'] == 'pyqt':
-    from PyQt4.QtWebKit import *  # analysis:ignore
+if os.environ['QT_API'] == 'pyqt5':
+    from PyQt5.QtWebKitWidgets import QWebPage, QWebView      # analysis:ignore
+    from PyQt5.QtWebKit import QWebSettings                   # analysis:ignore
+elif os.environ['QT_API'] == 'pyqt':
+    from PyQt4.QtWebKit import (QWebPage, QWebView,           # analysis:ignore
+                                QWebSettings)
 else:
-    from PySide.QtWebKit import *  # analysis:ignore
\ No newline at end of file
+    from PySide.QtWebKit import *                             # analysis:ignore
diff --git a/spyderlib/qt/__init__.py b/spyderlib/qt/__init__.py
index c6851a1..c1ec94a 100644
--- a/spyderlib/qt/__init__.py
+++ b/spyderlib/qt/__init__.py
@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2011 Pierre Raybaut
+# Copyright © 2011-2012 Pierre Raybaut
+#           © 2012-2014 anatoly techtonik
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -9,13 +10,15 @@
 import os
 
 os.environ.setdefault('QT_API', 'pyqt')
-assert os.environ['QT_API'] in ('pyqt', 'pyside')
+assert os.environ['QT_API'] in ('pyqt5', 'pyqt', 'pyside')
 
 API = os.environ['QT_API']
-API_NAME = {'pyqt': 'PyQt4', 'pyside': 'PySide'}[API]
+API_NAME = {'pyqt5': 'PyQt5', 'pyqt': 'PyQt4', 'pyside': 'PySide'}[API]
 
 if API == 'pyqt':
-    # Since Spyder 2.3.6 we only support API #2
+    # Spyder 2.3 is compatible with both #1 and #2 PyQt API,
+    # but to avoid issues with IPython and other Qt plugins
+    # we choose to support only API #2 for 2.4+
     try:
         import sip
         try:
@@ -27,13 +30,22 @@ if API == 'pyqt':
             sip.setapi('QTime', 2)
             sip.setapi('QUrl', 2)
         except AttributeError:
+            # PyQt < v4.6. The actual check is done by requirements.check_qt()
+            # call from spyder.py
             pass
-        
-        from PyQt4.QtCore import PYQT_VERSION_STR as __version__
-    except ImportError: # May fail on sip or on PyQt4 import
-        # Switching to PySide
-        API = os.environ['QT_API'] = 'pyside'
-        API_NAME = 'PySide'
+
+        from PyQt4.QtCore import PYQT_VERSION_STR as __version__ # analysis:ignore
+    except ImportError:
+        # Trying PyQt5 before switching to PySide (at this point, PyQt4 may 
+        # not be installed but PyQt5 or Pyside could still be if the QT_API 
+        # environment variable hasn't been set-up)
+        try:
+            import PyQt5  # analysis:ignore
+            API = os.environ['QT_API'] = 'pyqt5'
+            API_NAME = 'PyQt5'
+        except ImportError:
+            API = os.environ['QT_API'] = 'pyside'
+            API_NAME = 'PySide'
     else:
         is_old_pyqt = __version__.startswith(('4.4', '4.5', '4.6', '4.7'))
         is_pyqt46 = __version__.startswith('4.6')
@@ -42,6 +54,17 @@ if API == 'pyqt':
             API_NAME += (" (API v%d)" % sip.getapi('QString'))
         except AttributeError:
             pass
+        from PyQt4 import uic  # analysis:ignore
+
+PYQT5 = False
+if API == 'pyqt5':
+    try:
+        from PyQt5.QtCore import PYQT_VERSION_STR as __version__
+        from PyQt5 import uic  # analysis:ignore
+        PYQT5 = True
+        is_old_pyqt = is_pyqt46 = False
+    except ImportError:
+        pass
 
 if API == 'pyside':
     try:
diff --git a/spyderlib/requirements.py b/spyderlib/requirements.py
index a74392f..6ab9e6b 100644
--- a/spyderlib/requirements.py
+++ b/spyderlib/requirements.py
@@ -35,7 +35,8 @@ def check_path():
 
 def check_qt():
     """Check Qt binding requirements"""
-    qt_infos = dict(pyqt=("PyQt4", "4.6"), pyside=("PySide", "1.2.0"))
+    qt_infos = dict(pyqt5=("PyQt5", "5.2"), pyqt=("PyQt4", "4.6"),
+                    pyside=("PySide", "1.2.0"))
     try:
         from spyderlib import qt
         package_name, required_ver = qt_infos[qt.API]
@@ -45,6 +46,10 @@ def check_qt():
                          "%s %s+ is required (found v%s)."
                          % (package_name, required_ver, actual_ver))
     except ImportError:
-        show_warning("Please check Spyder installation requirements:\n"
-                     "%s %s+ (or %s %s+) is required."
-                     % (qt_infos['pyqt']+qt_infos['pyside']))
+        show_warning("Please check Spyder installation requirements:\n\n"
+                     "%s %s+ or\n"
+                     "%s %s+ or\n"
+                     "%s %s+\n\n"
+                     "is required to run Spyder"
+                     % (qt_infos['pyqt'] + qt_infos['pyside'] + \
+                        qt_infos['pyqt5']))
diff --git a/spyderlib/restart_app.py b/spyderlib/restart_app.py
new file mode 100644
index 0000000..ad38e9d
--- /dev/null
+++ b/spyderlib/restart_app.py
@@ -0,0 +1,274 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2015 The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+"""
+Restart Spyder
+
+A helper script that allows to restart (and also reset) Spyder from within the
+running application.
+"""
+
+import ast
+import os
+import os.path as osp
+import subprocess
+import sys
+import time
+
+
+from spyderlib.config.base import _, get_image_path
+from spyderlib.py3compat import to_text_string
+from spyderlib.qt.QtCore import Qt, QTimer
+from spyderlib.qt.QtGui import (QColor, QMessageBox, QPixmap, QSplashScreen,
+                                QWidget, QApplication)
+from spyderlib.utils import icon_manager as ima
+from spyderlib.utils.qthelpers import qapplication
+
+PY2 = sys.version[0] == '2'
+IS_WINDOWS = os.name == 'nt'
+SLEEP_TIME = 0.2  # Seconds for throttling control
+CLOSE_ERROR, RESET_ERROR, RESTART_ERROR = [1, 2, 3]  # Spyder error codes
+
+
+def _is_pid_running_on_windows(pid):
+    """Check if a process is running on windows systems based on the pid."""
+    pid = str(pid)
+
+    # Hide flashing command prompt
+    startupinfo = subprocess.STARTUPINFO()
+    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+
+    process = subprocess.Popen(r'tasklist /fi "PID eq {0}"'.format(pid),
+                               stdout=subprocess.PIPE,
+                               stderr=subprocess.STDOUT,
+                               startupinfo=startupinfo)
+    stdoutdata, stderrdata = process.communicate()
+    stdoutdata = to_text_string(stdoutdata)
+    process.kill()
+    check = pid in stdoutdata
+
+    return check
+
+
+def _is_pid_running_on_unix(pid):
+    """Check if a process is running on unix systems based on the pid."""
+    try:
+        # On unix systems os.kill with a 0 as second argument only pokes the
+        # process (if it exists) and does not kill it
+        os.kill(pid, 0)
+    except OSError:
+        return False
+    else:
+        return True
+
+
+def is_pid_running(pid):
+    """Check if a process is running based on the pid."""
+    # Select the correct function depending on the OS
+    if os.name == 'nt':
+        return _is_pid_running_on_windows(pid)
+    else:
+        return _is_pid_running_on_unix(pid)
+
+
+class Restarter(QWidget):
+    """Widget in charge of displaying the splash information screen and the
+       error messages.
+    """
+    def __init__(self):
+        super(Restarter, self).__init__()
+        self.ellipsis = ['', '.', '..', '...', '..', '.']
+
+        # Widgets
+        self.timer_ellipsis = QTimer(self)
+        self.splash = QSplashScreen(QPixmap(get_image_path('splash.png'),
+                                    'png'))
+
+        # Widget setup
+        self.setVisible(False)
+
+        font = self.splash.font()
+        font.setPixelSize(10)
+        self.splash.setFont(font)
+        self.splash.show()
+
+        self.timer_ellipsis.timeout.connect(self.animate_ellipsis)
+
+    def _show_message(self, text):
+        """Show message on splash screen."""
+        self.splash.showMessage(text, Qt.AlignBottom | Qt.AlignCenter |
+                                Qt.AlignAbsolute, QColor(Qt.white))
+
+    def animate_ellipsis(self):
+        """Animate dots at the end of the splash screen message."""
+        ellipsis = self.ellipsis.pop(0)
+        text = ' '*len(ellipsis) + self.splash_text + ellipsis
+        self.ellipsis.append(ellipsis)
+        self._show_message(text)
+
+    def set_splash_message(self, text):
+        """Sets the text in the bottom of the Splash screen."""
+        self.splash_text = text
+        self._show_message(text)
+        self.timer_ellipsis.start(500)
+
+    def launch_error_message(self, error_type, error=None):
+        """Launch a message box with a predefined error message.
+
+        Parameters
+        ----------
+        error_type : int [CLOSE_ERROR, RESET_ERROR, RESTART_ERROR]
+            Possible error codes when restarting/reseting spyder.
+        error : Exception
+            Actual Python exception error caught.
+        """
+        messages = {CLOSE_ERROR: _("It was not possible to close the previous "
+                                   "Spyder instance.\nRestart aborted."),
+                    RESET_ERROR: _("Spyder could not reset to factory "
+                                   "defaults.\nRestart aborted."),
+                    RESTART_ERROR: _("It was not possible to restart Spyder.\n"
+                                     "Operation aborted.")}
+        titles = {CLOSE_ERROR: _("Spyder exit error"),
+                  RESET_ERROR: _("Spyder reset error"),
+                  RESTART_ERROR: _("Spyder restart error")}
+
+        if error:
+            e = error.__repr__()
+            message = messages[error_type] + _("\n\n{0}").format(e)
+        else:
+            message = messages[error_type]
+
+        title = titles[error_type]
+        self.splash.hide()
+        QMessageBox.warning(self, title, message, QMessageBox.Ok)
+        raise RuntimeError(message)
+
+
+def main():
+    # Splash screen
+    # -------------------------------------------------------------------------
+    # Start Qt Splash to inform the user of the current status
+    app = qapplication()
+    restarter = Restarter()
+    resample = not IS_WINDOWS
+    # Resampling SVG icon only on non-Windows platforms (see Issue 1314):
+    icon = ima.icon('spyder', resample=resample)
+    app.setWindowIcon(icon)
+    restarter.set_splash_message(_('Closing Spyder'))
+
+    # Get variables
+    # Note: Variables defined in spyderlib\spyder.py 'restart()' method
+    spyder_args = os.environ.pop('SPYDER_ARGS', None)
+    pid = os.environ.pop('SPYDER_PID', None)
+    is_bootstrap = os.environ.pop('SPYDER_IS_BOOTSTRAP', None)
+    reset = os.environ.pop('SPYDER_RESET', None)
+
+    # Get the spyder base folder based on this file
+    spyder_folder = osp.split(osp.dirname(osp.abspath(__file__)))[0]
+
+    if not any([spyder_args, pid, is_bootstrap, reset]):
+        error = "This script can only be called from within a Spyder instance"
+        raise RuntimeError(error)
+
+    # Variables were stored as string literals in the environment, so to use
+    # them we need to parse them in a safe manner.
+    is_bootstrap = ast.literal_eval(is_bootstrap)
+    pid = ast.literal_eval(pid)
+    args = ast.literal_eval(spyder_args)
+    reset = ast.literal_eval(reset)
+
+    # Enforce the --new-instance flag when running spyder
+    if '--new-instance' not in args:
+        if is_bootstrap and '--' not in args:
+            args = args + ['--', '--new-instance']
+        else:
+            args.append('--new-instance')
+
+    # Create the arguments needed for reseting
+    if '--' in args:
+        args_reset = ['--', '--reset']
+    else:
+        args_reset = ['--reset']
+
+    # Arrange arguments to be passed to the restarter and reset subprocess
+    args = ' '.join(args)
+    args_reset = ' '.join(args_reset)
+
+    # Get python excutable running this script
+    python = sys.executable
+
+    # Build the command
+    if is_bootstrap:
+        spyder = osp.join(spyder_folder, 'bootstrap.py')
+    else:
+        spyderlib = osp.join(spyder_folder, 'spyderlib')
+        spyder = osp.join(spyderlib, 'start_app.py')
+
+    command = '"{0}" "{1}" {2}'.format(python, spyder, args)
+
+    # Adjust the command and/or arguments to subprocess depending on the OS
+    shell = not IS_WINDOWS
+
+    # Before launching a new Spyder instance we need to make sure that the
+    # previous one has closed. We wait for a fixed and "reasonable" amount of
+    # time and check, otherwise an error is launched
+    wait_time = 90 if IS_WINDOWS else 30  # Seconds
+    for counter in range(int(wait_time/SLEEP_TIME)):
+        if not is_pid_running(pid):
+            break
+        time.sleep(SLEEP_TIME)  # Throttling control
+        QApplication.processEvents()  # Needed to refresh the splash
+    else:
+        # The old spyder instance took too long to close and restart aborts
+        restarter.launch_error_message(error_type=CLOSE_ERROR)
+
+    env = os.environ.copy()
+
+    # Reset Spyder (if required)
+    # -------------------------------------------------------------------------
+    if reset:
+        restarter.set_splash_message(_('Resetting Spyder to defaults'))
+        command_reset = '"{0}" "{1}" {2}'.format(python, spyder, args_reset)
+
+        try:
+            p = subprocess.Popen(command_reset, shell=shell, env=env)
+        except Exception as error:
+            restarter.launch_error_message(error_type=RESET_ERROR, error=error)
+        else:
+            p.communicate()
+            pid_reset = p.pid
+
+        # Before launching a new Spyder instance we need to make sure that the
+        # reset subprocess has closed. We wait for a fixed and "reasonable"
+        # amount of time and check, otherwise an error is launched.
+        wait_time = 20  # Seconds
+        for counter in range(int(wait_time/SLEEP_TIME)):
+            if not is_pid_running(pid_reset):
+                break
+            time.sleep(SLEEP_TIME)  # Throttling control
+            QApplication.processEvents()  # Needed to refresh the splash
+        else:
+            # The reset subprocess took too long and it is killed
+            try:
+                p.kill()
+            except OSError as error:
+                restarter.launch_error_message(error_type=RESET_ERROR,
+                                               error=error)
+            else:
+                restarter.launch_error_message(error_type=RESET_ERROR)
+
+    # Restart
+    # -------------------------------------------------------------------------
+    restarter.set_splash_message(_('Restarting'))
+    try:
+        subprocess.Popen(command, shell=shell, env=env)
+    except Exception as error:
+        restarter.launch_error_message(error_type=RESTART_ERROR, error=error)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/spyderlib/rope_patch.py b/spyderlib/rope_patch.py
index ec56dfa..f6c31db 100644
--- a/spyderlib/rope_patch.py
+++ b/spyderlib/rope_patch.py
@@ -29,21 +29,22 @@ Patching rope:
 
 def apply():
     """Monkey patching rope
-    
+
     See [1], [2], [3], [4] and [5] in module docstring."""
-    import rope
-    if rope.VERSION not in ('0.10.2', '0.9.4-1', '0.9.4', '0.9.3', '0.9.2'):
+    from spyderlib.utils.programs import is_module_installed
+    if is_module_installed('rope', '<0.9.4'):
+        import rope
         raise ImportError("rope %s can't be patched" % rope.VERSION)
-    
+
     # [1] Patching project.Project for compatibility with py2exe/cx_Freeze
     #     distributions
-    from spyderlib.baseconfig import is_py2exe_or_cx_Freeze
+    from spyderlib.config.base import is_py2exe_or_cx_Freeze
     if is_py2exe_or_cx_Freeze():
         from rope.base import project
         class PatchedProject(project.Project):
             def _default_config(self):
                 # py2exe/cx_Freeze distribution
-                from spyderlib.baseconfig import get_module_source_path
+                from spyderlib.config.base import get_module_source_path
                 fname = get_module_source_path('spyderlib',
                                                'default_config.py')
                 return open(fname, 'rb').read()
diff --git a/spyderlib/scientific_startup.py b/spyderlib/scientific_startup.py
index 261dd96..cca5661 100644
--- a/spyderlib/scientific_startup.py
+++ b/spyderlib/scientific_startup.py
@@ -80,7 +80,7 @@ if os.environ.get('QT_API') != 'pyside':
         plt_.ion()
         exec_print("+ guidata %s, guiqwt %s" % (guidata.__version__,
                                            guiqwt.__version__))
-    except ImportError:
+    except (ImportError, AssertionError):
         exec_print()
 
 #==============================================================================
diff --git a/spyderlib/spyder.py b/spyderlib/spyder.py
index 86b6609..0c8f882 100644
--- a/spyderlib/spyder.py
+++ b/spyderlib/spyder.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2013 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -11,8 +11,7 @@ Spyder, the Scientific PYthon Development EnviRonment
 Developped and maintained by the Spyder Development
 Team
 
-Copyright © 2009 - 2015 Pierre Raybaut
-Copyright © 2010 - 2015 The Spyder Development Team
+Copyright © 2009- The Spyder Development Team
 Licensed under the terms of the MIT License
 (see spyderlib/__init__.py for details)
 """
@@ -30,8 +29,10 @@ import os.path as osp
 import re
 import socket
 import shutil
+import subprocess
 import sys
 import threading
+import traceback
 
 
 #==============================================================================
@@ -49,7 +50,7 @@ requirements.check_qt()
 
 
 #==============================================================================
-# Windows platforms only: support for hiding the attached console window
+# Windows only: support for hiding console window when started with python.exe
 #==============================================================================
 set_attached_console_visible = None
 is_attached_console_visible = None
@@ -85,21 +86,23 @@ except:
 #==============================================================================
 # Qt imports
 #==============================================================================
+from spyderlib.qt import PYQT5
 from spyderlib.qt.QtGui import (QApplication, QMainWindow, QSplashScreen,
                                 QPixmap, QMessageBox, QMenu, QColor, QShortcut,
                                 QKeySequence, QDockWidget, QAction,
                                 QDesktopServices, QStyleFactory)
-from spyderlib.qt.QtCore import (SIGNAL, QPoint, Qt, QSize, QByteArray, QUrl,
-                                 QCoreApplication)
+from spyderlib.qt.QtCore import (Signal, QPoint, Qt, QSize, QByteArray, QUrl,
+                                 Slot, QTimer, QCoreApplication, QThread)
 from spyderlib.qt.compat import (from_qvariant, getopenfilename,
                                  getsavefilename)
-# Avoid a "Cannot mix incompatible Qt library" error on Windows platforms 
-# when PySide is selected by the QT_API environment variable and when PyQt4 
+# Avoid a "Cannot mix incompatible Qt library" error on Windows platforms
+# when PySide is selected by the QT_API environment variable and when PyQt4
 # is also installed (or any other Qt-based application prepending a directory
 # containing incompatible Qt DLLs versions in PATH):
 from spyderlib.qt import QtSvg  # analysis:ignore
 
 
+
 #==============================================================================
 # Create our QApplication instance here because it's needed to render the
 # splash screen created below
@@ -111,13 +114,13 @@ MAIN_APP = qapplication()
 #==============================================================================
 # Create splash screen out of MainWindow to reduce perceived startup time. 
 #==============================================================================
-from spyderlib.baseconfig import _, get_image_path
+from spyderlib.config.base import _, get_image_path, DEV
 SPLASH = QSplashScreen(QPixmap(get_image_path('splash.png'), 'png'))
 SPLASH_FONT = SPLASH.font()
 SPLASH_FONT.setPixelSize(10)
 SPLASH.setFont(SPLASH_FONT)
 SPLASH.show()
-SPLASH.showMessage(_("Initializing..."), Qt.AlignBottom | Qt.AlignCenter | 
+SPLASH.showMessage(_("Initializing..."), Qt.AlignBottom | Qt.AlignCenter |
                    Qt.AlignAbsolute, QColor(Qt.white))
 QApplication.processEvents()
 
@@ -125,17 +128,18 @@ QApplication.processEvents()
 #==============================================================================
 # Local utility imports
 #==============================================================================
+import spyderlib.utils.icon_manager as ima
 from spyderlib import __version__, __project_url__, __forum_url__, get_versions
-from spyderlib.baseconfig import (get_conf_path, get_module_data_path,
-                                  get_module_source_path, STDERR, DEBUG, DEV,
-                                  debug_print, TEST, SUBFOLDER, MAC_APP_NAME,
-                                  running_in_mac_app)
-from spyderlib.config import (CONF, EDIT_EXT, IMPORT_EXT, OPEN_FILES_PORT,
-                              is_gtk_desktop)
+from spyderlib.config.base import (get_conf_path, get_module_data_path,
+                                   get_module_source_path, STDERR, DEBUG,
+                                   debug_print, TEST, SUBFOLDER, MAC_APP_NAME,
+                                   running_in_mac_app, get_module_path)
+from spyderlib.config.main import (CONF, EDIT_EXT, IMPORT_EXT, OPEN_FILES_PORT,
+                                   is_gtk_desktop)
 from spyderlib.cli_options import get_options
 from spyderlib import dependencies
-from spyderlib.ipythonconfig import IPYTHON_QT_INSTALLED
-from spyderlib.userconfig import NoDefault
+from spyderlib.config.ipython import IPYTHON_QT_INSTALLED
+from spyderlib.config.user import NoDefault
 from spyderlib.utils import encoding, programs
 from spyderlib.utils.iofuncs import load_session, save_session, reset_session
 from spyderlib.utils.programs import is_module_installed
@@ -155,16 +159,16 @@ try:
     from spyderlib.utils.environ import WinUserEnvDialog
 except ImportError:
     WinUserEnvDialog = None  # analysis:ignore
-    
+
 from spyderlib.utils.qthelpers import (create_action, add_actions, get_icon,
-                                       get_std_icon, add_shortcut_to_tooltip,
+                                       add_shortcut_to_tooltip,
                                        create_module_bookmark_actions,
-                                       create_bookmark_action,
                                        create_program_action, DialogManager,
                                        keybinding, create_python_script_action,
                                        file_uri)
-from spyderlib.guiconfig import get_shortcut, remove_deprecated_shortcuts
+from spyderlib.config.gui import get_shortcut, remove_deprecated_shortcuts
 from spyderlib.otherplugins import get_spyderplugins_mods
+from spyderlib import tour # FIXME: Better place for this?
 
 
 #==============================================================================
@@ -193,7 +197,7 @@ def get_python_doc_path():
         if not osp.isdir(doc_path):
             return
         python_chm = [path for path in os.listdir(doc_path)
-                      if re.match(r"(?i)Python[0-9]{3}.chm", path)]
+                      if re.match(r"(?i)Python[0-9]{3,6}.chm", path)]
         if python_chm:
             return file_uri(osp.join(doc_path, python_chm[0]))
     else:
@@ -255,21 +259,31 @@ class MainWindow(QMainWindow):
          ('winpython', "https://winpython.github.io/",
           _("WinPython"))
                 )
-    
+
+    # Signals
+    restore_scrollbar_position = Signal()
+    all_actions_defined = Signal()
+    sig_pythonpath_changed = Signal()
+    sig_open_external_file = Signal(str)
+    sig_resized = Signal("QResizeEvent")  # related to interactive tour
+    sig_moved = Signal("QMoveEvent")      # related to interactive tour
+
     def __init__(self, options=None):
         QMainWindow.__init__(self)
-        
+
         qapp = QApplication.instance()
+        if PYQT5:
+            qapp.setAttribute(Qt.AA_UseHighDpiPixmaps)
         self.default_style = str(qapp.style().objectName())
-        
+
         self.dialog_manager = DialogManager()
-        
+
         self.init_workdir = options.working_directory
         self.profile = options.profile
         self.multithreaded = options.multithreaded
         self.light = options.light
         self.new_instance = options.new_instance
-        
+
         self.debug_print("Start of MainWindow constructor")
 
         # Use a custom Qt stylesheet
@@ -280,7 +294,7 @@ class MainWindow(QMainWindow):
 
         # Shortcut management data
         self.shortcut_data = []
-        
+
         # Loading Spyder path
         self.path = []
         self.project_path = []
@@ -295,16 +309,16 @@ class MainWindow(QMainWindow):
                                         self.load_session(TEMP_SESSION_PATH))
         self.load_session_action = create_action(self,
                                         _("Load session..."),
-                                        None, 'fileopen.png',
+                                        None, ima.icon('fileopen'),
                                         triggered=self.load_session,
                                         tip=_("Load Spyder session"))
         self.save_session_action = create_action(self,
                                         _("Save session and quit..."),
-                                        None, 'filesaveas.png',
+                                        None, ima.icon('filesaveas'),
                                         triggered=self.save_session,
                                         tip=_("Save current session "
                                               "and quit application"))
-        
+
         # Plugins
         self.console = None
         self.workingdirectory = None
@@ -320,7 +334,18 @@ class MainWindow(QMainWindow):
         self.variableexplorer = None
         self.findinfiles = None
         self.thirdparty_plugins = []
-        
+
+        # Tour  # TODO: Should I consider it a plugin?? or?
+        self.tour = None
+        self.tours_available = None
+
+        # Check for updates Thread and Worker, refereces needed to prevent
+        # segfaulting
+        self.check_updates_action = None
+        self.thread_updates = None
+        self.worker_updates = None
+        self.give_updates_feedback = True
+
         # Preferences
         from spyderlib.plugins.configdialog import (MainConfigPage,
                                                     ColorSchemeConfigPage)
@@ -330,8 +355,16 @@ class MainWindow(QMainWindow):
                               ColorSchemeConfigPage, RunConfigPage]
         self.prefs_index = None
         self.prefs_dialog_size = None
-        
+
+        # Quick Layouts and Dialogs
+        from spyderlib.plugins.layoutdialog import (LayoutSaveDialog,
+                                                    LayoutSettingsDialog)
+        self.dialog_layout_save = LayoutSaveDialog
+        self.dialog_layout_settings = LayoutSettingsDialog
+
         # Actions
+        self.lock_dockwidgets_action = None
+        self.show_toolbars_action = None
         self.close_dockwidget_action = None
         self.find_action = None
         self.find_next_action = None
@@ -342,11 +375,10 @@ class MainWindow(QMainWindow):
         self.copy_action = None
         self.cut_action = None
         self.paste_action = None
-        self.delete_action = None
         self.selectall_action = None
         self.maximize_action = None
         self.fullscreen_action = None
-        
+
         # Menu bars
         self.file_menu = None
         self.file_menu_actions = []
@@ -372,12 +404,13 @@ class MainWindow(QMainWindow):
         self.toolbars_menu = None
         self.help_menu = None
         self.help_menu_actions = []
-        
+
         # Status bar widgets
         self.mem_status = None
         self.cpu_status = None
-        
+
         # Toolbars
+        self.visible_toolbars = []
         self.toolbarslist = []
         self.main_toolbar = None
         self.main_toolbar_actions = []
@@ -393,7 +426,10 @@ class MainWindow(QMainWindow):
         self.run_toolbar_actions = []
         self.debug_toolbar = None
         self.debug_toolbar_actions = []
-        
+        self.layout_toolbar = None
+        self.layout_toolbar_actions = []
+
+
         # Set Window title and icon
         if DEV is not None:
             title = "Spyder %s (Python %s.%s)" % (__version__,
@@ -405,136 +441,176 @@ class MainWindow(QMainWindow):
         if DEBUG:
             title += " [DEBUG MODE %d]" % DEBUG
         self.setWindowTitle(title)
-        icon_name = 'spyder_light.svg' if self.light else 'spyder.svg'
+        resample = os.name != 'nt'
+        icon = ima.icon('spyder_light', resample=resample) if self.light\
+          else ima.icon('spyder', resample=resample)
         # Resampling SVG icon only on non-Windows platforms (see Issue 1314):
-        self.setWindowIcon(get_icon(icon_name, resample=os.name != 'nt'))
+        self.setWindowIcon(icon)
         if set_windows_appusermodelid != None:
             res = set_windows_appusermodelid()
             debug_print("appusermodelid: " + str(res))
-        
+
+        # Setting QTimer if running in travis
+        test_travis = os.environ.get('TEST_CI_APP', None)
+        if test_travis is not None:
+            global MAIN_APP
+            timer_shutdown_time = 30000
+            self.timer_shutdown = QTimer(self)
+            self.timer_shutdown.timeout.connect(MAIN_APP.quit)
+            self.timer_shutdown.start(timer_shutdown_time)
+
         # Showing splash screen
         self.splash = SPLASH
         if not self.light:
             if CONF.get('main', 'current_version', '') != __version__:
                 CONF.set('main', 'current_version', __version__)
                 # Execute here the actions to be performed only once after
-                # each update (there is nothing there for now, but it could 
+                # each update (there is nothing there for now, but it could
                 # be useful some day...)
-        
+
         # List of satellite widgets (registered in add_dockwidget):
         self.widgetlist = []
-        
+
         # Flags used if closing() is called by the exit() shell command
         self.already_closed = False
         self.is_starting_up = True
         self.is_setting_up = True
-        
+
+        self.dockwidgets_locked = CONF.get('main', 'panes_locked')
         self.floating_dockwidgets = []
         self.window_size = None
         self.window_position = None
         self.state_before_maximizing = None
         self.current_quick_layout = None
-        self.previous_layout_settings = None
+        self.previous_layout_settings = None  # TODO: related to quick layouts
         self.last_plugin = None
         self.fullscreen_flag = None # isFullscreen does not work as expected
-        # The following flag remember the maximized state even when 
+        # The following flag remember the maximized state even when
         # the window is in fullscreen mode:
         self.maximized_flag = None
-        
+
         # Session manager
         self.next_session_name = None
         self.save_session_name = None
-        
+
         # Track which console plugin type had last focus
         # True: Console plugin
         # False: IPython console plugin
         self.last_console_plugin_focus_was_python = True
-        
+
         # To keep track of the last focused widget
         self.last_focused_widget = None
-        
+
         # Server to open external files on a single instance
         self.open_files_server = socket.socket(socket.AF_INET,
                                                socket.SOCK_STREAM,
                                                socket.IPPROTO_TCP)
-        
+
         self.apply_settings()
         self.debug_print("End of MainWindow constructor")
-    
+
     def debug_print(self, message):
         """Debug prints"""
         debug_print(message)
-        
+
     #---- Window setup
     def create_toolbar(self, title, object_name, iconsize=24):
         """Create and return toolbar with *title* and *object_name*"""
         toolbar = self.addToolBar(title)
         toolbar.setObjectName(object_name)
-        toolbar.setIconSize( QSize(iconsize, iconsize) )
+        toolbar.setIconSize(QSize(iconsize, iconsize))
         self.toolbarslist.append(toolbar)
         return toolbar
-    
+
     def setup(self):
         """Setup main window"""
         self.debug_print("*** Start of MainWindow setup ***")
         if not self.light:
             self.debug_print("  ..core actions")
             self.close_dockwidget_action = create_action(self,
-                                        _("Close current pane"),
+                                        icon=ima.icon('DialogCloseButton'),
+                                        text=_("Close current pane"),
                                         triggered=self.close_current_dockwidget,
                                         context=Qt.ApplicationShortcut)
             self.register_shortcut(self.close_dockwidget_action, "_",
                                    "Close pane")
-            
+            self.lock_dockwidgets_action = create_action(self, _("Lock panes"),
+                                            toggled=self.toggle_lock_dockwidgets,
+                                            context=Qt.ApplicationShortcut)
+            self.register_shortcut(self.lock_dockwidgets_action, "_",
+                                       "lock unlock panes")
+            # custom layouts shortcuts
+            self.toggle_next_layout_action = create_action(self,
+                                        _("Use next layout"),
+                                        triggered=self.toggle_next_layout,
+                                        context=Qt.ApplicationShortcut)
+            self.toggle_previous_layout_action = create_action(self,
+                                        _("Use previous layout"),
+                                        triggered=self.toggle_previous_layout,
+                                        context=Qt.ApplicationShortcut)
+            self.register_shortcut(self.toggle_next_layout_action, "_",
+                                   "Use next layout")
+            self.register_shortcut(self.toggle_previous_layout_action, "_",
+                                   "Use previous layout")
+
+
             _text = _("&Find text")
-            self.find_action = create_action(self, _text, icon='find.png',
+            self.find_action = create_action(self, _text, icon=ima.icon('find'),
                                              tip=_text, triggered=self.find,
                                              context=Qt.WidgetShortcut)
             self.register_shortcut(self.find_action, "Editor", "Find text")
             self.find_next_action = create_action(self, _("Find &next"),
-                  icon='findnext.png', triggered=self.find_next,
+                  icon=ima.icon('findnext'), 
+                  triggered=self.find_next,
                   context=Qt.WidgetShortcut)
             self.register_shortcut(self.find_next_action, "Editor",
                                    "Find next")
             self.find_previous_action = create_action(self,
                         _("Find &previous"),
-                        icon='findprevious.png', triggered=self.find_previous,
+                        icon=ima.icon('findprevious'),
+                                      triggered=self.find_previous,
                         context=Qt.WidgetShortcut)
             self.register_shortcut(self.find_previous_action, "Editor",
                                    "Find previous")
             _text = _("&Replace text")
-            self.replace_action = create_action(self, _text, icon='replace.png',
+            self.replace_action = create_action(self, _text, 
+                                            icon=ima.icon('replace'),
                                             tip=_text, triggered=self.replace,
                                             context=Qt.WidgetShortcut)
             self.register_shortcut(self.replace_action, "Editor",
                                    "Replace text")
-            def create_edit_action(text, tr_text, icon_name):
+
+            def create_edit_action(text, tr_text, icon):
                 textseq = text.split(' ')
                 method_name = textseq[0].lower()+"".join(textseq[1:])
-                return create_action(self, tr_text,
-                                     shortcut=keybinding(text.replace(' ', '')),
-                                     icon=get_icon(icon_name),
-                                     triggered=self.global_callback,
-                                     data=method_name,
-                                     context=Qt.WidgetShortcut)
-            self.undo_action = create_edit_action("Undo", _("Undo"),
-                                                  'undo.png')
-            self.redo_action = create_edit_action("Redo", _("Redo"), 'redo.png')
-            self.copy_action = create_edit_action("Copy", _("Copy"),
-                                                  'editcopy.png')
-            self.cut_action = create_edit_action("Cut", _("Cut"), 'editcut.png')
-            self.paste_action = create_edit_action("Paste", _("Paste"),
-                                                   'editpaste.png')
-            self.delete_action = create_edit_action("Delete", _("Delete"),
-                                                    'editdelete.png')
+                action = create_action(self, tr_text,
+                                    shortcut=keybinding(text.replace(' ', '')),
+                                    icon=icon,
+                                    triggered=self.global_callback,
+                                    data=method_name,
+                                    context=Qt.WidgetShortcut)
+                self.register_shortcut(action, "Editor", text)
+                return action
+
+            self.undo_action = create_edit_action('Undo', _('Undo'),
+                                                  ima.icon('undo'))
+            self.redo_action = create_edit_action('Redo', _('Redo'), 
+                                                  ima.icon('redo'))
+            self.copy_action = create_edit_action('Copy', _('Copy'),
+                                                  ima.icon('editcopy'))
+            self.cut_action = create_edit_action('Cut', _('Cut'),
+                                                 ima.icon('editcut'))
+            self.paste_action = create_edit_action('Paste', _('Paste'),
+                                                   ima.icon('editpaste'))
             self.selectall_action = create_edit_action("Select All",
                                                        _("Select All"),
-                                                       'selectall.png')
+                                                       ima.icon('selectall'))
+
             self.edit_menu_actions = [self.undo_action, self.redo_action,
                                       None, self.cut_action, self.copy_action,
-                                      self.paste_action, self.delete_action,
-                                      None, self.selectall_action]
-            self.search_menu_actions = [self.find_action, self.find_next_action,
+                                      self.paste_action, self.selectall_action]
+            self.search_menu_actions = [self.find_action,
+                                        self.find_next_action,
                                         self.find_previous_action,
                                         self.replace_action]
             self.search_toolbar_actions = [self.find_action,
@@ -546,73 +622,76 @@ class MainWindow(QMainWindow):
             self.debug_print("  ..toolbars")
             # File menu/toolbar
             self.file_menu = self.menuBar().addMenu(_("&File"))
-            self.connect(self.file_menu, SIGNAL("aboutToShow()"),
-                         self.update_file_menu)
+            self.file_menu.aboutToShow.connect(self.update_file_menu)
             self.file_toolbar = self.create_toolbar(_("File toolbar"),
                                                     "file_toolbar")
-            
+
             # Edit menu/toolbar
             self.edit_menu = self.menuBar().addMenu(_("&Edit"))
             self.edit_toolbar = self.create_toolbar(_("Edit toolbar"),
                                                     "edit_toolbar")
-            
+
             # Search menu/toolbar
             self.search_menu = self.menuBar().addMenu(_("&Search"))
             self.search_toolbar = self.create_toolbar(_("Search toolbar"),
                                                       "search_toolbar")
-            
+
             # Source menu/toolbar
             self.source_menu = self.menuBar().addMenu(_("Sour&ce"))
             self.source_toolbar = self.create_toolbar(_("Source toolbar"),
                                                       "source_toolbar")
-            
+
             # Run menu/toolbar
             self.run_menu = self.menuBar().addMenu(_("&Run"))
             self.run_toolbar = self.create_toolbar(_("Run toolbar"),
                                                    "run_toolbar")
-            
+
             # Debug menu/toolbar
             self.debug_menu = self.menuBar().addMenu(_("&Debug"))
             self.debug_toolbar = self.create_toolbar(_("Debug toolbar"),
                                                      "debug_toolbar")
-                                                  
+
             # Consoles menu/toolbar
             self.consoles_menu = self.menuBar().addMenu(_("C&onsoles"))
-            
+
             # Tools menu
             self.tools_menu = self.menuBar().addMenu(_("&Tools"))
-            
+
             # View menu
             self.view_menu = self.menuBar().addMenu(_("&View"))
-            
+
             # Help menu
             self.help_menu = self.menuBar().addMenu(_("&Help"))
-                    
+
             # Status bar
             status = self.statusBar()
             status.setObjectName("StatusBar")
             status.showMessage(_("Welcome to Spyder!"), 5000)
-            
-            
+
+
             self.debug_print("  ..tools")
             # Tools + External Tools
             prefs_action = create_action(self, _("Pre&ferences"),
-                                         icon='configure.png',
+                                         icon=ima.icon('configure'),
                                          triggered=self.edit_preferences)
             self.register_shortcut(prefs_action, "_", "Preferences")
             add_shortcut_to_tooltip(prefs_action, context="_",
                                     name="Preferences")
             spyder_path_action = create_action(self,
                                     _("PYTHONPATH manager"),
-                                    None, 'pythonpath_mgr.png',
+                                    None, icon=ima.icon('pythonpath'),
                                     triggered=self.path_manager_callback,
                                     tip=_("Python Path Manager"),
                                     menurole=QAction.ApplicationSpecificRole)
             update_modules_action = create_action(self,
                                         _("Update module names list"),
-                                        triggered=module_completion.reset,
+                                        triggered=lambda:
+                                                  module_completion.reset(),
                                         tip=_("Refresh list of module names "
                                               "available in PYTHONPATH"))
+            reset_spyder_action = create_action(
+                self, _("Reset Spyder to factory defaults"),
+                triggered=self.reset_spyder)
             self.tools_menu_actions = [prefs_action, spyder_path_action]
             if WinUserEnvDialog is not None:
                 winenv_action = create_action(self,
@@ -623,8 +702,9 @@ class MainWindow(QMainWindow):
                               "(i.e. for all sessions)"),
                         triggered=self.win_env)
                 self.tools_menu_actions.append(winenv_action)
-            self.tools_menu_actions += [None, update_modules_action]
-            
+            self.tools_menu_actions += [reset_spyder_action, None,
+                                        update_modules_action]
+
             # External Tools submenu
             self.external_tools_menu = QMenu(_("External Tools"))
             self.external_tools_menu_actions = []
@@ -633,7 +713,7 @@ class MainWindow(QMainWindow):
                                    _("Python(x,y) launcher"),
                                    icon=get_icon('pythonxy.png'),
                                    triggered=lambda:
-                                   programs.run_python_script('xy', 'xyhome'))    
+                                   programs.run_python_script('xy', 'xyhome'))
             if os.name == 'nt' and is_module_installed('xy'):
                 self.external_tools_menu_actions.append(self.xy_action)
             # WinPython control panel
@@ -666,48 +746,56 @@ class MainWindow(QMainWindow):
             if additact and (is_module_installed('winpython') or \
               is_module_installed('xy')):
                 self.external_tools_menu_actions += [None] + additact
-                
+
             # Guidata and Sift
             self.debug_print("  ..sift?")
             gdgq_act = []
-            if is_module_installed('guidata'):
+            # Guidata and Guiqwt don't support PyQt5 yet and they fail
+            # with an AssertionError when imported using those bindings
+            # (see issue 2274)
+            try:
                 from guidata import configtools
-                from guidata import config  # (loading icons) analysis:ignore
+                from guidata import config       # analysis:ignore
                 guidata_icon = configtools.get_icon('guidata.svg')
                 guidata_act = create_python_script_action(self,
-                               _("guidata examples"), guidata_icon, "guidata",
+                                       _("guidata examples"), guidata_icon,
+                                       "guidata",
+                                       osp.join("tests", "__init__"))
+                gdgq_act += [guidata_act]
+            except (ImportError, AssertionError):
+                pass
+            try:
+                from guidata import configtools
+                from guiqwt import config  # analysis:ignore
+                guiqwt_icon = configtools.get_icon('guiqwt.svg')
+                guiqwt_act = create_python_script_action(self,
+                               _("guiqwt examples"), guiqwt_icon, "guiqwt",
                                osp.join("tests", "__init__"))
-                if guidata_act:
-                    gdgq_act += [guidata_act]
-                if is_module_installed('guiqwt'):
-                    from guiqwt import config  # analysis:ignore
-                    guiqwt_icon = configtools.get_icon('guiqwt.svg')
-                    guiqwt_act = create_python_script_action(self,
-                                   _("guiqwt examples"), guiqwt_icon, "guiqwt",
-                                   osp.join("tests", "__init__"))
-                    if guiqwt_act:
-                        gdgq_act += [guiqwt_act]
-                    sift_icon = configtools.get_icon('sift.svg')
-                    sift_act = create_python_script_action(self, _("Sift"),
-                               sift_icon, "guiqwt", osp.join("tests", "sift"))
-                    if sift_act:
-                        gdgq_act += [sift_act]
+                if guiqwt_act:
+                    gdgq_act += [guiqwt_act]
+                sift_icon = configtools.get_icon('sift.svg')
+                sift_act = create_python_script_action(self, _("Sift"),
+                           sift_icon, "guiqwt", osp.join("tests", "sift"))
+                if sift_act:
+                    gdgq_act += [sift_act]
+            except (ImportError, AssertionError):
+                pass
             if gdgq_act:
                 self.external_tools_menu_actions += [None] + gdgq_act
-                
+
             # ViTables
             vitables_act = create_program_action(self, _("ViTables"),
                                                  "vitables", 'vitables.png')
             if vitables_act:
                 self.external_tools_menu_actions += [None, vitables_act]
-            
+
             # Maximize current plugin
             self.maximize_action = create_action(self, '',
                                             triggered=self.maximize_dockwidget)
             self.register_shortcut(self.maximize_action, "_",
                                    "Maximize pane")
             self.__update_maximize_action()
-            
+
             # Fullscreen mode
             self.fullscreen_action = create_action(self,
                                             _("Fullscreen mode"),
@@ -716,15 +804,15 @@ class MainWindow(QMainWindow):
                                    "Fullscreen mode")
             add_shortcut_to_tooltip(self.fullscreen_action, context="_",
                                     name="Fullscreen mode")
-            
+
             # Main toolbar
             self.main_toolbar_actions = [self.maximize_action,
                                          self.fullscreen_action, None,
                                          prefs_action, spyder_path_action]
-            
+
             self.main_toolbar = self.create_toolbar(_("Main toolbar"),
                                                     "main_toolbar")
-            
+
             # Internal console plugin
             self.debug_print("  ..plugin: internal console")
             from spyderlib.plugins.console import Console
@@ -738,21 +826,21 @@ class MainWindow(QMainWindow):
                                         "  spy.app, spy.window, dir(spy)\n\n"
                                         "Please don't use it to run your code\n\n"))
             self.console.register_plugin()
-            
+
             # Working directory plugin
             self.debug_print("  ..plugin: working directory")
             from spyderlib.plugins.workingdirectory import WorkingDirectory
-            self.workingdirectory = WorkingDirectory(self, self.init_workdir)
+            self.workingdirectory = WorkingDirectory(self, self.init_workdir, main=self)
             self.workingdirectory.register_plugin()
             self.toolbarslist.append(self.workingdirectory)
-        
+
             # Object inspector plugin
             if CONF.get('inspector', 'enable'):
                 self.set_splash(_("Loading object inspector..."))
                 from spyderlib.plugins.inspector import ObjectInspector
                 self.inspector = ObjectInspector(self)
                 self.inspector.register_plugin()
-            
+
             # Outline explorer widget
             if CONF.get('outline_explorer', 'enable'):
                 self.set_splash(_("Loading outline explorer..."))
@@ -761,31 +849,38 @@ class MainWindow(QMainWindow):
                 self.outlineexplorer = OutlineExplorer(self,
                                             fullpath_sorting=fullpath_sorting)
                 self.outlineexplorer.register_plugin()
-            
+
             # Editor plugin
             self.set_splash(_("Loading editor..."))
             from spyderlib.plugins.editor import Editor
             self.editor = Editor(self)
             self.editor.register_plugin()
-            
+
             # Populating file menu entries
             quit_action = create_action(self, _("&Quit"),
-                                        icon='exit.png', tip=_("Quit"),
+                                        icon=ima.icon('exit'), 
+                                        tip=_("Quit"),
                                         triggered=self.console.quit)
             self.register_shortcut(quit_action, "_", "Quit")
+            restart_action = create_action(self, _("&Restart"),
+                                           icon=ima.icon('restart'),
+                                           tip=_("Restart"),
+                                           triggered=self.restart)
+            self.register_shortcut(restart_action, "_", "Restart")
+
             self.file_menu_actions += [self.load_temp_session_action,
                                        self.load_session_action,
                                        self.save_session_action,
-                                       None, quit_action]
+                                       None, restart_action, quit_action]
             self.set_splash("")
-        
+
             self.debug_print("  ..widgets")
             # Find in files
             if CONF.get('find_in_files', 'enable'):
                 from spyderlib.plugins.findinfiles import FindInFiles
                 self.findinfiles = FindInFiles(self)
                 self.findinfiles.register_plugin()
-            
+
             # Explorer
             if CONF.get('explorer', 'enable'):
                 self.set_splash(_("Loading file explorer..."))
@@ -799,7 +894,7 @@ class MainWindow(QMainWindow):
                 from spyderlib.plugins.history import HistoryLog
                 self.historylog = HistoryLog(self)
                 self.historylog.register_plugin()
-                
+
             # Online help widget
             try:    # Qt >= v4.4
                 from spyderlib.plugins.onlinehelp import OnlineHelp
@@ -809,14 +904,14 @@ class MainWindow(QMainWindow):
                 self.set_splash(_("Loading online help..."))
                 self.onlinehelp = OnlineHelp(self)
                 self.onlinehelp.register_plugin()
-                
+
             # Project explorer widget
             if CONF.get('project_explorer', 'enable'):
                 self.set_splash(_("Loading project explorer..."))
                 from spyderlib.plugins.projectexplorer import ProjectExplorer
                 self.projectexplorer = ProjectExplorer(self)
                 self.projectexplorer.register_plugin()
-            
+
         # External console
         if self.light:
             # This is necessary to support the --working-directory option:
@@ -827,7 +922,7 @@ class MainWindow(QMainWindow):
         from spyderlib.plugins.externalconsole import ExternalConsole
         self.extconsole = ExternalConsole(self, light_mode=self.light)
         self.extconsole.register_plugin()
-        
+
         # Namespace browser
         if not self.light:
             # In light mode, namespace browser is opened inside external console
@@ -836,7 +931,7 @@ class MainWindow(QMainWindow):
             from spyderlib.plugins.variableexplorer import VariableExplorer
             self.variableexplorer = VariableExplorer(self)
             self.variableexplorer.register_plugin()
-        
+
         # IPython console
         if IPYTHON_QT_INSTALLED and not self.light:
             self.set_splash(_("Loading IPython console..."))
@@ -846,23 +941,26 @@ class MainWindow(QMainWindow):
 
         if not self.light:
             nsb = self.variableexplorer.add_shellwidget(self.console.shell)
-            self.connect(self.console.shell, SIGNAL('refresh()'),
-                         nsb.refresh_table)
+            self.console.shell.refresh.connect(nsb.refresh_table)
             nsb.auto_refresh_button.setEnabled(False)
-            
+
             self.set_splash(_("Setting up main window..."))
-            
+
             # Help menu
-            dep_action = create_action(self, _("Optional dependencies..."),
+            dep_action = create_action(self, _("Dependencies..."),
                                        triggered=self.show_dependencies,
-                                       icon='advanced.png')
+                                       icon=ima.icon('advanced'))
             report_action = create_action(self,
                                           _("Report issue..."),
-                                          icon=get_icon('bug.png'),
+                                          icon=ima.icon('bug'),
                                           triggered=self.report_issue)
             support_action = create_action(self,
                                            _("Spyder support..."),
                                            triggered=self.google_group)
+            self.check_updates_action = create_action(self,
+                                                  _("Check for updates..."),
+                                                  triggered=self.check_updates)
+
             # Spyder documentation
             doc_path = get_module_data_path('spyderlib', relpath="doc",
                                             attr_name='DOCPATH')
@@ -883,13 +981,41 @@ class MainWindow(QMainWindow):
                 spyder_doc = 'http://pythonhosted.org/spyder'
             else:
                 spyder_doc = file_uri(spyder_doc)
-            doc_action = create_bookmark_action(self, spyder_doc,
-                               _("Spyder documentation"), shortcut="F1",
-                               icon=get_std_icon('DialogHelpButton'))
+            doc_action = create_action( self, _("Spyder documentation"), shortcut="F1", 
+                                       icon=ima.icon('DialogHelpButton'),
+                                       triggered=lambda : programs.start_file(spyder_doc))
+
             tut_action = create_action(self, _("Spyder tutorial"),
                                        triggered=self.inspector.show_tutorial)
-            self.help_menu_actions = [doc_action, tut_action, None,
-                                      report_action, dep_action, support_action,
+
+        #----- Tours
+            self.tour = tour.AnimatedTour(self)
+            self.tours_menu = QMenu(_("Interactive tours"))
+            self.tour_menu_actions = []
+            # TODO: Only show intro tour for now. When we are close to finish
+            # 3.0, we will finish and show the other tour
+            self.tours_available = tour.get_tours(0)
+
+            for i, tour_available in enumerate(self.tours_available):
+                self.tours_available[i]['last'] = 0
+                tour_name = tour_available['name']
+
+                def trigger(i=i, self=self):  # closure needed!
+                    return lambda: self.show_tour(i)
+
+                temp_action = create_action(self, tour_name, tip="",
+                                            triggered=trigger())
+                self.tour_menu_actions += [temp_action]
+
+            self.tours_menu.addActions(self.tour_menu_actions)
+
+            if not DEV:
+                self.tours_menu = None
+
+            self.help_menu_actions = [doc_action, tut_action, self.tours_menu,
+                                      None,
+                                      report_action, dep_action,
+                                      self.check_updates_action, support_action,
                                       None]
             # Python documentation
             if get_python_doc_path() is not None:
@@ -905,7 +1031,7 @@ class MainWindow(QMainWindow):
                 quickref_action = create_action(self, _("Quick reference"),
                                        triggered=self.ipyconsole.show_quickref)
                 guiref_action = create_action(self, _("Console help"),
-                                         triggered=self.ipyconsole.show_guiref)                    
+                                         triggered=self.ipyconsole.show_guiref)
                 add_actions(ipython_menu, (intro_action, guiref_action,
                                            quickref_action))
                 self.help_menu_actions.append(ipython_menu)
@@ -974,19 +1100,21 @@ class MainWindow(QMainWindow):
             add_actions(web_resources, webres_actions)
             self.help_menu_actions.append(web_resources)
             # Qt assistant link
-            qta_exe = "assistant-qt4" if sys.platform.startswith('linux') else \
-                      "assistant"
-            qta_act = create_program_action(self, _("Qt documentation"), 
+            if sys.platform.startswith('linux') and not PYQT5:
+                qta_exe = "assistant-qt4"
+            else:
+                qta_exe = "assistant"
+            qta_act = create_program_action(self, _("Qt documentation"),
                                             qta_exe)
             if qta_act:
                 self.help_menu_actions += [qta_act, None]
             # About Spyder
             about_action = create_action(self,
                                     _("About %s...") % "Spyder",
-                                    icon=get_std_icon('MessageBoxInformation'),
+                                    icon=ima.icon('MessageBoxInformation'),
                                     triggered=self.about)
             self.help_menu_actions += [None, about_action]
-            
+
             # Status bar widgets
             from spyderlib.widgets.status import MemoryStatus, CPUStatus
             self.mem_status = MemoryStatus(self, status)
@@ -994,56 +1122,54 @@ class MainWindow(QMainWindow):
             self.apply_statusbar_settings()
 
             # Third-party plugins
-            for mod in get_spyderplugins_mods(prefix='p_', extension='.py'):
+            for mod in get_spyderplugins_mods():
                 try:
                     plugin = mod.PLUGIN_CLASS(self)
                     self.thirdparty_plugins.append(plugin)
                     plugin.register_plugin()
-                except AttributeError as error:
+                except Exception as error:
                     print("%s: %s" % (mod, str(error)), file=STDERR)
-                                
+                    traceback.print_exc(file=STDERR)
+
+
+    #----- View
             # View menu
             self.plugins_menu = QMenu(_("Panes"), self)
             self.toolbars_menu = QMenu(_("Toolbars"), self)
-            self.view_menu.addMenu(self.plugins_menu)
+            self.quick_layout_menu = QMenu(_("Window layouts"), self)
+            self.quick_layout_set_menu()
+
+            self.view_menu.addMenu(self.plugins_menu)  # Panes
+            add_actions(self.view_menu, (self.lock_dockwidgets_action,
+                                         self.close_dockwidget_action,
+                                         self.maximize_action,
+                                         None))
+            self.show_toolbars_action = create_action(self,
+                                    _("Show toolbars"),
+                                    triggered=self.show_toolbars)
+            self.register_shortcut(self.show_toolbars_action, "_",
+                                   "Show toolbars")
             self.view_menu.addMenu(self.toolbars_menu)
-            reset_layout_action = create_action(self, _("Reset window layout"),
-                                            triggered=self.reset_window_layout)
-            quick_layout_menu = QMenu(_("Custom window layouts"), self)
-            ql_actions = []
-            for index in range(1, 4):
-                if index > 0:
-                    ql_actions += [None]
-                qli_act = create_action(self,
-                                        _("Switch to/from layout %d") % index,
-                                        triggered=lambda i=index:
-                                        self.quick_layout_switch(i))
-                self.register_shortcut(qli_act, "_",
-                                       "Switch to/from layout %d" % index)
-                qlsi_act = create_action(self, _("Set layout %d") % index,
-                                         triggered=lambda i=index:
-                                         self.quick_layout_set(i))
-                self.register_shortcut(qlsi_act, "_", "Set layout %d" % index)
-                ql_actions += [qli_act, qlsi_act]
-            add_actions(quick_layout_menu, ql_actions)
+            self.view_menu.addAction(self.show_toolbars_action)
+            add_actions(self.view_menu, (None,
+                                         self.quick_layout_menu,
+                                         self.toggle_previous_layout_action,
+                                         self.toggle_next_layout_action,
+                                         None,
+                                         self.fullscreen_action))
             if set_attached_console_visible is not None:
                 cmd_act = create_action(self,
                                     _("Attached console window (debugging)"),
                                     toggled=set_attached_console_visible)
                 cmd_act.setChecked(is_attached_console_visible())
                 add_actions(self.view_menu, (None, cmd_act))
-            add_actions(self.view_menu, (None, self.fullscreen_action,
-                                         self.maximize_action,
-                                         self.close_dockwidget_action, None,
-                                         reset_layout_action,
-                                         quick_layout_menu))
-            
+
             # Adding external tools action to "Tools" menu
             if self.external_tools_menu_actions:
                 external_tools_act = create_action(self, _("External Tools"))
                 external_tools_act.setMenu(self.external_tools_menu)
                 self.tools_menu_actions += [None, external_tools_act]
-            
+
             # Filling out menu/toolbar entries:
             add_actions(self.file_menu, self.file_menu_actions)
             add_actions(self.edit_menu, self.edit_menu_actions)
@@ -1056,7 +1182,7 @@ class MainWindow(QMainWindow):
             add_actions(self.external_tools_menu,
                         self.external_tools_menu_actions)
             add_actions(self.help_menu, self.help_menu_actions)
-            
+
             add_actions(self.main_toolbar, self.main_toolbar_actions)
             add_actions(self.file_toolbar, self.file_toolbar_actions)
             add_actions(self.edit_toolbar, self.edit_toolbar_actions)
@@ -1064,47 +1190,46 @@ class MainWindow(QMainWindow):
             add_actions(self.source_toolbar, self.source_toolbar_actions)
             add_actions(self.debug_toolbar, self.debug_toolbar_actions)
             add_actions(self.run_toolbar, self.run_toolbar_actions)
-            
+
         # Apply all defined shortcuts (plugins + 3rd-party plugins)
         self.apply_shortcuts()
         #self.remove_deprecated_shortcuts()
-        
-        # Emitting the signal notifying plugins that main window menu and 
+
+        # Emitting the signal notifying plugins that main window menu and
         # toolbar actions are all defined:
-        self.emit(SIGNAL('all_actions_defined()'))
-        
+        self.all_actions_defined.emit()
+
         # Window set-up
         self.debug_print("Setting up window...")
         self.setup_layout(default=False)
-        
+
         self.splash.hide()
-        
+
         # Enabling tear off for all menus except help menu
         if CONF.get('main', 'tear_off_menus'):
             for child in self.menuBar().children():
                 if isinstance(child, QMenu) and child != self.help_menu:
                     child.setTearOffEnabled(True)
-        
+
         # Menu about to show
         for child in self.menuBar().children():
             if isinstance(child, QMenu):
-                self.connect(child, SIGNAL("aboutToShow()"),
-                             self.update_edit_menu)
+                child.aboutToShow.connect(self.update_edit_menu)
 
         self.debug_print("*** End of MainWindow setup ***")
         self.is_starting_up = False
-        
+
     def post_visible_setup(self):
-        """Actions to be performed only after the main window's `show` method 
+        """Actions to be performed only after the main window's `show` method
         was triggered"""
-        self.emit(SIGNAL('restore_scrollbar_position()'))
-        
+        self.restore_scrollbar_position.emit()
+
         if self.projectexplorer is not None:
             self.projectexplorer.check_for_io_errors()
-        
+
         # Remove our temporary dir
         atexit.register(self.remove_tmpdir)
-        
+
         # Remove settings test directory
         if TEST is not None:
             import tempfile
@@ -1112,7 +1237,7 @@ class MainWindow(QMainWindow):
             atexit.register(shutil.rmtree, conf_dir, ignore_errors=True)
 
         # [Workaround for Issue 880]
-        # QDockWidget objects are not painted if restored as floating 
+        # QDockWidget objects are not painted if restored as floating
         # windows, so we must dock them before showing the mainwindow,
         # then set them again as floating windows here.
         for widget in self.floating_dockwidgets:
@@ -1122,7 +1247,6 @@ class MainWindow(QMainWindow):
         # know why because this doesn't happen when started from the terminal),
         # so we need to resort to this hack to make it appear.
         if running_in_mac_app():
-            import subprocess
             idx = __file__.index(MAC_APP_NAME)
             app_path = __file__[:idx]
             subprocess.call(['open', app_path + MAC_APP_NAME])
@@ -1134,29 +1258,36 @@ class MainWindow(QMainWindow):
             t = threading.Thread(target=self.start_open_files_server)
             t.setDaemon(True)
             t.start()
-        
+
             # Connect the window to the signal emmited by the previous server
             # when it gets a client connected to it
-            self.connect(self, SIGNAL('open_external_file(QString)'),
-                         lambda fname: self.open_external_file(fname))
-        
+            self.sig_open_external_file.connect(self.open_external_file)
+
         # Create Plugins and toolbars submenus
         if not self.light:
             self.create_plugins_menu()
             self.create_toolbars_menu()
-        
+
         # Open a Python console for light mode
         if self.light:
             self.extconsole.open_interpreter()
         self.extconsole.setMinimumHeight(0)
-        
+
         if not self.light:
+            # Update toolbar visibility status
+            self.toolbars_visible = CONF.get('main', 'toolbars_visible')
+            self.load_last_visible_toolbars()
+
+            # Update lock status of dockidgets (panes)
+            self.lock_dockwidgets_action.setChecked(self.dockwidgets_locked)
+            self.apply_panes_settings()
+
             # Hide Internal Console so that people don't use it instead of
             # the External or IPython ones
             if self.console.dockwidget.isVisible() and DEV is None:
                 self.console.toggle_view_action.setChecked(False)
                 self.console.dockwidget.hide()
-        
+
             # Show the Object Inspector and Consoles by default
             plugins_to_show = [self.inspector]
             if self.ipyconsole is not None:
@@ -1169,21 +1300,26 @@ class MainWindow(QMainWindow):
             for plugin in plugins_to_show:
                 if plugin.dockwidget.isVisible():
                     plugin.dockwidget.raise_()
-            
+
             # Show history file if no console is visible
             ipy_visible = self.ipyconsole is not None and self.ipyconsole.isvisible
             if not self.extconsole.isvisible and not ipy_visible:
                 self.historylog.add_history(get_conf_path('history.py'))
-            
+
             # Give focus to the Editor
             if self.editor.dockwidget.isVisible():
                 try:
                     self.editor.get_focus_widget().setFocus()
                 except AttributeError:
                     pass
-        
+
+        # Check for spyder updates
+        if DEV is None and CONF.get('main', 'check_updates_on_startup'):
+            self.give_updates_feedback = False 
+            self.check_updates()
+
         self.is_setting_up = False
-        
+
     def load_window_settings(self, prefix, default=False, section='main'):
         """Load window layout settings from userconfig-based configuration
         with *prefix*, under *section*
@@ -1232,9 +1368,10 @@ class MainWindow(QMainWindow):
         if not self.light:
             # Window layout
             if hexstate:
-                self.restoreState( QByteArray().fromHex(str(hexstate)) )
+                self.restoreState( QByteArray().fromHex(
+                        str(hexstate).encode('utf-8')) )
                 # [Workaround for Issue 880]
-                # QDockWidget objects are not painted if restored as floating 
+                # QDockWidget objects are not painted if restored as floating
                 # windows, so we must dock them before showing the mainwindow.
                 for widget in self.children():
                     if isinstance(widget, QDockWidget) and widget.isFloating():
@@ -1250,13 +1387,13 @@ class MainWindow(QMainWindow):
         elif is_maximized:
             self.setWindowState(Qt.WindowMaximized)
         self.setUpdatesEnabled(True)
-        
+
     def save_current_window_settings(self, prefix, section='main'):
         """Save current window settings with *prefix* in
         the userconfig-based configuration, under *section*"""
         win_size = self.window_size
         prefs_size = self.prefs_dialog_size
-        
+
         CONF.set(section, prefix+'size', (win_size.width(), win_size.height()))
         CONF.set(section, prefix+'prefs_dialog_size',
                  (prefs_size.width(), prefs_size.height()))
@@ -1275,57 +1412,382 @@ class MainWindow(QMainWindow):
         """Tabify plugin dockwigdets"""
         self.tabifyDockWidget(first.dockwidget, second.dockwidget)
 
+    # --- Layouts 
     def setup_layout(self, default=False):
         """Setup window layout"""
         prefix = ('lightwindow' if self.light else 'window') + '/'
-        (hexstate, window_size, prefs_dialog_size, pos, is_maximized,
-         is_fullscreen) = self.load_window_settings(prefix, default)
+        settings = self.load_window_settings(prefix, default)
+        hexstate = settings[0]
         
+        self.first_spyder_run = False
         if hexstate is None and not self.light:
             # First Spyder execution:
-            # trying to set-up the dockwidget/toolbar positions to the best 
-            # appearance possible
-            splitting = (
-                         (self.projectexplorer, self.editor, Qt.Horizontal),
-                         (self.editor, self.outlineexplorer, Qt.Horizontal),
-                         (self.outlineexplorer, self.inspector, Qt.Horizontal),
-                         (self.inspector, self.console, Qt.Vertical),
-                         )
-            for first, second, orientation in splitting:
-                if first is not None and second is not None:
-                    self.splitDockWidget(first.dockwidget, second.dockwidget,
-                                         orientation)
-            for first, second in ((self.console, self.extconsole),
-                                  (self.extconsole, self.ipyconsole),
-                                  (self.ipyconsole, self.historylog),
-                                  (self.inspector, self.variableexplorer),
-                                  (self.variableexplorer, self.onlinehelp),
-                                  (self.onlinehelp, self.explorer),
-                                  (self.explorer, self.findinfiles),
-                                  ):
-                if first is not None and second is not None:
-                    self.tabify_plugins(first, second)
-            for plugin in [self.findinfiles, self.onlinehelp, self.console,
-                           ]+self.thirdparty_plugins:
-                if plugin is not None:
-                    plugin.dockwidget.close()
-            for plugin in (self.inspector, self.extconsole):
-                if plugin is not None:
-                    plugin.dockwidget.raise_()
+            self.setWindowState(Qt.WindowMaximized)
+            self.first_spyder_run = True
+            self.setup_default_layouts('default', settings)
             self.extconsole.setMinimumHeight(250)
-            hidden_toolbars = [self.source_toolbar, self.edit_toolbar,
-                               self.search_toolbar]
-            for toolbar in hidden_toolbars:
-                toolbar.close()
-            for plugin in (self.projectexplorer, self.outlineexplorer):
-                plugin.dockwidget.close()
 
-        self.set_window_settings(hexstate, window_size, prefs_dialog_size, pos,
-                                 is_maximized, is_fullscreen)
+            # Now that the initial setup is done, copy the window settings,
+            # except for the hexstate in the quick layouts sections for the
+            # default layouts. 
+            # Order and name of the default layouts is found in config.py
+            section = 'quick_layouts'
+            get_func = CONF.get_default if default else CONF.get
+            order = get_func(section, 'order')
+            
+            # restore the original defaults if reset layouts is called
+            if default:
+                CONF.set(section, 'active', order)
+                CONF.set(section, 'order', order)
+                CONF.set(section, 'names', order)
+
+            for index, name, in enumerate(order):
+                prefix = 'layout_{0}/'.format(index)
+                self.save_current_window_settings(prefix, section)
+                CONF.set(section, prefix+'state', None)        
+
+            # store the initial layout as the default in spyder
+            prefix = 'layout_default/'
+            section = 'quick_layouts'
+            self.save_current_window_settings(prefix, section)
+            self.current_quick_layout = 'default'
+            CONF.set(section, prefix+'state', None)
+            
+            # Regenerate menu
+            self.quick_layout_set_menu()
+        self.set_window_settings(*settings)
 
         for plugin in self.widgetlist:
             plugin.initialize_plugin_in_mainwindow_layout()
+       
+    def setup_default_layouts(self, index, settings):
+        """Setup default layouts when run for the first time"""
+        self.set_window_settings(*settings)
+        self.setUpdatesEnabled(False)
+
+        # IMPORTANT: order has to be the same as defined in the config file
+        MATLAB, RSTUDIO, VERTICAL, HORIZONTAL = range(4)
+
+        # define widgets locally
+        editor = self.editor
+        console_ipy = self.ipyconsole
+        console_ext = self.extconsole
+        console_int = self.console
+        outline = self.outlineexplorer
+        explorer_project = self.projectexplorer
+        explorer_file = self.explorer
+        explorer_variable = self.variableexplorer
+        history = self.historylog
+        finder = self.findinfiles
+        inspector = self.inspector
+        helper = self.onlinehelp
+        plugins = self.thirdparty_plugins
+
+        global_hidden_widgets = [finder, console_int, explorer_project,
+                                 helper] + plugins
+        global_hidden_toolbars = [self.source_toolbar, self.edit_toolbar,
+                                  self.search_toolbar]
+        # Layout definition
+        # layouts are organized by columns, each colum is organized by rows
+        # widths have to add 1.0, height per column have to add 1.0
+        # Spyder Default Initial Layout
+        s_layout = {'widgets': [
+                    # column 0
+                    [[explorer_project]],
+                    # column 1
+                    [[editor]],
+                    # column 2                                        
+                    [[outline]],
+                    # column 3
+                    [[inspector, explorer_variable, helper, explorer_file,
+                      finder] + plugins,
+                     [console_int, console_ext, console_ipy, history]]
+                    ],
+                    'width fraction': [0.0,             # column 0 width
+                                       0.55,            # column 1 width
+                                       0.0,             # column 2 width
+                                       0.45],           # column 3 width
+                    'height fraction': [[1.0],          # column 0, row heights
+                                        [1.0],          # column 1, row heights
+                                        [1.0],          # column 2, row heights
+                                        [0.46, 0.54]],  # column 3, row heights
+                    'hidden widgets': [outline],
+                    'hidden toolbars': [],                               
+                    }
+        r_layout = {'widgets': [
+                    # column 0
+                    [[editor],
+                     [console_ipy, console_ext, console_int]],
+                    # column 1
+                    [[explorer_variable, history, outline, finder] + plugins,
+                     [explorer_file, explorer_project, inspector, helper]]
+                    ],
+                    'width fraction': [0.55,            # column 0 width
+                                       0.45],           # column 1 width
+                    'height fraction': [[0.55, 0.45],   # column 0, row heights
+                                        [0.55, 0.45]],  # column 1, row heights
+                    'hidden widgets': [outline],
+                    'hidden toolbars': [],                               
+                    }
+        # Matlab
+        m_layout = {'widgets': [
+                    # column 0
+                    [[explorer_file, explorer_project],
+                     [outline]],
+                    # column 1
+                    [[editor],
+                     [console_ipy, console_ext, console_int]],
+                    # column 2
+                    [[explorer_variable, finder] + plugins,
+                     [history, inspector, helper]]
+                    ],
+                    'width fraction': [0.20,            # column 0 width
+                                       0.40,            # column 1 width
+                                       0.40],           # column 2 width
+                    'height fraction': [[0.55, 0.45],   # column 0, row heights
+                                        [0.55, 0.45],   # column 1, row heights
+                                        [0.55, 0.45]],  # column 2, row heights
+                    'hidden widgets': [],
+                    'hidden toolbars': [],
+                    }
+        # Vertically split
+        v_layout = {'widgets': [
+                    # column 0
+                    [[editor],
+                     [console_ipy, console_ext, console_int, explorer_file,
+                      explorer_project, inspector, explorer_variable,
+                      history, outline, finder, helper] + plugins]
+                    ],
+                    'width fraction': [1.0],            # column 0 width
+                    'height fraction': [[0.55, 0.45]],  # column 0, row heights
+                    'hidden widgets': [outline],
+                    'hidden toolbars': [],
+                    }
+        # Horizontally split
+        h_layout = {'widgets': [
+                    # column 0
+                    [[editor]],
+                    # column 1
+                    [[console_ipy, console_ext, console_int, explorer_file,
+                      explorer_project, inspector, explorer_variable,
+                      history, outline, finder, helper] + plugins]
+                    ],
+                    'width fraction': [0.55,      # column 0 width
+                                       0.45],     # column 1 width
+                    'height fraction': [[1.0],    # column 0, row heights
+                                        [1.0]],   # column 1, row heights
+                    'hidden widgets': [outline],
+                    'hidden toolbars': []
+                    }
+
+        # Layout selection
+        layouts = {'default': s_layout,
+                   RSTUDIO: r_layout,
+                   MATLAB: m_layout,
+                   VERTICAL: v_layout,
+                   HORIZONTAL: h_layout}
+
+        layout = layouts[index]
+
+        widgets_layout = layout['widgets']         
+        widgets = []
+        for column in widgets_layout :
+            for row in column:
+                for widget in row:
+                    if widget is not None:
+                        widgets.append(widget)
+
+        # Make every widget visible
+        for widget in widgets:
+            widget.toggle_view(True)
+            action = widget.toggle_view_action
+            action.setChecked(widget.dockwidget.isVisible())
+
+        # Set the widgets horizontally
+        for i in range(len(widgets) - 1):
+            first, second = widgets[i], widgets[i+1]
+            if first is not None and second is not None:
+                self.splitDockWidget(first.dockwidget, second.dockwidget,
+                                     Qt.Horizontal)
+
+        # Arrange rows vertically 
+        for column in widgets_layout :
+            for i in range(len(column) - 1):
+                first_row, second_row = column[i], column[i+1]
+                if first_row is not None and second_row is not None:
+                    self.splitDockWidget(first_row[0].dockwidget,
+                                         second_row[0].dockwidget,
+                                         Qt.Vertical)
+        # Tabify
+        for column in widgets_layout :
+            for row in column:
+                for i in range(len(row) - 1):
+                    first, second = row[i], row[i+1]
+                    if first is not None and second is not None:
+                        self.tabify_plugins(first, second)
+
+                # Raise front widget per row
+                row[0].dockwidget.show()
+                row[0].dockwidget.raise_()
+
+        # Hide toolbars
+        hidden_toolbars = global_hidden_toolbars + layout['hidden toolbars']
+        for toolbar in hidden_toolbars:
+            if toolbar is not None:
+                toolbar.close()
+
+        # Hide widgets
+        hidden_widgets = global_hidden_widgets + layout['hidden widgets']
+        for widget in hidden_widgets:
+            if widget is not None:
+                widget.dockwidget.close()
+
+        # set the width and height
+        self._layout_widget_info = []
+        width, height = self.window_size.width(), self.window_size.height()
+
+        # fix column width
+#        for c in range(len(widgets_layout)):
+#            widget = widgets_layout[c][0][0].dockwidget
+#            min_width, max_width = widget.minimumWidth(), widget.maximumWidth()
+#            info = {'widget': widget,
+#                    'min width': min_width,
+#                    'max width': max_width}
+#            self._layout_widget_info.append(info)
+#            new_width = int(layout['width fraction'][c] * width * 0.95)
+#            widget.setMinimumWidth(new_width)
+#            widget.setMaximumWidth(new_width)
+#            widget.updateGeometry()
+#            print(c, widgets_layout[c][0][0], new_width)
+        
+        # fix column height
+        for c, column in enumerate(widgets_layout):
+            for r in range(len(column) - 1):
+                widget = column[r][0]
+                dockwidget = widget.dockwidget
+                dock_min_h = dockwidget.minimumHeight()
+                dock_max_h = dockwidget.maximumHeight()
+                info = {'widget': widget,
+                        'dock min height': dock_min_h,
+                        'dock max height': dock_max_h}
+                self._layout_widget_info.append(info)
+                # The 0.95 factor is to adjust height based on usefull
+                # estimated area in the window
+                new_height = int(layout['height fraction'][c][r]*height*0.95)
+                dockwidget.setMinimumHeight(new_height)
+                dockwidget.setMaximumHeight(new_height)
+
+        self._custom_layout_timer = QTimer(self)
+        self._custom_layout_timer.timeout.connect(self.layout_fix_timer)
+        self._custom_layout_timer.setSingleShot(True)
+        self._custom_layout_timer.start(5000)
+
+    def layout_fix_timer(self):
+        """Fixes the height of docks after a new layout is set."""
+        info = self._layout_widget_info
+        for i in info:
+            dockwidget = i['widget'].dockwidget
+            if 'dock min width' in i:
+                dockwidget.setMinimumWidth(i['dock min width'])
+                dockwidget.setMaximumWidth(i['dock max width'])
+            if 'dock min height' in i:
+                dockwidget.setMinimumHeight(i['dock min height'])
+                dockwidget.setMaximumHeight(i['dock max height'])
+            dockwidget.updateGeometry()
+
+        self.setUpdatesEnabled(True)
+
+    def toggle_previous_layout(self):
+        """ """
+        self.toggle_layout('previous')
+
+    def toggle_next_layout(self):
+        """ """
+        self.toggle_layout('next')
+
+    def toggle_layout(self, direction='next'):
+        """ """
+        get = CONF.get
+        names = get('quick_layouts', 'names')
+        order = get('quick_layouts', 'order')
+        active = get('quick_layouts', 'active')
+
+        if len(active) == 0:
+            return
+
+        layout_index = ['default']
+        for name in order:
+            if name in active:
+                layout_index.append(names.index(name))
 
+        current_layout = self.current_quick_layout
+        dic = {'next': 1, 'previous': -1}
+
+        if current_layout is None:
+            # Start from default
+            current_layout = 'default'
+
+        if current_layout in layout_index:
+            current_index = layout_index.index(current_layout)
+        else:
+            current_index = 0
+
+        new_index = (current_index + dic[direction]) % len(layout_index)
+        self.quick_layout_switch(layout_index[new_index])
+
+    def quick_layout_set_menu(self):
+        """ """
+        get = CONF.get
+        names = get('quick_layouts', 'names')
+        order = get('quick_layouts', 'order')
+        active = get('quick_layouts', 'active')
+
+        ql_actions = []
+
+        ql_actions = [create_action(self, _('Spyder Default Layout'),
+                                    triggered=lambda:
+                                    self.quick_layout_switch('default'))]
+        for name in order:
+            if name in active:
+                index = names.index(name)
+
+                # closure required so lambda works with the default parameter
+                def trigger(i=index, self=self):
+                    return lambda: self.quick_layout_switch(i)
+
+                qli_act = create_action(self, name, triggered=trigger())
+                # closure above replaces the following which stopped working
+                # qli_act = create_action(self, name, triggered=lambda i=index:
+                #     self.quick_layout_switch(i)
+
+                ql_actions += [qli_act]
+
+        self.ql_save = create_action(self, _("Save current layout"),
+                                     triggered=lambda:
+                                     self.quick_layout_save(),
+                                     context=Qt.ApplicationShortcut)
+        self.ql_preferences = create_action(self, _("Layout preferences"),
+                                            triggered=lambda:
+                                            self.quick_layout_settings(),
+                                            context=Qt.ApplicationShortcut)
+        self.ql_reset = create_action(self, _('Reset to spyder default'),
+                                      triggered=self.reset_window_layout)
+
+        self.register_shortcut(self.ql_save, "_", "Save current layout")
+        self.register_shortcut(self.ql_preferences, "_", "Layout preferences")
+
+        ql_actions += [None]
+        ql_actions += [self.ql_save, self.ql_preferences, self.ql_reset]
+
+        self.quick_layout_menu.clear()
+        add_actions(self.quick_layout_menu, ql_actions)
+
+        if len(order) == 0:
+            self.ql_preferences.setEnabled(False)
+        else:
+            self.ql_preferences.setEnabled(True)
+
+    @Slot()
     def reset_window_layout(self):
         """Reset window layout to default"""
         answer = QMessageBox.warning(self, _("Warning"),
@@ -1335,30 +1797,161 @@ class MainWindow(QMainWindow):
                      QMessageBox.Yes | QMessageBox.No)
         if answer == QMessageBox.Yes:
             self.setup_layout(default=True)
-            
+
+    def quick_layout_save(self):
+        """Save layout dialog"""
+        get = CONF.get
+        set_ = CONF.set
+        names = get('quick_layouts', 'names')
+        order = get('quick_layouts', 'order')
+        active = get('quick_layouts', 'active')
+
+        dlg = self.dialog_layout_save(self, names)
+
+        if dlg.exec_():
+            name = dlg.combo_box.currentText()
+
+            if name in names:
+                answer = QMessageBox.warning(self, _("Warning"),
+                                             _("Layout <b>%s</b> will be \
+                                               overwritten. Do you want to \
+                                               continue?") % name,
+                                             QMessageBox.Yes | QMessageBox.No)
+                index = order.index(name)
+            else:
+                answer = True
+                if None in names:
+                    index = names.index(None)
+                    names[index] = name
+                else:
+                    index = len(names)
+                    names.append(name)
+                order.append(name)
+
+            # Always make active a new layout even if it overwrites an inactive
+            # layout
+            if name not in active:
+                active.append(name)
+
+            if answer:
+                self.save_current_window_settings('layout_{}/'.format(index),
+                                                  section='quick_layouts')
+                set_('quick_layouts', 'names', names)
+                set_('quick_layouts', 'order', order)
+                set_('quick_layouts', 'active', active)
+                self.quick_layout_set_menu()
+
+    def quick_layout_settings(self):
+        """Layout settings dialog"""
+        get = CONF.get
+        set_ = CONF.set
+
+        section = 'quick_layouts'
+
+        names = get(section, 'names')
+        order = get(section, 'order')
+        active = get(section, 'active')
+
+        dlg = self.dialog_layout_settings(self, names, order, active)
+        if dlg.exec_():
+            set_(section, 'names', dlg.names)
+            set_(section, 'order', dlg.order)
+            set_(section, 'active', dlg.active)
+            self.quick_layout_set_menu()
+
     def quick_layout_switch(self, index):
         """Switch to quick layout number *index*"""
-        if self.current_quick_layout == index:
-            self.set_window_settings(*self.previous_layout_settings)
-            self.current_quick_layout = None
+        section = 'quick_layouts'
+
+        try:
+            settings = self.load_window_settings('layout_{}/'.format(index),
+                                                 section=section)
+            (hexstate, window_size, prefs_dialog_size, pos, is_maximized,
+             is_fullscreen) = settings
+
+            # The defaults layouts will alwyas be regenerated unless there was
+            # an overwrite, either by rewriting with same name, or by deleting
+            # and then creating a new one
+            if hexstate is None:
+                self.setup_default_layouts(index, settings)
+        except cp.NoOptionError:
+            QMessageBox.critical(self, _("Warning"),
+                                 _("Quick switch layout #%s has not yet "
+                                   "been defined.") % str(index))
+            return
+            # TODO: is there any real use in calling the previous layout
+            # setting?
+            # self.previous_layout_settings = self.get_window_settings()
+        self.set_window_settings(*settings)
+        self.current_quick_layout = index
+
+        # make sure the flags are correctly set for visible panes
+        for plugin in self.widgetlist:
+            action = plugin.toggle_view_action
+            action.setChecked(plugin.dockwidget.isVisible())
+
+    # --- Show/Hide toolbars
+    def _update_show_toolbars_action(self):
+        """Update the text displayed in the menu entry."""
+        if self.toolbars_visible:
+            text = _("Hide toolbars")
+            tip = _("Hide toolbars")
         else:
-            try:
-                settings = self.load_window_settings('layout_%d/' % index,
-                                                     section='quick_layouts')
-            except cp.NoOptionError:
-                QMessageBox.critical(self, _("Warning"),
-                                     _("Quick switch layout #%d has not yet "
-                                       "been defined.") % index)
-                return
-            self.previous_layout_settings = self.get_window_settings()
-            self.set_window_settings(*settings)
-            self.current_quick_layout = index
-    
-    def quick_layout_set(self, index):
-        """Save current window settings as quick layout number *index*"""
-        self.save_current_window_settings('layout_%d/' % index,
-                                          section='quick_layouts')
+            text = _("Show toolbars")
+            tip = _("Show toolbars")
+        self.show_toolbars_action.setText(text)
+        self.show_toolbars_action.setToolTip(tip)
+
+    def save_visible_toolbars(self):
+        """Saves the name of the visible toolbars in the .ini file."""
+        toolbars = []
+        for toolbar in self.visible_toolbars:
+            toolbars.append(toolbar.objectName())
+        CONF.set('main', 'last_visible_toolbars', toolbars)
+
+    def get_visible_toolbars(self):
+        """Collects the visible toolbars."""
+        toolbars = []
+        for toolbar in self.toolbarslist:
+            if toolbar.toggleViewAction().isChecked():
+                toolbars.append(toolbar)
+        self.visible_toolbars = toolbars
+
+    def load_last_visible_toolbars(self):
+        """Loads the last visible toolbars from the .ini file."""
+        toolbars_names = CONF.get('main', 'last_visible_toolbars', default=[])
+
+        if toolbars_names:
+            dic = {}
+            for toolbar in self.toolbarslist:
+                dic[toolbar.objectName()] = toolbar
+
+            toolbars = []
+            for name in toolbars_names:
+                if name in dic:
+                    toolbars.append(dic[name])
+            self.visible_toolbars = toolbars
+        else:
+            self.get_visible_toolbars()
+        self._update_show_toolbars_action()
+
+    def show_toolbars(self):
+        """Show/Hides toolbars."""
+        value = not self.toolbars_visible
+        CONF.set('main', 'toolbars_visible', value)
+        if value:
+            self.save_visible_toolbars()
+        else:
+            self.get_visible_toolbars()
+
+        for toolbar in self.visible_toolbars:
+            toolbar.toggleViewAction().setChecked(value)
+            toolbar.setVisible(value)
+
+        self.toolbars_visible = value
+        self._update_show_toolbars_action()
 
+    # --- Other
     def plugin_focus_changed(self):
         """Focus has changed from one plugin to another"""
         if self.light:
@@ -1366,8 +1959,8 @@ class MainWindow(QMainWindow):
             return
         self.update_edit_menu()
         self.update_search_menu()
-        
-        # Now deal with Python shell and IPython plugins 
+
+        # Now deal with Python shell and IPython plugins
         shell = get_focus_python_shell()
         if shell is not None:
             # A Python shell widget has focus
@@ -1391,41 +1984,41 @@ class MainWindow(QMainWindow):
                         if self.inspector is not None:
                             self.inspector.set_shell(kw)
                         self.variableexplorer.set_shellwidget_from_id(kwid)
-                        # Setting the kernel widget as current widget for the 
+                        # Setting the kernel widget as current widget for the
                         # external console's tabwidget: this is necessary for
                         # the editor/console link to be working (otherwise,
-                        # features like "Execute in current interpreter" will 
+                        # features like "Execute in current interpreter" will
                         # not work with IPython clients unless the associated
-                        # IPython kernel has been selected in the external 
-                        # console... that's not brilliant, but it works for 
+                        # IPython kernel has been selected in the external
+                        # console... that's not brilliant, but it works for
                         # now: we shall take action on this later
                         self.extconsole.tabwidget.setCurrentWidget(kw)
                         focus_client.get_control().setFocus()
-        
+
     def update_file_menu(self):
         """Update file menu"""
         self.load_temp_session_action.setEnabled(osp.isfile(TEMP_SESSION_PATH))
-        
+
     def update_edit_menu(self):
         """Update edit menu"""
         if self.menuBar().hasFocus():
             return
         # Disabling all actions to begin with
         for child in self.edit_menu.actions():
-            child.setEnabled(False)        
-        
+            child.setEnabled(False)
+
         widget, textedit_properties = get_focus_widget_properties()
         if textedit_properties is None: # widget is not an editor/console
             return
         #!!! Below this line, widget is expected to be a QPlainTextEdit instance
         console, not_readonly, readwrite_editor = textedit_properties
-        
+
         # Editor has focus and there is no file opened in it
         if not console and not_readonly and not self.editor.is_file_opened():
             return
-        
+
         self.selectall_action.setEnabled(True)
-        
+
         # Undo, redo
         self.undo_action.setEnabled( readwrite_editor \
                                      and widget.document().isUndoAvailable() )
@@ -1437,23 +2030,22 @@ class MainWindow(QMainWindow):
         self.copy_action.setEnabled(has_selection)
         self.cut_action.setEnabled(has_selection and not_readonly)
         self.paste_action.setEnabled(not_readonly)
-        self.delete_action.setEnabled(has_selection and not_readonly)
-        
+
         # Comment, uncomment, indent, unindent...
         if not console and not_readonly:
             # This is the editor and current file is writable
             for action in self.editor.edit_menu_actions:
                 action.setEnabled(True)
-        
+
     def update_search_menu(self):
         """Update search menu"""
         if self.menuBar().hasFocus():
-            return        
+            return
         # Disabling all actions to begin with
         for child in [self.find_action, self.find_next_action,
                       self.find_previous_action, self.replace_action]:
             child.setEnabled(False)
-        
+
         widget, textedit_properties = get_focus_widget_properties()
         for action in self.editor.search_menu_actions:
             action.setEnabled(self.editor.isAncestorOf(widget))
@@ -1466,7 +2058,7 @@ class MainWindow(QMainWindow):
             action.setEnabled(True)
         self.replace_action.setEnabled(readwrite_editor)
         self.replace_action.setEnabled(readwrite_editor)
-    
+
     def create_plugins_menu(self):
         order = ['editor', 'console', 'ipython_console', 'variable_explorer',
                  'inspector', None, 'explorer', 'outline_explorer',
@@ -1490,7 +2082,7 @@ class MainWindow(QMainWindow):
             if type(action) is str:
                 actions.remove(action)
         add_actions(self.plugins_menu, actions)
-    
+
     def create_toolbars_menu(self):
         order = ['file_toolbar', 'run_toolbar', 'debug_toolbar',
                  'main_toolbar', 'Global working directory', None,
@@ -1507,7 +2099,7 @@ class MainWindow(QMainWindow):
             else:
                 order.append(action)
         add_actions(self.toolbars_menu, order)
-    
+
     def createPopupMenu(self):
         if self.light:
             menu = self.createPopupMenu()
@@ -1517,38 +2109,44 @@ class MainWindow(QMainWindow):
                       [None, self.help_menu_actions[-1]]
             add_actions(menu, actions)
         return menu
-    
+
     def set_splash(self, message):
         """Set splash message"""
         if message:
             self.debug_print(message)
         self.splash.show()
-        self.splash.showMessage(message, Qt.AlignBottom | Qt.AlignCenter | 
+        self.splash.showMessage(message, Qt.AlignBottom | Qt.AlignCenter |
                                 Qt.AlignAbsolute, QColor(Qt.white))
         QApplication.processEvents()
-    
+
     def remove_tmpdir(self):
         """Remove Spyder temporary directory"""
         shutil.rmtree(programs.TEMPDIR, ignore_errors=True)
-    
+
     def closeEvent(self, event):
         """closeEvent reimplementation"""
         if self.closing(True):
             event.accept()
         else:
             event.ignore()
-            
+
     def resizeEvent(self, event):
         """Reimplement Qt method"""
         if not self.isMaximized() and not self.fullscreen_flag:
             self.window_size = self.size()
         QMainWindow.resizeEvent(self, event)
+
+        # To be used by the tour to be able to resize
+        self.sig_resized.emit(event)
         
     def moveEvent(self, event):
         """Reimplement Qt method"""
         if not self.isMaximized() and not self.fullscreen_flag:
             self.window_position = self.pos()
         QMainWindow.moveEvent(self, event)
+
+        # To be used by the tour to be able to move
+        self.sig_moved.emit(event)
     
     def hideEvent(self, event):
         """Reimplement Qt method"""
@@ -1557,7 +2155,7 @@ class MainWindow(QMainWindow):
                 if plugin.isAncestorOf(self.last_focused_widget):
                     plugin.visibility_changed(True)
         QMainWindow.hideEvent(self, event)
-    
+
     def change_last_focused_widget(self, old, now):
         """To keep track of to the last focused widget"""
         if (now is None and QApplication.activeWindow() is not None):
@@ -1565,22 +2163,33 @@ class MainWindow(QMainWindow):
             self.last_focused_widget = QApplication.focusWidget()
         elif now is not None:
             self.last_focused_widget = now
-    
+
     def closing(self, cancelable=False):
         """Exit tasks"""
         if self.already_closed or self.is_starting_up:
             return True
+        if cancelable and CONF.get('main', 'prompt_on_exit'):
+            reply = QMessageBox.critical(self, 'Spyder',
+                                         'Do you really want to exit?',
+                                         QMessageBox.Yes, QMessageBox.No)
+            if reply == QMessageBox.No:
+                return False
         prefix = ('lightwindow' if self.light else 'window') + '/'
         self.save_current_window_settings(prefix)
         if CONF.get('main', 'single_instance'):
             self.open_files_server.close()
+        for plugin in self.thirdparty_plugins:
+            if not plugin.closing_plugin(cancelable):
+                return False
         for widget in self.widgetlist:
             if not widget.closing_plugin(cancelable):
                 return False
         self.dialog_manager.close_all()
+        if self.toolbars_visible:
+            self.save_visible_toolbars()
         self.already_closed = True
         return True
-        
+
     def add_dockwidget(self, child):
         """Add QDockWidget and toggleViewAction"""
         dockwidget, location = child.create_dockwidget()
@@ -1589,27 +2198,35 @@ class MainWindow(QMainWindow):
                                    QDockWidget.DockWidgetVerticalTitleBar)
         self.addDockWidget(location, dockwidget)
         self.widgetlist.append(child)
-        
+
+    @Slot()
     def close_current_dockwidget(self):
         widget = QApplication.focusWidget()
         for plugin in self.widgetlist:
             if plugin.isAncestorOf(widget):
                 plugin.dockwidget.hide()
                 break
-        
+
+    def toggle_lock_dockwidgets(self, value):
+        """Lock/Unlock dockwidgets"""
+        self.dockwidgets_locked = value
+        self.apply_panes_settings()
+        CONF.set('main', 'panes_locked', value)
+
     def __update_maximize_action(self):
         if self.state_before_maximizing is None:
             text = _("Maximize current pane")
             tip = _("Maximize current pane")
-            icon = "maximize.png"
+            icon = ima.icon('maximize')
         else:
             text = _("Restore current pane")
             tip = _("Restore pane to its original size")
-            icon = "unmaximize.png"
+            icon = ima.icon('unmaximize')
         self.maximize_action.setText(text)
-        self.maximize_action.setIcon(get_icon(icon))
+        self.maximize_action.setIcon(icon)
         self.maximize_action.setToolTip(tip)
-        
+
+    @Slot()
     def maximize_dockwidget(self, restore=False):
         """Shortcut: Ctrl+Alt+Shift+M
         First call: maximize current dockwidget
@@ -1647,14 +2264,17 @@ class MainWindow(QMainWindow):
             self.state_before_maximizing = None
             self.last_plugin.get_focus_widget().setFocus()
         self.__update_maximize_action()
-        
+
     def __update_fullscreen_action(self):
         if self.isFullScreen():
-            icon = "window_nofullscreen.png"
+            icon = ima.icon('window_nofullscreen')
         else:
-            icon = "window_fullscreen.png"
-        self.fullscreen_action.setIcon(get_icon(icon))
-        
+            icon = ima.icon('window_fullscreen')
+        if is_text_string(icon):
+            icon = get_icon(icon)
+        self.fullscreen_action.setIcon(icon)
+
+    @Slot()
     def toggle_fullscreen(self):
         if self.isFullScreen():
             self.fullscreen_flag = False
@@ -1673,6 +2293,7 @@ class MainWindow(QMainWindow):
         if actions is not None:
             add_actions(toolbar, actions)
 
+    @Slot()
     def about(self):
         """About Spyder"""
         versions = get_versions()
@@ -1686,8 +2307,7 @@ class MainWindow(QMainWindow):
             _("About %s") % "Spyder",
             """<b>Spyder %s</b> %s
             <br>The Scientific PYthon Development EnviRonment
-            <p>Copyright © 2009 - 2015 Pierre Raybaut
-            <br>Copyright © 2010 - 2015 The Spyder Development Team
+            <br>Copyright © 2009- The Spyder Development Team
             <br>Licensed under the terms of the MIT License
             <p>Created by Pierre Raybaut
             <br>Developed and maintained by the
@@ -1715,14 +2335,16 @@ class MainWindow(QMainWindow):
                versions['bitness'], versions['qt'], versions['qt_api'],
                versions['qt_api_ver'], versions['system']))
 
+    @Slot()
     def show_dependencies(self):
-        """Show Spyder's Optional Dependencies dialog box"""
+        """Show Spyder's Dependencies dialog box"""
         from spyderlib.widgets.dependencies import DependenciesDialog
         dlg = DependenciesDialog(None)
         dlg.set_data(dependencies.DEPENDENCIES)
         dlg.show()
         dlg.exec_()
 
+    @Slot()
     def report_issue(self):
         if PY3:
             from urllib.parse import quote
@@ -1752,9 +2374,9 @@ class MainWindow(QMainWindow):
 
 * Spyder Version: %s %s
 * Python Version: %s
-* Qt Versions:  %s, %s %s on %s
+* Qt Versions: %s, %s %s on %s
 
-## Optional dependencies
+## Dependencies
 ```
 %s
 ```
@@ -1766,11 +2388,19 @@ class MainWindow(QMainWindow):
        versions['qt_api_ver'],
        versions['system'],
        dependencies.status())
-       
+
         url = QUrl("https://github.com/spyder-ide/spyder/issues/new")
-        url.addEncodedQueryItem("body", quote(issue_template))
+        if PYQT5:
+            from spyderlib.qt.QtCore import QUrlQuery
+            query = QUrlQuery()
+            query.addQueryItem("body", quote(issue_template))
+            url.setQuery(query)
+        else:
+            url.addEncodedQueryItem("body", quote(issue_template))
+            
         QDesktopServices.openUrl(url)
-    
+
+    @Slot()
     def google_group(self):
         url = QUrl("http://groups.google.com/group/spyderlib")
         QDesktopServices.openUrl(url)
@@ -1795,8 +2425,9 @@ class MainWindow(QMainWindow):
             from spyderlib.widgets.editor import EditorWidget
             while not isinstance(plugin, EditorWidget):
                 plugin = plugin.parent()
-            return plugin         
-    
+            return plugin
+
+    @Slot()
     def find(self):
         """Global find callback"""
         plugin = self.get_current_editor_plugin()
@@ -1804,25 +2435,29 @@ class MainWindow(QMainWindow):
             plugin.find_widget.show()
             plugin.find_widget.search_text.setFocus()
             return plugin
-    
+
+    @Slot()
     def find_next(self):
         """Global find next callback"""
         plugin = self.get_current_editor_plugin()
         if plugin is not None:
             plugin.find_widget.find_next()
-            
+
+    @Slot()
     def find_previous(self):
         """Global find previous callback"""
         plugin = self.get_current_editor_plugin()
         if plugin is not None:
             plugin.find_widget.find_previous()
-        
+
+    @Slot()
     def replace(self):
         """Global replace callback"""
         plugin = self.find()
         if plugin is not None:
             plugin.find_widget.show_replace()
 
+    @Slot()
     def global_callback(self):
         """Global callback"""
         widget = QApplication.focusWidget()
@@ -1831,15 +2466,15 @@ class MainWindow(QMainWindow):
         from spyderlib.widgets.editor import TextEditBaseWidget
         if isinstance(widget, TextEditBaseWidget):
             getattr(widget, callback)()
-        
+
     def redirect_internalshell_stdio(self, state):
         if state:
             self.console.shell.interpreter.redirect_stds()
         else:
             self.console.shell.interpreter.restore_stds()
-        
+
     def open_external_console(self, fname, wdir, args, interact, debug, python,
-                              python_args, systerm):
+                              python_args, systerm, post_mortem=False):
         """Open external console"""
         if systerm:
             # Running script in an external system terminal
@@ -1857,7 +2492,7 @@ class MainWindow(QMainWindow):
             self.extconsole.start(
                 fname=to_text_string(fname), wdir=to_text_string(wdir),
                 args=to_text_string(args), interact=interact,
-                debug=debug, python=python,
+                debug=debug, python=python, post_mortem=post_mortem,
                 python_args=to_text_string(python_args) )
 
     def execute_in_external_console(self, lines, focus_to_editor):
@@ -1876,9 +2511,6 @@ class MainWindow(QMainWindow):
         if focus_to_editor:
             self.editor.visibility_changed(True)
 
-    def new_file(self, text):
-        self.editor.new(text=text)
-        
     def open_file(self, fname, external=False):
         """
         Open filename with the appropriate application
@@ -1896,7 +2528,7 @@ class MainWindow(QMainWindow):
         elif not external:
             fname = file_uri(fname)
             programs.start_file(fname)
-    
+
     def open_external_file(self, fname):
         """
         Open external files that can be handled either by the Editor or the
@@ -1912,7 +2544,7 @@ class MainWindow(QMainWindow):
     def get_spyder_pythonpath(self):
         """Return Spyder PYTHONPATH"""
         return self.path+self.project_path
-        
+
     def add_path_to_sys_path(self):
         """Add Spyder path to sys.path"""
         for path in reversed(self.get_spyder_pythonpath()):
@@ -1923,31 +2555,32 @@ class MainWindow(QMainWindow):
         sys_path = sys.path
         while sys_path[1] in self.get_spyder_pythonpath():
             sys_path.pop(1)
-        
+
+    @Slot()
     def path_manager_callback(self):
         """Spyder path manager"""
         from spyderlib.widgets.pathmanager import PathManager
         self.remove_path_from_sys_path()
         project_pathlist = self.projectexplorer.get_pythonpath()
         dialog = PathManager(self, self.path, project_pathlist, sync=True)
-        self.connect(dialog, SIGNAL('redirect_stdio(bool)'),
-                     self.redirect_internalshell_stdio)
+        dialog.redirect_stdio.connect(self.redirect_internalshell_stdio)
         dialog.exec_()
         self.add_path_to_sys_path()
         encoding.writelines(self.path, self.SPYDER_PATH) # Saving path
-        self.emit(SIGNAL("pythonpath_changed()"))
-        
+        self.sig_pythonpath_changed.emit()
+
     def pythonpath_changed(self):
         """Project Explorer PYTHONPATH contribution has changed"""
         self.remove_path_from_sys_path()
         self.project_path = self.projectexplorer.get_pythonpath()
         self.add_path_to_sys_path()
-        self.emit(SIGNAL("pythonpath_changed()"))
-    
+        self.sig_pythonpath_changed.emit()
+
+    @Slot()
     def win_env(self):
         """Show Windows current user environment variables"""
         self.dialog_manager.show(WinUserEnvDialog(self))
-        
+
     #---- Preferences
     def apply_settings(self):
         """Apply settings changed in 'Preferences' dialog box"""
@@ -1969,30 +2602,42 @@ class MainWindow(QMainWindow):
         if CONF.get('main', 'animated_docks'):
             default = default|QMainWindow.AnimatedDocks
         self.setDockOptions(default)
-        
+
+        self.apply_panes_settings()
+        self.apply_statusbar_settings()
+
+    def apply_panes_settings(self):
+        """Update dockwidgets features settings"""
+        # Update toggle action on menu
         for child in self.widgetlist:
             features = child.FEATURES
             if CONF.get('main', 'vertical_dockwidget_titlebars'):
-                features = features|QDockWidget.DockWidgetVerticalTitleBar
+                features = features | QDockWidget.DockWidgetVerticalTitleBar
+            if not self.dockwidgets_locked:
+                features = features | QDockWidget.DockWidgetMovable
             child.dockwidget.setFeatures(features)
             child.update_margins()
-        
-        self.apply_statusbar_settings()
-        
+
     def apply_statusbar_settings(self):
         """Update status bar widgets settings"""
-        for widget, name in ((self.mem_status, 'memory_usage'),
-                             (self.cpu_status, 'cpu_usage')):
-            if widget is not None:
-                widget.setVisible(CONF.get('main', '%s/enable' % name))
-                widget.set_interval(CONF.get('main', '%s/timeout' % name))
-        
+        show_status_bar = CONF.get('main', 'show_status_bar')
+        self.statusBar().setVisible(show_status_bar)
+
+        if show_status_bar:
+            for widget, name in ((self.mem_status, 'memory_usage'),
+                                 (self.cpu_status, 'cpu_usage')):
+                if widget is not None:
+                    widget.setVisible(CONF.get('main', '%s/enable' % name))
+                    widget.set_interval(CONF.get('main', '%s/timeout' % name))
+        else:
+            return
+
+    @Slot()
     def edit_preferences(self):
         """Edit Spyder preferences"""
         from spyderlib.plugins.configdialog import ConfigDialog
         dlg = ConfigDialog(self)
-        self.connect(dlg, SIGNAL("size_change(QSize)"),
-                     lambda s: self.set_prefs_size(s))
+        dlg.size_change.connect(self.set_prefs_size)
         if self.prefs_dialog_size is not None:
             dlg.resize(self.prefs_dialog_size)
         for PrefPageClass in self.general_prefs:
@@ -2005,21 +2650,23 @@ class MainWindow(QMainWindow):
                        self.onlinehelp, self.explorer, self.findinfiles
                        ]+self.thirdparty_plugins:
             if plugin is not None:
-                widget = plugin.create_configwidget(dlg)
-                if widget is not None:
-                    dlg.add_page(widget)
+                try:
+                    widget = plugin.create_configwidget(dlg)
+                    if widget is not None:
+                        dlg.add_page(widget)
+                except Exception:
+                    traceback.print_exc(file=sys.stderr)
         if self.prefs_index is not None:
             dlg.set_current_index(self.prefs_index)
         dlg.show()
         dlg.check_all_settings()
-        self.connect(dlg.pages_widget, SIGNAL("currentChanged(int)"),
-                     self.__preference_page_changed)
+        dlg.pages_widget.currentChanged.connect(self.__preference_page_changed)
         dlg.exec_()
-        
+
     def __preference_page_changed(self, index):
         """Preference page index has changed"""
         self.prefs_index = index
-    
+
     def set_prefs_size(self, size):
         """Save preferences dialog size"""
         self.prefs_dialog_size = size
@@ -2033,14 +2680,13 @@ class MainWindow(QMainWindow):
         """
         self.shortcut_data.append( (qaction_or_qshortcut,
                                     context, name, default) )
-        self.apply_shortcuts()
 
     def remove_deprecated_shortcuts(self):
         """Remove deprecated shortcuts"""
         data = [(context, name) for (qobject, context, name,
                 default) in self.shortcut_data]
         remove_deprecated_shortcuts(data)
-        
+
     def apply_shortcuts(self):
         """Apply shortcuts settings to all widgets/plugins"""
         toberemoved = []
@@ -2059,6 +2705,7 @@ class MainWindow(QMainWindow):
             self.shortcut_data.pop(index)
 
     #---- Sessions
+    @Slot()
     def load_session(self, filename=None):
         """Load session"""
         if filename is None:
@@ -2070,7 +2717,8 @@ class MainWindow(QMainWindow):
                 return
         if self.close():
             self.next_session_name = filename
-    
+
+    @Slot()
     def save_session(self):
         """Save session and quit application"""
         self.redirect_internalshell_stdio(False)
@@ -2080,7 +2728,7 @@ class MainWindow(QMainWindow):
         if filename:
             if self.close():
                 self.save_session_name = filename
-    
+
     def start_open_files_server(self):
         self.open_files_server.setsockopt(socket.SOL_SOCKET,
                                           socket.SO_REUSEADDR, 1)
@@ -2098,13 +2746,186 @@ class MainWindow(QMainWindow):
                 # To avoid a traceback after closing on Windows
                 if e.args[0] == eintr:
                     continue
+                # handle a connection abort on close error
+                enotsock = (errno.WSAENOTSOCK if os.name == 'nt'
+                            else errno.ENOTSOCK)
+                if e.args[0] in [errno.ECONNABORTED, enotsock]:
+                    return
                 raise
             fname = req.recv(1024)
             if not self.light:
                 fname = fname.decode('utf-8')
-                self.emit(SIGNAL('open_external_file(QString)'), fname)
+                self.sig_open_external_file.emit(fname)
             req.sendall(b' ')
 
+    # ---- Quit and restart, and reset spyder defaults
+    def reset_spyder(self):
+        """
+        Quit and reset Spyder and then Restart application.
+        """
+        answer = QMessageBox.warning(self, _("Warning"),
+             _("Spyder will restart and reset to default settings: <br><br>"
+               "Do you want to continue?"),
+             QMessageBox.Yes | QMessageBox.No)
+        if answer == QMessageBox.Yes:
+            self.restart(reset=True)
+
+    def restart(self, reset=False):
+        """
+        Quit and Restart Spyder application.
+
+        If reset True it allows to reset spyder on restart.
+        """
+        # Get start path to use in restart script
+        spyder_start_directory = get_module_path('spyderlib')
+        restart_script = osp.join(spyder_start_directory, 'restart_app.py')
+
+        # Get any initial argument passed when spyder was started
+        # Note: Variables defined in bootstrap.py and spyderlib\start_app.py
+        env = os.environ.copy()
+        bootstrap_args = env.pop('SPYDER_BOOTSTRAP_ARGS', None)
+        spyder_args = env.pop('SPYDER_ARGS')
+
+        # Get current process and python running spyder
+        pid = os.getpid()
+        python = sys.executable
+
+        # Check if started with bootstrap.py
+        if bootstrap_args is not None:
+            spyder_args = bootstrap_args
+            is_bootstrap = True
+        else:
+            is_bootstrap = False
+
+        # Pass variables as environment variables (str) to restarter subprocess
+        env['SPYDER_ARGS'] = spyder_args
+        env['SPYDER_PID'] = str(pid)
+        env['SPYDER_IS_BOOTSTRAP'] = str(is_bootstrap)
+        env['SPYDER_RESET'] = str(reset)
+
+        if DEV:
+            if os.name == 'nt':
+                env['PYTHONPATH'] = ';'.join(sys.path)
+            else:
+                env['PYTHONPATH'] = ':'.join(sys.path)
+
+        # Build the command and popen arguments depending on the OS
+        if os.name == 'nt':
+            # Hide flashing command prompt
+            startupinfo = subprocess.STARTUPINFO()
+            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+            shell = False
+        else:
+            startupinfo = None
+            shell = True
+
+        command = '"{0}" "{1}"'
+        command = command.format(python, restart_script)
+
+        try:
+            if self.closing(True):
+                subprocess.Popen(command, shell=shell, env=env,
+                                 startupinfo=startupinfo)
+                self.console.quit()
+        except Exception as error:
+            # If there is an error with subprocess, Spyder should not quit and
+            # the error can be inspected in the internal console
+            print(error)
+            print(command)
+
+    # ---- Interactive Tours
+    def show_tour(self, index):
+        """ """
+        frames = self.tours_available[index]
+        self.tour.set_tour(index, frames, self)
+        self.tour.start_tour()
+
+    # ---- Check for Spyder Updates
+    def _check_updates_ready(self):
+        """Called by WorkerUpdates when ready"""
+        from spyderlib.widgets.helperwidgets import MessageCheckBox
+
+        # feedback` = False is used on startup, so only positive feedback is
+        # given. `feedback` = True is used when after startup (when using the
+        # menu action, and gives feeback if updates are, or are not found.
+        feedback = self.give_updates_feedback
+
+        # Get results from worker
+        update_available = self.worker_updates.update_available
+        latest_release = self.worker_updates.latest_release
+        error_msg = self.worker_updates.error
+
+        url_r = 'https://github.com/spyder-ide/spyder/releases'
+        url_i = 'http://pythonhosted.org/spyder/installation.html'
+
+        # Define the custom QMessageBox
+        box = MessageCheckBox()
+        box.setWindowTitle(_("Spyder updates"))
+        box.set_checkbox_text(_("Check for updates on startup"))
+        box.setStandardButtons(QMessageBox.Ok)
+        box.setDefaultButton(QMessageBox.Ok)
+        box.setIcon(QMessageBox.Information)
+
+        # Adjust the checkbox depending on the stored configuration
+        section, option = 'main', 'check_updates_on_startup'
+        check_updates = CONF.get(section, option)
+        box.set_checked(check_updates)
+
+        if error_msg is not None:
+            msg = error_msg
+            box.setText(msg)
+            box.set_check_visible(False)
+            box.exec_()
+            check_updates = box.is_checked()
+        else:
+            if update_available:
+                msg = _("<b>Spyder %s is available!</b> <br><br>Please use "
+                        "your package manager to update Spyder or go to our "
+                        "<a href=\"%s\">Releases</a> page to download this "
+                        "new version. <br><br>If you are not sure how to "
+                        "proceed to update Spyder please refer to our "
+                        " <a href=\"%s\">Installation</a> instructions."
+                        "") % (latest_release, url_r, url_i)
+                box.setText(msg)
+                box.set_check_visible(True)
+                box.exec_()
+                check_updates = box.is_checked()
+            elif feedback:
+                msg = _("Spyder is up to date.")
+                box.setText(msg)
+                box.set_check_visible(False)
+                box.exec_()
+                check_updates = box.is_checked()
+
+        # Update checkbox based on user interaction
+        CONF.set(section, option, check_updates)
+
+        # Enable check_updates_action after the thread has finished
+        self.check_updates_action.setDisabled(False)
+        
+        # Provide feeback when clicking menu if check on startup is on
+        self.give_updates_feedback = True
+
+    def check_updates(self):
+        """
+        Check for spyder updates on github releases using a QThread.
+        """
+        from spyderlib.workers.updates import WorkerUpdates
+
+        # Disable check_updates_action while the thread is working
+        self.check_updates_action.setDisabled(True)
+
+        if self.thread_updates is not None:
+            self.thread_updates.terminate()
+
+        self.thread_updates = QThread(self)
+        self.worker_updates = WorkerUpdates(self)
+        self.worker_updates.sig_ready.connect(self._check_updates_ready)
+        self.worker_updates.sig_ready.connect(self.thread_updates.quit)
+        self.worker_updates.moveToThread(self.thread_updates)
+        self.thread_updates.started.connect(self.worker_updates.start)
+        self.thread_updates.start()
+
 
 #==============================================================================
 # Utilities to create the 'main' function
@@ -2115,7 +2936,7 @@ def initialize():
     # MAIN_APP, created above to show our splash screen as early as
     # possible
     app = qapplication()
-    
+
     #----Monkey patching PyQt4.QtGui.QApplication
     class FakeQApplication(QApplication):
         """Spyder's fake QApplication"""
@@ -2127,23 +2948,23 @@ def initialize():
             pass
     from spyderlib.qt import QtGui
     QtGui.QApplication = FakeQApplication
-    
+
     #----Monkey patching rope
     try:
         from spyderlib import rope_patch
         rope_patch.apply()
     except ImportError:
-        # rope 0.9.2/0.9.3 is not installed
+        # rope is not installed
         pass
-    
+
     #----Monkey patching sys.exit
     def fake_sys_exit(arg=[]):
         pass
     sys.exit = fake_sys_exit
-    
+
     # Removing arguments from sys.argv as in standard Python interpreter
     sys.argv = ['']
-    
+
     # Selecting Qt4 backend for Enthought Tool Suite (if installed)
     try:
         from enthought.etsconfig.api import ETSConfig
@@ -2151,44 +2972,13 @@ def initialize():
     except ImportError:
         pass
 
-    #----Monkey patching rope (if installed)
-    #       Compatibility with new Mercurial API (>= 1.3).
-    #       New versions of rope (> 0.9.2) already handle this issue
-    try:
-        import rope
-        if rope.VERSION == '0.9.2':
-            import rope.base.fscommands
-            
-            class MercurialCommands(rope.base.fscommands.MercurialCommands):
-                def __init__(self, root):
-                    self.hg = self._import_mercurial()
-                    self.normal_actions = rope.base.fscommands.FileSystemCommands()
-                    try:
-                        self.ui = self.hg.ui.ui(
-                            verbose=False, debug=False, quiet=True,
-                            interactive=False, traceback=False,
-                            report_untrusted=False)
-                    except:
-                        self.ui = self.hg.ui.ui()
-                        self.ui.setconfig('ui', 'interactive', 'no')
-                        self.ui.setconfig('ui', 'debug', 'no')
-                        self.ui.setconfig('ui', 'traceback', 'no')
-                        self.ui.setconfig('ui', 'verbose', 'no')
-                        self.ui.setconfig('ui', 'report_untrusted', 'no')
-                        self.ui.setconfig('ui', 'quiet', 'yes')
-                    self.repo = self.hg.hg.repository(self.ui, root)
-                
-            rope.base.fscommands.MercurialCommands = MercurialCommands
-    except ImportError:
-        pass
-    
     return app
 
 
 class Spy(object):
     """
     Inspect Spyder internals
-    
+
     Attributes:
         app       Reference to main QApplication object
         window    Reference to spyder.MainWindow widget
@@ -2223,7 +3013,7 @@ def run_spyder(app, options, args):
 
     main.show()
     main.post_visible_setup()
-    
+
     if main.console:
         main.console.shell.interpreter.namespace['spy'] = \
                                                     Spy(app=app, window=main)
@@ -2239,13 +3029,11 @@ def run_spyder(app, options, args):
 
     # Open external files with our Mac app
     if running_in_mac_app():
-        main.connect(app, SIGNAL('open_external_file(QString)'),
-                     lambda fname: main.open_external_file(fname))
-    
+        app.sig_open_external_file.connect(main.open_external_file)
+
     # To give focus again to the last focused widget after restoring
     # the window
-    main.connect(app, SIGNAL('focusChanged(QWidget*, QWidget*)'),
-                 main.change_last_focused_widget)
+    app.focusChanged.connect(main.change_last_focused_widget)
 
     app.exec_()
     return main
@@ -2262,19 +3050,19 @@ def __remove_temp_session():
 def main():
     """Session manager"""
     __remove_temp_session()
-    
+
     # **** Collect command line options ****
     # Note regarding Options:
     # It's important to collect options before monkey patching sys.exit,
     # otherwise, optparse won't be able to exit if --help option is passed
     options, args = get_options()
-    
+
     if set_attached_console_visible is not None:
         set_attached_console_visible(DEBUG or options.show_console\
                                      or options.reset_session\
                                      or options.reset_to_defaults\
                                      or options.optimize)
-    
+
     app = initialize()
     if options.reset_session:
         # <!> Remove all configuration files!
@@ -2292,7 +3080,7 @@ def main():
                                    args=[spyderlib.__path__[0]], p_args=['-O'])
         return
 
-    if CONF.get('main', 'crash', False):
+    if CONF.get('main', 'crash', False) and not DEV:
         CONF.set('main', 'crash', False)
         SPLASH.hide()
         QMessageBox.information(None, "Spyder",
@@ -2312,7 +3100,7 @@ def main():
             "Your feedback will always be greatly appreciated."
             "" % (get_conf_path(), __project_url__,
                   __forum_url__, __project_url__))
-        
+
     next_session_name = options.startup_session
     while is_text_string(next_session_name):
         if next_session_name:
@@ -2333,7 +3121,7 @@ def main():
             CONF.set('main', 'crash', True)
             import traceback
             traceback.print_exc(file=STDERR)
-            traceback.print_exc(file=open('spyder_crash.log', 'w'))            
+            traceback.print_exc(file=open('spyder_crash.log', 'w'))
         if mainwindow is None:
             # An exception occured
             SPLASH.hide()
diff --git a/spyderlib/start_app.py b/spyderlib/start_app.py
index da3de3f..43bfc5f 100644
--- a/spyderlib/start_app.py
+++ b/spyderlib/start_app.py
@@ -1,17 +1,18 @@
 # -*- coding: utf-8 -*-
 
+# Std imports
+import atexit
 import os
 import os.path as osp
+import random
 import socket
+import sys
 import time
-import atexit
-import random
 
 # Local imports
 from spyderlib.cli_options import get_options
-from spyderlib.baseconfig import get_conf_path, running_in_mac_app
-from spyderlib.config import CONF
-from spyderlib.baseconfig import DEV, TEST
+from spyderlib.config.base import get_conf_path, running_in_mac_app, DEV, TEST
+from spyderlib.config.main import CONF
 from spyderlib.utils.external import lockfile
 from spyderlib.py3compat import is_unicode
 
@@ -53,7 +54,7 @@ def main():
     options to the application.
     """
     # Renaming old configuration files (the '.' prefix has been removed)
-    # (except for .spyder.ini --> spyder.ini, which is done in userconfig.py)
+    # (except for .spyder.ini --> spyder.ini, which is done in config/user.py)
     if DEV is None:
         cpath = get_conf_path()
         for fname in os.listdir(cpath):
@@ -67,6 +68,9 @@ def main():
     # Parse command line options
     options, args = get_options()
 
+    # Store variable to be used in self.restart (restart spyder instance)
+    os.environ['SPYDER_ARGS'] = str(sys.argv[1:])
+
     if CONF.get('main', 'single_instance') and not options.new_instance \
       and not running_in_mac_app():
         # Minimal delay (0.1-0.2 secs) to avoid that several
diff --git a/spyderlib/tour.py b/spyderlib/tour.py
new file mode 100644
index 0000000..65cbf52
--- /dev/null
+++ b/spyderlib/tour.py
@@ -0,0 +1,1286 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2009-2013 Pierre Raybaut
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+"""Spyder interactive tours"""
+
+# pylint: disable=C0103
+# pylint: disable=R0903
+# pylint: disable=R0911
+# pylint: disable=R0201
+
+from __future__ import division
+
+import sys
+
+from spyderlib.qt.QtGui import (QColor, QLayout, QMenu, QApplication,
+                                QPainter, QIcon, QBrush, QToolButton,
+                                QPixmap, QLabel, QWidget, QVBoxLayout,
+                                QHBoxLayout, QDialog, QMainWindow, QAction,
+                                QPushButton, QPainterPath, QSpacerItem, QPen,
+                                QGraphicsOpacityEffect, QRegion, QComboBox)
+from spyderlib.qt.QtCore import (Qt, Signal, QPoint, QRectF,
+                                 QPropertyAnimation, QEasingCurve)
+
+# Local import
+from spyderlib.config.base import _, get_image_path
+from spyderlib.utils.qthelpers import (create_action, add_actions)
+
+# FIXME: Known issues
+# How to handle if an specific dockwidget does not exists/load, like ipython
+# on python3.3, should that frame be removed? should it display a warning?
+
+class SpyderWidgets(object):
+    """List of supported widgets to highlight/decorate"""
+    # Panes
+    external_console = 'extconsole'
+    ipython_console = 'ipyconsole'
+    editor = 'editor'
+    editor_line_number_area = 'editor.get_current_editor().linenumberarea'
+    editor_scroll_flag_area = 'editor.get_current_editor().scrollflagarea'
+    file_explorer = 'explorer'
+    object_inspector = 'inspector'
+    variable_explorer = 'variableexplorer'
+    history_log = "historylog"
+
+    # Toolbars
+    toolbars = ''
+    toolbars_active = ''
+    toolbar_file = ''
+    toolbar_edit = ''
+    toolbar_run = ''
+    toolbar_debug = ''
+    toolbar_main = ''
+
+    status_bar = ''
+    menu_bar = ''
+    menu_file = ''
+    menu_edit = ''
+
+
+def get_tours(index=None):
+    """
+    Get the list of available tours (if index=None), or the your given by
+    index
+    """
+    return get_tour(index)
+
+
+def get_tour(index):
+    """
+    This function generates a list of tours.
+    
+    The index argument is used to retrieve a particular tour. If None is
+    passed, it will return the full list of tours. If instead -1 is given,
+    this function will return a test tour
+
+    To add more tours a new variable needs to be created to hold the list of
+    dicts and the tours variable at the bottom of this function needs to be
+    updated accordingly
+    """
+    sw = SpyderWidgets
+    qtconsole_link = "http://ipython.org/ipython-doc/stable/interactive/qtconsole.html"
+
+    # This test should serve as example of keys to use in the tour frame dics
+    test = [{'title': "Welcome to Spyder introduction tour",
+             'content': "<b>Spyder</b> is an interactive development \
+                         environment. This tip panel supports rich text. <br>\
+                         <br> it also supports image insertion to the right so\
+                         far",
+             'image': 'tour-spyder-logo.png'},
+
+            {'title': "Widget display",
+             'content': ("This show how a widget is displayed. The tip panel "
+                         "is adjusted based on the first widget in the list"),
+             'widgets': ['button1'],
+             'decoration': ['button2'],
+             'interact': True},
+
+            {'title': "Widget display",
+             'content': ("This show how a widget is displayed. The tip panel "
+                         "is adjusted based on the first widget in the list"),
+             'widgets': ['button1'],
+             'decoration': ['button1'],
+             'interact': True},
+
+            {'title': "Widget display",
+             'content': ("This show how a widget is displayed. The tip panel "
+                         "is adjusted based on the first widget in the list"),
+             'widgets': ['button1'],
+             'interact': True},
+
+            {'title': "Widget display and highlight",
+             'content': "This shows how a highlighted widget looks",
+             'widgets': ['button'],
+             'decoration': ['button'],
+             'interact': False},
+            ]
+
+    intro = [{'title': _("Welcome to the Introduction tour"),
+              'content': _("<b>Spyder</b> is a powerful Interactive "
+                           "Development Environment (or IDE) for the Python "
+                           "programming language.<br><br>"
+                           "Here we are going to guide you through its most "
+                           "important features.<br><br>"
+                           "Please use the arrow keys or click on the buttons "
+                           "below to move along the tour."),
+              'image': 'tour-spyder-logo.png'},
+
+             {'title': _("The Editor"),
+              'content': _("This is the pane where you write Python code before "
+                           "evaluating it. You can get automatic suggestions "
+                           "and completions while writing, by pressing the "
+                           "<b>Tab</b> key next to a given text.<br><br>"
+                           "The Editor comes "
+                           "with a line number area (highlighted here in red), "
+                           "where Spyder shows warnings and syntax errors. They "
+                           "can help you to detect potential problems before "
+                           "running the code.<br><br>"
+                           "You can also set debug breakpoints in the line "
+                           "number area, by doing a double click next to "
+                           "a non-empty line."),
+              'widgets': [sw.editor],
+              'decoration': [sw.editor_line_number_area]},
+
+             {'title': _("The IPython console"),
+              'content': _("This is one of panes where you can run or "
+                           "execute the code you wrote on the Editor. To do it "
+                           "you need to press the <b>F5</b> key.<br><br>"
+                           "This console comes with several "
+                           "useful features that greatly improve your "
+                           "programming workflow (like syntax highlighting and "
+                           "inline plots). If you want to know more about them, "
+                           "please follow this <a href=\"{0}\">link</a>.<br><br>"
+                           "Please click on the button below to run some simple "
+                           "code in this console. This will be useful to show "
+                           "you other important features.").format(
+                           qtconsole_link),
+              'widgets': [sw.ipython_console],
+              'run': ["li = list(range(100))", "d = {'a': 1, 'b': 2}"]
+              },
+              
+             {'title': _("The Variable Explorer"),
+              'content': _("In this pane you can view and edit the variables "
+                           "generated during the execution of a program, or "
+                           "those entered directly in one of Spyder "
+                           "consoles.<br><br>"
+                           "As you can see, the Variable Explorer is showing "
+                           "the variables generated during the last step of "
+                           "this tour. By doing a double-click on any "
+                           "of them, a new window will be opened, where you "
+                           "can inspect and modify their contents."),
+              'widgets': [sw.variable_explorer],
+              'interact': True},
+
+             {'title': _("The Python console"),
+              'content': _("You can also run your code on a Python console. "
+                           "These consoles are useful because they let you "
+                           "run a file in a console dedicated only to it."
+                           "To select this behavior, please press the <b>F6</b> "
+                           "key.<br><br>"
+                           "By pressing the button below and then focusing the "
+                           "Variable Explorer, you will notice that "
+                           "Python consoles are also connected to that pane, "
+                           "and that the Variable Explorer only shows "
+                           "the variables of the currently focused console."),
+              'widgets': [sw.external_console],
+              'run': ["a = 2", "s='Hello, world!'"],
+              },
+
+             {'title': _("The Object Inspector"),
+              'content': _("This pane displays documentation of the "
+                           "functions, classes, methods or modules you are "
+                           "currently using in the Editor or the Consoles.<br><br>"
+                           "To use it, you need to press <b>Ctrl+I</b> in "
+                           "front of an object. If that object has some "
+                           "documentation associated with it, it will be "
+                           "displayed here."),
+              'widgets': [sw.object_inspector],
+              'interact': True},
+
+             {'title': _("The File Explorer"),
+              'content': _("This pane lets you navigate through the directories "
+                           "and files present in your computer.<br><br>"
+                           "You can also open any of these files with its "
+                           "corresponding application, by doing a double "
+                           "click on it.<br><br>"
+                           "There is one exception to this rule: plain-text "
+                           "files will always be opened in the Spyder Editor."),
+              'widgets': [sw.file_explorer],
+              'interact': True},
+
+             {'title': _("The History Log"),
+              'content': _("This pane records all commands introduced in "
+                           "the Python and IPython consoles."),
+              'widgets': [sw.history_log],
+              'interact': True},
+             ]
+
+#                   ['The run toolbar',
+#                       'Should be short',
+#                       ['self.run_toolbar'], None],
+#                   ['The debug toolbar',
+#                       '',
+#                       ['self.debug_toolbar'], None],
+#                   ['The main toolbar',
+#                       '',
+#                       ['self.main_toolbar'], None],
+#                   ['The editor',
+#                       'Spyder has differnet bla bla bla',
+#                       ['self.editor.dockwidget'], None],
+#                   ['The editor',
+#                       'Spyder has differnet bla bla bla',
+#                       ['self.outlineexplorer.dockwidget'], None],
+#
+#                   ['The menu bar',
+#                       'Spyder has differnet bla bla bla',
+#                       ['self.menuBar()'], None],
+#
+#                   ['The menu bar',
+#                       'Spyder has differnet bla bla bla',
+#                       ['self.statusBar()'], None],
+#
+#
+#                   ['The toolbars!',
+#                       'Spyder has differnet bla bla bla',
+#                       ['self.variableexplorer.dockwidget'], None],
+#                   ['The toolbars MO!',
+#                       'Spyder has differnet bla bla bla',
+#                       ['self.extconsole.dockwidget'], None],
+#                   ['The whole window?!',
+#                       'Spyder has differnet bla bla bla',
+#                       ['self'], None],
+#                   ['Lets try something!',
+#                       'Spyder has differnet bla bla bla',
+#                       ['self.extconsole.dockwidget',
+#                        'self.variableexplorer.dockwidget'], None]
+#
+#                      ]
+
+    feat30 = [{'title': "New features in Spyder 3.0",
+               'content': _("<b>Spyder</b> is an interactive development "
+                            "environment based on bla"),
+               'image': 'spyder.png'},
+
+              {'title': _("Welcome to Spyder introduction tour"),
+               'content': _("Spyder is an interactive development environment "
+                            "based on bla"),
+               'widgets': ['variableexplorer']},
+              ]
+
+    tours = [{'name': _('Introduction tour'), 'tour': intro},
+             {'name': _('New features in version 3.0'), 'tour': feat30}]
+
+    if index is None:
+        return tours
+    elif index == -1:
+        return [test]
+    else:
+        return [tours[index]]
+
+
+class FadingDialog(QDialog):
+    """A general fade in/fade out QDialog with some builtin functions"""
+    sig_key_pressed = Signal()
+
+    def __init__(self, parent, opacity, duration, easing_curve):
+        super(FadingDialog, self).__init__(parent)
+
+        self.parent = parent
+        self.opacity_min = min(opacity)
+        self.opacity_max = max(opacity)
+        self.duration_fadein = duration[0]
+        self.duration_fadeout = duration[-1]
+        self.easing_curve_in = easing_curve[0]
+        self.easing_curve_out = easing_curve[-1]
+        self.effect = None
+        self.anim = None
+
+        self._fade_running = False
+        self._funcs_before_fade_in = []
+        self._funcs_after_fade_in = []
+        self._funcs_before_fade_out = []
+        self._funcs_after_fade_out = []
+
+        self.setModal(False)
+
+    def _run(self, funcs):
+        """ """
+        for func in funcs:
+            func()
+
+    def _run_before_fade_in(self):
+        """ """
+        self._run(self._funcs_before_fade_in)
+
+    def _run_after_fade_in(self):
+        """ """
+        self._run(self._funcs_after_fade_in)
+
+    def _run_before_fade_out(self):
+        """ """
+        self._run(self._funcs_before_fade_out)
+
+    def _run_after_fade_out(self):
+        """ """
+        self._run(self._funcs_after_fade_out)
+
+    def _set_fade_finished(self):
+        """ """
+        self._fade_running = False
+
+    def _fade_setup(self):
+        """ """
+        self._fade_running = True
+        self.effect = QGraphicsOpacityEffect(self)
+        self.setGraphicsEffect(self.effect)
+        self.anim = QPropertyAnimation(self.effect, "opacity")
+
+    # --- public api
+    def fade_in(self, on_finished_connect):
+        """ """
+        self._run_before_fade_in()
+        self._fade_setup()
+        self.show()
+        self.raise_()
+        self.anim.setEasingCurve(self.easing_curve_in)
+        self.anim.setStartValue(self.opacity_min)
+        self.anim.setEndValue(self.opacity_max)
+        self.anim.setDuration(self.duration_fadein)
+        self.anim.finished.connect(on_finished_connect)
+        self.anim.finished.connect(self._set_fade_finished)
+        self.anim.finished.connect(self._run_after_fade_in)
+        self.anim.start()
+
+    def fade_out(self, on_finished_connect):
+        """ """
+        self._run_before_fade_out()
+        self._fade_setup()
+        self.anim.setEasingCurve(self.easing_curve_out)
+        self.anim.setStartValue(self.opacity_max)
+        self.anim.setEndValue(self.opacity_min)
+        self.anim.setDuration(self.duration_fadeout)
+        self.anim.finished.connect(on_finished_connect)
+        self.anim.finished.connect(self._set_fade_finished)
+        self.anim.finished.connect(self._run_after_fade_out)
+        self.anim.start()
+
+    def is_fade_running(self):
+        """ """
+        return self._fade_running
+
+    def set_funcs_before_fade_in(self, funcs):
+        """ """
+        self._funcs_before_fade_in = funcs
+
+    def set_funcs_after_fade_in(self, funcs):
+        """ """
+        self._funcs_after_fade_in = funcs
+
+    def set_funcs_before_fade_out(self, funcs):
+        """ """
+        self._funcs_before_fade_out = funcs
+
+    def set_funcs_after_fade_out(self, funcs):
+        """ """
+        self._funcs_after_fade_out = funcs
+
+
+class FadingCanvas(FadingDialog):
+    """The black semi transparent canvas that covers the application"""
+    def __init__(self, parent, opacity, duration, easing_curve, color):
+        super(FadingCanvas, self).__init__(parent, opacity, duration,
+                                           easing_curve)
+        self.parent = parent
+
+        self.color = color              # Canvas color
+        self.color_decoration = Qt.red  # Decoration color
+        self.stroke_decoration = 2      # width in pixels for decoration
+
+        self.region_mask = None
+        self.region_subtract = None
+        self.region_decoration = None
+
+        self.widgets = None             # The widget to uncover
+        self.decoration = None          # The widget to draw decoration
+        self.interaction_on = False
+
+        self.path_current = None
+        self.path_subtract = None
+        self.path_full = None
+        self.path_decoration = None
+
+        # widget setup
+        self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint)
+        self.setAttribute(Qt.WA_TranslucentBackground)
+        self.setAttribute(Qt.WA_TransparentForMouseEvents)
+        self.setModal(False)
+        self.setFocusPolicy(Qt.NoFocus)
+
+        self.set_funcs_before_fade_in([self.update_canvas])
+        self.set_funcs_after_fade_out([lambda: self.update_widgets(None),
+                                       lambda: self.update_decoration(None)])
+
+    def set_interaction(self, value):
+        """ """
+        self.interaction_on = value
+
+    def update_canvas(self):
+        """ """
+        w, h = self.parent.size().width(), self.parent.size().height()
+
+        self.path_full = QPainterPath()
+        self.path_subtract = QPainterPath()
+        self.path_decoration = QPainterPath()
+        self.region_mask = QRegion(0, 0, w, h)
+
+        self.path_full.addRect(0, 0, w, h)
+
+        # Add the path
+        if self.widgets is not None:
+            for widget in self.widgets:
+                temp_path = QPainterPath()
+                # if widget is not found... find more general way to handle
+                if widget is not None:
+                    widget.raise_()
+                    widget.show()
+                    geo = widget.frameGeometry()
+                    width, height = geo.width(), geo.height()
+                    point = widget.mapTo(self.parent, QPoint(0, 0))
+                    x, y = point.x(), point.y()
+    
+                    temp_path.addRect(QRectF(x, y, width, height))
+    
+                    temp_region = QRegion(x, y, width, height)
+
+                if self.interaction_on:
+                    self.region_mask = self.region_mask.subtracted(temp_region)
+                self.path_subtract = self.path_subtract.united(temp_path)
+
+            self.path_current = self.path_full.subtracted(self.path_subtract)
+        else:
+            self.path_current = self.path_full
+
+        if self.decoration is not None:
+            for widget in self.decoration:
+                temp_path = QPainterPath()
+                widget.raise_()
+                widget.show()
+                geo = widget.frameGeometry()
+                width, height = geo.width(), geo.height()
+                point = widget.mapTo(self.parent, QPoint(0, 0))
+                x, y = point.x(), point.y()
+                temp_path.addRect(QRectF(x, y, width, height))
+
+                temp_region_1 = QRegion(x-1, y-1, width+2, height+2)
+                temp_region_2 = QRegion(x+1, y+1, width-2, height-2)
+                temp_region = temp_region_1.subtracted(temp_region_2)
+
+                if self.interaction_on:
+                    self.region_mask = self.region_mask.united(temp_region)
+
+                self.path_decoration = self.path_decoration.united(temp_path)
+        else:
+            self.path_decoration.addRect(0, 0, 0, 0)
+
+        # Add a decoration stroke around widget
+        self.setMask(self.region_mask)
+        self.update()
+        self.repaint()
+
+    def update_widgets(self, widgets):
+        """ """
+        self.widgets = widgets
+
+    def update_decoration(self, widgets):
+        """ """
+        self.decoration = widgets
+
+    def paintEvent(self, event):
+        """Override Qt method"""
+        painter = QPainter(self)
+        painter.setRenderHint(QPainter.Antialiasing)
+        # Decoration
+        painter.fillPath(self.path_current, QBrush(self.color))
+        painter.strokePath(self.path_decoration, QPen(self.color_decoration,
+                                                      self.stroke_decoration))
+#        decoration_fill = QColor(self.color_decoration)
+#        decoration_fill.setAlphaF(0.25)
+#        painter.fillPath(self.path_decoration, decoration_fill)
+
+    def reject(self):
+        """Override Qt method"""
+        if not self.is_fade_running():
+            key = Qt.Key_Escape
+            self.key_pressed = key
+            self.sig_key_pressed.emit()
+
+    def mousePressEvent(self, event):
+        """Override Qt method"""
+        pass
+
+
+class FadingTipBox(FadingDialog):
+    """ """
+    def __init__(self, parent, opacity, duration, easing_curve):
+        super(FadingTipBox, self).__init__(parent, opacity, duration,
+                                           easing_curve)
+        self.holder = self.anim  # needed for qt to work
+        self.parent = parent
+
+        self.frames = None
+        self.color_top = QColor.fromRgb(230, 230, 230)
+        self.color_back = QColor.fromRgb(255, 255, 255)
+        self.offset_shadow = 0
+        self.fixed_width = 300
+
+        self.key_pressed = None
+
+        self.setAttribute(Qt.WA_TranslucentBackground)
+        self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint |
+                            Qt.WindowStaysOnTopHint)
+        self.setModal(False)
+
+        # Widgets
+        self.button_home = QPushButton("<<")
+        self.button_close = QPushButton("X")
+        self.button_previous = QPushButton(" < ")
+        self.button_end = QPushButton(">>")
+        self.button_next = QPushButton(" > ")
+        self.button_run = QPushButton(_('Run code'))
+        self.button_disable = None
+        self.button_current = QToolButton()
+        self.label_image = QLabel()
+
+        self.label_title = QLabel()
+        self.combo_title = QComboBox()
+        self.label_current = QLabel()
+        self.label_content = QLabel()
+
+        self.label_content.setMinimumWidth(self.fixed_width)
+        self.label_content.setMaximumWidth(self.fixed_width)
+
+        self.label_current.setAlignment(Qt.AlignCenter)
+
+        self.label_content.setWordWrap(True)
+
+        self.widgets = [self.label_content, self.label_title,
+                        self.label_current, self.combo_title,
+                        self.button_close, self.button_run, self.button_next,
+                        self.button_previous, self.button_end,
+                        self.button_home, self.button_current]
+
+        arrow = get_image_path('hide.png')
+
+        self.stylesheet = '''QPushButton {
+                             background-color: rgbs(200,200,200,100%);
+                             color: rgbs(0,0,0,100%);
+                             border-style: outset;
+                             border-width: 1px;
+                             border-radius: 3px;
+                             border-color: rgbs(100,100,100,100%);
+                             padding: 2px;
+                             }
+
+                             QPushButton:hover {
+                             background-color: rgbs(150, 150, 150, 100%);
+                             }
+
+                             QPushButton:disabled {
+                             background-color: rgbs(230,230,230,100%);
+                             color: rgbs(200,200,200,100%);
+                             border-color: rgbs(200,200,200,100%);
+                             }
+
+                             QComboBox {
+                             padding-left: 5px;
+                             background-color: rgbs(230,230,230,100%);
+                             border-width: 0px;
+                             border-radius: 0px;
+                             min-height:20px;
+                             max-height:20px;
+                             }
+
+                             QComboBox::drop-down  {
+                             subcontrol-origin: padding;
+                             subcontrol-position: top left;
+                             border-width: 0px;
+                             }
+                             
+                             QComboBox::down-arrow {
+                             image: url(''' + arrow + ''');
+                             }
+                             
+                             '''
+        # Windows fix, slashes should be always in unix-style
+        self.stylesheet = self.stylesheet.replace('\\', '/')
+
+        for widget in self.widgets:
+            widget.setFocusPolicy(Qt.NoFocus)
+            widget.setStyleSheet(self.stylesheet)
+
+        layout_top = QHBoxLayout()
+        layout_top.addWidget(self.combo_title)
+        layout_top.addStretch()
+        layout_top.addWidget(self.button_close)
+        layout_top.addSpacerItem(QSpacerItem(self.offset_shadow,
+                                             self.offset_shadow))
+
+        layout_content = QHBoxLayout()
+        layout_content.addWidget(self.label_content)
+        layout_content.addWidget(self.label_image)
+        layout_content.addSpacerItem(QSpacerItem(5, 5))
+
+        layout_run = QHBoxLayout()
+        layout_run.addStretch()
+        layout_run.addWidget(self.button_run)
+        layout_run.addStretch()
+        layout_run.addSpacerItem(QSpacerItem(self.offset_shadow,
+                                             self.offset_shadow))
+
+        layout_navigation = QHBoxLayout()
+        layout_navigation.addWidget(self.button_home)
+        layout_navigation.addWidget(self.button_previous)
+        layout_navigation.addStretch()
+        layout_navigation.addWidget(self.label_current)
+        layout_navigation.addStretch()
+        layout_navigation.addWidget(self.button_next)
+        layout_navigation.addWidget(self.button_end)
+        layout_navigation.addSpacerItem(QSpacerItem(self.offset_shadow,
+                                                    self.offset_shadow))
+
+        layout = QVBoxLayout()
+        layout.addLayout(layout_top)
+        layout.addStretch()
+        layout.addSpacerItem(QSpacerItem(15, 15))
+        layout.addLayout(layout_content)
+        layout.addLayout(layout_run)
+        layout.addStretch()
+        layout.addSpacerItem(QSpacerItem(15, 15))
+        layout.addLayout(layout_navigation)
+        layout.addSpacerItem(QSpacerItem(self.offset_shadow,
+                                         self.offset_shadow))
+
+        layout.setSizeConstraint(QLayout.SetFixedSize)
+
+        self.setLayout(layout)
+
+        self.set_funcs_before_fade_in([self._disable_widgets])
+        self.set_funcs_after_fade_in([self._enable_widgets])
+        self.set_funcs_before_fade_out([self._disable_widgets])
+
+        self.setContextMenuPolicy(Qt.CustomContextMenu)
+
+        # signals and slots
+        # These are defined every time by the AnimatedTour Class
+
+    def _disable_widgets(self):
+        """ """
+        for widget in self.widgets:
+            widget.setDisabled(True)
+
+    def _enable_widgets(self):
+        """ """
+        self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint |
+                            Qt.WindowStaysOnTopHint)
+        for widget in self.widgets:
+            widget.setDisabled(False)
+
+        if self.button_disable == 'previous':
+            self.button_previous.setDisabled(True)
+            self.button_home.setDisabled(True)
+        elif self.button_disable == 'next':
+            self.button_next.setDisabled(True)
+            self.button_end.setDisabled(True)
+
+    def set_data(self, title, content, current, image, run, frames=None,
+                 step=None):
+        """ """
+        self.label_title.setText(title)
+        self.combo_title.clear()
+        self.combo_title.addItems(frames)
+        self.combo_title.setCurrentIndex(step)
+#        min_content_len = max([len(f) for f in frames])
+#        self.combo_title.setMinimumContentsLength(min_content_len)
+
+        # Fix and try to see how it looks with a combo box
+        self.label_current.setText(current)
+        self.button_current.setText(current)
+        self.label_content.setText(content)
+        self.image = image
+
+        if image is None:
+            self.label_image.setFixedHeight(1)
+            self.label_image.setFixedWidth(1)
+        else:
+            extension = image.split('.')[-1]
+            self.image = QPixmap(get_image_path(image), extension)
+            self.label_image.setPixmap(self.image)
+            self.label_image.setFixedSize(self.image.size())
+
+        if run is None:
+            self.button_run.setVisible(False)
+        else:
+            self.button_run.setDisabled(False)
+            self.button_run.setVisible(True)
+
+        # Refresh layout
+        self.layout().activate()
+
+    def set_pos(self, x, y):
+        """ """
+        self.x = x
+        self.y = y
+        self.move(QPoint(x, y))
+
+    def build_paths(self):
+        """ """
+        geo = self.geometry()
+        radius = 30
+        shadow = self.offset_shadow
+        x0, y0 = geo.x(), geo.y()
+        width, height = geo.width() - shadow, geo.height() - shadow
+
+        left, top = 0, 0
+        right, bottom = width, height
+
+        self.round_rect_path = QPainterPath()
+        self.round_rect_path.moveTo(right, top + radius)
+        self.round_rect_path.arcTo(right-radius, top, radius, radius, 0.0,
+                                   90.0)
+        self.round_rect_path.lineTo(left+radius, top)
+        self.round_rect_path.arcTo(left, top, radius, radius, 90.0, 90.0)
+        self.round_rect_path.lineTo(left, bottom-radius)
+        self.round_rect_path.arcTo(left, bottom-radius, radius, radius, 180.0,
+                                   90.0)
+        self.round_rect_path.lineTo(right-radius, bottom)
+        self.round_rect_path.arcTo(right-radius, bottom-radius, radius, radius,
+                                   270.0, 90.0)
+        self.round_rect_path.closeSubpath()
+
+        # Top path
+        header = 36
+        offset = 2
+        left, top = offset, offset
+        right = width - (offset)
+        self.top_rect_path = QPainterPath()
+        self.top_rect_path.lineTo(right, top + radius)
+        self.top_rect_path.moveTo(right, top + radius)
+        self.top_rect_path.arcTo(right-radius, top, radius, radius, 0.0, 90.0)
+        self.top_rect_path.lineTo(left+radius, top)
+        self.top_rect_path.arcTo(left, top, radius, radius, 90.0, 90.0)
+        self.top_rect_path.lineTo(left, top + header)
+        self.top_rect_path.lineTo(right, top + header)
+
+    def paintEvent(self, event):
+        """ """
+        self.build_paths()
+
+        painter = QPainter(self)
+        painter.setRenderHint(QPainter.Antialiasing)
+
+        painter.fillPath(self.round_rect_path, self.color_back)
+        painter.fillPath(self.top_rect_path, self.color_top)
+        painter.strokePath(self.round_rect_path, QPen(Qt.gray, 1))
+
+        # TODO: Build the pointing arrow?
+
+    def keyReleaseEvent(self, event):
+        """ """
+        key = event.key()
+        self.key_pressed = key
+#        print(key)
+        keys = [Qt.Key_Right, Qt.Key_Left, Qt.Key_Down, Qt.Key_Up,
+                Qt.Key_Escape, Qt.Key_PageUp, Qt.Key_PageDown,
+                Qt.Key_Home, Qt.Key_End, Qt.Key_Menu]
+
+        if key in keys:
+            if not self.is_fade_running():
+                self.sig_key_pressed.emit()
+
+    def mousePressEvent(self, event):
+        """override Qt method"""
+        # Raise the main application window on click
+        self.parent.raise_()
+        self.raise_()
+
+        if event.button() == Qt.RightButton:
+            pass
+#            clicked_widget = self.childAt(event.x(), event.y())
+#            if clicked_widget == self.label_current:
+#            self.context_menu_requested(event)
+
+    def context_menu_requested(self, event):
+        """ """
+        pos = QPoint(event.x(), event.y())
+        menu = QMenu(self)
+
+        actions = []
+        action_title = create_action(self, _('Go to step: '), icon=QIcon())
+        action_title.setDisabled(True)
+        actions.append(action_title)
+#        actions.append(create_action(self, _(': '), icon=QIcon()))
+
+        add_actions(menu, actions)
+
+        menu.popup(self.mapToGlobal(pos))
+
+    def reject(self):
+        """Qt method to handle escape key event"""
+        if not self.is_fade_running():
+            key = Qt.Key_Escape
+            self.key_pressed = key
+            self.sig_key_pressed.emit()
+
+
+class AnimatedTour(QWidget):
+    """ """
+
+    def __init__(self, parent):
+        QWidget.__init__(self, parent)
+
+        self.parent = parent
+        
+        # Variables to adjust 
+        self.duration_canvas = [666, 666]
+        self.duration_tips = [333, 333]
+        self.opacity_canvas = [0.0, 0.7]
+        self.opacity_tips = [0.0, 1.0]
+        self.color = Qt.black
+        self.easing_curve = [QEasingCurve.Linear]
+
+        self.current_step = 0
+        self.step_current = 0
+        self.steps = 0
+        self.canvas = None
+        self.tips = None
+        self.frames = None
+        self.spy_window = None
+
+        self.widgets = None
+        self.dockwidgets = None
+        self.decoration = None
+        self.run = None
+
+        self.is_tour_set = False
+
+        # Widgets
+        self.canvas = FadingCanvas(self.parent, self.opacity_canvas,
+                                   self.duration_canvas, self.easing_curve,
+                                   self.color)
+        self.tips = FadingTipBox(self.parent, self.opacity_tips,
+                                 self.duration_tips, self.easing_curve)
+
+        # Widgets setup
+        # Needed to fix issue #2204
+        self.setAttribute(Qt.WA_TransparentForMouseEvents)
+
+        # Signals and slots
+        self.tips.button_next.clicked.connect(self.next_step)
+        self.tips.button_previous.clicked.connect(self.previous_step)
+        self.tips.button_close.clicked.connect(self.close_tour)
+        self.tips.button_run.clicked.connect(self.run_code)
+        self.tips.button_home.clicked.connect(self.first_step)
+        self.tips.button_end.clicked.connect(self.last_step)
+        self.tips.button_run.clicked.connect(
+            lambda: self.tips.button_run.setDisabled(True))
+        self.tips.combo_title.currentIndexChanged.connect(self.go_to_step)
+
+        # Main window move or resize
+        self.parent.sig_resized.connect(self._resized)
+        self.parent.sig_moved.connect(self._moved)
+
+        # To capture the arrow keys that allow moving the tour
+        self.tips.sig_key_pressed.connect(self._key_pressed)
+
+    def _resized(self, event):
+        """ """
+        size = event.size()
+        self.canvas.setFixedSize(size)
+        self.canvas.update_canvas()
+
+        if self.is_tour_set:
+            self._set_data()
+
+    def _moved(self, event):
+        """ """
+        pos = event.pos()
+        self.canvas.move(QPoint(pos.x(), pos.y()))
+
+        if self.is_tour_set:
+            self._set_data()
+
+    def _close_canvas(self):
+        """ """
+        self._set_modal(False, [self.tips])
+        self.tips.hide()
+        self.canvas.fade_out(self.canvas.hide)
+
+    def _clear_canvas(self):
+        """ """
+        # TODO: Add option to also make it white... might be usefull?
+        # Make canvas black before transitions
+        self.canvas.update_widgets(None)
+        self.canvas.update_decoration(None)
+        self.canvas.update_canvas()
+
+    def _move_step(self):
+        """ """
+        self._set_data()
+
+        # Show/raise the widget so it is located first!
+        widgets = self.dockwidgets
+        if widgets is not None:
+            widget = widgets[0]
+            if widget is not None:
+                widget.show()
+                widget.raise_()
+
+        self._locate_tip_box()
+
+        # Change in canvas only after fadein finishes, for visual aesthetics
+        self.tips.fade_in(self.canvas.update_canvas)
+        self.tips.raise_()
+
+    def _set_modal(self, value, widgets):
+        """ """
+        platform = sys.platform.lower()
+
+        if 'linux' in platform:
+            pass
+        elif 'win' in platform:
+            for widget in widgets:
+                widget.setModal(value)
+                widget.hide()
+                widget.show()
+        elif 'darwin' in platform:
+            pass
+        else:
+            pass
+
+    def _process_widgets(self, names, spy_window):
+        """ """
+        widgets = []
+        dockwidgets = []
+
+        for name in names:
+            base = name.split('.')[0]
+            temp = getattr(spy_window, base)
+
+            # Check if it is the current editor
+            if 'get_current_editor()' in name:
+                temp = temp.get_current_editor()
+                temp = getattr(temp, name.split('.')[-1])
+
+            widgets.append(temp)
+
+            # Check if it is a dockwidget and make the widget a dockwidget
+            # If not return the same widget
+            temp = getattr(temp, 'dockwidget', temp)
+            dockwidgets.append(temp)
+
+        return widgets, dockwidgets
+
+    def _set_data(self):
+        """ """
+        step, steps, frames = self.step_current, self.steps, self.frames
+        current = '{0}/{1}'.format(step + 1, steps)
+        frame = frames[step]
+
+        combobox_frames = ["{0}. {1}".format(i+1, f['title'])
+                           for i, f in enumerate(frames)]
+
+        title, content, image = '', '', None
+        widgets, dockwidgets, decoration = None, None, None
+        run = None
+
+        # Check if entry exists in dic and act accordingly
+        if 'title' in frame:
+            title = frame['title']
+
+        if 'content' in frame:
+            content = frame['content']
+
+        if 'widgets' in frame:
+            widget_names = frames[step]['widgets']
+            # Get the widgets based on their name
+            widgets, dockwidgets = self._process_widgets(widget_names,
+                                                         self.spy_window)
+        self.widgets = widgets
+        self.dockwidgets = dockwidgets
+
+        if 'decoration' in frame:
+            widget_names = frames[step]['decoration']
+            deco, decoration = self._process_widgets(widget_names,
+                                                     self.spy_window)
+            self.decoration = decoration
+
+        if 'image' in frame:
+            image = frames[step]['image']
+
+        if 'interact' in frame:
+            self.canvas.set_interaction(frame['interact'])
+            if frame['interact']:
+                self._set_modal(False, [self.tips])
+            else:
+                self._set_modal(True, [self.tips])
+        else:
+            self.canvas.set_interaction(False)
+            self._set_modal(True, [self.tips])
+
+        if 'run' in frame:
+            # Asume that the frist widget is the console
+            run = frame['run']
+            self.run = run
+
+        self.tips.set_data(title, content, current, image, run,
+                           frames=combobox_frames, step=step)
+        self._check_buttons()
+
+        # Make canvas black when starting a new place of decoration
+        self.canvas.update_widgets(dockwidgets)
+        self.canvas.update_decoration(decoration)
+
+    def _locate_tip_box(self):
+        """ """
+        dockwidgets = self.dockwidgets
+
+        # Store the dimensions of the main window
+        geo = self.parent.frameGeometry()
+        x, y, width, height = geo.x(), geo.y(), geo.width(), geo.height()
+        self.width_main = width
+        self.height_main = height
+        self.x_main = x
+        self.y_main = y
+
+        delta = 20
+
+        # Here is the tricky part to define the best position for the
+        # tip widget
+        if dockwidgets is not None:
+            if dockwidgets[0] is not None:
+                geo = dockwidgets[0].geometry()
+                x, y, width, height = geo.x(), geo.y(), geo.width(), geo.height()
+    
+                point = dockwidgets[0].mapToGlobal(QPoint(0, 0))
+                x_glob, y_glob = point.x(), point.y()
+    
+                # Check if is too tall and put to the side
+                y_fac = (height / self.height_main) * 100
+    
+                if y_fac > 60:  # FIXME:
+                    if x < self.tips.width():
+                        x = x_glob + width + delta
+                        y = y_glob + height/2 - self.tips.height()/2
+                    else:
+                        x = x_glob - self.tips.width() - delta
+                        y = y_glob + height/2 - self.tips.height()/2
+                else:
+                    if y < self.tips.height():
+                        x = x_glob + width/2 - self.tips.width()/2
+                        y = y_glob + height + delta
+                    else:
+                        x = x_glob + width/2 - self.tips.width()/2
+                        y = y_glob - delta - self.tips.height()
+        else:
+            # Center on parent
+            x = self.x_main + self.width_main/2 - self.tips.width()/2
+            y = self.y_main + self.height_main/2 - self.tips.height()/2
+
+        self.tips.set_pos(x, y)
+
+    def _check_buttons(self):
+        """ """
+        step, steps = self.step_current, self.steps
+        self.tips.button_disable = None
+
+        if step == 0:
+            self.tips.button_disable = 'previous'
+
+        if step == steps - 1:
+            self.tips.button_disable = 'next'
+
+    def _key_pressed(self):
+        """ """
+        key = self.tips.key_pressed
+
+        if ((key == Qt.Key_Right or key == Qt.Key_Down or
+             key == Qt.Key_PageDown) and self.step_current != self.steps - 1):
+            self.next_step()
+        elif ((key == Qt.Key_Left or key == Qt.Key_Up or
+               key == Qt.Key_PageUp) and self.step_current != 0):
+            self.previous_step()
+        elif key == Qt.Key_Escape:
+            self.close_tour()
+        elif key == Qt.Key_Home and self.step_current != 0:
+            self.first_step()
+        elif key == Qt.Key_End and self.step_current != self.steps - 1:
+            self.last_step()
+        elif key == Qt.Key_Menu:
+            pos = self.tips.label_current.pos()
+            self.tips.context_menu_requested(pos)
+
+    # --- public api
+    def run_code(self):
+        """ """
+        codelines = self.run
+        console = self.widgets[0]
+        for codeline in codelines:
+            console.execute_python_code(codeline)
+
+    def set_tour(self, index, frames, spy_window):
+        """ """
+        self.spy_window = spy_window
+        self.active_tour_index = index
+        self.last_frame_active = frames['last']
+        self.frames = frames['tour']
+        self.steps = len(self.frames)
+
+        self.is_tour_set = True
+
+    def start_tour(self):
+        """ """
+        geo = self.parent.geometry()
+        x, y, width, height = geo.x(), geo.y(), geo.width(), geo.height()
+#        self.parent_x = x
+#        self.parent_y = y
+#        self.parent_w = width
+#        self.parent_h = height
+
+        # FIXME: reset step to last used value
+        # Reset step to begining
+        self.step_current = self.last_frame_active
+
+        # Adjust the canvas size to match the main window size
+        self.canvas.setFixedSize(width, height)
+        self.canvas.move(QPoint(x, y))
+        self.canvas.fade_in(self._move_step)
+        self._clear_canvas()
+
+    def close_tour(self):
+        """ """
+        self.tips.fade_out(self._close_canvas)
+        self.tips.show()
+
+        try:
+            # set the last played frame by updating the available tours in 
+            # parent. This info will be lost on restart.
+            self.parent.tours_available[self.active_tour_index]['last'] =\
+                self.step_current
+        except:
+            pass
+
+    def next_step(self):
+        """ """
+        self._clear_canvas()
+        self.step_current += 1
+        self.tips.fade_out(self._move_step)
+
+    def previous_step(self):
+        """ """
+        self._clear_canvas()
+        self.step_current -= 1
+        self.tips.fade_out(self._move_step)
+
+    def go_to_step(self, number, id_=None):
+        """ """
+        self._clear_canvas()
+        self.step_current = number
+        self.tips.fade_out(self._move_step)
+
+    def last_step(self):
+        """ """
+        self.go_to_step(self.steps - 1)
+
+    def first_step(self):
+        """ """
+        self.go_to_step(0)
+
+# ----------------------------------------------------------------------------
+# Used for testing the functionality
+
+
+class TestWindow(QMainWindow):
+    """ """
+    sig_resized = Signal("QResizeEvent")
+    sig_moved = Signal("QMoveEvent")
+
+    def __init__(self):
+        super(TestWindow, self).__init__()
+        self.setGeometry(300, 100, 400, 600)
+        self.setWindowTitle('Exploring QMainWindow')
+
+        self.exit = QAction('Exit', self)
+        self.exit.setStatusTip('Exit program')
+
+        # create the menu bar
+        menubar = self.menuBar()
+        file_ = menubar.addMenu('&File')
+        file_.addAction(self.exit)
+
+        # create the status bar
+        self.statusBar()
+
+        # QWidget or its instance needed for box layout
+        self.widget = QWidget(self)
+
+        self.button = QPushButton('test')
+        self.button1 = QPushButton('1')
+        self.button2 = QPushButton('2')
+
+        effect = QGraphicsOpacityEffect(self.button2)
+        self.button2.setGraphicsEffect(effect)
+        self.anim = QPropertyAnimation(effect, "opacity")
+        self.anim.setStartValue(0.01)
+        self.anim.setEndValue(1.0)
+        self.anim.setDuration(500)
+
+        lay = QVBoxLayout()
+        lay.addWidget(self.button)
+        lay.addStretch()
+        lay.addWidget(self.button1)
+        lay.addWidget(self.button2)
+
+        self.widget.setLayout(lay)
+
+        self.setCentralWidget(self.widget)
+        self.button.clicked.connect(self.action1)
+        self.button1.clicked.connect(self.action2)
+
+        self.tour = AnimatedTour(self)
+
+    def action1(self):
+        """ """
+        frames = get_tour('test')
+        index = 0
+        dic = {'last': 0, 'tour': frames}
+        self.tour.set_tour(index, dic, self)
+        self.tour.start_tour()
+
+    def action2(self):
+        """ """
+        self.anim.start()
+
+    def resizeEvent(self, event):
+        """Reimplement Qt method"""
+        QMainWindow.resizeEvent(self, event)
+        self.sig_resized.emit(event)
+
+    def moveEvent(self, event):
+        """Reimplement Qt method"""
+        QMainWindow.moveEvent(self, event)
+        self.sig_moved.emit(event)
+
+
+def test():
+    """ """
+    app = QApplication([])
+    win = TestWindow()
+    win.show()
+    app.exec_()
+
+
+if __name__ == '__main__':
+    test()
diff --git a/spyderlib/utils/bsdsocket.py b/spyderlib/utils/bsdsocket.py
index 810276f..10946ce 100644
--- a/spyderlib/utils/bsdsocket.py
+++ b/spyderlib/utils/bsdsocket.py
@@ -18,7 +18,7 @@ import errno
 import traceback
 
 # Local imports
-from spyderlib.baseconfig import DEBUG, STDERR
+from spyderlib.config.base import DEBUG, STDERR
 DEBUG_EDITOR = DEBUG >= 3
 from spyderlib.py3compat import pickle
 PICKLE_HIGHEST_PROTOCOL = 2
@@ -141,43 +141,42 @@ PACKET_NOT_RECEIVED = PacketNotReceived()
 
 
 if __name__ == '__main__':
-    # socket read/write testing - client and server in one thread
+    if not os.name == 'nt':
+        # socket read/write testing - client and server in one thread
+        
+        # (techtonik): the stuff below is placed into public domain
+        print("-- Testing standard Python socket interface --")
     
-    # (techtonik): the stuff below is placed into public domain
-    print("-- Testing standard Python socket interface --")
-
-    address = ("127.0.0.1", 9999)
+        address = ("127.0.0.1", 9999)
+        
+        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        server.setblocking(0)
+        server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+        server.bind( address )
+        server.listen(2)
     
-    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-    server.setblocking(0)
-    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-    server.bind( address )
-    server.listen(2)
-
-    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-    client.connect( address )
-
-    client.send("data to be catched")
-    # accepted server socket is the one we can read from
-    # note that it is different from server socket
-    accsock, addr = server.accept()
-    print('..got "%s" from %s' % (accsock.recv(4096), addr))
-    client.send("more data for recv")
-    print('..got "%s" from %s' % (accsock.recv(4096), addr))
+        client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        client.connect( address )
     
-    # accsock.close()
-    # client.send("more data for recv")
-    #socket.error: [Errno 9] Bad file descriptor
-    # accsock, addr = server.accept()
-    #socket.error: [Errno 11] Resource temporarily unavailable
+        client.send("data to be catched".encode('utf-8'))
+        # accepted server socket is the one we can read from
+        # note that it is different from server socket
+        accsock, addr = server.accept()
+        print('..got "%s" from %s' % (accsock.recv(4096), addr))
     
-
-    print("-- Testing BSD socket write_packet/read_packet --")
-
-    write_packet(client, "a tiny piece of data")
-    print('..got "%s" from read_packet()' % (read_packet(accsock)))
+        # accsock.close()
+        # client.send("more data for recv")
+        #socket.error: [Errno 9] Bad file descriptor
+        # accsock, addr = server.accept()
+        #socket.error: [Errno 11] Resource temporarily unavailable
+        
     
-    client.close()
-    server.close()
+        print("-- Testing BSD socket write_packet/read_packet --")
     
-    print("-- Done.")
+        write_packet(client, "a tiny piece of data")
+        print('..got "%s" from read_packet()' % (read_packet(accsock)))
+        
+        client.close()
+        server.close()
+        
+        print("-- Done.")
diff --git a/spyderlib/utils/codeanalysis.py b/spyderlib/utils/codeanalysis.py
index 9bac468..9742085 100644
--- a/spyderlib/utils/codeanalysis.py
+++ b/spyderlib/utils/codeanalysis.py
@@ -16,7 +16,7 @@ import tempfile
 import traceback
 
 # Local import
-from spyderlib.baseconfig import _, DEBUG
+from spyderlib.config.base import _, DEBUG
 from spyderlib.utils import programs, encoding
 from spyderlib.py3compat import to_text_string, to_binary_string, PY3
 from spyderlib import dependencies
@@ -153,7 +153,11 @@ def check(args, source_code, filename=None, options=None):
     lines = source_code.splitlines()
     for line in output:
         lineno = int(re.search(r'(\:[\d]+\:)', line).group()[1:-1])
-        if 'analysis:ignore' not in to_text_string(lines[lineno-1], coding):
+        try:
+            text = to_text_string(lines[lineno-1], coding)
+        except TypeError:
+            text = to_text_string(lines[lineno-1])
+        if 'analysis:ignore' not in text:
             message = line[line.find(': ')+2:]
             results.append((message, lineno))
     return results
diff --git a/spyderlib/utils/debug.py b/spyderlib/utils/debug.py
index 4ef5538..86af242 100644
--- a/spyderlib/utils/debug.py
+++ b/spyderlib/utils/debug.py
@@ -9,7 +9,7 @@
 """
 Debug utilities that are independent of Spyder code.
 
-See spyderlib.baseconfig for other helpers.
+See spyderlib.config.base for other helpers.
 """
 
 from __future__ import print_function
diff --git a/spyderlib/utils/environ.py b/spyderlib/utils/environ.py
index 9a38583..6f0b633 100644
--- a/spyderlib/utils/environ.py
+++ b/spyderlib/utils/environ.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -8,14 +8,14 @@
 Environment variable utilities
 """
 
-from spyderlib.qt.QtGui import QDialog, QMessageBox
-
 import os
 
-# Local imports
-from spyderlib.baseconfig import _
-from spyderlib.widgets.dicteditor import DictEditor
+from spyderlib.qt.QtGui import QDialog, QMessageBox
+import spyderlib.utils.icon_manager as ima
 
+# Local imports
+from spyderlib.config.base import _
+from spyderlib.widgets.variableexplorer.collectionseditor import CollectionsEditor
 
 def envdict2listdict(envdict):
     """Dict --> Dict of lists"""
@@ -25,6 +25,7 @@ def envdict2listdict(envdict):
             envdict[key] = [path.strip() for path in envdict[key].split(sep)]
     return envdict
 
+
 def listdict2envdict(listdict):
     """Dict of lists --> Dict"""
     for key in listdict:
@@ -32,18 +33,20 @@ def listdict2envdict(listdict):
             listdict[key] = os.path.pathsep.join(listdict[key])
     return listdict
 
-class RemoteEnvDialog(DictEditor):
+
+class RemoteEnvDialog(CollectionsEditor):
     """Remote process environment variables Dialog"""
     def __init__(self, get_environ_func, set_environ_func, parent=None):
         super(RemoteEnvDialog, self).__init__(parent)
         self.setup(envdict2listdict(get_environ_func()),
-                   title="os.environ", width=600, icon='environ.png')
+                   title="os.environ", width=600, icon=ima.icon('environ'))
         self.set_environ = set_environ_func
     def accept(self):
         """Reimplement Qt method"""
         self.set_environ(listdict2envdict(self.get_value()))
         QDialog.accept(self)
 
+
 class EnvDialog(RemoteEnvDialog):
     """Environment variables Dialog"""
     def __init__(self):
@@ -95,8 +98,8 @@ try:
                         _("Module <b>pywin32 was not found</b>.<br>"
                           "Please restart this Windows <i>session</i> "
                           "(not the computer) for changes to take effect."))
-            
-    class WinUserEnvDialog(DictEditor):
+
+    class WinUserEnvDialog(CollectionsEditor):
         """Windows User Environment Variables Editor"""
         def __init__(self, parent=None):
             super(WinUserEnvDialog, self).__init__(parent)
@@ -128,7 +131,10 @@ def main():
     """Run Windows environment variable editor"""
     from spyderlib.utils.qthelpers import qapplication
     app = qapplication()
-    dialog = WinUserEnvDialog()
+    if os.name == 'nt':
+        dialog = WinUserEnvDialog()
+    else:
+        dialog = EnvDialog()
     dialog.show()
     app.exec_()
 
diff --git a/spyderlib/utils/external/__init__.py b/spyderlib/utils/external/__init__.py
index b80995e..0f2afcf 100644
--- a/spyderlib/utils/external/__init__.py
+++ b/spyderlib/utils/external/__init__.py
@@ -19,7 +19,7 @@ import os
 if os.name == 'nt':
     import os.path as osp
     import sys
-    from spyderlib.baseconfig import get_module_source_path
+    from spyderlib.config.base import get_module_source_path
 
     dirname = get_module_source_path(__name__)
     if osp.isdir(osp.join(dirname, 'rope')):
diff --git a/spyderlib/utils/external/path.py b/spyderlib/utils/external/path.py
deleted file mode 100644
index e14886c..0000000
--- a/spyderlib/utils/external/path.py
+++ /dev/null
@@ -1,1047 +0,0 @@
-#
-# Copyright (c) 2010 Mikhail Gusarov
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
-
-""" path.py - An object representing a path to a file or directory.
-
-Original author:
- Jason Orendorff <jason.orendorff\x40gmail\x2ecom>
-
-Contributors:
- Mikhail Gusarov <dottedmag at dottedmag.net>
- Marc Abramowitz <marc at marc-abramowitz.com>
-
-Example:
-
-from path import path
-d = path('/home/guido/bin')
-for f in d.files('*.py'):
-    f.chmod(0755)
-
-This module requires Python 2.3 or later.
-"""
-
-from __future__ import generators
-
-import sys
-import warnings
-import os
-import fnmatch
-import glob
-import shutil
-import codecs
-import hashlib
-import errno
-
-from spyderlib.py3compat import (TEXT_TYPES, getcwd, u,
-                                 is_text_string, is_unicode)
-
-__version__ = '2.4.1'
-__all__ = ['path']
-
-MODE_0777 = 511
-MODE_0666 = 438
-
-# Platform-specific support for path.owner
-if os.name == 'nt':
-    try:
-        import win32security
-    except ImportError:
-        win32security = None
-else:
-    try:
-        import pwd
-    except ImportError:
-        pwd = None
-
-_base = TEXT_TYPES[-1]
-_getcwd = getcwd
-
-# Universal newline support
-_textmode = 'U'
-if hasattr(__builtins__, 'open') and not hasattr(open, 'newlines'):
-    _textmode = 'r'
-
-class TreeWalkWarning(Warning):
-    pass
-
-class path(_base):
-    """ Represents a filesystem path.
-
-    For documentation on individual methods, consult their
-    counterparts in os.path.
-    """
-
-    # --- Special Python methods.
-
-    def __repr__(self):
-        return 'path(%s)' % _base.__repr__(self)
-
-    # Adding a path and a string yields a path.
-    def __add__(self, more):
-        try:
-            resultStr = _base.__add__(self, more)
-        except TypeError:  # Python bug
-            resultStr = NotImplemented
-        if resultStr is NotImplemented:
-            return resultStr
-        return self.__class__(resultStr)
-
-    def __radd__(self, other):
-        if is_text_string(other):
-            return self.__class__(other.__add__(self))
-        else:
-            return NotImplemented
-
-    # The / operator joins paths.
-    def __div__(self, rel):
-        """ fp.__div__(rel) == fp / rel == fp.joinpath(rel)
-
-        Join two path components, adding a separator character if
-        needed.
-        """
-        return self.__class__(os.path.join(self, rel))
-
-    # Make the / operator work even when true division is enabled.
-    __truediv__ = __div__
-
-    def __enter__(self):
-        self._old_dir = self.getcwd()
-        os.chdir(self)
-
-    def __exit__(self, *_):
-        os.chdir(self._old_dir)
-
-    def getcwd(cls):
-        """ Return the current working directory as a path object. """
-        return cls(_getcwd())
-    getcwd = classmethod(getcwd)
-
-    #
-    # --- Operations on path strings.
-
-    def abspath(self):       return self.__class__(os.path.abspath(self))
-    def normcase(self):      return self.__class__(os.path.normcase(self))
-    def normpath(self):      return self.__class__(os.path.normpath(self))
-    def realpath(self):      return self.__class__(os.path.realpath(self))
-    def expanduser(self):    return self.__class__(os.path.expanduser(self))
-    def expandvars(self):    return self.__class__(os.path.expandvars(self))
-    def dirname(self):       return self.__class__(os.path.dirname(self))
-    def basename(self):      return self.__class__(os.path.basename(self))
-
-    def expand(self):
-        """ Clean up a filename by calling expandvars(),
-        expanduser(), and normpath() on it.
-
-        This is commonly everything needed to clean up a filename
-        read from a configuration file, for example.
-        """
-        return self.expandvars().expanduser().normpath()
-
-    def _get_namebase(self):
-        base, ext = os.path.splitext(self.name)
-        return base
-
-    def _get_ext(self):
-        f, ext = os.path.splitext(_base(self))
-        return ext
-
-    def _get_drive(self):
-        drive, r = os.path.splitdrive(self)
-        return self.__class__(drive)
-
-    parent = property(
-        dirname, None, None,
-        """ This path's parent directory, as a new path object.
-
-        For example, path('/usr/local/lib/libpython.so').parent == path('/usr/local/lib')
-        """)
-
-    name = property(
-        basename, None, None,
-        """ The name of this file or directory without the full path.
-
-        For example, path('/usr/local/lib/libpython.so').name == 'libpython.so'
-        """)
-
-    namebase = property(
-        _get_namebase, None, None,
-        """ The same as path.name, but with one file extension stripped off.
-
-        For example, path('/home/guido/python.tar.gz').name     == 'python.tar.gz',
-        but          path('/home/guido/python.tar.gz').namebase == 'python.tar'
-        """)
-
-    ext = property(
-        _get_ext, None, None,
-        """ The file extension, for example '.py'. """)
-
-    drive = property(
-        _get_drive, None, None,
-        """ The drive specifier, for example 'C:'.
-        This is always empty on systems that don't use drive specifiers.
-        """)
-
-    def splitpath(self):
-        """ p.splitpath() -> Return (p.parent, p.name). """
-        parent, child = os.path.split(self)
-        return self.__class__(parent), child
-
-    def splitdrive(self):
-        """ p.splitdrive() -> Return (p.drive, <the rest of p>).
-
-        Split the drive specifier from this path.  If there is
-        no drive specifier, p.drive is empty, so the return value
-        is simply (path(''), p).  This is always the case on Unix.
-        """
-        drive, rel = os.path.splitdrive(self)
-        return self.__class__(drive), rel
-
-    def splitext(self):
-        """ p.splitext() -> Return (p.stripext(), p.ext).
-
-        Split the filename extension from this path and return
-        the two parts.  Either part may be empty.
-
-        The extension is everything from '.' to the end of the
-        last path segment.  This has the property that if
-        (a, b) == p.splitext(), then a + b == p.
-        """
-        filename, ext = os.path.splitext(self)
-        return self.__class__(filename), ext
-
-    def stripext(self):
-        """ p.stripext() -> Remove one file extension from the path.
-
-        For example, path('/home/guido/python.tar.gz').stripext()
-        returns path('/home/guido/python.tar').
-        """
-        return self.splitext()[0]
-
-    if hasattr(os.path, 'splitunc'):
-        def splitunc(self):
-            unc, rest = os.path.splitunc(self)
-            return self.__class__(unc), rest
-
-        def _get_uncshare(self):
-            unc, r = os.path.splitunc(self)
-            return self.__class__(unc)
-
-        uncshare = property(
-            _get_uncshare, None, None,
-            """ The UNC mount point for this path.
-            This is empty for paths on local drives. """)
-
-    def joinpath(self, *args):
-        """ Join two or more path components, adding a separator
-        character (os.sep) if needed.  Returns a new path
-        object.
-        """
-        return self.__class__(os.path.join(self, *args))
-
-    def splitall(self):
-        r""" Return a list of the path components in this path.
-
-        The first item in the list will be a path.  Its value will be
-        either os.curdir, os.pardir, empty, or the root directory of
-        this path (for example, '/' or 'C:\\').  The other items in
-        the list will be strings.
-
-        path.path.joinpath(*result) will yield the original path.
-        """
-        parts = []
-        loc = self
-        while loc != os.curdir and loc != os.pardir:
-            prev = loc
-            loc, child = prev.splitpath()
-            if loc == prev:
-                break
-            parts.append(child)
-        parts.append(loc)
-        parts.reverse()
-        return parts
-
-    def relpath(self):
-        """ Return this path as a relative path,
-        based from the current working directory.
-        """
-        cwd = self.__class__(os.getcwd())
-        return cwd.relpathto(self)
-
-    def relpathto(self, dest):
-        """ Return a relative path from self to dest.
-
-        If there is no relative path from self to dest, for example if
-        they reside on different drives in Windows, then this returns
-        dest.abspath().
-        """
-        origin = self.abspath()
-        dest = self.__class__(dest).abspath()
-
-        orig_list = origin.normcase().splitall()
-        # Don't normcase dest!  We want to preserve the case.
-        dest_list = dest.splitall()
-
-        if orig_list[0] != os.path.normcase(dest_list[0]):
-            # Can't get here from there.
-            return dest
-
-        # Find the location where the two paths start to differ.
-        i = 0
-        for start_seg, dest_seg in zip(orig_list, dest_list):
-            if start_seg != os.path.normcase(dest_seg):
-                break
-            i += 1
-
-        # Now i is the point where the two paths diverge.
-        # Need a certain number of "os.pardir"s to work up
-        # from the origin to the point of divergence.
-        segments = [os.pardir] * (len(orig_list) - i)
-        # Need to add the diverging part of dest_list.
-        segments += dest_list[i:]
-        if len(segments) == 0:
-            # If they happen to be identical, use os.curdir.
-            relpath = os.curdir
-        else:
-            relpath = os.path.join(*segments)
-        return self.__class__(relpath)
-
-    # --- Listing, searching, walking, and matching
-
-    def listdir(self, pattern=None):
-        """ D.listdir() -> List of items in this directory.
-
-        Use D.files() or D.dirs() instead if you want a listing
-        of just files or just subdirectories.
-
-        The elements of the list are path objects.
-
-        With the optional 'pattern' argument, this only lists
-        items whose names match the given pattern.
-        """
-        names = os.listdir(self)
-        if pattern is not None:
-            names = fnmatch.filter(names, pattern)
-        return [self / child for child in names]
-
-    def dirs(self, pattern=None):
-        """ D.dirs() -> List of this directory's subdirectories.
-
-        The elements of the list are path objects.
-        This does not walk recursively into subdirectories
-        (but see path.walkdirs).
-
-        With the optional 'pattern' argument, this only lists
-        directories whose names match the given pattern.  For
-        example, d.dirs('build-*').
-        """
-        return [p for p in self.listdir(pattern) if p.isdir()]
-
-    def files(self, pattern=None):
-        """ D.files() -> List of the files in this directory.
-
-        The elements of the list are path objects.
-        This does not walk into subdirectories (see path.walkfiles).
-
-        With the optional 'pattern' argument, this only lists files
-        whose names match the given pattern.  For example,
-        d.files('*.pyc').
-        """
-
-        return [p for p in self.listdir(pattern) if p.isfile()]
-
-    def walk(self, pattern=None, errors='strict'):
-        """ D.walk() -> iterator over files and subdirs, recursively.
-
-        The iterator yields path objects naming each child item of
-        this directory and its descendants.  This requires that
-        D.isdir().
-
-        This performs a depth-first traversal of the directory tree.
-        Each directory is returned just before all its children.
-
-        The errors= keyword argument controls behavior when an
-        error occurs.  The default is 'strict', which causes an
-        exception.  The other allowed values are 'warn', which
-        reports the error via warnings.warn(), and 'ignore'.
-        """
-        if errors not in ('strict', 'warn', 'ignore'):
-            raise ValueError("invalid errors parameter")
-
-        try:
-            childList = self.listdir()
-        except Exception:
-            if errors == 'ignore':
-                return
-            elif errors == 'warn':
-                warnings.warn(
-                    "Unable to list directory '%s': %s"
-                    % (self, sys.exc_info()[1]),
-                    TreeWalkWarning)
-                return
-            else:
-                raise
-
-        for child in childList:
-            if pattern is None or child.fnmatch(pattern):
-                yield child
-            try:
-                isdir = child.isdir()
-            except Exception:
-                if errors == 'ignore':
-                    isdir = False
-                elif errors == 'warn':
-                    warnings.warn(
-                        "Unable to access '%s': %s"
-                        % (child, sys.exc_info()[1]),
-                        TreeWalkWarning)
-                    isdir = False
-                else:
-                    raise
-
-            if isdir:
-                for item in child.walk(pattern, errors):
-                    yield item
-
-    def walkdirs(self, pattern=None, errors='strict'):
-        """ D.walkdirs() -> iterator over subdirs, recursively.
-
-        With the optional 'pattern' argument, this yields only
-        directories whose names match the given pattern.  For
-        example, mydir.walkdirs('*test') yields only directories
-        with names ending in 'test'.
-
-        The errors= keyword argument controls behavior when an
-        error occurs.  The default is 'strict', which causes an
-        exception.  The other allowed values are 'warn', which
-        reports the error via warnings.warn(), and 'ignore'.
-        """
-        if errors not in ('strict', 'warn', 'ignore'):
-            raise ValueError("invalid errors parameter")
-
-        try:
-            dirs = self.dirs()
-        except Exception:
-            if errors == 'ignore':
-                return
-            elif errors == 'warn':
-                warnings.warn(
-                    "Unable to list directory '%s': %s"
-                    % (self, sys.exc_info()[1]),
-                    TreeWalkWarning)
-                return
-            else:
-                raise
-
-        for child in dirs:
-            if pattern is None or child.fnmatch(pattern):
-                yield child
-            for subsubdir in child.walkdirs(pattern, errors):
-                yield subsubdir
-
-    def walkfiles(self, pattern=None, errors='strict'):
-        """ D.walkfiles() -> iterator over files in D, recursively.
-
-        The optional argument, pattern, limits the results to files
-        with names that match the pattern.  For example,
-        mydir.walkfiles('*.tmp') yields only files with the .tmp
-        extension.
-        """
-        if errors not in ('strict', 'warn', 'ignore'):
-            raise ValueError("invalid errors parameter")
-
-        try:
-            childList = self.listdir()
-        except Exception:
-            if errors == 'ignore':
-                return
-            elif errors == 'warn':
-                warnings.warn(
-                    "Unable to list directory '%s': %s"
-                    % (self, sys.exc_info()[1]),
-                    TreeWalkWarning)
-                return
-            else:
-                raise
-
-        for child in childList:
-            try:
-                isfile = child.isfile()
-                isdir = not isfile and child.isdir()
-            except:
-                if errors == 'ignore':
-                    continue
-                elif errors == 'warn':
-                    warnings.warn(
-                        "Unable to access '%s': %s"
-                        % (self, sys.exc_info()[1]),
-                        TreeWalkWarning)
-                    continue
-                else:
-                    raise
-
-            if isfile:
-                if pattern is None or child.fnmatch(pattern):
-                    yield child
-            elif isdir:
-                for f in child.walkfiles(pattern, errors):
-                    yield f
-
-    def fnmatch(self, pattern):
-        """ Return True if self.name matches the given pattern.
-
-        pattern - A filename pattern with wildcards,
-            for example '*.py'.
-        """
-        return fnmatch.fnmatch(self.name, pattern)
-
-    def glob(self, pattern):
-        """ Return a list of path objects that match the pattern.
-
-        pattern - a path relative to this directory, with wildcards.
-
-        For example, path('/users').glob('*/bin/*') returns a list
-        of all the files users have in their bin directories.
-        """
-        cls = self.__class__
-        return [cls(s) for s in glob.glob(_base(self / pattern))]
-
-    #
-    # --- Reading or writing an entire file at once.
-
-    def open(self, mode='r'):
-        """ Open this file.  Return a file object. """
-        return open(self, mode)
-
-    def bytes(self):
-        """ Open this file, read all bytes, return them as a string. """
-        f = self.open('rb')
-        try:
-            return f.read()
-        finally:
-            f.close()
-
-    def write_bytes(self, bytes, append=False):
-        """ Open this file and write the given bytes to it.
-
-        Default behavior is to overwrite any existing file.
-        Call p.write_bytes(bytes, append=True) to append instead.
-        """
-        if append:
-            mode = 'ab'
-        else:
-            mode = 'wb'
-        f = self.open(mode)
-        try:
-            f.write(bytes)
-        finally:
-            f.close()
-
-    def text(self, encoding=None, errors='strict'):
-        r""" Open this file, read it in, return the content as a string.
-
-        This uses 'U' mode in Python 2.3 and later, so '\r\n' and '\r'
-        are automatically translated to '\n'.
-
-        Optional arguments:
-
-        encoding - The Unicode encoding (or character set) of
-            the file.  If present, the content of the file is
-            decoded and returned as a unicode object; otherwise
-            it is returned as an 8-bit str.
-        errors - How to handle Unicode errors; see help(str.decode)
-            for the options.  Default is 'strict'.
-        """
-        if encoding is None:
-            # 8-bit
-            f = self.open(_textmode)
-            try:
-                return f.read()
-            finally:
-                f.close()
-        else:
-            # Unicode
-            f = codecs.open(self, 'r', encoding, errors)
-            # (Note - Can't use 'U' mode here, since codecs.open
-            # doesn't support 'U' mode, even in Python 2.3.)
-            try:
-                t = f.read()
-            finally:
-                f.close()
-            return (t.replace(u('\r\n'), u('\n'))
-                     .replace(u('\r\x85'), u('\n'))
-                     .replace(u('\r'), u('\n'))
-                     .replace(u('\x85'), u('\n'))
-                     .replace(u('\u2028'), u('\n')))
-
-    def write_text(self, text, encoding=None, errors='strict', linesep=os.linesep, append=False):
-        r""" Write the given text to this file.
-
-        The default behavior is to overwrite any existing file;
-        to append instead, use the 'append=True' keyword argument.
-
-        There are two differences between path.write_text() and
-        path.write_bytes(): newline handling and Unicode handling.
-        See below.
-
-        Parameters:
-
-          - text - str/unicode - The text to be written.
-
-          - encoding - str - The Unicode encoding that will be used.
-            This is ignored if 'text' isn't a Unicode string.
-
-          - errors - str - How to handle Unicode encoding errors.
-            Default is 'strict'.  See help(unicode.encode) for the
-            options.  This is ignored if 'text' isn't a Unicode
-            string.
-
-          - linesep - keyword argument - str/unicode - The sequence of
-            characters to be used to mark end-of-line.  The default is
-            os.linesep.  You can also specify None; this means to
-            leave all newlines as they are in 'text'.
-
-          - append - keyword argument - bool - Specifies what to do if
-            the file already exists (True: append to the end of it;
-            False: overwrite it.)  The default is False.
-
-
-        --- Newline handling.
-
-        write_text() converts all standard end-of-line sequences
-        ('\n', '\r', and '\r\n') to your platform's default end-of-line
-        sequence (see os.linesep; on Windows, for example, the
-        end-of-line marker is '\r\n').
-
-        If you don't like your platform's default, you can override it
-        using the 'linesep=' keyword argument.  If you specifically want
-        write_text() to preserve the newlines as-is, use 'linesep=None'.
-
-        This applies to Unicode text the same as to 8-bit text, except
-        there are three additional standard Unicode end-of-line sequences:
-        u'\x85', u'\r\x85', and u'\u2028'.
-
-        (This is slightly different from when you open a file for
-        writing with fopen(filename, "w") in C or open(filename, 'w')
-        in Python.)
-
-
-        --- Unicode
-
-        If 'text' isn't Unicode, then apart from newline handling, the
-        bytes are written verbatim to the file.  The 'encoding' and
-        'errors' arguments are not used and must be omitted.
-
-        If 'text' is Unicode, it is first converted to bytes using the
-        specified 'encoding' (or the default encoding if 'encoding'
-        isn't specified).  The 'errors' argument applies only to this
-        conversion.
-
-        """
-        if is_unicode(text):
-            if linesep is not None:
-                # Convert all standard end-of-line sequences to
-                # ordinary newline characters.
-                text = (text.replace(u('\r\n'), u('\n'))
-                            .replace(u('\r\x85'), u('\n'))
-                            .replace(u('\r'), u('\n'))
-                            .replace(u('\x85'), u('\n'))
-                            .replace(u('\u2028'), u('\n')))
-                text = text.replace(u('\n'), linesep)
-            if encoding is None:
-                encoding = sys.getdefaultencoding()
-            bytes = text.encode(encoding, errors)
-        else:
-            # It is an error to specify an encoding if 'text' is
-            # an 8-bit string.
-            assert encoding is None
-
-            if linesep is not None:
-                text = (text.replace('\r\n', '\n')
-                            .replace('\r', '\n'))
-                bytes = text.replace('\n', linesep)
-
-        self.write_bytes(bytes, append)
-
-    def lines(self, encoding=None, errors='strict', retain=True):
-        r""" Open this file, read all lines, return them in a list.
-
-        Optional arguments:
-            encoding - The Unicode encoding (or character set) of
-                the file.  The default is None, meaning the content
-                of the file is read as 8-bit characters and returned
-                as a list of (non-Unicode) str objects.
-            errors - How to handle Unicode errors; see help(str.decode)
-                for the options.  Default is 'strict'
-            retain - If true, retain newline characters; but all newline
-                character combinations ('\r', '\n', '\r\n') are
-                translated to '\n'.  If false, newline characters are
-                stripped off.  Default is True.
-
-        This uses 'U' mode in Python 2.3 and later.
-        """
-        if encoding is None and retain:
-            f = self.open(_textmode)
-            try:
-                return f.readlines()
-            finally:
-                f.close()
-        else:
-            return self.text(encoding, errors).splitlines(retain)
-
-    def write_lines(self, lines, encoding=None, errors='strict',
-                    linesep=os.linesep, append=False):
-        r""" Write the given lines of text to this file.
-
-        By default this overwrites any existing file at this path.
-
-        This puts a platform-specific newline sequence on every line.
-        See 'linesep' below.
-
-        lines - A list of strings.
-
-        encoding - A Unicode encoding to use.  This applies only if
-            'lines' contains any Unicode strings.
-
-        errors - How to handle errors in Unicode encoding.  This
-            also applies only to Unicode strings.
-
-        linesep - The desired line-ending.  This line-ending is
-            applied to every line.  If a line already has any
-            standard line ending ('\r', '\n', '\r\n', u'\x85',
-            u'\r\x85', u'\u2028'), that will be stripped off and
-            this will be used instead.  The default is os.linesep,
-            which is platform-dependent ('\r\n' on Windows, '\n' on
-            Unix, etc.)  Specify None to write the lines as-is,
-            like file.writelines().
-
-        Use the keyword argument append=True to append lines to the
-        file.  The default is to overwrite the file.  Warning:
-        When you use this with Unicode data, if the encoding of the
-        existing data in the file is different from the encoding
-        you specify with the encoding= parameter, the result is
-        mixed-encoding data, which can really confuse someone trying
-        to read the file later.
-        """
-        if append:
-            mode = 'ab'
-        else:
-            mode = 'wb'
-        f = self.open(mode)
-        try:
-            for line in lines:
-                isUnicode = is_unicode(line)
-                if linesep is not None:
-                    # Strip off any existing line-end and add the
-                    # specified linesep string.
-                    if isUnicode:
-                        if line[-2:] in (u('\r\n'), u('\x0d\x85')):
-                            line = line[:-2]
-                        elif line[-1:] in (u('\r'), u('\n'),
-                                           u('\x85'), u('\u2028')):
-                            line = line[:-1]
-                    else:
-                        if line[-2:] == '\r\n':
-                            line = line[:-2]
-                        elif line[-1:] in ('\r', '\n'):
-                            line = line[:-1]
-                    line += linesep
-                if isUnicode:
-                    if encoding is None:
-                        encoding = sys.getdefaultencoding()
-                    line = line.encode(encoding, errors)
-                f.write(line)
-        finally:
-            f.close()
-
-    def read_md5(self):
-        """ Calculate the md5 hash for this file.
-
-        This reads through the entire file.
-        """
-        return self.read_hash('md5')
-
-    def _hash(self, hash_name):
-        f = self.open('rb')
-        try:
-            m = hashlib.new(hash_name)
-            while True:
-                d = f.read(8192)
-                if not d:
-                    break
-                m.update(d)
-            return m
-        finally:
-            f.close()
-
-    def read_hash(self, hash_name):
-        """ Calculate given hash for this file.
-
-        List of supported hashes can be obtained from hashlib package. This
-        reads the entire file.
-        """
-        return self._hash(hash_name).digest()
-
-    def read_hexhash(self, hash_name):
-        """ Calculate given hash for this file, returning hexdigest.
-
-        List of supported hashes can be obtained from hashlib package. This
-        reads the entire file.
-        """
-        return self._hash(hash_name).hexdigest()
-
-    # --- Methods for querying the filesystem.
-    # N.B. On some platforms, the os.path functions may be implemented in C
-    # (e.g. isdir on Windows, Python 3.2.2), and compiled functions don't get
-    # bound. Playing it safe and wrapping them all in method calls.
-
-    def isabs(self): return os.path.isabs(self)
-    def exists(self): return os.path.exists(self)
-    def isdir(self): return os.path.isdir(self)
-    def isfile(self): return os.path.isfile(self)
-    def islink(self): return os.path.islink(self)
-    def ismount(self): return os.path.ismount(self)
-
-    if hasattr(os.path, 'samefile'):
-        def samefile(self): return os.path.samefile(self)
-
-    def getatime(self): return os.path.getatime(self)
-    atime = property(
-        getatime, None, None,
-        """ Last access time of the file. """)
-
-    def getmtime(self): return os.path.getmtime(self)
-    mtime = property(
-        getmtime, None, None,
-        """ Last-modified time of the file. """)
-
-    if hasattr(os.path, 'getctime'):
-        def getctime(self): return os.path.getctime(self)
-        ctime = property(
-            getctime, None, None,
-            """ Creation time of the file. """)
-
-    def getsize(self): return os.path.getsize(self)
-    size = property(
-        getsize, None, None,
-        """ Size of the file, in bytes. """)
-
-    if hasattr(os, 'access'):
-        def access(self, mode):
-            """ Return true if current user has access to this path.
-
-            mode - One of the constants os.F_OK, os.R_OK, os.W_OK, os.X_OK
-            """
-            return os.access(self, mode)
-
-    def stat(self):
-        """ Perform a stat() system call on this path. """
-        return os.stat(self)
-
-    def lstat(self):
-        """ Like path.stat(), but do not follow symbolic links. """
-        return os.lstat(self)
-
-    def get_owner(self):
-        r""" Return the name of the owner of this file or directory.
-
-        This follows symbolic links.
-
-        On Windows, this returns a name of the form ur'DOMAIN\User Name'.
-        On Windows, a group can own a file or directory.
-        """
-        if os.name == 'nt':
-            if win32security is None:
-                raise Exception("path.owner requires win32all to be installed")
-            desc = win32security.GetFileSecurity(
-                self, win32security.OWNER_SECURITY_INFORMATION)
-            sid = desc.GetSecurityDescriptorOwner()
-            account, domain, typecode = win32security.LookupAccountSid(None, sid)
-            return domain + u('\\') + account
-        else:
-            if pwd is None:
-                raise NotImplementedError("path.owner is not implemented on this platform.")
-            st = self.stat()
-            return pwd.getpwuid(st.st_uid).pw_name
-
-    owner = property(
-        get_owner, None, None,
-        """ Name of the owner of this file or directory. """)
-
-    if hasattr(os, 'statvfs'):
-        def statvfs(self):
-            """ Perform a statvfs() system call on this path. """
-            return os.statvfs(self)
-
-    if hasattr(os, 'pathconf'):
-        def pathconf(self, name):
-            return os.pathconf(self, name)
-
-    #
-    # --- Modifying operations on files and directories
-
-    def utime(self, times):
-        """ Set the access and modified times of this file. """
-        os.utime(self, times)
-
-    def chmod(self, mode):
-        os.chmod(self, mode)
-
-    if hasattr(os, 'chown'):
-        def chown(self, uid, gid):
-            os.chown(self, uid, gid)
-
-    def rename(self, new):
-        os.rename(self, new)
-
-    def renames(self, new):
-        os.renames(self, new)
-
-    #
-    # --- Create/delete operations on directories
-
-    def mkdir(self, mode=MODE_0777):
-        os.mkdir(self, mode)
-
-    def mkdir_p(self, mode=MODE_0777):
-        try:
-            self.mkdir(mode)
-        except OSError as e:
-            if e.errno != errno.EEXIST:
-                raise
-
-    def makedirs(self, mode=MODE_0777):
-        os.makedirs(self, mode)
-
-    def makedirs_p(self, mode=MODE_0777):
-        try:
-            self.makedirs(mode)
-        except OSError as e:
-            if e.errno != errno.EEXIST:
-                raise
-
-    def rmdir(self):
-        os.rmdir(self)
-
-    def rmdir_p(self):
-        try:
-            self.rmdir()
-        except OSError as e:
-            if e.errno != errno.ENOTEMPTY and e.errno != errno.EEXIST:
-                raise
-
-    def removedirs(self):
-        os.removedirs(self)
-
-    def removedirs_p(self):
-        try:
-            self.removedirs()
-        except OSError as e:
-            if e.errno != errno.ENOTEMPTY and e.errno != errno.EEXIST:
-                raise
-
-    # --- Modifying operations on files
-
-    def touch(self):
-        """ Set the access/modified times of this file to the current time.
-        Create the file if it does not exist.
-        """
-        fd = os.open(self, os.O_WRONLY | os.O_CREAT, MODE_0666)
-        os.close(fd)
-        os.utime(self, None)
-
-    def remove(self):
-        os.remove(self)
-
-    def remove_p(self):
-        try:
-            self.unlink()
-        except OSError as e:
-            if e.errno != errno.ENOENT:
-                raise
-
-    def unlink(self):
-        os.unlink(self)
-
-    def unlink_p(self):
-        self.remove_p()
-
-    # --- Links
-
-    if hasattr(os, 'link'):
-        def link(self, newpath):
-            """ Create a hard link at 'newpath', pointing to this file. """
-            os.link(self, newpath)
-
-    if hasattr(os, 'symlink'):
-        def symlink(self, newlink):
-            """ Create a symbolic link at 'newlink', pointing here. """
-            os.symlink(self, newlink)
-
-    if hasattr(os, 'readlink'):
-        def readlink(self):
-            """ Return the path to which this symbolic link points.
-
-            The result may be an absolute or a relative path.
-            """
-            return self.__class__(os.readlink(self))
-
-        def readlinkabs(self):
-            """ Return the path to which this symbolic link points.
-
-            The result is always an absolute path.
-            """
-            p = self.readlink()
-            if p.isabs():
-                return p
-            else:
-                return (self.parent / p).abspath()
-
-    #
-    # --- High-level functions from shutil
-
-    copyfile = shutil.copyfile
-    copymode = shutil.copymode
-    copystat = shutil.copystat
-    copy = shutil.copy
-    copy2 = shutil.copy2
-    copytree = shutil.copytree
-    if hasattr(shutil, 'move'):
-        move = shutil.move
-    rmtree = shutil.rmtree
-
-    def rmtree_p(self):
-        try:
-            self.rmtree()
-        except OSError as e:
-            if e.errno != errno.ENOENT:
-                raise
-
-    #
-    # --- Special stuff from os
-
-    if hasattr(os, 'chroot'):
-        def chroot(self):
-            os.chroot(self)
-
-    if hasattr(os, 'startfile'):
-        def startfile(self):
-            os.startfile(self)
diff --git a/spyderlib/utils/external/pickleshare.py b/spyderlib/utils/external/pickleshare.py
deleted file mode 100644
index a6c78b9..0000000
--- a/spyderlib/utils/external/pickleshare.py
+++ /dev/null
@@ -1,370 +0,0 @@
-#!/usr/bin/env python
-
-""" PickleShare - a small 'shelve' like datastore with concurrency support
-
-Like shelve, a PickleShareDB object acts like a normal dictionary. Unlike 
-shelve, many processes can access the database simultaneously. Changing a 
-value in database is immediately visible to other processes accessing the 
-same database.
-
-Concurrency is possible because the values are stored in separate files. Hence
-the "database" is a directory where *all* files are governed by PickleShare.
-
-Example usage::
-    
-    from pickleshare import *
-    db = PickleShareDB('~/testpickleshare')
-    db.clear()
-    print "Should be empty:",db.items()
-    db['hello'] = 15
-    db['aku ankka'] = [1,2,313]
-    db['paths/are/ok/key'] = [1,(5,46)]
-    print db.keys()
-    del db['aku ankka']
-
-This module is certainly not ZODB, but can be used for low-load 
-(non-mission-critical) situations where tiny code size trumps the 
-advanced features of a "real" object database.
-
-Installation guide: easy_install pickleshare
-
-Author: Ville Vainio <vivainio at gmail.com>
-License: MIT open source license.
-
-"""
-
-from __future__ import print_function
-
-from spyderlib.utils.external.path import path as Path
-from spyderlib.py3compat import pickle, MutableMapping
-
-import os
-import stat
-import time
-import glob
-import errno
-
-def gethashfile(key):
-    return ("%02x" % abs(hash(key) % 256))[-2:]
-
-_sentinel = object()
-
-class PickleShareDB(MutableMapping):
-    """ The main 'connection' object for PickleShare database """
-    def __init__(self, root):
-        """ Return a db object that will manage the specied directory"""
-        self.root = Path(root).expanduser().abspath()
-        if not self.root.isdir():
-            self.root.makedirs()
-        # cache has { 'key' : (obj, orig_mod_time) }
-        self.cache = {}
-    
-    #==========================================================================
-    # Only affects Python 3
-    def __iter__(self):
-        return iter(self.cache)
-    def __len__(self):
-        return len(self.cache)
-    #==========================================================================
-
-    def __getitem__(self, key):
-        """ db['key'] reading """
-        fil = self.root / key
-        try:
-            mtime = (fil.stat()[stat.ST_MTIME])
-        except OSError:
-            raise KeyError(key)
-
-        if fil in self.cache and mtime == self.cache[fil][1]:
-            return self.cache[fil][0]
-        try:
-            # The cached item has expired, need to read
-            obj = pickle.load(fil.open('rb'))
-        except:
-            raise KeyError(key)
-            
-        self.cache[fil] = (obj, mtime)
-        return obj
-    
-    def __setitem__(self, key, value):
-        """ db['key'] = 5 """
-        fil = self.root / key
-        parent = fil.parent
-        if parent and not parent.isdir():
-            parent.makedirs()
-        # We specify protocol 2, so that we can mostly go between Python 2
-        # and Python 3. We can upgrade to protocol 3 when Python 2 is obsolete.
-        pickled = pickle.dump(value, fil.open('wb'), protocol=2)
-        try:
-            self.cache[fil] = (value, fil.mtime)
-        except OSError as e:
-            if e.errno != errno.ENOENT:
-                raise
-    
-    def hset(self, hashroot, key, value):
-        """ hashed set """
-        hroot = self.root / hashroot
-        if not hroot.isdir():
-            hroot.makedirs()
-        hfile = hroot / gethashfile(key)
-        d = self.get(hfile, {})
-        d.update( {key : value})
-        self[hfile] = d                
-
-    
-    
-    def hget(self, hashroot, key, default = _sentinel, fast_only = True):
-        """ hashed get """
-        hroot = self.root / hashroot
-        hfile = hroot / gethashfile(key)
-        
-        d = self.get(hfile, _sentinel )
-        #print "got dict",d,"from",hfile
-        if d is _sentinel:
-            if fast_only:
-                if default is _sentinel:
-                    raise KeyError(key)
-                    
-                return default
-            
-            # slow mode ok, works even after hcompress()
-            d = self.hdict(hashroot)
-        
-        return d.get(key, default)
-
-    def hdict(self, hashroot):
-        """ Get all data contained in hashed category 'hashroot' as dict """
-        hfiles = self.keys(hashroot + "/*")
-        hfiles.sort()
-        last = len(hfiles) and hfiles[-1] or ''
-        if last.endswith('xx'):
-            # print "using xx"
-            hfiles = [last] + hfiles[:-1]
-            
-        all = {}
-        
-        for f in hfiles:
-            # print "using",f
-            try:
-                all.update(self[f])
-            except KeyError:
-                print("Corrupt", f, "deleted - hset is not threadsafe!")
-                del self[f]
-                
-            self.uncache(f)
-        
-        return all
-    
-    def hcompress(self, hashroot):
-        """ Compress category 'hashroot', so hset is fast again
-        
-        hget will fail if fast_only is True for compressed items (that were
-        hset before hcompress).
-        
-        """
-        hfiles = self.keys(hashroot + "/*")
-        all = {}
-        for f in hfiles:
-            # print "using",f
-            all.update(self[f])
-            self.uncache(f)
-            
-        self[hashroot + '/xx'] = all
-        for f in hfiles:
-            p = self.root / f
-            if p.basename() == 'xx':
-                continue
-            p.remove()
-            
-            
-        
-    def __delitem__(self, key):
-        """ del db["key"] """
-        fil = self.root / key
-        self.cache.pop(fil, None)
-        try:
-            fil.remove()
-        except OSError:
-            # notfound and permission denied are ok - we
-            # lost, the other process wins the conflict
-            pass
-        
-    def _normalized(self, p):
-        """ Make a key suitable for user's eyes """
-        return str(self.root.relpathto(p)).replace('\\', '/')
-    
-    def keys(self, globpat = None):
-        """ All keys in DB, or all keys matching a glob"""
-        
-        if globpat is None:
-            files = self.root.walkfiles()
-        else:
-            files = [Path(p) for p in glob.glob(self.root/globpat)]
-        return [self._normalized(p) for p in files if p.isfile()]
-
-    def uncache(self,*items):
-        """ Removes all, or specified items from cache
-        
-        Use this after reading a large amount of large objects
-        to free up memory, when you won't be needing the objects
-        for a while.
-         
-        """
-        if not items:
-            self.cache = {}
-        for it in items:
-            self.cache.pop(it, None)
-            
-    def waitget(self,key, maxwaittime = 60 ):
-        """ Wait (poll) for a key to get a value
-        
-        Will wait for `maxwaittime` seconds before raising a KeyError.
-        The call exits normally if the `key` field in db gets a value
-        within the timeout period.
-        
-        Use this for synchronizing different processes or for ensuring
-        that an unfortunately timed "db['key'] = newvalue" operation 
-        in another process (which causes all 'get' operation to cause a 
-        KeyError for the duration of pickling) won't screw up your program 
-        logic. 
-        """
-        
-        wtimes = [0.2] * 3 + [0.5] * 2 + [1]
-        tries = 0
-        waited = 0
-        while 1:
-            try:
-                val = self[key]
-                return val
-            except KeyError:
-                pass
-            
-            if waited > maxwaittime:
-                raise KeyError(key)
-            
-            time.sleep(wtimes[tries])
-            waited+=wtimes[tries]
-            if tries < len(wtimes) -1:
-                tries+=1
-    
-    def getlink(self, folder):
-        """ Get a convenient link for accessing items  """
-        return PickleShareLink(self, folder)
-    
-    def __repr__(self):
-        return "PickleShareDB('%s')" % self.root
-        
-        
-                
-class PickleShareLink:
-    """ A shortdand for accessing nested PickleShare data conveniently.
-
-    Created through PickleShareDB.getlink(), example::
-
-        lnk = db.getlink('myobjects/test')
-        lnk.foo = 2
-        lnk.bar = lnk.foo + 5
-    
-    """
-    def __init__(self, db, keydir ):    
-        self.__dict__.update(locals())
-        
-    def __getattr__(self, key):
-        return self.__dict__['db'][self.__dict__['keydir']+'/' + key]
-    def __setattr__(self, key, val):
-        self.db[self.keydir+'/' + key] = val
-    def __repr__(self):
-        db = self.__dict__['db']
-        keys = db.keys( self.__dict__['keydir'] +"/*")
-        return "<PickleShareLink '%s': %s>" % (
-            self.__dict__['keydir'],
-            ";".join([Path(k).basename() for k in keys]))
-            
-        
-def test():
-    db = PickleShareDB('~/testpickleshare')
-    db.clear()
-    print("Should be empty:", list(db.items()))
-    db['hello'] = 15
-    db['aku ankka'] = [1, 2, 313]
-    db['paths/nest/ok/keyname'] = [1, (5, 46)]
-    db.hset('hash', 'aku', 12)
-    db.hset('hash', 'ankka', 313)
-    print("12 =", db.hget('hash', 'aku'))
-    print("313 =", db.hget('hash', 'ankka'))
-    print("all hashed", db.hdict('hash'))
-    print(list(db.keys()))
-    print(db.keys('paths/nest/ok/k*'))
-    print(dict(db)) # snapsot of whole db
-    db.uncache() # frees memory, causes re-reads later
-
-    # shorthand for accessing deeply nested files
-    lnk = db.getlink('myobjects/test')
-    lnk.foo = 2
-    lnk.bar = lnk.foo + 5
-    print(lnk.bar) # 7
-
-def stress():
-    db = PickleShareDB('~/fsdbtest')
-    import time, sys
-    for i in range(1000):
-        for j in range(1000):
-            if i % 15 == 0 and i < 200:
-                if str(j) in db:
-                    del db[str(j)]
-                continue
-
-            if j%33 == 0:
-                time.sleep(0.02)
-            
-            db[str(j)] = db.get(str(j), []) + [(i, j, "proc %d" % os.getpid())]
-            db.hset('hash', j, db.hget('hash', j, 15) + 1 )
-            
-        print(i, end=' ')
-        sys.stdout.flush()
-        if i % 10 == 0:
-            db.uncache()
-    
-def main():
-    import textwrap
-    usage = textwrap.dedent("""\
-    pickleshare - manage PickleShare databases 
-    
-    Usage:
-        
-        pickleshare dump /path/to/db > dump.txt
-        pickleshare load /path/to/db < dump.txt
-        pickleshare test /path/to/db
-    """)
-    DB = PickleShareDB
-    import sys
-    if len(sys.argv) < 2:
-        print(usage)
-        return
-        
-    cmd = sys.argv[1]
-    args = sys.argv[2:]
-    if cmd == 'dump':
-        if not args: args= ['.']
-        db = DB(args[0])
-        import pprint
-        pprint.pprint(list(db.items()))
-    elif cmd == 'load':
-        cont = sys.stdin.read()
-        db = DB(args[0])
-        data = eval(cont)
-        db.clear()
-        for k, v in list(db.items()):
-            db[k] = v
-    elif cmd == 'testwait':
-        db = DB(args[0])
-        db.clear()
-        print(db.waitget('250'))
-    elif cmd == 'test':
-        test()
-        stress()
-    
-if __name__== "__main__":
-    main()
-    
-    
diff --git a/spyderlib/utils/icon_manager.py b/spyderlib/utils/icon_manager.py
new file mode 100644
index 0000000..d54498b
--- /dev/null
+++ b/spyderlib/utils/icon_manager.py
@@ -0,0 +1,264 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2009- The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+import os
+
+from spyderlib.qt.QtGui import QIcon, QWidget, QStyle
+
+from spyderlib.config.base import get_image_path
+from spyderlib.config.main import CONF
+
+from path import Path
+import qtawesome as qta
+
+
+_resource = {
+    'directory': os.path.join(os.path.dirname(os.path.realpath(__file__)), '../fonts'),
+    'loaded': False,
+}
+
+_qtaargs = {
+    'log':                     [('fa.file-text-o',), {}],
+    'configure':               [('fa.wrench',), {}],
+    'bold':                    [('fa.bold',), {}],
+    'italic':                  [('fa.italic',), {}],
+    'genprefs':                [('fa.cogs',), {}],
+    'exit':                    [('fa.power-off',), {}],
+    'run_small':               [('fa.play',), {'color':'green'}],
+    'stop':                    [('fa.stop',), {}],
+    'syspath':                 [('fa.cogs',), {}],
+    'font':                    [('fa.font',), {}],
+    'keyboard':                [('fa.keyboard-o',), {}],
+    'eyedropper':              [('fa.eyedropper',), {}],
+    'tooloptions':             [('fa.cog',), {}],
+    'edit24':                  [('fa.edit',), {}],
+    'edit':                    [('fa.edit',), {}],
+    'filenew':                 [('fa.file-o', 'fa.plus'), {'options': [{}, {'scale_factor': 0.5, 'offset': (0.0, 0.1)}]}],
+    'fileopen':                [('fa.folder-open',), {}],
+    'revert':                  [('fa.undo',), {}],
+    'filesave':                [('fa.save',), {}],
+    'save_all':                [('fa.save', 'fa.save'), {'options': [{'offset': (-0.2, -0.2), 'scale_factor': 0.6}, {'offset': (0.2, 0.2), 'scale_factor': 0.6}]}],
+    'filesaveas':              [('fa.save', 'fa.pencil'), {'options': [{'offset': (-0.2, -0.2), 'scale_factor': 0.6}, {'offset': (0.2, 0.2), 'scale_factor': 0.6}]}],
+    'print':                   [('fa.print',), {}],
+    'fileclose':               [('fa.close',), {}],
+    'filecloseall':            [('fa.close', 'fa.close', 'fa.close'), {'options': [{'scale_factor': 0.6, 'offset': (0.3, -0.3)},  {'scale_factor': 0.6, 'offset': (-0.3, -0.3)}, {'scale_factor': 0.6, 'offset': (0.3, 0.3)}]}],
+    'breakpoint_big':          [('fa.circle',), {'color': 'darkred'} ],
+    'breakpoint_cond_big':     [('fa.question-circle',), {'color':  'darkred'},],
+    'debug':                   [('spyder.debug',), {'color': '#3775a9'}],
+    'arrow-step-over':         [('spyder.step-forward',), {'color': '#3775a9'}],
+    'arrow-continue':          [('spyder.continue',), {'color': '#3775a9'}],
+    'arrow-step-in':           [('spyder.step-into',), {'color': '#3775a9'}],
+    'arrow-step-out':          [('spyder.step-out',), {'color': '#3775a9'}],
+    'stop_debug':              [('fa.stop',), {'color': '#3775a9'}],
+    'run':                     [('fa.play',), {'color': 'green'}],
+    'run_settings':            [('fa.wrench', 'fa.play'), {'options': [{'offset':(0.0, -0.1)}, {'offset': (0.2, 0.125), 'color': 'green', 'scale_factor': 0.8}]}],
+    'run_again':               [('fa.repeat', 'fa.play'), {'options': [{'offset':(0.0, -0.1)}, {'offset': (0.2, 0.125), 'color': 'green', 'scale_factor': 0.8}]}],
+    'run_selection':           [('spyder.run-selection',), {}],
+    'run_cell':                [('spyder.cell-page', 'spyder.cell-border', 'spyder.cell-code', 'spyder.cell-page-shadow', 'spyder.cell-play'),
+                                {'options': [{'color': 'white'}, {'color': 'gray'}, {'color': '#fff683'}, {}, {'color': 'green'}]}],
+    'run_cell_advance':        [('spyder.cell-page', 'spyder.cell-border', 'spyder.cell-code', 'spyder.cell-page-shadow', 'spyder.cell-play', 'spyder.cell-next'),
+                                {'options': [{'color': 'white'}, {'color': 'gray'}, {'color': '#fff683'}, {}, {'color': 'green'}, {'color': 'red'}]}],
+    'todo_list':               [('fa.th-list', 'fa.check'), {'options': [{'color': '#3775a9'}, {'offset': (0.0, 0.2), 'color': 'orange', 'color_disabled': '#face7e'}]}],
+    'wng_list':                [('fa.th-list', 'fa.warning'), {'options': [{'color': '#3775a9'}, {'offset': (0.0, 0.2), 'scale_factor': 0.75, 'color': 'orange', 'color_disabled': '#face7e'}]}],
+    'prev_wng':                [('fa.arrow-left', 'fa.warning'), {'options': [{'color': '#3775a9'}, {'offset': (0.0, 0.2), 'scale_factor': 0.75, 'color': 'orange', 'color_disabled': '#face7e'}]}],
+    'next_wng':                [('fa.arrow-right', 'fa.warning'), {'options': [{'color': '#3775a9'}, {'offset': (0.0, 0.2), 'scale_factor': 0.75, 'color': 'orange', 'color_disabled': '#face7e'}]}],
+    'last_edit_location':      [('fa.caret-up',), {}],
+    'prev_cursor':             [('fa.hand-o-left',), {}],
+    'next_cursor':             [('fa.hand-o-right',), {}],
+    'comment':                 [('fa.comment',), {}],
+    'indent':                  [('fa.indent',), {}],
+    'unindent':                [('fa.outdent',), {}],
+    'gotoline':                [('fa.sort-numeric-asc',), {}],
+    'error':                   [('fa.times-circle',), {}],
+    'warning':                 [('fa.warning',), {'color': 'orange'}],
+    'todo':                    [('fa.check',), {'color': 'orange'}],
+    'ipython_console':         [('spyder.ipython-logo-alt',), {}],
+    'ipython_console_t':       [('spyder.ipython-logo-alt',), {'color':'gray'}],
+    'python':                  [('spyder.python-logo-up', 'spyder.python-logo-down'), {'options': [{'color': '#3775a9'}, {'color': '#ffd444'}]}],
+    'python_t':                [('spyder.python-logo',), {'color':'gray'}],
+    'pythonpath':              [('spyder.python-logo-up', 'spyder.python-logo-down'), {'options': [{'color': '#3775a9'}, {'color': '#ffd444'}]}],
+    'terminated':              [('fa.circle',), {}],
+    'cmdprompt':               [('fa.terminal',), {}],
+    'cmdprompt_t':             [('fa.terminal',), {'color':'gray'}],
+    'console':                 [('spyder.python-logo-up', 'spyder.python-logo-down'), {'options': [{'color': '#3775a9'}, {'color': '#ffd444'}]}],
+    'findf':                   [('fa.file-o', 'fa.search'), {'options': [{'scale_factor': 1.0}, {'scale_factor': 0.6}]}],
+    'history24':               [('fa.history',), {}],
+    'history':                 [('fa.history',), {}],
+    'inspector':               [('fa.question-circle',), {}],
+    'lock':                    [('fa.lock',), {}],
+    'lock_open':               [('fa.unlock-alt',), {}],
+    'outline_explorer':        [('spyder.treeview',), {}],
+    'project_expanded':        [('fa.plus',), {}],
+    'dictedit':                [('fa.th-list',), {}],
+    'previous':                [('fa.arrow-left',), {}],
+    'next':                    [('fa.arrow-right',), {}],
+    'set_workdir':             [('fa.check',), {}],
+    'up':                      [('fa.arrow-up',), {}],
+    'down':                    [('fa.arrow-down',), {}],
+    'filesaveas2':             [('fa.save', 'fa.close'), {'options': [{'scale_factor': 0.8, 'offset': (-0.1, -0.1)}, {'offset': (0.2, 0.2)}]}],   # save_session_action
+    'spyder_light':            [('spyder.spyder-logo-background', 'spyder.spyder-logo-web'), {'options': [{'color': '#414141'}, {'color': '#fafafa'}]}],
+    'spyder':                  [('spyder.spyder-logo-background', 'spyder.spyder-logo-web', 'spyder.spyder-logo-snake'),  {'options': [{'color': '#414141'}, {'color': '#fafafa'}, {'color': '#ee0000'}]}],
+    'find':                    [('fa.search',), {}],
+    'findnext':                [('fa.search', 'fa.long-arrow-down'), {'options':[{'scale_factor': 0.6, 'offset': (0.3, 0.0)}, {'offset': (-0.3, 0.0)}]}],
+    'findprevious':            [('fa.search', 'fa.long-arrow-up'), {'options':[{'scale_factor': 0.6, 'offset': (0.3, 0.0)}, {'offset': (-0.3, 0.0)}]}],
+    'replace':                 [('fa.exchange',), {}],
+    'undo':                    [('fa.undo',), {}],
+    'redo':                    [('fa.repeat',), {}],
+    'restart':                 [('fa.repeat',), {}],
+    'editcopy':                [('fa.copy',), {}],
+    'editcut':                 [('fa.scissors',), {}],
+    'editpaste':               [('fa.clipboard',), {}],
+    'editdelete':              [('fa.eraser',), {}],
+    'editclear':               [('fa.times',), {}],
+    'selectall':               [('spyder.text-select-all',), {}],
+    'pythonpath_mgr':          [('spyder.python-logo-up', 'spyder.python-logo-down'), {'options': [{'color': '#3775a9'}, {'color': '#ffd444'}]}],
+    'exit':                    [('fa.power-off',), {}],
+    'advanced':                [('fa.gear',), {}],
+    'bug':                     [('fa.bug',), {}],
+    'maximize':                [('spyder.maximize-pane',), {}],
+    'unmaximize':              [('spyder.minimize-pane',), {}],
+    'window_nofullscreen':     [('spyder.inward',), {}],
+    'window_fullscreen':       [('fa.arrows-alt',), {}],
+    'MessageBoxWarning':       [('fa.warning',), {}],
+    'arredit':                 [('fa.table',), {}],
+    'zoom_out':                [('fa.search-minus',), {}],
+    'zoom_in':                 [('fa.search-plus',), {}],
+    'home':                    [('fa.home',), {}],
+    'find':                    [('fa.search',), {}],
+    'plot':                    [('fa.line-chart',), {}],
+    'hist':                    [('fa.bar-chart',), {}],
+    'imshow':                  [('fa.image',), {}],
+    'insert':                  [('fa.sign-in',), {}],
+    'rename':                  [('fa.pencil',), {}],
+    'edit_add':                [('fa.plus',), {}],
+    'edit_remove':             [('fa.minus',), {}],
+    'browse_tab':              [('fa.folder-o',), {}],
+    'filelist':                [('fa.list',), {}],
+    'newwindow':               [('spyder.window',), {}],
+    'versplit':                [('spyder.rows',), {}],
+    'horsplit':                [('fa.columns',), {}],
+    'close_panel':             [('fa.close',), {}],
+    'class':                   [('spyder.circle-letter-c',), {'color':'#3775a9'}],
+    'private2':                [('fa.minus-circle',), {'color':'#7ea67e'}],
+    'private1':                [('fa.minus-circle',), {'color':'#7ea67e'}],
+    'method':                  [('spyder.circle-letter-m',), {'color':'green'}],
+    'function':                [('spyder.circle-letter-f',), {'color':'orange'}],
+    'blockcomment':            [('spyder.circle-hash',), {'color':'grey'}],
+    'cell':                    [('spyder.circle-percent',), {'color':'red'}],
+    'fromcursor':              [('fa.hand-o-right',), {}],
+    'filter':                  [('fa.filter',), {}],
+    'folder_new':              [('fa.folder-o', 'fa.plus'), {'options': [{}, {'scale_factor': 0.5, 'offset': (0.0, 0.1)}]}],
+    'package_new':             [('fa.folder-o', 'spyder.python-logo'), {'options': [{'offset': (0.0, -0.125)}, {'offset': (0.0, 0.125)}]}],
+    'vcs_commit':              [('fa.check',), {'color': 'green'}],
+    'vcs_browse':              [('fa.search',), {'color': 'green'}],
+    'kill':                    [('fa.warning',), {}],
+    'reload':                  [('fa.repeat',), {}],
+    'auto_reload':             [('fa.repeat', 'fa.clock-o'), {'options': [{'scale_factor': 0.75, 'offset': (-0.1, -0.1)}, {'scale_factor': 0.5, 'offset': (0.25, 0.25)}]}],
+    'fileimport':              [('fa.download',), {}],
+    'environ':                 [('fa.th-list',), {}],
+    'options_less':            [('fa.minus-square',), {}],
+    'options_more':            [('fa.plus-square',), {}],
+    'ArrowDown':               [('fa.arrow-circle-down',), {}],
+    'ArrowUp':                 [('fa.arrow-circle-up',), {}],
+    'ArrowBack':               [('fa.arrow-circle-left',), {}],
+    'ArrowForward':            [('fa.arrow-circle-right',), {}],
+    'DialogApplyButton':       [('fa.check',), {}],
+    'DialogCloseButton':       [('fa.close',), {}],
+    'DialogHelpButton':        [('fa.question',), {}],
+    'DirClosedIcon':           [('fa.folder-o',), {}],
+    'DialogHelpButton':        [('fa.life-ring',), {}],
+    'MessageBoxInformation':   [('fa.info',), {}],
+    'DirOpenIcon':             [('fa.folder-open',), {}],
+    'FileIcon':                [('fa.file-o',), {}],
+    'DriveHDIcon':             [('fa.hdd-o',), {}],
+    'arrow':                   [('fa.arrow-right',), {}],
+    'collapse':                [('spyder.inward',), {}],
+    'expand':                  [('fa.arrows-alt',), {}],
+    'restore':                 [('fa.level-up',), {}],
+    'collapse_selection':      [('fa.minus-square-o',), {}],
+    'expand_selection':        [('fa.plus-square-o',), {}],
+    'copywop':                 [('fa.terminal',), {}],
+    'editpaste':               [('fa.paste',), {}],
+    'editcopy':                [('fa.copy',), {}],
+    'edit':                    [('fa.edit',), {}],
+    'convention':              [('spyder.circle-letter-c',), {'color':'#3775a9'}],
+    'refactor':                [('spyder.circle-letter-r',), {'color':'#3775a9'}],
+    '2uparrow':                [('fa.angle-double-up',), {}],
+    '1uparrow':                [('fa.angle-up',), {}],
+    '2downarrow':              [('fa.angle-double-down',), {}],
+    '1downarrow':              [('fa.angle-down',), {}],    
+    'attribute':               [('spyder.circle-letter-a',), {'color': 'magenta'}],
+    'module':                  [('spyder.circle-letter-m',), {'color': '#daa520'}],
+    'no_match':                [('fa.circle',), {'color': 'gray'}],
+    'no_match':                [('fa.circle',), {'color': 'gray'}],
+    # --- Third party plugins ------------------------------------------------
+    'profiler':                [('fa.clock-o',), {}],
+    'pylint':                  [('fa.search', 'fa.check'), {'options': [{}, {'offset': (0.125, 0.125), 'color': 'orange'}]}],
+    'condapackages':           [('fa.archive',), {}],
+    'spyder.example':          [('fa.eye',), {}],
+    'spyder.autopep8':         [('fa.eye',), {}],
+    'spyder.memory_profiler':  [('fa.eye',), {}],
+    'spyder.line_profiler':    [('fa.eye',), {}],
+}
+
+
+def get_std_icon(name, size=None):
+    """Get standard platform icon
+    Call 'show_std_icons()' for details"""
+    if not name.startswith('SP_'):
+        name = 'SP_' + name
+    icon = QWidget().style().standardIcon(getattr(QStyle, name))
+    if size is None:
+        return icon
+    else:
+        return QIcon(icon.pixmap(size, size))
+
+
+def get_icon(name, default=None, resample=False):
+    """Return image inside a QIcon object
+    default: default image name or icon
+    resample: if True, manually resample icon pixmaps for usual sizes
+    (16, 24, 32, 48, 96, 128, 256). This is recommended for QMainWindow icons 
+    created from SVG images on non-Windows platforms due to a Qt bug (see 
+    Issue 1314)."""
+
+    icon_path = get_image_path(name, default=None)
+    if icon_path is not None:
+        icon = QIcon(icon_path)
+    elif isinstance(default, QIcon):
+        icon = default
+    elif default is None:
+        try:
+            icon = get_std_icon(name[:-4])
+        except AttributeError:
+            icon = QIcon(get_image_path(name, default))
+    else:
+        icon = QIcon(get_image_path(name, default))
+    if resample:
+        icon0 = QIcon()
+        for size in (16, 24, 32, 48, 96, 128, 256, 512):
+            icon0.addPixmap(icon.pixmap(size, size))
+        return icon0
+    else:
+        return icon
+
+
+def icon(name, resample=False, icon_path=None):
+    theme = CONF.get('main', 'icon_theme')
+    if theme == 'spyder 3':
+        if not _resource['loaded']:
+            qta.load_font('spyder', 'spyder.ttf', 'spyder-charmap.json',
+                          directory=_resource['directory'])
+            _resource['loaded'] = True
+        args, kwargs = _qtaargs[name]
+        return qta.icon(*args, **kwargs)
+    elif theme == 'spyder 2':
+        icon = get_icon(name + '.png', resample=resample)
+        if icon_path:
+            icon_path = Path(icon_path) / (name + '.png')
+            if icon_path.isfile():
+                icon = QIcon(icon_path)
+        return icon if icon is not None else QIcon()
diff --git a/spyderlib/utils/inspector/__init__.py b/spyderlib/utils/inspector/__init__.py
index 1e94792..f83a57d 100644
--- a/spyderlib/utils/inspector/__init__.py
+++ b/spyderlib/utils/inspector/__init__.py
@@ -12,5 +12,5 @@ Configuration files for the object inspector rich text mode
 """
 
 import sys
-from spyderlib.baseconfig import get_module_source_path
+from spyderlib.config.base import get_module_source_path
 sys.path.insert(0, get_module_source_path(__name__))
\ No newline at end of file
diff --git a/spyderlib/utils/inspector/conf.py b/spyderlib/utils/inspector/conf.py
index 36515fa..02d0961 100644
--- a/spyderlib/utils/inspector/conf.py
+++ b/spyderlib/utils/inspector/conf.py
@@ -10,7 +10,7 @@
 from sphinx import __version__ as sphinx_version
 
 # Local imports
-from spyderlib.config import CONF
+from spyderlib.config.main import CONF
 from spyderlib.py3compat import u
 
 #==============================================================================
diff --git a/spyderlib/utils/inspector/sphinxify.py b/spyderlib/utils/inspector/sphinxify.py
index dc3822c..19f985a 100644
--- a/spyderlib/utils/inspector/sphinxify.py
+++ b/spyderlib/utils/inspector/sphinxify.py
@@ -23,6 +23,7 @@ import os.path as osp
 import shutil
 import sys
 from tempfile import mkdtemp
+from xml.sax.saxutils import escape
 
 # 3rd party imports
 from docutils.utils import SystemMessage as SystemMessage
@@ -31,7 +32,7 @@ import sphinx
 from sphinx.application import Sphinx
 
 # Local imports
-from spyderlib.baseconfig import (_, get_module_data_path,
+from spyderlib.config.base import (_, get_module_data_path,
                                   get_module_source_path)
 from spyderlib.utils import encoding
 
@@ -177,7 +178,9 @@ def sphinxify(docstring, context, buildername='html'):
     
     # Add a class to several characters on the argspec. This way we can
     # highlight them using css, in a similar way to what IPython does.
-    argspec = context['argspec']
+    # NOTE: Before doing this, we escape common html chars so that they
+    # don't interfere with the rest of html present in the page
+    argspec = escape(context['argspec'])
     for char in ['=', ',', '(', ')', '*', '**']:
         argspec = argspec.replace(char,
                          '<span class="argspec-highlight">' + char + '</span>')
diff --git a/spyderlib/utils/inspector/static/images/collapse_expand.png b/spyderlib/utils/inspector/static/images/collapse_expand.png
index 4edee42..001650e 100644
Binary files a/spyderlib/utils/inspector/static/images/collapse_expand.png and b/spyderlib/utils/inspector/static/images/collapse_expand.png differ
diff --git a/spyderlib/utils/inspector/static/images/debug-continue.png b/spyderlib/utils/inspector/static/images/debug-continue.png
index 38a87cd..fe021de 100644
Binary files a/spyderlib/utils/inspector/static/images/debug-continue.png and b/spyderlib/utils/inspector/static/images/debug-continue.png differ
diff --git a/spyderlib/utils/inspector/static/images/debug-step-in.png b/spyderlib/utils/inspector/static/images/debug-step-in.png
index 5978c72..34590bd 100644
Binary files a/spyderlib/utils/inspector/static/images/debug-step-in.png and b/spyderlib/utils/inspector/static/images/debug-step-in.png differ
diff --git a/spyderlib/utils/inspector/static/images/debug-step-out.png b/spyderlib/utils/inspector/static/images/debug-step-out.png
index a9ddc32..a2f006f 100644
Binary files a/spyderlib/utils/inspector/static/images/debug-step-out.png and b/spyderlib/utils/inspector/static/images/debug-step-out.png differ
diff --git a/spyderlib/utils/inspector/static/images/debug-step-over.png b/spyderlib/utils/inspector/static/images/debug-step-over.png
index 2310b2e..1686e73 100644
Binary files a/spyderlib/utils/inspector/static/images/debug-step-over.png and b/spyderlib/utils/inspector/static/images/debug-step-over.png differ
diff --git a/spyderlib/utils/inspector/static/images/spyder-hello-docstring.png b/spyderlib/utils/inspector/static/images/spyder-hello-docstring.png
index d53bdab..2dde094 100644
Binary files a/spyderlib/utils/inspector/static/images/spyder-hello-docstring.png and b/spyderlib/utils/inspector/static/images/spyder-hello-docstring.png differ
diff --git a/spyderlib/utils/inspector/static/images/spyder-nice-docstring-rendering.png b/spyderlib/utils/inspector/static/images/spyder-nice-docstring-rendering.png
index 627bc21..87c82fd 100644
Binary files a/spyderlib/utils/inspector/static/images/spyder-nice-docstring-rendering.png and b/spyderlib/utils/inspector/static/images/spyder-nice-docstring-rendering.png differ
diff --git a/spyderlib/utils/inspector/static/images/spyder-sympy-example.png b/spyderlib/utils/inspector/static/images/spyder-sympy-example.png
index a621550..eb6fdc0 100644
Binary files a/spyderlib/utils/inspector/static/images/spyder-sympy-example.png and b/spyderlib/utils/inspector/static/images/spyder-sympy-example.png differ
diff --git a/spyderlib/utils/inspector/tutorial.rst b/spyderlib/utils/inspector/tutorial.rst
index ff9b452..c8edb5a 100644
--- a/spyderlib/utils/inspector/tutorial.rst
+++ b/spyderlib/utils/inspector/tutorial.rst
@@ -169,7 +169,7 @@ Inspecting objects defined in the console
 
 * Once an object is visible in the current name space (as is ``hello``
   in this example), we can use the ``help`` function as follows to
-  learn about it: Typing ``help(hello)`` at the console prompt, you
+  learn about it: typing ``help(hello)`` at the console prompt, you
   should see an output like this::
 
     In [ ]: help(hello)
@@ -186,12 +186,12 @@ Inspecting objects defined in the console
   for the function object ``hello``. The documentation string is the
   first string immediately below the line ``def hello():``.
 
-  This strings are special, and they are called *docstrings* which is short for
+  These strings are special, and they are called *docstrings* which is short for
   *documentation strings*. As they usually extend over multiple lines, there
   are enclosed by triple single quotes (``'''``) or triple double quotes
   (``"""``).
 
-* The Spyder environment also provides the ``Object inspector`` which
+* The Spyder environment also provides the ``Object Inspector`` which
   by default is located in the top right corner.
 
   While the cursor is on the name of an object,
@@ -282,7 +282,7 @@ the console (in the example above, we updated the function object
 ``hello``), is of great use when developing and debugging more complex
 codes, and when creating objects/data in the console session take
 time. For example, by modifying only the functions (or
-classes/objects, etc) that we are actually developing or debugging, we
+classes/objects, etc.) that we are actually developing or debugging, we
 can keep re-using the data and other objects that are defined in the
 console session.
 
@@ -330,7 +330,7 @@ and press return, then confirm with ``y``::
 That's all.
 
 We discuss this a little further, but you can skip the following if
-you are not interested: After issuing the ``%reset`` command, we
+you are not interested: after issuing the ``%reset`` command, we
 should have only a few objects defined in the name space of that
 session. We can list all of them using the ``dir()`` command::
 
@@ -400,7 +400,7 @@ Automatic Symbolic Python
 Through ``Preferences > IPython console > Advanced Settings > Use
 symbolic math`` we can activate IPython's SYMbolic PYthon (sympy) mode that is
 provided by the `sympy <http://sympy.org>`__ module. This mode
-in Spyder allows nicely rendered mathematical output (latex style) and also
+in Spyder allows nicely rendered mathematical output (LaTeX style) and also
 imports some sympy objects automatically when the IPython console starts, and
 reports what it has done.
 
@@ -450,7 +450,7 @@ Shortcuts for useful functions
   (the selection will update automatically) and confirming by pressing
   ``Enter`` when the right name is identified.
 
-- ``Ctrl+Enter`` executes the current cell (menu enty ``Run > Run
+- ``Ctrl+Enter`` executes the current cell (menu entry ``Run > Run
   cell``). A cell is defined as the code between two lines which start with
   the agreed tag ``#%%``.
 
@@ -478,7 +478,7 @@ Shortcuts for useful functions
   size in the Editor, whereas ``Cmd + -`` (``Ctrl + -``) will decrease it.
   Also works in the IPython Console.
 
-  The font size for the Object Inspector, the Python console etc can be set
+  The font size for the Object Inspector, the Python console etc. can be set
   individually via ``Preferences > Object inspector`` etc.
 
   I couldn't find a way of changing the font size in the variable explorer.
@@ -609,7 +609,7 @@ Execute in new dedicated Python console
 ---------------------------------------
 
 Choosing ``Execute in new dedicated Python console`` under ``Run
-> Configure`` will start *a new Python console everytime* the
+> Configure`` will start *a new Python console every time* the
 ``hello.py`` program is executed. The major advantage of this mode
 over `Execute in current Python or IPython console`_ is that we
 can be certain that there are no global objects defined in this
@@ -677,7 +677,7 @@ right window in default layout). Click on the ``Options`` icon (the tooltip is
 Reset all customization
 -----------------------
 
-All customization saved on disk can be reset by calling spyder from
+All customization saved on disk can be reset by calling Spyder from
 the command line with the switch ``--reset``, i.e. a command like
 ``spyder --reset``.
 
@@ -705,7 +705,7 @@ format called restructured text (`quick reference
 also needs to follow a set of conventions called the `Numpydoc standard
 <https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt#id5>`__
 
-If you follow those guidelines, you can obtain beautifully formated docstrings
+If you follow those guidelines, you can obtain beautifully formatted docstrings
 in Spyder.
 
 For example, to get an ``average()`` function look like this in the
@@ -896,7 +896,7 @@ console is::
     In [3]: %matplotlib inline
 
 The command to get figures appear in their own window (which
-technically is a Qt windown) is::
+technically is a Qt window) is::
 
     In [4]: %matplotlib qt
 
@@ -945,6 +945,6 @@ by `Hans Fangohr <http://www.southampton.ac.uk/~fangohr>`__, that are
 used at the `University of Southampton <http://www.soton.ac.uk>`__ to
 `teach Python for computational modelling
 <http://www.southampton.ac.uk/~fangohr/teaching/python.html>`__ to
-undegraduate engineers and postgraduate PhD students for the
+undergraduate engineers and postgraduate PhD students for the
 `Next Generation Computational Modelling <http://ngcm.soton.ac.uk>`__
 doctoral training centre.
diff --git a/spyderlib/utils/introspection/__init__.py b/spyderlib/utils/introspection/__init__.py
index e8aa470..f1835da 100644
--- a/spyderlib/utils/introspection/__init__.py
+++ b/spyderlib/utils/introspection/__init__.py
@@ -9,3 +9,4 @@ Introspection utilities used by Spyder
 """
 from . import module_completion
 from .plugin_manager import PluginManager
+
diff --git a/spyderlib/utils/introspection/fallback_plugin.py b/spyderlib/utils/introspection/fallback_plugin.py
index 888aecd..741dfe6 100644
--- a/spyderlib/utils/introspection/fallback_plugin.py
+++ b/spyderlib/utils/introspection/fallback_plugin.py
@@ -29,14 +29,20 @@ class FallbackPlugin(IntrospectionPlugin):
     name = 'fallback'
 
     def get_completions(self, info):
-        """Return a list of completion strings
+        """Return a list of (completion, type) tuples
 
         Simple completion based on python-like identifiers and whitespace
         """
         items = []
-        if (info.line.strip().startswith(('import ', 'from ')) and
-                info.is_python_like):
+        line = info.line.strip()
+        is_from = line.startswith('from')
+        if ((line.startswith('import') or is_from and ' import' not in line)
+                and info.is_python_like):
             items += module_completion(info.line, [info.filename])
+            return [(i, 'module') for i in sorted(items)]
+        elif is_from and info.is_python_like:
+            items += module_completion(info.line, [info.filename])
+            return [(i, '') for i in sorted(items)]
         elif info.obj:
             base = info.obj
             tokens = set(info.split_words(-1))
@@ -46,7 +52,7 @@ class FallbackPlugin(IntrospectionPlugin):
                 start = base.rfind('.') + 1
             else:
                 start = 0
- 
+
             items = [i[start:len(base)] + i[len(base):].split('.')[0]
                      for i in items]
             # get path completions
@@ -54,7 +60,7 @@ class FallbackPlugin(IntrospectionPlugin):
             match = re.search('''[ "\']([\w\.\\\\/]+)\Z''', info.line)
             if match:
                 items += _complete_path(match.groups()[0])
-        return list(sorted(items))
+            return [(i, '') for i in sorted(items)]
 
     def get_definition(self, info):
         """
@@ -69,6 +75,8 @@ class FallbackPlugin(IntrospectionPlugin):
         filename = info.filename
 
         line_nr = None
+        if token is None:
+            return
         if '.' in token:
             token = token.split('.')[-1]
 
@@ -100,6 +108,21 @@ class FallbackPlugin(IntrospectionPlugin):
 
         return filename, line_nr
 
+    def get_info(self, info):
+        """Get a formatted calltip and docstring from Fallback"""
+        if info.docstring:
+            if info.filename:
+                filename = os.path.basename(info.filename)
+                filename = os.path.splitext(filename)[0]
+            else:
+                filename = '<module>'
+            resp = dict(docstring=info.docstring,
+                        name=filename,
+                        note='',
+                        argspec='',
+                        calltip=None)
+            return resp
+
 
 @memoize
 def python_like_mod_finder(import_line, alt_path=None,
@@ -316,7 +339,7 @@ if __name__ == '__main__':
     assert '.py' in ext and '.pyx' in ext
 
     ext = all_editable_exts()
-    assert '.cfg' in ext and '.iss' in ext
+    assert '.cpp' in ext and '.html' in ext
 
     path = p.get_parent_until(os.path.abspath(__file__))
     assert path == 'spyderlib.utils.introspection.fallback_plugin'
@@ -327,8 +350,10 @@ if __name__ == '__main__':
     path = python_like_mod_finder(line, stop_token='sourcecode')
     assert path.endswith('__init__.py') and 'sourcecode' in path
 
-    path = p.get_parent_until(osp.expanduser(r'~/.spyder2/temp.py'))
-    assert path == '.spyder2.temp'
+    path = osp.expanduser(r'~/.spyder2/temp.py')
+    if os.path.exists(path):
+        path = p.get_parent_until(path)
+        assert path == '.spyder2.temp', path
 
     code = 'import re\n\nre'
     path, line = p.get_definition(CodeInfo('definition', code, len(code),
@@ -337,19 +362,19 @@ if __name__ == '__main__':
 
     code = 'self.proxy.widget; self.p'
     comp = p.get_completions(CodeInfo('completions', code, len(code)))
-    assert comp == ['proxy']
+    assert comp[0] == ('proxy', '')
 
     code = 'self.sigMessageReady.emit; self.s'
     comp = p.get_completions(CodeInfo('completions', code, len(code)))
-    assert comp == ['sigMessageReady']
+    assert comp == [('sigMessageReady', '')]
 
     code = encoding.to_unicode('álfa;á')
     comp = p.get_completions(CodeInfo('completions', code, len(code)))
-    assert comp == [encoding.to_unicode('álfa')]
+    assert comp == [(encoding.to_unicode('álfa'), '')]
 
     code = 'from numpy import one'
     comp = p.get_completions(CodeInfo('completions', code, len(code)))
-    assert 'ones' in comp
+    assert ('ones', '') in comp
 
     comp = p.get_completions(CodeInfo('completions', code, len(code),
         is_python_like=False))
@@ -357,7 +382,7 @@ if __name__ == '__main__':
 
     code = 'from numpy.testing import (asse'
     comp = p.get_completions(CodeInfo('completions', code, len(code)))
-    assert 'assert_equal' in comp
+    assert ('assert_equal', '') in comp
 
     code = '''
 def test(a, b):
diff --git a/spyderlib/utils/introspection/jedi_plugin.py b/spyderlib/utils/introspection/jedi_plugin.py
index c7ee4aa..90fc2fb 100644
--- a/spyderlib/utils/introspection/jedi_plugin.py
+++ b/spyderlib/utils/introspection/jedi_plugin.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2013 The Spyder Development Team
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -14,7 +14,7 @@ import time
 import threading
 
 from spyderlib import dependencies
-from spyderlib.baseconfig import _, debug_print
+from spyderlib.config.base import _, debug_print
 from spyderlib.utils import programs
 from spyderlib.utils.debug import log_last_error, log_dt
 from spyderlib.utils.dochelpers import getsignaturefromtext
@@ -54,10 +54,11 @@ class JediPlugin(IntrospectionPlugin):
         self._warmup_thread.start()
 
     def get_completions(self, info):
-        """Return a list of completion strings"""
+        """Return a list of (completion, type) tuples"""
         completions = self.get_jedi_object('completions', info)
+        completions = [(c.name, c.type) for c in completions]
         debug_print(str(completions)[:100])
-        return [c.name for c in completions]
+        return completions
 
     def get_info(self, info):
         """
@@ -267,12 +268,12 @@ if __name__ == '__main__':
     source_code = "import n"
     completions = p.get_completions(CodeInfo('completions', source_code,
         len(source_code)))
-    assert 'numpy' in completions
+    assert ('numpy', 'module') in completions
 
-    source_code = "import matplotlib.pyplot as plt; plt.imsave"
+    source_code = "import pandas as pd; pd.DataFrame"
     path, line_nr = p.get_definition(CodeInfo('definition', source_code,
         len(source_code)))
-    assert 'pyplot.py' in path
+    assert 'frame.py' in path
 
     source_code = 'from .plugin_manager import memoize'
     path, line_nr = p.get_definition(CodeInfo('definition', source_code,
diff --git a/spyderlib/utils/introspection/module_completion.py b/spyderlib/utils/introspection/module_completion.py
index 589a842..c75f114 100644
--- a/spyderlib/utils/introspection/module_completion.py
+++ b/spyderlib/utils/introspection/module_completion.py
@@ -27,8 +27,10 @@ from time import time
 import sys
 from zipimport import zipimporter
 
-from spyderlib.baseconfig import get_conf_path, running_in_mac_app
-from spyderlib.utils.external.pickleshare import PickleShareDB
+from spyderlib.config.base import get_conf_path, running_in_mac_app
+from spyderlib.py3compat import PY3
+
+from pickleshare import PickleShareDB
 
 #-----------------------------------------------------------------------------
 # Globals and constants
@@ -38,7 +40,10 @@ from spyderlib.utils.external.pickleshare import PickleShareDB
 MODULES_PATH = get_conf_path('db')
 
 # Time in seconds after which we give up
-TIMEOUT_GIVEUP = 20
+if os.name == 'nt':
+    TIMEOUT_GIVEUP = 30
+else:
+    TIMEOUT_GIVEUP = 20
 
 # Py2app only uses .pyc files for the stdlib when optimize=0,
 # so we need to add it as another suffix here
@@ -314,8 +319,12 @@ if __name__ == "__main__":
     s = 'from xml.etree.ElementTree import '
     assert module_completion(s + 'V') == ['VERSION']
 
-    assert sorted(module_completion(s + 'VERSION, XM')) == \
-        ['XML', 'XMLID', 'XMLParser', 'XMLTreeBuilder']
+    if PY3:
+        assert sorted(module_completion(s + 'VERSION, XM')) == \
+            ['XML', 'XMLID', 'XMLParser', 'XMLPullParser']
+    else:
+        assert sorted(module_completion(s + 'VERSION, XM')) == \
+            ['XML', 'XMLID', 'XMLParser', 'XMLTreeBuilder']
 
     assert module_completion(s + '(dum') == ['dump']
 
diff --git a/spyderlib/utils/introspection/plugin_manager.py b/spyderlib/utils/introspection/plugin_manager.py
index 0f78fc4..258a684 100644
--- a/spyderlib/utils/introspection/plugin_manager.py
+++ b/spyderlib/utils/introspection/plugin_manager.py
@@ -14,7 +14,7 @@ import os
 import imp
 import time
 
-from spyderlib.baseconfig import DEBUG, get_conf_path, debug_print
+from spyderlib.config.base import DEBUG, get_conf_path, debug_print
 from spyderlib.utils.introspection.module_completion import (
     get_preferred_submodules)
 from spyderlib.utils import sourcecode
@@ -53,7 +53,7 @@ class RequestHandler(QObject):
             self._make_async_call(plugin, code_info)
 
     def _handle_timeout(self):
-        debug_print('got timeout')
+        debug_print('got timeout: %s' % self.plugins)
         if self.pending:
             for plugin in self.plugins:
                 if plugin.name in self.pending:
@@ -64,12 +64,19 @@ class RequestHandler(QObject):
     def _handle_incoming(self, name):
         # coerce to a str in case it is a QString
         name = str(name)
-        self._threads[name].wait()
+        try:
+            self._threads[name].wait()
+        except AttributeError:
+            return
         if self.result:
             return
         result = self._threads[name].result
         if name == self.plugins[0].name or not self.waiting:
-            self._finalize(name, result)
+            if result:
+                self._finalize(name, result)
+            else:
+                debug_print('No valid responses acquired')
+                self.introspection_complete.emit()
         else:
             self.pending[name] = result
 
@@ -84,7 +91,7 @@ class RequestHandler(QObject):
         self.waiting = False
         self.pending = None
         delta = time.time() - self._start_time
-        debug_print('%s request from %s complete: "%s" in %.1f sec'
+        debug_print('%s request from %s finished: "%s" in %.1f sec'
             % (self.info.name, name, str(result)[:100], delta))
         self.introspection_complete.emit()
 
@@ -136,23 +143,43 @@ class CodeInfo(object):
                                  re.UNICODE)
 
     def __init__(self, name, source_code, position, filename=None,
-            is_python_like=True, **kwargs):
+            is_python_like=True, in_comment_or_string=False, **kwargs):
         self.__dict__.update(kwargs)
         self.name = name
         self.filename = filename
         self.source_code = source_code
-        self.position = position
         self.is_python_like = is_python_like
+        self.in_comment_or_string = in_comment_or_string
+        self.position = position
+
+        # if in a comment, look for the previous definition
+        if in_comment_or_string:
+            # if this is a docstring, find it, set as our
+            self.docstring = self._get_docstring()
+            # backtrack and look for a line that starts with def or class
+            while position:
+                base = self.source_code[position: position + 6]
+                if base.startswith('def ') or base.startswith('class '):
+                    position += base.index(' ') + 1
+                    break
+                position -= 1
+        else:
+            self.docstring = ''
+
+        self.position = position
 
         if position == 0:
             self.lines = []
+            self.column = 0
             self.line_num = 0
-            self.obj = None
-            self.full_obj = None
+            self.line = ''
+            self.obj = ''
+            self.full_obj = ''
         else:
             self._get_info()
 
     def _get_info(self):
+
         self.lines = self.source_code[:self.position].splitlines()
         self.line_num = len(self.lines)
 
@@ -186,12 +213,30 @@ class CodeInfo(object):
         """
         Split our source code into valid identifiers.
 
-        P"""
+        """
         if position is None:
             position = self.offset
         text = self.source_code[:position]
         return re.findall(self.id_regex, text)
 
+    def _get_docstring(self):
+        """Find the docstring we are currently in"""
+        left = self.position
+        while left:
+            if self.source_code[left: left + 3] in ['"""', "'''"]:
+                left += 3
+                break
+            left -= 1
+        right = self.position
+        while right < len(self.source_code):
+            if self.source_code[right - 3: right] in ['"""', "'''"]:
+                right -= 3
+                break
+            right += 1
+        if left and right < len(self.source_code):
+            return self.source_code[left: right]
+        return ''
+
     def __eq__(self, other):
         try:
             return self.__dict__ == other.__dict__
@@ -240,6 +285,7 @@ class PluginManager(QObject):
 
         editor = self.editor_widget.get_current_editor()
         finfo = self.editor_widget.get_current_finfo()
+        in_comment_or_string = editor.in_comment_or_string()
 
         if position is None:
             position = editor.get_position('cursor')
@@ -249,7 +295,8 @@ class PluginManager(QObject):
         kwargs['editor_widget'] = self.editor_widget
 
         return CodeInfo(name, finfo.get_source_code(), position,
-            finfo.filename, editor.is_python_like, **kwargs)
+            finfo.filename, editor.is_python_like, in_comment_or_string,
+            **kwargs)
 
     def get_completions(self, automatic):
         """Get code completion"""
@@ -294,12 +341,12 @@ class PluginManager(QObject):
 
     def _handle_request(self, info, desired=None):
         """Handle an incoming request from the user."""
-        debug_print('%s request:' % info.name)
+        debug_print('%s request' % info.name)
 
         editor = info.editor
         if ((not editor.is_python_like())
                 or sourcecode.is_keyword(info.obj)
-                or editor.in_comment_or_string()):
+                or (editor.in_comment_or_string() and info.name != 'info')):
             desired = 'fallback'
 
         self.pending = (info, desired)
@@ -318,11 +365,13 @@ class PluginManager(QObject):
 
         if desired:
             plugins = [self.plugins[desired]]
-        elif info.name == 'definition' and not info.editor.is_python():
+        elif (info.name == 'definition' and not info.editor.is_python()
+              or info.name == 'info'):
             plugins = [p for p in self.plugins.values() if not p.busy]
         else:
             # use all but the fallback
-            plugins = [p for p in list(self.plugins.values())[:-1] if not p.busy]
+            plugins = [p for p in list(self.plugins.values())[:-1]
+                       if not p. busy]
 
         self.request = RequestHandler(info, plugins)
         self.request.introspection_complete.connect(
@@ -375,7 +424,8 @@ class PluginManager(QObject):
             return
 
         if info.full_obj and len(info.full_obj) > len(info.obj):
-            new_list = [c for c in comp_list if c.startswith(info.full_obj)]
+            new_list = [(c, t) for (c, t) in comp_list
+                        if c.startswith(info.full_obj)]
             if new_list:
                 pos = info.editor.get_position('cursor')
                 new_pos = pos + len(info.full_obj) - len(info.obj)
@@ -386,8 +436,9 @@ class PluginManager(QObject):
         if '.' in completion_text:
             completion_text = completion_text.split('.')[-1]
 
-        comp_list = [c.split('.')[-1]  for c in comp_list]
-        comp_list = [c for c in comp_list if c.startswith(completion_text)]
+        comp_list = [(c.split('.')[-1], t) for (c, t) in comp_list]
+        comp_list = [(c, t) for (c, t) in comp_list
+                     if c.startswith(completion_text)]
 
         info.editor.show_completion_list(comp_list, completion_text,
                                          prev_info.automatic)
@@ -429,9 +480,12 @@ class PluginManager(QObject):
         Post a message to the main window status bar with a timeout in ms
         """
         if self.editor_widget:
-            statusbar = self.editor_widget.window().statusBar()
-            statusbar.showMessage(message, timeout)
-            QApplication.processEvents()
+            try:
+                statusbar = self.editor_widget.window().statusBar()
+                statusbar.showMessage(message, timeout)
+                QApplication.processEvents()
+            except AttributeError:
+                pass
 
 
 def memoize(obj):
diff --git a/spyderlib/utils/introspection/rope_plugin.py b/spyderlib/utils/introspection/rope_plugin.py
index a869127..659d1ee 100644
--- a/spyderlib/utils/introspection/rope_plugin.py
+++ b/spyderlib/utils/introspection/rope_plugin.py
@@ -11,7 +11,7 @@ Rope introspection plugin
 import time
 
 from spyderlib import dependencies
-from spyderlib.baseconfig import get_conf_path, _, STDERR
+from spyderlib.config.base import get_conf_path, _, STDERR
 from spyderlib.utils import encoding, programs
 from spyderlib.py3compat import PY2
 from spyderlib.utils.dochelpers import getsignaturefromtext
@@ -24,7 +24,7 @@ try:
         from spyderlib import rope_patch
         rope_patch.apply()
     except ImportError:
-        # rope 0.9.2/0.9.3 is not installed
+        # rope is not installed
         pass
     import rope.base.libutils
     import rope.contrib.codeassist
@@ -32,7 +32,7 @@ except ImportError:
     pass
 
 
-ROPE_REQVER = '>=0.9.2'
+ROPE_REQVER = '>=0.9.4'
 dependencies.add('rope',
                  _("Editor's code completion, go-to-definition and help"),
                  required_version=ROPE_REQVER)
@@ -48,15 +48,15 @@ ROPE_PREFS = {'ignore_syntax_errors': True,
 class RopePlugin(IntrospectionPlugin):
     """
     Rope based introspection plugin for jedi
-    
+
     Editor's code completion, go-to-definition and help
     """
-    
+
     project = None
-    
+
     # ---- IntrospectionPlugin API --------------------------------------------
     name = 'rope'
-    
+
     def load_plugin(self):
         """Load the Rope introspection plugin"""
         if not programs.is_module_installed('rope', ROPE_REQVER):
@@ -65,9 +65,9 @@ class RopePlugin(IntrospectionPlugin):
         self.create_rope_project(root_path=get_conf_path())
 
     def get_completions(self, info):
-        """Get a list of completions using Rope"""
+        """Get a list of (completion, type) tuples using Rope"""
         if self.project is None:
-            return
+            return []
         filename = info.filename
         source_code = info.source_code
         offset = info.position
@@ -93,10 +93,11 @@ class RopePlugin(IntrospectionPlugin):
             proposals = rope.contrib.codeassist.sorted_proposals(proposals)
             if DEBUG_EDITOR:
                 log_dt(LOG_FILENAME, "code_assist/sorted_proposals", t0)
-            return [proposal.name for proposal in proposals]
+            return [(proposal.name, proposal.type) for proposal in proposals]
         except Exception as _error:  #analysis:ignore
             if DEBUG_EDITOR:
                 log_last_error(LOG_FILENAME, "get_completion_list")
+        return []
 
     def get_info(self, info):
         """Get a formatted calltip and docstring from Rope"""
@@ -182,6 +183,9 @@ class RopePlugin(IntrospectionPlugin):
                 module = obj_fullname[:module_end]
                 note = 'Present in %s module' % module
 
+        if not doc_text and not calltip:
+            return
+
         return dict(name=obj_fullname, argspec=argspec, note=note,
             docstring=doc_text, calltip=calltip)
 
@@ -225,7 +229,10 @@ class RopePlugin(IntrospectionPlugin):
     def validate(self):
         """Validate the Rope project"""
         if self.project is not None:
-            self.project.validate(self.project.root)
+            try:
+                self.project.validate(self.project.root)
+            except RuntimeError:
+                pass
 
     def set_pref(self, key, value):
         """Set a Rope preference"""
@@ -252,8 +259,6 @@ class RopePlugin(IntrospectionPlugin):
                 log_last_error(LOG_FILENAME,
                                "create_rope_project: %r" % root_path)
         except TypeError:
-            # Compatibility with new Mercurial API (>= 1.3).
-            # New versions of rope (> 0.9.2) already handle this issue
             self.project = None
             if DEBUG_EDITOR:
                 log_last_error(LOG_FILENAME,
@@ -269,7 +274,7 @@ class RopePlugin(IntrospectionPlugin):
 if __name__ == '__main__':
 
     from spyderlib.utils.introspection.plugin_manager import CodeInfo
-    
+
     p = RopePlugin()
     p.load_plugin()
 
@@ -277,16 +282,16 @@ if __name__ == '__main__':
     docs = p.get_info(CodeInfo('info', source_code, len(source_code),
                                            __file__))
     assert 'ones(' in docs['calltip'] and 'ones(' in docs['docstring']
-    
+
     source_code = "import numpy; n"
     completions = p.get_completions(CodeInfo('completions', source_code,
         len(source_code), __file__))
-    assert 'numpy' in completions 
-    
-    source_code = "import matplotlib.pyplot as plt; plt.imsave"
+    assert ('numpy', 'module') in completions
+
+    source_code = "import pandas as pd; pd.DataFrame"
     path, line_nr = p.get_definition(CodeInfo('definition', source_code,
         len(source_code), __file__))
-    assert 'pyplot.py' in path 
+    assert 'frame.py' in path
 
     code = '''
 def test(a, b):
diff --git a/spyderlib/utils/iofuncs.py b/spyderlib/utils/iofuncs.py
index 6043d28..fcdd256 100644
--- a/spyderlib/utils/iofuncs.py
+++ b/spyderlib/utils/iofuncs.py
@@ -371,13 +371,14 @@ def load_dictionary(filename):
     return data, error_message
 
 
-from spyderlib.baseconfig import get_conf_path, STDERR
+from spyderlib.config.base import get_conf_path, STDERR
 
 SAVED_CONFIG_FILES = ('inspector', 'onlinehelp', 'path', 'pylint.results',
                       'spyder.ini', 'temp.py', 'temp.spydata', 'template.py',
                       'history.py', 'history_internal.py', 'workingdir',
                       '.projects', '.spyderproject', '.ropeproject',
-                      'monitor.log', 'monitor_debug.log', 'rope.log')
+                      'monitor.log', 'monitor_debug.log', 'rope.log',
+                      'langconfig')
 
 def reset_session():
     """Remove all config files"""
@@ -462,7 +463,7 @@ def load_session(filename):
     return error_message
 
 
-from spyderlib.baseconfig import _
+from spyderlib.config.base import _
 
 class IOFunctions(object):
     def __init__(self):
@@ -524,7 +525,7 @@ class IOFunctions(object):
     def get_3rd_party_funcs(self):
         other_funcs = []
         from spyderlib.otherplugins import get_spyderplugins_mods
-        for mod in get_spyderplugins_mods(prefix='io_', extension='.py'):
+        for mod in get_spyderplugins_mods(io=True):
             try:
                 other_funcs.append((mod.FORMAT_EXT, mod.FORMAT_NAME,
                                     mod.FORMAT_LOAD, mod.FORMAT_SAVE))
diff --git a/spyderlib/utils/misc.py b/spyderlib/utils/misc.py
index c4fa1ef..fe4c819 100644
--- a/spyderlib/utils/misc.py
+++ b/spyderlib/utils/misc.py
@@ -86,9 +86,9 @@ def count_lines(path, extensions=None, excluded_dirnames=None):
     of *path* with names ending with *extensions*
     Directory names *excluded_dirnames* will be ignored"""
     if extensions is None:
-        extensions = ['.py', '.pyw', '.ipy', '.c', '.h', '.cpp', '.hpp',
-                      '.inc', '.', '.hh', '.hxx', '.cc', '.cxx', '.cl',
-                      '.f', '.for', '.f77', '.f90', '.f95', '.f2k']
+        extensions = ['.py', '.pyw', '.ipy', '.enaml', '.c', '.h', '.cpp', 
+                      '.hpp', '.inc', '.', '.hh', '.hxx', '.cc', '.cxx', 
+                      '.cl', '.f', '.for', '.f77', '.f90', '.f95', '.f2k']
     if excluded_dirnames is None:
         excluded_dirnames = ['build', 'dist', '.hg', '.svn']
     def get_filelines(path):
@@ -228,9 +228,17 @@ def get_common_path(pathlist):
                 return osp.abspath(common)
 
 if __name__ == '__main__':
-    assert get_common_path([
-                            'D:\\Python\\spyder-v21\\spyderlib\\widgets',
-                            'D:\\Python\\spyder\\spyderlib\\utils',
-                            'D:\\Python\\spyder\\spyderlib\\widgets',
-                            'D:\\Python\\spyder-v21\\spyderlib\\utils',
-                            ]) == 'D:\\Python'
+    if os.name == 'nt':
+        assert get_common_path([
+                                'D:\\Python\\spyder-v21\\spyderlib\\widgets',
+                                'D:\\Python\\spyder\\spyderlib\\utils',
+                                'D:\\Python\\spyder\\spyderlib\\widgets',
+                                'D:\\Python\\spyder-v21\\spyderlib\\utils',
+                                ]) == 'D:\\Python'
+    else:
+        assert get_common_path([
+                                '/Python/spyder-v21/spyderlib/widgets',
+                                '/Python/spyder/spyderlib/utils',
+                                '/Python/spyder/spyderlib/widgets',
+                                '/Python/spyder-v21/spyderlib/utils',
+                                ]) == '/Python'
diff --git a/spyderlib/utils/programs.py b/spyderlib/utils/programs.py
index b6e5a08..12e593b 100644
--- a/spyderlib/utils/programs.py
+++ b/spyderlib/utils/programs.py
@@ -171,7 +171,7 @@ def run_python_script_in_terminal(fname, wdir, args, interact,
             subprocess.Popen(cmd, shell=True, cwd=wdir)
         except WindowsError:
             from spyderlib.qt.QtGui import QMessageBox
-            from spyderlib.baseconfig import _
+            from spyderlib.config.base import _
             QMessageBox.critical(None, _('Run'),
                                  _("It was not possible to run this file in "
                                    "an external terminal"),
@@ -201,6 +201,23 @@ def run_python_script_in_terminal(fname, wdir, args, interact,
         raise NotImplementedError
 
 
+def is_stable_version(version):
+    """
+    A stable version has no letters in the final component, but only numbers.
+
+    Stable version example: 1.2, 1.3.4, 1.0.5
+    Not stable version: 1.2alpha, 1.3.4beta, 0.1.0rc1, 3.0.0dev
+    """
+    if not isinstance(version, tuple):
+        version = version.split('.')
+    last_part = version[-1]
+
+    if not re.search('[a-zA-Z]', last_part):
+        return True
+    else:
+        return False
+
+
 def check_version(actver, version, cmp_op):
     """
     Check version string of an active module against a required version.
@@ -216,6 +233,16 @@ def check_version(actver, version, cmp_op):
     """
     if isinstance(actver, tuple):
         actver = '.'.join([str(i) for i in actver])
+
+    # Hacks needed so that LooseVersion understands that (for example)
+    # version = '3.0.0' is in fact bigger than actver = '3.0.0rc1'
+    if is_stable_version(version) and not is_stable_version(actver) and \
+      actver.startswith(version) and version != actver:
+        version = version + 'zz'
+    elif is_stable_version(actver) and not is_stable_version(version) and \
+      version.startswith(actver) and version != actver:
+        actver = actver + 'zz'
+
     try:
         if cmp_op == '>':
             return LooseVersion(actver) > LooseVersion(version)
@@ -258,12 +285,14 @@ def is_module_installed(module_name, version=None, installed_version=None,
         if osp.isfile(interpreter) and ('python' in interpreter):
             checkver = inspect.getsource(check_version)
             get_modver = inspect.getsource(get_module_version)
+            stable_ver = inspect.getsource(is_stable_version)
             ismod_inst = inspect.getsource(is_module_installed)
             fd, script = tempfile.mkstemp(suffix='.py', dir=TEMPDIR)
             with os.fdopen(fd, 'w') as f:
                 f.write("# -*- coding: utf-8 -*-" + "\n\n")
                 f.write("from distutils.version import LooseVersion" + "\n")
                 f.write("import re" + "\n\n")
+                f.write(stable_ver + "\n")
                 f.write(checkver + "\n")
                 f.write(get_modver + "\n")
                 f.write(ismod_inst + "\n")
@@ -317,10 +346,18 @@ def is_module_installed(module_name, version=None, installed_version=None,
             return check_version(actver, version, symb)
 
 
+def test_programs():
+    assert find_program('git')
+    assert shell_split('-q -o -a') == ['-q', '-o', '-a']
+    assert shell_split('-q "d:\\Python de xxxx\\t.txt" -o -a') == \
+           ['-q', 'd:\\Python de xxxx\\t.txt', '-o', '-a']
+    assert check_version('0.9.4-1', '0.9.4', '>=')
+    assert check_version('3.0.0rc1', '3.0.0', '<')
+    assert check_version('1.0', '1.0b2', '>')
+    assert is_module_installed('qtconsole', '>=4.0')
+    assert not is_module_installed('IPython', '>=1.0;<3.0')
+    assert is_module_installed('jedi', '>=0.7.0')
+
+
 if __name__ == '__main__':
-    print(find_program('hg'))
-    print(shell_split('-q -o -a'))
-    print(shell_split('-q "d:\\Python de xxxx\\t.txt" -o -a'))
-    print(is_module_installed('IPython', '>=0.12'))
-    print(is_module_installed('IPython', '>=0.13;<1.0'))
-    print(is_module_installed('jedi', '>=0.7.0'))
+    test_programs()
diff --git a/spyderlib/utils/qthelpers.py b/spyderlib/utils/qthelpers.py
index 14c7b0a..fc0110b 100644
--- a/spyderlib/utils/qthelpers.py
+++ b/spyderlib/utils/qthelpers.py
@@ -1,18 +1,20 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2011 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
 """Qt utilities"""
 
-from spyderlib.qt.QtGui import (QAction, QStyle, QWidget, QIcon, QApplication,
+from spyderlib.qt.QtGui import (QAction, QStyle, QWidget, QApplication,
                                 QLabel, QVBoxLayout, QHBoxLayout, QLineEdit,
                                 QKeyEvent, QMenu, QKeySequence, QToolButton,
                                 QPixmap)
-from spyderlib.qt.QtCore import (SIGNAL, QObject, Qt, QLocale, QTranslator,
-                                 QLibraryInfo, QEvent)
+from spyderlib.qt.QtCore import (Signal, QObject, Qt, QLocale, QTranslator,
+                                 QLibraryInfo, QEvent, Slot, QTimer)
 from spyderlib.qt.compat import to_qvariant, from_qvariant
+import spyderlib.utils.icon_manager as ima
+from spyderlib.utils.icon_manager import get_icon, get_std_icon
 
 import os
 import re
@@ -20,8 +22,8 @@ import os.path as osp
 import sys
 
 # Local import
-from spyderlib.baseconfig import get_image_path, running_in_mac_app
-from spyderlib.guiconfig import get_shortcut
+from spyderlib.config.base import get_image_path, running_in_mac_app
+from spyderlib.config.gui import get_shortcut
 from spyderlib.utils import programs
 from spyderlib.py3compat import is_text_string, to_text_string
 
@@ -36,28 +38,6 @@ from spyderlib.py3compat import is_text_string, to_text_string
 #                 lambda *args: self.emit(SIGNAL('option_changed'), *args))
 
 
-def get_icon(name, default=None, resample=False):
-    """Return image inside a QIcon object
-    default: default image name or icon
-    resample: if True, manually resample icon pixmaps for usual sizes
-    (16, 24, 32, 48, 96, 128, 256). This is recommended for QMainWindow icons 
-    created from SVG images on non-Windows platforms due to a Qt bug (see 
-    Issue 1314)."""
-    if default is None:
-        icon = QIcon(get_image_path(name))
-    elif isinstance(default, QIcon):
-        icon_path = get_image_path(name, default=None)
-        icon = default if icon_path is None else QIcon(icon_path)
-    else:
-        icon = QIcon(get_image_path(name, default))
-    if resample:
-        icon0 = QIcon()
-        for size in (16, 24, 32, 48, 96, 128, 256, 512):
-            icon0.addPixmap(icon.pixmap(size, size))
-        return icon0 
-    else:
-        return icon
-
 
 def get_image_label(name, default="not_found.png"):
     """Return image inside a QLabel object"""
@@ -68,19 +48,26 @@ def get_image_label(name, default="not_found.png"):
 
 class MacApplication(QApplication):
     """Subclass to be able to open external files with our Mac app"""
+    open_external_file = Signal(str)
+    
     def __init__(self, *args):
         QApplication.__init__(self, *args)
 
     def event(self, event):
         if event.type() == QEvent.FileOpen:
             fname = str(event.file())
-            self.emit(SIGNAL('open_external_file(QString)'), fname)
+            self.open_external_file.emit(fname)
         return QApplication.event(self, event)
 
 
-def qapplication(translate=True):
-    """Return QApplication instance
-    Creates it if it doesn't already exist"""
+def qapplication(translate=True, test_time=3):
+    """
+    Return QApplication instance
+    Creates it if it doesn't already exist
+    
+    test_time: Time to maintain open the application when testing. It's given
+    in seconds
+    """
     if running_in_mac_app():
         SpyderApplication = MacApplication
     else:
@@ -96,6 +83,12 @@ def qapplication(translate=True):
         app.setApplicationName('Spyder')
     if translate:
         install_translator(app)
+
+    test_travis = os.environ.get('TEST_CI_WIDGETS', None)
+    if test_travis is not None:
+        timer_shutdown = QTimer(app)
+        timer_shutdown.timeout.connect(app.quit)
+        timer_shutdown.start(test_time*1000)
     return app
 
 
@@ -142,6 +135,7 @@ def _process_mime_path(path, extlist):
                 path = path[5:]
         else:
             path = path[7:]
+    path = path.replace('%5C' , os.sep)  # Transforming backslashes
     if osp.exists(path):
         if extlist is None or osp.splitext(path)[1] in extlist:
             return path
@@ -208,9 +202,9 @@ def create_toolbutton(parent, text=None, shortcut=None, icon=None, tip=None,
         button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
     button.setAutoRaise(autoraise)
     if triggered is not None:
-        QObject.connect(button, SIGNAL('clicked()'), triggered)
+        button.clicked.connect(triggered)
     if toggled is not None:
-        QObject.connect(button, SIGNAL("toggled(bool)"), toggled)
+        button.toggled.connect(toggled)
         button.setCheckable(True)
     if shortcut is not None:
         button.setShortcut(shortcut)
@@ -243,9 +237,9 @@ def create_action(parent, text, shortcut=None, icon=None, tip=None,
     """Create a QAction"""
     action = QAction(text, parent)
     if triggered is not None:
-        parent.connect(action, SIGNAL("triggered()"), triggered)
+        action.triggered.connect(triggered)
     if toggled is not None:
-        parent.connect(action, SIGNAL("toggled(bool)"), toggled)
+        action.toggled.connect(toggled)
         action.setCheckable(True)
     if icon is not None:
         if is_text_string(icon):
@@ -312,8 +306,13 @@ def set_item_user_text(item, text):
 
 def create_bookmark_action(parent, url, title, icon=None, shortcut=None):
     """Create bookmark action"""
+    
+    @Slot()
+    def open_url():
+        return programs.start_file(url)
+    
     return create_action( parent, title, shortcut=shortcut, icon=icon,
-                          triggered=lambda u=url: programs.start_file(u) )
+                          triggered=open_url)
 
 
 def create_module_bookmark_actions(parent, bookmarks):
@@ -378,11 +377,11 @@ class DialogManager(QObject):
         else:
             dialog.show()
             self.dialogs[id(dialog)] = dialog
-            self.connect(dialog, SIGNAL('accepted()'),
-                         lambda eid=id(dialog): self.dialog_finished(eid))
-            self.connect(dialog, SIGNAL('rejected()'),
-                         lambda eid=id(dialog): self.dialog_finished(eid))
-        
+            dialog.accepted.connect(
+                              lambda eid=id(dialog): self.dialog_finished(eid))
+            dialog.rejected.connect(
+                              lambda eid=id(dialog): self.dialog_finished(eid))
+    
     def dialog_finished(self, dialog_id):
         """Manage non-modal dialog boxes"""
         return self.dialogs.pop(dialog_id)
@@ -393,24 +392,12 @@ class DialogManager(QObject):
             dlg.reject()
 
         
-def get_std_icon(name, size=None):
-    """Get standard platform icon
-    Call 'show_std_icons()' for details"""
-    if not name.startswith('SP_'):
-        name = 'SP_'+name
-    icon = QWidget().style().standardIcon( getattr(QStyle, name) )
-    if size is None:
-        return icon
-    else:
-        return QIcon( icon.pixmap(size, size) )
-
-
 def get_filetype_icon(fname):
     """Return file type icon"""
     ext = osp.splitext(fname)[1]
     if ext.startswith('.'):
         ext = ext[1:]
-    return get_icon( "%s.png" % ext, get_std_icon('FileIcon') )
+    return get_icon( "%s.png" % ext, ima.icon('FileIcon') )
 
 
 class ShowStdIcons(QWidget):
diff --git a/spyderlib/utils/sourcecode.py b/spyderlib/utils/sourcecode.py
index cc33d8d..99b7f77 100644
--- a/spyderlib/utils/sourcecode.py
+++ b/spyderlib/utils/sourcecode.py
@@ -19,21 +19,12 @@ ALL_LANGUAGES = {
                  'Fortran77': ('f', 'for', 'f77'),
                  'Fortran': ('f90', 'f95', 'f2k'),
                  'Idl': ('pro',),
-                 'Matlab': ('m',),
-                 'Julia': ('jl',),
                  'Diff': ('diff', 'patch', 'rej'),
                  'GetText': ('po', 'pot'),
                  'Nsis': ('nsi', 'nsh'),
                  'Html': ('htm', 'html'),
-                 'Css': ('css',),
-                 'Xml': ('xml',),
-                 'Js': ('js',),
-                 'Json': ('json', 'ipynb'),
                  'Cpp': ('c', 'cc', 'cpp', 'cxx', 'h', 'hh', 'hpp', 'hxx'),
                  'OpenCL': ('cl',),
-                 'Batch': ('bat', 'cmd', 'nt'),
-                 'Ini': ('properties', 'session', 'ini', 'inf', 'reg', 'url',
-                         'cfg', 'cnf', 'aut', 'iss'),
                  'Yaml':('yaml','yml'),
                  }
 
@@ -126,8 +117,8 @@ def get_identifiers(source_code):
 if __name__ == '__main__':
     code = 'import functools\nfunctools.partial'
     assert get_primary_at(code, len(code)) == 'functools.partial'
-    assert get_identifiers(code) == ['import', 'functools', 
-                                     'functools.partial']
+    assert set(get_identifiers(code)) == set(['import', 'functools',
+                                              'functools.partial'])
     assert split_source(code) == ['import functools', 'functools.partial']
     code = code.replace('\n', '\r\n')
     assert split_source(code) == ['import functools', 'functools.partial']
diff --git a/spyderlib/utils/stringmatching.py b/spyderlib/utils/stringmatching.py
new file mode 100644
index 0000000..eeaaad0
--- /dev/null
+++ b/spyderlib/utils/stringmatching.py
@@ -0,0 +1,280 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2015 The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+"""
+String search and match utilities usefull when filtering a list of texts.
+"""
+
+import re
+
+
+NOT_FOUND_SCORE = -1
+NO_SCORE = 0
+
+
+def get_search_regex(query, ignore_case=True):
+    """Returns a compiled regex pattern to search for query letters in order.
+
+    Parameters
+    ----------
+    query : str
+        String to search in another string (in order of character occurence).
+    ignore_case : True
+        Optional value perform a case insensitive search (True by default).
+
+    Returns
+    -------
+    pattern : SRE_Pattern
+
+    Notes
+    -----
+    This function adds '.*' between the query characters and compiles the
+    resulting regular expression.
+    """
+    regex_text = [char for char in query if char != ' ']
+    regex_text = '.*'.join(regex_text)
+
+    regex = '({0})'.format(regex_text)
+
+    if ignore_case:
+        pattern = re.compile(regex, re.IGNORECASE)
+    else:
+        pattern = re.compile(regex)
+
+    return pattern
+
+
+def get_search_score(query, choice, ignore_case=True, apply_regex=True,
+                     template='{}'):
+    """Returns a tuple with the enriched text (if a template is provided) and
+    a score for the match.
+
+    Parameters
+    ----------
+    query : str
+        String with letters to search in choice (in order of appearance).
+    choice : str
+        Sentence/words in which to search for the 'query' letters.
+    ignore_case : bool, optional
+        Optional value perform a case insensitive search (True by default).
+    apply_regex : bool, optional
+        Optional value (True by default) to perform a regex search. Useful
+        when this function is called directly.
+    template : str, optional
+        Optional template string to surround letters found in choices. This is
+        useful when using a rich text editor ('{}' by default).
+        Examples: '<b>{}</b>', '<code>{}</code>', '<i>{}</i>'
+
+    Returns
+    -------
+    results : tuple
+        Tuples where the first item is the text (enriched if a template was
+        used) and the second item is a search score.
+
+    Notes
+    -----
+    The score is given according the following precedence (high to low):
+
+    - Letters in one word and no spaces with exact match.
+      Example: 'up' in 'up stroke'
+    - Letters in one word and no spaces with partial match.
+      Example: 'up' in 'upstream stroke'
+    - Letters in one word but with skip letters.
+      Example: 'cls' in 'close up'
+    - Letters in two or more words
+      Example: 'cls' in 'car lost'
+    """
+    original_choice = choice
+    result = (original_choice, NOT_FOUND_SCORE)
+
+    # Handle empty string case
+    if not query:
+        return result
+
+    if ignore_case:
+        query = query.lower()
+        choice = choice.lower()
+
+    if apply_regex:
+        pattern = get_search_regex(query, ignore_case=ignore_case)
+        r = re.search(pattern, choice)
+        if r is None:
+            return result
+    else:
+        sep = u'-'  # Matches will be replaced by this character
+        let = u'x'  # Nonmatches (except spaed) will be replaced by this
+        score = 0
+
+        exact_words = [query == word for word in choice.split(u' ')]
+        partial_words = [query in word for word in choice.split(u' ')]
+
+        if any(exact_words) or any(partial_words):
+            pos_start = choice.find(query)
+            pos_end = pos_start + len(query)
+            score += pos_start
+            text = choice.replace(query, sep*len(query), 1)
+
+            enriched_text = original_choice[:pos_start] +\
+                template.format(original_choice[pos_start:pos_end]) +\
+                original_choice[pos_end:]
+
+        if any(exact_words):
+            # Check if the query words exists in a word with exact match
+            score += 1
+        elif any(partial_words):
+            # Check if the query words exists in a word with partial match
+            score += 100
+        else:
+            # Check letter by letter
+            text = [l for l in original_choice]
+            if ignore_case:
+                temp_text = [l.lower() for l in original_choice]
+            else:
+                temp_text = text[:]
+
+            # Give points to start of string
+            score += temp_text.index(query[0])
+
+            # Find the query letters and replace them by `sep`, also apply
+            # template as needed for enricching the letters in the text
+            enriched_text = text[:]
+            for char in query:
+                if char != u'' and char in temp_text:
+                    index = temp_text.index(char)
+                    enriched_text[index] = template.format(text[index])
+                    text[index] = sep
+                    temp_text = [u' ']*(index + 1) + temp_text[index+1:]
+
+        enriched_text = u''.join(enriched_text)
+
+        patterns_text = []
+        for i, char in enumerate(text):
+            if char != u' ' and char != sep:
+                new_char = let
+            else:
+                new_char = char
+            patterns_text.append(new_char)
+        patterns_text = u''.join(patterns_text)
+        for i in reversed(range(1, len(query) + 1)):
+            score += (len(query) - patterns_text.count(sep*i))*100000
+
+        temp = patterns_text.split(sep)
+        while u'' in temp:
+            temp.remove(u'')
+        if not patterns_text.startswith(sep):
+            temp = temp[1:]
+        if not patterns_text.endswith(sep):
+            temp = temp[:-1]
+
+        for pat in temp:
+            score += pat.count(u' ')*10000
+            score += pat.count(let)*100
+
+    return original_choice, enriched_text, score
+
+
+def get_search_scores(query, choices, ignore_case=True, template='{}',
+                      valid_only=False, sort=False):
+    """Search for query inside choices and return a list of tuples.
+
+    Returns a list of tuples of text with the enriched text (if a template is
+    provided) and a score for the match. Lower scores imply a better match.
+
+    Parameters
+    ----------
+    query : str
+        String with letters to search in each choice (in order of appearance).
+    choices : list of str
+        List of sentences/words in which to search for the 'query' letters.
+    ignore_case : bool, optional
+        Optional value perform a case insensitive search (True by default).
+    template : str, optional
+        Optional template string to surround letters found in choices. This is
+        useful when using a rich text editor ('{}' by default).
+        Examples: '<b>{}</b>', '<code>{}</code>', '<i>{}</i>'
+
+    Returns
+    -------
+    results : list of tuples
+        List of tuples where the first item is the text (enriched if a
+        template was used) and a search score. Lower scores means better match.
+    """
+    # First remove spaces from query
+    query = query.replace(' ', '')
+    pattern = get_search_regex(query, ignore_case)
+    results = []
+
+    for choice in choices:
+        r = re.search(pattern, choice)
+        if query and r:
+            result = get_search_score(query, choice, ignore_case=ignore_case,
+                                      apply_regex=False, template=template)
+        else:
+            if query:
+                result = (choice, choice, NOT_FOUND_SCORE)
+            else:
+                result = (choice, choice, NO_SCORE)
+
+        if valid_only:
+            if result[-1] != NOT_FOUND_SCORE:
+                results.append(result)
+        else:
+            results.append(result)
+
+    if sort:
+        results = sorted(results, key=lambda row: row[-1])
+
+    return results
+
+
+def test():
+    template = '<b>{0}</b>'
+    names = ['close pane', 'debug continue', 'debug exit', 'debug step into',
+             'debug step over', 'debug step return', 'fullscreen mode',
+             'layout preferences', 'lock unlock panes', 'maximize pane',
+             'preferences', 'quit', 'restart', 'save current layout',
+             'switch to breakpoints', 'switch to console', 'switch to editor',
+             'switch to explorer', 'switch to find_in_files',
+             'switch to historylog', 'switch to inspector',
+             'switch to ipython_console', 'switch to onlinehelp',
+             'switch to outline_explorer', 'switch to project_explorer',
+             'switch to variable_explorer', 'toggle default layout',
+             'use next layout', 'use previous layout', 'clear line',
+             'clear shell', 'inspect current object', 'blockcomment',
+             'breakpoint', 'close all', 'code completion',
+             'conditional breakpoint', 'configure', 'copy', 'copy line', 'cut',
+             'debug', 'debug with winpdb', 'delete', 'delete line',
+             'duplicate line', 'end of document', 'end of line',
+             'file list management', 'find next', 'find previous', 'find text',
+             'go to definition', 'go to line', 'go to next file',
+             'go to previous file', 'inspect current object', 'kill next word',
+             'kill previous word', 'kill to line end', 'kill to line start',
+             'last edit location', 'move line down', 'move line up',
+             'new file', 'next char', 'next cursor position', 'next line',
+             'next word', 'open file', 'paste', 'previous char',
+             'previous cursor position', 'previous line', 'previous word',
+             'print', 're-run last script', 'redo', 'replace text',
+             'rotate kill ring', 'run', 'run selection', 'save all', 'save as',
+             'save file', 'select all', 'show/hide outline',
+             'show/hide project explorer', 'start of document',
+             'start of line', 'toggle comment', 'unblockcomment', 'undo',
+             'yank', 'run profiler', 'run analysis']
+
+    a = get_search_scores('lay', names, template=template, )
+    b = get_search_scores('lay', names, template=template, valid_only=True,
+                          sort=True)
+    # Full results
+    for r in a:
+        print(r)
+    
+    # Ordered and filtered results
+    print('\n')
+
+    for r in b:
+        print(r)
+
+if __name__ == '__main__':
+    test()
diff --git a/spyderlib/widgets/sourcecode/syntaxhighlighters.py b/spyderlib/utils/syntaxhighlighters.py
similarity index 91%
rename from spyderlib/widgets/sourcecode/syntaxhighlighters.py
rename to spyderlib/utils/syntaxhighlighters.py
index f0b8ce1..a587050 100644
--- a/spyderlib/widgets/sourcecode/syntaxhighlighters.py
+++ b/spyderlib/utils/syntaxhighlighters.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -11,17 +11,19 @@ Editor widget syntax highlighters based on QtGui.QSyntaxHighlighter
 
 from __future__ import print_function
 
+import os
 import re
 import keyword
 
 from spyderlib.qt.QtGui import (QColor, QApplication, QFont,
-                                QSyntaxHighlighter, QCursor, QTextCharFormat)
+                                QSyntaxHighlighter, QCursor, QTextCharFormat,
+                                QTextOption)
 from spyderlib.qt.QtCore import Qt
 
 # Local imports
 from spyderlib import dependencies
-from spyderlib.baseconfig import _
-from spyderlib.config import CONF
+from spyderlib.config.base import _
+from spyderlib.config.main import CONF
 from spyderlib.py3compat import builtins, is_text_string, to_text_string
 from spyderlib.utils.sourcecode import CELL_LANGUAGES
 
@@ -40,6 +42,25 @@ COLOR_SCHEME_KEYS = ("background", "currentline", "currentcell", "occurence",
                      "normal", "keyword", "builtin", "definition",
                      "comment", "string", "number", "instance")
 COLOR_SCHEME_NAMES = CONF.get('color_schemes', 'names')
+# Mapping for file extensions that use Pygments highlighting but should use
+# different lexers than Pygments' autodetection suggests.  Keys are file
+# extensions or tuples of extensions, values are Pygments lexer names.
+CUSTOM_EXTENSION_LEXER = {'.ipynb': 'json',
+                          '.nt': 'bat',
+                          '.scss': 'css',
+                          '.m': 'matlab',
+                          ('.properties', '.session', '.inf', '.reg', '.url',
+                           '.cfg', '.cnf', '.aut', '.iss'): 'ini'}
+# Convert custom extensions into a one-to-one mapping for easier lookup.
+_custom_extension_lexer_mapping = {}
+for key, value in CUSTOM_EXTENSION_LEXER.items():
+    # Single key is mapped unchanged.
+    if is_text_string(key):
+        _custom_extension_lexer_mapping[key] = value
+    # Tuple of keys is iterated over and each is mapped to value.
+    else:
+        for k in key:
+            _custom_extension_lexer_mapping[k] = value
 
 
 #==============================================================================
@@ -64,8 +85,12 @@ class BaseSH(QSyntaxHighlighter):
     """Base Syntax Highlighter Class"""
     # Syntax highlighting rules:
     PROG = None
+    BLANKPROG = re.compile("\s+")
     # Syntax highlighting states (from one text block to another):
     NORMAL = 0
+    # Syntax highlighting parameters.
+    BLANK_ALPHA_FACTOR = 0.31
+    
     def __init__(self, parent, font=None, color_scheme='Spyder'):
         QSyntaxHighlighter.__init__(self, parent)
         
@@ -170,7 +195,37 @@ class BaseSH(QSyntaxHighlighter):
 
     def highlightBlock(self, text):
         raise NotImplementedError
-            
+
+    def highlight_spaces(self, text, offset=0):
+        """
+        Make blank space less apparent by setting the foreground alpha.
+        This only has an effect when 'Show blank space' is turned on.
+        Derived classes could call this function at the end of
+        highlightBlock().
+        """
+        flags_text = self.document().defaultTextOption().flags()
+        show_blanks =  flags_text & QTextOption.ShowTabsAndSpaces
+        if show_blanks:
+            format_leading = self.formats.get("leading", None)
+            format_trailing = self.formats.get("trailing", None)
+            match = self.BLANKPROG.search(text, offset)
+            while match:
+                start, end = match.span()
+                start = max([0, start+offset])
+                end = max([0, end+offset])
+                # Format trailing spaces at the end of the line. 
+                if end == len(text) and format_trailing is not None:
+                    self.setFormat(start, end, format_trailing)
+                # Format leading spaces, e.g. indentation.
+                if start == 0 and format_leading is not None:
+                    self.setFormat(start, end, format_leading)
+                format = self.format(start)
+                color_foreground = format.foreground().color()
+                alpha_new = self.BLANK_ALPHA_FACTOR * color_foreground.alphaF()
+                color_foreground.setAlphaF(alpha_new)
+                self.setFormat(start, end-start, color_foreground)
+                match = self.BLANKPROG.search(text, match.end())
+    
     def get_outlineexplorer_data(self):
         return self.outlineexplorer_data
 
@@ -182,9 +237,9 @@ class BaseSH(QSyntaxHighlighter):
 
 
 class TextSH(BaseSH):
-    """Simple Text Syntax Highlighter Class (do nothing)"""
+    """Simple Text Syntax Highlighter Class (only highlight spaces)"""
     def highlightBlock(self, text):
-        pass
+        self.highlight_spaces(text)
 
 
 class GenericSH(BaseSH):
@@ -205,6 +260,8 @@ class GenericSH(BaseSH):
                     self.setFormat(start, end-start, self.formats[key])
                     
             match = self.PROG.search(text, match.end())
+        
+        self.highlight_spaces(text)
 
 
 #==============================================================================
@@ -247,6 +304,9 @@ def make_python_patterns(additional_keywords=[], additional_builtins=[]):
 
 class OutlineExplorerData(object):
     CLASS, FUNCTION, STATEMENT, COMMENT, CELL = list(range(5))
+    FUNCTION_TOKEN = 'def'
+    CLASS_TOKEN = 'class'
+
     def __init__(self):
         self.text = None
         self.fold_level = None
@@ -255,6 +315,9 @@ class OutlineExplorerData(object):
         
     def is_not_class_nor_function(self):
         return self.def_type not in (self.CLASS, self.FUNCTION)
+
+    def is_class_or_function(self):
+        return self.def_type in (self.CLASS, self.FUNCTION)
     
     def is_comment(self):
         return self.def_type in (self.COMMENT, self.CELL)
@@ -266,7 +329,16 @@ class OutlineExplorerData(object):
     def get_function_name(self):
         if self.def_type == self.FUNCTION:
             return self.def_name
-    
+
+    def get_token(self):
+        if self.def_type == self.FUNCTION:
+            token = self.FUNCTION_TOKEN
+        elif self.def_type == self.CLASS:
+            token = self.CLASS_TOKEN
+
+        return token
+
+
 class PythonSH(BaseSH):
     """Python Syntax Highlighter"""
     # Syntax highlighting rules:
@@ -364,6 +436,7 @@ class PythonSH(BaseSH):
                                     oedata.def_type = self.DEF_TYPES[
                                                         to_text_string(value)]
                                     oedata.def_name = text[start1:end1]
+                                    oedata.color = self.formats["definition"]
                             elif value in ("elif", "else", "except", "finally",
                                            "for", "if", "try", "while",
                                            "with"):
@@ -393,9 +466,14 @@ class PythonSH(BaseSH):
                                                    self.formats["keyword"])
                     
             match = self.PROG.search(text, match.end())
- 
+        
         self.setCurrentBlockState(state)
         
+        # Use normal format for indentation and trailing spaces.
+        self.formats['leading'] = self.formats['normal']
+        self.formats['trailing'] = self.formats['normal']
+        self.highlight_spaces(text, offset)
+        
         if oedata is not None:
             block_nb = self.currentBlock().blockNumber()
             self.outlineexplorer_data[block_nb] = oedata
@@ -433,7 +511,8 @@ class CythonSH(PythonSH):
 #==============================================================================
 class EnamlSH(PythonSH):
     """Enaml Syntax Highlighter"""
-    ADDITIONAL_KEYWORDS = ["enamldef", "template", "attr", "event", "const", "alias"]
+    ADDITIONAL_KEYWORDS = ["enamldef", "template", "attr", "event", "const", "alias",
+                           "func"]
     ADDITIONAL_BUILTINS = []
     PROG = re.compile(make_python_patterns(ADDITIONAL_KEYWORDS,
                                            ADDITIONAL_BUILTINS), re.S)
@@ -515,7 +594,9 @@ class CppSH(BaseSH):
                         self.setFormat(start, end-start, self.formats[key])
                     
             match = self.PROG.search(text, match.end())
-
+        
+        self.highlight_spaces(text)
+        
         last_state = self.INSIDE_COMMENT if inside_comment else self.NORMAL
         self.setCurrentBlockState(last_state)
 
@@ -590,6 +671,8 @@ class FortranSH(BaseSH):
                                            self.formats["definition"])
                     
             match = self.PROG.search(text, match.end())
+        
+        self.highlight_spaces(text)
 
 class Fortran77SH(FortranSH):
     """Fortran 77 Syntax Highlighter"""
@@ -597,6 +680,7 @@ class Fortran77SH(FortranSH):
         text = to_text_string(text)
         if text.startswith(("c", "C")):
             self.setFormat(0, len(text), self.formats["comment"])
+            self.highlight_spaces(text)
         else:
             FortranSH.highlightBlock(self, text)
             self.setFormat(0, 5, self.formats["comment"])
@@ -652,7 +736,8 @@ class DiffSH(BaseSH):
             self.setFormat(0, len(text), self.formats["number"])
         elif text.startswith("@"):
             self.setFormat(0, len(text), self.formats["builtin"])
-
+        
+        self.highlight_spaces(text)
 
 #==============================================================================
 # NSIS highlighter
@@ -782,6 +867,8 @@ class BaseWebSH(BaseSH):
             
             match = self.PROG.search(text, match.end())
             match_count += 1
+        
+        self.highlight_spaces(text)
 
 def make_html_patterns():
     """Strongly inspired from idlelib.ColorDelegator.make_pat """
@@ -864,38 +951,35 @@ class PygmentsSH(BaseSH):
             start = ct
             ct += len(val)        
             self.setFormat(start, ct-start, self.formats[key])
-
-class BatchSH(PygmentsSH):
-    """Batch highlighter"""
-    _lang_name = 'bat'
-
-class IniSH(PygmentsSH):
-    """INI highlighter"""
-    _lang_name = 'ini'
-
-class XmlSH(PygmentsSH):
-    """XML highlighter"""
-    _lang_name = 'xml'
-
-class JsSH(PygmentsSH):
-    """Javascript highlighter"""
-    _lang_name = 'js'
-
-class JsonSH(PygmentsSH):
-    """Json highlighter"""
-    _lang_name = 'json'
-
-class JuliaSH(PygmentsSH):
-    """Julia highlighter"""
-    _lang_name = 'julia'
         
-class CssSH(PygmentsSH):
-    """CSS Syntax Highlighter"""
-    _lang_name = 'css'
+        self.highlight_spaces(text)
+
+def guess_pygments_highlighter(filename):
+    """Factory to generate syntax highlighter for the given filename.
+
+    If a syntax highlighter is not available for a particular file, this
+    function will attempt to generate one based on the lexers in Pygments.  If
+    Pygments is not available or does not have an appropriate lexer, TextSH
+    will be returned instead.
+
+    """
+    try:
+        from pygments.lexers import get_lexer_for_filename, get_lexer_by_name
+        from pygments.util import ClassNotFound
+    except ImportError:
+        return TextSH
+    root, ext = os.path.splitext(filename)
+    if ext in _custom_extension_lexer_mapping:
+        lexer = get_lexer_by_name(_custom_extension_lexer_mapping[ext])
+    else:
+        try:
+            lexer = get_lexer_for_filename(filename)
+        except ClassNotFound:
+            return TextSH
+    class GuessedPygmentsSH(PygmentsSH):
+        _lexer = lexer
+    return GuessedPygmentsSH
 
-class MatlabSH(PygmentsSH):
-    """Matlab highlighter"""
-    _lang_name = 'matlab'
 
 
 if __name__ == '__main__':
diff --git a/spyderlib/utils/vcs.py b/spyderlib/utils/vcs.py
index 5067276..6a64915 100644
--- a/spyderlib/utils/vcs.py
+++ b/spyderlib/utils/vcs.py
@@ -8,6 +8,7 @@
 
 from __future__ import print_function
 
+import sys
 import os.path as osp
 import subprocess
 
@@ -38,7 +39,7 @@ SUPPORTED = [
 class ActionToolNotFound(RuntimeError):
     """Exception to transmit information about supported tools for
        failed attempt to execute given action"""
-       
+
     def __init__(self, vcsname, action, tools):
         RuntimeError.__init__(self)
         self.vcsname = vcsname
@@ -113,22 +114,38 @@ def get_hg_revision(repopath):
 
 def get_git_revision(repopath):
     """Return Git revision for the repository located at repopath
-       Result is the latest commit hash, with None on error
+       Result is a tuple (latest commit hash, branch), with None values on
+       error
     """
     try:
         git = programs.find_program('git')
         assert git is not None and osp.isdir(osp.join(repopath, '.git'))
+
+        # Revision
         commit = subprocess.Popen([git, 'rev-parse', '--short', 'HEAD'],
                                   stdout=subprocess.PIPE,
                                   cwd=repopath).communicate()
+        commit = commit[0].strip()
         if PY3:
-            commit = str(commit[0][:-1])
-            commit = commit[2:-1]
+            commit = commit.decode(sys.getdefaultencoding())
+
+        # Branch
+        branches = subprocess.Popen([git, 'branch'],
+                                     stdout=subprocess.PIPE,
+                                     cwd=repopath).communicate()
+        branches = branches[0]
+        if PY3:
+            branches = branches.decode(sys.getdefaultencoding())
+        branches = branches.split('\n')
+        active_branch = [b for b in branches if b.startswith('*')]
+        if len(active_branch) != 1:
+            branch = None
         else:
-            commit = commit[0][:-1]
-        return commit
+            branch = active_branch[0].split(None, 1)[1]
+
+        return commit, branch
     except (subprocess.CalledProcessError, AssertionError, AttributeError):
-        return None
+        return None, None
 
 
 if __name__ == '__main__':
diff --git a/spyderlib/widgets/__init__.py b/spyderlib/widgets/__init__.py
index 790e7e3..652d1c5 100644
--- a/spyderlib/widgets/__init__.py
+++ b/spyderlib/widgets/__init__.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
diff --git a/spyderlib/widgets/arraybuilder.py b/spyderlib/widgets/arraybuilder.py
new file mode 100644
index 0000000..a7838cb
--- /dev/null
+++ b/spyderlib/widgets/arraybuilder.py
@@ -0,0 +1,373 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2009- The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+"""
+Numpy Matrix/Array Builder Widget
+"""
+
+# TODO:
+# -Set font based on caller? editor console? and adjust size of widget
+# -Fix positioning
+# -Use the same font as editor/console?
+
+from __future__ import division
+
+import re
+
+from spyderlib.qt.QtCore import (QEvent, QPoint, Qt)
+from spyderlib.qt.QtGui import (QDialog, QHBoxLayout, QLineEdit, QTableWidget,
+                                QTableWidgetItem, QToolButton, QToolTip,
+                                QWidget)
+
+from spyderlib.config.base import _
+from spyderlib.utils import icon_manager as ima
+from spyderlib.widgets.helperwidgets import HelperToolButton
+
+
+# Constants
+SHORTCUT_INLINE = "Shift+Ctrl+*"  # Fixed shortcuts for editor and consoles
+SHORTCUT_TABLE = "Ctrl+*"         # Fixed shortcuts for editor and consoles
+ELEMENT_SEPARATOR = ', '
+ROW_SEPARATOR = ';'
+BRACES = '], ['
+NAN_VALUES = ['nan', 'NAN', 'NaN', 'Na', 'NA', 'na']
+
+
+class NumpyArrayInline(QLineEdit):
+    """ """
+    def __init__(self, parent):
+        QLineEdit.__init__(self, parent)
+        self._parent = parent
+
+    def keyPressEvent(self, event):
+        """ """
+        if event.key() in [Qt.Key_Enter, Qt.Key_Return]:
+            self._parent.process_text()
+            if self._parent.is_valid():
+                self._parent.keyPressEvent(event)
+        else:
+            QLineEdit.keyPressEvent(self, event)
+
+    # to catch the Tab key event
+    def event(self, event):
+        if event.type() == QEvent.KeyPress:
+            if (event.key() == Qt.Key_Tab or event.key() == Qt.Key_Space):
+                text = self.text()
+                cursor = self.cursorPosition()
+                # fix to include in "undo/redo" history
+                if cursor != 0 and text[cursor-1] == ' ':
+                    text = text[:cursor-1] + ROW_SEPARATOR + ' ' +\
+                        text[cursor:]
+                else:
+                    text = text[:cursor] + ' ' + text[cursor:]
+                self.setCursorPosition(cursor)
+                self.setText(text)
+                self.setCursorPosition(cursor + 1)
+                return False
+        return QWidget.event(self, event)
+
+
+class NumpyArrayTable(QTableWidget):
+    """ """
+    def __init__(self, parent):
+        QTableWidget.__init__(self, parent)
+        self._parent = parent
+        self.setRowCount(2)
+        self.setColumnCount(2)
+        self.reset_headers()
+        # signals
+        self.cellChanged.connect(self.cell_changed)
+
+    def keyPressEvent(self, event):
+        """ """
+        if event.key() in [Qt.Key_Enter, Qt.Key_Return]:
+            QTableWidget.keyPressEvent(self, event)
+            # To avoid having to enter one final tab
+            self.setDisabled(True)
+            self.setDisabled(False)
+            self._parent.keyPressEvent(event)
+        else:
+            QTableWidget.keyPressEvent(self, event)
+
+    def cell_changed(self, row, col):
+        """ """
+        value = self.item(row, col).text()
+        rows = self.rowCount()
+        cols = self.columnCount()
+
+        if value:
+            if row == rows - 1:
+                self.setRowCount(rows + 1)
+            if col == cols - 1:
+                self.setColumnCount(cols + 1)
+        self.reset_headers()
+
+    def reset_headers(self):
+        """ """
+        rows = self.rowCount()
+        cols = self.columnCount()
+
+        for r in range(rows):
+            self.setVerticalHeaderItem(r, QTableWidgetItem(str(r)))
+        for c in range(cols):
+            self.setHorizontalHeaderItem(c, QTableWidgetItem(str(c)))
+            self.setColumnWidth(c, 40)
+
+    def text(self):
+        """ """
+        text = []
+        rows = self.rowCount()
+        cols = self.columnCount()
+
+        # handle empty table case
+        if rows == 2 and cols == 2:
+            item = self.item(0, 0)
+            if item is None:
+                return ''
+            elif item.text() == '':
+                return ''
+
+        for r in range(rows - 1):
+            for c in range(cols - 1):
+                item = self.item(r, c)
+                if item is not None:
+                    value = item.text()
+                else:
+                    value = '0'
+
+                if value == '':
+                    value = '0'
+                text.append(' ')
+                text.append(value)
+            text.append(ROW_SEPARATOR)
+
+        return ''.join(text[:-1])  # to remove the final uneeded ;
+
+
+class NumpyArrayDialog(QDialog):
+    """ """
+    def __init__(self, parent, inline=True, offset=0):
+        QDialog.__init__(self, parent)
+        self._parent = parent
+        self._text = None
+        self._valid = None
+        self._offset = offset
+
+        # TODO: add this as an option in the General Preferences?
+        self._force_float = False
+
+        self._help_inline = _("""
+           <b>Numpy Array/Matrix Helper</b><br>
+           Type an array in Matlab    : <code>[1 2;3 4]</code><br>
+           or Spyder simplified syntax : <code>1 2;3 4</code>
+           <br><br>
+           Hit 'Enter' for array or 'Ctrl+Enter' for matrix.
+           <br><br>
+           <b>Hint:</b><br>
+           Use two spaces or two tabs to generate a ';'.
+           """)
+
+        self._help_table = _("""
+           <b>Numpy Array/Matrix Helper</b><br>
+           Enter an array in the table. <br>
+           Use Tab to move between cells.
+           <br><br>
+           Hit 'Enter' for array or 'Ctrl+Enter' for matrix.
+           <br><br>
+           <b>Hint:</b><br>
+           Use two tabs at the end of a row to move to the next row.
+           """)
+
+        # widgets
+        self._button_warning = QToolButton()
+        self._button_help = HelperToolButton()
+        self._button_help.setIcon(ima.icon('MessageBoxInformation'))
+
+        style = """
+            QToolButton {
+              border: 1px solid grey;
+              padding:0px;
+              border-radius: 2px;
+              background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
+                  stop: 0 #f6f7fa, stop: 1 #dadbde);
+            }
+            """
+        self._button_help.setStyleSheet(style)
+
+        if inline:
+            self._button_help.setToolTip(self._help_inline)
+            self._text = NumpyArrayInline(self)
+            self._widget = self._text
+        else:
+            self._button_help.setToolTip(self._help_table)
+            self._table = NumpyArrayTable(self)
+            self._widget = self._table
+
+        style = """
+            QDialog {
+              margin:0px;
+              border: 1px solid grey;
+              padding:0px;
+              border-radius: 2px;
+            }"""
+        self.setStyleSheet(style)
+
+        style = """
+            QToolButton {
+              margin:1px;
+              border: 0px solid grey;
+              padding:0px;
+              border-radius: 0px;
+            }"""
+        self._button_warning.setStyleSheet(style)
+
+        # widget setup
+        self.setWindowFlags(Qt.Window | Qt.Dialog | Qt.FramelessWindowHint)
+        self.setModal(True)
+        self.setWindowOpacity(0.90)
+        self._widget.setMinimumWidth(200)
+
+        # layout
+        self._layout = QHBoxLayout()
+        self._layout.addWidget(self._widget)
+        self._layout.addWidget(self._button_warning, 1, Qt.AlignTop)
+        self._layout.addWidget(self._button_help, 1, Qt.AlignTop)
+        self.setLayout(self._layout)
+
+        self._widget.setFocus()
+
+    def keyPressEvent(self, event):
+        """Override Qt method"""
+        QToolTip.hideText()
+        ctrl = event.modifiers() & Qt.ControlModifier
+
+        if event.key() in [Qt.Key_Enter, Qt.Key_Return]:
+            if ctrl:
+                self.process_text(array=False)
+            else:
+                self.process_text(array=True)
+            self.accept()
+        else:
+            QDialog.keyPressEvent(self, event)
+
+    def event(self, event):
+        if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
+            return False
+        return QWidget.event(self, event)
+
+    def process_text(self, array=True):
+        """ """
+        if array:
+            prefix = 'np.array([['
+        else:
+            prefix = 'np.matrix([['
+
+        suffix = ']])'
+        values = self._widget.text().strip()
+
+        if values != '':
+            # cleans repeated spaces
+            exp = r'(\s*)' + ROW_SEPARATOR + r'(\s*)'
+            values = re.sub(exp, ROW_SEPARATOR, values)
+            values = re.sub("\s+", " ", values)
+            values = re.sub("]$", "", values)
+            values = re.sub("^\[", "", values)
+            values = re.sub(ROW_SEPARATOR + r'*$', '', values)
+
+            # replaces spaces by commas
+            values = values.replace(' ',  ELEMENT_SEPARATOR)
+
+            # iterate to find number of rows and columns
+            new_values = []
+            rows = values.split(ROW_SEPARATOR)
+            nrows = len(rows)
+            ncols = []
+            for row in rows:
+                new_row = []
+                elements = row.split(ELEMENT_SEPARATOR)
+                ncols.append(len(elements))
+                for e in elements:
+                    num = e
+
+                    # replaces not defined values
+                    if num in NAN_VALUES:
+                        num = 'np.nan'
+
+                    # Convert numbers to floating point
+                    if self._force_float:
+                        try:
+                            num = str(float(e))
+                        except:
+                            pass
+                    new_row.append(num)
+                new_values.append(ELEMENT_SEPARATOR.join(new_row))
+            new_values = ROW_SEPARATOR.join(new_values)
+            values = new_values
+
+            # Check validity
+            if len(set(ncols)) == 1:
+                self._valid = True
+            else:
+                self._valid = False
+
+            # Single rows are parsed as 1D arrays/matrices
+            if nrows == 1:
+                prefix = prefix[:-1]
+                suffix = suffix.replace("]])", "])")
+            
+            # Fix offset
+            offset = self._offset
+            braces = BRACES.replace(' ', '\n' + ' '*(offset + len(prefix) - 1))
+
+            values = values.replace(ROW_SEPARATOR,  braces)
+            text = "{0}{1}{2}".format(prefix, values, suffix)
+
+            self._text = text
+        else:
+            self._text = ''
+        self.update_warning()
+
+    def update_warning(self):
+        """ """
+        widget = self._button_warning
+        if not self.is_valid():
+            tip = _('Array dimensions not valid')
+            widget.setIcon(ima.icon('MessageBoxWarning'))
+            widget.setToolTip(tip)
+            QToolTip.showText(self._widget.mapToGlobal(QPoint(0, 5)), tip)
+        else:
+            self._button_warning.setToolTip('')
+
+    def is_valid(self):
+        """ """
+        return self._valid
+
+    def text(self):
+        """ """
+        return self._text
+
+    def mousePressEvent(self, event):
+        """ """
+        pass
+
+
+def test():
+    from spyderlib.utils.qthelpers import qapplication
+    app = qapplication()
+    app.setStyle('Plastique')
+
+    dlg_table = NumpyArrayDialog(None, inline=False)
+    dlg_inline = NumpyArrayDialog(None, inline=True)
+
+    if dlg_table.exec_():
+        print(dlg_table.text())
+
+    if dlg_inline.exec_():
+        print(dlg_inline.text())
+
+
+if __name__ == "__main__":
+    test()
diff --git a/spyderlib/widgets/browser.py b/spyderlib/widgets/browser.py
index b6d8489..ec3eb12 100644
--- a/spyderlib/widgets/browser.py
+++ b/spyderlib/widgets/browser.py
@@ -1,22 +1,23 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
 """Simple web browser widget"""
 
+import sys
+
+from spyderlib.qt.QtCore import QUrl, Slot, Signal
 from spyderlib.qt.QtGui import (QHBoxLayout, QWidget, QVBoxLayout,
-                                QProgressBar, QLabel, QMenu)
+                                QProgressBar, QLabel, QMenu, QFrame)
 from spyderlib.qt.QtWebKit import QWebView, QWebPage, QWebSettings
-from spyderlib.qt.QtCore import SIGNAL, QUrl
-
-import sys
 
 # Local imports
-from spyderlib.utils.qthelpers import (get_icon, create_action, add_actions,
+from spyderlib.config.base import DEV, _
+from spyderlib.utils.qthelpers import (create_action, add_actions,
                                        create_toolbutton, action2button)
-from spyderlib.baseconfig import DEV, _
+from spyderlib.utils import icon_manager as ima
 from spyderlib.widgets.comboboxes import UrlComboBox
 from spyderlib.widgets.findreplace import FindReplace
 from spyderlib.py3compat import to_text_string, is_text_string
@@ -28,10 +29,10 @@ class WebView(QWebView):
         QWebView.__init__(self, parent)
         self.zoom_factor = 1.
         self.zoom_out_action = create_action(self, _("Zoom out"),
-                                             icon=get_icon('zoom_out.png'),
+                                             icon=ima.icon('zoom_out'),
                                              triggered=self.zoom_out)
         self.zoom_in_action = create_action(self, _("Zoom in"),
-                                            icon=get_icon('zoom_in.png'),
+                                            icon=ima.icon('zoom_in'),
                                             triggered=self.zoom_in)
         
     def find_text(self, text, changed=True,
@@ -78,12 +79,14 @@ class WebView(QWebView):
     def get_zoom_factor(self):
         """Return zoom factor"""
         return self.zoom_factor
-            
+
+    @Slot()
     def zoom_out(self):
         """Zoom out"""
         self.zoom_factor = max(.1, self.zoom_factor-.1)
         self.apply_zoom_factor()
-    
+
+    @Slot()
     def zoom_in(self):
         """Zoom in"""
         self.zoom_factor += .1
@@ -120,14 +123,11 @@ class WebBrowser(QWidget):
         self.home_url = None
         
         self.webview = WebView(self)
-        self.connect(self.webview, SIGNAL("loadFinished(bool)"),
-                     self.load_finished)
-        self.connect(self.webview, SIGNAL("titleChanged(QString)"),
-                     self.setWindowTitle)
-        self.connect(self.webview, SIGNAL("urlChanged(QUrl)"),
-                     self.url_changed)
+        self.webview.loadFinished.connect(self.load_finished)
+        self.webview.titleChanged.connect(self.setWindowTitle)
+        self.webview.urlChanged.connect(self.url_changed)
                 
-        home_button = create_toolbutton(self, icon=get_icon('home.png'),
+        home_button = create_toolbutton(self, icon=ima.icon('home'),
                                         tip=_("Home"),
                                         triggered=self.go_home)
         
@@ -142,36 +142,30 @@ class WebBrowser(QWidget):
         next_button = pageact2btn(QWebPage.Forward)
         
         stop_button.setEnabled(False)
-        self.connect(self.webview, SIGNAL("loadStarted()"),
-                     lambda: stop_button.setEnabled(True))
-        self.connect(self.webview, SIGNAL("loadFinished(bool)"),
-                     lambda: stop_button.setEnabled(False))
+        self.webview.loadStarted.connect(lambda: stop_button.setEnabled(True))
+        self.webview.loadFinished.connect(lambda: stop_button.setEnabled(False))
         
         progressbar = QProgressBar(self)
         progressbar.setTextVisible(False)
         progressbar.hide()
-        self.connect(self.webview, SIGNAL("loadStarted()"), progressbar.show)
-        self.connect(self.webview, SIGNAL("loadProgress(int)"),
-                     progressbar.setValue)
-        self.connect(self.webview, SIGNAL("loadFinished(bool)"),
-                     lambda _state: progressbar.hide())
+        self.webview.loadStarted.connect(progressbar.show)
+        self.webview.loadProgress.connect(progressbar.setValue)
+        self.webview.loadFinished.connect(lambda _state: progressbar.hide())
         
         label = QLabel(self.get_label())
         
         self.url_combo = UrlComboBox(self)
-        self.connect(self.url_combo, SIGNAL('valid(bool)'),
-                     self.url_combo_activated)
-        self.connect(self.webview, SIGNAL("iconChanged()"), self.icon_changed)
+        self.url_combo.valid.connect(self.url_combo_activated)
+        self.webview.iconChanged.connect(self.icon_changed)
         
         self.find_widget = FindReplace(self)
         self.find_widget.set_editor(self.webview)
         self.find_widget.hide()
 
-        find_button = create_toolbutton(self, icon='find.png',
+        find_button = create_toolbutton(self, icon=ima.icon('find'),
                                         tip=_("Find text"),
                                         toggled=self.toggle_find_widget)
-        self.connect(self.find_widget, SIGNAL("visibility_changed(bool)"),
-                     find_button.setChecked)
+        self.find_widget.visibility_changed.connect(find_button.setChecked)
 
         hlayout = QHBoxLayout()
         for widget in (previous_button, next_button, home_button, find_button,
@@ -205,7 +199,8 @@ class WebBrowser(QWidget):
         else:
             url = url_or_text
         self.webview.load(url)
-        
+
+    @Slot()
     def go_home(self):
         """Go to home page"""
         if self.home_url is not None:
@@ -236,7 +231,8 @@ class WebBrowser(QWidget):
         self.url_combo.setItemIcon(self.url_combo.currentIndex(),
                                    self.webview.icon())
         self.setWindowIcon(self.webview.icon())
-        
+
+    @Slot(bool)
     def toggle_find_widget(self, state):
         if state:
             self.find_widget.show()
@@ -244,15 +240,52 @@ class WebBrowser(QWidget):
             self.find_widget.hide()
 
 
-def main():
+class FrameWebView(QFrame):
+    """
+    Framed QWebView for UI consistency in Spyder.
+    """
+    linkClicked = Signal(QUrl)
+
+    def __init__(self, parent):
+        QFrame.__init__(self, parent)
+
+        self._webview = WebView(self)
+
+        layout = QHBoxLayout()
+        layout.addWidget(self._webview)
+        layout.setContentsMargins(0, 0, 0, 0)
+        self.setLayout(layout)
+
+        self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
+
+        self._webview.linkClicked.connect(self.linkClicked)
+
+    def set_font(self, font, fixed_font=None):
+        self._webview.set_font(font, fixed_font=fixed_font)
+
+    def setHtml(self, html_text, base_url):
+        self._webview.setHtml(html_text, base_url)
+
+    def url(self):
+        return self._webview.url()
+
+    def load(self, url):
+        self._webview.load(url)
+
+    def page(self):
+        return self._webview.page()
+
+
+def test():
     """Run web browser"""
     from spyderlib.utils.qthelpers import qapplication
-    app = qapplication()
+    app = qapplication(test_time=8)
     widget = WebBrowser()
     widget.show()
-    widget.set_home_url('http://localhost:7464/')
+    widget.set_home_url('http://www.google.com/')
     widget.go_home()
     sys.exit(app.exec_())
 
+
 if __name__ == '__main__':
-    main()
+    test()
diff --git a/spyderlib/widgets/colors.py b/spyderlib/widgets/colors.py
index 4b7a140..e355009 100644
--- a/spyderlib/widgets/colors.py
+++ b/spyderlib/widgets/colors.py
@@ -1,8 +1,12 @@
 # -*- coding: utf-8 -*-
+#
+# Copyright © 2009- The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
 
 from spyderlib.qt.QtGui import (QLineEdit, QIcon, QHBoxLayout, QColor,
                                 QPushButton, QColorDialog, QPixmap)
-from spyderlib.qt.QtCore import SIGNAL, QSize, Slot, Property
+from spyderlib.qt.QtCore import QSize, Signal, Slot, Property
 
 # Local imports
 from spyderlib.py3compat import is_text_string
@@ -12,13 +16,13 @@ class ColorButton(QPushButton):
     """
     Color choosing push button
     """
-    __pyqtSignals__ = ("colorChanged(QColor)",)
+    colorChanged = Signal(QColor)
     
     def __init__(self, parent=None):
         QPushButton.__init__(self, parent)
         self.setFixedSize(20, 20)
         self.setIconSize(QSize(12, 12))
-        self.connect(self, SIGNAL("clicked()"), self.choose_color)
+        self.clicked.connect(self.choose_color)
         self._color = QColor()
     
     def choose_color(self):
@@ -35,7 +39,7 @@ class ColorButton(QPushButton):
     def set_color(self, color):
         if color != self._color:
             self._color = color
-            self.emit(SIGNAL("colorChanged(QColor)"), self._color)
+            self.colorChanged.emit(self._color)
             pixmap = QPixmap(self.iconSize())
             pixmap.fill(color)
             self.setIcon(QIcon(pixmap))
@@ -69,13 +73,11 @@ class ColorLayout(QHBoxLayout):
         QHBoxLayout.__init__(self)
         assert isinstance(color, QColor)
         self.lineedit = QLineEdit(color.name(), parent)
-        self.connect(self.lineedit, SIGNAL("textChanged(QString)"),
-                     self.update_color)
+        self.lineedit.textChanged.connect(self.update_color)
         self.addWidget(self.lineedit)
         self.colorbtn = ColorButton(parent)
         self.colorbtn.color = color
-        self.connect(self.colorbtn, SIGNAL("colorChanged(QColor)"),
-                     self.update_text)
+        self.colorbtn.colorChanged.connect(self.update_text)
         self.addWidget(self.colorbtn)
 
     def update_color(self, text):
diff --git a/spyderlib/widgets/comboboxes.py b/spyderlib/widgets/comboboxes.py
index ce006e4..47401db 100644
--- a/spyderlib/widgets/comboboxes.py
+++ b/spyderlib/widgets/comboboxes.py
@@ -1,65 +1,96 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
-"""Customized combobox widgets"""
+"""Customized combobox widgets."""
 
 # pylint: disable=C0103
 # pylint: disable=R0903
 # pylint: disable=R0911
 # pylint: disable=R0201
 
-from spyderlib.qt.QtGui import (QComboBox, QFont, QToolTip, QSizePolicy,
-                                QCompleter)
-from spyderlib.qt.QtCore import SIGNAL, Qt, QUrl, QTimer
 
+# Standard library imports
+import glob
+import os
 import os.path as osp
 
+# Third party imports
+from spyderlib.qt.QtCore import QEvent, Qt, QTimer, QUrl, Signal
+from spyderlib.qt.QtGui import (QComboBox, QCompleter, QFont,
+                                QSizePolicy, QToolTip)
+
 # Local imports
-from spyderlib.baseconfig import _
+from spyderlib.config.base import _
 from spyderlib.py3compat import to_text_string
+from spyderlib.widgets.helperwidgets import IconLineEdit
 
 
 class BaseComboBox(QComboBox):
     """Editable combo box base class"""
+    valid = Signal(bool, bool)
+    sig_tab_pressed = Signal(bool)
+    sig_double_tab_pressed = Signal(bool)
+
     def __init__(self, parent):
         QComboBox.__init__(self, parent)
         self.setEditable(True)
         self.setCompleter(QCompleter(self))
+        self.numpress = 0
+        self.selected_text = self.currentText()
+
+    # --- Qt overrides
+    def event(self, event):
+        """Qt Override.
+
+        Filter tab keys and process double tab keys.
+        """
+        if (event.type() == QEvent.KeyPress) and (event.key() == Qt.Key_Tab):
+            self.sig_tab_pressed.emit(True)
+            self.numpress += 1
+            if self.numpress == 1:
+                self.presstimer = QTimer.singleShot(400, self.handle_keypress)
+            return True
+        return QComboBox.event(self, event)
 
-    # --- overrides
     def keyPressEvent(self, event):
-        """Handle key press events"""
+        """Qt Override.
+
+        Handle key press events.
+        """
         if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter:
             if self.add_current_text_if_valid():
                 self.selected()
+                self.hide_completer()
+        elif event.key() == Qt.Key_Escape:
+            self.set_current_text(self.selected_text)
+            self.hide_completer()
         else:
             QComboBox.keyPressEvent(self, event)
 
-    def focusOutEvent(self, event):
-        """Handle focus out event"""
-        # Calling asynchronously the 'add_current_text' to avoid crash
-        # https://groups.google.com/group/spyderlib/browse_thread/thread/2257abf530e210bd
-        QTimer.singleShot(50, self.add_current_text_if_valid)
-        QComboBox.focusOutEvent(self, event)
-
     # --- own methods
+    def handle_keypress(self):
+        """When hitting tab, it handles if single or double tab"""
+        if self.numpress == 2:
+            self.sig_double_tab_pressed.emit(True)
+        self.numpress = 0
+
     def is_valid(self, qstr):
         """
         Return True if string is valid
         Return None if validation can't be done
         """
         pass
-        
+
     def selected(self):
         """Action to be executed when a valid item has been selected"""
-        self.emit(SIGNAL('valid(bool)'), True)
-        
+        self.valid.emit(True, True)
+
     def add_text(self, text):
-        """Add text to combo box: add a new item if text is not found in 
-        combo box items"""
+        """Add text to combo box: add a new item if text is not found in
+        combo box items."""
         index = self.findText(text)
         while index != -1:
             self.removeItem(index)
@@ -75,18 +106,32 @@ class BaseComboBox(QComboBox):
                 self.setCurrentIndex(0)
         else:
             self.setCurrentIndex(0)
-            
+
+    def set_current_text(self, text):
+        """Sets the text of the QLineEdit of the QComboBox."""
+        self.lineEdit().setText(to_text_string(text))
+
     def add_current_text(self):
         """Add current text to combo box history (convenient method)"""
-        self.add_text(self.currentText())
-            
+        text = self.currentText()
+        if osp.isdir(text):
+            if text[-1] == os.sep:
+                text = text[:-1]
+        self.add_text(text)
+
     def add_current_text_if_valid(self):
         """Add current text to combo box history if valid"""
         valid = self.is_valid(self.currentText())
         if valid or valid is None:
             self.add_current_text()
             return True
-        
+        else:
+            self.set_current_text(self.selected_text)
+
+    def hide_completer(self):
+        """Hides the completion widget."""
+        self.setCompleter(QCompleter([], self))
+
 
 class PatternComboBox(BaseComboBox):
     """Search pattern combo box"""
@@ -106,83 +151,125 @@ class EditableComboBox(BaseComboBox):
     """
     Editable combo box + Validate
     """
+
     def __init__(self, parent):
         BaseComboBox.__init__(self, parent)
-        self.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength)
         self.font = QFont()
-        self.connect(self, SIGNAL("editTextChanged(QString)"), self.validate)
-        self.connect(self, SIGNAL("activated(QString)"),
-                     lambda qstr: self.validate(qstr, editing=False))
-        self.set_default_style()
+        self.selected_text = self.currentText()
+
+        # Widget setup
+        self.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength)
+
+        # Signals
+        self.editTextChanged.connect(self.validate)
         self.tips = {True: _("Press enter to validate this entry"),
                      False: _('This entry is incorrect')}
-        
+
     def show_tip(self, tip=""):
         """Show tip"""
         QToolTip.showText(self.mapToGlobal(self.pos()), tip, self)
-        
-    def set_default_style(self):
-        """Set widget style to default"""
-        self.font.setBold(False)
-        self.setFont(self.font)
-        self.setStyleSheet("")
-        self.show_tip()
-        
+
     def selected(self):
         """Action to be executed when a valid item has been selected"""
         BaseComboBox.selected(self)
-        self.set_default_style()
-        
+        self.selected_text = self.currentText()
+
     def validate(self, qstr, editing=True):
         """Validate entered path"""
+        if self.selected_text == qstr:
+            self.valid.emit(True, True)
+            return
+
         valid = self.is_valid(qstr)
-        if self.hasFocus() and valid is not None:
-            self.font.setBold(True)
-            self.setFont(self.font)
+        if editing:
             if valid:
-                self.setStyleSheet("color:rgb(50, 155, 50);")
+                self.valid.emit(True, False)
             else:
-                self.setStyleSheet("color:rgb(200, 50, 50);")
-            if editing:
-                # Combo box text is being modified: invalidate the entry
-                self.show_tip(self.tips[valid])
-                self.emit(SIGNAL('valid(bool)'), False)
-            else:
-                # A new item has just been selected
-                if valid:
-                    self.selected()
-                else:
-                    self.emit(SIGNAL('valid(bool)'), False)
-        else:
-            self.set_default_style()
-            
+                self.valid.emit(False, False)
+
 
 class PathComboBox(EditableComboBox):
     """
     QComboBox handling path locations
     """
+    open_dir = Signal(str)
+
     def __init__(self, parent, adjust_to_contents=False):
         EditableComboBox.__init__(self, parent)
+
+        # Replace the default lineedit by a custom one with icon display
+        lineedit = IconLineEdit(self)
+
+        # Widget setup
         if adjust_to_contents:
             self.setSizeAdjustPolicy(QComboBox.AdjustToContents)
         else:
             self.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength)
             self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
         self.tips = {True: _("Press enter to validate this path"),
-                     False: _('This path is incorrect.\n'
-                                    'Enter a correct directory path,\n'
-                                    'then press enter to validate')}
-        
+                     False: ''}
+        self.setLineEdit(lineedit)
+
+        # Signals
+        self.sig_tab_pressed.connect(self.tab_complete)
+        self.sig_double_tab_pressed.connect(self.double_tab_complete)
+        self.valid.connect(lineedit.update_status)
+
+    # --- Qt overrides
+    def focusInEvent(self, event):
+        """Handle focus in event restoring to display the status icon."""
+        show_status = getattr(self.lineEdit(), 'show_status_icon', None)
+        if show_status:
+            show_status()
+        QComboBox.focusInEvent(self, event)
+
+    def focusOutEvent(self, event):
+        """Handle focus out event restoring the last valid selected path."""
+        # Calling asynchronously the 'add_current_text' to avoid crash
+        # https://groups.google.com/group/spyderlib/browse_thread/thread/2257abf530e210bd
+        lineedit = self.lineEdit()
+        QTimer.singleShot(50, lambda: lineedit.setText(self.selected_text))
+
+        hide_status = getattr(self.lineEdit(), 'hide_status_icon', None)
+        if hide_status:
+            hide_status()
+        QComboBox.focusOutEvent(self, event)
+
+    # --- Own methods
+    def _complete_options(self):
+        """Find available completion options."""
+        text = to_text_string(self.currentText())
+        opts = glob.glob(text + "*")
+        opts = sorted([opt for opt in opts if osp.isdir(opt)])
+        self.setCompleter(QCompleter(opts, self))
+        return opts
+
+    def double_tab_complete(self):
+        """If several options available a double tab displays options."""
+        opts = self._complete_options()
+        if len(opts) > 1:
+            self.completer().complete()
+
+    def tab_complete(self):
+        """
+        If there is a single option available one tab completes the option.
+        """
+        opts = self._complete_options()
+        if len(opts) == 1:
+            self.set_current_text(opts[0] + os.sep)
+            self.hide_completer()
+
     def is_valid(self, qstr=None):
         """Return True if string is valid"""
         if qstr is None:
             qstr = self.currentText()
-        return osp.isdir( to_text_string(qstr) )
-    
+        return osp.isdir(to_text_string(qstr))
+
     def selected(self):
         """Action to be executed when a valid item has been selected"""
-        EditableComboBox.selected(self)
-        self.emit(SIGNAL("open_dir(QString)"), self.currentText())
+        self.selected_text = self.currentText()
+        self.valid.emit(True, True)
+        self.open_dir.emit(self.selected_text)
 
 
 class UrlComboBox(PathComboBox):
@@ -191,8 +278,8 @@ class UrlComboBox(PathComboBox):
     """
     def __init__(self, parent, adjust_to_contents=False):
         PathComboBox.__init__(self, parent, adjust_to_contents)
-        self.disconnect(self, SIGNAL("editTextChanged(QString)"), self.validate)
-        
+        self.editTextChanged.disconnect(self.validate)
+
     def is_valid(self, qstr=None):
         """Return True if string is valid"""
         if qstr is None:
@@ -206,6 +293,7 @@ def is_module_or_package(path):
     is_package = osp.isdir(path) and osp.isfile(osp.join(path, '__init__.py'))
     return is_module or is_package
 
+
 class PythonModulesComboBox(PathComboBox):
     """
     QComboBox handling Python modules or packages path
@@ -213,14 +301,14 @@ class PythonModulesComboBox(PathComboBox):
     """
     def __init__(self, parent, adjust_to_contents=False):
         PathComboBox.__init__(self, parent, adjust_to_contents)
-        
+
     def is_valid(self, qstr=None):
         """Return True if string is valid"""
         if qstr is None:
             qstr = self.currentText()
         return is_module_or_package(to_text_string(qstr))
-    
+
     def selected(self):
         """Action to be executed when a valid item has been selected"""
         EditableComboBox.selected(self)
-        self.emit(SIGNAL("open(QString)"), self.currentText())
+        self.open_dir.emit(self.currentText())
diff --git a/spyderlib/widgets/dependencies.py b/spyderlib/widgets/dependencies.py
index 2fb8032..f49bfe8 100644
--- a/spyderlib/widgets/dependencies.py
+++ b/spyderlib/widgets/dependencies.py
@@ -1,22 +1,21 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2013 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
-"""Module checking Spyder optional runtime dependencies"""
+"""Module checking Spyder runtime dependencies"""
 
 from spyderlib.qt.QtGui import (QDialog, QTableView, QItemDelegate, QColor,
                                 QVBoxLayout, QHBoxLayout, QPushButton,
                                 QApplication, QLabel, QDialogButtonBox)
-from spyderlib.qt.QtCore import (Qt, QModelIndex, QAbstractTableModel, SIGNAL,
-                                 SLOT)
+from spyderlib.qt.QtCore import Qt, QModelIndex, QAbstractTableModel
 from spyderlib.qt.compat import to_qvariant
+import spyderlib.utils.icon_manager as ima
 import sys
 
 # Local imports
-from spyderlib.baseconfig import _
-from spyderlib.utils.qthelpers import get_icon
+from spyderlib.config.base import _
 from spyderlib import __version__
 
 
@@ -91,6 +90,10 @@ class DependenciesTableModel(QAbstractTableModel):
                 color.setAlphaF(.25)
                 return to_qvariant(color)
 
+    def reset(self):
+        self.beginResetModel()
+        self.endResetModel()
+
 
 class DependenciesDelegate(QItemDelegate):
     def __init__(self, parent=None):
@@ -124,32 +127,30 @@ class DependenciesDialog(QDialog):
     def __init__(self, parent):
         QDialog.__init__(self, parent)
         self.setWindowTitle("Spyder %s: %s" % (__version__,
-                                               _("Optional Dependencies")))
-        self.setWindowIcon(get_icon('advanced.png'))
+                                               _("Dependencies")))
+        self.setWindowIcon(ima.icon('tooloptions'))
         self.setModal(True)
 
         self.view = DependenciesTableView(self, [])
 
-        important_mods = ['rope', 'pyflakes', 'IPython', 'matplotlib']
+        opt_mods = ['NumPy', 'Matplotlib', 'Pandas', 'SymPy']
         self.label = QLabel(_("Spyder depends on several Python modules to "
-                              "provide additional functionality for its "
-                              "plugins. The table below shows the required "
+                              "provide the right functionality for all its "
+                              "panes. The table below shows the required "
                               "and installed versions (if any) of all of "
                               "them.<br><br>"
-                              "Although Spyder can work without any of these "
-                              "modules, it's strongly recommended that at "
-                              "least you try to install <b>%s</b> and "
-                              "<b>%s</b> to have a much better experience.")
-                              % (', '.join(important_mods[:-1]),
-                                 important_mods[-1]))
+                              "<b>Note</b>: You can safely use Spyder "
+                              "without the following modules installed: "
+                              "<b>%s</b> and <b>%s</b>")
+                              % (', '.join(opt_mods[:-1]), opt_mods[-1]))
         self.label.setWordWrap(True)
         self.label.setAlignment(Qt.AlignJustify)
         self.label.setContentsMargins(5, 8, 12, 10)
 
         btn = QPushButton(_("Copy to clipboard"), )
-        self.connect(btn, SIGNAL('clicked()'), self.copy_to_clipboard)
+        btn.clicked.connect(self.copy_to_clipboard)
         bbox = QDialogButtonBox(QDialogButtonBox.Ok)
-        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
+        bbox.accepted.connect(self.accept)
         hlayout = QHBoxLayout()
         hlayout.addWidget(btn)
         hlayout.addStretch()
diff --git a/spyderlib/widgets/editor.py b/spyderlib/widgets/editor.py
index 200a7a6..59c9487 100644
--- a/spyderlib/widgets/editor.py
+++ b/spyderlib/widgets/editor.py
@@ -1,2429 +1,2324 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright © 2009-2011 Pierre Raybaut
-# Licensed under the terms of the MIT License
-# (see spyderlib/__init__.py for details)
-
-"""Editor Widget"""
-
-# pylint: disable=C0103
-# pylint: disable=R0903
-# pylint: disable=R0911
-# pylint: disable=R0201
-
-from __future__ import print_function
-
-from spyderlib.qt import is_pyqt46
-from spyderlib.qt.QtGui import (QVBoxLayout, QMessageBox, QMenu, QFont,
-                                QAction, QApplication, QWidget, QHBoxLayout,
-                                QLabel, QKeySequence, QMainWindow,
-                                QSplitter, QListWidget, QListWidgetItem,
-                                QDialog, QLineEdit)
-from spyderlib.qt.QtCore import (SIGNAL, Qt, QFileInfo, QThread, QObject,
-                                 QByteArray, QSize, QPoint, QTimer, Slot)
-from spyderlib.qt.compat import getsavefilename
-
-import os
-import sys
-import os.path as osp
-
-# Local imports
-from spyderlib.utils import encoding, sourcecode, codeanalysis
-from spyderlib.utils import introspection
-from spyderlib.baseconfig import _, DEBUG, STDOUT, STDERR
-from spyderlib.config import EDIT_FILTERS, EDIT_EXT, get_filter, EDIT_FILETYPES
-from spyderlib.guiconfig import create_shortcut, new_shortcut
-from spyderlib.utils.qthelpers import (get_icon, create_action, add_actions,
-                                       mimedata2url, get_filetype_icon,
-                                       create_toolbutton)
-from spyderlib.widgets.tabs import BaseTabs
-from spyderlib.widgets.findreplace import FindReplace
-from spyderlib.widgets.editortools import OutlineExplorerWidget
-from spyderlib.widgets.status import (ReadWriteStatus, EOLStatus,
-                                      EncodingStatus, CursorPositionStatus)
-from spyderlib.widgets.sourcecode import syntaxhighlighters, codeeditor
-from spyderlib.widgets.sourcecode.base import TextEditBaseWidget  #analysis:ignore
-from spyderlib.widgets.sourcecode.codeeditor import Printer  #analysis:ignore
-from spyderlib.widgets.sourcecode.codeeditor import get_file_language
-from spyderlib.py3compat import to_text_string, qbytearray_to_str, u
-
-
-DEBUG_EDITOR = DEBUG >= 3
-
-
-class FileListDialog(QDialog):
-    def __init__(self, parent, tabs, fullpath_sorting):
-        QDialog.__init__(self, parent)
-        
-        # Destroying the C++ object right after closing the dialog box,
-        # otherwise it may be garbage-collected in another QThread
-        # (e.g. the editor's analysis thread in Spyder), thus leading to
-        # a segmentation fault on UNIX or an application crash on Windows
-        self.setAttribute(Qt.WA_DeleteOnClose)
-        
-        self.indexes = None
-        
-        self.setWindowIcon(get_icon('filelist.png'))
-        self.setWindowTitle(_("File list management"))
-        
-        self.setModal(True)
-        
-        flabel = QLabel(_("Filter:"))
-        self.edit = QLineEdit(self)
-        self.connect(self.edit, SIGNAL("returnPressed()"), self.edit_file)
-        self.connect(self.edit, SIGNAL("textChanged(QString)"),
-                     lambda text: self.synchronize(0))
-        fhint = QLabel(_("(press <b>Enter</b> to edit file)"))
-        edit_layout = QHBoxLayout()
-        edit_layout.addWidget(flabel)
-        edit_layout.addWidget(self.edit)
-        edit_layout.addWidget(fhint)
-        
-        self.listwidget = QListWidget(self)
-        self.listwidget.setResizeMode(QListWidget.Adjust)
-        self.connect(self.listwidget, SIGNAL("itemSelectionChanged()"),
-                     self.item_selection_changed)
-        self.connect(self.listwidget, SIGNAL("itemActivated(QListWidgetItem*)"),
-                     self.edit_file)
-        
-        btn_layout = QHBoxLayout()
-        edit_btn = create_toolbutton(self, icon=get_icon('edit.png'),
-                     text=_("&Edit file"), autoraise=False,
-                     triggered=self.edit_file, text_beside_icon=True)
-        edit_btn.setMinimumHeight(28)
-        btn_layout.addWidget(edit_btn)
-        
-        btn_layout.addStretch()
-        btn_layout.addSpacing(150)
-        btn_layout.addStretch()
-        
-        close_btn = create_toolbutton(self, text=_("&Close file"),
-              icon=get_icon("fileclose.png"),
-              autoraise=False, text_beside_icon=True,
-              triggered=lambda: self.emit(SIGNAL("close_file(int)"),
-                                  self.indexes[self.listwidget.currentRow()]))
-        close_btn.setMinimumHeight(28)
-        btn_layout.addWidget(close_btn)
-
-        hint = QLabel(_("Hint: press <b>Alt</b> to show accelerators"))
-        hint.setAlignment(Qt.AlignCenter)
-        
-        vlayout = QVBoxLayout()
-        vlayout.addLayout(edit_layout)
-        vlayout.addWidget(self.listwidget)
-        vlayout.addLayout(btn_layout)
-        vlayout.addWidget(hint)
-        self.setLayout(vlayout)
-        
-        self.tabs = tabs
-        self.fullpath_sorting = fullpath_sorting
-        self.buttons = (edit_btn, close_btn)
-        
-    def edit_file(self):
-        row = self.listwidget.currentRow()
-        if self.listwidget.count() > 0 and row >= 0:
-            self.emit(SIGNAL("edit_file(int)"), self.indexes[row])
-            self.accept()
-            
-    def item_selection_changed(self):
-        for btn in self.buttons:
-            btn.setEnabled(self.listwidget.currentRow() >= 0)
-        
-    def synchronize(self, stack_index):
-        count = self.tabs.count()
-        if count == 0:
-            self.accept()
-            return
-        self.listwidget.setTextElideMode(Qt.ElideMiddle
-                                         if self.fullpath_sorting
-                                         else Qt.ElideRight)
-        current_row = self.listwidget.currentRow()
-        if current_row >= 0:
-            current_text = to_text_string(self.listwidget.currentItem().text())
-        else:
-            current_text = ""
-        self.listwidget.clear()
-        self.indexes = []
-        new_current_index = stack_index
-        filter_text = to_text_string(self.edit.text())
-        lw_index = 0
-        for index in range(count):
-            text = to_text_string(self.tabs.tabText(index))
-            if len(filter_text) == 0 or filter_text in text:
-                if text == current_text:
-                    new_current_index = lw_index
-                lw_index += 1
-                item = QListWidgetItem(self.tabs.tabIcon(index),
-                                       text, self.listwidget)
-                item.setSizeHint(QSize(0, 25))
-                self.listwidget.addItem(item)
-                self.indexes.append(index)
-        if new_current_index < self.listwidget.count():
-            self.listwidget.setCurrentRow(new_current_index)
-        for btn in self.buttons:
-            btn.setEnabled(lw_index > 0)
-
-
-class AnalysisThread(QThread):
-    """Analysis thread"""
-    def __init__(self, parent, checker, source_code):
-        super(AnalysisThread, self).__init__(parent)
-        self.checker = checker
-        self.results = None
-        self.source_code = source_code
-    
-    def run(self):
-        """Run analysis"""
-        try:
-            self.results = self.checker(self.source_code)
-        except Exception:
-            if DEBUG_EDITOR:
-                import traceback
-                traceback.print_exc(file=STDERR)
-
-
-class ThreadManager(QObject):
-    """Analysis thread manager"""
-    def __init__(self, parent, max_simultaneous_threads=2):
-        super(ThreadManager, self).__init__(parent)
-        self.max_simultaneous_threads = max_simultaneous_threads
-        self.started_threads = {}
-        self.pending_threads = []
-        self.end_callbacks = {}
-        
-    def close_threads(self, parent):
-        """Close threads associated to parent_id"""
-        if DEBUG_EDITOR:
-            print("Call to 'close_threads'", file=STDOUT)
-        if parent is None:
-            # Closing all threads
-            self.pending_threads = []
-            threadlist = []
-            for threads in list(self.started_threads.values()):
-                threadlist += threads
-        else:
-            parent_id = id(parent)
-            self.pending_threads = [(_th, _id) for (_th, _id)
-                                    in self.pending_threads
-                                    if _id != parent_id]
-            threadlist = self.started_threads.get(parent_id, [])
-        for thread in threadlist:
-            if DEBUG_EDITOR:
-                print("Waiting for thread %r to finish" % thread, file=STDOUT)
-            while thread.isRunning():
-                # We can't terminate thread safely, so we simply wait...
-                QApplication.processEvents()
-                
-    def close_all_threads(self):
-        """Close all threads"""
-        if DEBUG_EDITOR:
-            print("Call to 'close_all_threads'", file=STDOUT)
-        self.close_threads(None)
-        
-    def add_thread(self, checker, end_callback, source_code, parent):
-        """Add thread to queue"""
-        parent_id = id(parent)
-        thread = AnalysisThread(self, checker, source_code)
-        self.end_callbacks[id(thread)] = end_callback
-        self.pending_threads.append((thread, parent_id))
-        if DEBUG_EDITOR:
-            print("Added thread %r to queue" % thread, file=STDOUT)
-        QTimer.singleShot(50, self.update_queue)
-    
-    def update_queue(self):
-        """Update queue"""
-        started = 0
-        for parent_id, threadlist in list(self.started_threads.items()):
-            still_running = []
-            for thread in threadlist:
-                if thread.isFinished():
-                    end_callback = self.end_callbacks.pop(id(thread))
-                    if thread.results is not None:
-                        #  The thread was executed successfully
-                        end_callback(thread.results)
-                    thread.setParent(None)
-                    thread = None
-                else:
-                    still_running.append(thread)
-                    started += 1
-            threadlist = None
-            if still_running:
-                self.started_threads[parent_id] = still_running
-            else:
-                self.started_threads.pop(parent_id)
-        if DEBUG_EDITOR:
-            print("Updating queue:", file=STDOUT)
-            print("    started:", started, file=STDOUT)
-            print("    pending:", len(self.pending_threads), file=STDOUT)
-        if self.pending_threads and started < self.max_simultaneous_threads:
-            thread, parent_id = self.pending_threads.pop(0)
-            self.connect(thread, SIGNAL('finished()'), self.update_queue)
-            threadlist = self.started_threads.get(parent_id, [])
-            self.started_threads[parent_id] = threadlist+[thread]
-            if DEBUG_EDITOR:
-                print("===>starting:", thread, file=STDOUT)
-            thread.start()
-
-
-class FileInfo(QObject):
-    """File properties"""
-    def __init__(self, filename, encoding, editor, new, threadmanager,
-                 introspection_plugin):
-        QObject.__init__(self)
-        self.threadmanager = threadmanager
-        self.filename = filename
-        self.newly_created = new
-        self.default = False      # Default untitled file
-        self.encoding = encoding
-        self.editor = editor
-        self.path = []
-
-        self.classes = (filename, None, None)
-        self.analysis_results = []
-        self.todo_results = []
-        self.lastmodified = QFileInfo(filename).lastModified()
-
-        self.connect(self.editor, SIGNAL('textChanged()'),
-                     self.text_changed)
-        self.connect(self.editor, SIGNAL('breakpoints_changed()'),
-                     self.breakpoints_changed)
-
-        self.pyflakes_results = None
-        self.pep8_results = None
-
-    def text_changed(self):
-        """Editor's text has changed"""
-        self.default = False
-        self.emit(SIGNAL('text_changed_at(QString,int)'),
-                  self.filename, self.editor.get_position('cursor'))
-
-    def get_source_code(self):
-        """Return associated editor source code"""
-        return to_text_string(self.editor.toPlainText())
-    
-    def run_code_analysis(self, run_pyflakes, run_pep8):
-        """Run code analysis"""
-        run_pyflakes = run_pyflakes and codeanalysis.is_pyflakes_installed()
-        run_pep8 = run_pep8 and\
-                   codeanalysis.get_checker_executable('pep8') is not None
-        self.pyflakes_results = []
-        self.pep8_results = []
-        if self.editor.is_python():
-            enc = self.encoding.replace('-guessed', '').replace('-bom', '')
-            source_code = self.get_source_code().encode(enc)
-            if run_pyflakes:
-                self.pyflakes_results = None
-            if run_pep8:
-                self.pep8_results = None
-            if run_pyflakes:
-                self.threadmanager.add_thread(codeanalysis.check_with_pyflakes,
-                                              self.pyflakes_analysis_finished,
-                                              source_code, self)
-            if run_pep8:
-                self.threadmanager.add_thread(codeanalysis.check_with_pep8,
-                                              self.pep8_analysis_finished,
-                                              source_code, self)
-        
-    def pyflakes_analysis_finished(self, results):
-        """Pyflakes code analysis thread has finished"""
-        self.pyflakes_results = results
-        if self.pep8_results is not None:
-            self.code_analysis_finished()
-        
-    def pep8_analysis_finished(self, results):
-        """Pep8 code analysis thread has finished"""
-        self.pep8_results = results
-        if self.pyflakes_results is not None:
-            self.code_analysis_finished()
-        
-    def code_analysis_finished(self):
-        """Code analysis thread has finished"""
-        self.set_analysis_results(self.pyflakes_results+self.pep8_results)
-        self.emit(SIGNAL('analysis_results_changed()'))
-        
-    def set_analysis_results(self, results):
-        """Set analysis results and update warning markers in editor"""
-        self.analysis_results = results
-        self.editor.process_code_analysis(results)
-        
-    def cleanup_analysis_results(self):
-        """Clean-up analysis results"""
-        self.analysis_results = []
-        self.editor.cleanup_code_analysis()
-            
-    def run_todo_finder(self):
-        """Run TODO finder"""
-        if self.editor.is_python():
-            self.threadmanager.add_thread(codeanalysis.find_tasks,
-                                          self.todo_finished,
-                                          self.get_source_code(), self)
-        
-    def todo_finished(self, results):
-        """Code analysis thread has finished"""
-        self.set_todo_results(results)
-        self.emit(SIGNAL('todo_results_changed()'))
-        
-    def set_todo_results(self, results):
-        """Set TODO results and update markers in editor"""
-        self.todo_results = results
-        self.editor.process_todo(results)
-        
-    def cleanup_todo_results(self):
-        """Clean-up TODO finder results"""
-        self.todo_results = []
-        
-    def breakpoints_changed(self):
-        """Breakpoint list has changed"""
-        breakpoints = self.editor.get_breakpoints()
-        if self.editor.breakpoints != breakpoints:
-            self.editor.breakpoints = breakpoints
-            self.emit(SIGNAL("save_breakpoints(QString,QString)"),
-                      self.filename, repr(breakpoints))
-        
-
-class EditorStack(QWidget):
-    def __init__(self, parent, actions):
-        QWidget.__init__(self, parent)
-        
-        self.setAttribute(Qt.WA_DeleteOnClose)
-        
-        self.threadmanager = ThreadManager(self)
-        
-        self.newwindow_action = None
-        self.horsplit_action = None
-        self.versplit_action = None
-        self.close_action = None
-        self.__get_split_actions()
-        
-        layout = QVBoxLayout()
-        layout.setContentsMargins(0, 0, 0, 0)
-        self.setLayout(layout)
-
-        self.menu = None
-        self.filelist_dlg = None
-#        self.filelist_btn = None
-#        self.previous_btn = None
-#        self.next_btn = None
-        self.tabs = None
-
-        self.stack_history = []
-        
-        self.setup_editorstack(parent, layout)
-
-        self.find_widget = None
-
-        self.data = []
-        
-        filelist_action = create_action(self, _("File list management"),
-                                 icon=get_icon('filelist.png'),
-                                 triggered=self.open_filelistdialog)
-        copy_to_cb_action = create_action(self, _("Copy path to clipboard"),
-                icon="editcopy.png",
-                triggered=lambda:
-                QApplication.clipboard().setText(self.get_current_filename()))
-        self.menu_actions = actions+[None, filelist_action, copy_to_cb_action]
-        self.outlineexplorer = None
-        self.inspector = None
-        self.unregister_callback = None
-        self.is_closable = False
-        self.new_action = None
-        self.open_action = None
-        self.save_action = None
-        self.revert_action = None
-        self.tempfile_path = None
-        self.title = _("Editor")
-        self.pyflakes_enabled = True
-        self.pep8_enabled = False
-        self.todolist_enabled = True
-        self.realtime_analysis_enabled = False
-        self.is_analysis_done = False
-        self.linenumbers_enabled = True
-        self.blanks_enabled = False
-        self.edgeline_enabled = True
-        self.edgeline_column = 79
-        self.codecompletion_auto_enabled = True
-        self.codecompletion_case_enabled = False
-        self.codecompletion_enter_enabled = False
-        self.calltips_enabled = True
-        self.go_to_definition_enabled = True
-        self.close_parentheses_enabled = True
-        self.close_quotes_enabled = True
-        self.add_colons_enabled = True
-        self.auto_unindent_enabled = True
-        self.indent_chars = " "*4
-        self.tab_stop_width = 40
-        self.inspector_enabled = False
-        self.default_font = None
-        self.wrap_enabled = False
-        self.tabmode_enabled = False
-        self.intelligent_backspace_enabled = True
-        self.highlight_current_line_enabled = False
-        self.highlight_current_cell_enabled = False        
-        self.occurence_highlighting_enabled = True
-        self.checkeolchars_enabled = True
-        self.always_remove_trailing_spaces = False
-        self.fullpath_sorting_enabled = None
-        self.focus_to_editor = True
-        self.set_fullpath_sorting_enabled(False)
-        ccs = 'Spyder'
-        if ccs not in syntaxhighlighters.COLOR_SCHEME_NAMES:
-            ccs = syntaxhighlighters.COLOR_SCHEME_NAMES[0]
-        self.color_scheme = ccs
-        self.introspector = introspection.PluginManager(self)
-
-        self.introspector.send_to_inspector.connect(self.send_to_inspector)
-        self.introspector.edit_goto.connect(
-             lambda fname, lineno, name:
-             self.emit(SIGNAL("edit_goto(QString,int,QString)"),
-                              fname, lineno, name))
-
-        self.__file_status_flag = False
-        
-        # Real-time code analysis
-        self.analysis_timer = QTimer(self)
-        self.analysis_timer.setSingleShot(True)
-        self.analysis_timer.setInterval(2000)
-        self.connect(self.analysis_timer, SIGNAL("timeout()"), 
-                     self.analyze_script)
-        
-        # Accepting drops
-        self.setAcceptDrops(True)
-        
-        # Local shortcuts
-        self.shortcuts = self.create_shortcuts()
-
-    def create_shortcuts(self):
-        """Create local shortcuts"""
-        # Configurable shortcuts
-        inspect = create_shortcut(self.inspect_current_object, context='Editor',
-                                  name='Inspect current object', parent=self)
-        breakpoint = create_shortcut(self.set_or_clear_breakpoint,
-                                     context='Editor', name='Breakpoint',
-                                     parent=self)
-        cbreakpoint = create_shortcut(self.set_or_edit_conditional_breakpoint,
-                                      context='Editor',
-                                      name='Conditional breakpoint',
-                                      parent=self)
-        gotoline = create_shortcut(self.go_to_line, context='Editor',
-                                   name='Go to line', parent=self)
-        filelist = create_shortcut(self.open_filelistdialog, context='Editor',
-                                   name='File list management', parent=self)
-        tab = create_shortcut(self.go_to_previous_file, context='Editor',
-                              name='Go to previous file', parent=self)
-        tabshift = create_shortcut(self.go_to_next_file, context='Editor',
-                                   name='Go to next file', parent=self)
-        # Fixed shortcuts
-        new_shortcut(QKeySequence.ZoomIn, self,
-                     lambda: self.emit(SIGNAL('zoom_in()')))
-        new_shortcut("Ctrl+=", self, lambda: self.emit(SIGNAL('zoom_in()')))
-        new_shortcut(QKeySequence.ZoomOut, self,
-                     lambda: self.emit(SIGNAL('zoom_out()')))
-        new_shortcut("Ctrl+0", self, lambda: self.emit(SIGNAL('zoom_reset()')))
-        new_shortcut("Ctrl+W", self, self.close_file)
-        new_shortcut("Ctrl+F4", self, self.close_file)
-        # Return configurable ones
-        return [inspect, breakpoint, cbreakpoint, gotoline, filelist, tab,
-                tabshift]
-
-    def get_shortcut_data(self):
-        """
-        Returns shortcut data, a list of tuples (shortcut, text, default)
-        shortcut (QShortcut or QAction instance)
-        text (string): action/shortcut description
-        default (string): default key sequence
-        """
-        return [sc.data for sc in self.shortcuts]
-        
-    def setup_editorstack(self, parent, layout):
-        """Setup editorstack's layout"""
-        menu_btn = create_toolbutton(self, icon=get_icon("tooloptions.png"),
-                                     tip=_("Options"))
-        self.menu = QMenu(self)
-        menu_btn.setMenu(self.menu)
-        menu_btn.setPopupMode(menu_btn.InstantPopup)
-        self.connect(self.menu, SIGNAL("aboutToShow()"), self.__setup_menu)
-
-#        self.filelist_btn = create_toolbutton(self,
-#                             icon=get_icon('filelist.png'),
-#                             tip=_("File list management"),
-#                             triggered=self.open_filelistdialog)
-#        
-#        self.previous_btn = create_toolbutton(self,
-#                             icon=get_icon('previous.png'),
-#                             tip=_("Previous file"),
-#                             triggered=self.go_to_previous_file)
-#        
-#        self.next_btn = create_toolbutton(self,
-#                             icon=get_icon('next.png'),
-#                             tip=_("Next file"),
-#                             triggered=self.go_to_next_file)
-                
-        # Optional tabs
-#        corner_widgets = {Qt.TopRightCorner: [self.previous_btn,
-#                                              self.filelist_btn, self.next_btn,
-#                                              5, menu_btn]}
-        corner_widgets = {Qt.TopRightCorner: [menu_btn]}
-        self.tabs = BaseTabs(self, menu=self.menu, menu_use_tooltips=True,
-                             corner_widgets=corner_widgets)
-        self.tabs.tabBar().setObjectName('plugin-tab')
-        self.tabs.set_close_function(self.close_file)
-
-        if hasattr(self.tabs, 'setDocumentMode') \
-           and not sys.platform == 'darwin':
-            # Don't set document mode to true on OSX because it generates
-            # a crash when the editor is detached from the main window
-            # Fixes Issue 561
-            self.tabs.setDocumentMode(True)
-        self.connect(self.tabs, SIGNAL('currentChanged(int)'),
-                     self.current_changed)
-
-        if sys.platform == 'darwin':
-            tab_container = QWidget()
-            tab_container.setObjectName('tab-container')
-            tab_layout = QHBoxLayout(tab_container)
-            tab_layout.setContentsMargins(0, 0, 0, 0)
-            tab_layout.addWidget(self.tabs)
-            layout.addWidget(tab_container)
-        else:
-            layout.addWidget(self.tabs)
-        
-    def add_corner_widgets_to_tabbar(self, widgets):
-        self.tabs.add_corner_widgets(widgets)
-        
-    def closeEvent(self, event):
-        self.threadmanager.close_all_threads()
-        self.disconnect(self.analysis_timer, SIGNAL("timeout()"),
-                        self.analyze_script)
-        QWidget.closeEvent(self, event)
-        if is_pyqt46:
-            self.emit(SIGNAL('destroyed()'))        
-    
-    def clone_editor_from(self, other_finfo, set_current):
-        fname = other_finfo.filename
-        enc = other_finfo.encoding
-        new = other_finfo.newly_created
-        finfo = self.create_new_editor(fname, enc, "",
-                                       set_current=set_current, new=new,
-                                       cloned_from=other_finfo.editor)
-        finfo.set_analysis_results(other_finfo.analysis_results)
-        finfo.set_todo_results(other_finfo.todo_results)
-        return finfo.editor
-            
-    def clone_from(self, other):
-        """Clone EditorStack from other instance"""
-        for other_finfo in other.data:
-            self.clone_editor_from(other_finfo, set_current=True)
-        self.set_stack_index(other.get_stack_index())
-        
-    def open_filelistdialog(self):
-        """Open file list management dialog box"""
-        self.filelist_dlg = dlg = FileListDialog(self, self.tabs,
-                                                 self.fullpath_sorting_enabled)
-        self.connect(dlg, SIGNAL("edit_file(int)"), self.set_stack_index)
-        self.connect(dlg, SIGNAL("close_file(int)"), self.close_file)
-        dlg.synchronize(self.get_stack_index())
-        dlg.exec_()
-        self.filelist_dlg = None
-        
-    def update_filelistdialog(self):
-        """Synchronize file list dialog box with editor widget tabs"""
-        if self.filelist_dlg is not None:
-            self.filelist_dlg.synchronize(self.get_stack_index())
-            
-    def go_to_line(self):
-        """Go to line dialog"""
-        if self.data:
-            self.get_current_editor().exec_gotolinedialog()
-                
-    def set_or_clear_breakpoint(self):
-        """Set/clear breakpoint"""
-        if self.data:
-            editor = self.get_current_editor()
-            editor.add_remove_breakpoint()
-            
-    def set_or_edit_conditional_breakpoint(self):
-        """Set conditional breakpoint"""
-        if self.data:
-            editor = self.get_current_editor()
-            editor.add_remove_breakpoint(edit_condition=True)
-            
-    def inspect_current_object(self):
-        """Inspect current object in Object Inspector"""
-        if self.introspector:
-            editor = self.get_current_editor()
-            position = editor.get_position('cursor')
-            self.inspector.switch_to_editor_source()
-            self.introspector.show_object_info(position, auto=False)
-        else:
-            text = self.get_current_editor().get_current_object()
-            if text:
-                self.send_to_inspector(text, force=True)
-        
-    #------ Editor Widget Settings
-    def set_closable(self, state):
-        """Parent widget must handle the closable state"""
-        self.is_closable = state
-        
-    def set_io_actions(self, new_action, open_action,
-                       save_action, revert_action):
-        self.new_action = new_action
-        self.open_action = open_action
-        self.save_action = save_action
-        self.revert_action = revert_action
-        
-    def set_find_widget(self, find_widget):
-        self.find_widget = find_widget
-        
-    def set_outlineexplorer(self, outlineexplorer):
-        self.outlineexplorer = outlineexplorer
-        self.connect(self.outlineexplorer,
-                     SIGNAL("outlineexplorer_is_visible()"),
-                     self._refresh_outlineexplorer)
-
-    def initialize_outlineexplorer(self):
-        """This method is called separately from 'set_oulineexplorer' to avoid 
-        doing unnecessary updates when there are multiple editor windows"""
-        for index in range(self.get_stack_count()):
-            if index != self.get_stack_index():
-                self._refresh_outlineexplorer(index=index)
-        
-    def add_outlineexplorer_button(self, editor_plugin):
-        oe_btn = create_toolbutton(editor_plugin)
-        oe_btn.setDefaultAction(self.outlineexplorer.visibility_action)
-        self.add_corner_widgets_to_tabbar([5, oe_btn])
-        
-    def set_inspector(self, inspector):
-        self.inspector = inspector
-        
-    def set_tempfile_path(self, path):
-        self.tempfile_path = path
-        
-    def set_title(self, text):
-        self.title = text
-        
-    def __update_editor_margins(self, editor):
-        editor.setup_margins(linenumbers=self.linenumbers_enabled,
-                             markers=self.has_markers())
-        
-    def __codeanalysis_settings_changed(self, current_finfo):
-        if self.data:
-            run_pyflakes, run_pep8 = self.pyflakes_enabled, self.pep8_enabled
-            for finfo in self.data:
-                self.__update_editor_margins(finfo.editor)
-                finfo.cleanup_analysis_results()
-                if (run_pyflakes or run_pep8) and current_finfo is not None:
-                    if current_finfo is not finfo:
-                        finfo.run_code_analysis(run_pyflakes, run_pep8)
-        
-    def set_pyflakes_enabled(self, state, current_finfo=None):
-        # CONF.get(self.CONF_SECTION, 'code_analysis/pyflakes')
-        self.pyflakes_enabled = state
-        self.__codeanalysis_settings_changed(current_finfo)
-        
-    def set_pep8_enabled(self, state, current_finfo=None):
-        # CONF.get(self.CONF_SECTION, 'code_analysis/pep8')
-        self.pep8_enabled = state
-        self.__codeanalysis_settings_changed(current_finfo)
-    
-    def has_markers(self):
-        """Return True if this editorstack has a marker margin for TODOs or
-        code analysis"""
-        return self.todolist_enabled or self.pyflakes_enabled\
-               or self.pep8_enabled
-    
-    def set_todolist_enabled(self, state, current_finfo=None):
-        # CONF.get(self.CONF_SECTION, 'todo_list')
-        self.todolist_enabled = state
-        if self.data:
-            for finfo in self.data:
-                self.__update_editor_margins(finfo.editor)
-                finfo.cleanup_todo_results()
-                if state and current_finfo is not None:
-                    if current_finfo is not finfo:
-                        finfo.run_todo_finder()
-                        
-    def set_realtime_analysis_enabled(self, state):
-        self.realtime_analysis_enabled = state
-
-    def set_realtime_analysis_timeout(self, timeout):
-        self.analysis_timer.setInterval(timeout)
-    
-    def set_linenumbers_enabled(self, state, current_finfo=None):
-        # CONF.get(self.CONF_SECTION, 'line_numbers')
-        self.linenumbers_enabled = state
-        if self.data:
-            for finfo in self.data:
-                self.__update_editor_margins(finfo.editor)
-    
-    def set_blanks_enabled(self, state):
-        self.blanks_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_blanks_enabled(state)
-        
-    def set_edgeline_enabled(self, state):
-        # CONF.get(self.CONF_SECTION, 'edge_line')
-        self.edgeline_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_edge_line_enabled(state)
-        
-    def set_edgeline_column(self, column):
-        # CONF.get(self.CONF_SECTION, 'edge_line_column')
-        self.edgeline_column = column
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_edge_line_column(column)
-        
-    def set_codecompletion_auto_enabled(self, state):
-        # CONF.get(self.CONF_SECTION, 'codecompletion_auto')
-        self.codecompletion_auto_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_codecompletion_auto(state)
-                
-    def set_codecompletion_case_enabled(self, state):
-        self.codecompletion_case_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_codecompletion_case(state)
-                    
-    def set_codecompletion_enter_enabled(self, state):
-        self.codecompletion_enter_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_codecompletion_enter(state)
-                
-    def set_calltips_enabled(self, state):
-        # CONF.get(self.CONF_SECTION, 'calltips')
-        self.calltips_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_calltips(state)
-                
-    def set_go_to_definition_enabled(self, state):
-        # CONF.get(self.CONF_SECTION, 'go_to_definition')
-        self.go_to_definition_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_go_to_definition_enabled(state)
-        
-    def set_close_parentheses_enabled(self, state):
-        # CONF.get(self.CONF_SECTION, 'close_parentheses')
-        self.close_parentheses_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_close_parentheses_enabled(state)
-                
-    def set_close_quotes_enabled(self, state):
-        # CONF.get(self.CONF_SECTION, 'close_quotes')
-        self.close_quotes_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_close_quotes_enabled(state)
-    
-    def set_add_colons_enabled(self, state):
-        # CONF.get(self.CONF_SECTION, 'add_colons')
-        self.add_colons_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_add_colons_enabled(state)
-    
-    def set_auto_unindent_enabled(self, state):
-        # CONF.get(self.CONF_SECTION, 'auto_unindent')
-        self.auto_unindent_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_auto_unindent_enabled(state)
-                
-    def set_indent_chars(self, indent_chars):
-        # CONF.get(self.CONF_SECTION, 'indent_chars')
-        indent_chars = indent_chars[1:-1] # removing the leading/ending '*'
-        self.indent_chars = indent_chars
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_indent_chars(indent_chars)
-
-    def set_tab_stop_width(self, tab_stop_width):
-        # CONF.get(self.CONF_SECTION, 'tab_stop_width')
-        self.tab_stop_width = tab_stop_width
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.setTabStopWidth(tab_stop_width)
-                
-    def set_inspector_enabled(self, state):
-        self.inspector_enabled = state
-        
-    def set_default_font(self, font, color_scheme=None):
-        # get_font(self.CONF_SECTION)
-        self.default_font = font
-        if color_scheme is not None:
-            self.color_scheme = color_scheme
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_font(font, color_scheme)
-            
-    def set_color_scheme(self, color_scheme):
-        self.color_scheme = color_scheme
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_color_scheme(color_scheme)
-        
-    def set_wrap_enabled(self, state):
-        # CONF.get(self.CONF_SECTION, 'wrap')
-        self.wrap_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.toggle_wrap_mode(state)
-        
-    def set_tabmode_enabled(self, state):
-        # CONF.get(self.CONF_SECTION, 'tab_always_indent')
-        self.tabmode_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_tab_mode(state)
-                
-    def set_intelligent_backspace_enabled(self, state):
-        # CONF.get(self.CONF_SECTION, 'intelligent_backspace')
-        self.intelligent_backspace_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.toggle_intelligent_backspace(state)
-        
-    def set_occurence_highlighting_enabled(self, state):
-        # CONF.get(self.CONF_SECTION, 'occurence_highlighting')
-        self.occurence_highlighting_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_occurence_highlighting(state)
-                
-    def set_occurence_highlighting_timeout(self, timeout):
-        # CONF.get(self.CONF_SECTION, 'occurence_highlighting/timeout')
-        self.occurence_highlighting_timeout = timeout
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_occurence_timeout(timeout)
-                
-    def set_highlight_current_line_enabled(self, state):
-        self.highlight_current_line_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_highlight_current_line(state)
-
-    def set_highlight_current_cell_enabled(self, state):
-        self.highlight_current_cell_enabled = state
-        if self.data:
-            for finfo in self.data:
-                finfo.editor.set_highlight_current_cell(state)
-        
-    def set_checkeolchars_enabled(self, state):
-        # CONF.get(self.CONF_SECTION, 'check_eol_chars')
-        self.checkeolchars_enabled = state
-        
-    def set_fullpath_sorting_enabled(self, state):
-        # CONF.get(self.CONF_SECTION, 'fullpath_sorting')
-        self.fullpath_sorting_enabled = state
-        if self.data:
-            finfo = self.data[self.get_stack_index()]
-            self.data.sort(key=self.__get_sorting_func())
-            new_index = self.data.index(finfo)
-            self.__repopulate_stack()
-            self.set_stack_index(new_index)
-        
-    def set_always_remove_trailing_spaces(self, state):
-        # CONF.get(self.CONF_SECTION, 'always_remove_trailing_spaces')
-        self.always_remove_trailing_spaces = state
-            
-    def set_focus_to_editor(self, state):
-        self.focus_to_editor = state
-    
-    #------ Stacked widget management
-    def get_stack_index(self):
-        return self.tabs.currentIndex()
-    
-    def get_current_finfo(self):
-        if self.data:
-            return self.data[self.get_stack_index()]
-    
-    def get_current_editor(self):
-        return self.tabs.currentWidget()
-    
-    def get_stack_count(self):
-        return self.tabs.count()
-    
-    def set_stack_index(self, index):
-        self.tabs.setCurrentIndex(index)
-            
-    def set_tabbar_visible(self, state):
-        self.tabs.tabBar().setVisible(state)
-    
-    def remove_from_data(self, index):
-        self.tabs.blockSignals(True)
-        self.tabs.removeTab(index)
-        self.data.pop(index)
-        self.tabs.blockSignals(False)
-        self.update_actions()
-        self.update_filelistdialog()
-    
-    def __modified_readonly_title(self, title, is_modified, is_readonly):
-        if is_modified is not None and is_modified:
-            title += "*"
-        if is_readonly is not None and is_readonly:
-            title = "(%s)" % title
-        return title
-    
-    def get_tab_text(self, filename, is_modified=None, is_readonly=None):
-        """Return tab title"""
-        return self.__modified_readonly_title(osp.basename(filename),
-                                              is_modified, is_readonly)
-                
-    def get_tab_tip(self, filename, is_modified=None, is_readonly=None):
-        """Return tab menu title"""
-        if self.fullpath_sorting_enabled:
-            text = filename
-        else:
-            text = u("%s — %s")
-        text = self.__modified_readonly_title(text,
-                                              is_modified, is_readonly)
-        if self.tempfile_path is not None\
-           and filename == encoding.to_unicode_from_fs(self.tempfile_path):
-            temp_file_str = to_text_string(_("Temporary file"))
-            if self.fullpath_sorting_enabled:
-                return "%s (%s)" % (text, temp_file_str)
-            else:
-                return text % (temp_file_str, self.tempfile_path)
-        else:
-            if self.fullpath_sorting_enabled:
-                return text
-            else:
-                return text % (osp.basename(filename), osp.dirname(filename))
-        
-    def __get_sorting_func(self):
-        if self.fullpath_sorting_enabled:
-            return lambda item: osp.join(osp.dirname(item.filename),
-                                         '_'+osp.basename(item.filename))
-        else:
-            return lambda item: osp.basename(item.filename)
-    
-    def add_to_data(self, finfo, set_current):
-        self.data.append(finfo)
-        self.data.sort(key=self.__get_sorting_func())
-        index = self.data.index(finfo)
-        fname, editor = finfo.filename, finfo.editor
-        self.tabs.insertTab(index, editor, get_filetype_icon(fname),
-                            self.get_tab_text(fname))
-        self.set_stack_title(index, False)
-        if set_current:
-            self.set_stack_index(index)
-            self.current_changed(index)
-        self.update_actions()
-        self.update_filelistdialog()
-        
-    def __repopulate_stack(self):
-        self.tabs.blockSignals(True)
-        self.tabs.clear()
-        for finfo in self.data:
-            icon = get_filetype_icon(finfo.filename)
-            if finfo.newly_created:
-                is_modified = True
-            else:
-                is_modified = None
-            tab_text = self.get_tab_text(finfo.filename, is_modified)
-            tab_tip = self.get_tab_tip(finfo.filename)
-            index = self.tabs.addTab(finfo.editor, icon, tab_text)
-            self.tabs.setTabToolTip(index, tab_tip)
-        self.tabs.blockSignals(False)
-        self.update_filelistdialog()
-        
-    def rename_in_data(self, index, new_filename):
-        finfo = self.data[index]
-        if osp.splitext(finfo.filename)[1] != osp.splitext(new_filename)[1]:
-            # File type has changed!
-            txt = to_text_string(finfo.editor.get_text_with_eol())
-            language = get_file_language(new_filename, txt)
-            finfo.editor.set_language(language)
-        set_new_index = index == self.get_stack_index()
-        current_fname = self.get_current_filename()
-        finfo.filename = new_filename
-        self.data.sort(key=self.__get_sorting_func())
-        new_index = self.data.index(finfo)
-        self.__repopulate_stack()
-        if set_new_index:
-            self.set_stack_index(new_index)
-        else:
-            # Fixes Issue 1287
-            self.set_current_filename(current_fname)
-        if self.outlineexplorer is not None:
-            self.outlineexplorer.file_renamed(finfo.editor, finfo.filename)
-        return new_index
-        
-    def set_stack_title(self, index, is_modified):
-        finfo = self.data[index]
-        fname = finfo.filename
-        is_modified = (is_modified or finfo.newly_created) and not finfo.default
-        is_readonly = finfo.editor.isReadOnly()
-        tab_text = self.get_tab_text(fname, is_modified, is_readonly)
-        tab_tip = self.get_tab_tip(fname, is_modified, is_readonly)
-        self.tabs.setTabText(index, tab_text)
-        self.tabs.setTabToolTip(index, tab_tip)
-        
-        
-    #------ Context menu
-    def __setup_menu(self):
-        """Setup tab context menu before showing it"""
-        self.menu.clear()
-        if self.data:
-            actions = self.menu_actions
-        else:
-            actions = (self.new_action, self.open_action)
-            self.setFocus() # --> Editor.__get_focus_editortabwidget
-        add_actions(self.menu, list(actions)+self.__get_split_actions())
-        self.close_action.setEnabled(self.is_closable)
-
-
-    #------ Hor/Ver splitting
-    def __get_split_actions(self):
-        # New window
-        self.newwindow_action = create_action(self, _("New window"),
-                icon="newwindow.png", tip=_("Create a new editor window"),
-                triggered=lambda: self.emit(SIGNAL("create_new_window()")))
-        # Splitting
-        self.versplit_action = create_action(self, _("Split vertically"),
-                icon="versplit.png",
-                tip=_("Split vertically this editor window"),
-                triggered=lambda: self.emit(SIGNAL("split_vertically()")))
-        self.horsplit_action = create_action(self, _("Split horizontally"),
-                icon="horsplit.png",
-                tip=_("Split horizontally this editor window"),
-                triggered=lambda: self.emit(SIGNAL("split_horizontally()")))
-        self.close_action = create_action(self, _("Close this panel"),
-                icon="close_panel.png", triggered=self.close)
-        return [None, self.newwindow_action, None, 
-                self.versplit_action, self.horsplit_action, self.close_action]
-        
-    def reset_orientation(self):
-        self.horsplit_action.setEnabled(True)
-        self.versplit_action.setEnabled(True)
-        
-    def set_orientation(self, orientation):
-        self.horsplit_action.setEnabled(orientation == Qt.Horizontal)
-        self.versplit_action.setEnabled(orientation == Qt.Vertical)
-        
-    def update_actions(self):
-        state = self.get_stack_count() > 0
-        self.horsplit_action.setEnabled(state)
-        self.versplit_action.setEnabled(state)
-    
-    
-    #------ Accessors
-    def get_current_filename(self):
-        if self.data:
-            return self.data[self.get_stack_index()].filename
-        
-    def has_filename(self, filename):
-        fixpath = lambda path: osp.normcase(osp.realpath(path))
-        for index, finfo in enumerate(self.data):
-            if fixpath(filename) == fixpath(finfo.filename):
-                return index
-        
-    def set_current_filename(self, filename):
-        """Set current filename and return the associated editor instance"""
-        index = self.has_filename(filename)
-        if index is not None:
-            self.set_stack_index(index)
-            editor = self.data[index].editor
-            editor.setFocus()
-            return editor
-        
-    def is_file_opened(self, filename=None):
-        if filename is None:
-            # Is there any file opened?
-            return len(self.data) > 0
-        else:
-            return self.has_filename(filename)
-
-        
-    #------ Close file, tabwidget...
-    def close_file(self, index=None, force=False):
-        """Close file (index=None -> close current file)
-        Keep current file index unchanged (if current file 
-        that is being closed)"""
-        current_index = self.get_stack_index()
-        count = self.get_stack_count()
-        if index is None:
-            if count > 0:
-                index = current_index
-            else:
-                self.find_widget.set_editor(None)
-                return
-        new_index = None
-        if count > 1:
-            if current_index == index:
-                new_index = self._get_previous_file_index()
-            else:
-                new_index = current_index
-        is_ok = force or self.save_if_changed(cancelable=True, index=index)
-        if is_ok:
-            finfo = self.data[index]
-            self.threadmanager.close_threads(finfo)
-            # Removing editor reference from outline explorer settings:
-            if self.outlineexplorer is not None:
-                self.outlineexplorer.remove_editor(finfo.editor)
-            
-            self.remove_from_data(index)
-            
-            # We pass self object ID as a QString, because otherwise it would 
-            # depend on the platform: long for 64bit, int for 32bit. Replacing 
-            # by long all the time is not working on some 32bit platforms 
-            # (see Issue 1094, Issue 1098)
-            self.emit(SIGNAL('close_file(QString,int)'), str(id(self)), index)
-            
-            if not self.data and self.is_closable:
-                # editortabwidget is empty: removing it
-                # (if it's not the first editortabwidget)
-                self.close()
-            self.emit(SIGNAL('opened_files_list_changed()'))
-            self.emit(SIGNAL('update_code_analysis_actions()'))
-            self._refresh_outlineexplorer()
-            self.emit(SIGNAL('refresh_file_dependent_actions()'))
-            self.emit(SIGNAL('update_plugin_title()'))
-            editor = self.get_current_editor()
-            if editor:
-                editor.setFocus()
-            
-            if new_index is not None:
-                if index < new_index:
-                    new_index -= 1
-                self.set_stack_index(new_index)
-        if self.get_stack_count() == 0:
-            self.emit(SIGNAL('sig_new_file()'))
-            return False
-        return is_ok
-
-    def close_all_files(self):
-        """Close all opened scripts"""
-        while self.close_file():
-            pass
-        
-
-    #------ Save
-    def save_if_changed(self, cancelable=False, index=None):
-        """Ask user to save file if modified"""
-        if index is None:
-            indexes = list(range(self.get_stack_count()))
-        else:
-            indexes = [index]
-        buttons = QMessageBox.Yes | QMessageBox.No
-        if cancelable:
-            buttons |= QMessageBox.Cancel
-        unsaved_nb = 0
-        for index in indexes:
-            if self.data[index].editor.document().isModified():
-                unsaved_nb += 1
-        if not unsaved_nb:
-            # No file to save
-            return True
-        if unsaved_nb > 1:
-            buttons |= QMessageBox.YesAll | QMessageBox.NoAll
-        yes_all = False
-        for index in indexes:
-            self.set_stack_index(index)
-            finfo = self.data[index]
-            if finfo.filename == self.tempfile_path or yes_all:
-                if not self.save():
-                    return False
-            elif finfo.editor.document().isModified():
-                answer = QMessageBox.question(self, self.title,
-                            _("<b>%s</b> has been modified."
-                              "<br>Do you want to save changes?"
-                              ) % osp.basename(finfo.filename),
-                            buttons)
-                if answer == QMessageBox.Yes:
-                    if not self.save():
-                        return False
-                elif answer == QMessageBox.YesAll:
-                    if not self.save():
-                        return False
-                    yes_all = True
-                elif answer == QMessageBox.NoAll:
-                    return True
-                elif answer == QMessageBox.Cancel:
-                    return False
-        return True
-    
-    def save(self, index=None, force=False):
-        """Save file"""
-        if index is None:
-            # Save the currently edited file
-            if not self.get_stack_count():
-                return
-            index = self.get_stack_index()
-            
-        finfo = self.data[index]
-        if not finfo.editor.document().isModified() and not force:
-            return True
-        if not osp.isfile(finfo.filename) and not force:
-            # File has not been saved yet
-            return self.save_as(index=index)
-        if self.always_remove_trailing_spaces:
-            self.remove_trailing_spaces(index)
-        txt = to_text_string(finfo.editor.get_text_with_eol())
-        try:
-            finfo.encoding = encoding.write(txt, finfo.filename,
-                                            finfo.encoding)
-            finfo.newly_created = False
-            self.emit(SIGNAL('encoding_changed(QString)'), finfo.encoding)
-            finfo.lastmodified = QFileInfo(finfo.filename).lastModified()
-            
-            # We pass self object ID as a QString, because otherwise it would 
-            # depend on the platform: long for 64bit, int for 32bit. Replacing 
-            # by long all the time is not working on some 32bit platforms 
-            # (see Issue 1094, Issue 1098)
-            self.emit(SIGNAL('file_saved(QString,int,QString)'),
-                      str(id(self)), index, finfo.filename)
-
-            finfo.editor.document().setModified(False)
-            self.modification_changed(index=index)
-            self.analyze_script(index)
-            self.introspector.validate()
-            
-            #XXX CodeEditor-only: re-scan the whole text to rebuild outline 
-            # explorer data from scratch (could be optimized because 
-            # rehighlighting text means searching for all syntax coloring 
-            # patterns instead of only searching for class/def patterns which 
-            # would be sufficient for outline explorer data.
-            finfo.editor.rehighlight()
-            
-            self._refresh_outlineexplorer(index)
-            return True
-        except EnvironmentError as error:
-            QMessageBox.critical(self, _("Save"),
-                                 _("<b>Unable to save script '%s'</b>"
-                                   "<br><br>Error message:<br>%s"
-                                   ) % (osp.basename(finfo.filename),
-                                        str(error)))
-            return False
-        
-    def file_saved_in_other_editorstack(self, index, filename):
-        """
-        File was just saved in another editorstack, let's synchronize!
-        This avoid file to be automatically reloaded
-        
-        Filename is passed in case file was just saved as another name
-        """
-        finfo = self.data[index]
-        finfo.newly_created = False
-        finfo.filename = to_text_string(filename)
-        finfo.lastmodified = QFileInfo(finfo.filename).lastModified()
-    
-    def select_savename(self, original_filename):
-        selectedfilter = get_filter(EDIT_FILETYPES,
-                                    osp.splitext(original_filename)[1])
-        self.emit(SIGNAL('redirect_stdio(bool)'), False)
-        filename, _selfilter = getsavefilename(self, _("Save Python script"),
-                               original_filename, EDIT_FILTERS, selectedfilter)
-        self.emit(SIGNAL('redirect_stdio(bool)'), True)
-        if filename:
-            return osp.normpath(filename)
-    
-    def save_as(self, index=None):
-        """Save file as..."""
-        if index is None:
-            # Save the currently edited file
-            index = self.get_stack_index()
-        finfo = self.data[index]
-        filename = self.select_savename(finfo.filename)
-        if filename:
-            ao_index = self.has_filename(filename)
-            # Note: ao_index == index --> saving an untitled file
-            if ao_index and ao_index != index:
-                if not self.close_file(ao_index):
-                    return
-                if ao_index < index:
-                    index -= 1
-
-            new_index = self.rename_in_data(index, new_filename=filename)
-
-            # We pass self object ID as a QString, because otherwise it would 
-            # depend on the platform: long for 64bit, int for 32bit. Replacing 
-            # by long all the time is not working on some 32bit platforms 
-            # (see Issue 1094, Issue 1098)
-            self.emit(SIGNAL('file_renamed_in_data(QString,int,QString)'),
-                      str(id(self)), index, filename)
-
-            ok = self.save(index=new_index, force=True)
-            self.refresh(new_index)
-            self.set_stack_index(new_index)
-            return ok
-        else:
-            return False
-        
-    def save_all(self):
-        """Save all opened files"""
-        folders = set()
-        for index in range(self.get_stack_count()):
-            if self.data[index].editor.document().isModified():
-                folders.add(osp.dirname(self.data[index].filename))
-                self.save(index)
-    
-    #------ Update UI
-    def start_stop_analysis_timer(self):
-        self.is_analysis_done = False
-        if self.realtime_analysis_enabled:
-            self.analysis_timer.stop()
-            self.analysis_timer.start()
-    
-    def analyze_script(self, index=None):
-        """Analyze current script with pyflakes + find todos"""
-        if self.is_analysis_done:
-            return
-        if index is None:
-            index = self.get_stack_index()
-        if self.data:
-            finfo = self.data[index]
-            run_pyflakes, run_pep8 = self.pyflakes_enabled, self.pep8_enabled
-            if run_pyflakes or run_pep8:
-                finfo.run_code_analysis(run_pyflakes, run_pep8)
-            if self.todolist_enabled:
-                finfo.run_todo_finder()
-        self.is_analysis_done = True
-                
-    def set_analysis_results(self, index, analysis_results):
-        """Synchronize analysis results between editorstacks"""
-        self.data[index].set_analysis_results(analysis_results)
-        
-    def get_analysis_results(self):
-        if self.data:
-            return self.data[self.get_stack_index()].analysis_results
-                
-    def set_todo_results(self, index, todo_results):
-        """Synchronize todo results between editorstacks"""
-        self.data[index].set_todo_results(todo_results)
-        
-    def get_todo_results(self):
-        if self.data:
-            return self.data[self.get_stack_index()].todo_results
-        
-    def current_changed(self, index):
-        """Stack index has changed"""
-#        count = self.get_stack_count()
-#        for btn in (self.filelist_btn, self.previous_btn, self.next_btn):
-#            btn.setEnabled(count > 1)
-        
-        editor = self.get_current_editor()
-        if index != -1:
-            editor.setFocus()
-            if DEBUG_EDITOR:
-                print("setfocusto:", editor, file=STDOUT)
-        else:
-            self.emit(SIGNAL('reset_statusbar()'))
-        self.emit(SIGNAL('opened_files_list_changed()'))
-        
-        # Index history management
-        id_list = [id(self.tabs.widget(_i))
-                   for _i in range(self.tabs.count())]
-        for _id in self.stack_history[:]:
-            if _id not in id_list:
-                self.stack_history.pop(self.stack_history.index(_id))
-        current_id = id(self.tabs.widget(index))
-        while current_id in self.stack_history:
-            self.stack_history.pop(self.stack_history.index(current_id))
-        self.stack_history.append(current_id)
-        if DEBUG_EDITOR:
-            print("current_changed:", index, self.data[index].editor, end=' ', file=STDOUT)
-            print(self.data[index].editor.get_document_id(), file=STDOUT)
-            
-        self.emit(SIGNAL('update_plugin_title()'))
-        if editor is not None:
-            self.emit(SIGNAL('current_file_changed(QString,int)'),
-                      self.data[index].filename, editor.get_position('cursor'))
-        
-    def _get_previous_file_index(self):
-        if len(self.stack_history) > 1:
-            last = len(self.stack_history)-1
-            w_id = self.stack_history.pop(last)
-            self.stack_history.insert(0, w_id)
-            last_id = self.stack_history[last]
-            for _i in range(self.tabs.count()):
-                if id(self.tabs.widget(_i)) == last_id:
-                    return _i
-        
-    def go_to_previous_file(self):
-        """Ctrl+Tab"""
-        prev_index = self._get_previous_file_index()
-        if prev_index is not None:
-            self.set_stack_index(prev_index)
-        elif len(self.stack_history) == 0 and self.get_stack_count():
-            self.stack_history = [id(self.tabs.currentWidget())]
-    
-    def go_to_next_file(self):
-        """Ctrl+Shift+Tab"""
-        if len(self.stack_history) > 1:
-            last = len(self.stack_history)-1
-            w_id = self.stack_history.pop(0)
-            self.stack_history.append(w_id)
-            last_id = self.stack_history[last]
-            for _i in range(self.tabs.count()):
-                if id(self.tabs.widget(_i)) == last_id:
-                    self.set_stack_index(_i)
-                    break
-        elif len(self.stack_history) == 0 and self.get_stack_count():
-            self.stack_history = [id(self.tabs.currentWidget())]
-    
-    def focus_changed(self):
-        """Editor focus has changed"""
-        fwidget = QApplication.focusWidget()
-        for finfo in self.data:
-            if fwidget is finfo.editor:
-                self.refresh()
-        self.emit(SIGNAL("editor_focus_changed()"))
-        
-    def _refresh_outlineexplorer(self, index=None, update=True, clear=False):
-        """Refresh outline explorer panel"""
-        oe = self.outlineexplorer
-        if oe is None:
-            return
-        if index is None:
-            index = self.get_stack_index()
-        enable = False
-        if self.data:
-            finfo = self.data[index]
-            if finfo.editor.is_python():
-                enable = True
-                oe.setEnabled(True)
-                oe.set_current_editor(finfo.editor, finfo.filename,
-                                      update=update, clear=clear)
-        if not enable:
-            oe.setEnabled(False)
-            
-    def __refresh_statusbar(self, index):
-        """Refreshing statusbar widgets"""
-        finfo = self.data[index]
-        self.emit(SIGNAL('encoding_changed(QString)'), finfo.encoding)
-        # Refresh cursor position status:
-        line, index = finfo.editor.get_cursor_line_column()
-        self.emit(SIGNAL('editor_cursor_position_changed(int,int)'),
-                  line, index)
-        
-    def __refresh_readonly(self, index):
-        finfo = self.data[index]
-        read_only = not QFileInfo(finfo.filename).isWritable()
-        if not osp.isfile(finfo.filename):
-            # This is an 'untitledX.py' file (newly created)
-            read_only = False
-        finfo.editor.setReadOnly(read_only)
-        self.emit(SIGNAL('readonly_changed(bool)'), read_only)
-        
-    def __check_file_status(self, index):
-        """Check if file has been changed in any way outside Spyder:
-        1. removed, moved or renamed outside Spyder
-        2. modified outside Spyder"""
-        if self.__file_status_flag:
-            # Avoid infinite loop: when the QMessageBox.question pops, it
-            # gets focus and then give it back to the CodeEditor instance,
-            # triggering a refresh cycle which calls this method
-            return
-        self.__file_status_flag = True
-
-        finfo = self.data[index]
-        name = osp.basename(finfo.filename)        
-
-        if finfo.newly_created:
-            # File was just created (not yet saved): do nothing
-            # (do not return because of the clean-up at the end of the method)
-            pass
-
-        elif not osp.isfile(finfo.filename):
-            # File doesn't exist (removed, moved or offline):
-            answer = QMessageBox.warning(self, self.title,
-                                _("<b>%s</b> is unavailable "
-                                  "(this file may have been removed, moved "
-                                  "or renamed outside Spyder)."
-                                  "<br>Do you want to close it?") % name,
-                                QMessageBox.Yes | QMessageBox.No)
-            if answer == QMessageBox.Yes:
-                self.close_file(index)
-            else:
-                finfo.newly_created = True
-                finfo.editor.document().setModified(True)
-                self.modification_changed(index=index)
-
-        else:
-            # Else, testing if it has been modified elsewhere:
-            lastm = QFileInfo(finfo.filename).lastModified()
-            if to_text_string(lastm.toString()) \
-               != to_text_string(finfo.lastmodified.toString()):
-                if finfo.editor.document().isModified():
-                    answer = QMessageBox.question(self,
-                                self.title,
-                                _("<b>%s</b> has been modified outside Spyder."
-                                  "<br>Do you want to reload it and lose all "
-                                  "your changes?") % name,
-                                QMessageBox.Yes | QMessageBox.No)
-                    if answer == QMessageBox.Yes:
-                        self.reload(index)
-                    else:
-                        finfo.lastmodified = lastm
-                else:
-                    self.reload(index)
-
-        # Finally, resetting temporary flag:
-        self.__file_status_flag = False
-        
-    def refresh(self, index=None):
-        """Refresh tabwidget"""
-        if index is None:
-            index = self.get_stack_index()
-        # Set current editor
-        if self.get_stack_count():
-            index = self.get_stack_index()
-            finfo = self.data[index]
-            editor = finfo.editor
-            editor.setFocus()
-            self._refresh_outlineexplorer(index, update=False)
-            self.emit(SIGNAL('update_code_analysis_actions()'))
-            self.__refresh_statusbar(index)
-            self.__refresh_readonly(index)
-            self.__check_file_status(index)
-            self.emit(SIGNAL('update_plugin_title()'))
-        else:
-            editor = None
-        # Update the modification-state-dependent parameters
-        self.modification_changed()
-        # Update FindReplace binding
-        self.find_widget.set_editor(editor, refresh=False)
-                
-    def modification_changed(self, state=None, index=None, editor_id=None):
-        """
-        Current editor's modification state has changed
-        --> change tab title depending on new modification state
-        --> enable/disable save/save all actions
-        """
-        if editor_id is not None:
-            for index, _finfo in enumerate(self.data):
-                if id(_finfo.editor) == editor_id:
-                    break
-        # This must be done before refreshing save/save all actions:
-        # (otherwise Save/Save all actions will always be enabled)
-        self.emit(SIGNAL('opened_files_list_changed()'))
-        # --
-        if index is None:
-            index = self.get_stack_index()
-        if index == -1:
-            return
-        finfo = self.data[index]
-        if state is None:
-            state = finfo.editor.document().isModified()
-        self.set_stack_title(index, state)
-        # Toggle save/save all actions state
-        self.save_action.setEnabled(state)
-        self.emit(SIGNAL('refresh_save_all_action()'))
-        # Refreshing eol mode
-        eol_chars = finfo.editor.get_line_separator()
-        os_name = sourcecode.get_os_name_from_eol_chars(eol_chars)
-        self.emit(SIGNAL('refresh_eol_chars(QString)'), os_name)
-        
-
-    #------ Load, reload
-    def reload(self, index):
-        """Reload file from disk"""
-        finfo = self.data[index]
-        txt, finfo.encoding = encoding.read(finfo.filename)
-        finfo.lastmodified = QFileInfo(finfo.filename).lastModified()
-        position = finfo.editor.get_position('cursor')
-        finfo.editor.set_text(txt)
-        finfo.editor.document().setModified(False)
-        finfo.editor.set_cursor_position(position)
-        self.introspector.validate()
-
-        #XXX CodeEditor-only: re-scan the whole text to rebuild outline 
-        # explorer data from scratch (could be optimized because 
-        # rehighlighting text means searching for all syntax coloring 
-        # patterns instead of only searching for class/def patterns which 
-        # would be sufficient for outline explorer data.
-        finfo.editor.rehighlight()
-
-        self._refresh_outlineexplorer(index)
-        
-    def revert(self):
-        """Revert file from disk"""
-        index = self.get_stack_index()
-        finfo = self.data[index]
-        filename = finfo.filename
-        if finfo.editor.document().isModified():
-            answer = QMessageBox.warning(self, self.title,
-                                _("All changes to <b>%s</b> will be lost."
-                                  "<br>Do you want to revert file from disk?"
-                                  ) % osp.basename(filename),
-                                  QMessageBox.Yes|QMessageBox.No)
-            if answer != QMessageBox.Yes:
-                return
-        self.reload(index)
-        
-    def create_new_editor(self, fname, enc, txt, set_current, new=False,
-                          cloned_from=None):
-        """
-        Create a new editor instance
-        Returns finfo object (instead of editor as in previous releases)
-        """
-        editor = codeeditor.CodeEditor(self)
-        introspector = self.introspector
-        self.connect(editor, SIGNAL("get_completions(bool)"),
-                     introspector.get_completions)
-        self.connect(editor, SIGNAL("show_object_info(int)"),
-                     introspector.show_object_info)
-        self.connect(editor, SIGNAL("go_to_definition(int)"),
-                     introspector.go_to_definition)
-
-        finfo = FileInfo(fname, enc, editor, new, self.threadmanager,
-                         self.introspector)
-        self.add_to_data(finfo, set_current)
-        self.connect(finfo, SIGNAL(
-                    "send_to_inspector(QString,QString,QString,QString,bool)"),
-                    self.send_to_inspector)
-        self.connect(finfo, SIGNAL('analysis_results_changed()'),
-                     lambda: self.emit(SIGNAL('analysis_results_changed()')))
-        self.connect(finfo, SIGNAL('todo_results_changed()'),
-                     lambda: self.emit(SIGNAL('todo_results_changed()')))
-        self.connect(finfo, SIGNAL("edit_goto(QString,int,QString)"),
-                     lambda fname, lineno, name:
-                     self.emit(SIGNAL("edit_goto(QString,int,QString)"),
-                               fname, lineno, name))
-        self.connect(finfo, SIGNAL("save_breakpoints(QString,QString)"),
-                     lambda s1, s2:
-                     self.emit(SIGNAL("save_breakpoints(QString,QString)"),
-                               s1, s2))
-        self.connect(editor, SIGNAL("run_selection()"), self.run_selection)
-        self.connect(editor, SIGNAL("run_cell()"), self.run_cell)
-        self.connect(editor, SIGNAL('run_cell_and_advance()'),
-                     self.run_cell_and_advance)
-        editor.sig_new_file.connect(lambda s: self.parent().plugin.new(text=s))
-        language = get_file_language(fname, txt)
-        editor.setup_editor(
-                linenumbers=self.linenumbers_enabled,
-                show_blanks=self.blanks_enabled,
-                edge_line=self.edgeline_enabled,
-                edge_line_column=self.edgeline_column, language=language,
-                markers=self.has_markers(), font=self.default_font,
-                color_scheme=self.color_scheme,
-                wrap=self.wrap_enabled, tab_mode=self.tabmode_enabled,
-                intelligent_backspace=self.intelligent_backspace_enabled,
-                highlight_current_line=self.highlight_current_line_enabled,
-                highlight_current_cell=self.highlight_current_cell_enabled,
-                occurence_highlighting=self.occurence_highlighting_enabled,
-                occurence_timeout=self.occurence_highlighting_timeout,
-                codecompletion_auto=self.codecompletion_auto_enabled,
-                codecompletion_case=self.codecompletion_case_enabled,
-                codecompletion_enter=self.codecompletion_enter_enabled,
-                calltips=self.calltips_enabled,
-                go_to_definition=self.go_to_definition_enabled,
-                close_parentheses=self.close_parentheses_enabled,
-                close_quotes=self.close_quotes_enabled,
-                add_colons=self.add_colons_enabled,
-                auto_unindent=self.auto_unindent_enabled,
-                indent_chars=self.indent_chars,
-                tab_stop_width=self.tab_stop_width,
-                cloned_from=cloned_from)
-        if cloned_from is None:
-            editor.set_text(txt)
-            editor.document().setModified(False)
-        self.connect(finfo, SIGNAL('text_changed_at(QString,int)'),
-                     lambda fname, position:
-                     self.emit(SIGNAL('text_changed_at(QString,int)'),
-                               fname, position))
-        self.connect(editor, SIGNAL('cursorPositionChanged(int,int)'),
-                     self.editor_cursor_position_changed)
-        self.connect(editor, SIGNAL('textChanged()'),
-                     self.start_stop_analysis_timer)
-        self.connect(editor, SIGNAL('modificationChanged(bool)'),
-                     lambda state: self.modification_changed(state,
-                                                    editor_id=id(editor)))
-        self.connect(editor, SIGNAL("focus_in()"), self.focus_changed)
-        self.connect(editor, SIGNAL('zoom_in()'),
-                     lambda: self.emit(SIGNAL('zoom_in()')))
-        self.connect(editor, SIGNAL('zoom_out()'),
-                     lambda: self.emit(SIGNAL('zoom_out()')))
-        self.connect(editor, SIGNAL('zoom_reset()'),
-                     lambda: self.emit(SIGNAL('zoom_reset()')))
-        if self.outlineexplorer is not None:
-            # Removing editor reference from outline explorer settings:
-            self.connect(editor, SIGNAL("destroyed()"),
-                         lambda obj=editor:
-                         self.outlineexplorer.remove_editor(obj))
-
-        self.find_widget.set_editor(editor)
-       
-        self.emit(SIGNAL('refresh_file_dependent_actions()'))
-        self.modification_changed(index=self.data.index(finfo))
-        
-        return finfo
-    
-    def editor_cursor_position_changed(self, line, index):
-        """Cursor position of one of the editor in the stack has changed"""
-        self.emit(SIGNAL('editor_cursor_position_changed(int,int)'),
-                  line, index)
-    
-    def send_to_inspector(self, qstr1, qstr2=None, qstr3=None,
-                          qstr4=None, force=False):
-        """qstr1: obj_text, qstr2: argpspec, qstr3: note, qstr4: doc_text"""
-        if not force and not self.inspector_enabled:
-            return
-        if self.inspector is not None \
-           and (force or self.inspector.dockwidget.isVisible()):
-            # ObjectInspector widget exists and is visible
-            if qstr4 is None:
-                self.inspector.set_object_text(qstr1, ignore_unknown=True,
-                                               force_refresh=force)
-            else:
-                objtxt = to_text_string(qstr1)
-                name = objtxt.split('.')[-1]
-                argspec = to_text_string(qstr2)
-                note = to_text_string(qstr3)
-                docstring = to_text_string(qstr4)
-                doc = {'obj_text': objtxt, 'name': name, 'argspec': argspec,
-                       'note': note, 'docstring': docstring}
-                self.inspector.set_editor_doc(doc, force_refresh=force)
-            editor = self.get_current_editor()
-            editor.setFocus()
-
-    def new(self, filename, encoding, text, default_content=False):
-        """
-        Create new filename with *encoding* and *text*
-        """
-        finfo = self.create_new_editor(filename, encoding, text,
-                                       set_current=False, new=True)
-        finfo.editor.set_cursor_position('eof')
-        finfo.editor.insert_text(os.linesep)
-        if default_content:
-            finfo.default = True
-            finfo.editor.document().setModified(False)
-        return finfo
-
-    def load(self, filename, set_current=True):
-        """
-        Load filename, create an editor instance and return it
-        *Warning* This is loading file, creating editor but not executing
-        the source code analysis -- the analysis must be done by the editor
-        plugin (in case multiple editorstack instances are handled)
-        """
-        filename = osp.abspath(to_text_string(filename))
-        self.emit(SIGNAL('starting_long_process(QString)'),
-                  _("Loading %s...") % filename)
-        text, enc = encoding.read(filename)
-        finfo = self.create_new_editor(filename, enc, text, set_current)
-        index = self.data.index(finfo)
-        self._refresh_outlineexplorer(index, update=True)
-        self.emit(SIGNAL('ending_long_process(QString)'), "")
-        if self.isVisible() and self.checkeolchars_enabled \
-           and sourcecode.has_mixed_eol_chars(text):
-            name = osp.basename(filename)
-            QMessageBox.warning(self, self.title,
-                                _("<b>%s</b> contains mixed end-of-line "
-                                  "characters.<br>Spyder will fix this "
-                                  "automatically.") % name,
-                                QMessageBox.Ok)
-            self.set_os_eol_chars(index)
-        self.is_analysis_done = False
-        return finfo
-    
-    def set_os_eol_chars(self, index=None):
-        if index is None:
-            index = self.get_stack_index()
-        finfo = self.data[index]
-        eol_chars = sourcecode.get_eol_chars_from_os_name(os.name)
-        finfo.editor.set_eol_chars(eol_chars)
-        finfo.editor.document().setModified(True)
-        
-    def remove_trailing_spaces(self, index=None):
-        """Remove trailing spaces"""
-        if index is None:
-            index = self.get_stack_index()
-        finfo = self.data[index]
-        finfo.editor.remove_trailing_spaces()
-        
-    def fix_indentation(self, index=None):
-        """Replace tab characters by spaces"""
-        if index is None:
-            index = self.get_stack_index()
-        finfo = self.data[index]
-        finfo.editor.fix_indentation()
-
-    #------ Run
-    def run_selection(self):
-        """Run selected text or current line in console"""
-        text = self.get_current_editor().get_selection_as_executable_code()
-        if not text:
-            line = self.get_current_editor().get_current_line()
-            text = line.lstrip()
-        self.emit(SIGNAL('exec_in_extconsole(QString,bool)'), text, 
-                         self.focus_to_editor)
-
-    def run_cell(self):
-        """Run current cell"""
-        text = self.get_current_editor().get_cell_as_executable_code()
-        finfo = self.get_current_finfo()
-        if finfo.editor.is_python() and text:
-            self.emit(SIGNAL('exec_in_extconsole(QString,bool)'),
-                      text, self.focus_to_editor)
-
-    def run_cell_and_advance(self):
-        """Run current cell and advance to the next one"""
-        self.run_cell()
-        if self.focus_to_editor:
-            self.get_current_editor().go_to_next_cell()
-        else:
-            term = QApplication.focusWidget()
-            self.get_current_editor().go_to_next_cell()
-            term.setFocus()
-            
-    #------ Drag and drop
-    def dragEnterEvent(self, event):
-        """Reimplement Qt method
-        Inform Qt about the types of data that the widget accepts"""
-        source = event.mimeData()
-        # The second check is necessary on Windows, where source.hasUrls()
-        # can return True but source.urls() is []
-        if source.hasUrls() and source.urls():
-            if mimedata2url(source, extlist=EDIT_EXT):
-                event.acceptProposedAction()
-            else:
-                all_urls = mimedata2url(source)
-                text = [encoding.is_text_file(url) for url in all_urls]
-                if any(text):
-                    event.acceptProposedAction()
-                else:
-                    event.ignore()
-        elif source.hasText():
-            event.acceptProposedAction()
-        elif os.name == 'nt':
-            # This covers cases like dragging from compressed files,
-            # which can be opened by the Editor if they are plain
-            # text, but doesn't come with url info.
-            # Fixes Issue 2032
-            event.acceptProposedAction()
-        else:
-            event.ignore()
-            
-    def dropEvent(self, event):
-        """Reimplement Qt method
-        Unpack dropped data and handle it"""
-        source = event.mimeData()
-        if source.hasUrls():
-            files = mimedata2url(source)
-            files = [f for f in files if encoding.is_text_file(f)]
-            supported_files = mimedata2url(source, extlist=EDIT_EXT)
-            files = set(files or []) | set(supported_files or [])
-            for fname in files:
-                self.emit(SIGNAL('plugin_load(QString)'), fname)
-        elif source.hasText():
-            editor = self.get_current_editor()
-            if editor is not None:
-                editor.insert_text( source.text() )
-        event.acceptProposedAction()
-
-
-class EditorSplitter(QSplitter):
-    def __init__(self, parent, plugin, menu_actions, first=False,
-                 register_editorstack_cb=None, unregister_editorstack_cb=None):
-        QSplitter.__init__(self, parent)
-        self.setAttribute(Qt.WA_DeleteOnClose)
-        self.setChildrenCollapsible(False)
-        
-        self.toolbar_list = None
-        self.menu_list = None
-        
-        self.plugin = plugin
-        
-        if register_editorstack_cb is None:
-            register_editorstack_cb = self.plugin.register_editorstack
-        self.register_editorstack_cb = register_editorstack_cb
-        if unregister_editorstack_cb is None:
-            unregister_editorstack_cb = self.plugin.unregister_editorstack
-        self.unregister_editorstack_cb = unregister_editorstack_cb
-        
-        self.menu_actions = menu_actions
-        self.editorstack = EditorStack(self, menu_actions)
-        self.register_editorstack_cb(self.editorstack)
-        if not first:
-            self.plugin.clone_editorstack(editorstack=self.editorstack)
-        self.connect(self.editorstack, SIGNAL("destroyed()"),
-                     lambda: self.editorstack_closed())
-        self.connect(self.editorstack, SIGNAL("split_vertically()"),
-                     lambda: self.split(orientation=Qt.Vertical))
-        self.connect(self.editorstack, SIGNAL("split_horizontally()"),
-                     lambda: self.split(orientation=Qt.Horizontal))
-        self.addWidget(self.editorstack)
-
-    def closeEvent(self, event):
-        QSplitter.closeEvent(self, event)
-        if is_pyqt46:
-            self.emit(SIGNAL('destroyed()'))
-                                
-    def __give_focus_to_remaining_editor(self):
-        focus_widget = self.plugin.get_focus_widget()
-        if focus_widget is not None:
-            focus_widget.setFocus()
-        
-    def editorstack_closed(self):
-        if DEBUG_EDITOR:
-            print("method 'editorstack_closed':", file=STDOUT)
-            print("    self  :", self, file=STDOUT)
-#            print >>STDOUT, "    sender:", self.sender()
-        self.unregister_editorstack_cb(self.editorstack)
-        self.editorstack = None
-        try:
-            close_splitter = self.count() == 1
-        except RuntimeError:
-            # editorsplitter has been destroyed (happens when closing a
-            # EditorMainWindow instance)
-            return
-        if close_splitter:
-            # editorstack just closed was the last widget in this QSplitter
-            self.close()
-            return
-        self.__give_focus_to_remaining_editor()
-        
-    def editorsplitter_closed(self):
-        if DEBUG_EDITOR:
-            print("method 'editorsplitter_closed':", file=STDOUT)
-            print("    self  :", self, file=STDOUT)
-#            print >>STDOUT, "    sender:", self.sender()
-        try:
-            close_splitter = self.count() == 1 and self.editorstack is None
-        except RuntimeError:
-            # editorsplitter has been destroyed (happens when closing a
-            # EditorMainWindow instance)
-            return
-        if close_splitter:
-            # editorsplitter just closed was the last widget in this QSplitter
-            self.close()
-            return
-        elif self.count() == 2 and self.editorstack:
-            # back to the initial state: a single editorstack instance,
-            # as a single widget in this QSplitter: orientation may be changed
-            self.editorstack.reset_orientation()
-        self.__give_focus_to_remaining_editor()
-        
-    def split(self, orientation=Qt.Vertical):
-        self.setOrientation(orientation)
-        self.editorstack.set_orientation(orientation)
-        editorsplitter = EditorSplitter(self.parent(), self.plugin,
-                    self.menu_actions,
-                    register_editorstack_cb=self.register_editorstack_cb,
-                    unregister_editorstack_cb=self.unregister_editorstack_cb)
-        self.addWidget(editorsplitter)
-        self.connect(editorsplitter, SIGNAL("destroyed()"),
-                     lambda: self.editorsplitter_closed())
-        current_editor = editorsplitter.editorstack.get_current_editor()
-        if current_editor is not None:
-            current_editor.setFocus()
-            
-    def iter_editorstacks(self):
-        editorstacks = [(self.widget(0), self.orientation())]
-        if self.count() > 1:
-            editorsplitter = self.widget(1)
-            editorstacks += editorsplitter.iter_editorstacks()
-        return editorstacks
-
-    def get_layout_settings(self):
-        """Return layout state"""
-        splitsettings = []
-        for editorstack, orientation in self.iter_editorstacks():
-            clines = [finfo.editor.get_cursor_line_number()
-                      for finfo in editorstack.data]
-            cfname = editorstack.get_current_filename()
-            splitsettings.append((orientation == Qt.Vertical, cfname, clines))
-        return dict(hexstate=qbytearray_to_str(self.saveState()),
-                    sizes=self.sizes(), splitsettings=splitsettings)
-    
-    def set_layout_settings(self, settings):
-        """Restore layout state"""
-        splitsettings = settings.get('splitsettings')
-        if splitsettings is None:
-            return
-        splitter = self
-        editor = None
-        for index, (is_vertical, cfname, clines) in enumerate(splitsettings):
-            if index > 0:
-                splitter.split(Qt.Vertical if is_vertical else Qt.Horizontal)
-                splitter = splitter.widget(1)
-            editorstack = splitter.widget(0)
-            for index, finfo in enumerate(editorstack.data):
-                editor = finfo.editor
-                editor.go_to_line(clines[index])
-            editorstack.set_current_filename(cfname)
-        hexstate = settings.get('hexstate')
-        if hexstate is not None:
-            self.restoreState( QByteArray().fromHex(str(hexstate)) )
-        sizes = settings.get('sizes')
-        if sizes is not None:
-            self.setSizes(sizes)
-        if editor is not None:
-            editor.clearFocus()
-            editor.setFocus()
-
-
-class EditorWidget(QSplitter):
-    def __init__(self, parent, plugin, menu_actions, show_fullpath,
-                 fullpath_sorting, show_all_files, show_comments):
-        QSplitter.__init__(self, parent)
-        self.setAttribute(Qt.WA_DeleteOnClose)
-        
-        statusbar = parent.statusBar() # Create a status bar
-        self.readwrite_status = ReadWriteStatus(self, statusbar)
-        self.eol_status = EOLStatus(self, statusbar)
-        self.encoding_status = EncodingStatus(self, statusbar)
-        self.cursorpos_status = CursorPositionStatus(self, statusbar)
-        
-        self.editorstacks = []
-        
-        self.plugin = plugin
-        
-        self.find_widget = FindReplace(self, enable_replace=True)
-        self.plugin.register_widget_shortcuts("Editor", self.find_widget)
-        self.find_widget.hide()
-        self.outlineexplorer = OutlineExplorerWidget(self,
-                                            show_fullpath=show_fullpath,
-                                            fullpath_sorting=fullpath_sorting,
-                                            show_all_files=show_all_files,
-                                            show_comments=show_comments)
-        self.connect(self.outlineexplorer,
-                     SIGNAL("edit_goto(QString,int,QString)"),
-                     lambda filenames, goto, word:
-                     plugin.load(filenames=filenames, goto=goto, word=word,
-                                 editorwindow=self.parent()))
-        
-        editor_widgets = QWidget(self)
-        editor_layout = QVBoxLayout()
-        editor_layout.setContentsMargins(0, 0, 0, 0)
-        editor_widgets.setLayout(editor_layout)
-        editorsplitter = EditorSplitter(self, plugin, menu_actions,
-                        register_editorstack_cb=self.register_editorstack,
-                        unregister_editorstack_cb=self.unregister_editorstack)
-        self.editorsplitter = editorsplitter
-        editor_layout.addWidget(editorsplitter)
-        editor_layout.addWidget(self.find_widget)
-        
-        splitter = QSplitter(self)
-        splitter.setContentsMargins(0, 0, 0, 0)
-        splitter.addWidget(editor_widgets)
-        splitter.addWidget(self.outlineexplorer)
-        splitter.setStretchFactor(0, 5)
-        splitter.setStretchFactor(1, 1)
-
-        # Refreshing outline explorer
-        editorsplitter.editorstack.initialize_outlineexplorer()
-        
-    def register_editorstack(self, editorstack):
-        self.editorstacks.append(editorstack)
-        if DEBUG_EDITOR:
-            print("EditorWidget.register_editorstack:", editorstack, file=STDOUT)
-            self.__print_editorstacks()
-        self.plugin.last_focus_editorstack[self.parent()] = editorstack
-        editorstack.set_closable( len(self.editorstacks) > 1 )
-        editorstack.set_outlineexplorer(self.outlineexplorer)
-        editorstack.set_find_widget(self.find_widget)
-        self.connect(editorstack, SIGNAL('reset_statusbar()'),
-                     self.readwrite_status.hide)
-        self.connect(editorstack, SIGNAL('reset_statusbar()'),
-                     self.encoding_status.hide)
-        self.connect(editorstack, SIGNAL('reset_statusbar()'),
-                     self.cursorpos_status.hide)
-        self.connect(editorstack, SIGNAL('readonly_changed(bool)'),
-                     self.readwrite_status.readonly_changed)
-        self.connect(editorstack, SIGNAL('encoding_changed(QString)'),
-                     self.encoding_status.encoding_changed)
-        self.connect(editorstack,
-                     SIGNAL('editor_cursor_position_changed(int,int)'),
-                     self.cursorpos_status.cursor_position_changed)
-        self.connect(editorstack, SIGNAL('refresh_eol_chars(QString)'),
-                     self.eol_status.eol_changed)
-        self.plugin.register_editorstack(editorstack)
-        oe_btn = create_toolbutton(self)
-        oe_btn.setDefaultAction(self.outlineexplorer.visibility_action)
-        editorstack.add_corner_widgets_to_tabbar([5, oe_btn])
-        
-    def __print_editorstacks(self):
-        print("%d editorstack(s) in editorwidget:" \
-                        % len(self.editorstacks), file=STDOUT)
-        for edst in self.editorstacks:
-            print("    ", edst, file=STDOUT)
-        
-    def unregister_editorstack(self, editorstack):
-        if DEBUG_EDITOR:
-            print("EditorWidget.unregister_editorstack:", editorstack, file=STDOUT)
-        self.plugin.unregister_editorstack(editorstack)
-        self.editorstacks.pop(self.editorstacks.index(editorstack))
-        if DEBUG_EDITOR:
-            self.__print_editorstacks()
-        
-
-class EditorMainWindow(QMainWindow):
-    def __init__(self, plugin, menu_actions, toolbar_list, menu_list,
-                 show_fullpath, fullpath_sorting, show_all_files,
-                 show_comments):
-        QMainWindow.__init__(self)
-        self.setAttribute(Qt.WA_DeleteOnClose)
-
-        self.window_size = None
-        
-        self.editorwidget = EditorWidget(self, plugin, menu_actions,
-                                         show_fullpath, fullpath_sorting,
-                                         show_all_files, show_comments)
-        self.setCentralWidget(self.editorwidget)
-
-        # Give focus to current editor to update/show all status bar widgets
-        editorstack = self.editorwidget.editorsplitter.editorstack
-        editor = editorstack.get_current_editor()
-        if editor is not None:
-            editor.setFocus()
-        
-        self.setWindowTitle("Spyder - %s" % plugin.windowTitle())
-        self.setWindowIcon(plugin.windowIcon())
-        
-        if toolbar_list:
-            toolbars = []
-            for title, actions in toolbar_list:
-                toolbar = self.addToolBar(title)
-                toolbar.setObjectName(str(id(toolbar)))
-                add_actions(toolbar, actions)
-                toolbars.append(toolbar)
-        if menu_list:
-            quit_action = create_action(self, _("Close window"),
-                                        icon="close_panel.png",
-                                        tip=_("Close this window"),
-                                        triggered=self.close)
-            menus = []
-            for index, (title, actions) in enumerate(menu_list):
-                menu = self.menuBar().addMenu(title)
-                if index == 0:
-                    # File menu
-                    add_actions(menu, actions+[None, quit_action])
-                else:
-                    add_actions(menu, actions)
-                menus.append(menu)
-            
-    def resizeEvent(self, event):
-        """Reimplement Qt method"""
-        if not self.isMaximized() and not self.isFullScreen():
-            self.window_size = self.size()
-        QMainWindow.resizeEvent(self, event)
-                
-    def closeEvent(self, event):
-        """Reimplement Qt method"""
-        QMainWindow.closeEvent(self, event)
-        if is_pyqt46:
-            self.emit(SIGNAL('destroyed()'))
-            for editorstack in self.editorwidget.editorstacks[:]:
-                if DEBUG_EDITOR:
-                    print("--> destroy_editorstack:", editorstack, file=STDOUT)
-                editorstack.emit(SIGNAL('destroyed()'))
-                                
-    def get_layout_settings(self):
-        """Return layout state"""
-        splitsettings = self.editorwidget.editorsplitter.get_layout_settings()
-        return dict(size=(self.window_size.width(), self.window_size.height()),
-                    pos=(self.pos().x(), self.pos().y()),
-                    is_maximized=self.isMaximized(),
-                    is_fullscreen=self.isFullScreen(),
-                    hexstate=qbytearray_to_str(self.saveState()),
-                    splitsettings=splitsettings)
-    
-    def set_layout_settings(self, settings):
-        """Restore layout state"""
-        size = settings.get('size')
-        if size is not None:
-            self.resize( QSize(*size) )
-            self.window_size = self.size()
-        pos = settings.get('pos')
-        if pos is not None:
-            self.move( QPoint(*pos) )
-        hexstate = settings.get('hexstate')
-        if hexstate is not None:
-            self.restoreState( QByteArray().fromHex(str(hexstate)) )
-        if settings.get('is_maximized'):
-            self.setWindowState(Qt.WindowMaximized)
-        if settings.get('is_fullscreen'):
-            self.setWindowState(Qt.WindowFullScreen)
-        splitsettings = settings.get('splitsettings')
-        if splitsettings is not None:
-            self.editorwidget.editorsplitter.set_layout_settings(splitsettings)
-
-
-class EditorPluginExample(QSplitter):
-    def __init__(self):
-        QSplitter.__init__(self)
-                
-        menu_actions = []
-                
-        self.editorstacks = []
-        self.editorwindows = []
-        
-        self.last_focus_editorstack = {} # fake
-
-        self.find_widget = FindReplace(self, enable_replace=True)
-        self.outlineexplorer = OutlineExplorerWidget(self, show_fullpath=False,
-                                                     show_all_files=False)
-        self.connect(self.outlineexplorer,
-                     SIGNAL("edit_goto(QString,int,QString)"),
-                     self.go_to_file)
-        
-        editor_widgets = QWidget(self)
-        editor_layout = QVBoxLayout()
-        editor_layout.setContentsMargins(0, 0, 0, 0)
-        editor_widgets.setLayout(editor_layout)
-        editor_layout.addWidget(EditorSplitter(self, self, menu_actions,
-                                               first=True))
-        editor_layout.addWidget(self.find_widget)
-        
-        self.setContentsMargins(0, 0, 0, 0)
-        self.addWidget(editor_widgets)
-        self.addWidget(self.outlineexplorer)
-        
-        self.setStretchFactor(0, 5)
-        self.setStretchFactor(1, 1)
-        
-        self.menu_actions = menu_actions
-        self.toolbar_list = None
-        self.menu_list = None
-        self.setup_window([], [])
-        
-    def go_to_file(self, fname, lineno, text):
-        editorstack = self.editorstacks[0]
-        editorstack.set_current_filename(to_text_string(fname))
-        editor = editorstack.get_current_editor()
-        editor.go_to_line(lineno, word=text)
-
-    def closeEvent(self, event):
-        for win in self.editorwindows[:]:
-            win.close()
-        if DEBUG_EDITOR:
-            print(len(self.editorwindows), ":", self.editorwindows, file=STDOUT)
-            print(len(self.editorstacks), ":", self.editorstacks, file=STDOUT)
-        
-        event.accept()
-        
-    def load(self, fname):
-        QApplication.processEvents()
-        editorstack = self.editorstacks[0]
-        editorstack.load(fname)
-        editorstack.analyze_script()
-    
-    def register_editorstack(self, editorstack):
-        if DEBUG_EDITOR:
-            print("FakePlugin.register_editorstack:", editorstack, file=STDOUT)
-        self.editorstacks.append(editorstack)
-        if self.isAncestorOf(editorstack):
-            # editorstack is a child of the Editor plugin
-            editorstack.set_fullpath_sorting_enabled(True)
-            editorstack.set_closable( len(self.editorstacks) > 1 )
-            editorstack.set_outlineexplorer(self.outlineexplorer)
-            editorstack.set_find_widget(self.find_widget)
-            oe_btn = create_toolbutton(self)
-            oe_btn.setDefaultAction(self.outlineexplorer.visibility_action)
-            editorstack.add_corner_widgets_to_tabbar([5, oe_btn])
-            
-        action = QAction(self)
-        editorstack.set_io_actions(action, action, action, action)
-        font = QFont("Courier New")
-        font.setPointSize(10)
-        editorstack.set_default_font(font, color_scheme='Spyder')
-
-        self.connect(editorstack, SIGNAL('close_file(QString,int)'),
-                     self.close_file_in_all_editorstacks)
-        self.connect(editorstack, SIGNAL('file_saved(QString,int,QString)'),
-                     self.file_saved_in_editorstack)
-        self.connect(editorstack,
-                     SIGNAL('file_renamed_in_data(QString,int,QString)'),
-                     self.file_renamed_in_data_in_editorstack)
-
-        self.connect(editorstack, SIGNAL("create_new_window()"),
-                     self.create_new_window)
-        self.connect(editorstack, SIGNAL('plugin_load(QString)'),
-                     self.load)
-                    
-    def unregister_editorstack(self, editorstack):
-        if DEBUG_EDITOR:
-            print("FakePlugin.unregister_editorstack:", editorstack, file=STDOUT)
-        self.editorstacks.pop(self.editorstacks.index(editorstack))
-        
-    def clone_editorstack(self, editorstack):
-        editorstack.clone_from(self.editorstacks[0])
-        
-    def setup_window(self, toolbar_list, menu_list):
-        self.toolbar_list = toolbar_list
-        self.menu_list = menu_list
-        
-    def create_new_window(self):
-        window = EditorMainWindow(self, self.menu_actions,
-                                  self.toolbar_list, self.menu_list,
-                                  show_fullpath=False, fullpath_sorting=True,
-                                  show_all_files=False, show_comments=True)
-        window.resize(self.size())
-        window.show()
-        self.register_editorwindow(window)
-        self.connect(window, SIGNAL("destroyed()"),
-                     lambda win=window: self.unregister_editorwindow(win))
-        
-    def register_editorwindow(self, window):
-        if DEBUG_EDITOR:
-            print("register_editorwindowQObject*:", window, file=STDOUT)
-        self.editorwindows.append(window)
-        
-    def unregister_editorwindow(self, window):
-        if DEBUG_EDITOR:
-            print("unregister_editorwindow:", window, file=STDOUT)
-        self.editorwindows.pop(self.editorwindows.index(window))
-    
-    def get_focus_widget(self):
-        pass
-
-    @Slot(int, int)
-    def close_file_in_all_editorstacks(self, editorstack_id_str, index):
-        for editorstack in self.editorstacks:
-            if str(id(editorstack)) != editorstack_id_str:
-                editorstack.blockSignals(True)
-                editorstack.close_file(index, force=True)
-                editorstack.blockSignals(False)
-
-    # This method is never called in this plugin example. It's here only 
-    # to show how to use the file_saved signal (see above).
-    @Slot(int, int)
-    def file_saved_in_editorstack(self, editorstack_id_str, index, filename):
-        """A file was saved in editorstack, this notifies others"""
-        for editorstack in self.editorstacks:
-            if str(id(editorstack)) != editorstack_id_str:
-                editorstack.file_saved_in_other_editorstack(index, filename)
-
-    # This method is never called in this plugin example. It's here only 
-    # to show how to use the file_saved signal (see above).
-    @Slot(int, int)
-    def file_renamed_in_data_in_editorstack(self, editorstack_id_str,
-                                            index, filename):
-        """A file was renamed in data in editorstack, this notifies others"""
-        for editorstack in self.editorstacks:
-            if str(id(editorstack)) != editorstack_id_str:
-                editorstack.rename_in_data(index, filename)
-
-    def register_widget_shortcuts(self, context, widget):
-        """Fake!"""
-        pass
-    
-def test():
-    from spyderlib.utils.qthelpers import qapplication
-    app = qapplication()
-    test = EditorPluginExample()
-    test.resize(900, 700)
-    test.show()
-    import time
-    t0 = time.time()
-    test.load(__file__)
-    test.load("explorer.py")
-    test.load("dicteditor.py")
-    test.load("sourcecode/codeeditor.py")
-    test.load("../spyder.py")
-    print("Elapsed time: %.3f s" % (time.time()-t0))
-    sys.exit(app.exec_())
-    
-if __name__ == "__main__":
-    test()
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2009- The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+"""Editor Widget"""
+
+# pylint: disable=C0103
+# pylint: disable=R0903
+# pylint: disable=R0911
+# pylint: disable=R0201
+
+from __future__ import print_function
+
+from spyderlib.qt import is_pyqt46
+from spyderlib.qt.QtGui import (QVBoxLayout, QMessageBox, QMenu, QFont,
+                                QAction, QApplication, QWidget,
+                                QKeySequence, QMainWindow, QSplitter,
+                                QHBoxLayout)
+from spyderlib.qt.QtCore import (Signal, Qt, QFileInfo, QThread, QObject,
+                                 QByteArray, QSize, QPoint, QTimer, Slot)
+from spyderlib.qt.compat import getsavefilename
+import spyderlib.utils.icon_manager as ima
+
+import os
+import sys
+import os.path as osp
+
+# Local imports
+from spyderlib.utils import encoding, sourcecode, codeanalysis
+from spyderlib.utils import introspection
+from spyderlib.config.base import _, DEBUG, STDOUT, STDERR
+from spyderlib.config.main import EDIT_FILTERS, EDIT_EXT, get_filter, EDIT_FILETYPES
+from spyderlib.config.gui import create_shortcut, new_shortcut
+from spyderlib.utils.qthelpers import (create_action, add_actions,
+                                       mimedata2url, get_filetype_icon,
+                                       create_toolbutton)
+from spyderlib.utils import syntaxhighlighters
+from spyderlib.widgets.tabs import BaseTabs
+from spyderlib.widgets.findreplace import FindReplace
+from spyderlib.widgets.editortools import OutlineExplorerWidget
+from spyderlib.widgets.status import (ReadWriteStatus, EOLStatus,
+                                      EncodingStatus, CursorPositionStatus)
+from spyderlib.widgets.sourcecode import codeeditor
+from spyderlib.widgets.sourcecode.base import TextEditBaseWidget  #analysis:ignore
+from spyderlib.widgets.sourcecode.codeeditor import Printer  #analysis:ignore
+from spyderlib.widgets.sourcecode.codeeditor import get_file_language
+from spyderlib.widgets.fileswitcher import FileSwitcher
+from spyderlib.py3compat import to_text_string, qbytearray_to_str, u
+
+DEBUG_EDITOR = DEBUG >= 3
+
+
+class AnalysisThread(QThread):
+    """Analysis thread"""
+    def __init__(self, parent, checker, source_code):
+        super(AnalysisThread, self).__init__(parent)
+        self.checker = checker
+        self.results = None
+        self.source_code = source_code
+
+    def run(self):
+        """Run analysis"""
+        try:
+            self.results = self.checker(self.source_code)
+        except Exception:
+            if DEBUG_EDITOR:
+                import traceback
+                traceback.print_exc(file=STDERR)
+
+
+class ThreadManager(QObject):
+    """Analysis thread manager"""
+    def __init__(self, parent, max_simultaneous_threads=2):
+        super(ThreadManager, self).__init__(parent)
+        self.max_simultaneous_threads = max_simultaneous_threads
+        self.started_threads = {}
+        self.pending_threads = []
+        self.end_callbacks = {}
+
+    def close_threads(self, parent):
+        """Close threads associated to parent_id"""
+        if DEBUG_EDITOR:
+            print("Call to 'close_threads'", file=STDOUT)
+        if parent is None:
+            # Closing all threads
+            self.pending_threads = []
+            threadlist = []
+            for threads in list(self.started_threads.values()):
+                threadlist += threads
+        else:
+            parent_id = id(parent)
+            self.pending_threads = [(_th, _id) for (_th, _id)
+                                    in self.pending_threads
+                                    if _id != parent_id]
+            threadlist = self.started_threads.get(parent_id, [])
+        for thread in threadlist:
+            if DEBUG_EDITOR:
+                print("Waiting for thread %r to finish" % thread, file=STDOUT)
+            while thread.isRunning():
+                # We can't terminate thread safely, so we simply wait...
+                QApplication.processEvents()
+
+    def close_all_threads(self):
+        """Close all threads"""
+        if DEBUG_EDITOR:
+            print("Call to 'close_all_threads'", file=STDOUT)
+        self.close_threads(None)
+
+    def add_thread(self, checker, end_callback, source_code, parent):
+        """Add thread to queue"""
+        parent_id = id(parent)
+        thread = AnalysisThread(self, checker, source_code)
+        self.end_callbacks[id(thread)] = end_callback
+        self.pending_threads.append((thread, parent_id))
+        if DEBUG_EDITOR:
+            print("Added thread %r to queue" % thread, file=STDOUT)
+        QTimer.singleShot(50, self.update_queue)
+
+    def update_queue(self):
+        """Update queue"""
+        started = 0
+        for parent_id, threadlist in list(self.started_threads.items()):
+            still_running = []
+            for thread in threadlist:
+                if thread.isFinished():
+                    end_callback = self.end_callbacks.pop(id(thread))
+                    if thread.results is not None:
+                        #  The thread was executed successfully
+                        end_callback(thread.results)
+                    thread.setParent(None)
+                    thread = None
+                else:
+                    still_running.append(thread)
+                    started += 1
+            threadlist = None
+            if still_running:
+                self.started_threads[parent_id] = still_running
+            else:
+                self.started_threads.pop(parent_id)
+        if DEBUG_EDITOR:
+            print("Updating queue:", file=STDOUT)
+            print("    started:", started, file=STDOUT)
+            print("    pending:", len(self.pending_threads), file=STDOUT)
+        if self.pending_threads and started < self.max_simultaneous_threads:
+            thread, parent_id = self.pending_threads.pop(0)
+            thread.finished.connect(self.update_queue)
+            threadlist = self.started_threads.get(parent_id, [])
+            self.started_threads[parent_id] = threadlist+[thread]
+            if DEBUG_EDITOR:
+                print("===>starting:", thread, file=STDOUT)
+            thread.start()
+
+
+class FileInfo(QObject):
+    """File properties"""
+    analysis_results_changed = Signal()
+    todo_results_changed = Signal()
+    save_breakpoints = Signal(str, str)
+    text_changed_at = Signal(str, int)
+    edit_goto = Signal(str, int, str)
+    send_to_inspector = Signal(str, str, str, str, bool)
+
+    def __init__(self, filename, encoding, editor, new, threadmanager,
+                 introspection_plugin):
+        QObject.__init__(self)
+        self.threadmanager = threadmanager
+        self.filename = filename
+        self.newly_created = new
+        self.default = False      # Default untitled file
+        self.encoding = encoding
+        self.editor = editor
+        self.path = []
+
+        self.classes = (filename, None, None)
+        self.analysis_results = []
+        self.todo_results = []
+        self.lastmodified = QFileInfo(filename).lastModified()
+
+        self.editor.textChanged.connect(self.text_changed)
+        self.editor.breakpoints_changed.connect(self.breakpoints_changed)
+
+        self.pyflakes_results = None
+        self.pep8_results = None
+
+    def text_changed(self):
+        """Editor's text has changed"""
+        self.default = False
+        self.text_changed_at.emit(self.filename,
+                                  self.editor.get_position('cursor'))
+
+    def get_source_code(self):
+        """Return associated editor source code"""
+        return to_text_string(self.editor.toPlainText())
+
+    def run_code_analysis(self, run_pyflakes, run_pep8):
+        """Run code analysis"""
+        run_pyflakes = run_pyflakes and codeanalysis.is_pyflakes_installed()
+        run_pep8 = run_pep8 and\
+                   codeanalysis.get_checker_executable('pep8') is not None
+        self.pyflakes_results = []
+        self.pep8_results = []
+        if self.editor.is_python():
+            enc = self.encoding.replace('-guessed', '').replace('-bom', '')
+            source_code = self.get_source_code().encode(enc)
+            if run_pyflakes:
+                self.pyflakes_results = None
+            if run_pep8:
+                self.pep8_results = None
+            if run_pyflakes:
+                self.threadmanager.add_thread(codeanalysis.check_with_pyflakes,
+                                              self.pyflakes_analysis_finished,
+                                              source_code, self)
+            if run_pep8:
+                self.threadmanager.add_thread(codeanalysis.check_with_pep8,
+                                              self.pep8_analysis_finished,
+                                              source_code, self)
+
+    def pyflakes_analysis_finished(self, results):
+        """Pyflakes code analysis thread has finished"""
+        self.pyflakes_results = results
+        if self.pep8_results is not None:
+            self.code_analysis_finished()
+
+    def pep8_analysis_finished(self, results):
+        """Pep8 code analysis thread has finished"""
+        self.pep8_results = results
+        if self.pyflakes_results is not None:
+            self.code_analysis_finished()
+
+    def code_analysis_finished(self):
+        """Code analysis thread has finished"""
+        self.set_analysis_results(self.pyflakes_results+self.pep8_results)
+        self.analysis_results_changed.emit()
+
+    def set_analysis_results(self, results):
+        """Set analysis results and update warning markers in editor"""
+        self.analysis_results = results
+        self.editor.process_code_analysis(results)
+
+    def cleanup_analysis_results(self):
+        """Clean-up analysis results"""
+        self.analysis_results = []
+        self.editor.cleanup_code_analysis()
+
+    def run_todo_finder(self):
+        """Run TODO finder"""
+        if self.editor.is_python():
+            self.threadmanager.add_thread(codeanalysis.find_tasks,
+                                          self.todo_finished,
+                                          self.get_source_code(), self)
+
+    def todo_finished(self, results):
+        """Code analysis thread has finished"""
+        self.set_todo_results(results)
+        self.todo_results_changed.emit()
+
+    def set_todo_results(self, results):
+        """Set TODO results and update markers in editor"""
+        self.todo_results = results
+        self.editor.process_todo(results)
+
+    def cleanup_todo_results(self):
+        """Clean-up TODO finder results"""
+        self.todo_results = []
+
+    def breakpoints_changed(self):
+        """Breakpoint list has changed"""
+        breakpoints = self.editor.get_breakpoints()
+        if self.editor.breakpoints != breakpoints:
+            self.editor.breakpoints = breakpoints
+            self.save_breakpoints.emit(self.filename, repr(breakpoints))
+
+
+class EditorStack(QWidget):
+    reset_statusbar = Signal()
+    readonly_changed = Signal(bool)
+    encoding_changed = Signal(str)
+    sig_editor_cursor_position_changed = Signal(int, int)
+    refresh_eol_chars = Signal(str)
+    starting_long_process = Signal(str)
+    ending_long_process = Signal(str)
+    redirect_stdio = Signal(bool)
+    exec_in_extconsole = Signal(str, bool)
+    update_plugin_title = Signal()
+    editor_focus_changed = Signal()
+    zoom_in = Signal()
+    zoom_out = Signal()
+    zoom_reset = Signal()
+    sig_close_file = Signal(str, int)
+    file_saved = Signal(str, int, str)
+    file_renamed_in_data = Signal(str, int, str)
+    create_new_window = Signal()
+    opened_files_list_changed = Signal()
+    analysis_results_changed = Signal()
+    todo_results_changed = Signal()
+    update_code_analysis_actions = Signal()
+    refresh_file_dependent_actions = Signal()
+    refresh_save_all_action = Signal()
+    save_breakpoints = Signal(str, str)
+    text_changed_at = Signal(str, int)
+    current_file_changed = Signal(str ,int)
+    plugin_load = Signal(str)
+    edit_goto = Signal(str, int, str)
+    split_vertically = Signal()
+    split_horizontally = Signal()
+    sig_new_file = Signal((str,), ())
+
+    def __init__(self, parent, actions):
+        QWidget.__init__(self, parent)
+
+        self.setAttribute(Qt.WA_DeleteOnClose)
+
+        self.threadmanager = ThreadManager(self)
+
+        self.newwindow_action = None
+        self.horsplit_action = None
+        self.versplit_action = None
+        self.close_action = None
+        self.__get_split_actions()
+
+        layout = QVBoxLayout()
+        layout.setContentsMargins(0, 0, 0, 0)
+        self.setLayout(layout)
+
+        self.menu = None
+        self.fileswitcher_dlg = None
+#        self.filelist_btn = None
+#        self.previous_btn = None
+#        self.next_btn = None
+        self.tabs = None
+
+        self.stack_history = []
+
+        self.setup_editorstack(parent, layout)
+
+        self.find_widget = None
+
+        self.data = []
+        fileswitcher_action = create_action(self, _("File switcher..."),
+                icon=ima.icon('filelist'),
+                triggered=self.open_fileswitcher_dlg)
+        copy_to_cb_action = create_action(self, _("Copy path to clipboard"),
+                icon=ima.icon('editcopy'),
+                triggered=lambda:
+                QApplication.clipboard().setText(self.get_current_filename()))
+        self.menu_actions = actions + [None, fileswitcher_action,
+                                       copy_to_cb_action]
+        self.outlineexplorer = None
+        self.inspector = None
+        self.unregister_callback = None
+        self.is_closable = False
+        self.new_action = None
+        self.open_action = None
+        self.save_action = None
+        self.revert_action = None
+        self.tempfile_path = None
+        self.title = _("Editor")
+        self.pyflakes_enabled = True
+        self.pep8_enabled = False
+        self.todolist_enabled = True
+        self.realtime_analysis_enabled = False
+        self.is_analysis_done = False
+        self.linenumbers_enabled = True
+        self.blanks_enabled = False
+        self.edgeline_enabled = True
+        self.edgeline_column = 79
+        self.codecompletion_auto_enabled = True
+        self.codecompletion_case_enabled = False
+        self.codecompletion_enter_enabled = False
+        self.calltips_enabled = True
+        self.go_to_definition_enabled = True
+        self.close_parentheses_enabled = True
+        self.close_quotes_enabled = True
+        self.add_colons_enabled = True
+        self.auto_unindent_enabled = True
+        self.indent_chars = " "*4
+        self.tab_stop_width = 40
+        self.inspector_enabled = False
+        self.default_font = None
+        self.wrap_enabled = False
+        self.tabmode_enabled = False
+        self.intelligent_backspace_enabled = True
+        self.highlight_current_line_enabled = False
+        self.highlight_current_cell_enabled = False
+        self.occurence_highlighting_enabled = True
+        self.occurence_highlighting_timeout=1500
+        self.checkeolchars_enabled = True
+        self.always_remove_trailing_spaces = False
+        self.fullpath_sorting_enabled = None
+        self.focus_to_editor = True
+        self.set_fullpath_sorting_enabled(False)
+        ccs = 'Spyder'
+        if ccs not in syntaxhighlighters.COLOR_SCHEME_NAMES:
+            ccs = syntaxhighlighters.COLOR_SCHEME_NAMES[0]
+        self.color_scheme = ccs
+        self.introspector = introspection.PluginManager(self)
+
+        self.introspector.send_to_inspector.connect(self.send_to_inspector)
+        self.introspector.edit_goto.connect(
+             lambda fname, lineno, name:
+             self.edit_goto.emit(fname, lineno, name))
+
+        self.__file_status_flag = False
+
+        # Real-time code analysis
+        self.analysis_timer = QTimer(self)
+        self.analysis_timer.setSingleShot(True)
+        self.analysis_timer.setInterval(2000)
+        self.analysis_timer.timeout.connect(self.analyze_script)
+
+        # Accepting drops
+        self.setAcceptDrops(True)
+
+        # Local shortcuts
+        self.shortcuts = self.create_shortcuts()
+
+    def create_shortcuts(self):
+        """Create local shortcuts"""
+        # Configurable shortcuts
+        inspect = create_shortcut(self.inspect_current_object, context='Editor',
+                                  name='Inspect current object', parent=self)
+        breakpoint = create_shortcut(self.set_or_clear_breakpoint,
+                                     context='Editor', name='Breakpoint',
+                                     parent=self)
+        cbreakpoint = create_shortcut(self.set_or_edit_conditional_breakpoint,
+                                      context='Editor',
+                                      name='Conditional breakpoint',
+                                      parent=self)
+        gotoline = create_shortcut(self.go_to_line, context='Editor',
+                                   name='Go to line', parent=self)
+        tab = create_shortcut(self.go_to_previous_file, context='Editor',
+                              name='Go to previous file', parent=self)
+        tabshift = create_shortcut(self.go_to_next_file, context='Editor',
+                                   name='Go to next file', parent=self)
+
+        # Fixed shortcuts
+        new_shortcut(QKeySequence.ZoomIn, self, lambda: self.zoom_in.emit())
+        new_shortcut("Ctrl+=", self, lambda: self.zoom_in.emit())
+        new_shortcut(QKeySequence.ZoomOut, self, lambda: self.zoom_out.emit())
+        new_shortcut("Ctrl+0", self, lambda: self.zoom_reset.emit())
+        new_shortcut("Ctrl+W", self, self.close_file)
+        new_shortcut("Ctrl+F4", self, self.close_file)
+
+        # Return configurable ones
+        return [inspect, breakpoint, cbreakpoint, gotoline, tab,
+                tabshift]
+
+    def get_shortcut_data(self):
+        """
+        Returns shortcut data, a list of tuples (shortcut, text, default)
+        shortcut (QShortcut or QAction instance)
+        text (string): action/shortcut description
+        default (string): default key sequence
+        """
+        return [sc.data for sc in self.shortcuts]
+
+    def setup_editorstack(self, parent, layout):
+        """Setup editorstack's layout"""
+        menu_btn = create_toolbutton(self, icon=ima.icon('tooloptions'),
+                                     tip=_('Options'))
+        self.menu = QMenu(self)
+        menu_btn.setMenu(self.menu)
+        menu_btn.setPopupMode(menu_btn.InstantPopup)
+        self.menu.aboutToShow.connect(self.__setup_menu)
+
+#        self.filelist_btn = create_toolbutton(self,
+#                             icon=ima.icon('filelist'),
+#                             tip=_("File list management"),
+#                             triggered=self.open_fileswitcher_dlg)
+#
+#        self.previous_btn = create_toolbutton(self,
+#                             icon=ima.icon('previous'),
+#                             tip=_("Previous file"),
+#                             triggered=self.go_to_previous_file)
+#
+#        self.next_btn = create_toolbutton(self,
+#                             icon=ima.icon('next'),
+#                             tip=_("Next file"),
+#                             triggered=self.go_to_next_file)
+
+        # Optional tabs
+#        corner_widgets = {Qt.TopRightCorner: [self.previous_btn,
+#                                              self.filelist_btn, self.next_btn,
+#                                              5, menu_btn]}
+        corner_widgets = {Qt.TopRightCorner: [menu_btn]}
+        self.tabs = BaseTabs(self, menu=self.menu, menu_use_tooltips=True,
+                             corner_widgets=corner_widgets)
+        self.tabs.tabBar().setObjectName('plugin-tab')
+        self.tabs.set_close_function(self.close_file)
+
+        if hasattr(self.tabs, 'setDocumentMode') \
+           and not sys.platform == 'darwin':
+            # Don't set document mode to true on OSX because it generates
+            # a crash when the editor is detached from the main window
+            # Fixes Issue 561
+            self.tabs.setDocumentMode(True)
+        self.tabs.currentChanged.connect(self.current_changed)
+
+        if sys.platform == 'darwin':
+            tab_container = QWidget()
+            tab_container.setObjectName('tab-container')
+            tab_layout = QHBoxLayout(tab_container)
+            tab_layout.setContentsMargins(0, 0, 0, 0)
+            tab_layout.addWidget(self.tabs)
+            layout.addWidget(tab_container)
+        else:
+            layout.addWidget(self.tabs)
+
+    def add_corner_widgets_to_tabbar(self, widgets):
+        self.tabs.add_corner_widgets(widgets)
+
+    def closeEvent(self, event):
+        self.threadmanager.close_all_threads()
+        self.analysis_timer.timeout.disconnect(self.analyze_script)
+        QWidget.closeEvent(self, event)
+        if is_pyqt46:
+            self.destroyed.emit()
+
+    def clone_editor_from(self, other_finfo, set_current):
+        fname = other_finfo.filename
+        enc = other_finfo.encoding
+        new = other_finfo.newly_created
+        finfo = self.create_new_editor(fname, enc, "",
+                                       set_current=set_current, new=new,
+                                       cloned_from=other_finfo.editor)
+        finfo.set_analysis_results(other_finfo.analysis_results)
+        finfo.set_todo_results(other_finfo.todo_results)
+        return finfo.editor
+
+    def clone_from(self, other):
+        """Clone EditorStack from other instance"""
+        for other_finfo in other.data:
+            self.clone_editor_from(other_finfo, set_current=True)
+        self.set_stack_index(other.get_stack_index())
+
+    @Slot()
+    def open_fileswitcher_dlg(self):
+        """Open file list management dialog box"""
+        if not self.tabs.count():
+            return
+        self.fileswitcher_dlg = FileSwitcher(self, self.tabs, self.data)
+        self.fileswitcher_dlg.sig_goto_file.connect(self.set_stack_index)
+        self.fileswitcher_dlg.sig_close_file.connect(self.close_file)
+        self.fileswitcher_dlg.show()
+
+    def update_fileswitcher_dlg(self):
+        """Synchronize file list dialog box with editor widget tabs"""
+        if self.fileswitcher_dlg:
+            self.fileswitcher_dlg.setup()
+
+    def go_to_line(self):
+        """Go to line dialog"""
+        if self.data:
+            self.get_current_editor().exec_gotolinedialog()
+
+    def set_or_clear_breakpoint(self):
+        """Set/clear breakpoint"""
+        if self.data:
+            editor = self.get_current_editor()
+            editor.add_remove_breakpoint()
+
+    def set_or_edit_conditional_breakpoint(self):
+        """Set conditional breakpoint"""
+        if self.data:
+            editor = self.get_current_editor()
+            editor.add_remove_breakpoint(edit_condition=True)
+
+    def inspect_current_object(self):
+        """Inspect current object in Object Inspector"""
+        if self.introspector:
+            editor = self.get_current_editor()
+            position = editor.get_position('cursor')
+            self.inspector.switch_to_editor_source()
+            self.introspector.show_object_info(position, auto=False)
+        else:
+            text = self.get_current_editor().get_current_object()
+            if text:
+                self.send_to_inspector(text, force=True)
+
+    #------ Editor Widget Settings
+    def set_closable(self, state):
+        """Parent widget must handle the closable state"""
+        self.is_closable = state
+
+    def set_io_actions(self, new_action, open_action,
+                       save_action, revert_action):
+        self.new_action = new_action
+        self.open_action = open_action
+        self.save_action = save_action
+        self.revert_action = revert_action
+
+    def set_find_widget(self, find_widget):
+        self.find_widget = find_widget
+
+    def set_outlineexplorer(self, outlineexplorer):
+        self.outlineexplorer = outlineexplorer
+        self.outlineexplorer.outlineexplorer_is_visible.connect(
+                                                 self._refresh_outlineexplorer)
+
+    def initialize_outlineexplorer(self):
+        """This method is called separately from 'set_oulineexplorer' to avoid
+        doing unnecessary updates when there are multiple editor windows"""
+        for index in range(self.get_stack_count()):
+            if index != self.get_stack_index():
+                self._refresh_outlineexplorer(index=index)
+
+    def add_outlineexplorer_button(self, editor_plugin):
+        oe_btn = create_toolbutton(editor_plugin)
+        oe_btn.setDefaultAction(self.outlineexplorer.visibility_action)
+        self.add_corner_widgets_to_tabbar([5, oe_btn])
+
+    def set_inspector(self, inspector):
+        self.inspector = inspector
+
+    def set_tempfile_path(self, path):
+        self.tempfile_path = path
+
+    def set_title(self, text):
+        self.title = text
+
+    def __update_editor_margins(self, editor):
+        editor.setup_margins(linenumbers=self.linenumbers_enabled,
+                             markers=self.has_markers())
+
+    def __codeanalysis_settings_changed(self, current_finfo):
+        if self.data:
+            run_pyflakes, run_pep8 = self.pyflakes_enabled, self.pep8_enabled
+            for finfo in self.data:
+                self.__update_editor_margins(finfo.editor)
+                finfo.cleanup_analysis_results()
+                if (run_pyflakes or run_pep8) and current_finfo is not None:
+                    if current_finfo is not finfo:
+                        finfo.run_code_analysis(run_pyflakes, run_pep8)
+
+    def set_pyflakes_enabled(self, state, current_finfo=None):
+        # CONF.get(self.CONF_SECTION, 'code_analysis/pyflakes')
+        self.pyflakes_enabled = state
+        self.__codeanalysis_settings_changed(current_finfo)
+
+    def set_pep8_enabled(self, state, current_finfo=None):
+        # CONF.get(self.CONF_SECTION, 'code_analysis/pep8')
+        self.pep8_enabled = state
+        self.__codeanalysis_settings_changed(current_finfo)
+
+    def has_markers(self):
+        """Return True if this editorstack has a marker margin for TODOs or
+        code analysis"""
+        return self.todolist_enabled or self.pyflakes_enabled\
+               or self.pep8_enabled
+
+    def set_todolist_enabled(self, state, current_finfo=None):
+        # CONF.get(self.CONF_SECTION, 'todo_list')
+        self.todolist_enabled = state
+        if self.data:
+            for finfo in self.data:
+                self.__update_editor_margins(finfo.editor)
+                finfo.cleanup_todo_results()
+                if state and current_finfo is not None:
+                    if current_finfo is not finfo:
+                        finfo.run_todo_finder()
+
+    def set_realtime_analysis_enabled(self, state):
+        self.realtime_analysis_enabled = state
+
+    def set_realtime_analysis_timeout(self, timeout):
+        self.analysis_timer.setInterval(timeout)
+
+    def set_linenumbers_enabled(self, state, current_finfo=None):
+        # CONF.get(self.CONF_SECTION, 'line_numbers')
+        self.linenumbers_enabled = state
+        if self.data:
+            for finfo in self.data:
+                self.__update_editor_margins(finfo.editor)
+
+    def set_blanks_enabled(self, state):
+        self.blanks_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_blanks_enabled(state)
+        
+    def set_edgeline_enabled(self, state):
+        # CONF.get(self.CONF_SECTION, 'edge_line')
+        self.edgeline_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_edge_line_enabled(state)
+
+    def set_edgeline_column(self, column):
+        # CONF.get(self.CONF_SECTION, 'edge_line_column')
+        self.edgeline_column = column
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_edge_line_column(column)
+
+    def set_codecompletion_auto_enabled(self, state):
+        # CONF.get(self.CONF_SECTION, 'codecompletion_auto')
+        self.codecompletion_auto_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_codecompletion_auto(state)
+
+    def set_codecompletion_case_enabled(self, state):
+        self.codecompletion_case_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_codecompletion_case(state)
+
+    def set_codecompletion_enter_enabled(self, state):
+        self.codecompletion_enter_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_codecompletion_enter(state)
+
+    def set_calltips_enabled(self, state):
+        # CONF.get(self.CONF_SECTION, 'calltips')
+        self.calltips_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_calltips(state)
+
+    def set_go_to_definition_enabled(self, state):
+        # CONF.get(self.CONF_SECTION, 'go_to_definition')
+        self.go_to_definition_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_go_to_definition_enabled(state)
+
+    def set_close_parentheses_enabled(self, state):
+        # CONF.get(self.CONF_SECTION, 'close_parentheses')
+        self.close_parentheses_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_close_parentheses_enabled(state)
+
+    def set_close_quotes_enabled(self, state):
+        # CONF.get(self.CONF_SECTION, 'close_quotes')
+        self.close_quotes_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_close_quotes_enabled(state)
+
+    def set_add_colons_enabled(self, state):
+        # CONF.get(self.CONF_SECTION, 'add_colons')
+        self.add_colons_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_add_colons_enabled(state)
+
+    def set_auto_unindent_enabled(self, state):
+        # CONF.get(self.CONF_SECTION, 'auto_unindent')
+        self.auto_unindent_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_auto_unindent_enabled(state)
+
+    def set_indent_chars(self, indent_chars):
+        # CONF.get(self.CONF_SECTION, 'indent_chars')
+        indent_chars = indent_chars[1:-1] # removing the leading/ending '*'
+        self.indent_chars = indent_chars
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_indent_chars(indent_chars)
+
+    def set_tab_stop_width(self, tab_stop_width):
+        # CONF.get(self.CONF_SECTION, 'tab_stop_width')
+        self.tab_stop_width = tab_stop_width
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.setTabStopWidth(tab_stop_width)
+
+    def set_inspector_enabled(self, state):
+        self.inspector_enabled = state
+
+    def set_default_font(self, font, color_scheme=None):
+        # get_font(self.CONF_SECTION)
+        self.default_font = font
+        if color_scheme is not None:
+            self.color_scheme = color_scheme
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_font(font, color_scheme)
+
+    def set_color_scheme(self, color_scheme):
+        self.color_scheme = color_scheme
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_color_scheme(color_scheme)
+
+    def set_wrap_enabled(self, state):
+        # CONF.get(self.CONF_SECTION, 'wrap')
+        self.wrap_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.toggle_wrap_mode(state)
+
+    def set_tabmode_enabled(self, state):
+        # CONF.get(self.CONF_SECTION, 'tab_always_indent')
+        self.tabmode_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_tab_mode(state)
+
+    def set_intelligent_backspace_enabled(self, state):
+        # CONF.get(self.CONF_SECTION, 'intelligent_backspace')
+        self.intelligent_backspace_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.toggle_intelligent_backspace(state)
+
+    def set_occurence_highlighting_enabled(self, state):
+        # CONF.get(self.CONF_SECTION, 'occurence_highlighting')
+        self.occurence_highlighting_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_occurence_highlighting(state)
+
+    def set_occurence_highlighting_timeout(self, timeout):
+        # CONF.get(self.CONF_SECTION, 'occurence_highlighting/timeout')
+        self.occurence_highlighting_timeout = timeout
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_occurence_timeout(timeout)
+
+    def set_highlight_current_line_enabled(self, state):
+        self.highlight_current_line_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_highlight_current_line(state)
+
+    def set_highlight_current_cell_enabled(self, state):
+        self.highlight_current_cell_enabled = state
+        if self.data:
+            for finfo in self.data:
+                finfo.editor.set_highlight_current_cell(state)
+
+    def set_checkeolchars_enabled(self, state):
+        # CONF.get(self.CONF_SECTION, 'check_eol_chars')
+        self.checkeolchars_enabled = state
+
+    def set_fullpath_sorting_enabled(self, state):
+        # CONF.get(self.CONF_SECTION, 'fullpath_sorting')
+        self.fullpath_sorting_enabled = state
+        if self.data:
+            finfo = self.data[self.get_stack_index()]
+            self.data.sort(key=self.__get_sorting_func())
+            new_index = self.data.index(finfo)
+            self.__repopulate_stack()
+            self.set_stack_index(new_index)
+
+    def set_always_remove_trailing_spaces(self, state):
+        # CONF.get(self.CONF_SECTION, 'always_remove_trailing_spaces')
+        self.always_remove_trailing_spaces = state
+
+    def set_focus_to_editor(self, state):
+        self.focus_to_editor = state
+
+    #------ Stacked widget management
+    def get_stack_index(self):
+        return self.tabs.currentIndex()
+
+    def get_current_finfo(self):
+        if self.data:
+            return self.data[self.get_stack_index()]
+
+    def get_current_editor(self):
+        return self.tabs.currentWidget()
+
+    def get_stack_count(self):
+        return self.tabs.count()
+
+    def set_stack_index(self, index):
+        self.tabs.setCurrentIndex(index)
+
+    def set_tabbar_visible(self, state):
+        self.tabs.tabBar().setVisible(state)
+
+    def remove_from_data(self, index):
+        self.tabs.blockSignals(True)
+        self.tabs.removeTab(index)
+        self.data.pop(index)
+        self.tabs.blockSignals(False)
+        self.update_actions()
+        self.update_fileswitcher_dlg()
+
+    def __modified_readonly_title(self, title, is_modified, is_readonly):
+        if is_modified is not None and is_modified:
+            title += "*"
+        if is_readonly is not None and is_readonly:
+            title = "(%s)" % title
+        return title
+
+    def get_tab_text(self, filename, is_modified=None, is_readonly=None):
+        """Return tab title"""
+        return self.__modified_readonly_title(osp.basename(filename),
+                                              is_modified, is_readonly)
+
+    def get_tab_tip(self, filename, is_modified=None, is_readonly=None):
+        """Return tab menu title"""
+        if self.fullpath_sorting_enabled:
+            text = filename
+        else:
+            text = u("%s — %s")
+        text = self.__modified_readonly_title(text,
+                                              is_modified, is_readonly)
+        if self.tempfile_path is not None\
+           and filename == encoding.to_unicode_from_fs(self.tempfile_path):
+            temp_file_str = to_text_string(_("Temporary file"))
+            if self.fullpath_sorting_enabled:
+                return "%s (%s)" % (text, temp_file_str)
+            else:
+                return text % (temp_file_str, self.tempfile_path)
+        else:
+            if self.fullpath_sorting_enabled:
+                return text
+            else:
+                return text % (osp.basename(filename), osp.dirname(filename))
+
+    def __get_sorting_func(self):
+        if self.fullpath_sorting_enabled:
+            return lambda item: osp.join(osp.dirname(item.filename),
+                                         '_'+osp.basename(item.filename))
+        else:
+            return lambda item: osp.basename(item.filename)
+
+    def add_to_data(self, finfo, set_current):
+        self.data.append(finfo)
+        self.data.sort(key=self.__get_sorting_func())
+        index = self.data.index(finfo)
+        fname, editor = finfo.filename, finfo.editor
+        self.tabs.insertTab(index, editor, get_filetype_icon(fname),
+                            self.get_tab_text(fname))
+        self.set_stack_title(index, False)
+        if set_current:
+            self.set_stack_index(index)
+            self.current_changed(index)
+        self.update_actions()
+        self.update_fileswitcher_dlg()
+
+    def __repopulate_stack(self):
+        self.tabs.blockSignals(True)
+        self.tabs.clear()
+        for finfo in self.data:
+            icon = get_filetype_icon(finfo.filename)
+            if finfo.newly_created:
+                is_modified = True
+            else:
+                is_modified = None
+            tab_text = self.get_tab_text(finfo.filename, is_modified)
+            tab_tip = self.get_tab_tip(finfo.filename)
+            index = self.tabs.addTab(finfo.editor, icon, tab_text)
+            self.tabs.setTabToolTip(index, tab_tip)
+        self.tabs.blockSignals(False)
+        self.update_fileswitcher_dlg()
+
+    def rename_in_data(self, index, new_filename):
+        finfo = self.data[index]
+        if osp.splitext(finfo.filename)[1] != osp.splitext(new_filename)[1]:
+            # File type has changed!
+            txt = to_text_string(finfo.editor.get_text_with_eol())
+            language = get_file_language(new_filename, txt)
+            finfo.editor.set_language(language)
+        set_new_index = index == self.get_stack_index()
+        current_fname = self.get_current_filename()
+        finfo.filename = new_filename
+        self.data.sort(key=self.__get_sorting_func())
+        new_index = self.data.index(finfo)
+        self.__repopulate_stack()
+        if set_new_index:
+            self.set_stack_index(new_index)
+        else:
+            # Fixes Issue 1287
+            self.set_current_filename(current_fname)
+        if self.outlineexplorer is not None:
+            self.outlineexplorer.file_renamed(finfo.editor, finfo.filename)
+        return new_index
+
+    def set_stack_title(self, index, is_modified):
+        finfo = self.data[index]
+        fname = finfo.filename
+        is_modified = (is_modified or finfo.newly_created) and not finfo.default
+        is_readonly = finfo.editor.isReadOnly()
+        tab_text = self.get_tab_text(fname, is_modified, is_readonly)
+        tab_tip = self.get_tab_tip(fname, is_modified, is_readonly)
+        self.tabs.setTabText(index, tab_text)
+        self.tabs.setTabToolTip(index, tab_tip)
+
+
+    #------ Context menu
+    def __setup_menu(self):
+        """Setup tab context menu before showing it"""
+        self.menu.clear()
+        if self.data:
+            actions = self.menu_actions
+        else:
+            actions = (self.new_action, self.open_action)
+            self.setFocus() # --> Editor.__get_focus_editortabwidget
+        add_actions(self.menu, list(actions)+self.__get_split_actions())
+        self.close_action.setEnabled(self.is_closable)
+
+
+    #------ Hor/Ver splitting
+    def __get_split_actions(self):
+        # New window
+        self.newwindow_action = create_action(self, _("New window"),
+                icon=ima.icon('newwindow'), tip=_("Create a new editor window"),
+                triggered=lambda: self.create_new_window.emit())
+        # Splitting
+        self.versplit_action = create_action(self, _("Split vertically"),
+                icon=ima.icon('versplit'),
+                tip=_("Split vertically this editor window"),
+                triggered=lambda: self.split_vertically.emit())
+        self.horsplit_action = create_action(self, _("Split horizontally"),
+                icon=ima.icon('horsplit'),
+                tip=_("Split horizontally this editor window"),
+                triggered=lambda: self.split_horizontally.emit())
+        self.close_action = create_action(self, _("Close this panel"),
+                icon=ima.icon('close_panel'), triggered=self.close)
+        return [None, self.newwindow_action, None,
+                self.versplit_action, self.horsplit_action, self.close_action]
+
+    def reset_orientation(self):
+        self.horsplit_action.setEnabled(True)
+        self.versplit_action.setEnabled(True)
+
+    def set_orientation(self, orientation):
+        self.horsplit_action.setEnabled(orientation == Qt.Horizontal)
+        self.versplit_action.setEnabled(orientation == Qt.Vertical)
+
+    def update_actions(self):
+        state = self.get_stack_count() > 0
+        self.horsplit_action.setEnabled(state)
+        self.versplit_action.setEnabled(state)
+
+
+    #------ Accessors
+    def get_current_filename(self):
+        if self.data:
+            return self.data[self.get_stack_index()].filename
+
+    def has_filename(self, filename):
+        fixpath = lambda path: osp.normcase(osp.realpath(path))
+        for index, finfo in enumerate(self.data):
+            if fixpath(filename) == fixpath(finfo.filename):
+                return index
+
+    def set_current_filename(self, filename):
+        """Set current filename and return the associated editor instance"""
+        index = self.has_filename(filename)
+        if index is not None:
+            self.set_stack_index(index)
+            editor = self.data[index].editor
+            editor.setFocus()
+            return editor
+
+    def is_file_opened(self, filename=None):
+        if filename is None:
+            # Is there any file opened?
+            return len(self.data) > 0
+        else:
+            return self.has_filename(filename)
+
+
+    #------ Close file, tabwidget...
+    def close_file(self, index=None, force=False):
+        """Close file (index=None -> close current file)
+        Keep current file index unchanged (if current file
+        that is being closed)"""
+        current_index = self.get_stack_index()
+        count = self.get_stack_count()
+
+        if index is None:
+            if count > 0:
+                index = current_index
+            else:
+                self.find_widget.set_editor(None)
+                return
+
+        new_index = None
+        if count > 1:
+            if current_index == index:
+                new_index = self._get_previous_file_index()
+            else:
+                new_index = current_index
+
+        is_ok = force or self.save_if_changed(cancelable=True, index=index)
+        if is_ok:
+            finfo = self.data[index]
+            self.threadmanager.close_threads(finfo)
+            # Removing editor reference from outline explorer settings:
+            if self.outlineexplorer is not None:
+                self.outlineexplorer.remove_editor(finfo.editor)
+
+            self.remove_from_data(index)
+
+            # We pass self object ID as a QString, because otherwise it would
+            # depend on the platform: long for 64bit, int for 32bit. Replacing
+            # by long all the time is not working on some 32bit platforms
+            # (see Issue 1094, Issue 1098)
+            self.sig_close_file.emit(str(id(self)), index)
+
+            if not self.data and self.is_closable:
+                # editortabwidget is empty: removing it
+                # (if it's not the first editortabwidget)
+                self.close()
+
+            self.opened_files_list_changed.emit()
+            self.update_code_analysis_actions.emit()
+            self._refresh_outlineexplorer()
+            self.refresh_file_dependent_actions.emit()
+            self.update_plugin_title.emit()
+
+            editor = self.get_current_editor()
+            if editor:
+                editor.setFocus()
+
+            if new_index is not None:
+                if index < new_index:
+                    new_index -= 1
+                self.set_stack_index(new_index)
+
+        if self.get_stack_count() == 0:
+            self.sig_new_file[()].emit()
+            return False
+
+        return is_ok
+
+    def close_all_files(self):
+        """Close all opened scripts"""
+        while self.close_file():
+            pass
+
+
+    #------ Save
+    def save_if_changed(self, cancelable=False, index=None):
+        """Ask user to save file if modified"""
+        if index is None:
+            indexes = list(range(self.get_stack_count()))
+        else:
+            indexes = [index]
+        buttons = QMessageBox.Yes | QMessageBox.No
+        if cancelable:
+            buttons |= QMessageBox.Cancel
+        unsaved_nb = 0
+        for index in indexes:
+            if self.data[index].editor.document().isModified():
+                unsaved_nb += 1
+        if not unsaved_nb:
+            # No file to save
+            return True
+        if unsaved_nb > 1:
+            buttons |= QMessageBox.YesAll | QMessageBox.NoAll
+        yes_all = False
+        for index in indexes:
+            self.set_stack_index(index)
+            finfo = self.data[index]
+            if finfo.filename == self.tempfile_path or yes_all:
+                if not self.save():
+                    return False
+            elif finfo.editor.document().isModified():
+                answer = QMessageBox.question(self, self.title,
+                            _("<b>%s</b> has been modified."
+                              "<br>Do you want to save changes?"
+                              ) % osp.basename(finfo.filename),
+                            buttons)
+                if answer == QMessageBox.Yes:
+                    if not self.save():
+                        return False
+                elif answer == QMessageBox.YesAll:
+                    if not self.save():
+                        return False
+                    yes_all = True
+                elif answer == QMessageBox.NoAll:
+                    return True
+                elif answer == QMessageBox.Cancel:
+                    return False
+        return True
+
+    def save(self, index=None, force=False):
+        """Save file"""
+        if index is None:
+            # Save the currently edited file
+            if not self.get_stack_count():
+                return
+            index = self.get_stack_index()
+
+        finfo = self.data[index]
+        if not finfo.editor.document().isModified() and not force:
+            return True
+        if not osp.isfile(finfo.filename) and not force:
+            # File has not been saved yet
+            return self.save_as(index=index)
+        if self.always_remove_trailing_spaces:
+            self.remove_trailing_spaces(index)
+        txt = to_text_string(finfo.editor.get_text_with_eol())
+        try:
+            finfo.encoding = encoding.write(txt, finfo.filename,
+                                            finfo.encoding)
+            finfo.newly_created = False
+            self.encoding_changed.emit(finfo.encoding)
+            finfo.lastmodified = QFileInfo(finfo.filename).lastModified()
+
+            # We pass self object ID as a QString, because otherwise it would
+            # depend on the platform: long for 64bit, int for 32bit. Replacing
+            # by long all the time is not working on some 32bit platforms
+            # (see Issue 1094, Issue 1098)
+            self.file_saved.emit(str(id(self)), index, finfo.filename)
+
+            finfo.editor.document().setModified(False)
+            self.modification_changed(index=index)
+            self.analyze_script(index)
+            self.introspector.validate()
+
+            #XXX CodeEditor-only: re-scan the whole text to rebuild outline
+            # explorer data from scratch (could be optimized because
+            # rehighlighting text means searching for all syntax coloring
+            # patterns instead of only searching for class/def patterns which
+            # would be sufficient for outline explorer data.
+            finfo.editor.rehighlight()
+
+            self._refresh_outlineexplorer(index)
+            return True
+        except EnvironmentError as error:
+            QMessageBox.critical(self, _("Save"),
+                                 _("<b>Unable to save script '%s'</b>"
+                                   "<br><br>Error message:<br>%s"
+                                   ) % (osp.basename(finfo.filename),
+                                        str(error)))
+            return False
+
+    def file_saved_in_other_editorstack(self, index, filename):
+        """
+        File was just saved in another editorstack, let's synchronize!
+        This avoid file to be automatically reloaded
+
+        Filename is passed in case file was just saved as another name
+        """
+        finfo = self.data[index]
+        finfo.newly_created = False
+        finfo.filename = to_text_string(filename)
+        finfo.lastmodified = QFileInfo(finfo.filename).lastModified()
+
+    def select_savename(self, original_filename):
+        selectedfilter = get_filter(EDIT_FILETYPES,
+                                    osp.splitext(original_filename)[1])
+        self.redirect_stdio.emit(False)
+        filename, _selfilter = getsavefilename(self, _("Save Python script"),
+                               original_filename, EDIT_FILTERS, selectedfilter)
+        self.redirect_stdio.emit(True)
+        if filename:
+            return osp.normpath(filename)
+
+    def save_as(self, index=None):
+        """Save file as..."""
+        if index is None:
+            # Save the currently edited file
+            index = self.get_stack_index()
+        finfo = self.data[index]
+        filename = self.select_savename(finfo.filename)
+        if filename:
+            ao_index = self.has_filename(filename)
+            # Note: ao_index == index --> saving an untitled file
+            if ao_index and ao_index != index:
+                if not self.close_file(ao_index):
+                    return
+                if ao_index < index:
+                    index -= 1
+
+            new_index = self.rename_in_data(index, new_filename=filename)
+
+            # We pass self object ID as a QString, because otherwise it would
+            # depend on the platform: long for 64bit, int for 32bit. Replacing
+            # by long all the time is not working on some 32bit platforms
+            # (see Issue 1094, Issue 1098)
+            self.file_renamed_in_data.emit(str(id(self)), index, filename)
+
+            ok = self.save(index=new_index, force=True)
+            self.refresh(new_index)
+            self.set_stack_index(new_index)
+            return ok
+        else:
+            return False
+
+    def save_all(self):
+        """Save all opened files"""
+        folders = set()
+        for index in range(self.get_stack_count()):
+            if self.data[index].editor.document().isModified():
+                folders.add(osp.dirname(self.data[index].filename))
+                self.save(index)
+
+    #------ Update UI
+    def start_stop_analysis_timer(self):
+        self.is_analysis_done = False
+        if self.realtime_analysis_enabled:
+            self.analysis_timer.stop()
+            self.analysis_timer.start()
+
+    def analyze_script(self, index=None):
+        """Analyze current script with pyflakes + find todos"""
+        if self.is_analysis_done:
+            return
+        if index is None:
+            index = self.get_stack_index()
+        if self.data:
+            finfo = self.data[index]
+            run_pyflakes, run_pep8 = self.pyflakes_enabled, self.pep8_enabled
+            if run_pyflakes or run_pep8:
+                finfo.run_code_analysis(run_pyflakes, run_pep8)
+            if self.todolist_enabled:
+                finfo.run_todo_finder()
+        self.is_analysis_done = True
+
+    def set_analysis_results(self, index, analysis_results):
+        """Synchronize analysis results between editorstacks"""
+        self.data[index].set_analysis_results(analysis_results)
+
+    def get_analysis_results(self):
+        if self.data:
+            return self.data[self.get_stack_index()].analysis_results
+
+    def set_todo_results(self, index, todo_results):
+        """Synchronize todo results between editorstacks"""
+        self.data[index].set_todo_results(todo_results)
+
+    def get_todo_results(self):
+        if self.data:
+            return self.data[self.get_stack_index()].todo_results
+
+    def current_changed(self, index):
+        """Stack index has changed"""
+#        count = self.get_stack_count()
+#        for btn in (self.filelist_btn, self.previous_btn, self.next_btn):
+#            btn.setEnabled(count > 1)
+
+        editor = self.get_current_editor()
+        if index != -1:
+            editor.setFocus()
+            if DEBUG_EDITOR:
+                print("setfocusto:", editor, file=STDOUT)
+        else:
+            self.reset_statusbar.emit()
+        self.opened_files_list_changed.emit()
+
+        # Index history management
+        id_list = [id(self.tabs.widget(_i))
+                   for _i in range(self.tabs.count())]
+        for _id in self.stack_history[:]:
+            if _id not in id_list:
+                self.stack_history.pop(self.stack_history.index(_id))
+        current_id = id(self.tabs.widget(index))
+        while current_id in self.stack_history:
+            self.stack_history.pop(self.stack_history.index(current_id))
+        self.stack_history.append(current_id)
+        if DEBUG_EDITOR:
+            print("current_changed:", index, self.data[index].editor, end=' ', file=STDOUT)
+            print(self.data[index].editor.get_document_id(), file=STDOUT)
+
+        self.update_plugin_title.emit()
+        if editor is not None:
+            self.current_file_changed.emit(self.data[index].filename,
+                                           editor.get_position('cursor'))
+
+    def _get_previous_file_index(self):
+        if len(self.stack_history) > 1:
+            last = len(self.stack_history)-1
+            w_id = self.stack_history.pop(last)
+            self.stack_history.insert(0, w_id)
+            last_id = self.stack_history[last]
+            for _i in range(self.tabs.count()):
+                if id(self.tabs.widget(_i)) == last_id:
+                    return _i
+
+    def go_to_previous_file(self):
+        """Ctrl+Tab"""
+        prev_index = self._get_previous_file_index()
+        if prev_index is not None:
+            self.set_stack_index(prev_index)
+        elif len(self.stack_history) == 0 and self.get_stack_count():
+            self.stack_history = [id(self.tabs.currentWidget())]
+
+    def go_to_next_file(self):
+        """Ctrl+Shift+Tab"""
+        if len(self.stack_history) > 1:
+            last = len(self.stack_history)-1
+            w_id = self.stack_history.pop(0)
+            self.stack_history.append(w_id)
+            last_id = self.stack_history[last]
+            for _i in range(self.tabs.count()):
+                if id(self.tabs.widget(_i)) == last_id:
+                    self.set_stack_index(_i)
+                    break
+        elif len(self.stack_history) == 0 and self.get_stack_count():
+            self.stack_history = [id(self.tabs.currentWidget())]
+
+    def focus_changed(self):
+        """Editor focus has changed"""
+        fwidget = QApplication.focusWidget()
+        for finfo in self.data:
+            if fwidget is finfo.editor:
+                self.refresh()
+        self.editor_focus_changed.emit()
+
+    def _refresh_outlineexplorer(self, index=None, update=True, clear=False):
+        """Refresh outline explorer panel"""
+        oe = self.outlineexplorer
+        if oe is None:
+            return
+        if index is None:
+            index = self.get_stack_index()
+        enable = False
+        if self.data:
+            finfo = self.data[index]
+            if finfo.editor.is_python():
+                enable = True
+                oe.setEnabled(True)
+                oe.set_current_editor(finfo.editor, finfo.filename,
+                                      update=update, clear=clear)
+        if not enable:
+            oe.setEnabled(False)
+
+    def __refresh_statusbar(self, index):
+        """Refreshing statusbar widgets"""
+        finfo = self.data[index]
+        self.encoding_changed.emit(finfo.encoding)
+        # Refresh cursor position status:
+        line, index = finfo.editor.get_cursor_line_column()
+        self.sig_editor_cursor_position_changed.emit(line, index)
+
+    def __refresh_readonly(self, index):
+        finfo = self.data[index]
+        read_only = not QFileInfo(finfo.filename).isWritable()
+        if not osp.isfile(finfo.filename):
+            # This is an 'untitledX.py' file (newly created)
+            read_only = False
+        finfo.editor.setReadOnly(read_only)
+        self.readonly_changed.emit(read_only)
+
+    def __check_file_status(self, index):
+        """Check if file has been changed in any way outside Spyder:
+        1. removed, moved or renamed outside Spyder
+        2. modified outside Spyder"""
+        if self.__file_status_flag:
+            # Avoid infinite loop: when the QMessageBox.question pops, it
+            # gets focus and then give it back to the CodeEditor instance,
+            # triggering a refresh cycle which calls this method
+            return
+        self.__file_status_flag = True
+
+        finfo = self.data[index]
+        name = osp.basename(finfo.filename)
+
+        if finfo.newly_created:
+            # File was just created (not yet saved): do nothing
+            # (do not return because of the clean-up at the end of the method)
+            pass
+
+        elif not osp.isfile(finfo.filename):
+            # File doesn't exist (removed, moved or offline):
+            answer = QMessageBox.warning(self, self.title,
+                                _("<b>%s</b> is unavailable "
+                                  "(this file may have been removed, moved "
+                                  "or renamed outside Spyder)."
+                                  "<br>Do you want to close it?") % name,
+                                QMessageBox.Yes | QMessageBox.No)
+            if answer == QMessageBox.Yes:
+                self.close_file(index)
+            else:
+                finfo.newly_created = True
+                finfo.editor.document().setModified(True)
+                self.modification_changed(index=index)
+
+        else:
+            # Else, testing if it has been modified elsewhere:
+            lastm = QFileInfo(finfo.filename).lastModified()
+            if to_text_string(lastm.toString()) \
+               != to_text_string(finfo.lastmodified.toString()):
+                if finfo.editor.document().isModified():
+                    answer = QMessageBox.question(self,
+                                self.title,
+                                _("<b>%s</b> has been modified outside Spyder."
+                                  "<br>Do you want to reload it and lose all "
+                                  "your changes?") % name,
+                                QMessageBox.Yes | QMessageBox.No)
+                    if answer == QMessageBox.Yes:
+                        self.reload(index)
+                    else:
+                        finfo.lastmodified = lastm
+                else:
+                    self.reload(index)
+
+        # Finally, resetting temporary flag:
+        self.__file_status_flag = False
+
+    def refresh(self, index=None):
+        """Refresh tabwidget"""
+        if index is None:
+            index = self.get_stack_index()
+        # Set current editor
+        if self.get_stack_count():
+            index = self.get_stack_index()
+            finfo = self.data[index]
+            editor = finfo.editor
+            editor.setFocus()
+            self._refresh_outlineexplorer(index, update=False)
+            self.update_code_analysis_actions.emit()
+            self.__refresh_statusbar(index)
+            self.__refresh_readonly(index)
+            self.__check_file_status(index)
+            self.update_plugin_title.emit()
+        else:
+            editor = None
+        # Update the modification-state-dependent parameters
+        self.modification_changed()
+        # Update FindReplace binding
+        self.find_widget.set_editor(editor, refresh=False)
+
+    def modification_changed(self, state=None, index=None, editor_id=None):
+        """
+        Current editor's modification state has changed
+        --> change tab title depending on new modification state
+        --> enable/disable save/save all actions
+        """
+        if editor_id is not None:
+            for index, _finfo in enumerate(self.data):
+                if id(_finfo.editor) == editor_id:
+                    break
+        # This must be done before refreshing save/save all actions:
+        # (otherwise Save/Save all actions will always be enabled)
+        self.opened_files_list_changed.emit()
+        # --
+        if index is None:
+            index = self.get_stack_index()
+        if index == -1:
+            return
+        finfo = self.data[index]
+        if state is None:
+            state = finfo.editor.document().isModified()
+        self.set_stack_title(index, state)
+        # Toggle save/save all actions state
+        self.save_action.setEnabled(state)
+        self.refresh_save_all_action.emit()
+        # Refreshing eol mode
+        eol_chars = finfo.editor.get_line_separator()
+        os_name = sourcecode.get_os_name_from_eol_chars(eol_chars)
+        self.refresh_eol_chars.emit(os_name)
+
+
+    #------ Load, reload
+    def reload(self, index):
+        """Reload file from disk"""
+        finfo = self.data[index]
+        txt, finfo.encoding = encoding.read(finfo.filename)
+        finfo.lastmodified = QFileInfo(finfo.filename).lastModified()
+        position = finfo.editor.get_position('cursor')
+        finfo.editor.set_text(txt)
+        finfo.editor.document().setModified(False)
+        finfo.editor.set_cursor_position(position)
+        self.introspector.validate()
+
+        #XXX CodeEditor-only: re-scan the whole text to rebuild outline
+        # explorer data from scratch (could be optimized because
+        # rehighlighting text means searching for all syntax coloring
+        # patterns instead of only searching for class/def patterns which
+        # would be sufficient for outline explorer data.
+        finfo.editor.rehighlight()
+
+        self._refresh_outlineexplorer(index)
+
+    def revert(self):
+        """Revert file from disk"""
+        index = self.get_stack_index()
+        finfo = self.data[index]
+        filename = finfo.filename
+        if finfo.editor.document().isModified():
+            answer = QMessageBox.warning(self, self.title,
+                                _("All changes to <b>%s</b> will be lost."
+                                  "<br>Do you want to revert file from disk?"
+                                  ) % osp.basename(filename),
+                                  QMessageBox.Yes|QMessageBox.No)
+            if answer != QMessageBox.Yes:
+                return
+        self.reload(index)
+
+    def create_new_editor(self, fname, enc, txt, set_current, new=False,
+                          cloned_from=None):
+        """
+        Create a new editor instance
+        Returns finfo object (instead of editor as in previous releases)
+        """
+        editor = codeeditor.CodeEditor(self)
+        introspector = self.introspector
+        editor.get_completions.connect(introspector.get_completions)
+        editor.sig_show_object_info.connect(introspector.show_object_info)
+        editor.go_to_definition.connect(introspector.go_to_definition)
+
+        finfo = FileInfo(fname, enc, editor, new, self.threadmanager,
+                         self.introspector)
+
+        self.add_to_data(finfo, set_current)
+        finfo.send_to_inspector.connect(self.send_to_inspector)
+        finfo.analysis_results_changed.connect(
+                                  lambda: self.analysis_results_changed.emit())
+        finfo.todo_results_changed.connect(
+                                      lambda: self.todo_results_changed.emit())
+        finfo.edit_goto.connect(lambda fname, lineno, name:
+                                self.edit_goto.emit(fname, lineno, name))
+        finfo.save_breakpoints.connect(lambda s1, s2:
+                                       self.save_breakpoints.emit(s1, s2))
+        editor.run_selection.connect(self.run_selection)
+        editor.run_cell.connect(self.run_cell)
+        editor.run_cell_and_advance.connect(self.run_cell_and_advance)
+        editor.sig_new_file.connect(self.sig_new_file.emit)
+        language = get_file_language(fname, txt)
+        editor.setup_editor(
+                linenumbers=self.linenumbers_enabled,
+                show_blanks=self.blanks_enabled,
+                edge_line=self.edgeline_enabled,
+                edge_line_column=self.edgeline_column, language=language,
+                markers=self.has_markers(), font=self.default_font,
+                color_scheme=self.color_scheme,
+                wrap=self.wrap_enabled, tab_mode=self.tabmode_enabled,
+                intelligent_backspace=self.intelligent_backspace_enabled,
+                highlight_current_line=self.highlight_current_line_enabled,
+                highlight_current_cell=self.highlight_current_cell_enabled,
+                occurence_highlighting=self.occurence_highlighting_enabled,
+                occurence_timeout=self.occurence_highlighting_timeout,
+                codecompletion_auto=self.codecompletion_auto_enabled,
+                codecompletion_case=self.codecompletion_case_enabled,
+                codecompletion_enter=self.codecompletion_enter_enabled,
+                calltips=self.calltips_enabled,
+                go_to_definition=self.go_to_definition_enabled,
+                close_parentheses=self.close_parentheses_enabled,
+                close_quotes=self.close_quotes_enabled,
+                add_colons=self.add_colons_enabled,
+                auto_unindent=self.auto_unindent_enabled,
+                indent_chars=self.indent_chars,
+                tab_stop_width=self.tab_stop_width,
+                cloned_from=cloned_from,
+                filename=fname)
+        if cloned_from is None:
+            editor.set_text(txt)
+            editor.document().setModified(False)
+        finfo.text_changed_at.connect(
+                                    lambda fname, position:
+                                    self.text_changed_at.emit(fname, position))
+        editor.sig_cursor_position_changed.connect(
+                                           self.editor_cursor_position_changed)
+        editor.textChanged.connect(self.start_stop_analysis_timer)
+        editor.modificationChanged.connect(
+                     lambda state: self.modification_changed(state,
+                                                    editor_id=id(editor)))
+        editor.focus_in.connect(self.focus_changed)
+        editor.zoom_in.connect(lambda: self.zoom_in.emit())
+        editor.zoom_out.connect(lambda: self.zoom_out.emit())
+        editor.zoom_reset.connect(lambda: self.zoom_reset.emit())
+        if self.outlineexplorer is not None:
+            # Removing editor reference from outline explorer settings:
+            editor.destroyed.connect(lambda obj=editor:
+                                     self.outlineexplorer.remove_editor(obj))
+
+        self.find_widget.set_editor(editor)
+
+        self.refresh_file_dependent_actions.emit()
+        self.modification_changed(index=self.data.index(finfo))
+
+        return finfo
+
+    def editor_cursor_position_changed(self, line, index):
+        """Cursor position of one of the editor in the stack has changed"""
+        self.sig_editor_cursor_position_changed.emit(line, index)
+
+    def send_to_inspector(self, qstr1, qstr2=None, qstr3=None,
+                          qstr4=None, force=False):
+        """qstr1: obj_text, qstr2: argpspec, qstr3: note, qstr4: doc_text"""
+        if not force and not self.inspector_enabled:
+            return
+        if self.inspector is not None \
+           and (force or self.inspector.dockwidget.isVisible()):
+            # ObjectInspector widget exists and is visible
+            if qstr4 is None:
+                self.inspector.set_object_text(qstr1, ignore_unknown=True,
+                                               force_refresh=force)
+            else:
+                objtxt = to_text_string(qstr1)
+                name = objtxt.split('.')[-1]
+                argspec = to_text_string(qstr2)
+                note = to_text_string(qstr3)
+                docstring = to_text_string(qstr4)
+                doc = {'obj_text': objtxt, 'name': name, 'argspec': argspec,
+                       'note': note, 'docstring': docstring}
+                self.inspector.set_editor_doc(doc, force_refresh=force)
+            editor = self.get_current_editor()
+            editor.setFocus()
+
+    def new(self, filename, encoding, text, default_content=False):
+        """
+        Create new filename with *encoding* and *text*
+        """
+        finfo = self.create_new_editor(filename, encoding, text,
+                                       set_current=False, new=True)
+        finfo.editor.set_cursor_position('eof')
+        finfo.editor.insert_text(os.linesep)
+        if default_content:
+            finfo.default = True
+            finfo.editor.document().setModified(False)
+        return finfo
+
+    def load(self, filename, set_current=True):
+        """
+        Load filename, create an editor instance and return it
+        *Warning* This is loading file, creating editor but not executing
+        the source code analysis -- the analysis must be done by the editor
+        plugin (in case multiple editorstack instances are handled)
+        """
+        filename = osp.abspath(to_text_string(filename))
+        self.starting_long_process.emit(_("Loading %s...") % filename)
+        text, enc = encoding.read(filename)
+        finfo = self.create_new_editor(filename, enc, text, set_current)
+        index = self.data.index(finfo)
+        self._refresh_outlineexplorer(index, update=True)
+        self.ending_long_process.emit("")
+        if self.isVisible() and self.checkeolchars_enabled \
+           and sourcecode.has_mixed_eol_chars(text):
+            name = osp.basename(filename)
+            QMessageBox.warning(self, self.title,
+                                _("<b>%s</b> contains mixed end-of-line "
+                                  "characters.<br>Spyder will fix this "
+                                  "automatically.") % name,
+                                QMessageBox.Ok)
+            self.set_os_eol_chars(index)
+        self.is_analysis_done = False
+        return finfo
+
+    def set_os_eol_chars(self, index=None):
+        if index is None:
+            index = self.get_stack_index()
+        finfo = self.data[index]
+        eol_chars = sourcecode.get_eol_chars_from_os_name(os.name)
+        finfo.editor.set_eol_chars(eol_chars)
+        finfo.editor.document().setModified(True)
+
+    def remove_trailing_spaces(self, index=None):
+        """Remove trailing spaces"""
+        if index is None:
+            index = self.get_stack_index()
+        finfo = self.data[index]
+        finfo.editor.remove_trailing_spaces()
+
+    def fix_indentation(self, index=None):
+        """Replace tab characters by spaces"""
+        if index is None:
+            index = self.get_stack_index()
+        finfo = self.data[index]
+        finfo.editor.fix_indentation()
+
+    #------ Run
+    def run_selection(self):
+        """Run selected text or current line in console"""
+        text = self.get_current_editor().get_selection_as_executable_code()
+        if not text:
+            line = self.get_current_editor().get_current_line()
+            text = line.lstrip()
+        self.exec_in_extconsole.emit(text, self.focus_to_editor)
+
+    def run_cell(self):
+        """Run current cell"""
+        text = self.get_current_editor().get_cell_as_executable_code()
+        finfo = self.get_current_finfo()
+        if finfo.editor.is_python() and text:
+            self.exec_in_extconsole.emit(text, self.focus_to_editor)
+
+    def run_cell_and_advance(self):
+        """Run current cell and advance to the next one"""
+        self.run_cell()
+        if self.focus_to_editor:
+            self.get_current_editor().go_to_next_cell()
+        else:
+            term = QApplication.focusWidget()
+            self.get_current_editor().go_to_next_cell()
+            term.setFocus()
+            term = QApplication.focusWidget()
+            self.get_current_editor().go_to_next_cell()
+            term.setFocus()
+
+    #------ Drag and drop
+    def dragEnterEvent(self, event):
+        """Reimplement Qt method
+        Inform Qt about the types of data that the widget accepts"""
+        source = event.mimeData()
+        # The second check is necessary on Windows, where source.hasUrls()
+        # can return True but source.urls() is []
+        if source.hasUrls() and source.urls():
+            if mimedata2url(source, extlist=EDIT_EXT):
+                event.acceptProposedAction()
+            else:
+                all_urls = mimedata2url(source)
+                text = [encoding.is_text_file(url) for url in all_urls]
+                if any(text):
+                    event.acceptProposedAction()
+                else:
+                    event.ignore()
+        elif source.hasText():
+            event.acceptProposedAction()
+        elif os.name == 'nt':
+            # This covers cases like dragging from compressed files,
+            # which can be opened by the Editor if they are plain
+            # text, but doesn't come with url info.
+            # Fixes Issue 2032
+            event.acceptProposedAction()
+        else:
+            event.ignore()
+
+    def dropEvent(self, event):
+        """Reimplement Qt method
+        Unpack dropped data and handle it"""
+        source = event.mimeData()
+        if source.hasUrls():
+            files = mimedata2url(source)
+            files = [f for f in files if encoding.is_text_file(f)]
+            supported_files = mimedata2url(source, extlist=EDIT_EXT)
+            files = set(files or []) | set(supported_files or [])
+            for fname in files:
+                self.plugin_load.emit(fname)
+        elif source.hasText():
+            editor = self.get_current_editor()
+            if editor is not None:
+                editor.insert_text( source.text() )
+        event.acceptProposedAction()
+
+
+class EditorSplitter(QSplitter):
+    def __init__(self, parent, plugin, menu_actions, first=False,
+                 register_editorstack_cb=None, unregister_editorstack_cb=None):
+        QSplitter.__init__(self, parent)
+        self.setAttribute(Qt.WA_DeleteOnClose)
+        self.setChildrenCollapsible(False)
+
+        self.toolbar_list = None
+        self.menu_list = None
+
+        self.plugin = plugin
+
+        if register_editorstack_cb is None:
+            register_editorstack_cb = self.plugin.register_editorstack
+        self.register_editorstack_cb = register_editorstack_cb
+        if unregister_editorstack_cb is None:
+            unregister_editorstack_cb = self.plugin.unregister_editorstack
+        self.unregister_editorstack_cb = unregister_editorstack_cb
+
+        self.menu_actions = menu_actions
+        self.editorstack = EditorStack(self, menu_actions)
+        self.register_editorstack_cb(self.editorstack)
+        if not first:
+            self.plugin.clone_editorstack(editorstack=self.editorstack)
+        self.editorstack.destroyed.connect(lambda: self.editorstack_closed())
+        self.editorstack.split_vertically.connect(
+                     lambda: self.split(orientation=Qt.Vertical))
+        self.editorstack.split_horizontally.connect(
+                     lambda: self.split(orientation=Qt.Horizontal))
+        self.addWidget(self.editorstack)
+
+    def closeEvent(self, event):
+        QSplitter.closeEvent(self, event)
+        if is_pyqt46:
+            self.destroyed.emit()
+
+    def __give_focus_to_remaining_editor(self):
+        focus_widget = self.plugin.get_focus_widget()
+        if focus_widget is not None:
+            focus_widget.setFocus()
+
+    def editorstack_closed(self):
+        if DEBUG_EDITOR:
+            print("method 'editorstack_closed':", file=STDOUT)
+            print("    self  :", self, file=STDOUT)
+#            print >>STDOUT, "    sender:", self.sender()
+        self.unregister_editorstack_cb(self.editorstack)
+        self.editorstack = None
+        try:
+            close_splitter = self.count() == 1
+        except RuntimeError:
+            # editorsplitter has been destroyed (happens when closing a
+            # EditorMainWindow instance)
+            return
+        if close_splitter:
+            # editorstack just closed was the last widget in this QSplitter
+            self.close()
+            return
+        self.__give_focus_to_remaining_editor()
+
+    def editorsplitter_closed(self):
+        if DEBUG_EDITOR:
+            print("method 'editorsplitter_closed':", file=STDOUT)
+            print("    self  :", self, file=STDOUT)
+#            print >>STDOUT, "    sender:", self.sender()
+        try:
+            close_splitter = self.count() == 1 and self.editorstack is None
+        except RuntimeError:
+            # editorsplitter has been destroyed (happens when closing a
+            # EditorMainWindow instance)
+            return
+        if close_splitter:
+            # editorsplitter just closed was the last widget in this QSplitter
+            self.close()
+            return
+        elif self.count() == 2 and self.editorstack:
+            # back to the initial state: a single editorstack instance,
+            # as a single widget in this QSplitter: orientation may be changed
+            self.editorstack.reset_orientation()
+        self.__give_focus_to_remaining_editor()
+
+    def split(self, orientation=Qt.Vertical):
+        self.setOrientation(orientation)
+        self.editorstack.set_orientation(orientation)
+        editorsplitter = EditorSplitter(self.parent(), self.plugin,
+                    self.menu_actions,
+                    register_editorstack_cb=self.register_editorstack_cb,
+                    unregister_editorstack_cb=self.unregister_editorstack_cb)
+        self.addWidget(editorsplitter)
+        editorsplitter.destroyed.connect(lambda: self.editorsplitter_closed())
+        current_editor = editorsplitter.editorstack.get_current_editor()
+        if current_editor is not None:
+            current_editor.setFocus()
+
+    def iter_editorstacks(self):
+        editorstacks = [(self.widget(0), self.orientation())]
+        if self.count() > 1:
+            editorsplitter = self.widget(1)
+            editorstacks += editorsplitter.iter_editorstacks()
+        return editorstacks
+
+    def get_layout_settings(self):
+        """Return layout state"""
+        splitsettings = []
+        for editorstack, orientation in self.iter_editorstacks():
+            clines = [finfo.editor.get_cursor_line_number()
+                      for finfo in editorstack.data]
+            cfname = editorstack.get_current_filename()
+            splitsettings.append((orientation == Qt.Vertical, cfname, clines))
+        return dict(hexstate=qbytearray_to_str(self.saveState()),
+                    sizes=self.sizes(), splitsettings=splitsettings)
+
+    def set_layout_settings(self, settings):
+        """Restore layout state"""
+        splitsettings = settings.get('splitsettings')
+        if splitsettings is None:
+            return
+        splitter = self
+        editor = None
+        for index, (is_vertical, cfname, clines) in enumerate(splitsettings):
+            if index > 0:
+                splitter.split(Qt.Vertical if is_vertical else Qt.Horizontal)
+                splitter = splitter.widget(1)
+            editorstack = splitter.widget(0)
+            for index, finfo in enumerate(editorstack.data):
+                editor = finfo.editor
+                editor.go_to_line(clines[index])
+            editorstack.set_current_filename(cfname)
+        hexstate = settings.get('hexstate')
+        if hexstate is not None:
+            self.restoreState( QByteArray().fromHex(
+                    str(hexstate).encode('utf-8')) )
+        sizes = settings.get('sizes')
+        if sizes is not None:
+            self.setSizes(sizes)
+        if editor is not None:
+            editor.clearFocus()
+            editor.setFocus()
+
+
+class EditorWidget(QSplitter):
+    def __init__(self, parent, plugin, menu_actions, show_fullpath,
+                 fullpath_sorting, show_all_files, show_comments):
+        QSplitter.__init__(self, parent)
+        self.setAttribute(Qt.WA_DeleteOnClose)
+
+        statusbar = parent.statusBar() # Create a status bar
+        self.readwrite_status = ReadWriteStatus(self, statusbar)
+        self.eol_status = EOLStatus(self, statusbar)
+        self.encoding_status = EncodingStatus(self, statusbar)
+        self.cursorpos_status = CursorPositionStatus(self, statusbar)
+
+        self.editorstacks = []
+
+        self.plugin = plugin
+
+        self.find_widget = FindReplace(self, enable_replace=True)
+        self.plugin.register_widget_shortcuts("Editor", self.find_widget)
+        self.find_widget.hide()
+        self.outlineexplorer = OutlineExplorerWidget(self,
+                                            show_fullpath=show_fullpath,
+                                            fullpath_sorting=fullpath_sorting,
+                                            show_all_files=show_all_files,
+                                            show_comments=show_comments)
+        self.outlineexplorer.edit_goto.connect(
+                     lambda filenames, goto, word:
+                     plugin.load(filenames=filenames, goto=goto, word=word,
+                                 editorwindow=self.parent()))
+
+        editor_widgets = QWidget(self)
+        editor_layout = QVBoxLayout()
+        editor_layout.setContentsMargins(0, 0, 0, 0)
+        editor_widgets.setLayout(editor_layout)
+        editorsplitter = EditorSplitter(self, plugin, menu_actions,
+                        register_editorstack_cb=self.register_editorstack,
+                        unregister_editorstack_cb=self.unregister_editorstack)
+        self.editorsplitter = editorsplitter
+        editor_layout.addWidget(editorsplitter)
+        editor_layout.addWidget(self.find_widget)
+
+        splitter = QSplitter(self)
+        splitter.setContentsMargins(0, 0, 0, 0)
+        splitter.addWidget(editor_widgets)
+        splitter.addWidget(self.outlineexplorer)
+        splitter.setStretchFactor(0, 5)
+        splitter.setStretchFactor(1, 1)
+
+        # Refreshing outline explorer
+        editorsplitter.editorstack.initialize_outlineexplorer()
+
+    def register_editorstack(self, editorstack):
+        self.editorstacks.append(editorstack)
+        if DEBUG_EDITOR:
+            print("EditorWidget.register_editorstack:", editorstack, file=STDOUT)
+            self.__print_editorstacks()
+        self.plugin.last_focus_editorstack[self.parent()] = editorstack
+        editorstack.set_closable( len(self.editorstacks) > 1 )
+        editorstack.set_outlineexplorer(self.outlineexplorer)
+        editorstack.set_find_widget(self.find_widget)
+        editorstack.reset_statusbar.connect(self.readwrite_status.hide)
+        editorstack.reset_statusbar.connect(self.encoding_status.hide)
+        editorstack.reset_statusbar.connect(self.cursorpos_status.hide)
+        editorstack.readonly_changed.connect(
+                                        self.readwrite_status.readonly_changed)
+        editorstack.encoding_changed.connect(
+                                         self.encoding_status.encoding_changed)
+        editorstack.sig_editor_cursor_position_changed.connect(
+                     self.cursorpos_status.cursor_position_changed)
+        editorstack.refresh_eol_chars.connect(self.eol_status.eol_changed)
+        self.plugin.register_editorstack(editorstack)
+        oe_btn = create_toolbutton(self)
+        oe_btn.setDefaultAction(self.outlineexplorer.visibility_action)
+        editorstack.add_corner_widgets_to_tabbar([5, oe_btn])
+
+    def __print_editorstacks(self):
+        print("%d editorstack(s) in editorwidget:" \
+                        % len(self.editorstacks), file=STDOUT)
+        for edst in self.editorstacks:
+            print("    ", edst, file=STDOUT)
+
+    def unregister_editorstack(self, editorstack):
+        if DEBUG_EDITOR:
+            print("EditorWidget.unregister_editorstack:", editorstack, file=STDOUT)
+        self.plugin.unregister_editorstack(editorstack)
+        self.editorstacks.pop(self.editorstacks.index(editorstack))
+        if DEBUG_EDITOR:
+            self.__print_editorstacks()
+
+
+class EditorMainWindow(QMainWindow):
+    def __init__(self, plugin, menu_actions, toolbar_list, menu_list,
+                 show_fullpath, fullpath_sorting, show_all_files,
+                 show_comments):
+        QMainWindow.__init__(self)
+        self.setAttribute(Qt.WA_DeleteOnClose)
+
+        self.window_size = None
+
+        self.editorwidget = EditorWidget(self, plugin, menu_actions,
+                                         show_fullpath, fullpath_sorting,
+                                         show_all_files, show_comments)
+        self.setCentralWidget(self.editorwidget)
+
+        # Give focus to current editor to update/show all status bar widgets
+        editorstack = self.editorwidget.editorsplitter.editorstack
+        editor = editorstack.get_current_editor()
+        if editor is not None:
+            editor.setFocus()
+
+        self.setWindowTitle("Spyder - %s" % plugin.windowTitle())
+        self.setWindowIcon(plugin.windowIcon())
+
+        if toolbar_list:
+            toolbars = []
+            for title, actions in toolbar_list:
+                toolbar = self.addToolBar(title)
+                toolbar.setObjectName(str(id(toolbar)))
+                add_actions(toolbar, actions)
+                toolbars.append(toolbar)
+        if menu_list:
+            quit_action = create_action(self, _("Close window"),
+                                        icon="close_panel.png",
+                                        tip=_("Close this window"),
+                                        triggered=self.close)
+            menus = []
+            for index, (title, actions) in enumerate(menu_list):
+                menu = self.menuBar().addMenu(title)
+                if index == 0:
+                    # File menu
+                    add_actions(menu, actions+[None, quit_action])
+                else:
+                    add_actions(menu, actions)
+                menus.append(menu)
+
+    def resizeEvent(self, event):
+        """Reimplement Qt method"""
+        if not self.isMaximized() and not self.isFullScreen():
+            self.window_size = self.size()
+        QMainWindow.resizeEvent(self, event)
+
+    def closeEvent(self, event):
+        """Reimplement Qt method"""
+        QMainWindow.closeEvent(self, event)
+        if is_pyqt46:
+            self.destroyed.emit()
+            for editorstack in self.editorwidget.editorstacks[:]:
+                if DEBUG_EDITOR:
+                    print("--> destroy_editorstack:", editorstack, file=STDOUT)
+                editorstack.destroyed.emit()
+
+    def get_layout_settings(self):
+        """Return layout state"""
+        splitsettings = self.editorwidget.editorsplitter.get_layout_settings()
+        return dict(size=(self.window_size.width(), self.window_size.height()),
+                    pos=(self.pos().x(), self.pos().y()),
+                    is_maximized=self.isMaximized(),
+                    is_fullscreen=self.isFullScreen(),
+                    hexstate=qbytearray_to_str(self.saveState()),
+                    splitsettings=splitsettings)
+
+    def set_layout_settings(self, settings):
+        """Restore layout state"""
+        size = settings.get('size')
+        if size is not None:
+            self.resize( QSize(*size) )
+            self.window_size = self.size()
+        pos = settings.get('pos')
+        if pos is not None:
+            self.move( QPoint(*pos) )
+        hexstate = settings.get('hexstate')
+        if hexstate is not None:
+            self.restoreState( QByteArray().fromHex(
+                    str(hexstate).encode('utf-8')) )
+        if settings.get('is_maximized'):
+            self.setWindowState(Qt.WindowMaximized)
+        if settings.get('is_fullscreen'):
+            self.setWindowState(Qt.WindowFullScreen)
+        splitsettings = settings.get('splitsettings')
+        if splitsettings is not None:
+            self.editorwidget.editorsplitter.set_layout_settings(splitsettings)
+
+
+class EditorPluginExample(QSplitter):
+    def __init__(self):
+        QSplitter.__init__(self)
+
+        menu_actions = []
+
+        self.editorstacks = []
+        self.editorwindows = []
+
+        self.last_focus_editorstack = {} # fake
+
+        self.find_widget = FindReplace(self, enable_replace=True)
+        self.outlineexplorer = OutlineExplorerWidget(self, show_fullpath=False,
+                                                     show_all_files=False)
+        self.outlineexplorer.edit_goto.connect(self.go_to_file)
+
+        editor_widgets = QWidget(self)
+        editor_layout = QVBoxLayout()
+        editor_layout.setContentsMargins(0, 0, 0, 0)
+        editor_widgets.setLayout(editor_layout)
+        editor_layout.addWidget(EditorSplitter(self, self, menu_actions,
+                                               first=True))
+        editor_layout.addWidget(self.find_widget)
+
+        self.setContentsMargins(0, 0, 0, 0)
+        self.addWidget(editor_widgets)
+        self.addWidget(self.outlineexplorer)
+
+        self.setStretchFactor(0, 5)
+        self.setStretchFactor(1, 1)
+
+        self.menu_actions = menu_actions
+        self.toolbar_list = None
+        self.menu_list = None
+        self.setup_window([], [])
+
+    def go_to_file(self, fname, lineno, text):
+        editorstack = self.editorstacks[0]
+        editorstack.set_current_filename(to_text_string(fname))
+        editor = editorstack.get_current_editor()
+        editor.go_to_line(lineno, word=text)
+
+    def closeEvent(self, event):
+        for win in self.editorwindows[:]:
+            win.close()
+        if DEBUG_EDITOR:
+            print(len(self.editorwindows), ":", self.editorwindows, file=STDOUT)
+            print(len(self.editorstacks), ":", self.editorstacks, file=STDOUT)
+
+        event.accept()
+
+    def load(self, fname):
+        QApplication.processEvents()
+        editorstack = self.editorstacks[0]
+        editorstack.load(fname)
+        editorstack.analyze_script()
+
+    def register_editorstack(self, editorstack):
+        if DEBUG_EDITOR:
+            print("FakePlugin.register_editorstack:", editorstack, file=STDOUT)
+        self.editorstacks.append(editorstack)
+        if self.isAncestorOf(editorstack):
+            # editorstack is a child of the Editor plugin
+            editorstack.set_fullpath_sorting_enabled(True)
+            editorstack.set_closable( len(self.editorstacks) > 1 )
+            editorstack.set_outlineexplorer(self.outlineexplorer)
+            editorstack.set_find_widget(self.find_widget)
+            oe_btn = create_toolbutton(self)
+            oe_btn.setDefaultAction(self.outlineexplorer.visibility_action)
+            editorstack.add_corner_widgets_to_tabbar([5, oe_btn])
+
+        action = QAction(self)
+        editorstack.set_io_actions(action, action, action, action)
+        font = QFont("Courier New")
+        font.setPointSize(10)
+        editorstack.set_default_font(font, color_scheme='Spyder')
+
+        editorstack.sig_close_file.connect(self.close_file_in_all_editorstacks)
+        editorstack.file_saved.connect(self.file_saved_in_editorstack)
+        editorstack.file_renamed_in_data.connect(
+                                      self.file_renamed_in_data_in_editorstack)
+        editorstack.create_new_window.connect(self.create_new_window)
+        editorstack.plugin_load.connect(self.load)
+
+    def unregister_editorstack(self, editorstack):
+        if DEBUG_EDITOR:
+            print("FakePlugin.unregister_editorstack:", editorstack, file=STDOUT)
+        self.editorstacks.pop(self.editorstacks.index(editorstack))
+
+    def clone_editorstack(self, editorstack):
+        editorstack.clone_from(self.editorstacks[0])
+
+    def setup_window(self, toolbar_list, menu_list):
+        self.toolbar_list = toolbar_list
+        self.menu_list = menu_list
+
+    def create_new_window(self):
+        window = EditorMainWindow(self, self.menu_actions,
+                                  self.toolbar_list, self.menu_list,
+                                  show_fullpath=False, fullpath_sorting=True,
+                                  show_all_files=False, show_comments=True)
+        window.resize(self.size())
+        window.show()
+        self.register_editorwindow(window)
+        window.destroyed.connect(lambda: self.unregister_editorwindow(window))
+
+    def register_editorwindow(self, window):
+        if DEBUG_EDITOR:
+            print("register_editorwindowQObject*:", window, file=STDOUT)
+        self.editorwindows.append(window)
+
+    def unregister_editorwindow(self, window):
+        if DEBUG_EDITOR:
+            print("unregister_editorwindow:", window, file=STDOUT)
+        self.editorwindows.pop(self.editorwindows.index(window))
+
+    def get_focus_widget(self):
+        pass
+
+    @Slot(int, int)
+    def close_file_in_all_editorstacks(self, editorstack_id_str, index):
+        for editorstack in self.editorstacks:
+            if str(id(editorstack)) != editorstack_id_str:
+                editorstack.blockSignals(True)
+                editorstack.close_file(index, force=True)
+                editorstack.blockSignals(False)
+
+    # This method is never called in this plugin example. It's here only
+    # to show how to use the file_saved signal (see above).
+    @Slot(int, int)
+    def file_saved_in_editorstack(self, editorstack_id_str, index, filename):
+        """A file was saved in editorstack, this notifies others"""
+        for editorstack in self.editorstacks:
+            if str(id(editorstack)) != editorstack_id_str:
+                editorstack.file_saved_in_other_editorstack(index, filename)
+
+    # This method is never called in this plugin example. It's here only
+    # to show how to use the file_saved signal (see above).
+    @Slot(int, int)
+    def file_renamed_in_data_in_editorstack(self, editorstack_id_str,
+                                            index, filename):
+        """A file was renamed in data in editorstack, this notifies others"""
+        for editorstack in self.editorstacks:
+            if str(id(editorstack)) != editorstack_id_str:
+                editorstack.rename_in_data(index, filename)
+
+    def register_widget_shortcuts(self, context, widget):
+        """Fake!"""
+        pass
+
+
+def test():
+    from spyderlib.utils.qthelpers import qapplication
+    app = qapplication()
+    test = EditorPluginExample()
+    test.resize(900, 700)
+    test.show()
+    import time
+    cur_dir = osp.dirname(osp.abspath(__file__))
+    t0 = time.time()
+    test.load(osp.join(cur_dir, "editor.py"))
+    test.load(osp.join(cur_dir, "explorer.py"))
+    test.load(osp.join(cur_dir, "variableexplorer", "collectionseditor.py"))
+    test.load(osp.join(cur_dir, "sourcecode", "codeeditor.py"))
+    print("Elapsed time: %.3f s" % (time.time()-t0))
+    sys.exit(app.exec_())
+
+
+if __name__ == "__main__":
+    test()
diff --git a/spyderlib/widgets/editortools.py b/spyderlib/widgets/editortools.py
index c613266..48ba59b 100644
--- a/spyderlib/widgets/editortools.py
+++ b/spyderlib/widgets/editortools.py
@@ -13,13 +13,14 @@ import os.path as osp
 
 from spyderlib.qt.QtGui import (QWidget, QTreeWidgetItem,  QHBoxLayout,
                                 QVBoxLayout)
-from spyderlib.qt.QtCore import Qt, SIGNAL
+from spyderlib.qt.QtCore import Qt, Signal, Slot
 from spyderlib.qt.compat import from_qvariant
+import spyderlib.utils.icon_manager as ima
 
 # Local import
-from spyderlib.baseconfig import _, STDOUT
-from spyderlib.utils.qthelpers import (get_icon, create_action,
-                                       create_toolbutton, set_item_user_text)
+from spyderlib.config.base import _, STDOUT
+from spyderlib.utils.qthelpers import (create_action, create_toolbutton,
+                                       set_item_user_text)
 from spyderlib.widgets.onecolumntree import OneColumnTree
 from spyderlib.py3compat import to_text_string
 
@@ -51,7 +52,7 @@ class FileRootItem(QTreeWidgetItem):
     def __init__(self, path, treewidget):
         QTreeWidgetItem.__init__(self, treewidget, QTreeWidgetItem.Type)
         self.path = path
-        self.setIcon(0, get_icon('python.png'))
+        self.setIcon(0, ima.icon('python'))
         self.setToolTip(0, path)
         set_item_user_text(self, path)
         
@@ -86,15 +87,15 @@ class TreeItem(QTreeWidgetItem):
         set_item_user_text(self, parent_text+'/'+name)
         self.line = line
         
-    def set_icon(self, icon_name):
-        self.setIcon(0, get_icon(icon_name))
+    def set_icon(self, icon):
+        self.setIcon(0, icon)
         
     def setup(self):
         self.setToolTip(0, _("Line %s") % str(self.line))
 
 class ClassItem(TreeItem):
     def setup(self):
-        self.set_icon('class.png')
+        self.set_icon(ima.icon('class'))
         self.setToolTip(0, _("Class defined at line %s") % str(self.line))
 
 class FunctionItem(TreeItem):
@@ -106,13 +107,13 @@ class FunctionItem(TreeItem):
             self.setToolTip(0, _("Method defined at line %s") % str(self.line))
             name = to_text_string(self.text(0))
             if name.startswith('__'):
-                self.set_icon('private2.png')
+                self.set_icon(ima.icon('private2'))
             elif name.startswith('_'):
-                self.set_icon('private1.png')
+                self.set_icon(ima.icon('private1'))
             else:
-                self.set_icon('method.png')
+                self.set_icon(ima.icon('method'))
         else:
-            self.set_icon('function.png')
+            self.set_icon(ima.icon('function'))
             self.setToolTip(0, _("Function defined at line %s"
                                  ) % str(self.line))
 
@@ -122,7 +123,7 @@ class CommentItem(TreeItem):
         TreeItem.__init__(self, name, line, parent, preceding)
 
     def setup(self):
-        self.set_icon('blockcomment.png')
+        self.set_icon(ima.icon('blockcomment'))
         font = self.font(0)
         font.setItalic(True)
         self.setFont(0, font)
@@ -141,7 +142,7 @@ class CellItem(TreeItem):
         TreeItem.__init__(self, name, line, parent, preceding)
 
     def setup(self):
-        self.set_icon('cell.png')
+        self.set_icon(ima.icon('cell'))
         font = self.font(0)
         font.setItalic(True)
         self.setFont(0, font)
@@ -199,7 +200,7 @@ class OutlineExplorerTreeWidget(OneColumnTree):
     def get_actions_from_items(self, items):
         """Reimplemented OneColumnTree method"""
         fromcursor_act = create_action(self, text=_('Go to cursor position'),
-                        icon=get_icon('fromcursor.png'),
+                        icon=ima.icon('fromcursor'),
                         triggered=self.go_to_cursor_position)
         fullpath_act = create_action(self, text=_( 'Show absolute path'),
                         toggled=self.toggle_fullpath_mode)
@@ -212,7 +213,8 @@ class OutlineExplorerTreeWidget(OneColumnTree):
         comment_act.setChecked(self.show_comments)
         actions = [fullpath_act, allfiles_act, comment_act, fromcursor_act]
         return actions
-    
+
+    @Slot(bool)
     def toggle_fullpath_mode(self, state):
         self.show_fullpath = state
         self.setTextElideMode(Qt.ElideMiddle if state else Qt.ElideRight)
@@ -226,14 +228,16 @@ class OutlineExplorerTreeWidget(OneColumnTree):
         """
         for _it in self.get_top_level_items():
             _it.setHidden(_it is not item and not self.show_all_files)
-            
+
+    @Slot(bool)
     def toggle_show_all_files(self, state):
         self.show_all_files = state
         if self.current_editor is not None:
             editor_id = self.editor_ids[self.current_editor]
             item = self.editor_items[editor_id]
             self.__hide_or_show_root_items(item)
-            
+
+    @Slot(bool)
     def toggle_show_comments(self, state):
         self.show_comments = state
         self.update_all()
@@ -241,7 +245,8 @@ class OutlineExplorerTreeWidget(OneColumnTree):
     def set_fullpath_sorting(self, state):
         self.fullpath_sorting = state
         self.__sort_toplevel_items()
-        
+
+    @Slot()
     def go_to_cursor_position(self):
         if self.current_editor is not None:
             line = self.current_editor.get_cursor_line_number()
@@ -464,10 +469,9 @@ class OutlineExplorerTreeWidget(OneColumnTree):
         root_item = self.get_root_item(item)
         self.freeze = True
         if line:
-            self.parent().emit(SIGNAL("edit_goto(QString,int,QString)"),
-                               root_item.path, line, item.text(0))
+            self.parent().edit_goto.emit(root_item.path, line, item.text(0))
         else:
-            self.parent().emit(SIGNAL("edit(QString)"), root_item.path)
+            self.parent().edit.emit(root_item.path)
         self.freeze = False
         parent = self.current_editor.parent()
         for editor_id, i_item in list(self.editor_items.items()):
@@ -487,13 +491,11 @@ class OutlineExplorerTreeWidget(OneColumnTree):
 
 
 class OutlineExplorerWidget(QWidget):
-    """
-    Class browser
+    """Class browser"""
+    edit_goto = Signal(str, int, str)
+    edit = Signal(str)
+    outlineexplorer_is_visible = Signal()
     
-    Signals:
-        SIGNAL("edit_goto(QString,int,QString)")
-        SIGNAL("edit(QString)")
-    """
     def __init__(self, parent=None, show_fullpath=True, fullpath_sorting=True,
                  show_all_files=True, show_comments=True):
         QWidget.__init__(self, parent)
@@ -520,7 +522,8 @@ class OutlineExplorerWidget(QWidget):
         layout.addLayout(btn_layout)
         layout.addWidget(self.treewidget)
         self.setLayout(layout)
-        
+
+    @Slot(bool)
     def toggle_visibility(self, state):
         self.setVisible(state)
         current_editor = self.treewidget.current_editor
@@ -528,11 +531,11 @@ class OutlineExplorerWidget(QWidget):
             current_editor.clearFocus()
             current_editor.setFocus()
             if state:
-                self.emit(SIGNAL("outlineexplorer_is_visible()"))
+                self.outlineexplorer_is_visible.emit()
         
     def setup_buttons(self):
         fromcursor_btn = create_toolbutton(self,
-                             icon=get_icon("fromcursor.png"),
+                             icon=ima.icon('fromcursor'),
                              tip=_('Go to cursor position'),
                              triggered=self.treewidget.go_to_cursor_position)
         collapse_btn = create_toolbutton(self)
diff --git a/spyderlib/widgets/explorer.py b/spyderlib/widgets/explorer.py
index 414736e..4eb2bf7 100644
--- a/spyderlib/widgets/explorer.py
+++ b/spyderlib/widgets/explorer.py
@@ -1,1107 +1,1155 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright © 2009-2010 Pierre Raybaut
-# Licensed under the terms of the MIT License
-# (see spyderlib/__init__.py for details)
-
-"""Files and Directories Explorer"""
-
-# pylint: disable=C0103
-# pylint: disable=R0903
-# pylint: disable=R0911
-# pylint: disable=R0201
-
-from __future__ import with_statement
-
-from spyderlib.qt.QtGui import (QVBoxLayout, QLabel, QHBoxLayout, QInputDialog,
-                                QFileSystemModel, QMenu, QWidget, QToolButton,
-                                QLineEdit, QMessageBox, QToolBar, QTreeView,
-                                QDrag, QSortFilterProxyModel)
-from spyderlib.qt.QtCore import (Qt, SIGNAL, QMimeData, QSize, QDir, QUrl,
-                                 Signal, QTimer)
-from spyderlib.qt.compat import getsavefilename, getexistingdirectory
-
-import os
-import sys
-import re
-import os.path as osp
-import shutil
-
-# Local imports
-from spyderlib.utils.qthelpers import (get_icon, create_action, add_actions,
-                                       file_uri, get_std_icon)
-from spyderlib.utils import misc, encoding, programs, vcs
-from spyderlib.baseconfig import _
-from spyderlib.py3compat import (to_text_string, to_binary_string, getcwd,
-                                 str_lower)
-
-try:
-    from IPython.nbconvert import PythonExporter as nbexporter
-except:
-    nbexporter = None      # analysis:ignore
-
-
-def fixpath(path):
-    """Normalize path fixing case, making absolute and removing symlinks"""
-    norm = osp.normcase if os.name == 'nt' else osp.normpath
-    return norm(osp.abspath(osp.realpath(path)))
-
-
-def create_script(fname):
-    """Create a new Python script"""
-    text = os.linesep.join(["# -*- coding: utf-8 -*-", "", ""])
-    encoding.write(to_text_string(text), fname, 'utf-8')
-
-
-def listdir(path, include='.', exclude=r'\.pyc$|^\.', show_all=False,
-            folders_only=False):
-    """List files and directories"""
-    namelist = []
-    dirlist = [to_text_string(osp.pardir)]
-    for item in os.listdir(to_text_string(path)):
-        if re.search(exclude, item) and not show_all:
-            continue
-        if osp.isdir(osp.join(path, item)):
-            dirlist.append(item)
-        elif folders_only:
-            continue
-        elif re.search(include, item) or show_all:
-            namelist.append(item)
-    return sorted(dirlist, key=str_lower) + \
-           sorted(namelist, key=str_lower)
-
-
-def has_subdirectories(path, include, exclude, show_all):
-    """Return True if path has subdirectories"""
-    try:
-        # > 1 because of '..'
-        return len( listdir(path, include, exclude,
-                            show_all, folders_only=True) ) > 1
-    except (IOError, OSError):
-        return False
-
-
-class DirView(QTreeView):
-    """Base file/directory tree view"""
-    def __init__(self, parent=None):
-        super(DirView, self).__init__(parent)
-        self.name_filters = None
-        self.parent_widget = parent
-        self.show_all = None
-        self.menu = None
-        self.common_actions = None
-        self.__expanded_state = None
-        self._to_be_loaded = None
-        self.fsmodel = None
-        self.setup_fs_model()
-        self._scrollbar_positions = None
-                
-    #---- Model
-    def setup_fs_model(self):
-        """Setup filesystem model"""
-        filters = QDir.AllDirs | QDir.Files | QDir.Drives | QDir.NoDotAndDotDot
-        self.fsmodel = QFileSystemModel(self)
-        self.fsmodel.setFilter(filters)
-        self.fsmodel.setNameFilterDisables(False)
-        
-    def install_model(self):
-        """Install filesystem model"""
-        self.setModel(self.fsmodel)
-        
-    def setup_view(self):
-        """Setup view"""
-        self.install_model()
-        self.connect(self.fsmodel, SIGNAL('directoryLoaded(QString)'),
-                     lambda: self.resizeColumnToContents(0))
-        self.setAnimated(False)
-        self.setSortingEnabled(True)
-        self.sortByColumn(0, Qt.AscendingOrder)
-        
-    def set_name_filters(self, name_filters):
-        """Set name filters"""
-        self.name_filters = name_filters
-        self.fsmodel.setNameFilters(name_filters)
-        
-    def set_show_all(self, state):
-        """Toggle 'show all files' state"""
-        if state:
-            self.fsmodel.setNameFilters([])
-        else:
-            self.fsmodel.setNameFilters(self.name_filters)
-            
-    def get_filename(self, index):
-        """Return filename associated with *index*"""
-        if index:
-            return osp.normpath(to_text_string(self.fsmodel.filePath(index)))
-        
-    def get_index(self, filename):
-        """Return index associated with filename"""
-        return self.fsmodel.index(filename)
-        
-    def get_selected_filenames(self):
-        """Return selected filenames"""
-        if self.selectionMode() == self.ExtendedSelection:
-            return [self.get_filename(idx) for idx in self.selectedIndexes()]
-        else:
-            return [self.get_filename(self.currentIndex())]
-            
-    def get_dirname(self, index):
-        """Return dirname associated with *index*"""
-        fname = self.get_filename(index)
-        if fname:
-            if osp.isdir(fname):
-                return fname
-            else:
-                return osp.dirname(fname)
-        
-    #---- Tree view widget
-    def setup(self, name_filters=['*.py', '*.pyw'], show_all=False):
-        """Setup tree widget"""
-        self.setup_view()
-        
-        self.set_name_filters(name_filters)
-        self.show_all = show_all
-        
-        # Setup context menu
-        self.menu = QMenu(self)
-        self.common_actions = self.setup_common_actions()
-        
-    #---- Context menu
-    def setup_common_actions(self):
-        """Setup context menu common actions"""
-        # Filters
-        filters_action = create_action(self, _("Edit filename filters..."),
-                                       None, get_icon('filter.png'),
-                                       triggered=self.edit_filter)
-        # Show all files
-        all_action = create_action(self, _("Show all files"),
-                                   toggled=self.toggle_all)
-        all_action.setChecked(self.show_all)
-        self.toggle_all(self.show_all)
-        
-        return [filters_action, all_action]
-        
-    def edit_filter(self):
-        """Edit name filters"""
-        filters, valid = QInputDialog.getText(self, _('Edit filename filters'),
-                                              _('Name filters:'),
-                                              QLineEdit.Normal,
-                                              ", ".join(self.name_filters))
-        if valid:
-            filters = [f.strip() for f in to_text_string(filters).split(',')]
-            self.parent_widget.sig_option_changed.emit('name_filters', filters)
-            self.set_name_filters(filters)
-            
-    def toggle_all(self, checked):
-        """Toggle all files mode"""
-        self.parent_widget.sig_option_changed.emit('show_all', checked)
-        self.show_all = checked
-        self.set_show_all(checked)
-        
-    def create_file_new_actions(self, fnames):
-        """Return actions for submenu 'New...'"""
-        if not fnames:
-            return []
-        new_file_act = create_action(self, _("File..."), icon='filenew.png',
-                                     triggered=lambda:
-                                     self.new_file(fnames[-1]))
-        new_module_act = create_action(self, _("Module..."), icon='py.png',
-                                       triggered=lambda:
-                                         self.new_module(fnames[-1]))
-        new_folder_act = create_action(self, _("Folder..."),
-                                       icon='folder_new.png',
-                                       triggered=lambda:
-                                        self.new_folder(fnames[-1]))
-        new_package_act = create_action(self, _("Package..."),
-                                        icon=get_icon('package_collapsed.png'),
-                                        triggered=lambda:
-                                         self.new_package(fnames[-1]))
-        return [new_file_act, new_folder_act, None,
-                new_module_act, new_package_act]
-        
-    def create_file_import_actions(self, fnames):
-        """Return actions for submenu 'Import...'"""
-        return []
-
-    def create_file_manage_actions(self, fnames):
-        """Return file management actions"""
-        only_files = all([osp.isfile(_fn) for _fn in fnames])
-        only_modules = all([osp.splitext(_fn)[1] in ('.py', '.pyw', '.ipy')
-                            for _fn in fnames])
-        only_notebooks = all([osp.splitext(_fn)[1] == '.ipynb'
-                              for _fn in fnames])
-        only_valid = all([encoding.is_text_file(_fn) for _fn in fnames])
-        run_action = create_action(self, _("Run"), icon="run_small.png",
-                                   triggered=self.run)
-        edit_action = create_action(self, _("Edit"), icon="edit.png",
-                                    triggered=self.clicked)
-        move_action = create_action(self, _("Move..."),
-                                    icon="move.png",
-                                    triggered=self.move)
-        delete_action = create_action(self, _("Delete..."),
-                                      icon="delete.png",
-                                      triggered=self.delete)
-        rename_action = create_action(self, _("Rename..."),
-                                      icon="rename.png",
-                                      triggered=self.rename)
-        open_action = create_action(self, _("Open"), triggered=self.open)
-        ipynb_convert_action = create_action(self, _("Convert to Python script"),
-                                             icon="python.png",
-                                             triggered=self.convert)
-        
-        actions = []
-        if only_modules:
-            actions.append(run_action)
-        if only_valid and only_files:
-            actions.append(edit_action)
-        else:
-            actions.append(open_action)
-        actions += [delete_action, rename_action]
-        basedir = fixpath(osp.dirname(fnames[0]))
-        if all([fixpath(osp.dirname(_fn)) == basedir for _fn in fnames]):
-            actions.append(move_action)
-        actions += [None]
-        if only_notebooks and nbexporter is not None:
-            actions.append(ipynb_convert_action)
-        
-        # VCS support is quite limited for now, so we are enabling the VCS
-        # related actions only when a single file/folder is selected:
-        dirname = fnames[0] if osp.isdir(fnames[0]) else osp.dirname(fnames[0])
-        if len(fnames) == 1 and vcs.is_vcs_repository(dirname):
-            vcs_ci = create_action(self, _("Commit"),
-                                   icon="vcs_commit.png",
-                                   triggered=lambda fnames=[dirname]:
-                                   self.vcs_command(fnames, 'commit'))
-            vcs_log = create_action(self, _("Browse repository"),
-                                    icon="vcs_browse.png",
-                                    triggered=lambda fnames=[dirname]:
-                                    self.vcs_command(fnames, 'browse'))
-            actions += [None, vcs_ci, vcs_log]
-        
-        return actions
-
-    def create_folder_manage_actions(self, fnames):
-        """Return folder management actions"""
-        actions = []
-        if os.name == 'nt':
-            _title = _("Open command prompt here")
-        else:
-            _title = _("Open terminal here")
-        action = create_action(self, _title, icon="cmdprompt.png",
-                               triggered=lambda fnames=fnames:
-                               self.open_terminal(fnames))
-        actions.append(action)
-        _title = _("Open Python console here")
-        action = create_action(self, _title, icon="python.png",
-                               triggered=lambda fnames=fnames:
-                               self.open_interpreter(fnames))
-        actions.append(action)
-        return actions
-        
-    def create_context_menu_actions(self):
-        """Create context menu actions"""
-        actions = []
-        fnames = self.get_selected_filenames()
-        new_actions = self.create_file_new_actions(fnames)
-        if len(new_actions) > 1:
-            # Creating a submenu only if there is more than one entry
-            new_act_menu = QMenu(_('New'), self)
-            add_actions(new_act_menu, new_actions)
-            actions.append(new_act_menu)
-        else:
-            actions += new_actions
-        import_actions = self.create_file_import_actions(fnames)
-        if len(import_actions) > 1:
-            # Creating a submenu only if there is more than one entry
-            import_act_menu = QMenu(_('Import'), self)
-            add_actions(import_act_menu, import_actions)
-            actions.append(import_act_menu)
-        else:
-            actions += import_actions
-        if actions:
-            actions.append(None)
-        if fnames:
-            actions += self.create_file_manage_actions(fnames)
-        if actions:
-            actions.append(None)
-        if fnames and all([osp.isdir(_fn) for _fn in fnames]):
-            actions += self.create_folder_manage_actions(fnames)
-        if actions:
-            actions.append(None)
-        actions += self.common_actions
-        return actions
-
-    def update_menu(self):
-        """Update context menu"""
-        self.menu.clear()
-        add_actions(self.menu, self.create_context_menu_actions())
-    
-    #---- Events
-    def viewportEvent(self, event):
-        """Reimplement Qt method"""
-
-        # Prevent Qt from crashing or showing warnings like:
-        # "QSortFilterProxyModel: index from wrong model passed to 
-        # mapFromSource", probably due to the fact that the file system model 
-        # is being built. See Issue 1250.
-        #
-        # This workaround was inspired by the following KDE bug:
-        # https://bugs.kde.org/show_bug.cgi?id=172198
-        #
-        # Apparently, this is a bug from Qt itself.
-        self.executeDelayedItemsLayout()
-        
-        return QTreeView.viewportEvent(self, event)        
-                
-    def contextMenuEvent(self, event):
-        """Override Qt method"""
-        self.update_menu()
-        self.menu.popup(event.globalPos())
-
-    def keyPressEvent(self, event):
-        """Reimplement Qt method"""
-        if event.key() in (Qt.Key_Enter, Qt.Key_Return):
-            self.clicked()
-        elif event.key() == Qt.Key_F2:
-            self.rename()
-        elif event.key() == Qt.Key_Delete:
-            self.delete()
-        else:
-            QTreeView.keyPressEvent(self, event)
-
-    def mouseDoubleClickEvent(self, event):
-        """Reimplement Qt method"""
-        QTreeView.mouseDoubleClickEvent(self, event)
-        self.clicked()
-        
-    def clicked(self):
-        """Selected item was double-clicked or enter/return was pressed"""
-        fnames = self.get_selected_filenames()
-        for fname in fnames:
-            if osp.isdir(fname):
-                self.directory_clicked(fname)
-            else:
-                self.open([fname])
-                
-    def directory_clicked(self, dirname):
-        """Directory was just clicked"""
-        pass
-        
-    #---- Drag
-    def dragEnterEvent(self, event):
-        """Drag and Drop - Enter event"""
-        event.setAccepted(event.mimeData().hasFormat("text/plain"))
-
-    def dragMoveEvent(self, event):
-        """Drag and Drop - Move event"""
-        if (event.mimeData().hasFormat("text/plain")):
-            event.setDropAction(Qt.MoveAction)
-            event.accept()
-        else:
-            event.ignore()
-            
-    def startDrag(self, dropActions):
-        """Reimplement Qt Method - handle drag event"""
-        data = QMimeData()
-        data.setUrls([QUrl(fname) for fname in self.get_selected_filenames()])
-        drag = QDrag(self)
-        drag.setMimeData(data)
-        drag.exec_()
-        
-    #---- File/Directory actions
-    def open(self, fnames=None):
-        """Open files with the appropriate application"""
-        if fnames is None:
-            fnames = self.get_selected_filenames()
-        for fname in fnames:
-            if osp.isfile(fname) and encoding.is_text_file(fname):
-                self.parent_widget.sig_open_file.emit(fname)
-            else:
-                self.open_outside_spyder([fname])
-        
-    def open_outside_spyder(self, fnames):
-        """Open file outside Spyder with the appropriate application
-        If this does not work, opening unknown file in Spyder, as text file"""
-        for path in sorted(fnames):
-            path = file_uri(path)
-            ok = programs.start_file(path)
-            if not ok:
-                self.parent_widget.emit(SIGNAL("edit(QString)"), path)
-                
-    def open_terminal(self, fnames):
-        """Open terminal"""
-        for path in sorted(fnames):
-            self.parent_widget.emit(SIGNAL("open_terminal(QString)"), path)
-            
-    def open_interpreter(self, fnames):
-        """Open interpreter"""
-        for path in sorted(fnames):
-            self.parent_widget.emit(SIGNAL("open_interpreter(QString)"), path)
-        
-    def run(self, fnames=None):
-        """Run Python scripts"""
-        if fnames is None:
-            fnames = self.get_selected_filenames()
-        for fname in fnames:
-            self.parent_widget.emit(SIGNAL("run(QString)"), fname)
-    
-    def remove_tree(self, dirname):
-        """Remove whole directory tree
-        Reimplemented in project explorer widget"""
-        shutil.rmtree(dirname, onerror=misc.onerror)
-    
-    def delete_file(self, fname, multiple, yes_to_all):
-        """Delete file"""
-        if multiple:
-            buttons = QMessageBox.Yes|QMessageBox.YesAll| \
-                      QMessageBox.No|QMessageBox.Cancel
-        else:
-            buttons = QMessageBox.Yes|QMessageBox.No
-        if yes_to_all is None:
-            answer = QMessageBox.warning(self, _("Delete"),
-                                 _("Do you really want "
-                                   "to delete <b>%s</b>?"
-                                   ) % osp.basename(fname), buttons)
-            if answer == QMessageBox.No:
-                return yes_to_all
-            elif answer == QMessageBox.Cancel:
-                return False
-            elif answer == QMessageBox.YesAll:
-                yes_to_all = True
-        try:
-            if osp.isfile(fname):
-                misc.remove_file(fname)
-                self.parent_widget.emit(SIGNAL("removed(QString)"),
-                                        fname)
-            else:
-                self.remove_tree(fname)
-                self.parent_widget.emit(SIGNAL("removed_tree(QString)"),
-                                        fname)
-            return yes_to_all
-        except EnvironmentError as error:
-            action_str = _('delete')
-            QMessageBox.critical(self, _("Project Explorer"),
-                            _("<b>Unable to %s <i>%s</i></b>"
-                              "<br><br>Error message:<br>%s"
-                              ) % (action_str, fname, to_text_string(error)))
-        return False
-        
-    def delete(self, fnames=None):
-        """Delete files"""
-        if fnames is None:
-            fnames = self.get_selected_filenames()
-        multiple = len(fnames) > 1
-        yes_to_all = None
-        for fname in fnames:
-            yes_to_all = self.delete_file(fname, multiple, yes_to_all)
-            if yes_to_all is not None and not yes_to_all:
-                # Canceled
-                return
-
-    def convert_notebook(self, fname):
-        """Convert an IPython notebook to a Python script in editor"""
-        try: 
-            script = nbexporter().from_filename(fname)[0]
-        except Exception as e:
-            QMessageBox.critical(self, _('Conversion error'), 
-                                 _("It was not possible to convert this "
-                                 "notebook. The error is:\n\n") + \
-                                 to_text_string(e))
-            return
-        self.parent_widget.sig_new_file.emit(script)
-    
-    def convert(self, fnames=None):
-        """Convert IPython notebooks to Python scripts in editor"""
-        if fnames is None:
-            fnames = self.get_selected_filenames()
-        if not isinstance(fnames, (tuple, list)):
-            fnames = [fnames]
-        for fname in fnames:
-            self.convert_notebook(fname)
-
-    def rename_file(self, fname):
-        """Rename file"""
-        path, valid = QInputDialog.getText(self, _('Rename'),
-                              _('New name:'), QLineEdit.Normal,
-                              osp.basename(fname))
-        if valid:
-            path = osp.join(osp.dirname(fname), to_text_string(path))
-            if path == fname:
-                return
-            if osp.exists(path):
-                if QMessageBox.warning(self, _("Rename"),
-                         _("Do you really want to rename <b>%s</b> and "
-                           "overwrite the existing file <b>%s</b>?"
-                           ) % (osp.basename(fname), osp.basename(path)),
-                         QMessageBox.Yes|QMessageBox.No) == QMessageBox.No:
-                    return
-            try:
-                misc.rename_file(fname, path)
-                self.parent_widget.emit( \
-                     SIGNAL("renamed(QString,QString)"), fname, path)
-                return path
-            except EnvironmentError as error:
-                QMessageBox.critical(self, _("Rename"),
-                            _("<b>Unable to rename file <i>%s</i></b>"
-                              "<br><br>Error message:<br>%s"
-                              ) % (osp.basename(fname), to_text_string(error)))
-    
-    def rename(self, fnames=None):
-        """Rename files"""
-        if fnames is None:
-            fnames = self.get_selected_filenames()
-        if not isinstance(fnames, (tuple, list)):
-            fnames = [fnames]
-        for fname in fnames:
-            self.rename_file(fname)
-        
-    def move(self, fnames=None):
-        """Move files/directories"""
-        if fnames is None:
-            fnames = self.get_selected_filenames()
-        orig = fixpath(osp.dirname(fnames[0]))
-        while True:
-            self.parent_widget.emit(SIGNAL('redirect_stdio(bool)'), False)
-            folder = getexistingdirectory(self, _("Select directory"), orig)
-            self.parent_widget.emit(SIGNAL('redirect_stdio(bool)'), True)
-            if folder:
-                folder = fixpath(folder)
-                if folder != orig:
-                    break
-            else:
-                return
-        for fname in fnames:
-            basename = osp.basename(fname)
-            try:
-                misc.move_file(fname, osp.join(folder, basename))
-            except EnvironmentError as error:
-                QMessageBox.critical(self, _("Error"),
-                                     _("<b>Unable to move <i>%s</i></b>"
-                                       "<br><br>Error message:<br>%s"
-                                       ) % (basename, to_text_string(error)))
-        
-    def create_new_folder(self, current_path, title, subtitle, is_package):
-        """Create new folder"""
-        if current_path is None:
-            current_path = ''
-        if osp.isfile(current_path):
-            current_path = osp.dirname(current_path)
-        name, valid = QInputDialog.getText(self, title, subtitle,
-                                           QLineEdit.Normal, "")
-        if valid:
-            dirname = osp.join(current_path, to_text_string(name))
-            try:
-                os.mkdir(dirname)
-            except EnvironmentError as error:
-                QMessageBox.critical(self, title,
-                                     _("<b>Unable "
-                                       "to create folder <i>%s</i></b>"
-                                       "<br><br>Error message:<br>%s"
-                                       ) % (dirname, to_text_string(error)))
-            finally:
-                if is_package:
-                    fname = osp.join(dirname, '__init__.py')
-                    try:
-                        with open(fname, 'wb') as f:
-                            f.write(to_binary_string('#'))
-                        return dirname
-                    except EnvironmentError as error:
-                        QMessageBox.critical(self, title,
-                                             _("<b>Unable "
-                                               "to create file <i>%s</i></b>"
-                                               "<br><br>Error message:<br>%s"
-                                               ) % (fname,
-                                                    to_text_string(error)))
-
-    def new_folder(self, basedir):
-        """New folder"""
-        title = _('New folder')
-        subtitle = _('Folder name:')
-        self.create_new_folder(basedir, title, subtitle, is_package=False)
-    
-    def new_package(self, basedir):
-        """New package"""
-        title = _('New package')
-        subtitle = _('Package name:')
-        self.create_new_folder(basedir, title, subtitle, is_package=True)
-    
-    def create_new_file(self, current_path, title, filters, create_func):
-        """Create new file
-        Returns True if successful"""
-        if current_path is None:
-            current_path = ''
-        if osp.isfile(current_path):
-            current_path = osp.dirname(current_path)
-        self.parent_widget.emit(SIGNAL('redirect_stdio(bool)'), False)
-        fname, _selfilter = getsavefilename(self, title, current_path, filters)
-        self.parent_widget.emit(SIGNAL('redirect_stdio(bool)'), True)
-        if fname:
-            try:
-                create_func(fname)
-                return fname
-            except EnvironmentError as error:
-                QMessageBox.critical(self, _("New file"),
-                                     _("<b>Unable to create file <i>%s</i>"
-                                       "</b><br><br>Error message:<br>%s"
-                                       ) % (fname, to_text_string(error)))
-
-    def new_file(self, basedir):
-        """New file"""
-        title = _("New file")
-        filters = _("All files")+" (*)"
-        def create_func(fname):
-            """File creation callback"""
-            if osp.splitext(fname)[1] in ('.py', '.pyw', '.ipy'):
-                create_script(fname)
-            else:
-                with open(fname, 'wb') as f:
-                    f.write(to_binary_string(''))
-        fname = self.create_new_file(basedir, title, filters, create_func)
-        if fname is not None:
-            self.open([fname])
-    
-    def new_module(self, basedir):
-        """New module"""
-        title = _("New module")
-        filters = _("Python scripts")+" (*.py *.pyw *.ipy)"
-        create_func = lambda fname: self.parent_widget.emit( \
-                                     SIGNAL("create_module(QString)"), fname)
-        self.create_new_file(basedir, title, filters, create_func)
-        
-    #----- VCS actions
-    def vcs_command(self, fnames, action):
-        """VCS action (commit, browse)"""
-        try:
-            for path in sorted(fnames):
-                vcs.run_vcs_tool(path, action)
-        except vcs.ActionToolNotFound as error:
-            msg = _("For %s support, please install one of the<br/> "
-                    "following tools:<br/><br/>  %s")\
-                        % (error.vcsname, ', '.join(error.tools))
-            QMessageBox.critical(self, _("Error"),
-                _("""<b>Unable to find external program.</b><br><br>%s""")
-                    % to_text_string(msg))
-        
-    #----- Settings
-    def get_scrollbar_position(self):
-        """Return scrollbar positions"""
-        return (self.horizontalScrollBar().value(),
-                self.verticalScrollBar().value())
-        
-    def set_scrollbar_position(self, position):
-        """Set scrollbar positions"""
-        # Scrollbars will be restored after the expanded state
-        self._scrollbar_positions = position
-        if self._to_be_loaded is not None and len(self._to_be_loaded) == 0:
-            self.restore_scrollbar_positions()
-            
-    def restore_scrollbar_positions(self):
-        """Restore scrollbar positions once tree is loaded"""
-        hor, ver = self._scrollbar_positions
-        self.horizontalScrollBar().setValue(hor)
-        self.verticalScrollBar().setValue(ver)
-        
-    def get_expanded_state(self):
-        """Return expanded state"""
-        self.save_expanded_state()
-        return self.__expanded_state
-    
-    def set_expanded_state(self, state):
-        """Set expanded state"""
-        self.__expanded_state = state
-        self.restore_expanded_state()
-    
-    def save_expanded_state(self):
-        """Save all items expanded state"""
-        model = self.model()
-        # If model is not installed, 'model' will be None: this happens when
-        # using the Project Explorer without having selected a workspace yet
-        if model is not None:
-            self.__expanded_state = []
-            for idx in model.persistentIndexList():
-                if self.isExpanded(idx):
-                    self.__expanded_state.append(self.get_filename(idx))
-
-    def restore_directory_state(self, fname):
-        """Restore directory expanded state"""
-        root = osp.normpath(to_text_string(fname))
-        if not osp.exists(root):
-            # Directory has been (re)moved outside Spyder
-            return
-        for basename in os.listdir(root):
-            path = osp.normpath(osp.join(root, basename))
-            if osp.isdir(path) and path in self.__expanded_state:
-                self.__expanded_state.pop(self.__expanded_state.index(path))
-                if self._to_be_loaded is None:
-                    self._to_be_loaded = []
-                self._to_be_loaded.append(path)
-                self.setExpanded(self.get_index(path), True)
-        if not self.__expanded_state:
-            self.disconnect(self.fsmodel, SIGNAL('directoryLoaded(QString)'),
-                            self.restore_directory_state)
-                
-    def follow_directories_loaded(self, fname):
-        """Follow directories loaded during startup"""
-        if self._to_be_loaded is None:
-            return
-        path = osp.normpath(to_text_string(fname))
-        if path in self._to_be_loaded:
-            self._to_be_loaded.remove(path)
-        if self._to_be_loaded is not None and len(self._to_be_loaded) == 0:
-            self.disconnect(self.fsmodel, SIGNAL('directoryLoaded(QString)'),
-                            self.follow_directories_loaded)
-            if self._scrollbar_positions is not None:
-                # The tree view need some time to render branches:
-                QTimer.singleShot(50, self.restore_scrollbar_positions)
-
-    def restore_expanded_state(self):
-        """Restore all items expanded state"""
-        if self.__expanded_state is not None:
-            # In the old project explorer, the expanded state was a dictionnary:
-            if isinstance(self.__expanded_state, list):
-                self.connect(self.fsmodel, SIGNAL('directoryLoaded(QString)'),
-                             self.restore_directory_state)
-                self.connect(self.fsmodel, SIGNAL('directoryLoaded(QString)'),
-                             self.follow_directories_loaded)
-
-
-class ProxyModel(QSortFilterProxyModel):
-    """Proxy model: filters tree view"""
-    def __init__(self, parent):
-        super(ProxyModel, self).__init__(parent)
-        self.root_path = None
-        self.path_list = []
-        self.setDynamicSortFilter(True)
-        
-    def setup_filter(self, root_path, path_list):
-        """Setup proxy model filter parameters"""
-        self.root_path = osp.normpath(to_text_string(root_path))
-        self.path_list = [osp.normpath(to_text_string(p)) for p in path_list]
-        self.invalidateFilter()
-
-    def sort(self, column, order=Qt.AscendingOrder):
-        """Reimplement Qt method"""
-        self.sourceModel().sort(column, order)
-        
-    def filterAcceptsRow(self, row, parent_index):
-        """Reimplement Qt method"""
-        if self.root_path is None:
-            return True
-        index = self.sourceModel().index(row, 0, parent_index)
-        path = osp.normpath(to_text_string(self.sourceModel().filePath(index)))
-        if self.root_path.startswith(path):
-            # This is necessary because parent folders need to be scanned
-            return True
-        else:
-            for p in self.path_list:
-                if path == p or path.startswith(p+os.sep):
-                    return True
-            else:
-                return False
-
-
-class FilteredDirView(DirView):
-    """Filtered file/directory tree view"""
-    def __init__(self, parent=None):
-        super(FilteredDirView, self).__init__(parent)
-        self.proxymodel = None
-        self.setup_proxy_model()
-        self.root_path = None
-        
-    #---- Model
-    def setup_proxy_model(self):
-        """Setup proxy model"""
-        self.proxymodel = ProxyModel(self)
-        self.proxymodel.setSourceModel(self.fsmodel)
-        
-    def install_model(self):
-        """Install proxy model"""
-        if self.root_path is not None:
-            self.fsmodel.setNameFilters(self.name_filters)
-            self.setModel(self.proxymodel)
-        
-    def set_root_path(self, root_path):
-        """Set root path"""
-        self.root_path = root_path
-        self.install_model()
-        index = self.fsmodel.setRootPath(root_path)
-        self.setRootIndex(self.proxymodel.mapFromSource(index))
-        
-    def get_index(self, filename):
-        """Return index associated with filename"""
-        index = self.fsmodel.index(filename)
-        if index.isValid() and index.model() is self.fsmodel:
-            return self.proxymodel.mapFromSource(index)
-        
-    def set_folder_names(self, folder_names):
-        """Set folder names"""
-        assert self.root_path is not None
-        path_list = [osp.join(self.root_path, dirname)
-                     for dirname in folder_names]
-        self.proxymodel.setup_filter(self.root_path, path_list)
-        
-    def get_filename(self, index):
-        """Return filename from index"""
-        if index:
-            path = self.fsmodel.filePath(self.proxymodel.mapToSource(index))
-            return osp.normpath(to_text_string(path))
-
-
-class ExplorerTreeWidget(DirView):
-    """File/directory explorer tree widget
-    show_cd_only: Show current directory only
-    (True/False: enable/disable the option
-     None: enable the option and do not allow the user to disable it)"""
-    def __init__(self, parent=None, show_cd_only=None):
-        DirView.__init__(self, parent)
-                
-        self.history = []
-        self.histindex = None
-
-        self.show_cd_only = show_cd_only
-        self.__original_root_index = None
-        self.__last_folder = None
-
-        self.menu = None
-        self.common_actions = None
-        
-        # Enable drag events
-        self.setDragEnabled(True)
-        
-    #---- Context menu
-    def setup_common_actions(self):
-        """Setup context menu common actions"""
-        actions = super(ExplorerTreeWidget, self).setup_common_actions()
-        if self.show_cd_only is None:
-            # Enabling the 'show current directory only' option but do not
-            # allow the user to disable it
-            self.show_cd_only = True
-        else:
-            # Show current directory only
-            cd_only_action = create_action(self,
-                                           _("Show current directory only"),
-                                           toggled=self.toggle_show_cd_only)
-            cd_only_action.setChecked(self.show_cd_only)
-            self.toggle_show_cd_only(self.show_cd_only)
-            actions.append(cd_only_action)
-        return actions
-            
-    def toggle_show_cd_only(self, checked):
-        """Toggle show current directory only mode"""
-        self.parent_widget.sig_option_changed.emit('show_cd_only', checked)
-        self.show_cd_only = checked
-        if checked:
-            if self.__last_folder is not None:
-                self.set_current_folder(self.__last_folder)
-        elif self.__original_root_index is not None:
-            self.setRootIndex(self.__original_root_index)
-        
-    #---- Refreshing widget
-    def set_current_folder(self, folder):
-        """Set current folder and return associated model index"""
-        index = self.fsmodel.setRootPath(folder)
-        self.__last_folder = folder
-        if self.show_cd_only:
-            if self.__original_root_index is None:
-                self.__original_root_index = self.rootIndex()
-            self.setRootIndex(index)
-        return index
-        
-    def refresh(self, new_path=None, force_current=False):
-        """Refresh widget
-        force=False: won't refresh widget if path has not changed"""
-        if new_path is None:
-            new_path = getcwd()
-        if force_current:
-            index = self.set_current_folder(new_path)
-            self.expand(index)
-            self.setCurrentIndex(index)
-        self.emit(SIGNAL("set_previous_enabled(bool)"),
-                  self.histindex is not None and self.histindex > 0)
-        self.emit(SIGNAL("set_next_enabled(bool)"),
-                  self.histindex is not None and \
-                  self.histindex < len(self.history)-1)
-            
-    #---- Events
-    def directory_clicked(self, dirname):
-        """Directory was just clicked"""
-        self.chdir(directory=dirname)
-        
-    #---- Files/Directories Actions
-    def go_to_parent_directory(self):
-        """Go to parent directory"""
-        self.chdir( osp.abspath(osp.join(getcwd(), os.pardir)) )
-        
-    def go_to_previous_directory(self):
-        """Back to previous directory"""
-        self.histindex -= 1
-        self.chdir(browsing_history=True)
-        
-    def go_to_next_directory(self):
-        """Return to next directory"""
-        self.histindex += 1
-        self.chdir(browsing_history=True)
-        
-    def update_history(self, directory):
-        """Update browse history"""
-        directory = osp.abspath(to_text_string(directory))
-        if directory in self.history:
-            self.histindex = self.history.index(directory)
-        
-    def chdir(self, directory=None, browsing_history=False):
-        """Set directory as working directory"""
-        if directory is not None:
-            directory = osp.abspath(to_text_string(directory))
-        if browsing_history:
-            directory = self.history[self.histindex]
-        elif directory in self.history:
-            self.histindex = self.history.index(directory)
-        else:
-            if self.histindex is None:
-                self.history = []
-            else:
-                self.history = self.history[:self.histindex+1]
-            if len(self.history) == 0 or \
-               (self.history and self.history[-1] != directory):
-                self.history.append(directory)
-            self.histindex = len(self.history)-1
-        directory = to_text_string(directory)
-        os.chdir(directory)
-        self.parent_widget.emit(SIGNAL("open_dir(QString)"), directory)
-        self.refresh(new_path=directory, force_current=True)
-
-
-class ExplorerWidget(QWidget):
-    """Explorer widget"""
-    sig_option_changed = Signal(str, object)
-    sig_open_file = Signal(str)
-    sig_new_file = Signal(str)
-    
-    def __init__(self, parent=None, name_filters=['*.py', '*.pyw'],
-                 show_all=False, show_cd_only=None, show_icontext=True):
-        QWidget.__init__(self, parent)
-        
-        self.treewidget = ExplorerTreeWidget(self, show_cd_only=show_cd_only)
-        self.treewidget.setup(name_filters=name_filters, show_all=show_all)
-        self.treewidget.chdir(getcwd())
-        
-        icontext_action = create_action(self, _("Show icons and text"),
-                                        toggled=self.toggle_icontext)
-        self.treewidget.common_actions += [None, icontext_action]
-        
-        # Setup toolbar
-        self.toolbar = QToolBar(self)
-        self.toolbar.setIconSize(QSize(16, 16))
-        
-        self.previous_action = create_action(self, text=_("Previous"),
-                            icon=get_std_icon("ArrowBack"),
-                            triggered=self.treewidget.go_to_previous_directory)
-        self.toolbar.addAction(self.previous_action)
-        self.previous_action.setEnabled(False)
-        self.connect(self.treewidget, SIGNAL("set_previous_enabled(bool)"),
-                     self.previous_action.setEnabled)
-        
-        self.next_action = create_action(self, text=_("Next"),
-                            icon=get_std_icon("ArrowForward"),
-                            triggered=self.treewidget.go_to_next_directory)
-        self.toolbar.addAction(self.next_action)
-        self.next_action.setEnabled(False)
-        self.connect(self.treewidget, SIGNAL("set_next_enabled(bool)"),
-                     self.next_action.setEnabled)
-        
-        parent_action = create_action(self, text=_("Parent"),
-                            icon=get_std_icon("ArrowUp"),
-                            triggered=self.treewidget.go_to_parent_directory)
-        self.toolbar.addAction(parent_action)
-        self.toolbar.addSeparator()
-
-        options_action = create_action(self, text='', tip=_("Options"),
-                                       icon=get_icon('tooloptions.png'))
-        self.toolbar.addAction(options_action)
-        widget = self.toolbar.widgetForAction(options_action)
-        widget.setPopupMode(QToolButton.InstantPopup)
-        menu = QMenu(self)
-        add_actions(menu, self.treewidget.common_actions)
-        options_action.setMenu(menu)
-            
-        icontext_action.setChecked(show_icontext)
-        self.toggle_icontext(show_icontext)     
-        
-        vlayout = QVBoxLayout()
-        vlayout.addWidget(self.toolbar)
-        vlayout.addWidget(self.treewidget)
-        self.setLayout(vlayout)
-
-    def toggle_icontext(self, state):
-        """Toggle icon text"""
-        self.sig_option_changed.emit('show_icontext', state)
-        for action in self.toolbar.actions():
-            if not action.isSeparator():
-                widget = self.toolbar.widgetForAction(action)
-                if state:
-                    widget.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
-                else:
-                    widget.setToolButtonStyle(Qt.ToolButtonIconOnly)
-
-
-class FileExplorerTest(QWidget):
-    def __init__(self):
-        QWidget.__init__(self)
-        vlayout = QVBoxLayout()
-        self.setLayout(vlayout)
-        self.explorer = ExplorerWidget(self, show_cd_only=None)
-        vlayout.addWidget(self.explorer)
-        
-        hlayout1 = QHBoxLayout()
-        vlayout.addLayout(hlayout1)
-        label = QLabel("<b>Open file:</b>")
-        label.setAlignment(Qt.AlignRight)
-        hlayout1.addWidget(label)
-        self.label1 = QLabel()
-        hlayout1.addWidget(self.label1)
-        self.explorer.sig_open_file.connect(self.label1.setText)
-        
-        hlayout2 = QHBoxLayout()
-        vlayout.addLayout(hlayout2)
-        label = QLabel("<b>Open dir:</b>")
-        label.setAlignment(Qt.AlignRight)
-        hlayout2.addWidget(label)
-        self.label2 = QLabel()
-        hlayout2.addWidget(self.label2)
-        self.connect(self.explorer, SIGNAL("open_dir(QString)"),
-                     self.label2.setText)
-        
-        hlayout3 = QHBoxLayout()
-        vlayout.addLayout(hlayout3)
-        label = QLabel("<b>Option changed:</b>")
-        label.setAlignment(Qt.AlignRight)
-        hlayout3.addWidget(label)
-        self.label3 = QLabel()
-        hlayout3.addWidget(self.label3)
-        self.explorer.sig_option_changed.connect(
-           lambda x, y: self.label3.setText('option_changed: %r, %r' % (x, y)))
-
-        self.connect(self.explorer, SIGNAL("open_parent_dir()"),
-                     lambda: self.explorer.listwidget.refresh('..'))
-
-class ProjectExplorerTest(QWidget):
-    def __init__(self, parent=None):
-        QWidget.__init__(self, parent)
-        vlayout = QVBoxLayout()
-        self.setLayout(vlayout)
-        self.treewidget = FilteredDirView(self)
-        self.treewidget.setup_view()
-        self.treewidget.set_root_path(r'D:\Python')
-        self.treewidget.set_folder_names(['spyder', 'spyder-2.0'])
-        vlayout.addWidget(self.treewidget)
-
-    
-if __name__ == "__main__":
-    from spyderlib.utils.qthelpers import qapplication
-    app = qapplication()
-    test = FileExplorerTest()
-#    test = ProjectExplorerTest()
-    test.resize(640, 480)
-    test.show()
-    sys.exit(app.exec_())
-    
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2009- The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+"""Files and Directories Explorer"""
+
+# pylint: disable=C0103
+# pylint: disable=R0903
+# pylint: disable=R0911
+# pylint: disable=R0201
+
+from __future__ import with_statement
+
+import os
+import re
+import os.path as osp
+import shutil
+
+from spyderlib.qt import is_pyqt46
+from spyderlib.qt.QtGui import (QVBoxLayout, QLabel, QHBoxLayout, QInputDialog,
+                                QFileSystemModel, QMenu, QWidget, QToolButton,
+                                QLineEdit, QMessageBox, QTreeView,
+                                QDrag, QSortFilterProxyModel)
+from spyderlib.qt.QtCore import (Qt, Signal, QMimeData, QSize, QDir, QUrl,
+                                 QTimer, Slot)
+from spyderlib.qt.compat import getsavefilename, getexistingdirectory
+import spyderlib.utils.icon_manager as ima
+
+# Local imports
+from spyderlib.utils.qthelpers import create_action, add_actions, file_uri
+from spyderlib.utils import misc, encoding, programs, vcs
+from spyderlib.config.base import _
+from spyderlib.py3compat import (PY2, to_text_string, to_binary_string, getcwd,
+                                 str_lower)
+
+try:
+    from IPython.nbconvert import PythonExporter as nbexporter
+except:
+    nbexporter = None      # analysis:ignore
+
+
+def fixpath(path):
+    """Normalize path fixing case, making absolute and removing symlinks"""
+    norm = osp.normcase if os.name == 'nt' else osp.normpath
+    return norm(osp.abspath(osp.realpath(path)))
+
+
+def create_script(fname):
+    """Create a new Python script"""
+    text = os.linesep.join(["# -*- coding: utf-8 -*-", "", ""])
+    encoding.write(to_text_string(text), fname, 'utf-8')
+
+
+def listdir(path, include='.', exclude=r'\.pyc$|^\.', show_all=False,
+            folders_only=False):
+    """List files and directories"""
+    namelist = []
+    dirlist = [to_text_string(osp.pardir)]
+    for item in os.listdir(to_text_string(path)):
+        if re.search(exclude, item) and not show_all:
+            continue
+        if osp.isdir(osp.join(path, item)):
+            dirlist.append(item)
+        elif folders_only:
+            continue
+        elif re.search(include, item) or show_all:
+            namelist.append(item)
+    return sorted(dirlist, key=str_lower) + \
+           sorted(namelist, key=str_lower)
+
+
+def has_subdirectories(path, include, exclude, show_all):
+    """Return True if path has subdirectories"""
+    try:
+        # > 1 because of '..'
+        return len( listdir(path, include, exclude,
+                            show_all, folders_only=True) ) > 1
+    except (IOError, OSError):
+        return False
+
+
+class DirView(QTreeView):
+    """Base file/directory tree view"""
+    def __init__(self, parent=None):
+        super(DirView, self).__init__(parent)
+        self.name_filters = ['*.py']
+        self.parent_widget = parent
+        self.show_all = None
+        self.menu = None
+        self.common_actions = None
+        self.__expanded_state = None
+        self._to_be_loaded = None
+        self.fsmodel = None
+        self.setup_fs_model()
+        self._scrollbar_positions = None
+                
+    #---- Model
+    def setup_fs_model(self):
+        """Setup filesystem model"""
+        filters = QDir.AllDirs | QDir.Files | QDir.Drives | QDir.NoDotAndDotDot
+        self.fsmodel = QFileSystemModel(self)
+        self.fsmodel.setFilter(filters)
+        self.fsmodel.setNameFilterDisables(False)
+        
+    def install_model(self):
+        """Install filesystem model"""
+        self.setModel(self.fsmodel)
+        
+    def setup_view(self):
+        """Setup view"""
+        self.install_model()
+        if not is_pyqt46:
+            self.fsmodel.directoryLoaded.connect(
+                                        lambda: self.resizeColumnToContents(0))
+        self.setAnimated(False)
+        self.setSortingEnabled(True)
+        self.sortByColumn(0, Qt.AscendingOrder)
+        
+    def set_name_filters(self, name_filters):
+        """Set name filters"""
+        self.name_filters = name_filters
+        self.fsmodel.setNameFilters(name_filters)
+        
+    def set_show_all(self, state):
+        """Toggle 'show all files' state"""
+        if state:
+            self.fsmodel.setNameFilters([])
+        else:
+            self.fsmodel.setNameFilters(self.name_filters)
+            
+    def get_filename(self, index):
+        """Return filename associated with *index*"""
+        if index:
+            return osp.normpath(to_text_string(self.fsmodel.filePath(index)))
+        
+    def get_index(self, filename):
+        """Return index associated with filename"""
+        return self.fsmodel.index(filename)
+        
+    def get_selected_filenames(self):
+        """Return selected filenames"""
+        if self.selectionMode() == self.ExtendedSelection:
+            return [self.get_filename(idx) for idx in self.selectedIndexes()]
+        else:
+            return [self.get_filename(self.currentIndex())]
+            
+    def get_dirname(self, index):
+        """Return dirname associated with *index*"""
+        fname = self.get_filename(index)
+        if fname:
+            if osp.isdir(fname):
+                return fname
+            else:
+                return osp.dirname(fname)
+        
+    #---- Tree view widget
+    def setup(self, name_filters=['*.py', '*.pyw'], show_all=False):
+        """Setup tree widget"""
+        self.setup_view()
+        
+        self.set_name_filters(name_filters)
+        self.show_all = show_all
+        
+        # Setup context menu
+        self.menu = QMenu(self)
+        self.common_actions = self.setup_common_actions()
+        
+    #---- Context menu
+    def setup_common_actions(self):
+        """Setup context menu common actions"""
+        # Filters
+        filters_action = create_action(self, _("Edit filename filters..."),
+                                       None, ima.icon('filter'),
+                                       triggered=self.edit_filter)
+        # Show all files
+        all_action = create_action(self, _("Show all files"),
+                                   toggled=self.toggle_all)
+        all_action.setChecked(self.show_all)
+        self.toggle_all(self.show_all)
+        
+        return [filters_action, all_action]
+
+    @Slot()
+    def edit_filter(self):
+        """Edit name filters"""
+        filters, valid = QInputDialog.getText(self, _('Edit filename filters'),
+                                              _('Name filters:'),
+                                              QLineEdit.Normal,
+                                              ", ".join(self.name_filters))
+        if valid:
+            filters = [f.strip() for f in to_text_string(filters).split(',')]
+            self.parent_widget.sig_option_changed.emit('name_filters', filters)
+            self.set_name_filters(filters)
+
+    @Slot(bool)
+    def toggle_all(self, checked):
+        """Toggle all files mode"""
+        self.parent_widget.sig_option_changed.emit('show_all', checked)
+        self.show_all = checked
+        self.set_show_all(checked)
+        
+    def create_file_new_actions(self, fnames):
+        """Return actions for submenu 'New...'"""
+        if not fnames:
+            return []
+        new_file_act = create_action(self, _("File..."), 
+                                     icon=ima.icon('filenew'),
+                                     triggered=lambda:
+                                     self.new_file(fnames[-1]))
+        new_module_act = create_action(self, _("Module..."),
+                                       icon=ima.icon('spyder'),
+                                       triggered=lambda:
+                                         self.new_module(fnames[-1]))
+        new_folder_act = create_action(self, _("Folder..."),
+                                       icon=ima.icon('folder_new'),
+                                       triggered=lambda:
+                                        self.new_folder(fnames[-1]))
+        new_package_act = create_action(self, _("Package..."),
+                                        icon=ima.icon('package_new'),
+                                        triggered=lambda:
+                                         self.new_package(fnames[-1]))
+        return [new_file_act, new_folder_act, None,
+                new_module_act, new_package_act]
+        
+    def create_file_import_actions(self, fnames):
+        """Return actions for submenu 'Import...'"""
+        return []
+
+    def create_file_manage_actions(self, fnames):
+        """Return file management actions"""
+        only_files = all([osp.isfile(_fn) for _fn in fnames])
+        only_modules = all([osp.splitext(_fn)[1] in ('.py', '.pyw', '.ipy')
+                            for _fn in fnames])
+        only_notebooks = all([osp.splitext(_fn)[1] == '.ipynb'
+                              for _fn in fnames])
+        only_valid = all([encoding.is_text_file(_fn) for _fn in fnames])
+        run_action = create_action(self, _("Run"), icon=ima.icon('run'),
+                                   triggered=self.run)
+        edit_action = create_action(self, _("Edit"), icon=ima.icon('edit'),
+                                    triggered=self.clicked)
+        move_action = create_action(self, _("Move..."),
+                                    icon="move.png",
+                                    triggered=self.move)
+        delete_action = create_action(self, _("Delete..."),
+                                      icon=ima.icon('editdelete'),
+                                      triggered=self.delete)
+        rename_action = create_action(self, _("Rename..."),
+                                      icon=ima.icon('rename'),
+                                      triggered=self.rename)
+        open_action = create_action(self, _("Open"), triggered=self.open)
+        ipynb_convert_action = create_action(self, _("Convert to Python script"),
+                                             icon=ima.icon('python'),
+                                             triggered=self.convert_notebooks)
+        
+        actions = []
+        if only_modules:
+            actions.append(run_action)
+        if only_valid and only_files:
+            actions.append(edit_action)
+        else:
+            actions.append(open_action)
+        actions += [delete_action, rename_action]
+        basedir = fixpath(osp.dirname(fnames[0]))
+        if all([fixpath(osp.dirname(_fn)) == basedir for _fn in fnames]):
+            actions.append(move_action)
+        actions += [None]
+        if only_notebooks and nbexporter is not None:
+            actions.append(ipynb_convert_action)
+        
+        # VCS support is quite limited for now, so we are enabling the VCS
+        # related actions only when a single file/folder is selected:
+        dirname = fnames[0] if osp.isdir(fnames[0]) else osp.dirname(fnames[0])
+        if len(fnames) == 1 and vcs.is_vcs_repository(dirname):
+            vcs_ci = create_action(self, _("Commit"),
+                                   icon=ima.icon('vcs_commit'),
+                                   triggered=lambda fnames=[dirname]:
+                                   self.vcs_command(fnames, 'commit'))
+            vcs_log = create_action(self, _("Browse repository"),
+                                    icon=ima.icon('vcs_browse'),
+                                    triggered=lambda fnames=[dirname]:
+                                    self.vcs_command(fnames, 'browse'))
+            actions += [None, vcs_ci, vcs_log]
+        
+        return actions
+
+    def create_folder_manage_actions(self, fnames):
+        """Return folder management actions"""
+        actions = []
+        if os.name == 'nt':
+            _title = _("Open command prompt here")
+        else:
+            _title = _("Open terminal here")
+        action = create_action(self, _title, icon=ima.icon('cmdprompt'),
+                               triggered=lambda:
+                               self.open_terminal(fnames))
+        actions.append(action)
+        _title = _("Open Python console here")
+        action = create_action(self, _title, icon=ima.icon('python'),
+                               triggered=lambda:
+                               self.open_interpreter(fnames))
+        actions.append(action)
+        return actions
+        
+    def create_context_menu_actions(self):
+        """Create context menu actions"""
+        actions = []
+        fnames = self.get_selected_filenames()
+        new_actions = self.create_file_new_actions(fnames)
+        if len(new_actions) > 1:
+            # Creating a submenu only if there is more than one entry
+            new_act_menu = QMenu(_('New'), self)
+            add_actions(new_act_menu, new_actions)
+            actions.append(new_act_menu)
+        else:
+            actions += new_actions
+        import_actions = self.create_file_import_actions(fnames)
+        if len(import_actions) > 1:
+            # Creating a submenu only if there is more than one entry
+            import_act_menu = QMenu(_('Import'), self)
+            add_actions(import_act_menu, import_actions)
+            actions.append(import_act_menu)
+        else:
+            actions += import_actions
+        if actions:
+            actions.append(None)
+        if fnames:
+            actions += self.create_file_manage_actions(fnames)
+        if actions:
+            actions.append(None)
+        if fnames and all([osp.isdir(_fn) for _fn in fnames]):
+            actions += self.create_folder_manage_actions(fnames)
+        if actions:
+            actions.append(None)
+        actions += self.common_actions
+        return actions
+
+    def update_menu(self):
+        """Update context menu"""
+        self.menu.clear()
+        add_actions(self.menu, self.create_context_menu_actions())
+    
+    #---- Events
+    def viewportEvent(self, event):
+        """Reimplement Qt method"""
+
+        # Prevent Qt from crashing or showing warnings like:
+        # "QSortFilterProxyModel: index from wrong model passed to 
+        # mapFromSource", probably due to the fact that the file system model 
+        # is being built. See Issue 1250.
+        #
+        # This workaround was inspired by the following KDE bug:
+        # https://bugs.kde.org/show_bug.cgi?id=172198
+        #
+        # Apparently, this is a bug from Qt itself.
+        self.executeDelayedItemsLayout()
+        
+        return QTreeView.viewportEvent(self, event)        
+                
+    def contextMenuEvent(self, event):
+        """Override Qt method"""
+        self.update_menu()
+        self.menu.popup(event.globalPos())
+
+    def keyPressEvent(self, event):
+        """Reimplement Qt method"""
+        if event.key() in (Qt.Key_Enter, Qt.Key_Return):
+            self.clicked()
+        elif event.key() == Qt.Key_F2:
+            self.rename()
+        elif event.key() == Qt.Key_Delete:
+            self.delete()
+        else:
+            QTreeView.keyPressEvent(self, event)
+
+    def mouseDoubleClickEvent(self, event):
+        """Reimplement Qt method"""
+        QTreeView.mouseDoubleClickEvent(self, event)
+        self.clicked()
+
+    @Slot()
+    def clicked(self):
+        """Selected item was double-clicked or enter/return was pressed"""
+        fnames = self.get_selected_filenames()
+        for fname in fnames:
+            if osp.isdir(fname):
+                self.directory_clicked(fname)
+            else:
+                self.open([fname])
+                
+    def directory_clicked(self, dirname):
+        """Directory was just clicked"""
+        pass
+        
+    #---- Drag
+    def dragEnterEvent(self, event):
+        """Drag and Drop - Enter event"""
+        event.setAccepted(event.mimeData().hasFormat("text/plain"))
+
+    def dragMoveEvent(self, event):
+        """Drag and Drop - Move event"""
+        if (event.mimeData().hasFormat("text/plain")):
+            event.setDropAction(Qt.MoveAction)
+            event.accept()
+        else:
+            event.ignore()
+            
+    def startDrag(self, dropActions):
+        """Reimplement Qt Method - handle drag event"""
+        data = QMimeData()
+        data.setUrls([QUrl(fname) for fname in self.get_selected_filenames()])
+        drag = QDrag(self)
+        drag.setMimeData(data)
+        drag.exec_()
+        
+    #---- File/Directory actions
+    @Slot()
+    def open(self, fnames=None):
+        """Open files with the appropriate application"""
+        if fnames is None:
+            fnames = self.get_selected_filenames()
+        for fname in fnames:
+            if osp.isfile(fname) and encoding.is_text_file(fname):
+                self.parent_widget.sig_open_file.emit(fname)
+            else:
+                self.open_outside_spyder([fname])
+        
+    def open_outside_spyder(self, fnames):
+        """Open file outside Spyder with the appropriate application
+        If this does not work, opening unknown file in Spyder, as text file"""
+        for path in sorted(fnames):
+            path = file_uri(path)
+            ok = programs.start_file(path)
+            if not ok:
+                self.parent_widget.edit.emit(path)
+                
+    def open_terminal(self, fnames):
+        """Open terminal"""
+        for path in sorted(fnames):
+            self.parent_widget.open_terminal.emit(path)
+            
+    def open_interpreter(self, fnames):
+        """Open interpreter"""
+        for path in sorted(fnames):
+            self.parent_widget.open_interpreter.emit(path)
+
+    @Slot()
+    def run(self, fnames=None):
+        """Run Python scripts"""
+        if fnames is None:
+            fnames = self.get_selected_filenames()
+        for fname in fnames:
+            self.parent_widget.run.emit(fname)
+    
+    def remove_tree(self, dirname):
+        """Remove whole directory tree
+        Reimplemented in project explorer widget"""
+        shutil.rmtree(dirname, onerror=misc.onerror)
+    
+    def delete_file(self, fname, multiple, yes_to_all):
+        """Delete file"""
+        if multiple:
+            buttons = QMessageBox.Yes|QMessageBox.YesAll| \
+                      QMessageBox.No|QMessageBox.Cancel
+        else:
+            buttons = QMessageBox.Yes|QMessageBox.No
+        if yes_to_all is None:
+            answer = QMessageBox.warning(self, _("Delete"),
+                                 _("Do you really want "
+                                   "to delete <b>%s</b>?"
+                                   ) % osp.basename(fname), buttons)
+            if answer == QMessageBox.No:
+                return yes_to_all
+            elif answer == QMessageBox.Cancel:
+                return False
+            elif answer == QMessageBox.YesAll:
+                yes_to_all = True
+        try:
+            if osp.isfile(fname):
+                misc.remove_file(fname)
+                self.parent_widget.removed.emit(fname)
+            else:
+                self.remove_tree(fname)
+                self.parent_widget.removed_tree.emit(fname)
+            return yes_to_all
+        except EnvironmentError as error:
+            action_str = _('delete')
+            QMessageBox.critical(self, _("Project Explorer"),
+                            _("<b>Unable to %s <i>%s</i></b>"
+                              "<br><br>Error message:<br>%s"
+                              ) % (action_str, fname, to_text_string(error)))
+        return False
+
+    @Slot()
+    def delete(self, fnames=None):
+        """Delete files"""
+        if fnames is None:
+            fnames = self.get_selected_filenames()
+        multiple = len(fnames) > 1
+        yes_to_all = None
+        for fname in fnames:
+            yes_to_all = self.delete_file(fname, multiple, yes_to_all)
+            if yes_to_all is not None and not yes_to_all:
+                # Canceled
+                return
+
+    def convert_notebook(self, fname):
+        """Convert an IPython notebook to a Python script in editor"""
+        try: 
+            script = nbexporter().from_filename(fname)[0]
+        except Exception as e:
+            QMessageBox.critical(self, _('Conversion error'), 
+                                 _("It was not possible to convert this "
+                                 "notebook. The error is:\n\n") + \
+                                 to_text_string(e))
+            return
+        self.parent_widget.sig_new_file.emit(script)
+
+    @Slot()
+    def convert_notebooks(self):
+        """Convert IPython notebooks to Python scripts in editor"""
+        fnames = self.get_selected_filenames()
+        if not isinstance(fnames, (tuple, list)):
+            fnames = [fnames]
+        for fname in fnames:
+            self.convert_notebook(fname)
+
+    def rename_file(self, fname):
+        """Rename file"""
+        path, valid = QInputDialog.getText(self, _('Rename'),
+                              _('New name:'), QLineEdit.Normal,
+                              osp.basename(fname))
+        if valid:
+            path = osp.join(osp.dirname(fname), to_text_string(path))
+            if path == fname:
+                return
+            if osp.exists(path):
+                if QMessageBox.warning(self, _("Rename"),
+                         _("Do you really want to rename <b>%s</b> and "
+                           "overwrite the existing file <b>%s</b>?"
+                           ) % (osp.basename(fname), osp.basename(path)),
+                         QMessageBox.Yes|QMessageBox.No) == QMessageBox.No:
+                    return
+            try:
+                misc.rename_file(fname, path)
+                self.parent_widget.renamed.emit(fname, path)
+                return path
+            except EnvironmentError as error:
+                QMessageBox.critical(self, _("Rename"),
+                            _("<b>Unable to rename file <i>%s</i></b>"
+                              "<br><br>Error message:<br>%s"
+                              ) % (osp.basename(fname), to_text_string(error)))
+
+    @Slot()
+    def rename(self, fnames=None):
+        """Rename files"""
+        if fnames is None:
+            fnames = self.get_selected_filenames()
+        if not isinstance(fnames, (tuple, list)):
+            fnames = [fnames]
+        for fname in fnames:
+            self.rename_file(fname)
+
+    @Slot()
+    def move(self, fnames=None):
+        """Move files/directories"""
+        if fnames is None:
+            fnames = self.get_selected_filenames()
+        orig = fixpath(osp.dirname(fnames[0]))
+        while True:
+            self.parent_widget.redirect_stdio.emit(False)
+            folder = getexistingdirectory(self, _("Select directory"), orig)
+            self.parent_widget.redirect_stdio.emit(True)
+            if folder:
+                folder = fixpath(folder)
+                if folder != orig:
+                    break
+            else:
+                return
+        for fname in fnames:
+            basename = osp.basename(fname)
+            try:
+                misc.move_file(fname, osp.join(folder, basename))
+            except EnvironmentError as error:
+                QMessageBox.critical(self, _("Error"),
+                                     _("<b>Unable to move <i>%s</i></b>"
+                                       "<br><br>Error message:<br>%s"
+                                       ) % (basename, to_text_string(error)))
+        
+    def create_new_folder(self, current_path, title, subtitle, is_package):
+        """Create new folder"""
+        if current_path is None:
+            current_path = ''
+        if osp.isfile(current_path):
+            current_path = osp.dirname(current_path)
+        name, valid = QInputDialog.getText(self, title, subtitle,
+                                           QLineEdit.Normal, "")
+        if valid:
+            dirname = osp.join(current_path, to_text_string(name))
+            try:
+                os.mkdir(dirname)
+            except EnvironmentError as error:
+                QMessageBox.critical(self, title,
+                                     _("<b>Unable "
+                                       "to create folder <i>%s</i></b>"
+                                       "<br><br>Error message:<br>%s"
+                                       ) % (dirname, to_text_string(error)))
+            finally:
+                if is_package:
+                    fname = osp.join(dirname, '__init__.py')
+                    try:
+                        with open(fname, 'wb') as f:
+                            f.write(to_binary_string('#'))
+                        return dirname
+                    except EnvironmentError as error:
+                        QMessageBox.critical(self, title,
+                                             _("<b>Unable "
+                                               "to create file <i>%s</i></b>"
+                                               "<br><br>Error message:<br>%s"
+                                               ) % (fname,
+                                                    to_text_string(error)))
+
+    def new_folder(self, basedir):
+        """New folder"""
+        title = _('New folder')
+        subtitle = _('Folder name:')
+        self.create_new_folder(basedir, title, subtitle, is_package=False)
+    
+    def new_package(self, basedir):
+        """New package"""
+        title = _('New package')
+        subtitle = _('Package name:')
+        self.create_new_folder(basedir, title, subtitle, is_package=True)
+    
+    def create_new_file(self, current_path, title, filters, create_func):
+        """Create new file
+        Returns True if successful"""
+        if current_path is None:
+            current_path = ''
+        if osp.isfile(current_path):
+            current_path = osp.dirname(current_path)
+        self.parent_widget.redirect_stdio.emit(False)
+        fname, _selfilter = getsavefilename(self, title, current_path, filters)
+        self.parent_widget.redirect_stdio.emit(True)
+        if fname:
+            try:
+                create_func(fname)
+                return fname
+            except EnvironmentError as error:
+                QMessageBox.critical(self, _("New file"),
+                                     _("<b>Unable to create file <i>%s</i>"
+                                       "</b><br><br>Error message:<br>%s"
+                                       ) % (fname, to_text_string(error)))
+
+    def new_file(self, basedir):
+        """New file"""
+        title = _("New file")
+        filters = _("All files")+" (*)"
+        def create_func(fname):
+            """File creation callback"""
+            if osp.splitext(fname)[1] in ('.py', '.pyw', '.ipy'):
+                create_script(fname)
+            else:
+                with open(fname, 'wb') as f:
+                    f.write(to_binary_string(''))
+        fname = self.create_new_file(basedir, title, filters, create_func)
+        if fname is not None:
+            self.open([fname])
+    
+    def new_module(self, basedir):
+        """New module"""
+        title = _("New module")
+        filters = _("Python scripts")+" (*.py *.pyw *.ipy)"
+        create_func = lambda fname: self.parent_widget.create_module.emit(fname)
+        self.create_new_file(basedir, title, filters, create_func)
+        
+    #----- VCS actions
+    def vcs_command(self, fnames, action):
+        """VCS action (commit, browse)"""
+        try:
+            for path in sorted(fnames):
+                vcs.run_vcs_tool(path, action)
+        except vcs.ActionToolNotFound as error:
+            msg = _("For %s support, please install one of the<br/> "
+                    "following tools:<br/><br/>  %s")\
+                        % (error.vcsname, ', '.join(error.tools))
+            QMessageBox.critical(self, _("Error"),
+                _("""<b>Unable to find external program.</b><br><br>%s""")
+                    % to_text_string(msg))
+        
+    #----- Settings
+    def get_scrollbar_position(self):
+        """Return scrollbar positions"""
+        return (self.horizontalScrollBar().value(),
+                self.verticalScrollBar().value())
+        
+    def set_scrollbar_position(self, position):
+        """Set scrollbar positions"""
+        # Scrollbars will be restored after the expanded state
+        self._scrollbar_positions = position
+        if self._to_be_loaded is not None and len(self._to_be_loaded) == 0:
+            self.restore_scrollbar_positions()
+            
+    def restore_scrollbar_positions(self):
+        """Restore scrollbar positions once tree is loaded"""
+        hor, ver = self._scrollbar_positions
+        self.horizontalScrollBar().setValue(hor)
+        self.verticalScrollBar().setValue(ver)
+        
+    def get_expanded_state(self):
+        """Return expanded state"""
+        self.save_expanded_state()
+        return self.__expanded_state
+    
+    def set_expanded_state(self, state):
+        """Set expanded state"""
+        self.__expanded_state = state
+        self.restore_expanded_state()
+    
+    def save_expanded_state(self):
+        """Save all items expanded state"""
+        model = self.model()
+        # If model is not installed, 'model' will be None: this happens when
+        # using the Project Explorer without having selected a workspace yet
+        if model is not None:
+            self.__expanded_state = []
+            for idx in model.persistentIndexList():
+                if self.isExpanded(idx):
+                    self.__expanded_state.append(self.get_filename(idx))
+
+    def restore_directory_state(self, fname):
+        """Restore directory expanded state"""
+        root = osp.normpath(to_text_string(fname))
+        if not osp.exists(root):
+            # Directory has been (re)moved outside Spyder
+            return
+        for basename in os.listdir(root):
+            path = osp.normpath(osp.join(root, basename))
+            if osp.isdir(path) and path in self.__expanded_state:
+                self.__expanded_state.pop(self.__expanded_state.index(path))
+                if self._to_be_loaded is None:
+                    self._to_be_loaded = []
+                self._to_be_loaded.append(path)
+                self.setExpanded(self.get_index(path), True)
+        if not self.__expanded_state and not is_pyqt46:
+            self.fsmodel.directoryLoaded.disconnect(self.restore_directory_state)
+                
+    def follow_directories_loaded(self, fname):
+        """Follow directories loaded during startup"""
+        if self._to_be_loaded is None:
+            return
+        path = osp.normpath(to_text_string(fname))
+        if path in self._to_be_loaded:
+            self._to_be_loaded.remove(path)
+        if self._to_be_loaded is not None and len(self._to_be_loaded) == 0 \
+          and not is_pyqt46:
+            self.fsmodel.directoryLoaded.disconnect(
+                                        self.follow_directories_loaded)
+            if self._scrollbar_positions is not None:
+                # The tree view need some time to render branches:
+                QTimer.singleShot(50, self.restore_scrollbar_positions)
+
+    def restore_expanded_state(self):
+        """Restore all items expanded state"""
+        if self.__expanded_state is not None:
+            # In the old project explorer, the expanded state was a dictionnary:
+            if isinstance(self.__expanded_state, list) and not is_pyqt46:
+                self.fsmodel.directoryLoaded.connect(
+                                                  self.restore_directory_state)
+                self.fsmodel.directoryLoaded.connect(
+                                                self.follow_directories_loaded)
+
+
+class ProxyModel(QSortFilterProxyModel):
+    """Proxy model: filters tree view"""
+    def __init__(self, parent):
+        super(ProxyModel, self).__init__(parent)
+        self.root_path = None
+        self.path_list = []
+        self.setDynamicSortFilter(True)
+        
+    def setup_filter(self, root_path, path_list):
+        """Setup proxy model filter parameters"""
+        self.root_path = osp.normpath(to_text_string(root_path))
+        self.path_list = [osp.normpath(to_text_string(p)) for p in path_list]
+        self.invalidateFilter()
+
+    def sort(self, column, order=Qt.AscendingOrder):
+        """Reimplement Qt method"""
+        self.sourceModel().sort(column, order)
+        
+    def filterAcceptsRow(self, row, parent_index):
+        """Reimplement Qt method"""
+        if self.root_path is None:
+            return True
+        index = self.sourceModel().index(row, 0, parent_index)
+        path = osp.normpath(to_text_string(self.sourceModel().filePath(index)))
+        if self.root_path.startswith(path):
+            # This is necessary because parent folders need to be scanned
+            return True
+        else:
+            for p in self.path_list:
+                if path == p or path.startswith(p+os.sep):
+                    return True
+            else:
+                return False
+
+
+class FilteredDirView(DirView):
+    """Filtered file/directory tree view"""
+    def __init__(self, parent=None):
+        super(FilteredDirView, self).__init__(parent)
+        self.proxymodel = None
+        self.setup_proxy_model()
+        self.root_path = None
+        
+    #---- Model
+    def setup_proxy_model(self):
+        """Setup proxy model"""
+        self.proxymodel = ProxyModel(self)
+        self.proxymodel.setSourceModel(self.fsmodel)
+        
+    def install_model(self):
+        """Install proxy model"""
+        if self.root_path is not None:
+            self.fsmodel.setNameFilters(self.name_filters)
+            self.setModel(self.proxymodel)
+        
+    def set_root_path(self, root_path):
+        """Set root path"""
+        self.root_path = root_path
+        self.install_model()
+        index = self.fsmodel.setRootPath(root_path)
+        self.setRootIndex(self.proxymodel.mapFromSource(index))
+        
+    def get_index(self, filename):
+        """Return index associated with filename"""
+        index = self.fsmodel.index(filename)
+        if index.isValid() and index.model() is self.fsmodel:
+            return self.proxymodel.mapFromSource(index)
+        
+    def set_folder_names(self, folder_names):
+        """Set folder names"""
+        assert self.root_path is not None
+        path_list = [osp.join(self.root_path, dirname)
+                     for dirname in folder_names]
+        self.proxymodel.setup_filter(self.root_path, path_list)
+        
+    def get_filename(self, index):
+        """Return filename from index"""
+        if index:
+            path = self.fsmodel.filePath(self.proxymodel.mapToSource(index))
+            return osp.normpath(to_text_string(path))
+
+
+class ExplorerTreeWidget(DirView):
+    """File/directory explorer tree widget
+    show_cd_only: Show current directory only
+    (True/False: enable/disable the option
+     None: enable the option and do not allow the user to disable it)"""
+    set_previous_enabled = Signal(bool)
+    set_next_enabled = Signal(bool)
+    
+    def __init__(self, parent=None, show_cd_only=None):
+        DirView.__init__(self, parent)
+                
+        self.history = []
+        self.histindex = None
+
+        self.show_cd_only = show_cd_only
+        self.__original_root_index = None
+        self.__last_folder = None
+
+        self.menu = None
+        self.common_actions = None
+        
+        # Enable drag events
+        self.setDragEnabled(True)
+        
+    #---- Context menu
+    def setup_common_actions(self):
+        """Setup context menu common actions"""
+        actions = super(ExplorerTreeWidget, self).setup_common_actions()
+        if self.show_cd_only is None:
+            # Enabling the 'show current directory only' option but do not
+            # allow the user to disable it
+            self.show_cd_only = True
+        else:
+            # Show current directory only
+            cd_only_action = create_action(self,
+                                           _("Show current directory only"),
+                                           toggled=self.toggle_show_cd_only)
+            cd_only_action.setChecked(self.show_cd_only)
+            self.toggle_show_cd_only(self.show_cd_only)
+            actions.append(cd_only_action)
+        return actions
+
+    @Slot(bool)
+    def toggle_show_cd_only(self, checked):
+        """Toggle show current directory only mode"""
+        self.parent_widget.sig_option_changed.emit('show_cd_only', checked)
+        self.show_cd_only = checked
+        if checked:
+            if self.__last_folder is not None:
+                self.set_current_folder(self.__last_folder)
+        elif self.__original_root_index is not None:
+            self.setRootIndex(self.__original_root_index)
+        
+    #---- Refreshing widget
+    def set_current_folder(self, folder):
+        """Set current folder and return associated model index"""
+        index = self.fsmodel.setRootPath(folder)
+        self.__last_folder = folder
+        if self.show_cd_only:
+            if self.__original_root_index is None:
+                self.__original_root_index = self.rootIndex()
+            self.setRootIndex(index)
+        return index
+        
+    def refresh(self, new_path=None, force_current=False):
+        """Refresh widget
+        force=False: won't refresh widget if path has not changed"""
+        if new_path is None:
+            new_path = getcwd()
+        if force_current:
+            index = self.set_current_folder(new_path)
+            self.expand(index)
+            self.setCurrentIndex(index)
+        self.set_previous_enabled.emit(
+                             self.histindex is not None and self.histindex > 0)
+        self.set_next_enabled.emit(self.histindex is not None and \
+                                   self.histindex < len(self.history)-1)
+            
+    #---- Events
+    def directory_clicked(self, dirname):
+        """Directory was just clicked"""
+        self.chdir(directory=dirname)
+        
+    #---- Files/Directories Actions
+    @Slot()
+    def go_to_parent_directory(self):
+        """Go to parent directory"""
+        self.chdir( osp.abspath(osp.join(getcwd(), os.pardir)) )
+
+    @Slot()
+    def go_to_previous_directory(self):
+        """Back to previous directory"""
+        self.histindex -= 1
+        self.chdir(browsing_history=True)
+
+    @Slot()
+    def go_to_next_directory(self):
+        """Return to next directory"""
+        self.histindex += 1
+        self.chdir(browsing_history=True)
+        
+    def update_history(self, directory):
+        """Update browse history"""
+        directory = osp.abspath(to_text_string(directory))
+        if directory in self.history:
+            self.histindex = self.history.index(directory)
+        
+    def chdir(self, directory=None, browsing_history=False):
+        """Set directory as working directory"""
+        if directory is not None:
+            directory = osp.abspath(to_text_string(directory))
+        if browsing_history:
+            directory = self.history[self.histindex]
+        elif directory in self.history:
+            self.histindex = self.history.index(directory)
+        else:
+            if self.histindex is None:
+                self.history = []
+            else:
+                self.history = self.history[:self.histindex+1]
+            if len(self.history) == 0 or \
+               (self.history and self.history[-1] != directory):
+                self.history.append(directory)
+            self.histindex = len(self.history)-1
+        directory = to_text_string(directory)
+        if PY2:
+            PermissionError = OSError
+        try:
+            os.chdir(directory)
+            self.parent_widget.open_dir.emit(directory)
+            self.refresh(new_path=directory, force_current=True)
+        except PermissionError:
+            QMessageBox.critical(self.parent_widget, "Error",
+                                 _("You don't have the right permissions to "
+                                   "open this directory"))
+
+
+class ExplorerWidget(QWidget):
+    """Explorer widget"""
+    sig_option_changed = Signal(str, object)
+    sig_open_file = Signal(str)
+    sig_new_file = Signal(str)
+    redirect_stdio = Signal(bool)
+    open_dir = Signal(str)
+
+    def __init__(self, parent=None, name_filters=['*.py', '*.pyw'],
+                 show_all=False, show_cd_only=None, show_icontext=True):
+        QWidget.__init__(self, parent)
+
+        # Widgets
+        self.treewidget = ExplorerTreeWidget(self, show_cd_only=show_cd_only)
+        button_previous = QToolButton(self)
+        button_next = QToolButton(self)
+        button_parent = QToolButton(self)
+        self.button_menu = QToolButton(self)
+        menu = QMenu(self)
+
+        self.action_widgets = [button_previous, button_next, button_parent,
+                               self.button_menu]
+
+        # Actions
+        icontext_action = create_action(self, _("Show icons and text"),
+                                        toggled=self.toggle_icontext)
+        previous_action = create_action(self, text=_("Previous"),
+                            icon=ima.icon('ArrowBack'),
+                            triggered=self.treewidget.go_to_previous_directory)
+        next_action = create_action(self, text=_("Next"),
+                            icon=ima.icon('ArrowForward'),
+                            triggered=self.treewidget.go_to_next_directory)
+        parent_action = create_action(self, text=_("Parent"),
+                            icon=ima.icon('ArrowUp'),
+                            triggered=self.treewidget.go_to_parent_directory)
+        options_action = create_action(self, text='', tip=_('Options'))
+
+        # Setup widgets
+        self.treewidget.setup(name_filters=name_filters, show_all=show_all)
+        self.treewidget.chdir(getcwd())
+        self.treewidget.common_actions += [None, icontext_action]
+
+        button_previous.setDefaultAction(previous_action)
+        previous_action.setEnabled(False)
+
+        button_next.setDefaultAction(next_action)
+        next_action.setEnabled(False)
+
+        button_parent.setDefaultAction(parent_action)
+
+        self.button_menu.setIcon(ima.icon('tooloptions'))
+        self.button_menu.setPopupMode(QToolButton.InstantPopup)
+        self.button_menu.setMenu(menu)
+        add_actions(menu, self.treewidget.common_actions)
+        options_action.setMenu(menu)
+
+        self.toggle_icontext(show_icontext)
+        icontext_action.setChecked(show_icontext)
+
+        for widget in self.action_widgets:
+            widget.setAutoRaise(True)
+            widget.setIconSize(QSize(16, 16))
+
+        # Layouts
+        blayout = QHBoxLayout()
+        blayout.addWidget(button_previous)
+        blayout.addWidget(button_next)
+        blayout.addWidget(button_parent)
+        blayout.addStretch()
+        blayout.addWidget(self.button_menu)
+
+        layout = QVBoxLayout()
+        layout.addLayout(blayout)
+        layout.addWidget(self.treewidget)
+        self.setLayout(layout)
+
+        # Signals and slots
+        self.treewidget.set_previous_enabled.connect(
+                                               previous_action.setEnabled)
+        self.treewidget.set_next_enabled.connect(next_action.setEnabled)
+
+    @Slot(bool)
+    def toggle_icontext(self, state):
+        """Toggle icon text"""
+        self.sig_option_changed.emit('show_icontext', state)
+        for widget in self.action_widgets:
+            if widget is not self.button_menu:
+                if state:
+                    widget.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
+                else:
+                    widget.setToolButtonStyle(Qt.ToolButtonIconOnly)
+
+
+#==============================================================================
+# Tests
+#==============================================================================
+class FileExplorerTest(QWidget):
+    def __init__(self):
+        QWidget.__init__(self)
+        vlayout = QVBoxLayout()
+        self.setLayout(vlayout)
+        self.explorer = ExplorerWidget(self, show_cd_only=None)
+        vlayout.addWidget(self.explorer)
+        
+        hlayout1 = QHBoxLayout()
+        vlayout.addLayout(hlayout1)
+        label = QLabel("<b>Open file:</b>")
+        label.setAlignment(Qt.AlignRight)
+        hlayout1.addWidget(label)
+        self.label1 = QLabel()
+        hlayout1.addWidget(self.label1)
+        self.explorer.sig_open_file.connect(self.label1.setText)
+        
+        hlayout2 = QHBoxLayout()
+        vlayout.addLayout(hlayout2)
+        label = QLabel("<b>Open dir:</b>")
+        label.setAlignment(Qt.AlignRight)
+        hlayout2.addWidget(label)
+        self.label2 = QLabel()
+        hlayout2.addWidget(self.label2)
+        self.explorer.open_dir.connect(self.label2.setText)
+        
+        hlayout3 = QHBoxLayout()
+        vlayout.addLayout(hlayout3)
+        label = QLabel("<b>Option changed:</b>")
+        label.setAlignment(Qt.AlignRight)
+        hlayout3.addWidget(label)
+        self.label3 = QLabel()
+        hlayout3.addWidget(self.label3)
+        self.explorer.sig_option_changed.connect(
+           lambda x, y: self.label3.setText('option_changed: %r, %r' % (x, y)))
+        self.explorer.open_dir.connect(
+                                lambda: self.explorer.treewidget.refresh('..'))
+
+
+class ProjectExplorerTest(QWidget):
+    def __init__(self, parent=None):
+        QWidget.__init__(self, parent)
+        vlayout = QVBoxLayout()
+        self.setLayout(vlayout)
+        self.treewidget = FilteredDirView(self)
+        self.treewidget.setup_view()
+        self.treewidget.set_root_path(osp.dirname(osp.abspath(__file__)))
+        self.treewidget.set_folder_names(['variableexplorer', 'sourcecode'])
+        vlayout.addWidget(self.treewidget)
+
+
+def test(file_explorer):
+    from spyderlib.utils.qthelpers import qapplication
+    app = qapplication()
+    if file_explorer:
+        test = FileExplorerTest()
+    else:
+        test = ProjectExplorerTest()
+    test.resize(640, 480)
+    test.show()
+    app.exec_()
+
+
+if __name__ == "__main__":
+    test(file_explorer=True)
+    test(file_explorer=False)
diff --git a/spyderlib/widgets/externalshell/baseshell.py b/spyderlib/widgets/externalshell/baseshell.py
index 366c9ec..807e48c 100644
--- a/spyderlib/widgets/externalshell/baseshell.py
+++ b/spyderlib/widgets/externalshell/baseshell.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -9,22 +9,22 @@
 # pylint: disable=R0911
 # pylint: disable=R0201
 
-import sys
 import os
 import os.path as osp
 from time import time, strftime, gmtime
 
-from spyderlib.qt.QtGui import (QApplication, QWidget, QVBoxLayout,
-                                QHBoxLayout, QMenu, QLabel, QInputDialog,
-                                QLineEdit, QToolButton)
-from spyderlib.qt.QtCore import (QProcess, SIGNAL, QByteArray, QTimer, Qt,
-                                 QTextCodec)
+from spyderlib.qt.QtGui import (QWidget, QVBoxLayout, QHBoxLayout, QMenu,
+                                QLabel, QInputDialog, QLineEdit, QToolButton)
+from spyderlib.qt.QtCore import (QProcess, Signal, QByteArray, QTimer, Qt,
+                                 QTextCodec, Slot)
+import spyderlib.utils.icon_manager as ima
+
 LOCALE_CODEC = QTextCodec.codecForLocale()
 
 # Local imports
-from spyderlib.utils.qthelpers import (get_icon, create_toolbutton,
-                                       create_action, add_actions)
-from spyderlib.baseconfig import get_conf_path, _
+from spyderlib.utils.qthelpers import (create_toolbutton, create_action, 
+                                       add_actions)
+from spyderlib.config.base import get_conf_path, _
 from spyderlib.py3compat import is_text_string, to_text_string
 
 
@@ -49,6 +49,9 @@ def add_pathlist_to_PYTHONPATH(env, pathlist, drop_env=False):
 class ExternalShellBase(QWidget):
     """External Shell widget: execute Python script in a separate process"""
     SHELL_CLASS = None
+    redirect_stdio = Signal(bool)
+    sig_finished = Signal()
+    
     def __init__(self, parent=None, fname=None, wdir=None,
                  history_filename=None, show_icontext=True,
                  light_background=True, menu_actions=None,
@@ -72,14 +75,11 @@ class ExternalShellBase(QWidget):
         
         self.shell = self.SHELL_CLASS(parent, get_conf_path(history_filename))
         self.shell.set_light_background(light_background)
-        self.connect(self.shell, SIGNAL("execute(QString)"),
-                     self.send_to_process)
-        self.connect(self.shell, SIGNAL("keyboard_interrupt()"),
-                     self.keyboard_interrupt)
+        self.shell.execute.connect(self.send_to_process)
+        self.shell.sig_keyboard_interrupt.connect(self.keyboard_interrupt)
         # Redirecting some SIGNALs:
-        self.connect(self.shell, SIGNAL('redirect_stdio(bool)'),
-                     lambda state: self.emit(SIGNAL('redirect_stdio(bool)'),
-                                             state))
+        self.shell.redirect_stdio.connect(
+                     lambda state: self.redirect_stdio.emit(state))
         
         self.state_label = None
         self.time_label = None
@@ -114,7 +114,8 @@ class ExternalShellBase(QWidget):
 
         if show_buttons_inside:
             self.update_time_label_visibility()
-        
+
+    @Slot(bool)
     def set_elapsed_time_visible(self, state):
         self.show_elapsed_time = state
         if self.time_label is not None:
@@ -136,20 +137,20 @@ class ExternalShellBase(QWidget):
     def get_toolbar_buttons(self):
         if self.run_button is None:
             self.run_button = create_toolbutton(self, text=_("Run"),
-                                             icon=get_icon('run.png'),
+                                             icon=ima.icon('run'),
                                              tip=_("Run again this program"),
                                              triggered=self.start_shell)
         if self.kill_button is None:
             self.kill_button = create_toolbutton(self, text=_("Kill"),
-                                     icon=get_icon('kill.png'),
+                                     icon=ima.icon('kill'),
                                      tip=_("Kills the current process, "
                                            "causing it to exit immediately"))
         buttons = [self.run_button]
         if self.options_button is None:
             options = self.get_options_menu()
             if options:
-                self.options_button = create_toolbutton(self, text=_("Options"),
-                                            icon=get_icon('tooloptions.png'))
+                self.options_button = create_toolbutton(self, text=_('Options'),
+                                            icon=ima.icon('tooloptions'))
                 self.options_button.setPopupMode(QToolButton.InstantPopup)
                 menu = QMenu(self)
                 add_actions(menu, options)
@@ -203,7 +204,11 @@ class ExternalShellBase(QWidget):
             self.is_closing = True
             self.process.kill()
             self.process.waitForFinished(100)
-        self.disconnect(self.timer, SIGNAL("timeout()"), self.show_time)
+
+        try:
+            self.timer.timeout.disconnect(self.show_time)
+        except (RuntimeError, TypeError):
+            pass
     
     def set_running_state(self, state=True):
         self.set_buttons_runnning_state(state)
@@ -213,31 +218,34 @@ class ExternalShellBase(QWidget):
                 self.state_label.setText(_(
                    "<span style=\'color: #44AA44\'><b>Running...</b></span>"))
             self.t0 = time()
-            self.connect(self.timer, SIGNAL("timeout()"), self.show_time)
+            self.timer.timeout.connect(self.show_time)
             self.timer.start(1000)        
         else:
             if self.state_label is not None:
                 self.state_label.setText(_('Terminated.'))
-            self.disconnect(self.timer, SIGNAL("timeout()"), self.show_time)
+            try:
+                self.timer.timeout.disconnect(self.show_time)
+            except (RuntimeError, TypeError):
+                pass
 
     def set_buttons_runnning_state(self, state):
         self.run_button.setVisible(not state and not self.is_ipykernel)
         self.kill_button.setVisible(state)
-    
+
+    @Slot(bool)
     def start_shell(self, ask_for_arguments=False):
         """Start shell"""
         if ask_for_arguments and not self.get_arguments():
             self.set_running_state(False)
             return
         try:
-            self.disconnect(self.terminate_button, SIGNAL("clicked()"),
-                            self.process.terminate)
-            self.disconnect(self.kill_button, SIGNAL("clicked()"),
-                            self.process.terminate)
-        except:
+            self.terminate_button.clicked.disconnect(self.process.terminate)
+            self.kill_button.clicked.disconnect(self.process.terminate)
+        except (AttributeError, RuntimeError, TypeError):
             pass
         self.create_process()
 
+    @Slot()
     def get_arguments(self):
         arguments, valid = QInputDialog.getText(self, _('Arguments'),
                                                 _('Command line arguments:'),
@@ -252,7 +260,7 @@ class ExternalShellBase(QWidget):
     
     def finished(self, exit_code, exit_status):
         self.shell.flush()
-        self.emit(SIGNAL('finished()'))
+        self.sig_finished.emit()
         if self.is_closing:
             return
         self.set_running_state(False)
@@ -280,14 +288,16 @@ class ExternalShellBase(QWidget):
         while self.process.bytesAvailable():
             qba += self.process.readAllStandardError()
         return self.transcode(qba)
-    
+
     def write_output(self):
         self.shell.write(self.get_stdout(), flush=True)
-        QApplication.processEvents()
-        
+        # Commenting the line below improves crashes on long
+        # output. See Issue 2251
+        # QApplication.processEvents()
+
     def send_to_process(self, qstr):
         raise NotImplementedError
-        
+
     def send_ctrl_to_process(self, letter):
         char = chr("abcdefghijklmnopqrstuvwxyz".index(letter) + 1)
         byte_array = QByteArray()
@@ -295,38 +305,6 @@ class ExternalShellBase(QWidget):
         self.process.write(byte_array)
         self.process.waitForBytesWritten(-1)
         self.shell.write(LOCALE_CODEC.toUnicode(byte_array), flush=True)
-        
+
     def keyboard_interrupt(self):
         raise NotImplementedError
-
-
-def test():
-    from spyderlib.utils.qthelpers import qapplication
-    app = qapplication()
-    from spyderlib.widgets.externalshell.pythonshell import ExternalPythonShell
-    from spyderlib.widgets.externalshell.systemshell import ExternalSystemShell
-    import spyderlib
-    from spyderlib.plugins.variableexplorer import VariableExplorer
-    settings = VariableExplorer.get_settings()
-    shell = ExternalPythonShell(wdir=osp.dirname(spyderlib.__file__),
-                                ipykernel=True, stand_alone=settings,
-                                arguments="-q4thread -pylab -colors LightBG",
-                                light_background=False)
-#    shell = ExternalPythonShell(wdir=osp.dirname(spyderlib.__file__),
-#                                interact=True, umr_enabled=True,
-#                                stand_alone=settings,
-#                                umr_namelist=['guidata', 'guiqwt'],
-#                                umr_verbose=True, light_background=False)
-#    shell = ExternalSystemShell(wdir=osp.dirname(spyderlib.__file__),
-#                                light_background=False)
-    shell.shell.toggle_wrap_mode(True)
-    shell.start_shell(False)
-    from spyderlib.qt.QtGui import QFont
-    font = QFont("Lucida console")
-    font.setPointSize(10)
-    shell.shell.set_font(font)
-    shell.show()
-    sys.exit(app.exec_())
-
-if __name__ == "__main__":
-    test()
\ No newline at end of file
diff --git a/spyderlib/widgets/externalshell/inputhooks.py b/spyderlib/widgets/externalshell/inputhooks.py
index 77ea5a9..d209604 100644
--- a/spyderlib/widgets/externalshell/inputhooks.py
+++ b/spyderlib/widgets/externalshell/inputhooks.py
@@ -11,11 +11,16 @@ import ctypes
 import os
 import sys
 
+QT_API = os.environ["QT_API"]
+
 # Qt imports
-if os.environ["QT_API"] == 'pyqt':
-    from PyQt4 import QtCore, QtGui
-elif os.environ["QT_API"] == 'pyside':
-    from PySide import QtCore, QtGui   # analysis:ignore
+if QT_API == 'pyqt5':
+    from PyQt5 import QtCore
+elif QT_API == 'pyqt':
+    from PyQt4 import QtCore
+elif QT_API == 'pyside':
+    from PySide import QtCore
+
 
 #-----------------------------------------------------------------------------
 # Utilities
@@ -84,8 +89,11 @@ def set_pyft_callback(callback):
     return callback
 
 def remove_pyqt_inputhook():
-    if os.environ["QT_API"] == 'pyqt':
+    if QT_API == 'pyqt' or QT_API == 'pyqt5':
         QtCore.pyqtRemoveInputHook()
+    else:
+        pass
+
 
 #------------------------------------------------------------------------------
 # Input hooks
@@ -106,7 +114,7 @@ def qt4():
         allow_CTRL_C()
         app = QtCore.QCoreApplication.instance()
         if not app:
-            app = QtGui.QApplication([" "])
+            return 0
         app.processEvents(QtCore.QEventLoop.AllEvents, 300)
         if not stdin_ready():
             # Generally a program would run QCoreApplication::exec()
diff --git a/spyderlib/widgets/externalshell/introspection.py b/spyderlib/widgets/externalshell/introspection.py
index ad345cd..0a9aa2b 100644
--- a/spyderlib/widgets/externalshell/introspection.py
+++ b/spyderlib/widgets/externalshell/introspection.py
@@ -6,7 +6,7 @@
 
 """External shell's introspection and notification servers"""
 
-from spyderlib.qt.QtCore import QThread, SIGNAL, Signal
+from spyderlib.qt.QtCore import QThread, Signal
 
 import threading
 import socket
@@ -14,7 +14,7 @@ import errno
 import os
 
 # Local imports
-from spyderlib.baseconfig import get_conf_path, DEBUG
+from spyderlib.config.base import get_conf_path, DEBUG
 from spyderlib.utils.misc import select_port
 from spyderlib.utils.debug import log_last_error
 from spyderlib.utils.bsdsocket import read_packet, write_packet
@@ -138,6 +138,11 @@ def start_notification_server():
 class NotificationThread(QThread):
     """Notification thread"""
     sig_process_remote_view = Signal(object)
+    sig_pdb = Signal(str, int)
+    open_file = Signal(str, int)
+    new_ipython_kernel = Signal(str)
+    refresh_namespace_browser = Signal()
+    
     def __init__(self):
         QThread.__init__(self)
         self.notify_socket = None
@@ -173,17 +178,17 @@ class NotificationThread(QThread):
                 data = cdict.get('data')
                 if command == 'pdb_step':
                     fname, lineno = data
-                    self.emit(SIGNAL('pdb(QString,int)'), fname, lineno)
-                    self.emit(SIGNAL('refresh_namespace_browser()'))
+                    self.sig_pdb.emit(fname, lineno)
+                    self.refresh_namespace_browser.emit()
                 elif command == 'refresh':
-                    self.emit(SIGNAL('refresh_namespace_browser()'))
+                    self.refresh_namespace_browser.emit()
                 elif command == 'remote_view':
                     self.sig_process_remote_view.emit(data)
                 elif command == 'ipykernel':
-                    self.emit(SIGNAL('new_ipython_kernel(QString)'), data)
+                    self.new_ipython_kernel.emit(data)
                 elif command == 'open_file':
                     fname, lineno = data
-                    self.emit(SIGNAL('open_file(QString,int)'), fname, lineno)
+                    self.open_file.emit(fname, lineno)
                 else:
                     raise RuntimeError('Unsupported command: %r' % command)
                 if DEBUG_INTROSPECTION:
diff --git a/spyderlib/widgets/externalshell/monitor.py b/spyderlib/widgets/externalshell/monitor.py
index ebfa1fa..27f82bb 100644
--- a/spyderlib/widgets/externalshell/monitor.py
+++ b/spyderlib/widgets/externalshell/monitor.py
@@ -1,8 +1,13 @@
 # -*- coding: utf-8 -*-
+#
+# Copyright © 2009- The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
 """External shell's monitor"""
 
-#TODO: The "disable auto-refresh when variable explorer is hidden" feature 
-#      broken since we removed the "shell" widget reference from notification 
+#TODO: The "disable auto-refresh when variable explorer is hidden" feature
+#      broken since we removed the "shell" widget reference from notification
 #      thread. We must find another mechanism to avoid refreshing systematically
 #      remote views for all consoles...!
 
@@ -19,7 +24,7 @@ from spyderlib.utils.dochelpers import (getargtxt, getdoc, getsource,
 from spyderlib.utils.bsdsocket import (communicate, read_packet, write_packet,
                                        PACKET_NOT_RECEIVED, PICKLE_HIGHEST_PROTOCOL)
 from spyderlib.utils.introspection.module_completion import module_completion
-from spyderlib.baseconfig import get_conf_path, get_supported_types, DEBUG
+from spyderlib.config.base import get_conf_path, get_supported_types, DEBUG
 from spyderlib.py3compat import getcwd, is_text_string, pickle, _thread
 
 
@@ -47,7 +52,7 @@ def get_remote_data(data, settings, mode, more_excluded_names=None):
         * mode (string): 'editable' or 'picklable'
         * more_excluded_names: additional excluded names (list)
     """
-    from spyderlib.widgets.dicteditorutils import globalsfilter
+    from spyderlib.widgets.variableexplorer.utils import globalsfilter
     global SUPPORTED_TYPES
     if not SUPPORTED_TYPES:
         SUPPORTED_TYPES = get_supported_types()
@@ -68,7 +73,7 @@ def make_remote_view(data, settings, more_excluded_names=None):
     Make a remote view of dictionary *data*
     -> globals explorer
     """
-    from spyderlib.widgets.dicteditorutils import (get_human_readable_type,
+    from spyderlib.widgets.variableexplorer.utils import (get_human_readable_type,
                                     get_size, get_color_name, value_to_display)
     assert all([name in REMOTE_SETTINGS for name in settings])
     data = get_remote_data(data, settings, mode='editable',
diff --git a/spyderlib/widgets/externalshell/pythonshell.py b/spyderlib/widgets/externalshell/pythonshell.py
index 4ebecf7..1667ad7 100644
--- a/spyderlib/widgets/externalshell/pythonshell.py
+++ b/spyderlib/widgets/externalshell/pythonshell.py
@@ -1,40 +1,46 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
 """External Python Shell widget: execute Python script in a separate process"""
 
-import sys
 import os
 import os.path as osp
 import socket
+import sys
 
 from spyderlib.qt.QtGui import QApplication, QMessageBox, QSplitter, QMenu
-from spyderlib.qt.QtCore import QProcess, SIGNAL, Qt
+from spyderlib.qt.QtCore import QProcess, Signal, Slot, Qt
+from spyderlib.qt.QtCore import QProcessEnvironment
 from spyderlib.qt.compat import getexistingdirectory
+import spyderlib.utils.icon_manager as ima
 
 # Local imports
-from spyderlib.utils.qthelpers import (get_icon, get_std_icon, add_actions,
-                                       create_toolbutton, create_action,
-                                       DialogManager)
+from spyderlib.utils.qthelpers import (add_actions, create_toolbutton,
+                                       create_action, DialogManager)
 from spyderlib.utils.environ import RemoteEnvDialog
 from spyderlib.utils.programs import get_python_args
 from spyderlib.utils.misc import get_python_executable
-from spyderlib.baseconfig import (_, get_module_source_path, DEBUG,
+from spyderlib.config.base import (_, get_module_source_path, DEBUG,
                                   MAC_APP_NAME, running_in_mac_app)
 from spyderlib.widgets.shell import PythonShellWidget
-from spyderlib.widgets.externalshell.namespacebrowser import NamespaceBrowser
+from spyderlib.widgets.variableexplorer.namespacebrowser import NamespaceBrowser
 from spyderlib.utils.bsdsocket import communicate, write_packet
 from spyderlib.widgets.externalshell.baseshell import (ExternalShellBase,
                                                    add_pathlist_to_PYTHONPATH)
-from spyderlib.widgets.dicteditor import DictEditor
+from spyderlib.widgets.variableexplorer.collectionseditor import CollectionsEditor
 from spyderlib.py3compat import (is_text_string, to_text_string,
                                  to_binary_string)
 
 
 class ExtPythonShellWidget(PythonShellWidget):
+    
+    wait_for_ready_read = Signal()
+    go_to_error = Signal(str)
+    focus_changed = Signal()
+    
     def __init__(self, parent, history_filename, profile=False):
         PythonShellWidget.__init__(self, parent, history_filename, profile)
         self.path = []
@@ -46,7 +52,7 @@ class ExtPythonShellWidget(PythonShellWidget):
     def clear_terminal(self):
         """Reimplement ShellBaseWidget method"""
         self.clear()
-        self.emit(SIGNAL("execute(QString)"), "\n")
+        self.execute.emit("\n")
 
     def execute_lines(self, lines):
         """
@@ -66,7 +72,7 @@ class ExtPythonShellWidget(PythonShellWidget):
                 import time
                 time.sleep(0.025)
             else:
-                self.emit(SIGNAL("wait_for_ready_read()"))
+                self.wait_for_ready_read.emit()
             self.flush()
 
     #------ Code completion / Calltips
@@ -153,36 +159,42 @@ class ExtPythonShellWidget(PythonShellWidget):
 class ExternalPythonShell(ExternalShellBase):
     """External Shell widget: execute Python script in a separate process"""
     SHELL_CLASS = ExtPythonShellWidget
+    sig_pdb = Signal(str, int)
+    open_file = Signal(str, int)
+    ipython_kernel_start_error = Signal(str)
+    create_ipython_client = Signal(str)
+    started = Signal()
+    sig_finished = Signal()
+    
     def __init__(self, parent=None, fname=None, wdir=None,
-                 interact=False, debug=False, path=[], python_args='',
+                 interact=False, debug=False, post_mortem=False,
+                 path=[], python_args='',
                  ipykernel=False, arguments='', stand_alone=None,
                  umr_enabled=True, umr_namelist=[], umr_verbose=True,
                  pythonstartup=None, pythonexecutable=None,
+                 external_interpreter=False,
                  monitor_enabled=True, mpl_backend=None, ets_backend='qt4',
-                 qt_api=None, pyqt_api=0,
-                 ignore_sip_setapi_errors=False, merge_output_channels=False,
+                 qt_api=None, merge_output_channels=False,
                  colorize_sys_stderr=False, autorefresh_timeout=3000,
                  autorefresh_state=True, light_background=True,
                  menu_actions=None, show_buttons_inside=True,
                  show_elapsed_time=True):
 
-        assert qt_api in (None, 'pyqt', 'pyside')
+        assert qt_api in (None, 'pyqt', 'pyside', 'pyqt5')
 
         self.namespacebrowser = None # namespace browser widget!
-        
         self.dialog_manager = DialogManager()
-        
+
         self.stand_alone = stand_alone # stand alone settings (None: plugin)
         self.interact = interact
         self.is_ipykernel = ipykernel
         self.pythonstartup = pythonstartup
         self.pythonexecutable = pythonexecutable
+        self.external_interpreter = external_interpreter
         self.monitor_enabled = monitor_enabled
         self.mpl_backend = mpl_backend
         self.ets_backend = ets_backend
         self.qt_api = qt_api
-        self.pyqt_api = pyqt_api
-        self.ignore_sip_setapi_errors = ignore_sip_setapi_errors
         self.merge_output_channels = merge_output_channels
         self.colorize_sys_stderr = colorize_sys_stderr
         self.umr_enabled = umr_enabled
@@ -232,11 +244,14 @@ class ExternalPythonShell(ExternalShellBase):
         self.interact_action.setChecked(self.interact)
         self.debug_action.setChecked(debug)
         
+        
         self.introspection_socket = None
         self.is_interpreter = fname is None
         
         if self.is_interpreter:
             self.terminate_button.hide()
+            
+        self.post_mortem_action.setChecked(post_mortem and not self.is_interpreter)
         
         # Additional python path list
         self.path = path
@@ -266,12 +281,12 @@ class ExternalPythonShell(ExternalShellBase):
         if self.namespacebrowser_button is None \
            and self.stand_alone is not None:
             self.namespacebrowser_button = create_toolbutton(self,
-                  text=_("Variables"), icon=get_icon('dictedit.png'),
+                  text=_("Variables"), icon=ima.icon('dictedit'),
                   tip=_("Show/hide global variables explorer"),
                   toggled=self.toggle_globals_explorer, text_beside_icon=True)
         if self.terminate_button is None:
             self.terminate_button = create_toolbutton(self,
-                  text=_("Terminate"), icon=get_icon('stop.png'),
+                  text=_("Terminate"), icon=ima.icon('stop'),
                   tip=_("Attempts to stop the process. The process\n"
                         "may not exit as a result of clicking this\n"
                         "button (it is given the chance to prompt\n"
@@ -291,19 +306,22 @@ class ExternalPythonShell(ExternalShellBase):
         self.debug_action.setCheckable(True)
         self.args_action = create_action(self, _("Arguments..."),
                                          triggered=self.get_arguments)
+        self.post_mortem_action = create_action(self, _("Post Mortem Debug"))
+        self.post_mortem_action.setCheckable(True)
         run_settings_menu = QMenu(_("Run settings"), self)
         add_actions(run_settings_menu,
-                    (self.interact_action, self.debug_action, self.args_action))
+                    (self.interact_action, self.debug_action, self.args_action,
+                     self.post_mortem_action))
         self.cwd_button = create_action(self, _("Working directory"),
-                                icon=get_std_icon('DirOpenIcon'),
+                                icon=ima.icon('DirOpenIcon'),
                                 tip=_("Set current working directory"),
                                 triggered=self.set_current_working_directory)
         self.env_button = create_action(self, _("Environment variables"),
-                                        icon=get_icon('environ.png'),
+                                        icon=ima.icon('environ'),
                                         triggered=self.show_env)
         self.syspath_button = create_action(self,
                                             _("Show sys.path contents"),
-                                            icon=get_icon('syspath.png'),
+                                            icon=ima.icon('syspath'),
                                             triggered=self.show_syspath)
         actions = [run_settings_menu, self.show_time_action, None,
                    self.cwd_button, self.env_button, self.syspath_button]
@@ -323,12 +341,11 @@ class ExternalPythonShell(ExternalShellBase):
             settings = self.stand_alone
             self.namespacebrowser.set_shellwidget(self)
             self.namespacebrowser.setup(**settings)
-            self.connect(self.namespacebrowser, SIGNAL('collapse()'),
+            self.namespacebrowser.sig_collapse.connect(
                          lambda: self.toggle_globals_explorer(False))
             # Shell splitter
             self.splitter = splitter = QSplitter(Qt.Vertical, self)
-            self.connect(self.splitter, SIGNAL('splitterMoved(int, int)'),
-                         self.splitter_moved)
+            self.splitter.splitterMoved.connect(self.splitter_moved)
             splitter.addWidget(self.shell)
             splitter.setCollapsible(0, False)
             splitter.addWidget(self.namespacebrowser)
@@ -339,13 +356,14 @@ class ExternalPythonShell(ExternalShellBase):
             return splitter
     
     def get_icon(self):
-        return get_icon('python.png')
+        return ima.icon('python')
 
     def set_buttons_runnning_state(self, state):
         ExternalShellBase.set_buttons_runnning_state(self, state)
         self.interact_action.setEnabled(not state and not self.is_interpreter)
         self.debug_action.setEnabled(not state and not self.is_interpreter)
         self.args_action.setEnabled(not state and not self.is_interpreter)
+        self.post_mortem_action.setEnabled(not state and not self.is_interpreter)
         if state:
             if self.arguments:
                 argstr = _("Arguments: %s") % self.arguments
@@ -373,8 +391,7 @@ class ExternalPythonShell(ExternalShellBase):
     def configure_namespacebrowser(self):
         """Connect the namespace browser to the notification thread"""
         if self.notification_thread is not None:
-            self.connect(self.notification_thread,
-                         SIGNAL('refresh_namespace_browser()'),
+            self.notification_thread.refresh_namespace_browser.connect(
                          self.namespacebrowser.refresh_table)
             signal = self.notification_thread.sig_process_remote_view
             signal.connect(lambda data:
@@ -388,14 +405,14 @@ class ExternalPythonShell(ExternalShellBase):
             self.process.setProcessChannelMode(QProcess.MergedChannels)
         else:
             self.process.setProcessChannelMode(QProcess.SeparateChannels)
-        self.connect(self.shell, SIGNAL("wait_for_ready_read()"),
+        self.shell.wait_for_ready_read.connect(
                      lambda: self.process.waitForReadyRead(250))
         
         # Working directory
         if self.wdir is not None:
             self.process.setWorkingDirectory(self.wdir)
 
-        #-------------------------Python specific-------------------------------
+        #-------------------------Python specific------------------------------
         # Python arguments
         p_args = ['-u']
         if DEBUG >= 3:
@@ -410,13 +427,18 @@ class ExternalPythonShell(ExternalShellBase):
         if self.pythonstartup:
             env.append('PYTHONSTARTUP=%s' % self.pythonstartup)
         
+        #-------------------------Python specific-------------------------------
+        # Post mortem debugging
+        if self.post_mortem_action.isChecked():
+            env.append('SPYDER_EXCEPTHOOK=True')
+
         # Set standard input/output encoding for Python consoles
         # (IPython handles it on its own)
         # See http://stackoverflow.com/q/26312400/438386, specifically
         # the comments of Martijn Pieters
         if not self.is_ipykernel:
             env.append('PYTHONIOENCODING=UTF-8')
-        
+
         # Monitor
         if self.monitor_enabled:
             env.append('SPYDER_SHELL_ID=%s' % id(self))
@@ -427,29 +449,27 @@ class ExternalPythonShell(ExternalShellBase):
             introspection_server.register(self)
             notification_server = introspection.start_notification_server()
             self.notification_thread = notification_server.register(self)
-            self.connect(self.notification_thread, SIGNAL('pdb(QString,int)'),
-                         lambda fname, lineno:
-                         self.emit(SIGNAL('pdb(QString,int)'), fname, lineno))
-            self.connect(self.notification_thread,
-                         SIGNAL('new_ipython_kernel(QString)'),
-                         lambda args:
-                         self.emit(SIGNAL('create_ipython_client(QString)'),
-                         args))
-            self.connect(self.notification_thread,
-                         SIGNAL('open_file(QString,int)'),
-                         lambda fname, lineno:
-                         self.emit(SIGNAL('open_file(QString,int)'),
-                                   fname, lineno))
+            self.notification_thread.sig_pdb.connect(
+                                              lambda fname, lineno:
+                                              self.sig_pdb.emit(fname, lineno))
+            self.notification_thread.new_ipython_kernel.connect(
+                                         lambda args:
+                                         self.create_ipython_client.emit(args))
+            self.notification_thread.open_file.connect(
+                                            lambda fname, lineno:
+                                            self.open_file.emit(fname, lineno))
             if self.namespacebrowser is not None:
                 self.configure_namespacebrowser()
             env.append('SPYDER_I_PORT=%d' % introspection_server.port)
             env.append('SPYDER_N_PORT=%d' % notification_server.port)
-        
+
         # External modules options
-        env.append('ETS_TOOLKIT=%s' % self.ets_backend)
-        if self.mpl_backend:
-            env.append('MATPLOTLIB_BACKEND=%s' % self.mpl_backend)
-        if self.qt_api:
+        if not self.is_ipykernel:
+            env.append('ETS_TOOLKIT=%s' % self.ets_backend)
+        if self.mpl_backend is not None:
+            backends = {0: 'Automatic', 1: 'None', 2: 'TkAgg'}
+            env.append('SPY_MPL_BACKEND=%s' % backends[self.mpl_backend])
+        if self.qt_api and not self.is_ipykernel:
             env.append('QT_API=%s' % self.qt_api)
         env.append('COLORIZE_SYS_STDERR=%s' % self.colorize_sys_stderr)
 #        # Socket-based alternative (see input hook in sitecustomize.py):
@@ -457,11 +477,7 @@ class ExternalPythonShell(ExternalShellBase):
 #            from PyQt4.QtNetwork import QLocalServer
 #            self.local_server = QLocalServer()
 #            self.local_server.listen(str(id(self)))
-        if self.pyqt_api:
-            env.append('PYQT_API=%d' % self.pyqt_api)
-        env.append('IGNORE_SIP_SETAPI_ERRORS=%s'
-                   % self.ignore_sip_setapi_errors)
-        
+
         # User Module Deleter
         if self.is_interpreter:
             env.append('UMR_ENABLED=%r' % self.umr_enabled)
@@ -477,7 +493,10 @@ class ExternalPythonShell(ExternalShellBase):
         # IPython kernel
         env.append('IPYTHON_KERNEL=%r' % self.is_ipykernel)
 
-        # Add sitecustomize path to path list 
+        # External interpreter
+        env.append('EXTERNAL_INTERPRETER=%r' % self.external_interpreter)
+
+        # Add sitecustomize path to path list
         pathlist = []
         scpath = osp.dirname(osp.abspath(__file__))
         pathlist.append(scpath)
@@ -488,23 +507,17 @@ class ExternalPythonShell(ExternalShellBase):
         # Adding path list to PYTHONPATH environment variable
         add_pathlist_to_PYTHONPATH(env, pathlist)
 
-        #-------------------------Python specific-------------------------------
+        #-------------------------Python specific------------------------------
                         
-        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
-                     self.write_output)
-        self.connect(self.process, SIGNAL("readyReadStandardError()"),
-                     self.write_error)
-        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
-                     self.finished)
-                     
-        self.connect(self, SIGNAL('finished()'), self.dialog_manager.close_all)
-
-        self.connect(self.terminate_button, SIGNAL("clicked()"),
-                     self.process.terminate)
-        self.connect(self.kill_button, SIGNAL("clicked()"),
-                     self.process.kill)
-        
-        #-------------------------Python specific-------------------------------
+        self.process.readyReadStandardOutput.connect(self.write_output)
+        self.process.readyReadStandardError.connect(self.write_error)
+        self.process.finished.connect(lambda ec, es=QProcess.ExitStatus:
+                                      self.finished(ec, es))
+        self.sig_finished.connect(self.dialog_manager.close_all)
+        self.terminate_button.clicked.connect(self.process.terminate)
+        self.kill_button.clicked.connect(self.process.kill)
+        
+        #-------------------------Python specific------------------------------
         # Fixes for our Mac app:
         # 1. PYTHONPATH and PYTHONHOME are set while bootstrapping the app,
         #    but their values are messing sys.path for external interpreters
@@ -514,7 +527,6 @@ class ExternalPythonShell(ExternalShellBase):
         # 3. Remove PYTHONOPTIMIZE from env so that we can have assert
         #    statements working with our interpreters (See Issue 1281)
         if running_in_mac_app():
-            env.append('SPYDER_INTERPRETER=%s' % self.pythonexecutable)
             if MAC_APP_NAME not in self.pythonexecutable:
                 env = [p for p in env if not (p.startswith('PYTHONPATH') or \
                                               p.startswith('PYTHONHOME'))] # 1.
@@ -522,15 +534,19 @@ class ExternalPythonShell(ExternalShellBase):
                 add_pathlist_to_PYTHONPATH(env, pathlist, drop_env=True)   # 2.
             env = [p for p in env if not p.startswith('PYTHONOPTIMIZE')]   # 3.
 
-        self.process.setEnvironment(env)
+        processEnvironment = QProcessEnvironment()
+        for envItem in env:
+            envName, separator, envValue = envItem.partition('=')
+            processEnvironment.insert(envName, envValue)
+        self.process.setProcessEnvironment(processEnvironment)                   
         self.process.start(self.pythonexecutable, p_args)
-        #-------------------------Python specific-------------------------------
+        #-------------------------Python specific------------------------------
             
         running = self.process.waitForStarted(3000)
         self.set_running_state(running)
         if not running:
             if self.is_ipykernel:
-                self.emit(SIGNAL("ipython_kernel_start_error(QString)"),
+                self.ipython_kernel_start_error.emit(
                           _("The kernel failed to start!! That's all we know... "
                             "Please close this console and open a new one."))
             else:
@@ -538,21 +554,20 @@ class ExternalPythonShell(ExternalShellBase):
                                      _("A Python console failed to start!"))
         else:
             self.shell.setFocus()
-            self.emit(SIGNAL('started()'))
+            self.started.emit()
         return self.process
 
     def finished(self, exit_code, exit_status):
         """Reimplement ExternalShellBase method"""
         if self.is_ipykernel and exit_code == 1:
-            self.emit(SIGNAL("ipython_kernel_start_error(QString)"),
-                      self.shell.get_text_with_eol())
+            self.ipython_kernel_start_error.emit(self.shell.get_text_with_eol())
         ExternalShellBase.finished(self, exit_code, exit_status)
         self.introspection_socket = None
 
     
-#===============================================================================
+#==============================================================================
 #    Input/Output
-#===============================================================================
+#==============================================================================
     def write_error(self):
         if os.name == 'nt':
             #---This is apparently necessary only on Windows (not sure though):
@@ -566,13 +581,11 @@ class ExternalPythonShell(ExternalShellBase):
     def send_to_process(self, text):
         if not self.is_running():
             return
-            
         if not is_text_string(text):
             text = to_text_string(text)
-        if self.mpl_backend == 'Qt4Agg' and os.name == 'nt' and \
+        if self.mpl_backend == 0 and os.name == 'nt' and \
           self.introspection_socket is not None:
-            communicate(self.introspection_socket,
-                        "toggle_inputhook_flag(True)")
+            communicate(self.introspection_socket, "toggle_inputhook_flag(True)")
 #            # Socket-based alternative (see input hook in sitecustomize.py):
 #            while self.local_server.hasPendingConnections():
 #                self.local_server.nextPendingConnection().write('go!')
@@ -600,9 +613,10 @@ class ExternalPythonShell(ExternalShellBase):
             except socket.error:
                 pass
             
-#===============================================================================
+#==============================================================================
 #    Globals explorer
-#===============================================================================
+#==============================================================================
+    @Slot(bool)
     def toggle_globals_explorer(self, state):
         if self.stand_alone is not None:
             self.splitter.setSizes([1, 1 if state else 0])
@@ -613,27 +627,60 @@ class ExternalPythonShell(ExternalShellBase):
     def splitter_moved(self, pos, index):
         self.namespacebrowser_button.setChecked( self.splitter.sizes()[1] )
 
-#===============================================================================
+#==============================================================================
 #    Misc.
-#===============================================================================
+#==============================================================================
+    @Slot()
     def set_current_working_directory(self):
         """Set current working directory"""
         cwd = self.shell.get_cwd()
-        self.emit(SIGNAL('redirect_stdio(bool)'), False)
+        self.redirect_stdio.emit(False)
         directory = getexistingdirectory(self, _("Select directory"), cwd)
         if directory:
             self.shell.set_cwd(directory)
-        self.emit(SIGNAL('redirect_stdio(bool)'), True)
+        self.redirect_stdio.emit(True)
 
+    @Slot()
     def show_env(self):
         """Show environment variables"""
         get_func = self.shell.get_env
         set_func = self.shell.set_env
         self.dialog_manager.show(RemoteEnvDialog(get_func, set_func))
-        
+
+    @Slot()
     def show_syspath(self):
         """Show sys.path contents"""
-        editor = DictEditor()
+        editor = CollectionsEditor()
         editor.setup(self.shell.get_syspath(), title="sys.path", readonly=True,
-                     width=600, icon='syspath.png')
+                     width=600, icon=ima.icon('syspath'))
         self.dialog_manager.show(editor)
+
+
+def test():
+    from spyderlib.utils.qthelpers import qapplication
+    app = qapplication()
+
+    from spyderlib.plugins.variableexplorer import VariableExplorer
+    settings = VariableExplorer.get_settings()
+
+    shell = ExternalPythonShell(pythonexecutable=sys.executable,
+                                interact=True,
+                                stand_alone=settings,
+                                wdir=osp.dirname(__file__),
+                                mpl_backend=0,
+                                light_background=False)
+
+    from spyderlib.qt.QtGui import QFont
+    from spyderlib.config.main import CONF
+    font = QFont(CONF.get('console', 'font/family')[0])
+    font.setPointSize(10)
+    shell.shell.set_font(font)
+
+    shell.shell.toggle_wrap_mode(True)
+    shell.start_shell(False)
+    shell.show()
+    sys.exit(app.exec_())
+
+
+if __name__ == "__main__":
+    test()
\ No newline at end of file
diff --git a/spyderlib/widgets/externalshell/sitecustomize.py b/spyderlib/widgets/externalshell/sitecustomize.py
index 6f49c1d..5046c27 100644
--- a/spyderlib/widgets/externalshell/sitecustomize.py
+++ b/spyderlib/widgets/externalshell/sitecustomize.py
@@ -1,4 +1,8 @@
 #
+# Copyright (c) 2009- The Spyder Development Team)
+# Licensed under the terms of the MIT License)
+# (see spyderlib/__init__.py for details)
+#
 # IMPORTANT NOTE: Don't add a coding line here! It's not necessary for
 # site files
 #
@@ -10,6 +14,9 @@ import os
 import os.path as osp
 import pdb
 import bdb
+import time
+import traceback
+import shlex
 
 
 PY2 = sys.version[0] == '2'
@@ -93,17 +100,17 @@ except ImportError:
 #==============================================================================
 if os.environ.get("COLORIZE_SYS_STDERR", "").lower() == "true":
     class StderrProxy(object):
-        """Proxy to sys.stderr file object overriding only the `write` method 
-        to provide red colorization for the whole stream, and blue-underlined 
-        for traceback file links""" 
+        """Proxy to sys.stderr file object overriding only the `write` method
+        to provide red colorization for the whole stream, and blue-underlined
+        for traceback file links"""
         def __init__(self):
             self.old_stderr = sys.stderr
             self.__buffer = ''
             sys.stderr = self
-        
+
         def __getattr__(self, name):
             return getattr(self.old_stderr, name)
-            
+
         def write(self, text):
             if os.name == 'nt' and '\n' not in text:
                 self.__buffer += text
@@ -118,20 +125,20 @@ if os.environ.get("COLORIZE_SYS_STDERR", "").lower() == "true":
                     colored_text = '\x1b[31m'+text+'\x1b[0m'
                 self.old_stderr.write(colored_text)
             self.__buffer = ''
-    
+
     stderrproxy = StderrProxy()
 
 
 #==============================================================================
-# Prepending this spyderlib package's path to sys.path to be sure 
+# Prepending this spyderlib package's path to sys.path to be sure
 # that another version of spyderlib won't be imported instead:
 #==============================================================================
 spyderlib_path = osp.dirname(__file__)
 while not osp.isdir(osp.join(spyderlib_path, 'spyderlib')):
     spyderlib_path = osp.abspath(osp.join(spyderlib_path, os.pardir))
 if not spyderlib_path.startswith(sys.prefix):
-    # Spyder is not installed: moving its parent directory to the top of 
-    # sys.path to be sure that this spyderlib package will be imported in 
+    # Spyder is not installed: moving its parent directory to the top of
+    # sys.path to be sure that this spyderlib package will be imported in
     # the remote process (instead of another installed version of Spyder)
     while spyderlib_path in sys.path:
         sys.path.remove(spyderlib_path)
@@ -140,23 +147,6 @@ os.environ['SPYDER_PARENT_DIR'] = spyderlib_path
 
 
 #==============================================================================
-# Set PyQt4 API to #1 or #2
-#==============================================================================
-pyqt_api = int(os.environ.get("PYQT_API", "0"))
-if pyqt_api:
-    try:
-        import sip
-        try:
-            for qtype in ('QString', 'QVariant'):
-                sip.setapi(qtype, pyqt_api)
-        except AttributeError:
-            # Old version of sip
-            pass
-    except ImportError:
-        pass
-
-
-#==============================================================================
 # Setting console encoding (otherwise Python does not recognize encoding)
 # for Windows platforms
 #==============================================================================
@@ -178,11 +168,12 @@ if os.name == 'nt':
 #==============================================================================
 # Settings for our MacOs X app
 #==============================================================================
+IS_EXT_INTERPRETER = os.environ.get('EXTERNAL_INTERPRETER', '').lower() == "true"
+
 if sys.platform == 'darwin':
-    from spyderlib.baseconfig import MAC_APP_NAME
+    from spyderlib.config.base import MAC_APP_NAME
     if MAC_APP_NAME in __file__:
-        interpreter = os.environ.get('SPYDER_INTERPRETER')
-        if MAC_APP_NAME not in interpreter:
+        if IS_EXT_INTERPRETER.lower() == "true":
             # Add a minimal library (with spyderlib) at the end of sys.path to
             # be able to connect our monitor to the external console
             py_ver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
@@ -233,8 +224,9 @@ try:
 except ImportError:
     matplotlib = None   # analysis:ignore
 
+
 #==============================================================================
-# Communication between Spyder and the remote process
+# Monitor-based functionality
 #==============================================================================
 if os.environ.get('SPYDER_SHELL_ID') is None:
     monitor = None
@@ -247,12 +239,12 @@ else:
                       float(os.environ['SPYDER_AR_TIMEOUT']),
                       os.environ["SPYDER_AR_STATE"].lower() == "true")
     monitor.start()
-    
+
     def open_in_spyder(source, lineno=1):
         """
-        Open a source file in Spyder's editor (it could be a filename or a 
+        Open a source file in Spyder's editor (it could be a filename or a
         Python module/package).
-        
+
         If you want to use IPython's %edit use %ed instead
         """
         try:
@@ -273,23 +265,27 @@ else:
         else:
             _print("Can't open file %s" % source, file=sys.stderr)
     builtins.open_in_spyder = open_in_spyder
-    
-    if os.environ["QT_API"] == 'pyqt':
-        from PyQt4 import QtCore
-    elif os.environ["QT_API"] == 'pyside':
-        from PySide import QtCore          #analysis:ignore
 
-    def qt_nt_inputhook():
-        """Qt input hook for Windows
-        
-        This input hook wait for available stdin data (notified by
-        ExternalPythonShell through the monitor's inputhook_flag
-        attribute), and in the meantime it processes Qt events.
-        """
-        # Refreshing variable explorer, except on first input hook call:
-        # (otherwise, on slow machines, this may freeze Spyder)
-        monitor.refresh_from_inputhook()
-        if os.name == 'nt':
+    # Our own input hook, monitor based and for Windows only
+    if os.name == 'nt':
+        # Qt imports
+        if os.environ["QT_API"] == 'pyqt5':
+            from PyQt5 import QtCore
+        elif os.environ["QT_API"] == 'pyqt':
+            from PyQt4 import QtCore           # analysis:ignore
+        elif os.environ["QT_API"] == 'pyside':
+            from PySide import QtCore          # analysis:ignore
+
+        def qt_nt_inputhook():
+            """Qt input hook for Windows
+            
+            This input hook wait for available stdin data (notified by
+            ExternalPythonShell through the monitor's inputhook_flag
+            attribute), and in the meantime it processes Qt events.
+            """
+            # Refreshing variable explorer, except on first input hook call:
+            # (otherwise, on slow machines, this may freeze Spyder)
+            monitor.refresh_from_inputhook()
             try:
                 # This call fails for Python without readline support
                 # (or on Windows platforms) when PyOS_InputHook is called
@@ -300,37 +296,80 @@ else:
                 sys.stdin.tell()
             except IOError:
                 return 0
-        app = QtCore.QCoreApplication.instance()
-        if app and app.thread() is QtCore.QThread.currentThread():
-            timer = QtCore.QTimer()
-            QtCore.QObject.connect(timer, QtCore.SIGNAL('timeout()'),
-                                   app, QtCore.SLOT('quit()'))
-            monitor.toggle_inputhook_flag(False)
-            while not monitor.inputhook_flag:
-                timer.start(50)
-                QtCore.QCoreApplication.exec_()
-                timer.stop()
-#            # Socket-based alternative:
-#            socket = QtNetwork.QLocalSocket()
-#            socket.connectToServer(os.environ['SPYDER_SHELL_ID'])
-#            socket.waitForConnected(-1)
-#            while not socket.waitForReadyRead(10):
-#                timer.start(50)
-#                QtCore.QCoreApplication.exec_()
-#                timer.stop()
-#            socket.read(3)
-#            socket.disconnectFromServer()
-        return 0
     
+            # Input hook
+            app = QtCore.QCoreApplication.instance()
+            if app and app.thread() is QtCore.QThread.currentThread():
+                timer = QtCore.QTimer()
+                timer.timeout.connect(app.quit)
+                monitor.toggle_inputhook_flag(False)
+                while not monitor.inputhook_flag:
+                    timer.start(50)
+                    QtCore.QCoreApplication.exec_()
+                    timer.stop()
+    
+                # Socket-based alternative:
+                #socket = QtNetwork.QLocalSocket()
+                #socket.connectToServer(os.environ['SPYDER_SHELL_ID'])
+                #socket.waitForConnected(-1)
+                #while not socket.waitForReadyRead(10):
+                #    timer.start(50)
+                #    QtCore.QCoreApplication.exec_()
+                #    timer.stop()
+                #socket.read(3)
+                #socket.disconnectFromServer()
+            return 0
+
 
 #==============================================================================
 # Matplotlib settings
 #==============================================================================
+IS_IPYTHON = os.environ.get("IPYTHON_KERNEL", "").lower() == "true"
+
 if matplotlib is not None:
-    mpl_backend = os.environ.get("MATPLOTLIB_BACKEND", "")
+    mpl_backend = os.environ.get("SPY_MPL_BACKEND", "")
     mpl_ion = os.environ.get("MATPLOTLIB_ION", "")
-    if not mpl_backend:
-        mpl_backend = 'Qt4Agg'
+
+    # Setting no backend if the user asks for it
+    if not mpl_backend or mpl_backend.lower() == 'none':
+        mpl_backend = ""
+
+    # Set backend automatically
+    if mpl_backend.lower() == 'automatic':
+        if not IS_EXT_INTERPRETER:
+            if os.environ["QT_API"] == 'pyqt5':
+                mpl_backend = 'Qt5Agg'
+            else:
+                mpl_backend = 'Qt4Agg'
+        else:
+            # Test for backend libraries on external interpreters
+            def set_mpl_backend(backend):
+                mod, bend, qt_api = backend
+                try:
+                    if mod:
+                        __import__(mod)
+                    if qt_api and (os.environ["QT_API"] != qt_api):
+                        return None
+                    else:
+                        matplotlib.use(bend)
+                        return bend
+                except (ImportError, ValueError):
+                    return None
+
+            backends = [('PyQt5', 'Qt5Agg', 'pyqt5'),
+                        ('PyQt4', 'Qt4Agg', 'pyqt'),
+                        ('PySide', 'Qt4Agg', 'pyqt')]
+            if not os.name == 'nt':
+                 backends.append( ('_tkinter', 'TkAgg', None) )
+
+            for b in backends:
+                mpl_backend = set_mpl_backend(b)
+                if mpl_backend:
+                    break
+
+            if not mpl_backend:
+                _print("NOTE: No suitable Matplotlib backend was found!\n"
+                       "      You won't be able to create plots\n")
 
     # To have mpl docstrings as rst
     matplotlib.rcParams['docstring.hardcopy'] = True
@@ -339,48 +378,55 @@ if matplotlib is not None:
     if mpl_ion.lower() == "true":
         matplotlib.rcParams['interactive'] = True
 
-    if os.environ.get("IPYTHON_KERNEL", "").lower() != "true":
-        import ctypes
+    if not IS_IPYTHON:
         from spyderlib.widgets.externalshell import inputhooks
-
-        # Setting the user defined backend
-        matplotlib.use(mpl_backend)
-
-        # Setting the right input hook according to mpl_backend,
-        # IMPORTANT NOTE: Don't try to abstract the steps to set a PyOS
-        # input hook callback in a function. It will *crash* the
-        # interpreter!!
-        if mpl_backend == "Qt4Agg" and os.name == 'nt' and \
-          monitor is not None:
-            # Removing PyQt4 input hook which is not working well on
-            # Windows since opening a subprocess does not attach a real
-            # console to it (with keyboard events...)
-            if os.environ["QT_API"] == 'pyqt': 
+        if mpl_backend:
+            import ctypes
+
+            # Grab QT_API
+            qt_api = os.environ["QT_API"]
+
+            # Setting the user defined backend
+            if not IS_EXT_INTERPRETER:
+                matplotlib.use(mpl_backend)
+
+            # Setting the right input hook according to mpl_backend,
+            # IMPORTANT NOTE: Don't try to abstract the steps to set a PyOS
+            # input hook callback in a function. It will **crash** the
+            # interpreter!!
+            if (mpl_backend == "Qt4Agg" or mpl_backend == "Qt5Agg") and \
+              os.name == 'nt' and monitor is not None:
+                # Removing PyQt4 input hook which is not working well on
+                # Windows since opening a subprocess does not attach a real
+                # console to it (with keyboard events...)
+                if qt_api == 'pyqt' or qt_api == 'pyqt5':
+                    inputhooks.remove_pyqt_inputhook()
+                # Using our own input hook
+                # NOTE: it's not working correctly for some configurations
+                # (See issue 1831)
+                callback = inputhooks.set_pyft_callback(qt_nt_inputhook)
+                pyos_ih = inputhooks.get_pyos_inputhook()
+                pyos_ih.value = ctypes.cast(callback, ctypes.c_void_p).value
+            elif mpl_backend == "Qt4Agg" and qt_api == 'pyside':
+                # PySide doesn't have an input hook, so we need to install one
+                # to be able to show plots
+                # Note: This only works well for Posix systems
+                callback = inputhooks.set_pyft_callback(inputhooks.qt4)
+                pyos_ih = inputhooks.get_pyos_inputhook()
+                pyos_ih.value = ctypes.cast(callback, ctypes.c_void_p).value
+            elif (mpl_backend != "Qt4Agg" and qt_api == 'pyqt') \
+              or (mpl_backend != "Qt5Agg" and qt_api == 'pyqt5'):
+                # Matplotlib backends install their own input hooks, so we
+                # need to remove the PyQt one to make them work
                 inputhooks.remove_pyqt_inputhook()
-            # Using our own input hook
-            # NOTE: it's not working correctly for some configurations
-            # (See issue 1831)
-            callback = inputhooks.set_pyft_callback(qt_nt_inputhook)
-            pyos_ih = inputhooks.get_pyos_inputhook()
-            pyos_ih.value = ctypes.cast(callback, ctypes.c_void_p).value
-        elif mpl_backend == "Qt4Agg" and os.environ["QT_API"] == 'pyside':
-            # PySide doesn't have an input hook, so we need to install one
-            # to be able to show plots.
-            # Note: This only works well for Posix systems
-            callback = inputhooks.set_pyft_callback(inputhooks.qt4)
-            pyos_ih = inputhooks.get_pyos_inputhook()
-            pyos_ih.value = ctypes.cast(callback, ctypes.c_void_p).value
-        elif mpl_backend != "Qt4Agg" and os.environ["QT_API"] == 'pyqt':
-            # Matplotlib backends install their own input hooks, so we
-            # need to remove the PyQt one to make them work
+        else:
             inputhooks.remove_pyqt_inputhook()
 
 
 #==============================================================================
 # IPython adjustments
 #==============================================================================
-if os.environ.get("IPYTHON_KERNEL", "").lower() == "true":
-
+if IS_IPYTHON:
     # Use ipydb as the debugger to patch on IPython consoles
     from IPython.core.debugger import Pdb as ipyPdb
     pdb.Pdb = ipyPdb
@@ -417,6 +463,8 @@ if os.environ.get("IPYTHON_KERNEL", "").lower() == "true":
 # Pdb adjustments
 #==============================================================================
 class SpyderPdb(pdb.Pdb):
+    send_initial_notification = True
+
     def set_spyder_breakpoints(self):
         self.clear_all_breaks()
         #------Really deleting all breakpoints:
@@ -427,7 +475,7 @@ class SpyderPdb(pdb.Pdb):
         bdb.Breakpoint.bplist = {}
         bdb.Breakpoint.bpbynumber = [None]
         #------
-        from spyderlib.config import CONF
+        from spyderlib.config.main import CONF
         CONF.load_from_ini()
         if CONF.get('run', 'breakpoints/enabled', True):
             breakpoints = CONF.get('run', 'breakpoints', {})
@@ -437,7 +485,7 @@ class SpyderPdb(pdb.Pdb):
                     i += 1
                     self.set_break(self.canonic(fname), linenumber,
                                    cond=condition)
-                    
+
     def notify_spyder(self, frame):
         if not frame:
             return
@@ -451,7 +499,8 @@ class SpyderPdb(pdb.Pdb):
         if isinstance(fname, basestring) and isinstance(lineno, int):
             if osp.isfile(fname) and monitor is not None:
                 monitor.notify_pdb_step(fname, lineno)
-
+                time.sleep(0.1)
+                
 pdb.Pdb = SpyderPdb
 
 #XXX: I know, this function is now also implemented as is in utils/misc.py but
@@ -464,10 +513,10 @@ def monkeypatch_method(cls, patch_name):
     # (Tue Jan 15 19:13:25 CET 2008)
     """
     Add the decorated method to the given class; replace as needed.
-    
+
     If the named method already exists on the given class, it will
-    be replaced, and a reference to the old method is created as 
-    cls._old<patch_name><name>. If the "_old_<patch_name>_<name>" attribute 
+    be replaced, and a reference to the old method is created as
+    cls._old<patch_name><name>. If the "_old_<patch_name>_<name>" attribute
     already exists, KeyError is raised.
     """
     def decorator(func):
@@ -498,11 +547,12 @@ def user_return(self, frame, return_value):
             return
         self._wait_for_mainpyfile = 0
     self._old_Pdb_user_return(frame, return_value)
-        
+
 @monkeypatch_method(pdb.Pdb, 'Pdb')
 def interaction(self, frame, traceback):
     self.setup(frame, traceback)
-    self.notify_spyder(frame) #-----Spyder-specific-------------------------
+    if self.send_initial_notification:
+        self.notify_spyder(frame) #-----Spyder-specific-----------------------
     self.print_stack_entry(self.stack[self.curindex])
     self.cmdloop()
     self.forget()
@@ -514,7 +564,7 @@ def reset(self):
         monitor.register_pdb_session(self)
     self.set_spyder_breakpoints()
 
-#XXX: notify spyder on any pdb command (is that good or too lazy? i.e. is more 
+#XXX: notify spyder on any pdb command (is that good or too lazy? i.e. is more
 #     specific behaviour desired?)
 @monkeypatch_method(pdb.Pdb, 'Pdb')
 def postcmd(self, stop, line):
@@ -554,10 +604,11 @@ if sys.version[0] == '2':
 
 
 #==============================================================================
-# # Restoring (almost) original sys.path:
-# (Note: do not remove spyderlib_path from sys.path because if Spyder has been
-#  installed using python setup.py install, then this could remove the 
-#  'site-packages' directory from sys.path!)
+# Restoring (almost) original sys.path:
+#
+# NOTE: do not remove spyderlib_path from sys.path because if Spyder has been
+# installed using python setup.py install, then this could remove the
+# 'site-packages' directory from sys.path!
 #==============================================================================
 try:
     sys.path.remove(osp.join(spyderlib_path,
@@ -567,31 +618,13 @@ except ValueError:
 
 
 #==============================================================================
-# Ignore PyQt4's sip API changes (this should be used wisely -e.g. for
-# debugging- as dynamic API change is not supported by PyQt) 
-#==============================================================================
-if os.environ.get("IGNORE_SIP_SETAPI_ERRORS", "").lower() == "true":
-    try:
-        import sip
-        from sip import setapi as original_setapi
-        def patched_setapi(name, no):
-            try:
-                original_setapi(name, no)
-            except ValueError as msg:
-                _print("Warning/PyQt4-Spyder (%s)" % str(msg), file=sys.stderr)
-        sip.setapi = patched_setapi
-    except ImportError:
-        pass
-
-
-#==============================================================================
 # User module reloader
 #==============================================================================
 class UserModuleReloader(object):
     """
     User Module Reloader (UMR) aims at deleting user modules 
     to force Python to deeply reload them during import
-    
+
     pathlist [list]: blacklist in terms of module path
     namelist [list]: blacklist in terms of module name
     """
@@ -599,9 +632,9 @@ class UserModuleReloader(object):
         if namelist is None:
             namelist = []
         spy_modules = ['sitecustomize', 'spyderlib', 'spyderplugins']
-        mpl_modules = ['matplotlib', 'tkinter', 'Tkinter', 'gtk']
+        mpl_modules = ['matplotlib', 'tkinter', 'Tkinter']
         self.namelist = namelist + spy_modules + mpl_modules
-        
+
         if pathlist is None:
             pathlist = []
         self.pathlist = pathlist
@@ -613,12 +646,12 @@ class UserModuleReloader(object):
                 return True
         else:
             return set(modname.split('.')) & set(self.namelist)
-        
+
     def run(self, verbose=False):
         """
         Del user modules to force Python to deeply reload them
-        
-        Do not del modules which are considered as system modules, i.e. 
+
+        Do not del modules which are considered as system modules, i.e.
         modules installed in subdirectories of Python interpreter's binary
         Do not del C modules
         """
@@ -627,8 +660,8 @@ class UserModuleReloader(object):
             if modname not in self.previous_modules:
                 modpath = getattr(module, '__file__', None)
                 if modpath is None:
-                    # *module* is a C module that is statically linked into the 
-                    # interpreter. There is no way to know its path, so we 
+                    # *module* is a C module that is statically linked into the
+                    # interpreter. There is no way to know its path, so we
                     # choose to ignore it.
                     continue
                 if not self.is_module_blacklisted(modname, modpath):
@@ -641,6 +674,78 @@ class UserModuleReloader(object):
 __umr__ = None
 
 
+#===============================================================================
+# Handle Post Mortem Debugging and Traceback Linkage to Spyder
+#===============================================================================
+
+def clear_post_mortem():
+    """
+    Remove the post mortem excepthook and replace with a standard one.
+    """
+    if IS_IPYTHON:
+        from IPython.core.getipython import get_ipython
+        ipython_shell = get_ipython()
+        if ipython_shell:
+            ipython_shell.set_custom_exc((), None)
+    else:
+        sys.excepthook = sys.__excepthook__
+
+
+def post_mortem_excepthook(type, value, tb):
+    """
+    For post mortem exception handling, print a banner and enable post
+    mortem debugging.
+    """
+    clear_post_mortem()
+    if IS_IPYTHON:
+        from IPython.core.getipython import get_ipython
+        ipython_shell = get_ipython()
+        ipython_shell.showtraceback((type, value, tb))
+        p = pdb.Pdb(ipython_shell.colors)
+    else:
+        traceback.print_exception(type, value, tb, file=sys.stderr)
+        p = pdb.Pdb()
+
+    if not type == SyntaxError:
+        # wait for stderr to print (stderr.flush does not work in this case)
+        time.sleep(0.1)
+        _print('*' * 40)
+        _print('Entering post mortem debugging...')
+        _print('*' * 40)
+        #  add ability to move between frames
+        p.send_initial_notification = False
+        p.reset()
+        frame = tb.tb_frame
+        prev = frame
+        while frame.f_back:
+            prev = frame
+            frame = frame.f_back
+        frame = prev
+        # wait for stdout to print
+        time.sleep(0.1)
+        p.interaction(frame, tb)
+
+
+def set_post_mortem():
+    """
+    Enable the post mortem debugging excepthook.
+    """
+    if IS_IPYTHON:
+        from IPython.core.getipython import get_ipython
+        def ipython_post_mortem_debug(shell, etype, evalue, tb,
+                   tb_offset=None):
+            post_mortem_excepthook(etype, evalue, tb)
+        ipython_shell = get_ipython()
+        ipython_shell.set_custom_exc((Exception,), ipython_post_mortem_debug)
+    else:
+        sys.excepthook = post_mortem_excepthook
+
+# Add post mortem debugging if requested and in a dedicated interpreter
+# existing interpreters use "runfile" below
+if "SPYDER_EXCEPTHOOK" in os.environ:
+    set_post_mortem()
+
+
 #==============================================================================
 # runfile and debugfile commands
 #==============================================================================
@@ -657,11 +762,12 @@ def _get_globals():
     return namespace
 
 
-def runfile(filename, args=None, wdir=None, namespace=None):
+def runfile(filename, args=None, wdir=None, namespace=None, post_mortem=False):
     """
     Run filename
     args: command line arguments (string)
     wdir: working directory
+    post_mortem: boolean, whether to enter post-mortem mode on error
     """
     try:
         filename = filename.decode('utf-8')
@@ -686,7 +792,7 @@ def runfile(filename, args=None, wdir=None, namespace=None):
     namespace['__file__'] = filename
     sys.argv = [filename]
     if args is not None:
-        for arg in args.split():
+        for arg in shlex.split(args):
             sys.argv.append(arg)
     if wdir is not None:
         try:
@@ -696,18 +802,22 @@ def runfile(filename, args=None, wdir=None, namespace=None):
             # AttributeError --> systematically raised in Python 3
             pass
         os.chdir(wdir)
+    if post_mortem:
+        set_post_mortem()
     execfile(filename, namespace)
+    clear_post_mortem()
     sys.argv = ['']
     namespace.pop('__file__')
-    
+
 builtins.runfile = runfile
 
 
-def debugfile(filename, args=None, wdir=None):
+def debugfile(filename, args=None, wdir=None, post_mortem=False):
     """
     Debug filename
     args: command line arguments (string)
     wdir: working directory
+    post_mortem: boolean, included for compatiblity with runfile
     """
     debugger = pdb.Pdb()
     filename = debugger.canonic(filename)
@@ -759,8 +869,8 @@ def evalsc(command):
             Popen('ls', shell=True, stdin=PIPE)
             _print('\n')
     elif command == 'scientific':
-        from spyderlib import baseconfig
-        execfile(baseconfig.SCIENTIFIC_STARTUP, namespace)
+        from spyderlib.config import base
+        execfile(base.SCIENTIFIC_STARTUP, namespace)
     else:
         raise NotImplementedError("Unsupported command: '%s'" % command)
 
@@ -776,3 +886,4 @@ try:
 except KeyError:
     if os.environ.get('PYTHONPATH') is not None:
         del os.environ['PYTHONPATH']
+
diff --git a/spyderlib/widgets/externalshell/start_ipython_kernel.py b/spyderlib/widgets/externalshell/start_ipython_kernel.py
index d39d848..4814bb7 100644
--- a/spyderlib/widgets/externalshell/start_ipython_kernel.py
+++ b/spyderlib/widgets/externalshell/start_ipython_kernel.py
@@ -38,9 +38,11 @@ init_session()
 
 def kernel_config():
     """Create a config object with IPython kernel options"""
+    import os
+
     from IPython.config.loader import Config, load_pyconfig_files
     from IPython.core.application import get_ipython_dir
-    from spyderlib.config import CONF
+    from spyderlib.config.main import CONF
     from spyderlib.utils.programs import is_module_installed
     
     # ---- IPython config ----
@@ -69,13 +71,23 @@ def kernel_config():
     mpl_backend = None
     mpl_installed = is_module_installed('matplotlib')
     pylab_o = CONF.get('ipython_console', 'pylab')
+    external_interpreter = \
+                   os.environ.get('EXTERNAL_INTERPRETER', '').lower() == "true"
 
     if mpl_installed and pylab_o:
         # Get matplotlib backend
-        backend_o = CONF.get('ipython_console', 'pylab/backend', 0)
-        backends = {0: 'inline', 1: 'auto', 2: 'qt', 3: 'osx', 4: 'gtk',
-                    5: 'wx', 6: 'tk'}
-        mpl_backend = backends[backend_o]
+        if not external_interpreter:
+            if os.environ["QT_API"] == 'pyqt5':
+                qt_backend = 'qt5'
+            else:
+                qt_backend = 'qt'
+
+            backend_o = CONF.get('ipython_console', 'pylab/backend', 0)
+            backends = {0: 'inline', 1: qt_backend, 2: qt_backend, 3: 'osx',
+                        4: 'gtk', 5: 'wx', 6: 'tk'}
+            mpl_backend = backends[backend_o]
+        else:
+            mpl_backend = 'inline'
 
         # Automatically load Pylab and Numpy, or only set Matplotlib
         # backend
diff --git a/spyderlib/widgets/externalshell/systemshell.py b/spyderlib/widgets/externalshell/systemshell.py
index 757fc35..48c1453 100644
--- a/spyderlib/widgets/externalshell/systemshell.py
+++ b/spyderlib/widgets/externalshell/systemshell.py
@@ -1,31 +1,35 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
 """External System Shell widget: execute terminal in a separate process"""
 
 import os
+import sys
 
 from spyderlib.qt.QtGui import QMessageBox
-from spyderlib.qt.QtCore import QProcess, SIGNAL, QTextCodec
+from spyderlib.qt.QtCore import (QProcess, Signal, QTextCodec,
+                                 QProcessEnvironment)
 LOCALE_CODEC = QTextCodec.codecForLocale()
 CP850_CODEC = QTextCodec.codecForName('cp850')
 
 # Local imports
 from spyderlib.utils.programs import shell_split
-from spyderlib.baseconfig import _
-from spyderlib.utils.qthelpers import get_icon
+from spyderlib.config.base import _
 from spyderlib.widgets.externalshell.baseshell import (ExternalShellBase,
                                                    add_pathlist_to_PYTHONPATH)
 from spyderlib.widgets.shell import TerminalWidget
 from spyderlib.py3compat import to_text_string, is_text_string
+import spyderlib.utils.icon_manager as ima
 
 
 class ExternalSystemShell(ExternalShellBase):
     """External Shell widget: execute Python script in a separate process"""
     SHELL_CLASS = TerminalWidget
+    started = Signal()
+    
     def __init__(self, parent=None, wdir=None, path=[], light_background=True,
                  menu_actions=None, show_buttons_inside=True,
                  show_elapsed_time=True):
@@ -45,19 +49,30 @@ class ExternalSystemShell(ExternalShellBase):
         self.connection_file = None
 
     def get_icon(self):
-        return get_icon('cmdprompt.png')
-    
+        return ima.icon('cmdprompt')
+
+    def finish_process(self):
+        while not self.process.waitForFinished(100):
+            self.process.kill();
+
     def create_process(self):
         self.shell.clear()
-            
+
         self.process = QProcess(self)
         self.process.setProcessChannelMode(QProcess.MergedChannels)
-        
+
         # PYTHONPATH (in case we use Python in this terminal, e.g. py2exe)
         env = [to_text_string(_path)
                for _path in self.process.systemEnvironment()]
+
+        processEnvironment = QProcessEnvironment()
+        for envItem in env:
+            envName, separator, envValue = envItem.partition('=')
+            processEnvironment.insert(envName, envValue)
+
         add_pathlist_to_PYTHONPATH(env, self.path)
-        self.process.setEnvironment(env)
+        self.process.setProcessEnvironment(processEnvironment)                   
+
         
         # Working directory
         if self.wdir is not None:
@@ -71,14 +86,10 @@ class ExternalSystemShell(ExternalShellBase):
             
         if self.arguments:
             p_args.extend( shell_split(self.arguments) )
-                        
-        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
-                     self.write_output)
-        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
-                     self.finished)
         
-        self.connect(self.kill_button, SIGNAL("clicked()"),
-                     self.process.kill)
+        self.process.readyReadStandardOutput.connect(self.write_output)
+        self.process.finished.connect(self.finished)
+        self.kill_button.clicked.connect(self.process.kill)
         
         if os.name == 'nt':
             self.process.start('cmd.exe', p_args)
@@ -94,7 +105,7 @@ class ExternalSystemShell(ExternalShellBase):
                                  _("Process failed to start"))
         else:
             self.shell.setFocus()
-            self.emit(SIGNAL('started()'))
+            self.started.emit()
             
         return self.process
     
@@ -143,4 +154,31 @@ class ExternalSystemShell(ExternalShellBase):
 #                                              x.dwProcessID)
 #        else:
 #            self.send_ctrl_to_process('c')
-                
\ No newline at end of file
+
+
+#==============================================================================
+# Tests
+#==============================================================================
+def test():
+    import os.path as osp
+    from spyderlib.utils.qthelpers import qapplication
+    app = qapplication(test_time=5)
+    shell = ExternalSystemShell(wdir=osp.dirname(__file__),
+                                light_background=False)
+
+    app.aboutToQuit.connect(shell.finish_process)
+
+    from spyderlib.qt.QtGui import QFont
+    from spyderlib.config.main import CONF
+    font = QFont(CONF.get('console', 'font/family')[0])
+    font.setPointSize(10)
+    shell.shell.set_font(font)
+
+    shell.shell.toggle_wrap_mode(True)
+    shell.start_shell(False)
+    shell.show()
+    sys.exit(app.exec_())
+
+
+if __name__ == "__main__":
+    test()
\ No newline at end of file
diff --git a/spyderlib/widgets/fileswitcher.py b/spyderlib/widgets/fileswitcher.py
new file mode 100644
index 0000000..b65ce71
--- /dev/null
+++ b/spyderlib/widgets/fileswitcher.py
@@ -0,0 +1,584 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2009- The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+from __future__ import print_function
+
+import os
+import os.path as osp
+
+from spyderlib.qt.QtGui import (QDialog, QHBoxLayout, QIcon, QLabel, QLineEdit,
+                                QListWidget, QListWidgetItem, QRegExpValidator,
+                                QTextCursor, QVBoxLayout)
+from spyderlib.qt.QtCore import Signal, QEvent, QObject, QRegExp, QSize, Qt
+
+# Local imports
+from spyderlib.config.base import _
+from spyderlib.py3compat import iteritems, to_text_string
+from spyderlib.utils import icon_manager as ima
+from spyderlib.utils.stringmatching import get_search_scores
+from spyderlib.widgets.helperwidgets import HelperToolButton, HTMLDelegate
+
+
+# --- Python Outline explorer helpers
+def process_python_symbol_data(oedata):
+    """Returns a list with line number, definition name, fold and token."""
+    symbol_list = []
+    for key in oedata:
+        val = oedata[key]
+        if val and key != 'found_cell_separators':
+            if val.is_class_or_function():
+                symbol_list.append((key, val.def_name, val.fold_level,
+                                    val.get_token()))
+    return sorted(symbol_list)
+
+
+def get_python_symbol_icons(oedata):
+    """Return a list of icons for oedata of a python file."""
+    class_icon = ima.icon('class')
+    method_icon = ima.icon('method')
+    function_icon = ima.icon('function')
+    private_icon = ima.icon('private1')
+    super_private_icon = ima.icon('private2')
+
+    symbols = process_python_symbol_data(oedata)
+
+    # line - 1, name, fold level
+    fold_levels = sorted(list(set([s[2] for s in symbols])))
+    parents = [None]*len(symbols)
+    icons = [None]*len(symbols)
+    indexes = []
+
+    parent = None
+    for level in fold_levels:
+        for index, item in enumerate(symbols):
+            line, name, fold_level, token = item
+            if index in indexes:
+                continue
+
+            if fold_level == level:
+                indexes.append(index)
+                parent = item
+            else:
+                parents[index] = parent
+
+    for index, item in enumerate(symbols):
+        parent = parents[index]
+
+        if item[-1] == 'def':
+            icons[index] = function_icon
+        elif item[-1] == 'class':
+            icons[index] = class_icon
+        else:
+            icons[index] = QIcon()
+
+        if parent is not None:
+            if parent[-1] == 'class':
+                if item[-1] == 'def' and item[1].startswith('__'):
+                    icons[index] = super_private_icon
+                elif item[-1] == 'def' and item[1].startswith('_'):
+                    icons[index] = private_icon
+                else:
+                    icons[index] = method_icon
+
+    return icons
+
+
+def shorten_paths(path_list, is_unsaved):
+    """
+    Takes a list of paths and tries to "intelligently" shorten them all. The
+    aim is to make it clear to the user where the paths differ, as that is
+    likely what they care about. Note that this operates on a list of paths
+    not on individual paths.
+
+    If the path ends in an actual file name, it will be trimmed off.
+    """
+    # TODO: at the end, if the path is too long, should do a more dumb kind of
+    # shortening, but not completely dumb.
+
+    # Convert the path strings to a list of tokens and start building the
+    # new_path using the drive
+    path_list = path_list[:]  # Make a local copy
+    new_path_list = []
+
+    for ii, (path, is_unsav) in enumerate(zip(path_list, is_unsaved)):
+        if is_unsav:
+            new_path_list.append(_('unsaved file'))
+            path_list[ii] = None
+        else:
+            drive, path = osp.splitdrive(osp.dirname(path))
+            new_path_list.append(drive + osp.sep)
+            path_list[ii] = [part for part in path.split(osp.sep) if part]
+
+    def recurse_level(level_idx):
+        sep = os.sep
+
+        # If toks are all empty we need not have recursed here
+        if not any(level_idx.values()):
+            return
+
+        # Firstly, find the longest common prefix for all in the level
+        # s = len of longest common prefix
+        sample_toks = list(level_idx.values())[0]
+        if not sample_toks:
+            s = 0
+        else:
+            for s, sample_val in enumerate(sample_toks):
+                if not all(len(toks) > s and toks[s] == sample_val
+                           for toks in level_idx.values()):
+                    break
+
+        # Shorten longest common prefix
+        if s == 0:
+            short_form = ''
+        else:
+            if s == 1:
+                short_form = sample_toks[0]
+            elif s == 2:
+                short_form = sample_toks[0] + sep + sample_toks[1]
+            else:
+                short_form = "..." + sep + sample_toks[s-1]
+            for idx in level_idx:
+                new_path_list[idx] += short_form + sep
+                level_idx[idx] = level_idx[idx][s:]
+
+        # Group the remaining bit after the common prefix, shorten, and recurse
+        while level_idx:
+            k, group = 0, level_idx  # k is length of the group's common prefix
+            while True:
+                # Abort if we've gone beyond end of one or more in the group
+                prospective_group = {idx: toks for idx, toks
+                                     in group.items() if len(toks) == k}
+                if prospective_group:
+                    if k == 0:  # we spit out the group with no suffix
+                        group = prospective_group
+                    break
+                # Only keep going if all n still match on the kth token
+                _, sample_toks = next(iteritems(group))
+                prospective_group = {idx: toks for idx, toks
+                                     in group.items()
+                                     if toks[k] == sample_toks[k]}
+                if len(prospective_group) == len(group) or k == 0:
+                    group = prospective_group
+                    k += 1
+                else:
+                    break
+            _, sample_toks = next(iteritems(group))
+            if k == 0:
+                short_form = ''
+            elif k == 1:
+                short_form = sample_toks[0]
+            elif k == 2:
+                short_form = sample_toks[0] + sep + sample_toks[1]
+            else:  # k > 2
+                short_form = sample_toks[0] + "..." + sep + sample_toks[k-1]
+            for idx in group.keys():
+                new_path_list[idx] += short_form + (sep if k > 0 else '')
+                del level_idx[idx]
+            recurse_level({idx: toks[k:] for idx, toks in group.items()})
+
+    recurse_level({i: pl for i, pl in enumerate(path_list) if pl})
+
+    return [path.rstrip(os.sep) for path in new_path_list]
+
+
+class KeyPressFilter(QObject):
+    """
+    Use with `installEventFilter` to get up/down arrow key press signal.
+    """
+    UP, DOWN = [-1, 1]  # Step constants
+
+    sig_up_key_pressed = Signal()
+    sig_down_key_pressed = Signal()
+
+    def eventFilter(self, src, e):
+        if e.type() == QEvent.KeyPress:
+            if e.key() == Qt.Key_Up:
+                self.sig_up_key_pressed.emit()
+            elif e.key() == Qt.Key_Down:
+                self.sig_down_key_pressed.emit()
+
+        return super(KeyPressFilter, self).eventFilter(src, e)
+
+
+class FileSwitcher(QDialog):
+    """A Sublime-like file switcher."""
+    sig_goto_file = Signal(int)
+    sig_close_file = Signal(int)
+
+    # Constants that define the mode in which the list widget is working
+    # FILE_MODE is for a list of files, SYMBOL_MODE if for a list of symbols
+    # in a given file when using the '@' symbol.
+    FILE_MODE, SYMBOL_MODE = [1, 2]
+
+    def __init__(self, parent, tabs, data):
+        QDialog.__init__(self, parent)
+
+        # Variables
+        self.tabs = tabs                  # Editor stack tabs
+        self.data = data                  # Editor data
+        self.mode = self.FILE_MODE        # By default start in this mode
+        self.initial_cursors = None       # {fullpath: QCursor}
+        self.initial_path = None          # Fullpath of initial active editor
+        self.initial_editor = None        # Initial active editor
+        self.line_number = None           # Selected line number in filer
+
+        help_text = _("Press <b>Enter</b> to switch files or <b>Esc</b> to "
+                      "cancel.<br><br>Type to filter filenames.<br><br>"
+                      "Use <b>:number</b> to go to a line, e.g. "
+                      "<b><code>main:42</code></b><br>"
+                      "Use <b>@symbol_text</b> to go to a symbol, e.g. "
+                      "<b><code>@init</code></b>"
+                      "<br><br> Press <b>Ctrl+W</b> to close current tab.<br>")
+
+        # Either allow searching for a line number or a symbol but not both
+        regex = QRegExp("([A-Za-z0-9_]{0,100}@[A-Za-z0-9_]{0,100})|" +
+                        "([A-Za-z]{0,100}:{0,1}[0-9]{0,100})")
+
+        # Widgets
+        self.edit = QLineEdit(self)
+        self.help = HelperToolButton()
+        self.list = QListWidget(self)
+        self.filter = KeyPressFilter()
+        regex_validator = QRegExpValidator(regex, self.edit)
+
+        # Widgets setup
+        self.setWindowFlags(Qt.Popup | Qt.FramelessWindowHint)
+        self.setWindowOpacity(0.95)
+        self.edit.installEventFilter(self.filter)
+        self.edit.setValidator(regex_validator)
+        self.help.setToolTip(help_text)
+        self.list.setItemDelegate(HTMLDelegate(self))
+
+        # Layout
+        edit_layout = QHBoxLayout()
+        edit_layout.addWidget(self.edit)
+        edit_layout.addWidget(self.help)
+        layout = QVBoxLayout()
+        layout.addLayout(edit_layout)
+        layout.addWidget(self.list)
+        self.setLayout(layout)
+
+        # Signals
+        self.rejected.connect(self.restore_initial_state)
+        self.filter.sig_up_key_pressed.connect(self.previous_row)
+        self.filter.sig_down_key_pressed.connect(self.next_row)
+        self.edit.returnPressed.connect(self.accept)
+        self.edit.textChanged.connect(self.setup)
+        self.list.itemSelectionChanged.connect(self.item_selection_changed)
+        self.list.clicked.connect(self.edit.setFocus)
+
+        # Setup
+        self.save_initial_state()
+        self.set_dialog_position()
+        self.setup()
+
+    # --- Properties
+    @property
+    def editors(self):
+        return [self.tabs.widget(index) for index in range(self.tabs.count())]
+
+    @property
+    def line_count(self):
+        return [editor.get_line_count() for editor in self.editors]
+
+    @property
+    def save_status(self):
+        return [getattr(td, 'newly_created', False) for td in self.data]
+
+    @property
+    def paths(self):
+        return [getattr(td, 'filename', None) for td in self.data]
+
+    @property
+    def filenames(self):
+        return [self.tabs.tabText(index) for index in range(self.tabs.count())]
+
+    @property
+    def current_path(self):
+        return self.paths_by_editor[self.get_editor()]
+
+    @property
+    def paths_by_editor(self):
+        return dict(zip(self.editors, self.paths))
+
+    @property
+    def editors_by_path(self):
+        return dict(zip(self.paths, self.editors))
+
+    @property
+    def filter_text(self):
+        """Get the normalized (lowecase) content of the filter text."""
+        return to_text_string(self.edit.text()).lower()
+
+    def save_initial_state(self):
+        """Saves initial cursors and initial active editor."""
+        paths = self.paths
+        self.initial_editor = self.get_editor()
+        self.initial_cursors = {}
+
+        for i, editor in enumerate(self.editors):
+            if editor is self.initial_editor:
+                self.initial_path = paths[i]
+            self.initial_cursors[paths[i]] = editor.textCursor()
+
+    def accept(self):
+        QDialog.accept(self)
+        self.list.clear()
+
+    def restore_initial_state(self):
+        """Restores initial cursors and initial active editor."""
+        self.list.clear()
+        editors = self.editors_by_path
+
+        for path in self.initial_cursors:
+            cursor = self.initial_cursors[path]
+            if path in editors:
+                self.set_editor_cursor(editors[path], cursor)
+
+        if self.initial_editor in self.paths_by_editor:
+            index = self.paths.index(self.initial_path)
+            self.sig_goto_file.emit(index)
+
+    def set_dialog_position(self):
+        """Positions the file switcher dialog in the center of the editor."""
+        parent = self.parent()
+        geo = parent.geometry()
+        width = self.list.width()  # This has been set in setup
+
+        left = parent.geometry().width()/2 - width/2
+        top = 0
+        while parent:
+            geo = parent.geometry()
+            top += geo.top()
+            left += geo.left()
+            parent = parent.parent()
+
+        # Note: the +1 pixel on the top makes it look better
+        self.move(left, top + self.tabs.tabBar().geometry().height() + 1)
+
+    def fix_size(self, content, extra=50):
+        """Adjusts the width of the file switcher, based on the content."""
+        # Update size of dialog based on longest shortened path
+        strings = []
+        if content:
+            for rich_text in content:
+                label = QLabel(rich_text)
+                label.setTextFormat(Qt.PlainText)
+                strings.append(label.text())
+                fm = label.fontMetrics()
+            max_width = max([fm.width(s)*1.3 for s in strings])
+            self.list.setMinimumWidth(max_width + extra)
+            self.set_dialog_position()
+
+    # --- Helper methods: List widget
+    def count(self):
+        """Gets the item count in the list widget."""
+        return self.list.count()
+
+    def current_row(self):
+        """Returns the current selected row in the list widget."""
+        return self.list.currentRow()
+
+    def set_current_row(self, row):
+        """Sets the current selected row in the list widget."""
+        return self.list.setCurrentRow(row)
+
+    def select_row(self, steps):
+        """Select row in list widget based on a number of steps with direction.
+
+        Steps can be positive (next rows) or negative (previous rows).
+        """
+        row = self.current_row() + steps
+        if 0 <= row < self.count():
+            self.set_current_row(row)
+
+    def previous_row(self):
+        """Select previous row in list widget."""
+        self.select_row(-1)
+
+    def next_row(self):
+        """Select next row in list widget."""
+        self.select_row(+1)
+
+    # --- Helper methods: Editor
+    def get_editor(self, index=None, path=None):
+        """Get editor by index or path.
+        
+        If no path or index specified the current active editor is returned
+        """
+        if index:
+            return self.tabs.widget(index)
+        elif path:
+            return self.tabs.widget(index)
+        else:
+            return self.parent().get_current_editor()
+
+    def set_editor_cursor(self, editor, cursor):
+        """Set the cursor of an editor."""
+        pos = cursor.position()
+        anchor = cursor.anchor()
+
+        new_cursor = QTextCursor()
+        if pos == anchor:
+            new_cursor.movePosition(pos)
+        else:
+            new_cursor.movePosition(anchor)
+            new_cursor.movePosition(pos, QTextCursor.KeepAnchor)
+        editor.setTextCursor(cursor)
+
+    def goto_line(self, line_number):
+        """Go to specified line number in current active editor."""
+        if line_number:
+            line_number = int(line_number)
+            editor = self.get_editor()
+            editor.go_to_line(min(line_number, editor.get_line_count()))
+
+    # --- Helper methods: Outline explorer
+    def get_symbol_list(self):
+        """Get the object explorer data."""
+        return self.get_editor().highlighter.get_outlineexplorer_data()
+
+    # --- Handlers
+    def item_selection_changed(self):
+        """List widget item selection change handler."""
+        row = self.current_row()
+        if self.count() and row >= 0:
+            if self.mode == self.FILE_MODE:
+                try:
+                    stack_index = self.paths.index(self.filtered_path[row])
+                    self.sig_goto_file.emit(stack_index)
+                    self.goto_line(self.line_number)
+                    self.edit.setFocus()
+                except ValueError:
+                    pass
+            else:
+                line_number = self.filtered_symbol_lines[row]
+                self.goto_line(line_number)
+
+    def setup_file_list(self, filter_text, current_path):
+        """Setup list widget content for file list display."""
+        short_paths = shorten_paths(self.paths, self.save_status)
+        paths = self.paths
+        results = []
+        trying_for_line_number = ':' in filter_text
+
+        # Get optional line number
+        if trying_for_line_number:
+            filter_text, line_number = filter_text.split(':')
+        else:
+            line_number = None
+
+        # Get all available filenames and get the scores for "fuzzy" matching
+        scores = get_search_scores(filter_text, self.filenames,
+                                   template="<b>{0}</b>")
+
+        # Build the text that will appear on the list widget
+        for index, score in enumerate(scores):
+            text, rich_text, score_value = score
+            if score_value != -1:
+                text_item = '<big>' + rich_text + '</big>'
+                if trying_for_line_number:
+                    text_item += " [{0:} {1:}]".format(self.line_count[index],
+                                                       _("lines"))
+                text_item += "<br><i>{0:}</i>".format(
+                    short_paths[index])
+
+                results.append((score_value, index, text_item))
+
+        # Sort the obtained scores and populate the list widget
+        self.filtered_path = []
+        for result in sorted(results):
+            index = result[1]
+            text = result[-1]
+            path = paths[index]
+            item = QListWidgetItem(self.tabs.tabIcon(index), text)
+            item.setToolTip(path)
+            item.setSizeHint(QSize(0, 25))
+            self.list.addItem(item)
+            self.filtered_path.append(path)
+
+        # Move selected item in list accordingly and update list size
+        if current_path in self.filtered_path:
+            self.set_current_row(self.filtered_path.index(current_path))
+        elif self.filtered_path:
+            self.set_current_row(0)
+        self.fix_size(short_paths)
+
+        # If a line number is searched look for it
+        self.line_number = line_number
+        self.goto_line(line_number)
+
+    def setup_symbol_list(self, filter_text, current_path):
+        """Setup list widget content for symbol list display."""
+        # Get optional symbol name
+        filter_text, symbol_text = filter_text.split('@')
+
+        # Fetch the Outline explorer data, get the icons and values
+        oedata = self.get_symbol_list()
+        icons = get_python_symbol_icons(oedata)
+
+        symbol_list = process_python_symbol_data(oedata)
+        line_fold_token = [(item[0], item[2], item[3]) for item in symbol_list]
+        choices = [item[1] for item in symbol_list]
+        scores = get_search_scores(symbol_text, choices, template="<b>{0}</b>")
+
+        # Build the text that will appear on the list widget
+        results = []
+        lines = []
+        self.filtered_symbol_lines = []
+        for index, score in enumerate(scores):
+            text, rich_text, score_value = score
+            line, fold_level, token = line_fold_token[index]
+            lines.append(text)
+            if score_value != -1:
+                results.append((score_value, line, text, rich_text,
+                                fold_level, icons[index], token))
+
+        template_1 = '<code>{0}<big>{1} {2}</big></code>'
+        template_2 = '<br><code>{0}</code><i>[Line {1}]</i>'
+
+        for (score, line, text, rich_text, fold_level, icon,
+             token) in sorted(results):
+            fold_space = ' '*(fold_level)
+            line_number = line + 1
+            self.filtered_symbol_lines.append(line_number)
+            textline = template_1.format(fold_space, token, rich_text)
+            textline += template_2.format(fold_space, line_number)
+            item = QListWidgetItem(icon, textline)
+            item.setSizeHint(QSize(0, 16))
+            self.list.addItem(item)
+
+        # Move selected item in list accordingly
+        # NOTE: Doing this is causing two problems:
+        # 1. It makes the cursor to auto-jump to the last selected
+        #    symbol after opening or closing a different file
+        # 2. It moves the cursor to the first symbol by default,
+        #    which is very distracting.
+        # That's why this line is commented!
+        # self.set_current_row(0)
+
+        # Update list size
+        self.fix_size(lines, extra=125)
+
+    def setup(self):
+        """Setup list widget content."""
+        if not self.tabs.count():
+            self.close()
+            return
+
+        self.list.clear()
+        current_path = self.current_path
+        filter_text = self.filter_text
+
+        # Get optional line or symbol to define mode and method handler
+        trying_for_symbol = ('@' in self.filter_text)
+
+        if trying_for_symbol:
+            self.mode = self.SYMBOL_MODE
+            self.setup_symbol_list(filter_text, current_path)
+        else:
+            self.mode = self.FILE_MODE
+            self.setup_file_list(filter_text, current_path)
diff --git a/spyderlib/widgets/findinfiles.py b/spyderlib/widgets/findinfiles.py
index a8f2372..fb3d312 100644
--- a/spyderlib/widgets/findinfiles.py
+++ b/spyderlib/widgets/findinfiles.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -15,8 +15,10 @@ from __future__ import with_statement
 
 from spyderlib.qt.QtGui import (QHBoxLayout, QWidget, QTreeWidgetItem,
                                 QSizePolicy, QRadioButton, QVBoxLayout, QLabel)
-from spyderlib.qt.QtCore import SIGNAL, Qt, QThread, QMutexLocker, QMutex
+from spyderlib.qt.QtCore import (Signal, Slot, Qt, QThread, QMutexLocker,
+                                 QMutex)
 from spyderlib.qt.compat import getexistingdirectory
+import spyderlib.utils.icon_manager as ima
 
 import sys
 import os
@@ -29,9 +31,8 @@ import traceback
 # Local imports
 from spyderlib.utils.vcs import is_hg_installed, get_vcs_root
 from spyderlib.utils.misc import abspardir, get_common_path
-from spyderlib.utils.qthelpers import (get_icon, get_std_icon,
-                                       create_toolbutton, get_filetype_icon)
-from spyderlib.baseconfig import _
+from spyderlib.utils.qthelpers import create_toolbutton, get_filetype_icon
+from spyderlib.config.base import _
 from spyderlib.widgets.comboboxes import PathComboBox, PatternComboBox
 from spyderlib.widgets.onecolumntree import OneColumnTree
 from spyderlib.py3compat import to_text_string, getcwd
@@ -106,6 +107,8 @@ from spyderlib.py3compat import to_text_string, getcwd
 
 class SearchThread(QThread):
     """Find in files search thread"""
+    sig_finished = Signal(bool)
+    
     def __init__(self, parent):
         QThread.__init__(self, parent)
         self.mutex = QMutex()
@@ -154,7 +157,7 @@ class SearchThread(QThread):
             traceback.print_exc()
             self.error_flag = _("Unexpected error: see internal console")
         self.stop()
-        self.emit(SIGNAL("finished(bool)"), self.completed)
+        self.sig_finished.emit(self.completed)
         
     def stop(self):
         with QMutexLocker(self.mutex):
@@ -284,6 +287,9 @@ class SearchThread(QThread):
 
 class FindOptions(QWidget):
     """Find widget with options"""
+    find = Signal()
+    stop = Signal()
+    
     def __init__(self, parent, search_text, search_text_regexp, search_path,
                  include, include_idx, include_regexp,
                  exclude, exclude_idx, exclude_regexp,
@@ -309,8 +315,8 @@ class FindOptions(QWidget):
         self.search_text = PatternComboBox(self, search_text,
                                            _("Search pattern"))
         self.edit_regexp = create_toolbutton(self,
-                                             icon=get_icon("advanced.png"),
-                                             tip=_("Regular expression"))
+                                             icon=ima.icon('advanced'),
+                                             tip=_('Regular expression'))
         self.edit_regexp.setCheckable(True)
         self.edit_regexp.setChecked(search_text_regexp)
         self.more_widgets = ()
@@ -320,14 +326,14 @@ class FindOptions(QWidget):
         self.more_options.setChecked(more_options)
         
         self.ok_button = create_toolbutton(self, text=_("Search"),
-                                icon=get_std_icon("DialogApplyButton"),
-                                triggered=lambda: self.emit(SIGNAL('find()')),
+                                icon=ima.icon('DialogApplyButton'),
+                                triggered=lambda: self.find.emit(),
                                 tip=_("Start search"),
                                 text_beside_icon=True)
-        self.connect(self.ok_button, SIGNAL('clicked()'), self.update_combos)
+        self.ok_button.clicked.connect(self.update_combos)
         self.stop_button = create_toolbutton(self, text=_("Stop"),
-                                icon=get_icon("stop.png"),
-                                triggered=lambda: self.emit(SIGNAL('stop()')),
+                                icon=ima.icon('stop'),
+                                triggered=lambda: self.stop.emit(),
                                 tip=_("Stop search"),
                                 text_beside_icon=True)
         self.stop_button.setEnabled(False)
@@ -343,8 +349,8 @@ class FindOptions(QWidget):
            and include_idx < self.include_pattern.count():
             self.include_pattern.setCurrentIndex(include_idx)
         self.include_regexp = create_toolbutton(self,
-                                            icon=get_icon("advanced.png"),
-                                            tip=_("Regular expression"))
+                                            icon=ima.icon('advanced'),
+                                            tip=_('Regular expression'))
         self.include_regexp.setCheckable(True)
         self.include_regexp.setChecked(include_regexp)
         include_label = QLabel(_("Include:"))
@@ -355,8 +361,8 @@ class FindOptions(QWidget):
            and exclude_idx < self.exclude_pattern.count():
             self.exclude_pattern.setCurrentIndex(exclude_idx)
         self.exclude_regexp = create_toolbutton(self,
-                                            icon=get_icon("advanced.png"),
-                                            tip=_("Regular expression"))
+                                            icon=ima.icon('advanced'),
+                                            tip=_('Regular expression'))
         self.exclude_regexp.setCheckable(True)
         self.exclude_regexp.setChecked(exclude_regexp)
         exclude_label = QLabel(_("Exclude:"))
@@ -383,27 +389,20 @@ class FindOptions(QWidget):
         self.dir_combo = PathComboBox(self)
         self.dir_combo.addItems(search_path)
         self.dir_combo.setToolTip(_("Search recursively in this directory"))
-        self.connect(self.dir_combo, SIGNAL("open_dir(QString)"),
-                     self.set_directory)
-        self.connect(self.python_path, SIGNAL('toggled(bool)'),
-                     self.dir_combo.setDisabled)
-        self.connect(self.hg_manifest, SIGNAL('toggled(bool)'),
-                     self.dir_combo.setDisabled)
-        browse = create_toolbutton(self, icon=get_std_icon('DirOpenIcon'),
+        self.dir_combo.open_dir.connect(self.set_directory)
+        self.python_path.toggled.connect(self.dir_combo.setDisabled)
+        self.hg_manifest.toggled.connect(self.dir_combo.setDisabled)
+        browse = create_toolbutton(self, icon=ima.icon('DirOpenIcon'),
                                    tip=_('Browse a search directory'),
                                    triggered=self.select_directory)
         for widget in [self.python_path, self.hg_manifest, self.custom_dir,
                        self.dir_combo, browse]:
             hlayout3.addWidget(widget)
             
-        self.connect(self.search_text, SIGNAL("valid(bool)"),
-                     lambda valid: self.emit(SIGNAL('find()')))
-        self.connect(self.include_pattern, SIGNAL("valid(bool)"),
-                     lambda valid: self.emit(SIGNAL('find()')))
-        self.connect(self.exclude_pattern, SIGNAL("valid(bool)"),
-                     lambda valid: self.emit(SIGNAL('find()')))
-        self.connect(self.dir_combo, SIGNAL("valid(bool)"),
-                     lambda valid: self.emit(SIGNAL('find()')))
+        self.search_text.valid.connect(lambda valid: self.find.emit())
+        self.include_pattern.valid.connect(lambda valid: self.find.emit())
+        self.exclude_pattern.valid.connect(lambda valid: self.find.emit())
+        self.dir_combo.valid.connect(lambda valid: self.find.emit())
             
         vlayout = QVBoxLayout()
         vlayout.setContentsMargins(0, 0, 0, 0)
@@ -415,25 +414,26 @@ class FindOptions(QWidget):
         self.setLayout(vlayout)
                 
         self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
-        
+
+    @Slot(bool)
     def toggle_more_options(self, state):
         for layout in self.more_widgets:
             for index in range(layout.count()):
                 if state and self.isVisible() or not state:
                     layout.itemAt(index).widget().setVisible(state)
         if state:
-            icon_name = 'options_less.png'
+            icon = ima.icon('options_less')
             tip = _('Hide advanced options')
         else:
-            icon_name = 'options_more.png'
+            icon = ima.icon('options_more')
             tip = _('Show advanced options')
-        self.more_options.setIcon(get_icon(icon_name))
+        self.more_options.setIcon(icon)
         self.more_options.setToolTip(tip)
         
     def update_combos(self):
-        self.search_text.lineEdit().emit(SIGNAL('returnPressed()'))
-        self.include_pattern.lineEdit().emit(SIGNAL('returnPressed()'))
-        self.exclude_pattern.lineEdit().emit(SIGNAL('returnPressed()'))
+        self.search_text.lineEdit().returnPressed.emit()
+        self.include_pattern.lineEdit().returnPressed.emit()
+        self.exclude_pattern.lineEdit().returnPressed.emit()
         
     def detect_hg_repository(self, path=None):
         if path is None:
@@ -497,15 +497,16 @@ class FindOptions(QWidget):
         else:
             return (path, python_path, hg_manifest,
                     include, exclude, texts, text_re)
-        
+
+    @Slot()
     def select_directory(self):
         """Select directory"""
-        self.parent().emit(SIGNAL('redirect_stdio(bool)'), False)
+        self.parent().redirect_stdio.emit(False)
         directory = getexistingdirectory(self, _("Select directory"),
                                          self.dir_combo.currentText())
         if directory:
             self.set_directory(directory)
-        self.parent().emit(SIGNAL('redirect_stdio(bool)'), True)
+        self.parent().redirect_stdio.emit(True)
         
     def set_directory(self, directory):
         path = to_text_string(osp.abspath(to_text_string(directory)))
@@ -517,11 +518,10 @@ class FindOptions(QWidget):
         ctrl = event.modifiers() & Qt.ControlModifier
         shift = event.modifiers() & Qt.ShiftModifier
         if event.key() in (Qt.Key_Enter, Qt.Key_Return):
-            self.emit(SIGNAL('find()'))
+            self.find.emit()
         elif event.key() == Qt.Key_F and ctrl and shift:
             # Toggle find widgets
-            self.parent().emit(SIGNAL('toggle_visibility(bool)'),
-                               not self.isVisible())
+            self.parent().toggle_visibility.emit(not self.isVisible())
         else:
             QWidget.keyPressEvent(self, event)
 
@@ -543,8 +543,7 @@ class ResultsBrowser(OneColumnTree):
         itemdata = self.data.get(id(self.currentItem()))
         if itemdata is not None:
             filename, lineno = itemdata
-            self.parent().emit(SIGNAL("edit_goto(QString,int,QString)"),
-                               filename, lineno, self.search_text)
+            self.parent().edit_goto.emit(filename, lineno, self.search_text)
 
     def clicked(self, item):
         """Click event"""
@@ -620,7 +619,7 @@ class ResultsBrowser(OneColumnTree):
                 displayed_name = dirname
             item = QTreeWidgetItem(parent, [displayed_name],
                                    QTreeWidgetItem.Type)
-            item.setIcon(0, get_std_icon('DirClosedIcon'))
+            item.setIcon(0, ima.icon('DirClosedIcon'))
             return item
         dirs = {}
         for dirname in sorted(list(dir_set)):
@@ -664,7 +663,7 @@ class ResultsBrowser(OneColumnTree):
                 item = QTreeWidgetItem(file_item,
                            ["%d (%s): %s" % (lineno, colno_str, line.rstrip())],
                            QTreeWidgetItem.Type)
-                item.setIcon(0, get_icon('arrow.png'))
+                item.setIcon(0, ima.icon('arrow'))
                 self.data[id(item)] = (filename, lineno)
         # Removing empty directories
         top_level_items = [self.topLevelItem(index)
@@ -699,9 +698,8 @@ class FindInFilesWidget(QWidget):
                                         exclude, exclude_idx, exclude_regexp,
                                         supported_encodings, in_python_path,
                                         more_options)
-        self.connect(self.find_options, SIGNAL('find()'), self.find)
-        self.connect(self.find_options, SIGNAL('stop()'),
-                     self.stop_and_reset_thread)
+        self.find_options.find.connect(self.find)
+        self.find_options.stop.connect(self.stop_and_reset_thread)
         
         self.result_browser = ResultsBrowser(self)
         
@@ -748,8 +746,7 @@ class FindInFilesWidget(QWidget):
         self.search_thread = SearchThread(self)
         self.search_thread.get_pythonpath_callback = \
                                                 self.get_pythonpath_callback
-        self.connect(self.search_thread, SIGNAL("finished(bool)"),
-                     self.search_complete)
+        self.search_thread.sig_finished.connect(self.search_complete)
         self.search_thread.initialize(*options)
         self.search_thread.start()
         self.find_options.ok_button.setEnabled(False)
@@ -760,9 +757,8 @@ class FindInFilesWidget(QWidget):
         if self.search_thread is not None:
             if self.search_thread.isRunning():
                 if ignore_results:
-                    self.disconnect(self.search_thread,
-                                    SIGNAL("finished(bool)"),
-                                    self.search_complete)
+                    self.search_thread.sig_finished.disconnect(
+                                                         self.search_complete)
                 self.search_thread.stop()
                 self.search_thread.wait()
             self.search_thread.setParent(None)
@@ -794,9 +790,10 @@ def test():
     from spyderlib.utils.qthelpers import qapplication
     app = qapplication()
     widget = FindInFilesWidget(None)
+    widget.resize(640, 480)
     widget.show()
     sys.exit(app.exec_())
-    
+
+
 if __name__ == '__main__':
     test()
-    
\ No newline at end of file
diff --git a/spyderlib/widgets/findreplace.py b/spyderlib/widgets/findreplace.py
index 521195a..8c2314d 100644
--- a/spyderlib/widgets/findreplace.py
+++ b/spyderlib/widgets/findreplace.py
@@ -13,15 +13,15 @@
 
 from spyderlib.qt.QtGui import (QHBoxLayout, QGridLayout, QCheckBox, QLabel,
                                 QWidget, QSizePolicy, QTextCursor)
-from spyderlib.qt.QtCore import SIGNAL, Qt, QTimer
+from spyderlib.qt.QtCore import Signal, Slot, Qt, QTimer
+import spyderlib.utils.icon_manager as ima
 
 import re
 
 # Local imports
-from spyderlib.baseconfig import _
-from spyderlib.guiconfig import create_shortcut, new_shortcut
-from spyderlib.utils.qthelpers import (get_icon, get_std_icon,
-                                       create_toolbutton)
+from spyderlib.config.base import _
+from spyderlib.config.gui import create_shortcut, new_shortcut
+from spyderlib.utils.qthelpers import get_icon, create_toolbutton
 from spyderlib.widgets.comboboxes import PatternComboBox
 from spyderlib.py3compat import to_text_string
 
@@ -36,14 +36,11 @@ def is_position_inf(pos1, pos2):
 
 
 class FindReplace(QWidget):
-    """
-    Find widget
-    
-    Signals:
-        visibility_changed(bool)
-    """
+    """Find widget"""
     STYLE = {False: "background-color:rgb(255, 175, 90);",
              True: ""}
+    visibility_changed = Signal(bool)
+    
     def __init__(self, parent, enable_replace=False):
         QWidget.__init__(self, parent)
         self.enable_replace = enable_replace
@@ -55,55 +52,49 @@ class FindReplace(QWidget):
         self.setLayout(glayout)
         
         self.close_button = create_toolbutton(self, triggered=self.hide,
-                                      icon=get_std_icon("DialogCloseButton"))
+                                      icon=ima.icon('DialogCloseButton'))
         glayout.addWidget(self.close_button, 0, 0)
         
         # Find layout
         self.search_text = PatternComboBox(self, tip=_("Search string"),
                                            adjust_to_minimum=False)
-        self.connect(self.search_text, SIGNAL('valid(bool)'),
+        self.search_text.valid.connect(
                      lambda state:
                      self.find(changed=False, forward=True, rehighlight=False))
-        self.connect(self.search_text.lineEdit(),
-                     SIGNAL("textEdited(QString)"), self.text_has_been_edited)
+        self.search_text.lineEdit().textEdited.connect(
+                                                     self.text_has_been_edited)
         
         self.previous_button = create_toolbutton(self,
                                              triggered=self.find_previous,
-                                             icon=get_std_icon("ArrowBack"))
+                                             icon=ima.icon('ArrowUp'))
         self.next_button = create_toolbutton(self,
                                              triggered=self.find_next,
-                                             icon=get_std_icon("ArrowForward"))
-        self.connect(self.next_button, SIGNAL('clicked()'),
-                     self.update_search_combo)
-        self.connect(self.previous_button, SIGNAL('clicked()'),
-                     self.update_search_combo)
+                                             icon=ima.icon('ArrowDown'))
+        self.next_button.clicked.connect(self.update_search_combo)
+        self.previous_button.clicked.connect(self.update_search_combo)
 
-        self.re_button = create_toolbutton(self, icon=get_icon("advanced.png"),
+        self.re_button = create_toolbutton(self, icon=ima.icon('advanced'),
                                            tip=_("Regular expression"))
         self.re_button.setCheckable(True)
-        self.connect(self.re_button, SIGNAL("toggled(bool)"),
-                     lambda state: self.find())
+        self.re_button.toggled.connect(lambda state: self.find())
         
         self.case_button = create_toolbutton(self,
                                              icon=get_icon("upper_lower.png"),
                                              tip=_("Case Sensitive"))
         self.case_button.setCheckable(True)
-        self.connect(self.case_button, SIGNAL("toggled(bool)"),
-                     lambda state: self.find())
+        self.case_button.toggled.connect(lambda state: self.find())
                      
         self.words_button = create_toolbutton(self,
                                               icon=get_icon("whole_words.png"),
                                               tip=_("Whole words"))
         self.words_button.setCheckable(True)
-        self.connect(self.words_button, SIGNAL("toggled(bool)"),
-                     lambda state: self.find())
+        self.words_button.toggled.connect(lambda state: self.find())
                      
         self.highlight_button = create_toolbutton(self,
                                               icon=get_icon("highlight.png"),
                                               tip=_("Highlight matches"))
         self.highlight_button.setCheckable(True)
-        self.connect(self.highlight_button, SIGNAL("toggled(bool)"),
-                     self.toggle_highlighting)
+        self.highlight_button.toggled.connect(self.toggle_highlighting)
 
         hlayout = QHBoxLayout()
         self.widgets = [self.close_button, self.search_text,
@@ -117,17 +108,15 @@ class FindReplace(QWidget):
         # Replace layout
         replace_with = QLabel(_("Replace with:"))
         self.replace_text = PatternComboBox(self, adjust_to_minimum=False,
-                                            tip=_("Replace string"))
+                                            tip=_('Replace string'))
         
         self.replace_button = create_toolbutton(self,
-                                     text=_("Replace/find"),
-                                     icon=get_std_icon("DialogApplyButton"),
+                                     text=_('Replace/find'),
+                                     icon=ima.icon('DialogApplyButton'),
                                      triggered=self.replace_find,
                                      text_beside_icon=True)
-        self.connect(self.replace_button, SIGNAL('clicked()'),
-                     self.update_replace_combo)
-        self.connect(self.replace_button, SIGNAL('clicked()'),
-                     self.update_search_combo)
+        self.replace_button.clicked.connect(self.update_replace_combo)
+        self.replace_button.clicked.connect(self.update_search_combo)
         
         self.all_check = QCheckBox(_("Replace all"))
         
@@ -150,8 +139,7 @@ class FindReplace(QWidget):
         self.highlight_timer = QTimer(self)
         self.highlight_timer.setSingleShot(True)
         self.highlight_timer.setInterval(1000)
-        self.connect(self.highlight_timer, SIGNAL("timeout()"),
-                     self.highlight_matches)
+        self.highlight_timer.timeout.connect(self.highlight_matches)
         
     def create_shortcuts(self, parent):
         """Create shortcuts for this widget"""
@@ -180,10 +168,10 @@ class FindReplace(QWidget):
         return [sc.data for sc in self.shortcuts]
         
     def update_search_combo(self):
-        self.search_text.lineEdit().emit(SIGNAL('returnPressed()'))
+        self.search_text.lineEdit().returnPressed.emit()
         
     def update_replace_combo(self):
-        self.replace_text.lineEdit().emit(SIGNAL('returnPressed()'))
+        self.replace_text.lineEdit().returnPressed.emit()
     
     def toggle_replace_widgets(self):
         if self.enable_replace:
@@ -194,7 +182,8 @@ class FindReplace(QWidget):
             else:
                 self.show_replace()
                 self.replace_text.setFocus()
-                
+
+    @Slot(bool)
     def toggle_highlighting(self, state):
         """Toggle the 'highlight all results' feature"""
         if self.editor is not None:
@@ -206,7 +195,7 @@ class FindReplace(QWidget):
     def show(self):
         """Overrides Qt Method"""
         QWidget.show(self)
-        self.emit(SIGNAL("visibility_changed(bool)"), True)
+        self.visibility_changed.emit(True)
         if self.editor is not None:
             text = self.editor.get_selected_text()
             if len(text) > 0:
@@ -216,13 +205,14 @@ class FindReplace(QWidget):
             else:
                 self.search_text.lineEdit().selectAll()
             self.search_text.setFocus()
-        
+
+    @Slot()
     def hide(self):
         """Overrides Qt Method"""
         for widget in self.replace_widgets:
             widget.hide()
         QWidget.hide(self)
-        self.emit(SIGNAL("visibility_changed(bool)"), False)
+        self.visibility_changed.emit(False)
         if self.editor is not None:
             self.editor.setFocus()
             self.clear_matches()
@@ -267,14 +257,16 @@ class FindReplace(QWidget):
             self.refresh()
         if self.isHidden() and editor is not None:
             self.clear_matches()
-        
+
+    @Slot()
     def find_next(self):
         """Find next occurence"""
         state = self.find(changed=False, forward=True, rehighlight=False)
         self.editor.setFocus()
         self.search_text.add_current_text()
         return state
-        
+
+    @Slot()
     def find_previous(self):
         """Find previous occurence"""
         state = self.find(changed=False, forward=False, rehighlight=False)
@@ -324,7 +316,8 @@ class FindReplace(QWidget):
             else:
                 self.clear_matches()
             return found
-            
+
+    @Slot()
     def replace_find(self):
         """Replace and find"""
         if (self.editor is not None):
diff --git a/spyderlib/widgets/formlayout.py b/spyderlib/widgets/formlayout.py
index 8236350..33f5e7a 100644
--- a/spyderlib/widgets/formlayout.py
+++ b/spyderlib/widgets/formlayout.py
@@ -64,12 +64,12 @@ from spyderlib.qt.QtGui import (QWidget, QLineEdit, QComboBox, QLabel,
                                 QDateEdit, QDateTimeEdit, QFont, QFontComboBox,
                                 QFontDatabase, QGridLayout, QDoubleValidator,
                                 QTextEdit)
-from spyderlib.qt.QtCore import Qt, SIGNAL, SLOT, QSize, Slot, Property
+from spyderlib.qt.QtCore import Qt, Signal, QSize, Slot, Property
 import datetime
 
 # Local imports
-from spyderlib.baseconfig import _, DEBUG, STDERR
-from spyderlib.py3compat import is_text_string, to_text_string, is_string, u
+from spyderlib.config.base import _, DEBUG, STDERR
+from spyderlib.py3compat import is_text_string, to_text_string, is_string
 
 DEBUG_FORMLAYOUT = DEBUG >= 2
 
@@ -84,7 +84,7 @@ class ColorButton(QPushButton):
         QPushButton.__init__(self, parent)
         self.setFixedSize(20, 20)
         self.setIconSize(QSize(12, 12))
-        self.connect(self, SIGNAL("clicked()"), self.choose_color)
+        self.clicked.connect(self.choose_color)
         self._color = QColor()
     
     def choose_color(self):
@@ -99,7 +99,7 @@ class ColorButton(QPushButton):
     def set_color(self, color):
         if color != self._color:
             self._color = color
-            self.emit(SIGNAL("colorChanged(QColor)"), self._color)
+            self.colorChanged.emit(self._color)
             pixmap = QPixmap(self.iconSize())
             pixmap.fill(color)
             self.setIcon(QIcon(pixmap))
@@ -134,13 +134,11 @@ class ColorLayout(QHBoxLayout):
         QHBoxLayout.__init__(self)
         assert isinstance(color, QColor)
         self.lineedit = QLineEdit(color.name(), parent)
-        self.connect(self.lineedit, SIGNAL("textChanged(QString)"),
-                     self.update_color)
+        self.lineedit.textChanged.connect(self.update_color)
         self.addWidget(self.lineedit)
         self.colorbtn = ColorButton(parent)
         self.colorbtn.color = color
-        self.connect(self.colorbtn, SIGNAL("colorChanged(QColor)"),
-                     self.update_text)
+        self.colorbtn.colorChanged.connect(self.update_text)
         self.addWidget(self.colorbtn)
 
     def update_color(self, text):
@@ -231,6 +229,8 @@ def is_edit_valid(edit):
     return state == QDoubleValidator.Acceptable
 
 class FormWidget(QWidget):
+    update_buttons = Signal()
+
     def __init__(self, data, comment="", parent=None):
         QWidget.__init__(self, parent)
         from copy import deepcopy
@@ -276,7 +276,7 @@ class FormWidget(QWidget):
                 if '\n' in value:
                     for linesep in (os.linesep, '\n'):
                         if linesep in value:
-                            value = value.replace(linesep, u("\u2029"))
+                            value = value.replace(linesep, u"\u2029")
                     field = QTextEdit(value, self)
                 else:
                     field = QLineEdit(value, self)
@@ -308,8 +308,7 @@ class FormWidget(QWidget):
                 field.setValidator(QDoubleValidator(field))
                 dialog = self.get_dialog()
                 dialog.register_float_field(field)
-                self.connect(field, SIGNAL('textChanged(QString)'),
-                             lambda text: dialog.update_buttons())
+                field.textChanged.connect(lambda text: dialog.update_buttons())
             elif isinstance(value, int):
                 field = QSpinBox(self)
                 field.setRange(-1e9, 1e9)
@@ -337,7 +336,7 @@ class FormWidget(QWidget):
             elif is_text_string(value):
                 if isinstance(field, QTextEdit):
                     value = to_text_string(field.toPlainText()
-                                           ).replace(u("\u2029"), os.linesep)
+                                           ).replace(u"\u2029", os.linesep)
                 else:
                     value = to_text_string(field.text())
             elif isinstance(value, (list, tuple)):
@@ -374,6 +373,8 @@ class FormWidget(QWidget):
 
 
 class FormComboWidget(QWidget):
+    update_buttons = Signal()
+    
     def __init__(self, datalist, comment="", parent=None):
         QWidget.__init__(self, parent)
         layout = QVBoxLayout()
@@ -383,8 +384,8 @@ class FormComboWidget(QWidget):
         
         self.stackwidget = QStackedWidget(self)
         layout.addWidget(self.stackwidget)
-        self.connect(self.combobox, SIGNAL("currentIndexChanged(int)"),
-                     self.stackwidget, SLOT("setCurrentIndex(int)"))
+        self.combobox.currentIndexChanged.connect(
+                                              self.stackwidget.setCurrentIndex)
         
         self.widgetlist = []
         for data, title, comment in datalist:
@@ -399,9 +400,11 @@ class FormComboWidget(QWidget):
 
     def get(self):
         return [ widget.get() for widget in self.widgetlist]
-        
+
 
 class FormTabWidget(QWidget):
+    update_buttons = Signal()
+
     def __init__(self, datalist, comment="", parent=None):
         QWidget.__init__(self, parent)
         layout = QVBoxLayout()
@@ -453,13 +456,12 @@ class FormDialog(QDialog):
         # Button box
         self.bbox = bbox = QDialogButtonBox(QDialogButtonBox.Ok
                                             |QDialogButtonBox.Cancel)
-        self.connect(self.formwidget, SIGNAL('update_buttons()'),
-                     self.update_buttons)
+        self.formwidget.update_buttons.connect(self.update_buttons)
         if self.apply_callback is not None:
             apply_btn = bbox.addButton(QDialogButtonBox.Apply)
-            self.connect(apply_btn, SIGNAL("clicked()"), self.apply)
-        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
-        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
+            apply_btn.clicked.connect(self.apply)
+        bbox.accepted.connect(self.accept)
+        bbox.rejected.connect(self.reject)
         layout.addWidget(bbox)
 
         self.setLayout(layout)
@@ -481,11 +483,13 @@ class FormDialog(QDialog):
             btn = self.bbox.button(btn_type)
             if btn is not None:
                 btn.setEnabled(valid)
-        
+    
+    @Slot()
     def accept(self):
         self.data = self.formwidget.get()
         QDialog.accept(self)
-        
+    
+    @Slot()
     def reject(self):
         self.data = None
         QDialog.reject(self)
@@ -530,9 +534,13 @@ def fedit(data, title="", comment="", icon=None, parent=None, apply=None):
     """
     # Create a QApplication instance if no instance currently exists
     # (e.g. if the module is used directly from the interpreter)
-    if QApplication.startingUp():
+    test_travis = os.environ.get('TEST_CI_WIDGETS', None)
+    if test_travis is not None:
+        from spyderlib.utils.qthelpers import qapplication
+        _app = qapplication(test_time=1)
+    elif QApplication.startingUp():
         _app = QApplication([])
-        
+
     dialog = FormDialog(data, title, comment, icon, parent, apply)
     if dialog.exec_():
         return dialog.get()
diff --git a/spyderlib/widgets/helperwidgets.py b/spyderlib/widgets/helperwidgets.py
new file mode 100644
index 0000000..03ee710
--- /dev/null
+++ b/spyderlib/widgets/helperwidgets.py
@@ -0,0 +1,253 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2013-2015 The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+"""
+Helper widgets.
+"""
+
+# Third party imports
+from spyderlib.qt.QtCore import QPoint, QSize, Qt
+from spyderlib.qt.QtGui import (QToolButton, QToolTip,
+                                QStyledItemDelegate, QApplication,
+                                QTextDocument, QStyleOptionViewItem,
+                                QAbstractTextDocumentLayout, QStyle,
+                                QVBoxLayout, QSpacerItem, QPainter,
+                                QMessageBox, QCheckBox, QLineEdit)
+
+# Local imports
+from spyderlib.config.base import _
+from spyderlib.utils import icon_manager as ima
+from spyderlib.utils.qthelpers import get_std_icon
+
+
+class HelperToolButton(QToolButton):
+    """Subclasses QToolButton, to provide a simple tooltip on mousedown.
+    """
+    def __init__(self):
+        QToolButton.__init__(self)
+        self.setIcon(get_std_icon('MessageBoxInformation'))
+        style = """
+            QToolButton {
+              border: 1px solid grey;
+              padding:0px;
+              border-radius: 2px;
+              background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
+                  stop: 0 #f6f7fa, stop: 1 #dadbde);
+            }
+            """
+        self.setStyleSheet(style)
+
+    def setToolTip(self, text):
+        self._tip_text = text
+
+    def toolTip(self):
+        return self._tip_text
+
+    def mousePressEvent(self, event):
+        QToolTip.hideText()
+
+    def mouseReleaseEvent(self, event):
+        QToolTip.showText(self.mapToGlobal(QPoint(0, self.height())),
+                          self._tip_text)
+
+
+class MessageCheckBox(QMessageBox):
+    """
+    A QMessageBox derived widget that includes a QCheckBox aligned to the right
+    under the message and on top of the buttons.
+    """
+    def __init__(self, *args, **kwargs):
+        super(MessageCheckBox, self).__init__(*args, **kwargs)
+
+        self._checkbox = QCheckBox()
+
+        # Set layout to include checkbox
+        size = 9
+        check_layout = QVBoxLayout()
+        check_layout.addItem(QSpacerItem(size, size))
+        check_layout.addWidget(self._checkbox, 0, Qt.AlignRight)
+        check_layout.addItem(QSpacerItem(size, size))
+
+        # Access the Layout of the MessageBox to add the Checkbox
+        layout = self.layout()
+        layout.addLayout(check_layout, 1, 1)
+
+    # --- Public API
+    # Methods to access the checkbox
+    def is_checked(self):
+        return self._checkbox.isChecked()
+
+    def set_checked(self, value):
+        return self._checkbox.setChecked(value)
+
+    def set_check_visible(self, value):
+        self._checkbox.setVisible(value)
+
+    def is_check_visible(self):
+        self._checkbox.isVisible()
+
+    def checkbox_text(self):
+        self._checkbox.text()
+
+    def set_checkbox_text(self, text):
+        self._checkbox.setText(text)
+
+
+class HTMLDelegate(QStyledItemDelegate):
+    """With this delegate, a QListWidgetItem or a QTableItem can render HTML.
+
+    Taken from http://stackoverflow.com/a/5443112/2399799
+    """
+    def __init__(self, parent, margin=0):
+        super(HTMLDelegate, self).__init__(parent)
+        self._margin = margin
+
+    def paint(self, painter, option, index):
+        options = QStyleOptionViewItem(option)
+        self.initStyleOption(options, index)
+
+        style = (QApplication.style() if options.widget is None
+                 else options.widget.style())
+
+        doc = QTextDocument()
+        doc.setDocumentMargin(self._margin)
+        doc.setHtml(options.text)
+
+        options.text = ""
+        style.drawControl(QStyle.CE_ItemViewItem, options, painter)
+
+        ctx = QAbstractTextDocumentLayout.PaintContext()
+
+        textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options)
+        painter.save()
+        if style.objectName() == 'oxygen':
+            painter.translate(textRect.topLeft() + QPoint(5, -9))
+        else:
+            painter.translate(textRect.topLeft())
+            painter.setClipRect(textRect.translated(-textRect.topLeft()))
+        doc.documentLayout().draw(painter, ctx)
+
+        painter.restore()
+
+    def sizeHint(self, option, index):
+        options = QStyleOptionViewItem(option)
+        self.initStyleOption(options, index)
+
+        doc = QTextDocument()
+        doc.setHtml(options.text)
+        doc.setTextWidth(options.rect.width())
+
+        return QSize(doc.idealWidth(), doc.size().height())
+
+
+class IconLineEdit(QLineEdit):
+    """Custom QLineEdit that includes an icon representing the validation."""
+
+    def __init__(self, *args, **kwargs):
+        super(IconLineEdit, self).__init__(*args, **kwargs)
+
+        self._status = True
+        self._status_set = True
+        self._valid_icon = ima.icon('todo')
+        self._invalid_icon = ima.icon('warning')
+        self._set_icon = ima.icon('todo_list')
+        self._application_style = QApplication.style().objectName()
+        self._refresh()
+        self._paint_count = 0
+        self._icon_visible = False
+
+    def _refresh(self):
+        """After an application style change, the paintEvent updates the
+        custom defined stylesheet.
+        """
+        padding = self.height()
+        css_base = """QLineEdit {{
+                                 border: none;
+                                 padding-right: {padding}px;
+                                 }}
+                   """
+        css_oxygen = """QLineEdit {{background: transparent;
+                                   border: none;
+                                   padding-right: {padding}px;
+                                   }}
+                     """
+        if self._application_style == 'oxygen':
+            css_template = css_oxygen
+        else:
+            css_template = css_base
+
+        css = css_template.format(padding=padding)
+        self.setStyleSheet(css)
+        self.update()
+
+    def hide_status_icon(self):
+        """Show the status icon."""
+        self._icon_visible = False
+        self.repaint()
+        self.update()
+
+    def show_status_icon(self):
+        """Hide the status icon."""
+        self._icon_visible = True
+        self.repaint()
+        self.update()
+
+    def update_status(self, value, value_set):
+        """Update the status and set_status to update the icons to display."""
+        self._status = value
+        self._status_set = value_set
+        self.repaint()
+        self.update()
+
+    def paintEvent(self, event):
+        """Qt Override.
+
+        Include a validation icon to the left of the line edit.
+        """
+        super(IconLineEdit, self).paintEvent(event)
+        painter = QPainter(self)
+
+        rect = self.geometry()
+        space = int((rect.height())/6)
+        h = rect.height() - space
+        w = rect.width() - h
+
+        if self._icon_visible:
+            if self._status and self._status_set:
+                pixmap = self._set_icon.pixmap(h, h)
+            elif self._status:
+                pixmap = self._valid_icon.pixmap(h, h)
+            else:
+                pixmap = self._invalid_icon.pixmap(h, h)
+
+            painter.drawPixmap(w, space, pixmap)
+
+        application_style = QApplication.style().objectName()
+        if self._application_style != application_style:
+            self._application_style = application_style
+            self._refresh()
+
+        # Small hack to gurantee correct padding on Spyder start
+        if self._paint_count < 5:
+            self._paint_count += 1
+            self._refresh()
+
+
+def test_msgcheckbox():
+    from spyderlib.utils.qthelpers import qapplication
+    app = qapplication()
+    box = MessageCheckBox()
+    box.setWindowTitle(_("Spyder updates"))
+    box.setText("Testing checkbox")
+    box.set_checkbox_text("Check for updates on startup?")
+    box.setStandardButtons(QMessageBox.Ok)
+    box.setDefaultButton(QMessageBox.Ok)
+    box.setIcon(QMessageBox.Information)
+    box.exec_()
+
+
+if __name__ == '__main__':
+    test_msgcheckbox()
diff --git a/spyderlib/widgets/internalshell.py b/spyderlib/widgets/internalshell.py
index 2b23a17..2f4cc65 100644
--- a/spyderlib/widgets/internalshell.py
+++ b/spyderlib/widgets/internalshell.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -15,7 +15,7 @@
 
 #----Builtins*
 from spyderlib.py3compat import builtins
-from spyderlib.widgets.objecteditor import oedit
+from spyderlib.widgets.variableexplorer.objecteditor import oedit
 builtins.oedit = oedit
 
 import os
@@ -24,21 +24,22 @@ from time import time
 from subprocess import Popen
 
 from spyderlib.qt.QtGui import QMessageBox
-from spyderlib.qt.QtCore import SIGNAL, QObject, QEventLoop
+from spyderlib.qt.QtCore import Signal, Slot, QObject, QEventLoop
 
 # Local import
 from spyderlib import get_versions
-from spyderlib.utils.qthelpers import create_action, get_std_icon
+from spyderlib.utils.qthelpers import create_action
 from spyderlib.interpreter import Interpreter
 from spyderlib.utils.dochelpers import getargtxt, getsource, getdoc, getobjdir
 from spyderlib.utils.misc import get_error_match
 #TODO: remove the CONF object and make it work anyway
 # In fact, this 'CONF' object has nothing to do in package spyderlib.widgets
 # which should not contain anything directly related to Spyder's main app
-from spyderlib.baseconfig import get_conf_path, _, DEBUG
-from spyderlib.config import CONF
+from spyderlib.config.base import get_conf_path, _, DEBUG
+from spyderlib.config.main import CONF
 from spyderlib.widgets.shell import PythonShellWidget
 from spyderlib.py3compat import to_text_string, getcwd, to_binary_string, u
+import spyderlib.utils.icon_manager as ima
 
 
 def create_banner(message):
@@ -53,6 +54,8 @@ def create_banner(message):
 
 class SysOutput(QObject):
     """Handle standard I/O queue"""
+    data_avail = Signal()
+    
     def __init__(self):
         QObject.__init__(self)
         self.queue = []
@@ -62,7 +65,7 @@ class SysOutput(QObject):
         self.lock.acquire()
         self.queue.append(val)
         self.lock.release()
-        self.emit(SIGNAL("void data_avail()"))
+        self.data_avail.emit()
 
     def empty_queue(self):
         self.lock.acquire()
@@ -80,19 +83,25 @@ class WidgetProxyData(object):
 
 class WidgetProxy(QObject):
     """Handle Shell widget refresh signal"""
+    
+    sig_new_prompt = Signal(str)
+    sig_set_readonly = Signal(bool)
+    sig_edit = Signal(str, bool)
+    sig_wait_input = Signal(str)
+    
     def __init__(self, input_condition):
         QObject.__init__(self)
         self.input_data = None
         self.input_condition = input_condition
         
     def new_prompt(self, prompt):
-        self.emit(SIGNAL("new_prompt(QString)"), prompt)
+        self.sig_new_prompt.emit(prompt)
         
     def set_readonly(self, state):
-        self.emit(SIGNAL("set_readonly(bool)"), state)
+        self.sig_set_readonly.emit(state)
         
     def edit(self, filename, external_editor=False):
-        self.emit(SIGNAL("edit(QString,bool)"), filename, external_editor)
+        self.sig_edit.emit(filename, external_editor)
     
     def data_available(self):
         """Return True if input data is available"""
@@ -100,7 +109,7 @@ class WidgetProxy(QObject):
     
     def wait_input(self, prompt=''):
         self.input_data = WidgetProxyData
-        self.emit(SIGNAL("wait_input(QString)"), prompt)
+        self.sig_wait_input.emit(prompt)
     
     def end_input(self, cmd):
         self.input_condition.acquire()
@@ -111,6 +120,12 @@ class WidgetProxy(QObject):
 
 class InternalShell(PythonShellWidget):
     """Shell base widget: link between PythonShellWidget and Interpreter"""
+    
+    status = Signal(str)
+    refresh = Signal()
+    go_to_error = Signal(str)
+    focus_changed = Signal()
+    
     def __init__(self, parent=None, namespace=None, commands=[], message=None,
                  max_line_count=300, font=None, exitfunc=None, profile=False,
                  multithreaded=True, light_background=True):
@@ -134,8 +149,7 @@ class InternalShell(PythonShellWidget):
         
         # KeyboardInterrupt support
         self.interrupted = False # used only for not-multithreaded mode
-        self.connect(self, SIGNAL("keyboard_interrupt()"),
-                     self.keyboard_interrupt)
+        self.sig_keyboard_interrupt.connect(self.keyboard_interrupt)
         
         # Code completion / calltips
         getcfg = lambda option: CONF.get('internal_console', option)
@@ -153,14 +167,12 @@ class InternalShell(PythonShellWidget):
         self.start_interpreter(namespace)
         
         # Clear status bar
-        self.emit(SIGNAL("status(QString)"), '')
+        self.status.emit('')
         
         # Embedded shell -- requires the monitor (which installs the
         # 'open_in_spyder' function in builtins)
         if hasattr(builtins, 'open_in_spyder'):
-            self.connect(self, SIGNAL("go_to_error(QString)"),
-                         self.open_with_external_spyder)
-
+            self.go_to_error.connect(self.open_with_external_spyder)
 
     #------ Interpreter
     def start_interpreter(self, namespace):
@@ -171,18 +183,12 @@ class InternalShell(PythonShellWidget):
             self.interpreter.closing()
         self.interpreter = Interpreter(namespace, self.exitfunc,
                                        SysOutput, WidgetProxy, DEBUG)
-        self.connect(self.interpreter.stdout_write,
-                     SIGNAL("void data_avail()"), self.stdout_avail)
-        self.connect(self.interpreter.stderr_write,
-                     SIGNAL("void data_avail()"), self.stderr_avail)
-        self.connect(self.interpreter.widget_proxy,
-                     SIGNAL("set_readonly(bool)"), self.setReadOnly)
-        self.connect(self.interpreter.widget_proxy,
-                     SIGNAL("new_prompt(QString)"), self.new_prompt)
-        self.connect(self.interpreter.widget_proxy,
-                     SIGNAL("edit(QString,bool)"), self.edit_script)
-        self.connect(self.interpreter.widget_proxy,
-                     SIGNAL("wait_input(QString)"), self.wait_input)
+        self.interpreter.stdout_write.data_avail.connect(self.stdout_avail)
+        self.interpreter.stderr_write.data_avail.connect(self.stderr_avail)
+        self.interpreter.widget_proxy.sig_set_readonly.connect(self.setReadOnly)
+        self.interpreter.widget_proxy.sig_new_prompt.connect(self.new_prompt)
+        self.interpreter.widget_proxy.sig_edit.connect(self.edit_script)
+        self.interpreter.widget_proxy.sig_wait_input.connect(self.wait_input)
         if self.multithreaded:
             self.interpreter.start()
         
@@ -196,7 +202,7 @@ class InternalShell(PythonShellWidget):
                 
         # First prompt
         self.new_prompt(self.interpreter.p1)
-        self.emit(SIGNAL("refresh()"))
+        self.refresh.emit()
 
         return self.interpreter
 
@@ -250,10 +256,11 @@ class InternalShell(PythonShellWidget):
         """Reimplement PythonShellWidget method"""
         PythonShellWidget.setup_context_menu(self)
         self.help_action = create_action(self, _("Help..."),
-                           icon=get_std_icon('DialogHelpButton'),
+                           icon=ima.icon('DialogHelpButton'),
                            triggered=self.help)
         self.menu.addAction(self.help_action)
 
+    @Slot()
     def help(self):
         """Help on Spyder console"""
         QMessageBox.about(self, _("Help"),
@@ -400,7 +407,7 @@ class InternalShell(PythonShellWidget):
         self.interpreter.stdin_write.write(to_binary_string(cmd + '\n'))
         if not self.multithreaded:
             self.interpreter.run_line()
-            self.emit(SIGNAL("refresh()"))
+            self.refresh.emit()
     
     
     #------ Code completion / Calltips
diff --git a/spyderlib/widgets/ipython.py b/spyderlib/widgets/ipython.py
index 066ea24..9b36a0a 100644
--- a/spyderlib/widgets/ipython.py
+++ b/spyderlib/widgets/ipython.py
@@ -22,10 +22,8 @@ import time
 from spyderlib.qt.QtGui import (QTextEdit, QKeySequence, QWidget, QMenu,
                                 QHBoxLayout, QToolButton, QVBoxLayout,
                                 QMessageBox)
-from spyderlib.qt.QtCore import SIGNAL, Qt
-
-from spyderlib import pygments_patch
-pygments_patch.apply()
+from spyderlib.qt.QtCore import Signal, Slot, Qt
+import spyderlib.utils.icon_manager as ima
 
 # IPython imports
 try:
@@ -38,20 +36,20 @@ from IPython.core.oinspect import call_tip
 from IPython.config.loader import Config, load_pyconfig_files
 
 # Local imports
-from spyderlib.baseconfig import (get_conf_path, get_image_path,
-                                  get_module_source_path, _)
-from spyderlib.config import CONF
-from spyderlib.guiconfig import (create_shortcut, get_font, get_shortcut,
-                                 new_shortcut)
+from spyderlib.config.base import (get_conf_path, get_image_path,
+                                   get_module_source_path, _)
+from spyderlib.config.main import CONF
+from spyderlib.config.gui import (create_shortcut, get_font, get_shortcut,
+                                  new_shortcut)
 from spyderlib.utils.dochelpers import getargspecfromtext, getsignaturefromtext
-from spyderlib.utils.qthelpers import (get_std_icon, create_toolbutton,
-                                       add_actions, create_action, get_icon,
-                                       restore_keyevent)
+from spyderlib.utils.qthelpers import (create_toolbutton, add_actions, 
+                                       create_action, restore_keyevent)
 from spyderlib.utils import programs, sourcecode
 from spyderlib.widgets.browser import WebView
 from spyderlib.widgets.calltip import CallTipWidget
 from spyderlib.widgets.mixins import (BaseEditMixin, InspectObjectMixin,
                                       SaveHistoryMixin, TracebackLinksMixin)
+from spyderlib.widgets.arraybuilder import (SHORTCUT_INLINE, SHORTCUT_TABLE)
 from spyderlib.py3compat import PY3
 
 
@@ -78,6 +76,10 @@ class IPythonControlWidget(TracebackLinksMixin, InspectObjectMixin, QTextEdit,
     control widget for IPython widgets
     """
     QT_CLASS = QTextEdit
+    visibility_changed = Signal(bool)
+    go_to_error = Signal(str)
+    focus_changed = Signal()
+    
     def __init__(self, parent=None):
         QTextEdit.__init__(self, parent)
         BaseEditMixin.__init__(self)
@@ -92,7 +94,7 @@ class IPythonControlWidget(TracebackLinksMixin, InspectObjectMixin, QTextEdit,
 
     def showEvent(self, event):
         """Reimplement Qt Method"""
-        self.emit(SIGNAL("visibility_changed(bool)"), True)
+        self.visibility_changed.emit(True)
 
     def _key_question(self, text):
         """ Action for '?' and '(' """
@@ -116,12 +118,12 @@ class IPythonControlWidget(TracebackLinksMixin, InspectObjectMixin, QTextEdit,
 
     def focusInEvent(self, event):
         """Reimplement Qt method to send focus change notification"""
-        self.emit(SIGNAL('focus_changed()'))
+        self.focus_changed.emit()
         return super(IPythonControlWidget, self).focusInEvent(event)
     
     def focusOutEvent(self, event):
         """Reimplement Qt method to send focus change notification"""
-        self.emit(SIGNAL('focus_changed()'))
+        self.focus_changed.emit()
         return super(IPythonControlWidget, self).focusOutEvent(event)
 
 
@@ -131,6 +133,10 @@ class IPythonPageControlWidget(QTextEdit, BaseEditMixin):
     use as the paging widget for IPython widgets
     """
     QT_CLASS = QTextEdit
+    visibility_changed = Signal(bool)
+    show_find_widget = Signal()
+    focus_changed = Signal()
+    
     def __init__(self, parent=None):
         QTextEdit.__init__(self, parent)
         BaseEditMixin.__init__(self)
@@ -138,23 +144,23 @@ class IPythonPageControlWidget(QTextEdit, BaseEditMixin):
     
     def showEvent(self, event):
         """Reimplement Qt Method"""
-        self.emit(SIGNAL("visibility_changed(bool)"), True)
+        self.visibility_changed.emit(True)
     
     def keyPressEvent(self, event):
         """Reimplement Qt Method - Basic keypress event handler"""
         event, text, key, ctrl, shift = restore_keyevent(event)
         
         if key == Qt.Key_Slash and self.isVisible():
-            self.emit(SIGNAL("show_find_widget()"))
+            self.show_find_widget.emit()
 
     def focusInEvent(self, event):
         """Reimplement Qt method to send focus change notification"""
-        self.emit(SIGNAL('focus_changed()'))
+        self.focus_changed.emit()
         return super(IPythonPageControlWidget, self).focusInEvent(event)
     
     def focusOutEvent(self, event):
         """Reimplement Qt method to send focus change notification"""
-        self.emit(SIGNAL('focus_changed()'))
+        self.focus_changed.emit()
         return super(IPythonPageControlWidget, self).focusOutEvent(event)
 
 
@@ -168,6 +174,9 @@ class IPythonShellWidget(RichIPythonWidget):
     This class has custom control and page_control widgets, additional methods
     to provide missing functionality and a couple more keyboard shortcuts.
     """
+    focus_changed = Signal()
+    new_client = Signal()
+    
     def __init__(self, *args, **kw):
         # To override the Qt widget used by RichIPythonWidget
         self.custom_control = IPythonControlWidget
@@ -228,17 +237,14 @@ These commands were executed:
         banner = 'Python %s on %s -- IPython %s' % (py_ver, sys.platform,
                                                     version)
         return banner
-    
+
     def clear_console(self):
         self.execute("%clear")
-        
+
     def write_to_stdin(self, line):
         """Send raw characters to the IPython kernel through stdin"""
-        try:
-            self.kernel_client.stdin_channel.input(line)
-        except AttributeError:
-            self.kernel_client.input(line)
-    
+        self.kernel_client.input(line)
+
     def set_background_color(self):
         lightbg_o = CONF.get('ipython_console', 'light_color')
         if not lightbg_o:
@@ -252,8 +258,11 @@ These commands were executed:
                                         name='Clear shell', parent=self)
 
         # Fixed shortcuts
-        new_shortcut("Ctrl+T", self,
-                     lambda: self.emit(SIGNAL("new_ipyclient()")))
+        new_shortcut("Ctrl+T", self, lambda: self.new_client.emit())
+        new_shortcut(SHORTCUT_INLINE, self,
+                     lambda: self._control.enter_array_inline())
+        new_shortcut(SHORTCUT_TABLE, self,
+                     lambda: self._control.enter_array_table())
 
         return [inspect, clear_console]
 
@@ -362,12 +371,12 @@ These commands were executed:
     #---- Qt methods ----------------------------------------------------------
     def focusInEvent(self, event):
         """Reimplement Qt method to send focus change notification"""
-        self.emit(SIGNAL('focus_changed()'))
+        self.focus_changed.emit()
         return super(IPythonShellWidget, self).focusInEvent(event)
     
     def focusOutEvent(self, event):
         """Reimplement Qt method to send focus change notification"""
-        self.emit(SIGNAL('focus_changed()'))
+        self.focus_changed.emit()
         return super(IPythonShellWidget, self).focusOutEvent(event)
 
 
@@ -379,11 +388,12 @@ class IPythonClient(QWidget, SaveHistoryMixin):
     IPython client or frontend for Spyder
 
     This is a widget composed of a shell widget (i.e. RichIPythonWidget
-    + our additions = IPythonShellWidget) and an WebView info widget to 
+    + our additions = IPythonShellWidget) and a WebView info widget to 
     print kernel error and other messages.
     """
     
     SEPARATOR = '%s##---(%s)---' % (os.linesep*2, time.ctime())
+    append_to_history = Signal(str, str)
     
     def __init__(self, plugin, name, history_filename, connection_file=None, 
                  hostname=None, sshkey=None, password=None, 
@@ -394,8 +404,7 @@ class IPythonClient(QWidget, SaveHistoryMixin):
         
         # stop button and icon
         self.stop_button = None
-        self.stop_icon = get_icon("stop.png")
-        
+        self.stop_icon = ima.icon('stop')        
         self.connection_file = connection_file
         self.kernel_widget_id = kernel_widget_id
         self.hostname = hostname
@@ -464,8 +473,10 @@ class IPythonClient(QWidget, SaveHistoryMixin):
    
     def disable_stop_button(self):
         self.stop_button.setDisabled(True)
-        
+
+    @Slot()
     def stop_button_click_handler(self):
+        """Method to handle what to do when the stop button is pressed"""
         self.stop_button.setDisabled(True)
         # Interrupt computations or stop debugging
         if not self.shellwidget._reading:
@@ -500,6 +511,7 @@ class IPythonClient(QWidget, SaveHistoryMixin):
         self.infowidget.setHtml(page)
     
     def show_restart_animation(self):
+        """Show loading_page while restarting the kernel"""
         self.shellwidget.hide()
         self.infowidget.setHtml(self.loading_page)
         self.infowidget.show()
@@ -522,7 +534,7 @@ class IPythonClient(QWidget, SaveHistoryMixin):
         """Return options menu"""
         restart_action = create_action(self, _("Restart kernel"),
                                        shortcut=QKeySequence("Ctrl+."),
-                                       icon=get_icon('restart.png'),
+                                       icon=ima.icon('restart'),
                                        triggered=self.restart_kernel)
         restart_action.setShortcutContext(Qt.WidgetWithChildrenShortcut)
         
@@ -553,7 +565,7 @@ class IPythonClient(QWidget, SaveHistoryMixin):
             options = self.get_options_menu()
             if options:
                 self.options_button = create_toolbutton(self,
-                        text=_("Options"), icon=get_icon('tooloptions.png'))
+                        text=_('Options'), icon=ima.icon('tooloptions'))
                 self.options_button.setPopupMode(QToolButton.InstantPopup)
                 menu = QMenu(self)
                 add_actions(menu, options)
@@ -569,18 +581,18 @@ class IPythonClient(QWidget, SaveHistoryMixin):
         inspect_action = create_action(self, _("Inspect current object"),
                                     QKeySequence(get_shortcut('console',
                                                     'inspect current object')),
-                                    icon=get_std_icon('MessageBoxInformation'),
+                                    icon=ima.icon('MessageBoxInformation'),
                                     triggered=self.inspect_object)
         clear_line_action = create_action(self, _("Clear line or block"),
                                           QKeySequence("Shift+Escape"),
-                                          icon=get_icon('eraser.png'),
+                                          icon=ima.icon('editdelete'),
                                           triggered=self.clear_line)
         clear_console_action = create_action(self, _("Clear console"),
                                              QKeySequence(get_shortcut('console',
                                                                'clear shell')),
-                                             icon=get_icon('clear.png'),
+                                             icon=ima.icon('editclear'),
                                              triggered=self.clear_console)
-        quit_action = create_action(self, _("&Quit"), icon='exit.png',
+        quit_action = create_action(self, _("&Quit"), icon=ima.icon('exit'),
                                     triggered=self.exit_callback)
         add_actions(menu, (None, inspect_action, clear_line_action,
                            clear_console_action, None, quit_action))
@@ -592,25 +604,30 @@ class IPythonClient(QWidget, SaveHistoryMixin):
         self.shellwidget.font = font
     
     def set_infowidget_font(self):
+        """Set font for infowidget"""
         font = get_font('inspector', 'rich_text')
         self.infowidget.set_font(font)
     
     def interrupt_kernel(self):
         """Interrupt the associanted Spyder kernel if it's running"""
         self.shellwidget.request_interrupt_kernel()
-    
+
+    @Slot()
     def restart_kernel(self):
         """Restart the associanted Spyder kernel"""
         self.shellwidget.request_restart_kernel()
-    
+
+    @Slot()
     def inspect_object(self):
         """Show how to inspect an object with our object inspector"""
         self.shellwidget._control.inspect_current_object()
-    
+
+    @Slot()
     def clear_line(self):
         """Clear a console line"""
         self.shellwidget._keyboard_quit()
-    
+
+    @Slot()
     def clear_console(self):
         """Clear the whole console"""
         self.shellwidget.execute("%clear")
@@ -628,6 +645,10 @@ class IPythonClient(QWidget, SaveHistoryMixin):
         self.history = self.shellwidget._history
     
     def set_backend_for_mayavi(self, command):
+        """
+        Mayavi plots require the Qt backend, so we try to detect if one is
+        generated to change backends
+        """
         calling_mayavi = False
         lines = command.splitlines()
         for l in lines:
@@ -668,7 +689,8 @@ class IPythonClient(QWidget, SaveHistoryMixin):
             self.namespacebrowser.refresh_table()
     
     def shellwidget_config(self):
-        """Generate a Config instance for shell widgets using our config
+        """
+        Generate a Config instance for shell widgets using our config
         system
         
         This lets us create each widget with its own config (as opposed to
@@ -693,9 +715,9 @@ class IPythonClient(QWidget, SaveHistoryMixin):
         spy_cfg.IPythonWidget.kind = 'rich'
         
         # Gui completion widget
-        gui_comp_o = self.get_option('use_gui_completion')
-        completions = {True: 'droplist', False: 'ncurses'}
-        spy_cfg.IPythonWidget.gui_completion = completions[gui_comp_o]
+        completion_type_o = CONF.get('ipython_console', 'completion_type')
+        completions = {0: "droplist", 1: "ncurses", 2: "plain"}
+        spy_cfg.IPythonWidget.gui_completion = completions[completion_type_o]
 
         # Pager
         pager_o = self.get_option('use_pager')
@@ -727,6 +749,7 @@ class IPythonClient(QWidget, SaveHistoryMixin):
     
     #------ Private API -------------------------------------------------------
     def _create_loading_page(self):
+        """Create html page to show while the kernel is created"""
         loading_template = Template(LOADING)
         loading_img = get_image_path('loading_sprites.png')
         if os.name == 'nt':
diff --git a/spyderlib/widgets/mixins.py b/spyderlib/widgets/mixins.py
index abd292f..4fafc1b 100644
--- a/spyderlib/widgets/mixins.py
+++ b/spyderlib/widgets/mixins.py
@@ -19,26 +19,26 @@ from xml.sax.saxutils import escape
 
 from spyderlib.qt.QtGui import (QTextCursor, QTextDocument, QApplication,
                                 QCursor, QToolTip)
-from spyderlib.qt.QtCore import Qt, QPoint, QRegExp, SIGNAL
+from spyderlib.qt.QtCore import Qt, QPoint, QRegExp
 
 # Local imports
-from spyderlib.baseconfig import _
+from spyderlib.config.base import _
 from spyderlib.utils import encoding, sourcecode
 from spyderlib.utils.misc import get_error_match
 from spyderlib.utils.dochelpers import (getobj, getargspecfromtext,
                                         getsignaturefromtext)
 from spyderlib.py3compat import is_text_string, to_text_string, u
-
+from spyderlib.widgets.arraybuilder import NumpyArrayDialog
 
 HISTORY_FILENAMES = []
 
 
 class BaseEditMixin(object):
+    
     def __init__(self):
         self.eol_chars = None
         self.calltip_size = 600
     
-    
     #------Line number area
     def get_linenumberarea_width(self):
         """Return line number area width"""
@@ -495,9 +495,56 @@ class BaseEditMixin(object):
                 return True
         return False
 
+    def is_editor(self):
+        """Needs to be overloaded in the codeeditor where it will be True"""
+        return False
+
+    # --- Numpy matrix/array helper / See 'spyderlib/widgets/arraybuilder.py'
+    def enter_array_inline(self):
+        """ """
+        self._enter_array(True)
+
+    def enter_array_table(self):
+        """ """
+        self._enter_array(False)
+
+    def _enter_array(self, inline):
+        """ """
+        offset = self.get_position('cursor') - self.get_position('sol')
+        rect = self.cursorRect()
+        dlg = NumpyArrayDialog(self, inline, offset)
+
+        # TODO: adapt to font size
+        x = rect.left()
+        x = x + self.get_linenumberarea_width() - 14
+        y = rect.top() + (rect.bottom() - rect.top())/2
+        y = y - dlg.height()/2 - 3
+
+        pos = QPoint(x, y)
+        dlg.move(self.mapToGlobal(pos))
+
+        # called from editor
+        if self.is_editor():
+            python_like_check = self.is_python_like()
+            suffix = '\n'
+        # called from a console
+        else:
+            python_like_check = True
+            suffix = ''
+
+        if python_like_check and dlg.exec_():
+            text = dlg.text() + suffix
+            if text != '':
+                cursor = self.textCursor()
+                cursor.beginEditBlock()
+                cursor.insertText(text)
+                cursor.endEditBlock()
+
 
 class TracebackLinksMixin(object):
+    """ """
     QT_CLASS = None
+    go_to_error = None
     
     def __init__(self):
         self.__cursor_changed = False
@@ -509,7 +556,8 @@ class TracebackLinksMixin(object):
         self.QT_CLASS.mouseReleaseEvent(self, event)            
         text = self.get_line_at(event.pos())
         if get_error_match(text) and not self.has_selected_text():
-            self.emit(SIGNAL("go_to_error(QString)"), text)
+            if self.go_to_error is not None:
+                self.go_to_error.emit(text)
 
     def mouseMoveEvent(self, event):
         """Show Pointing Hand Cursor on error messages"""
@@ -619,6 +667,7 @@ class SaveHistoryMixin(object):
     
     INITHISTORY = None
     SEPARATOR = None
+    append_to_history = None
     
     def __init__(self):
         pass
@@ -643,5 +692,5 @@ class SaveHistoryMixin(object):
             text = self.SEPARATOR + text
         
         encoding.write(text, self.history_filename, mode='ab')
-        self.emit(SIGNAL('append_to_history(QString,QString)'),
-                  self.history_filename, text)
+        if self.append_to_history is not None:
+            self.append_to_history.emit(self.history_filename, text)
diff --git a/spyderlib/widgets/onecolumntree.py b/spyderlib/widgets/onecolumntree.py
index c8a6f6c..813d8f5 100644
--- a/spyderlib/widgets/onecolumntree.py
+++ b/spyderlib/widgets/onecolumntree.py
@@ -1,26 +1,16 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
-"""
-spyderlib.widgets
-=================
-
-Widgets defined in this module may be used in any other Qt-based application
-
-They are also used in Spyder through the Plugin interface
-(see spyderlib.plugins)
-"""
-
+from spyderlib.qt.QtCore import Slot
 from spyderlib.qt.QtGui import QTreeWidget, QMenu
-from spyderlib.qt.QtCore import SIGNAL
+import spyderlib.utils.icon_manager as ima
 
 # Local imports
-from spyderlib.baseconfig import _
-from spyderlib.utils.qthelpers import (get_icon, create_action, add_actions,
-                                       get_item_user_text)
+from spyderlib.config.base import _
+from spyderlib.utils.qthelpers import create_action, add_actions, get_item_user_text
 
 
 class OneColumnTree(QTreeWidget):
@@ -29,10 +19,8 @@ class OneColumnTree(QTreeWidget):
         QTreeWidget.__init__(self, parent)
         self.setItemsExpandable(True)
         self.setColumnCount(1)
-        self.connect(self, SIGNAL('itemActivated(QTreeWidgetItem*,int)'),
-                     self.activated)
-        self.connect(self, SIGNAL('itemClicked(QTreeWidgetItem*,int)'),
-                     self.clicked)
+        self.itemActivated.connect(self.activated)
+        self.itemClicked.connect(self.clicked)
         # Setup context menu
         self.menu = QMenu(self)
         self.collapse_all_action = None
@@ -43,8 +31,7 @@ class OneColumnTree(QTreeWidget):
         
         self.__expanded_state = None
 
-        self.connect(self, SIGNAL('itemSelectionChanged()'),
-                     self.item_selection_changed)
+        self.itemSelectionChanged.connect(self.item_selection_changed)
         self.item_selection_changed()
                      
     def activated(self, item):
@@ -61,24 +48,24 @@ class OneColumnTree(QTreeWidget):
         """Setup context menu common actions"""
         self.collapse_all_action = create_action(self,
                                      text=_('Collapse all'),
-                                     icon=get_icon('collapse.png'),
+                                     icon=ima.icon('collapse'),
                                      triggered=self.collapseAll)
         self.expand_all_action = create_action(self,
                                      text=_('Expand all'),
-                                     icon=get_icon('expand.png'),
+                                     icon=ima.icon('expand'),
                                      triggered=self.expandAll)
         self.restore_action = create_action(self,
                                      text=_('Restore'),
                                      tip=_('Restore original tree layout'),
-                                     icon=get_icon('restore.png'),
+                                     icon=ima.icon('restore'),
                                      triggered=self.restore)
         self.collapse_selection_action = create_action(self,
                                      text=_('Collapse selection'),
-                                     icon=get_icon('collapse_selection.png'),
+                                     icon=ima.icon('collapse_selection'),
                                      triggered=self.collapse_selection)
         self.expand_selection_action = create_action(self,
                                      text=_('Expand selection'),
-                                     icon=get_icon('expand_selection.png'),
+                                     icon=ima.icon('expand_selection'),
                                      triggered=self.expand_selection)
         return [self.collapse_all_action, self.expand_all_action,
                 self.restore_action, None,
@@ -98,6 +85,7 @@ class OneColumnTree(QTreeWidget):
         # (reimplement this method)
         return []
 
+    @Slot()
     def restore(self):
         self.collapseAll()
         for item in self.get_top_level_items():
@@ -114,7 +102,8 @@ class OneColumnTree(QTreeWidget):
             for index in range(item.childCount()):
                 child = item.child(index)
                 self.__expand_item(child)
-        
+    
+    @Slot()
     def expand_selection(self):
         items = self.selectedItems()
         if not items:
@@ -130,6 +119,7 @@ class OneColumnTree(QTreeWidget):
             child = item.child(index)
             self.__collapse_item(child)
 
+    @Slot()
     def collapse_selection(self):
         items = self.selectedItems()
         if not items:
diff --git a/spyderlib/widgets/pathmanager.py b/spyderlib/widgets/pathmanager.py
index e96d853..ca3b090 100644
--- a/spyderlib/widgets/pathmanager.py
+++ b/spyderlib/widgets/pathmanager.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -11,20 +11,23 @@ from __future__ import print_function
 from spyderlib.qt.QtGui import (QDialog, QListWidget, QDialogButtonBox,
                                 QVBoxLayout, QHBoxLayout, QMessageBox,
                                 QListWidgetItem)
-from spyderlib.qt.QtCore import Qt, SIGNAL, SLOT
+from spyderlib.qt.QtCore import Qt, Signal, Slot
 from spyderlib.qt.compat import getexistingdirectory
+import spyderlib.utils.icon_manager as ima
 
 import os
 import sys
 import os.path as osp
 
 # Local imports
-from spyderlib.utils.qthelpers import get_icon, get_std_icon, create_toolbutton
-from spyderlib.baseconfig import _
+from spyderlib.utils.qthelpers import create_toolbutton
+from spyderlib.config.base import _
 from spyderlib.py3compat import getcwd
 
 
 class PathManager(QDialog):
+    redirect_stdio = Signal(bool)
+    
     def __init__(self, parent=None, pathlist=None, ro_pathlist=None, sync=True):
         QDialog.__init__(self, parent)
         
@@ -43,7 +46,7 @@ class PathManager(QDialog):
         self.last_path = getcwd()
         
         self.setWindowTitle(_("PYTHONPATH manager"))
-        self.setWindowIcon(get_icon('pythonpath.png'))
+        self.setWindowIcon(ima.icon('pythonpath'))
         self.resize(500, 300)
         
         self.selection_widgets = []
@@ -56,8 +59,7 @@ class PathManager(QDialog):
         self.toolbar_widgets1 = self.setup_top_toolbar(top_layout)
 
         self.listwidget = QListWidget(self)
-        self.connect(self.listwidget, SIGNAL("currentRowChanged(int)"),
-                     self.refresh)
+        self.listwidget.currentRowChanged.connect(self.refresh)
         layout.addWidget(self.listwidget)
 
         bottom_layout = QHBoxLayout()
@@ -67,7 +69,7 @@ class PathManager(QDialog):
         
         # Buttons configuration
         bbox = QDialogButtonBox(QDialogButtonBox.Close)
-        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
+        bbox.rejected.connect(self.reject)
         bottom_layout.addWidget(bbox)
         
         self.update_list()
@@ -82,25 +84,25 @@ class PathManager(QDialog):
         toolbar = []
         movetop_button = create_toolbutton(self,
                                     text=_("Move to top"),
-                                    icon=get_icon('2uparrow.png'),
+                                    icon=ima.icon('2uparrow'),
                                     triggered=lambda: self.move_to(absolute=0),
                                     text_beside_icon=True)
         toolbar.append(movetop_button)
         moveup_button = create_toolbutton(self,
                                     text=_("Move up"),
-                                    icon=get_icon('1uparrow.png'),
+                                    icon=ima.icon('1uparrow'),
                                     triggered=lambda: self.move_to(relative=-1),
                                     text_beside_icon=True)
         toolbar.append(moveup_button)
         movedown_button = create_toolbutton(self,
                                     text=_("Move down"),
-                                    icon=get_icon('1downarrow.png'),
+                                    icon=ima.icon('1downarrow'),
                                     triggered=lambda: self.move_to(relative=1),
                                     text_beside_icon=True)
         toolbar.append(movedown_button)
         movebottom_button = create_toolbutton(self,
                                     text=_("Move to bottom"),
-                                    icon=get_icon('2downarrow.png'),
+                                    icon=ima.icon('2downarrow'),
                                     triggered=lambda: self.move_to(absolute=1),
                                     text_beside_icon=True)
         toolbar.append(movebottom_button)
@@ -110,13 +112,13 @@ class PathManager(QDialog):
     
     def setup_bottom_toolbar(self, layout, sync=True):
         toolbar = []
-        add_button = create_toolbutton(self, text=_("Add path"),
-                                       icon=get_icon('edit_add.png'),
+        add_button = create_toolbutton(self, text=_('Add path'),
+                                       icon=ima.icon('edit_add'),
                                        triggered=self.add_path,
                                        text_beside_icon=True)
         toolbar.append(add_button)
-        remove_button = create_toolbutton(self, text=_("Remove path"),
-                                          icon=get_icon('edit_remove.png'),
+        remove_button = create_toolbutton(self, text=_('Remove path'),
+                                          icon=ima.icon('edit_remove'),
                                           triggered=self.remove_path,
                                           text_beside_icon=True)
         toolbar.append(remove_button)
@@ -126,13 +128,14 @@ class PathManager(QDialog):
         if os.name == 'nt' and sync:
             self.sync_button = create_toolbutton(self,
                   text=_("Synchronize..."),
-                  icon=get_icon('synchronize.png'), triggered=self.synchronize,
+                  icon=ima.icon('fileimport'), triggered=self.synchronize,
                   tip=_("Synchronize Spyder's path list with PYTHONPATH "
                               "environment variable"),
                   text_beside_icon=True)
             layout.addWidget(self.sync_button)
         return toolbar
-    
+
+    @Slot()
     def synchronize(self):
         """
         Synchronize Spyder's path list with PYTHONPATH environment variable
@@ -176,7 +179,7 @@ class PathManager(QDialog):
         self.listwidget.clear()
         for name in self.pathlist+self.ro_pathlist:
             item = QListWidgetItem(name)
-            item.setIcon(get_std_icon('DirClosedIcon'))
+            item.setIcon(ima.icon('DirClosedIcon'))
             if name in self.ro_pathlist:
                 item.setFlags(Qt.NoItemFlags)
             self.listwidget.addItem(item)
@@ -204,7 +207,8 @@ class PathManager(QDialog):
         self.pathlist.insert(new_index, path)
         self.update_list()
         self.listwidget.setCurrentRow(new_index)
-        
+
+    @Slot()
     def remove_path(self):
         answer = QMessageBox.warning(self, _("Remove path"),
             _("Do you really want to remove selected path?"),
@@ -212,12 +216,13 @@ class PathManager(QDialog):
         if answer == QMessageBox.Yes:
             self.pathlist.pop(self.listwidget.currentRow())
             self.update_list()
-    
+
+    @Slot()
     def add_path(self):
-        self.emit(SIGNAL('redirect_stdio(bool)'), False)
+        self.redirect_stdio.emit(False)
         directory = getexistingdirectory(self, _("Select directory"),
                                          self.last_path)
-        self.emit(SIGNAL('redirect_stdio(bool)'), True)
+        self.redirect_stdio.emit(True)
         if directory:
             directory = osp.abspath(directory)
             self.last_path = directory
@@ -239,9 +244,11 @@ def test():
     """Run path manager test"""
     from spyderlib.utils.qthelpers import qapplication
     _app = qapplication()  # analysis:ignore
-    test = PathManager(None, sys.path[:-10], sys.path[-10:])
+    test = PathManager(None, pathlist=sys.path[:-10],
+                       ro_pathlist=sys.path[-10:])
     test.exec_()
     print(test.get_path_list())
 
+
 if __name__ == "__main__":
     test()
diff --git a/spyderlib/widgets/projectexplorer.py b/spyderlib/widgets/projectexplorer.py
index 6bc7efa..4f2a4ac 100644
--- a/spyderlib/widgets/projectexplorer.py
+++ b/spyderlib/widgets/projectexplorer.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2010-2011 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -10,23 +10,25 @@
 
 from __future__ import print_function
 
-from spyderlib.qt.QtGui import (QVBoxLayout, QLabel, QHBoxLayout, QWidget,
-                                QFileIconProvider, QMessageBox, QInputDialog,
-                                QLineEdit, QPushButton, QHeaderView,
-                                QAbstractItemView)
-from spyderlib.qt.QtCore import Qt, SIGNAL, QFileInfo, Slot, Signal
-from spyderlib.qt.compat import getexistingdirectory
-
 import os
 import re
 import shutil
 import os.path as osp
 import xml.etree.ElementTree as ElementTree
 
+from spyderlib.qt import PYQT5
+from spyderlib.qt.QtGui import (QVBoxLayout, QLabel, QHBoxLayout, QWidget,
+                                QFileIconProvider, QMessageBox, QInputDialog,
+                                QLineEdit, QPushButton, QHeaderView,
+                                QAbstractItemView)
+from spyderlib.qt.QtCore import Qt, QFileInfo, Slot, Signal
+from spyderlib.qt.compat import getexistingdirectory
+import spyderlib.utils.icon_manager as ima
+
 # Local imports
 from spyderlib.utils import misc
-from spyderlib.utils.qthelpers import get_icon, get_std_icon, create_action
-from spyderlib.baseconfig import _, STDERR, get_image_path
+from spyderlib.utils.qthelpers import get_icon, create_action
+from spyderlib.config.base import _, STDERR, get_image_path
 from spyderlib.widgets.explorer import FilteredDirView, listdir, fixpath
 from spyderlib.widgets.formlayout import fedit
 from spyderlib.widgets.pathmanager import PathManager
@@ -50,17 +52,17 @@ def is_drive_path(path):
 def get_dir_icon(dirname, project):
     """Return appropriate directory icon"""
     if is_drive_path(dirname):
-        return get_std_icon('DriveHDIcon')
+        return ima.icon('DriveHDIcon')
     prefix = 'pp_' if dirname in project.get_pythonpath() else ''
     if dirname == project.root_path:
         if project.is_opened():
-            return get_icon(prefix+'project.png')
+            return get_icon(prefix + 'project.png')
         else:
             return get_icon('project_closed.png')
     elif osp.isfile(osp.join(dirname, '__init__.py')):
-        return get_icon(prefix+'package.png')
+        return get_icon(prefix + 'package.png')
     else:
-        return get_icon(prefix+'folder.png')
+        return get_icon(prefix + 'folder.png')
 
 
 class Project(object):
@@ -510,13 +512,15 @@ class ExplorerTreeWidget(FilteredDirView):
     
     workspace: this is the explorer tree widget root path
     (this attribute name is specific to project explorer)"""
+
+    select_workspace = Signal()
+    
     def __init__(self, parent, show_hscrollbar=True):
         FilteredDirView.__init__(self, parent)
         
         self.workspace = Workspace()
         
-        self.connect(self.fsmodel, SIGNAL('modelReset()'),
-                     self.reset_icon_provider)
+        self.fsmodel.modelReset.connect(self.reset_icon_provider)
         self.reset_icon_provider()
 
         self.last_folder = None
@@ -552,11 +556,11 @@ class ExplorerTreeWidget(FilteredDirView):
         """Return actions for submenu 'Import...'"""
         import_folder_act = create_action(self,
                                 text=_('Existing directory'),
-                                icon=get_std_icon('DirOpenIcon'),
+                                icon=ima.icon('DirOpenIcon'),
                                 triggered=self.import_existing_directory)
         import_spyder_act = create_action(self,
                                 text=_('Existing Spyder project'),
-                                icon=get_icon('spyder.svg'),
+                                icon=ima.icon('spyder'),
                                 triggered=self.import_existing_project)
         import_pydev_act = create_action(self,
                                 text=_('Existing Pydev project'),
@@ -656,13 +660,17 @@ class ExplorerTreeWidget(FilteredDirView):
         return actions + [hscrollbar_action]
 
     #------Public API----------------------------------------------------------
+    @Slot(bool)
     def toggle_hscrollbar(self, checked):
         """Toggle horizontal scrollbar"""
         self.parent_widget.sig_option_changed.emit('show_hscrollbar', checked)
         self.show_hscrollbar = checked
         self.header().setStretchLastSection(not checked)
         self.header().setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
-        self.header().setResizeMode(QHeaderView.ResizeToContents)
+        if PYQT5:
+            self.header().setSectionResizeMode(QHeaderView.ResizeToContents)
+        else:
+            self.header().setResizeMode(QHeaderView.ResizeToContents)
         
     def set_folder_names(self, folder_names):
         """Set folder names"""
@@ -707,7 +715,7 @@ class ExplorerTreeWidget(FilteredDirView):
         # (see spyderlib/widgets/projectexplorer.py).
         self.set_show_all(self.show_all)
 
-        self.parent_widget.emit(SIGNAL("pythonpath_changed()"))
+        self.parent_widget.pythonpath_changed.emit()
 #        print "folders:", self.workspace.get_folder_names()
 #        print "is_valid:", self.workspace.is_valid()
 #        print "is_empty:", self.workspace.is_empty()
@@ -767,7 +775,7 @@ class ExplorerTreeWidget(FilteredDirView):
         
         project = self.workspace.add_project(folder)
         self.set_folder_names(self.workspace.get_folder_names())
-        self.parent_widget.emit(SIGNAL("pythonpath_changed()"))
+        self.parent_widget.pythonpath_changed.emit()
         
         self.check_for_io_errors()
         
@@ -776,7 +784,7 @@ class ExplorerTreeWidget(FilteredDirView):
     def open_projects(self, projects, open_related=True):
         """Open projects"""
         self.workspace.open_projects(projects, open_related)
-        self.parent_widget.emit(SIGNAL("pythonpath_changed()"))
+        self.parent_widget.pythonpath_changed.emit()
         self.reset_icon_provider()
         for project in projects:
             self.update(self.get_index(project.root_path))
@@ -784,8 +792,8 @@ class ExplorerTreeWidget(FilteredDirView):
     def close_projects(self, projects):
         """Close projects"""
         self.workspace.close_projects(projects)
-        self.parent_widget.emit(SIGNAL("pythonpath_changed()"))
-        self.parent_widget.emit(SIGNAL("projects_were_closed()"))
+        self.parent_widget.pythonpath_changed.emit()
+        self.parent_widget.sig_projects_were_closed.emit()
         self.reset_icon_provider()
         for project in projects:
             index = self.get_index(project.root_path)
@@ -796,7 +804,7 @@ class ExplorerTreeWidget(FilteredDirView):
         """Remove projects"""
         self.workspace.remove_projects(projects)
         self.set_folder_names(self.workspace.get_folder_names())
-        self.parent_widget.emit(SIGNAL("pythonpath_changed()"))
+        self.parent_widget.pythonpath_changed.emit()
         
     def close_unrelated_projects(self, projects):
         """Close unrelated projects"""
@@ -861,7 +869,8 @@ class ExplorerTreeWidget(FilteredDirView):
                 return name
             else:
                 return
-    
+
+    @Slot()
     def new_project(self):
         """Return True if project was created"""
         title = _('New project')
@@ -877,7 +886,7 @@ class ExplorerTreeWidget(FilteredDirView):
                                             "Do you want to do this now?"),
                                           QMessageBox.Yes|QMessageBox.Cancel)
             if answer == QMessageBox.Yes:
-                self.emit(SIGNAL('select_workspace()'))
+                self.select_workspace.emit()
         
     def _select_existing_directory(self):
         """Select existing source code directory,
@@ -886,10 +895,10 @@ class ExplorerTreeWidget(FilteredDirView):
         if self.last_folder is None:
             self.last_folder = self.workspace.root_path
         while True:
-            self.parent_widget.emit(SIGNAL('redirect_stdio(bool)'), False)
+            self.parent_widget.redirect_stdio.emit(False)
             folder = getexistingdirectory(self, _("Select directory"),
                                           self.last_folder)
-            self.parent_widget.emit(SIGNAL('redirect_stdio(bool)'), True)
+            self.parent_widget.redirect_stdio.emit(True)
             if folder:
                 folder = osp.abspath(folder)
                 self.last_folder = folder
@@ -898,7 +907,8 @@ class ExplorerTreeWidget(FilteredDirView):
                 return folder
             else:
                 return
-    
+
+    @Slot()
     def import_existing_directory(self):
         """Create project from existing directory
         Eventually copy the whole directory to current workspace"""
@@ -939,7 +949,8 @@ class ExplorerTreeWidget(FilteredDirView):
                                        ) % (osp.basename(folder), typename))
                     continue
             return folder
-    
+
+    @Slot()
     def import_existing_project(self):
         """Import existing project"""
         folders = self.__select_existing_project("Spyder", Project.CONFIG_NAME)
@@ -949,7 +960,8 @@ class ExplorerTreeWidget(FilteredDirView):
             folders = [folders]
         for folder in folders:
             self.add_project(folder, silent=True)
-    
+
+    @Slot()
     def import_existing_pydev_project(self):
         """Import existing Pydev project"""
         folders = self.__select_existing_project("Pydev", ".pydevproject")
@@ -973,7 +985,7 @@ class ExplorerTreeWidget(FilteredDirView):
                     project.name = name
                     project.set_related_projects(related_projects)
                     project.set_pythonpath(path)
-                    self.parent_widget.emit(SIGNAL("pythonpath_changed()"))
+                    self.parent_widget.pythonpath_changed.emit()
 
     def rename_file(self, fname):
         """Rename file"""
@@ -1018,7 +1030,7 @@ class ExplorerTreeWidget(FilteredDirView):
         for path in fnames:
             project = self.get_source_project(path)
             if project.add_to_pythonpath(path):
-                self.parent_widget.emit(SIGNAL("pythonpath_changed()"))
+                self.parent_widget.pythonpath_changed.emit()
                 indexes.append(self.get_index(path))
         if indexes:
             self.reset_icon_provider()
@@ -1028,7 +1040,7 @@ class ExplorerTreeWidget(FilteredDirView):
     def remove_path_from_project_pythonpath(self, project, path):
         """Remove path from project's PYTHONPATH"""
         ok = project.remove_from_pythonpath(path)
-        self.parent_widget.emit(SIGNAL("pythonpath_changed()"))
+        self.parent_widget.pythonpath_changed.emit()
         return ok
     
     def remove_from_path(self, fnames):
@@ -1050,7 +1062,7 @@ class ExplorerTreeWidget(FilteredDirView):
             dlg = PathManager(self, pathlist, sync=False)
             dlg.exec_()
             project.set_pythonpath(dlg.get_path_list())
-            self.parent_widget.emit(SIGNAL("pythonpath_changed()"))
+            self.parent_widget.pythonpath_changed.emit()
     
     def edit_related_projects(self, projects):
         """Edit related projects"""
@@ -1088,7 +1100,8 @@ class ExplorerTreeWidget(FilteredDirView):
             lines += l
         QMessageBox.information(self, _("Project Explorer"),
                                 _("Statistics on source files only:<br>"
-                                  "(Python, C/C++, Fortran)<br><br>"
+                                  "(Python, Cython, IPython, Enaml,"
+                                  "C/C++, Fortran)<br><br>"
                                   "<b>%s</b> files.<br>"
                                   "<b>%s</b> lines of code."
                                   ) % (str(files), str(lines)))
@@ -1164,7 +1177,7 @@ class ExplorerTreeWidget(FilteredDirView):
                         misc.move_file(src, dst)
                     else:
                         shutil.move(src, dst)
-                    self.parent_widget.emit(SIGNAL("removed(QString)"), src)
+                    self.parent_widget.removed.emit(src)
             except EnvironmentError as error:
                 if action == Qt.CopyAction:
                     action_str = _('copy')
@@ -1191,6 +1204,8 @@ class WorkspaceSelector(QWidget):
             "<b>.spyderproject</b>) with project settings (PYTHONPATH, linked "
             "projects, ...).<br>"
             )
+    
+    selected_workspace = Signal(str)
 
     def __init__(self, parent):
         super(WorkspaceSelector, self).__init__(parent)
@@ -1211,10 +1226,9 @@ class WorkspaceSelector(QWidget):
                                   +'<br><br>'+self.TIP)
         self.line_edit.setReadOnly(True)
         self.line_edit.setDisabled(True)
-        self.browse_btn = QPushButton(get_std_icon('DirOpenIcon'), "", self)
+        self.browse_btn = QPushButton(ima.icon('DirOpenIcon'), '', self)
         self.browse_btn.setToolTip(self.TITLE)
-        self.connect(self.browse_btn, SIGNAL("clicked()"),
-                     self.select_directory)
+        self.browse_btn.clicked.connect(self.select_directory)
         layout = QHBoxLayout()
         layout.addWidget(self.line_edit)
         layout.addWidget(self.browse_btn)
@@ -1230,9 +1244,9 @@ class WorkspaceSelector(QWidget):
         if not osp.isdir(basedir):
             basedir = getcwd()
         while True:
-            self.parent().emit(SIGNAL('redirect_stdio(bool)'), False)
+            self.parent().redirect_stdio.emit(False)
             directory = getexistingdirectory(self, self.TITLE, basedir)
-            self.parent().emit(SIGNAL('redirect_stdio(bool)'), True)
+            self.parent().redirect_stdio.emit(True)
             if not directory:
                 break
             path = osp.join(directory, Workspace.CONFIG_NAME)
@@ -1246,24 +1260,16 @@ class WorkspaceSelector(QWidget):
                     continue
             directory = osp.abspath(osp.normpath(directory))
             self.set_workspace(directory)
-            self.emit(SIGNAL('selected_workspace(QString)'), directory)
+            self.selected_workspace.emit(directory)
             break
 
 
 class ProjectExplorerWidget(QWidget):
-    """
-    Project Explorer
-    
-    Signals:
-        sig_open_file
-        SIGNAL("create_module(QString)")
-        SIGNAL("pythonpath_changed()")
-        SIGNAL("renamed(QString,QString)")
-        SIGNAL("removed(QString)")
-    """
+    """Project Explorer"""
     sig_option_changed = Signal(str, object)
     sig_open_file = Signal(str)
-    
+    pythonpath_changed = Signal()
+
     def __init__(self, parent, name_filters=['*.py', '*.pyw'],
                  show_all=False, show_hscrollbar=True):
         QWidget.__init__(self, parent)
@@ -1275,14 +1281,12 @@ class ProjectExplorerWidget(QWidget):
         """Setup project explorer widget layout"""
         self.selector = WorkspaceSelector(self)
         self.selector.setup_widget()
-        self.connect(self.selector, SIGNAL('selected_workspace(QString)'),
-                     self.set_workspace)
+        self.selector.selected_workspace.connect(self.set_workspace)
 
         self.treewidget = ExplorerTreeWidget(self,
                                              show_hscrollbar=show_hscrollbar)
         self.treewidget.setup(name_filters=name_filters, show_all=show_all)
-        self.connect(self.treewidget, SIGNAL('select_workspace()'),
-                     self.selector.select_directory)
+        self.treewidget.select_workspace.connect(self.selector.select_directory)
         
         layout = QVBoxLayout()
         layout.setContentsMargins(0, 0, 0, 0)
@@ -1323,14 +1327,17 @@ class ProjectExplorerWidget(QWidget):
         return self.treewidget.get_source_project(fname)
 
 
+#==============================================================================
+# Tests
+#==============================================================================
 class Test(QWidget):
     def __init__(self):
         QWidget.__init__(self)
         vlayout = QVBoxLayout()
         self.setLayout(vlayout)
-        
+
         self.explorer = ProjectExplorerWidget(None, show_all=True)
-        self.explorer.set_workspace(r'D:/Python')
+        self.explorer.set_workspace(osp.dirname(osp.abspath(__file__)))
 #        p1 = self.explorer.add_project(r"D:/Python/spyder")
 #        p1.set_pythonpath([r"D:\Python\spyder\spyderlib"])
 #        p1.save()
@@ -1359,10 +1366,14 @@ class Test(QWidget):
            lambda x, y: self.label3.setText('option_changed: %r, %r' % (x, y)))
 
 
-if __name__ == "__main__":
+def test():
     from spyderlib.utils.qthelpers import qapplication
     app = qapplication()
     test = Test()
     test.resize(640, 480)
     test.show()
     app.exec_()
+
+
+if __name__ == "__main__":
+    test()
diff --git a/spyderlib/widgets/pydocgui.py b/spyderlib/widgets/pydocgui.py
index 1388e1e..4c94595 100644
--- a/spyderlib/widgets/pydocgui.py
+++ b/spyderlib/widgets/pydocgui.py
@@ -1,19 +1,19 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
 """pydoc widget"""
 
 from spyderlib.qt.QtGui import QApplication, QCursor
-from spyderlib.qt.QtCore import QThread, QUrl, Qt, SIGNAL
+from spyderlib.qt.QtCore import QThread, QUrl, Qt, Signal
 
 import sys
 import os.path as osp
 
 # Local imports
-from spyderlib.baseconfig import _
+from spyderlib.config.base import _
 from spyderlib.widgets.browser import WebBrowser
 from spyderlib.utils.misc import select_port
 from spyderlib.py3compat import to_text_string, PY3
@@ -21,6 +21,8 @@ from spyderlib.py3compat import to_text_string, PY3
 
 class PydocServer(QThread):
     """Pydoc server"""
+    server_started = Signal()
+    
     def __init__(self, port=7464):
         QThread.__init__(self)
         self.port = port
@@ -38,7 +40,7 @@ class PydocServer(QThread):
 
     def callback(self, server):
         self.server = server
-        self.emit(SIGNAL('server_started()'))
+        self.server_started.emit()
         
     def completer(self):
         self.complete = True
@@ -93,12 +95,10 @@ class PydocBrowser(WebBrowser):
             self.port = select_port(default_port=self.DEFAULT_PORT)
             self.set_home_url('http://localhost:%d/' % self.port)
         elif self.server.isRunning():
-            self.disconnect(self.server, SIGNAL('server_started()'),
-                            self.initialize_continued)
+            self.server.server_started.disconnect(self.initialize_continued)
             self.server.quit()
         self.server = PydocServer(port=self.port)
-        self.connect(self.server, SIGNAL('server_started()'),
-                     self.initialize_continued)
+        self.server.server_started.connect(self.initialize_continued)
         self.server.start()
 
     #------ WebBrowser API -----------------------------------------------------
@@ -122,14 +122,15 @@ class PydocBrowser(WebBrowser):
         return osp.splitext(to_text_string(url.path()))[0][1:]
 
 
-def main():
+def test():
     """Run web browser"""
     from spyderlib.utils.qthelpers import qapplication
-    app = qapplication()
+    app = qapplication(test_time=8)
     widget = PydocBrowser(None)
     widget.show()
     widget.initialize()
     sys.exit(app.exec_())
 
+
 if __name__ == '__main__':
-    main()
+    test()
diff --git a/spyderlib/widgets/shell.py b/spyderlib/widgets/shell.py
index 4d2588e..8a4cb69 100644
--- a/spyderlib/widgets/shell.py
+++ b/spyderlib/widgets/shell.py
@@ -21,20 +21,23 @@ import time
 
 from spyderlib.qt.QtGui import (QMenu, QApplication, QToolTip, QKeySequence,
                                 QMessageBox, QTextCursor, QTextCharFormat)
-from spyderlib.qt.QtCore import (Qt, QCoreApplication, QTimer, SIGNAL,
-                                 Property)
+from spyderlib.qt.QtCore import (Qt, QCoreApplication, QTimer, Signal,
+                                 Property, Slot)
 from spyderlib.qt.compat import getsavefilename
+import spyderlib.utils.icon_manager as ima
 
 # Local import
-from spyderlib.baseconfig import get_conf_path, _, STDERR, DEBUG
-from spyderlib.config import CONF
-from spyderlib.guiconfig import get_font, create_shortcut, get_shortcut
+from spyderlib.config.base import get_conf_path, _, STDERR, DEBUG
+from spyderlib.config.main import CONF
+from spyderlib.config.gui import (get_font, create_shortcut, get_shortcut,
+                                  new_shortcut)
 from spyderlib.utils import encoding
 from spyderlib.utils.qthelpers import (keybinding, create_action, add_actions,
-                                       restore_keyevent, get_icon)
+                                       restore_keyevent)
 from spyderlib.widgets.sourcecode.base import ConsoleBaseWidget
 from spyderlib.widgets.mixins import (InspectObjectMixin, TracebackLinksMixin,
                                       SaveHistoryMixin)
+from spyderlib.widgets.arraybuilder import (SHORTCUT_INLINE, SHORTCUT_TABLE)
 from spyderlib.py3compat import (is_text_string, to_text_string, builtins,
                                  is_string, PY3)
 
@@ -44,6 +47,11 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin):
     Shell base widget
     """
     
+    redirect_stdio = Signal(bool)
+    sig_keyboard_interrupt = Signal()
+    execute = Signal(str)
+    append_to_history = Signal(str, str)
+    
     def __init__(self, parent, history_filename, profile=False):
         """
         parent : specifies the parent widget
@@ -78,7 +86,7 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin):
         self.__timestamp = 0.0
         self.__flushtimer = QTimer(self)
         self.__flushtimer.setSingleShot(True)
-        self.connect(self.__flushtimer, SIGNAL('timeout()'), self.flush)
+        self.__flushtimer.timeout.connect(self.flush)
 
         # Give focus to widget
         self.setFocus()
@@ -113,28 +121,28 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin):
         self.menu = QMenu(self)
         self.cut_action = create_action(self, _("Cut"),
                                         shortcut=keybinding('Cut'),
-                                        icon=get_icon('editcut.png'),
+                                        icon=ima.icon('editcut'),
                                         triggered=self.cut)
         self.copy_action = create_action(self, _("Copy"),
                                          shortcut=keybinding('Copy'),
-                                         icon=get_icon('editcopy.png'),
+                                         icon=ima.icon('editcopy'),
                                          triggered=self.copy)
         paste_action = create_action(self, _("Paste"),
                                      shortcut=keybinding('Paste'),
-                                     icon=get_icon('editpaste.png'),
+                                     icon=ima.icon('editpaste'),
                                      triggered=self.paste)
         save_action = create_action(self, _("Save history log..."),
-                                    icon=get_icon('filesave.png'),
+                                    icon=ima.icon('filesave'),
                                     tip=_("Save current history log (i.e. all "
                                           "inputs and outputs) in a text file"),
                                     triggered=self.save_historylog)
         self.delete_action = create_action(self, _("Delete"),
                                     shortcut=keybinding('Delete'),
-                                    icon=get_icon('editdelete.png'),
+                                    icon=ima.icon('editdelete'),
                                     triggered=self.delete)
         selectall_action = create_action(self, _("Select All"),
                                     shortcut=keybinding('SelectAll'),
-                                    icon=get_icon('selectall.png'),
+                                    icon=ima.icon('selectall'),
                                     triggered=self.selectAll)
         add_actions(self.menu, (self.cut_action, self.copy_action,
                                 paste_action, self.delete_action, None,
@@ -162,12 +170,14 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin):
         else:
             pline, pindex = self.current_prompt_pos
         self.setSelection(pline, pindex, line, index)
-            
+
+    @Slot()
     def clear_line(self):
         """Clear current line (without clearing console prompt)"""
         if self.current_prompt_pos is not None:
             self.remove_text(self.current_prompt_pos, 'eof')
-        
+
+    @Slot()
     def clear_terminal(self):
         """
         Clear terminal window
@@ -220,6 +230,7 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin):
         
         
     #------ Copy / Keyboard interrupt
+    @Slot()
     def copy(self):
         """Copy text to clipboard... or keyboard interrupt"""
         if self.has_selected_text():
@@ -229,27 +240,30 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin):
 
     def interrupt(self):
         """Keyboard interrupt"""
-        self.emit(SIGNAL("keyboard_interrupt()"))
+        self.sig_keyboard_interrupt.emit()
 
+    @Slot()
     def cut(self):
         """Cut text"""
         self.check_selection()
         if self.has_selected_text():
             ConsoleBaseWidget.cut(self)
 
+    @Slot()
     def delete(self):
         """Remove selected text"""
         self.check_selection()
         if self.has_selected_text():
             ConsoleBaseWidget.remove_selected_text(self)
-        
+
+    @Slot()
     def save_historylog(self):
         """Save current history log (all text in console)"""
         title = _("Save history log")
-        self.emit(SIGNAL('redirect_stdio(bool)'), False)
+        self.redirect_stdio.emit(False)
         filename, _selfilter = getsavefilename(self, title,
                     self.historylog_filename, "%s (*.log)" % _("History logs"))
-        self.emit(SIGNAL('redirect_stdio(bool)'), True)
+        self.redirect_stdio.emit(True)
         if filename:
             filename = osp.normpath(filename)
             try:
@@ -271,7 +285,7 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin):
         self.execute_command(command)
         
     def execute_command(self, command):
-        self.emit(SIGNAL("execute(QString)"), command)
+        self.execute.emit(command)
         self.add_to_history(command)
         self.new_input_line = True
         
@@ -280,7 +294,8 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin):
         self.set_cursor_position('eof')
         self.current_prompt_pos = self.get_position('cursor')
         self.new_input_line = False
-        
+
+    @Slot()
     def paste(self):
         """Reimplemented slot to handle multiline paste action"""
         if self.new_input_line:
@@ -664,10 +679,10 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
                         InspectObjectMixin):
     """Python shell widget"""
     QT_CLASS = ShellBaseWidget
-
     INITHISTORY = ['# -*- coding: utf-8 -*-',
                    '# *** Spyder Python Console History Log ***',]
     SEPARATOR = '%s##---(%s)---' % (os.linesep*2, time.ctime())
+    go_to_error = Signal(str)
     
     def __init__(self, parent, history_filename, profile=False):
         ShellBaseWidget.__init__(self, parent, history_filename, profile)
@@ -678,6 +693,8 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
         self.shortcuts = self.create_shortcuts()
     
     def create_shortcuts(self):
+        new_shortcut(SHORTCUT_INLINE, self, lambda: self.enter_array_inline())
+        new_shortcut(SHORTCUT_TABLE, self, lambda: self.enter_array_table())        
         inspectsc = create_shortcut(self.inspect_current_object,
                                     context='Console',
                                     name='Inspect current object',
@@ -699,18 +716,18 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
         ShellBaseWidget.setup_context_menu(self)
         self.copy_without_prompts_action = create_action(self,
                                      _("Copy without prompts"),
-                                     icon=get_icon('copywop.png'),
+                                     icon=ima.icon('copywop'),
                                      triggered=self.copy_without_prompts)
         clear_line_action = create_action(self, _("Clear line"),
                                      QKeySequence(get_shortcut('console',
                                                                'Clear line')),
-                                     icon=get_icon('eraser.png'),
+                                     icon=ima.icon('editdelete'),
                                      tip=_("Clear line"),
                                      triggered=self.clear_line)
         clear_action = create_action(self, _("Clear shell"),
                                      QKeySequence(get_shortcut('console',
                                                                'Clear shell')),
-                                     icon=get_icon('clear.png'),
+                                     icon=ima.icon('editclear'),
                                      tip=_("Clear shell contents "
                                            "('cls' command)"),
                                      triggered=self.clear_terminal)
@@ -722,7 +739,8 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
         state = self.has_selected_text()
         self.copy_without_prompts_action.setEnabled(state)
         ShellBaseWidget.contextMenuEvent(self, event)
-        
+
+    @Slot()
     def copy_without_prompts(self):
         """Copy text to clipboard without prompts"""
         text = self.get_selected_text()
@@ -880,6 +898,9 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
         text = to_text_string(self.get_current_line_to_cursor())
         last_obj = self.get_last_obj()
         
+        if not text:
+            return
+
         if text.startswith('import '):
             obj_list = self.get_module_completion(text)
             words = text.split(' ')
@@ -968,6 +989,7 @@ class TerminalWidget(ShellBaseWidget):
     COM = 'rem' if os.name == 'nt' else '#'
     INITHISTORY = ['%s *** Spyder Terminal History Log ***' % COM, COM,]
     SEPARATOR = '%s%s ---(%s)---' % (os.linesep*2, COM, time.ctime())
+    go_to_error = Signal(str)
     
     def __init__(self, parent, history_filename, profile=False):
         ShellBaseWidget.__init__(self, parent, history_filename, profile)
diff --git a/spyderlib/widgets/sourcecode/base.py b/spyderlib/widgets/sourcecode/base.py
index de4c5cf..26879bc 100644
--- a/spyderlib/widgets/sourcecode/base.py
+++ b/spyderlib/widgets/sourcecode/base.py
@@ -19,9 +19,11 @@ from spyderlib.qt.QtGui import (QTextCursor, QColor, QFont, QApplication,
                                 QTextEdit, QTextCharFormat, QToolTip,
                                 QListWidget, QPlainTextEdit, QPalette,
                                 QMainWindow, QTextOption, QMouseEvent,
-                                QTextFormat, QClipboard)
-from spyderlib.qt.QtCore import SIGNAL, Qt, QEventLoop, QEvent, QPoint
+                                QTextFormat, QClipboard, QAbstractItemView,
+                                QListWidgetItem)
+from spyderlib.qt.QtCore import Signal, Slot, Qt, QEventLoop, QEvent, QPoint
 from spyderlib.qt.compat import to_qvariant
+import spyderlib.utils.icon_manager as ima
 
 
 # Local imports
@@ -31,6 +33,19 @@ from spyderlib.widgets.calltip import CallTipWidget
 from spyderlib.py3compat import to_text_string, str_lower, PY3
 
 
+def insert_text_to(cursor, text, fmt):
+    """Helper to print text, taking into account backspaces"""
+    while True:
+        index = text.find(chr(8))  # backspace
+        if index == -1:
+            break
+        cursor.insertText(text[:index], fmt)
+        if cursor.positionInBlock() > 0:
+            cursor.deletePreviousChar()
+        text = text[index+1:]
+    cursor.insertText(text, fmt)
+
+
 class CompletionWidget(QListWidget):
     """Completion list widget"""
     def __init__(self, parent, ancestor):
@@ -41,23 +56,39 @@ class CompletionWidget(QListWidget):
         self.case_sensitive = False
         self.enter_select = None
         self.hide()
-        self.connect(self, SIGNAL("itemActivated(QListWidgetItem*)"),
-                     self.item_selected)
+        self.itemActivated.connect(self.item_selected)
         
     def setup_appearance(self, size, font):
         self.resize(*size)
         self.setFont(font)
         
     def show_list(self, completion_list, automatic=True):
+        types = [c[1] for c in completion_list]
+        completion_list = [c[0] for c in completion_list]
         if len(completion_list) == 1 and not automatic:
             self.textedit.insert_completion(completion_list[0])
             return
-        
+
         self.completion_list = completion_list
         self.clear()
-        self.addItems(completion_list)
+
+        icons_map = {'instance': 'attribute',
+                     'statement': 'attribute',
+                     'method': 'method',
+                     'function': 'function',
+                     'class': 'class',
+                     'module': 'module'}
+
+        self.type_list = types
+        if any(types):
+            for (c, t) in zip(completion_list, types):
+                icon = icons_map.get(t, 'no_match')
+                self.addItem(QListWidgetItem(ima.icon(icon), c))
+        else:
+            self.addItems(completion_list)
+
         self.setCurrentRow(0)
-        
+
         QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)
         self.show()
         self.setFocus()
@@ -151,6 +182,8 @@ class CompletionWidget(QListWidget):
                     completion_text = completion_text.lower()
                 if completion.startswith(completion_text):
                     self.setCurrentRow(row)
+                    self.scrollTo(self.currentIndex(),
+                                  QAbstractItemView.PositionAtTop)
                     break
             else:
                 self.hide()
@@ -179,6 +212,11 @@ class TextEditBaseWidget(QPlainTextEdit, BaseEditMixin):
     """Text edit base widget"""
     BRACE_MATCHING_SCOPE = ('sof', 'eof')
     cell_separators = None
+    focus_in = Signal()
+    zoom_in = Signal()
+    zoom_out = Signal()
+    zoom_reset = Signal()
+    focus_changed = Signal()
     
     def __init__(self, parent=None):
         QPlainTextEdit.__init__(self, parent)
@@ -187,9 +225,8 @@ class TextEditBaseWidget(QPlainTextEdit, BaseEditMixin):
         
         self.extra_selections_dict = {}
         
-        self.connect(self, SIGNAL('textChanged()'), self.changed)
-        self.connect(self, SIGNAL('cursorPositionChanged()'),
-                     self.cursor_position_changed)
+        self.textChanged.connect(self.changed)
+        self.cursorPositionChanged.connect(self.cursor_position_changed)
         
         self.indent_chars = " "*4
         
@@ -277,8 +314,7 @@ class TextEditBaseWidget(QPlainTextEdit, BaseEditMixin):
         
     def changed(self):
         """Emit changed signal"""
-        self.emit(SIGNAL('modificationChanged(bool)'),
-                  self.document().isModified())
+        self.modificationChanged.emit(self.document().isModified())
 
 
     #------Highlight current line
@@ -445,6 +481,7 @@ class TextEditBaseWidget(QPlainTextEdit, BaseEditMixin):
         
         
     #------Reimplementing Qt methods
+    @Slot()
     def copy(self):
         """
         Reimplement Qt method
@@ -776,6 +813,7 @@ class TextEditBaseWidget(QPlainTextEdit, BaseEditMixin):
         cursor = self.textCursor()
         cursor.beginEditBlock()
         start_pos, end_pos = self.__save_selection()
+        add_linesep = False
         if to_text_string(cursor.selectedText()):
             # Check if start_pos is at the start of a block
             cursor.setPosition(start_pos)
@@ -795,22 +833,41 @@ class TextEditBaseWidget(QPlainTextEdit, BaseEditMixin):
             start_pos = cursor.position()
             cursor.movePosition(QTextCursor.NextBlock)
             end_pos = cursor.position()
+            # check if on last line
+            if end_pos == start_pos:
+                cursor.movePosition(QTextCursor.End)
+                end_pos = cursor.position()
+                if start_pos == end_pos:
+                    cursor.endEditBlock()
+                    return
+                add_linesep = True
         cursor.setPosition(start_pos)
         cursor.setPosition(end_pos, QTextCursor.KeepAnchor)
-        
+
         sel_text = to_text_string(cursor.selectedText())
+        if add_linesep:
+            sel_text += os.linesep
         cursor.removeSelectedText()
-        
+
         if after_current_line:
             text = to_text_string(cursor.block().text())
+            if not text:
+                cursor.insertText(sel_text)
+                cursor.endEditBlock()
+                return
             start_pos += len(text)+1
             end_pos += len(text)+1
             cursor.movePosition(QTextCursor.NextBlock)
+            if cursor.position() < start_pos:
+                cursor.movePosition(QTextCursor.End)
+                sel_text = os.linesep + sel_text
+                end_pos -= 1
         else:
             cursor.movePosition(QTextCursor.PreviousBlock)
             text = to_text_string(cursor.block().text())
             start_pos -= len(text)+1
             end_pos -= len(text)+1
+
         cursor.insertText(sel_text)
 
         cursor.endEditBlock()
@@ -884,16 +941,21 @@ class TextEditBaseWidget(QPlainTextEdit, BaseEditMixin):
     def show_completion_list(self, completions, completion_text="",
                              automatic=True):
         """Display the possible completions"""
-        if completions is None or len(completions) == 0 or \
-          completions == [completion_text]:
+        if not completions:
+            return
+        if not isinstance(completions[0], tuple):
+            completions = [(c, '') for c in completions]
+        if len(completions) == 1 and completions[0][0] == completion_text:
             return
         self.completion_text = completion_text
         # Sorting completion list (entries starting with underscore are
         # put at the end of the list):
-        underscore = set([comp for comp in completions
+        underscore = set([(comp, t) for (comp, t) in completions
                           if comp.startswith('_')])
-        completions = sorted(set(completions)-underscore, key=str_lower)+\
-                      sorted(underscore, key=str_lower)
+
+        completions = sorted(set(completions) - underscore,
+                             key=lambda x: str_lower(x[0]))
+        completions += sorted(underscore, key=lambda x: str_lower(x[0]))
         self.show_completion_widget(completions, automatic=automatic)
         
     def select_completion_list(self):
@@ -1002,14 +1064,14 @@ class TextEditBaseWidget(QPlainTextEdit, BaseEditMixin):
 
     def focusInEvent(self, event):
         """Reimplemented to handle focus"""
-        self.emit(SIGNAL("focus_changed()"))
-        self.emit(SIGNAL("focus_in()"))
+        self.focus_changed.emit()
+        self.focus_in.emit()
         self.highlight_current_cell()
         QPlainTextEdit.focusInEvent(self, event)
         
     def focusOutEvent(self, event):
         """Reimplemented to handle focus"""
-        self.emit(SIGNAL("focus_changed()"))
+        self.focus_changed.emit()
         QPlainTextEdit.focusOutEvent(self, event)
     
     def wheelEvent(self, event):
@@ -1017,10 +1079,16 @@ class TextEditBaseWidget(QPlainTextEdit, BaseEditMixin):
         # This feature is disabled on MacOS, see Issue 1510
         if sys.platform != 'darwin':
             if event.modifiers() & Qt.ControlModifier:
-                if event.delta() < 0:
-                    self.emit(SIGNAL("zoom_out()"))
-                elif event.delta() > 0:
-                    self.emit(SIGNAL("zoom_in()"))
+                if hasattr(event, 'angleDelta'):
+                    if event.angleDelta().y() < 0:
+                        self.zoom_out.emit()
+                    elif event.angleDelta().y() > 0:
+                        self.zoom_in.emit()
+                elif hasattr(event, 'delta'):
+                    if event.delta() < 0:
+                        self.zoom_out.emit()
+                    elif event.delta() > 0:
+                        self.zoom_in.emit()
                 return
         QPlainTextEdit.wheelEvent(self, event)
         self.highlight_current_cell()
@@ -1122,11 +1190,15 @@ class ConsoleFontStyle(object):
         font.setItalic(self.italic)
         font.setUnderline(self.underline)
         self.format.setFont(font)
-    
+
+
 class ConsoleBaseWidget(TextEditBaseWidget):
     """Console base widget"""
     BRACE_MATCHING_SCOPE = ('sol', 'eol')
     COLOR_PATTERN = re.compile('\x01?\x1b\[(.*?)m\x02?')
+    traceback_available = Signal()
+    userListActivated = Signal(int, str)
+    completion_widget_activated = Signal(str)
     
     def __init__(self, parent=None):
         TextEditBaseWidget.__init__(self, parent)
@@ -1141,10 +1213,8 @@ class ConsoleBaseWidget(TextEditBaseWidget):
         # Disable undo/redo (nonsense for a console widget...):
         self.setUndoRedoEnabled(False)
         
-        self.connect(self, SIGNAL('userListActivated(int, const QString)'),
-                     lambda user_id, text:
-                     self.emit(SIGNAL('completion_widget_activated(QString)'),
-                               text))
+        self.userListActivated.connect(lambda user_id, text:
+                                   self.completion_widget_activated.emit(text))
         
         self.default_style = ConsoleFontStyle(
                             foregroundcolor=0x000000, backgroundcolor=0xFFFFFF,
@@ -1203,6 +1273,8 @@ class ConsoleBaseWidget(TextEditBaseWidget):
     #------Python shell
     def insert_text(self, text):
         """Reimplement TextEditBaseWidget method"""
+        # Eventually this maybe should wrap to insert_text_to if
+        # backspace-handling is required
         self.textCursor().insertText(text, self.default_style.format)
         
     def paste(self):
@@ -1223,6 +1295,9 @@ class ConsoleBaseWidget(TextEditBaseWidget):
         """
         cursor = self.textCursor()
         cursor.movePosition(QTextCursor.End)
+        if '\r' in text:    # replace \r\n with \n
+            text = text.replace('\r\n', '\n')
+            text = text.replace('\r', '\n')
         while True:
             index = text.find(chr(12))
             if index == -1:
@@ -1243,21 +1318,21 @@ class ConsoleBaseWidget(TextEditBaseWidget):
                     # Show error/warning messages in red
                     cursor.insertText(text, self.error_style.format)
             if is_traceback:
-                self.emit(SIGNAL('traceback_available()'))
+                self.traceback_available.emit()
         elif prompt:
             # Show prompt in green
-            cursor.insertText(text, self.prompt_style.format)
+            insert_text_to(cursor, text, self.prompt_style.format)
         else:
             # Show other outputs in black
             last_end = 0
             for match in self.COLOR_PATTERN.finditer(text):
-                cursor.insertText(text[last_end:match.start()],
-                                  self.default_style.format)
+                insert_text_to(cursor, text[last_end:match.start()],
+                               self.default_style.format)
                 last_end = match.end()
                 for code in [int(_c) for _c in match.group(1).split(';')]:
                     self.ansi_handler.set_code(code)
                 self.default_style.format = self.ansi_handler.get_format()
-            cursor.insertText(text[last_end:], self.default_style.format)
+            insert_text_to(cursor, text[last_end:], self.default_style.format)
 #            # Slower alternative:
 #            segments = self.COLOR_PATTERN.split(text)
 #            cursor.insertText(segments.pop(0), self.default_style.format)
@@ -1269,7 +1344,7 @@ class ConsoleBaseWidget(TextEditBaseWidget):
 #                    cursor.insertText(text, self.default_style.format)
         self.set_cursor_position('eof')
         self.setCurrentCharFormat(self.default_style.format)
-    
+
     def set_pythonshell_font(self, font=None):
         """Python Shell only"""
         if font is None:
diff --git a/spyderlib/widgets/sourcecode/codeeditor.py b/spyderlib/widgets/sourcecode/codeeditor.py
index 0441cdc..6e09be2 100644
--- a/spyderlib/widgets/sourcecode/codeeditor.py
+++ b/spyderlib/widgets/sourcecode/codeeditor.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -8,7 +8,7 @@
 Editor widget based on QtGui.QPlainTextEdit
 """
 
-#%% This line is for cell execution testing
+# %% This line is for cell execution testing
 # pylint: disable=C0103
 # pylint: disable=R0903
 # pylint: disable=R0911
@@ -21,64 +21,78 @@ import re
 import sre_constants
 import os.path as osp
 import time
+from unicodedata import category
 
 from spyderlib.qt import is_pyqt46
 from spyderlib.qt.QtGui import (QColor, QMenu, QApplication, QSplitter, QFont,
                                 QTextEdit, QTextFormat, QPainter, QTextCursor,
                                 QBrush, QTextDocument, QTextCharFormat,
-                                QPixmap, QPrinter, QToolTip, QCursor, QLabel,
+                                QPrinter, QToolTip, QCursor, QLabel,
                                 QInputDialog, QTextBlockUserData, QLineEdit,
-                                QKeySequence, QWidget, QVBoxLayout,
-                                QHBoxLayout, QDialog, QIntValidator,
-                                QDialogButtonBox, QGridLayout, QPaintEvent,
-                                QMessageBox, QTextOption)
-from spyderlib.qt.QtCore import (Qt, SIGNAL, Signal, QTimer, QRect, QRegExp,
-                                 QSize, SLOT, Slot)
+                                QKeySequence, QVBoxLayout, QHBoxLayout,
+                                QDialog, QIntValidator, QDialogButtonBox,
+                                QGridLayout, QPaintEvent, QMessageBox, QWidget,
+                                QTextOption)
+from spyderlib.qt.QtCore import (Qt, Signal, QTimer, QRect, QRegExp, QSize,
+                                 Slot)
 from spyderlib.qt.compat import to_qvariant
+import spyderlib.utils.icon_manager as ima
 
-#%% This line is for cell execution testing
+# %% This line is for cell execution testing
 # Local import
-#TODO: Try to separate this module from spyderlib to create a self
-#      consistent editor module (Qt source code and shell widgets library)
-from spyderlib.baseconfig import get_conf_path, _, DEBUG, get_image_path
-from spyderlib.config import CONF
-from spyderlib.guiconfig import get_font, create_shortcut
+# TODO: Try to separate this module from spyderlib to create a self
+#       consistent editor module (Qt source code and shell widgets library)
+from spyderlib.config.base import get_conf_path, _, DEBUG
+from spyderlib.config.main import CONF
+from spyderlib.config.gui import (get_font, create_shortcut, new_shortcut,
+                                  get_shortcut)
 from spyderlib.utils.qthelpers import (add_actions, create_action, keybinding,
-                                       mimedata2url, get_icon)
+                                       mimedata2url)
 from spyderlib.utils.dochelpers import getobj
 from spyderlib.utils import encoding, sourcecode
 from spyderlib.utils.sourcecode import ALL_LANGUAGES, CELL_LANGUAGES
+from spyderlib.utils import syntaxhighlighters as sh
 from spyderlib.widgets.editortools import PythonCFM
 from spyderlib.widgets.sourcecode.base import TextEditBaseWidget
-from spyderlib.widgets.sourcecode import syntaxhighlighters as sh
+from spyderlib.widgets.sourcecode.kill_ring import QtKillRing
+from spyderlib.widgets.arraybuilder import SHORTCUT_INLINE, SHORTCUT_TABLE
 from spyderlib.py3compat import to_text_string
 
 try:
-    import IPython.nbformat as nbformat
-    import IPython.nbformat.current      # analysis:ignore
-    from IPython.nbconvert import PythonExporter as nbexporter
-except:
+    try:   # Ipython 4
+        import nbformat as nbformat
+        from nbconvert import PythonExporter as nbexporter  
+    except ImportError:  # Ipython 3
+        import IPython.nbformat as nbformat
+        from IPython.nbconvert import PythonExporter as nbexporter
+except ImportError:
     nbformat = None                      # analysis:ignore
 
-#%% This line is for cell execution testing
+# %% This line is for cell execution testing
 # For debugging purpose:
 LOG_FILENAME = get_conf_path('codeeditor.log')
 DEBUG_EDITOR = DEBUG >= 3
 
 
-#===============================================================================
+def is_letter_or_number(char):
+    """ Returns whether the specified unicode character is a letter or a number.
+    """
+    cat = category(char)
+    return cat.startswith('L') or cat.startswith('N')
+
+# =============================================================================
 # Go to line dialog box
-#===============================================================================
+# =============================================================================
 class GoToLineDialog(QDialog):
     def __init__(self, editor):
         QDialog.__init__(self, editor)
-        
+
         # Destroying the C++ object right after closing the dialog box,
         # otherwise it may be garbage-collected in another QThread
         # (e.g. the editor's analysis thread in Spyder), thus leading to
         # a segmentation fault on UNIX or an application crash on Windows
         self.setAttribute(Qt.WA_DeleteOnClose)
-        
+
         self.lineno = None
         self.editor = editor
 
@@ -90,8 +104,7 @@ class GoToLineDialog(QDialog):
         validator = QIntValidator(self.lineedit)
         validator.setRange(1, editor.get_line_count())
         self.lineedit.setValidator(validator)
-        self.connect(self.lineedit, SIGNAL('textChanged(QString)'),
-                     self.text_has_changed)
+        self.lineedit.textChanged.connect(self.text_has_changed)
         cl_label = QLabel(_("Current line:"))
         cl_label_v = QLabel("<b>%d</b>" % editor.get_cursor_line_number())
         last_label = QLabel(_("Line count:"))
@@ -107,15 +120,15 @@ class GoToLineDialog(QDialog):
 
         bbox = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel,
                                 Qt.Vertical, self)
-        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
-        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
+        bbox.accepted.connect(self.accept)
+        bbox.rejected.connect(self.reject)
         btnlayout = QVBoxLayout()
         btnlayout.addWidget(bbox)
         btnlayout.addStretch(1)
 
         ok_button = bbox.button(QDialogButtonBox.Ok)
         ok_button.setEnabled(False)
-        self.connect(self.lineedit, SIGNAL("textChanged(QString)"),
+        self.lineedit.textChanged.connect(
                      lambda text: ok_button.setEnabled(len(text) > 0))
 
         layout = QHBoxLayout()
@@ -124,7 +137,7 @@ class GoToLineDialog(QDialog):
         self.setLayout(layout)
 
         self.lineedit.setFocus()
-        
+
     def text_has_changed(self, text):
         """Line edit's text has changed"""
         text = to_text_string(text)
@@ -184,13 +197,13 @@ class ScrollFlagArea(QWidget):
     WIDTH = 12
     FLAGS_DX = 4
     FLAGS_DY = 2
-    
+
     def __init__(self, editor):
         QWidget.__init__(self, editor)
         self.setAttribute(Qt.WA_OpaquePaintEvent)
         self.code_editor = editor
-        self.connect(editor.verticalScrollBar(), SIGNAL('valueChanged(int)'),
-                     lambda value: self.repaint())
+        editor.verticalScrollBar().valueChanged.connect(
+                                                  lambda value: self.repaint())
 
     def sizeHint(self):
         """Override Qt method"""
@@ -205,7 +218,7 @@ class ScrollFlagArea(QWidget):
         vsb = self.code_editor.verticalScrollBar()
         value = self.position_to_value(event.pos().y()-1)
         vsb.setValue(value-.5*vsb.pageStep())
-        
+
     def get_scale_factor(self, slider=False):
         """Return scrollbar's scale factor:
         ratio between pixel span height and value span height"""
@@ -214,13 +227,13 @@ class ScrollFlagArea(QWidget):
         position_height = vsb.height()-delta-1
         value_height = vsb.maximum()-vsb.minimum()+vsb.pageStep()
         return float(position_height)/value_height
-        
+
     def value_to_position(self, y, slider=False):
         """Convert value to position"""
         offset = 0 if slider else 1
         vsb = self.code_editor.verticalScrollBar()
         return (y-vsb.minimum())*self.get_scale_factor(slider)+offset
-        
+
     def position_to_value(self, y, slider=False):
         """Convert position to value"""
         offset = 0 if slider else 1
@@ -310,50 +323,46 @@ def get_file_language(filename, text=None):
 
 class CodeEditor(TextEditBaseWidget):
     """Source Code Editor Widget based exclusively on Qt"""
-    
+
     LANGUAGES = {'Python': (sh.PythonSH, '#', PythonCFM),
                  'Cython': (sh.CythonSH, '#', PythonCFM),
                  'Fortran77': (sh.Fortran77SH, 'c', None),
                  'Fortran': (sh.FortranSH, '!', None),
                  'Idl': (sh.IdlSH, ';', None),
-                 'Matlab': (sh.MatlabSH, '%', None),
                  'Diff': (sh.DiffSH, '', None),
                  'GetText': (sh.GetTextSH, '#', None),
                  'Nsis': (sh.NsisSH, '#', None),
                  'Html': (sh.HtmlSH, '', None),
-                 'Css': (sh.CssSH, '', None),
-                 'Xml': (sh.XmlSH, '', None),
-                 'Js': (sh.JsSH, '//', None),
-                 'Json': (sh.JsonSH, '', None),
-                 'Julia': (sh.JuliaSH, '#', None),
                  'Yaml': (sh.YamlSH, '#', None),
                  'Cpp': (sh.CppSH, '//', None),
                  'OpenCL': (sh.OpenCLSH, '//', None),
-                 'Batch': (sh.BatchSH, 'rem ', None),
-                 'Ini': (sh.IniSH, '#', None),
                  'Enaml': (sh.EnamlSH, '#', PythonCFM),
                 }
 
-    try:
-        import pygments  # analysis:ignore
-    except ImportError:
-        # Removing all syntax highlighters requiring pygments to be installed
-        for key, (sh_class, comment_string, CFMatch) in list(LANGUAGES.items()):
-            if issubclass(sh_class, sh.PygmentsSH):
-                LANGUAGES.pop(key)
-    
     TAB_ALWAYS_INDENTS = ('py', 'pyw', 'python', 'c', 'cpp', 'cl', 'h')
 
-    # Custom signal to be emitted upon completion of the editor's paintEvent 
+    # Custom signal to be emitted upon completion of the editor's paintEvent
     painted = Signal(QPaintEvent)
-    sig_new_file = Signal(str)
-    
+
     # To have these attrs when early viewportEvent's are triggered
     edge_line = None
     linenumberarea = None
-    
+
+    breakpoints_changed = Signal()
+    get_completions = Signal(bool)
+    go_to_definition = Signal(int)
+    sig_show_object_info = Signal(int)
+    run_selection = Signal()
+    run_cell_and_advance = Signal()
+    run_cell = Signal()
+    go_to_definition_regex = Signal(int)
+    sig_cursor_position_changed = Signal(int, int)
+    focus_changed = Signal()
+    sig_new_file = Signal(str)
+
     def __init__(self, parent=None):
         TextEditBaseWidget.__init__(self, parent)
+
         self.setFocusPolicy(Qt.StrongFocus)
 
         # We use these object names to set the right background
@@ -388,21 +397,18 @@ class CodeEditor(TextEditBaseWidget):
         # Markers
         self.markers_margin = True
         self.markers_margin_width = 15
-        self.error_pixmap = QPixmap(get_image_path('error.png'), 'png')
-        self.warning_pixmap = QPixmap(get_image_path('warning.png'), 'png')
-        self.todo_pixmap = QPixmap(get_image_path('todo.png'), 'png')
-        self.bp_pixmap = QPixmap(get_image_path('breakpoint_small.png'), 'png')
-        self.bpc_pixmap = QPixmap(get_image_path('breakpoint_cond_small.png'),
-                                                 'png')
+        self.error_pixmap = ima.icon('error').pixmap(QSize(14, 14))
+        self.warning_pixmap = ima.icon('warning').pixmap(QSize(14, 14))
+        self.todo_pixmap = ima.icon('todo').pixmap(QSize(14, 14))
+        self.bp_pixmap = ima.icon('breakpoint_big').pixmap(QSize(14, 14))
+        self.bpc_pixmap = ima.icon('breakpoint_cond_big').pixmap(QSize(14, 14))
 
         # Line number area management
         self.linenumbers_margin = True
         self.linenumberarea_enabled = None
         self.linenumberarea = LineNumberArea(self)
-        self.connect(self, SIGNAL("blockCountChanged(int)"),
-                     self.update_linenumberarea_width)
-        self.connect(self, SIGNAL("updateRequest(QRect,int)"),
-                     self.update_linenumberarea)
+        self.blockCountChanged.connect(self.update_linenumberarea_width)
+        self.updateRequest.connect(self.update_linenumberarea)
         self.linenumberarea_pressed = -1
         self.linenumberarea_released = -1
 
@@ -415,7 +421,7 @@ class CodeEditor(TextEditBaseWidget):
         self.unmatched_p_color = None
         self.normal_color = None
         self.comment_color = None
-        
+
         self.linenumbers_color = QColor(Qt.darkGray)
 
         # --- Syntax highlight entrypoint ---
@@ -453,8 +459,7 @@ class CodeEditor(TextEditBaseWidget):
         self.document_id = id(self)
 
         # Indicate occurences of the selected word
-        self.connect(self, SIGNAL('cursorPositionChanged()'),
-                     self.__cursor_position_changed)
+        self.cursorPositionChanged.connect(self.__cursor_position_changed)
         self.__find_first_pos = None
         self.__find_flags = None
 
@@ -462,26 +467,25 @@ class CodeEditor(TextEditBaseWidget):
         self.supported_cell_language = False
         self.classfunc_match = None
         self.comment_string = None
+        self._kill_ring = QtKillRing(self)
 
         # Block user data
         self.blockuserdata_list = []
-        
+
         # Update breakpoints if the number of lines in the file changes
-        self.connect(self, SIGNAL("blockCountChanged(int)"),
-                     self.update_breakpoints)
+        self.blockCountChanged.connect(self.update_breakpoints)
 
         # Mark occurences timer
         self.occurence_highlighting = None
         self.occurence_timer = QTimer(self)
         self.occurence_timer.setSingleShot(True)
         self.occurence_timer.setInterval(1500)
-        self.connect(self.occurence_timer, SIGNAL("timeout()"),
-                     self.__mark_occurences)
+        self.occurence_timer.timeout.connect(self.__mark_occurences)
         self.occurences = []
         self.occurence_color = QColor(Qt.yellow).lighter(160)
-        
+
         # Mark found results
-        self.connect(self, SIGNAL('textChanged()'), self.__text_has_changed)
+        self.textChanged.connect(self.__text_has_changed)
         self.found_results = []
         self.found_results_color = QColor(Qt.magenta).lighter(180)
 
@@ -516,13 +520,13 @@ class CodeEditor(TextEditBaseWidget):
         # Code editor
         self.__visible_blocks = []  # Visible blocks, update with repaint
         self.painted.connect(self._draw_editor_cell_divider)
-        
-        self.connect(self.verticalScrollBar(), SIGNAL('valueChanged(int)'),
-                     lambda value: self.rehighlight_cells())
+
+        self.verticalScrollBar().valueChanged.connect(
+                                       lambda value: self.rehighlight_cells())                                 
 
     def create_shortcuts(self):
         codecomp = create_shortcut(self.do_completion, context='Editor',
-                                   name='Code completion', parent=self)
+                                   name='Code Completion', parent=self)
         duplicate_line = create_shortcut(self.duplicate_line, context='Editor',
                                          name='Duplicate line', parent=self)
         copyline = create_shortcut(self.copy_line, context='Editor',
@@ -541,9 +545,72 @@ class CodeEditor(TextEditBaseWidget):
                                        name='Blockcomment', parent=self)
         unblockcomment = create_shortcut(self.unblockcomment, context='Editor',
                                          name='Unblockcomment', parent=self)
+
+        def cb_maker(attr):
+            """Make a callback for cursor move event type, (e.g. "Start")
+            """
+            def cursor_move_event():
+                cursor = self.textCursor()
+                move_type = getattr(QTextCursor, attr)
+                cursor.movePosition(move_type)
+                self.setTextCursor(cursor)
+            return cursor_move_event
+
+        line_start = create_shortcut(cb_maker('StartOfLine'), context='Editor',
+                                     name='Start of line', parent=self)
+        line_end = create_shortcut(cb_maker('EndOfLine'), context='Editor',
+                                   name='End of line', parent=self)
+
+        prev_line = create_shortcut(cb_maker('Up'), context='Editor',
+                                    name='Previous line', parent=self)
+        next_line = create_shortcut(cb_maker('Down'), context='Editor',
+                                    name='Next line', parent=self)
+
+        prev_char = create_shortcut(cb_maker('Left'), context='Editor',
+                                    name='Previous char', parent=self)
+        next_char = create_shortcut(cb_maker('Right'), context='Editor',
+                                    name='Next char', parent=self)
+
+        prev_word = create_shortcut(cb_maker('StartOfWord'), context='Editor',
+                                    name='Previous word', parent=self)
+        next_word = create_shortcut(cb_maker('EndOfWord'), context='Editor',
+                                    name='Next word', parent=self)
+
+        kill_line_end = create_shortcut(self.kill_line_end, context='Editor',
+                                        name='Kill to line end', parent=self)
+        kill_line_start = create_shortcut(self.kill_line_start,
+                                          context='Editor',
+                                          name='Kill to line start',
+                                          parent=self)
+        yank = create_shortcut(self._kill_ring.yank, context='Editor',
+                               name='Yank', parent=self)
+        kill_ring_rotate = create_shortcut(self._kill_ring.rotate,
+                                           context='Editor',
+                                           name='Rotate kill ring',
+                                           parent=self)
+
+        kill_prev_word = create_shortcut(self.kill_prev_word, context='Editor',
+                                         name='Kill previous word',
+                                         parent=self)
+        kill_next_word = create_shortcut(self.kill_next_word, context='Editor',
+                                         name='Kill next word', parent=self)
+
+        start_doc = create_shortcut(cb_maker('Start'), context='Editor',
+                                    name='Start of Document', parent=self)
+
+        end_doc = create_shortcut(cb_maker('End'), context='Editor',
+                                  name='End of document', parent=self)
+
+        # Fixed shortcuts
+        new_shortcut(SHORTCUT_INLINE, self, lambda: self.enter_array_inline())
+        new_shortcut(SHORTCUT_TABLE, self, lambda: self.enter_array_table())
+
         return [codecomp, duplicate_line, copyline, deleteline, movelineup,
                 movelinedown, gotodef, toggle_comment, blockcomment,
-                unblockcomment]
+                unblockcomment, line_start, line_end, prev_line, next_line,
+                prev_char, next_char, prev_word, next_word, kill_line_end,
+                kill_line_start, yank, kill_ring_rotate, kill_prev_word,
+                kill_next_word, start_doc, end_doc]
 
     def get_shortcut_data(self):
         """
@@ -557,8 +624,7 @@ class CodeEditor(TextEditBaseWidget):
     def closeEvent(self, event):
         TextEditBaseWidget.closeEvent(self, event)
         if is_pyqt46:
-            self.emit(SIGNAL('destroyed()'))
-
+            self.destroyed.emit()
 
     def get_document_id(self):
         return self.document_id
@@ -585,7 +651,7 @@ class CodeEditor(TextEditBaseWidget):
                      calltips=None, go_to_definition=False,
                      close_parentheses=True, close_quotes=False,
                      add_colons=True, auto_unindent=True, indent_chars=" "*4,
-                     tab_stop_width=40, cloned_from=None,
+                     tab_stop_width=40, cloned_from=None, filename=None,
                      occurence_timeout=1500):
         
         # Code completion and calltips
@@ -617,7 +683,7 @@ class CodeEditor(TextEditBaseWidget):
         self.setup_margins(linenumbers, markers)
 
         # Lexer
-        self.set_language(language)
+        self.set_language(language, filename)
 
         # Highlight current cell
         self.set_highlight_current_cell(highlight_current_cell)
@@ -663,11 +729,11 @@ class CodeEditor(TextEditBaseWidget):
     def set_close_parentheses_enabled(self, enable):
         """Enable/disable automatic parentheses insertion feature"""
         self.close_parentheses_enabled = enable
-    
+
     def set_close_quotes_enabled(self, enable):
         """Enable/disable automatic quote insertion feature"""
         self.close_quotes_enabled = enable
-    
+
     def set_add_colons_enabled(self, enable):
         """Enable/disable automatic colons insertion feature"""
         self.add_colons_enabled = enable
@@ -703,7 +769,7 @@ class CodeEditor(TextEditBaseWidget):
         else:
             self.unhighlight_current_cell()
 
-    def set_language(self, language):
+    def set_language(self, language, filename=None):
         self.tab_indents = language in self.TAB_ALWAYS_INDENTS
         self.comment_string = ''
         sh_class = sh.TextSH
@@ -721,6 +787,9 @@ class CodeEditor(TextEditBaseWidget):
                     else:
                         self.classfunc_match = CFMatch()
                     break
+        if filename is not None and not self.supported_language:
+            sh_class = sh.guess_pygments_highlighter(filename)
+            self.support_language = sh_class is not sh.TextSH
         self._set_highlighter(sh_class)
 
     def _set_highlighter(self, sh_class):
@@ -736,20 +805,21 @@ class CodeEditor(TextEditBaseWidget):
         self._apply_highlighter_color_scheme()
 
     def is_json(self):
-        return self.highlighter_class is sh.JsonSH
+        return (isinstance(self.highlighter, sh.PygmentsSH) and
+                self.highlighter._lexer.name == 'JSON')
 
     def is_python(self):
         return self.highlighter_class is sh.PythonSH
 
     def is_cython(self):
         return self.highlighter_class is sh.CythonSH
-        
+
     def is_enaml(self):
         return self.highlighter_class is sh.EnamlSH
 
     def is_python_like(self):
         return self.is_python() or self.is_cython() or self.is_enaml()
-        
+
     def intelligent_tab(self):
         """Provide intelligent behavoir for Tab key press"""
         leading_text = self.get_text('sol', 'cursor')
@@ -762,7 +832,7 @@ class CodeEditor(TextEditBaseWidget):
         elif leading_text.endswith('import ') or leading_text[-1] == '.':
             # blank import or dot completion
             self.do_completion()
-        elif (leading_text.split()[0] in ['from', 'import'] and 
+        elif (leading_text.split()[0] in ['from', 'import'] and
               not ';' in leading_text):
             # import line with a single statement
             #  (prevents lines like: `import pdb; pdb.set_trace()`)
@@ -785,14 +855,14 @@ class CodeEditor(TextEditBaseWidget):
             # blank line
             self.unindent()
         elif self.in_comment_or_string():
-            self.unindent()  
+            self.unindent()
         elif leading_text[-1] in '(,' or leading_text.endswith(', '):
             position = self.get_position('cursor')
             self.show_object_info(position)
         else:
             # if the line ends with any other character but comma
             self.unindent()
-            
+
     def rehighlight(self):
         """
         Rehighlight the whole document to rebuild outline explorer data
@@ -803,12 +873,12 @@ class CodeEditor(TextEditBaseWidget):
         if self.highlight_current_cell_enabled:
             self.highlight_current_cell()
         else:
-            self.unhighlight_current_cell()   
+            self.unhighlight_current_cell()
         if self.highlight_current_line_enabled:
             self.highlight_current_line()
         else:
             self.unhighlight_current_line()
-    
+
     def rehighlight_cells(self):
         """Rehighlight cells when moving the scrollbar"""
         if self.highlight_current_cell_enabled:
@@ -878,7 +948,7 @@ class CodeEditor(TextEditBaseWidget):
     def __cursor_position_changed(self):
         """Cursor position has changed"""
         line, column = self.get_cursor_line_column()
-        self.emit(SIGNAL('cursorPositionChanged(int,int)'), line, column)
+        self.sig_cursor_position_changed.emit(line, column)
         if self.highlight_current_cell_enabled:
             self.highlight_current_cell()
         else:
@@ -926,13 +996,13 @@ class CodeEditor(TextEditBaseWidget):
 
         if not self.supported_language:
             return
-            
+
         text = self.get_current_word()
         if text is None:
             return
         if self.has_selected_text() and self.get_selected_text() != text:
             return
-            
+
         if (self.is_python_like()) and \
            (sourcecode.is_keyword(to_text_string(text)) or \
            to_text_string(text) == 'self'):
@@ -949,7 +1019,7 @@ class CodeEditor(TextEditBaseWidget):
         self.update_extra_selections()
         if len(self.occurences) > 1 and self.occurences[-1] == 0:
             # XXX: this is never happening with PySide but it's necessary
-            # for PyQt4... this must be related to a different behavior for 
+            # for PyQt4... this must be related to a different behavior for
             # the QTextDocument.find function between those two libraries
             self.occurences.pop(-1)
         self.scrollflagarea.update()
@@ -981,13 +1051,13 @@ class CodeEditor(TextEditBaseWidget):
             extra_selections.append(selection)
         self.set_extra_selections('find', extra_selections)
         self.update_extra_selections()
-        
+
     def clear_found_results(self):
         """Clear found results highlighting"""
         self.found_results = []
         self.clear_extra_selections('find')
         self.scrollflagarea.update()
-        
+
     def __text_has_changed(self):
         """Text has changed, eventually clear found results highlighting"""
         if self.found_results:
@@ -1028,7 +1098,7 @@ class CodeEditor(TextEditBaseWidget):
     def update_linenumberarea_width(self, new_block_count=None):
         """
         Update line number area width.
-        
+
         new_block_count is needed to handle blockCountChanged(int) signal
         """
         self.setViewportMargins(self.compute_linenumberarea_width(), 0,
@@ -1226,7 +1296,7 @@ class CodeEditor(TextEditBaseWidget):
         block.setUserData(data)
         self.linenumberarea.update()
         self.scrollflagarea.update()
-        self.emit(SIGNAL('breakpoints_changed()'))
+        self.breakpoints_changed.emit()
 
     def get_breakpoints(self):
         """Get breakpoints"""
@@ -1256,22 +1326,22 @@ class CodeEditor(TextEditBaseWidget):
 
     def update_breakpoints(self):
         """Update breakpoints"""
-        self.emit(SIGNAL('breakpoints_changed()'))
+        self.breakpoints_changed.emit()
 
     #-----Code introspection
     def do_completion(self, automatic=False):
         """Trigger completion"""
         if not self.is_completion_widget_visible():
-            self.emit(SIGNAL('get_completions(bool)'), automatic)
+            self.get_completions.emit(automatic)
 
     def do_go_to_definition(self):
         """Trigger go-to-definition"""
         if not self.in_comment_or_string():
-            self.emit(SIGNAL("go_to_definition(int)"), self.textCursor().position())
+            self.go_to_definition.emit(self.textCursor().position())
 
     def show_object_info(self, position):
         """Trigger a calltip"""
-        self.emit(SIGNAL('show_object_info(int)'), position)
+        self.sig_show_object_info.emit(position)
 
     #-----edge line
     def set_edge_line_enabled(self, state):
@@ -1296,6 +1366,8 @@ class CodeEditor(TextEditBaseWidget):
         else:
             option.setFlags(option.flags() & ~QTextOption.ShowTabsAndSpaces)
         self.document().setDefaultTextOption(option)
+        # Rehighlight to make the spaces less apparent.
+        self.rehighlight()
 
     #-----scrollflagarea
     def set_scrollflagarea_enabled(self, state):
@@ -1315,12 +1387,12 @@ class CodeEditor(TextEditBaseWidget):
         """Painting the scroll flag area"""
         make_flag = self.scrollflagarea.make_flag_qrect
         make_slider = self.scrollflagarea.make_slider_range
-        
+
         # Filling the whole painting area
         painter = QPainter(self.scrollflagarea)
         painter.fillRect(event.rect(), self.sideareas_color)
         block = self.document().firstBlock()
-        
+
         # Painting warnings and todos
         for line_number in range(1, self.document().blockCount()+1):
             data = block.userData()
@@ -1344,14 +1416,14 @@ class CodeEditor(TextEditBaseWidget):
                     set_scrollflagarea_painter(painter, self.breakpoint_color)
                     painter.drawRect(make_flag(position))
             block = block.next()
-            
+
         # Occurences
         if self.occurences:
             set_scrollflagarea_painter(painter, self.occurence_color)
             for line_number in self.occurences:
                 position = self.scrollflagarea.value_to_position(line_number)
                 painter.drawRect(make_flag(position))
-            
+
         # Found results
         if self.found_results:
             set_scrollflagarea_painter(painter, self.found_results_color)
@@ -1409,11 +1481,6 @@ class CodeEditor(TextEditBaseWidget):
         return TextEditBaseWidget.viewportEvent(self, event)
 
     #-----Misc.
-    def delete(self):
-        """Remove selected text"""
-        # Used by global callbacks in Spyder -> delete_action
-        self.remove_selected_text()
-
     def _apply_highlighter_color_scheme(self):
         """Apply color scheme from syntax highlighter to the editor"""
         hl = self.highlighter
@@ -1479,7 +1546,7 @@ class CodeEditor(TextEditBaseWidget):
         text, _enc = encoding.read(filename)
         if language is None:
             language = get_file_language(filename, text)
-        self.set_language(language)
+        self.set_language(language, filename)
         self.set_text(text)
 
     def append(self, text):
@@ -1488,6 +1555,7 @@ class CodeEditor(TextEditBaseWidget):
         cursor.movePosition(QTextCursor.End)
         cursor.insertText(text)
 
+    @Slot()
     def paste(self):
         """
         Reimplement QPlainTextEdit's method to fix the following issue:
@@ -1521,8 +1589,7 @@ class CodeEditor(TextEditBaseWidget):
     def center_cursor_on_next_focus(self):
         """QPlainTextEdit's "centerCursor" requires the widget to be visible"""
         self.centerCursor()
-        self.disconnect(self, SIGNAL("focus_in()"),
-                        self.center_cursor_on_next_focus)
+        self.focus_in.disconnect(self.center_cursor_on_next_focus)
 
     def go_to_line(self, line, word=''):
         """Go to line number *line* and eventually highlight it"""
@@ -1531,8 +1598,7 @@ class CodeEditor(TextEditBaseWidget):
         if self.isVisible():
             self.centerCursor()
         else:
-            self.connect(self, SIGNAL("focus_in()"),
-                         self.center_cursor_on_next_focus)
+            self.focus_in.connect(self.center_cursor_on_next_focus)
         self.horizontalScrollBar().setValue(0)
         if word and to_text_string(word) in to_text_string(block.text()):
             self.find(word, QTextDocument.FindCaseSensitively)
@@ -1553,7 +1619,7 @@ class CodeEditor(TextEditBaseWidget):
                 del data
         self.setUpdatesEnabled(True)
         # When the new code analysis results are empty, it is necessary
-        # to update manually the scrollflag and linenumber areas (otherwise, 
+        # to update manually the scrollflag and linenumber areas (otherwise,
         # the old flags will still be displayed):
         self.scrollflagarea.update()
         self.linenumberarea.update()
@@ -1818,12 +1884,28 @@ class CodeEditor(TextEditBaseWidget):
             return
         cursor = self.textCursor()
         block_nb = cursor.blockNumber()
+        # find the line that contains our scope
+        diff = 0
+        add_indent = False
         prevline = None
         for prevline in range(block_nb-1, -1, -1):
             cursor.movePosition(QTextCursor.PreviousBlock)
             prevtext = to_text_string(cursor.block().text()).rstrip()
             if not prevtext.strip().startswith('#'):
-                break
+                if prevtext.strip().endswith(')'):
+                    comment_or_string = True  # prevent further parsing
+                elif prevtext.strip().endswith(':'):
+                    add_indent = True
+                    comment_or_string = True
+                if prevtext.count(')') > prevtext.count('('):
+                    diff = prevtext.count(')') - prevtext.count('(')
+                    continue
+                elif diff:
+                    diff += prevtext.count(')') - prevtext.count('(')
+                    if not diff:
+                        break
+                else:
+                    break
 
         if not prevline:
             return False
@@ -1831,6 +1913,9 @@ class CodeEditor(TextEditBaseWidget):
         indent = self.get_block_indentation(block_nb)
         correct_indent = self.get_block_indentation(prevline)
 
+        if add_indent:
+            correct_indent += len(self.indent_chars)
+
         if not comment_or_string:
             if prevtext.endswith(':'):
                 # Indent
@@ -1853,8 +1938,11 @@ class CodeEditor(TextEditBaseWidget):
                             else:
                                 break
                 else:
-                    prevexpr = re.split(r'\(|\{|\[', prevtext)[-1]
-                    correct_indent = len(prevtext)-len(prevexpr)
+                    if prevtext.strip():
+                        prevexpr = re.split(r'\(|\{|\[', prevtext)[-1]
+                        correct_indent = len(prevtext)-len(prevexpr)
+                    else:
+                        correct_indent = len(prevtext)
 
         if (forward and indent >= correct_indent) or \
            (not forward and indent <= correct_indent):
@@ -1871,44 +1959,40 @@ class CodeEditor(TextEditBaseWidget):
             cursor.endEditBlock()
             return True
 
+    @Slot()
     def clear_all_output(self):
-        """removes all ouput in the ipynb format (Json only)"""
-        if self.is_json() and nbformat is not None:
-            try:
-                nb = nbformat.current.reads(self.toPlainText(), 'json')
-            except Exception as e:
-                QMessageBox.critical(self, _('Removal error'), 
-                               _("It was not possible to remove outputs from "
-                                 "this notebook. The error is:\n\n") + \
-                                 to_text_string(e))
-                return
-            if nb.worksheets:
-                for cell in nb.worksheets[0].cells:
+        """Removes all ouput in the ipynb format (Json only)"""
+        try:
+            nb = nbformat.reads(self.toPlainText(), as_version=4)
+            if nb.cells:
+                for cell in nb.cells:
                     if 'outputs' in cell:
                         cell['outputs'] = []
                     if 'prompt_number' in cell:
                         cell['prompt_number'] = None
             # We do the following rather than using self.setPlainText
-            # to benefit from QTextEdit's undo/redo feature. 
+            # to benefit from QTextEdit's undo/redo feature.
             self.selectAll()
-            self.insertPlainText(nbformat.current.writes(nb, 'json'))
-        else:
+            self.insertPlainText(nbformat.writes(nb))
+        except Exception as e:
+            QMessageBox.critical(self, _('Removal error'),
+                           _("It was not possible to remove outputs from "
+                             "this notebook. The error is:\n\n") + \
+                             to_text_string(e))
             return
 
+    @Slot()
     def convert_notebook(self):
         """Convert an IPython notebook to a Python script in editor"""
         try:
-            try: # >3.0
-                nb = nbformat.reads(self.toPlainText(), as_version=4)
-            except AttributeError:
-                nb = nbformat.current.reads(self.toPlainText(), 'json')
+            nb = nbformat.reads(self.toPlainText(), as_version=4)
+            script = nbexporter().from_notebook_node(nb)[0]
         except Exception as e:
-            QMessageBox.critical(self, _('Conversion error'), 
+            QMessageBox.critical(self, _('Conversion error'),
                                  _("It was not possible to convert this "
                                  "notebook. The error is:\n\n") + \
                                  to_text_string(e))
             return
-        script = nbexporter().from_notebook_node(nb)[0]
         self.sig_new_file.emit(script)
 
     def indent(self, force=False):
@@ -1973,6 +2057,7 @@ class CodeEditor(TextEditBaseWidget):
                 else:
                     self.remove_prefix(self.indent_chars)
 
+    @Slot()
     def toggle_comment(self):
         """Toggle comment on current line or selection"""
         cursor = self.textCursor()
@@ -2084,7 +2169,83 @@ class CodeEditor(TextEditBaseWidget):
             cursor3.select(QTextCursor.BlockUnderCursor)
             cursor3.removeSelectedText()
         cursor3.endEditBlock()
-    
+
+    #------Kill ring handlers
+    # Taken from Jupyter's QtConsole
+    # Copyright (c) 2001-2015, IPython Development Team
+    # Copyright (c) 2015-, Jupyter Development Team
+    def kill_line_end(self):
+        """Kill the text on the current line from the cursor forward"""
+        cursor = self.textCursor()
+        cursor.clearSelection()
+        cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor)
+        if not cursor.hasSelection():
+            # Line deletion
+            cursor.movePosition(QTextCursor.NextBlock,
+                                QTextCursor.KeepAnchor)
+        self._kill_ring.kill_cursor(cursor)
+        self.setTextCursor(cursor)
+
+    def kill_line_start(self):
+        """Kill the text on the current line from the cursor backward"""
+        cursor = self.textCursor()
+        cursor.clearSelection()
+        cursor.movePosition(QTextCursor.StartOfBlock,
+                            QTextCursor.KeepAnchor)
+        self._kill_ring.kill_cursor(cursor)
+        self.setTextCursor(cursor)
+
+    def _get_word_start_cursor(self, position):
+        """Find the start of the word to the left of the given position. If a
+           sequence of non-word characters precedes the first word, skip over
+           them. (This emulates the behavior of bash, emacs, etc.)
+        """
+        document = self.document()
+        position -= 1
+        while (position and not
+               is_letter_or_number(document.characterAt(position))):
+            position -= 1
+        while position and is_letter_or_number(document.characterAt(position)):
+            position -= 1
+        cursor = self.textCursor()
+        cursor.setPosition(position + 1)
+        return cursor
+
+    def _get_word_end_cursor(self, position):
+        """Find the end of the word to the right of the given position. If a
+           sequence of non-word characters precedes the first word, skip over
+           them. (This emulates the behavior of bash, emacs, etc.)
+        """
+        document = self.document()
+        cursor = self.textCursor()
+        position = cursor.position()
+        cursor.movePosition(QTextCursor.End)
+        end = cursor.position()
+        while (position < end and
+               not is_letter_or_number(document.characterAt(position))):
+            position += 1
+        while (position < end and
+               is_letter_or_number(document.characterAt(position))):
+            position += 1
+        cursor.setPosition(position)
+        return cursor
+
+    def kill_prev_word(self):
+        """Kill the previous word"""
+        position = self.textCursor().position()
+        cursor = self._get_word_start_cursor(position)
+        cursor.setPosition(position, QTextCursor.KeepAnchor)
+        self._kill_ring.kill_cursor(cursor)
+        self.setTextCursor(cursor)
+
+    def kill_next_word(self):
+        """Kill the next word"""
+        position = self.textCursor().position()
+        cursor = self._get_word_end_cursor(position)
+        cursor.setPosition(position, QTextCursor.KeepAnchor)
+        self._kill_ring.kill_cursor(cursor)
+        self.setTextCursor(cursor)
+
     #------Autoinsertion of quotes/colons
     def __get_current_color(self):
         """Get the syntax highlighting color for the current cursor position"""
@@ -2093,7 +2254,7 @@ class CodeEditor(TextEditBaseWidget):
         pos = cursor.position() - block.position()  # relative pos within block
         layout = block.layout()
         block_formats = layout.additionalFormats()
-        
+
         if block_formats:
             # To easily grab current format for autoinsert_colons
             if cursor.atBlockEnd():
@@ -2107,7 +2268,7 @@ class CodeEditor(TextEditBaseWidget):
             return color
         else:
             return None
-    
+
     def in_comment_or_string(self):
         """Is the cursor inside or next to a comment or string?"""
         if self.highlighter:
@@ -2169,15 +2330,15 @@ class CodeEditor(TextEditBaseWidget):
             return False
         else:
             return True
-    
+
     def __unmatched_quotes_in_line(self, text):
         """Return whether a string has open quotes.
         This simply counts whether the number of quote characters of either
         type in the string is odd.
-        
+
         Take from the IPython project (in IPython/core/completer.py in v0.13)
         Spyder team: Add some changes to deal with escaped quotes
-        
+
         - Copyright (C) 2008-2011 IPython Development Team
         - Copyright (C) 2001-2007 Fernando Perez. <fperez at colorado.edu>
         - Copyright (C) 2001 Python Software Foundation, www.python.org
@@ -2197,7 +2358,7 @@ class CodeEditor(TextEditBaseWidget):
 
     def __next_char(self):
         cursor = self.textCursor()
-        cursor.movePosition(QTextCursor.NextCharacter, 
+        cursor.movePosition(QTextCursor.NextCharacter,
                             QTextCursor.KeepAnchor)
         next_char = to_text_string(cursor.selectedText())
         return next_char
@@ -2216,7 +2377,7 @@ class CodeEditor(TextEditBaseWidget):
     def autoinsert_quotes(self, key):
         """Control how to automatically insert quotes in various situations"""
         char = {Qt.Key_QuoteDbl: '"', Qt.Key_Apostrophe: '\''}[key]
-        
+
         line_text = self.get_text('sol', 'eol')
         line_to_cursor = self.get_text('sol', 'cursor')
         cursor = self.textCursor()
@@ -2267,59 +2428,64 @@ class CodeEditor(TextEditBaseWidget):
         """Setup context menu"""
         self.undo_action = create_action(self, _("Undo"),
                            shortcut=keybinding('Undo'),
-                           icon=get_icon('undo.png'), triggered=self.undo)
+                           icon=ima.icon('undo'), triggered=self.undo)
         self.redo_action = create_action(self, _("Redo"),
                            shortcut=keybinding('Redo'),
-                           icon=get_icon('redo.png'), triggered=self.redo)
+                           icon=ima.icon('redo'), triggered=self.redo)
         self.cut_action = create_action(self, _("Cut"),
                            shortcut=keybinding('Cut'),
-                           icon=get_icon('editcut.png'), triggered=self.cut)
+                           icon=ima.icon('editcut'), triggered=self.cut)
         self.copy_action = create_action(self, _("Copy"),
                            shortcut=keybinding('Copy'),
-                           icon=get_icon('editcopy.png'), triggered=self.copy)
-        paste_action = create_action(self, _("Paste"),
+                           icon=ima.icon('editcopy'), triggered=self.copy)
+        self.paste_action = create_action(self, _("Paste"),
                            shortcut=keybinding('Paste'),
-                           icon=get_icon('editpaste.png'), triggered=self.paste)
-        self.delete_action = create_action(self, _("Delete"),
-                           shortcut=keybinding('Delete'),
-                           icon=get_icon('editdelete.png'),
-                           triggered=self.delete)
+                           icon=ima.icon('editpaste'), triggered=self.paste)
         selectall_action = create_action(self, _("Select All"),
                            shortcut=keybinding('SelectAll'),
-                           icon=get_icon('selectall.png'),
+                           icon=ima.icon('selectall'),
                            triggered=self.selectAll)
         toggle_comment_action = create_action(self,
-                           _("Comment")+"/"+_("Uncomment"),
-                           icon=get_icon("comment.png"),
-                           triggered=self.toggle_comment)
+                                _("Comment")+"/"+_("Uncomment"),
+                                icon=ima.icon('comment'),
+                                triggered=self.toggle_comment)
         self.clear_all_output_action = create_action(self,
-                           _("Clear all ouput"), icon='ipython_console.png',
+                           _("Clear all ouput"), icon=ima.icon('ipython_console'),
                            triggered=self.clear_all_output)
         self.ipynb_convert_action = create_action(self,
                                                _("Convert to Python script"),
                                                triggered=self.convert_notebook,
-                                               icon='python.png')
+                                               icon=ima.icon('python'))
         self.gotodef_action = create_action(self, _("Go to definition"),
                                    triggered=self.go_to_definition_from_cursor)
+        self.run_cell_action = create_action(self,
+                        _("Run cell"),
+                        icon=ima.icon('run_cell'),
+                        triggered=lambda: self.run_cell.emit())
+        self.run_cell_and_advance_action = create_action(self,
+                        _("Run cell and advance"),
+                        icon=ima.icon('run_cell'),
+                        triggered=lambda: self.run_cell_and_advance.emit())
         self.run_selection_action = create_action(self,
                         _("Run &selection or current line"),
-                        icon='run_selection.png',
-                        triggered=lambda: self.emit(SIGNAL('run_selection()')))
+                        icon=ima.icon('run_selection'),
+                        triggered=lambda: self.run_selection.emit())
         zoom_in_action = create_action(self, _("Zoom in"),
-                      QKeySequence(QKeySequence.ZoomIn), icon='zoom_in.png',
-                      triggered=lambda: self.emit(SIGNAL('zoom_in()')))
+                      QKeySequence(QKeySequence.ZoomIn), icon=ima.icon('zoom_in'),
+                      triggered=lambda: self.zoom_in.emit())
         zoom_out_action = create_action(self, _("Zoom out"),
-                      QKeySequence(QKeySequence.ZoomOut), icon='zoom_out.png',
-                      triggered=lambda: self.emit(SIGNAL('zoom_out()')))
+                      QKeySequence(QKeySequence.ZoomOut), icon=ima.icon('zoom_out'),
+                      triggered=lambda: self.zoom_out.emit())
         zoom_reset_action = create_action(self, _("Zoom reset"),
                       QKeySequence("Ctrl+0"),
-                      triggered=lambda: self.emit(SIGNAL('zoom_reset()')))
+                      triggered=lambda: self.zoom_reset.emit())
         self.menu = QMenu(self)
-        actions_1 = [self.undo_action, self.redo_action, None, self.cut_action,
-                     self.copy_action, paste_action, self.delete_action, None]
-        actions_2 = [selectall_action, None, zoom_in_action, zoom_out_action,
-                     zoom_reset_action, None, toggle_comment_action, None,
-                     self.run_selection_action, self.gotodef_action]
+        actions_1 = [self.run_cell_action, self.run_cell_and_advance_action,
+                     self.run_selection_action, self.gotodef_action, None,
+                     self.undo_action, self.redo_action, None, self.cut_action,
+                     self.copy_action, self.paste_action, selectall_action]
+        actions_2 = [None, zoom_in_action, zoom_out_action, zoom_reset_action,
+                     None, toggle_comment_action]
         if nbformat is not None:
             nb_actions = [self.clear_all_output_action,
                           self.ipynb_convert_action, None]
@@ -2327,8 +2493,8 @@ class CodeEditor(TextEditBaseWidget):
             add_actions(self.menu, actions)
         else:
             actions = actions_1 + actions_2
-            add_actions(self.menu, actions) 
-            
+            add_actions(self.menu, actions)
+
         # Read-only context-menu
         self.readonly_menu = QMenu(self)
         add_actions(self.readonly_menu,
@@ -2345,6 +2511,30 @@ class CodeEditor(TextEditBaseWidget):
             self.__clear_occurences()
         if QToolTip.isVisible():
             self.hide_tooltip_if_necessary(key)
+
+        # Handle the Qt Builtin key sequences
+        checks = [('SelectAll', 'Select All'),
+                  ('Copy', 'Copy'),
+                  ('Cut', 'Cut'),
+                  ('Paste', 'Paste')]
+
+        for qname, name in checks:
+            seq = getattr(QKeySequence, qname)
+            sc = get_shortcut('editor', name)
+            default = QKeySequence(seq).toString()
+            if event == seq and sc != default:
+                # if we have overridden it, call our action
+                for shortcut in self.shortcuts:
+                    qsc, name, keystr = shortcut.data
+                    if keystr == default:
+                        qsc.activated.emit()
+                        event.ignore()
+                        return
+
+                # otherwise, pass it on to parent
+                event.ignore()
+                return
+
         if key in (Qt.Key_Enter, Qt.Key_Return):
             if not shift and not ctrl:
                 if self.add_colons_enabled and self.is_python_like() and \
@@ -2359,9 +2549,9 @@ class CodeEditor(TextEditBaseWidget):
                     TextEditBaseWidget.keyPressEvent(self, event)
                     self.fix_indent(comment_or_string=cmt_or_str)
             elif shift:
-                self.emit(SIGNAL('run_cell_and_advance()'))
+                self.run_cell_and_advance.emit()
             elif ctrl:
-                self.emit(SIGNAL('run_cell()'))
+                self.run_cell.emit()
         elif key == Qt.Key_Insert and not shift and not ctrl:
             self.setOverwriteMode(not self.overwriteMode())
         elif key == Qt.Key_Backspace and not shift and not ctrl:
@@ -2403,25 +2593,15 @@ class CodeEditor(TextEditBaseWidget):
         elif key == Qt.Key_Home:
             self.stdkey_home(shift, ctrl)
         elif key == Qt.Key_End:
-            # See Issue 495: on MacOS X, it is necessary to redefine this 
+            # See Issue 495: on MacOS X, it is necessary to redefine this
             # basic action which should have been implemented natively
             self.stdkey_end(shift, ctrl)
         elif text == '(' and not self.has_selected_text():
             self.hide_completion_widget()
-            position = self.get_position('cursor')
-            s_trailing_text = self.get_text('cursor', 'eol').strip()
-            if self.close_parentheses_enabled and \
-              (len(s_trailing_text) == 0 or \
-              s_trailing_text[0] in (',', ')', ']', '}')):
-                self.insert_text('()')
-                cursor = self.textCursor()
-                cursor.movePosition(QTextCursor.PreviousCharacter)
-                self.setTextCursor(cursor)
+            if self.close_parentheses_enabled:
+                self.handle_close_parentheses(text)
             else:
                 self.insert_text(text)
-            if self.is_python_like() and self.get_text('sol', 'cursor') and \
-              self.calltips:
-                self.emit(SIGNAL('show_object_info(int)'), position)
         elif text in ('[', '{') and not self.has_selected_text() \
           and self.close_parentheses_enabled:
             s_trailing_text = self.get_text('cursor', 'eol').strip()
@@ -2490,6 +2670,22 @@ class CodeEditor(TextEditBaseWidget):
             if self.is_completion_widget_visible() and text:
                 self.completion_text += text
 
+    def handle_close_parentheses(self, text):
+        if not self.close_parentheses_enabled:
+            return
+        position = self.get_position('cursor')
+        rest = self.get_text('cursor', 'eol').rstrip()
+        if not rest or rest[0] in (',', ')', ']', '}'):
+            self.insert_text('()')
+            cursor = self.textCursor()
+            cursor.movePosition(QTextCursor.PreviousCharacter)
+            self.setTextCursor(cursor)
+        else:
+            self.insert_text(text)
+        if self.is_python_like() and self.get_text('sol', 'cursor') and \
+                self.calltips:
+            self.sig_show_object_info.emit(position)
+
     def mouseMoveEvent(self, event):
         """Underline words when pressing <CONTROL>"""
         if self.has_selected_text():
@@ -2526,7 +2722,8 @@ class CodeEditor(TextEditBaseWidget):
             self.__cursor_changed = False
             self.clear_extra_selections('ctrl_click')
         TextEditBaseWidget.leaveEvent(self, event)
-        
+
+    @Slot()
     def go_to_definition_from_cursor(self, cursor=None):
         """Go to definition from cursor instance (QTextCursor)"""
         if not self.go_to_definition_enabled:
@@ -2541,7 +2738,7 @@ class CodeEditor(TextEditBaseWidget):
             cursor.select(QTextCursor.WordUnderCursor)
             text = to_text_string(cursor.selectedText())
         if not text is None:
-            self.emit(SIGNAL("go_to_definition(int)"), position)
+            self.go_to_definition.emit(position)
 
     def mousePressEvent(self, event):
         """Reimplement Qt method"""
@@ -2558,21 +2755,23 @@ class CodeEditor(TextEditBaseWidget):
         nonempty_selection = self.has_selected_text()
         self.copy_action.setEnabled(nonempty_selection)
         self.cut_action.setEnabled(nonempty_selection)
-        self.delete_action.setEnabled(nonempty_selection)
-        self.clear_all_output_action.setVisible(self.is_json())
-        self.ipynb_convert_action.setVisible(self.is_json())
-        self.run_selection_action.setEnabled(nonempty_selection)
+        self.clear_all_output_action.setVisible(self.is_json() and \
+                                                nbformat is not None)
+        self.ipynb_convert_action.setVisible(self.is_json() and \
+                                             nbformat is not None)
+        self.run_cell_action.setVisible(self.is_python())
+        self.run_cell_and_advance_action.setVisible(self.is_python())
         self.run_selection_action.setVisible(self.is_python())
         self.gotodef_action.setVisible(self.go_to_definition_enabled \
-                                       and self.is_python_like())   
-        
+                                       and self.is_python_like())
+
         # Code duplication go_to_definition_from_cursor and mouse_move_event
         cursor = self.textCursor()
         text = to_text_string(cursor.selectedText())
         if len(text) == 0:
             cursor.select(QTextCursor.WordUnderCursor)
             text = to_text_string(cursor.selectedText())
-           
+
         self.undo_action.setEnabled( self.document().isUndoAvailable())
         self.redo_action.setEnabled( self.document().isRedoAvailable())
         menu = self.menu
@@ -2638,7 +2837,7 @@ class CodeEditor(TextEditBaseWidget):
             pen.setStyle(Qt.SolidLine)
             pen.setBrush(cell_line_color)
             painter.setPen(pen)
-    
+
             for top, line_number, block in self.visible_blocks:
                 if self.is_cell_separator(block):
                     painter.drawLine(4, top, self.width(), top)
@@ -2656,6 +2855,10 @@ class CodeEditor(TextEditBaseWidget):
         """
         return self.__visible_blocks
 
+    def is_editor(self):
+        return True
+
+
 #===============================================================================
 # CodeEditor's Printer
 #===============================================================================
@@ -2693,17 +2896,17 @@ class TestWidget(QSplitter):
         self.editor = CodeEditor(self)
         self.editor.setup_editor(linenumbers=True, markers=True, tab_mode=False,
                                  font=QFont("Courier New", 10),
-                                 show_blanks=True, color_scheme='Pydev')
+                                 show_blanks=True, color_scheme='Zenburn')
         self.addWidget(self.editor)
         from spyderlib.widgets.editortools import OutlineExplorerWidget
         self.classtree = OutlineExplorerWidget(self)
         self.addWidget(self.classtree)
-        self.connect(self.classtree, SIGNAL("edit_goto(QString,int,QString)"),
-                     lambda _fn, line, word: self.editor.go_to_line(line, word))
+        self.classtree.edit_goto.connect(
+                    lambda _fn, line, word: self.editor.go_to_line(line, word))
         self.setStretchFactor(0, 4)
         self.setStretchFactor(1, 1)
-        self.setWindowIcon(get_icon('spyder.svg'))
-
+        self.setWindowIcon(ima.icon('spyder'))
+ 
     def load(self, filename):
         self.editor.set_text_from_file(filename)
         self.setWindowTitle("%s - %s (%s)" % (_("Editor"),
@@ -2711,32 +2914,28 @@ class TestWidget(QSplitter):
                                               osp.dirname(filename)))
         self.classtree.set_current_editor(self.editor, filename, False, False)
 
+
 def test(fname):
     from spyderlib.utils.qthelpers import qapplication
-    app = qapplication()
-    app.setStyle('Plastique')
+    app = qapplication(test_time=5)
     win = TestWidget(None)
     win.show()
     win.load(fname)
-    win.resize(1000, 800)
+    win.resize(900, 700)
 
     from spyderlib.utils.codeanalysis import (check_with_pyflakes,
                                               check_with_pep8)
     source_code = to_text_string(win.editor.toPlainText())
-    res = check_with_pyflakes(source_code, fname)#+\
-#          check_with_pep8(source_code, fname)
-    win.editor.process_code_analysis(res)
+    results = check_with_pyflakes(source_code, fname) + \
+              check_with_pep8(source_code, fname)
+    win.editor.process_code_analysis(results)
 
     sys.exit(app.exec_())
 
+
 if __name__ == '__main__':
     if len(sys.argv) > 1:
         fname = sys.argv[1]
     else:
         fname = __file__
-#        fname = r"d:\Python\scintilla\src\LexCPP.cxx"
-#        fname = r"C:\Python26\Lib\pdb.py"
-#        fname = r"C:\Python26\Lib\ssl.py"
-#        fname = r"D:\Python\testouille.py"
-#        fname = r"C:\Python26\Lib\pydoc.py"
     test(fname)
diff --git a/spyderlib/widgets/sourcecode/kill_ring.py b/spyderlib/widgets/sourcecode/kill_ring.py
new file mode 100644
index 0000000..6698571
--- /dev/null
+++ b/spyderlib/widgets/sourcecode/kill_ring.py
@@ -0,0 +1,132 @@
+""" A generic Emacs-style kill ring, as well as a Qt-specific version.
+Copyright (c) 2001-2015, IPython Development Team
+Copyright (c) 2015-, Jupyter Development Team
+All rights reserved.
+"""
+#-----------------------------------------------------------------------------
+# Imports
+#-----------------------------------------------------------------------------
+
+# System library imports
+from spyderlib.qt import QtCore, QtGui
+
+#-----------------------------------------------------------------------------
+# Classes
+#-----------------------------------------------------------------------------
+
+class KillRing(object):
+    """ A generic Emacs-style kill ring.
+    """
+
+    def __init__(self):
+        self.clear()
+
+    def clear(self):
+        """ Clears the kill ring.
+        """
+        self._index = -1
+        self._ring = []
+
+    def kill(self, text):
+        """ Adds some killed text to the ring.
+        """
+        self._ring.append(text)
+
+    def yank(self):
+        """ Yank back the most recently killed text.
+
+        Returns
+        -------
+        A text string or None.
+        """
+        self._index = len(self._ring)
+        return self.rotate()
+
+    def rotate(self):
+        """ Rotate the kill ring, then yank back the new top.
+
+        Returns
+        -------
+        A text string or None.
+        """
+        self._index -= 1
+        if self._index >= 0:
+            return self._ring[self._index]
+        return None
+
+
+class QtKillRing(QtCore.QObject):
+    """ A kill ring attached to Q[Plain]TextEdit.
+    """
+
+    #--------------------------------------------------------------------------
+    # QtKillRing interface
+    #--------------------------------------------------------------------------
+
+    def __init__(self, text_edit):
+        """ Create a kill ring attached to the specified Qt text edit.
+        """
+        assert isinstance(text_edit, (QtGui.QTextEdit, QtGui.QPlainTextEdit))
+        super(QtKillRing, self).__init__()
+
+        self._ring = KillRing()
+        self._prev_yank = None
+        self._skip_cursor = False
+        self._text_edit = text_edit
+
+        text_edit.cursorPositionChanged.connect(self._cursor_position_changed)
+
+    def clear(self):
+        """ Clears the kill ring.
+        """
+        self._ring.clear()
+        self._prev_yank = None
+
+    def kill(self, text):
+        """ Adds some killed text to the ring.
+        """
+        self._ring.kill(text)
+
+    def kill_cursor(self, cursor):
+        """ Kills the text selected by the give cursor.
+        """
+        text = cursor.selectedText()
+        if text:
+            cursor.removeSelectedText()
+            self.kill(text)
+
+    def yank(self):
+        """ Yank back the most recently killed text.
+        """
+        text = self._ring.yank()
+        if text:
+            self._skip_cursor = True
+            cursor = self._text_edit.textCursor()
+            cursor.insertText(text)
+            self._prev_yank = text
+
+    def rotate(self):
+        """ Rotate the kill ring, then yank back the new top.
+        """
+        if self._prev_yank:
+            text = self._ring.rotate()
+            if text:
+                self._skip_cursor = True
+                cursor = self._text_edit.textCursor()
+                cursor.movePosition(QtGui.QTextCursor.Left,
+                                    QtGui.QTextCursor.KeepAnchor,
+                                    n=len(self._prev_yank))
+                cursor.insertText(text)
+                self._prev_yank = text
+
+    #--------------------------------------------------------------------------
+    # Protected interface
+    #--------------------------------------------------------------------------
+
+    #------ Signal handlers ----------------------------------------------------
+
+    def _cursor_position_changed(self):
+        if self._skip_cursor:
+            self._skip_cursor = False
+        else:
+            self._prev_yank = None
diff --git a/spyderlib/widgets/status.py b/spyderlib/widgets/status.py
index 12bd4f0..e082e3d 100644
--- a/spyderlib/widgets/status.py
+++ b/spyderlib/widgets/status.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2012 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -9,11 +9,11 @@
 import os
 
 from spyderlib.qt.QtGui import QWidget, QHBoxLayout, QLabel
-from spyderlib.qt.QtCore import QTimer, SIGNAL
+from spyderlib.qt.QtCore import QTimer
 
 # Local import
-from spyderlib.baseconfig import _
-from spyderlib.guiconfig import get_font
+from spyderlib.config.base import _
+from spyderlib.config.gui import get_font
 from spyderlib.py3compat import to_text_string
 from spyderlib import dependencies
 
@@ -56,7 +56,7 @@ class BaseTimerStatus(StatusBarWidget):
         layout.addSpacing(20)
         if self.is_supported():
             self.timer = QTimer()
-            self.connect(self.timer, SIGNAL('timeout()'), self.update_label)
+            self.timer.timeout.connect(self.update_label)
             self.timer.start(2000)
         else:
             self.timer = None
@@ -184,7 +184,7 @@ class CursorPositionStatus(StatusBarWidget):
 def test():
     from spyderlib.qt.QtGui import QMainWindow
     from spyderlib.utils.qthelpers import qapplication
-    app = qapplication()
+    app = qapplication(test_time=5)
     win = QMainWindow()
     win.setWindowTitle("Status widgets test")
     win.resize(900, 300)
@@ -196,6 +196,7 @@ def test():
         swidgets.append(swidget)
     win.show()
     app.exec_()
-    
+
+
 if __name__ == "__main__":
     test()
diff --git a/spyderlib/widgets/tabs.py b/spyderlib/widgets/tabs.py
index 1cb245b..1fd770d 100644
--- a/spyderlib/widgets/tabs.py
+++ b/spyderlib/widgets/tabs.py
@@ -13,22 +13,25 @@
 
 from spyderlib.qt.QtGui import (QTabWidget, QMenu, QDrag, QApplication,
                                 QTabBar, QWidget, QHBoxLayout)
-from spyderlib.qt.QtCore import SIGNAL, Qt, QPoint, QMimeData, QByteArray
+from spyderlib.qt.QtCore import Signal, Qt, QPoint, QMimeData, QByteArray
+import spyderlib.utils.icon_manager as ima
 
 import os.path as osp
 import sys
 
 # Local imports
-from spyderlib.baseconfig import _
-from spyderlib.guiconfig import new_shortcut
+from spyderlib.config.base import _
+from spyderlib.config.gui import new_shortcut
 from spyderlib.utils.misc import get_common_path
 from spyderlib.utils.qthelpers import (add_actions, create_toolbutton,
-                                       create_action, get_icon)
+                                       create_action)
 from spyderlib.py3compat import PY2, to_text_string
 
 
 class TabBar(QTabBar):
     """Tabs base class with drag and drop support"""
+    sig_move_tab = Signal((int, int), (str, int, int))
+    
     def __init__(self, parent, ancestor):
         QTabBar.__init__(self, parent)
         self.ancestor = ancestor
@@ -96,18 +99,20 @@ class TabBar(QTabBar):
             # depend on the platform: long for 64bit, int for 32bit. Replacing 
             # by long all the time is not working on some 32bit platforms 
             # (see Issue 1094, Issue 1098)
-            self.emit(SIGNAL("move_tab(QString,int,int)"), 
-                      tabwidget_from, index_from, index_to)
+            self.sig_move_tab[(str, int, int)].emit(tabwidget_from, index_from,
+                                                    index_to)
 
             event.acceptProposedAction()
         elif index_from != index_to:
-            self.emit(SIGNAL("move_tab(int,int)"), index_from, index_to)
+            self.sig_move_tab.emit(index_from, index_to)
             event.acceptProposedAction()
         QTabBar.dropEvent(self, event)
         
         
 class BaseTabs(QTabWidget):
     """TabWidget with context menu and corner widgets"""
+    sig_close_tab = Signal(int)
+    
     def __init__(self, parent, actions=None, menu=None,
                  corner_widgets=None, menu_use_tooltips=False):
         QTabWidget.__init__(self, parent)
@@ -133,13 +138,12 @@ class BaseTabs(QTabWidget):
         corner_widgets.setdefault(Qt.TopLeftCorner, [])
         corner_widgets.setdefault(Qt.TopRightCorner, [])
         self.browse_button = create_toolbutton(self,
-                                          icon=get_icon("browse_tab.png"),
+                                          icon=ima.icon('browse_tab'),
                                           tip=_("Browse tabs"))
         self.browse_tabs_menu = QMenu(self)
         self.browse_button.setMenu(self.browse_tabs_menu)
         self.browse_button.setPopupMode(self.browse_button.InstantPopup)
-        self.connect(self.browse_tabs_menu, SIGNAL("aboutToShow()"),
-                     self.update_browse_tabs_menu)
+        self.browse_tabs_menu.aboutToShow.connect(self.update_browse_tabs_menu)
         corner_widgets[Qt.TopLeftCorner] += [self.browse_button]
 
         self.set_corner_widgets(corner_widgets)
@@ -222,7 +226,7 @@ class BaseTabs(QTabWidget):
         if event.button() == Qt.MidButton:
             index = self.tabBar().tabAt(event.pos())
             if index >= 0:
-                self.emit(SIGNAL("close_tab(int)"), index)
+                self.sig_close_tab.emit(index)
                 event.accept()
                 return
         QTabWidget.mousePressEvent(self, event)
@@ -234,11 +238,17 @@ class BaseTabs(QTabWidget):
         handled = False
         if ctrl and self.count() > 0:
             index = self.currentIndex()
-            if key == Qt.Key_PageUp and index > 0:
-                self.setCurrentIndex(index-1)
+            if key == Qt.Key_PageUp:
+                if index > 0:
+                    self.setCurrentIndex(index - 1)
+                else:
+                    self.setCurrentIndex(self.count() - 1)
                 handled = True
-            elif key == Qt.Key_PageDown and index < self.count()-1:
-                self.setCurrentIndex(index+1)
+            elif key == Qt.Key_PageDown:
+                if index < self.count() - 1:
+                    self.setCurrentIndex(index + 1)
+                else:
+                    self.setCurrentIndex(0)
                 handled = True
         if not handled:
             QTabWidget.keyPressEvent(self, event)
@@ -248,37 +258,42 @@ class BaseTabs(QTabWidget):
         None -> tabs are not closable"""
         state = func is not None
         if state:
-            self.connect(self, SIGNAL("close_tab(int)"), func)
+            self.sig_close_tab.connect(func)
         try:
             # Assuming Qt >= 4.5
             QTabWidget.setTabsClosable(self, state)
-            self.connect(self, SIGNAL("tabCloseRequested(int)"), func)
+            self.tabCloseRequested.connect(func)
         except AttributeError:
             # Workaround for Qt < 4.5
             close_button = create_toolbutton(self, triggered=func,
-                                             icon=get_icon("fileclose.png"),
+                                             icon=ima.icon('fileclose'),
                                              tip=_("Close current tab"))
             self.setCornerWidget(close_button if state else None)
 
         
 class Tabs(BaseTabs):
     """BaseTabs widget with movable tabs and tab navigation shortcuts"""
+    # Signals
+    move_data = Signal(int, int)
+    move_tab_finished = Signal()
+    sig_move_tab = Signal(str, str, int, int)
+    
     def __init__(self, parent, actions=None, menu=None,
                  corner_widgets=None, menu_use_tooltips=False):
         BaseTabs.__init__(self, parent, actions, menu,
                           corner_widgets, menu_use_tooltips)
         tab_bar = TabBar(self, parent)
-        self.connect(tab_bar, SIGNAL('move_tab(int,int)'), self.move_tab)
-        self.connect(tab_bar, SIGNAL('move_tab(QString,int,int)'),
-                     self.move_tab_from_another_tabwidget)
+        tab_bar.sig_move_tab.connect(self.move_tab)
+        tab_bar.sig_move_tab[(str, int, int)].connect(
+                                          self.move_tab_from_another_tabwidget)
         self.setTabBar(tab_bar)
         
         new_shortcut("Ctrl+Tab", parent, lambda: self.tab_navigate(1))
         new_shortcut("Shift+Ctrl+Tab", parent, lambda: self.tab_navigate(-1))
-        new_shortcut("Ctrl+W", parent, lambda: self.emit(SIGNAL("close_tab(int)"),
-                                                         self.currentIndex()))
-        new_shortcut("Ctrl+F4", parent, lambda: self.emit(SIGNAL("close_tab(int)"),
-                                                          self.currentIndex()))
+        new_shortcut("Ctrl+W", parent,
+                     lambda: self.sig_close_tab.emit(self.currentIndex()))
+        new_shortcut("Ctrl+F4", parent,
+                     lambda: self.sig_close_tab.emit(self.currentIndex()))
         
     def tab_navigate(self, delta=1):
         """Ctrl+Tab"""
@@ -292,7 +307,7 @@ class Tabs(BaseTabs):
 
     def move_tab(self, index_from, index_to):
         """Move tab inside a tabwidget"""
-        self.emit(SIGNAL('move_data(int,int)'), index_from, index_to)
+        self.move_data.emit(index_from, index_to)
 
         tip, text = self.tabToolTip(index_from), self.tabText(index_from)
         icon, widget = self.tabIcon(index_from), self.widget(index_from)
@@ -303,8 +318,7 @@ class Tabs(BaseTabs):
         self.setTabToolTip(index_to, tip)
         
         self.setCurrentWidget(current_widget)
-        
-        self.emit(SIGNAL('move_tab_finished()'))
+        self.move_tab_finished.emit()
 
     def move_tab_from_another_tabwidget(self, tabwidget_from,
                                         index_from, index_to):
@@ -314,5 +328,5 @@ class Tabs(BaseTabs):
         # depend on the platform: long for 64bit, int for 32bit. Replacing 
         # by long all the time is not working on some 32bit platforms 
         # (see Issue 1094, Issue 1098)
-        self.emit(SIGNAL('move_tab(QString,QString,int,int)'),
-                  tabwidget_from, str(id(self)), index_from, index_to)
+        self.sig_move_tab.emit(tabwidget_from, str(id(self)), index_from,
+                               index_to)
diff --git a/spyderlib/widgets/variableexplorer/__init__.py b/spyderlib/widgets/variableexplorer/__init__.py
new file mode 100644
index 0000000..77e6402
--- /dev/null
+++ b/spyderlib/widgets/variableexplorer/__init__.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2009- The Spyder Development team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+"""
+spyderlib.widgets.variableexplorer
+========================
+
+Variable Explorer related widgets
+"""
diff --git a/spyderlib/widgets/arrayeditor.py b/spyderlib/widgets/variableexplorer/arrayeditor.py
similarity index 75%
rename from spyderlib/widgets/arrayeditor.py
rename to spyderlib/widgets/variableexplorer/arrayeditor.py
index b0089a8..bd8f772 100644
--- a/spyderlib/widgets/arrayeditor.py
+++ b/spyderlib/widgets/variableexplorer/arrayeditor.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2012 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -20,19 +20,24 @@ from spyderlib.qt.QtGui import (QHBoxLayout, QColor, QTableView, QItemDelegate,
                                 QDoubleValidator, QDialog, QDialogButtonBox,
                                 QMessageBox, QPushButton, QInputDialog, QMenu,
                                 QApplication, QKeySequence, QLabel, QComboBox,
-                                QSpinBox, QStackedWidget, QWidget, QVBoxLayout)
-from spyderlib.qt.QtCore import (Qt, QModelIndex, QAbstractTableModel, SIGNAL,
-                                 SLOT)
+                                QSpinBox, QStackedWidget, QWidget, QVBoxLayout,
+                                QAbstractItemDelegate)
+from spyderlib.qt.QtCore import (Qt, QModelIndex, QAbstractTableModel, Slot,
+                                 QItemSelection, QItemSelectionRange)
+
 from spyderlib.qt.compat import to_qvariant, from_qvariant
+import spyderlib.utils.icon_manager as ima
 
 import numpy as np
 
 # Local imports
-from spyderlib.baseconfig import _
-from spyderlib.guiconfig import get_font, new_shortcut
+from spyderlib.config.base import _
+from spyderlib.config.gui import get_font, new_shortcut
 from spyderlib.utils.qthelpers import (add_actions, create_action, keybinding,
-                                       qapplication, get_icon)
-from spyderlib.py3compat import io, to_text_string, is_text_string
+                                       qapplication)
+from spyderlib.py3compat import (PY3, io, to_text_string, is_text_string,
+                                 is_binary_string, to_binary_string, is_string)
+
 
 # Note: string and unicode data types will be formatted with '%s' (see below)
 SUPPORTED_FORMATS = {
@@ -52,6 +57,7 @@ SUPPORTED_FORMATS = {
                      'complex192': '%r',
                      'complex256': '%r',
                      'byte': '%d',
+                     'bytes8': '%s',
                      'short': '%d',
                      'intc': '%d',
                      'int_': '%d',
@@ -82,27 +88,35 @@ LARGE_NROWS = 1e5
 LARGE_COLS = 60
 
 
+#==============================================================================
+# Utility functions
+#==============================================================================
 def is_float(dtype):
     """Return True if datatype dtype is a float kind"""
     return ('float' in dtype.name) or dtype.name in ['single', 'double']
 
+
 def is_number(dtype):
     """Return True is datatype dtype is a number kind"""
     return is_float(dtype) or ('int' in dtype.name) or ('long' in dtype.name) \
            or ('short' in dtype.name)
 
+
 def get_idx_rect(index_list):
     """Extract the boundaries from a list of indexes"""
     rows, cols = list(zip(*[(i.row(), i.column()) for i in index_list]))
     return ( min(rows), max(rows), min(cols), max(cols) )
 
 
+#==============================================================================
+# Main classes
+#==============================================================================
 class ArrayModel(QAbstractTableModel):
     """Array Editor Table Model"""
-    
+
     ROWS_TO_LOAD = 500
     COLS_TO_LOAD = 40
-    
+
     def __init__(self, data, format="%.3f", xlabels=None, ylabels=None,
                  readonly=False, parent=None):
         QAbstractTableModel.__init__(self)
@@ -135,8 +149,8 @@ class ArrayModel(QAbstractTableModel):
         size = self.total_rows * self.total_cols
         
         try:
-            self.vmin = self.color_func(data).min()
-            self.vmax = self.color_func(data).max()
+            self.vmin = np.nanmin(self.color_func(data))
+            self.vmax = np.nanmax(self.color_func(data))
             if self.vmax == self.vmin:
                 self.vmin -= 1
             self.hue0 = huerange[0]
@@ -235,6 +249,11 @@ class ArrayModel(QAbstractTableModel):
         if not index.isValid():
             return to_qvariant()
         value = self.get_value(index)
+        if is_binary_string(value):
+            try:
+                value = to_text_string(value, 'utf8')
+            except:
+                pass
         if role == Qt.DisplayRole:
             if value is np.ma.masked:
                 return ''
@@ -242,10 +261,10 @@ class ArrayModel(QAbstractTableModel):
                 return to_qvariant(self._format % value)
         elif role == Qt.TextAlignmentRole:
             return to_qvariant(int(Qt.AlignCenter|Qt.AlignVCenter))
-        elif role == Qt.BackgroundColorRole and self.bgcolor_enabled\
-             and value is not np.ma.masked:
+        elif role == Qt.BackgroundColorRole and self.bgcolor_enabled \
+          and value is not np.ma.masked:
             hue = self.hue0+\
-                  self.dhue*(self.vmax-self.color_func(value))\
+                  self.dhue*(self.vmax-self.color_func(value)) \
                   /(self.vmax-self.vmin)
             hue = float(np.abs(hue))
             color = QColor.fromHsvF(hue, self.sat, self.val, self.alp)
@@ -261,14 +280,15 @@ class ArrayModel(QAbstractTableModel):
         i = index.row()
         j = index.column()
         value = from_qvariant(value, str)
-        if self._data.dtype.name == "bool":
+        dtype = self._data.dtype.name
+        if dtype == "bool":
             try:
                 val = bool(float(value))
             except ValueError:
                 val = value.lower() == "true"
-        elif self._data.dtype.name.startswith("string"):
-            val = str(value)
-        elif self._data.dtype.name.startswith("unicode"):
+        elif dtype.startswith("string") or dtype.startswith("bytes"):
+            val = to_binary_string(value, 'utf8')
+        elif dtype.startswith("unicode") or dtype.startswith("str"):
             val = to_text_string(value)
         else:
             if value.lower().startswith('e') or value.lower().endswith('e'):
@@ -291,14 +311,14 @@ class ArrayModel(QAbstractTableModel):
         
         # Add change to self.changes
         self.changes[(i, j)] = val
-        self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
-                  index, index)
-        if val > self.vmax:
-            self.vmax = val
-        if val < self.vmin:
-            self.vmin = val
+        self.dataChanged.emit(index, index)
+        if not is_string(val):
+            if val > self.vmax:
+                self.vmax = val
+            if val < self.vmin:
+                self.vmin = val
         return True
-    
+
     def flags(self, index):
         """Set editable flag"""
         if not index.isValid():
@@ -316,6 +336,10 @@ class ArrayModel(QAbstractTableModel):
         else:
             return to_qvariant(labels[section])
 
+    def reset(self):
+        self.beginResetModel()
+        self.endResetModel()
+
 
 class ArrayDelegate(QItemDelegate):
     """Array Editor Item Delegate"""
@@ -337,15 +361,21 @@ class ArrayDelegate(QItemDelegate):
             editor.setAlignment(Qt.AlignCenter)
             if is_number(self.dtype):
                 editor.setValidator(QDoubleValidator(editor))
-            self.connect(editor, SIGNAL("returnPressed()"),
-                         self.commitAndCloseEditor)
+            editor.returnPressed.connect(self.commitAndCloseEditor)
             return editor
 
     def commitAndCloseEditor(self):
         """Commit and close editor"""
         editor = self.sender()
-        self.emit(SIGNAL("commitData(QWidget*)"), editor)
-        self.emit(SIGNAL("closeEditor(QWidget*)"), editor)
+        # Avoid a segfault with PyQt5. Variable value won't be changed
+        # but at least Spyder won't crash. It seems generated by a
+        # bug in sip. See
+        # http://comments.gmane.org/gmane.comp.python.pyqt-pykde/26544
+        try:
+            self.commitData.emit(editor)
+        except AttributeError:
+            pass
+        self.closeEditor.emit(editor, QAbstractItemDelegate.NoHint)
 
     def setEditorData(self, editor, index):
         """Set editor widget's data"""
@@ -368,16 +398,45 @@ class ArrayView(QTableView):
         self.shape = shape
         self.menu = self.setup_menu()
         new_shortcut(QKeySequence.Copy, self, self.copy)
-        self.connect(self.horizontalScrollBar(), SIGNAL("valueChanged(int)"),
-                     lambda val: self.load_more_data(val, columns=True))
-        self.connect(self.verticalScrollBar(), SIGNAL("valueChanged(int)"),
-                     lambda val: self.load_more_data(val, rows=True))
+        self.horizontalScrollBar().valueChanged.connect(
+                            lambda val: self.load_more_data(val, columns=True))
+        self.verticalScrollBar().valueChanged.connect(
+                               lambda val: self.load_more_data(val, rows=True))
     
     def load_more_data(self, value, rows=False, columns=False):
+        old_selection = self.selectionModel().selection()
+        old_rows_loaded = old_cols_loaded = None
+        
         if rows and value == self.verticalScrollBar().maximum():
+            old_rows_loaded = self.model().rows_loaded
             self.model().fetch_more(rows=rows)
+            
         if columns and value == self.horizontalScrollBar().maximum():
+            old_cols_loaded = self.model().cols_loaded
             self.model().fetch_more(columns=columns)
+            
+        if old_rows_loaded is not None or old_cols_loaded is not None:
+            # if we've changed anything, update selection
+            new_selection = QItemSelection()
+            for part in old_selection:
+                top = part.top()
+                bottom = part.bottom()
+                if (old_rows_loaded is not None and 
+                    top == 0 and bottom == (old_rows_loaded-1)):
+                    # complete column selected (so expand it to match updated range)
+                    bottom = self.model().rows_loaded-1
+                left = part.left()
+                right = part.right()
+                if (old_cols_loaded is not None
+                    and left == 0 and right == (old_cols_loaded-1)):
+                    # compete row selected (so expand it to match updated range)
+                    right = self.model().cols_loaded-1
+                top_left = self.model().index(top, left)
+                bottom_right = self.model().index(bottom, right)
+                part = QItemSelectionRange(top_left, bottom_right)
+                new_selection.append(part)
+            self.selectionModel().select(new_selection, self.selectionModel().ClearAndSelect)
+                    
 
     def resize_to_contents(self):
         """Resize cells to contents"""
@@ -389,9 +448,9 @@ class ArrayView(QTableView):
 
     def setup_menu(self):
         """Setup context menu"""
-        self.copy_action = create_action(self, _( "Copy"),
-                                         shortcut=keybinding("Copy"),
-                                         icon=get_icon('editcopy.png'),
+        self.copy_action = create_action(self, _('Copy'),
+                                         shortcut=keybinding('Copy'),
+                                         icon=ima.icon('editcopy'),
                                          triggered=self.copy,
                                          context=Qt.WidgetShortcut)
         menu = QMenu(self)
@@ -412,16 +471,35 @@ class ArrayView(QTableView):
 
     def _sel_to_text(self, cell_range):
         """Copy an array portion to a unicode string"""
+        if not cell_range:
+            return
         row_min, row_max, col_min, col_max = get_idx_rect(cell_range)
+        if col_min == 0 and col_max == (self.model().cols_loaded-1):
+            # we've selected a whole column. It isn't possible to
+            # select only the first part of a column without loading more, 
+            # so we can treat it as intentional and copy the whole thing
+            col_max = self.model().total_cols-1
+        if row_min == 0 and row_max == (self.model().rows_loaded-1):
+            row_max = self.model().total_rows-1
+        
         _data = self.model().get_data()
-        output = io.StringIO()
-        np.savetxt(output,
-                  _data[row_min:row_max+1, col_min:col_max+1],
-                  delimiter='\t')
-        contents = output.getvalue()
+        if PY3:
+            output = io.BytesIO()
+        else:
+            output = io.StringIO()
+        try:
+            np.savetxt(output, _data[row_min:row_max+1, col_min:col_max+1],
+                       delimiter='\t')
+        except:
+            QMessageBox.warning(self, _("Warning"),
+                                _("It was not possible to copy values for "
+                                  "this array"))
+            return
+        contents = output.getvalue().decode('utf-8')
         output.close()
         return contents
-    
+
+    @Slot()
     def copy(self):
         """Copy text to clipboard"""
         cliptxt = self._sel_to_text( self.selectedIndexes() )
@@ -453,14 +531,14 @@ class ArrayEditorWidget(QWidget):
         # disable format button for int type
         btn.setEnabled(is_float(data.dtype))
         btn_layout.addWidget(btn)
-        self.connect(btn, SIGNAL("clicked()"), self.change_format)
+        btn.clicked.connect(self.change_format)
         btn = QPushButton(_( "Resize"))
         btn_layout.addWidget(btn)
-        self.connect(btn, SIGNAL("clicked()"), self.view.resize_to_contents)
+        btn.clicked.connect(self.view.resize_to_contents)
         bgcolor = QCheckBox(_( 'Background color'))
         bgcolor.setChecked(self.model.bgcolor_enabled)
         bgcolor.setEnabled(self.model.bgcolor_enabled)
-        self.connect(bgcolor, SIGNAL("stateChanged(int)"), self.model.bgcolor)
+        bgcolor.stateChanged.connect(self.model.bgcolor)
         btn_layout.addWidget(bgcolor)
         
         layout = QVBoxLayout()
@@ -528,16 +606,15 @@ class ArrayEditor(QDialog):
             self.error(_("Array is empty"))
             return False
         if data.ndim > 3:
-            self.error(_("Arrays with more than 3 dimensions "
-                               "are not supported"))
+            self.error(_("Arrays with more than 3 dimensions are not supported"))
             return False
         if xlabels is not None and len(xlabels) != self.data.shape[1]:
-            self.error(_("The 'xlabels' argument length "
-						 	   "do no match array column number"))
+            self.error(_("The 'xlabels' argument length do no match array "
+                         "column number"))
             return False
         if ylabels is not None and len(ylabels) != self.data.shape[0]:
-            self.error(_("The 'ylabels' argument length "
-							   "do no match array row number"))
+            self.error(_("The 'ylabels' argument length do no match array row "
+                         "number"))
             return False
         if not is_record_array:
             dtn = data.dtype.name
@@ -549,7 +626,7 @@ class ArrayEditor(QDialog):
         
         self.layout = QGridLayout()
         self.setLayout(self.layout)
-        self.setWindowIcon(get_icon('arredit.png'))
+        self.setWindowIcon(ima.icon('arredit'))
         if title:
             title = to_text_string(title) + " - " + _("NumPy array")
         else:
@@ -578,8 +655,7 @@ class ArrayEditor(QDialog):
             self.stack.addWidget(ArrayEditorWidget(self, data, readonly,
                                                    xlabels, ylabels))
         self.arraywidget = self.stack.currentWidget()
-        self.connect(self.stack, SIGNAL('currentChanged(int)'),
-                     self.current_widget_changed)
+        self.stack.currentChanged.connect(self.current_widget_changed)
         self.layout.addWidget(self.stack, 1, 0)
 
         # Buttons configuration
@@ -602,14 +678,12 @@ class ArrayEditor(QDialog):
             if data.ndim == 3:
                 # QSpinBox
                 self.index_spin = QSpinBox(self, keyboardTracking=False)
-                self.connect(self.index_spin, SIGNAL('valueChanged(int)'),
-                             self.change_active_widget)
+                self.index_spin.valueChanged.connect(self.change_active_widget)
                 # QComboBox
                 names = [str(i) for i in range(3)]
                 ra_combo = QComboBox(self)
                 ra_combo.addItems(names)
-                self.connect(ra_combo, SIGNAL('currentIndexChanged(int)'),
-                             self.current_dim_changed)    
+                ra_combo.currentIndexChanged.connect(self.current_dim_changed)    
                 # Adding the widgets to layout
                 label = QLabel(_("Axis:"))
                 btn_layout.addWidget(label)
@@ -625,8 +699,7 @@ class ArrayEditor(QDialog):
                 self.current_dim_changed(self.last_dim)
             else:
                 ra_combo = QComboBox(self)
-                self.connect(ra_combo, SIGNAL('currentIndexChanged(int)'),
-                             self.stack.setCurrentIndex)
+                ra_combo.currentIndexChanged.connect(self.stack.setCurrentIndex)
                 ra_combo.addItems(names)
                 btn_layout.addWidget(ra_combo)
             if is_masked_array:
@@ -637,8 +710,8 @@ class ArrayEditor(QDialog):
                 btn_layout.addWidget(label)
             btn_layout.addStretch()
         bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
-        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
-        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
+        bbox.accepted.connect(self.accept)
+        bbox.rejected.connect(self.reject)
         btn_layout.addWidget(bbox)
         self.layout.addLayout(btn_layout, 2, 0)
 
@@ -696,6 +769,7 @@ class ArrayEditor(QDialog):
         self.index_spin.setRange(-self.data.shape[index],
                                  self.data.shape[index]-1)
 
+    @Slot()
     def accept(self):
         """Reimplement Qt method"""
         for index in range(self.stack.count()):
@@ -714,64 +788,77 @@ class ArrayEditor(QDialog):
         self.setAttribute(Qt.WA_DeleteOnClose)
         self.reject()
 
+    @Slot()
     def reject(self):
         """Reimplement Qt method"""
         if self.arraywidget is not None:
             for index in range(self.stack.count()):
                 self.stack.widget(index).reject_changes()
         QDialog.reject(self)
-    
-    
+
+
+#==============================================================================
+# Tests
+#==============================================================================    
 def test_edit(data, title="", xlabels=None, ylabels=None,
               readonly=False, parent=None):
     """Test subroutine"""
+    app = qapplication(test_time=1.5)    # analysis:ignore
     dlg = ArrayEditor(parent)
+
     if dlg.setup_and_check(data, title, xlabels=xlabels, ylabels=ylabels,
-                           readonly=readonly) and dlg.exec_():
+                           readonly=readonly):
+        dlg.exec_()
         return dlg.get_value()
     else:
         import sys
-        sys.exit()
+        sys.exit(1)
 
 
 def test():
     """Array editor test"""
-    _app = qapplication()
-    
+    from numpy.testing import assert_array_equal
+
     arr = np.array(["kjrekrjkejr"])
-    print("out:", test_edit(arr, "string array"))
-    from spyderlib.py3compat import u
-    arr = np.array([u("kjrekrjkejr")])
-    print("out:", test_edit(arr, "unicode array"))
+    assert arr == test_edit(arr, "string array")
+
+    arr = np.array([u"ñññéáíó"])
+    assert arr == test_edit(arr, "unicode array")
+
     arr = np.ma.array([[1, 0], [1, 0]], mask=[[True, False], [False, False]])
-    print("out:", test_edit(arr, "masked array"))
+    assert_array_equal(arr, test_edit(arr, "masked array"))
+
     arr = np.zeros((2, 2), {'names': ('red', 'green', 'blue'),
                            'formats': (np.float32, np.float32, np.float32)})
-    print("out:", test_edit(arr, "record array"))
+    assert_array_equal(arr, test_edit(arr, "record array"))
+
     arr = np.array([(0, 0.0), (0, 0.0), (0, 0.0)],
                    dtype=[(('title 1', 'x'), '|i1'),
                           (('title 2', 'y'), '>f4')])
-    print("out:", test_edit(arr, "record array with titles"))
+    assert_array_equal(arr, test_edit(arr, "record array with titles"))
+
     arr = np.random.rand(5, 5)
-    print("out:", test_edit(arr, "float array",
-                            xlabels=['a', 'b', 'c', 'd', 'e']))
+    assert_array_equal(arr, test_edit(arr, "float array",
+                                      xlabels=['a', 'b', 'c', 'd', 'e']))
+
     arr = np.round(np.random.rand(5, 5)*10)+\
                    np.round(np.random.rand(5, 5)*10)*1j
-    print("out:", test_edit(arr, "complex array",
-                            xlabels=np.linspace(-12, 12, 5),
-                            ylabels=np.linspace(-12, 12, 5)))
+    assert_array_equal(arr, test_edit(arr, "complex array",
+                                      xlabels=np.linspace(-12, 12, 5),
+                                      ylabels=np.linspace(-12, 12, 5)))
+
     arr_in = np.array([True, False, True])
-    print("in:", arr_in)
     arr_out = test_edit(arr_in, "bool array")
-    print("out:", arr_out)
-    print(arr_in is arr_out)
+    assert arr_in is arr_out
+
     arr = np.array([1, 2, 3], dtype="int8")
-    print("out:", test_edit(arr, "int array"))
+    assert_array_equal(arr, test_edit(arr, "int array"))
+
     arr = np.zeros((3,3,4))
     arr[0,0,0]=1
     arr[0,0,1]=2
     arr[0,0,2]=3
-    print("out:", test_edit(arr))
+    assert_array_equal(arr, test_edit(arr, "3D array"))
 
 
 if __name__ == "__main__":
diff --git a/spyderlib/widgets/dicteditor.py b/spyderlib/widgets/variableexplorer/collectionseditor.py
similarity index 83%
rename from spyderlib/widgets/dicteditor.py
rename to spyderlib/widgets/variableexplorer/collectionseditor.py
index afac7d7..a2a5057 100644
--- a/spyderlib/widgets/dicteditor.py
+++ b/spyderlib/widgets/variableexplorer/collectionseditor.py
@@ -1,11 +1,11 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
 """
-Dictionary Editor Widget and Dialog based on Qt
+Collections (i.e. dictionary, list and tuple) editor widget and dialog
 """
 
 #TODO: Multiple selection: open as many editors (array/dict/...) as necessary,
@@ -17,106 +17,62 @@ Dictionary Editor Widget and Dialog based on Qt
 # pylint: disable=R0201
 
 from __future__ import print_function
+
+import sys
+import datetime
+import warnings
+
 from spyderlib.qt.QtGui import (QMessageBox, QTableView, QItemDelegate,
                                 QLineEdit, QVBoxLayout, QWidget, QColor,
                                 QDialog, QDateEdit, QDialogButtonBox, QMenu,
                                 QInputDialog, QDateTimeEdit, QApplication,
-                                QKeySequence)
-from spyderlib.qt.QtCore import (Qt, QModelIndex, QAbstractTableModel, SIGNAL,
-                                 SLOT, QDateTime, Signal)
-from spyderlib.qt.compat import to_qvariant, from_qvariant, getsavefilename
+                                QKeySequence, QAbstractItemDelegate)
+from spyderlib.qt.QtCore import (Qt, QModelIndex, QAbstractTableModel, Signal,
+                                 QDateTime, Slot)
+import spyderlib.utils.icon_manager as ima
+from spyderlib.qt.compat import to_qvariant, getsavefilename
 from spyderlib.utils.qthelpers import mimedata2url
 
-import sys
-import datetime
-
 # Local import
-from spyderlib.baseconfig import _
-from spyderlib.guiconfig import get_font
+from spyderlib.config.base import _
+from spyderlib.config.gui import get_font
 from spyderlib.utils.misc import fix_reference_name
-from spyderlib.utils.qthelpers import (get_icon, add_actions, create_action,
-                                       qapplication)
-from spyderlib.widgets.dicteditorutils import (sort_against, get_size,
+from spyderlib.utils.qthelpers import add_actions, create_action, qapplication
+from spyderlib.widgets.variableexplorer.utils import (sort_against, get_size,
                get_human_readable_type, value_to_display, get_color_name,
                is_known_type, FakeObject, Image, ndarray, array, MaskedArray,
-               unsorted_unique, try_to_eval, datestr_to_datetime,
-               get_numpy_dtype, is_editable_type, DataFrame, Series)
+               unsorted_unique, try_to_eval, is_editable_type, DataFrame,
+               Series, display_to_value, np_savetxt)
 if ndarray is not FakeObject:
-    from spyderlib.widgets.arrayeditor import ArrayEditor
+    from spyderlib.widgets.variableexplorer.arrayeditor import ArrayEditor
 if DataFrame is not FakeObject:
-    from spyderlib.widgets.dataframeeditor import DataFrameEditor
-from spyderlib.widgets.texteditor import TextEditor
-from spyderlib.widgets.importwizard import ImportWizard
-from spyderlib.py3compat import (to_text_string, to_binary_string,
-                                 is_text_string, is_binary_string, getcwd, u)
+    from spyderlib.widgets.variableexplorer.dataframeeditor import DataFrameEditor
+from spyderlib.widgets.variableexplorer.texteditor import TextEditor
+from spyderlib.widgets.variableexplorer.importwizard import ImportWizard
+from spyderlib.py3compat import (to_text_string, is_text_string, PY3, io,
+                                 is_binary_string, getcwd)
 
 
 LARGE_NROWS = 100
 
 
-def display_to_value(value, default_value, ignore_errors=True):
-    """Convert back to value"""
-    value = from_qvariant(value, to_text_string)
-    try:
-        np_dtype = get_numpy_dtype(default_value)
-        if isinstance(default_value, bool):
-            # We must test for boolean before NumPy data types
-            # because `bool` class derives from `int` class
-            try:
-                value = bool(float(value))
-            except ValueError:
-                value = value.lower() == "true"
-        elif np_dtype is not None:
-            if 'complex' in str(type(default_value)):
-                value = np_dtype(complex(value))
-            else:
-                value = np_dtype(value)
-        elif is_binary_string(default_value):
-            value = to_binary_string(value, 'utf8')
-        elif is_text_string(default_value):
-            value = to_text_string(value)
-        elif isinstance(default_value, complex):
-            value = complex(value)
-        elif isinstance(default_value, float):
-            value = float(value)
-        elif isinstance(default_value, int):
-            try:
-                value = int(value)
-            except ValueError:
-                value = float(value)
-        elif isinstance(default_value, datetime.datetime):
-            value = datestr_to_datetime(value)
-        elif isinstance(default_value, datetime.date):
-            value = datestr_to_datetime(value).date()
-        elif ignore_errors:
-            value = try_to_eval(value)
-        else:
-            value = eval(value)
-    except (ValueError, SyntaxError):
-        if ignore_errors:
-            value = try_to_eval(value)
-        else:
-            return default_value
-    return value
-
-
 class ProxyObject(object):
     """Dictionary proxy to an unknown object"""
     def __init__(self, obj):
         self.__obj__ = obj
-    
+
     def __len__(self):
         return len(dir(self.__obj__))
-    
+
     def __getitem__(self, key):
         return getattr(self.__obj__, key)
-    
+
     def __setitem__(self, key, value):
         setattr(self.__obj__, key, value)
-        
 
-class ReadOnlyDictModel(QAbstractTableModel):
-    """DictEditor Read-Only Table Model"""
+
+class ReadOnlyCollectionsModel(QAbstractTableModel):
+    """CollectionsEditor Read-Only Table Model"""
     ROWS_TO_LOAD = 50
 
     def __init__(self, parent, data, title="", names=False, truncate=True,
@@ -143,14 +99,14 @@ class ReadOnlyDictModel(QAbstractTableModel):
     def get_data(self):
         """Return model data"""
         return self._data
-            
-    def set_data(self, data, dictfilter=None):
+
+    def set_data(self, data, coll_filter=None):
         """Set model data"""
         self._data = data
 
-        if dictfilter is not None and not self.remote and \
+        if coll_filter is not None and not self.remote and \
           isinstance(data, (tuple, list, dict)):
-            data = dictfilter(data)
+            data = coll_filter(data)
         self.showndata = data
 
         self.header0 = _("Index")
@@ -249,7 +205,8 @@ class ReadOnlyDictModel(QAbstractTableModel):
             self.keys = sort_against(self.keys, values, reverse)
             self.sizes = sort_against(self.sizes, values, reverse)
             self.types = sort_against(self.types, values, reverse)
-        self.reset()
+        self.beginResetModel()
+        self.endResetModel()
 
     def columnCount(self, qindex=QModelIndex()):
         """Array column number"""
@@ -319,9 +276,12 @@ class ReadOnlyDictModel(QAbstractTableModel):
         value = self.get_value(index)
         if index.column() == 3 and self.remote:
             value = value['view']
-        display = value_to_display(value,
+        if index.column() == 3:
+            display = value_to_display(value,
                                truncate=index.column() == 3 and self.truncate,
                                minmax=self.minmax)
+        else:
+             display = to_text_string(value)
         if role == Qt.DisplayRole:
             return to_qvariant(display)
         elif role == Qt.EditRole:
@@ -359,16 +319,20 @@ class ReadOnlyDictModel(QAbstractTableModel):
 
     def flags(self, index):
         """Overriding method flags"""
-        # This method was implemented in DictModel only, but to enable tuple
-        # exploration (even without editing), this method was moved here
+        # This method was implemented in CollectionsModel only, but to enable
+        # tuple exploration (even without editing), this method was moved here
         if not index.isValid():
             return Qt.ItemIsEnabled
         return Qt.ItemFlags(QAbstractTableModel.flags(self, index)|
                             Qt.ItemIsEditable)
+    def reset(self):
+        self.beginResetModel()
+        self.endResetModel()
+
+
+class CollectionsModel(ReadOnlyCollectionsModel):
+    """Collections Table Model"""
 
-class DictModel(ReadOnlyDictModel):
-    """DictEditor Table Model"""
-    
     def set_value(self, index, value):
         """Set value"""
         self._data[ self.keys[index.row()] ] = value
@@ -380,7 +344,7 @@ class DictModel(ReadOnlyDictModel):
         """Background color depending on value"""
         value = self.get_value(index)
         if index.column() < 3:
-            color = ReadOnlyDictModel.get_bgcolor(self, index)
+            color = ReadOnlyCollectionsModel.get_bgcolor(self, index)
         else:
             if self.remote:
                 color_name = value['color']
@@ -399,14 +363,13 @@ class DictModel(ReadOnlyDictModel):
         value = display_to_value(value, self.get_value(index),
                                  ignore_errors=True)
         self.set_value(index, value)
-        self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
-                  index, index)
+        self.dataChanged.emit(index, index)
         return True
 
 
-class DictDelegate(QItemDelegate):
-    """DictEditor Item Delegate"""
-    
+class CollectionsDelegate(QItemDelegate):
+    """CollectionsEditor Item Delegate"""
+
     def __init__(self, parent=None):
         QItemDelegate.__init__(self, parent)
         self._editors = {} # keep references on opened editors
@@ -463,9 +426,9 @@ class DictDelegate(QItemDelegate):
         key = index.model().get_key(index)
         readonly = isinstance(value, tuple) or self.parent().readonly \
                    or not is_known_type(value)
-        #---editor = DictEditor
+        #---editor = CollectionsEditor
         if isinstance(value, (list, tuple, dict)):
-            editor = DictEditor()
+            editor = CollectionsEditor()
             editor.setup(value, key, icon=self.parent().windowIcon(),
                          readonly=readonly)
             self.create_dialog(editor, dict(model=index.model(), editor=editor,
@@ -484,7 +447,7 @@ class DictDelegate(QItemDelegate):
             return None
         #---showing image
         elif isinstance(value, Image) and ndarray is not FakeObject \
-             and Image is not FakeObject:
+          and Image is not FakeObject:
             arr = array(value)
             if arr.size == 0:
                 return None
@@ -505,24 +468,19 @@ class DictDelegate(QItemDelegate):
             self.create_dialog(editor, dict(model=index.model(), editor=editor,
                                             key=key, readonly=readonly))
             return None
-
         #---editor = QDateTimeEdit
         elif isinstance(value, datetime.datetime):
             editor = QDateTimeEdit(value, parent)
             editor.setCalendarPopup(True)
             editor.setFont(get_font('dicteditor'))
-            self.connect(editor, SIGNAL("returnPressed()"),
-                         self.commitAndCloseEditor)
             return editor
         #---editor = QDateEdit
         elif isinstance(value, datetime.date):
             editor = QDateEdit(value, parent)
             editor.setCalendarPopup(True)
             editor.setFont(get_font('dicteditor'))
-            self.connect(editor, SIGNAL("returnPressed()"),
-                         self.commitAndCloseEditor)
             return editor
-        #---editor = QTextEdit
+        #---editor = TextEditor
         elif is_text_string(value) and len(value)>40:
             editor = TextEditor(value, key)
             self.create_dialog(editor, dict(model=index.model(), editor=editor,
@@ -533,12 +491,11 @@ class DictDelegate(QItemDelegate):
             editor = QLineEdit(parent)
             editor.setFont(get_font('dicteditor'))
             editor.setAlignment(Qt.AlignLeft)
-            self.connect(editor, SIGNAL("returnPressed()"),
-                         self.commitAndCloseEditor)
+            editor.returnPressed.connect(self.commitAndCloseEditor)
             return editor
-        #---editor = DictEditor for an arbitrary object
+        #---editor = CollectionsEditor for an arbitrary object
         else:
-            editor = DictEditor()
+            editor = CollectionsEditor()
             editor.setup(value, key, icon=self.parent().windowIcon(),
                          readonly=readonly)
             self.create_dialog(editor, dict(model=index.model(), editor=editor,
@@ -547,9 +504,9 @@ class DictDelegate(QItemDelegate):
             
     def create_dialog(self, editor, data):
         self._editors[id(editor)] = data
-        self.connect(editor, SIGNAL('accepted()'),
+        editor.accepted.connect(
                      lambda eid=id(editor): self.editor_accepted(eid))
-        self.connect(editor, SIGNAL('rejected()'),
+        editor.rejected.connect(
                      lambda eid=id(editor): self.editor_rejected(eid))
         editor.show()
         
@@ -568,12 +525,21 @@ class DictDelegate(QItemDelegate):
     def commitAndCloseEditor(self):
         """Overriding method commitAndCloseEditor"""
         editor = self.sender()
-        self.emit(SIGNAL("commitData(QWidget*)"), editor)
-        self.emit(SIGNAL("closeEditor(QWidget*)"), editor)
+        # Avoid a segfault with PyQt5. Variable value won't be changed
+        # but at least Spyder won't crash. It seems generated by a
+        # bug in sip. See
+        # http://comments.gmane.org/gmane.comp.python.pyqt-pykde/26544
+        try:
+            self.commitData.emit(editor)
+        except AttributeError:
+            pass
+        self.closeEditor.emit(editor, QAbstractItemDelegate.NoHint)
 
     def setEditorData(self, editor, index):
-        """Overriding method setEditorData
-        Model --> Editor"""
+        """
+        Overriding method setEditorData
+        Model --> Editor
+        """
         value = self.get_value(index)
         if isinstance(editor, QLineEdit):
             if is_binary_string(value):
@@ -590,8 +556,10 @@ class DictDelegate(QItemDelegate):
             editor.setDateTime(QDateTime(value.date(), value.time()))
 
     def setModelData(self, editor, model, index):
-        """Overriding method setModelData
-        Editor --> Model"""
+        """
+        Overriding method setModelData
+        Editor --> Model
+        """
         if not hasattr(model, "set_value"):
             # Read-only mode
             return
@@ -626,9 +594,10 @@ class DictDelegate(QItemDelegate):
 
 
 class BaseTableView(QTableView):
-    """Base dictionary editor table view"""
+    """Base collection editor table view"""
     sig_option_changed = Signal(str, object)
     sig_files_dropped = Signal(list)
+    redirect_stdio = Signal(bool)
     
     def __init__(self, parent):
         QTableView.__init__(self, parent)
@@ -669,35 +638,35 @@ class BaseTableView(QTableView):
         resize_action = create_action(self, _("Resize rows to contents"),
                                       triggered=self.resizeRowsToContents)
         self.paste_action = create_action(self, _("Paste"),
-                                          icon=get_icon('editpaste.png'),
+                                          icon=ima.icon('editpaste'),
                                           triggered=self.paste)
         self.copy_action = create_action(self, _("Copy"),
-                                         icon=get_icon('editcopy.png'),
+                                         icon=ima.icon('editcopy'),
                                          triggered=self.copy)                                      
         self.edit_action = create_action(self, _("Edit"),
-                                         icon=get_icon('edit.png'),
+                                         icon=ima.icon('edit'),
                                          triggered=self.edit_item)
         self.plot_action = create_action(self, _("Plot"),
-                                    icon=get_icon('plot.png'),
+                                    icon=ima.icon('plot'),
                                     triggered=lambda: self.plot_item('plot'))
         self.plot_action.setVisible(False)
         self.hist_action = create_action(self, _("Histogram"),
-                                    icon=get_icon('hist.png'),
+                                    icon=ima.icon('hist'),
                                     triggered=lambda: self.plot_item('hist'))
         self.hist_action.setVisible(False)
         self.imshow_action = create_action(self, _("Show image"),
-                                           icon=get_icon('imshow.png'),
+                                           icon=ima.icon('imshow'),
                                            triggered=self.imshow_item)
         self.imshow_action.setVisible(False)
         self.save_array_action = create_action(self, _("Save array"),
-                                               icon=get_icon('filesave.png'),
+                                               icon=ima.icon('filesave'),
                                                triggered=self.save_array)
         self.save_array_action.setVisible(False)
         self.insert_action = create_action(self, _("Insert"),
-                                           icon=get_icon('insert.png'),
+                                           icon=ima.icon('insert'),
                                            triggered=self.insert_item)
         self.remove_action = create_action(self, _("Remove"),
-                                           icon=get_icon('editdelete.png'),
+                                           icon=ima.icon('editdelete'),
                                            triggered=self.remove_item)
         self.truncate_action = create_action(self, _("Truncate values"),
                                              toggled=self.toggle_truncate)
@@ -707,11 +676,11 @@ class BaseTableView(QTableView):
                                            toggled=self.toggle_minmax)
         self.minmax_action.setChecked(minmax)
         self.toggle_minmax(minmax)
-        self.rename_action = create_action(self, _( "Rename"),
-                                           icon=get_icon('rename.png'),
+        self.rename_action = create_action(self, _("Rename"),
+                                           icon=ima.icon('rename'),
                                            triggered=self.rename_item)
-        self.duplicate_action = create_action(self, _( "Duplicate"),
-                                              icon=get_icon('edit_add.png'),
+        self.duplicate_action = create_action(self, _("Duplicate"),
+                                              icon=ima.icon('edit_add'),
                                               triggered=self.duplicate_item)
         menu = QMenu(self)
         menu_actions = [self.edit_action, self.plot_action, self.hist_action,
@@ -898,16 +867,19 @@ class BaseTableView(QTableView):
         else:
             event.ignore()
 
+    @Slot(bool)
     def toggle_truncate(self, state):
         """Toggle display truncating option"""
         self.sig_option_changed.emit('truncate', state)
         self.model.truncate = state
-        
+
+    @Slot(bool)
     def toggle_minmax(self, state):
         """Toggle min/max display for numpy arrays"""
         self.sig_option_changed.emit('minmax', state)
         self.model.minmax = state
-        
+
+    @Slot()
     def edit_item(self):
         """Edit item"""
         index = self.currentIndex()
@@ -915,7 +887,8 @@ class BaseTableView(QTableView):
             return
         # TODO: Remove hard coded "Value" column number (3 here)
         self.edit(index.child(index.row(), 3))
-    
+
+    @Slot()
     def remove_item(self):
         """Remove item"""
         indexes = self.selectedIndexes()
@@ -952,15 +925,18 @@ class BaseTableView(QTableView):
             self.copy_value(orig_key, new_key)
             if erase_original:
                 self.remove_values([orig_key])
-    
+
+    @Slot()
     def duplicate_item(self):
         """Duplicate item"""
         self.copy_item()
 
+    @Slot()
     def rename_item(self):
         """Rename item"""
         self.copy_item(True)
-    
+
+    @Slot()
     def insert_item(self):
         """Insert item"""
         index = self.currentIndex()
@@ -988,9 +964,9 @@ class BaseTableView(QTableView):
             
     def __prepare_plot(self):
         try:
-            import guiqwt.pyplot #analysis:ignore
+            import guiqwt.pyplot   #analysis:ignore
             return True
-        except ImportError:
+        except (ImportError, AssertionError):
             try:
                 if 'matplotlib' not in sys.modules:
                     import matplotlib
@@ -1013,7 +989,8 @@ class BaseTableView(QTableView):
                                      _("<b>Unable to plot data.</b>"
                                        "<br><br>Error message:<br>%s"
                                        ) % str(error))
-            
+
+    @Slot()
     def imshow_item(self):
         """Imshow item"""
         index = self.currentIndex()
@@ -1029,17 +1006,18 @@ class BaseTableView(QTableView):
                                      _("<b>Unable to show image.</b>"
                                        "<br><br>Error message:<br>%s"
                                        ) % str(error))
-            
+
+    @Slot()
     def save_array(self):
         """Save array"""
         title = _( "Save array")
         if self.array_filename is None:
             self.array_filename = getcwd()
-        self.emit(SIGNAL('redirect_stdio(bool)'), False)
+        self.redirect_stdio.emit(False)
         filename, _selfilter = getsavefilename(self, title,
                                                self.array_filename,
                                                _("NumPy arrays")+" (*.npy)")
-        self.emit(SIGNAL('redirect_stdio(bool)'), True)
+        self.redirect_stdio.emit(True)
         if filename:
             self.array_filename = filename
             data = self.delegate.get_value( self.currentIndex() )
@@ -1051,6 +1029,8 @@ class BaseTableView(QTableView):
                                      _("<b>Unable to save array</b>"
                                        "<br><br>Error message:<br>%s"
                                        ) % str(error))
+    
+    @Slot()
     def copy(self):
         """Copy text to clipboard"""
         clipboard = QApplication.clipboard()
@@ -1058,9 +1038,36 @@ class BaseTableView(QTableView):
         for idx in self.selectedIndexes():
             if not idx.isValid():
                 continue
-            clipl.append(to_text_string(self.delegate.get_value(idx)))
-        clipboard.setText(u('\n').join(clipl))
-    
+            obj = self.delegate.get_value(idx)
+            # Check if we are trying to copy a numpy array, and if so make sure
+            # to copy the whole thing in a tab separated format
+            if isinstance(obj, (ndarray, MaskedArray)) \
+              and ndarray is not FakeObject:
+                if PY3:
+                    output = io.BytesIO()
+                else:
+                    output = io.StringIO()
+                try:
+                    np_savetxt(output, obj, delimiter='\t')
+                except:
+                    QMessageBox.warning(self, _("Warning"),
+                                        _("It was not possible to copy "
+                                          "this array"))
+                    return
+                obj = output.getvalue().decode('utf-8')
+                output.close()
+            elif isinstance(obj, (DataFrame, Series)) \
+              and DataFrame is not FakeObject:
+                output = io.StringIO()
+                obj.to_csv(output, sep='\t', index=True, header=True)
+                if PY3:
+                    obj = output.getvalue()
+                else:
+                    obj = output.getvalue().decode('utf-8')
+                output.close()
+            clipl.append(obj)
+        clipboard.setText('\n'.join(clipl))
+
     def import_from_string(self, text, title=None):
         """Import data from string"""
         data = self.model.get_data()
@@ -1071,7 +1078,8 @@ class BaseTableView(QTableView):
         if editor.exec_():
             var_name, clip_data = editor.get_data()
             self.new_value(var_name, clip_data)
-    
+
+    @Slot()
     def paste(self):
         """Import text/data/code from clipboard"""
         clipboard = QApplication.clipboard()
@@ -1083,20 +1091,21 @@ class BaseTableView(QTableView):
         else:
             QMessageBox.warning(self, _( "Empty clipboard"),
                                 _("Nothing to be imported from clipboard."))
-        
 
-class DictEditorTableView(BaseTableView):
-    """DictEditor table view"""
+
+class CollectionsEditorTableView(BaseTableView):
+    """CollectionsEditor table view"""
     def __init__(self, parent, data, readonly=False, title="",
                  names=False, truncate=True, minmax=False):
         BaseTableView.__init__(self, parent)
         self.dictfilter = None
         self.readonly = readonly or isinstance(data, tuple)
-        DictModelClass = ReadOnlyDictModel if self.readonly else DictModel
-        self.model = DictModelClass(self, data, title, names=names,
-                                    truncate=truncate, minmax=minmax)
+        CollectionsModelClass = ReadOnlyCollectionsModel if self.readonly \
+                                else CollectionsModel
+        self.model = CollectionsModelClass(self, data, title, names=names,
+                                           truncate=truncate, minmax=minmax)
         self.setModel(self.model)
-        self.delegate = DictDelegate(self)
+        self.delegate = CollectionsDelegate(self)
         self.setItemDelegate(self.delegate)
 
         self.setup_table()
@@ -1156,13 +1165,13 @@ class DictEditorTableView(BaseTableView):
         """Return array's ndim"""
         data = self.model.get_data()
         return data[key].ndim
-    
+
     def oedit(self, key):
         """Edit item"""
         data = self.model.get_data()
-        from spyderlib.widgets.objecteditor import oedit
+        from spyderlib.widgets.variableexplorer.objecteditor import oedit
         oedit(data[key])
-    
+
     def plot(self, key, funcname):
         """Plot item"""
         data = self.model.get_data()
@@ -1201,14 +1210,15 @@ class DictEditorTableView(BaseTableView):
         self.dictfilter = dictfilter
 
 
-class DictEditorWidget(QWidget):
-    """Dictionary Editor Dialog"""
+class CollectionsEditorWidget(QWidget):
+    """Dictionary Editor Widget"""
     def __init__(self, parent, data, readonly=False, title="", remote=False):
         QWidget.__init__(self, parent)
         if remote:
-            self.editor = RemoteDictEditorTableView(self, data, readonly)
+            self.editor = RemoteCollectionsEditorTableView(self, data, readonly)
         else:
-            self.editor = DictEditorTableView(self, data, readonly, title)
+            self.editor = CollectionsEditorTableView(self, data, readonly,
+                                                     title)
         layout = QVBoxLayout()
         layout.addWidget(self.editor)
         self.setLayout(layout)
@@ -1222,22 +1232,22 @@ class DictEditorWidget(QWidget):
         return self.editor.model.title
 
 
-class DictEditor(QDialog):
-    """Dictionary/List Editor Dialog"""
+class CollectionsEditor(QDialog):
+    """Collections Editor Dialog"""
     def __init__(self, parent=None):
         QDialog.__init__(self, parent)
-        
+
         # Destroying the C++ object right after closing the dialog box,
         # otherwise it may be garbage-collected in another QThread
         # (e.g. the editor's analysis thread in Spyder), thus leading to
         # a segmentation fault on UNIX or an application crash on Windows
         self.setAttribute(Qt.WA_DeleteOnClose)
-        
+
         self.data_copy = None
         self.widget = None
-        
-    def setup(self, data, title='', readonly=False, width=500,
-              icon='dictedit.png', remote=False, parent=None):
+
+    def setup(self, data, title='', readonly=False, width=500, remote=False,
+              icon=None, parent=None):
         if isinstance(data, dict):
             # dictionnary
             self.data_copy = data.copy()
@@ -1251,9 +1261,9 @@ class DictEditor(QDialog):
             import copy
             self.data_copy = copy.deepcopy(data)
             datalen = len(dir(data))
-        self.widget = DictEditorWidget(self, self.data_copy, title=title,
-                                       readonly=readonly, remote=remote)
-        
+        self.widget = CollectionsEditorWidget(self, self.data_copy, title=title,
+                                              readonly=readonly, remote=remote)
+
         layout = QVBoxLayout()
         layout.addWidget(self.widget)
         self.setLayout(layout)
@@ -1263,9 +1273,9 @@ class DictEditor(QDialog):
         if not readonly:
             buttons = buttons | QDialogButtonBox.Cancel
         bbox = QDialogButtonBox(buttons)
-        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
+        bbox.accepted.connect(self.accept)
         if not readonly:
-            self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
+            bbox.rejected.connect(self.reject)
         layout.addWidget(bbox)
 
         constant = 121
@@ -1275,12 +1285,11 @@ class DictEditor(QDialog):
         self.resize(width, height)
 
         self.setWindowTitle(self.widget.get_title())
-        if is_text_string(icon):
-            icon = get_icon(icon)
-        self.setWindowIcon(icon)
+        if icon is None:
+            self.setWindowIcon(ima.icon('dictedit'))
         # Make the dialog act as a window
         self.setWindowFlags(Qt.Window)
-        
+
     def get_value(self):
         """Return modified copy of dictionary or list"""
         # It is import to avoid accessing Qt C++ object as it has probably
@@ -1288,14 +1297,22 @@ class DictEditor(QDialog):
         return self.data_copy
 
 
-#----Remote versions of DictDelegate and DictEditorTableView
-class RemoteDictDelegate(DictDelegate):
-    """DictEditor Item Delegate"""
+class DictEditor(CollectionsEditor):
+    def __init__(self, parent=None):
+        warnings.warn("`DictEditor` has been renamed to `CollectionsEditor` in "
+                      "Spyder 3. Please use `CollectionsEditor` instead",
+                      RuntimeWarning)
+        CollectionsEditor.__init__(self, parent)
+
+
+#----Remote versions of CollectionsDelegate and CollectionsEditorTableView
+class RemoteCollectionsDelegate(CollectionsDelegate):
+    """CollectionsEditor Item Delegate"""
     def __init__(self, parent=None, get_value_func=None, set_value_func=None):
-        DictDelegate.__init__(self, parent)
+        CollectionsDelegate.__init__(self, parent)
         self.get_value_func = get_value_func
         self.set_value_func = set_value_func
-        
+
     def get_value(self, index):
         if index.isValid():
             name = index.model().keys[index.row()]
@@ -1307,9 +1324,9 @@ class RemoteDictDelegate(DictDelegate):
             self.set_value_func(name, value)
 
 
-class RemoteDictEditorTableView(BaseTableView):
+class RemoteCollectionsEditorTableView(BaseTableView):
     """DictEditor table view"""
-    def __init__(self, parent, data, truncate=True, minmax=False, 
+    def __init__(self, parent, data, truncate=True, minmax=False,
                  get_value_func=None, set_value_func=None,
                  new_value_func=None, remove_values_func=None,
                  copy_value_func=None, is_list_func=None, get_len_func=None,
@@ -1344,13 +1361,14 @@ class RemoteDictEditorTableView(BaseTableView):
         self.model = None
         self.delegate = None
         self.readonly = False
-        self.model = DictModel(self, data, names=True,
-                               truncate=truncate, minmax=minmax,
-                               remote=True)
+        self.model = CollectionsModel(self, data, names=True,
+                                      truncate=truncate, minmax=minmax,
+                                      remote=True)
         self.setModel(self.model)
-        self.delegate = RemoteDictDelegate(self, get_value_func, set_value_func)
+        self.delegate = RemoteCollectionsDelegate(self, get_value_func,
+                                                  set_value_func)
         self.setItemDelegate(self.delegate)
-        
+
         self.setup_table()
         self.menu = self.setup_menu(truncate, minmax)
 
@@ -1390,6 +1408,9 @@ class RemoteDictEditorTableView(BaseTableView):
             BaseTableView.edit_item(self)
 
 
+#==============================================================================
+# Tests
+#==============================================================================
 def get_test_data():
     """Create test data"""
     import numpy as np
@@ -1429,32 +1450,36 @@ def get_test_data():
             'bool_scalar': np.bool(8),
             'unsupported1': np.arccos,
             'unsupported2': np.cast,
-            #1: (1, 2, 3), -5: ("a", "b", "c"), 2.5: np.array((4.0, 6.0, 8.0)),            
+            #1: (1, 2, 3), -5: ("a", "b", "c"), 2.5: np.array((4.0, 6.0, 8.0)),
             }
 
-def test():
-    """Dictionary editor test"""
-    app = qapplication() #analysis:ignore
-    dialog = DictEditor()
+
+def editor_test():
+    """Collections editor test"""
+    app = qapplication()             #analysis:ignore
+    dialog = CollectionsEditor()
     dialog.setup(get_test_data())
     dialog.show()
     app.exec_()
     print("out:", dialog.get_value())
-    
+
+
 def remote_editor_test():
-    """Remote dictionary editor test"""
+    """Remote collections editor test"""
+    app = qapplication()
     from spyderlib.plugins.variableexplorer import VariableExplorer
     from spyderlib.widgets.externalshell.monitor import make_remote_view
     remote = make_remote_view(get_test_data(), VariableExplorer.get_settings())
     from pprint import pprint
     pprint(remote)
-    app = qapplication()
-    dialog = DictEditor()
+    dialog = CollectionsEditor()
     dialog.setup(remote, remote=True)
     dialog.show()
     app.exec_()
     if dialog.result():
         print(dialog.get_value())
 
+
 if __name__ == "__main__":
+    editor_test()
     remote_editor_test()
diff --git a/spyderlib/widgets/dataframeeditor.py b/spyderlib/widgets/variableexplorer/dataframeeditor.py
similarity index 87%
rename from spyderlib/widgets/dataframeeditor.py
rename to spyderlib/widgets/variableexplorer/dataframeeditor.py
index c7f21a1..9bd405e 100644
--- a/spyderlib/widgets/dataframeeditor.py
+++ b/spyderlib/widgets/variableexplorer/dataframeeditor.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2014 Spyder development team
+# Copyright © 2009- Spyder development team
 # Licensed under the terms of the New BSD License
 #
 # DataFrameModel is based on the class ArrayModel from array editor
@@ -13,21 +13,21 @@
 Pandas DataFrame Editor Dialog
 """
 
-from spyderlib.qt.QtCore import (QAbstractTableModel, Qt, QModelIndex,
-                                 SIGNAL, SLOT)
+from spyderlib.qt.QtCore import QAbstractTableModel, Qt, QModelIndex, Slot
 from spyderlib.qt.QtGui import (QDialog, QTableView, QColor, QGridLayout,
                                 QDialogButtonBox, QHBoxLayout, QPushButton,
                                 QCheckBox, QMessageBox, QInputDialog, QCursor,
                                 QLineEdit, QApplication, QMenu, QKeySequence)
 from spyderlib.qt.compat import to_qvariant, from_qvariant
-from spyderlib.utils.qthelpers import (qapplication, get_icon, create_action,
+import spyderlib.utils.icon_manager as ima
+from spyderlib.utils.qthelpers import (qapplication, create_action,
                                        add_actions, keybinding)
 
-from spyderlib.baseconfig import _
-from spyderlib.guiconfig import get_font, new_shortcut
-from spyderlib.py3compat import io, is_text_string, to_text_string, PY2
+from spyderlib.config.base import _
+from spyderlib.config.gui import get_font, new_shortcut
+from spyderlib.py3compat import PY2, io, is_text_string, to_text_string
 from spyderlib.utils import encoding
-from spyderlib.widgets.arrayeditor import get_idx_rect
+from spyderlib.widgets.variableexplorer.arrayeditor import get_idx_rect
 
 from pandas import DataFrame, Series
 import numpy as np
@@ -370,6 +370,10 @@ class DataFrameModel(QAbstractTableModel):
         else:
             return self.cols_loaded + 1
 
+    def reset(self):
+        self.beginResetModel()
+        self.endResetModel()
+
 
 class DataFrameView(QTableView):
     """Data Frame view class"""
@@ -379,14 +383,13 @@ class DataFrameView(QTableView):
 
         self.sort_old = [None]
         self.header_class = self.horizontalHeader()
-        self.connect(self.header_class,
-                     SIGNAL("sectionClicked(int)"), self.sortByColumn)
+        self.header_class.sectionClicked.connect(self.sortByColumn)
         self.menu = self.setup_menu()
         new_shortcut(QKeySequence.Copy, self, self.copy)
-        self.connect(self.horizontalScrollBar(), SIGNAL("valueChanged(int)"),
-                     lambda val: self.load_more_data(val, columns=True))
-        self.connect(self.verticalScrollBar(), SIGNAL("valueChanged(int)"),
-                     lambda val: self.load_more_data(val, rows=True))
+        self.horizontalScrollBar().valueChanged.connect(
+                            lambda val: self.load_more_data(val, columns=True))
+        self.verticalScrollBar().valueChanged.connect(
+                               lambda val: self.load_more_data(val, rows=True))
     
     def load_more_data(self, value, rows=False, columns=False):
         if rows and value == self.verticalScrollBar().maximum():
@@ -415,9 +418,9 @@ class DataFrameView(QTableView):
 
     def setup_menu(self):
         """Setup context menu"""
-        copy_action = create_action(self, _( "Copy"),
-                                    shortcut=keybinding("Copy"),
-                                    icon=get_icon('editcopy.png'),
+        copy_action = create_action(self, _('Copy'),
+                                    shortcut=keybinding('Copy'),
+                                    icon=ima.icon('editcopy'),
                                     triggered=self.copy,
                                     context=Qt.WidgetShortcut)
         functions = ((_("To bool"), bool), (_("To complex"), complex),
@@ -439,8 +442,11 @@ class DataFrameView(QTableView):
         index_list = self.selectedIndexes()
         [model.setData(i, '', change_type=func) for i in index_list]
 
+    @Slot()
     def copy(self):
         """Copy text to clipboard"""
+        if not self.selectedIndexes():
+            return
         (row_min, row_max,
          col_min, col_max) = get_idx_rect(self.selectedIndexes())
         index = header = False
@@ -457,7 +463,10 @@ class DataFrameView(QTableView):
             obj = df.iloc[slice(row_min, row_max+1), slice(col_min-1, col_max)]
             output = io.StringIO()
             obj.to_csv(output, sep='\t', index=index, header=header)
-            contents = output.getvalue()
+            if not PY2:
+                contents = output.getvalue()
+            else:
+                contents = output.getvalue().decode('utf-8')
             output.close()
         clipboard = QApplication.clipboard()
         clipboard.setText(contents)
@@ -482,7 +491,7 @@ class DataFrameEditor(QDialog):
         """
         self.layout = QGridLayout()
         self.setLayout(self.layout)
-        self.setWindowIcon(get_icon('arredit.png'))
+        self.setWindowIcon(ima.icon('arredit'))
         if title:
             title = to_text_string(title) + " - %s" % data.__class__.__name__
         else:
@@ -507,30 +516,28 @@ class DataFrameEditor(QDialog):
         btn = QPushButton(_("Format"))
         # disable format button for int type
         btn_layout.addWidget(btn)
-        self.connect(btn, SIGNAL("clicked()"), self.change_format)
+        btn.clicked.connect(self.change_format)
         btn = QPushButton(_('Resize'))
         btn_layout.addWidget(btn)
-        self.connect(btn, SIGNAL("clicked()"), self.resize_to_contents)
+        btn.clicked.connect(self.resize_to_contents)
 
         bgcolor = QCheckBox(_('Background color'))
         bgcolor.setChecked(self.dataModel.bgcolor_enabled)
         bgcolor.setEnabled(self.dataModel.bgcolor_enabled)
-        self.connect(bgcolor, SIGNAL("stateChanged(int)"),
-                     self.change_bgcolor_enable)
+        bgcolor.stateChanged.connect(self.change_bgcolor_enable)
         btn_layout.addWidget(bgcolor)
 
         self.bgcolor_global = QCheckBox(_('Column min/max'))
         self.bgcolor_global.setChecked(self.dataModel.colum_avg_enabled)
         self.bgcolor_global.setEnabled(not self.is_series and
                                        self.dataModel.bgcolor_enabled)
-        self.connect(self.bgcolor_global, SIGNAL("stateChanged(int)"),
-                     self.dataModel.colum_avg)
+        self.bgcolor_global.stateChanged.connect(self.dataModel.colum_avg)
         btn_layout.addWidget(self.bgcolor_global)
 
         btn_layout.addStretch()
         bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
-        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
-        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
+        bbox.accepted.connect(self.accept)
+        bbox.rejected.connect(self.reject)
         btn_layout.addWidget(bbox)
 
         self.layout.addLayout(btn_layout, 2, 0)
@@ -578,19 +585,26 @@ class DataFrameEditor(QDialog):
         QApplication.restoreOverrideCursor()
 
 
+#==============================================================================
+# Tests
+#==============================================================================
 def test_edit(data, title="", parent=None):
     """Test subroutine"""
+    app = qapplication()                  # analysis:ignore
     dlg = DataFrameEditor(parent=parent)
-    if dlg.setup_and_check(data, title=title) and dlg.exec_():
+
+    if dlg.setup_and_check(data, title=title):
+        dlg.exec_()
         return dlg.get_value()
     else:
         import sys
-        sys.exit()
+        sys.exit(1)
 
 
 def test():
     """DataFrame editor test"""
     from numpy import nan
+    from pandas.util.testing import assert_frame_equal, assert_series_equal
 
     df1 = DataFrame([
                      [True, "bool"],
@@ -606,19 +620,22 @@ def test():
                            "Test global max", 'd'],
                     columns=[nan, 'Type'])
     out = test_edit(df1)
-    print("out:", out)
+    assert_frame_equal(df1, out)
+
+    result = Series([True, "bool"], index=[nan, 'Type'], name='a')
     out = test_edit(df1.iloc[0])
-    print("out:", out)
-    df1 = DataFrame(np.random.rand(100001, 10))
+    assert_series_equal(result, out)
+
     # Sorting large DataFrame takes time
+    df1 = DataFrame(np.random.rand(100100, 10))
     df1.sort(columns=[0, 1], inplace=True)
     out = test_edit(df1)
-    print("out:", out)
-    out = test_edit(Series(np.arange(10)))
-    print("out:", out)
-    return out
+    assert_frame_equal(out, df1)
+
+    series = Series(np.arange(10), name=0)
+    out = test_edit(series)
+    assert_series_equal(series, out)
 
 
 if __name__ == '__main__':
-    _app = qapplication()
-    df = test()
+    test()
diff --git a/spyderlib/widgets/importwizard.py b/spyderlib/widgets/variableexplorer/importwizard.py
similarity index 89%
rename from spyderlib/widgets/importwizard.py
rename to spyderlib/widgets/variableexplorer/importwizard.py
index cd5d3b3..4e9384f 100644
--- a/spyderlib/widgets/importwizard.py
+++ b/spyderlib/widgets/variableexplorer/importwizard.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -16,9 +16,10 @@ from spyderlib.qt.QtGui import (QTableView, QVBoxLayout, QHBoxLayout,
                                 QSizePolicy, QCheckBox, QColor, QRadioButton,
                                 QLineEdit, QFrame, QMenu, QIntValidator,
                                 QGroupBox, QMessageBox)
-from spyderlib.qt.QtCore import (Qt, QModelIndex, QAbstractTableModel,
-                                 SIGNAL, SLOT, Slot)
+from spyderlib.qt.QtCore import (Qt, QModelIndex, QAbstractTableModel, Signal,
+                                 Slot)
 from spyderlib.qt.compat import to_qvariant
+import spyderlib.utils.icon_manager as ima
 
 from functools import partial as ft_partial
 
@@ -28,11 +29,12 @@ except ImportError:
     pd = None
 
 # Local import
-from spyderlib.baseconfig import _
+from spyderlib.config.base import _
 from spyderlib.utils import programs
-from spyderlib.utils.qthelpers import get_icon, add_actions, create_action
-from spyderlib.py3compat import (TEXT_TYPES, INT_TYPES, to_text_string, u,
-                                 zip_longest, io)
+from spyderlib.utils.qthelpers import add_actions, create_action
+from spyderlib.py3compat import (TEXT_TYPES, INT_TYPES, to_text_string, io,
+                                 zip_longest)
+
 
 def try_to_parse(value):
     _types = ('int', 'float')
@@ -97,8 +99,11 @@ def get_color(value, alpha):
     color.setAlphaF(alpha)
     return color
 
+
 class ContentsWidget(QWidget):
     """Import wizard contents widget"""
+    asDataChanged = Signal(bool)
+    
     def __init__(self, parent, text):
         QWidget.__init__(self, parent)
 
@@ -145,8 +150,7 @@ class ContentsWidget(QWidget):
         self.line_edt = QLineEdit(",")
         self.line_edt.setMaximumWidth(30)
         self.line_edt.setEnabled(True)
-        self.connect(other_btn_col, SIGNAL("toggled(bool)"),
-                     self.line_edt, SLOT("setEnabled(bool)"))
+        other_btn_col.toggled.connect(self.line_edt.setEnabled)
         grid_layout.addWidget(self.line_edt, 0, 2)
 
         row_label = QLabel(_("Row separator:"))
@@ -163,8 +167,7 @@ class ContentsWidget(QWidget):
         self.line_edt_row = QLineEdit(";")
         self.line_edt_row.setMaximumWidth(30)
         self.line_edt_row.setEnabled(False)
-        self.connect(other_btn_row, SIGNAL("toggled(bool)"),
-                     self.line_edt_row, SLOT("setEnabled(bool)"))
+        other_btn_row.toggled.connect(self.line_edt_row.setEnabled)
         grid_layout.addWidget(self.line_edt_row, 1, 2)
 
         grid_layout.setRowMinimumHeight(2, 15)
@@ -199,12 +202,9 @@ class ContentsWidget(QWidget):
         opts_frame = QFrame()
         opts_frame.setLayout(grid_layout)
 
-        self.connect(data_btn, SIGNAL("toggled(bool)"),
-                     opts_frame, SLOT("setEnabled(bool)"))
-        self.connect(data_btn, SIGNAL("toggled(bool)"),
-                     self, SLOT("set_as_data(bool)"))
-        self.connect(code_btn, SIGNAL("toggled(bool)"),
-                     self, SLOT("set_as_code(bool)"))
+        data_btn.toggled.connect(opts_frame.setEnabled)
+        data_btn.toggled.connect(self.set_as_data)
+        code_btn.toggled.connect(self.set_as_code)
 #        self.connect(txt_btn, SIGNAL("toggled(bool)"),
 #                     self, SLOT("is_text(bool)"))
 
@@ -230,13 +230,13 @@ class ContentsWidget(QWidget):
     def get_col_sep(self):
         """Return the column separator"""
         if self.tab_btn.isChecked():
-            return u("\t")
+            return u"\t"
         return to_text_string(self.line_edt.text())
 
     def get_row_sep(self):
         """Return the row separator"""
         if self.eol_btn.isChecked():
-            return u("\n")
+            return u"\n"
         return to_text_string(self.line_edt_row.text())
 
     def get_skiprows(self):
@@ -251,7 +251,7 @@ class ContentsWidget(QWidget):
     def set_as_data(self, as_data):
         """Set if data type conversion"""
         self._as_data = as_data
-        self.emit(SIGNAL("asDataChanged(bool)"), as_data)
+        self.asDataChanged.emit(as_data)
 
     @Slot(bool)
     def set_as_code(self, as_code):
@@ -321,10 +321,14 @@ class PreviewTableModel(QAbstractTableModel):
             elif kwargs['atype'] == "float":
                 self._data[index.row()][index.column()] = float(
                     self._data[index.row()][index.column()])
-            self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"), index, index)
+            self.dataChanged.emit(index, index)
         except Exception as instance:
             print(instance)
 
+    def reset(self):
+        self.beginResetModel()
+        self.endResetModel()
+
 class PreviewTable(QTableView):
     """Import wizard preview widget"""
     def __init__(self, parent):
@@ -361,7 +365,7 @@ class PreviewTable(QTableView):
         add_actions( self.opt_menu, (self.str_action, self.int_action,
                                      self.float_action))
 
-    def _shape_text(self, text, colsep=u("\t"), rowsep=u("\n"),
+    def _shape_text(self, text, colsep=u"\t", rowsep=u"\n",
                     transpose=False, skiprows=0, comments='#'):
         """Decode the shape of the given text"""
         assert colsep != rowsep
@@ -392,7 +396,7 @@ class PreviewTable(QTableView):
             return None
         return self._model.get_data()
 
-    def process_data(self, text, colsep=u("\t"), rowsep=u("\n"),
+    def process_data(self, text, colsep=u"\t", rowsep=u"\n",
                      transpose=False, skiprows=0, comments='#'):
         """Put data into table model"""
         data = self._shape_text(text, colsep, rowsep, transpose, skiprows,
@@ -400,6 +404,7 @@ class PreviewTable(QTableView):
         self._model = PreviewTableModel(data)
         self.setModel(self._model)
 
+    @Slot()
     def parse_to_type(self,**kwargs):
         """Parse to a given type"""
         indexes = self.selectedIndexes()
@@ -412,6 +417,7 @@ class PreviewTable(QTableView):
         self.opt_menu.popup(event.globalPos())
         event.accept()
 
+
 class PreviewWidget(QWidget):
     """Import wizard preview widget"""
 
@@ -450,7 +456,7 @@ class PreviewWidget(QWidget):
         vert_layout.addWidget(self._table_view)
         self.setLayout(vert_layout)
 
-    def open_data(self, text, colsep=u("\t"), rowsep=u("\n"),
+    def open_data(self, text, colsep=u"\t", rowsep=u"\n",
                   transpose=False, skiprows=0, comments='#'):
         """Open clipboard text as table"""
         if pd:
@@ -464,6 +470,7 @@ class PreviewWidget(QWidget):
         """Return table data"""
         return self._table_view.get_data()
 
+
 class ImportWizard(QDialog):
     """Text data import wizard"""
     def __init__(self, parent, text,
@@ -480,7 +487,7 @@ class ImportWizard(QDialog):
             title = _("Import wizard")
         self.setWindowTitle(title)
         if icon is None:
-            self.setWindowIcon(get_icon("fileimport.png"))
+            self.setWindowIcon(ima.icon('fileimport'))
         if contents_title is None:
             contents_title = _("Raw text")
 
@@ -511,29 +518,24 @@ class ImportWizard(QDialog):
         btns_layout = QHBoxLayout()
         cancel_btn = QPushButton(_("Cancel"))
         btns_layout.addWidget(cancel_btn)
-        self.connect(cancel_btn, SIGNAL("clicked()"), self, SLOT("reject()"))
+        cancel_btn.clicked.connect(self.reject)
         h_spacer = QSpacerItem(40, 20,
                                QSizePolicy.Expanding, QSizePolicy.Minimum)
         btns_layout.addItem(h_spacer)
         self.back_btn = QPushButton(_("Previous"))
         self.back_btn.setEnabled(False)
         btns_layout.addWidget(self.back_btn)
-        self.connect(self.back_btn, SIGNAL("clicked()"),
-                     ft_partial(self._set_step, step=-1))
+        self.back_btn.clicked.connect(ft_partial(self._set_step, step=-1))
         self.fwd_btn = QPushButton(_("Next"))
         btns_layout.addWidget(self.fwd_btn)
-        self.connect(self.fwd_btn, SIGNAL("clicked()"),
-                     ft_partial(self._set_step, step=1))
+        self.fwd_btn.clicked.connect(ft_partial(self._set_step, step=1))
         self.done_btn = QPushButton(_("Done"))
         self.done_btn.setEnabled(False)
         btns_layout.addWidget(self.done_btn)
-        self.connect(self.done_btn, SIGNAL("clicked()"),
-                     self, SLOT("process()"))
+        self.done_btn.clicked.connect(self.process)
 
-        self.connect(self.text_widget, SIGNAL("asDataChanged(bool)"),
-                     self.fwd_btn, SLOT("setEnabled(bool)"))
-        self.connect(self.text_widget, SIGNAL("asDataChanged(bool)"),
-                     self.done_btn, SLOT("setDisabled(bool)"))
+        self.text_widget.asDataChanged.connect(self.fwd_btn.setEnabled)
+        self.text_widget.asDataChanged.connect(self.done_btn.setDisabled)
         layout = QVBoxLayout()
         layout.addLayout(name_layout)
         layout.addWidget(self.tab_widget)
@@ -634,4 +636,4 @@ def test(text):
         print(dialog.get_data())
 
 if __name__ == "__main__":
-    test(u("17/11/1976\t1.34\n14/05/09\t3.14"))
+    test(u"17/11/1976\t1.34\n14/05/09\t3.14")
diff --git a/spyderlib/widgets/externalshell/namespacebrowser.py b/spyderlib/widgets/variableexplorer/namespacebrowser.py
similarity index 88%
rename from spyderlib/widgets/externalshell/namespacebrowser.py
rename to spyderlib/widgets/variableexplorer/namespacebrowser.py
index 2822ed2..95e7fbc 100644
--- a/spyderlib/widgets/externalshell/namespacebrowser.py
+++ b/spyderlib/widgets/variableexplorer/namespacebrowser.py
@@ -1,10 +1,14 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
-"""Namespace browser widget"""
+"""
+Namespace browser widget
+
+This is the main widget used in the Variable Explorer plugin
+"""
 
 import os.path as osp
 import socket
@@ -12,25 +16,26 @@ import socket
 from spyderlib.qt.QtGui import (QWidget, QVBoxLayout, QHBoxLayout, QMenu,
                                 QToolButton, QMessageBox, QApplication,
                                 QCursor, QInputDialog)
-from spyderlib.qt.QtCore import SIGNAL, Qt, Signal
+from spyderlib.qt.QtCore import Qt, Signal, Slot
 from spyderlib.qt.compat import getopenfilenames, getsavefilename
+import spyderlib.utils.icon_manager as ima
 
 # Local imports
 from spyderlib.widgets.externalshell.monitor import (
             monitor_set_global, monitor_get_global, monitor_del_global,
             monitor_copy_global, monitor_save_globals, monitor_load_globals,
             communicate, REMOTE_SETTINGS)
-from spyderlib.widgets.dicteditor import (RemoteDictEditorTableView,
-                                          DictEditorTableView)
-from spyderlib.widgets.dicteditorutils import globalsfilter
+from spyderlib.widgets.variableexplorer.collectionseditor import (
+                  RemoteCollectionsEditorTableView, CollectionsEditorTableView)
+from spyderlib.widgets.variableexplorer.utils import globalsfilter
 from spyderlib.utils import encoding
 from spyderlib.utils.misc import fix_reference_name
 from spyderlib.utils.programs import is_module_installed
-from spyderlib.utils.qthelpers import (get_icon, create_toolbutton,
-                                       add_actions, create_action)
+from spyderlib.utils.qthelpers import (create_toolbutton, add_actions,
+                                       create_action)
 from spyderlib.utils.iofuncs import iofunctions
-from spyderlib.widgets.importwizard import ImportWizard
-from spyderlib.baseconfig import _, get_supported_types
+from spyderlib.widgets.variableexplorer.importwizard import ImportWizard
+from spyderlib.config.base import _, get_supported_types
 from spyderlib.py3compat import is_text_string, to_text_string, getcwd
 
 
@@ -40,6 +45,8 @@ SUPPORTED_TYPES = get_supported_types()
 class NamespaceBrowser(QWidget):
     """Namespace browser (global variables explorer widget)"""
     sig_option_changed = Signal(str, object)
+    sig_collapse = Signal()
+    
     def __init__(self, parent):
         QWidget.__init__(self, parent)
         
@@ -103,13 +110,14 @@ class NamespaceBrowser(QWidget):
                 self.auto_refresh_button.setChecked(autorefresh)
             self.refresh_table()
             return
-        
+
         # Dict editor:
         if self.is_internal_shell:
-            self.editor = DictEditorTableView(self, None, truncate=truncate,
-                                              minmax=minmax)
+            self.editor = CollectionsEditorTableView(self, None,
+                                                     truncate=truncate,
+                                                     minmax=minmax)
         else:
-            self.editor = RemoteDictEditorTableView(self, None,
+            self.editor = RemoteCollectionsEditorTableView(self, None,
                             truncate=truncate, minmax=minmax,
                             remote_editing=remote_editing,
                             get_value_func=self.get_value,
@@ -131,21 +139,37 @@ class NamespaceBrowser(QWidget):
                             show_image_func=self.show_image)
         self.editor.sig_option_changed.connect(self.sig_option_changed.emit)
         self.editor.sig_files_dropped.connect(self.import_data)
-        
-        
+
         # Setup layout
-        hlayout = QHBoxLayout()
-        vlayout = QVBoxLayout()
+        layout = QVBoxLayout()
+        blayout = QHBoxLayout()
         toolbar = self.setup_toolbar(exclude_private, exclude_uppercase,
                                      exclude_capitalized, exclude_unsupported,
                                      autorefresh)
-        vlayout.setAlignment(Qt.AlignTop)
         for widget in toolbar:
-            vlayout.addWidget(widget)
-        hlayout.addWidget(self.editor)
-        hlayout.addLayout(vlayout)
-        self.setLayout(hlayout)
-        hlayout.setContentsMargins(0, 0, 0, 0)
+            blayout.addWidget(widget)
+
+        # Options menu
+        options_button = create_toolbutton(self, text=_('Options'),
+                                           icon=ima.icon('tooloptions'))
+        options_button.setPopupMode(QToolButton.InstantPopup)
+        menu = QMenu(self)
+        editor = self.editor
+        actions = [self.exclude_private_action, self.exclude_uppercase_action,
+                   self.exclude_capitalized_action,
+                   self.exclude_unsupported_action, None,
+                   editor.truncate_action]
+        if is_module_installed('numpy'):
+            actions.append(editor.minmax_action)
+        add_actions(menu, actions)
+        options_button.setMenu(menu)
+
+        blayout.addStretch()
+        blayout.addWidget(options_button)
+        layout.addLayout(blayout)
+        layout.addWidget(self.editor)
+        self.setLayout(layout)
+        layout.setContentsMargins(0, 0, 0, 0)
 
         self.sig_option_changed.connect(self.option_changed)
         
@@ -170,24 +194,24 @@ class NamespaceBrowser(QWidget):
                           
         toolbar = []
 
-        refresh_button = create_toolbutton(self, text=_("Refresh"),
-                                           icon=get_icon('reload.png'),
+        refresh_button = create_toolbutton(self, text=_('Refresh'),
+                                           icon=ima.icon('reload'),
                                            triggered=self.refresh_table)
         self.auto_refresh_button = create_toolbutton(self,
-                                           text=_("Refresh periodically"),
-                                           icon=get_icon('auto_reload.png'),
+                                           text=_('Refresh periodically'),
+                                           icon=ima.icon('auto_reload'),
                                            toggled=self.toggle_auto_refresh)
         self.auto_refresh_button.setChecked(autorefresh)
-        load_button = create_toolbutton(self, text=_("Import data"),
-                                        icon=get_icon('fileimport.png'),
-                                        triggered=self.import_data)
+        load_button = create_toolbutton(self, text=_('Import data'),
+                                        icon=ima.icon('fileimport'),
+                                        triggered=lambda: self.import_data())
         self.save_button = create_toolbutton(self, text=_("Save data"),
-                            icon=get_icon('filesave.png'),
+                            icon=ima.icon('filesave'),
                             triggered=lambda: self.save_data(self.filename))
         self.save_button.setEnabled(False)
         save_as_button = create_toolbutton(self,
                                            text=_("Save data as..."),
-                                           icon=get_icon('filesaveas.png'),
+                                           icon=ima.icon('filesaveas'),
                                            triggered=self.save_data)
         toolbar += [refresh_button, self.auto_refresh_button, load_button,
                     self.save_button, save_as_button]
@@ -223,21 +247,6 @@ class NamespaceBrowser(QWidget):
                 self.sig_option_changed.emit('exclude_unsupported', state))
         self.exclude_unsupported_action.setChecked(exclude_unsupported)
         
-        options_button = create_toolbutton(self, text=_("Options"),
-                                           icon=get_icon('tooloptions.png'))
-        toolbar.append(options_button)
-        options_button.setPopupMode(QToolButton.InstantPopup)
-        menu = QMenu(self)
-        editor = self.editor
-        actions = [self.exclude_private_action, self.exclude_uppercase_action,
-                   self.exclude_capitalized_action,
-                   self.exclude_unsupported_action, None,
-                   editor.truncate_action]
-        if is_module_installed('numpy'):
-            actions.append(editor.minmax_action)
-        add_actions(menu, actions)
-        options_button.setMenu(menu)
-        
         self.setup_in_progress = False
         
         return toolbar
@@ -266,6 +275,7 @@ class NamespaceBrowser(QWidget):
         #     self.refresh_table()
         pass
 
+    @Slot(bool)
     def toggle_auto_refresh(self, state):
         """Toggle auto refresh state"""
         self.autorefresh = state
@@ -305,7 +315,8 @@ class NamespaceBrowser(QWidget):
         for name in REMOTE_SETTINGS:
             settings[name] = getattr(self, name)
         return settings
-        
+
+    @Slot()
     def refresh_table(self):
         """Refresh variable table"""
         if self.is_visible and self.isVisible():
@@ -386,7 +397,7 @@ class NamespaceBrowser(QWidget):
     def is_series(self, name):
         """Return True if variable is a Series"""
         return communicate(self._get_sock(),
-             "isinstance(globals()['%s'], Series)" % name)   
+             "isinstance(globals()['%s'], Series)" % name)
 
     def get_array_shape(self, name):
         """Return array's shape"""
@@ -424,12 +435,12 @@ class NamespaceBrowser(QWidget):
             self.ipyclient.shellwidget.execute(command)
         else:
             self.shellwidget.send_to_process(command)
-        
+
     def oedit(self, name):
-        command = "from spyderlib.widgets.objecteditor import oedit; " \
+        command = "from spyderlib.widgets.variableexplorer.objecteditor import oedit; " \
                   "oedit('%s', modal=False, namespace=locals());" % name
         self.shellwidget.send_to_process(command)
-        
+
     #------ Set, load and save data -------------------------------------------
     def set_data(self, data):
         """Set data"""
@@ -439,8 +450,9 @@ class NamespaceBrowser(QWidget):
         
     def collapse(self):
         """Collapse"""
-        self.emit(SIGNAL('collapse()'))
-        
+        self.sig_collapse.emit()
+
+    @Slot(list)
     def import_data(self, filenames=None):
         """Import data from text file"""
         title = _("Import data")
@@ -456,12 +468,10 @@ class NamespaceBrowser(QWidget):
         elif is_text_string(filenames):
             filenames = [filenames]
 
-            
         for filename in filenames:
-            
             self.filename = to_text_string(filename)
             ext = osp.splitext(self.filename)[1].lower()
-            
+
             if ext not in iofunctions.load_funcs:
                 buttons = QMessageBox.Yes | QMessageBox.Cancel
                 answer = QMessageBox.question(self, title,
@@ -526,7 +536,7 @@ class NamespaceBrowser(QWidget):
                                        ) % (self.filename, error_message))
             self.refresh_table()
             
-    
+    @Slot()
     def save_data(self, filename=None):
         """Save data"""
         if filename is None:
@@ -558,4 +568,3 @@ class NamespaceBrowser(QWidget):
                             _("<b>Unable to save current workspace</b>"
                               "<br><br>Error message:<br>%s") % error_message)
         self.save_button.setEnabled(self.filename is not None)
-        
diff --git a/spyderlib/widgets/objecteditor.py b/spyderlib/widgets/variableexplorer/objecteditor.py
similarity index 79%
rename from spyderlib/widgets/objecteditor.py
rename to spyderlib/widgets/variableexplorer/objecteditor.py
index b91659d..f3ee2b9 100644
--- a/spyderlib/widgets/objecteditor.py
+++ b/spyderlib/widgets/variableexplorer/objecteditor.py
@@ -1,16 +1,16 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
 """
-Object Editor Dialog based on Qt
+Generic object editor dialog
 """
 
 from __future__ import print_function
 
-from spyderlib.qt.QtCore import QObject, SIGNAL
+from spyderlib.qt.QtCore import QObject
 
 # Local imports
 from spyderlib.py3compat import is_text_string
@@ -27,9 +27,9 @@ class DialogKeeper(QObject):
     
     def create_dialog(self, dialog, refname, func):
         self.dialogs[id(dialog)] = dialog, refname, func
-        self.connect(dialog, SIGNAL('accepted()'),
+        dialog.accepted.connect(
                      lambda eid=id(dialog): self.editor_accepted(eid))
-        self.connect(dialog, SIGNAL('rejected()'),
+        dialog.rejected.connect(
                      lambda eid=id(dialog): self.editor_rejected(eid))
         dialog.show()
         dialog.activateWindow()
@@ -56,15 +56,15 @@ def create_dialog(obj, obj_name):
     oedit to show eMZed related data)
     """
     # Local import
-    from spyderlib.widgets.texteditor import TextEditor
-    from spyderlib.widgets.dicteditorutils import (ndarray, FakeObject,
-                                                   Image, is_known_type,
-                                                   DataFrame, Series)
-    from spyderlib.widgets.dicteditor import DictEditor
-    from spyderlib.widgets.arrayeditor import ArrayEditor
+    from spyderlib.widgets.variableexplorer.texteditor import TextEditor
+    from spyderlib.widgets.variableexplorer.utils import (ndarray, FakeObject,
+                                               Image, is_known_type, DataFrame,
+                                               Series)
+    from spyderlib.widgets.variableexplorer.collectionseditor import CollectionsEditor
+    from spyderlib.widgets.variableexplorer.arrayeditor import ArrayEditor
     if DataFrame is not FakeObject:
-        from spyderlib.widgets.dataframeeditor import DataFrameEditor
-    
+        from spyderlib.widgets.variableexplorer.dataframeeditor import DataFrameEditor
+
     conv_func = lambda data: data
     readonly = not is_known_type(obj)
     if isinstance(obj, ndarray) and ndarray is not FakeObject:
@@ -89,7 +89,7 @@ def create_dialog(obj, obj_name):
     elif is_text_string(obj):
         dialog = TextEditor(obj, title=obj_name, readonly=readonly)
     else:
-        dialog = DictEditor()
+        dialog = CollectionsEditor()
         dialog.setup(obj, title=obj_name, readonly=readonly)
 
     def end_func(dialog):
@@ -141,11 +141,15 @@ def oedit(obj, modal=True, namespace=None):
             app.exec_()
 
 
+#==============================================================================
+# Tests
+#==============================================================================
 def test():
     """Run object editor test"""
     import datetime, numpy as np
     from spyderlib.pil_patch import Image
-    image = Image.fromarray(np.random.random_integers(255, size=(100, 100)))
+    data = np.random.random_integers(255, size=(100, 100)).astype('uint8')
+    image = Image.fromarray(data)
     example = {'str': 'kjkj kj k j j kj k jkj',
                'list': [1, 3, 4, 'kjkj', None],
                'dict': {'d': 1, 'a': np.random.rand(10, 10), 'b': [1, 2]},
@@ -160,11 +164,13 @@ def test():
         def __init__(self):
             self.text = "toto"
     foobar = Foobar()
+
     print(oedit(foobar))
     print(oedit(example))
     print(oedit(np.random.rand(10, 10)))
     print(oedit(oedit.__doc__))
     print(example)
-    
+
+
 if __name__ == "__main__":
     test()
diff --git a/spyderlib/widgets/texteditor.py b/spyderlib/widgets/variableexplorer/texteditor.py
similarity index 73%
rename from spyderlib/widgets/texteditor.py
rename to spyderlib/widgets/variableexplorer/texteditor.py
index c523e0d..8a7aa69 100644
--- a/spyderlib/widgets/texteditor.py
+++ b/spyderlib/widgets/variableexplorer/texteditor.py
@@ -1,22 +1,22 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
 """
-Text Editor Dialog based on Qt
+Text editor dialog
 """
 
 from __future__ import print_function
 
-from spyderlib.qt.QtCore import Qt, SIGNAL, SLOT
+from spyderlib.qt.QtCore import Qt
 from spyderlib.qt.QtGui import QVBoxLayout, QTextEdit, QDialog, QDialogButtonBox
+import spyderlib.utils.icon_manager as ima
 
 # Local import
-from spyderlib.baseconfig import _
-from spyderlib.guiconfig import get_font
-from spyderlib.utils.qthelpers import get_icon
+from spyderlib.config.base import _
+from spyderlib.config.gui import get_font
 from spyderlib.py3compat import (to_text_string, to_binary_string,
                                  is_binary_string)
 
@@ -48,7 +48,7 @@ class TextEditor(QDialog):
 
         # Text edit
         self.edit = QTextEdit(parent)
-        self.connect(self.edit, SIGNAL('textChanged()'), self.text_changed)
+        self.edit.textChanged.connect(self.text_changed)
         self.edit.setReadOnly(readonly)
         self.edit.setPlainText(text)
         if font is None:
@@ -61,14 +61,14 @@ class TextEditor(QDialog):
         if not readonly:
             buttons = buttons | QDialogButtonBox.Cancel
         bbox = QDialogButtonBox(buttons)
-        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
-        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
+        bbox.accepted.connect(self.accept)
+        bbox.rejected.connect(self.reject)
         self.layout.addWidget(bbox)
         
         # Make the dialog act as a window
         self.setWindowFlags(Qt.Window)
         
-        self.setWindowIcon(get_icon('edit.png'))
+        self.setWindowIcon(ima.icon('edit'))
         self.setWindowTitle(_("Text editor") + \
                             "%s" % (" - "+str(title) if str(title) else ""))
         self.resize(size[0], size[1])
@@ -86,24 +86,24 @@ class TextEditor(QDialog):
         # It is import to avoid accessing Qt C++ object as it has probably
         # already been destroyed, due to the Qt.WA_DeleteOnClose attribute
         return self.text
-    
-    
+
+
+#==============================================================================
+# Tests
+#==============================================================================
 def test():
     """Text editor demo"""
     from spyderlib.utils.qthelpers import qapplication
     _app = qapplication()  # analysis:ignore
-    dialog = TextEditor("""
-    01234567890123456789012345678901234567890123456789012345678901234567890123456789
-    dedekdh elkd ezd ekjd lekdj elkdfjelfjk e
-    """)
-    dialog.show()
-    if dialog.exec_():
-        text = dialog.get_value()
-        print("Accepted:", text)
-        dialog = TextEditor(text)
-        dialog.exec_()
-    else:
-        print("Canceled")
+
+    text = """01234567890123456789012345678901234567890123456789012345678901234567890123456789
+dedekdh elkd ezd ekjd lekdj elkdfjelfjk e"""
+    dialog = TextEditor(text)
+    dialog.exec_()
+
+    dlg_text = dialog.get_value()
+    assert text == dlg_text
+
 
 if __name__ == "__main__":
-    test()
\ No newline at end of file
+    test()
diff --git a/spyderlib/widgets/dicteditorutils.py b/spyderlib/widgets/variableexplorer/utils.py
similarity index 61%
rename from spyderlib/widgets/dicteditorutils.py
rename to spyderlib/widgets/variableexplorer/utils.py
index 716b28c..0dbd7bf 100644
--- a/spyderlib/widgets/dicteditorutils.py
+++ b/spyderlib/widgets/variableexplorer/utils.py
@@ -1,11 +1,11 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2011 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
 """
-Utilities for the Dictionary Editor Widget and Dialog based on Qt
+Utilities for the Collections editor widget and dialog
 """
 
 from __future__ import print_function
@@ -15,23 +15,42 @@ import re
 # Local imports
 from spyderlib.py3compat import (NUMERIC_TYPES, TEXT_TYPES, to_text_string,
                                  is_text_string, is_binary_string, reprlib,
-                                 PY2)
+                                 PY2, to_binary_string)
 from spyderlib.utils import programs
 from spyderlib import dependencies
-from spyderlib.baseconfig import _
+from spyderlib.config.base import _
 
 
+#==============================================================================
+# Dependencies
+#==============================================================================
+PANDAS_REQVER = '>=0.13.1'
+dependencies.add('pandas',  _("View and edit DataFrames and Series in the "
+                              "Variable Explorer"),
+                 required_version=PANDAS_REQVER)
+
+NUMPY_REQVER = '>=1.7'
+dependencies.add("numpy", _("View and edit two and three dimensional arrays "
+                            "in the Variable Explorer"),
+                 required_version=NUMPY_REQVER)
+
+#==============================================================================
+# FakeObject
+#==============================================================================
 class FakeObject(object):
     """Fake class used in replacement of missing modules"""
     pass
 
 
-#----Numpy arrays support
+#==============================================================================
+# Numpy arrays support
+#==============================================================================
 try:
     from numpy import ndarray, array, matrix, recarray
     from numpy.ma import MaskedArray
+    from numpy import savetxt as np_savetxt
 except ImportError:
-    ndarray = array = matrix = recarray = MaskedArray = FakeObject  # analysis:ignore
+    ndarray = array = matrix = recarray = MaskedArray = np_savetxt = FakeObject  # analysis:ignore
 
 
 def get_numpy_dtype(obj):
@@ -54,18 +73,18 @@ def get_numpy_dtype(obj):
                 return
 
 
-#----Pandas support
-PANDAS_REQVER = '>=0.13.1'
-dependencies.add('pandas',  _("View and edit DataFrames and Series in the "
-                              "Variable Explorer"),
-                 required_version=PANDAS_REQVER)
+#==============================================================================
+# Pandas support
+#==============================================================================
 if programs.is_module_installed('pandas', PANDAS_REQVER):
     from pandas import DataFrame, Series
 else:
     DataFrame = Series = FakeObject      # analysis:ignore
 
 
-#----PIL Images support
+#==============================================================================
+# PIL Images support
+#==============================================================================
 try:
     from spyderlib import pil_patch
     Image = pil_patch.Image.Image
@@ -73,7 +92,9 @@ except ImportError:
     Image = FakeObject  # analysis:ignore
 
 
-#----BeautifulSoup support (see Issue 2448)
+#==============================================================================
+# BeautifulSoup support (see Issue 2448)
+#==============================================================================
 try:
     import bs4
     NavigableString = bs4.element.NavigableString
@@ -81,15 +102,41 @@ except ImportError:
     NavigableString = FakeObject  # analysis:ignore
 
 
-#----Misc.
+#==============================================================================
+# Misc.
+#==============================================================================
 def address(obj):
     """Return object address as a string: '<classname @ address>'"""
     return "<%s @ %s>" % (obj.__class__.__name__,
                           hex(id(obj)).upper().replace('X', 'x'))
 
 
-#----Set limits for the amount of elements in the repr of collections
-#    (lists, dicts, tuples and sets)
+def try_to_eval(value):
+    """Try to eval value"""
+    try:
+        return eval(value)
+    except (NameError, SyntaxError, ImportError):
+        return value
+
+    
+def get_size(item):
+    """Return size of an item of arbitrary type"""
+    if isinstance(item, (list, tuple, dict)):
+        return len(item)
+    elif isinstance(item, (ndarray, MaskedArray)):
+        return item.shape
+    elif isinstance(item, Image):
+        return item.size
+    if isinstance(item, (DataFrame, Series)):
+        return item.shape
+    else:
+        return 1
+
+
+#==============================================================================
+# Set limits for the amount of elements in the repr of collections (lists,
+# dicts, tuples and sets)
+#==============================================================================
 CollectionsRepr = reprlib.Repr()
 CollectionsRepr.maxlist = 10
 CollectionsRepr.maxdict = 10
@@ -97,14 +144,20 @@ CollectionsRepr.maxtuple = 10
 CollectionsRepr.maxset = 10
 
 
-#----date and datetime objects support
+#==============================================================================
+# Date and datetime objects support
+#==============================================================================
 import datetime
+
+
 try:
     from dateutil.parser import parse as dateparse
 except ImportError:
     def dateparse(datestr):  # analysis:ignore
         """Just for 'year, month, day' strings"""
         return datetime.datetime( *list(map(int, datestr.split(','))) )
+
+
 def datestr_to_datetime(value):
     rp = value.rfind('(')+1
     v = dateparse(value[rp:-1])
@@ -112,7 +165,9 @@ def datestr_to_datetime(value):
     return v
 
 
-#----Background colors for supported types
+#==============================================================================
+# Background colors for supported types
+#==============================================================================
 ARRAY_COLOR = "#00ff00"
 SCALAR_COLOR = "#0000ff"
 COLORS = {
@@ -149,13 +204,16 @@ def get_color_name(value):
         else:
             return ARRAY_COLOR
 
+
 def is_editable_type(value):
     """Return True if data type is editable with a standard GUI-based editor,
-    like DictEditor, ArrayEditor, QDateEdit or a simple QLineEdit"""
+    like CollectionsEditor, ArrayEditor, QDateEdit or a simple QLineEdit"""
     return get_color_name(value) not in (UNSUPPORTED_COLOR, CUSTOM_TYPE_COLOR)
 
 
-#----Sorting
+#==============================================================================
+# Sorting
+#==============================================================================
 def sort_against(lista, listb, reverse=False):
     """Arrange lista items in the same order as sorted(listb)"""
     try:
@@ -163,19 +221,24 @@ def sort_against(lista, listb, reverse=False):
     except:
         return lista
 
+
 def unsorted_unique(lista):
     """Removes duplicates from lista neglecting its initial ordering"""
     return list(set(lista))
 
 
-#----Display <--> Value
+#==============================================================================
+# Display <--> Value
+#==============================================================================
 def value_to_display(value, truncate=False, trunc_len=80, minmax=False):
     """Convert value for display purpose"""
     try:
         if isinstance(value, recarray):
             fields = value.names
             display = 'Field names: ' + ', '.join(fields)
-        elif minmax and isinstance(value, (ndarray, MaskedArray)):
+        elif isinstance(value, MaskedArray):
+            display = 'Masked array'
+        elif minmax and isinstance(value, ndarray):
             if value.size == 0:
                 display = repr(value)
             try:
@@ -185,6 +248,8 @@ def value_to_display(value, truncate=False, trunc_len=80, minmax=False):
             except ValueError:
                 # Happens when one of the array cell contains a sequence
                 pass
+        elif isinstance(value, ndarray):
+            display = repr(value)
         elif isinstance(value, (list, tuple, dict, set)):
             display = CollectionsRepr.repr(value)
         elif isinstance(value, Image):
@@ -215,36 +280,75 @@ def value_to_display(value, truncate=False, trunc_len=80, minmax=False):
                 pass
         elif is_text_string(value):
             display = value
-        else:
+        elif isinstance(value, NUMERIC_TYPES) or isinstance(value, bool) or \
+          isinstance(value, datetime.date):
             display = repr(value)
+        else:
+            # Note: Don't trust on repr's. They can be inefficient and
+            # so freeze Spyder quite easily
+            # display = repr(value)
+            type_str = to_text_string(type(value))
+            display = type_str[1:-1]
             if truncate and len(display) > trunc_len:
                 display = display[:trunc_len].rstrip() + ' ...'
     except:
-        display = to_text_string(type(value))
+        type_str = to_text_string(type(value))
+        display = type_str[1:-1]
 
     return display
 
 
-def try_to_eval(value):
-    """Try to eval value"""
+
+def display_to_value(value, default_value, ignore_errors=True):
+    """Convert back to value"""
+    from spyderlib.qt.compat import from_qvariant
+    value = from_qvariant(value, to_text_string)
     try:
-        return eval(value)
-    except (NameError, SyntaxError, ImportError):
-        return value
-    
-def get_size(item):
-    """Return size of an item of arbitrary type"""
-    if isinstance(item, (list, tuple, dict)):
-        return len(item)
-    elif isinstance(item, (ndarray, MaskedArray)):
-        return item.shape
-    elif isinstance(item, Image):
-        return item.size
-    if isinstance(item, (DataFrame, Series)):
-        return item.shape
-    else:
-        return 1
+        np_dtype = get_numpy_dtype(default_value)
+        if isinstance(default_value, bool):
+            # We must test for boolean before NumPy data types
+            # because `bool` class derives from `int` class
+            try:
+                value = bool(float(value))
+            except ValueError:
+                value = value.lower() == "true"
+        elif np_dtype is not None:
+            if 'complex' in str(type(default_value)):
+                value = np_dtype(complex(value))
+            else:
+                value = np_dtype(value)
+        elif is_binary_string(default_value):
+            value = to_binary_string(value, 'utf8')
+        elif is_text_string(default_value):
+            value = to_text_string(value)
+        elif isinstance(default_value, complex):
+            value = complex(value)
+        elif isinstance(default_value, float):
+            value = float(value)
+        elif isinstance(default_value, int):
+            try:
+                value = int(value)
+            except ValueError:
+                value = float(value)
+        elif isinstance(default_value, datetime.datetime):
+            value = datestr_to_datetime(value)
+        elif isinstance(default_value, datetime.date):
+            value = datestr_to_datetime(value).date()
+        elif ignore_errors:
+            value = try_to_eval(value)
+        else:
+            value = eval(value)
+    except (ValueError, SyntaxError):
+        if ignore_errors:
+            value = try_to_eval(value)
+        else:
+            return default_value
+    return value
+
 
+#==============================================================================
+# Types
+#==============================================================================
 def get_type_string(item):
     """Return type string of an object"""
     if isinstance(item, DataFrame):
@@ -261,6 +365,7 @@ def is_known_type(item):
     # Unfortunately, the masked array case is specific
     return isinstance(item, MaskedArray) or get_type_string(item) is not None
 
+
 def get_human_readable_type(item):
     """Return human-readable type string of an item"""
     if isinstance(item, (ndarray, MaskedArray)):
@@ -275,7 +380,10 @@ def get_human_readable_type(item):
             return text[text.find('.')+1:]
 
 
-#----Globals filter: filter namespace dictionaries (to be edited in DictEditor)
+#==============================================================================
+# Globals filter: filter namespace dictionaries (to be edited in
+# CollectionsEditor)
+#==============================================================================
 def is_supported(value, check_all=False, filters=None, iterate=True):
     """Return True if the value is supported, False otherwise"""
     assert filters is not None
@@ -300,6 +408,7 @@ def is_supported(value, check_all=False, filters=None, iterate=True):
                     break
     return True
 
+
 def globalsfilter(input_dict, check_all=False, filters=None,
                   exclude_private=None, exclude_capitalized=None,
                   exclude_uppercase=None, exclude_unsupported=None,
diff --git a/spyderplugins/__init__.py b/spyderlib/workers/__init__.py
similarity index 100%
copy from spyderplugins/__init__.py
copy to spyderlib/workers/__init__.py
diff --git a/spyderlib/workers/updates.py b/spyderlib/workers/updates.py
new file mode 100644
index 0000000..924f2ad
--- /dev/null
+++ b/spyderlib/workers/updates.py
@@ -0,0 +1,96 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2009-2013 Pierre Raybaut
+# Copyright © 2013-2015 The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+import json
+import ssl
+
+from spyderlib import __version__
+from spyderlib.config.base import _
+from spyderlib.py3compat import PY3
+from spyderlib.qt.QtCore import Signal, QObject
+from spyderlib.utils.programs import check_version, is_stable_version
+
+
+if PY3:
+    from urllib.request import urlopen
+    from urllib.error import URLError, HTTPError
+else:
+    from urllib2 import urlopen, URLError, HTTPError
+
+
+class WorkerUpdates(QObject):
+    """
+    Worker that checks for releases using the Github API without blocking the
+    Spyder user interface, in case of connections issues.
+    """
+    sig_ready = Signal()
+
+    def __init__(self, parent):
+        QObject.__init__(self)
+        self._parent = parent
+        self.error = None
+        self.latest_release = None
+
+    def check_update_available(self, version, releases):
+        """Checks if there is an update available.
+
+        It takes as parameters the current version of Spyder and a list of
+        valid cleaned releases in chronological order (what github api returns
+        by default). Example: ['2.3.4', '2.3.3' ...]
+        """
+        if is_stable_version(version):
+            # Remove non stable versions from the list
+            releases = [r for r in releases if is_stable_version(r)]
+
+        latest_release = releases[0]
+
+        if version.endswith('dev'):
+            return (False, latest_release)
+
+        return (check_version(version, latest_release, '<'), latest_release)
+
+    def start(self):
+        """Main method of the WorkerUpdates worker"""
+        self.url = 'https://api.github.com/repos/spyder-ide/spyder/releases'
+        self.update_available = False
+        self.latest_release = __version__
+
+        error_msg = None
+
+        try:
+            if hasattr(ssl, '_create_unverified_context'):
+                # Fix for issue # 2685 [Works only with Python >=2.7.9]
+                # More info: https://www.python.org/dev/peps/pep-0476/#opting-out
+                context = ssl._create_unverified_context()
+                page = urlopen(self.url, context=context)
+            else:
+                page = urlopen(self.url)
+            try:
+                data = page.read()
+
+                # Needed step for python3 compatibility
+                if not isinstance(data, str):
+                    data = data.decode()
+
+                data = json.loads(data)
+                releases = [item['tag_name'].replace('v', '') for item in data]
+                version = __version__
+
+                result = self.check_update_available(version, releases)
+                self.update_available, self.latest_release = result
+            except Exception:
+                error_msg = _('Unable to retrieve information.')
+        except HTTPError:
+            error_msg = _('Unable to retrieve information.')
+        except URLError:
+            error_msg = _('Unable to connect to the internet. <br><br>Make '
+                          'sure the connection is working properly.')
+        except Exception:
+            error_msg = _('Unable to check for updates.')
+
+        self.error = error_msg
+        self.sig_ready.emit()
diff --git a/spyderplugins/images/pylint.png b/spyderplugins/images/pylint.png
deleted file mode 100644
index ebba4e1..0000000
Binary files a/spyderplugins/images/pylint.png and /dev/null differ
diff --git a/spyderplugins/io_dicom.py b/spyderplugins/io_dicom.py
deleted file mode 100644
index af4499a..0000000
--- a/spyderplugins/io_dicom.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# -*- coding:utf-8 -*-
-"""Example of I/O plugin for loading DICOM files"""
-
-import os.path as osp
-
-try:
-    import dicom
-    def load_dicom(filename):
-        try:
-            name = osp.splitext(osp.basename(filename))[0]
-            return {name: dicom.ReadFile(filename).PixelArray}, None
-        except Exception as error:
-            return None, str(error)
-except ImportError:
-    load_dicom = None
-
-#===============================================================================
-# The following statements are required to register this I/O plugin:
-#===============================================================================
-FORMAT_NAME = "DICOM images"
-FORMAT_EXT  = ".dcm"
-FORMAT_LOAD = load_dicom
-FORMAT_SAVE = None
diff --git a/spyderplugins/locale/fr/LC_MESSAGES/p_breakpoints.mo b/spyderplugins/locale/fr/LC_MESSAGES/p_breakpoints.mo
deleted file mode 100644
index 484129d..0000000
Binary files a/spyderplugins/locale/fr/LC_MESSAGES/p_breakpoints.mo and /dev/null differ
diff --git a/spyderplugins/locale/fr/LC_MESSAGES/p_profiler.mo b/spyderplugins/locale/fr/LC_MESSAGES/p_profiler.mo
deleted file mode 100644
index 5b2dd66..0000000
Binary files a/spyderplugins/locale/fr/LC_MESSAGES/p_profiler.mo and /dev/null differ
diff --git a/spyderplugins/locale/fr/LC_MESSAGES/p_pylint.mo b/spyderplugins/locale/fr/LC_MESSAGES/p_pylint.mo
deleted file mode 100644
index 811b31f..0000000
Binary files a/spyderplugins/locale/fr/LC_MESSAGES/p_pylint.mo and /dev/null differ
diff --git a/spyderplugins/widgets/__init__.py b/spyderplugins/widgets/__init__.py
deleted file mode 100644
index 790e7e3..0000000
--- a/spyderplugins/widgets/__init__.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright © 2009-2010 Pierre Raybaut
-# Licensed under the terms of the MIT License
-# (see spyderlib/__init__.py for details)
-
-"""
-spyderlib.widgets
-=================
-
-Widgets defined in this module may be used in any other Qt-based application
-
-They are also used in Spyder through the Plugin interface
-(see spyderlib.plugins)
-"""
diff --git a/spyplugins/__init__.py b/spyplugins/__init__.py
new file mode 100644
index 0000000..b98aaa1
--- /dev/null
+++ b/spyplugins/__init__.py
@@ -0,0 +1,12 @@
+"""
+'spyplugins' makes uses of namespace packages to keep different plugins
+organized in the sitepackages directory and in the user directory.
+
+Spyder plugins can be of 'io' type or 'ui' type. Each type also makes use
+of namespace packages.
+
+For more information on namespace packages visit:
+- https://www.python.org/dev/peps/pep-0382/
+- https://www.python.org/dev/peps/pep-0420/
+"""
+__import__('pkg_resources').declare_namespace(__name__)
diff --git a/spyplugins/io/__init__.py b/spyplugins/io/__init__.py
new file mode 100644
index 0000000..f74acdb
--- /dev/null
+++ b/spyplugins/io/__init__.py
@@ -0,0 +1,12 @@
+"""
+'spyplugins' makes uses of namespace packages to keep different plugins
+organized in the sitepackages directory and in the user directory.
+
+Spyder plugins can be of 'io' type or 'ui' type. Each type also makes use
+of namespace packages.
+
+For more information on namespace packages visit:
+- https://www.python.org/dev/peps/pep-0382/
+- https://www.python.org/dev/peps/pep-0420/
+"""
+__import__('pkg_resources').declare_namespace(__name__)
\ No newline at end of file
diff --git a/spyplugins/io/dcm/__init__.py b/spyplugins/io/dcm/__init__.py
new file mode 100644
index 0000000..04f3a59
--- /dev/null
+++ b/spyplugins/io/dcm/__init__.py
@@ -0,0 +1,9 @@
+# =============================================================================
+# The following statements are required to register this I/O plugin:
+# =============================================================================
+from .dcm import load_dicom
+
+FORMAT_NAME = "DICOM images"
+FORMAT_EXT  = ".dcm"
+FORMAT_LOAD = load_dicom
+FORMAT_SAVE = None
\ No newline at end of file
diff --git a/spyplugins/io/dcm/dcm.py b/spyplugins/io/dcm/dcm.py
new file mode 100644
index 0000000..33b6fde
--- /dev/null
+++ b/spyplugins/io/dcm/dcm.py
@@ -0,0 +1,26 @@
+# -*- coding:utf-8 -*-
+"""Example of I/O plugin for loading DICOM files"""
+
+import os.path as osp
+
+try:
+    try:
+        # pydicom 0.9
+        import dicom as dicomio
+    except ImportError:
+        # pydicom 1.0
+        from pydicom import dicomio
+    def load_dicom(filename):
+        try:
+            name = osp.splitext(osp.basename(filename))[0]
+            try:
+                data = dicomio.read_file(filename, force=True)
+            except TypeError:
+                data = dicomio.read_file(filename)                
+            arr = data.pixel_array
+            return {name: arr}, None
+        except Exception as error:
+            return None, str(error)
+except ImportError:
+    load_dicom = None
+
diff --git a/spyplugins/io/hdf5/__init__.py b/spyplugins/io/hdf5/__init__.py
new file mode 100644
index 0000000..1b23fea
--- /dev/null
+++ b/spyplugins/io/hdf5/__init__.py
@@ -0,0 +1,9 @@
+# =============================================================================
+# The following statements are required to register this I/O plugin:
+# =============================================================================
+from .hdf5 import load_hdf5, save_hdf5
+
+FORMAT_NAME = "HDF5"
+FORMAT_EXT  = ".h5"
+FORMAT_LOAD = load_hdf5
+FORMAT_SAVE = save_hdf5
diff --git a/spyderplugins/io_hdf5.py b/spyplugins/io/hdf5/hdf5.py
similarity index 86%
rename from spyderplugins/io_hdf5.py
rename to spyplugins/io/hdf5/hdf5.py
index be19ed6..6b02599 100644
--- a/spyderplugins/io_hdf5.py
+++ b/spyplugins/io/hdf5/hdf5.py
@@ -71,13 +71,6 @@ except ImportError:
     load_hdf5 = None
     save_hdf5 = None
 
-#===============================================================================
-# The following statements are required to register this I/O plugin:
-#===============================================================================
-FORMAT_NAME = "HDF5"
-FORMAT_EXT  = ".h5"
-FORMAT_LOAD = load_hdf5
-FORMAT_SAVE = save_hdf5
 
 if __name__ == "__main__":
     data = {'a' : [1, 2, 3, 4], 'b' : 4.5}
diff --git a/spyplugins/ui/__init__.py b/spyplugins/ui/__init__.py
new file mode 100644
index 0000000..f74acdb
--- /dev/null
+++ b/spyplugins/ui/__init__.py
@@ -0,0 +1,12 @@
+"""
+'spyplugins' makes uses of namespace packages to keep different plugins
+organized in the sitepackages directory and in the user directory.
+
+Spyder plugins can be of 'io' type or 'ui' type. Each type also makes use
+of namespace packages.
+
+For more information on namespace packages visit:
+- https://www.python.org/dev/peps/pep-0382/
+- https://www.python.org/dev/peps/pep-0420/
+"""
+__import__('pkg_resources').declare_namespace(__name__)
\ No newline at end of file
diff --git a/spyplugins/ui/breakpoints/__init__.py b/spyplugins/ui/breakpoints/__init__.py
new file mode 100644
index 0000000..9b8bfbb
--- /dev/null
+++ b/spyplugins/ui/breakpoints/__init__.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+
+#==============================================================================
+# The following statement is required to register this 3rd party plugin:
+#==============================================================================
+from .breakpoints import Breakpoints as PLUGIN_CLASS
diff --git a/spyderplugins/p_breakpoints.py b/spyplugins/ui/breakpoints/breakpoints.py
similarity index 70%
rename from spyderplugins/p_breakpoints.py
rename to spyplugins/ui/breakpoints/breakpoints.py
index 501f9c7..9ef5d7b 100644
--- a/spyderplugins/p_breakpoints.py
+++ b/spyplugins/ui/breakpoints/breakpoints.py
@@ -12,20 +12,24 @@
 # pylint: disable=R0911
 # pylint: disable=R0201
 
-from spyderlib.qt.QtCore import SIGNAL
+# Standard library imports
+import os.path as osp
 
 # Local imports
-from spyderlib.baseconfig import get_translation
-_ = get_translation("p_breakpoints", dirname="spyderplugins")
-from spyderlib.utils.qthelpers import get_icon, create_action
+from spyderlib.config.base import get_translation
+from spyderlib.utils import icon_manager as ima
+from spyderlib.utils.qthelpers import create_action
 from spyderlib.plugins import SpyderPluginMixin
-from spyderplugins.widgets.breakpointsgui import BreakpointWidget
 from spyderlib.py3compat import to_text_string, is_text_string
+from .widgets.breakpointsgui import BreakpointWidget
+
+_ = get_translation("breakpoints", "spyplugins.ui.breakpoints")
 
 
 class Breakpoints(BreakpointWidget, SpyderPluginMixin):
     """Breakpoint list"""
     CONF_SECTION = 'breakpoints'
+
 #    CONFIGWIDGET_CLASS = BreakpointConfigPage
     def __init__(self, parent=None):
         BreakpointWidget.__init__(self, parent=parent)
@@ -42,7 +46,8 @@ class Breakpoints(BreakpointWidget, SpyderPluginMixin):
     
     def get_plugin_icon(self):
         """Return widget icon"""
-        return get_icon('bug.png')
+        path = osp.join(self.PLUGIN_PATH, self.IMG_PATH)
+        return ima.icon('profiler', icon_path=path)
     
     def get_focus_widget(self):
         """
@@ -61,19 +66,14 @@ class Breakpoints(BreakpointWidget, SpyderPluginMixin):
 
     def register_plugin(self):
         """Register plugin in Spyder's main window"""
-        self.connect(self, SIGNAL("edit_goto(QString,int,QString)"),
-                     self.main.editor.load)
-        self.connect(self, SIGNAL('redirect_stdio(bool)'),
-                     self.main.redirect_internalshell_stdio)
-        self.connect(self, SIGNAL('clear_all_breakpoints()'),
-                     self.main.editor.clear_all_breakpoints)
-        self.connect(self, SIGNAL('clear_breakpoint(QString,int)'),
-                     self.main.editor.clear_breakpoint)
-        self.connect(self, SIGNAL('set_or_edit_conditional_breakpoint()'),
-                     self.main.editor.set_or_edit_conditional_breakpoint)
-        self.connect(self.main.editor,
-                     SIGNAL("breakpoints_saved()"),
-                     self.set_data)
+        self.edit_goto.connect(self.main.editor.load)
+        #self.redirect_stdio.connect(self.main.redirect_internalshell_stdio)
+        self.clear_all_breakpoints.connect(
+                                        self.main.editor.clear_all_breakpoints)
+        self.clear_breakpoint.connect(self.main.editor.clear_breakpoint)
+        self.main.editor.breakpoints_saved.connect(self.set_data)
+        self.set_or_edit_conditional_breakpoint.connect(
+                           self.main.editor.set_or_edit_conditional_breakpoint)
         
         self.main.add_dockwidget(self)
         
@@ -119,10 +119,3 @@ class Breakpoints(BreakpointWidget, SpyderPluginMixin):
             self.dockwidget.setVisible(True)
             self.dockwidget.setFocus()
             self.dockwidget.raise_()
-
-
-#==============================================================================
-# The following statements are required to register this 3rd party plugin:
-#==============================================================================
-PLUGIN_CLASS = Breakpoints
-
diff --git a/spyderplugins/locale/es/LC_MESSAGES/p_breakpoints.mo b/spyplugins/ui/breakpoints/locale/es/LC_MESSAGES/breakpoints.mo
similarity index 100%
rename from spyderplugins/locale/es/LC_MESSAGES/p_breakpoints.mo
rename to spyplugins/ui/breakpoints/locale/es/LC_MESSAGES/breakpoints.mo
diff --git a/spyplugins/ui/breakpoints/locale/fr/LC_MESSAGES/breakpoints.mo b/spyplugins/ui/breakpoints/locale/fr/LC_MESSAGES/breakpoints.mo
new file mode 100644
index 0000000..8c28814
Binary files /dev/null and b/spyplugins/ui/breakpoints/locale/fr/LC_MESSAGES/breakpoints.mo differ
diff --git a/spyplugins/ui/breakpoints/locale/pt_BR/LC_MESSAGES/breakpoints.mo b/spyplugins/ui/breakpoints/locale/pt_BR/LC_MESSAGES/breakpoints.mo
new file mode 100644
index 0000000..2ad5a3c
Binary files /dev/null and b/spyplugins/ui/breakpoints/locale/pt_BR/LC_MESSAGES/breakpoints.mo differ
diff --git a/spyderplugins/__init__.py b/spyplugins/ui/breakpoints/widgets/__init__.py
similarity index 100%
copy from spyderplugins/__init__.py
copy to spyplugins/ui/breakpoints/widgets/__init__.py
diff --git a/spyderplugins/widgets/breakpointsgui.py b/spyplugins/ui/breakpoints/widgets/breakpointsgui.py
similarity index 75%
rename from spyderplugins/widgets/breakpointsgui.py
rename to spyplugins/ui/breakpoints/widgets/breakpointsgui.py
index a1fec6f..c233528 100644
--- a/spyderplugins/widgets/breakpointsgui.py
+++ b/spyplugins/ui/breakpoints/widgets/breakpointsgui.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2012 Jed Ludlow
+# Copyright © 2009- The Spyder Development Team
 # based loosley on pylintgui.py by Pierre Raybaut
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
@@ -14,19 +14,25 @@
 
 from spyderlib.qt.QtGui import (QWidget, QTableView, QItemDelegate,
                                 QVBoxLayout, QMenu)
-from spyderlib.qt.QtCore import (Qt, SIGNAL, QTextCodec,
-                                 QModelIndex, QAbstractTableModel)
+from spyderlib.qt.QtCore import (Qt, Signal, QTextCodec, QModelIndex,
+                                 QAbstractTableModel)
 locale_codec = QTextCodec.codecForLocale()
 from spyderlib.qt.compat import to_qvariant
 import sys
 import os.path as osp
 
 # Local imports
-from spyderlib.baseconfig import get_translation
-from spyderlib.config import CONF
+from spyderlib.config.base import get_translation
+from spyderlib.config.main import CONF
 from spyderlib.utils.qthelpers import create_action, add_actions
 
-_ = get_translation("p_breakpoints", dirname="spyderplugins")
+# This is needed for testing this module as a stand alone script
+try:
+    _ = get_translation("breakpoints", "spyplugins.ui.breakpoints")
+except KeyError as error:
+    import gettext
+    _ = gettext.gettext
+
 
 class BreakpointTableModel(QAbstractTableModel):
     """
@@ -110,12 +116,23 @@ class BreakpointTableModel(QAbstractTableModel):
                 return to_qvariant(value)
             else:
                 return to_qvariant()
+
+    def reset(self):
+        self.beginResetModel()
+        self.endResetModel()
+
     
 class BreakpointDelegate(QItemDelegate):
     def __init__(self, parent=None):
         QItemDelegate.__init__(self, parent)
 
+
 class BreakpointTableView(QTableView):
+    edit_goto = Signal(str, int, str)
+    clear_breakpoint = Signal(str, int)
+    clear_all_breakpoints = Signal()
+    set_or_edit_conditional_breakpoint = Signal()
+    
     def __init__(self, parent, data):
         QTableView.__init__(self, parent)
         self.model = BreakpointTableModel(self, data)
@@ -145,10 +162,9 @@ class BreakpointTableView(QTableView):
         if self.model.breakpoints:
             filename = self.model.breakpoints[index_clicked.row()][0]
             line_number_str = self.model.breakpoints[index_clicked.row()][1]
-            self.emit(SIGNAL("edit_goto(QString,int,QString)"),
-                               filename, int(line_number_str), '') 
+            self.edit_goto.emit(filename, int(line_number_str), '')
         if index_clicked.column()==2:
-            self.emit(SIGNAL("set_or_edit_conditional_breakpoint()")) 
+            self.set_or_edit_conditional_breakpoint.emit()
                            
     def contextMenuEvent(self, event):
         index_clicked = self.indexAt(event.pos())
@@ -156,7 +172,7 @@ class BreakpointTableView(QTableView):
         self.popup_menu = QMenu(self)
         clear_all_breakpoints_action = create_action(self, 
             _("Clear breakpoints in all files"),
-            triggered=lambda: self.emit(SIGNAL('clear_all_breakpoints()')))
+            triggered=lambda: self.clear_all_breakpoints.emit())
         actions.append(clear_all_breakpoints_action)
         if self.model.breakpoints:
             filename = self.model.breakpoints[index_clicked.row()][0]
@@ -164,27 +180,30 @@ class BreakpointTableView(QTableView):
             clear_breakpoint_action = create_action(self,
                     _("Clear this breakpoint"),
                     triggered=lambda filename=filename, lineno=lineno: \
-                    self.emit(SIGNAL('clear_breakpoint(QString,int)'),
-                              filename, lineno))
+                    self.clear_breakpoint.emit(filename, lineno))
             actions.insert(0,clear_breakpoint_action)
 
             edit_breakpoint_action = create_action(self,
                     _("Edit this breakpoint"),
                     triggered=lambda filename=filename, lineno=lineno: \
-                    (self.emit(SIGNAL('edit_goto(QString,int,QString)'),
-                              filename, lineno, ''),
-                     self.emit(SIGNAL("set_or_edit_conditional_breakpoint()")))
+                    (self.edit_goto.emit(filename, lineno, ''),
+                     self.set_or_edit_conditional_breakpoint.emit())
                     )
             actions.append(edit_breakpoint_action)
         add_actions(self.popup_menu, actions)        
         self.popup_menu.popup(event.globalPos())
         event.accept()
 
+
 class BreakpointWidget(QWidget):
     """
     Breakpoint widget
     """
     VERSION = '1.0.0'
+    clear_all_breakpoints = Signal()
+    set_or_edit_conditional_breakpoint = Signal()
+    clear_breakpoint = Signal(str, int)
+    edit_goto = Signal(str, int, str)
     
     def __init__(self, parent):
         QWidget.__init__(self, parent)
@@ -195,16 +214,14 @@ class BreakpointWidget(QWidget):
         layout = QVBoxLayout()
         layout.addWidget(self.dictwidget)
         self.setLayout(layout)
-        self.connect(self.dictwidget, SIGNAL('clear_all_breakpoints()'),
-                     lambda: self.emit(SIGNAL('clear_all_breakpoints()')))
-        self.connect(self.dictwidget, SIGNAL('clear_breakpoint(QString,int)'),
-                     lambda s1, lino: self.emit(
-                     SIGNAL('clear_breakpoint(QString,int)'), s1, lino))
-        self.connect(self.dictwidget, SIGNAL("edit_goto(QString,int,QString)"),
-                     lambda s1, lino, s2: self.emit(
-                     SIGNAL("edit_goto(QString,int,QString)"), s1, lino, s2))
-        self.connect(self.dictwidget, SIGNAL('set_or_edit_conditional_breakpoint()'),
-                     lambda: self.emit(SIGNAL('set_or_edit_conditional_breakpoint()')))    
+        self.dictwidget.clear_all_breakpoints.connect(
+                                     lambda: self.clear_all_breakpoints.emit())
+        self.dictwidget.clear_breakpoint.connect(
+                         lambda s1, lino: self.clear_breakpoint.emit(s1, lino))
+        self.dictwidget.edit_goto.connect(
+                        lambda s1, lino, s2: self.edit_goto.emit(s1, lino, s2))
+        self.dictwidget.set_or_edit_conditional_breakpoint.connect(
+                        lambda: self.set_or_edit_conditional_breakpoint.emit())
                      
     def _load_all_breakpoints(self):
         bp_dict = CONF.get('run', 'breakpoints', {})
@@ -222,6 +239,10 @@ class BreakpointWidget(QWidget):
         self.dictwidget.adjust_columns()
         self.dictwidget.sortByColumn(0, Qt.DescendingOrder)
 
+
+#==============================================================================
+# Tests
+#==============================================================================
 def test():
     """Run breakpoint widget test"""
     from spyderlib.utils.qthelpers import qapplication
@@ -229,6 +250,7 @@ def test():
     widget = BreakpointWidget(None)
     widget.show()
     sys.exit(app.exec_())
-    
+
+
 if __name__ == '__main__':
     test()
diff --git a/spyplugins/ui/profiler/__init__.py b/spyplugins/ui/profiler/__init__.py
new file mode 100644
index 0000000..72d8de8
--- /dev/null
+++ b/spyplugins/ui/profiler/__init__.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+
+#==============================================================================
+# The following statement is required to register this 3rd party plugin:
+#==============================================================================
+from .profiler import Profiler as PLUGIN_CLASS
diff --git a/spyderplugins/images/profiler.png b/spyplugins/ui/profiler/images/profiler.png
similarity index 89%
rename from spyderplugins/images/profiler.png
rename to spyplugins/ui/profiler/images/profiler.png
index 91c768f..496ab30 100644
Binary files a/spyderplugins/images/profiler.png and b/spyplugins/ui/profiler/images/profiler.png differ
diff --git a/spyderplugins/locale/es/LC_MESSAGES/p_profiler.mo b/spyplugins/ui/profiler/locale/es/LC_MESSAGES/profiler.mo
similarity index 100%
rename from spyderplugins/locale/es/LC_MESSAGES/p_profiler.mo
rename to spyplugins/ui/profiler/locale/es/LC_MESSAGES/profiler.mo
diff --git a/spyplugins/ui/profiler/locale/fr/LC_MESSAGES/profiler.mo b/spyplugins/ui/profiler/locale/fr/LC_MESSAGES/profiler.mo
new file mode 100644
index 0000000..f36f05d
Binary files /dev/null and b/spyplugins/ui/profiler/locale/fr/LC_MESSAGES/profiler.mo differ
diff --git a/spyplugins/ui/profiler/locale/pt_BR/LC_MESSAGES/profiler.mo b/spyplugins/ui/profiler/locale/pt_BR/LC_MESSAGES/profiler.mo
new file mode 100644
index 0000000..d32074a
Binary files /dev/null and b/spyplugins/ui/profiler/locale/pt_BR/LC_MESSAGES/profiler.mo differ
diff --git a/spyderplugins/p_profiler.py b/spyplugins/ui/profiler/profiler.py
similarity index 78%
rename from spyderplugins/p_profiler.py
rename to spyplugins/ui/profiler/profiler.py
index 2210b98..ed4f529 100644
--- a/spyderplugins/p_profiler.py
+++ b/spyplugins/ui/profiler/profiler.py
@@ -1,35 +1,40 @@
 # -*- coding:utf-8 -*-
 #
-# Copyright © 2011 Santiago Jaramillo
+# Copyright © 2009- The Spyder Development Team
 # based on p_pylint.py by Pierre Raybaut
 #
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
-"""Profiler Plugin"""
+"""Profiler Plugin."""
 
+# Standard library imports
+import os.path as osp
+
+# Third party imports
+from spyderlib.qt.QtCore import Signal, Qt
 from spyderlib.qt.QtGui import QVBoxLayout, QGroupBox, QLabel
-from spyderlib.qt.QtCore import SIGNAL, Qt
 
 # Local imports
-from spyderlib.baseconfig import get_translation
-_ = get_translation("p_profiler", dirname="spyderplugins")
-from spyderlib.utils.qthelpers import get_icon, create_action
+from spyderlib.config.base import get_translation
 from spyderlib.plugins import SpyderPluginMixin, PluginConfigPage, runconfig
+from spyderlib.utils import icon_manager as ima
+from spyderlib.utils.qthelpers import create_action
+from .widgets.profilergui import (ProfilerWidget, is_profiler_installed)
+
 
-from spyderplugins.widgets.profilergui import (ProfilerWidget,
-                                               is_profiler_installed)
+_ = get_translation("profiler", "spyplugins.ui.profiler")
 
 
 class ProfilerConfigPage(PluginConfigPage):
     def setup_page(self):
         results_group = QGroupBox(_("Results"))
-        results_label1 = QLabel(_("Profiler plugin results "\
+        results_label1 = QLabel(_("Profiler plugin results "
                                   "(the output of python's profile/cProfile)\n"
                                   "are stored here:"))
         results_label1.setWordWrap(True)
 
-        # Warning: do not try to regroup the following QLabel contents with 
+        # Warning: do not try to regroup the following QLabel contents with
         # widgets above -- this string was isolated here in a single QLabel
         # on purpose: to fix Issue 863
         results_label2 = QLabel(ProfilerWidget.DATAPATH)
@@ -47,10 +52,13 @@ class ProfilerConfigPage(PluginConfigPage):
         vlayout.addStretch(1)
         self.setLayout(vlayout)
 
+
 class Profiler(ProfilerWidget, SpyderPluginMixin):
     """Profiler (after python's profile and pstats)"""
     CONF_SECTION = 'profiler'
     CONFIGWIDGET_CLASS = ProfilerConfigPage
+    edit_goto = Signal(str, int, str)
+    
     def __init__(self, parent=None):
         ProfilerWidget.__init__(self, parent=parent,
                               max_entries=self.get_option('max_entries', 50))
@@ -66,8 +74,9 @@ class Profiler(ProfilerWidget, SpyderPluginMixin):
 
     def get_plugin_icon(self):
         """Return widget icon"""
-        return get_icon('profiler.png')
-    
+        path = osp.join(self.PLUGIN_PATH, self.IMG_PATH)
+        return ima.icon('profiler', icon_path=path)
+
     def get_focus_widget(self):
         """
         Return the widget to give focus to when
@@ -86,14 +95,12 @@ class Profiler(ProfilerWidget, SpyderPluginMixin):
 
     def register_plugin(self):
         """Register plugin in Spyder's main window"""
-        self.connect(self, SIGNAL("edit_goto(QString,int,QString)"),
-                     self.main.editor.load)
-        self.connect(self, SIGNAL('redirect_stdio(bool)'),
-                     self.main.redirect_internalshell_stdio)
+        self.edit_goto.connect(self.main.editor.load)
+        self.redirect_stdio.connect(self.main.redirect_internalshell_stdio)
         self.main.add_dockwidget(self)
-        
+
         profiler_act = create_action(self, _("Profile"),
-                                     icon=get_icon('profiler.png'),
+                                     icon=self.get_plugin_icon(),
                                      triggered=self.run_profiler)
         profiler_act.setEnabled(is_profiler_installed())
         self.register_shortcut(profiler_act, context="Profiler",
@@ -119,7 +126,8 @@ class Profiler(ProfilerWidget, SpyderPluginMixin):
     #------ Public API ---------------------------------------------------------        
     def run_profiler(self):
         """Run profiler"""
-        self.analyze(self.main.editor.get_current_filename())
+        if self.main.editor.save():
+            self.analyze(self.main.editor.get_current_filename())
 
     def analyze(self, filename):
         """Reimplement analyze method"""
@@ -129,7 +137,7 @@ class Profiler(ProfilerWidget, SpyderPluginMixin):
             self.dockwidget.raise_()
         pythonpath = self.main.get_spyder_pythonpath()
         runconf = runconfig.get_run_configuration(filename)
-        wdir, args = None, None
+        wdir, args = None, []
         if runconf is not None:
             if runconf.wdir_enabled:
                 wdir = runconf.wdir
@@ -137,10 +145,3 @@ class Profiler(ProfilerWidget, SpyderPluginMixin):
                 args = runconf.args
         ProfilerWidget.analyze(self, filename, wdir=wdir, args=args,
                                pythonpath=pythonpath)
-
-
-#===============================================================================
-# The following statements are required to register this 3rd party plugin:
-#===============================================================================
-PLUGIN_CLASS = Profiler
-
diff --git a/spyderplugins/__init__.py b/spyplugins/ui/profiler/widgets/__init__.py
similarity index 100%
copy from spyderplugins/__init__.py
copy to spyplugins/ui/profiler/widgets/__init__.py
diff --git a/spyderplugins/widgets/profilergui.py b/spyplugins/ui/profiler/widgets/profilergui.py
similarity index 64%
rename from spyderplugins/widgets/profilergui.py
rename to spyplugins/ui/profiler/widgets/profilergui.py
index 342011f..1dfcb49 100644
--- a/spyderplugins/widgets/profilergui.py
+++ b/spyplugins/ui/profiler/widgets/profilergui.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2011 Santiago Jaramillo
+# Copyright © 2009- The Spyder Development Team
 # based on pylintgui.py by Pierre Raybaut
 #
 # Licensed under the terms of the MIT License
@@ -11,19 +11,19 @@ Profiler widget
 
 See the official documentation on python profiling:
 http://docs.python.org/library/profile.html
-
-Questions for Pierre and others:
-    - Where in the menu should profiler go?  Run > Profile code ?
 """
 
 from __future__ import with_statement
 
 from spyderlib.qt.QtGui import (QHBoxLayout, QWidget, QMessageBox, QVBoxLayout,
                                 QLabel, QTreeWidget, QTreeWidgetItem,
-                                QApplication)
-from spyderlib.qt.QtCore import SIGNAL, QProcess, QByteArray, Qt, QTextCodec
+                                QApplication, QColor)
+from spyderlib.qt.QtCore import (Signal, QProcess, QByteArray, Qt, QTextCodec,
+                                 QProcessEnvironment)
+
+import spyderlib.utils.icon_manager as ima
 locale_codec = QTextCodec.codecForLocale()
-from spyderlib.qt.compat import getopenfilename
+from spyderlib.qt.compat import getopenfilename, getsavefilename
 
 import sys
 import os
@@ -32,14 +32,20 @@ import time
 
 # Local imports
 from spyderlib.utils.qthelpers import (create_toolbutton, get_item_user_text,
-                                       set_item_user_text, get_icon)
+                                       set_item_user_text)
 from spyderlib.utils.programs import shell_split
-from spyderlib.baseconfig import get_conf_path, get_translation
-from spyderlib.widgets.texteditor import TextEditor
+from spyderlib.config.base import get_conf_path, get_translation
+from spyderlib.widgets.variableexplorer.texteditor import TextEditor
 from spyderlib.widgets.comboboxes import PythonModulesComboBox
 from spyderlib.widgets.externalshell import baseshell
 from spyderlib.py3compat import to_text_string, getcwd
-_ = get_translation("p_profiler", dirname="spyderplugins")
+
+# This is needed for testing this module as a stand alone script
+try:
+    _ = get_translation("profiler", "spyplugins.ui.profiler")
+except KeyError as error:
+    import gettext
+    _ = gettext.gettext
 
 
 def is_profiler_installed():
@@ -53,6 +59,7 @@ class ProfilerWidget(QWidget):
     """
     DATAPATH = get_conf_path('profiler.results')
     VERSION = '0.0.1'
+    redirect_stdio = Signal(bool)
     
     def __init__(self, parent, max_entries=100):
         QWidget.__init__(self, parent)
@@ -68,28 +75,28 @@ class ProfilerWidget(QWidget):
         
         self.filecombo = PythonModulesComboBox(self)
         
-        self.start_button = create_toolbutton(self, icon=get_icon('run.png'),
+        self.start_button = create_toolbutton(self, icon=ima.icon('run'),
                                     text=_("Profile"),
                                     tip=_("Run profiler"),
-                                    triggered=self.start, text_beside_icon=True)
+                                    triggered=lambda : self.start(),
+                                    text_beside_icon=True)
         self.stop_button = create_toolbutton(self,
-                                             icon=get_icon('stop.png'),
+                                             icon=ima.icon('stop'),
                                              text=_("Stop"),
                                              tip=_("Stop current profiling"),
                                              text_beside_icon=True)
-        self.connect(self.filecombo, SIGNAL('valid(bool)'),
-                     self.start_button.setEnabled)
+        self.filecombo.valid.connect(self.start_button.setEnabled)
         #self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data)
         # FIXME: The combobox emits this signal on almost any event
         #        triggering show_data() too early, too often. 
 
-        browse_button = create_toolbutton(self, icon=get_icon('fileopen.png'),
-                               tip=_('Select Python script'),
-                               triggered=self.select_file)
+        browse_button = create_toolbutton(self, icon=ima.icon('fileopen'),
+                                          tip=_('Select Python script'),
+                                          triggered=self.select_file)
 
         self.datelabel = QLabel()
 
-        self.log_button = create_toolbutton(self, icon=get_icon('log.png'),
+        self.log_button = create_toolbutton(self, icon=ima.icon('log'),
                                             text=_("Output"),
                                             text_beside_icon=True,
                                             tip=_("Show program's output"),
@@ -98,15 +105,30 @@ class ProfilerWidget(QWidget):
         self.datatree = ProfilerDataTree(self)
 
         self.collapse_button = create_toolbutton(self,
-                                                 icon=get_icon('collapse.png'),
-                                                 triggered=lambda dD=-1:
-                                                 self.datatree.change_view(dD),
+                                                 icon=ima.icon('collapse'),
+                                                 triggered=lambda dD:
+                                                 self.datatree.change_view(-1),
                                                  tip=_('Collapse one level up'))
         self.expand_button = create_toolbutton(self,
-                                               icon=get_icon('expand.png'),
-                                               triggered=lambda dD=1:
-                                               self.datatree.change_view(dD),
+                                               icon=ima.icon('expand'),
+                                               triggered=lambda dD:
+                                               self.datatree.change_view(1),
                                                tip=_('Expand one level down'))
+                                
+        self.save_button = create_toolbutton(self, text_beside_icon=True,
+                                             text=_("Save data"),
+                                             icon=ima.icon('filesave'),
+                                             triggered=self.save_data,
+                                             tip=_('Save profiling data'))
+        self.load_button = create_toolbutton(self, text_beside_icon=True,
+                            text=_("Load data"),
+                            icon=ima.icon('fileimport'),
+                            triggered=self.compare,
+                            tip=_('Load profiling data for comparison'))
+        self.clear_button = create_toolbutton(self, text_beside_icon=True,
+                                              text=_("Clear comparison"),
+                                              icon=ima.icon('editdelete'),
+                                              triggered=self.clear)
 
         hlayout1 = QHBoxLayout()
         hlayout1.addWidget(self.filecombo)
@@ -121,6 +143,9 @@ class ProfilerWidget(QWidget):
         hlayout2.addWidget(self.datelabel)
         hlayout2.addStretch()
         hlayout2.addWidget(self.log_button)
+        hlayout2.addWidget(self.save_button)
+        hlayout2.addWidget(self.load_button)
+        hlayout2.addWidget(self.clear_button)
         
         layout = QVBoxLayout()
         layout.addLayout(hlayout1)
@@ -131,7 +156,8 @@ class ProfilerWidget(QWidget):
         self.process = None
         self.set_running_state(False)
         self.start_button.setEnabled(False)
-        
+        self.clear_button.setEnabled(False)
+
         if not is_profiler_installed():
             # This should happen only on certain GNU/Linux distributions 
             # or when this a home-made Python build because the Python 
@@ -145,7 +171,30 @@ class ProfilerWidget(QWidget):
             self.datelabel.setText(text)
         else:
             pass # self.show_data()
-        
+            
+    def save_data(self):
+        """Save data"""
+        title = _( "Save profiler result")
+        filename, _selfilter = getsavefilename(self, title,
+                                               getcwd(),
+                                               _("Profiler result")+" (*.Result)")
+        if filename:
+            self.datatree.save_data(filename)
+            
+    def compare(self):
+        filename, _selfilter = getopenfilename(self, _("Select script to compare"),
+                                               getcwd(), _("Profiler result")+" (*.Result)")
+        if filename:
+            self.datatree.compare(filename)
+            self.show_data()
+            self.clear_button.setEnabled(True)
+
+    def clear(self):
+        self.datatree.compare(None)
+        self.datatree.hide_diff_cols(True)
+        self.show_data()
+        self.clear_button.setEnabled(False)
+
     def analyze(self, filename, wdir=None, args=None, pythonpath=None):
         if not is_profiler_installed():
             return
@@ -164,10 +213,10 @@ class ProfilerWidget(QWidget):
             self.start(wdir, args, pythonpath)
             
     def select_file(self):
-        self.emit(SIGNAL('redirect_stdio(bool)'), False)
+        self.redirect_stdio.emit(False)
         filename, _selfilter = getopenfilename(self, _("Select Python script"),
                            getcwd(), _("Python scripts")+" (*.py ; *.pyw)")
-        self.emit(SIGNAL('redirect_stdio(bool)'), False)
+        self.redirect_stdio.emit(True)
         if filename:
             self.analyze(filename)
         
@@ -202,20 +251,22 @@ class ProfilerWidget(QWidget):
         self.process = QProcess(self)
         self.process.setProcessChannelMode(QProcess.SeparateChannels)
         self.process.setWorkingDirectory(wdir)
-        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
-                     self.read_output)
-        self.connect(self.process, SIGNAL("readyReadStandardError()"),
-                     lambda: self.read_output(error=True))
-        self.connect(self.process,
-                     SIGNAL("finished(int,QProcess::ExitStatus)"),
-                     self.finished)
-        self.connect(self.stop_button, SIGNAL("clicked()"), self.process.kill)
+        self.process.readyReadStandardOutput.connect(self.read_output)
+        self.process.readyReadStandardError.connect(
+                                          lambda: self.read_output(error=True))
+        self.process.finished.connect(lambda ec, es=QProcess.ExitStatus:
+                                      self.finished(ec, es))
+        self.stop_button.clicked.connect(self.process.kill)
 
         if pythonpath is not None:
             env = [to_text_string(_pth)
                    for _pth in self.process.systemEnvironment()]
             baseshell.add_pathlist_to_PYTHONPATH(env, pythonpath)
-            self.process.setEnvironment(env)
+            processEnvironment = QProcessEnvironment()
+            for envItem in env:
+                envName, separator, envValue = envItem.partition('=')
+                processEnvironment.insert(envName, envValue)
+            self.process.setProcessEnvironment(processEnvironment)
         
         self.output = ''
         self.error_output = ''
@@ -263,7 +314,7 @@ class ProfilerWidget(QWidget):
         else:
             self.output += text
         
-    def finished(self):
+    def finished(self, exit_code, exit_status):
         self.set_running_state(False)
         self.show_errorlog()  # If errors occurred, show them.
         self.output = self.error_output + self.output
@@ -287,9 +338,10 @@ class ProfilerWidget(QWidget):
         if not filename:
             return
 
-        self.datatree.load_data(self.DATAPATH)
         self.datelabel.setText(_('Sorting data, please wait...'))
         QApplication.processEvents()
+        
+        self.datatree.load_data(self.DATAPATH)
         self.datatree.show_tree()
             
         text_style = "<span style=\'color: #444444\'><b>%s </b></span>"
@@ -332,25 +384,25 @@ class ProfilerDataTree(QTreeWidget):
     # (must be improbable as a filename to avoid splitting the filename itself)
     def __init__(self, parent=None):
         QTreeWidget.__init__(self, parent)
-        self.header_list = [_('Function/Module'), _('Total Time'),
-                            _('Local Time'), _('Calls'), _('File:line')]
-        self.icon_list = {'module':      'python.png',
-                         'function':    'function.png',
-                         'builtin':     'python_t.png',
-                         'constructor': 'class.png'}
+        self.header_list = [_('Function/Module'), _('Total Time'), _('Diff'),
+                            _('Local Time'), _('Diff'), _('Calls'), _('Diff'),
+                            _('File:line')]
+        self.icon_list = {'module': ima.icon('python'),
+                         'function': ima.icon('function'),
+                         'builtin': ima.icon('python_t'),
+                         'constructor': ima.icon('class')}
         self.profdata = None   # To be filled by self.load_data()
         self.stats = None      # To be filled by self.load_data()
         self.item_depth = None
         self.item_list = None
         self.items_to_be_shown = None
         self.current_view_depth = None
+        self.compare_file = None
         self.setColumnCount(len(self.header_list))
         self.setHeaderLabels(self.header_list)
         self.initialize_view()
-        self.connect(self, SIGNAL('itemActivated(QTreeWidgetItem*,int)'),
-                     self.item_activated)
-        self.connect(self, SIGNAL('itemExpanded(QTreeWidgetItem*)'),
-                     self.item_expanded)
+        self.itemActivated.connect(self.item_activated)
+        self.itemExpanded.connect(self.item_expanded)
 
     def set_item_data(self, item, filename, line_number):
         """Set tree item user data: filename (string) and line_number (int)"""
@@ -372,15 +424,34 @@ class ProfilerDataTree(QTreeWidget):
     def load_data(self, profdatafile):
         """Load profiler data saved by profile/cProfile module"""
         import pstats
-        self.profdata = pstats.Stats(profdatafile)
+        stats_indi = [pstats.Stats(profdatafile),]
+        self.profdata = stats_indi[0]
+        
+        if self.compare_file is not None:
+            stats_indi.append(pstats.Stats(self.compare_file))
+        map(lambda x: x.calc_callees(), stats_indi)
         self.profdata.calc_callees()
-        self.stats = self.profdata.stats
+        self.stats1 = stats_indi
+        self.stats = stats_indi[0].stats
+        
+    def compare(self,filename):
+        self.hide_diff_cols(False)
+        self.compare_file = filename
+        
+    def hide_diff_cols(self, hide):
+        for i in (2,4,6):
+            self.setColumnHidden(i, hide)
+    
+    def save_data(self, filename):
+        """"""
+        self.stats1[0].dump_stats(filename)
 
     def find_root(self):
         """Find a function without a caller"""
         self.profdata.sort_stats("cumulative")
         for func in self.profdata.fcn_list:
-            if ('~', 0, '<built-in method exec>') != func: 
+            if ('~', 0) != func[0:2] and not func[2].startswith(
+                    '<built-in method exec>'):
                 # This skips the profiler function at the top of the list
                 # it does only occur in Python 3
                 return func
@@ -401,7 +472,7 @@ class ProfilerDataTree(QTreeWidget):
             self.populate_tree(self, self.find_callees(rootkey))
             self.resizeColumnToContents(0)
             self.setSortingEnabled(True)
-            self.sortItems(1, Qt.DescendingOrder) # FIXME: hardcoded index
+            self.sortItems(1, Qt.AscendingOrder) # FIXME: hardcoded index
             self.change_view(1)
 
     def function_info(self, functionKey):
@@ -422,13 +493,38 @@ class ProfilerDataTree(QTreeWidget):
                 node_type = 'constructor'                
             file_and_line = '%s : %d' % (filename, line_number)
         return filename, line_number, function_name, file_and_line, node_type
-    
+        
+    def color_string(self, args):
+        x, format = args
+        diff_str = ""
+        color = "black"
+        if len(x) == 2 and self.compare_file is not None:
+            difference = x[0] - x[1]
+            if difference < 0:
+                diff_str = "".join(['',format[1] % difference])
+                color = "green"
+            elif difference > 0:
+                diff_str = "".join(['+',format[1] % difference])
+                color = "red"
+        return [format[0] % x[0], [diff_str, color]]
+
+
+    def format_output(self,child_key):
+        """ Formats the data"""
+        if True:
+            data = [x.stats.get(child_key,[0,0,0,0,0]) for x in self.stats1]
+            return map(self.color_string,zip(list(zip(*data))[1:4], [["%i"]*2, ["%.3f","%.3f"], ["%.3f","%.3f"]]))
+            
     def populate_tree(self, parentItem, children_list):
         """Recursive method to create each item (and associated data) in the tree."""
         for child_key in children_list:
             self.item_depth += 1
             (filename, line_number, function_name, file_and_line, node_type
              ) = self.function_info(child_key)
+
+            ((total_calls, total_calls_dif), (loc_time, loc_time_dif), (cum_time,
+             cum_time_dif)) = self.format_output(child_key)
+
             (primcalls, total_calls, loc_time, cum_time, callers
              ) = self.stats[child_key]
             child_item = TreeWidgetItem(parentItem)
@@ -438,31 +534,43 @@ class ProfilerDataTree(QTreeWidget):
             # FIXME: indexes to data should be defined by a dictionary on init
             child_item.setToolTip(0, 'Function or module name')
             child_item.setData(0, Qt.DisplayRole, function_name)
-            child_item.setIcon(0, get_icon(self.icon_list[node_type]))
+            child_item.setIcon(0, self.icon_list[node_type])
 
             child_item.setToolTip(1, _('Time in function '\
                                        '(including sub-functions)'))
-            #child_item.setData(1, Qt.DisplayRole, cum_time)
-            child_item.setData(1, Qt.DisplayRole, '%.3f' % cum_time)
-            child_item.setTextAlignment(1, Qt.AlignCenter)
+            child_item.setData(1, Qt.DisplayRole, cum_time)
+            child_item.setTextAlignment(1, Qt.AlignRight)
+            
+            child_item.setData(2, Qt.DisplayRole, cum_time_dif[0])
+            child_item.setForeground(2, QColor(cum_time_dif[1]))
+            child_item.setTextAlignment(2, Qt.AlignLeft)
 
-            child_item.setToolTip(2, _('Local time in function '\
+            child_item.setToolTip(3, _('Local time in function '\
                                       '(not in sub-functions)'))
-            #child_item.setData(2, Qt.DisplayRole, loc_time)
-            child_item.setData(2, Qt.DisplayRole, '%.3f' % loc_time)
-            child_item.setTextAlignment(2, Qt.AlignCenter)
 
-            child_item.setToolTip(3, _('Total number of calls '\
+            child_item.setData(3, Qt.DisplayRole, loc_time)
+            child_item.setTextAlignment(3, Qt.AlignRight)
+            
+            child_item.setData(4, Qt.DisplayRole, loc_time_dif[0])
+            child_item.setForeground(4, QColor(loc_time_dif[1]))
+            child_item.setTextAlignment(4, Qt.AlignLeft)
+
+            child_item.setToolTip(5, _('Total number of calls '\
                                        '(including recursion)'))
-            child_item.setData(3, Qt.DisplayRole, total_calls)
-            child_item.setTextAlignment(3, Qt.AlignCenter)
 
-            child_item.setToolTip(4, _('File:line '\
+            child_item.setData(5, Qt.DisplayRole, total_calls)
+            child_item.setTextAlignment(5, Qt.AlignRight)
+            
+            child_item.setData(6, Qt.DisplayRole, total_calls_dif[0])
+            child_item.setForeground(6, QColor(total_calls_dif[1]))
+            child_item.setTextAlignment(6, Qt.AlignLeft)
+
+            child_item.setToolTip(7, _('File:line '\
                                        'where function is defined'))
-            child_item.setData(4, Qt.DisplayRole, file_and_line)
+            child_item.setData(7, Qt.DisplayRole, file_and_line)
             #child_item.setExpanded(True)
             if self.is_recursive(child_item):
-                child_item.setData(4, Qt.DisplayRole, '(%s)' % _('recursion'))
+                child_item.setData(7, Qt.DisplayRole, '(%s)' % _('recursion'))
                 child_item.setDisabled(True)
             else:
                 callees = self.find_callees(child_key)
@@ -475,8 +583,7 @@ class ProfilerDataTree(QTreeWidget):
         
     def item_activated(self, item):
         filename, line_number = self.get_item_data(item)
-        self.parent().emit(SIGNAL("edit_goto(QString,int,QString)"),
-                           filename, line_number, '')
+        self.parent().edit_goto.emit(filename, line_number, '')
             
     def item_expanded(self, item):
         if item.childCount() == 0 and id(item) in self.items_to_be_shown:
@@ -502,7 +609,7 @@ class ProfilerDataTree(QTreeWidget):
         return [self.topLevelItem(_i) for _i in range(self.topLevelItemCount())]
     
     def get_items(self, maxlevel):
-        """Return items (excluding top level items)"""
+        """Return all items with a level <= `maxlevel`"""
         itemlist = []
         def add_to_itemlist(item, maxlevel, level=1):
             level += 1
@@ -513,31 +620,70 @@ class ProfilerDataTree(QTreeWidget):
                     add_to_itemlist(citem, maxlevel, level)
         for tlitem in self.get_top_level_items():
             itemlist.append(tlitem)
-            if maxlevel > 1:
+            if maxlevel > 0:
                 add_to_itemlist(tlitem, maxlevel=maxlevel)
         return itemlist
             
     def change_view(self, change_in_depth):
         """Change the view depth by expand or collapsing all same-level nodes"""
         self.current_view_depth += change_in_depth
-        if self.current_view_depth < 1:
-            self.current_view_depth = 1
+        if self.current_view_depth < 0:
+            self.current_view_depth = 0
         self.collapseAll()
-        for item in self.get_items(maxlevel=self.current_view_depth):
-            item.setExpanded(True)
+        if self.current_view_depth > 0:
+            for item in self.get_items(maxlevel=self.current_view_depth-1):
+                item.setExpanded(True)
     
 
+#==============================================================================
+# Tests
+#==============================================================================
+def primes(n):
+    """
+    Simple test function
+    Taken from http://www.huyng.com/posts/python-performance-analysis/
+    """
+    if n==2:
+        return [2]
+    elif n<2:
+        return []
+    s=list(range(3,n+1,2))
+    mroot = n ** 0.5
+    half=(n+1)//2-1
+    i=0
+    m=3
+    while m <= mroot:
+        if s[i]:
+            j=(m*m-3)//2
+            s[j]=0
+            while j<half:
+                s[j]=0
+                j+=m
+        i=i+1
+        m=2*i+3
+    return [2]+[x for x in s if x]
+
+
 def test():
     """Run widget test"""
+    import inspect
+    import tempfile
     from spyderlib.utils.qthelpers import qapplication
-    app = qapplication()
+
+    primes_sc = inspect.getsource(primes)
+    fd, script = tempfile.mkstemp(suffix='.py')
+    with os.fdopen(fd, 'w') as f:
+        f.write("# -*- coding: utf-8 -*-" + "\n\n")
+        f.write(primes_sc + "\n\n")
+        f.write("primes(100000)")
+    
+    app = qapplication(test_time=5)
     widget = ProfilerWidget(None)
     widget.resize(800, 600)
     widget.show()
-    #widget.analyze(__file__)
-    widget.analyze(osp.join(osp.dirname(__file__), os.pardir, os.pardir,
-                            'spyderlib/widgets', 'texteditor.py'))
+    widget.analyze(script)
     sys.exit(app.exec_())
-    
+
+
 if __name__ == '__main__':
     test()
diff --git a/spyplugins/ui/pylint/__init__.py b/spyplugins/ui/pylint/__init__.py
new file mode 100644
index 0000000..6e29824
--- /dev/null
+++ b/spyplugins/ui/pylint/__init__.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+
+#==============================================================================
+# The following statement is required to register this 3rd party plugin:
+#==============================================================================
+from .pylint import Pylint as PLUGIN_CLASS
diff --git a/spyplugins/ui/pylint/images/pylint.png b/spyplugins/ui/pylint/images/pylint.png
new file mode 100644
index 0000000..dec028d
Binary files /dev/null and b/spyplugins/ui/pylint/images/pylint.png differ
diff --git a/spyderplugins/locale/es/LC_MESSAGES/p_pylint.mo b/spyplugins/ui/pylint/locale/es/LC_MESSAGES/pylint.mo
similarity index 100%
rename from spyderplugins/locale/es/LC_MESSAGES/p_pylint.mo
rename to spyplugins/ui/pylint/locale/es/LC_MESSAGES/pylint.mo
diff --git a/spyplugins/ui/pylint/locale/fr/LC_MESSAGES/pylint.mo b/spyplugins/ui/pylint/locale/fr/LC_MESSAGES/pylint.mo
new file mode 100644
index 0000000..8572426
Binary files /dev/null and b/spyplugins/ui/pylint/locale/fr/LC_MESSAGES/pylint.mo differ
diff --git a/spyplugins/ui/pylint/locale/pt_BR/LC_MESSAGES/pylint.mo b/spyplugins/ui/pylint/locale/pt_BR/LC_MESSAGES/pylint.mo
new file mode 100644
index 0000000..14f6f1f
Binary files /dev/null and b/spyplugins/ui/pylint/locale/pt_BR/LC_MESSAGES/pylint.mo differ
diff --git a/spyderplugins/p_pylint.py b/spyplugins/ui/pylint/pylint.py
similarity index 84%
rename from spyderplugins/p_pylint.py
rename to spyplugins/ui/pylint/pylint.py
index 829506b..36563bc 100644
--- a/spyderplugins/p_pylint.py
+++ b/spyplugins/ui/pylint/pylint.py
@@ -4,23 +4,30 @@
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
-"""Pylint Code Analysis Plugin"""
+"""Pylint Code Analysis Plugin."""
 
 # pylint: disable=C0103
 # pylint: disable=R0903
 # pylint: disable=R0911
 # pylint: disable=R0201
 
+# Standard library imports
+import os.path as osp
+
+# Third party imports
+from spyderlib.qt.QtCore import Signal, Qt
 from spyderlib.qt.QtGui import QInputDialog, QVBoxLayout, QGroupBox, QLabel
-from spyderlib.qt.QtCore import SIGNAL, Qt
 
 # Local imports
-from spyderlib.baseconfig import get_translation
-_ = get_translation("p_pylint", dirname="spyderplugins")
-from spyderlib.utils.qthelpers import get_icon, create_action
+from spyderlib.config.base import get_translation
+from spyderlib.utils import icon_manager as ima
+from spyderlib.utils.qthelpers import create_action
 from spyderlib.plugins import SpyderPluginMixin, PluginConfigPage
 
-from spyderplugins.widgets.pylintgui import PylintWidget, PYLINT_PATH
+from .widgets.pylintgui import PylintWidget, PYLINT_PATH
+
+
+_ = get_translation("pylint", "spyplugins.ui.pylint")
 
 
 class PylintConfigPage(PluginConfigPage):
@@ -75,6 +82,8 @@ class Pylint(PylintWidget, SpyderPluginMixin):
     """Python source code analysis based on pylint"""
     CONF_SECTION = 'pylint'
     CONFIGWIDGET_CLASS = PylintConfigPage
+    edit_goto = Signal(str, int, str)
+
     def __init__(self, parent=None):
         PylintWidget.__init__(self, parent=parent,
                               max_entries=self.get_option('max_entries', 50))
@@ -87,11 +96,12 @@ class Pylint(PylintWidget, SpyderPluginMixin):
     def get_plugin_title(self):
         """Return widget title"""
         return _("Static code analysis")
-    
+
     def get_plugin_icon(self):
         """Return widget icon"""
-        return get_icon('pylint.png')
-    
+        path = osp.join(self.PLUGIN_PATH, self.IMG_PATH)
+        return ima.icon('pylint', icon_path=path)
+
     def get_focus_widget(self):
         """
         Return the widget to give focus to when
@@ -103,7 +113,7 @@ class Pylint(PylintWidget, SpyderPluginMixin):
         """Return a list of actions related to plugin"""
         # Font
         history_action = create_action(self, _("History..."),
-                                       None, 'history.png',
+                                       None, ima.icon('history'),
                                        _("Set history maximum entries"),
                                        triggered=self.change_history_depth)
         self.treewidget.common_actions += (None, history_action)
@@ -116,10 +126,8 @@ class Pylint(PylintWidget, SpyderPluginMixin):
 
     def register_plugin(self):
         """Register plugin in Spyder's main window"""
-        self.connect(self, SIGNAL("edit_goto(QString,int,QString)"),
-                     self.main.editor.load)
-        self.connect(self, SIGNAL('redirect_stdio(bool)'),
-                     self.main.redirect_internalshell_stdio)
+        self.edit_goto.connect(self.main.editor.load)
+        self.redirect_stdio.connect(self.main.redirect_internalshell_stdio)
         self.main.add_dockwidget(self)
         
         pylint_act = create_action(self, _("Run static code analysis"),
@@ -169,10 +177,3 @@ class Pylint(PylintWidget, SpyderPluginMixin):
             self.dockwidget.setFocus()
             self.dockwidget.raise_()
         PylintWidget.analyze(self, filename)
-
-
-#==============================================================================
-# The following statements are required to register this 3rd party plugin:
-#==============================================================================
-PLUGIN_CLASS = Pylint
-
diff --git a/spyderplugins/__init__.py b/spyplugins/ui/pylint/widgets/__init__.py
similarity index 100%
rename from spyderplugins/__init__.py
rename to spyplugins/ui/pylint/widgets/__init__.py
diff --git a/spyderplugins/widgets/pylintgui.py b/spyplugins/ui/pylint/widgets/pylintgui.py
similarity index 86%
rename from spyderplugins/widgets/pylintgui.py
rename to spyplugins/ui/pylint/widgets/pylintgui.py
index 43ed816..621c6e4 100644
--- a/spyderplugins/widgets/pylintgui.py
+++ b/spyplugins/ui/pylint/widgets/pylintgui.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright © 2009-2010 Pierre Raybaut
+# Copyright © 2009- The Spyder Development Team
 # Licensed under the terms of the MIT License
 # (see spyderlib/__init__.py for details)
 
@@ -15,9 +15,10 @@ from __future__ import with_statement, print_function
 
 from spyderlib.qt.QtGui import (QHBoxLayout, QWidget, QTreeWidgetItem,
                                 QMessageBox, QVBoxLayout, QLabel)
-from spyderlib.qt.QtCore import SIGNAL, QProcess, QByteArray, QTextCodec
+from spyderlib.qt.QtCore import Signal, QProcess, QByteArray, QTextCodec
 locale_codec = QTextCodec.codecForLocale()
 from spyderlib.qt.compat import getopenfilename
+import spyderlib.utils.icon_manager as ima
 
 import sys
 import os
@@ -30,14 +31,20 @@ import subprocess
 from spyderlib import dependencies
 from spyderlib.utils import programs
 from spyderlib.utils.encoding import to_unicode_from_fs
-from spyderlib.utils.qthelpers import get_icon, create_toolbutton
-from spyderlib.baseconfig import get_conf_path, get_translation
+from spyderlib.utils.qthelpers import create_toolbutton
+from spyderlib.config.base import get_conf_path, get_translation
 from spyderlib.widgets.onecolumntree import OneColumnTree
-from spyderlib.widgets.texteditor import TextEditor
+from spyderlib.widgets.variableexplorer.texteditor import TextEditor
 from spyderlib.widgets.comboboxes import (PythonModulesComboBox,
                                           is_module_or_package)
 from spyderlib.py3compat import PY3, to_text_string, getcwd, pickle
-_ = get_translation("p_pylint", dirname="spyderplugins")
+
+# This is needed for testing this module as a stand alone script
+try:
+    _ = get_translation("pylint", "spyplugins.ui.pylint")
+except KeyError as error:
+    import gettext
+    _ = gettext.gettext
 
 
 PYLINT = 'pylint'
@@ -87,8 +94,7 @@ class ResultsTree(OneColumnTree):
         data = self.data.get(id(item))
         if data is not None:
             fname, lineno = data
-            self.parent().emit(SIGNAL("edit_goto(QString,int,QString)"),
-                               fname, lineno, '')
+            self.parent().edit_goto.emit(fname, lineno, '')
 
     def clicked(self, item):
         """Click event"""
@@ -110,13 +116,13 @@ class ResultsTree(OneColumnTree):
         self.data = {}
         # Populating tree
         results = ((_('Convention'),
-                    get_icon('convention.png'), self.results['C:']),
+                   ima.icon('convention'), self.results['C:']),
                    (_('Refactor'),
-                    get_icon('refactor.png'), self.results['R:']),
+                   ima.icon('refactor'), self.results['R:']),
                    (_('Warning'),
-                    get_icon('warning.png'), self.results['W:']),
+                   ima.icon('warning'), self.results['W:']),
                    (_('Error'),
-                    get_icon('error.png'), self.results['E:']))
+                   ima.icon('error'), self.results['E:']))
         for title, icon, messages in results:
             title += ' (%d message%s)' % (len(messages),
                                           's' if len(messages)>1 else '')
@@ -147,7 +153,7 @@ class ResultsTree(OneColumnTree):
                     if parent is None:
                         item = QTreeWidgetItem(title_item, [module],
                                                QTreeWidgetItem.Type)
-                        item.setIcon(0, get_icon('py.png'))
+                        item.setIcon(0, ima.icon('python'))
                         modules[modname] = item
                         parent = item
                 else:
@@ -157,7 +163,7 @@ class ResultsTree(OneColumnTree):
                 else:
                     text = "%d : %s" % (lineno, message)
                 msg_item = QTreeWidgetItem(parent, [text], QTreeWidgetItem.Type)
-                msg_item.setIcon(0, get_icon('arrow.png'))
+                msg_item.setIcon(0, ima.icon('arrow'))
                 self.data[id(msg_item)] = (modname, lineno)
 
 
@@ -167,6 +173,7 @@ class PylintWidget(QWidget):
     """
     DATAPATH = get_conf_path('pylint.results')
     VERSION = '1.1.0'
+    redirect_stdio = Signal(bool)
     
     def __init__(self, parent, max_entries=100):
         QWidget.__init__(self, parent)
@@ -191,26 +198,25 @@ class PylintWidget(QWidget):
             self.remove_obsolete_items()
             self.filecombo.addItems(self.get_filenames())
         
-        self.start_button = create_toolbutton(self, icon=get_icon('run.png'),
+        self.start_button = create_toolbutton(self, icon=ima.icon('run'),
                                     text=_("Analyze"),
                                     tip=_("Run analysis"),
                                     triggered=self.start, text_beside_icon=True)
         self.stop_button = create_toolbutton(self,
-                                             icon=get_icon('stop.png'),
+                                             icon=ima.icon('stop'),
                                              text=_("Stop"),
                                              tip=_("Stop current analysis"),
                                              text_beside_icon=True)
-        self.connect(self.filecombo, SIGNAL('valid(bool)'),
-                     self.start_button.setEnabled)
-        self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data)
+        self.filecombo.valid.connect(self.start_button.setEnabled)
+        self.filecombo.valid.connect(self.show_data)
 
-        browse_button = create_toolbutton(self, icon=get_icon('fileopen.png'),
+        browse_button = create_toolbutton(self, icon=ima.icon('fileopen'),
                                tip=_('Select Python file'),
                                triggered=self.select_file)
 
         self.ratelabel = QLabel()
         self.datelabel = QLabel()
-        self.log_button = create_toolbutton(self, icon=get_icon('log.png'),
+        self.log_button = create_toolbutton(self, icon=ima.icon('log'),
                                     text=_("Output"),
                                     text_beside_icon=True,
                                     tip=_("Complete output"),
@@ -273,10 +279,10 @@ class PylintWidget(QWidget):
             self.start()
             
     def select_file(self):
-        self.emit(SIGNAL('redirect_stdio(bool)'), False)
+        self.redirect_stdio.emit(False)
         filename, _selfilter = getopenfilename(self, _("Select Python file"),
                            getcwd(), _("Python files")+" (*.py ; *.pyw)")
-        self.emit(SIGNAL('redirect_stdio(bool)'), False)
+        self.redirect_stdio.emit(True)
         if filename:
             self.analyze(filename)
             
@@ -320,14 +326,12 @@ class PylintWidget(QWidget):
         self.process = QProcess(self)
         self.process.setProcessChannelMode(QProcess.SeparateChannels)
         self.process.setWorkingDirectory(osp.dirname(filename))
-        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
-                     self.read_output)
-        self.connect(self.process, SIGNAL("readyReadStandardError()"),
-                     lambda: self.read_output(error=True))
-        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
-                     self.finished)
-        self.connect(self.stop_button, SIGNAL("clicked()"),
-                     self.process.kill)
+        self.process.readyReadStandardOutput.connect(self.read_output)
+        self.process.readyReadStandardError.connect(
+                                          lambda: self.read_output(error=True))
+        self.process.finished.connect(lambda ec, es=QProcess.ExitStatus:
+                                      self.finished(ec, es))
+        self.stop_button.clicked.connect(self.process.kill)
         
         self.output = ''
         self.error_output = ''
@@ -373,7 +377,7 @@ class PylintWidget(QWidget):
         else:
             self.output += text
         
-    def finished(self):
+    def finished(self, exit_code, exit_status):
         self.set_running_state(False)
         if not self.output:
             if self.error_output:
@@ -486,14 +490,19 @@ class PylintWidget(QWidget):
         self.datelabel.setText(date_text)
 
 
+#==============================================================================
+# Tests
+#==============================================================================
 def test():
     """Run pylint widget test"""
     from spyderlib.utils.qthelpers import qapplication
-    app = qapplication()
+    app = qapplication(test_time=20)
     widget = PylintWidget(None)
+    widget.resize(640, 480)
     widget.show()
     widget.analyze(__file__)
     sys.exit(app.exec_())
-    
+
+
 if __name__ == '__main__':
     test()

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/spyder.git



More information about the debian-science-commits mailing list