ProjectFlask/Project.py

changeset 16
dd3f6bfb85f7
parent 15
3f5c05eb2d5f
child 17
f31df56510a1
equal deleted inserted replaced
15:3f5c05eb2d5f 16:dd3f6bfb85f7
6 """ 6 """
7 Module implementing the Flask project support. 7 Module implementing the Flask project support.
8 """ 8 """
9 9
10 import os 10 import os
11 import re
11 12
12 from PyQt5.QtCore import ( 13 from PyQt5.QtCore import (
13 pyqtSlot, QObject, QProcess, QProcessEnvironment, QTimer 14 pyqtSlot, QObject, QProcess, QProcessEnvironment, QTimer
14 ) 15 )
15 from PyQt5.QtWidgets import QMenu, QDialog 16 from PyQt5.QtWidgets import QMenu, QDialog
22 23
23 import UI.PixmapCache 24 import UI.PixmapCache
24 import Utilities 25 import Utilities
25 26
26 from .FlaskCommandDialog import FlaskCommandDialog 27 from .FlaskCommandDialog import FlaskCommandDialog
28 from .PyBabelCommandDialog import PyBabelCommandDialog
27 29
28 30
31 # TODO: move PyBabel related code to a separate package (FlaskBabelExtension)
32 # TODO: move database related code to a separate package (FlaskMigrateExtension)
29 class Project(QObject): 33 class Project(QObject):
30 """ 34 """
31 Class implementing the Flask project support. 35 Class implementing the Flask project support.
32 """ 36 """
33 def __init__(self, plugin, iconSuffix, parent=None): 37 def __init__(self, plugin, iconSuffix, parent=None):
64 68
65 self.__flaskVersions = { 69 self.__flaskVersions = {
66 "python": "", 70 "python": "",
67 "flask": "", 71 "flask": "",
68 "werkzeug": "", 72 "werkzeug": "",
73 }
74
75 self.__capabilities = {
76 "pybabel": False,
77 "migrate": False,
69 } 78 }
70 79
71 def initActions(self): 80 def initActions(self):
72 """ 81 """
73 Public method to define the Flask actions. 82 Public method to define the Flask actions.
176 )) 185 ))
177 self.initDatabaseAct.triggered.connect(self.__initDatabase) 186 self.initDatabaseAct.triggered.connect(self.__initDatabase)
178 self.actions.append(self.initDatabaseAct) 187 self.actions.append(self.initDatabaseAct)
179 188
180 ################################## 189 ##################################
181 ## database action below ## 190 ## pybabel action below ##
182 ################################## 191 ##################################
183 192
184 self.pybabelConfigAct = E5Action( 193 self.pybabelConfigAct = E5Action(
185 self.tr('Configure PyBabel'), 194 self.tr('Configure PyBabel'),
186 self.tr('Configure Py&Babel'), 195 self.tr('Configure Py&Babel'),
241 self.__menus = {} # clear menus references 250 self.__menus = {} # clear menus references
242 251
243 menu = QMenu(self.tr('&Flask'), self.__ui) 252 menu = QMenu(self.tr('&Flask'), self.__ui)
244 menu.setTearOffEnabled(True) 253 menu.setTearOffEnabled(True)
245 254
246 menu.addSection("flask run")
247 menu.addAction(self.runServerAct) 255 menu.addAction(self.runServerAct)
248 menu.addAction(self.runDevServerAct) 256 menu.addAction(self.runDevServerAct)
249 menu.addAction(self.askForServerOptionsAct) 257 menu.addAction(self.askForServerOptionsAct)
250 menu.addSection("flask shell") 258 menu.addSeparator()
251 menu.addAction(self.runPythonShellAct) 259 menu.addAction(self.runPythonShellAct)
252 menu.addSection("flask routes") 260 menu.addSeparator()
253 menu.addAction(self.showRoutesAct) 261 menu.addAction(self.showRoutesAct)
254 menu.addSection("flask init-db") 262 menu.addSeparator()
255 menu.addAction(self.initDatabaseAct) 263 menu.addAction(self.initDatabaseAct)
256 menu.addSection(self.tr("Translations")) 264 menu.addSeparator()
257 menu.addAction(self.pybabelConfigAct) 265 menu.addAction(self.pybabelConfigAct)
258 menu.addSection(self.tr("Various")) 266 menu.addSeparator()
259 menu.addAction(self.documentationAct) 267 menu.addAction(self.documentationAct)
260 menu.addSeparator() 268 menu.addSeparator()
261 menu.addAction(self.aboutFlaskAct) 269 menu.addAction(self.aboutFlaskAct)
262 270
263 self.__menus["main"] = menu 271 self.__menus["main"] = menu
306 def projectOpenedHooks(self): 314 def projectOpenedHooks(self):
307 """ 315 """
308 Public method to add our hook methods. 316 Public method to add our hook methods.
309 """ 317 """
310 if self.__e5project.getProjectType() == "Flask": 318 if self.__e5project.getProjectType() == "Flask":
319 # TODO: add some methods for standard templates
311 ## self.__formsBrowser = ( 320 ## self.__formsBrowser = (
312 ## e5App().getObject("ProjectBrowser") 321 ## e5App().getObject("ProjectBrowser")
313 ## .getProjectBrowser("forms")) 322 ## .getProjectBrowser("forms"))
314 ## self.__formsBrowser.addHookMethodAndMenuEntry( 323 ## self.__formsBrowser.addHookMethodAndMenuEntry(
315 ## "newForm", self.newForm, self.tr("New template...")) 324 ## "newForm", self.newForm, self.tr("New template..."))
316 ## 325 ##
317 if self.flaskBabelAvailable(): 326 self.__determineCapabilities()
327
328 if self.__capabilities["pybabel"]:
318 self.__e5project.projectLanguageAddedByCode.connect( 329 self.__e5project.projectLanguageAddedByCode.connect(
319 self.__projectLanguageAdded) 330 self.__projectLanguageAdded)
320 self.__translationsBrowser = ( 331 self.__translationsBrowser = (
321 e5App().getObject("ProjectBrowser") 332 e5App().getObject("ProjectBrowser")
322 .getProjectBrowser("translations")) 333 .getProjectBrowser("translations"))
331 self.tr("Compile Selected Catalogs")) 342 self.tr("Compile Selected Catalogs"))
332 self.__translationsBrowser.addHookMethodAndMenuEntry( 343 self.__translationsBrowser.addHookMethodAndMenuEntry(
333 "generateAll", self.updateCatalogs, 344 "generateAll", self.updateCatalogs,
334 self.tr("Update All Catalogs")) 345 self.tr("Update All Catalogs"))
335 self.__translationsBrowser.addHookMethodAndMenuEntry( 346 self.__translationsBrowser.addHookMethodAndMenuEntry(
347 "generateAllWithObsolete", self.updateCatalogsObsolete,
348 self.tr("Update All Catalogs (with obsolete)"))
349 self.__translationsBrowser.addHookMethodAndMenuEntry(
336 "generateSelected", self.updateSelectedCatalogs, 350 "generateSelected", self.updateSelectedCatalogs,
337 self.tr("Update Selected Catalogs")) 351 self.tr("Update Selected Catalogs"))
352 self.__translationsBrowser.addHookMethodAndMenuEntry(
353 "generateSelectedWithObsolete",
354 self.updateSelectedCatalogsObsolete,
355 self.tr("Update Selected Catalogs (with obsolete)"))
338 356
339 self.__hooksInstalled = True 357 self.__hooksInstalled = True
340 358
341 self.registerOpenHook() 359 self.registerOpenHook()
342 360
348 ## self.__formsBrowser.removeHookMethod("newForm") 366 ## self.__formsBrowser.removeHookMethod("newForm")
349 ## self.__formsBrowser = None 367 ## self.__formsBrowser = None
350 ## 368 ##
351 self.__e5project.projectLanguageAddedByCode.disconnect( 369 self.__e5project.projectLanguageAddedByCode.disconnect(
352 self.__projectLanguageAdded) 370 self.__projectLanguageAdded)
353 self.__translationsBrowser.removeHookMethod("extractMessages") 371 self.__translationsBrowser.removeHookMethod(
354 self.__translationsBrowser.removeHookMethod("releaseAll") 372 "extractMessages")
355 self.__translationsBrowser.removeHookMethod("releaseSelected") 373 self.__translationsBrowser.removeHookMethod(
356 self.__translationsBrowser.removeHookMethod("generateAll") 374 "releaseAll")
357 self.__translationsBrowser.removeHookMethod("generateSelected") 375 self.__translationsBrowser.removeHookMethod(
358 self.__translationsBrowser.removeHookMethod("open") 376 "releaseSelected")
377 self.__translationsBrowser.removeHookMethod(
378 "generateAll")
379 self.__translationsBrowser.removeHookMethod(
380 "generateAllWithObsolete")
381 self.__translationsBrowser.removeHookMethod(
382 "generateSelected")
383 self.__translationsBrowser.removeHookMethod(
384 "generateSelectedWithObsolete")
385 self.__translationsBrowser.removeHookMethod(
386 "open")
359 self.__translationsBrowser = None 387 self.__translationsBrowser = None
360 388
361 self.__hooksInstalled = False 389 self.__hooksInstalled = False
362 390
363 ################################################################## 391 ##################################################################
647 self.__projectData[category][key] = value 675 self.__projectData[category][key] = value
648 676
649 self.__e5project.setData( 677 self.__e5project.setData(
650 "PROJECTTYPESPECIFICDATA", category, self.__projectData[category]) 678 "PROJECTTYPESPECIFICDATA", category, self.__projectData[category])
651 679
652 ################################################################## 680 def __determineCapabilities(self):
653 ## slots below implement documentation functions 681 """
682 Private method to determine capabilities provided by supported
683 extensions.
684 """
685 # 1. support for flask-babel (i.e. pybabel)
686 self.__capabilities["pybabel"] = self.flaskBabelAvailable()
687 self.pybabelConfigAct.setEnabled(self.__capabilities["pybabel"])
688
689 # 2. support for flask-migrate
690 # TODO: add support for flask-migrate
691
692 ##################################################################
693 ## slot below implements project specific flask configuration
694 ##################################################################
695
696 @pyqtSlot()
697 def __configureFlaskForProject(self):
698 """
699 Private slot to configure the project specific flask parameters.
700 """
701 # TODO: implement the flask project config dialog
702 # 1. check boxes to override flask-babel and flask-migrate
703 # 2. support for project specific virtual environment
704
705 ##################################################################
706 ## slot below implements documentation function
654 ################################################################## 707 ##################################################################
655 708
656 def __showDocumentation(self): 709 def __showDocumentation(self):
657 """ 710 """
658 Private slot to show the helpviewer with the Flask documentation. 711 Private slot to show the helpviewer with the Flask documentation.
757 dlg = RoutesDialog(self) 810 dlg = RoutesDialog(self)
758 if dlg.showRoutes(): 811 if dlg.showRoutes():
759 dlg.show() 812 dlg.show()
760 self.__routesDialog = dlg 813 self.__routesDialog = dlg
761 814
815 # TODO: replace this by commands made by flask-migrate (flask db ...)
762 @pyqtSlot() 816 @pyqtSlot()
763 def __initDatabase(self): 817 def __initDatabase(self):
764 """ 818 """
765 Private slot showing the result of the database creation. 819 Private slot showing the result of the database creation.
766 """ 820 """
767 dlg = FlaskCommandDialog(self) 821 dlg = FlaskCommandDialog(self)
768 if dlg.startFlaskCommand("init-db"): 822 if dlg.startCommand("init-db"):
769 dlg.exec() 823 dlg.exec()
770 824
771 ################################################################## 825 ##################################################################
772 ## slots and methods below implement i18n and l10n support 826 ## slots and methods below implement i18n and l10n support
773 ################################################################## 827 ##################################################################
797 @pyqtSlot() 851 @pyqtSlot()
798 def __configurePybabel(self): 852 def __configurePybabel(self):
799 """ 853 """
800 Private slot to show a dialog to edit the pybabel configuration. 854 Private slot to show a dialog to edit the pybabel configuration.
801 """ 855 """
802 # TODO: implement this
803 from .PyBabelConfigDialog import PyBabelConfigDialog 856 from .PyBabelConfigDialog import PyBabelConfigDialog
804 857
805 config = self.getData("pybabel", "") 858 config = self.getData("pybabel", "")
806 dlg = PyBabelConfigDialog(config) 859 dlg = PyBabelConfigDialog(config)
807 if dlg.exec() == QDialog.Accepted: 860 if dlg.exec() == QDialog.Accepted:
808 config = dlg.getConfiguration() 861 config = dlg.getConfiguration()
809 self.setData("pybabel", "", config) 862 self.setData("pybabel", "", config)
863
864 self.__e5project.setTranslationPattern(os.path.join(
865 config["translationsDirectory"], "%language%", "LC_MESSAGES",
866 "{0}.po".format(config["domain"])
867 ))
868 self.__e5project.setDirty(True)
810 869
811 cfgFileName = self.__e5project.getAbsoluteUniversalPath( 870 cfgFileName = self.__e5project.getAbsoluteUniversalPath(
812 config["configFile"]) 871 config["configFile"])
813 if not os.path.exists(cfgFileName): 872 if not os.path.exists(cfgFileName):
814 self.__createBabelCfg(cfgFileName) 873 self.__createBabelCfg(cfgFileName)
838 897
839 def __createBabelCfg(self, configFile): 898 def __createBabelCfg(self, configFile):
840 """ 899 """
841 Private method to create a template pybabel configuration file. 900 Private method to create a template pybabel configuration file.
842 901
902 @param configFile name of the configuration file to be created
903 @type str
843 @return flag indicating successful configuration file creation 904 @return flag indicating successful configuration file creation
844 @rtype bool 905 @rtype bool
845 """ 906 """
846 _, app = self.getApplication() 907 _, app = self.getApplication()
847 if app.endswith(".py"): 908 if app.endswith(".py"):
876 """ generated.</p><p>Reason: {0}</p>""") 937 """ generated.</p><p>Reason: {0}</p>""")
877 .format(str(err)) 938 .format(str(err))
878 ) 939 )
879 return False 940 return False
880 941
881 def __projectLanguageAdded(self, code): 942 def __getLocale(self, filename):
882 # TODO: implement this with pybabel ... 943 """
883 pass 944 Private method to extract the locale out of a file name.
945
946 @param filename name of the file used for extraction
947 @type str
948 @return extracted locale
949 @rtype str or None
950 """
951 if self.__e5project.getTranslationPattern():
952 filename = os.path.splitext(filename)[0] + ".po"
953
954 # On Windows, path typically contains backslashes. This leads
955 # to an invalid search pattern '...\(' because the opening bracket
956 # will be escaped.
957 pattern = self.__e5project.getTranslationPattern()
958 pattern = os.path.normpath(pattern)
959 pattern = pattern.replace("%language%", "(.*?)")
960 pattern = pattern.replace('\\', '\\\\')
961 match = re.search(pattern, filename)
962 if match is not None:
963 return match.group(1)
964
965 return None
884 966
885 def openPOEditor(self, poFile): 967 def openPOEditor(self, poFile):
886 """ 968 """
887 Public method to edit the given file in an external .po editor. 969 Public method to edit the given file in an external .po editor.
888 970
905 """ 987 """
906 Public method to extract the messages catalog template file. 988 Public method to extract the messages catalog template file.
907 """ 989 """
908 title = self.tr("Extract messages") 990 title = self.tr("Extract messages")
909 if self.__ensurePybabelConfigured(): 991 if self.__ensurePybabelConfigured():
992 workdir = self.getApplication()[0]
910 potFile = self.__e5project.getAbsoluteUniversalPath( 993 potFile = self.__e5project.getAbsoluteUniversalPath(
911 self.getData("pybabel", "catalogFile")) 994 self.getData("pybabel", "catalogFile"))
912 995
913 try: 996 try:
914 potFilePath = os.path.dirname(potFile) 997 potFilePath = os.path.dirname(potFile)
916 except EnvironmentError: 999 except EnvironmentError:
917 pass 1000 pass
918 1001
919 args = [ 1002 args = [
920 "-F", 1003 "-F",
921 self.__e5project.getAbsoluteUniversalPath( 1004 os.path.relpath(
922 self.getData("pybabel", "configFile")) 1005 self.__e5project.getAbsoluteUniversalPath(
1006 self.getData("pybabel", "configFile")),
1007 workdir
1008 )
923 ] 1009 ]
924 if self.getData("pybabel", "markersList"): 1010 if self.getData("pybabel", "markersList"):
925 for marker in self.getData("pybabel", "markersList"): 1011 for marker in self.getData("pybabel", "markersList"):
926 args += ["-k", marker] 1012 args += ["-k", marker]
927 args += [ 1013 args += [
928 "-o", 1014 "-o",
929 potFile, 1015 os.path.relpath(potFile, workdir),
930 "." 1016 "."
931 ] 1017 ]
932 1018
933 dlg = FlaskCommandDialog(self) 1019 dlg = PyBabelCommandDialog(
934 res = dlg.startBabelCommand( 1020 self, title,
935 "extract", args, title,
936 msgSuccess=self.tr("\nMessages extracted successfully.") 1021 msgSuccess=self.tr("\nMessages extracted successfully.")
937 ) 1022 )
1023 res = dlg.startCommand("extract", args, workdir)
938 if res: 1024 if res:
939 dlg.exec() 1025 dlg.exec()
940 self.__e5project.appendFile(potFile) 1026 self.__e5project.appendFile(potFile)
941 # TODO: implement this with pybabel ... 1027
942 pass 1028 def __projectLanguageAdded(self, code):
943 1029 """
944 def compileCatalogs(self): 1030 Private slot handling the addition of a new language.
945 # TODO: implement this with pybabel ... 1031
946 pass 1032 @param code language code of the new language
947 1033 @type str
948 def compileSelectedCatalogs(self): 1034 """
949 # TODO: implement this with pybabel ... 1035 title = self.tr(
950 pass 1036 "Initializing message catalog for '{0}'").format(code)
951 1037
952 def updateCatalogs(self): 1038 if self.__ensurePybabelConfigured():
953 # TODO: implement this with pybabel ... 1039 workdir = self.getApplication()[0]
954 pass 1040 langFile = self.__e5project.getAbsoluteUniversalPath(
955 1041 self.__e5project.getTranslationPattern().replace(
956 def updateSelectedCatalogs(self): 1042 "%language%", code))
957 # TODO: implement this with pybabel ... 1043 potFile = self.__e5project.getAbsoluteUniversalPath(
958 pass 1044 self.getData("pybabel", "catalogFile"))
1045
1046 args = [
1047 "--domain={0}".format(self.getData("pybabel", "domain")),
1048 "--input-file={0}".format(os.path.relpath(potFile, workdir)),
1049 "--output-file={0}".format(os.path.relpath(langFile, workdir)),
1050 "--locale={0}".format(code),
1051 ]
1052
1053 dlg = PyBabelCommandDialog(
1054 self, title,
1055 msgSuccess=self.tr(
1056 "\nMessage catalog initialized successfully.")
1057 )
1058 res = dlg.startCommand("init", args, workdir)
1059 if res:
1060 dlg.exec()
1061
1062 self.__e5project.appendFile(langFile)
1063
1064 def compileCatalogs(self, filenames):
1065 """
1066 Public method to compile the message catalogs.
1067
1068 @param filenames list of filenames (not used)
1069 @type list of str
1070 """
1071 title = self.tr("Compiling message catalogs")
1072
1073 if self.__ensurePybabelConfigured():
1074 workdir = self.getApplication()[0]
1075 translationsDirectory = self.__e5project.getAbsoluteUniversalPath(
1076 self.getData("pybabel", "translationsDirectory"))
1077
1078 args = [
1079 "--domain={0}".format(self.getData("pybabel", "domain")),
1080 "--directory={0}".format(
1081 os.path.relpath(translationsDirectory, workdir)),
1082 "--use-fuzzy",
1083 "--statistics",
1084 ]
1085
1086 dlg = PyBabelCommandDialog(
1087 self, title,
1088 msgSuccess=self.tr("\nMessage catalogs compiled successfully.")
1089 )
1090 res = dlg.startCommand("compile", args, workdir)
1091 if res:
1092 dlg.exec()
1093
1094 for entry in os.walk(translationsDirectory):
1095 for fileName in entry[2]:
1096 fullName = os.path.join(entry[0], fileName)
1097 if fullName.endswith('.mo'):
1098 self.__e5project.appendFile(fullName)
1099
1100 def compileSelectedCatalogs(self, filenames):
1101 """
1102 Public method to update the message catalogs.
1103
1104 @param filenames list of file names
1105 @type list of str
1106 """
1107 title = self.tr("Compiling message catalogs")
1108
1109 locales = {self.__getLocale(f) for f in filenames}
1110
1111 if len(locales) == 0:
1112 E5MessageBox.warning(
1113 self.__ui,
1114 title,
1115 self.tr('No locales detected. Aborting...'))
1116 return
1117
1118 if self.__ensurePybabelConfigured():
1119 workdir = self.getApplication()[0]
1120 translationsDirectory = self.__e5project.getAbsoluteUniversalPath(
1121 self.getData("pybabel", "translationsDirectory"))
1122
1123 argsList = []
1124 for loc in locales:
1125 argsList.append([
1126 "compile",
1127 "--domain={0}".format(self.getData("pybabel", "domain")),
1128 "--directory={0}".format(
1129 os.path.relpath(translationsDirectory, workdir)),
1130 "--use-fuzzy",
1131 "--statistics",
1132 "--locale={0}".format(loc),
1133 ])
1134
1135 dlg = PyBabelCommandDialog(
1136 self, title=title,
1137 msgSuccess=self.tr("\nMessage catalogs compiled successfully.")
1138 )
1139 res = dlg.startBatchCommand(argsList, workdir)
1140 if res:
1141 dlg.exec()
1142
1143 for entry in os.walk(translationsDirectory):
1144 for fileName in entry[2]:
1145 fullName = os.path.join(entry[0], fileName)
1146 if fullName.endswith('.mo'):
1147 self.__e5project.appendFile(fullName)
1148
1149 def updateCatalogs(self, filenames, withObsolete=False):
1150 """
1151 Public method to update the message catalogs.
1152
1153 @param filenames list of filenames (not used)
1154 @type list of str
1155 @param withObsolete flag indicating to keep obsolete translations
1156 @type bool
1157 """
1158 title = self.tr("Updating message catalogs")
1159
1160 if self.__ensurePybabelConfigured():
1161 workdir = self.getApplication()[0]
1162 translationsDirectory = self.__e5project.getAbsoluteUniversalPath(
1163 self.getData("pybabel", "translationsDirectory"))
1164 potFile = self.__e5project.getAbsoluteUniversalPath(
1165 self.getData("pybabel", "catalogFile"))
1166
1167 args = [
1168 "--domain={0}".format(self.getData("pybabel", "domain")),
1169 "--input-file={0}".format(os.path.relpath(potFile, workdir)),
1170 "--output-dir={0}".format(
1171 os.path.relpath(translationsDirectory, workdir)),
1172 ]
1173 if not withObsolete:
1174 args.append("--ignore-obsolete")
1175
1176 dlg = PyBabelCommandDialog(
1177 self, title,
1178 msgSuccess=self.tr("\nMessage catalogs updated successfully.")
1179 )
1180 res = dlg.startCommand("update", args, workdir)
1181 if res:
1182 dlg.exec()
1183
1184 def updateCatalogsObsolete(self, filenames):
1185 """
1186 Public method to update the message catalogs keeping obsolete
1187 translations.
1188
1189 @param filenames list of filenames (not used)
1190 @type list of str
1191 """
1192 self.updateCatalogs(filenames, withObsolete=True)
1193
1194 def updateSelectedCatalogs(self, filenames, withObsolete=False):
1195 """
1196 Public method to update the selected message catalogs.
1197
1198 @param filenames list of filenames
1199 @type list of str
1200 @param withObsolete flag indicating to keep obsolete translations
1201 @type bool
1202 """
1203 title = self.tr("Updating message catalogs")
1204
1205 locales = {self.__getLocale(f) for f in filenames}
1206
1207 if len(locales) == 0:
1208 E5MessageBox.warning(
1209 self.__ui,
1210 title,
1211 self.tr('No locales detected. Aborting...'))
1212 return
1213
1214 if self.__ensurePybabelConfigured():
1215 workdir = self.getApplication()[0]
1216 translationsDirectory = self.__e5project.getAbsoluteUniversalPath(
1217 self.getData("pybabel", "translationsDirectory"))
1218 potFile = self.__e5project.getAbsoluteUniversalPath(
1219 self.getData("pybabel", "catalogFile"))
1220 argsList = []
1221 for loc in locales:
1222 args = [
1223 "update",
1224 "--domain={0}".format(self.getData("pybabel", "domain")),
1225 "--input-file={0}".format(
1226 os.path.relpath(potFile, workdir)),
1227 "--output-dir={0}".format(
1228 os.path.relpath(translationsDirectory, workdir)),
1229 "--locale={0}".format(loc),
1230 ]
1231 if not withObsolete:
1232 args.append("--ignore-obsolete")
1233 argsList.append(args)
1234
1235 dlg = PyBabelCommandDialog(
1236 self, title=title,
1237 msgSuccess=self.tr("\nMessage catalogs updated successfully.")
1238 )
1239 res = dlg.startBatchCommand(argsList, workdir)
1240 if res:
1241 dlg.exec()
1242
1243 def updateSelectedCatalogsObsolete(self, filenames):
1244 """
1245 Public method to update the message catalogs keeping obsolete
1246 translations.
1247
1248 @param filenames list of filenames (not used)
1249 @type list of str
1250 """
1251 self.updateSelectedCatalogs(filenames, withObsolete=True)

eric ide

mercurial