[spyder] 02/08: Imported Upstream version 2.3.0~beta3+dfsg

Frédéric-Emmanuel Picca picca at moszumanska.debian.org
Thu Apr 10 21:06:28 UTC 2014


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

picca pushed a commit to branch experimental
in repository spyder.

commit 036378918c92c1fd9c18c4a736b40acbf484466e
Author: Picca Frédéric-Emmanuel <picca at debian.org>
Date:   Sat Feb 1 07:45:40 2014 +0100

    Imported Upstream version 2.3.0~beta3+dfsg
---
 PKG-INFO                                           |   4 +-
 setup.py                                           |   5 +-
 spyderlib/__init__.py                              |   2 +-
 spyderlib/locale/fr/LC_MESSAGES/spyderlib.mo       | Bin 85312 -> 85560 bytes
 spyderlib/locale/fr/LC_MESSAGES/spyderlib.po       | 564 +++++++++++----------
 spyderlib/locale/spyderlib.pot                     | 503 +++++++++---------
 spyderlib/plugins/__init__.py                      |  26 +-
 spyderlib/plugins/externalconsole.py               |  19 +-
 spyderlib/plugins/inspector.py                     |  18 +-
 spyderlib/plugins/ipythonconsole.py                |  10 +-
 spyderlib/spyder.py                                | 297 +++++++----
 spyderlib/utils/inspector/static/css/default.css   |   4 -
 spyderlib/utils/introspection/__init__.py          |  11 +
 spyderlib/utils/introspection/base.py              | 453 +++++++++++++++++
 .../utils/{ => introspection}/module_completion.py |   0
 spyderlib/utils/introspection/rope_plugin.py       | 241 +++++++++
 spyderlib/utils/programs.py                        |   4 +
 spyderlib/utils/qthelpers.py                       |   2 +-
 spyderlib/utils/sourcecode.py                      |  72 +++
 spyderlib/widgets/calltip.py                       |  82 ++-
 spyderlib/widgets/dependencies.py                  |   1 +
 spyderlib/widgets/editor.py                        | 141 ++++--
 spyderlib/widgets/externalshell/monitor.py         |   2 +-
 spyderlib/widgets/externalshell/pythonshell.py     |   4 +-
 spyderlib/widgets/findreplace.py                   |   2 +-
 spyderlib/widgets/ipython.py                       |  25 +-
 spyderlib/widgets/mixins.py                        |  35 +-
 spyderlib/widgets/sourcecode/base.py               |   6 +-
 spyderlib/widgets/sourcecode/codeeditor.py         | 360 +++++--------
 spyderplugins/p_pylint.py                          |   8 +-
 spyderplugins/widgets/pylintgui.py                 |   8 +-
 31 files changed, 1877 insertions(+), 1032 deletions(-)

diff --git a/PKG-INFO b/PKG-INFO
index f930a7b..80dc915 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,12 +1,12 @@
 Metadata-Version: 1.1
 Name: spyder
-Version: 2.3.0beta2
+Version: 2.3.0beta3
 Summary: Scientific PYthon Development EnviRonment
 Home-page: http://code.google.com/p/spyderlib
 Author: Pierre Raybaut
 Author-email: UNKNOWN
 License: MIT
-Download-URL: http://code.google.com/p/spyderlib/files/spyder-2.3.0beta2.zip
+Download-URL: http://code.google.com/p/spyderlib/files/spyder-2.3.0beta3.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 
diff --git a/setup.py b/setup.py
index dcbe881..e3efe5a 100644
--- a/setup.py
+++ b/setup.py
@@ -34,7 +34,7 @@ if 'USE_SETUPTOOLS' in os.environ or 'pip' in __file__:
     except:
         with_setuptools = False
 
-if with_setuptools is False:
+if not with_setuptools:
     from distutils.command.install import install  # analysis:ignore
 
 
@@ -128,6 +128,9 @@ 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)
 
             hhc_exe = get_html_help_exe()
             self.builder = "html" if hhc_exe is None else "htmlhelp"
