76 file_delete_id_stmt = """ |
77 file_delete_id_stmt = """ |
77 DELETE FROM file WHERE id = :id |
78 DELETE FROM file WHERE id = :id |
78 """ |
79 """ |
79 |
80 |
80 def __init__(self, proxy, language, apiFiles, projectPath="", |
81 def __init__(self, proxy, language, apiFiles, projectPath="", |
81 refresh=False): |
82 refresh=False, projectType=""): |
82 """ |
83 """ |
83 Constructor |
84 Constructor |
84 |
85 |
85 @param proxy reference to the object that is proxied (DbAPIs) |
86 @param proxy reference to the object that is proxied |
86 @param language language of the APIs object (string) |
87 @type DbAPIs |
87 @param apiFiles list of API files to process (list of strings) |
88 @param language language of the APIs object |
|
89 @type str |
|
90 @param apiFiles list of API files to process |
|
91 @type list of str |
88 @param projectPath path of the project. Only needed, if the APIs |
92 @param projectPath path of the project. Only needed, if the APIs |
89 are extracted out of the sources of a project. (string) |
93 are extracted out of the sources of a project. |
|
94 @type str |
90 @param refresh flag indicating a refresh of the APIs of one file |
95 @param refresh flag indicating a refresh of the APIs of one file |
91 (boolean) |
96 @type bool |
|
97 @param projectType type of the project |
|
98 @type str |
92 """ |
99 """ |
93 QThread.__init__(self) |
100 QThread.__init__(self) |
94 |
101 |
95 self.setTerminationEnabled(True) |
102 self.setTerminationEnabled(True) |
96 |
103 |
103 if lexer is not None: |
110 if lexer is not None: |
104 self.__wseps[lang] = lexer.autoCompletionWordSeparators() |
111 self.__wseps[lang] = lexer.autoCompletionWordSeparators() |
105 |
112 |
106 self.__proxy = proxy |
113 self.__proxy = proxy |
107 self.__language = language |
114 self.__language = language |
|
115 self.__projectType = projectType |
108 self.__apiFiles = apiFiles[:] |
116 self.__apiFiles = apiFiles[:] |
109 self.__aborted = False |
117 self.__aborted = False |
110 self.__projectPath = projectPath |
118 self.__projectPath = projectPath |
111 self.__refresh = refresh |
119 self.__refresh = refresh |
|
120 |
|
121 if self.__projectType: |
|
122 self.__connectionName = "{0}_{1}".format( |
|
123 self.__language, self.__projectType) |
|
124 else: |
|
125 self.__connectionName = self.__language |
112 |
126 |
113 def __autoCompletionWordSeparators(self, language): |
127 def __autoCompletionWordSeparators(self, language): |
114 """ |
128 """ |
115 Private method to get the word separator characters for a language. |
129 Private method to get the word separator characters for a language. |
116 |
130 |
130 Private method to load an API file, if it is newer than the one read |
144 Private method to load an API file, if it is newer than the one read |
131 into the database. |
145 into the database. |
132 |
146 |
133 @param apiFile filename of the raw API file (string) |
147 @param apiFile filename of the raw API file (string) |
134 """ |
148 """ |
135 db = QSqlDatabase.database(self.__language) |
149 db = QSqlDatabase.database(self.__connectionName) |
136 db.transaction() |
150 db.transaction() |
137 try: |
151 try: |
138 query = QSqlQuery(db) |
152 query = QSqlQuery(db) |
139 query.prepare(self.file_loaded_stmt) |
153 query.prepare(self.file_loaded_stmt) |
140 query.bindValue(":file", apiFile) |
154 query.bindValue(":file", apiFile) |
247 Doing this avoids rereading the file whenever the API is initialized |
261 Doing this avoids rereading the file whenever the API is initialized |
248 in case the given file doesn't contain API data. |
262 in case the given file doesn't contain API data. |
249 |
263 |
250 @param apiFile file name of the API file (string) |
264 @param apiFile file name of the API file (string) |
251 """ |
265 """ |
252 db = QSqlDatabase.database(self.__language) |
266 db = QSqlDatabase.database(self.__connectionName) |
253 db.transaction() |
267 db.transaction() |
254 try: |
268 try: |
255 query = QSqlQuery(db) |
269 query = QSqlQuery(db) |
256 # step 1: create entry in file table |
270 # step 1: create entry in file table |
257 query.prepare(self.populate_file_stmt) |
271 query.prepare(self.populate_file_stmt) |
444 """ |
458 """ |
445 Public method to perform the threads work. |
459 Public method to perform the threads work. |
446 """ |
460 """ |
447 self.processing.emit(WorkerStatusStarted, "") |
461 self.processing.emit(WorkerStatusStarted, "") |
448 |
462 |
449 db = QSqlDatabase.database(self.__language) |
463 db = QSqlDatabase.database(self.__connectionName) |
450 if db.isValid() and db.isOpen(): |
464 if db.isValid() and db.isOpen(): |
451 # step 1: remove API files not wanted any longer |
465 # step 1: remove API files not wanted any longer |
452 if not self.__refresh: |
466 if not self.__refresh: |
453 loadedApiFiles = self.__proxy.getApiFiles() |
467 loadedApiFiles = self.__proxy.getApiFiles() |
454 for apiFile in loadedApiFiles: |
468 for apiFile in loadedApiFiles: |
572 """ |
586 """ |
573 mgmt_insert_stmt = """ |
587 mgmt_insert_stmt = """ |
574 INSERT INTO mgmt (format) VALUES ({0:d}) |
588 INSERT INTO mgmt (format) VALUES ({0:d}) |
575 """.format(DB_VERSION) |
589 """.format(DB_VERSION) |
576 |
590 |
577 def __init__(self, language, parent=None): |
591 def __init__(self, language, projectType="", parent=None): |
578 """ |
592 """ |
579 Constructor |
593 Constructor |
580 |
594 |
581 @param language language of the APIs object (string) |
595 @param language language of the APIs object |
582 @param parent reference to the parent object (QObject) |
596 @type str |
|
597 @param projectType type of the project |
|
598 @type str |
|
599 @param parent reference to the parent object |
|
600 @type QObject |
583 """ |
601 """ |
584 QObject.__init__(self, parent) |
602 QObject.__init__(self, parent) |
585 self.setObjectName("DbAPIs_{0}".format(language)) |
603 if projectType: |
|
604 self.setObjectName("DbAPIs_{0}_{1}".format(language, projectType)) |
|
605 else: |
|
606 self.setObjectName("DbAPIs_{0}".format(language)) |
586 |
607 |
587 self.__inPreparation = False |
608 self.__inPreparation = False |
588 self.__worker = None |
609 self.__worker = None |
589 self.__workerQueue = [] |
610 self.__workerQueue = [] |
590 self.__opened = False |
611 self.__opened = False |
591 |
612 |
|
613 self.__projectType = projectType |
592 self.__language = language |
614 self.__language = language |
|
615 |
|
616 if self.__projectType: |
|
617 self.__connectionName = "{0}_{1}".format( |
|
618 self.__language, self.__projectType) |
|
619 else: |
|
620 self.__connectionName = self.__language |
|
621 |
593 if self.__language == ApisNameProject: |
622 if self.__language == ApisNameProject: |
594 self.__initAsProject() |
623 self.__initAsProject() |
595 else: |
624 else: |
596 self.__initAsLanguage() |
625 self.__initAsLanguage() |
597 |
626 |
618 if self.__language in ["Python", "Python2", "Python3"]: |
647 if self.__language in ["Python", "Python2", "Python3"]: |
619 self.__discardFirst = ["self", "cls"] |
648 self.__discardFirst = ["self", "cls"] |
620 else: |
649 else: |
621 self.__discardFirst = [] |
650 self.__discardFirst = [] |
622 self.__lexer = QScintilla.Lexers.getLexer(self.__language) |
651 self.__lexer = QScintilla.Lexers.getLexer(self.__language) |
623 self.__apifiles = Preferences.getEditorAPI(self.__language) |
652 try: |
|
653 self.__apifiles = Preferences.getEditorAPI( |
|
654 self.__language, projectType=self.__projectType) |
|
655 except TypeError: |
|
656 # older interface |
|
657 self.__apifiles = Preferences.getEditorAPI(self.__language) |
624 self.__apifiles.sort() |
658 self.__apifiles.sort() |
625 if self.__lexer is not None: |
659 if self.__lexer is not None: |
626 self.__openAPIs() |
660 self.__openAPIs() |
627 |
661 |
628 def _apiDbName(self): |
662 def _apiDbName(self): |
633 """ |
667 """ |
634 if self.__language == ApisNameProject: |
668 if self.__language == ApisNameProject: |
635 return os.path.join(self.__project.getProjectManagementDir(), |
669 return os.path.join(self.__project.getProjectManagementDir(), |
636 "project-apis.db") |
670 "project-apis.db") |
637 else: |
671 else: |
638 apiDir = os.path.join(Utilities.getConfigDir(), "APIs") |
672 apisDir = os.path.join(Globals.getConfigDir(), "APIs") |
639 if not os.path.exists(apiDir): |
673 if not os.path.exists(apisDir): |
640 os.makedirs(apiDir) |
674 os.makedirs(apisDir) |
641 return os.path.join(apiDir, "{0}-api.db".format(self.__language)) |
675 if self.__projectType: |
|
676 filename = "{0}_{1}-api.db".format(self.__language, |
|
677 self.__projectType) |
|
678 else: |
|
679 filename = "{0}-api.db".format(self.__language) |
|
680 return os.path.join(apisDir, filename) |
642 |
681 |
643 def close(self): |
682 def close(self): |
644 """ |
683 """ |
645 Public method to close the database. |
684 Public method to close the database. |
646 """ |
685 """ |
653 not self.__worker.isFinished(): |
692 not self.__worker.isFinished(): |
654 self.__worker.terminate() |
693 self.__worker.terminate() |
655 if self.__worker is not None: |
694 if self.__worker is not None: |
656 self.__worker.wait(5000) |
695 self.__worker.wait(5000) |
657 |
696 |
658 if QSqlDatabase and QSqlDatabase.database(self.__language).isOpen(): |
697 if QSqlDatabase and QSqlDatabase.database( |
659 QSqlDatabase.database(self.__language).close() |
698 self.__connectionName).isOpen(): |
|
699 QSqlDatabase.database(self.__connectionName).close() |
660 QSqlDatabase.removeDatabase(self.__language) |
700 QSqlDatabase.removeDatabase(self.__language) |
661 |
701 |
662 self.__opened = False |
702 self.__opened = False |
663 |
703 |
664 def __openApiDb(self): |
704 def __openApiDb(self): |
665 """ |
705 """ |
666 Private method to open the API database. |
706 Private method to open the API database. |
667 |
707 |
668 @return flag indicating the database status (boolean) |
708 @return flag indicating the database status (boolean) |
669 """ |
709 """ |
670 db = QSqlDatabase.database(self.__language, False) |
710 db = QSqlDatabase.database(self.__connectionName, False) |
671 if not db.isValid(): |
711 if not db.isValid(): |
672 # the database connection is a new one |
712 # the database connection is a new one |
673 db = QSqlDatabase.addDatabase("QSQLITE", self.__language) |
713 db = QSqlDatabase.addDatabase("QSQLITE", self.__connectionName) |
674 dbName = self._apiDbName() |
714 dbName = self._apiDbName() |
675 if self.__language == ApisNameProject and \ |
715 if self.__language == ApisNameProject and \ |
676 not os.path.exists( |
716 not os.path.exists( |
677 self.__project.getProjectManagementDir()): |
717 self.__project.getProjectManagementDir()): |
678 opened = False |
718 opened = False |
679 else: |
719 else: |
680 db.setDatabaseName(dbName) |
720 db.setDatabaseName(dbName) |
681 opened = db.open() |
721 opened = db.open() |
682 if not opened: |
722 if not opened: |
683 QSqlDatabase.removeDatabase(self.__language) |
723 QSqlDatabase.removeDatabase(self.__connectionName) |
684 else: |
724 else: |
685 opened = True |
725 opened = True |
686 return opened |
726 return opened |
687 |
727 |
688 def __createApiDB(self): |
728 def __createApiDB(self): |
689 """ |
729 """ |
690 Private method to create an API database. |
730 Private method to create an API database. |
691 """ |
731 """ |
692 db = QSqlDatabase.database(self.__language) |
732 db = QSqlDatabase.database(self.__connectionName) |
693 db.transaction() |
733 db.transaction() |
694 try: |
734 try: |
695 query = QSqlQuery(db) |
735 query = QSqlQuery(db) |
696 # step 1: drop old tables |
736 # step 1: drop old tables |
697 query.exec_(self.drop_mgmt_stmt) |
737 query.exec_(self.drop_mgmt_stmt) |
843 base classes (boolean) |
883 base classes (boolean) |
844 @return list of calltips (list of string) |
884 @return list of calltips (list of string) |
845 """ |
885 """ |
846 calltips = [] |
886 calltips = [] |
847 |
887 |
848 db = QSqlDatabase.database(self.__language) |
888 db = QSqlDatabase.database(self.__connectionName) |
849 if db.isOpen() and not self.__inPreparation: |
889 if db.isOpen() and not self.__inPreparation: |
850 if self.autoCompletionWordSeparators(): |
890 if self.autoCompletionWordSeparators(): |
851 contextSeparator = self.autoCompletionWordSeparators()[0] |
891 contextSeparator = self.autoCompletionWordSeparators()[0] |
852 else: |
892 else: |
853 contextSeparator = " " |
893 contextSeparator = " " |
983 apiFiles = self.__project.getSources()[:] |
1023 apiFiles = self.__project.getSources()[:] |
984 apiFiles.extend( |
1024 apiFiles.extend( |
985 [f for f in self.__getProjectFormSources() if |
1025 [f for f in self.__getProjectFormSources() if |
986 f not in apiFiles]) |
1026 f not in apiFiles]) |
987 projectPath = self.__project.getProjectPath() |
1027 projectPath = self.__project.getProjectPath() |
988 else: |
1028 projectType = "" |
989 apiFiles = Preferences.getEditorAPI(self.__language) |
1029 else: |
|
1030 try: |
|
1031 apiFiles = Preferences.getEditorAPI( |
|
1032 self.__language, projectType=self.__projectType) |
|
1033 except TypeError: |
|
1034 # older interface |
|
1035 apiFiles = Preferences.getEditorAPI(self.__language) |
|
1036 projectType = self.__projectType |
990 self.__worker = DbAPIsWorker(self, self.__language, apiFiles, |
1037 self.__worker = DbAPIsWorker(self, self.__language, apiFiles, |
991 projectPath) |
1038 projectPath, projectType=projectType) |
992 self.__worker.processing.connect( |
1039 self.__worker.processing.connect( |
993 self.__processingStatus, Qt.QueuedConnection) |
1040 self.__processingStatus, Qt.QueuedConnection) |
994 self.__worker.start() |
1041 self.__worker.start() |
995 |
1042 |
996 def __processQueue(self): |
1043 def __processQueue(self): |
1004 if self.__worker is None and len(self.__workerQueue) > 0: |
1051 if self.__worker is None and len(self.__workerQueue) > 0: |
1005 apiFiles = [self.__workerQueue.pop(0)] |
1052 apiFiles = [self.__workerQueue.pop(0)] |
1006 if self.__language == ApisNameProject: |
1053 if self.__language == ApisNameProject: |
1007 projectPath = self.__project.getProjectPath() |
1054 projectPath = self.__project.getProjectPath() |
1008 apiFiles = [apiFiles[0].replace(projectPath + os.sep, "")] |
1055 apiFiles = [apiFiles[0].replace(projectPath + os.sep, "")] |
|
1056 projectType = "" |
1009 else: |
1057 else: |
1010 projectPath = "" |
1058 projectPath = "" |
|
1059 projectType = self.__projectType |
1011 self.__worker = DbAPIsWorker(self, self.__language, apiFiles, |
1060 self.__worker = DbAPIsWorker(self, self.__language, apiFiles, |
1012 projectPath, refresh=True) |
1061 projectPath, projectType=projectType, |
|
1062 refresh=True) |
1013 self.__worker.processing.connect( |
1063 self.__worker.processing.connect( |
1014 self.__processingStatus, Qt.QueuedConnection) |
1064 self.__processingStatus, Qt.QueuedConnection) |
1015 self.__worker.start() |
1065 self.__worker.start() |
1016 |
1066 |
1017 def getLexer(self): |
1067 def getLexer(self): |
1120 |
1170 |
1121 @param mainWindow reference to the main eric6 window (QMainWindow) |
1171 @param mainWindow reference to the main eric6 window (QMainWindow) |
1122 @param parent reference to the parent object (QObject) |
1172 @param parent reference to the parent object (QObject) |
1123 """ |
1173 """ |
1124 QObject.__init__(self, parent) |
1174 QObject.__init__(self, parent) |
1125 self.setObjectName("APIsManager") |
1175 self.setObjectName("Assistant_APIsManager") |
1126 |
1176 |
1127 self.__mw = mainWindow |
1177 self.__mw = mainWindow |
1128 |
1178 |
1129 # initialize the apis dictionary |
1179 # initialize the apis dictionary |
1130 self.__apis = {} |
1180 self.__apis = {} |
1134 Public slot to reload the api information. |
1184 Public slot to reload the api information. |
1135 """ |
1185 """ |
1136 for api in list(self.__apis.values()): |
1186 for api in list(self.__apis.values()): |
1137 api and api.prepareAPIs() |
1187 api and api.prepareAPIs() |
1138 |
1188 |
1139 def getAPIs(self, language): |
1189 def getAPIs(self, language, projectType=""): |
1140 """ |
1190 """ |
1141 Public method to get an apis object for autocompletion/calltips. |
1191 Public method to get an apis object for autocompletion/calltips. |
1142 |
1192 |
1143 This method creates and loads an APIs object dynamically upon request. |
1193 This method creates and loads an APIs object dynamically upon request. |
1144 This saves memory for languages, that might not be needed at the |
1194 This saves memory for languages, that might not be needed at the |
1145 moment. |
1195 moment. |
1146 |
1196 |
1147 @param language the language of the requested api object (string) |
1197 @param language language of the requested APIs object |
1148 @return the apis object (APIs) |
1198 @type str |
|
1199 @param projectType type of the project |
|
1200 @type str |
|
1201 @return reference to the APIs object |
|
1202 @rtype APIs |
1149 """ |
1203 """ |
1150 try: |
1204 try: |
1151 return self.__apis[language] |
1205 return self.__apis[(language, projectType)] |
1152 except KeyError: |
1206 except KeyError: |
1153 if language in QScintilla.Lexers.getSupportedLanguages() or \ |
1207 if language in self.__supportedApiLanguages() or \ |
1154 language == ApisNameProject: |
1208 language == ApisNameProject: |
1155 # create the api object |
1209 # create the api object |
1156 api = DbAPIs(language) |
1210 api = DbAPIs(language, projectType=projectType) |
1157 api.apiPreparationStatus.connect(self.__apiPreparationStatus) |
1211 api.apiPreparationStatus.connect(self.__apiPreparationStatus) |
1158 self.__apis[language] = api |
1212 self.__apis[(language, projectType)] = api |
1159 return self.__apis[language] |
1213 return self.__apis[(language, projectType)] |
1160 else: |
1214 else: |
1161 return None |
1215 return None |
|
1216 |
|
1217 def __supportedApiLanguages(self): |
|
1218 """ |
|
1219 Private method to build a list of supported API languages. |
|
1220 |
|
1221 Note: This is a compatibility method to make this code work with |
|
1222 older eric versions. |
|
1223 |
|
1224 @return list of supported API languages |
|
1225 @rtype list of str |
|
1226 """ |
|
1227 try: |
|
1228 return QScintilla.Lexers.getSupportedApiLanguages() |
|
1229 except AttributeError: |
|
1230 return [lang for lang in |
|
1231 QScintilla.Lexers.getSupportedLanguages().keys() |
|
1232 if lang != "Guessed" and not lang.startswith("Pygments|")] |
1162 |
1233 |
1163 def deactivate(self): |
1234 def deactivate(self): |
1164 """ |
1235 """ |
1165 Public method to perform actions upon deactivation. |
1236 Public method to perform actions upon deactivation. |
1166 """ |
1237 """ |