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)
Exemple #2
0
    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)
Exemple #4
0
 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)
Exemple #6
0
    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)
Exemple #7
0
 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)
Exemple #10
0
    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
Exemple #12
0
 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)
Exemple #14
0
    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()
Exemple #15
0
    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)
Exemple #18
0
    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])
Exemple #19
0
    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])
Exemple #20
0
    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)
Exemple #21
0
 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)
Exemple #23
0
 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))
Exemple #25
0
 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()
Exemple #27
0
    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))
Exemple #28
0
    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")
Exemple #30
0
    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
Exemple #31
0
 def __open_database(self, path=''):
     central_widget = Pireal.get_service("central")
     central_widget.open_database(path)
Exemple #32
0
 def __new_relation(self):
     central_service = Pireal.get_service("central")
     central_service.create_new_relation()
Exemple #33
0
 def __open_preferences(self):
     central_widget = Pireal.get_service("central")
     central_widget.show_settings()
Exemple #34
0
 def __remove_current(self, path):
     central_widget = Pireal.get_service("central")
     central_widget.recent_databases.remove(path)
Exemple #35
0
    def __init__(self):
        super(StatusBar, self).__init__()

        Pireal.load_service("status", self)

        self.messageChanged['QString'].connect(self.__message_end)
Exemple #36
0
    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
Exemple #37
0
    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
Exemple #38
0
 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()