diff --git a/spyderlib/__init__.py b/spyderlib/__init__.py
index d1ff089..bd7a029 100644
--- a/spyderlib/__init__.py
+++ b/spyderlib/__init__.py
@@ -27,7 +27,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 """
 
-__version__ = '2.3.0beta2'
+__version__ = '2.3.0beta3'
 __license__ = __doc__
 __project_url__ = 'http://code.google.com/p/spyderlib'
 __forum_url__   = 'http://groups.google.com/group/spyderlib'
diff --git a/spyderlib/locale/fr/LC_MESSAGES/spyderlib.mo b/spyderlib/locale/fr/LC_MESSAGES/spyderlib.mo
index aa1c63b..f974d65 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 11a5ec5..ca89ccc 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: 2013-11-09 14:09+Paris, Madrid\n"
+"POT-Creation-Date: 2014-01-04 15:22+Paris, Madrid\n"
 "PO-Revision-Date: 2011-04-11 21:41+2\n"
 "Last-Translator: Pierre Raybaut\n"
 "Language-Team: Python\n"
@@ -223,7 +223,7 @@ msgid "Background:"
 msgstr "Fond :"
 
 #: spyderlib\plugins\configdialog.py:768
-#: spyderlib\widgets\sourcecode\codeeditor.py:280
+#: spyderlib\widgets\sourcecode\codeeditor.py:90
 msgid "Current line:"
 msgstr "Ligne actuelle :"
 
@@ -291,12 +291,12 @@ msgstr "Rétablir les valeurs par défaut"
 msgid "Internal console"
 msgstr "Console interne"
 
-#: spyderlib\plugins\console.py:125 spyderlib\spyder.py:810
-#: spyderlib\widgets\ipython.py:473
+#: spyderlib\plugins\console.py:125 spyderlib\spyder.py:800
+#: spyderlib\widgets\ipython.py:515
 msgid "&Quit"
 msgstr "&Quitter"
 
-#: spyderlib\plugins\console.py:126 spyderlib\spyder.py:811
+#: spyderlib\plugins\console.py:126 spyderlib\spyder.py:801
 msgid "Quit"
 msgstr "Quitter"
 
@@ -335,7 +335,7 @@ msgid "Set maximum line count"
 msgstr "Modifier le nombre maximum de lignes"
 
 #: spyderlib\plugins\console.py:148 spyderlib\plugins\explorer.py:60
-#: spyderlib\plugins\history.py:153 spyderlib\plugins\inspector.py:349
+#: spyderlib\plugins\history.py:153 spyderlib\plugins\inspector.py:350
 #: spyderlib\plugins\projectexplorer.py:58
 msgid "&Font..."
 msgstr "&Police..."
@@ -354,15 +354,16 @@ msgstr "Modifier le chemin d'accès de l'éditeur externe"
 
 #: spyderlib\plugins\console.py:156 spyderlib\plugins\editor.py:134
 #: spyderlib\plugins\externalconsole.py:95 spyderlib\plugins\history.py:41
-#: spyderlib\plugins\history.py:156 spyderlib\plugins\inspector.py:170
-#: spyderlib\plugins\inspector.py:352
+#: spyderlib\plugins\history.py:156 spyderlib\plugins\inspector.py:171
+#: spyderlib\plugins\inspector.py:353
 msgid "Wrap lines"
 msgstr "Retour à la ligne automatique"
 
 #: spyderlib\plugins\console.py:159 spyderlib\plugins\editor.py:164
 #: spyderlib\plugins\externalconsole.py:144
-msgid "Balloon tips"
-msgstr "Info-bulles"
+#: spyderlib\plugins\ipythonconsole.py:84
+msgid "Display balloon tips"
+msgstr "Afficher des info-bulles"
 
 #: spyderlib\plugins\console.py:163 spyderlib\plugins\editor.py:156
 #: spyderlib\plugins\externalconsole.py:136
@@ -388,7 +389,7 @@ msgid "Python scripts"
 msgstr "Scripts Python"
 
 #: spyderlib\plugins\console.py:269 spyderlib\plugins\explorer.py:111
-#: spyderlib\plugins\history.py:271 spyderlib\plugins\inspector.py:643
+#: spyderlib\plugins\history.py:271 spyderlib\plugins\inspector.py:645
 #: spyderlib\plugins\projectexplorer.py:120
 msgid "Select a new font"
 msgstr "Sélectionner une police d'écriture"
@@ -411,9 +412,9 @@ msgstr "Chemin d'accès de l'exécutable :"
 
 #: spyderlib\plugins\editor.py:87 spyderlib\plugins\editor.py:505
 #: spyderlib\plugins\editor.py:1570 spyderlib\plugins\inspector.py:133
-#: spyderlib\plugins\inspector.py:380 spyderlib\widgets\editor.py:574
-#: spyderlib\widgets\sourcecode\codeeditor.py:270
-#: spyderlib\widgets\sourcecode\codeeditor.py:2558
+#: spyderlib\plugins\inspector.py:381 spyderlib\widgets\editor.py:589
+#: spyderlib\widgets\sourcecode\codeeditor.py:80
+#: spyderlib\widgets\sourcecode\codeeditor.py:2378
 msgid "Editor"
 msgstr "Éditeur"
 
@@ -436,7 +437,7 @@ msgstr "Afficher la barre d'onglets"
 #: spyderlib\plugins\editor.py:110 spyderlib\plugins\editor.py:178
 #: spyderlib\plugins\externalconsole.py:90
 #: spyderlib\plugins\externalconsole.py:135 spyderlib\plugins\history.py:40
-#: spyderlib\plugins\inspector.py:169 spyderlib\plugins\ipythonconsole.py:108
+#: spyderlib\plugins\inspector.py:170 spyderlib\plugins\ipythonconsole.py:108
 msgid "Source code"
 msgstr "Code source"
 
@@ -461,13 +462,13 @@ msgid "Highlight occurences after"
 msgstr "Surligner les occurences après"
 
 #: spyderlib\plugins\editor.py:137 spyderlib\plugins\history.py:49
-#: spyderlib\plugins\inspector.py:173
+#: spyderlib\plugins\inspector.py:174
 msgid "Syntax color scheme: "
 msgstr "Thème de coloration syntaxique : "
 
 #: spyderlib\plugins\editor.py:149 spyderlib\plugins\runconfig.py:304
 #: spyderlib\plugins\runconfig.py:426 spyderlib\plugins\runconfig.py:431
-#: spyderlib\spyder.py:1795 spyderlib\widgets\explorer.py:230
+#: spyderlib\spyder.py:1829 spyderlib\widgets\explorer.py:230
 #: spyderlib\widgets\externalshell\baseshell.py:138
 msgid "Run"
 msgstr "Exécuter"
@@ -596,7 +597,7 @@ msgstr ""
 "veuillez visiter la page de la %s."
 
 #: spyderlib\plugins\editor.py:219
-#: spyderlib\widgets\sourcecode\codeeditor.py:1607
+#: spyderlib\widgets\sourcecode\codeeditor.py:1422
 msgid "Code analysis"
 msgstr "Analyse de code"
 
@@ -779,7 +780,7 @@ msgstr "Points d'arrêt"
 msgid "Debug with winpdb"
 msgstr "Déboguer avec winpdb"
 
-#: spyderlib\plugins\editor.py:663 spyderlib\spyder.py:609
+#: spyderlib\plugins\editor.py:663 spyderlib\spyder.py:606
 msgid "&Debug"
 msgstr "&Déboguer"
 
@@ -834,7 +835,7 @@ msgid "Debugging control"
 msgstr "Contrôle du débogage"
 
 #: spyderlib\plugins\editor.py:722 spyderlib\plugins\editor.py:1222
-#: spyderlib\spyder.py:604
+#: spyderlib\spyder.py:601
 msgid "&Run"
 msgstr "E&xécution"
 
@@ -860,7 +861,7 @@ msgid "Run again last file"
 msgstr "Exécuter de nouveau le dernier fichier"
 
 #: spyderlib\plugins\editor.py:748
-#: spyderlib\widgets\sourcecode\codeeditor.py:2243
+#: spyderlib\widgets\sourcecode\codeeditor.py:2058
 msgid "Run &selection"
 msgstr "Exécuter la &sélection"
 
@@ -948,12 +949,12 @@ msgid "Go to next cursor position"
 msgstr "Aller à la position suivante du curseur"
 
 #: spyderlib\plugins\editor.py:823
-#: spyderlib\widgets\sourcecode\codeeditor.py:2237
+#: spyderlib\widgets\sourcecode\codeeditor.py:2052
 msgid "Comment"
 msgstr "Commenter"
 
 #: spyderlib\plugins\editor.py:823
-#: spyderlib\widgets\sourcecode\codeeditor.py:2237
+#: spyderlib\widgets\sourcecode\codeeditor.py:2052
 msgid "Uncomment"
 msgstr "Décommenter"
 
@@ -1056,47 +1057,47 @@ msgstr "Effacer cette liste"
 msgid "Open &recent"
 msgstr "Fichiers &récents"
 
-#: spyderlib\plugins\editor.py:1210 spyderlib\spyder.py:585
+#: spyderlib\plugins\editor.py:1210 spyderlib\spyder.py:582
 msgid "File toolbar"
 msgstr "Barre d'outil fichiers"
 
-#: spyderlib\plugins\editor.py:1211 spyderlib\spyder.py:595
+#: spyderlib\plugins\editor.py:1211 spyderlib\spyder.py:592
 msgid "Search toolbar"
 msgstr "Barre d'outil de recherche"
 
-#: spyderlib\plugins\editor.py:1212 spyderlib\spyder.py:600
+#: spyderlib\plugins\editor.py:1212 spyderlib\spyder.py:597
 msgid "Source toolbar"
 msgstr "Barre d'outils code source"
 
-#: spyderlib\plugins\editor.py:1213 spyderlib\spyder.py:605
+#: spyderlib\plugins\editor.py:1213 spyderlib\spyder.py:602
 msgid "Run toolbar"
 msgstr "Barre d'outil exécution"
 
-#: spyderlib\plugins\editor.py:1214 spyderlib\spyder.py:610
+#: spyderlib\plugins\editor.py:1214 spyderlib\spyder.py:607
 msgid "Debug toolbar"
 msgstr "Barre d'outil de débogage"
 
-#: spyderlib\plugins\editor.py:1215 spyderlib\spyder.py:590
+#: spyderlib\plugins\editor.py:1215 spyderlib\spyder.py:587
 msgid "Edit toolbar"
 msgstr "Barre d'outil édition"
 
-#: spyderlib\plugins\editor.py:1218 spyderlib\spyder.py:582
+#: spyderlib\plugins\editor.py:1218 spyderlib\spyder.py:579
 msgid "&File"
 msgstr "&Fichier"
 
-#: spyderlib\plugins\editor.py:1219 spyderlib\spyder.py:589
+#: spyderlib\plugins\editor.py:1219 spyderlib\spyder.py:586
 msgid "&Edit"
 msgstr "&Édition"
 
-#: spyderlib\plugins\editor.py:1220 spyderlib\spyder.py:594
+#: spyderlib\plugins\editor.py:1220 spyderlib\spyder.py:591
 msgid "&Search"
 msgstr "&Recherche"
 
-#: spyderlib\plugins\editor.py:1221 spyderlib\spyder.py:599
+#: spyderlib\plugins\editor.py:1221 spyderlib\spyder.py:596
 msgid "Sour&ce"
 msgstr "Sour&ce"
 
-#: spyderlib\plugins\editor.py:1223 spyderlib\spyder.py:617
+#: spyderlib\plugins\editor.py:1223 spyderlib\spyder.py:614
 msgid "&Tools"
 msgstr "Ou&tils"
 
@@ -1128,7 +1129,7 @@ msgstr "Impression en cours..."
 msgid "File explorer"
 msgstr "Explorateur de fichiers"
 
-#: spyderlib\plugins\explorer.py:61 spyderlib\plugins\inspector.py:350
+#: spyderlib\plugins\explorer.py:61 spyderlib\plugins\inspector.py:351
 #: spyderlib\plugins\projectexplorer.py:59
 msgid "Set font style"
 msgstr "Changer la police d'écriture"
@@ -1139,9 +1140,9 @@ msgstr "Visualisation interactive de données"
 
 #: spyderlib\plugins\externalconsole.py:60
 #: spyderlib\plugins\externalconsole.py:1083
-#: spyderlib\plugins\inspector.py:380
+#: spyderlib\plugins\inspector.py:381
 #: spyderlib\widgets\externalshell\baseshell.py:106
-#: spyderlib\widgets\ipython.py:412
+#: spyderlib\widgets\ipython.py:454
 msgid "Console"
 msgstr "Console"
 
@@ -1495,8 +1496,8 @@ msgstr ""
 "sur le bouton à l'extrême droite pour tuer le processus du noyau."
 
 #: spyderlib\plugins\externalconsole.py:686
-#: spyderlib\plugins\ipythonconsole.py:480 spyderlib\spyder.py:1327
-#: spyderlib\spyder.py:1345 spyderlib\utils\environ.py:95
+#: spyderlib\plugins\ipythonconsole.py:480 spyderlib\spyder.py:1323
+#: spyderlib\spyder.py:1341 spyderlib\utils\environ.py:95
 #: spyderlib\utils\environ.py:108
 msgid "Warning"
 msgstr "Attention"
@@ -1629,11 +1630,11 @@ msgstr "Taille de l'historique : "
 msgid "Scroll automatically to last entry"
 msgstr "Défiler automatiquement jusqu'à la dernière ligne"
 
-#: spyderlib\plugins\history.py:102 spyderlib\plugins\inspector.py:433
-#: spyderlib\widgets\editor.py:661 spyderlib\widgets\explorer.py:990
+#: spyderlib\plugins\history.py:102 spyderlib\plugins\inspector.py:435
+#: spyderlib\widgets\editor.py:677 spyderlib\widgets\explorer.py:990
 #: spyderlib\widgets\externalshell\baseshell.py:151
 #: spyderlib\widgets\externalshell\namespacebrowser.py:231
-#: spyderlib\widgets\ipython.py:449
+#: spyderlib\widgets\ipython.py:491
 msgid "Options"
 msgstr "Options"
 
@@ -1670,104 +1671,107 @@ msgid "Rich text font style"
 msgstr "Police d'écriture du texte enrichi"
 
 #: spyderlib\plugins\inspector.py:125
-#, fuzzy
 msgid "Automatic connections"
-msgstr "Complétion de code automatique"
+msgstr "Connexions automatiques"
 
 #: spyderlib\plugins\inspector.py:126
 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 ""
+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:136
+#: spyderlib\plugins\inspector.py:137
 msgid "Python Console"
 msgstr "Console Python"
 
-#: spyderlib\plugins\inspector.py:138
+#: spyderlib\plugins\inspector.py:139
 msgid "IPython Console"
 msgstr "Console IPython"
 
-#: spyderlib\plugins\inspector.py:151
+#: spyderlib\plugins\inspector.py:152
 msgid "Additional features"
 msgstr "Options supplémentaires"
 
-#: spyderlib\plugins\inspector.py:152
+#: spyderlib\plugins\inspector.py:153
 msgid "Render mathematical equations"
 msgstr "Styliser les équations mathématiques"
 
-#: spyderlib\plugins\inspector.py:158
+#: spyderlib\plugins\inspector.py:159
 msgid "This feature requires Sphinx 1.1 or superior."
 msgstr "Cette fonctionnalité nécessite l'installation de Sphinx 1.1+."
 
-#: spyderlib\plugins\inspector.py:160
+#: spyderlib\plugins\inspector.py:161
 msgid "Sphinx %s is currently installed."
 msgstr "Sphinx %s n'est pas installé."
 
-#: spyderlib\plugins\inspector.py:334
+#: spyderlib\plugins\inspector.py:335
 msgid "No documentation available"
 msgstr "Aucune documentation disponible"
 
-#: spyderlib\plugins\inspector.py:373
+#: spyderlib\plugins\inspector.py:374
 msgid "Source"
 msgstr "Source"
 
-#: spyderlib\plugins\inspector.py:388 spyderlib\widgets\dicteditor.py:162
+#: spyderlib\plugins\inspector.py:390 spyderlib\widgets\dicteditor.py:162
 msgid "Object"
 msgstr "Objet"
 
-#: spyderlib\plugins\inspector.py:403
+#: spyderlib\plugins\inspector.py:405
 msgid "Plain Text"
 msgstr "Texte brut"
 
-#: spyderlib\plugins\inspector.py:407
+#: spyderlib\plugins\inspector.py:409
 msgid "Show Source"
 msgstr "Afficher les sources"
 
-#: spyderlib\plugins\inspector.py:411
+#: spyderlib\plugins\inspector.py:413
 msgid "Rich Text"
 msgstr "Texte enrichi"
 
-#: spyderlib\plugins\inspector.py:421
+#: spyderlib\plugins\inspector.py:423
 msgid "Automatic import"
 msgstr "Import automatique"
 
-#: spyderlib\plugins\inspector.py:476 spyderlib\plugins\inspector.py:885
+#: spyderlib\plugins\inspector.py:478 spyderlib\plugins\inspector.py:887
 msgid "Object inspector"
 msgstr "Inspecteur d'objets"
 
-#: spyderlib\plugins\inspector.py:599
+#: spyderlib\plugins\inspector.py:601
 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 "Pour obtenir de l'aide ici, sélectionner (ou placer le curseur sur) un objet dans l'éditeur ou la console, puis appuyer sur %s.%sL'aide apparaît automatiquement après la saisie d'une parenthèse gauche après un objet si l'option correspondante est activée dans %s."
+msgstr ""
+"Pour obtenir de l'aide ici, sélectionner (ou placer le curseur sur) un objet "
+"dans l'éditeur ou la console, puis appuyer sur %s.%sL'aide apparaît "
+"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:605
+#: spyderlib\plugins\inspector.py:607
 msgid "Preferences > Object Inspector"
 msgstr "Préférences > Inspecteur d'objets"
 
-#: spyderlib\plugins\inspector.py:607
+#: spyderlib\plugins\inspector.py:609
 msgid "Usage"
 msgstr "Utilisation"
 
-#: spyderlib\plugins\inspector.py:613
+#: spyderlib\plugins\inspector.py:615
 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:846
+#: spyderlib\plugins\inspector.py:848
 msgid "Lock"
 msgstr "Verrouiller"
 
-#: spyderlib\plugins\inspector.py:846
+#: spyderlib\plugins\inspector.py:848
 msgid "Unlock"
 msgstr "Déverrouiller"
 
-#: spyderlib\plugins\inspector.py:886
+#: spyderlib\plugins\inspector.py:888
 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"
@@ -1776,7 +1780,7 @@ 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:930
+#: spyderlib\plugins\inspector.py:932
 msgid "No source code available."
 msgstr "Aucun code source disponible."
 
@@ -1822,10 +1826,6 @@ 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:84
-msgid "Display balloon tips"
-msgstr "Afficher des info-bulles"
-
 #: spyderlib\plugins\ipythonconsole.py:85
 msgid "Ask for confirmation before closing"
 msgstr "Demander confirmation avant de fermer une console"
@@ -2516,11 +2516,10 @@ msgid "Global working directory"
 msgstr "Répertoire de travail global"
 
 #: spyderlib\spyder.py:48
-#, fuzzy
 msgid "IPython Console integration"
 msgstr "Intégration de la console IPython"
 
-#: spyderlib\spyder.py:125 spyderlib\spyder.py:455
+#: spyderlib\spyder.py:125
 msgid "Initializing..."
 msgstr "Initialisation..."
 
@@ -2544,7 +2543,7 @@ msgstr "WinPython"
 msgid "Numpy and Scipy documentation"
 msgstr "Documentation de Numpy et Scipy"
 
-#: spyderlib\spyder.py:297 spyderlib\spyder.py:989
+#: spyderlib\spyder.py:297 spyderlib\spyder.py:971
 msgid "Matplotlib documentation"
 msgstr "Documentation de Matplotlib"
 
@@ -2568,106 +2567,106 @@ msgstr "Enregistrer la session et quitter..."
 msgid "Save current session and quit application"
 msgstr "Enregistrer la session en cours et quitter l'application"
 
-#: spyderlib\spyder.py:516
-msgid "Close current dockwidget"
-msgstr "Fermer le panneau actif"
+#: spyderlib\spyder.py:513
+msgid "Close current plugin"
+msgstr "Fermer la fenêtre courante"
 
-#: spyderlib\spyder.py:522
+#: spyderlib\spyder.py:519
 msgid "&Find text"
 msgstr "Rec&hercher"
 
-#: spyderlib\spyder.py:528
+#: spyderlib\spyder.py:525
 msgid "Find &next"
 msgstr "Rechercher le &suivant"
 
-#: spyderlib\spyder.py:534
+#: spyderlib\spyder.py:531
 msgid "Find &previous"
 msgstr "Rechercher le &précédent"
 
-#: spyderlib\spyder.py:539
+#: spyderlib\spyder.py:536
 msgid "&Replace text"
 msgstr "&Remplacer"
 
-#: spyderlib\spyder.py:554 spyderlib\widgets\sourcecode\codeeditor.py:2213
+#: spyderlib\spyder.py:551 spyderlib\widgets\sourcecode\codeeditor.py:2028
 msgid "Undo"
 msgstr "Annuler"
 
-#: spyderlib\spyder.py:556 spyderlib\widgets\sourcecode\codeeditor.py:2216
+#: spyderlib\spyder.py:553 spyderlib\widgets\sourcecode\codeeditor.py:2031
 msgid "Redo"
 msgstr "Répéter"
 
-#: spyderlib\spyder.py:557 spyderlib\widgets\arrayeditor.py:327
-#: spyderlib\widgets\dicteditor.py:563 spyderlib\widgets\shell.py:121
-#: spyderlib\widgets\sourcecode\codeeditor.py:2222
+#: spyderlib\spyder.py:554 spyderlib\widgets\arrayeditor.py:327
+#: spyderlib\widgets\dicteditor.py:563 spyderlib\widgets\shell.py:122
+#: spyderlib\widgets\sourcecode\codeeditor.py:2037
 msgid "Copy"
 msgstr "Copier"
 
-#: spyderlib\spyder.py:559 spyderlib\widgets\shell.py:117
-#: spyderlib\widgets\sourcecode\codeeditor.py:2219
+#: spyderlib\spyder.py:556 spyderlib\widgets\shell.py:118
+#: spyderlib\widgets\sourcecode\codeeditor.py:2034
 msgid "Cut"
 msgstr "Couper"
 
-#: spyderlib\spyder.py:560 spyderlib\widgets\dicteditor.py:560
-#: spyderlib\widgets\shell.py:125
-#: spyderlib\widgets\sourcecode\codeeditor.py:2225
+#: spyderlib\spyder.py:557 spyderlib\widgets\dicteditor.py:560
+#: spyderlib\widgets\shell.py:126
+#: spyderlib\widgets\sourcecode\codeeditor.py:2040
 msgid "Paste"
 msgstr "Coller"
 
-#: spyderlib\spyder.py:562 spyderlib\widgets\explorer.py:453
-#: spyderlib\widgets\projectexplorer.py:1002 spyderlib\widgets\shell.py:134
-#: spyderlib\widgets\sourcecode\codeeditor.py:2228
+#: spyderlib\spyder.py:559 spyderlib\widgets\explorer.py:453
+#: spyderlib\widgets\projectexplorer.py:1002 spyderlib\widgets\shell.py:135
+#: spyderlib\widgets\sourcecode\codeeditor.py:2043
 msgid "Delete"
 msgstr "Supprimer"
 
-#: spyderlib\spyder.py:565 spyderlib\widgets\shell.py:138
-#: spyderlib\widgets\sourcecode\codeeditor.py:2232
+#: spyderlib\spyder.py:562 spyderlib\widgets\shell.py:139
+#: spyderlib\widgets\sourcecode\codeeditor.py:2047
 msgid "Select All"
 msgstr "Sélectionner tout"
 
-#: spyderlib\spyder.py:614
+#: spyderlib\spyder.py:611
 msgid "C&onsoles"
 msgstr "C&onsoles"
 
-#: spyderlib\spyder.py:620
+#: spyderlib\spyder.py:617
 msgid "&View"
 msgstr "&Affichage"
 
-#: spyderlib\spyder.py:623
+#: spyderlib\spyder.py:620
 msgid "&Help"
 msgstr "A&ide"
 
-#: spyderlib\spyder.py:628
+#: spyderlib\spyder.py:625
 msgid "Welcome to Spyder!"
 msgstr "Bienvenue dans Spyder !"
 
-#: spyderlib\spyder.py:633
+#: spyderlib\spyder.py:630
 msgid "Pre&ferences"
 msgstr "Pré&férences"
 
-#: spyderlib\spyder.py:641 spyderlib\widgets\pathmanager.py:45
+#: spyderlib\spyder.py:638 spyderlib\widgets\pathmanager.py:45
 #: spyderlib\widgets\projectexplorer.py:593
 msgid "PYTHONPATH manager"
 msgstr "Gestionnaire de PYTHONPATH"
 
-#: spyderlib\spyder.py:644
+#: spyderlib\spyder.py:641
 msgid "Python Path Manager"
 msgstr "Gestionnaire de chemins d'accès Python"
 
-#: spyderlib\spyder.py:647
+#: spyderlib\spyder.py:644
 msgid "Update module names list"
 msgstr "Mise à jour de la liste des modules"
 
-#: spyderlib\spyder.py:649
+#: spyderlib\spyder.py:646
 msgid "Refresh list of module names available in PYTHONPATH"
 msgstr ""
 "Mise à jour de la liste des modules disponibles notamment à travers "
 "PYTHONPATH"
 
-#: spyderlib\spyder.py:655
+#: spyderlib\spyder.py:651
 msgid "Current user environment variables..."
 msgstr "Variables d'environnement de l'utilisateur..."
 
-#: spyderlib\spyder.py:657
+#: spyderlib\spyder.py:653
 msgid ""
 "Show and edit current user environment variables in Windows registry (i.e. "
 "for all sessions)"
@@ -2675,199 +2674,207 @@ 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:664 spyderlib\spyder.py:1064
+#: spyderlib\spyder.py:661 spyderlib\spyder.py:1063
 msgid "External Tools"
 msgstr "Outils externes"
 
-#: spyderlib\spyder.py:668
+#: spyderlib\spyder.py:665
 msgid "Python(x,y) launcher"
 msgstr "Accueil de Python(x,y)"
 
-#: spyderlib\spyder.py:679
+#: spyderlib\spyder.py:672
 msgid "WinPython control panel"
 msgstr "Panneau de contrôle WinPython"
 
-#: spyderlib\spyder.py:692
+#: spyderlib\spyder.py:681
 msgid "Qt Designer"
 msgstr "Qt Designer"
 
-#: spyderlib\spyder.py:697
+#: spyderlib\spyder.py:686
 msgid "Qt Linguist"
 msgstr "Qt Linguist"
 
-#: spyderlib\spyder.py:703
+#: spyderlib\spyder.py:692
 msgid "Qt examples"
 msgstr "Exemples Qt"
 
-#: spyderlib\spyder.py:721
+#: spyderlib\spyder.py:710
 msgid "guidata examples"
 msgstr "Exemples guidata"
 
-#: spyderlib\spyder.py:729
+#: spyderlib\spyder.py:718
 msgid "guiqwt examples"
 msgstr "Exemples guiqwt"
 
-#: spyderlib\spyder.py:734
+#: spyderlib\spyder.py:723
 msgid "Sift"
 msgstr "Sift"
 
-#: spyderlib\spyder.py:742
+#: spyderlib\spyder.py:731
 msgid "ViTables"
 msgstr "ViTables"
 
-#: spyderlib\spyder.py:756
+#: spyderlib\spyder.py:745
 msgid "Fullscreen mode"
 msgstr "Mode plein écran"
 
-#: spyderlib\spyder.py:768
+#: spyderlib\spyder.py:757
 msgid "Main toolbar"
 msgstr "Barre d'outil principale"
 
-#: spyderlib\spyder.py:789
+#: spyderlib\spyder.py:779
 msgid "Loading object inspector..."
 msgstr "Chargement de l'inspecteur d'objet..."
 
-#: spyderlib\spyder.py:796
+#: spyderlib\spyder.py:786
 msgid "Loading outline explorer..."
 msgstr "Chargement de l'explorateur de structure..."
 
-#: spyderlib\spyder.py:804
+#: spyderlib\spyder.py:794
 msgid "Loading editor..."
 msgstr "Chargement de l'éditeur..."
 
-#: spyderlib\spyder.py:829
+#: spyderlib\spyder.py:819
 msgid "Loading file explorer..."
 msgstr "Chargement de l'explorateur de fichiers..."
 
-#: spyderlib\spyder.py:836
+#: spyderlib\spyder.py:826
 msgid "Loading history plugin..."
 msgstr "Chargement du journal d'historique..."
 
-#: spyderlib\spyder.py:847
+#: spyderlib\spyder.py:837
 msgid "Loading online help..."
 msgstr "Chargement de l'aide en ligne..."
 
-#: spyderlib\spyder.py:853
+#: spyderlib\spyder.py:843
 msgid "Loading project explorer..."
 msgstr "Chargement de l'explorateur de projet..."
 
-#: spyderlib\spyder.py:864
+#: spyderlib\spyder.py:854
 msgid "Loading external console..."
 msgstr "Chargement de la console externe..."
 
-#: spyderlib\spyder.py:873
+#: spyderlib\spyder.py:863
 msgid "Loading namespace browser..."
 msgstr "Chargement de l'explorateur d'espace de noms..."
 
-#: spyderlib\spyder.py:880
+#: spyderlib\spyder.py:870
 msgid "Loading IPython console..."
 msgstr "Chargement de la console IPython..."
 
-#: spyderlib\spyder.py:891
+#: spyderlib\spyder.py:881
 msgid "Setting up main window..."
 msgstr "Configuration de la fenêtre principale..."
 
-#: spyderlib\spyder.py:895
-msgid "About %s..."
-msgstr "À propos de %s..."
-
-#: spyderlib\spyder.py:898
-msgid "Optional dependencies..."
-msgstr "Dépendances optionnelles..."
+#: spyderlib\spyder.py:900
+msgid "Spyder documentation"
+msgstr "Documentation de Spyder"
 
-#: spyderlib\spyder.py:901
+#: spyderlib\spyder.py:904
 msgid "Report issue..."
 msgstr "Rapport d'erreur..."
 
-#: spyderlib\spyder.py:922
-msgid "Spyder documentation"
-msgstr "Documentation de Spyder"
+#: spyderlib\spyder.py:908
+msgid "Spyder support..."
+msgstr "Support technique de Spyder..."
 
-#: spyderlib\spyder.py:928
+#: spyderlib\spyder.py:910
+msgid "Optional dependencies..."
+msgstr "Dépendances optionnelles..."
+
+#: spyderlib\spyder.py:917
 msgid "Python documentation"
 msgstr "Documentation de Python"
 
-#: spyderlib\spyder.py:935
-msgid "IPython Help"
-msgstr "Aide IPython"
+#: spyderlib\spyder.py:923 spyderlib\spyder.py:963
+msgid "IPython documentation"
+msgstr "Documentation de IPython"
 
-#: spyderlib\spyder.py:936
+#: spyderlib\spyder.py:924
 msgid "Intro to IPython"
 msgstr "Introduction à IPython"
 
-#: spyderlib\spyder.py:938
-msgid "Quick Reference"
-msgstr "Documentation de IPython"
+#: spyderlib\spyder.py:926
+msgid "Quick reference"
+msgstr "Référence rapide"
 
-#: spyderlib\spyder.py:940
+#: spyderlib\spyder.py:928
 msgid "Console help"
 msgstr "Aide sur la console"
 
-#: spyderlib\spyder.py:946
-msgid "Qt Help"
-msgstr "Aide Qt"
-
-#: spyderlib\spyder.py:950
-msgid "Web Resources"
-msgstr "Documentation en ligne"
-
-#: spyderlib\spyder.py:979
+#: spyderlib\spyder.py:961
 msgid "Python(x,y) documentation folder"
 msgstr "Dossier de documentation Python(x,y)"
 
-#: spyderlib\spyder.py:981
-msgid "IPython documentation"
-msgstr "Documentation de IPython"
-
-#: spyderlib\spyder.py:983
+#: spyderlib\spyder.py:965
 msgid "guidata documentation"
 msgstr "Documentation de guidata"
 
-#: spyderlib\spyder.py:986
+#: spyderlib\spyder.py:968
 msgid "guiqwt documentation"
 msgstr "Documentation de guiqwt"
 
-#: spyderlib\spyder.py:992
+#: spyderlib\spyder.py:974
 msgid "NumPy documentation"
 msgstr "Documentation de NumPy"
 
-#: spyderlib\spyder.py:994
+#: spyderlib\spyder.py:976
 msgid "NumPy reference guide"
 msgstr "Manuel de référence de NumPy"
 
-#: spyderlib\spyder.py:996
+#: spyderlib\spyder.py:978
 msgid "NumPy user guide"
 msgstr "Manuel de l'utilisateur de NumPy"
 
-#: spyderlib\spyder.py:998
+#: spyderlib\spyder.py:980
 msgid "SciPy documentation"
 msgstr "Documentation de SciPy"
 
-#: spyderlib\spyder.py:1026
-msgid "Windows and toolbars"
-msgstr "Fenêtres et barres d'outils"
+#: spyderlib\spyder.py:987
+msgid "Installed Python modules"
+msgstr "Modules Python installés"
+
+#: spyderlib\spyder.py:991
+msgid "Online documentation"
+msgstr "Documentation en ligne"
+
+#: spyderlib\spyder.py:996
+msgid "Qt documentation"
+msgstr "Documentation de Qt"
+
+#: spyderlib\spyder.py:1002
+msgid "About %s..."
+msgstr "À propos de %s..."
+
+#: spyderlib\spyder.py:1023
+msgid "Windows"
+msgstr "Fenêtres"
+
+#: spyderlib\spyder.py:1024
+msgid "Toolbars"
+msgstr "Barres d'outils"
 
-#: spyderlib\spyder.py:1030
+#: spyderlib\spyder.py:1027
 msgid "Reset window layout"
 msgstr "Réinitialiser la disposition des fenêtres"
 
-#: spyderlib\spyder.py:1032
+#: spyderlib\spyder.py:1029
 msgid "Custom window layouts"
 msgstr "Dispositions de fenêtres personnalisées"
 
-#: spyderlib\spyder.py:1038
+#: spyderlib\spyder.py:1035
 msgid "Switch to/from layout %d"
 msgstr "Basculer vers/depuis la disposition %d"
 
-#: spyderlib\spyder.py:1044
+#: spyderlib\spyder.py:1041
 msgid "Set layout %d"
 msgstr "Définir la disposition %d"
 
-#: spyderlib\spyder.py:1054
+#: spyderlib\spyder.py:1051
 msgid "Attached console window (debugging)"
 msgstr "Invite de commandes attaché (débogage)"
 
-#: spyderlib\spyder.py:1328
+#: spyderlib\spyder.py:1324
 msgid ""
 "Window layout will be reset to default settings: this affects window "
 "position, size and dockwidgets.\n"
@@ -2877,46 +2884,46 @@ msgstr ""
 "défaut.\n"
 "Souhaitez-vous continuer ?"
 
-#: spyderlib\spyder.py:1346
+#: spyderlib\spyder.py:1342
 msgid "Quick switch layout #%d 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:1537 spyderlib\spyder.py:1538
+#: spyderlib\spyder.py:1568 spyderlib\spyder.py:1569
 msgid "Maximize current plugin"
 msgstr "Agrandir la fenêtre courante"
 
-#: spyderlib\spyder.py:1541
+#: spyderlib\spyder.py:1572
 msgid "Restore current plugin"
 msgstr "Réduire la fenêtre courante"
 
-#: spyderlib\spyder.py:1542
+#: spyderlib\spyder.py:1573
 msgid "Restore plugin to its original size"
 msgstr "Restaurer la fenêtre à sa taille d'origine"
 
-#: spyderlib\spyder.py:1613
+#: spyderlib\spyder.py:1644
 msgid "(not installed)"
 msgstr "(non installé)"
 
-#: spyderlib\spyder.py:1631
+#: spyderlib\spyder.py:1662
 msgid "About %s"
 msgstr "À propos de %s"
 
-#: spyderlib\spyder.py:1796
+#: spyderlib\spyder.py:1830
 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:1997
+#: spyderlib\spyder.py:2031
 msgid "Open session"
 msgstr "Ouvrir une session"
 
-#: spyderlib\spyder.py:1998 spyderlib\spyder.py:2009
+#: spyderlib\spyder.py:2032 spyderlib\spyder.py:2043
 msgid "Spyder sessions"
 msgstr "Sessions Spyder"
 
-#: spyderlib\spyder.py:2008
+#: spyderlib\spyder.py:2042
 msgid "Save session"
 msgstr "Enregistrer la session"
 
@@ -2966,6 +2973,10 @@ msgstr ""
 "Le processus de génération de l'aide sous la forme de texte enrichi a échoué."
 "</br>Merci d'activer le mode d'affichage en texte brut."
 
+#: spyderlib\utils\introspection\rope_plugin.py:34
+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:331
 msgid "Supported files"
 msgstr "Fichiers compatibles"
@@ -3103,12 +3114,12 @@ msgstr ""
 "réciproquement)."
 
 #: spyderlib\widgets\browser.py:30
-#: spyderlib\widgets\sourcecode\codeeditor.py:2248
+#: spyderlib\widgets\sourcecode\codeeditor.py:2063
 msgid "Zoom out"
 msgstr "Réduire"
 
 #: spyderlib\widgets\browser.py:33
-#: spyderlib\widgets\sourcecode\codeeditor.py:2245
+#: spyderlib\widgets\sourcecode\codeeditor.py:2060
 msgid "Zoom in"
 msgstr "Agrandir"
 
@@ -3170,7 +3181,7 @@ msgstr "Fonctionnalités associées"
 msgid "Optional Dependencies"
 msgstr "Dépendances optionnelles"
 
-#: spyderlib\widgets\dependencies.py:133
+#: spyderlib\widgets\dependencies.py:134
 msgid ""
 "Spyder depends on several Python modules to provide additional functionality "
 "for its plugins. The table below shows the required and installed versions "
@@ -3185,7 +3196,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:148
+#: spyderlib\widgets\dependencies.py:149
 msgid "Copy to clipboard"
 msgstr "Copier dans le presse-papier"
 
@@ -3338,86 +3349,86 @@ msgstr "Presse-papiers vide"
 msgid "Nothing to be imported from clipboard."
 msgstr "Aucune donnée ne peut être importée depuis le presse-papiers."
 
-#: spyderlib\widgets\editor.py:69 spyderlib\widgets\editor.py:557
+#: spyderlib\widgets\editor.py:70 spyderlib\widgets\editor.py:572
 msgid "File list management"
 msgstr "Gestionnaire de fichiers"
 
-#: spyderlib\widgets\editor.py:73
+#: spyderlib\widgets\editor.py:74
 msgid "Filter:"
 msgstr "Filtre :"
 
-#: spyderlib\widgets\editor.py:78
+#: spyderlib\widgets\editor.py:79
 msgid "(press <b>Enter</b> to edit file)"
 msgstr "(appuyer sur <b>Entrée</b> pour modifier le fichier)"
 
-#: spyderlib\widgets\editor.py:93
+#: spyderlib\widgets\editor.py:94
 msgid "&Edit file"
 msgstr "Modifi&er le fichier"
 
-#: spyderlib\widgets\editor.py:102
+#: spyderlib\widgets\editor.py:103
 msgid "&Close file"
 msgstr "&Fermer le fichier"
 
-#: spyderlib\widgets\editor.py:110
+#: spyderlib\widgets\editor.py:111
 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:560
+#: spyderlib\widgets\editor.py:575
 msgid "Copy path to clipboard"
 msgstr "Copier le chemin d'accès dans le presse-papier"
 
-#: spyderlib\widgets\editor.py:1099
+#: spyderlib\widgets\editor.py:1115
 msgid "Temporary file"
 msgstr "Fichier temporaire"
 
-#: spyderlib\widgets\editor.py:1196
+#: spyderlib\widgets\editor.py:1212
 msgid "New window"
 msgstr "Nouvelle fenêtre"
 
-#: spyderlib\widgets\editor.py:1197
+#: spyderlib\widgets\editor.py:1213
 msgid "Create a new editor window"
 msgstr "Créer une nouvelle fenêtre d'édition"
 
-#: spyderlib\widgets\editor.py:1200
+#: spyderlib\widgets\editor.py:1216
 msgid "Split vertically"
 msgstr "Séparation verticale"
 
-#: spyderlib\widgets\editor.py:1202
+#: spyderlib\widgets\editor.py:1218
 msgid "Split vertically this editor window"
 msgstr "Séparer en deux verticalement cette fenêtre d'édition"
 
-#: spyderlib\widgets\editor.py:1204
+#: spyderlib\widgets\editor.py:1220
 msgid "Split horizontally"
 msgstr "Séparation horizontale"
 
-#: spyderlib\widgets\editor.py:1206
+#: spyderlib\widgets\editor.py:1222
 msgid "Split horizontally this editor window"
 msgstr "Séparer en deux horizontalement cette fenêtre d'édition"
 
-#: spyderlib\widgets\editor.py:1208
+#: spyderlib\widgets\editor.py:1224
 msgid "Close this panel"
 msgstr "Fermer ce panneau"
 
-#: spyderlib\widgets\editor.py:1340
+#: spyderlib\widgets\editor.py:1356
 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:1403
+#: spyderlib\widgets\editor.py:1419
 msgid "Save"
 msgstr "Enregistrer"
 
-#: spyderlib\widgets\editor.py:1404
+#: spyderlib\widgets\editor.py:1420
 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:1426
+#: spyderlib\widgets\editor.py:1442
 msgid "Save Python script"
 msgstr "Enregistrer le script Python"
 
-#: spyderlib\widgets\editor.py:1647
+#: spyderlib\widgets\editor.py:1663
 msgid ""
 "<b>%s</b> is unavailable (this file may have been removed, moved or renamed "
 "outside Spyder).<br>Do you want to close it?"
@@ -3425,7 +3436,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:1667
+#: spyderlib\widgets\editor.py:1683
 msgid ""
 "<b>%s</b> has been modified outside Spyder.<br>Do you want to reload it and "
 "lose all your changes?"
@@ -3433,7 +3444,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:1763
+#: spyderlib\widgets\editor.py:1779
 msgid ""
 "All changes to <b>%s</b> will be lost.<br>Do you want to revert file from "
 "disk?"
@@ -3442,11 +3453,11 @@ msgstr ""
 "<br>Souhaitez-vous revenir à la version du fichier enregistrée sur le "
 "disque ?"
 
-#: spyderlib\widgets\editor.py:1902
+#: spyderlib\widgets\editor.py:1919
 msgid "Loading %s..."
 msgstr "Chargement de \"%s\" en cours..."
 
-#: spyderlib\widgets\editor.py:1912
+#: spyderlib\widgets\editor.py:1929
 msgid ""
 "<b>%s</b> contains mixed end-of-line characters.<br>Spyder will fix this "
 "automatically."
@@ -3454,11 +3465,11 @@ 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:2260
+#: spyderlib\widgets\editor.py:2277
 msgid "Close window"
 msgstr "Fermer la fenêtre"
 
-#: spyderlib\widgets\editor.py:2262
+#: spyderlib\widgets\editor.py:2279
 msgid "Close this window"
 msgstr "Fermer cette fenêtre d'édition"
 
@@ -3690,7 +3701,7 @@ msgid "Terminated."
 msgstr "Terminé."
 
 #: spyderlib\widgets\externalshell\baseshell.py:235
-#: spyderlib\widgets\mixins.py:511
+#: spyderlib\widgets\ipython.py:336 spyderlib\widgets\mixins.py:599
 msgid "Arguments"
 msgstr "Arguments"
 
@@ -3825,9 +3836,10 @@ msgid "No argument"
 msgstr "Aucun argument"
 
 #: spyderlib\widgets\externalshell\pythonshell.py:524
+#, fuzzy
 msgid ""
-"The console failed to start! That's all we know :(<br>Please close it and "
-"open a new one."
+"The kernel failed to start!! That's all we know... Please close this console "
+"and open a new one."
 msgstr ""
 "Le démarrage de la console a échoué !<br>C'est malheureusement tout ce que "
 "nous savons...<br>Merci de fermer la console et d'en réouvrir une autre."
@@ -4078,71 +4090,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:248
+#: spyderlib\widgets\internalshell.py:250
 msgid "Help..."
 msgstr "Aide..."
 
-#: spyderlib\widgets\internalshell.py:255
+#: spyderlib\widgets\internalshell.py:257
 msgid "Help"
 msgstr "Aide"
 
-#: spyderlib\widgets\internalshell.py:264
+#: spyderlib\widgets\internalshell.py:266
 msgid "Shell special commands:"
 msgstr "Commandes spéciales de la console :"
 
-#: spyderlib\widgets\internalshell.py:265
+#: spyderlib\widgets\internalshell.py:267
 msgid "Internal editor:"
 msgstr "Éditeur interne :"
 
-#: spyderlib\widgets\internalshell.py:266
+#: spyderlib\widgets\internalshell.py:268
 msgid "External editor:"
 msgstr "Éditeur externe :"
 
-#: spyderlib\widgets\internalshell.py:267
+#: spyderlib\widgets\internalshell.py:269
 msgid "Run script:"
 msgstr "Exécuter un script :"
 
-#: spyderlib\widgets\internalshell.py:268
+#: spyderlib\widgets\internalshell.py:270
 msgid "Remove references:"
 msgstr "Supprimer des références :"
 
-#: spyderlib\widgets\internalshell.py:269
+#: spyderlib\widgets\internalshell.py:271
 msgid "System commands:"
 msgstr "Commandes systèmes :"
 
-#: spyderlib\widgets\internalshell.py:270
+#: spyderlib\widgets\internalshell.py:272
 msgid "Python help:"
 msgstr "Aide Python :"
 
-#: spyderlib\widgets\internalshell.py:271
+#: spyderlib\widgets\internalshell.py:273
 msgid "GUI-based editor:"
 msgstr "Éditeur graphique :"
 
-#: spyderlib\widgets\ipython.py:398
+#: spyderlib\widgets\ipython.py:440
 msgid "An error ocurred while starting the kernel!"
 msgstr "Une erreur est survenue lors du démarrage du noyau !"
 
-#: spyderlib\widgets\ipython.py:426
+#: spyderlib\widgets\ipython.py:468
 msgid "Interrupt kernel"
 msgstr "Interrompre le noyau"
 
-#: spyderlib\widgets\ipython.py:429
+#: spyderlib\widgets\ipython.py:471
 msgid "Restart kernel"
 msgstr "Redémarrer le noyau"
 
-#: spyderlib\widgets\ipython.py:461
+#: spyderlib\widgets\ipython.py:503
 msgid "Inspect current object"
 msgstr "Inspecter l'onglet courant"
 
-#: spyderlib\widgets\ipython.py:465
+#: spyderlib\widgets\ipython.py:507
 msgid "Clear line or block"
 msgstr "Effacer la ligne ou le bloc"
 
-#: spyderlib\widgets\ipython.py:469
+#: spyderlib\widgets\ipython.py:511
 msgid "Clear console"
 msgstr "Effacer la console"
 
-#: spyderlib\widgets\ipython.py:512
+#: spyderlib\widgets\ipython.py:555
 msgid ""
 "It seems the kernel died unexpectedly. Use 'Restart kernel' to continue "
 "using this console."
@@ -4150,26 +4162,22 @@ 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:524
+#: spyderlib\widgets\ipython.py:567
 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:533
+#: spyderlib\widgets\ipython.py:576
 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:550
+#: spyderlib\widgets\ipython.py:593
 msgid "Connecting to kernel..."
 msgstr "Connexion à un noyau existant..."
 
-#: spyderlib\widgets\mixins.py:516
-msgid "Documentation"
-msgstr "Documentation"
-
 #: spyderlib\widgets\onecolumntree.py:63
 msgid "Collapse all"
 msgstr "Replier tout"
@@ -4494,71 +4502,67 @@ msgstr ""
 msgid "Module or package:"
 msgstr "Module ou paquet :"
 
-#: spyderlib\widgets\shell.py:129
+#: spyderlib\widgets\shell.py:130
 msgid "Save history log..."
 msgstr "Enregistrer l'historique..."
 
-#: spyderlib\widgets\shell.py:131
+#: spyderlib\widgets\shell.py:132
 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:251
+#: spyderlib\widgets\shell.py:252
 msgid "Save history log"
 msgstr "Enregistrer l'historique"
 
-#: spyderlib\widgets\shell.py:254
+#: spyderlib\widgets\shell.py:255
 msgid "History logs"
 msgstr "Fichiers d'historique"
 
-#: spyderlib\widgets\shell.py:265
+#: spyderlib\widgets\shell.py:266
 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:690
+#: spyderlib\widgets\shell.py:691
 msgid "Copy without prompts"
 msgstr "Copier sans les préfixes"
 
-#: spyderlib\widgets\shell.py:693 spyderlib\widgets\shell.py:696
+#: spyderlib\widgets\shell.py:694 spyderlib\widgets\shell.py:697
 msgid "Clear line"
 msgstr "Effacer la ligne"
 
-#: spyderlib\widgets\shell.py:698
+#: spyderlib\widgets\shell.py:699
 msgid "Clear shell"
 msgstr "Effacer la console"
 
-#: spyderlib\widgets\shell.py:701
+#: spyderlib\widgets\shell.py:702
 msgid "Clear shell contents ('cls' command)"
 msgstr "Effacer le contenu de la console"
 
-#: spyderlib\widgets\sourcecode\codeeditor.py:69
-msgid "Editor's code completion, go-to-definition and help"
-msgstr "Editeur : complétion de code, aller à la définition, etc."
-
-#: spyderlib\widgets\sourcecode\codeeditor.py:273
+#: spyderlib\widgets\sourcecode\codeeditor.py:83
 msgid "Go to line:"
 msgstr "Aller à la ligne :"
 
-#: spyderlib\widgets\sourcecode\codeeditor.py:282
+#: spyderlib\widgets\sourcecode\codeeditor.py:92
 msgid "Line count:"
 msgstr "Nombre de lignes :"
 
-#: spyderlib\widgets\sourcecode\codeeditor.py:1224
+#: spyderlib\widgets\sourcecode\codeeditor.py:1027
 msgid "Breakpoint"
 msgstr "Point d'arrêt"
 
-#: spyderlib\widgets\sourcecode\codeeditor.py:1225
+#: spyderlib\widgets\sourcecode\codeeditor.py:1028
 msgid "Condition:"
 msgstr "Condition :"
 
-#: spyderlib\widgets\sourcecode\codeeditor.py:1661
+#: spyderlib\widgets\sourcecode\codeeditor.py:1476
 msgid "To do"
 msgstr "À faire"
 
-#: spyderlib\widgets\sourcecode\codeeditor.py:2240
+#: spyderlib\widgets\sourcecode\codeeditor.py:2055
 msgid "Go to definition"
 msgstr "Aller à la définition de l'objet"
 
@@ -4614,6 +4618,36 @@ msgstr "Fermer l'onglet"
 msgid "Text editor"
 msgstr "Éditeur de texte"
 
+#, fuzzy
+#~ msgid "Plugins"
+#~ msgstr " lignes"
+
+#~ msgid "Web resources"
+#~ msgstr "Ressources en ligne"
+
+#, fuzzy
+#~ msgid "Qt help"
+#~ msgstr "Aide Qt"
+
+#, fuzzy
+#~ msgid "IPython help"
+#~ msgstr "Aide Python :"
+
+#~ msgid "Balloon tips"
+#~ msgstr "Info-bulles"
+
+#~ msgid "Close current dockwidget"
+#~ msgstr "Fermer le panneau actif"
+
+#~ msgid "IPython Help"
+#~ msgstr "Aide IPython"
+
+#~ msgid "Windows and toolbars"
+#~ msgstr "Fenêtres et barres d'outils"
+
+#~ msgid "Documentation"
+#~ msgstr "Documentation"
+
 #~ msgid "Automatic notification to object inspector"
 #~ msgstr "Notification automatique à l'inspecteur d'objets"
 
diff --git a/spyderlib/locale/spyderlib.pot b/spyderlib/locale/spyderlib.pot
index 49b5c00..2277e8d 100755
--- 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: 2013-11-09 14:09+Paris, Madrid\n"
+"POT-Creation-Date: 2014-01-04 15:22+Paris, Madrid\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"
@@ -219,7 +219,7 @@ msgid "Background:"
 msgstr ""
 
 #: spyderlib\plugins\configdialog.py:768
-#: spyderlib\widgets\sourcecode\codeeditor.py:280
+#: spyderlib\widgets\sourcecode\codeeditor.py:90
 msgid "Current line:"
 msgstr ""
 
@@ -287,12 +287,12 @@ msgstr ""
 msgid "Internal console"
 msgstr ""
 
-#: spyderlib\plugins\console.py:125 spyderlib\spyder.py:810
-#: spyderlib\widgets\ipython.py:473
+#: spyderlib\plugins\console.py:125 spyderlib\spyder.py:800
+#: spyderlib\widgets\ipython.py:515
 msgid "&Quit"
 msgstr ""
 
-#: spyderlib\plugins\console.py:126 spyderlib\spyder.py:811
+#: spyderlib\plugins\console.py:126 spyderlib\spyder.py:801
 msgid "Quit"
 msgstr ""
 
@@ -330,7 +330,7 @@ msgid "Set maximum line count"
 msgstr ""
 
 #: spyderlib\plugins\console.py:148 spyderlib\plugins\explorer.py:60
-#: spyderlib\plugins\history.py:153 spyderlib\plugins\inspector.py:349
+#: spyderlib\plugins\history.py:153 spyderlib\plugins\inspector.py:350
 #: spyderlib\plugins\projectexplorer.py:58
 msgid "&Font..."
 msgstr ""
@@ -349,14 +349,15 @@ msgstr ""
 
 #: spyderlib\plugins\console.py:156 spyderlib\plugins\editor.py:134
 #: spyderlib\plugins\externalconsole.py:95 spyderlib\plugins\history.py:41
-#: spyderlib\plugins\history.py:156 spyderlib\plugins\inspector.py:170
-#: spyderlib\plugins\inspector.py:352
+#: spyderlib\plugins\history.py:156 spyderlib\plugins\inspector.py:171
+#: spyderlib\plugins\inspector.py:353
 msgid "Wrap lines"
 msgstr ""
 
 #: spyderlib\plugins\console.py:159 spyderlib\plugins\editor.py:164
 #: spyderlib\plugins\externalconsole.py:144
-msgid "Balloon tips"
+#: spyderlib\plugins\ipythonconsole.py:84
+msgid "Display balloon tips"
 msgstr ""
 
 #: spyderlib\plugins\console.py:163 spyderlib\plugins\editor.py:156
@@ -383,7 +384,7 @@ msgid "Python scripts"
 msgstr ""
 
 #: spyderlib\plugins\console.py:269 spyderlib\plugins\explorer.py:111
-#: spyderlib\plugins\history.py:271 spyderlib\plugins\inspector.py:643
+#: spyderlib\plugins\history.py:271 spyderlib\plugins\inspector.py:645
 #: spyderlib\plugins\projectexplorer.py:120
 msgid "Select a new font"
 msgstr ""
@@ -406,9 +407,9 @@ msgstr ""
 
 #: spyderlib\plugins\editor.py:87 spyderlib\plugins\editor.py:505
 #: spyderlib\plugins\editor.py:1570 spyderlib\plugins\inspector.py:133
-#: spyderlib\plugins\inspector.py:380 spyderlib\widgets\editor.py:574
-#: spyderlib\widgets\sourcecode\codeeditor.py:270
-#: spyderlib\widgets\sourcecode\codeeditor.py:2558
+#: spyderlib\plugins\inspector.py:381 spyderlib\widgets\editor.py:589
+#: spyderlib\widgets\sourcecode\codeeditor.py:80
+#: spyderlib\widgets\sourcecode\codeeditor.py:2378
 msgid "Editor"
 msgstr ""
 
@@ -431,7 +432,7 @@ msgstr ""
 #: spyderlib\plugins\editor.py:110 spyderlib\plugins\editor.py:178
 #: spyderlib\plugins\externalconsole.py:90
 #: spyderlib\plugins\externalconsole.py:135 spyderlib\plugins\history.py:40
-#: spyderlib\plugins\inspector.py:169 spyderlib\plugins\ipythonconsole.py:108
+#: spyderlib\plugins\inspector.py:170 spyderlib\plugins\ipythonconsole.py:108
 msgid "Source code"
 msgstr ""
 
@@ -456,13 +457,13 @@ msgid "Highlight occurences after"
 msgstr ""
 
 #: spyderlib\plugins\editor.py:137 spyderlib\plugins\history.py:49
-#: spyderlib\plugins\inspector.py:173
+#: spyderlib\plugins\inspector.py:174
 msgid "Syntax color scheme: "
 msgstr ""
 
 #: spyderlib\plugins\editor.py:149 spyderlib\plugins\runconfig.py:304
 #: spyderlib\plugins\runconfig.py:426 spyderlib\plugins\runconfig.py:431
-#: spyderlib\spyder.py:1795 spyderlib\widgets\explorer.py:230
+#: spyderlib\spyder.py:1829 spyderlib\widgets\explorer.py:230
 #: spyderlib\widgets\externalshell\baseshell.py:138
 msgid "Run"
 msgstr ""
@@ -568,7 +569,7 @@ msgid "<u>Note</u>: add <b>analysis:ignore</b> in a comment to ignore code/style
 msgstr ""
 
 #: spyderlib\plugins\editor.py:219
-#: spyderlib\widgets\sourcecode\codeeditor.py:1607
+#: spyderlib\widgets\sourcecode\codeeditor.py:1422
 msgid "Code analysis"
 msgstr ""
 
@@ -738,7 +739,7 @@ msgstr ""
 msgid "Debug with winpdb"
 msgstr ""
 
-#: spyderlib\plugins\editor.py:663 spyderlib\spyder.py:609
+#: spyderlib\plugins\editor.py:663 spyderlib\spyder.py:606
 msgid "&Debug"
 msgstr ""
 
@@ -791,7 +792,7 @@ msgid "Debugging control"
 msgstr ""
 
 #: spyderlib\plugins\editor.py:722 spyderlib\plugins\editor.py:1222
-#: spyderlib\spyder.py:604
+#: spyderlib\spyder.py:601
 msgid "&Run"
 msgstr ""
 
@@ -817,7 +818,7 @@ msgid "Run again last file"
 msgstr ""
 
 #: spyderlib\plugins\editor.py:748
-#: spyderlib\widgets\sourcecode\codeeditor.py:2243
+#: spyderlib\widgets\sourcecode\codeeditor.py:2058
 msgid "Run &selection"
 msgstr ""
 
@@ -900,12 +901,12 @@ msgid "Go to next cursor position"
 msgstr ""
 
 #: spyderlib\plugins\editor.py:823
-#: spyderlib\widgets\sourcecode\codeeditor.py:2237
+#: spyderlib\widgets\sourcecode\codeeditor.py:2052
 msgid "Comment"
 msgstr ""
 
 #: spyderlib\plugins\editor.py:823
-#: spyderlib\widgets\sourcecode\codeeditor.py:2237
+#: spyderlib\widgets\sourcecode\codeeditor.py:2052
 msgid "Uncomment"
 msgstr ""
 
@@ -1001,47 +1002,47 @@ msgstr ""
 msgid "Open &recent"
 msgstr ""
 
-#: spyderlib\plugins\editor.py:1210 spyderlib\spyder.py:585
+#: spyderlib\plugins\editor.py:1210 spyderlib\spyder.py:582
 msgid "File toolbar"
 msgstr ""
 
-#: spyderlib\plugins\editor.py:1211 spyderlib\spyder.py:595
+#: spyderlib\plugins\editor.py:1211 spyderlib\spyder.py:592
 msgid "Search toolbar"
 msgstr ""
 
-#: spyderlib\plugins\editor.py:1212 spyderlib\spyder.py:600
+#: spyderlib\plugins\editor.py:1212 spyderlib\spyder.py:597
 msgid "Source toolbar"
 msgstr ""
 
-#: spyderlib\plugins\editor.py:1213 spyderlib\spyder.py:605
+#: spyderlib\plugins\editor.py:1213 spyderlib\spyder.py:602
 msgid "Run toolbar"
 msgstr ""
 
-#: spyderlib\plugins\editor.py:1214 spyderlib\spyder.py:610
+#: spyderlib\plugins\editor.py:1214 spyderlib\spyder.py:607
 msgid "Debug toolbar"
 msgstr ""
 
-#: spyderlib\plugins\editor.py:1215 spyderlib\spyder.py:590
+#: spyderlib\plugins\editor.py:1215 spyderlib\spyder.py:587
 msgid "Edit toolbar"
 msgstr ""
 
-#: spyderlib\plugins\editor.py:1218 spyderlib\spyder.py:582
+#: spyderlib\plugins\editor.py:1218 spyderlib\spyder.py:579
 msgid "&File"
 msgstr ""
 
-#: spyderlib\plugins\editor.py:1219 spyderlib\spyder.py:589
+#: spyderlib\plugins\editor.py:1219 spyderlib\spyder.py:586
 msgid "&Edit"
 msgstr ""
 
-#: spyderlib\plugins\editor.py:1220 spyderlib\spyder.py:594
+#: spyderlib\plugins\editor.py:1220 spyderlib\spyder.py:591
 msgid "&Search"
 msgstr ""
 
-#: spyderlib\plugins\editor.py:1221 spyderlib\spyder.py:599
+#: spyderlib\plugins\editor.py:1221 spyderlib\spyder.py:596
 msgid "Sour&ce"
 msgstr ""
 
-#: spyderlib\plugins\editor.py:1223 spyderlib\spyder.py:617
+#: spyderlib\plugins\editor.py:1223 spyderlib\spyder.py:614
 msgid "&Tools"
 msgstr ""
 
@@ -1073,7 +1074,7 @@ msgstr ""
 msgid "File explorer"
 msgstr ""
 
-#: spyderlib\plugins\explorer.py:61 spyderlib\plugins\inspector.py:350
+#: spyderlib\plugins\explorer.py:61 spyderlib\plugins\inspector.py:351
 #: spyderlib\plugins\projectexplorer.py:59
 msgid "Set font style"
 msgstr ""
@@ -1084,9 +1085,9 @@ msgstr ""
 
 #: spyderlib\plugins\externalconsole.py:60
 #: spyderlib\plugins\externalconsole.py:1083
-#: spyderlib\plugins\inspector.py:380
+#: spyderlib\plugins\inspector.py:381
 #: spyderlib\widgets\externalshell\baseshell.py:106
-#: spyderlib\widgets\ipython.py:412
+#: spyderlib\widgets\ipython.py:454
 msgid "Console"
 msgstr ""
 
@@ -1337,8 +1338,8 @@ msgid "You can't close this kernel because it has one or more consoles connected
 msgstr ""
 
 #: spyderlib\plugins\externalconsole.py:686
-#: spyderlib\plugins\ipythonconsole.py:480 spyderlib\spyder.py:1327
-#: spyderlib\spyder.py:1345 spyderlib\utils\environ.py:95
+#: spyderlib\plugins\ipythonconsole.py:480 spyderlib\spyder.py:1323
+#: spyderlib\spyder.py:1341 spyderlib\utils\environ.py:95
 #: spyderlib\utils\environ.py:108
 msgid "Warning"
 msgstr ""
@@ -1447,11 +1448,11 @@ msgstr ""
 msgid "Scroll automatically to last entry"
 msgstr ""
 
-#: spyderlib\plugins\history.py:102 spyderlib\plugins\inspector.py:433
-#: spyderlib\widgets\editor.py:661 spyderlib\widgets\explorer.py:990
+#: spyderlib\plugins\history.py:102 spyderlib\plugins\inspector.py:435
+#: spyderlib\widgets\editor.py:677 spyderlib\widgets\explorer.py:990
 #: spyderlib\widgets\externalshell\baseshell.py:151
 #: spyderlib\widgets\externalshell\namespacebrowser.py:231
-#: spyderlib\widgets\ipython.py:449
+#: spyderlib\widgets\ipython.py:491
 msgid "Options"
 msgstr ""
 
@@ -1495,91 +1496,91 @@ msgstr ""
 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:136
+#: spyderlib\plugins\inspector.py:137
 msgid "Python Console"
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:138
+#: spyderlib\plugins\inspector.py:139
 msgid "IPython Console"
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:151
+#: spyderlib\plugins\inspector.py:152
 msgid "Additional features"
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:152
+#: spyderlib\plugins\inspector.py:153
 msgid "Render mathematical equations"
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:158
+#: spyderlib\plugins\inspector.py:159
 msgid "This feature requires Sphinx 1.1 or superior."
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:160
+#: spyderlib\plugins\inspector.py:161
 msgid "Sphinx %s is currently installed."
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:334
+#: spyderlib\plugins\inspector.py:335
 msgid "No documentation available"
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:373
+#: spyderlib\plugins\inspector.py:374
 msgid "Source"
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:388 spyderlib\widgets\dicteditor.py:162
+#: spyderlib\plugins\inspector.py:390 spyderlib\widgets\dicteditor.py:162
 msgid "Object"
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:403
+#: spyderlib\plugins\inspector.py:405
 msgid "Plain Text"
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:407
+#: spyderlib\plugins\inspector.py:409
 msgid "Show Source"
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:411
+#: spyderlib\plugins\inspector.py:413
 msgid "Rich Text"
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:421
+#: spyderlib\plugins\inspector.py:423
 msgid "Automatic import"
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:476 spyderlib\plugins\inspector.py:885
+#: spyderlib\plugins\inspector.py:478 spyderlib\plugins\inspector.py:887
 msgid "Object inspector"
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:599
+#: spyderlib\plugins\inspector.py:601
 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:605
+#: spyderlib\plugins\inspector.py:607
 msgid "Preferences > Object Inspector"
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:607
+#: spyderlib\plugins\inspector.py:609
 msgid "Usage"
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:613
+#: spyderlib\plugins\inspector.py:615
 msgid "Please consider installing Sphinx to get documentation rendered in rich text."
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:846
+#: spyderlib\plugins\inspector.py:848
 msgid "Lock"
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:846
+#: spyderlib\plugins\inspector.py:848
 msgid "Unlock"
 msgstr ""
 
-#: spyderlib\plugins\inspector.py:886
+#: spyderlib\plugins\inspector.py:888
 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:930
+#: spyderlib\plugins\inspector.py:932
 msgid "No source code available."
 msgstr ""
 
@@ -1620,10 +1621,6 @@ msgid ""
 "Note: Use the Q key to get out of the pager."
 msgstr ""
 
-#: spyderlib\plugins\ipythonconsole.py:84
-msgid "Display balloon tips"
-msgstr ""
-
 #: spyderlib\plugins\ipythonconsole.py:85
 msgid "Ask for confirmation before closing"
 msgstr ""
@@ -2237,7 +2234,7 @@ msgstr ""
 msgid "IPython Console integration"
 msgstr ""
 
-#: spyderlib\spyder.py:125 spyderlib\spyder.py:455
+#: spyderlib\spyder.py:125
 msgid "Initializing..."
 msgstr ""
 
@@ -2261,7 +2258,7 @@ msgstr ""
 msgid "Numpy and Scipy documentation"
 msgstr ""
 
-#: spyderlib\spyder.py:297 spyderlib\spyder.py:989
+#: spyderlib\spyder.py:297 spyderlib\spyder.py:971
 msgid "Matplotlib documentation"
 msgstr ""
 
@@ -2285,342 +2282,350 @@ msgstr ""
 msgid "Save current session and quit application"
 msgstr ""
 
-#: spyderlib\spyder.py:516
-msgid "Close current dockwidget"
+#: spyderlib\spyder.py:513
+msgid "Close current plugin"
 msgstr ""
 
-#: spyderlib\spyder.py:522
+#: spyderlib\spyder.py:519
 msgid "&Find text"
 msgstr ""
 
-#: spyderlib\spyder.py:528
+#: spyderlib\spyder.py:525
 msgid "Find &next"
 msgstr ""
 
-#: spyderlib\spyder.py:534
+#: spyderlib\spyder.py:531
 msgid "Find &previous"
 msgstr ""
 
-#: spyderlib\spyder.py:539
+#: spyderlib\spyder.py:536
 msgid "&Replace text"
 msgstr ""
 
-#: spyderlib\spyder.py:554 spyderlib\widgets\sourcecode\codeeditor.py:2213
+#: spyderlib\spyder.py:551 spyderlib\widgets\sourcecode\codeeditor.py:2028
 msgid "Undo"
 msgstr ""
 
-#: spyderlib\spyder.py:556 spyderlib\widgets\sourcecode\codeeditor.py:2216
+#: spyderlib\spyder.py:553 spyderlib\widgets\sourcecode\codeeditor.py:2031
 msgid "Redo"
 msgstr ""
 
-#: spyderlib\spyder.py:557 spyderlib\widgets\arrayeditor.py:327
-#: spyderlib\widgets\dicteditor.py:563 spyderlib\widgets\shell.py:121
-#: spyderlib\widgets\sourcecode\codeeditor.py:2222
+#: spyderlib\spyder.py:554 spyderlib\widgets\arrayeditor.py:327
+#: spyderlib\widgets\dicteditor.py:563 spyderlib\widgets\shell.py:122
+#: spyderlib\widgets\sourcecode\codeeditor.py:2037
 msgid "Copy"
 msgstr ""
 
-#: spyderlib\spyder.py:559 spyderlib\widgets\shell.py:117
-#: spyderlib\widgets\sourcecode\codeeditor.py:2219
+#: spyderlib\spyder.py:556 spyderlib\widgets\shell.py:118
+#: spyderlib\widgets\sourcecode\codeeditor.py:2034
 msgid "Cut"
 msgstr ""
 
-#: spyderlib\spyder.py:560 spyderlib\widgets\dicteditor.py:560
-#: spyderlib\widgets\shell.py:125
-#: spyderlib\widgets\sourcecode\codeeditor.py:2225
+#: spyderlib\spyder.py:557 spyderlib\widgets\dicteditor.py:560
+#: spyderlib\widgets\shell.py:126
+#: spyderlib\widgets\sourcecode\codeeditor.py:2040
 msgid "Paste"
 msgstr ""
 
-#: spyderlib\spyder.py:562 spyderlib\widgets\explorer.py:453
-#: spyderlib\widgets\projectexplorer.py:1002 spyderlib\widgets\shell.py:134
-#: spyderlib\widgets\sourcecode\codeeditor.py:2228
+#: spyderlib\spyder.py:559 spyderlib\widgets\explorer.py:453
+#: spyderlib\widgets\projectexplorer.py:1002 spyderlib\widgets\shell.py:135
+#: spyderlib\widgets\sourcecode\codeeditor.py:2043
 msgid "Delete"
 msgstr ""
 
-#: spyderlib\spyder.py:565 spyderlib\widgets\shell.py:138
-#: spyderlib\widgets\sourcecode\codeeditor.py:2232
+#: spyderlib\spyder.py:562 spyderlib\widgets\shell.py:139
+#: spyderlib\widgets\sourcecode\codeeditor.py:2047
 msgid "Select All"
 msgstr ""
 
-#: spyderlib\spyder.py:614
+#: spyderlib\spyder.py:611
 msgid "C&onsoles"
 msgstr ""
 
-#: spyderlib\spyder.py:620
+#: spyderlib\spyder.py:617
 msgid "&View"
 msgstr ""
 
-#: spyderlib\spyder.py:623
+#: spyderlib\spyder.py:620
 msgid "&Help"
 msgstr ""
 
-#: spyderlib\spyder.py:628
+#: spyderlib\spyder.py:625
 msgid "Welcome to Spyder!"
 msgstr ""
 
-#: spyderlib\spyder.py:633
+#: spyderlib\spyder.py:630
 msgid "Pre&ferences"
 msgstr ""
 
-#: spyderlib\spyder.py:641 spyderlib\widgets\pathmanager.py:45
+#: spyderlib\spyder.py:638 spyderlib\widgets\pathmanager.py:45
 #: spyderlib\widgets\projectexplorer.py:593
 msgid "PYTHONPATH manager"
 msgstr ""
 
-#: spyderlib\spyder.py:644
+#: spyderlib\spyder.py:641
 msgid "Python Path Manager"
 msgstr ""
 
-#: spyderlib\spyder.py:647
+#: spyderlib\spyder.py:644
 msgid "Update module names list"
 msgstr ""
 
-#: spyderlib\spyder.py:649
+#: spyderlib\spyder.py:646
 msgid "Refresh list of module names available in PYTHONPATH"
 msgstr ""
 
-#: spyderlib\spyder.py:655
+#: spyderlib\spyder.py:651
 msgid "Current user environment variables..."
 msgstr ""
 
-#: spyderlib\spyder.py:657
+#: spyderlib\spyder.py:653
 msgid "Show and edit current user environment variables in Windows registry (i.e. for all sessions)"
 msgstr ""
 
-#: spyderlib\spyder.py:664 spyderlib\spyder.py:1064
+#: spyderlib\spyder.py:661 spyderlib\spyder.py:1063
 msgid "External Tools"
 msgstr ""
 
-#: spyderlib\spyder.py:668
+#: spyderlib\spyder.py:665
 msgid "Python(x,y) launcher"
 msgstr ""
 
-#: spyderlib\spyder.py:679
+#: spyderlib\spyder.py:672
 msgid "WinPython control panel"
 msgstr ""
 
-#: spyderlib\spyder.py:692
+#: spyderlib\spyder.py:681
 msgid "Qt Designer"
 msgstr ""
 
-#: spyderlib\spyder.py:697
+#: spyderlib\spyder.py:686
 msgid "Qt Linguist"
 msgstr ""
 
-#: spyderlib\spyder.py:703
+#: spyderlib\spyder.py:692
 msgid "Qt examples"
 msgstr ""
 
-#: spyderlib\spyder.py:721
+#: spyderlib\spyder.py:710
 msgid "guidata examples"
 msgstr ""
 
-#: spyderlib\spyder.py:729
+#: spyderlib\spyder.py:718
 msgid "guiqwt examples"
 msgstr ""
 
-#: spyderlib\spyder.py:734
+#: spyderlib\spyder.py:723
 msgid "Sift"
 msgstr ""
 
-#: spyderlib\spyder.py:742
+#: spyderlib\spyder.py:731
 msgid "ViTables"
 msgstr ""
 
-#: spyderlib\spyder.py:756
+#: spyderlib\spyder.py:745
 msgid "Fullscreen mode"
 msgstr ""
 
-#: spyderlib\spyder.py:768
+#: spyderlib\spyder.py:757
 msgid "Main toolbar"
 msgstr ""
 
-#: spyderlib\spyder.py:789
+#: spyderlib\spyder.py:779
 msgid "Loading object inspector..."
 msgstr ""
 
-#: spyderlib\spyder.py:796
+#: spyderlib\spyder.py:786
 msgid "Loading outline explorer..."
 msgstr ""
 
-#: spyderlib\spyder.py:804
+#: spyderlib\spyder.py:794
 msgid "Loading editor..."
 msgstr ""
 
-#: spyderlib\spyder.py:829
+#: spyderlib\spyder.py:819
 msgid "Loading file explorer..."
 msgstr ""
 
-#: spyderlib\spyder.py:836
+#: spyderlib\spyder.py:826
 msgid "Loading history plugin..."
 msgstr ""
 
-#: spyderlib\spyder.py:847
+#: spyderlib\spyder.py:837
 msgid "Loading online help..."
 msgstr ""
 
-#: spyderlib\spyder.py:853
+#: spyderlib\spyder.py:843
 msgid "Loading project explorer..."
 msgstr ""
 
-#: spyderlib\spyder.py:864
+#: spyderlib\spyder.py:854
 msgid "Loading external console..."
 msgstr ""
 
-#: spyderlib\spyder.py:873
+#: spyderlib\spyder.py:863
 msgid "Loading namespace browser..."
 msgstr ""
 
-#: spyderlib\spyder.py:880
+#: spyderlib\spyder.py:870
 msgid "Loading IPython console..."
 msgstr ""
 
-#: spyderlib\spyder.py:891
+#: spyderlib\spyder.py:881
 msgid "Setting up main window..."
 msgstr ""
 
-#: spyderlib\spyder.py:895
-msgid "About %s..."
+#: spyderlib\spyder.py:900
+msgid "Spyder documentation"
 msgstr ""
 
-#: spyderlib\spyder.py:898
-msgid "Optional dependencies..."
+#: spyderlib\spyder.py:904
+msgid "Report issue..."
 msgstr ""
 
-#: spyderlib\spyder.py:901
-msgid "Report issue..."
+#: spyderlib\spyder.py:908
+msgid "Spyder support..."
 msgstr ""
 
-#: spyderlib\spyder.py:922
-msgid "Spyder documentation"
+#: spyderlib\spyder.py:910
+msgid "Optional dependencies..."
 msgstr ""
 
-#: spyderlib\spyder.py:928
+#: spyderlib\spyder.py:917
 msgid "Python documentation"
 msgstr ""
 
-#: spyderlib\spyder.py:935
-msgid "IPython Help"
+#: spyderlib\spyder.py:923 spyderlib\spyder.py:963
+msgid "IPython documentation"
 msgstr ""
 
-#: spyderlib\spyder.py:936
+#: spyderlib\spyder.py:924
 msgid "Intro to IPython"
 msgstr ""
 
-#: spyderlib\spyder.py:938
-msgid "Quick Reference"
+#: spyderlib\spyder.py:926
+msgid "Quick reference"
 msgstr ""
 
-#: spyderlib\spyder.py:940
+#: spyderlib\spyder.py:928
 msgid "Console help"
 msgstr ""
 
-#: spyderlib\spyder.py:946
-msgid "Qt Help"
-msgstr ""
-
-#: spyderlib\spyder.py:950
-msgid "Web Resources"
-msgstr ""
-
-#: spyderlib\spyder.py:979
+#: spyderlib\spyder.py:961
 msgid "Python(x,y) documentation folder"
 msgstr ""
 
-#: spyderlib\spyder.py:981
-msgid "IPython documentation"
-msgstr ""
-
-#: spyderlib\spyder.py:983
+#: spyderlib\spyder.py:965
 msgid "guidata documentation"
 msgstr ""
 
-#: spyderlib\spyder.py:986
+#: spyderlib\spyder.py:968
 msgid "guiqwt documentation"
 msgstr ""
 
-#: spyderlib\spyder.py:992
+#: spyderlib\spyder.py:974
 msgid "NumPy documentation"
 msgstr ""
 
-#: spyderlib\spyder.py:994
+#: spyderlib\spyder.py:976
 msgid "NumPy reference guide"
 msgstr ""
 
-#: spyderlib\spyder.py:996
+#: spyderlib\spyder.py:978
 msgid "NumPy user guide"
 msgstr ""
 
-#: spyderlib\spyder.py:998
+#: spyderlib\spyder.py:980
 msgid "SciPy documentation"
 msgstr ""
 
-#: spyderlib\spyder.py:1026
-msgid "Windows and toolbars"
+#: spyderlib\spyder.py:987
+msgid "Installed Python modules"
+msgstr ""
+
+#: spyderlib\spyder.py:991
+msgid "Online documentation"
+msgstr ""
+
+#: spyderlib\spyder.py:996
+msgid "Qt documentation"
+msgstr ""
+
+#: spyderlib\spyder.py:1002
+msgid "About %s..."
 msgstr ""
 
-#: spyderlib\spyder.py:1030
+#: spyderlib\spyder.py:1023
+msgid "Windows"
+msgstr ""
+
+#: spyderlib\spyder.py:1024
+msgid "Toolbars"
+msgstr ""
+
+#: spyderlib\spyder.py:1027
 msgid "Reset window layout"
 msgstr ""
 
-#: spyderlib\spyder.py:1032
+#: spyderlib\spyder.py:1029
 msgid "Custom window layouts"
 msgstr ""
 
-#: spyderlib\spyder.py:1038
+#: spyderlib\spyder.py:1035
 msgid "Switch to/from layout %d"
 msgstr ""
 
-#: spyderlib\spyder.py:1044
+#: spyderlib\spyder.py:1041
 msgid "Set layout %d"
 msgstr ""
 
-#: spyderlib\spyder.py:1054
+#: spyderlib\spyder.py:1051
 msgid "Attached console window (debugging)"
 msgstr ""
 
-#: spyderlib\spyder.py:1328
+#: spyderlib\spyder.py:1324
 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:1346
+#: spyderlib\spyder.py:1342
 msgid "Quick switch layout #%d has not yet been defined."
 msgstr ""
 
-#: spyderlib\spyder.py:1537 spyderlib\spyder.py:1538
+#: spyderlib\spyder.py:1568 spyderlib\spyder.py:1569
 msgid "Maximize current plugin"
 msgstr ""
 
-#: spyderlib\spyder.py:1541
+#: spyderlib\spyder.py:1572
 msgid "Restore current plugin"
 msgstr ""
 
-#: spyderlib\spyder.py:1542
+#: spyderlib\spyder.py:1573
 msgid "Restore plugin to its original size"
 msgstr ""
 
-#: spyderlib\spyder.py:1613
+#: spyderlib\spyder.py:1644
 msgid "(not installed)"
 msgstr ""
 
-#: spyderlib\spyder.py:1631
+#: spyderlib\spyder.py:1662
 msgid "About %s"
 msgstr ""
 
-#: spyderlib\spyder.py:1796
+#: spyderlib\spyder.py:1830
 msgid "Running an external system terminal is not supported on platform %s."
 msgstr ""
 
-#: spyderlib\spyder.py:1997
+#: spyderlib\spyder.py:2031
 msgid "Open session"
 msgstr ""
 
-#: spyderlib\spyder.py:1998 spyderlib\spyder.py:2009
+#: spyderlib\spyder.py:2032 spyderlib\spyder.py:2043
 msgid "Spyder sessions"
 msgstr ""
 
-#: spyderlib\spyder.py:2008
+#: spyderlib\spyder.py:2042
 msgid "Save session"
 msgstr ""
 
@@ -2645,6 +2650,10 @@ msgstr ""
 msgid "It was not possible to generate rich text help for this object.</br>Please see it in plain text."
 msgstr ""
 
+#: spyderlib\utils\introspection\rope_plugin.py:34
+msgid "Editor's code completion, go-to-definition and help"
+msgstr ""
+
 #: spyderlib\utils\iofuncs.py:331
 msgid "Supported files"
 msgstr ""
@@ -2772,12 +2781,12 @@ msgid "For performance reasons, changes applied to masked array won't be reflect
 msgstr ""
 
 #: spyderlib\widgets\browser.py:30
-#: spyderlib\widgets\sourcecode\codeeditor.py:2248
+#: spyderlib\widgets\sourcecode\codeeditor.py:2063
 msgid "Zoom out"
 msgstr ""
 
 #: spyderlib\widgets\browser.py:33
-#: spyderlib\widgets\sourcecode\codeeditor.py:2245
+#: spyderlib\widgets\sourcecode\codeeditor.py:2060
 msgid "Zoom in"
 msgstr ""
 
@@ -2836,11 +2845,11 @@ msgstr ""
 msgid "Optional Dependencies"
 msgstr ""
 
-#: spyderlib\widgets\dependencies.py:133
+#: spyderlib\widgets\dependencies.py:134
 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:148
+#: spyderlib\widgets\dependencies.py:149
 msgid "Copy to clipboard"
 msgstr ""
 
@@ -2988,107 +2997,107 @@ msgstr ""
 msgid "Nothing to be imported from clipboard."
 msgstr ""
 
-#: spyderlib\widgets\editor.py:69 spyderlib\widgets\editor.py:557
+#: spyderlib\widgets\editor.py:70 spyderlib\widgets\editor.py:572
 msgid "File list management"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:73
+#: spyderlib\widgets\editor.py:74
 msgid "Filter:"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:78
+#: spyderlib\widgets\editor.py:79
 msgid "(press <b>Enter</b> to edit file)"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:93
+#: spyderlib\widgets\editor.py:94
 msgid "&Edit file"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:102
+#: spyderlib\widgets\editor.py:103
 msgid "&Close file"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:110
+#: spyderlib\widgets\editor.py:111
 msgid "Hint: press <b>Alt</b> to show accelerators"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:560
+#: spyderlib\widgets\editor.py:575
 msgid "Copy path to clipboard"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:1099
+#: spyderlib\widgets\editor.py:1115
 msgid "Temporary file"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:1196
+#: spyderlib\widgets\editor.py:1212
 msgid "New window"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:1197
+#: spyderlib\widgets\editor.py:1213
 msgid "Create a new editor window"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:1200
+#: spyderlib\widgets\editor.py:1216
 msgid "Split vertically"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:1202
+#: spyderlib\widgets\editor.py:1218
 msgid "Split vertically this editor window"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:1204
+#: spyderlib\widgets\editor.py:1220
 msgid "Split horizontally"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:1206
+#: spyderlib\widgets\editor.py:1222
 msgid "Split horizontally this editor window"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:1208
+#: spyderlib\widgets\editor.py:1224
 msgid "Close this panel"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:1340
+#: spyderlib\widgets\editor.py:1356
 msgid "<b>%s</b> has been modified.<br>Do you want to save changes?"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:1403
+#: spyderlib\widgets\editor.py:1419
 msgid "Save"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:1404
+#: spyderlib\widgets\editor.py:1420
 msgid "<b>Unable to save script '%s'</b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:1426
+#: spyderlib\widgets\editor.py:1442
 msgid "Save Python script"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:1647
+#: spyderlib\widgets\editor.py:1663
 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:1667
+#: spyderlib\widgets\editor.py:1683
 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:1763
+#: spyderlib\widgets\editor.py:1779
 msgid "All changes to <b>%s</b> will be lost.<br>Do you want to revert file from disk?"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:1902
+#: spyderlib\widgets\editor.py:1919
 msgid "Loading %s..."
 msgstr ""
 
-#: spyderlib\widgets\editor.py:1912
+#: spyderlib\widgets\editor.py:1929
 msgid "<b>%s</b> contains mixed end-of-line characters.<br>Spyder will fix this automatically."
 msgstr ""
 
-#: spyderlib\widgets\editor.py:2260
+#: spyderlib\widgets\editor.py:2277
 msgid "Close window"
 msgstr ""
 
-#: spyderlib\widgets\editor.py:2262
+#: spyderlib\widgets\editor.py:2279
 msgid "Close this window"
 msgstr ""
 
@@ -3305,7 +3314,7 @@ msgid "Terminated."
 msgstr ""
 
 #: spyderlib\widgets\externalshell\baseshell.py:235
-#: spyderlib\widgets\mixins.py:511
+#: spyderlib\widgets\ipython.py:336 spyderlib\widgets\mixins.py:599
 msgid "Arguments"
 msgstr ""
 
@@ -3425,7 +3434,7 @@ msgid "No argument"
 msgstr ""
 
 #: spyderlib\widgets\externalshell\pythonshell.py:524
-msgid "The console failed to start! That's all we know :(<br>Please close it and open a new one."
+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:528
@@ -3666,90 +3675,86 @@ msgstr ""
 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:248
+#: spyderlib\widgets\internalshell.py:250
 msgid "Help..."
 msgstr ""
 
-#: spyderlib\widgets\internalshell.py:255
+#: spyderlib\widgets\internalshell.py:257
 msgid "Help"
 msgstr ""
 
-#: spyderlib\widgets\internalshell.py:264
+#: spyderlib\widgets\internalshell.py:266
 msgid "Shell special commands:"
 msgstr ""
 
-#: spyderlib\widgets\internalshell.py:265
+#: spyderlib\widgets\internalshell.py:267
 msgid "Internal editor:"
 msgstr ""
 
-#: spyderlib\widgets\internalshell.py:266
+#: spyderlib\widgets\internalshell.py:268
 msgid "External editor:"
 msgstr ""
 
-#: spyderlib\widgets\internalshell.py:267
+#: spyderlib\widgets\internalshell.py:269
 msgid "Run script:"
 msgstr ""
 
-#: spyderlib\widgets\internalshell.py:268
+#: spyderlib\widgets\internalshell.py:270
 msgid "Remove references:"
 msgstr ""
 
-#: spyderlib\widgets\internalshell.py:269
+#: spyderlib\widgets\internalshell.py:271
 msgid "System commands:"
 msgstr ""
 
-#: spyderlib\widgets\internalshell.py:270
+#: spyderlib\widgets\internalshell.py:272
 msgid "Python help:"
 msgstr ""
 
-#: spyderlib\widgets\internalshell.py:271
+#: spyderlib\widgets\internalshell.py:273
 msgid "GUI-based editor:"
 msgstr ""
 
-#: spyderlib\widgets\ipython.py:398
+#: spyderlib\widgets\ipython.py:440
 msgid "An error ocurred while starting the kernel!"
 msgstr ""
 
-#: spyderlib\widgets\ipython.py:426
+#: spyderlib\widgets\ipython.py:468
 msgid "Interrupt kernel"
 msgstr ""
 
-#: spyderlib\widgets\ipython.py:429
+#: spyderlib\widgets\ipython.py:471
 msgid "Restart kernel"
 msgstr ""
 
-#: spyderlib\widgets\ipython.py:461
+#: spyderlib\widgets\ipython.py:503
 msgid "Inspect current object"
 msgstr ""
 
-#: spyderlib\widgets\ipython.py:465
+#: spyderlib\widgets\ipython.py:507
 msgid "Clear line or block"
 msgstr ""
 
-#: spyderlib\widgets\ipython.py:469
+#: spyderlib\widgets\ipython.py:511
 msgid "Clear console"
 msgstr ""
 
-#: spyderlib\widgets\ipython.py:512
+#: spyderlib\widgets\ipython.py:555
 msgid "It seems the kernel died unexpectedly. Use 'Restart kernel' to continue using this console."
 msgstr ""
 
-#: spyderlib\widgets\ipython.py:524
+#: spyderlib\widgets\ipython.py:567
 msgid "Kernel process is either remote or unspecified. Cannot interrupt"
 msgstr ""
 
-#: spyderlib\widgets\ipython.py:533
+#: spyderlib\widgets\ipython.py:576
 msgid "Kernel process is either remote or unspecified. Cannot restart."
 msgstr ""
 
-#: spyderlib\widgets\ipython.py:550
+#: spyderlib\widgets\ipython.py:593
 msgid "Connecting to kernel..."
 msgstr ""
 
-#: spyderlib\widgets\mixins.py:516
-msgid "Documentation"
-msgstr ""
-
 #: spyderlib\widgets\onecolumntree.py:63
 msgid "Collapse all"
 msgstr ""
@@ -4005,67 +4010,63 @@ msgstr ""
 msgid "Module or package:"
 msgstr ""
 
-#: spyderlib\widgets\shell.py:129
+#: spyderlib\widgets\shell.py:130
 msgid "Save history log..."
 msgstr ""
 
-#: spyderlib\widgets\shell.py:131
+#: spyderlib\widgets\shell.py:132
 msgid "Save current history log (i.e. all inputs and outputs) in a text file"
 msgstr ""
 
-#: spyderlib\widgets\shell.py:251
+#: spyderlib\widgets\shell.py:252
 msgid "Save history log"
 msgstr ""
 
-#: spyderlib\widgets\shell.py:254
+#: spyderlib\widgets\shell.py:255
 msgid "History logs"
 msgstr ""
 
-#: spyderlib\widgets\shell.py:265
+#: spyderlib\widgets\shell.py:266
 msgid "<b>Unable to save file '%s'</b><br><br>Error message:<br>%s"
 msgstr ""
 
-#: spyderlib\widgets\shell.py:690
+#: spyderlib\widgets\shell.py:691
 msgid "Copy without prompts"
 msgstr ""
 
-#: spyderlib\widgets\shell.py:693 spyderlib\widgets\shell.py:696
+#: spyderlib\widgets\shell.py:694 spyderlib\widgets\shell.py:697
 msgid "Clear line"
 msgstr ""
 
-#: spyderlib\widgets\shell.py:698
+#: spyderlib\widgets\shell.py:699
 msgid "Clear shell"
 msgstr ""
 
-#: spyderlib\widgets\shell.py:701
+#: spyderlib\widgets\shell.py:702
 msgid "Clear shell contents ('cls' command)"
 msgstr ""
 
-#: spyderlib\widgets\sourcecode\codeeditor.py:69
-msgid "Editor's code completion, go-to-definition and help"
-msgstr ""
-
-#: spyderlib\widgets\sourcecode\codeeditor.py:273
+#: spyderlib\widgets\sourcecode\codeeditor.py:83
 msgid "Go to line:"
 msgstr ""
 
-#: spyderlib\widgets\sourcecode\codeeditor.py:282
+#: spyderlib\widgets\sourcecode\codeeditor.py:92
 msgid "Line count:"
 msgstr ""
 
-#: spyderlib\widgets\sourcecode\codeeditor.py:1224
+#: spyderlib\widgets\sourcecode\codeeditor.py:1027
 msgid "Breakpoint"
 msgstr ""
 
-#: spyderlib\widgets\sourcecode\codeeditor.py:1225
+#: spyderlib\widgets\sourcecode\codeeditor.py:1028
 msgid "Condition:"
 msgstr ""
 
-#: spyderlib\widgets\sourcecode\codeeditor.py:1661
+#: spyderlib\widgets\sourcecode\codeeditor.py:1476
 msgid "To do"
 msgstr ""
 
-#: spyderlib\widgets\sourcecode\codeeditor.py:2240
+#: spyderlib\widgets\sourcecode\codeeditor.py:2055
 msgid "Go to definition"
 msgstr ""
 
diff --git a/spyderlib/plugins/__init__.py b/spyderlib/plugins/__init__.py
index f33af3e..99d81eb 100644
--- a/spyderlib/plugins/__init__.py
+++ b/spyderlib/plugins/__init__.py
@@ -23,7 +23,8 @@ from spyderlib.qt.QtGui import (QDockWidget, QWidget, QShortcut, QCursor,
 from spyderlib.qt.QtCore import SIGNAL, Qt, QObject, Signal
 
 # Local imports
-from spyderlib.utils.qthelpers import toggle_actions, get_icon
+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
@@ -80,6 +81,10 @@ class SpyderPluginMixin(object):
         self.mainwindow = None
         self.ismaximized = False
         self.isvisible = False
+        # 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
         
     def initialize_plugin(self):
         """Initialize plugin: connect signals, setup actions, ..."""
@@ -91,6 +96,7 @@ class SpyderPluginMixin(object):
         if self.sig_option_changed is not None:
             self.sig_option_changed.connect(self.set_option)
         self.setWindowTitle(self.get_plugin_title())
+        self.create_toggle_view_action()
 
     def on_first_registration(self):
         """Action to be performed on first plugin registration"""
@@ -225,6 +231,8 @@ class SpyderPluginMixin(object):
         self.isvisible = enable and visible
         if self.isvisible:
             self.refresh_plugin()   # To give focus to the plugin's widget
+        if self.dockwidget.isHidden():
+            self.toggle_view_action.setChecked(False)
 
     def set_option(self, option, value):
         """
