Sat, 02 Jul 2016 19:14:09 +0200
Added capability to search the file tree via the keyboard (directories and files only) to the file browser and the project browsers.
--- a/APIs/Python3/eric6.api Sat Jul 02 14:54:14 2016 +0200 +++ b/APIs/Python3/eric6.api Sat Jul 02 19:14:09 2016 +0200 @@ -7158,6 +7158,7 @@ eric6.Project.ProjectBaseBrowser.ProjectBaseBrowser._expandAllDirs?5() eric6.Project.ProjectBaseBrowser.ProjectBaseBrowser._initHookMethods?5() eric6.Project.ProjectBaseBrowser.ProjectBaseBrowser._initMenusAndVcs?5() +eric6.Project.ProjectBaseBrowser.ProjectBaseBrowser._keyboardSearchType?5(item) eric6.Project.ProjectBaseBrowser.ProjectBaseBrowser._newProject?5() eric6.Project.ProjectBaseBrowser.ProjectBaseBrowser._prepareRepopulateItem?5(name) eric6.Project.ProjectBaseBrowser.ProjectBaseBrowser._projectClosed?5() @@ -8493,6 +8494,7 @@ eric6.UI.Browser.Browser._editPixmap?5() eric6.UI.Browser.Browser._gotoAttribute?5(act) eric6.UI.Browser.Browser._init?5() +eric6.UI.Browser.Browser._keyboardSearchType?5(item) eric6.UI.Browser.Browser._openHexEditor?5() eric6.UI.Browser.Browser._openItem?5() eric6.UI.Browser.Browser._resizeColumns?5(index) @@ -8507,6 +8509,7 @@ eric6.UI.Browser.Browser.handlePreferencesChanged?4() eric6.UI.Browser.Browser.handleProgramChange?4(fn) eric6.UI.Browser.Browser.handleUnittest?4() +eric6.UI.Browser.Browser.keyboardSearch?4(search) eric6.UI.Browser.Browser.layoutDisplay?4() eric6.UI.Browser.Browser.linguistFile?7 eric6.UI.Browser.Browser.mouseDoubleClickEvent?4(mouseEvent) @@ -10670,6 +10673,7 @@ eric6.WebBrowser.Tools.WebBrowserTools.readAllFileByteContents?4(filename) eric6.WebBrowser.Tools.WebBrowserTools.readAllFileContents?4(filename) eric6.WebBrowser.Tools.WebHitTestResult.WebHitTestResult.alternateText?4() +eric6.WebBrowser.Tools.WebHitTestResult.WebHitTestResult.baseUrl?4() eric6.WebBrowser.Tools.WebHitTestResult.WebHitTestResult.boundingRect?4() eric6.WebBrowser.Tools.WebHitTestResult.WebHitTestResult.imageUrl?4() eric6.WebBrowser.Tools.WebHitTestResult.WebHitTestResult.isContentEditable?4()
--- a/Documentation/Help/source.qhp Sat Jul 02 14:54:14 2016 +0200 +++ b/Documentation/Help/source.qhp Sat Jul 02 19:14:09 2016 +0200 @@ -2379,6 +2379,7 @@ <keyword name="Browser._editPixmap" id="Browser._editPixmap" ref="eric6.UI.Browser.html#Browser._editPixmap" /> <keyword name="Browser._gotoAttribute" id="Browser._gotoAttribute" ref="eric6.UI.Browser.html#Browser._gotoAttribute" /> <keyword name="Browser._init" id="Browser._init" ref="eric6.UI.Browser.html#Browser._init" /> + <keyword name="Browser._keyboardSearchType" id="Browser._keyboardSearchType" ref="eric6.UI.Browser.html#Browser._keyboardSearchType" /> <keyword name="Browser._openHexEditor" id="Browser._openHexEditor" ref="eric6.UI.Browser.html#Browser._openHexEditor" /> <keyword name="Browser._openItem" id="Browser._openItem" ref="eric6.UI.Browser.html#Browser._openItem" /> <keyword name="Browser._resizeColumns" id="Browser._resizeColumns" ref="eric6.UI.Browser.html#Browser._resizeColumns" /> @@ -2391,6 +2392,7 @@ <keyword name="Browser.handlePreferencesChanged" id="Browser.handlePreferencesChanged" ref="eric6.UI.Browser.html#Browser.handlePreferencesChanged" /> <keyword name="Browser.handleProgramChange" id="Browser.handleProgramChange" ref="eric6.UI.Browser.html#Browser.handleProgramChange" /> <keyword name="Browser.handleUnittest" id="Browser.handleUnittest" ref="eric6.UI.Browser.html#Browser.handleUnittest" /> + <keyword name="Browser.keyboardSearch" id="Browser.keyboardSearch" ref="eric6.UI.Browser.html#Browser.keyboardSearch" /> <keyword name="Browser.layoutDisplay" id="Browser.layoutDisplay" ref="eric6.UI.Browser.html#Browser.layoutDisplay" /> <keyword name="Browser.mouseDoubleClickEvent" id="Browser.mouseDoubleClickEvent" ref="eric6.UI.Browser.html#Browser.mouseDoubleClickEvent" /> <keyword name="Browser.saveToplevelDirs" id="Browser.saveToplevelDirs" ref="eric6.UI.Browser.html#Browser.saveToplevelDirs" /> @@ -10949,6 +10951,7 @@ <keyword name="ProjectBaseBrowser._expandAllDirs" id="ProjectBaseBrowser._expandAllDirs" ref="eric6.Project.ProjectBaseBrowser.html#ProjectBaseBrowser._expandAllDirs" /> <keyword name="ProjectBaseBrowser._initHookMethods" id="ProjectBaseBrowser._initHookMethods" ref="eric6.Project.ProjectBaseBrowser.html#ProjectBaseBrowser._initHookMethods" /> <keyword name="ProjectBaseBrowser._initMenusAndVcs" id="ProjectBaseBrowser._initMenusAndVcs" ref="eric6.Project.ProjectBaseBrowser.html#ProjectBaseBrowser._initMenusAndVcs" /> + <keyword name="ProjectBaseBrowser._keyboardSearchType" id="ProjectBaseBrowser._keyboardSearchType" ref="eric6.Project.ProjectBaseBrowser.html#ProjectBaseBrowser._keyboardSearchType" /> <keyword name="ProjectBaseBrowser._newProject" id="ProjectBaseBrowser._newProject" ref="eric6.Project.ProjectBaseBrowser.html#ProjectBaseBrowser._newProject" /> <keyword name="ProjectBaseBrowser._prepareRepopulateItem" id="ProjectBaseBrowser._prepareRepopulateItem" ref="eric6.Project.ProjectBaseBrowser.html#ProjectBaseBrowser._prepareRepopulateItem" /> <keyword name="ProjectBaseBrowser._projectClosed" id="ProjectBaseBrowser._projectClosed" ref="eric6.Project.ProjectBaseBrowser.html#ProjectBaseBrowser._projectClosed" /> @@ -15733,6 +15736,7 @@ <keyword name="WebHitTestResult (Module)" id="WebHitTestResult (Module)" ref="eric6.WebBrowser.Tools.WebHitTestResult.html" /> <keyword name="WebHitTestResult.__populate" id="WebHitTestResult.__populate" ref="eric6.WebBrowser.Tools.WebHitTestResult.html#WebHitTestResult.__populate" /> <keyword name="WebHitTestResult.alternateText" id="WebHitTestResult.alternateText" ref="eric6.WebBrowser.Tools.WebHitTestResult.html#WebHitTestResult.alternateText" /> + <keyword name="WebHitTestResult.baseUrl" id="WebHitTestResult.baseUrl" ref="eric6.WebBrowser.Tools.WebHitTestResult.html#WebHitTestResult.baseUrl" /> <keyword name="WebHitTestResult.boundingRect" id="WebHitTestResult.boundingRect" ref="eric6.WebBrowser.Tools.WebHitTestResult.html#WebHitTestResult.boundingRect" /> <keyword name="WebHitTestResult.imageUrl" id="WebHitTestResult.imageUrl" ref="eric6.WebBrowser.Tools.WebHitTestResult.html#WebHitTestResult.imageUrl" /> <keyword name="WebHitTestResult.isContentEditable" id="WebHitTestResult.isContentEditable" ref="eric6.WebBrowser.Tools.WebHitTestResult.html#WebHitTestResult.isContentEditable" />
--- a/Documentation/Source/eric6.Project.ProjectBaseBrowser.html Sat Jul 02 14:54:14 2016 +0200 +++ b/Documentation/Source/eric6.Project.ProjectBaseBrowser.html Sat Jul 02 19:14:09 2016 +0200 @@ -109,6 +109,9 @@ <td><a href="#ProjectBaseBrowser._initMenusAndVcs">_initMenusAndVcs</a></td> <td>Protected slot to initialize the menus and the Vcs interface.</td> </tr><tr> +<td><a href="#ProjectBaseBrowser._keyboardSearchType">_keyboardSearchType</a></td> +<td>Protected method to check, if the item is of the correct type.</td> +</tr><tr> <td><a href="#ProjectBaseBrowser._newProject">_newProject</a></td> <td>Protected slot to handle the newProject signal.</td> </tr><tr> @@ -320,7 +323,27 @@ <b>_initMenusAndVcs</b>(<i></i>) <p> Protected slot to initialize the menus and the Vcs interface. -</p><a NAME="ProjectBaseBrowser._newProject" ID="ProjectBaseBrowser._newProject"></a> +</p><a NAME="ProjectBaseBrowser._keyboardSearchType" ID="ProjectBaseBrowser._keyboardSearchType"></a> +<h4>ProjectBaseBrowser._keyboardSearchType</h4> +<b>_keyboardSearchType</b>(<i>item</i>) +<p> + Protected method to check, if the item is of the correct type. +</p><dl> +<dt><i>item</i> (BrowserItem)</dt> +<dd> +reference to the item +</dd> +</dl><dl> +<dt>Returns:</dt> +<dd> +flag indicating a correct type +</dd> +</dl><dl> +<dt>Return Type:</dt> +<dd> +bool +</dd> +</dl><a NAME="ProjectBaseBrowser._newProject" ID="ProjectBaseBrowser._newProject"></a> <h4>ProjectBaseBrowser._newProject</h4> <b>_newProject</b>(<i></i>) <p>
--- a/Documentation/Source/eric6.UI.Browser.html Sat Jul 02 14:54:14 2016 +0200 +++ b/Documentation/Source/eric6.UI.Browser.html Sat Jul 02 19:14:09 2016 +0200 @@ -148,6 +148,9 @@ <td><a href="#Browser._init">_init</a></td> <td>Protected method to perform initialization tasks common to this base class and all derived classes.</td> </tr><tr> +<td><a href="#Browser._keyboardSearchType">_keyboardSearchType</a></td> +<td>Protected method to check, if the item is of the correct type.</td> +</tr><tr> <td><a href="#Browser._openHexEditor">_openHexEditor</a></td> <td>Protected slot to handle the open in hex editor popup menu entry.</td> </tr><tr> @@ -184,6 +187,9 @@ <td><a href="#Browser.handleUnittest">handleUnittest</a></td> <td>Public slot to handle the unittest popup menu entry.</td> </tr><tr> +<td><a href="#Browser.keyboardSearch">keyboardSearch</a></td> +<td>Public function to search the tree via the keyboard.</td> +</tr><tr> <td><a href="#Browser.layoutDisplay">layoutDisplay</a></td> <td>Public slot to perform a layout operation.</td> </tr><tr> @@ -292,7 +298,27 @@ <p> Protected method to perform initialization tasks common to this base class and all derived classes. -</p><a NAME="Browser._openHexEditor" ID="Browser._openHexEditor"></a> +</p><a NAME="Browser._keyboardSearchType" ID="Browser._keyboardSearchType"></a> +<h4>Browser._keyboardSearchType</h4> +<b>_keyboardSearchType</b>(<i>item</i>) +<p> + Protected method to check, if the item is of the correct type. +</p><dl> +<dt><i>item</i> (BrowserItem)</dt> +<dd> +reference to the item +</dd> +</dl><dl> +<dt>Returns:</dt> +<dd> +flag indicating a correct type +</dd> +</dl><dl> +<dt>Return Type:</dt> +<dd> +bool +</dd> +</dl><a NAME="Browser._openHexEditor" ID="Browser._openHexEditor"></a> <h4>Browser._openHexEditor</h4> <b>_openHexEditor</b>(<i></i>) <p> @@ -402,7 +428,17 @@ <b>handleUnittest</b>(<i></i>) <p> Public slot to handle the unittest popup menu entry. -</p><a NAME="Browser.layoutDisplay" ID="Browser.layoutDisplay"></a> +</p><a NAME="Browser.keyboardSearch" ID="Browser.keyboardSearch"></a> +<h4>Browser.keyboardSearch</h4> +<b>keyboardSearch</b>(<i>search</i>) +<p> + Public function to search the tree via the keyboard. +</p><dl> +<dt><i>search</i> (str)</dt> +<dd> +the character entered via the keyboard +</dd> +</dl><a NAME="Browser.layoutDisplay" ID="Browser.layoutDisplay"></a> <h4>Browser.layoutDisplay</h4> <b>layoutDisplay</b>(<i></i>) <p>
--- a/Documentation/Source/eric6.WebBrowser.Tools.WebHitTestResult.html Sat Jul 02 14:54:14 2016 +0200 +++ b/Documentation/Source/eric6.WebBrowser.Tools.WebHitTestResult.html Sat Jul 02 19:14:09 2016 +0200 @@ -66,6 +66,9 @@ <td><a href="#WebHitTestResult.alternateText">alternateText</a></td> <td>Public method to get the alternate text.</td> </tr><tr> +<td><a href="#WebHitTestResult.baseUrl">baseUrl</a></td> +<td>Public method to get the base URL of the page.</td> +</tr><tr> <td><a href="#WebHitTestResult.boundingRect">boundingRect</a></td> <td>Public method to get the bounding rectangle.</td> </tr><tr> @@ -151,6 +154,21 @@ <dd> str </dd> +</dl><a NAME="WebHitTestResult.baseUrl" ID="WebHitTestResult.baseUrl"></a> +<h4>WebHitTestResult.baseUrl</h4> +<b>baseUrl</b>(<i></i>) +<p> + Public method to get the base URL of the page. +</p><dl> +<dt>Returns:</dt> +<dd> +base URL +</dd> +</dl><dl> +<dt>Return Type:</dt> +<dd> +QUrl +</dd> </dl><a NAME="WebHitTestResult.boundingRect" ID="WebHitTestResult.boundingRect"></a> <h4>WebHitTestResult.boundingRect</h4> <b>boundingRect</b>(<i></i>)
--- a/Preferences/ConfigurationPages/ApplicationPage.py Sat Jul 02 14:54:14 2016 +0200 +++ b/Preferences/ConfigurationPages/ApplicationPage.py Sat Jul 02 19:14:09 2016 +0200 @@ -63,6 +63,9 @@ self.errorlogCheckBox.setChecked( Preferences.getUI("CheckErrorLog")) + self.intervalSpinBox.setValue( + Preferences.getUI("KeyboardInputInterval")) + def save(self): """ Public slot to save the Application configuration. @@ -105,6 +108,10 @@ Preferences.setUI( "CheckErrorLog", self.errorlogCheckBox.isChecked()) + + Preferences.setUI( + "KeyboardInputInterval", + self.intervalSpinBox.value()) def create(dlg):
--- a/Preferences/ConfigurationPages/ApplicationPage.ui Sat Jul 02 14:54:14 2016 +0200 +++ b/Preferences/ConfigurationPages/ApplicationPage.ui Sat Jul 02 19:14:09 2016 +0200 @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>589</width> - <height>563</height> + <width>591</width> + <height>642</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout_3"> @@ -208,6 +208,57 @@ </widget> </item> <item> + <widget class="QGroupBox" name="groupBox_5"> + <property name="title"> + <string>Keyboard Input Interval</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0" colspan="2"> + <widget class="QLabel" name="label"> + <property name="text"> + <string><b>Note</b>: Enter a value of 0 to use the system default value.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QSpinBox" name="intervalSpinBox"> + <property name="toolTip"> + <string>Enter the keyboard input interval, '0' for default</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix"> + <string> ms</string> + </property> + <property name="maximum"> + <number>2000</number> + </property> + <property name="singleStep"> + <number>100</number> + </property> + </widget> + </item> + <item row="1" column="1"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>453</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> <spacer> <property name="orientation"> <enum>Qt::Vertical</enum>
--- a/Preferences/__init__.py Sat Jul 02 14:54:14 2016 +0200 +++ b/Preferences/__init__.py Sat Jul 02 19:14:09 2016 +0200 @@ -125,6 +125,7 @@ # defaults for the UI settings uiDefaults = { + "KeyboardInputInterval": 0, # 0 = use system default "Language": "System", "Style": "System", "StyleSheet": "", @@ -1804,7 +1805,7 @@ "ProxyPort/Http", "ProxyPort/Https", "ProxyPort/Ftp", "ProxyType/Ftp", "OpenOnStartup", "PerformVersionCheck", "RecentNumber", "NotificationTimeout", - "SidebarDelay"]: + "SidebarDelay", "KeyboardInputInterval"]: return int(prefClass.settings.value( "UI/" + key, prefClass.uiDefaults[key])) elif key in ["ProxyPassword/Http", "ProxyPassword/Https",
--- a/Project/ProjectBaseBrowser.py Sat Jul 02 14:54:14 2016 +0200 +++ b/Project/ProjectBaseBrowser.py Sat Jul 02 19:14:09 2016 +0200 @@ -12,7 +12,7 @@ import os from PyQt5.QtCore import QModelIndex, pyqtSignal, Qt, QCoreApplication, \ - QItemSelectionModel, QItemSelection + QItemSelectionModel, QItemSelection, QElapsedTimer from PyQt5.QtGui import QCursor from PyQt5.QtWidgets import QTreeView, QApplication, QMenu, QDialog, \ QAbstractItemView @@ -21,6 +21,7 @@ from E5Gui import E5MessageBox from UI.Browser import Browser +from UI.BrowserModel import BrowserDirectoryItem, BrowserFileItem from .ProjectBrowserModel import ProjectBrowserSimpleDirectoryItem, \ ProjectBrowserDirectoryItem, ProjectBrowserFileItem @@ -81,6 +82,10 @@ self._init() # perform common initialization tasks + self._keyboardSearchString = "" + self._keyboardSearchTimer = QElapsedTimer() + self._keyboardSearchTimer.invalidate() + self._initHookMethods() # perform initialization of the hooks self.hooksMenuEntries = {} @@ -680,6 +685,20 @@ itm = self.model().item(self.currentIndex()) return itm + def _keyboardSearchType(self, item): + """ + Protected method to check, if the item is of the correct type. + + @param item reference to the item + @type BrowserItem + @return flag indicating a correct type + @rtype bool + """ + return isinstance( + item, (BrowserDirectoryItem, BrowserFileItem, + ProjectBrowserSimpleDirectoryItem, + ProjectBrowserDirectoryItem, ProjectBrowserFileItem)) + ########################################################################### ## Support for hooks below ###########################################################################
--- a/UI/Browser.py Sat Jul 02 14:54:14 2016 +0200 +++ b/UI/Browser.py Sat Jul 02 19:14:09 2016 +0200 @@ -12,7 +12,7 @@ import os from PyQt5.QtCore import QModelIndex, pyqtSignal, QUrl, Qt, qVersion, \ - QCoreApplication, QItemSelectionModel + QCoreApplication, QItemSelectionModel, QElapsedTimer from PyQt5.QtGui import QDesktopServices from PyQt5.QtWidgets import QTreeView, QApplication, QMenu, QAbstractItemView @@ -141,6 +141,10 @@ self._init() # perform common initialization tasks + self._keyboardSearchString = "" + self._keyboardSearchTimer = QElapsedTimer() + self._keyboardSearchTimer.invalidate() + def _init(self): """ Protected method to perform initialization tasks common to this @@ -729,3 +733,57 @@ elif self.__embeddedBrowser == 2: e5App().getObject("UserInterface")\ .showPreferences("projectBrowserPage") + + def keyboardSearch(self, search): + """ + Public function to search the tree via the keyboard. + + @param search the character entered via the keyboard + @type str + """ + if self.model().rowCount() == 0: + return + + if self.currentIndex().isValid(): + startIndex = self.currentIndex() + else: + startIndex = self.model().index(0, 0) + + keyboardSearchTimeWasValid = self._keyboardSearchTimer.isValid() + keyboardSearchTimeElapsed = self._keyboardSearchTimer.restart() + if not search or not keyboardSearchTimeWasValid or \ + keyboardSearchTimeElapsed > \ + QApplication.keyboardInputInterval(): + self._keyboardSearchString = search.lower() + else: + self._keyboardSearchString += search.lower() + + index = startIndex + found = False + while True: + name = self.model().data(index) + if name.lower().startswith(self._keyboardSearchString) and \ + self._keyboardSearchType(self.model().item(index)): + found = True + break + + index = self.indexBelow(index) + if not index.isValid(): + index = self.model().index(0, 0) + if index == startIndex: + break + + if found: + self.setCurrentIndex(index) + + def _keyboardSearchType(self, item): + """ + Protected method to check, if the item is of the correct type. + + @param item reference to the item + @type BrowserItem + @return flag indicating a correct type + @rtype bool + """ + return isinstance( + item, (BrowserDirectoryItem, BrowserFileItem, BrowserSysPathItem))
--- a/UI/UserInterface.py Sat Jul 02 14:54:14 2016 +0200 +++ b/UI/UserInterface.py Sat Jul 02 19:14:09 2016 +0200 @@ -611,6 +611,11 @@ self.__lastConfigurationPageName = "" self.__expandedConfigurationEntries = [] + # set the keyboard input interval + interval = Preferences.getUI("KeyboardInputInterval") + if interval > 0: + QApplication.setKeyboardInputInterval(interval) + def __createLayout(self, debugServer): """ Private method to create the layout of the various windows. @@ -5446,6 +5451,13 @@ for hexEditor in HexEditMainWindow.windows: hexEditor.preferencesChanged() + # set the keyboard input interval + interval = Preferences.getUI("KeyboardInputInterval") + if interval > 0: + QApplication.setKeyboardInputInterval(interval) + else: + QApplication.setKeyboardInputInterval(-1) + self.preferencesChanged.emit() def __masterPasswordChanged(self, oldPassword, newPassword):
--- a/changelog Sat Jul 02 14:54:14 2016 +0200 +++ b/changelog Sat Jul 02 19:14:09 2016 +0200 @@ -18,6 +18,9 @@ - Project -- added a dialog to quickly search for files in the list of project files (thanks to Mike C. Fletcher for contributing the majority of this) +- Project Browser + -- added capability to search the file tree via the keyboard (directories and + files only) - Tools -- Tray Starter --- added an entry to show the version information