1# -*- coding: utf-8 -*- 2 3# Copyright (c) 2004 - 2021 Detlev Offenbach <detlev@die-offenbachs.de> 4# 5 6""" 7Module implementing a dialog to enter the parameters for eric6_api. 8""" 9 10import sys 11import os 12import copy 13 14from PyQt5.QtCore import pyqtSlot, Qt 15from PyQt5.QtWidgets import QDialog, QDialogButtonBox 16 17from E5Gui.E5PathPicker import E5PathPickerModes 18 19from .Ui_EricapiConfigDialog import Ui_EricapiConfigDialog 20import Utilities 21import DocumentationTools 22 23from eric6config import getConfig 24 25 26class EricapiConfigDialog(QDialog, Ui_EricapiConfigDialog): 27 """ 28 Class implementing a dialog to enter the parameters for eric6_api. 29 """ 30 def __init__(self, project, parms=None, parent=None): 31 """ 32 Constructor 33 34 @param project reference to the project object (Project.Project) 35 @param parms parameters to set in the dialog 36 @param parent parent widget of this dialog 37 """ 38 super().__init__(parent) 39 self.setupUi(self) 40 41 self.outputFilePicker.setMode(E5PathPickerModes.SaveFileMode) 42 self.outputFilePicker.setDefaultDirectory(project.getProjectPath()) 43 self.outputFilePicker.setFilters(self.tr( 44 "API files (*.api);;All files (*)")) 45 46 self.ignoreDirPicker.setMode(E5PathPickerModes.DirectoryMode) 47 self.ignoreDirPicker.setDefaultDirectory(project.getProjectPath()) 48 49 self.buttonBox.button( 50 QDialogButtonBox.StandardButton.Ok).setEnabled(False) 51 for language in sorted( 52 DocumentationTools.supportedExtensionsDictForApis.keys()): 53 self.languagesList.addItem(language) 54 55 self.ppath = project.getProjectPath() 56 self.project = project 57 58 self.__initializeDefaults() 59 60 # get a copy of the defaults to store the user settings 61 self.parameters = copy.deepcopy(self.defaults) 62 63 # combine it with the values of parms 64 if parms is not None: 65 self.parameters.update(parms) 66 self.parameters['outputFile'] = Utilities.toNativeSeparators( 67 self.parameters['outputFile']) 68 69 self.recursionCheckBox.setChecked(self.parameters['useRecursion']) 70 self.includePrivateCheckBox.setChecked( 71 self.parameters['includePrivate']) 72 self.outputFilePicker.setText(self.parameters['outputFile']) 73 self.baseEdit.setText(self.parameters['basePackage']) 74 self.ignoreDirsList.clear() 75 for d in self.parameters['ignoreDirectories']: 76 self.ignoreDirsList.addItem(d) 77 self.sourceExtEdit.setText( 78 ", ".join(self.parameters['sourceExtensions'])) 79 self.excludeFilesEdit.setText( 80 ", ".join(self.parameters['ignoreFilePatterns'])) 81 for language in self.parameters['languages']: 82 if language == "Python": 83 # convert Python to the more specific Python3 84 language = "Python3" 85 items = self.languagesList.findItems( 86 language, Qt.MatchFlags(Qt.MatchFlag.MatchExactly)) 87 items and items[0].setSelected(True) 88 89 def __initializeDefaults(self): 90 """ 91 Private method to set the default values. 92 93 These are needed later on to generate the commandline 94 parameters. 95 """ 96 self.defaults = { 97 'useRecursion': False, 98 'includePrivate': False, 99 'outputFile': '', 100 'basePackage': '', 101 'ignoreDirectories': [], 102 'ignoreFilePatterns': [], 103 'sourceExtensions': [], 104 } 105 106 lang = self.project.getProjectLanguage() 107 if lang in DocumentationTools.supportedExtensionsDictForApis: 108 self.defaults['languages'] = [lang] 109 else: 110 self.defaults['languages'] = ["Python3"] 111 112 def generateParameters(self): 113 """ 114 Public method that generates the commandline parameters. 115 116 It generates a list of strings to be used 117 to set the QProcess arguments for the ericapi call and 118 a dictionary containing the non default parameters. This 119 dictionary can be passed back upon object generation to overwrite 120 the default settings. 121 122 @return a tuple of the commandline parameters and non default 123 parameters (list of strings, dictionary) 124 """ 125 parms = {} 126 args = [] 127 128 # 1. the program name 129 args.append(sys.executable) 130 args.append( 131 Utilities.normabsjoinpath(getConfig('ericDir'), "eric6_api.py")) 132 133 # 2. the commandline options 134 if self.parameters['outputFile'] != self.defaults['outputFile']: 135 parms['outputFile'] = Utilities.fromNativeSeparators( 136 self.project.getRelativePath(self.parameters['outputFile'])) 137 args.append('-o') 138 if os.path.isabs(self.parameters['outputFile']): 139 args.append(self.parameters['outputFile']) 140 else: 141 args.append( 142 os.path.join(self.ppath, self.parameters['outputFile'])) 143 else: 144 self.parameters['outputFile'] = self.defaults['outputFile'] 145 if self.parameters['basePackage'] != self.defaults['basePackage']: 146 parms['basePackage'] = self.parameters['basePackage'] 147 args.append('-b') 148 args.append(self.parameters['basePackage']) 149 if ( 150 self.parameters['ignoreDirectories'] != 151 self.defaults['ignoreDirectories'] 152 ): 153 parms['ignoreDirectories'] = ( 154 self.parameters['ignoreDirectories'][:] 155 ) 156 for d in self.parameters['ignoreDirectories']: 157 args.append('-x') 158 args.append(d) 159 if ( 160 self.parameters['ignoreFilePatterns'] != 161 self.defaults['ignoreFilePatterns'] 162 ): 163 parms['ignoreFilePatterns'] = ( 164 self.parameters['ignoreFilePatterns'][:] 165 ) 166 for pattern in self.parameters['ignoreFilePatterns']: 167 args.append("--exclude-file={0}".format(pattern)) 168 if self.parameters['useRecursion'] != self.defaults['useRecursion']: 169 parms['useRecursion'] = self.parameters['useRecursion'] 170 args.append('-r') 171 if ( 172 self.parameters['sourceExtensions'] != 173 self.defaults['sourceExtensions'] 174 ): 175 parms['sourceExtensions'] = self.parameters['sourceExtensions'][:] 176 for ext in self.parameters['sourceExtensions']: 177 args.append('-t') 178 args.append(ext) 179 if ( 180 self.parameters['includePrivate'] != 181 self.defaults['includePrivate'] 182 ): 183 parms['includePrivate'] = self.parameters['includePrivate'] 184 args.append('-p') 185 parms['languages'] = self.parameters['languages'][:] 186 for lang in self.parameters['languages']: 187 args.append('--language={0}'.format(lang)) 188 189 return (args, parms) 190 191 @pyqtSlot() 192 def on_outputFilePicker_aboutToShowPathPickerDialog(self): 193 """ 194 Private slot called before the file selection dialog is shown. 195 """ 196 startFile = self.outputFilePicker.text() 197 if not startFile: 198 self.outputFilePicker.setText( 199 self.project.getProjectName() + ".api") 200 201 @pyqtSlot(str) 202 def on_outputFilePicker_pathSelected(self, path): 203 """ 204 Private slot handling the selection of an output file. 205 206 @param path path of the output file 207 @type str 208 """ 209 # make it relative, if it is in a subdirectory of the project path 210 fn = self.project.getRelativePath(path) 211 self.outputFilePicker.setText(fn) 212 213 def on_outputFilePicker_textChanged(self, filename): 214 """ 215 Private slot to enable/disable the "OK" button. 216 217 @param filename name of the file (string) 218 """ 219 self.buttonBox.button( 220 QDialogButtonBox.StandardButton.Ok).setEnabled(filename != "") 221 222 @pyqtSlot(str) 223 def on_ignoreDirPicker_pathSelected(self, path): 224 """ 225 Private slot handling the selection of a directory to be ignored. 226 227 @param path path of the directory to be ignored 228 @type str 229 """ 230 # make it relative, if it is in a subdirectory of the project path 231 dn = self.project.getRelativePath(path) 232 while dn.endswith(os.sep): 233 dn = dn[:-1] 234 self.ignoreDirPicker.setText(dn) 235 236 @pyqtSlot() 237 def on_addButton_clicked(self): 238 """ 239 Private slot to add the directory displayed to the listview. 240 241 The directory in the ignore directories 242 line edit is moved to the listbox above and the edit is cleared. 243 """ 244 basename = os.path.basename(self.ignoreDirPicker.text()) 245 if basename: 246 self.ignoreDirsList.addItem(basename) 247 self.ignoreDirPicker.clear() 248 249 @pyqtSlot() 250 def on_deleteButton_clicked(self): 251 """ 252 Private slot to delete the currently selected directory of the listbox. 253 """ 254 itm = self.ignoreDirsList.takeItem(self.ignoreDirsList.currentRow()) 255 del itm 256 257 def accept(self): 258 """ 259 Public slot called by the Ok button. 260 261 It saves the values in the parameters dictionary. 262 """ 263 self.parameters['useRecursion'] = self.recursionCheckBox.isChecked() 264 self.parameters['includePrivate'] = ( 265 self.includePrivateCheckBox.isChecked() 266 ) 267 outfile = self.outputFilePicker.text() 268 if outfile != '': 269 outfile = os.path.normpath(outfile) 270 self.parameters['outputFile'] = outfile 271 self.parameters['basePackage'] = self.baseEdit.text() 272 self.parameters['ignoreDirectories'] = [] 273 for row in range(0, self.ignoreDirsList.count()): 274 itm = self.ignoreDirsList.item(row) 275 self.parameters['ignoreDirectories'].append( 276 os.path.normpath(itm.text())) 277 extensions = self.sourceExtEdit.text().split(',') 278 self.parameters['sourceExtensions'] = [ 279 ext.strip() for ext in extensions if len(ext) > 0 280 ] 281 patterns = self.excludeFilesEdit.text().split(',') 282 self.parameters['ignoreFilePatterns'] = [ 283 pattern.strip() for pattern in patterns 284 ] 285 self.parameters['languages'] = [] 286 for itm in self.languagesList.selectedItems(): 287 self.parameters['languages'].append(itm.text()) 288 289 # call the accept slot of the base class 290 super().accept() 291