@@ -276,6 +284,22 @@ class SpyderPluginMixin(object):
             if name not in names:
                 name = names[0]
             self.set_option('color_scheme_name', name)
+    
+    def create_toggle_view_action(self):
+        """Associate a toggle view action with each plugin"""
+        title = self.get_plugin_title()
+        if self.CONF_SECTION == 'editor':
+            title = _('Editor')
+        action = create_action(self, title, toggled=self.toggle_view)
+        self.toggle_view_action = action
+    
+    def toggle_view(self, checked):
+        """Toggle view"""
+        if checked:
+            self.dockwidget.show()
+            self.dockwidget.raise_()
+        else:
+            self.dockwidget.hide()
 
 
 class SpyderPluginWidget(QWidget, SpyderPluginMixin):
diff --git a/spyderlib/plugins/externalconsole.py b/spyderlib/plugins/externalconsole.py
index 887c552..ae58f62 100644
--- a/spyderlib/plugins/externalconsole.py
+++ b/spyderlib/plugins/externalconsole.py
@@ -732,7 +732,8 @@ class ExternalConsole(SpyderPluginWidget):
             shellwidget.shell.set_spyder_breakpoints()    
     
     def start(self, fname, wdir=None, args='', interact=False, debug=False,
-              python=True, ipykernel=False, ipyclient=None, python_args=''):
+              python=True, ipykernel=False, ipyclient=None,
+              give_ipyclient_focus=True, python_args=''):
         """
         Start new console
         
@@ -936,8 +937,9 @@ class ExternalConsole(SpyderPluginWidget):
                         self.connect(shellwidget,
                                      SIGNAL('create_ipython_client(QString)'),
                                      lambda cf: self.register_ipyclient(cf,
-                                                                  ipyclient,
-                                                                  shellwidget))
+                                              ipyclient,
+                                              shellwidget,
+                                              give_focus=give_ipyclient_focus))
                     else:
                         shellwidget.emit(
                           SIGNAL("ipython_kernel_start_error(QString)"),
@@ -1024,7 +1026,8 @@ class ExternalConsole(SpyderPluginWidget):
         name = "%s %s" % (text, kernel_id)
         self.tabwidget.setTabText(index, name)
     
-    def register_ipyclient(self, connection_file, ipyclient, kernel_widget):
+    def register_ipyclient(self, connection_file, ipyclient, kernel_widget,
+                           give_focus=True):
         """
         Register `ipyclient` to be connected to `kernel_widget`
         """
@@ -1047,7 +1050,9 @@ class ExternalConsole(SpyderPluginWidget):
         ipyconsole = self.main.ipyconsole
         ipyclient.connection_file = connection_file
         ipyclient.kernel_widget_id = id(kernel_widget)
-        ipyconsole.register_client(ipyclient, client_name, restart_kernel)
+        ipyconsole.register_client(ipyclient, client_name,
+                                   restart=restart_kernel,
+                                   give_focus=give_focus)
         
     def open_file_in_spyder(self, fname, lineno):
         """Open file in Spyder's editor from remote process"""
