| 
									
										
										
										
											2013-05-15 13:17:33 +02:00
										 |  |  | ############################################################################# | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). | 
					
						
							|  |  |  | ## Contact: http://www.qt-project.org/legal | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## This file is part of Qt Creator. | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## Commercial License Usage | 
					
						
							|  |  |  | ## Licensees holding valid commercial Qt licenses may use this file in | 
					
						
							|  |  |  | ## accordance with the commercial license agreement provided with the | 
					
						
							|  |  |  | ## Software or, alternatively, in accordance with the terms contained in | 
					
						
							|  |  |  | ## a written agreement between you and Digia.  For licensing terms and | 
					
						
							|  |  |  | ## conditions see http://qt.digia.com/licensing.  For further information | 
					
						
							|  |  |  | ## use the contact form at http://qt.digia.com/contact-us. | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## GNU Lesser General Public License Usage | 
					
						
							|  |  |  | ## Alternatively, this file may be used under the terms of the GNU Lesser | 
					
						
							|  |  |  | ## General Public License version 2.1 as published by the Free Software | 
					
						
							|  |  |  | ## Foundation and appearing in the file LICENSE.LGPL included in the | 
					
						
							|  |  |  | ## packaging of this file.  Please review the following information to | 
					
						
							|  |  |  | ## ensure the GNU Lesser General Public License version 2.1 requirements | 
					
						
							|  |  |  | ## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## In addition, as a special exception, Digia gives you certain additional | 
					
						
							|  |  |  | ## rights.  These rights are described in the Digia Qt LGPL Exception | 
					
						
							|  |  |  | ## version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ############################################################################# | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-21 17:29:18 +02:00
										 |  |  | import re; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # places the cursor inside the given editor into the given line | 
					
						
							|  |  |  | # (leading and trailing whitespaces are ignored!) | 
					
						
							|  |  |  | # and goes to the end of the line | 
					
						
							|  |  |  | # line can be a regex - but if so, remember to set isRegex to True | 
					
						
							|  |  |  | # the function returns True if this went fine, False on error | 
					
						
							| 
									
										
										
										
											2012-05-23 15:36:30 +02:00
										 |  |  | def placeCursorToLine(editor, line, isRegex=False): | 
					
						
							| 
									
										
										
										
											2012-10-01 12:16:56 +02:00
										 |  |  |     def getEditor(): | 
					
						
							|  |  |  |         return waitForObject(editor) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     isDarwin = platform.system() == 'Darwin' | 
					
						
							|  |  |  |     if not isinstance(editor, (str, unicode)): | 
					
						
							|  |  |  |         editor = objectMap.realName(editor) | 
					
						
							| 
									
										
										
										
											2011-09-21 17:29:18 +02:00
										 |  |  |     oldPosition = 0 | 
					
						
							| 
									
										
										
										
											2012-10-01 12:16:56 +02:00
										 |  |  |     if isDarwin: | 
					
						
							|  |  |  |         type(getEditor(), "<Home>") | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         type(getEditor(), "<Ctrl+Home>") | 
					
						
							| 
									
										
										
										
											2011-09-21 17:29:18 +02:00
										 |  |  |     found = False | 
					
						
							|  |  |  |     if isRegex: | 
					
						
							|  |  |  |         regex = re.compile(line) | 
					
						
							|  |  |  |     while not found: | 
					
						
							| 
									
										
										
										
											2012-10-01 12:16:56 +02:00
										 |  |  |         currentLine = str(lineUnderCursor(getEditor())).strip() | 
					
						
							| 
									
										
										
										
											2012-05-23 15:36:30 +02:00
										 |  |  |         found = isRegex and regex.match(currentLine) or not isRegex and currentLine == line | 
					
						
							|  |  |  |         if not found: | 
					
						
							| 
									
										
										
										
											2012-10-01 12:16:56 +02:00
										 |  |  |             type(getEditor(), "<Down>") | 
					
						
							|  |  |  |             newPosition = getEditor().textCursor().position() | 
					
						
							| 
									
										
										
										
											2012-05-23 15:36:30 +02:00
										 |  |  |             if oldPosition == newPosition: | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |             oldPosition = newPosition | 
					
						
							| 
									
										
										
										
											2011-09-21 17:29:18 +02:00
										 |  |  |     if not found: | 
					
						
							|  |  |  |         test.fatal("Couldn't find line matching\n\n%s\n\nLeaving test..." % line) | 
					
						
							|  |  |  |         return False | 
					
						
							| 
									
										
										
										
											2012-10-01 12:16:56 +02:00
										 |  |  |     if isDarwin: | 
					
						
							|  |  |  |         type(getEditor(), "<Ctrl+Right>") | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         type(getEditor(), "<End>") | 
					
						
							| 
									
										
										
										
											2011-09-21 17:29:18 +02:00
										 |  |  |     return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-24 17:47:12 +01:00
										 |  |  | # this function returns True if a QMenu is | 
					
						
							|  |  |  | # popped up above the given editor | 
					
						
							|  |  |  | # param editor is the editor where the menu should appear | 
					
						
							|  |  |  | # param menuInList is a list containing one item. This item will be assigned the menu if there is one. | 
					
						
							|  |  |  | #                  THIS IS A HACK to get a pass-by-reference | 
					
						
							|  |  |  | def menuVisibleAtEditor(editor, menuInList): | 
					
						
							|  |  |  |     menuInList[0] = None | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											2013-02-11 17:29:08 +01:00
										 |  |  |         menu = waitForObject("{type='QMenu' unnamed='1' visible='1'}", 500) | 
					
						
							| 
									
										
										
										
											2013-05-03 10:31:00 +02:00
										 |  |  |         if platform.system() == 'Darwin': | 
					
						
							|  |  |  |             menu.activateWindow() | 
					
						
							| 
									
										
										
										
											2012-01-24 17:47:12 +01:00
										 |  |  |         success = menu.visible and widgetContainsPoint(editor, menu.mapToGlobal(QPoint(0, 0))) | 
					
						
							|  |  |  |         if success: | 
					
						
							|  |  |  |             menuInList[0] = menu | 
					
						
							|  |  |  |         return success | 
					
						
							|  |  |  |     except: | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # this function checks whether the given global point (QPoint) | 
					
						
							|  |  |  | # is contained in the given widget | 
					
						
							|  |  |  | def widgetContainsPoint(widget, point): | 
					
						
							|  |  |  |     return QRect(widget.mapToGlobal(QPoint(0, 0)), widget.size).contains(point) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-21 17:29:18 +02:00
										 |  |  | # this function simply opens the context menu inside the given editor | 
					
						
							|  |  |  | # at the same position where the text cursor is located at | 
					
						
							|  |  |  | def openContextMenuOnTextCursorPosition(editor): | 
					
						
							|  |  |  |     rect = editor.cursorRect(editor.textCursor()) | 
					
						
							| 
									
										
										
										
											2013-02-11 17:29:08 +01:00
										 |  |  |     if platform.system() == 'Darwin': | 
					
						
							| 
									
										
										
										
											2013-04-22 14:37:05 +02:00
										 |  |  |         JIRA.performWorkaroundForBug(8735, JIRA.Bug.CREATOR, editor) | 
					
						
							| 
									
										
										
										
											2011-09-21 17:29:18 +02:00
										 |  |  |     openContextMenu(editor, rect.x+rect.width/2, rect.y+rect.height/2, 0) | 
					
						
							| 
									
										
										
										
											2012-01-24 17:47:12 +01:00
										 |  |  |     menuInList = [None] | 
					
						
							|  |  |  |     waitFor("menuVisibleAtEditor(editor, menuInList)", 5000) | 
					
						
							|  |  |  |     return menuInList[0] | 
					
						
							| 
									
										
										
										
											2011-09-21 17:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-18 16:28:27 +01:00
										 |  |  | # this function marks/selects the text inside the given editor from current cursor position | 
					
						
							|  |  |  | # param direction is one of "Left", "Right", "Up", "Down", but "End" and combinations work as well | 
					
						
							|  |  |  | # param typeCount defines how often the cursor will be moved in the given direction (while marking) | 
					
						
							|  |  |  | def markText(editor, direction, typeCount=1): | 
					
						
							|  |  |  |     for i in range(typeCount): | 
					
						
							|  |  |  |         type(editor, "<Shift+%s>" % direction) | 
					
						
							| 
									
										
										
										
											2011-09-21 17:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-26 15:24:49 +02:00
										 |  |  | # works for all standard editors | 
					
						
							|  |  |  | def replaceEditorContent(editor, newcontent): | 
					
						
							|  |  |  |     type(editor, "<Ctrl+A>") | 
					
						
							|  |  |  |     type(editor, "<Delete>") | 
					
						
							|  |  |  |     type(editor, newcontent) | 
					
						
							| 
									
										
										
										
											2011-12-08 11:52:38 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | def typeLines(editor, lines): | 
					
						
							|  |  |  |     if isinstance(lines, (str, unicode)): | 
					
						
							|  |  |  |         lines = [lines] | 
					
						
							|  |  |  |     if isinstance(lines, (list, tuple)): | 
					
						
							|  |  |  |         for line in lines: | 
					
						
							|  |  |  |             type(editor, line) | 
					
						
							| 
									
										
										
										
											2012-10-22 17:19:33 +02:00
										 |  |  |             type(editor, "<Return>") | 
					
						
							| 
									
										
										
										
											2011-12-08 11:52:38 +01:00
										 |  |  |     else: | 
					
						
							|  |  |  |         test.warning("Illegal parameter passed to typeLines()") | 
					
						
							| 
									
										
										
										
											2011-12-19 11:18:24 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | # function to verify hoverings on e.g. code inside of the given editor | 
					
						
							|  |  |  | # param editor the editor object | 
					
						
							|  |  |  | # param lines a list/tuple of regex that indicates which lines should be verified | 
					
						
							|  |  |  | # param additionalKeyPresses an array holding the additional typings to do (special chars for cursor movement) | 
					
						
							|  |  |  | #       to get to the location (inside line) where to trigger the hovering (must be the same for all lines) | 
					
						
							|  |  |  | # param expectedTypes list/tuple holding the type of the (tool)tips that should occur (for each line) | 
					
						
							|  |  |  | # param expectedValues list/tuple of dict or list/tuple of strings regarding the types that have been used | 
					
						
							|  |  |  | #       if it's a dict it indicates a property value pair, if it's a string it is type specific (e.g. color value for ColorTip) | 
					
						
							|  |  |  | # param alternativeValues same as expectedValues, but here you can submit alternatives - this is for example | 
					
						
							|  |  |  | #       necessary if you do not add the correct documentation (from where the tip gets its content) | 
					
						
							|  |  |  | def verifyHoveringOnEditor(editor, lines, additionalKeyPresses, expectedTypes, expectedValues, alternativeValues=None): | 
					
						
							|  |  |  |     counter = 0 | 
					
						
							|  |  |  |     for line in lines: | 
					
						
							|  |  |  |         expectedVals = expectedValues[counter] | 
					
						
							|  |  |  |         expectedType = expectedTypes[counter] | 
					
						
							|  |  |  |         altVal = None | 
					
						
							|  |  |  |         if isinstance(alternativeValues, (list, tuple)): | 
					
						
							|  |  |  |             altVal = alternativeValues[counter] | 
					
						
							|  |  |  |         counter += 1 | 
					
						
							|  |  |  |         placeCursorToLine(editor, line, True) | 
					
						
							|  |  |  |         for ty in additionalKeyPresses: | 
					
						
							|  |  |  |             type(editor, ty) | 
					
						
							|  |  |  |         rect = editor.cursorRect(editor.textCursor()) | 
					
						
							|  |  |  |         sendEvent("QMouseEvent", editor, QEvent.MouseMove, rect.x+rect.width/2, rect.y+rect.height/2, Qt.NoButton, 0) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             tip = waitForObject("{type='%s' visible='1'}" % expectedType) | 
					
						
							|  |  |  |         except: | 
					
						
							|  |  |  |             tip = None | 
					
						
							|  |  |  |         if tip == None: | 
					
						
							|  |  |  |             test.warning("Could not get %s for line containing pattern '%s'" % (expectedType,line)) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             if expectedType == "ColorTip": | 
					
						
							|  |  |  |                 __handleColorTips__(tip, expectedVals) | 
					
						
							|  |  |  |             elif expectedType == "TextTip": | 
					
						
							|  |  |  |                 __handleTextTips__(tip, expectedVals, altVal) | 
					
						
							|  |  |  |             elif expectedType == "WidgetTip": | 
					
						
							|  |  |  |                 test.warning("Sorry - WidgetTip checks aren't implemented yet.") | 
					
						
							| 
									
										
										
										
											2012-02-21 14:36:25 +01:00
										 |  |  |             sendEvent("QMouseEvent", editor, QEvent.MouseMove, 0, -50, Qt.NoButton, 0) | 
					
						
							|  |  |  |             waitFor("isNull(tip)", 10000) | 
					
						
							| 
									
										
										
										
											2011-12-19 11:18:24 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | # helper function that handles verification of TextTip hoverings | 
					
						
							|  |  |  | # param textTip the TextTip object | 
					
						
							|  |  |  | # param expectedVals a dict holding property value pairs that must match | 
					
						
							|  |  |  | def __handleTextTips__(textTip, expectedVals, alternativeVals): | 
					
						
							|  |  |  |     props = object.properties(textTip) | 
					
						
							|  |  |  |     expFail = altFail = False | 
					
						
							|  |  |  |     eResult = verifyProperties(props, expectedVals) | 
					
						
							|  |  |  |     for val in eResult.itervalues(): | 
					
						
							|  |  |  |         if not val: | 
					
						
							|  |  |  |             expFail = True | 
					
						
							|  |  |  |             break | 
					
						
							|  |  |  |     if expFail and alternativeVals != None: | 
					
						
							|  |  |  |         aResult = verifyProperties(props, alternativeVals) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         altFail = True | 
					
						
							|  |  |  |         aResult = None | 
					
						
							|  |  |  |     if not expFail: | 
					
						
							|  |  |  |         test.passes("TextTip verified") | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         for key,val in eResult.iteritems(): | 
					
						
							|  |  |  |             if val == False: | 
					
						
							|  |  |  |                 if aResult and aResult.get(key): | 
					
						
							|  |  |  |                     test.passes("Property '%s' does not match expected, but alternative value" % key) | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     aVal = None | 
					
						
							|  |  |  |                     if alternativeVals: | 
					
						
							|  |  |  |                         aVal = alternativeVals.get(key, None) | 
					
						
							|  |  |  |                     if aVal: | 
					
						
							|  |  |  |                         test.fail("Property '%s' does not match - expected '%s' or '%s', got '%s'" % (key, expectedVals.get(key), aVal, props.get(key))) | 
					
						
							|  |  |  |                     else: | 
					
						
							|  |  |  |                         test.fail("Property '%s' does not match - expected '%s', got '%s" % (key, expectedVals.get(key), props.get(key))) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 test.fail("Property '%s' could not be found inside properties" % key) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # helper function that handles verification of ColorTip hoverings | 
					
						
							|  |  |  | # param colTip the ColorTip object | 
					
						
							|  |  |  | # param expectedColor a single string holding the color the ColorTip should have | 
					
						
							|  |  |  | # Attention: because of being a non-standard Qt object it's not possible to | 
					
						
							|  |  |  | # verify colors which are (semi-)transparent! | 
					
						
							|  |  |  | def __handleColorTips__(colTip, expectedColor): | 
					
						
							|  |  |  |     cmp = QColor() | 
					
						
							|  |  |  |     cmp.setNamedColor(expectedColor) | 
					
						
							|  |  |  |     if cmp.alpha() != 255: | 
					
						
							|  |  |  |         test.warning("Cannot handle transparent colors - cancelling this verification") | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     dPM = QPixmap.grabWidget(colTip, 1, 1, colTip.width-2, colTip.height-2) | 
					
						
							|  |  |  |     img = dPM.toImage() | 
					
						
							|  |  |  |     rgb = img.pixel(1, 1) | 
					
						
							|  |  |  |     rgb = QColor(rgb) | 
					
						
							|  |  |  |     if rgb.rgba() == cmp.rgba(): | 
					
						
							|  |  |  |         test.passes("ColorTip verified") | 
					
						
							|  |  |  |     else: | 
					
						
							| 
									
										
										
										
											2013-09-02 17:30:24 +02:00
										 |  |  |         test.fail("ColorTip does not match - expected color '%s' got '%s'" % (cmp.rgb(), rgb.rgb())) | 
					
						
							| 
									
										
										
										
											2011-12-19 11:18:24 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | # function that checks whether all expected properties (including their values) | 
					
						
							|  |  |  | # match the given properties | 
					
						
							|  |  |  | # param properties a dict holding the properties to check | 
					
						
							|  |  |  | # param expectedProps a dict holding the key value pairs that must be found inside properties | 
					
						
							|  |  |  | # this function returns a dict holding the keys of the expectedProps - the value of each key | 
					
						
							|  |  |  | # is a boolean that indicates whether this key could have been found inside properties and | 
					
						
							|  |  |  | # the values matched or None if the key could not be found | 
					
						
							|  |  |  | def verifyProperties(properties, expectedProps): | 
					
						
							|  |  |  |     if not isinstance(properties, dict) or not isinstance(expectedProps, dict): | 
					
						
							|  |  |  |         test.warning("Wrong usage - both parameter must be of type dict") | 
					
						
							|  |  |  |         return {} | 
					
						
							|  |  |  |     result = {} | 
					
						
							|  |  |  |     for key,val in expectedProps.iteritems(): | 
					
						
							|  |  |  |         foundVal = properties.get(key, None) | 
					
						
							|  |  |  |         if foundVal != None: | 
					
						
							|  |  |  |             result[key] = val == foundVal | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             result[key] = None | 
					
						
							|  |  |  |     return result | 
					
						
							| 
									
										
										
										
											2012-03-30 13:05:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | def getEditorForFileSuffix(curFile): | 
					
						
							|  |  |  |     cppEditorSuffixes = ["cpp", "cc", "CC", "h", "H", "cp", "cxx", "C", "c++", "inl", "moc", "qdoc", | 
					
						
							|  |  |  |                          "tcc", "tpp", "t++", "c", "cu", "m", "mm", "hh", "hxx", "h++", "hpp", "hp"] | 
					
						
							|  |  |  |     qmlEditorSuffixes = ["qml", "qmlproject", "js", "qs", "qtt"] | 
					
						
							|  |  |  |     proEditorSuffixes = ["pro", "pri", "prf"] | 
					
						
							| 
									
										
										
										
											2012-06-18 19:52:38 +02:00
										 |  |  |     glslEditorSuffixes= ["frag", "vert", "fsh", "vsh", "glsl", "shader", "gsh"] | 
					
						
							| 
									
										
										
										
											2013-07-11 15:20:40 +02:00
										 |  |  |     pytEditorSuffixes = ["py", "pyw", "wsgi"] | 
					
						
							| 
									
										
										
										
											2012-03-30 13:05:29 +02:00
										 |  |  |     suffix = __getFileSuffix__(curFile) | 
					
						
							|  |  |  |     if suffix in cppEditorSuffixes: | 
					
						
							| 
									
										
										
										
											2012-10-19 17:36:14 +02:00
										 |  |  |         editor = waitForObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget") | 
					
						
							| 
									
										
										
										
											2012-03-30 13:05:29 +02:00
										 |  |  |     elif suffix in qmlEditorSuffixes: | 
					
						
							| 
									
										
										
										
											2012-09-05 16:49:35 +02:00
										 |  |  |         editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget") | 
					
						
							| 
									
										
										
										
											2012-03-30 13:05:29 +02:00
										 |  |  |     elif suffix in proEditorSuffixes: | 
					
						
							| 
									
										
										
										
											2012-10-19 17:36:14 +02:00
										 |  |  |         editor = waitForObject(":Qt Creator_ProFileEditorWidget") | 
					
						
							| 
									
										
										
										
											2012-06-13 18:09:13 +02:00
										 |  |  |     elif suffix in glslEditorSuffixes: | 
					
						
							|  |  |  |         editor = waitForObject("{type='GLSLEditor::GLSLTextEditorWidget' unnamed='1' " | 
					
						
							|  |  |  |                                "visible='1' window=':Qt Creator_Core::Internal::MainWindow'}") | 
					
						
							| 
									
										
										
										
											2013-07-11 15:20:40 +02:00
										 |  |  |     elif suffix in pytEditorSuffixes: | 
					
						
							|  |  |  |         editor = waitForObject(":Qt Creator_PythonEditor::EditorWidget") | 
					
						
							| 
									
										
										
										
											2012-03-30 13:05:29 +02:00
										 |  |  |     else: | 
					
						
							|  |  |  |         test.log("Trying PlainTextEditor (file suffix: %s)" % suffix) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             editor = waitForObject("{type='TextEditor::PlainTextEditorWidget' unnamed='1' " | 
					
						
							|  |  |  |                                    "visible='1' window=':Qt Creator_Core::Internal::MainWindow'}", 3000) | 
					
						
							|  |  |  |         except: | 
					
						
							|  |  |  |             test.fatal("Unsupported file suffix for file '%s'" % curFile) | 
					
						
							|  |  |  |             editor = None | 
					
						
							|  |  |  |     return editor | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # helper that determines the file suffix of the given fileName | 
					
						
							|  |  |  | # (doesn't matter if fileName contains the path as well) | 
					
						
							|  |  |  | def __getFileSuffix__(fileName): | 
					
						
							|  |  |  |     suffix = os.path.basename(fileName).rsplit(".", 1) | 
					
						
							|  |  |  |     if len(suffix) == 1: | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         return suffix[1] | 
					
						
							| 
									
										
										
										
											2012-04-23 13:17:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | def maskSpecialCharsForSearchResult(filename): | 
					
						
							|  |  |  |     filename = filename.replace("_", "\\_").replace(".","\\.") | 
					
						
							|  |  |  |     return filename | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def validateSearchResult(expectedCount): | 
					
						
							|  |  |  |     searchResult = waitForObject(":Qt Creator_SearchResult_Core::Internal::OutputPaneToggleButton") | 
					
						
							|  |  |  |     ensureChecked(searchResult) | 
					
						
							|  |  |  |     resultTreeView = waitForObject("{type='Find::Internal::SearchResultTreeView' unnamed='1' " | 
					
						
							|  |  |  |                                    "visible='1' window=':Qt Creator_Core::Internal::MainWindow'}") | 
					
						
							|  |  |  |     counterLabel = waitForObject("{type='QLabel' unnamed='1' visible='1' text?='*matches found.' " | 
					
						
							|  |  |  |                                  "window=':Qt Creator_Core::Internal::MainWindow'}") | 
					
						
							|  |  |  |     matches = cast((str(counterLabel.text)).split(" ", 1)[0], "int") | 
					
						
							|  |  |  |     test.compare(matches, expectedCount, "Verified match count.") | 
					
						
							|  |  |  |     model = resultTreeView.model() | 
					
						
							| 
									
										
										
										
											2012-10-25 12:59:03 +02:00
										 |  |  |     for index in dumpIndices(model): | 
					
						
							| 
									
										
										
										
											2012-04-23 13:17:40 +02:00
										 |  |  |         itemText = str(model.data(index).toString()) | 
					
						
							|  |  |  |         doubleClickItem(resultTreeView, maskSpecialCharsForSearchResult(itemText), 5, 5, 0, Qt.LeftButton) | 
					
						
							|  |  |  |         test.log("%d occurrences in %s" % (model.rowCount(index), itemText)) | 
					
						
							| 
									
										
										
										
											2012-10-25 12:59:03 +02:00
										 |  |  |         for chIndex in dumpIndices(model, index): | 
					
						
							| 
									
										
										
										
											2012-04-23 13:17:40 +02:00
										 |  |  |             resultTreeView.scrollTo(chIndex) | 
					
						
							| 
									
										
										
										
											2012-10-17 17:23:07 +02:00
										 |  |  |             text = str(chIndex.data()).rstrip('\r') | 
					
						
							| 
									
										
										
										
											2012-04-23 13:17:40 +02:00
										 |  |  |             rect = resultTreeView.visualRect(chIndex) | 
					
						
							|  |  |  |             doubleClick(resultTreeView, rect.x+5, rect.y+5, 0, Qt.LeftButton) | 
					
						
							|  |  |  |             editor = getEditorForFileSuffix(itemText) | 
					
						
							|  |  |  |             waitFor("lineUnderCursor(editor) == text", 2000) | 
					
						
							|  |  |  |             test.compare(lineUnderCursor(editor), text) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # this function invokes context menu and command from it | 
					
						
							|  |  |  | def invokeContextMenuItem(editorArea, command1, command2 = None): | 
					
						
							|  |  |  |     ctxtMenu = openContextMenuOnTextCursorPosition(editorArea) | 
					
						
							| 
									
										
										
										
											2013-02-11 17:29:08 +01:00
										 |  |  |     activateItem(waitForObjectItem(objectMap.realName(ctxtMenu), command1, 2000)) | 
					
						
							| 
									
										
										
										
											2012-04-23 13:17:40 +02:00
										 |  |  |     if command2: | 
					
						
							| 
									
										
										
										
											2013-03-18 15:04:58 +01:00
										 |  |  |         activateItem(waitForObjectItem("{title='%s' type='QMenu' visible='1' window=%s}" | 
					
						
							|  |  |  |                                        % (command1, objectMap.realName(ctxtMenu)), command2, 2000)) | 
					
						
							| 
									
										
										
										
											2012-04-23 13:17:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | # this function invokes the "Find Usages" item from context menu | 
					
						
							|  |  |  | # param editor an editor object | 
					
						
							|  |  |  | # param line a line in editor (content of the line as a string) | 
					
						
							|  |  |  | # param typeOperation a key to type | 
					
						
							|  |  |  | # param n how often repeat the type operation? | 
					
						
							|  |  |  | def invokeFindUsage(editor, line, typeOperation, n=1): | 
					
						
							|  |  |  |     if not placeCursorToLine(editor, line, True): | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     for i in range(n): | 
					
						
							|  |  |  |         type(editor, typeOperation) | 
					
						
							|  |  |  |     invokeContextMenuItem(editor, "Find Usages") | 
					
						
							|  |  |  |     return True | 
					
						
							| 
									
										
										
										
											2012-10-09 15:00:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-30 18:15:38 +01:00
										 |  |  | def addBranchWildcardToRoot(rootNode): | 
					
						
							|  |  |  |     pos = rootNode.find(".") | 
					
						
							| 
									
										
										
										
											2013-01-31 17:08:05 +01:00
										 |  |  |     if pos == -1: | 
					
						
							|  |  |  |         return rootNode + " (*)" | 
					
						
							| 
									
										
										
										
											2013-01-30 18:15:38 +01:00
										 |  |  |     return rootNode[:pos] + " (*)" + rootNode[pos:] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-09 15:00:17 +02:00
										 |  |  | def openDocument(treeElement): | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											2012-10-30 12:05:27 +01:00
										 |  |  |         selectFromCombo(":Qt Creator_Core::Internal::NavComboBox", "Open Documents") | 
					
						
							| 
									
										
										
										
											2012-10-09 15:00:17 +02:00
										 |  |  |         navigator = waitForObject(":Qt Creator_Utils::NavigationTreeView") | 
					
						
							| 
									
										
										
										
											2013-01-30 18:15:38 +01:00
										 |  |  |         try: | 
					
						
							|  |  |  |             item = waitForObjectItem(navigator, treeElement, 3000) | 
					
						
							|  |  |  |         except: | 
					
						
							|  |  |  |             treeElement = addBranchWildcardToRoot(treeElement) | 
					
						
							|  |  |  |             item = waitForObjectItem(navigator, treeElement) | 
					
						
							| 
									
										
										
										
											2012-10-09 15:00:17 +02:00
										 |  |  |         doubleClickItem(navigator, treeElement, 5, 5, 0, Qt.LeftButton) | 
					
						
							|  |  |  |         mainWindow = waitForObject(":Qt Creator_Core::Internal::MainWindow") | 
					
						
							| 
									
										
										
										
											2013-01-30 18:15:38 +01:00
										 |  |  |         waitFor("item.text in str(mainWindow.windowTitle)") | 
					
						
							| 
									
										
										
										
											2012-10-09 15:00:17 +02:00
										 |  |  |         return True | 
					
						
							|  |  |  |     except: | 
					
						
							|  |  |  |         return False | 
					
						
							| 
									
										
										
										
											2013-03-28 16:58:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | def earlyExit(details="No additional information"): | 
					
						
							|  |  |  |     test.fail("Something went wrong running this test", details) | 
					
						
							|  |  |  |     invokeMenuItem("File", "Save All") | 
					
						
							|  |  |  |     invokeMenuItem("File", "Exit") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def openDocumentPlaceCursor(doc, line, additionalFunction=None): | 
					
						
							|  |  |  |     cppEditorStr = ":Qt Creator_CppEditor::Internal::CPPEditorWidget" | 
					
						
							|  |  |  |     if openDocument(doc) and placeCursorToLine(cppEditorStr, line): | 
					
						
							|  |  |  |         if additionalFunction: | 
					
						
							|  |  |  |             additionalFunction() | 
					
						
							|  |  |  |         return str(waitForObject(cppEditorStr).plainText) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         earlyExit("Open %s or placing cursor to line (%s) failed." % (doc, line)) | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Replaces a line in the editor with another | 
					
						
							|  |  |  | # param fileSpec a string specifying a file in Projects view | 
					
						
							|  |  |  | # param oldLine a string holding the line to be replaced | 
					
						
							|  |  |  | # param newLine a string holding the line to be inserted | 
					
						
							|  |  |  | def replaceLine(fileSpec, oldLine, newLine): | 
					
						
							|  |  |  |     if openDocumentPlaceCursor(fileSpec, oldLine) == None: | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     editor = waitForObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget") | 
					
						
							|  |  |  |     for i in range(len(oldLine)): | 
					
						
							|  |  |  |         type(editor, "<Backspace>") | 
					
						
							|  |  |  |     type(editor, newLine) | 
					
						
							|  |  |  |     return True |