def __on_copy_available(self, value): """ Change states of cut and copy action """ cut_action = Pireal.get_action("cut_action") cut_action.setEnabled(value) copy_action = Pireal.get_action("copy_action") copy_action.setEnabled(value)
def __init__(self): super(StatusBar, self).__init__() Pireal.load_service("status", self) self.connect(self, SIGNAL("messageChanged(QString)"), self.__message_end)
def execute_queries(self, query=''): """ This function executes queries """ # Hide tooltip if visible if QToolTip.isVisible(): QToolTip.hideText() # If text is selected, then this text is the query, # otherwise the query is all text that has the editor editor_widget = self.currentWidget().get_editor() if editor_widget.textCursor().hasSelection(): query = editor_widget.textCursor().selectedText() else: query = editor_widget.toPlainText() relations = self.currentWidget().relations central = Pireal.get_service("central") table_widget = central.get_active_db().table_widget # Restore relations.clear() self.currentWidget().clear_results() # Parse query sc = scanner.Scanner(query) lex = lexer.Lexer(sc) try: par = parser.Parser(lex) interpreter = parser.Interpreter(par) interpreter.clear() interpreter.to_python() except Exception as reason: pireal = Pireal.get_service("pireal") pireal.show_error_message(self.parse_error(reason.__str__())) return relations.update(table_widget.relations) for relation_name, expression in list(interpreter.SCOPE.items()): if relation_name in relations: QMessageBox.critical(self, self.tr("Query Error"), self.tr("<b>{}</b> is a duplicate " "relation name.<br><br> " "Please choose a unique name " "and re-execute the " "queries.".format( relation_name))) del interpreter.SCOPE[relation_name] return try: new_relation = eval(expression, {}, relations) except Exception as reason: pireal = Pireal.get_service("pireal") pireal.show_error_message(self.parse_error(reason.__str__()), syntax_error=False) return relations[relation_name] = new_relation self.__add_table(new_relation, relation_name)
def execute_queries(self): # Editor instance query_editor = Pireal.get_service("query-editor").editor query = query_editor.toPlainText() # Text # Parse query expression = parser.convert_to_python(query) table_widget = Pireal.get_service("db") rel = eval(expression, table_widget.relations)
def add_table(self, rela, rname): central_widget = Pireal.get_service("central") lateral_widget = Pireal.get_service("lateral_widget") db = central_widget.get_active_db() _view = db.create_table(rela, rname, editable=False) table_widget = central_widget.get_active_db().table_widget index = table_widget.stacked_result.addWidget(_view) table_widget.stacked_result.setCurrentIndex(index) lateral_widget.result_list.add_item( rname, rela.cardinality(), rela.degree()) # lateral_widget.result_list.select_last() table_widget._tabs.setCurrentIndex(1)
def new_query(self, filename=''): query_widget = Pireal.get_service("query_widget") self.addWidget(query_widget) if not query_widget.isVisible(): query_widget.show() pireal = Pireal.get_service("pireal") pireal.enable_disable_query_actions() query_widget.new_query(filename) self.connect(query_widget, SIGNAL("currentEditorSaved(QPlainTextEdit)"), self.save_query)
def new_query(self): from src.gui.query_editor import query_widget widget = query_widget.QueryWidget() pireal = Pireal.get_service("pireal") # Load the instance Pireal.load_service("query-editor", widget) # MdiArea mdi = Pireal.get_service("mdi") widget.setMinimumSize(mdi.width(), mdi.minimumSizeHint().height()) mdi.addSubWindow(widget) # Enable querie's QAction pireal.enable_disable_query_actions() widget.show()
def __init__(self, parent=None): super(Notification, self).__init__(parent) box = QVBoxLayout(self) box.setContentsMargins(50, 0, 0, 0) self.notificator = QLabel("") box.addWidget(self.notificator) # Timer self.timer = QTimer(self) self.timer.timeout.connect(self.clear) # Install service Pireal.load_service("notification", self)
def __init__(self): super(LateralWidget, self).__init__() self._list_widget = QListWidget() self.setWidget(self._list_widget) Pireal.load_service("lateral", self) self._list_widget.setContextMenuPolicy(Qt.CustomContextMenu) self.connect(self._list_widget, SIGNAL("currentRowChanged(int)"), self._change_item) self.connect(self._list_widget, SIGNAL("customContextMenuRequested(const QPoint)"), self.__show_context_menu)
def __init__(self, orientation=Qt.Vertical): super(Container, self).__init__(orientation) self._data_bases = [] self.__filename = "" vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) self.__created = False # Stacked self.stacked = QStackedWidget() vbox.addWidget(self.stacked) # Table self.table_widget = table_widget.TableWidget() Pireal.load_service("container", self)
def clear_results(self): central_widget = Pireal.get_service("central") lateral_widget = Pireal.get_service("lateral_widget") lateral_widget.result_list.clear_items() table_widget = central_widget.get_active_db().table_widget i = table_widget.stacked_result.count() # i = self._stack_tables.count() while i >= 0: # widget = self._stack_tables.widget(i) widget = table_widget.stacked_result.widget(i) # self._stack_tables.removeWidget(widget) table_widget.stacked_result.removeWidget(widget) if widget is not None: widget.deleteLater() i -= 1
def create_data_base(self): mdi = Pireal.get_service("mdi") db_name, ok = QInputDialog.getText(mdi, self.tr("New DB"), self.tr("Name:"), text=getpass.getuser()) if ok: from src.gui import table_widget db_widget = table_widget.MdiDB() db_widget.setWindowTitle(db_name + '.pdb') db_widget.setMinimumSize(mdi.width(), mdi.height() / 1.7) mdi.addSubWindow(db_widget) # Enable QAction's pireal = Pireal.get_service("pireal") pireal.enable_disable_db_actions() db_widget.show()
def __init__(self): QWidget.__init__(self) box = QVBoxLayout(self) box.setContentsMargins(0, 0, 0, 0) box.setSpacing(0) self.stacked = QStackedWidget() box.addWidget(self.stacked) self.created = False self.__last_open_folder = None self.__recent_dbs = [] if PSetting.RECENT_DBS: self.__recent_dbs = PSetting.RECENT_DBS Pireal.load_service("central", self)
def _check_count(self): """ Hide dock if count = 0 """ if self.tab.count() == 0: pireal = Pireal.get_service("pireal") pireal.enable_disable_query_actions(False) self.hide()
def execute_queries(self): import re # Editor instance editor = self.tab.currentWidget() # Text text = editor.toPlainText() # Ignore comments table = Pireal.get_service("container").table_widget for line in text.splitlines(): if line.startswith('--'): continue parts = line.split('=', 1) parts[0] = parts[0].strip() if re.match(r'^[_a-zA-Z]+[_a-zA-Z0-9]*$', parts[0]): relation_name, line = parts else: relation_name = 'rel_{}'.format(self.__nrelation) self.__nrelation += 1 try: expression = parser.convert_to_python(line.strip()) rel = eval(expression, table.relations) except Exception as reason: #try: #except Exception as reason: QMessageBox.critical(self, self.tr("Error en consulta"), reason.__str__()) return table.add_new_table(rel, relation_name) table.relations[relation_name] = rel
def __on_wizard_finished(self, data, wizard_widget): """ This slot execute when wizard to create a database is finished """ pireal = Pireal.get_service("pireal") if not data: # If it's canceled, remove wizard widget and return to Start Page self.remove_last_widget() else: # Create a new data base container db_container = database_container.DatabaseContainer() # Associate the file name with the PFile object pfile_object = pfile.File(data['filename']) # Associate PFile object with data base container # and add widget to stacked db_container.pfile = pfile_object self.add_widget(db_container) # Remove wizard self.stacked.removeWidget(wizard_widget) # Set window title pireal.change_title(file_manager.get_basename(data['filename'])) # Enable db actions pireal.set_enabled_db_actions(True) pireal.set_enabled_relation_actions(True) self.created = True DEBUG("Base de datos creada correctamente: '{}'".format( data['filename'])) # If data or not, show menubar and toolbar again pireal.show_hide_menubar() pireal.show_hide_toolbar()
def __hide(self): if self.count() == 0: self.hide() # Disable query actions pireal = Pireal.get_service("pireal") pireal.set_enabled_query_actions(False) pireal.set_enabled_editor_actions(False)
def add_new_table(self, rel, name): import itertools table = QTableWidget() table.setRowCount(0) table.setColumnCount(0) data = itertools.chain([rel.fields], rel.content) for row_data in data: row = table.rowCount() table.setColumnCount(len(row_data)) for col, text in enumerate(row_data): item = QTableWidgetItem() item.setText(text) if row == 0: table.setHorizontalHeaderItem(col, item) else: table.setItem(row - 1, col, item) table.insertRow(row) table.removeRow(table.rowCount() - 1) self.stacked.addWidget(table) self.stacked.setCurrentIndex(self.stacked.count() - 1) lateral = Pireal.get_service("lateral") lateral.add_item_list([name])
def add_data_base(self, data): lateral = Pireal.get_service("lateral") rel = None for part in data.split('@'): for e, line in enumerate(part.splitlines()): if e == 0: name = line.split(':')[0] rel = relation.Relation() rel.fields = line.split(':')[-1].split(',') else: rel.insert(line.split(',')) if rel is not None: table = Table() table.setRowCount(1) table.setColumnCount(0) self.relations[name] = rel for _tuple in rel.content: row = table.rowCount() table.setColumnCount(len(rel.fields)) for column, text in enumerate(_tuple): item = Item() item.setText(text) table.setItem(row - 1, column, item) table.insertRow(row) table.setHorizontalHeaderLabels(rel.fields) self.stacked.addWidget(table) table.removeRow(table.rowCount() - 1) lateral.add_item_list([name])
def __init__(self, orientation=Qt.Vertical): super(Container, self).__init__(orientation) self.__last_open_folder = None self.__filename = "" self.__created = False self.__modified = False vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) # Stacked self.stacked = QStackedWidget() vbox.addWidget(self.stacked) # Table self.table_widget = table_widget.TableWidget() Pireal.load_service("container", self)
def __open_example(self): central_widget = Pireal.get_service("central") db_filename = os.path.join(settings.EXAMPLES, 'database.pdb') central_widget.open_database(filename=db_filename, remember=False) query_filename = os.path.join(settings.EXAMPLES, 'queries.pqf') central_widget.open_query(filename=query_filename, remember=False) # Ejecuto las consultas de ejemplo luego de 1.3 segundos QTimer.singleShot(1300, central_widget.execute_queries)
def execute_queries(self, query=''): """ This function executes queries """ # If text is selected, then this text is the query, # otherwise the query is all text that has the editor editor_widget = self.currentWidget().get_editor() if editor_widget.textCursor().hasSelection(): query = "\n".join( editor_widget.textCursor().selectedText().splitlines()) else: query = editor_widget.toPlainText() relations = self.currentWidget().relations central = Pireal.get_service("central") table_widget = central.get_active_db().table_widget # Restore relations.clear() self.currentWidget().clear_results() editor_widget.show_run_cursor() # Parse query error = True try: result = parser.parse(query) except MissingQuoteError as reason: title = self.tr("Error de Sintáxis") text = self.parse_error(str(reason)) except InvalidSyntaxError as reason: title = self.tr("Error de Sintáxis") text = self.parse_error(str(reason) + "\n" + self.tr( "El error comienza con " + reason.character)) except DuplicateRelationNameError as reason: title = self.tr("Nombre duplicado") text = self.tr("Ya existe una relación con el nombre <b>{}</b> :(." "<br><br>Elige otro por favor ;).".format( reason.rname)) except ConsumeError as reason: title = self.tr("Error de Sintáxis") text = self.parse_error(str(reason)) else: error = False if error: QMessageBox.critical(self, title, text) return relations.update(table_widget.relations) for relation_name, expression in result.items(): try: new_relation = eval(expression, {}, relations) except Exception as reason: QMessageBox.critical( self, self.tr("Error de Consulta"), self.parse_error(str(reason)) ) return relations[relation_name] = new_relation self.__add_table(new_relation, relation_name)
def _change_font(self, font): # FIXME: un quilombo esto central = Pireal.get_service("central") mcontainer = central.get_active_db() if mcontainer is not None: query_widget = mcontainer.query_container.currentWidget() if query_widget is not None: weditor = query_widget.get_editor() if weditor is not None: qs = QSettings(settings.SETTINGS_PATH, QSettings.IniFormat) weditor.set_font(font) qs.setValue("font", font)
def __init__(self, parent=None): super().__init__(parent) self.setOrientation(Qt.Vertical) # Lista de relaciones de la base de datos self._relations_list = RelationListQML() self._relations_list.set_title(self.tr("Relaciones")) self.addWidget(self._relations_list) # Lista de relaciones del resultado de consultas self._results_list = RelationListQML() self._results_list.set_title(self.tr("Resultados")) self.addWidget(self._results_list) Pireal.load_service("lateral_widget", self) self._relations_list.itemClicked.connect( lambda i: self.relationClicked.emit(i)) # self._relations_list.row())) # self._relations_list.itemSelectionChanged.connect( # lambda: self.relationSelectionChanged.emit( # self._relations_list.row())) self._results_list.itemClicked.connect( lambda i: self.resultClicked.emit(i))
def save_query_as(self, editor=None): if editor is None: query_widget = Pireal.get_service("query_widget") editor = query_widget.get_active_editor() directory = os.path.expanduser("~") filename = QFileDialog.getSaveFileName(self, self.tr("Guardar Archivo"), directory) if not filename: return content = editor.toPlainText() editor.rfile.write(content, filename) editor.document().setModified(False)
def __undock_editor(self): new_editor = editor.Editor() actual_doc = self._editor.document() new_editor.setDocument(actual_doc) new_editor.resize(900, 400) # Set text cursor tc = self._editor.textCursor() new_editor.setTextCursor(tc) # Set title db = Pireal.get_service("central").get_active_db() qc = db.query_container new_editor.setWindowTitle(qc.tab_text(qc.current_index())) new_editor.show()
def save_query(self, weditor=None): if weditor is None: query_widget = Pireal.get_service("query_widget") # Editor instance weditor = query_widget.get_active_editor() if weditor.rfile.is_new: return self.save_query_as(weditor) content = weditor.toPlainText() weditor.rfile.write(content) weditor.document().setModified(False) self.emit(SIGNAL("currentFileSaved(QString)"), self.tr("Archivo guardado: {}").format(weditor.filename))
def __init__(self): super(QueryWidget, self).__init__() self.__nrelation = 1 self.__nquery = 1 self._cursor_position = "Lin: %s, Col: %s" self._cursor_position_widget = QLabel(self._cursor_position % (0, 0)) box = QVBoxLayout(self) box.setContentsMargins(0, 0, 5, 0) # Tabs self.tab = QTabWidget() self.tab.setCornerWidget(self._cursor_position_widget) self.tab.setTabsClosable(True) self.tab.setMovable(True) box.addWidget(self.tab) Pireal.load_service("query_widget", self) # Connections self.connect(self.tab, SIGNAL("tabCloseRequested(int)"), self.removeTab) self.connect(self.tab, SIGNAL("tabCloseRequested(int)"), self._check_count)
def _on_finished(self, code, status): if status == QProcess.NormalExit == code: QMessageBox.information( self, self.tr("Completado!"), self.tr("Todo ha salido muy bien!")) if self._check_open.isChecked(): central = Pireal.get_service("central") rdb = os.path.splitext(self._line_location.text())[0] pdb = rdb + ".pdb" central.open_database(pdb) self.close() else: QMessageBox.critical( self, "Error", "El proceso no se ha completado")
def close_db(self): """ Close data base """ widget = self.stacked.currentWidget() if isinstance(widget, table_widget.TableWidget): # Clear list of relations lateral = Pireal.get_service("lateral") lateral.clear_items() lateral.hide() # Close table widget self.stacked.removeWidget(widget) # Add start page self.show_start_page() self.__created = False
def __open_database(self, path=''): central_widget = Pireal.get_service("central") central_widget.open_database(path)
def __new_relation(self): central_service = Pireal.get_service("central") central_service.create_new_relation()
def __open_preferences(self): central_widget = Pireal.get_service("central") central_widget.show_settings()
def __remove_current(self, path): central_widget = Pireal.get_service("central") central_widget.recent_databases.remove(path)
def __init__(self): super(StatusBar, self).__init__() Pireal.load_service("status", self) self.messageChanged['QString'].connect(self.__message_end)
def open_database(self, filename='', remember=True): """ This function opens a database and set this on the UI """ if self.created: return self.__say_about_one_db_at_time() # If not filename provide, then open dialog to select if not filename: if self.__last_open_folder is None: directory = os.path.expanduser("~") else: directory = self.__last_open_folder filter_ = settings.SUPPORTED_FILES.split(';;')[0] filename, _ = QFileDialog.getOpenFileName( self, self.tr("Abrir Base de " "Datos"), directory, filter_) # If is canceled, return if not filename: return # If filename provide try: logger.debug("Intentando abrir el archivo {}".format(filename)) # Read pdb file pfile_object = pfile.File(filename) db_data = pfile_object.read() # Create a dict to manipulate data more easy db_data = self.__sanitize_data(db_data) except Exception as reason: QMessageBox.information(self, self.tr("El archivo no se puede abrir"), reason.__str__()) logger.debug("Error al abrir el archivo {0}: '{1}'".format( filename, reason.__str__())) return # Create a database container widget db_container = database_container.DatabaseContainer() try: db_container.create_database(db_data) except Exception as reason: QMessageBox.information(self, self.tr("Error"), str(reason)) logger.debug("Error al crear la base de datos: {}".format( reason.__str__())) return # Set the PFile object to the new database db_container.pfile = pfile_object # Add data base container to stacked self.add_widget(db_container) # Database name db_name = file_manager.get_basename(filename) # Update title with the new database name, and enable some actions pireal = Pireal.get_service("pireal") self.databaseConected.emit(self.tr("Conectado a: {}".format(db_name))) pireal.set_enabled_db_actions(True) pireal.set_enabled_relation_actions(True) if remember: # Add to recent databases self.recent_databases = filename # Remember the folder self.__last_open_folder = file_manager.get_path(filename) self.created = True
def close_database(self): """ Close the database and return to the main widget """ db = self.get_active_db() query_container = db.query_container if db.modified: msgbox = QMessageBox(self) msgbox.setIcon(QMessageBox.Question) msgbox.setWindowTitle(self.tr("Guardar cambios?")) msgbox.setText( self.tr("La base de datos <b>{}</b> ha sido " "modificada.<br>Quiere guardar los " "cambios?".format(db.dbname()))) cancel_btn = msgbox.addButton(self.tr("Cancelar"), QMessageBox.RejectRole) msgbox.addButton(self.tr("No"), QMessageBox.NoRole) yes_btn = msgbox.addButton(self.tr("Si"), QMessageBox.YesRole) msgbox.exec_() r = msgbox.clickedButton() if r == cancel_btn: return if r == yes_btn: self.save_database() # Check if editor is modified query_widget = query_container.currentWidget() if query_widget is not None: weditor = query_widget.get_editor() if weditor is not None: # TODO: duplicate code, see tab widget if weditor.modified: msgbox = QMessageBox(self) msgbox.setIcon(QMessageBox.Question) msgbox.setWindowTitle(self.tr("Archivo modificado")) msgbox.setText( self.tr("El archivo <b>{}</b> tiene cambios" " no guardados. Quiere " "mantenerlos?".format(weditor.name))) cancel_btn = msgbox.addButton(self.tr("Cancelar"), QMessageBox.RejectRole) msgbox.addButton(self.tr("No"), QMessageBox.NoRole) yes_btn = msgbox.addButton(self.tr("Si"), QMessageBox.YesRole) msgbox.exec_() r = msgbox.clickedButton() if r == cancel_btn: return if r == yes_btn: self.save_query(weditor) self.stacked.removeWidget(db) pireal = Pireal.get_service("pireal") pireal.set_enabled_db_actions(False) pireal.set_enabled_relation_actions(False) pireal.set_enabled_query_actions(False) pireal.set_enabled_editor_actions(False) pireal.change_title() # Título en la ventana principal 'Pireal' self.created = False del db
def __new_database(self): central_widget = Pireal.get_service("central") central_widget.create_database()
def _create(self): relation_name = self._line_relation_name.text().strip() if not relation_name: QMessageBox.critical(self, "Error", self.tr("Relation name " "not specified")) return central = Pireal.get_service("central") if relation_name in central.get_active_db().table_widget.relations: QMessageBox.information( self, "Error", self.tr("Ya existe una relación con el nombre " "<b>{}</b>.".format(relation_name)) ) return # Table model model = self._view.model() # Row and column count nrow = model.rowCount() ncol = model.columnCount() # Create new relation object rela = relation.Relation() # Header try: header = [] for i in range(ncol): text = model.horizontalHeaderItem(i).text().strip() header.append(text) rela.header = header except Exception as reason: QMessageBox.critical(self, self.tr("Header error"), str(reason)) return # Load relation for row in range(nrow): tuples = [] for column in range(ncol): item = model.item(row, column) try: if not item.text().strip(): raise Exception except: QMessageBox.information( self, "Algo ha salido mal", self.tr("Los espacios en blanco son tan aburridos :/." "<br><br>Por favor ingrese un dato en la " "fila <b>{}</b>, columna:<b>{}</b>".format( row + 1, column + 1))) return tuples.append(item.text().strip()) rela.insert(tuple(tuples)) # Data # self.data = rela, relation_name self.created.emit(rela, relation_name) self.close()