@@ -1260,7 +1265,7 @@ class ExternalConsole(SpyderPluginWidget):
         self.start(fname=None, wdir=to_text_string(wdir), args='',
                    interact=True, debug=False, python=True)
     
-    def start_ipykernel(self, client, wdir=None):
+    def start_ipykernel(self, client, wdir=None, give_focus=True):
         """Start new IPython kernel"""
         if not self.get_option('monitor/enabled'):
             QMessageBox.warning(self, _('Open an IPython console'),
@@ -1273,7 +1278,7 @@ class ExternalConsole(SpyderPluginWidget):
         self.main.ipyconsole.visibility_changed(True)
         self.start(fname=None, wdir=to_text_string(wdir), args='',
                    interact=True, debug=False, python=True, ipykernel=True,
-                   ipyclient=client)
+                   ipyclient=client, give_ipyclient_focus=give_focus)
 
     def open_terminal(self, wdir=None):
         """Open terminal"""
diff --git a/spyderlib/plugins/inspector.py b/spyderlib/plugins/inspector.py
index 072f454..e436c3a 100644
--- a/spyderlib/plugins/inspector.py
+++ b/spyderlib/plugins/inspector.py
@@ -132,7 +132,8 @@ class ObjectInspectorConfigPage(PluginConfigPage):
         connections_label.setWordWrap(True)
         editor_box = self.create_checkbox(_("Editor"), 'connect/editor')
         rope_installed = programs.is_module_installed('rope')
