75 SELECT id FROM file WHERE file = :file |
75 SELECT id FROM file WHERE file = :file |
76 """ |
76 """ |
77 file_delete_id_stmt = """ |
77 file_delete_id_stmt = """ |
78 DELETE FROM file WHERE id = :id |
78 DELETE FROM file WHERE id = :id |
79 """ |
79 """ |
80 |
80 |
81 def __init__(self, proxy, language, apiFiles, projectPath="", |
81 api_files_stmt = """ |
|
82 SELECT file FROM file |
|
83 """ |
|
84 |
|
85 def __init__(self, proxy, language, apiFiles, dbName, projectPath="", |
82 refresh=False, projectType=""): |
86 refresh=False, projectType=""): |
83 """ |
87 """ |
84 Constructor |
88 Constructor |
85 |
89 |
86 @param proxy reference to the object that is proxied |
90 @param proxy reference to the object that is proxied |
87 @type DbAPIs |
91 @type DbAPIs |
88 @param language language of the APIs object |
92 @param language language of the APIs object |
89 @type str |
93 @type str |
90 @param apiFiles list of API files to process |
94 @param apiFiles list of API files to process |
91 @type list of str |
95 @type list of str |
|
96 @param dbName path name of the database file |
|
97 @type str |
92 @param projectPath path of the project. Only needed, if the APIs |
98 @param projectPath path of the project. Only needed, if the APIs |
93 are extracted out of the sources of a project. |
99 are extracted out of the sources of a project. |
94 @type str |
100 @type str |
95 @param refresh flag indicating a refresh of the APIs of one file |
101 @param refresh flag indicating a refresh of the APIs of one file |
96 @type bool |
102 @type bool |
116 self.__apiFiles = apiFiles[:] |
122 self.__apiFiles = apiFiles[:] |
117 self.__aborted = False |
123 self.__aborted = False |
118 self.__projectPath = projectPath |
124 self.__projectPath = projectPath |
119 self.__refresh = refresh |
125 self.__refresh = refresh |
120 |
126 |
|
127 self.__databaseName = dbName |
|
128 |
121 if self.__projectType: |
129 if self.__projectType: |
|
130 self.__connectionName = "{0}_{1}_{2}".format( |
|
131 self.__language, self.__projectType, id(self)) |
|
132 else: |
122 self.__connectionName = "{0}_{1}".format( |
133 self.__connectionName = "{0}_{1}".format( |
123 self.__language, self.__projectType) |
134 self.__language, id(self)) |
124 else: |
|
125 self.__connectionName = self.__language |
|
126 |
135 |
127 def __autoCompletionWordSeparators(self, language): |
136 def __autoCompletionWordSeparators(self, language): |
128 """ |
137 """ |
129 Private method to get the word separator characters for a language. |
138 Private method to get the word separator characters for a language. |
130 |
139 |
131 @param language language of the APIs object (string) |
140 @param language language of the APIs object (string) |
132 @return word separator characters (list of strings) |
141 @return word separator characters (list of strings) |
133 """ |
142 """ |
134 return self.__wseps.get(language, None) |
143 if language: |
|
144 return self.__wseps.get(language, None) |
|
145 else: |
|
146 return self.__proxy.autoCompletionWordSeparators() |
135 |
147 |
136 def abort(self): |
148 def abort(self): |
137 """ |
149 """ |
138 Public method to ask the thread to stop. |
150 Public method to ask the thread to stop. |
139 """ |
151 """ |
155 query.exec_() |
167 query.exec_() |
156 if query.next() and query.isValid(): # __IGNORE_WARNING_M513__ |
168 if query.next() and query.isValid(): # __IGNORE_WARNING_M513__ |
157 loadTime = QDateTime.fromString(query.value(0), Qt.ISODate) |
169 loadTime = QDateTime.fromString(query.value(0), Qt.ISODate) |
158 else: |
170 else: |
159 loadTime = QDateTime(1970, 1, 1, 0, 0) |
171 loadTime = QDateTime(1970, 1, 1, 0, 0) |
|
172 query.finish() |
160 del query |
173 del query |
161 finally: |
174 finally: |
162 db.commit() |
175 db.commit() |
163 if self.__projectPath: |
176 if self.__projectPath: |
164 modTime = QFileInfo(os.path.join(self.__projectPath, apiFile))\ |
177 modTime = QFileInfo(os.path.join(self.__projectPath, apiFile))\ |
291 @param apis list of api entries (list of strings) |
305 @param apis list of api entries (list of strings) |
292 @param bases list of base class entries (list of strings) |
306 @param bases list of base class entries (list of strings) |
293 @param apiFile filename of the file read to get the APIs (string) |
307 @param apiFile filename of the file read to get the APIs (string) |
294 @param language programming language of the file of the APIs (string) |
308 @param language programming language of the file of the APIs (string) |
295 """ |
309 """ |
296 if language: |
310 wseps = self.__autoCompletionWordSeparators(language) |
297 wseps = self.__autoCompletionWordSeparators(language) |
|
298 else: |
|
299 wseps = self.__proxy.autoCompletionWordSeparators() |
|
300 if wseps is None: |
311 if wseps is None: |
301 return |
312 return |
302 |
313 |
303 db = QSqlDatabase.database(self.__connectionName) |
314 db = QSqlDatabase.database(self.__connectionName) |
304 db.transaction() |
315 db.transaction() |
449 # step 4: delete the file entry |
461 # step 4: delete the file entry |
450 query.prepare(self.file_delete_id_stmt) |
462 query.prepare(self.file_delete_id_stmt) |
451 query.bindValue(":id", fileId) |
463 query.bindValue(":id", fileId) |
452 query.exec_() |
464 query.exec_() |
453 finally: |
465 finally: |
|
466 query.finish() |
454 del query |
467 del query |
455 db.commit() |
468 db.commit() |
|
469 |
|
470 def __getApiFiles(self): |
|
471 """ |
|
472 Private method to get a list of API files loaded into the database. |
|
473 |
|
474 @return list of API filenames |
|
475 @rtype list of str |
|
476 """ |
|
477 apiFiles = [] |
|
478 |
|
479 db = QSqlDatabase.database(self.__connectionName) |
|
480 db.transaction() |
|
481 try: |
|
482 query = QSqlQuery(db) |
|
483 query.exec_(self.api_files_stmt) |
|
484 while query.next(): # __IGNORE_WARNING_M513__ |
|
485 apiFiles.append(query.value(0)) |
|
486 finally: |
|
487 query.finish() |
|
488 del query |
|
489 db.commit() |
|
490 |
|
491 return apiFiles |
456 |
492 |
457 def run(self): |
493 def run(self): |
458 """ |
494 """ |
459 Public method to perform the threads work. |
495 Public method to perform the threads work. |
460 """ |
496 """ |
461 self.processing.emit(WorkerStatusStarted, "") |
497 self.processing.emit(WorkerStatusStarted, "") |
462 |
498 |
463 db = QSqlDatabase.database(self.__connectionName) |
499 db = QSqlDatabase.addDatabase("QSQLITE", self.__connectionName) |
|
500 db.setDatabaseName(self.__databaseName) |
|
501 db.open() |
|
502 |
464 if db.isValid() and db.isOpen(): |
503 if db.isValid() and db.isOpen(): |
465 # step 1: remove API files not wanted any longer |
504 # step 1: remove API files not wanted any longer |
466 if not self.__refresh: |
505 if not self.__refresh: |
467 loadedApiFiles = self.__proxy.getApiFiles() |
506 loadedApiFiles = self.__getApiFiles() |
468 for apiFile in loadedApiFiles: |
507 for apiFile in loadedApiFiles: |
469 if not self.__aborted and apiFile not in self.__apiFiles: |
508 if not self.__aborted and apiFile not in self.__apiFiles: |
470 self.__deleteApiFile(apiFile) |
509 self.__deleteApiFile(apiFile) |
471 |
510 |
472 # step 2: (re-)load api files |
511 # step 2: (re-)load api files |
473 for apiFile in self.__apiFiles: |
512 for apiFile in self.__apiFiles: |
474 if not self.__aborted: |
513 if not self.__aborted: |
475 self.__loadApiFileIfNewer(apiFile) |
514 self.__loadApiFileIfNewer(apiFile) |
|
515 |
|
516 db.close() |
476 |
517 |
477 if self.__aborted: |
518 if self.__aborted: |
478 self.processing.emit(WorkerStatusAborted, "") |
519 self.processing.emit(WorkerStatusAborted, "") |
479 else: |
520 else: |
480 self.processing.emit(WorkerStatusFinished, "") |
521 self.processing.emit(WorkerStatusFinished, "") |
695 self.__worker.wait(5000) |
736 self.__worker.wait(5000) |
696 |
737 |
697 if QSqlDatabase and QSqlDatabase.database( |
738 if QSqlDatabase and QSqlDatabase.database( |
698 self.__connectionName).isOpen(): |
739 self.__connectionName).isOpen(): |
699 QSqlDatabase.database(self.__connectionName).close() |
740 QSqlDatabase.database(self.__connectionName).close() |
700 QSqlDatabase.removeDatabase(self.__language) |
741 |
|
742 for connectionName in QSqlDatabase.connectionNames(): |
|
743 QSqlDatabase.removeDatabase(connectionName) |
701 |
744 |
702 self.__opened = False |
745 self.__opened = False |
703 |
746 |
704 def __openApiDb(self): |
747 def __openApiDb(self): |
705 """ |
748 """ |
799 query.next() # __IGNORE_WARNING_M513__ |
844 query.next() # __IGNORE_WARNING_M513__ |
800 formatVersion = int(query.value(0)) |
845 formatVersion = int(query.value(0)) |
801 if formatVersion >= self.DB_VERSION: |
846 if formatVersion >= self.DB_VERSION: |
802 prepared = True |
847 prepared = True |
803 finally: |
848 finally: |
|
849 query.finish() |
804 del query |
850 del query |
805 db.commit() |
851 db.commit() |
806 return prepared |
852 return prepared |
807 |
853 |
808 def getCompletions(self, start=None, context=None, followHierarchy=False): |
854 def getCompletions(self, start=None, context=None, followHierarchy=False): |
862 else: |
909 else: |
863 bases = [] |
910 bases = [] |
864 for base in bases: |
911 for base in bases: |
865 completions.extend(self.getCompletions(start, base, |
912 completions.extend(self.getCompletions(start, base, |
866 followHierarchy=True)) |
913 followHierarchy=True)) |
|
914 query.finish() |
|
915 del query |
867 |
916 |
868 return completions |
917 return completions |
869 |
918 |
870 def getCalltips(self, acWord, commas, context=None, fullContext=None, |
919 def getCalltips(self, acWord, commas, context=None, fullContext=None, |
871 showContext=True, followHierarchy=False): |
920 showContext=True, followHierarchy=False): |
937 bases = [] |
987 bases = [] |
938 for base in bases: |
988 for base in bases: |
939 calltips.extend(self.getCalltips( |
989 calltips.extend(self.getCalltips( |
940 acWord, commas, context=base, showContext=showContext, |
990 acWord, commas, context=base, showContext=showContext, |
941 followHierarchy=True)) |
991 followHierarchy=True)) |
|
992 query.finish() |
|
993 del query |
942 |
994 |
943 if context and len(calltips) == 0 and not followHierarchy: |
995 if context and len(calltips) == 0 and not followHierarchy: |
944 # nothing found, try without a context |
996 # nothing found, try without a context |
945 calltips = self.getCalltips( |
997 calltips = self.getCalltips( |
946 acWord, commas, showContext=showContext) |
998 acWord, commas, showContext=showContext) |
1034 except TypeError: |
1086 except TypeError: |
1035 # older interface |
1087 # older interface |
1036 apiFiles = Preferences.getEditorAPI(self.__language) |
1088 apiFiles = Preferences.getEditorAPI(self.__language) |
1037 projectType = self.__projectType |
1089 projectType = self.__projectType |
1038 self.__worker = DbAPIsWorker(self, self.__language, apiFiles, |
1090 self.__worker = DbAPIsWorker(self, self.__language, apiFiles, |
1039 projectPath, projectType=projectType) |
1091 self._apiDbName(), projectPath, |
|
1092 projectType=projectType) |
1040 self.__worker.processing.connect( |
1093 self.__worker.processing.connect( |
1041 self.__processingStatus, Qt.QueuedConnection) |
1094 self.__processingStatus, Qt.QueuedConnection) |
1042 self.__worker.start() |
1095 self.__worker.start() |
1043 |
1096 |
1044 def __processQueue(self): |
1097 def __processQueue(self): |
1057 projectType = "" |
1110 projectType = "" |
1058 else: |
1111 else: |
1059 projectPath = "" |
1112 projectPath = "" |
1060 projectType = self.__projectType |
1113 projectType = self.__projectType |
1061 self.__worker = DbAPIsWorker(self, self.__language, apiFiles, |
1114 self.__worker = DbAPIsWorker(self, self.__language, apiFiles, |
1062 projectPath, projectType=projectType, |
1115 self._apiDbName(), projectPath, |
1063 refresh=True) |
1116 projectType=projectType, refresh=True) |
1064 self.__worker.processing.connect( |
1117 self.__worker.processing.connect( |
1065 self.__processingStatus, Qt.QueuedConnection) |
1118 self.__processingStatus, Qt.QueuedConnection) |
1066 self.__worker.start() |
1119 self.__worker.start() |
1067 |
1120 |
1068 def getLexer(self): |
1121 def getLexer(self): |