-        editor_box.setEnabled(rope_installed)
+        jedi_installed = programs.is_module_installed('jedi', '>=0.7.0')
+        editor_box.setEnabled(rope_installed or jedi_installed)
         python_box = self.create_checkbox(_("Python Console"),
                                           'connect/python_console')
         ipython_box = self.create_checkbox(_("IPython Console"),
@@ -365,7 +366,7 @@ class ObjectInspector(SpyderPluginWidget):
         # locked = disable link with Console
         self.locked = False
         self._last_texts = [None, None]
-        self._last_rope_doc = None
+        self._last_editor_doc = None
         
         # Object name
         layout_edit = QHBoxLayout()
@@ -380,7 +381,8 @@ class ObjectInspector(SpyderPluginWidget):
         self.source_combo.addItems([_("Console"), _("Editor")])
         self.connect(self.source_combo, SIGNAL('currentIndexChanged(int)'),
                      self.source_changed)
-        if not programs.is_module_installed('rope'):
+        if (not programs.is_module_installed('rope') and 
+                not programs.is_module_installed('jedi', '>=0.7.0')):
             self.source_combo.hide()
             source_label.hide()
         layout_edit.addWidget(self.source_combo)
@@ -720,8 +722,8 @@ class ObjectInspector(SpyderPluginWidget):
     def force_refresh(self):
         if self.source_is_console():
             self.set_object_text(None, force_refresh=True)
-        elif self._last_rope_doc is not None:
-            self.set_rope_doc(self._last_rope_doc, 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"""
@@ -749,15 +751,15 @@ class ObjectInspector(SpyderPluginWidget):
         if self.dockwidget is not None:
             self.dockwidget.blockSignals(False)
         
-    def set_rope_doc(self, doc, force_refresh=False):
+    def set_editor_doc(self, doc, force_refresh=False):
         """
         Use the object inspector to show docstring dictionary computed
-        with rope from the Editor plugin
+        with introspection plugin from the Editor plugin
         """
         if (self.locked and not force_refresh):
             return
         self.switch_to_editor_source()
-        self._last_rope_doc = doc
+        self._last_editor_doc = doc
         self.object_edit.setText(doc['obj_text'])
 
         if self.rich_help:
diff --git a/spyderlib/plugins/ipythonconsole.py b/spyderlib/plugins/ipythonconsole.py
index 01cbd63..ed3bffc 100644
--- a/spyderlib/plugins/ipythonconsole.py
+++ b/spyderlib/plugins/ipythonconsole.py
@@ -494,12 +494,12 @@ class IPythonConsole(SpyderPluginWidget):
         if client is not None:
             client.shellwidget.write_to_stdin(line)
 
-    def create_new_client(self):
+    def create_new_client(self, give_focus=True):
         """Create a new client"""
         client = IPythonClient(self, history_filename='history.py',
                                menu_actions=self.menu_actions)
         self.add_tab(client, name=client.get_name())
-        self.main.extconsole.start_ipykernel(client)
+        self.main.extconsole.start_ipykernel(client, give_focus=give_focus)
 
     def get_plugin_actions(self):
         """Return a list of actions related to plugin"""
@@ -798,10 +798,10 @@ class IPythonConsole(SpyderPluginWidget):
         ip_cfg._merge(spy_cfg)
         return ip_cfg
 
-    def register_client(self, client, name, restart=False):
+    def register_client(self, client, name, restart=False, give_focus=True):
         """Register new IPython client"""
         self.connect_client_to_kernel(client)
-        client.show_shellwidget()
+        client.show_shellwidget(give_focus=give_focus)
         client.name = name
         
         # If we are restarting the kernel we just need to rename the client tab
@@ -892,7 +892,7 @@ class IPythonConsole(SpyderPluginWidget):
     
     def open_client_at_startup(self):
         if self.get_option('open_ipython_at_startup', False):
-            self.create_new_client()
+            self.create_new_client(give_focus=False)
     
     def close_related_ipyclients(self, client):
         """Close all IPython clients related to *client*, except itself"""
diff --git a/spyderlib/spyder.py b/spyderlib/spyder.py
index 8123b14..76316ce 100644
--- a/spyderlib/spyder.py
+++ b/spyderlib/spyder.py
@@ -140,7 +140,7 @@ from spyderlib.userconfig 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
-from spyderlib.utils import module_completion
+from spyderlib.utils.introspection import module_completion
 from spyderlib.utils.misc import select_port
 from spyderlib.py3compat import (PY3, to_text_string, is_text_string, getcwd,
                                  u, qbytearray_to_str, configparser as cp)
@@ -281,6 +281,10 @@ class MainWindow(QMainWindow):
     DOCKOPTIONS = QMainWindow.AllowTabbedDocks|QMainWindow.AllowNestedDocks
     SPYDER_PATH = get_conf_path('path')
     BOOKMARKS = (
+         ('numpy', "http://docs.scipy.org/doc/",
+          _("Numpy and Scipy documentation")),
+         ('matplotlib', "http://matplotlib.sourceforge.net/contents.html",
+          _("Matplotlib documentation")),
          ('PyQt4',
           "http://pyqt.sourceforge.net/Docs/PyQt4/",
           _("PyQt4 Reference Guide")),
@@ -290,11 +294,7 @@ class MainWindow(QMainWindow):
          ('xy', "http://code.google.com/p/pythonxy/",
           _("Python(x,y)")),
          ('winpython', "http://code.google.com/p/winpython/",
-          _("WinPython")),
-         ('numpy', "http://docs.scipy.org/doc/",
-          _("Numpy and Scipy documentation")),
-         ('matplotlib', "http://matplotlib.sourceforge.net/contents.html",
-          _("Matplotlib documentation")),
+          _("WinPython"))
                 )
     
     def __init__(self, options=None):
@@ -405,7 +405,8 @@ class MainWindow(QMainWindow):
         # otherwise the external tools menu is lost after leaving setup method
         self.external_tools_menu_actions = []
         self.view_menu = None
-        self.windows_toolbars_menu = None
+        self.plugins_menu = None
+        self.toolbars_menu = None
         self.help_menu = None
         self.help_menu_actions = []
         
@@ -414,6 +415,7 @@ class MainWindow(QMainWindow):
         self.cpu_status = None
         
         # Toolbars
+        self.toolbarslist = []
         self.main_toolbar = None
         self.main_toolbar_actions = []
         self.file_toolbar = None
@@ -445,14 +447,8 @@ class MainWindow(QMainWindow):
         self.setWindowIcon(get_icon(icon_name, resample=os.name != 'nt'))
         
         # Showing splash screen
-        pixmap = QPixmap(get_image_path('splash.png'), 'png')
-        self.splash = QSplashScreen(pixmap)
-        font = self.splash.font()
-        font.setPixelSize(10)
-        self.splash.setFont(font)
+        self.splash = SPLASH
         if not self.light:
-            self.splash.show()
-            self.set_splash(_("Initializing..."))
             if CONF.get('main', 'current_version', '') != __version__:
                 CONF.set('main', 'current_version', __version__)
                 # Execute here the actions to be performed only once after
@@ -487,6 +483,9 @@ class MainWindow(QMainWindow):
         # 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,
@@ -505,6 +504,7 @@ class MainWindow(QMainWindow):
         toolbar = self.addToolBar(title)
         toolbar.setObjectName(object_name)
         toolbar.setIconSize( QSize(iconsize, iconsize) )
+        self.toolbarslist.append(toolbar)
         return toolbar
     
     def setup(self):
@@ -513,11 +513,11 @@ class MainWindow(QMainWindow):
         if not self.light:
             self.debug_print("  ..core actions")
             self.close_dockwidget_action = create_action(self,
-                                        _("Close current dockwidget"),
+                                        _("Close current plugin"),
                                         triggered=self.close_current_dockwidget,
                                         context=Qt.ApplicationShortcut)
             self.register_shortcut(self.close_dockwidget_action,
-                                   "_", "Close dockwidget", "Shift+Ctrl+F4")
+                                   "_", "Close plugin", "Shift+Ctrl+F4")
             
             _text = _("&Find text")
             self.find_action = create_action(self, _text, icon='find.png',
@@ -649,7 +649,6 @@ class MainWindow(QMainWindow):
                                         tip=_("Refresh list of module names "
                                               "available in PYTHONPATH"))
             self.tools_menu_actions = [prefs_action, spyder_path_action]
-            self.tools_menu_actions += [update_modules_action, None]
             if WinUserEnvDialog is not None:
                 winenv_action = create_action(self,
                         _("Current user environment variables..."),
@@ -659,6 +658,7 @@ 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]
             
             # External Tools submenu
             self.external_tools_menu = QMenu(_("External Tools"))
@@ -668,26 +668,18 @@ class MainWindow(QMainWindow):
                                    _("Python(x,y) launcher"),
                                    icon=get_icon('pythonxy.png'),
                                    triggered=lambda:
-                                   programs.run_python_script('xy', 'xyhome'))
-            self.external_tools_menu_actions.append(self.xy_action)
-            if not is_module_installed('xy'):
-                self.xy_action.setDisabled(True)
-                self.xy_action.setToolTip(self.xy_action.toolTip() + \
-                                          '\nPlease install Python(x,y) to '
-                                          'enable this feature')
+                                   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
             self.wp_action = create_action(self, _("WinPython control panel"),
                        icon=get_icon('winpython.svg'),
                        triggered=lambda:
                        programs.run_python_script('winpython', 'controlpanel'))
-            self.external_tools_menu_actions.append(self.wp_action)
-            if not is_module_installed('winpython'):
-                self.wp_action.setDisabled(True)
-                self.wp_action.setToolTip(self.wp_action.toolTip() + \
-                                          '\nPlease install WinPython to '
-                                          'enable this feature')
+            if os.name == 'nt' and is_module_installed('winpython'):
+                self.external_tools_menu_actions.append(self.wp_action)
             # Qt-related tools
-            additact = [None]
+            additact = []
             for name in ("designer-qt4", "designer"):
                 qtdact = create_program_action(self, _("Qt Designer"),
                                                name, 'qtdesigner.png')
@@ -706,11 +698,11 @@ class MainWindow(QMainWindow):
             for act in (qtdact, qtlact, qteact):
                 if act:
                     additact.append(act)
-            if len(additact) > 1 and (is_module_installed('winpython') or \
+            if additact and (is_module_installed('winpython') or \
               is_module_installed('xy')):
-                self.external_tools_menu_actions += additact
+                self.external_tools_menu_actions += [None] + additact
                 
-            # Sift
+            # Guidata and Sift
             self.debug_print("  ..sift?")
             gdgq_act = []
             if is_module_installed('guidata'):
@@ -748,7 +740,7 @@ class MainWindow(QMainWindow):
             self.maximize_action = create_action(self, '',
                                             triggered=self.maximize_dockwidget)
             self.register_shortcut(self.maximize_action, "_",
-                                   "Maximize dockwidget", "Ctrl+Alt+Shift+M")
+                                   "Maximize plugin", "Ctrl+Alt+Shift+M")
             self.__update_maximize_action()
             
             # Fullscreen mode
@@ -768,8 +760,8 @@ class MainWindow(QMainWindow):
             self.main_toolbar = self.create_toolbar(_("Main toolbar"),
                                                     "main_toolbar")
             
-            self.debug_print("  ..plugin: internal console")
             # Internal console plugin
+            self.debug_print("  ..plugin: internal console")
             from spyderlib.plugins.console import Console
             self.console = Console(self, namespace, exitfunc=self.closing,
                                    profile=self.profile,
@@ -778,11 +770,12 @@ class MainWindow(QMainWindow):
                                            '  spy.app, spy.window, dir(spy)')
             self.console.register_plugin()
             
-            self.debug_print("  ..plugin: working directory")
             # Working directory plugin
+            self.debug_print("  ..plugin: working directory")
             from spyderlib.plugins.workingdirectory import WorkingDirectory
             self.workingdirectory = WorkingDirectory(self, self.init_workdir)
             self.workingdirectory.register_plugin()
+            self.toolbarslist.append(self.workingdirectory)
         
             # Object inspector plugin
             if CONF.get('inspector', 'enable'):
@@ -890,74 +883,69 @@ class MainWindow(QMainWindow):
             
             self.set_splash(_("Setting up main window..."))
             
-            # ? menu
-            about_action = create_action(self,
-                                    _("About %s...") % "Spyder",
-                                    icon=get_std_icon('MessageBoxInformation'),
-                                    triggered=self.about)
+            # Help menu
             dep_action = create_action(self, _("Optional dependencies..."),
-                                       triggered=self.show_dependencies)
+                                       triggered=self.show_dependencies,
+                                       icon='advanced.png')
             report_action = create_action(self,
-                                    _("Report issue..."),
-                                    icon=get_icon('bug.png'),
-                                    triggered=self.report_issue
-                                    )
+                                          _("Report issue..."),
+                                          icon=get_icon('bug.png'),
+                                          triggered=self.report_issue)
+            support_action = create_action(self,
+                                           _("Spyder support..."),
+                                           triggered=self.google_group)
             # Spyder documentation
             doc_path = get_module_data_path('spyderlib', relpath="doc",
                                             attr_name='DOCPATH')
             # * Trying to find the chm doc
             spyder_doc = osp.join(doc_path, "Spyderdoc.chm")
             if not osp.isfile(spyder_doc):
-                spyder_doc = osp.join(doc_path, os.pardir, os.pardir,
-                                      "Spyderdoc.chm")
+                spyder_doc = osp.join(doc_path, os.pardir, "Spyderdoc.chm")
             # * Trying to find the html doc
             if not osp.isfile(spyder_doc):
                 spyder_doc = osp.join(doc_path, "index.html")
-                if not osp.isfile(spyder_doc):  # development version
-                    spyder_doc = osp.join(get_module_source_path('spyderlib'),
-                                          os.pardir, 'build', 'lib',
-                                          'spyderlib', 'doc', "index.html")
-            spyder_doc = file_uri(spyder_doc)
+            # * Trying to find the development-version html doc
+            if not osp.isfile(spyder_doc):
+                spyder_doc = osp.join(get_module_source_path('spyderlib'),
+                                      os.pardir, 'build', 'lib', 'spyderlib',
+                                      'doc', "index.html")
+            # * If we totally fail, point to our web build
+            if not osp.isfile(spyder_doc):
+                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'))
-            self.help_menu_actions = [doc_action, report_action, dep_action,
-                                      None]
+            self.help_menu_actions = [doc_action, report_action,
+                                      dep_action, support_action, None]
             # Python documentation
             if get_python_doc_path() is not None:
                 pydoc_act = create_action(self, _("Python documentation"),
-                                  icon=get_icon('python.png'),
                                   triggered=lambda:
                                   programs.start_file(get_python_doc_path()))
                 self.help_menu_actions.append(pydoc_act)
             # IPython documentation
             if self.ipyconsole is not None:
-                ipython_menu = QMenu(_("IPython Help"), self)
+                ipython_menu = QMenu(_("IPython documentation"), self)
                 intro_action = create_action(self, _("Intro to IPython"),
                                           triggered=self.ipyconsole.show_intro)
-                quickref_action = create_action(self, _("Quick Reference"),
+                quickref_action = create_action(self, _("Quick reference"),
                                        triggered=self.ipyconsole.show_quickref)
                 guiref_action = create_action(self, _("Console help"),
                                          triggered=self.ipyconsole.show_guiref)                    
                 add_actions(ipython_menu, (intro_action, guiref_action,
                                            quickref_action))
                 self.help_menu_actions.append(ipython_menu)
-            # Qt assistant link
-            qta_act = create_program_action(self, _("Qt Help"), "assistant")
-            if qta_act:
-                self.help_menu_actions.append(qta_act)
-            # Online documentation
-            web_resources = QMenu(_("Web Resources"))
-            add_actions(web_resources,
-                        create_module_bookmark_actions(self, self.BOOKMARKS))
-            self.help_menu_actions += [web_resources, None]
             # Windows-only: documentation located in sys.prefix/Doc
-            def add_doc_action(text, path):
-                """Add doc action to help menu"""
+            ipm_actions = []
+            def add_ipm_action(text, path):
+                """Add installed Python module doc action to help submenu"""
                 path = file_uri(path)
-                action = create_action(self, text, icon=None,
+                action = create_action(self, text,
+                       icon='%s.png' % osp.splitext(path)[1][1:],
                        triggered=lambda path=path: programs.start_file(path))
-                self.help_menu_actions.append(action)
+                ipm_actions.append(action)
             sysdocpth = osp.join(sys.prefix, 'Doc')
             if osp.isdir(sysdocpth): # exists on Windows, except frozen dist.
                 for docfn in os.listdir(sysdocpth):
@@ -966,7 +954,7 @@ class MainWindow(QMainWindow):
                     if match is not None:
                         pname = match.groups()[0]
                         if pname not in ('Python', ):
-                            add_doc_action(pname, osp.join(sysdocpth, docfn))
+                            add_ipm_action(pname, osp.join(sysdocpth, docfn))
             # Documentation provided by Python(x,y), if available
             try:
                 from xy.config import DOC_PATH as xy_doc_path
@@ -974,7 +962,7 @@ class MainWindow(QMainWindow):
                 def add_xydoc(text, pathlist):
                     for path in pathlist:
                         if osp.exists(path):
-                            add_doc_action(text, path)
+                            add_ipm_action(text, path)
                             break
                 add_xydoc(_("Python(x,y) documentation folder"),
                           [xy_doc_path])
@@ -998,14 +986,32 @@ class MainWindow(QMainWindow):
                 add_xydoc(_("SciPy documentation"),
                           [osp.join(xydoc, "SciPy", "scipy.chm"),
                            osp.join(xydoc, "SciPy", "scipy-ref.pdf")])
-                self.help_menu_actions.append(None)
             except (ImportError, KeyError, RuntimeError):
                 pass
-            if self.help_menu_actions[-1] is None:
-                last_action = [about_action]
-            else:
-                last_action = [None, about_action]
-            self.help_menu_actions += last_action
+            # Installed Python modules submenu (Windows only)
+            if ipm_actions:
+                pymods_menu = QMenu(_("Installed Python modules"), self)
+                add_actions(pymods_menu, ipm_actions)
+                self.help_menu_actions.append(pymods_menu)
+            # Online documentation
+            web_resources = QMenu(_("Online documentation"))
+            webres_actions = create_module_bookmark_actions(self,
+                                                            self.BOOKMARKS)
+            webres_actions.insert(2, None)
+            webres_actions.insert(5, None)
+            add_actions(web_resources, webres_actions)
+            self.help_menu_actions.append(web_resources)
+            # Qt assistant link
+            qta_act = create_program_action(self, _("Qt documentation"),
+                                            "assistant")
+            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'),
+                                    triggered=self.about)
+            self.help_menu_actions += [None, about_action]
             
             # Status bar widgets
             from spyderlib.widgets.status import MemoryStatus, CPUStatus
@@ -1023,10 +1029,10 @@ class MainWindow(QMainWindow):
                     print("%s: %s" % (mod, str(error)), file=STDERR)
                                 
             # View menu
-            self.windows_toolbars_menu = QMenu(_("Windows and toolbars"), self)
-            self.connect(self.windows_toolbars_menu, SIGNAL("aboutToShow()"),
-                         self.update_windows_toolbars_menu)
-            self.view_menu.addMenu(self.windows_toolbars_menu)
+            self.plugins_menu = QMenu(_("Windows"), self)
+            self.toolbars_menu = QMenu(_("Toolbars"), self)
+            self.view_menu.addMenu(self.plugins_menu)
+            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)
@@ -1055,21 +1061,18 @@ class MainWindow(QMainWindow):
                                     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.maximize_action,
-                                         self.fullscreen_action, None,
-                                         reset_layout_action, quick_layout_menu,
-                                         None, self.close_dockwidget_action))
+            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
-            external_tools_act = create_action(self, _("External Tools"),
-                                               icon="ext_tools.png")
-            external_tools_act.setMenu(self.external_tools_menu)
-            add_ext_tools = False
-            for et in self.external_tools_menu_actions:
-                if et and et.isEnabled():
-                    add_ext_tools = True
-            if add_ext_tools:
-                self.tools_menu_actions.append(external_tools_act)
+            if self.external_tools_menu_actions:
+                external_tools_act = create_action(self, _("External Tools"),
+                                                   icon="ext_tools.png")
+                external_tools_act.setMenu(self.external_tools_menu)
+                self.tools_menu_actions += [None, external_tools_act]
                 self.main_toolbar_actions.append(external_tools_act)
             
             # Filling out menu/toolbar entries:
@@ -1105,7 +1108,6 @@ class MainWindow(QMainWindow):
         self.debug_print("Setting up window...")
         self.setup_layout(default=False)
         
-        SPLASH.hide()
         self.splash.hide()
         
         # Enabling tear off for all menus except help menu
@@ -1127,7 +1129,7 @@ class MainWindow(QMainWindow):
         """Actions to be performed only after the main window's `show` method 
         was triggered"""
         self.emit(SIGNAL('restore_scrollbar_position()'))
-       
+        
         if self.projectexplorer is not None:
             self.projectexplorer.check_for_io_errors()
         
@@ -1170,9 +1172,6 @@ class MainWindow(QMainWindow):
                          lambda fname: self.open_external_file(fname))
         
         # Open a Python or IPython console at startup
-        # NOTE: Leave this at the end of post_visible_setup because
-        #       it seems to avoid being unable to start a console at
-        #       startup *sometimes* if using PySide
         if self.light:
             self.extconsole.open_interpreter()
         else:
@@ -1181,6 +1180,25 @@ class MainWindow(QMainWindow):
                 self.ipyconsole.open_client_at_startup()
         self.extconsole.setMinimumHeight(0)
         
+        # Hide Internal Console so that people doesn't use it instead of
+        # the External or IPython ones
+        if self.console.dockwidget.isVisible() and DEV is None:
+            self.console.dockwidget.hide()
+        
+        # Create Plugins and toolbars submenus
+        if not self.light:
+            self.create_plugins_menu()
+            self.create_toolbars_menu()
+        
+        # Show the Object Inspector and Consoles by default
+        for plugin in (self.inspector, self.extconsole, self.ipyconsole):
+            if plugin is not None and plugin.dockwidget.isVisible():
+                plugin.dockwidget.raise_()
+        
+        # Give focus to the Editor
+        if self.editor.dockwidget.isVisible():
+            self.editor.get_focus_widget().setFocus()
+        
     def load_window_settings(self, prefix, default=False, section='main'):
         """Load window layout settings from userconfig-based configuration
         with *prefix*, under *section*
@@ -1462,12 +1480,47 @@ class MainWindow(QMainWindow):
             action.setEnabled(True)
         self.replace_action.setEnabled(readwrite_editor)
         self.replace_action.setEnabled(readwrite_editor)
-        
-    def update_windows_toolbars_menu(self):
-        """Update windows&toolbars menu"""
-        self.windows_toolbars_menu.clear()
-        popmenu = self.createPopupMenu()
-        add_actions(self.windows_toolbars_menu, popmenu.actions())
+    
+    def create_plugins_menu(self):
+        order = ['editor', 'outline_explorer', 'project_explorer',
+                 'breakpoints', 'pylint', None, 'ipython_console', 'console',
+                 'historylog', 'profiler', None, 'variable_explorer',
+                 'inspector', 'explorer', 'find_in_files', None, 'onlinehelp',
+                 'internal_console']
+        for plugin in self.widgetlist:
+            action = plugin.toggle_view_action
+            action.setChecked(plugin.dockwidget.isVisible())
+            try:
+                name = plugin.CONF_SECTION
+                pos = order.index(name)
+            except ValueError:
+                pos = None
+            if pos is not None:
+                order[pos] = action
+            else:
+                order.append(action)
+        actions = order[:]
+        for action in order:
+            if type(action) is str:
+                actions.remove(action)
+        add_actions(self.plugins_menu, actions)
+    
+    def create_toolbars_menu(self):
+        actions = []
+        for toolbar in self.toolbarslist:
+            action = toolbar.toggleViewAction()
+            actions.append(action)
+        add_actions(self.toolbars_menu, actions)
+    
+    def createPopupMenu(self):
+        if self.light:
+            menu = self.createPopupMenu()
+        else:
+            menu = QMenu('', self)
+            actions = self.help_menu_actions[:3] + \
+                      [None, self.help_menu_actions[-1]]
+            add_actions(menu, actions)
+        return menu
     
     def set_splash(self, message):
         """Set splash message"""
@@ -1500,7 +1553,22 @@ class MainWindow(QMainWindow):
         if not self.isMaximized() and not self.fullscreen_flag:
             self.window_position = self.pos()
         QMainWindow.moveEvent(self, event)
-        
+    
+    def hideEvent(self, event):
+        """Reimplement Qt method"""
+        for plugin in self.widgetlist:
+            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):
+            QApplication.activeWindow().setFocus()
+            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:
@@ -1718,7 +1786,11 @@ Please provide any additional information below.
        
         url = QUrl("http://code.google.com/p/spyderlib/issues/entry")
         url.addEncodedQueryItem("comment", quote(issue_template))
-        QDesktopServices.openUrl(url)    
+        QDesktopServices.openUrl(url)
+    
+    def google_group(self):
+        url = QUrl("http://groups.google.com/group/spyderlib")
+        QDesktopServices.openUrl(url)
 
     #---- Global callbacks (called from plugins)
     def get_current_editor_plugin(self):
@@ -2159,6 +2231,11 @@ def run_spyder(app, options, args):
     if sys.platform == "darwin" and 'Spyder.app' in __file__:
         main.connect(app, SIGNAL('open_external_file(QString)'),
                      lambda fname: main.open_external_file(fname))
+    
+    # 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.exec_()
     return main
diff --git a/spyderlib/utils/inspector/static/css/default.css b/spyderlib/utils/inspector/static/css/default.css
index 4e694f8..f236b48 100644
--- a/spyderlib/utils/inspector/static/css/default.css
+++ b/spyderlib/utils/inspector/static/css/default.css
@@ -303,7 +303,3 @@ tt {
     border-color: #eed3d7;
     background-color: rgb(199, 28, 34);
 }
-
-.panel-danger > .panel-heading > .panel-title {
-    text-align: center;
-}
diff --git a/spyderlib/utils/introspection/__init__.py b/spyderlib/utils/introspection/__init__.py
new file mode 100644
index 0000000..095df41
--- /dev/null
+++ b/spyderlib/utils/introspection/__init__.py
@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2013 The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+"""
+Introspection utilities used by Spyder
+"""
+from .base import get_plugin
+from . import module_completion
diff --git a/spyderlib/utils/introspection/base.py b/spyderlib/utils/introspection/base.py
new file mode 100644
index 0000000..3fbb96a
--- /dev/null
+++ b/spyderlib/utils/introspection/base.py
@@ -0,0 +1,453 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2013 The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+"""
+Introspection utilities used by Spyder
+"""
+from __future__ import print_function
+import imp
+import os
+import os.path as osp
+import re
+import time
+import functools
+from collections import OrderedDict
+
+from spyderlib.baseconfig import DEBUG, get_conf_path, debug_print
+from spyderlib.py3compat import PY2
+from spyderlib.utils.debug import log_dt, log_last_error
+from spyderlib.utils import sourcecode
+
+from spyderlib.qt.QtGui import QApplication
+
+
+PLUGINS = ['jedi', 'rope', 'fallback']
+LOG_FILENAME = get_conf_path('introspection.log')
+DEBUG_EDITOR = DEBUG >= 3
+    
+    
+def get_plugin(editor_widget):
+    """Get and load a plugin, checking in order of PLUGINS"""
+    plugin = None
+    for plugin_name in PLUGINS:
+        mod_name = plugin_name + '_plugin'
+        try:
+            mod = __import__('spyderlib.utils.introspection.' + mod_name,
+                             fromlist=[mod_name])
+            cls = getattr(mod, '%sPlugin' % plugin_name.capitalize())
+            plugin = cls()
+            plugin.load_plugin()
+        except Exception:
+            if DEBUG_EDITOR:
+                log_last_error(LOG_FILENAME)
+        else:
+            break
+    if not plugin:
+        plugin = IntrospectionPlugin()
+    debug_print('Instropection Plugin Loaded: %s' % plugin.name)
+    plugin.editor_widget = editor_widget
+    return plugin
+
+
+def memoize(obj):
+    """
+    Memoize objects to trade memory for execution speed
+
+    Use a limited size cache to store the value, which takes into account
+    The calling args and kwargs
+
+    See https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
+    """
+    cache = obj.cache = OrderedDict()
+
+    @functools.wraps(obj)
+    def memoizer(*args, **kwargs):
+        key = str(args) + str(kwargs)
+        if key not in cache:
+            cache[key] = obj(*args, **kwargs)
+        # only keep the most recent 100 entries
+        if len(cache) > 100:
+            cache.popitem(last=False)
+        return cache[key]
+    return memoizer
+    
+    
+def fallback(func):
+    """
+    Call the super method if the method throws an error.
+    
+    Handles all exceptions and input that evaluates to False.
+    """
+    @functools.wraps(func)
+    def inner(self, *args, **kwargs):
+        try:
+            return func(self, *args, **kwargs)
+        except Exception:
+            super_cls = super(self.__class__, self)
+            if PY2:
+                super_method = getattr(super_cls, func.func_name)
+            else:
+                super_method = getattr(super_cls, func.__name__)
+            return super_method(*args, **kwargs)
+    return inner
+
+
+class IntrospectionPlugin(object):
+    """Basic Introspection Plugin for Spyder"""
+    
+    editor_widget = None
+    
+    # ---- IntrospectionPlugin API --------------------------------------------
+    name = 'fallback'
+
+    def load_plugin(self):
+        """Load the plugin"""
+        pass
+
+    def get_completion_list(self, source_code, offset, filename):
+        """Return a list of completion strings"""
+        return self.get_token_completion_list(source_code, offset, filename)
+
+    def get_calltip_and_docs(self, source_code, offset, filename):
+        """
+        Find the calltip and docs
+
+        Calltip is a string with the function or class and its arguments
+            e.g. 'match(patern, string, flags=0)'
+                 'ones(shape, dtype=None, order='C')'
+        Docs is a a string or a dict with the following keys:
+           e.g. 'Try to apply the pattern at the start of the string...'
+           or {'note': 'Function of numpy.core.numeric...',
+               'argspec': "(shape, dtype=None, order='C')'
+               'docstring': 'Return an array of given...'
+               'name': 'ones'}
+        """
+        return None
+
+    def get_definition_location(self, source_code, offset, filename):
+        """Find a path and line number for a definition"""
+        return self.get_definition_location_regex(source_code, offset, 
+                                                  filename)
+        
+    def get_definition_location_regex(self, source_code, offset, filename):
+        """Find a path and line number for a definition using regex"""
+        ret = None, None
+        try:
+            ret = self._get_definition_location_regex(source_code, offset, 
+                                                      filename)
+            debug_print('get regex definition: ' + str(ret))
+        except Exception as e:
+            debug_print('Regex error: %s' % e)
+            if DEBUG_EDITOR:
+                log_last_error(LOG_FILENAME)
+        return ret
+        
+    def get_token_completion_list(self, source_code, offset, filename):
+        """Return a list of completion strings using token matching"""
+        ret = None
+        try:
+            ret = self._token_based_completion(source_code, offset)
+            debug_print('token completion: %s ...(%s)' % (ret[:2], len(ret)))
+        except Exception:
+            if DEBUG_EDITOR:
+                log_last_error(LOG_FILENAME)
+        return ret or []
+
+    def set_pref(self, name, value):
+        """Set a plugin preference to a value"""
+        pass
+
+    def validate(self):
+        """Validate the plugin"""
+        pass
+    
+    # ---- Private API -------------------------------------------------------
+
+    @staticmethod
+    def _token_based_completion(script, offset):
+        """Simple completion based on python-like identifiers and whitespace"""
+        base_tokens = split_words(script[:offset])
+        base = base_tokens[-1]
+        tokens = set(split_words(script))
+        items = [item for item in tokens if
+                 item.startswith(base) and len(item) > len(base)]
+        if '.' in base:
+            start = base.rfind('.') + 1
+        else:
+            start = 0
+        items = [i[start:len(base)] + i[len(base):].split('.')[0] for i in items]
+        return list(sorted(items))
+
+    def is_editor_ready(self):
+        """Check if the main app is starting up"""
+        if self.editor_widget:
+            window = self.editor_widget.window()
+            if hasattr(window, 'is_starting_up') and not window.is_starting_up:
+                return True
+
+    def get_current_source(self):
+        """Get the source code in the current file"""
+        if self.editor_widget:
+            finfo = self.editor_widget.get_current_finfo()
+            if finfo:
+                return finfo.get_source_code()
+
+    def post_message(self, message, timeout=60000):
+        """
+        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()
+            
+    @memoize
+    def python_like_mod_finder(self, import_line, alt_path=None, 
+                               stop_token=None):
+        """
+        Locate a module path based on an import line in an python-like file
+    
+        import_line is the line of source code containing the import
+        alt_path specifies an alternate base path for the module
+        stop_token specifies the desired name to stop on
+    
+        This is used to a find the path to python-like modules 
+        (e.g. cython and enaml) for a goto definition.
+        """
+        if stop_token and '.' in stop_token:
+            stop_token = stop_token.split('.')[-1]
+        tokens = re.split(r'\W', import_line)
+        if tokens[0] in ['from', 'import']:
+            # find the base location
+            try:
+                _, path, _ = imp.find_module(tokens[1])
+            except ImportError:
+                if alt_path:
+                    path = osp.join(alt_path, tokens[1])
+                else:
+                    path = None
+            if path:
+                path = osp.realpath(path)
+                if not tokens[1] == stop_token:
+                    for part in tokens[2:]:
+                        if part in ['import', 'cimport', 'as']:
+                            break
+                        path = osp.join(path, part)
+                        if part == stop_token:
+                            break
+                # from package import module
+                if stop_token and not stop_token in path:
+                    for ext in self.python_like_exts():
+                        fname = '%s%s' % (stop_token, ext)
+                        if osp.exists(osp.join(path, fname)):
+                            return osp.join(path, fname)
+                # from module import name
+                for ext in self.python_like_exts():
+                    fname = '%s%s' % (path, ext)
+                    if osp.exists(fname):
+                        return fname
+                # if it is a file, return it
+                if osp.exists(path) and not osp.isdir(path):
+                    return path
+                # default to the package file
+                path = osp.join(path, '__init__.py')
+                if osp.exists(path):
+                    return path
+
+    def _get_definition_location_regex(self, source_code, offset, filename):
+        """
+        Find the definition for an object within a set of source code
+        
+        This is used to find the path of python-like modules 
+        (e.g. cython and enaml) for a goto definition
+        """
+        token = sourcecode.get_primary_at(source_code, offset)
+        eol = sourcecode.get_eol_chars(source_code) or '\n'
+        lines = source_code[:offset].split(eol)
+        line_nr = self.get_definition_with_regex(source_code, token, 
+                                                 len(lines))
+        line = source_code.split(eol)[line_nr - 1].strip()
+        exts = self.python_like_exts()
+        if not osp.splitext(filename)[-1] in exts:
+            line_nr = self.get_definition_with_regex(source_code, token, 
+                                                     line_nr)
+            return filename, line_nr
+        if line.startswith('import ') or line.startswith('from '):
+            alt_path = osp.dirname(filename)
+            source_file = self.python_like_mod_finder(line, alt_path=alt_path,
+                                                 stop_token=token)
+            if (not source_file or
+                    not osp.splitext(source_file)[-1] in exts):
+                line_nr = self.get_definition_with_regex(source_code, token, 
+                                                         line_nr)
+                return filename, line_nr
+            mod_name = osp.basename(source_file).split('.')[0]
+            if mod_name == token or mod_name == '__init__':
+                return source_file, 1
+            else:
+                line_nr = self.get_definition_from_file(source_file, token)
+                return source_file, line_nr
+        return filename, line_nr
+        
+    @memoize
+    def get_definition_from_file(self, filename, name, line_nr=-1):
+        """Find the definition for an object in a filename"""
+        with open(filename, 'rb') as fid:
+            code = fid.read()
+        return self.get_definition_with_regex(code, name, line_nr)
+        
+    @staticmethod
+    def get_definition_with_regex(source, token, start_line=-1):
+        """
+        Find the definition of an object within a source closest to a given line
+        """
+        if not token:
+            return None
+        if DEBUG_EDITOR:
+            t0 = time.time()
+        patterns = [  # python / cython keyword definitions
+                    '^c?import.*\W{0}{1}',
+                    'from.*\W{0}\W.*c?import ',
+                    'from .* c?import.*\W{0}{1}',
+                    'class\s*{0}{1}',
+                    'c?p?def[^=]*\W{0}{1}',
+                    'cdef.*\[.*\].*\W{0}{1}',
+                    # "self.item =" or "item ="
+                    '.*\Wself.{0}{1}[^=!<>]*=[^=]',
+                    '.*\W{0}{1}[^=!<>]*=[^=]',
+                    'self.{0}{1}[^=!<>]*=[^=]',
+                    '{0}{1}[^=!<>]*=[^=]',
+                    # enaml keyword definitions
+                    'enamldef.*\W{0}{1}',
+                    'attr.*\W{0}{1}',
+                    'event.*\W{0}{1}',
+                    'id\s*:.*\W{0}{1}']
+        patterns = [pattern.format(token, r'[^0-9a-zA-Z.[]')
+                    for pattern in patterns]
+        pattern = re.compile('|^'.join(patterns))
+        # add the trailing space to allow some regexes to match
+        eol = sourcecode.get_eol_chars(source) or '\n'
+        lines = source.split(eol)
+        lines = [line.strip() + ' ' for line in lines]
+        if start_line == -1:
+            start_line = len(lines)
+        matches = []
+        for (index, line) in enumerate(lines):
+            if re.match(pattern, line):
+                matches.append(index + 1)
+        # find the one closest to the start line (prefer before the start line)
+        if matches:
+            min_dist = len(lines)
+            best_ind = 0
+            for match in matches:
+                dist = abs(start_line - match)
+                if match <= start_line or not best_ind:
+                    if dist < min_dist:
+                        min_dist = dist
+                        best_ind = match
+        if matches:
+            if DEBUG_EDITOR:
+                log_dt(LOG_FILENAME, 'regex definition match', t0)
+            return best_ind
+        else:
+            if DEBUG_EDITOR:
+                log_dt(LOG_FILENAME, 'regex definition failed match', t0)
+            return None
+
+    @staticmethod
+    @memoize
+    def get_parent_until(path):
+        """
+        Given a file path, determine the full module path
+    
+        e.g. '/usr/lib/python2.7/dist-packages/numpy/core/__init__.pyc' yields
+        'numpy.core'
+        """
+        dirname = osp.dirname(path)
+        try:
+            mod = osp.basename(path)
+            mod = osp.splitext(mod)[0]
+            imp.find_module(mod, [dirname])
+        except ImportError:
+            return
+        items = [mod]
+        while 1:
+            items.append(osp.basename(dirname))
+            try:
+                dirname = osp.dirname(dirname)
+                imp.find_module('__init__', [dirname + os.sep])
+            except ImportError:
+                break
+        return '.'.join(reversed(items))
+
+    @staticmethod
+    def python_like_exts():
+        """Return a list of all python-like extensions"""
+        exts = []
+        for lang in sourcecode.PYTHON_LIKE_LANGUAGES:
+            exts.extend(list(sourcecode.ALL_LANGUAGES[lang]))
+        return ['.' + ext for ext in exts]
+    
+    @staticmethod
+    def all_editable_exts():
+        """Return a list of all editable extensions"""
+        exts = []
+        for (language, extensions) in sourcecode.ALL_LANGUAGES.items():
+            exts.extend(list(extensions))
+        return ['.' + ext for ext in exts]
+
+
+def split_words(string):
+    """Split a string into unicode-aware words"""
+    return re.findall(r"[\w.]+", string, re.UNICODE)
+    
+
+if __name__ == '__main__':
+    p = IntrospectionPlugin()
+    
+    with open(__file__) as fid:
+        code = fid.read()
+    code += '\nget_conf_path'
+    path, line = p.get_definition_location_regex(code, len(code), __file__)
+    assert path.endswith('baseconfig.py')
+    
+    comp = p.get_token_completion_list(code[:-2], len(code) - 2, None)
+    assert comp == ['get_conf_path']
+    
+    ext = p.python_like_exts()
+    assert '.py' in ext and '.pyx' in ext
+    
+    ext = p.all_editable_exts()
+    assert '.cfg' in ext and '.iss' in ext
+    
+    path = p.get_parent_until(__file__)
+    assert path == 'spyderlib.utils.introspection.base'
+    
+    line = 'from spyderlib.widgets.sourcecode.codeeditor import CodeEditor'
+    path = p.python_like_mod_finder(line)
+    assert path.endswith('codeeditor.py')
+    path = p.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'
+    
+    code = 'import re\n\nre'
+    path, line = p.get_definition_location_regex(code, len(code), 'dummy.txt')
+    assert path == 'dummy.txt' and line == 1
+    
+    code = 'self.proxy.widget; self.'
+    comp = p.get_token_completion_list(code, len(code), None)
+    assert comp == ['proxy']
+    
+    code = 'self.sigMessageReady.emit; self.'
+    comp = p.get_token_completion_list(code, len(code), None)
+    assert comp == ['sigMessageReady']
+    
+    code = u'álfa;á'
+    comp = p.get_token_completion_list(code, len(code), None)
+    assert comp == [u'álfa']
+    
\ No newline at end of file
diff --git a/spyderlib/utils/module_completion.py b/spyderlib/utils/introspection/module_completion.py
similarity index 100%
rename from spyderlib/utils/module_completion.py
rename to spyderlib/utils/introspection/module_completion.py
diff --git a/spyderlib/utils/introspection/rope_plugin.py b/spyderlib/utils/introspection/rope_plugin.py
new file mode 100644
index 0000000..584c195
--- /dev/null
+++ b/spyderlib/utils/introspection/rope_plugin.py
@@ -0,0 +1,241 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2013 The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+"""
+Rope introspection plugin
+"""
+import time
+
+from spyderlib import dependencies
+from spyderlib.baseconfig import get_conf_path, _, STDERR
+from spyderlib.utils import encoding, programs
+from spyderlib.py3compat import PY2
+from spyderlib.utils.debug import log_last_error, log_dt
+from spyderlib.utils.introspection.base import (
+    DEBUG_EDITOR, LOG_FILENAME, IntrospectionPlugin, fallback)
+try:
+    try:
+        from spyderlib import rope_patch
+        rope_patch.apply()
+    except ImportError:
+        # rope 0.9.2/0.9.3 is not installed
+        pass
+    import rope.base.libutils
+    import rope.contrib.codeassist
+except ImportError:
+    pass
+
+
+ROPE_REQVER = '>=0.9.2'
+dependencies.add('rope',
+                 _("Editor's code completion, go-to-definition and help"),
+                 required_version=ROPE_REQVER)
+
+#TODO: The following preferences should be customizable in the future
+ROPE_PREFS = {'ignore_syntax_errors': True,
+              'ignore_bad_imports': True,
+              'soa_followed_calls': 2,
+              'extension_modules': [],
+              }
+
+
+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):
+            raise ImportError('Requires Rope %s' % ROPE_REQVER)
+        self.project = None
+        self.create_rope_project(root_path=get_conf_path())
+        
+    @fallback
+    def get_completion_list(self, source_code, offset, filename):
+        """Get a list of completions using Rope"""
+        if self.project is None:
+            raise ValueError
+        if PY2:
+            filename = filename.encode('utf-8')
+        else:
+            #TODO: test if this is working without any further change in
+            # Python 3 with a user account containing unicode characters
+            pass
+        try:
+            resource = rope.base.libutils.path_to_resource(self.project,
+                                                           filename)
+        except Exception as _error:
+            if DEBUG_EDITOR:
+                log_last_error(LOG_FILENAME, "path_to_resource: %r" % filename)
+            resource = None
+        try:
+            if DEBUG_EDITOR:
+                t0 = time.time()
+            proposals = rope.contrib.codeassist.code_assist(self.project,
+                                    source_code, offset, resource, maxfixes=3)
+            proposals = rope.contrib.codeassist.sorted_proposals(proposals)
+            if DEBUG_EDITOR:
+                log_dt(LOG_FILENAME, "code_assist/sorted_proposals", t0)
+            if not proposals:
+                raise ValueError
+            return [proposal.name for proposal in proposals]
+        except Exception as _error:  #analysis:ignore
+            if DEBUG_EDITOR:
+                log_last_error(LOG_FILENAME, "get_completion_list")
+            raise ValueError
+
+    @fallback 
+    def get_calltip_and_docs(self, source_code, offset, filename):
+        """Get a formatted calltip and docstring from Rope"""
+        if self.project is None:
+            raise ValueError
+        if PY2:
+            filename = filename.encode('utf-8')
+        else:
+            #TODO: test if this is working without any further change in
+            # Python 3 with a user account containing unicode characters
+            pass
+        try:
+            resource = rope.base.libutils.path_to_resource(self.project,
+                                                           filename)
+        except Exception as _error:
+            if DEBUG_EDITOR:
+                log_last_error(LOG_FILENAME, "path_to_resource: %r" % filename)
+            resource = None
+        try:
+            if DEBUG_EDITOR:
+                t0 = time.time()
+            cts = rope.contrib.codeassist.get_calltip(
+                            self.project, source_code, offset, resource,
+                            ignore_unknown=False, remove_self=True, maxfixes=3)
+            if DEBUG_EDITOR:
+                log_dt(LOG_FILENAME, "get_calltip", t0)
+            if cts is not None:
+                while '..' in cts:
+                    cts = cts.replace('..', '.')
+                if '(.)' in cts:
+                    cts = cts.replace('(.)', '(...)')
+            try:
+                doc_text = rope.contrib.codeassist.get_doc(self.project,
+                                     source_code, offset, resource, maxfixes=3)
+                if DEBUG_EDITOR:
+                    log_dt(LOG_FILENAME, "get_doc", t0)
+            except Exception as _error:
+                doc_text = ''
+                if DEBUG_EDITOR:
+                    log_last_error(LOG_FILENAME, "get_doc")
+            return [cts, doc_text]
+        except Exception as _error:  #analysis:ignore
+            if DEBUG_EDITOR:
+                log_last_error(LOG_FILENAME, "get_calltip_text")
+            raise ValueError
+            
+    @fallback              
+    def get_definition_location(self, source_code, offset, filename):
+        """Find a definition location using Rope"""
+        if self.project is None:
+            raise ValueError
+        if PY2:
+            filename = filename.encode('utf-8')
+        else:
+            #TODO: test if this is working without any further change in
+            # Python 3 with a user account containing unicode characters
+            pass
+        try:
+            resource = rope.base.libutils.path_to_resource(self.project,
+                                                           filename)
+        except Exception as _error:
+            if DEBUG_EDITOR:
+                log_last_error(LOG_FILENAME, "path_to_resource: %r" % filename)
+            resource = None
+        try:
+            if DEBUG_EDITOR:
+                t0 = time.time()
+            resource, lineno = rope.contrib.codeassist.get_definition_location(
+                    self.project, source_code, offset, resource, maxfixes=3)
+            if DEBUG_EDITOR:
+                log_dt(LOG_FILENAME, "get_definition_location", t0)
+            if resource is not None:
+                filename = resource.real_path
+            else:
+                raise ValueError
+            return filename, lineno
+        except Exception as _error:  #analysis:ignore
+            if DEBUG_EDITOR:
+                log_last_error(LOG_FILENAME, "get_definition_location")
+            raise ValueError
+                             
+    def validate(self):
+        """Validate the Rope project"""
+        if self.project is not None:
+            self.project.validate(self.project.root)
+
+    def set_pref(self, key, value):
+        """Set a Rope preference"""
+        if self.project is not None:
+            self.project.prefs.set(key, value)
+
+    # ---- Private API -------------------------------------------------------
+
+    def create_rope_project(self, root_path):
+        """Create a Rope project on a desired path"""
+        if PY2:
+            root_path = encoding.to_fs_from_unicode(root_path)
+        else:
+            #TODO: test if this is working without any further change in
+            # Python 3 with a user account containing unicode characters
+            pass
+        try:
+            import rope.base.project
+            self.project = rope.base.project.Project(root_path, **ROPE_PREFS)
+        except ImportError:
+            print >>STDERR, 'project error'
+            self.project = None
+            if DEBUG_EDITOR:
+                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,
+                               "create_rope_project: %r" % root_path)
+        self.validate()
+
+    def close_rope_project(self):
+        """Close the Rope project"""
+        if self.project is not None:
+            self.project.close()
+
+
+if __name__ == '__main__':
+
+    p = RopePlugin()
+    p.load_plugin()
+
+    source_code = "import numpy; numpy.ones"
+    calltip, docs = p.get_calltip_and_docs(source_code, len(source_code),
+                                           __file__)
+    assert 'ones(' in calltip and 'ones(' in docs
+    
+    source_code = "import numpy; n"
+    completions = p.get_completion_list(source_code, len(source_code),
+                                        __file__)
+    assert 'numpy' in completions 
+    
+    source_code = "import matplotlib.pyplot as plt; plt.imsave"
+    path, line_nr = p.get_definition_location(source_code, len(source_code),
+                                            __file__)
+    assert 'pyplot.py' in path 
diff --git a/spyderlib/utils/programs.py b/spyderlib/utils/programs.py
index 8d6e227..6eca7f1 100644
--- a/spyderlib/utils/programs.py
+++ b/spyderlib/utils/programs.py
@@ -194,6 +194,8 @@ def check_version(actver, version, cmp_op):
 
     Distributed under the terms of the BSD License.
     """
+    if isinstance(actver, tuple):
+        actver = '.'.join([str(i) for i in actver])
     try:
         if cmp_op == '>':
             return LooseVersion(actver) > LooseVersion(version)
@@ -289,6 +291,7 @@ def is_module_installed(module_name, version=None, installed_version=None,
             assert symb in ('>=', '>', '=', '<'),\
                     "Invalid version condition '%s'" % symb
             version = version[match.start():]
+            
             return check_version(actver, version, symb)
 
 
@@ -298,3 +301,4 @@ if __name__ == '__main__':
     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'))
diff --git a/spyderlib/utils/qthelpers.py b/spyderlib/utils/qthelpers.py
index c7dc787..fb22898 100644
--- a/spyderlib/utils/qthelpers.py
+++ b/spyderlib/utils/qthelpers.py
@@ -328,7 +328,7 @@ def create_module_bookmark_actions(parent, bookmarks):
                 create_act = False
         if create_act:
             act = create_bookmark_action(parent, url, title)
-        actions.append(act)
+            actions.append(act)
     return actions
 
         
diff --git a/spyderlib/utils/sourcecode.py b/spyderlib/utils/sourcecode.py
index 9714385..2f7c421 100644
--- a/spyderlib/utils/sourcecode.py
+++ b/spyderlib/utils/sourcecode.py
@@ -7,10 +7,34 @@
 """
 Source code text utilities
 """
+import re
 
 # Order is important:
 EOL_CHARS = (("\r\n", 'nt'), ("\n", 'posix'), ("\r", 'mac'))
 
+ALL_LANGUAGES = {
+                 'Python': ('py', 'pyw', 'python', 'ipy'),
+                 'Cython': ('pyx', 'pxi', 'pxd'),
+                 'Fortran77': ('f', 'for', 'f77'),
+                 'Fortran': ('f90', 'f95', 'f2k'),
+                 'Idl': ('pro',),
+                 'Matlab': ('m',),
+                 'Diff': ('diff', 'patch', 'rej'),
+                 'GetText': ('po', 'pot'),
+                 'Nsis': ('nsi', 'nsh'),
+                 'Html': ('htm', 'html'),
+                 'Css': ('css',),
+                 'Xml': ('xml',),
+                 'Js': ('js',),
+                 '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'),
+                 }
+
+PYTHON_LIKE_LANGUAGES = ('Python', 'Cython')             
+
 def get_eol_chars(text):
     """Get text EOL characters"""
     for eol_chars, _os_name in EOL_CHARS:
@@ -52,3 +76,51 @@ def is_keyword(text):
     """Test if passed string is the name of a Python keyword"""
     import keyword
     return text in keyword.kwlist
+    
+    
+def get_primary_at(source_code, offset, retry=True):
+    """Return Python object in *source_code* at *offset*
+    Periods to the left of the cursor are carried forward 
+      e.g. 'functools.par^tial' would yield 'functools.partial'
+    Retry prevents infinite recursion: retry only once
+    """
+    obj = ''
+    left = re.split(r"[^0-9a-zA-Z_.]", source_code[:offset])
+    if left and left[-1]:
+        obj = left[-1]
+    right = re.split(r"\W", source_code[offset:])
+    if right and right[0]:
+        obj += right[0]
+    if obj and obj[0].isdigit():
+        obj = ''
+    # account for opening chars with no text to the right
+    if not obj and retry and offset and source_code[offset - 1] in '([.':
+        return get_primary_at(source_code, offset - 1, retry=False)
+    return obj
+
+
+def split_source(source_code):
+    '''Split source code into lines
+    '''
+    eol_chars = get_eol_chars(source_code)
+    if eol_chars:
+        return source_code.split(eol_chars)
+    else:
+        return [source_code]
+
+
+def get_identifiers(source_code):
+    '''Split source code into python identifier-like tokens'''
+    tokens = set(re.split(r"[^0-9a-zA-Z_.]", source_code))
+    valid = re.compile(r'[a-zA-Z_]')
+    return [token for token in tokens if re.match(valid, token)]
+
+
+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 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/widgets/calltip.py b/spyderlib/widgets/calltip.py
index f3cab6f..9b6b51b 100644
--- a/spyderlib/widgets/calltip.py
+++ b/spyderlib/widgets/calltip.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 #-----------------------------------------------------------------------------
 # Copyright (c) 2010, IPython Development Team.
 #
@@ -11,7 +12,6 @@ Calltip widget used only to show signatures
 """
 
 # Standard library imports
-import re
 from unicodedata import category
 
 # System library imports
@@ -26,7 +26,7 @@ class CallTipWidget(QtGui.QLabel):
     # 'QObject' interface
     #--------------------------------------------------------------------------
 
-    def __init__(self, text_edit):
+    def __init__(self, text_edit, hide_timer_on=False):
         """ Create a call tip manager that is attached to the specified Qt
             text edit widget.
         """
@@ -34,6 +34,7 @@ class CallTipWidget(QtGui.QLabel):
         super(CallTipWidget, self).__init__(None, QtCore.Qt.ToolTip)
         self.app = QtCore.QCoreApplication.instance()
 
+        self.hide_timer_on = hide_timer_on
         self._hide_timer = QtCore.QBasicTimer()
         self._text_edit = text_edit
 
@@ -47,8 +48,6 @@ class CallTipWidget(QtGui.QLabel):
         self.setFrameStyle(QtGui.QFrame.NoFrame)
         self.setMargin(1 + self.style().pixelMetric(
                 QtGui.QStyle.PM_ToolTipLabelFrameWidth, None, self))
-        self.setWindowOpacity(self.style().styleHint(
-                QtGui.QStyle.SH_ToolTipLabel_Opacity, None, self, None) / 255.0)
 
     def eventFilter(self, obj, event):
         """ Reimplemented to hide on certain key presses and on text edit focus
@@ -70,7 +69,9 @@ class CallTipWidget(QtGui.QLabel):
                 self.hide()
 
             elif etype == QtCore.QEvent.Enter:
-                self._hide_timer.stop()
+                if (self._hide_timer.isActive() and
+                  self.app.topLevelAt(QtGui.QCursor.pos()) == self):
+                    self._hide_timer.stop()
 
             elif etype == QtCore.QEvent.Leave:
                 self._leave_event_hide()
@@ -92,7 +93,9 @@ class CallTipWidget(QtGui.QLabel):
         """ Reimplemented to cancel the hide timer.
         """
         super(CallTipWidget, self).enterEvent(event)
-        self._hide_timer.stop()
+        if (self._hide_timer.isActive() and
+          self.app.topLevelAt(QtGui.QCursor.pos()) == self):
+            self._hide_timer.stop()
 
     def hideEvent(self, event):
         """ Reimplemented to disconnect signal handlers and event filter.
@@ -140,25 +143,7 @@ class CallTipWidget(QtGui.QLabel):
     # 'CallTipWidget' interface
     #--------------------------------------------------------------------------
 
-    def show_call_info(self, point, call_line, doc=None, maxlines=20):
-        """ Attempts to show the specified call line and docstring at the
-            current cursor location. The docstring is possibly truncated for
-            length.
-        """
-        if doc:
-            match = re.match("(?:[^\n]*\n){%i}" % maxlines, doc)
-            if match:
-                doc = doc[:match.end()] + '\n[Documentation continues...]'
-        else:
-            doc = ''
-
-        if doc:
-            doc = '\n\n'.join([call_line, doc])
-        else:
-            doc = call_line
-        return self.show_tip(point, doc)
-
-    def show_tip(self, point, tip):
+    def show_tip(self, point, tip, wrapped_tiplines):
         """ Attempts to show the specified tip at the current cursor location.
         """
         # Attempt to find the cursor position at which to show the call tip.
@@ -170,6 +155,30 @@ class CallTipWidget(QtGui.QLabel):
         if self._start_position == -1:
             return False
 
+        if self.hide_timer_on:
+            self._hide_timer.stop()
+            # Logic to decide how much time to show the calltip depending
+            # on the amount of text present
+            if len(wrapped_tiplines) == 1:
+                args = wrapped_tiplines[0].split('(')[1]
+                nargs = len(args.split(','))
+                if nargs == 1:
+                    hide_time = 1400
+                elif nargs == 2:
+                    hide_time = 1600
+                else:
+                    hide_time = 1800
+            elif len(wrapped_tiplines) == 2:
+                args1 = wrapped_tiplines[1].strip()
+                nargs1 = len(args1.split(','))
+                if nargs1 == 1:
+                    hide_time = 2500
+                else:
+                    hide_time = 2800
+            else:
+                hide_time = 3500
+            self._hide_timer.start(hide_time, self)
+
         # Set the text and resize the widget accordingly.
         self.setText(tip)
         self.resize(self.sizeHint())
@@ -263,21 +272,7 @@ class CallTipWidget(QtGui.QLabel):
             # this check. But on Mac OS, it sometimes happens the other way
             # around when the tooltip is created.
             self.app.topLevelAt(QtGui.QCursor.pos()) != self):
-            self._hide_timer.start(300, self)
-
-    def _format_tooltip(self,doc):
-        import textwrap
-
-        # make sure a long argument list does not make
-        # the first row overflow the width of the actual tip body
-        rows = doc.split("\n")
-        # An object which is not a callable has '<no docstring>' as doc
-        if len(rows) == 1:
-            return doc
-        max_text_width = max(80, max([len(x) for x in rows[1:]]))
-        rows= textwrap.wrap(rows[0],max_text_width) + rows[1:]
-        doc = "\n".join(rows)
-        return doc
+            self._hide_timer.start(800, self)
 
     #------ Signal handlers ----------------------------------------------------
 
@@ -288,6 +283,7 @@ class CallTipWidget(QtGui.QLabel):
         if cursor.position() <= self._start_position:
             self.hide()
         else:
-            position, commas = self._find_parenthesis(self._start_position + 1)
-            if position != -1:
-                self.hide()
+            if not self.hide_timer_on:
+                position, commas = self._find_parenthesis(self._start_position + 1)
+                if position != -1:
+                    self.hide()
diff --git a/spyderlib/widgets/dependencies.py b/spyderlib/widgets/dependencies.py
index 1344501..baf4dd7 100644
--- a/spyderlib/widgets/dependencies.py
+++ b/spyderlib/widgets/dependencies.py
@@ -125,6 +125,7 @@ class DependenciesDialog(QDialog):
         QDialog.__init__(self, parent)
         self.setWindowTitle("Spyder %s: %s" % (__version__,
                                                _("Optional Dependencies")))
+        self.setWindowIcon(get_icon('advanced.png'))
         self.setModal(True)
 
         self.view = DependenciesTableView(self, [])
diff --git a/spyderlib/widgets/editor.py b/spyderlib/widgets/editor.py
index 4c309c9..b7e0269 100644
--- a/spyderlib/widgets/editor.py
+++ b/spyderlib/widgets/editor.py
@@ -29,10 +29,11 @@ import re
 import os.path as osp
 
 # Local imports
-from spyderlib.utils import encoding, sourcecode, programs, codeanalysis
+from spyderlib.utils import encoding, sourcecode, codeanalysis
 from spyderlib.utils.dochelpers import getsignaturefromtext
-from spyderlib.utils.module_completion import (module_completion,
-                                               get_preferred_submodules)
+from spyderlib.utils import introspection
+from spyderlib.utils.introspection.module_completion import (module_completion,
+                                                      get_preferred_submodules)
 from spyderlib.baseconfig import _, DEBUG, STDOUT, STDERR
 from spyderlib.config import EDIT_FILTERS, EDIT_EXT, get_filter, EDIT_FILETYPES
 from spyderlib.utils.qthelpers import (get_icon, create_action, add_actions,
@@ -283,7 +284,8 @@ class ThreadManager(QObject):
 
 class FileInfo(QObject):
     """File properties"""
-    def __init__(self, filename, encoding, editor, new, threadmanager):
+    def __init__(self, filename, encoding, editor, new, threadmanager,
+                 introspection_plugin):
         QObject.__init__(self)
         self.threadmanager = threadmanager
         self.filename = filename
@@ -292,19 +294,23 @@ class FileInfo(QObject):
         self.editor = editor
         self.path = []
         self.submods_thread = GetSubmodulesThread()
-        self.rope_project = codeeditor.get_rope_project()
+        self.introspection_plugin = introspection_plugin
+
         self.classes = (filename, None, None)
         self.analysis_results = []
         self.todo_results = []
         self.lastmodified = QFileInfo(filename).lastModified()
 
-        self.connect(editor, SIGNAL('trigger_code_completion(bool)'),
+        self.connect(editor, SIGNAL('trigger_code_completion(bool)'),                     
                      self.trigger_code_completion)
-        self.connect(editor, SIGNAL('show_object_info(int)'), 
+        self.connect(editor, SIGNAL('trigger_token_completion(bool)'),
+                     self.trigger_token_completion)
+        self.connect(editor, SIGNAL('show_object_info(int)'),
                      self.show_object_info)
         self.connect(editor, SIGNAL("go_to_definition(int)"),
                      self.go_to_definition)
-        
+        self.connect(editor, SIGNAL("go_to_definition_regex(int)"),
+                     self.go_to_definition_regex)
         self.connect(editor, SIGNAL('textChanged()'),
                      self.text_changed)
         
@@ -319,32 +325,31 @@ class FileInfo(QObject):
         self.submods_thread.start()
     
     def update_extension_modules(self):
-        self.rope_project.set_pref('extension_modules',
+        self.introspection_plugin.set_pref('extension_modules',
                                    self.submods_thread.submods)
     
     def text_changed(self):
         """Editor's text has changed"""
         self.emit(SIGNAL('text_changed_at(QString,int)'),
                   self.filename, self.editor.get_position('cursor'))
-        
-    def trigger_code_completion(self, automatic):
+
+    def trigger_code_completion(self, automatic, token_based=False):
         """Trigger code completion"""
         source_code = self.get_source_code()
         offset = self.editor.get_position('cursor')
         text = self.editor.get_text('sol', 'cursor')
-        
-        if text.lstrip().startswith('import '):
+
+        jedi = self.introspection_plugin.name == 'jedi'
+
+        comp_list = ''
+        if not jedi and text.lstrip().startswith('import '):
             text = text.lstrip()
             comp_list = module_completion(text, self.path)
             words = text.split(' ')
             if ',' in words[-1]:
                 words = words[-1].split(',')
-            if comp_list:
-                self.editor.show_completion_list(comp_list,
-                                                 completion_text=words[-1],
-                                                 automatic=automatic)
-            return
-        elif text.lstrip().startswith('from '):
+            completion_text = words[-1]
+        elif not jedi and text.lstrip().startswith('from '):
             text = text.lstrip()
             comp_list = module_completion(text, self.path)
             words = text.split(' ')
@@ -352,20 +357,49 @@ class FileInfo(QObject):
                 words = words[:-2] + words[-1].split('(')
             if ',' in words[-1]:
                 words = words[:-2] + words[-1].split(',')
-            self.editor.show_completion_list(comp_list,
-                                             completion_text=words[-1],
-                                             automatic=automatic)
-            return
+            completion_text = words[-1]
         else:
-            textlist = self.rope_project.get_completion_list(source_code,
-                                                             offset,
-                                                             self.filename)
-            if textlist:
-                completion_text = re.split(r"[^a-zA-Z0-9_]", text)[-1]
-                self.editor.show_completion_list(textlist, completion_text,
-                                                 automatic)
-                return
+            if token_based:
+                func = self.introspection_plugin.get_token_completion_list
+            else:
+                func = self.introspection_plugin.get_completion_list
+            comp_list = func(source_code, offset, self.filename)
+            if comp_list:
+                completion_text = re.findall(r"[\w.]+", text, re.UNICODE)[-1]
+                if '.' in completion_text:
+                    completion_text = completion_text.split('.')[-1]
+        if comp_list:
+            self.editor.show_completion_list(comp_list, completion_text,
+                                         automatic)
+
+    def trigger_token_completion(self, automatic):
+        """Trigger a completion using tokens only"""
+        self.trigger_code_completion(automatic, token_based=True)
         
+        
+    def find_nearest_function_call(self, position):
+        """Find the nearest function call at or prior to current position"""
+        source_code = self.get_source_code()
+        position = min(len(source_code) - 1, position)
+        orig_pos = position
+        # find the first preceding opening parens (keep track of closing parens)
+        if not position or not source_code[position] == '(':
+            close_parens = 0
+            position -= 1
+            while position and not (source_code[position] == '(' and close_parens == 0):
+                if source_code[position] == ')':
+                    close_parens += 1
+                elif source_code[position] == '(' and close_parens:
+                    close_parens -= 1
+                position -= 1
+                if source_code[position] in ['\n', '\r']:
+                    position = orig_pos
+                    break
+        if position and source_code[position] == '(':
+            position -= 1
+                
+        return position
+
     def show_object_info(self, position, auto=True):
         """Show signature calltip and/or docstring in the Object Inspector"""
         # auto is True means that this method was called automatically,
@@ -373,10 +407,11 @@ class FileInfo(QObject):
         # case, we don't want to force the object inspector to be visible, 
         # to avoid polluting the window layout
         source_code = self.get_source_code()
-        offset = position
+        offset = self.find_nearest_function_call(position)
         
-        helplist = self.rope_project.get_calltip_and_docs(source_code, offset,
-                                                          self.filename)
+        # Get calltip and docs
+        helplist = self.introspection_plugin.get_calltip_and_docs(source_code,
+                                                         offset, self.filename)
         if not helplist:
             return
         obj_fullname = ''
@@ -396,7 +431,7 @@ class FileInfo(QObject):
                     # the following attempt may succeed:
                     signature = getsignaturefromtext(doc_text, obj_name)
         if not obj_fullname:
-            obj_fullname = codeeditor.get_primary_at(source_code, offset)
+            obj_fullname = sourcecode.get_primary_at(source_code, offset)
         if obj_fullname and not obj_fullname.startswith('self.') and doc_text:
             # doc_text was generated by utils.dochelpers.getdoc
             if type(doc_text) is dict:
@@ -423,17 +458,24 @@ class FileInfo(QObject):
         if signature:
             self.editor.show_calltip('Arguments', signature, signature=True,
                                      at_position=position)
-                    
-    def go_to_definition(self, position):
+
+    def go_to_definition(self, position, regex=False):
         """Go to definition"""
         source_code = self.get_source_code()
         offset = position
-        fname, lineno = self.rope_project.get_definition_location(source_code,
-                                                    offset, self.filename)
+        if regex:
+            func = self.introspection_plugin.get_definition_location_regex
+        else:
+            func = self.introspection_plugin.get_definition_location
+        fname, lineno = func(source_code, offset, self.filename)
         if fname is not None and lineno is not None:
             self.emit(SIGNAL("edit_goto(QString,int,QString)"),
                       fname, lineno, "")
-    
+
+    def go_to_definition_regex(self, position):
+        """Go to definition using regex lookups"""
+        self.go_to_definition(position, regex=True)
+
     def get_source_code(self):
         """Return associated editor source code"""
         return to_text_string(self.editor.toPlainText())
@@ -605,6 +647,7 @@ class EditorStack(QWidget):
         if ccs not in syntaxhighlighters.COLOR_SCHEME_NAMES:
             ccs = syntaxhighlighters.COLOR_SCHEME_NAMES[0]
         self.color_scheme = ccs
+        self.introspection_plugin = introspection.get_plugin(self)
         
         self.__file_status_flag = False
         
@@ -636,7 +679,7 @@ class EditorStack(QWidget):
                               lambda: self.emit(SIGNAL('zoom_in()')))
         self.zoomoutsc = newsc(QKeySequence.ZoomOut,
                                lambda: self.emit(SIGNAL('zoom_out()')))
-        
+
     def get_shortcut_data(self):
         """
         Returns shortcut data, a list of tuples (shortcut, text, default)
@@ -756,7 +799,7 @@ class EditorStack(QWidget):
             
     def inspect_current_object(self):
         """Inspect current object in Object Inspector"""
-        if programs.is_module_installed('rope'):
+        if self.introspection_plugin:
             editor = self.get_current_editor()
             position = editor.get_position('cursor')
             finfo = self.get_current_finfo()
@@ -917,7 +960,7 @@ class EditorStack(QWidget):
         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
@@ -1293,6 +1336,9 @@ class EditorStack(QWidget):
             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:
@@ -1385,7 +1431,7 @@ class EditorStack(QWidget):
             finfo.editor.document().setModified(False)
             self.modification_changed(index=index)
             self.analyze_script(index)
-            codeeditor.validate_rope_project()
+            self.introspection_plugin.validate()
             
             #XXX CodeEditor-only: re-scan the whole text to rebuild outline 
             # explorer data from scratch (could be optimized because 
@@ -1739,7 +1785,7 @@ class EditorStack(QWidget):
         finfo.editor.set_text(txt)
         finfo.editor.document().setModified(False)
         finfo.editor.set_cursor_position(position)
-        codeeditor.validate_rope_project()
+        self.introspection_plugin.validate()
 
         #XXX CodeEditor-only: re-scan the whole text to rebuild outline 
         # explorer data from scratch (could be optimized because 
@@ -1772,7 +1818,8 @@ class EditorStack(QWidget):
         Returns finfo object (instead of editor as in previous releases)
         """
         editor = codeeditor.CodeEditor(self)
-        finfo = FileInfo(fname, enc, editor, new, self.threadmanager)
+        finfo = FileInfo(fname, enc, editor, new, self.threadmanager,
+                         self.introspection_plugin)
         self.add_to_data(finfo, set_current)
         self.connect(finfo, SIGNAL(
                     "send_to_inspector(QString,QString,QString,QString,bool)"),
@@ -1873,7 +1920,7 @@ class EditorStack(QWidget):
                 docstring = to_text_string(qstr4)
                 doc = {'obj_text': objtxt, 'name': name, 'argspec': argspec,
                        'note': note, 'docstring': docstring}
-                self.inspector.set_rope_doc(doc, force_refresh=force)
+                self.inspector.set_editor_doc(doc, force_refresh=force)
             editor = self.get_current_editor()
             editor.setFocus()
     
diff --git a/spyderlib/widgets/externalshell/monitor.py b/spyderlib/widgets/externalshell/monitor.py
index fbf3418..9f72481 100644
--- a/spyderlib/widgets/externalshell/monitor.py
+++ b/spyderlib/widgets/externalshell/monitor.py
@@ -18,7 +18,7 @@ from spyderlib.utils.dochelpers import (getargtxt, getdoc, getsource,
                                         getobjdir, isdefined)
 from spyderlib.utils.bsdsocket import (communicate, read_packet, write_packet,
                                        PACKET_NOT_RECEIVED)
-from spyderlib.utils.module_completion import module_completion
+from spyderlib.utils.introspection.module_completion import module_completion
 from spyderlib.baseconfig import get_conf_path, get_supported_types, DEBUG
 from spyderlib.py3compat import getcwd, is_text_string, pickle, _thread
 
diff --git a/spyderlib/widgets/externalshell/pythonshell.py b/spyderlib/widgets/externalshell/pythonshell.py
index 17f8bc7..26abfce 100644
--- a/spyderlib/widgets/externalshell/pythonshell.py
+++ b/spyderlib/widgets/externalshell/pythonshell.py
@@ -521,8 +521,8 @@ The process may not exit as a result of clicking this button
         if not running:
             if self.is_ipykernel:
                 self.emit(SIGNAL("ipython_kernel_start_error(QString)"),
-                          _("The console failed to start! That's all we know "
-                            ":(<br>Please close it and open a new one."))
+                          _("The kernel failed to start!! That's all we know... "
+                            "Please close this console and open a new one."))
             else:
                 QMessageBox.critical(self, _("Error"),
                                      _("A Python console failed to start!"))
diff --git a/spyderlib/widgets/findreplace.py b/spyderlib/widgets/findreplace.py
index fe68092..4cf68b1 100644
--- a/spyderlib/widgets/findreplace.py
+++ b/spyderlib/widgets/findreplace.py
@@ -158,7 +158,7 @@ class FindReplace(QWidget):
                                           self.toggle_replace_widgets)
         self.togglereplace_sc.setContext(Qt.WidgetWithChildrenShortcut)
         
-        escape_sc = QShortcut(QKeySequence("Escape"), parent, self.hide)
+        escape_sc = QShortcut(QKeySequence("Escape"), self, self.hide)
         escape_sc.setContext(Qt.WidgetWithChildrenShortcut)
 
         self.highlight_timer = QTimer(self)
diff --git a/spyderlib/widgets/ipython.py b/spyderlib/widgets/ipython.py
index 49b4bb3..904bd26 100644
--- a/spyderlib/widgets/ipython.py
+++ b/spyderlib/widgets/ipython.py
@@ -38,7 +38,7 @@ 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 import programs
+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,
@@ -110,7 +110,7 @@ class IPythonControlWidget(TracebackLinksMixin, InspectObjectMixin, QTextEdit,
         TracebackLinksMixin.__init__(self)
         InspectObjectMixin.__init__(self)
         self.found_results = []
-        self.signature_widget = CallTipWidget(self)
+        self.calltip_widget = CallTipWidget(self, hide_timer_on=True)
         # To not use Spyder calltips obtained through the monitor
         self.calltips = False
     
@@ -223,8 +223,7 @@ class IPythonShellWidget(RichIPythonWidget):
     
     #---- Public API ----------------------------------------------------------
     def set_ipyclient(self, ipyclient):
-        """Bind this IPython widget to an IPython client widget
-        (see spyderlib/plugins/ipythonconsole.py)"""
+        """Bind this shell widget to an IPython client one"""
         self.ipyclient = ipyclient
         self.exit_requested.connect(ipyclient.exit_callback)
     
@@ -323,7 +322,7 @@ These commands were executed:
                 call_info, doc = None, None
             else:
                 call_info, doc = call_tip(content, format_call=True)
-                if not call_info:
+                if call_info is None and doc is not None:
                     name = content['name'].split('.')[-1]
                     argspec = getargspecfromtext(doc)
                     if argspec:
@@ -399,12 +398,13 @@ class IPythonClient(QWidget, SaveHistoryMixin):
         self.exit_callback = lambda: plugin.close_console(client=self)
         
     #------ Public API --------------------------------------------------------
-    def show_shellwidget(self):
+    def show_shellwidget(self, give_focus=True):
         """Show shellwidget and configure it"""
         self.infowidget.hide()
         self.shellwidget.show()
         self.infowidget.setHtml(BLANK)
-        self.get_control().setFocus()
+        if give_focus:
+            self.get_control().setFocus()
         
         # Connect shellwidget to the client
         self.shellwidget.set_ipyclient(self)
@@ -420,12 +420,13 @@ class IPythonClient(QWidget, SaveHistoryMixin):
         self.shellwidget.executed.connect(self.auto_refresh_namespacebrowser)
     
     def show_kernel_error(self, error):
-        """Show kernel initialization errors in the client"""
-        # Remove explanation about how to kill the kernel
-        # (doesn't apply to us)
+        """Show kernel initialization errors in infowidget"""
+        # Remove explanation about how to kill the kernel (doesn't apply to us)
         error = error.split('issues/2049')[-1]
-        error = error.replace('\n', '<br>')
         # Remove unneeded blank lines at the beginning
+        eol = sourcecode.get_eol_chars(error)
+        if eol:
+            error = error.replace(eol, '<br>')
         while error.startswith('<br>'):
             error = error[4:]
         # Remove connection message
@@ -437,7 +438,7 @@ class IPythonClient(QWidget, SaveHistoryMixin):
         # From http://stackoverflow.com/q/7691569/438386
         error = error.replace('-', '&#8209')
             
-        message = _("An error ocurred while starting the kernel!")
+        message = _("An error ocurred while starting the kernel")
         kernel_error_template = Template(KERNEL_ERROR)
         page = kernel_error_template.substitute(css_path=CSS_PATH,
                                                 message=message,
diff --git a/spyderlib/widgets/mixins.py b/spyderlib/widgets/mixins.py
index b5d1d4a..33d8f9f 100644
--- a/spyderlib/widgets/mixins.py
+++ b/spyderlib/widgets/mixins.py
@@ -15,6 +15,7 @@ import os
 import re
 import sre_constants
 import textwrap
+from xml.sax.saxutils import escape
 
 from spyderlib.qt.QtGui import (QTextCursor, QTextDocument, QApplication,
                                 QCursor, QToolTip)
@@ -47,31 +48,43 @@ class BaseEditMixin(object):
     
     #------Calltips
     def _format_signature(self, text):
-        lines = []
+        formatted_lines = []
         name = text.split('(')[0]
-        rows = textwrap.wrap(text, 50)
+        rows = textwrap.wrap(text, width=50,
+                             subsequent_indent=' '*(len(name)+1))
         for r in rows:
+            r = escape(r) # Escape most common html chars
+            r = r.replace(' ', ' ')
             for char in ['=', ',', '(', ')', '*', '**']:
                 r = r.replace(char,
                        '<span style=\'color: red; font-weight: bold\'>' + \
                        char + '</span>')
-            lines.append(r)
-        concat_str = '<br>' + ' '*(len(name)+1)
-        signature = concat_str.join(lines)
-        return signature
+            formatted_lines.append(r)
+        signature = '<br>'.join(formatted_lines)
+        return signature, rows
     
     def show_calltip(self, title, text, signature=False, color='#2D62FF',
                      at_line=None, at_position=None):
         """Show calltip"""
         if text is None or len(text) == 0:
             return
+
         # Saving cursor position:
         if at_position is None:
             at_position = self.get_position('cursor')
         self.calltip_position = at_position
+
         # Preparing text:
         if signature:
-            text = self._format_signature(text)
+            text, wrapped_textlines = self._format_signature(text)
+        else:
+            if isinstance(text, list):
+                text = "\n    ".join(text)
+            text = text.replace('\n', '<br>')
+            if len(text) > self.calltip_size:
+                text = text[:self.calltip_size] + " ..."
+
+        # Formatting text
         font = self.font()
         size = font.pointSize()
         family = font.family()
@@ -79,13 +92,9 @@ class BaseEditMixin(object):
                   % (family, size, color)
         format2 = '<div style=\'font-family: "%s"; font-size: %spt\'>'\
                   % (family, size-1 if size > 9 else size)
-        if isinstance(text, list):
-            text = "\n    ".join(text)
-        text = text.replace('\n', '<br>')
-        if len(text) > self.calltip_size and not signature:
-            text = text[:self.calltip_size] + " ..."
         tiptext = format1 + ('<b>%s</b></div>' % title) + '<hr>' + \
                   format2 + text + "</div>"
+
         # Showing tooltip at cursor position:
         cx, cy = self.get_coordinates('cursor')
         if at_line is not None:
@@ -96,7 +105,7 @@ class BaseEditMixin(object):
         point.setX(point.x()+self.get_linenumberarea_width())
         point.setY(point.y()+font.pointSize()+5)
         if signature:
-            self.signature_widget.show_call_info(point, tiptext)
+            self.calltip_widget.show_tip(point, tiptext, wrapped_textlines)
         else:
             QToolTip.showText(point, tiptext)
     
diff --git a/spyderlib/widgets/sourcecode/base.py b/spyderlib/widgets/sourcecode/base.py
index 8aa94f3..9e76184 100644
--- a/spyderlib/widgets/sourcecode/base.py
+++ b/spyderlib/widgets/sourcecode/base.py
@@ -212,7 +212,7 @@ class TextEditBaseWidget(QPlainTextEdit, BaseEditMixin):
         self.calltip_position = None
         self.calltip_font = QFont()
         self.completion_text = ""
-        self.signature_widget = CallTipWidget(self)
+        self.calltip_widget = CallTipWidget(self, hide_timer_on=True)
         
         # Highlight current line color
         self.currentline_color = QColor(Qt.red).lighter(190)
@@ -849,7 +849,7 @@ class TextEditBaseWidget(QPlainTextEdit, BaseEditMixin):
     def mousePressEvent(self, event):
         """Reimplement Qt method"""
         if os.name != 'posix' and event.button() == Qt.MidButton:
-            self.signature_widget.hide()
+            self.calltip_widget.hide()
             self.setFocus()
             event = QMouseEvent(QEvent.MouseButtonPress, event.pos(),
                                 Qt.LeftButton, Qt.LeftButton, Qt.NoModifier)
@@ -857,7 +857,7 @@ class TextEditBaseWidget(QPlainTextEdit, BaseEditMixin):
             QPlainTextEdit.mouseReleaseEvent(self, event)
             self.paste()
         else:
-            self.signature_widget.hide()
+            self.calltip_widget.hide()
             QPlainTextEdit.mousePressEvent(self, event)
 
     def focusInEvent(self, event):
diff --git a/spyderlib/widgets/sourcecode/codeeditor.py b/spyderlib/widgets/sourcecode/codeeditor.py
index 183bb99..8ce894c 100644
--- a/spyderlib/widgets/sourcecode/codeeditor.py
+++ b/spyderlib/widgets/sourcecode/codeeditor.py
@@ -47,6 +47,7 @@ from spyderlib.utils.qthelpers import (add_actions, create_action, keybinding,
                                        mimedata2url, get_icon)
 from spyderlib.utils.dochelpers import getobj
 from spyderlib.utils import encoding, sourcecode
+from spyderlib.utils.sourcecode import ALL_LANGUAGES
 from spyderlib.utils.debug import log_last_error, log_dt
 from spyderlib.widgets.editortools import PythonCFM
 from spyderlib.widgets.sourcecode.base import TextEditBaseWidget
@@ -56,202 +57,11 @@ from spyderlib import dependencies
 
 #%% This line is for cell execution testing
 # For debugging purpose:
-LOG_FILENAME = get_conf_path('rope.log')
-
+LOG_FILENAME = get_conf_path('codeeditor.log')
 DEBUG_EDITOR = DEBUG >= 3
 
 
 #===============================================================================
-# Code introspection features: rope integration
-#===============================================================================
-ROPE_REQVER = '>=0.9.2'
-dependencies.add('rope',
-                 _("Editor's code completion, go-to-definition and help"),
-                 required_version=ROPE_REQVER)
-
-try:
-    try:
-        from spyderlib import rope_patch
-        rope_patch.apply()
-    except ImportError:
-        # rope 0.9.2/0.9.3 is not installed
-        pass
-    import rope.base.libutils
-    import rope.contrib.codeassist
-except ImportError:
-    pass
-
-
-#TODO: The following preferences should be customizable in the future
-ROPE_PREFS = {'ignore_syntax_errors': True,
-              'ignore_bad_imports': True,
-              'soa_followed_calls': 2,
-              'extension_modules': [],
-              }
-
-
-class RopeProject(object):
-    def __init__(self):
-        self.project = None
-        self.create_rope_project(root_path=get_conf_path())
-
-    #------rope integration
-    def create_rope_project(self, root_path):
-        if PY2:
-            root_path = encoding.to_fs_from_unicode(root_path)
-        else:
-            #TODO: test if this is working without any further change in 
-            # Python 3 with a user account containing unicode characters
-            pass
-        try:
-            import rope.base.project
-            self.project = rope.base.project.Project(root_path, **ROPE_PREFS)
-        except ImportError:
-            self.project = None
-            if DEBUG_EDITOR:
-                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,
-                               "create_rope_project: %r" % root_path)
-        self.validate_rope_project()
-
-    def close_rope_project(self):
-        if self.project is not None:
-            self.project.close()
-
-    def validate_rope_project(self):
-        if self.project is not None:
-            self.project.validate(self.project.root)
-
-    def set_pref(self, key, value):
-        if self.project is not None:
-            self.project.prefs.set(key, value)
-
-    def get_completion_list(self, source_code, offset, filename):
-        if self.project is None:
-            return []
-        if PY2:
-            filename = filename.encode('utf-8')
-        else:
-            #TODO: test if this is working without any further change in 
-            # Python 3 with a user account containing unicode characters
-            pass
-        try:
-            resource = rope.base.libutils.path_to_resource(self.project,
-                                                           filename)
-        except Exception as _error:
-            if DEBUG_EDITOR:
-                log_last_error(LOG_FILENAME, "path_to_resource: %r" % filename)
-            resource = None
-        try:
-            if DEBUG_EDITOR:
-                t0 = time.time()
-            proposals = rope.contrib.codeassist.code_assist(self.project,
-                                    source_code, offset, resource, maxfixes=3)
-            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]
-        except Exception as _error:  #analysis:ignore
-            if DEBUG_EDITOR:
-                log_last_error(LOG_FILENAME, "get_completion_list")
-            return []
-
-    def get_calltip_and_docs(self, source_code, offset, filename):
-        if self.project is None:
-            return []
-        if PY2:
-            filename = filename.encode('utf-8')
-        else:
-            #TODO: test if this is working without any further change in 
-            # Python 3 with a user account containing unicode characters
-            pass
-        try:
-            resource = rope.base.libutils.path_to_resource(self.project,
-                                                           filename)
-        except Exception as _error:
-            if DEBUG_EDITOR:
-                log_last_error(LOG_FILENAME, "path_to_resource: %r" % filename)
-            resource = None
-        try:
-            if DEBUG_EDITOR:
-                t0 = time.time()
-            cts = rope.contrib.codeassist.get_calltip(
-                            self.project, source_code, offset, resource,
-                            ignore_unknown=False, remove_self=True, maxfixes=3)
-            if DEBUG_EDITOR:
-                log_dt(LOG_FILENAME, "get_calltip", t0)
-            if cts is not None:
-                while '..' in cts:
-                    cts = cts.replace('..', '.')
-                if '(.)' in cts:
-                    cts = cts.replace('(.)', '(...)')
-            try:
-                doc_text = rope.contrib.codeassist.get_doc(self.project,
-                                     source_code, offset, resource, maxfixes=3)
-                if DEBUG_EDITOR:
-                    log_dt(LOG_FILENAME, "get_doc", t0)
-            except Exception as _error:
-                doc_text = ''
-                if DEBUG_EDITOR:
-                    log_last_error(LOG_FILENAME, "get_doc")
-            return [cts, doc_text]
-        except Exception as _error:  #analysis:ignore
-            if DEBUG_EDITOR:
-                log_last_error(LOG_FILENAME, "get_calltip_text")
-            return []
-
-    def get_definition_location(self, source_code, offset, filename):
-        if self.project is None:
-            return (None, None)
-        if PY2:
-            filename = filename.encode('utf-8')
-        else:
-            #TODO: test if this is working without any further change in 
-            # Python 3 with a user account containing unicode characters
-            pass
-        try:
-            resource = rope.base.libutils.path_to_resource(self.project,
-                                                           filename)
-        except Exception as _error:
-            if DEBUG_EDITOR:
-                log_last_error(LOG_FILENAME, "path_to_resource: %r" % filename)
-            resource = None
-        try:
-            if DEBUG_EDITOR:
-                t0 = time.time()
-            resource, lineno = rope.contrib.codeassist.get_definition_location(
-                    self.project, source_code, offset, resource, maxfixes=3)
-            if DEBUG_EDITOR:
-                log_dt(LOG_FILENAME, "get_definition_location", t0)
-            if resource is not None:
-                filename = resource.real_path
-            return filename, lineno
-        except Exception as _error:  #analysis:ignore
-            if DEBUG_EDITOR:
-                log_last_error(LOG_FILENAME, "get_definition_location")
-            return (None, None)
-
-
-ROPE_PROJECT = None
-def get_rope_project():
-    """Create a single rope project"""
-    global ROPE_PROJECT
-    if ROPE_PROJECT is None:
-        ROPE_PROJECT = RopeProject()
-    return ROPE_PROJECT
-
-def validate_rope_project():
-    """Validate rope project"""
-    get_rope_project().validate_rope_project()
-
-
-#===============================================================================
 # Go to line dialog box
 #===============================================================================
 class GoToLineDialog(QDialog):
@@ -449,16 +259,6 @@ class BlockUserData(QTextBlockUserData):
         bud_list.pop(bud_list.index(self))
 
 
-def get_primary_at(source_code, offset):
-    """Return Python object in *source_code* at *offset*"""
-    try:
-        import rope.base.worder
-        word_finder = rope.base.worder.Worder(source_code, True)
-        return word_finder.get_primary_at(offset)
-    except ImportError:
-        return
-
-
 def set_scrollflagarea_painter(painter, light_color):
     """Set scroll flag area painter pen and brush colors"""
     painter.setPen(QColor(light_color).darker(120))
@@ -487,26 +287,23 @@ def get_file_language(filename, text=None):
 
 class CodeEditor(TextEditBaseWidget):
     """Source Code Editor Widget based exclusively on Qt"""
-    LANGUAGES = {
-                 ('py', 'pyw', 'python', 'ipy'): (sh.PythonSH, '#', PythonCFM),
-                 ('pyx', 'pxi', 'pxd'): (sh.CythonSH, '#', PythonCFM),
-                 ('f', 'for', 'f77'): (sh.Fortran77SH, 'c', None),
-                 ('f90', 'f95', 'f2k'): (sh.FortranSH, '!', None),
-                 ('pro',): (sh.IdlSH, ';', None),
-                 ('m',): (sh.MatlabSH, '%', None),
-                 ('diff', 'patch', 'rej'): (sh.DiffSH, '', None),
-                 ('po', 'pot'): (sh.GetTextSH, '#', None),
-                 ('nsi', 'nsh'): (sh.NsisSH, '#', None),
-                 ('htm', 'html'): (sh.HtmlSH, '', None),
-                 ('css',): (sh.CssSH, '', None),
-                 ('xml',): (sh.XmlSH, '', None),
-                 ('js',): (sh.JsSH, '', None),
-                 ('c', 'cc', 'cpp', 'cxx', 'h', 'hh', 'hpp', 'hxx',
-                  ): (sh.CppSH, '//', None),
-                 ('cl',): (sh.OpenCLSH, '//', None),
-                 ('bat', 'cmd', 'nt'): (sh.BatchSH, 'rem ', None),
-                 ('properties', 'session', 'ini', 'inf', 'reg', 'url',
-                  'cfg', 'cnf', 'aut', 'iss'): (sh.IniSH, '#', None),
+    LANGUAGES ={ 'Python': (sh.PythonSH, '#', PythonCFM),
+                 'Cython': (sh.Fortran77SH, 'c', 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),
+                 'Cpp': (sh.CppSH, '//', None),
+                 'OpenCL': (sh.OpenCLSH, '//', None),
+                 'Batch': (sh.BatchSH, 'rem ', None),
+                 'Ini': (sh.IniSH, '#', None),
                  }
     try:
         import pygments  # analysis:ignore
@@ -520,6 +317,7 @@ class CodeEditor(TextEditBaseWidget):
 
     def __init__(self, parent=None):
         TextEditBaseWidget.__init__(self, parent)
+        self.setFocusPolicy(Qt.StrongFocus)
 
         # Calltips
         calltip_size = CONF.get('editor_appearance', 'calltips/size')
@@ -848,8 +646,8 @@ class CodeEditor(TextEditBaseWidget):
         self.comment_string = ''
         sh_class = sh.TextSH
         if language is not None:
-            for key in self.LANGUAGES:
-                if language.lower() in key:
+            for (key, value) in ALL_LANGUAGES.items():
+                if language.lower() in value:
                     self.supported_language = True
                     sh_class, comment_string, CFMatch = self.LANGUAGES[key]
                     self.comment_string = comment_string
@@ -878,6 +676,52 @@ class CodeEditor(TextEditBaseWidget):
     def is_cython(self):
         return self.highlighter_class is sh.CythonSH
 
+    def is_python_like(self):
+        return self.is_python() or self.is_cython()
+        
+    def intelligent_tab(self):
+        """Provide intelligent behavoir for Tab key press"""
+        leading_text = self.get_text('sol', 'cursor')
+        if not leading_text.strip(): 
+            # blank line
+            self.indent_or_replace()
+        elif self.in_comment_or_string() and not leading_text.endswith(' '):
+            # in a word in a comment
+            self.do_token_completion()
+        elif leading_text.endswith('import ') or leading_text[-1] == '.':
+            # blank import or dot completion
+            self.do_code_completion()
+        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()`)
+            self.do_code_completion()
+        elif leading_text[-1] in '(,' or leading_text.endswith(', '):
+            self.indent_or_replace()
+        elif leading_text.endswith(' '):
+            # if the line ends with a space, indent
+            self.indent_or_replace()
+        elif re.search(r"[^\d\W]\w*\Z", leading_text, re.UNICODE):
+            # if the line ends with a non-whitespace character
+            self.do_code_completion()
+        else:
+            self.indent_or_replace()
+
+    def intelligent_backtab(self):
+        """Provide intelligent behavoir for Shift+Tab key press"""
+        leading_text = self.get_text('sol', 'cursor')
+        if not leading_text.strip():
+            # blank line
+            self.unindent()
+        elif self.in_comment_or_string():
+            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
@@ -927,10 +771,10 @@ class CodeEditor(TextEditBaseWidget):
             self.document().setModified(True)
 
     def get_current_object(self):
-        """Return current object (string) -- requires 'rope'"""
+        """Return current object (string) """
         source_code = to_text_string(self.toPlainText())
         offset = self.get_position('cursor')
-        return get_primary_at(source_code, offset)
+        return sourcecode.get_primary_at(source_code, offset)
 
     #------Find occurences
     def __find_first(self, text):
@@ -1006,7 +850,7 @@ class CodeEditor(TextEditBaseWidget):
         if self.has_selected_text() and self.get_selected_text() != text:
             return
             
-        if (self.is_python() or self.is_cython()) and \
+        if (self.is_python_like()) and \
            (sourcecode.is_keyword(to_text_string(text)) or \
            to_text_string(text) == 'self'):
             return
@@ -1200,7 +1044,7 @@ class CodeEditor(TextEditBaseWidget):
     def add_remove_breakpoint(self, line_number=None, condition=None,
                               edit_condition=False):
         """Add/remove breakpoint"""
-        if not self.is_python() and not self.is_cython():
+        if not self.is_python_like():
             return
         if line_number is None:
             block = self.textCursor().block()
@@ -1275,12 +1119,23 @@ class CodeEditor(TextEditBaseWidget):
     def do_code_completion(self):
         """Trigger code completion"""
         if not self.is_completion_widget_visible():
-            self.emit(SIGNAL('trigger_code_completion(bool)'), False)
+            if self.is_python_like() and not self.in_comment_or_string():
+                self.emit(SIGNAL('trigger_code_completion(bool)'), False)
+            else:
+                self.do_token_completion()
+
+    def do_token_completion(self):
+        """Trigger a token-based completion"""
+        if not self.is_completion_widget_visible():
+            self.emit(SIGNAL('trigger_token_completion(bool)'), False)
 
     def do_go_to_definition(self):
         """Trigger go-to-definition"""
         self.emit(SIGNAL("go_to_definition(int)"), self.textCursor().position())
 
+    def show_object_info(self, position):
+        """Trigger a calltip"""
+        self.emit(SIGNAL('show_object_info(int)'), position)
 
     #-----edge line
     def set_edge_line_enabled(self, state):
@@ -1805,7 +1660,7 @@ class CodeEditor(TextEditBaseWidget):
 
         Returns True if indent needed to be fixed
         """
-        if not self.is_python() and not self.is_cython():
+        if not self.is_python_like():
             return
         cursor = self.textCursor()
         block_nb = cursor.blockNumber()
@@ -1814,6 +1669,7 @@ class CodeEditor(TextEditBaseWidget):
             prevtext = to_text_string(cursor.block().text()).rstrip()
             if not prevtext.strip().startswith('#'):
                 break
+
         indent = self.get_block_indentation(block_nb)
         correct_indent = self.get_block_indentation(prevline)
 
@@ -1868,7 +1724,7 @@ class CodeEditor(TextEditBaseWidget):
             self.add_prefix(self.indent_chars)
         elif force or not leading_text.strip() \
              or (self.tab_indents and self.tab_mode):
-            if self.is_python() or self.is_cython():
+            if self.is_python_like():
                 if not self.fix_indent(forward=True):
                     self.add_prefix(self.indent_chars)
             else:
@@ -1911,7 +1767,7 @@ class CodeEditor(TextEditBaseWidget):
             leading_text = self.get_text('sol', 'cursor')
             if force or not leading_text.strip() \
                or (self.tab_indents and self.tab_mode):
-                if self.is_python() or self.is_cython():
+                if self.is_python_like():
                     if not self.fix_indent(forward=False):
                         self.remove_prefix(self.indent_chars)
                 elif leading_text.endswith('\t'):
@@ -2260,7 +2116,8 @@ class CodeEditor(TextEditBaseWidget):
         # Read-only context-menu
         self.readonly_menu = QMenu(self)
         add_actions(self.readonly_menu,
-                    (self.copy_action, None, selectall_action))
+                    (self.copy_action, None, selectall_action,
+                     self.gotodef_action))
     
     def keyPressEvent(self, event):
         """Reimplement Qt method"""
@@ -2274,7 +2131,7 @@ class CodeEditor(TextEditBaseWidget):
             self.hide_tooltip_if_necessary(key)
         if key in (Qt.Key_Enter, Qt.Key_Return):
             if not shift and not ctrl:
-                if self.add_colons_enabled and self.is_python() and \
+                if self.add_colons_enabled and self.is_python_like() and \
                   self.autoinsert_colons():
                     self.insert_text(':' + self.get_line_separator())
                     self.fix_indent()
@@ -2321,12 +2178,12 @@ class CodeEditor(TextEditBaseWidget):
                         self.completion_text = self.completion_text[:-1]
         elif key == Qt.Key_Period:
             self.insert_text(text)
-            if (self.is_python() or self.is_cython()) and not \
+            if (self.is_python_like()) and not \
               self.in_comment_or_string() and self.codecompletion_auto:
                 # Enable auto-completion only if last token isn't a float
                 last_obj = getobj(self.get_text('sol', 'cursor'))
                 if last_obj and not last_obj.isdigit():
-                    self.emit(SIGNAL('trigger_code_completion(bool)'), True)
+                    self.do_code_completion()
         elif key == Qt.Key_Home:
             self.stdkey_home(shift, ctrl)
         elif key == Qt.Key_End:
@@ -2338,16 +2195,16 @@ class CodeEditor(TextEditBaseWidget):
             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 (',', ')', ']', '}')):
+              (len(s_trailing_text) == 0 or \
+              s_trailing_text[0] in (',', ')', ']', '}')):
                 self.insert_text('()')
                 cursor = self.textCursor()
                 cursor.movePosition(QTextCursor.PreviousCharacter)
                 self.setTextCursor(cursor)
             else:
                 self.insert_text(text)
-            if (self.is_python() or self.is_cython()) and \
-               self.get_text('sol', 'cursor') and self.calltips:
+            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:
@@ -2363,7 +2220,8 @@ class CodeEditor(TextEditBaseWidget):
         elif key in (Qt.Key_QuoteDbl, Qt.Key_Apostrophe) and \
           self.close_quotes_enabled:
             self.autoinsert_quotes(key)
-        elif key in (Qt.Key_ParenRight, Qt.Key_BraceRight, Qt.Key_BracketRight)\
+        elif ((key in (Qt.Key_ParenRight, Qt.Key_BraceRight, Qt.Key_BracketRight)) or (
+              shift and key == Qt.Key_0)) \
           and not self.has_selected_text() and self.close_parentheses_enabled \
           and not self.textCursor().atBlockEnd():
             cursor = self.textCursor()
@@ -2371,7 +2229,7 @@ class CodeEditor(TextEditBaseWidget):
                                 QTextCursor.KeepAnchor)
             text = to_text_string(cursor.selectedText())
             if text == {Qt.Key_ParenRight: ')', Qt.Key_BraceRight: '}',
-                        Qt.Key_BracketRight: ']'}[key]:
+                        Qt.Key_BracketRight: ']', Qt.Key_0: ')'}[key]:
                 cursor.clearSelection()
                 self.setTextCursor(cursor)
             else:
@@ -2399,11 +2257,19 @@ class CodeEditor(TextEditBaseWidget):
         elif key == Qt.Key_Tab:
             # Important note: <TAB> can't be called with a QShortcut because
             # of its singular role with respect to widget focus management
-            self.indent_or_replace()
+            if not self.has_selected_text() and not self.tab_mode:
+                self.intelligent_tab()
+            else:
+                # indent the selected text
+                self.indent_or_replace()
         elif key == Qt.Key_Backtab:
             # Backtab, i.e. Shift+<TAB>, could be treated as a QShortcut but
             # there is no point since <TAB> can't (see above)
-            self.unindent()
+            if not self.has_selected_text() and not self.tab_mode:
+                self.intelligent_backtab()
+            else:
+                # indent the selected text
+                self.unindent()
         else:
             TextEditBaseWidget.keyPressEvent(self, event)
             if self.is_completion_widget_visible() and text:
@@ -2417,7 +2283,7 @@ class CodeEditor(TextEditBaseWidget):
         if self.go_to_definition_enabled and \
            event.modifiers() & Qt.ControlModifier:
             text = self.get_word_at(event.pos())
-            if text and (self.is_python() or self.is_cython())\
+            if text and (self.is_python_like())\
                and not sourcecode.is_keyword(to_text_string(text)):
                 if not self.__cursor_changed:
                     QApplication.setOverrideCursor(
@@ -2456,9 +2322,11 @@ class CodeEditor(TextEditBaseWidget):
             cursor.select(QTextCursor.WordUnderCursor)
             text = to_text_string(cursor.selectedText())
         if self.go_to_definition_enabled and text is not None\
-           and (self.is_python() or self.is_cython())\
+           and (self.is_python_like())\
            and not sourcecode.is_keyword(text):
             self.emit(SIGNAL("go_to_definition(int)"), position)
+        else:
+            self.emit(SIGNAL("go_to_definition_regex(int)"), position)
 
     def mousePressEvent(self, event):
         """Reimplement Qt method"""
diff --git a/spyderplugins/p_pylint.py b/spyderplugins/p_pylint.py
index 76dc7ad..3167efe 100644
--- a/spyderplugins/p_pylint.py
+++ b/spyderplugins/p_pylint.py
@@ -26,7 +26,7 @@ from spyderplugins.widgets.pylintgui import PylintWidget, PYLINT_PATH
 class PylintConfigPage(PluginConfigPage):
     def setup_page(self):
         settings_group = QGroupBox(_("Settings"))
-        save_box = self.create_checkbox(_("Save script before analyzing it"),
+        save_box = self.create_checkbox(_("Save file before analyzing it"),
                                         'save_before', default=True)
         
         hist_group = QGroupBox(_("History"))
@@ -38,7 +38,7 @@ class PylintConfigPage(PluginConfigPage):
                             min_=10, max_=1000000, step=10)
 
         results_group = QGroupBox(_("Results"))
-        results_label1 = QLabel(_("Pylint plugin results are stored here:"))
+        results_label1 = QLabel(_("Results are stored here:"))
         results_label1.setWordWrap(True)
 
         # Warning: do not try to regroup the following QLabel contents with 
@@ -86,7 +86,7 @@ class Pylint(PylintWidget, SpyderPluginMixin):
     #------ SpyderPluginWidget API --------------------------------------------
     def get_plugin_title(self):
         """Return widget title"""
-        return _("Pylint")
+        return _("Static code analysis")
     
     def get_plugin_icon(self):
         """Return widget icon"""
@@ -122,7 +122,7 @@ class Pylint(PylintWidget, SpyderPluginMixin):
                      self.main.redirect_internalshell_stdio)
         self.main.add_dockwidget(self)
         
-        pylint_act = create_action(self, _("Run pylint code analysis"),
+        pylint_act = create_action(self, _("Run static code analysis"),
                                    triggered=self.run_pylint)
         pylint_act.setEnabled(PYLINT_PATH is not None)
         self.register_shortcut(pylint_act, context="Pylint",
diff --git a/spyderplugins/widgets/pylintgui.py b/spyderplugins/widgets/pylintgui.py
index a69c7c3..877c053 100644
--- a/spyderplugins/widgets/pylintgui.py
+++ b/spyderplugins/widgets/pylintgui.py
@@ -198,7 +198,7 @@ class PylintWidget(QWidget):
         self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data)
 
         browse_button = create_toolbutton(self, icon=get_icon('fileopen.png'),
-                               tip=_('Select Python script'),
+                               tip=_('Select Python file'),
                                triggered=self.select_file)
 
         self.ratelabel = QLabel()
@@ -206,7 +206,7 @@ class PylintWidget(QWidget):
         self.log_button = create_toolbutton(self, icon=get_icon('log.png'),
                                     text=_("Output"),
                                     text_beside_icon=True,
-                                    tip=_("Complete Pylint output"),
+                                    tip=_("Complete output"),
                                     triggered=self.show_log)
         self.treewidget = ResultsTree(self)
         
@@ -267,8 +267,8 @@ class PylintWidget(QWidget):
             
     def select_file(self):
         self.emit(SIGNAL('redirect_stdio(bool)'), False)
-        filename, _selfilter = getopenfilename(self, _("Select Python script"),
-                           getcwd(), _("Python scripts")+" (*.py ; *.pyw)")
+        filename, _selfilter = getopenfilename(self, _("Select Python file"),
+                           getcwd(), _("Python files")+" (*.py ; *.pyw)")
         self.emit(SIGNAL('redirect_stdio(bool)'), False)
         if filename:
             self.analyze(filename)

-- 
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