示例#1
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        container = QWidget()
        layout = QVBoxLayout()

        self.search = QLineEdit()
        self.search.textChanged.connect(self.update_filter)
        self.table = QTableView()

        layout.addWidget(self.search)
        layout.addWidget(self.table)
        container.setLayout(layout)

        self.model = QSqlTableModel(db=db)

        self.table.setModel(self.model)

        self.model.setTable("Track")
        self.model.select()

        self.setMinimumSize(QSize(1024, 600))
        self.setCentralWidget(container)

    # tag::filter[]
    def update_filter(self, s):
        s = re.sub("[\W_]+", "", s)
        filter_str = 'Name LIKE "%{}%"'.format(s)
        self.model.setFilter(filter_str)
示例#2
0
class AddAssetDialog(QDialog, Ui_AddAssetDialog):
    def __init__(self, parent, db, symbol):
        QDialog.__init__(self)
        self.setupUi(self)
        self.db = db
        self.asset_id = None

        self.SymbolEdit.setText(symbol)

        self.type_model = QSqlTableModel(db=db)
        self.type_model.setTable('asset_types')
        self.type_model.select()
        self.TypeCombo.setModel(self.type_model)
        self.TypeCombo.setModelColumn(1)

        self.data_src_model = QSqlTableModel(db=db)
        self.data_src_model.setTable('data_sources')
        self.data_src_model.select()
        self.DataSrcCombo.setModel(self.data_src_model)
        self.DataSrcCombo.setModelColumn(1)

        # center dialog with respect to parent window
        x = parent.x() + parent.width()/2 - self.width()/2
        y = parent.y() + parent.height()/2 - self.height()/2
        self.setGeometry(x, y, self.width(), self.height())

    def accept(self):
        self.asset_id = addNewAsset(self.db, self.SymbolEdit.text(), self.NameEdit.text(),
                                    self.type_model.record(self.TypeCombo.currentIndex()).value("id"),
                                    self.isinEdit.text(),
                                    self.data_src_model.record(self.DataSrcCombo.currentIndex()).value("id"))
        super().accept()
示例#3
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.table = QTableView()

        self.model = QSqlTableModel(db=db)

        self.table.setModel(self.model)

        # tag::titles[]
        self.model.setTable("Track")
        column_titles = {
            "Name": "Name",
            "AlbumId": "Album (ID)",
            "MediaTypeId": "Media Type (ID)",
            "GenreId": "Genre (ID)",
            "Composer": "Composer",
        }
        for n, t in column_titles.items():
            idx = self.model.fieldIndex(n)
            self.model.setHeaderData(idx, Qt.Horizontal, t)

        self.model.select()
        # end::titles[]

        self.model.select()

        self.setMinimumSize(QSize(1024, 600))
        self.setCentralWidget(self.table)
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        form = QFormLayout()

        self.track_id = QSpinBox()
        self.track_id.setRange(0, 2147483647)
        self.track_id.setDisabled(True)
        self.name = QLineEdit()
        self.album = QComboBox()
        self.media_type = QComboBox()
        self.genre = QComboBox()
        self.composer = QLineEdit()

        self.milliseconds = QSpinBox()
        self.milliseconds.setRange(0, 2147483647)  # <1>
        self.milliseconds.setSingleStep(1)

        self.bytes = QSpinBox()
        self.bytes.setRange(0, 2147483647)
        self.bytes.setSingleStep(1)

        self.unit_price = QDoubleSpinBox()
        self.unit_price.setRange(0, 999)
        self.unit_price.setSingleStep(0.01)
        self.unit_price.setPrefix("$")

        form.addRow(QLabel("Track ID"), self.track_id)
        form.addRow(QLabel("Track name"), self.name)
        form.addRow(QLabel("Composer"), self.composer)
        form.addRow(QLabel("Milliseconds"), self.milliseconds)
        form.addRow(QLabel("Bytes"), self.bytes)
        form.addRow(QLabel("Unit Price"), self.unit_price)

        self.model = QSqlTableModel(db=db)

        self.mapper = QDataWidgetMapper()  # <2>
        self.mapper.setModel(self.model)

        self.mapper.addMapping(self.track_id, 0)  # <3>
        self.mapper.addMapping(self.name, 1)
        self.mapper.addMapping(self.composer, 5)
        self.mapper.addMapping(self.milliseconds, 6)
        self.mapper.addMapping(self.bytes, 7)
        self.mapper.addMapping(self.unit_price, 8)

        self.model.setTable("Track")
        self.model.select()  # <4>

        self.mapper.toFirst()  # <5>

        self.setMinimumSize(QSize(400, 400))

        widget = QWidget()
        widget.setLayout(form)
        self.setCentralWidget(widget)
示例#5
0
    def update_torna_settings(self):
        torna_settings_model = QSqlTableModel(db=db)
        torna_settings_model.setTable("torna_settings")
        record = torna_settings_model.record()
        torna_settings_model.select()
        # for x in range(torna_settings_model.rowCount()):
        #     record.setGenerated(x, False)
        record.setValue(0, self.torna_id)
        record.setValue(1, self.torna_name.text())
        if self.is_roundrobin.isChecked():
            record.setValue(2, 1)
        else:
            record.setValue(2, 0)
        record.setValue(3, self.csoport_number.value())
        record.setValue(4, self.jatekos_per_csoport.value())
        record.setValue(5, self.variant.value())
        if self.is_sets.isChecked():
            record.setValue(6, 1)
        else:
            record.setValue(6, 0)
        record.setValue(7, self.sets_number.value())
        record.setValue(8, self.legs_number.value())
        if self.is_best.isChecked():
            record.setValue(9, 1)
        else:
            record.setValue(9, 0)
        if self.is_draw.isChecked():
            record.setValue(10, 1)
        else:
            record.setValue(10, 0)
        record.setValue(11, self.pont_win.value())
        record.setValue(12, self.pont_draw.value())
        record.setValue(13, self.pont_lost.value())
        if self.is_single_elim.isChecked():
            record.setValue(14, 1)
        else:
            record.setValue(14, 0)
        record.setValue(15, self.num_single.value())
        if self.is_3place.isChecked():
            record.setValue(16, 1)
        else:
            record.setValue(16, 0)
        record.setValue(17, self.leg_num_single.value())
        record.setValue(18, self.leg_num_semifinal.value())
        record.setValue(19, self.leg_num_3place.value())
        record.setValue(20, self.leg_num_final.value())
        record.setValue(21, 2)

        for i in range(torna_settings_model.rowCount()):
            if torna_settings_model.record(i).value(0) == self.torna_id:
                # print(torna_settings_model.record(i).value(0), ":", i)
                record_number = i
        # print(record)
        if torna_settings_model.setRecord(record_number, record):
            torna_settings_model.submitAll()
        else:
            db.rollback()
示例#6
0
def get_terms_table(term_type: int) -> QSqlTableModel:
    model = QSqlTableModel()
    model.setTable("terms")
    model.setFilter(f"term_type = {term_type}")
    model.removeColumn(
        1)  # remove term_type column as it no longer carries any value
    model.select()
    while model.canFetchMore():
        model.fetchMore()
    return model
示例#7
0
class SQLite(QSqlDatabase):
    """
    Класс для инициализации и открытия базы данных каталога, полученный из Slot'а (openFile)
    """
    def __init__(self, path=None):
        """
        Инициализация экземпляра класса
        :param path: путь до каталога, полученный изиз Slot'а (openFile)
        """
        super().__init__()
        self.path = path
        self.width = 0
        self.heigh = 0
        self.db = QSqlDatabase.addDatabase('QSQLITE')
        self.db.setDatabaseName(self.path)
        self.db.open()
        self.window = QWidget()
        self.window.setWindowTitle("Каталог книг")
        self.conn = sqlite3.connect(self.path)
        cursor = self.conn.cursor()
        sql = f'select * from sqlite_master where type = "table"'  # получение имени таблицы(первая в списке), к которой будет
        # осуществлено подключение
        cursor.execute(sql)
        self.search_result = cursor.fetchall()[0][1]
        self.model = QSqlTableModel(parent=self.window, db=self.db)
        self.model.setTable(self.search_result)
        self.db_record = QSqlRecord(self.db.record(self.search_result))
        self.tableView = QTableView()

    def on(self):
        """
        Метод для подключения и отображения подключенного каталога
        :return: виджет self.window
        """
        self.model.setEditStrategy(QSqlTableModel.OnManualSubmit)
        self.model.select()
        self.model.setHeaderData(-1, Qt.Horizontal,
                                 self.db_record.fieldName(0))
        vbox = QVBoxLayout()
        self.tableView.setModel(self.model)
        self.tableView.resizeColumnsToContents()
        self.tableView.resizeRowsToContents()
        for i in range(self.model.columnCount() + 2):
            self.width += self.tableView.columnWidth(i)
        for j in range(self.model.rowCount() + 1):
            self.heigh += self.tableView.rowHeight(j)
        self.tableView.resize(self.width + 50, self.heigh + 50)
        vbox.addWidget(self.tableView)
        self.window.setLayout(vbox)
        self.window.resize(self.tableView.width() + 30,
                           self.tableView.height() + 120)
        return self.window
示例#8
0
class MainWindow(QMainWindow):
    """
    Class responsible for displaying primary interface.
    """
    def __init__(self):
        super().__init__()

        self.table = QTableView()
        self.model = QSqlTableModel(db=db)
        self.table.setModel(self.model)
        self.model.setTable("hello")
        self.model.select()
        self.setCentralWidget(self.table)
示例#9
0
class Window(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle('Desktop application')

        self._label = QLabel('Collection', self)

        self._open_button = QPushButton('Open')
        self._open_button.setToolTip('Choose the collection database')

        self._add_button = QPushButton('Add')
        self._add_button.setToolTip('Add a new entry into the collection')

        self._model = None
        self._view = QTableView(self)

        horizontal_layout = QHBoxLayout()
        horizontal_layout.addWidget(self._label)
        horizontal_layout.addWidget(self._open_button)
        horizontal_layout.addWidget(self._add_button)

        layout = QVBoxLayout()
        layout.addLayout(horizontal_layout)
        layout.addWidget(self._view)

        self.setLayout(layout)

        self._open_button.clicked.connect(self.__open_collection)
        self._add_button.clicked.connect(self.__add_new_entry)

    @Slot()
    def __open_collection(self):
        collection = QFileDialog.getOpenFileName()[0]
        db = QSqlDatabase.addDatabase('QSQLITE')
        db.setDatabaseName(collection)
        db.open()

        self._model = QSqlTableModel(self, db)
        self._model.setTable('objects')
        self._model.select()

        self._view.setModel(self._model)

    @Slot()
    def __add_new_entry(self):
        dialog = AddEntryDialog(self)

        if dialog.exec_() == AddEntryDialog.Accepted:
            entry = dialog.entry
            print(entry)
示例#10
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.table = QTableView()

        self.model = QSqlTableModel(db=db)

        self.table.setModel(self.model)

        self.model.setTable("Track")
        self.model.select()

        self.setMinimumSize(QSize(1024, 600))
        self.setCentralWidget(self.table)
示例#11
0
 def alapertekek(self):
     if not self.torna_id:
         self.torna_name.clear()
         self.is_roundrobin.setChecked(True)
         self.csoport_number.setValue(1)
         self.jatekos_per_csoport.setValue(4)
         self.variant.setValue(501)
         self.is_sets.setChecked(False)
         self.sets_number.setValue(1)
         self.legs_number.setValue(2)
         self.is_best.setChecked(False)
         self.is_draw.setChecked(False)
         self.pont_win.setValue(2)
         self.pont_draw.setValue(1)
         self.pont_lost.setValue(0)
         self.is_single_elim.setChecked(False)
         self.num_single.setValue(8)
         self.leg_num_single.setValue(3)
         self.leg_num_semifinal.setValue(4)
         self.leg_num_final.setValue(5)
         self.is_3place.setChecked(False)
         self.leg_num_3place.setValue(4)
     else:
         model = QSqlTableModel(db=db)
         model.setTable("torna_settings")
         model.setFilter(f"torna_id={self.torna_id}")
         model.select()
         # print(model.record(0))
         self.torna_name.setText(model.record(0).value(1))
         self.is_roundrobin.setChecked(model.record(0).value(2))
         self.csoport_number.setValue(model.record(0).value(3))
         self.jatekos_per_csoport.setValue(model.record(0).value(4))
         self.variant.setValue(int(model.record(0).value(5)))
         self.is_sets.setChecked(model.record(0).value(6))
         self.sets_number.setValue(model.record(0).value(7))
         self.legs_number.setValue(model.record(0).value(8))
         self.is_best.setChecked(model.record(0).value(9))
         self.is_draw.setChecked(model.record(0).value(10))
         self.pont_win.setValue(model.record(0).value(11))
         self.pont_draw.setValue(model.record(0).value(12))
         self.pont_lost.setValue(model.record(0).value(13))
         self.is_single_elim.setChecked(model.record(0).value(14))
         self.num_single.setValue(model.record(0).value(15))
         self.leg_num_single.setValue(model.record(0).value(17))
         self.leg_num_semifinal.setValue(model.record(0).value(18))
         self.leg_num_final.setValue(model.record(0).value(20))
         self.is_3place.setChecked(model.record(0).value(16))
         self.leg_num_3place.setValue(model.record(0).value(19))
示例#12
0
    def create_model() -> QSqlTableModel:
        """Create and return the model to use with the playlist table view."""
        model = QSqlTableModel()
        model.setTable("playlist")
        model.setEditStrategy(QSqlTableModel.OnManualSubmit)

        model.setHeaderData(1, Qt.Horizontal, "Title", Qt.DisplayRole)
        model.setHeaderData(2, Qt.Horizontal, "Artist", Qt.DisplayRole)
        model.setHeaderData(3, Qt.Horizontal, "Album", Qt.DisplayRole)
        model.setHeaderData(4, Qt.Horizontal, "Genre", Qt.DisplayRole)
        model.setHeaderData(5, Qt.Horizontal, "Date", Qt.DisplayRole)

        # Default is a descending sort, which leads to an inconsistency given media is appended
        model.setSort(0, Qt.AscendingOrder)
        model.select()  # Force-update the view

        return model
示例#13
0
class CurrencyCombo(QComboBox):
    def __init__(self, parent):
        QComboBox.__init__(self, parent)
        self.model = None

    def init_db(self, db):
        self.model = QSqlTableModel(db=db)
        self.model.setTable('currencies')
        self.model.select()
        self.setModel(self.model)
        self.setModelColumn(1)
        self.setCurrentIndex(self.findText(get_base_currency_name(db)))

    def selected_currency(self):
        return self.model.record(self.currentIndex()).value("id")

    def selected_currency_name(self):
        return self.model.record(self.currentIndex()).value("name")
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.table = QTableView()

        self.model = QSqlTableModel(db=db)

        self.table.setModel(self.model)

        # tag::sortTable[]
        self.model.setTable("Track")
        self.model.setSort(2, Qt.DescendingOrder)
        self.model.select()
        # end::sortTable[]

        self.setMinimumSize(QSize(1024, 600))
        self.setCentralWidget(self.table)
示例#15
0
class CurrencyComboBox(QComboBox):
    changed = Signal(int)

    def __init__(self, parent):
        QComboBox.__init__(self, parent)
        self.p_selected_id = 0
        self.model = None
        self.table_name = 'currencies'
        self.field_name = 'name'
        self.activated.connect(self.OnUserSelection)

        self.model = QSqlTableModel(db=db_connection())
        self.model.setTable(self.table_name)
        self.model.select()
        self.setModel(self.model)
        self.setModelColumn(self.model.fieldIndex(self.field_name))

    def isCustom(self):
        return True

    def getId(self):
        return self.p_selected_id

    def setId(self, new_id):
        if self.p_selected_id == new_id:
            return
        self.p_selected_id = new_id
        name = get_field_by_id_from_table(self.table_name, self.field_name,
                                          self.p_selected_id)
        if self.currentIndex() == self.findText(name):
            return
        self.setCurrentIndex(self.findText(name))

    selected_id = Property(int, getId, setId, notify=changed, user=True)

    def setIndex(self, index):
        if index is not None:
            self.selected_id = index
            self.changed.emit(self.selected_id)

    @Slot()
    def OnUserSelection(self, _selected_index):
        self.selected_id = self.model.record(self.currentIndex()).value("id")
        self.changed.emit(self.selected_id)
示例#16
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.button_change_file.clicked.connect(self.get_file)
        self.db = None
        self.model = None
        self.tables = None

    def get_file(self):
        fname = QFileDialog.getOpenFileName(self, 'Open file', "c://",
                                            "SQLite files (*.db)")
        self.connect_db(fname[0])

    def connect_db(self, fname):
        if fname.endswith(".db"):
            db = QSqlDatabase.addDatabase("QSQLITE")
            db.setDatabaseName(fname)
            db.open()
            self.ui.label_current_file.setText(fname)
            self.db = db
            self.tables = self.db.tables()
            self.populate_combo()
            self.show_table()
        else:
            self.ui.label_current_file.setText("Invalid File Selected")

    def populate_combo(self):
        self.ui.combo_table_select.clear()
        self.ui.combo_table_select.addItems(self.tables)
        self.ui.combo_table_select.activated.connect(self.update_table)

    def show_table(self):
        self.model = QSqlTableModel(db=self.db)
        self.ui.table_view.setModel(self.model)
        self.ui.table_view.show()

    def update_table(self, table):
        self.model.setTable(self.tables[table])
        self.model.select()
示例#17
0
文件: update.py 项目: kostafey/jal
class AddAssetDialog(QDialog, Ui_AddAssetDialog):
    def __init__(self, symbol, isin='', name=''):
        QDialog.__init__(self)
        self.setupUi(self)
        self.asset_id = None

        self.SymbolEdit.setText(symbol)
        self.isinEdit.setText(isin)
        self.NameEdit.setText(name)

        self.type_model = QSqlTableModel(db=db_connection())
        self.type_model.setTable('asset_types')
        self.type_model.select()
        self.TypeCombo.setModel(self.type_model)
        self.TypeCombo.setModelColumn(1)

        self.data_src_model = QSqlTableModel(db=db_connection())
        self.data_src_model.setTable('data_sources')
        self.data_src_model.select()
        self.DataSrcCombo.setModel(self.data_src_model)
        self.DataSrcCombo.setModelColumn(1)

        # center dialog with respect to main application window
        parent = None
        for widget in QApplication.topLevelWidgets():
            if widget.objectName() == Setup.MAIN_WND_NAME:
                parent = widget
        if parent:
            x = parent.x() + parent.width() / 2 - self.width() / 2
            y = parent.y() + parent.height() / 2 - self.height() / 2
            self.setGeometry(x, y, self.width(), self.height())

    def accept(self):
        self.asset_id = JalDB().add_asset(
            self.SymbolEdit.text(), self.NameEdit.text(),
            self.type_model.record(self.TypeCombo.currentIndex()).value("id"),
            self.isinEdit.text(),
            self.data_src_model.record(
                self.DataSrcCombo.currentIndex()).value("id"))
        super().accept()
示例#18
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.table = QTableView()

        self.model = QSqlTableModel(db=db)

        self.table.setModel(self.model)

        # tag::titles[]
        self.model.setTable("Track")
        self.model.setHeaderData(1, Qt.Horizontal, "Name")
        self.model.setHeaderData(2, Qt.Horizontal, "Album (ID)")
        self.model.setHeaderData(3, Qt.Horizontal, "Media Type (ID)")
        self.model.setHeaderData(4, Qt.Horizontal, "Genre (ID)")
        self.model.setHeaderData(5, Qt.Horizontal, "Composer")
        self.model.select()
        # end::titles[]

        self.model.select()

        self.setMinimumSize(QSize(1024, 600))
        self.setCentralWidget(self.table)
示例#19
0
class SqlTreeModel(QAbstractItemModel):
    ROOT_PID = 0

    @property
    def completion_model(self):
        return self._completion_model

    def __init__(self, table, parent_view):
        super().__init__(parent_view)
        self._table = table
        self._view = parent_view
        self._default_name = "name"
        self._stretch = None
        # This is auxiliary 'plain' model of the same table - to be given as QCompleter source of data
        self._completion_model = QSqlTableModel(parent=parent_view,
                                                db=db_connection())
        self._completion_model.setTable(self._table)
        self._completion_model.select()

    def index(self, row, column, parent=None):
        if parent is None:
            return QModelIndex()
        if not parent.isValid():
            parent_id = self.ROOT_PID
        else:
            parent_id = parent.internalId()
        child_id = readSQL(
            f"SELECT id FROM {self._table} WHERE pid=:pid LIMIT 1 OFFSET :row_n",
            [(":pid", parent_id), (":row_n", row)])
        if child_id:
            return self.createIndex(row, column, id=child_id)
        return QModelIndex()

    def parent(self, index):
        if not index.isValid():
            return QModelIndex()
        child_id = index.internalId()
        parent_id = readSQL(f"SELECT pid FROM {self._table} WHERE id=:id",
                            [(":id", child_id)])
        if parent_id == self.ROOT_PID:
            return QModelIndex()
        row = readSQL(
            f"SELECT row_number FROM ("
            f"SELECT ROW_NUMBER() OVER (ORDER BY id) AS row_number, id, pid "
            f"FROM {self._table} WHERE pid IN (SELECT pid FROM {self._table} WHERE id=:id)) "
            f"WHERE id=:id", [(":id", parent_id)])
        return self.createIndex(row - 1, 0, id=parent_id)

    def rowCount(self, parent=None):
        if not parent.isValid():
            parent_id = self.ROOT_PID
        else:
            parent_id = parent.internalId()
        count = readSQL(f"SELECT COUNT(id) FROM {self._table} WHERE pid=:pid",
                        [(":pid", parent_id)])
        if count:
            return int(count)
        else:
            return 0

    def columnCount(self, parent=None):
        return len(self._columns)

    def flags(self, index):
        if not index.isValid():
            return Qt.NoItemFlags
        return Qt.ItemIsEditable | super().flags(index)

    def data(self, index, role=Qt.DisplayRole):
        if not index.isValid():
            return None
        item_id = index.internalId()
        if role == Qt.DisplayRole:
            col = index.column()
            if (col >= 0) and (col < len(self._columns)):
                return readSQL(
                    f"SELECT {self._columns[col][0]} FROM {self._table} WHERE id=:id",
                    [(":id", item_id)])
            else:
                return None
        return None

    def setData(self, index, value, role=Qt.EditRole):
        if role != Qt.EditRole:
            return False
        if not index.isValid():
            return False
        item_id = index.internalId()
        col = index.column()
        db_connection().transaction()
        _ = executeSQL(
            f"UPDATE {self._table} SET {self._columns[col][0]}=:value WHERE id=:id",
            [(":id", item_id), (":value", value)])
        self.dataChanged.emit(index, index, Qt.DisplayRole | Qt.EditRole)
        return True

    def fieldIndex(self, field):
        column_data = [
            i for i, column in enumerate(self._columns) if column[0] == field
        ]
        if len(column_data) > 0:
            return column_data[0]
        else:
            return -1

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if orientation == Qt.Horizontal:
            if role == Qt.DisplayRole:
                return self._columns[section][1]
        return None

    def configureView(self):
        self.setStretching()
        font = self._view.header().font()
        font.setBold(True)
        self._view.header().setFont(font)

    def setStretching(self):
        if self._stretch:
            self._view.header().setSectionResizeMode(
                self.fieldIndex(self._stretch), QHeaderView.Stretch)

    def getId(self, index):
        if not index.isValid():
            return None
        return index.internalId()

    def getName(self, index):
        item_id = self.getId(index)
        if item_id is not None:
            self.getFieldValue(item_id, self._default_name)

    def getFieldValue(self, item_id, field_name):
        return readSQL(f"SELECT {field_name} FROM {self._table} WHERE id=:id",
                       [(":id", item_id)])

    def deleteWithChilderen(self, parent_id: int) -> None:
        query = executeSQL(f"SELECT id FROM {self._table} WHERE pid=:pid",
                           [(":pid", parent_id)])
        while query.next():
            self.deleteWithChilderen(query.value(0))
        _ = executeSQL(f"DELETE FROM {self._table} WHERE id=:id",
                       [(":id", parent_id)])

    def insertRows(self, row, count, parent=None):
        if parent is None:
            return False
        if not parent.isValid():
            parent_id = self.ROOT_PID
        else:
            parent_id = parent.internalId()

        self.beginInsertRows(parent, row, row + count - 1)
        db_connection().transaction()
        _ = executeSQL(
            f"INSERT INTO {self._table}(pid, name) VALUES (:pid, '')",
            [(":pid", parent_id)])
        self.endInsertRows()
        self.layoutChanged.emit()
        return True

    def removeRows(self, row, count, parent=None):
        if parent is None:
            return False
        if not parent.isValid():
            parent_id = self.ROOT_PID
        else:
            parent_id = parent.internalId()

        self.beginRemoveRows(parent, row, row + count - 1)
        db_connection().transaction()
        query = executeSQL(
            f"SELECT id FROM {self._table} WHERE pid=:pid LIMIT :row_c OFFSET :row_n",
            [(":pid", parent_id), (":row_c", count), (":row_n", row)])
        while query.next():
            self.deleteWithChilderen(query.value(0))
        self.endRemoveRows()
        self.layoutChanged.emit()
        return True

    def addElement(
            self,
            index,
            in_group=0):  # in_group is used for plain model only, not tree
        row = index.row()
        assert self.insertRows(row, 1, index.parent())

    def addChildElement(self, index):
        assert self.insertRows(0, 1, index)
        self._view.expand(index)

    def removeElement(self, index):
        row = index.row()
        assert self.removeRows(row, 1, index.parent())

    def submitAll(self):
        _ = executeSQL("COMMIT")
        self.layoutChanged.emit()
        return True

    def revertAll(self):
        _ = executeSQL("ROLLBACK")
        self.layoutChanged.emit()

    # expand all parent elements for tree element with given index
    def expand_parent(self, index):
        parent = index.parent()
        if parent.isValid():
            self.expand_parent(parent)
        self._view.expand(index)

    # find item by ID and make it selected in associated self._view
    def locateItem(self, item_id):
        row = readSQL(
            f"SELECT row_number FROM ("
            f"SELECT ROW_NUMBER() OVER (ORDER BY id) AS row_number, id, pid "
            f"FROM {self._table} WHERE pid IN (SELECT pid FROM {self._table} WHERE id=:id)) "
            f"WHERE id=:id", [(":id", item_id)])
        if row is None:
            return
        item_idx = self.createIndex(row - 1, 0, id=item_id)
        self.expand_parent(item_idx)
        self._view.setCurrentIndex(item_idx)

    def setFilter(self, filter_str):
        pass
示例#20
0
class ManageMembers(QMainWindow):
    def __init__(self, parent):
        super(ManageMembers, self).__init__(parent)
        self.setWindowTitle("Tagok kezelése")
        widget = QWidget()
        main_layout = QHBoxLayout()
        widget.setLayout(main_layout)

        self.setCentralWidget(widget)
        self.table_view = QTableView()
        main_layout.addWidget(self.table_view)

        self.model = QSqlTableModel(db=db)
        self.model.setTable("members")
        self.model.select()
        self.model.setEditStrategy(QSqlTableModel.OnManualSubmit)
        self.model.setHeaderData(1, Qt.Horizontal, "Vezetéknév")
        self.model.setHeaderData(2, Qt.Horizontal, "Utónév")
        self.model.setHeaderData(3, Qt.Horizontal, "Született")
        self.model.setHeaderData(4, Qt.Horizontal, "Ir.szám")
        self.model.setHeaderData(5, Qt.Horizontal, "Helység")
        self.model.setHeaderData(6, Qt.Horizontal, "Cím")
        self.model.setHeaderData(7, Qt.Horizontal, "Telefon")
        self.model.setHeaderData(8, Qt.Horizontal, "E-mail")
        self.model.setHeaderData(9, Qt.Horizontal, "Tagság kezdete")
        self.model.setHeaderData(10, Qt.Horizontal, "Aktív")
        # self.model.setFilter('vezeteknev Like "Czi%"')

        self.table_view.setModel(self.model)
        self.table_view.hideColumn(0)
        self.table_view.resizeColumnsToContents()
        # Ha ez engedélyezve, akkor a model-nél beállított sort nem működik, ez felülírja
        # Enélkül működik a model-es beállítás
        self.table_view.setSortingEnabled(True)
        # Ha engedélyezve van a fejléc szerinti rendezés, akkor UTÁNA meg lehet adni az alap sorrendet
        self.table_view.sortByColumn(1, Qt.AscendingOrder)

        self.model.dataChanged.connect(self.valtozott)
        gomb_layout = QVBoxLayout()
        main_layout.addLayout(gomb_layout)

        self.delete_button = QPushButton("&Tag törlése")
        self.add_button = QPushButton("&Új tag")
        self.apply_button = QPushButton("Módosítások alkalmazása")
        self.cancel_button = QPushButton("Módosítások elvetése")

        gomb_layout.addWidget(self.delete_button)
        gomb_layout.addWidget(self.add_button)
        gomb_layout.addWidget(self.apply_button)
        gomb_layout.addWidget(self.cancel_button)

        self.space = QSpacerItem(0, 0, QSizePolicy.Minimum,
                                 QSizePolicy.Expanding)
        gomb_layout.addItem(self.space)

        self.setFixedSize(1000, 800)
        tb = self.addToolBar("File")

        exit = QAction(QIcon("images/door--arrow.png"), "Kilépés", self)
        tb.addAction(exit)

        excel = QAction(QIcon("images/excel.png"), "Excel", self)
        tb.addAction(excel)

        tb.actionTriggered[QAction].connect(self.toolbarpressed)

        self.delete_button.clicked.connect(self.tag_torles)
        self.add_button.clicked.connect(self.tag_hozzadas)
        self.apply_button.clicked.connect(self.valtozas_mentese)
        self.cancel_button.clicked.connect(self.valtozas_elvetese)

    def tag_hozzadas(self):
        self.form_window = UjtagFormDialog()
        self.form_window.setWindowTitle("Új tag felvétele")
        if self.form_window.exec_():
            record = self.model.record()
            record.remove(record.indexOf('id'))

            for i in range(len(self.form_window.mezo_ertekek)):
                record.setValue(i, self.form_window.mezo_ertekek[i].text())
                # print(i, record.value(i))
            if self.model.insertRecord(-1, record):
                self.model.submitAll()
                self.apply_button.setStyleSheet('')
                self.cancel_button.setStyleSheet('')
            else:
                db.rollback()

    def tag_torles(self):
        if len(self.table_view.selectedIndexes()) > 0:
            self.model.removeRow(self.table_view.selectedIndexes()[0].row())
            self.model.submitAll()
        else:
            reply = QMessageBox.question(None, 'Hiba!',
                                         'Törlés előtt jelöljön ki egy sort!',
                                         QMessageBox.Ok)

    def toolbarpressed(self, a):
        if a.text() == "Kilépés":
            self.close()
        if a.text() == "Excel":
            data = []
            for i in range(self.model.rowCount()):
                sor = []
                for j in range(self.model.columnCount()):
                    if isinstance(self.model.record(i).value(j), QDate):
                        sor.append(
                            self.model.record(i).value(j).toString(
                                "yyyy-MM-dd"))
                    else:
                        sor.append(self.model.record(i).value(j))
                data.append(sor)
            p.save_as(array=data, dest_file_name="tagok.xlsx")

    def valtozott(self):
        self.apply_button.setStyleSheet('background-color: green;')
        self.cancel_button.setStyleSheet('background-color: red;')

    def valtozas_mentese(self):
        self.model.submitAll()
        self.apply_button.setStyleSheet('')
        self.cancel_button.setStyleSheet('')

    def valtozas_elvetese(self):
        self.model.revertAll()
        self.apply_button.setStyleSheet('')
        self.cancel_button.setStyleSheet('')
示例#21
0
def get_customer_record(customer_id: int) -> QSqlRecord:
    model = QSqlTableModel()
    model.setTable("customers")
    model.setFilter(F"customer_id = '{customer_id}'")
    model.select()
    return model.record(0)
示例#22
0
class ManageSettings(QMainWindow):
    def __init__(self, parent):
        super(ManageSettings, self).__init__(parent)
        self.setWindowTitle("Paraméterek kezelése")
        widget = QWidget()
        main_layout = QHBoxLayout()
        widget.setLayout(main_layout)

        self.setCentralWidget(widget)
        self.table_view = QTableView()
        main_layout.addWidget(self.table_view)

        self.model = QSqlTableModel(db=db)
        self.model.setTable("settings")
        self.model.select()
        self.model.setEditStrategy(QSqlTableModel.OnManualSubmit)
        self.model.setHeaderData(1, Qt.Horizontal, "Paraméter")
        self.model.setHeaderData(2, Qt.Horizontal, "Érték")

        self.table_view.setModel(self.model)
        self.table_view.setSortingEnabled(True)
        self.table_view.hideColumn(0)
        self.table_view.resizeColumnsToContents()

        self.model.dataChanged.connect(self.valtozott)
        gomb_layout = QVBoxLayout()
        main_layout.addLayout(gomb_layout)

        self.apply_button = QPushButton("Módosítások alkalmazása")
        self.cancel_button = QPushButton("Módosítások elvetése")

        gomb_layout.addWidget(self.apply_button)
        gomb_layout.addWidget(self.cancel_button)

        self.space = QSpacerItem(0, 0, QSizePolicy.Minimum,
                                 QSizePolicy.Expanding)
        gomb_layout.addItem(self.space)

        self.setFixedSize(400, 600)
        tb = self.addToolBar("File")

        exit = QAction(QIcon("images/door--arrow.png"), "Kilépés", self)
        tb.addAction(exit)

        tb.actionTriggered[QAction].connect(self.toolbarpressed)

        self.apply_button.clicked.connect(self.valtozas_mentese)
        self.cancel_button.clicked.connect(self.valtozas_elvetese)

    def toolbarpressed(self, a):
        if a.text() == "Kilépés":
            self.close()

    def valtozott(self):
        self.apply_button.setStyleSheet('background-color: green;')
        self.cancel_button.setStyleSheet('background-color: red;')

    def valtozas_mentese(self):
        self.model.submitAll()
        self.apply_button.setStyleSheet('')
        self.cancel_button.setStyleSheet('')

    def valtozas_elvetese(self):
        self.model.revertAll()
        self.apply_button.setStyleSheet('')
        self.cancel_button.setStyleSheet('')
示例#23
0
def get_users_table() -> QSqlTableModel:
    model = QSqlTableModel()
    model.setTable("users")
    model.setSort(0, Qt.AscendingOrder)
    model.select()
    return model
示例#24
0
class VentanaPrincipal(QTabWidget):

	def __init__(self):
		super(VentanaPrincipal, self).__init__()
		self.ui = Ui_TabWidget()
		self.ui.setupUi(self)

		# DB
		self.db = QSqlDatabase.addDatabase("QSQLITE")
		self.db.setDatabaseName("cuentas.db")
		self.conector = QSqlDatabase.database()
		self.general_query = QSqlQuery()
		self.organizar_db()
		# Querys para psw_tool
		self.master_query = QSqlQuery()
		self.save_query = QSqlQuery()
		self.passwords_query_retrieve = QSqlQuery()
		self.passwords_query_write = QSqlQuery()
		self.popular = QSqlQuery()
		self.comboBoxes_query_categoria = QSqlQuery()
		self.comboBoxes_query_mail = QSqlQuery()
		self.comboBoxes_query_usuario = QSqlQuery()
		self.verificar_columna_contrasenas = QSqlQuery()
		self.filtro = QSqlQuery()
		# Querys para pswItemDelegate
		self.all_data = QSqlQuery()
		#  BASE DE DATOS en UI
		self.model = QSqlTableModel()  # pswItemDelegate.CustomSqlModel()
		self.organizar_tabla_ui()
		self.model.setEditStrategy(QSqlTableModel.OnManualSubmit)  # Va aca abajo por self.model.setTable('passwords')
		# Para cuando se cambian datos
		self.model.dataChanged.connect(self.celdas_cambiadas)
		self.ui.tabla_db.setContextMenuPolicy(Qt.CustomContextMenu)
		self.ui.tabla_db.customContextMenuRequested.connect(self.context_menu)
		# Filtro DB
		# .connect(lambda: self.
		self.tabBarClicked.connect(self.actualizar_tabs)
		# Iconos DB en UI
		self.icon_seguridad = QIcon()
		self.icon_seguridad.addPixmap(QPixmap(":/media/iconografia/locked.png"), QIcon.Normal, QIcon.Off)
		self.icon_desbloqueado = QIcon()
		self.icon_desbloqueado.addPixmap(QPixmap(":/media/iconografia/unlocked.png"), QIcon.Normal, QIcon.Off)
		self.icon_editar = QIcon()
		self.icon_editar.addPixmap(QPixmap(":/media/iconografia/pencil.png"), QIcon.Normal, QIcon.Off)
		self.icon_guardar = QIcon()
		self.icon_guardar.addPixmap(QPixmap(":/media/iconografia/broken-pencil.png"), QIcon.Normal, QIcon.Off)

		# Procesos iniciales
		self.cargar_config()
		self.master_key = None
		self.seguridad_alterada = False
		self.candado = "cerrado"
		self.modo_boton_editar_guardar = "editar"
		self.contrasenas_nuevas = {}
		self.edits = {}
		self.revisar_columna_contrasenas()
		self.cargar_opciones_combo_boxes()
		# Alertas
		# Iconos para las alertas sin UI
		self.icon_ventana = QIcon()
		self.icon_ventana.addPixmap(QPixmap(":/media/imagenes/main_frame.png"), QIcon.Normal, QIcon.Off)
		self.alerta_config = QMessageBox(QMessageBox.Warning,
										"Problema con la configuración actual",
										"Existen dos posibilidades para este error:\n\n1. El archivo de configuración está dañando\n2. Usted tiene todas las opciones desmarcadas (el amor no cuenta)\n\nPara solucionarlo, borre el archivo de configuración ('opciones.ini'),\no marque alguna opción en la pestaña de configuración y guarde su selección\n"
										)
		self.alerta_master_psw_mala = QMessageBox(QMessageBox.Warning,
												"Problema con la contraseña ingresada",
												"Por favor tome precauciones con la elección de la contraseña maestra.\nPara poder proseguir debe ingresar una contraseña con más de 5 y menos de 17 caracteres, o sino presione cancelar."
												)
		self.alerta_master_psw_incorrecta = QMessageBox(QMessageBox.Warning,
														"Problema con la contraseña ingresada",
														"La contraseña que ingresaste es incorrecta"
														)
		self.alerta_guardado_exitoso = QMessageBox(QMessageBox.Information, "Información guardada",
													"Toda la información que ingresaste se guardó con éxito."
												)
		self.alerta_config.setWindowIcon(self.icon_ventana)
		self.alerta_master_psw_mala.setWindowIcon(self.icon_ventana)
		self.alerta_master_psw_incorrecta.setWindowIcon(self.icon_ventana)
		self.alerta_guardado_exitoso.setWindowIcon(self.icon_ventana)
		# Alertas con su propia UI
		# Dialog info
		self.dialogo_info = QDialog()
		self.info_app = Ui_dialogo_info()
		self.info_app.setupUi(self.dialogo_info)
		# Alerta master psw
		self.dialogo_master_psw = QDialog()
		self.alerta_master_psw = Ui_dialogo_master_psw()
		self.alerta_master_psw.setupUi(self.dialogo_master_psw)

		# Botones
		self.ui.boton_guardar_config.clicked.connect(self.guardar_config)
		self.ui.boton_info.clicked.connect(self.cargar_info)
		self.ui.boton_generar.clicked.connect(self.llamar_generar_contrasena)  # Boton generar contrasñea
		self.ui.boton_guardar.clicked.connect(self.guardar_contrasena)  # boton guardar data
		# Si presionan el boton revelar contraseña
		self.ui.reveal_psw.clicked.connect(self.mostrar_contrasena)
		self.alerta_master_psw.reveal_master_psw.clicked.connect(self.mostrar_contrasena_maestra)
		# Icono del boton revelar contraseña
		self.icon_not_view = QIcon()
		self.icon_not_view.addPixmap(QPixmap(":/media/iconografia/not_view.png"), QIcon.Normal, QIcon.Off)
		self.icon_view = QIcon()
		self.icon_view.addPixmap(QPixmap(":/media/iconografia/view.png"), QIcon.Normal, QIcon.Off)
		# Click en botones copiar # Otra manera de hacerlo: partial(self.llamar_copiar(n)) using functools.partial
		self.ui.cp1.clicked.connect(lambda: self.llamar_copiar(1))
		self.ui.cp2.clicked.connect(lambda: self.llamar_copiar(2))
		self.ui.cp3.clicked.connect(lambda: self.llamar_copiar(3))
		# Botones DB
		self.ui.boton_filtro.clicked.connect(lambda: self.filtrar())
		self.ui.boton_editar.clicked.connect(lambda: self.gestor_boton_editar_guardar())
		self.ui.boton_seguridad.clicked.connect(lambda: self.mostrar_contrasenas())
		# Botones Info
		self.info_app.boton_steam.clicked.connect(lambda: backend.abrir_link("https://steamcommunity.com/id/JosephKm"))
		self.info_app.boton_discord.clicked.connect(lambda: backend.abrir_link("https://discord.gg/wYuXPQS"))
		self.info_app.boton_github.clicked.connect(
			lambda: backend.abrir_link("https://github.com/kuttz-dev/Password-manager"))
		# Si se presiona la pestaña de configuracion
		# self.ui.tab_3.connect(self.cargar_config)
		# SETEAR COMBOBOXES
		self.ui.comboBox_usuario.setInsertPolicy(QComboBox.InsertAlphabetically)
		self.ui.comboBox_mail.setInsertPolicy(QComboBox.InsertAlphabetically)
		self.ui.comboBox_categoria.setInsertPolicy(QComboBox.InsertAlphabetically)
		self.ui.comboBox_usuario.setDuplicatesEnabled(False)
		self.ui.comboBox_mail.setDuplicatesEnabled(False)
		self.ui.comboBox_categoria.setDuplicatesEnabled(False)
		self.ui.comboBox_usuario.clearEditText()
		self.ui.comboBox_mail.clearEditText()
		self.ui.comboBox_categoria.clearEditText()


	def organizar_db(self):
		self.general_query.exec_(
			'CREATE TABLE IF NOT EXISTS passwords (id INTEGER PRIMARY KEY ASC, categoria TEXT, icono BLOB, servicio TEXT, mail TEXT, usuario TEXT, contraseña_encriptada BLOB);'
		)
		self.general_query.exec_(
			'CREATE TABLE IF NOT EXISTS maestra (id INTEGER PRIMARY KEY, muestra BLOB);'
		)
		self.general_query.exec_(
			'DELETE FROM passwords WHERE usuario = "" AND mail = "" AND contraseña_encriptada = ""'
		)
		self.db.commit()

	def borrar_columna_contrasenas(self):
		self.general_query.exec_(
			'DROP TABLE IF EXISTS temporal'
		)
		self.general_query.exec_(
			'CREATE TABLE temporal (id INTEGER PRIMARY KEY ASC, categoria TEXT, icono BLOB, servicio TEXT, mail TEXT, usuario TEXT, contraseña_encriptada BLOB);'
		)
		self.popular.exec_(
			'INSERT INTO temporal(id, categoria, icono, servicio, mail, usuario, contraseña_encriptada) SELECT id, categoria, icono, servicio, mail, usuario, contraseña_encriptada FROM passwords'
		)
		self.db.commit()
		self.general_query.exec_(
			'DROP TABLE IF EXISTS passwords'
		)
		self.popular.exec_(
			'ALTER TABLE temporal RENAME TO passwords'
		)
		self.general_query.exec_(
			'DROP TABLE IF EXISTS temporal'
		)
		self.db.commit()

	def cargar_config(self):
		largo, mayus, minus, numeros, special, icono = backend.obtener_cfg()
		self.ui.spinBox_largo.setProperty("value", int(largo))
		self.ui.check_mayus.setChecked(backend.string2bool(mayus))
		self.ui.check_min.setChecked(backend.string2bool(minus))
		self.ui.check_numeros.setChecked(backend.string2bool(numeros))
		self.ui.check_caracteres.setChecked(backend.string2bool(special))
		self.ui.check_amor.setChecked(backend.string2bool(icono))

	def guardar_config(self):
		hay_opcion_verdadera = False
		largo = self.ui.spinBox_largo.value()
		mayus = self.ui.check_mayus.checkState()
		minus = self.ui.check_min.checkState()
		numeros = self.ui.check_numeros.checkState()
		special = self.ui.check_caracteres.checkState()
		icono = self.ui.check_amor.checkState()

		estado_checkeado = [mayus, minus, numeros, special, icono]
		for i in range(len(estado_checkeado)):
			if str(estado_checkeado[i]) == "PySide2.QtCore.Qt.CheckState.Checked":
				if i != 4:  # len de estado_checkeado - 1
					hay_opcion_verdadera = True
				estado_checkeado[i] = True
			else:
				estado_checkeado[i] = False

		if hay_opcion_verdadera is False:
			return self.alerta_config.exec()

		backend.generar_cfg(largo,
							estado_checkeado[0],
							estado_checkeado[1],
							estado_checkeado[2],
							estado_checkeado[3],
							estado_checkeado[4]
							)

		self.cargar_config()

	def cargar_info(self):
		return self.dialogo_info.exec()

	def llamar_generar_contrasena(self):
		#  Primero obtenemos que tipo de contraseña quiere el usuario
		largo, mayus, minus, numeros, special, icono = backend.obtener_cfg()
		mayus = backend.string2bool(mayus)
		minus = backend.string2bool(minus)
		numeros = backend.string2bool(numeros)
		special = backend.string2bool(special)

		if mayus is False and minus is False and numeros is False and special is False:
			self.alerta_config.exec()

		texto_contrasena = backend.generar_contraseña(int(largo), mayus, minus, numeros, special)
		self.ui.input_psw.setText(str(texto_contrasena))  # Ponemos la contraseña en la aplicacion

	def mostrar_contrasena(self):
		# Si esta en password a normal y viceversa
		if self.ui.input_psw.echoMode() == QLineEdit.EchoMode.Password:
			self.ui.reveal_psw.setIcon(self.icon_not_view)
			self.ui.input_psw.setEchoMode(QLineEdit.Normal)
		else:
			self.ui.reveal_psw.setIcon(self.icon_view)
			self.ui.input_psw.setEchoMode(QLineEdit.Password)

	def mostrar_contrasena_maestra(self, modo_echo=False):
		# Si no se cambio el estado va a estar en False y se va a usar el echoMode del input
		if modo_echo is False:
			modo_echo = self.alerta_master_psw.input_master_psw.echoMode()
		# Si esta en password a normal y viceversa
		if modo_echo == QLineEdit.EchoMode.Password:
			self.alerta_master_psw.reveal_master_psw.setIcon(self.icon_not_view)
			self.alerta_master_psw.input_master_psw.setEchoMode(QLineEdit.Normal)
		else:
			self.alerta_master_psw.reveal_master_psw.setIcon(self.icon_view)
			self.alerta_master_psw.input_master_psw.setEchoMode(QLineEdit.Password)

	def llamar_copiar(self, numero_boton):
		if numero_boton == 1:
			backend.copiar(str(self.ui.input_psw.text()))
		if numero_boton == 2:
			backend.copiar(str(self.ui.comboBox_usuario.currentText()))
		if numero_boton == 3:
			backend.copiar(str(self.ui.comboBox_mail.currentText()))

	def preparar_favicon(self, url):
		try:
			archivo_ico = backend.descargar_favico(url)
		except Exception:  # Si lo que se ingreso era un link pero no se consiguio favicon
			with open("media/favicons/domain.ico") as ico:
				return QByteArray(ico.read())
		# Si no se consiguio la imagen
		if archivo_ico is None:
			return None
		with open(archivo_ico, "rb") as ico:
			return QByteArray(ico.read())

	def guardar_contrasena(self):
		# self.ui.comboBox_usuario.currentText() / self.ui.comboBox_mail.currentText()
		# self.ui.comboBox_categoria.currentText() / self.ui.input_url.text()
		# self.ui.input_psw.text()

		if self.master_key is None:
			try:
				self.master_key = self.pedir_contrasena_maestra()
			except Exception:
				return
		if self.ui.input_psw.text() != "":
			contrasena_ingresada_encriptada = QByteArray(pswCrypto.encriptar(self.ui.input_psw.text(), self.master_key))
		else:
			contrasena_ingresada_encriptada = ""

		try:
			fav_icon = self.preparar_favicon(self.ui.input_url.text())

			self.save_query.prepare(
				'INSERT INTO passwords (categoria, icono, servicio, mail, usuario, contraseña_encriptada) VALUES(?,?,?,?,?,?)'
			)
			self.save_query.addBindValue(self.ui.comboBox_categoria.currentText())
			self.save_query.addBindValue(fav_icon)
			self.save_query.addBindValue(self.ui.input_url.text())
			self.save_query.addBindValue(self.ui.comboBox_mail.currentText())
			self.save_query.addBindValue(self.ui.comboBox_usuario.currentText())
			self.save_query.addBindValue(contrasena_ingresada_encriptada)
			self.save_query.exec_()
			self.db.commit()
			self.model.select()
			self.ui.tabla_db.resizeColumnsToContents()
			self.cargar_opciones_combo_boxes()
			return self.alerta_guardado_exitoso.exec()

		except Exception as ex:
			template = "An exception of type {0} occurred. Arguments:\n{1!r}"
			message = template.format(type(ex).__name__, ex.args)
			print(message)

	def pedir_contrasena_maestra(self):
		self.dialogo_master_psw.exec()

		contrasena_maestra = self.alerta_master_psw.input_master_psw.text()
		# Borrarmos el texto porque no se borra solo, y lo volvemos secreto de nuevo
		self.alerta_master_psw.input_master_psw.setText("")
		self.mostrar_contrasena_maestra(QLineEdit.EchoMode.Normal)

		# Si le dio a cancelar
		if bool(self.dialogo_master_psw.result()) is False:
			raise Exception("Accion canelada")

		# Comprobamos que cumpla requisitos
		if contrasena_maestra == "" or len(contrasena_maestra) < 6 or len(contrasena_maestra) > 16:
			self.alerta_master_psw_mala.exec()
			return self.pedir_contraseña_maestra()

		# Encriptacion
		key_contrasena_maestra = pswCrypto.generar_key(contrasena_maestra)  # La convertimos en una key
		# Verificacion
		# Obtenemos la muestra guardada en la db
		muestra_db = backend.obtener_muestra_db()
		# Si no habia guardamos una nueva con esta contraseña maestra
		if muestra_db is None:
			array = QByteArray(backend.generar_muestra(key_contrasena_maestra))
			self.master_query.prepare("INSERT INTO maestra (id, muestra) VALUES(1, ?)")
			self.master_query.addBindValue(array)
			self.master_query.exec_()

			return key_contrasena_maestra

		else:
			# Ahora si verificamos
			psw_correcta = backend.verificar_key(muestra_db, key_contrasena_maestra)
			if psw_correcta is True:
				return key_contrasena_maestra
			else:
				self.alerta_master_psw_incorrecta.exec_()
				raise Exception("Contraseña maestra incorrecta")

	def filtrar(self):
		if self.ui.input_filtro.text() == "":
			self.model.setFilter("")
			return self.model.select()
		else:
			self.model.setFilter(
				"{} LIKE '{}%'".format(self.ui.combobox_filtro.currentText().lower(), self.ui.input_filtro.text())
			)
			return self.model.select()

	def mostrar_contrasenas(self):
		if self.master_key is None:
			try:
				self.master_key = self.pedir_contrasena_maestra()
			except Exception:
				return

		if self.candado == "abierto":  # Si esta abierto
			self.borrar_columna_contrasenas()
			self.ui.combobox_filtro.removeItem(4)
			self.organizar_tabla_ui()
			self.ui.boton_seguridad.setIcon(self.icon_seguridad)
			self.candado = "cerrado"  # lo cerramos
			return

		else:  # Si estaba cerrado
			self.candado = "abierto"  # lo abrimos
		# y se abre asi:
		self.ui.boton_seguridad.setIcon(self.icon_desbloqueado)
		# Conseguimos las contraseñas encriptadas
		self.passwords_query_retrieve.exec_('SELECT id, contraseña_encriptada FROM passwords')
		# Creamos una columna para las contraseñas descifradas
		self.general_query.exec_('ALTER TABLE passwords ADD contraseña TEXT')
		self.db.commit()
		# Para cada contraseña
		while self.passwords_query_retrieve.next():
			# Si se guardo un texto vacio
			contrasena_descifrada = self.passwords_query_retrieve.value(1)
			if type(contrasena_descifrada) != str:
				contrasena_descifrada = pswCrypto.descifrar(contrasena_descifrada.data(), self.master_key)

			self.passwords_query_write.prepare('UPDATE passwords SET contraseña = ? WHERE id= ?')
			self.passwords_query_write.addBindValue(contrasena_descifrada)
			self.passwords_query_write.addBindValue(self.passwords_query_retrieve.value(0))
			self.passwords_query_write.exec_()
		self.ui.combobox_filtro.addItem("Contraseña")
		self.organizar_tabla_ui()  # Las hacemos visibles el la tabla

	def actualizar_tabs(self, index):
		if index == 0:
			self.resize(437, 200)
			self.cargar_opciones_combo_boxes()
		if index == 1 and self.ui.boton_seguridad.isEnabled() is True:
			self.organizar_tabla_ui()
		elif index == 2:
			self.resize(437, 200)
			self.cargar_config()

	def organizar_tabla_ui(self):
		self.model.setTable('passwords')
		self.model.setSort(1, Qt.AscendingOrder)
		self.model.select()
		self.ui.tabla_db.setModel(self.model)
		self.ui.tabla_db.setItemDelegateForColumn(2, pswItemDelegate.ImageDelegate(self.ui.tabla_db))
		self.ui.tabla_db.hideColumn(0)  # Escondemos id
		self.ui.tabla_db.hideColumn(6)  # Escondemos las contraseñas encriptadas
		self.ui.tabla_db.setWindowTitle("Lista de cuentas")
		# Tamaño columnas
		#self.ui.tabla_db.resizeColumnsToContents()
		self.ui.tabla_db.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
		self.ui.tabla_db.horizontalHeader().setSectionResizeMode(2, QHeaderView.Fixed)  # iconos
		self.ui.tabla_db.setColumnWidth(2, 32)  # tamaño iconos
		self.ui.tabla_db.verticalHeader().setVisible(False)
		self.ui.tabla_db.setSortingEnabled(True)

	def cargar_opciones_combo_boxes(self):
		a = self.ui.comboBox_categoria.currentText()
		b = self.ui.comboBox_mail.currentText()
		c = self.ui.comboBox_usuario.currentText()

		self.comboBoxes_query_categoria.exec_(
			'SELECT DISTINCT categoria FROM passwords'
		)
		self.comboBoxes_query_mail.exec_(
			'SELECT DISTINCT mail FROM passwords'
		)
		self.comboBoxes_query_usuario.exec_(
			'SELECT DISTINCT usuario FROM passwords'
		)
		# Borramos las anteriores
		self.ui.comboBox_usuario.clear()
		self.ui.comboBox_mail.clear()
		self.ui.comboBox_categoria.clear()
		# Cargamos las nuevas
		while self.comboBoxes_query_categoria.next():
			if self.comboBoxes_query_categoria.value(0) == "" or self.comboBoxes_query_categoria.value(0) is None:
				continue
			self.ui.comboBox_categoria.addItem(self.comboBoxes_query_categoria.value(0))

		while self.comboBoxes_query_mail.next():
			if self.comboBoxes_query_mail.value(0) == "" or self.comboBoxes_query_mail.value(0) is None:
				continue
			self.ui.comboBox_mail.addItem(self.comboBoxes_query_mail.value(0))

		while self.comboBoxes_query_usuario.next():
			if self.comboBoxes_query_usuario.value(0) == "" or self.comboBoxes_query_usuario.value(0) is None:
				continue
			self.ui.comboBox_usuario.addItem(self.comboBoxes_query_usuario.value(0))
		self.ui.comboBox_categoria.setCurrentText(a)
		self.ui.comboBox_mail.setCurrentText(b)
		self.ui.comboBox_usuario.setCurrentText(c)

	def revisar_columna_contrasenas(self, borrar=True):
		existe = self.verificar_columna_contrasenas.exec_('SELECT contraseña FROM passwords LIMIT 1')
		if existe is True and borrar is True:
			self.verificar_columna_contrasenas.finish()
			self.borrar_columna_contrasenas()
			return self.organizar_tabla_ui()

		elif existe is True:
			return "Existe"

	def gestor_boton_editar_guardar(self):
		if self.modo_boton_editar_guardar == "editar":
			try:
				self.editar_tabla_ui()
			except Exception:
				return
			self.modo_boton_editar_guardar = "guardar"  # Cambiamos al proximo modo
			return self.ui.boton_editar.setIcon(self.icon_guardar)

		elif self.modo_boton_editar_guardar == "guardar":
			self.borrar_columna_contrasenas()
			self.organizar_tabla_ui()
			self.candado = "cerrado"
			self.ui.boton_seguridad.setDisabled(False)
			self.ui.boton_seguridad.setIcon(self.icon_seguridad)
			self.ui.boton_editar.setIcon(self.icon_editar)
			self.modo_boton_editar_guardar = "editar"  # Cambiamos al proximo modo
			return

	def editar_tabla_ui(self):
		if self.master_key is None:
			try:
				self.master_key = self.pedir_contrasena_maestra()
			except Exception:
				raise Exception("No se pudo conseguir master key")

		self.ui.boton_seguridad.setDisabled(True)
		if self.candado == "cerrado":
			self.mostrar_contrasenas()

	def celdas_cambiadas(self, top_left, bottom_right):
		if self.modo_boton_editar_guardar == "editar":
			return
		else:
			if top_left.column() == 7:

				contrasena_editada_encriptada = ""
				if self.model.record(top_left.row()).value('contraseña') != "":
					contrasena_editada_encriptada = QByteArray(
						pswCrypto.encriptar(self.model.record(top_left.row()).value('contraseña'), self.master_key))

				casilla_editada = QSqlField("contraseña_encriptada")
				casilla_editada.setValue(contrasena_editada_encriptada)
				valores_fila = self.model.record(top_left.row())
				valores_fila.replace(6, casilla_editada)
				return self.model.updateRowInTable(top_left.row(), valores_fila)
			else:
				self.model.updateRowInTable(top_left.row(), self.model.record(top_left.row()))
				return self.db.commit()

	def borrar_linea(self, row):
		self.model.deleteRowFromTable(row)
		return self.model.select()

	def context_menu(self):
		# Menu con click derecho
		if self.ui.tabla_db.selectedIndexes() and self.modo_boton_editar_guardar == "guardar":
			menu = QMenu()
			borrar_data = menu.addAction("Borrar linea de la base de datos")
			borrar_data.triggered.connect(lambda: self.borrar_linea(self.ui.tabla_db.currentIndex().row()))
			cursor = QCursor()
			menu.exec_(cursor.pos())
示例#25
0
class AbstractReferenceListModel(QSqlRelationalTableModel):
    @property
    def completion_model(self):
        return self._completion_model

    def __init__(self, table, parent_view):
        self._view = parent_view
        self._table = table
        self._columns = []
        self._default_name = "name"
        self._group_by = None
        self._sort_by = None
        self._hidden = []
        self._stretch = None
        QSqlRelationalTableModel.__init__(self,
                                          parent=parent_view,
                                          db=db_connection())
        self.setJoinMode(QSqlRelationalTableModel.LeftJoin)
        self.setTable(self._table)
        self.setEditStrategy(QSqlTableModel.OnManualSubmit)
        self.select()
        # This is auxiliary 'plain' model of the same table - to be given as QCompleter source of data
        self._completion_model = QSqlTableModel(parent=parent_view,
                                                db=db_connection())
        self._completion_model.setTable(self._table)
        self._completion_model.select()

    @property
    def group_by(self):
        return self._group_by

    def fieldIndex(self, field):
        column_data = [
            i for i, column in enumerate(self._columns) if column[0] == field
        ]
        if len(column_data) > 0:
            return column_data[0]
        else:
            return -1

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if orientation == Qt.Horizontal:
            if role == Qt.DisplayRole:
                return self._columns[section][1]
        return None

    def configureView(self):
        self.setSorting()
        self.hideColumns()
        self.setStretching()
        font = self._view.horizontalHeader().font()
        font.setBold(True)
        self._view.horizontalHeader().setFont(font)

    def setSorting(self):
        if self._sort_by:
            self.setSort(self.fieldIndex(self._sort_by), Qt.AscendingOrder)

    def hideColumns(self):
        for column_name in self._hidden:
            self._view.setColumnHidden(self.fieldIndex(column_name), True)

    def setStretching(self):
        if self._stretch:
            self._view.horizontalHeader().setSectionResizeMode(
                self.fieldIndex(self._stretch), QHeaderView.Stretch)

    def getId(self, index):
        return self.record(index.row()).value('id')

    def getName(self, index):
        return self.getFieldValue(self.getId(index), self._default_name)

    def getFieldValue(self, item_id, field_name):
        return readSQL(f"SELECT {field_name} FROM {self._table} WHERE id=:id",
                       [(":id", item_id)])

    def addElement(self, index, in_group=0):
        row = index.row() if index.isValid() else 0
        assert self.insertRows(row, 1)
        new_record = self.record()
        if in_group != 0:
            new_record.setValue(self.fieldIndex(self._group_by),
                                in_group)  # by index as it is lookup field
        self.setRecord(row, new_record)

    def removeElement(self, index):
        if index.isValid():
            row = index.row()
        else:
            return
        assert self.removeRow(row)

    def locateItem(self, item_id, use_filter=''):
        raise NotImplementedError(
            "locateItem() method is not defined in subclass of AbstractReferenceListModel"
        )
示例#26
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        layout = QVBoxLayout()

        form = QFormLayout()

        self.track_id = QSpinBox()
        self.track_id.setDisabled(True)
        self.name = QLineEdit()
        self.album = QComboBox()
        self.media_type = QComboBox()
        self.genre = QComboBox()
        self.composer = QLineEdit()

        self.milliseconds = QSpinBox()
        self.milliseconds.setRange(0, 2147483647)
        self.milliseconds.setSingleStep(1)

        self.bytes = QSpinBox()
        self.bytes.setRange(0, 2147483647)
        self.bytes.setSingleStep(1)

        self.unit_price = QDoubleSpinBox()
        self.unit_price.setRange(0, 999)
        self.unit_price.setSingleStep(0.01)
        self.unit_price.setPrefix("$")

        form.addRow(QLabel("Track ID"), self.track_id)
        form.addRow(QLabel("Track name"), self.name)
        form.addRow(QLabel("Composer"), self.composer)
        form.addRow(QLabel("Milliseconds"), self.milliseconds)
        form.addRow(QLabel("Bytes"), self.bytes)
        form.addRow(QLabel("Unit Price"), self.unit_price)

        self.model = QSqlTableModel(db=db)

        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.model)

        self.mapper.addMapping(self.track_id, 0)
        self.mapper.addMapping(self.name, 1)
        self.mapper.addMapping(self.composer, 5)
        self.mapper.addMapping(self.milliseconds, 6)
        self.mapper.addMapping(self.bytes, 7)
        self.mapper.addMapping(self.unit_price, 8)

        self.model.setTable("Track")
        self.model.select()

        self.mapper.toFirst()

        self.setMinimumSize(QSize(400, 400))

        controls = QHBoxLayout()

        # tag::controls[]
        prev_rec = QPushButton("Previous")
        prev_rec.clicked.connect(self.mapper.toPrevious)

        next_rec = QPushButton("Next")
        next_rec.clicked.connect(self.mapper.toNext)

        save_rec = QPushButton("Save Changes")
        save_rec.clicked.connect(self.mapper.submit)
        # end::controls[]

        controls.addWidget(prev_rec)
        controls.addWidget(next_rec)
        controls.addWidget(save_rec)

        layout.addLayout(form)
        layout.addLayout(controls)

        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
示例#27
0
文件: interface.py 项目: setrsw/Test
class Stats(Ui_armus):
    def __init__(self):
        # 从文件中加载UI定义
        # qfile=QFile(r'E:\Pycharm\armus1\ui\armus1.ui')
        # qfile.open(QFile.ReadOnly)
        # # qfile_stats.close()
        # # 从 UI 定义中动态 创建一个相应的窗口对象
        # # 注意:里面的控件对象也成为窗口对象的属性了
        # # 比如 self.ui.button , self.ui.textEdit
        # # loader=QUiLoader()
        # self.ui=QUiLoader().load(qfile)
        # self.ui.show()
        super(Stats,self).__init__()
        # self.ui=Ui_armus()

        # self.tableView.setModel()
        db=QSqlDatabase.addDatabase('QSQLITE')
        db.setDatabaseName('universitys.db')
        self.spider=Data_Spider()#爬虫连接
        self.session=DBSession()#数据库连接
        self.setupUi(self)
        # self.query=QSqlQuery(db)
        self.init_connect_db()
        # self.model = QStandardItemModel()  # 存储任意结构数据
        # self.model=QSqlQueryModel()
        self.comboBox.activated[str].connect(self.orderinfo)
        self.pushButton.clicked.connect(self.add_college)
        self.pushButton_2.clicked.connect(self.update_college)
        self.pushButton_4.clicked.connect(self.spiders_info)
        self.pushButton_5.clicked.connect(self.spider_info)
        # self.pushButton_3.clicked.connect(self.help_info)
        self.comboBox_2.activated[str].connect(self.link_collegeurl)

    #初始化连接数据库
    def init_connect_db(self):
        self.model = QSqlTableModel()
        self.tableView.setModel(self.model)
        self.model.setTable('notifications')
        self.model.setHeaderData(0, Qt.Horizontal, "全文链接")
        self.model.setHeaderData(1, Qt.Horizontal, "讲座标题")
        self.model.setHeaderData(2, Qt.Horizontal, "报告大学")
        self.model.setHeaderData(3, Qt.Horizontal, "报告人")
        self.model.setHeaderData(4, Qt.Horizontal, "报告地点")
        self.model.setHeaderData(5, Qt.Horizontal, "举办时间")
        self.model.setHeaderData(6, Qt.Horizontal, "发布时间")
        # self.model.setFilter('college="华南理工大学软件学院"')
        self.model.select()

    #排序筛选信息
    def orderinfo(self,text):
        if text=="按举办时间排序":
            # print('按举办时间排序')
            self.model.setFilter('title like "%%密码%" or title like "%%安全%" or title like "%security%"')
            self.model.setSort(5,Qt.DescendingOrder)#按举办时间降序
            self.model.select()

        elif text=='按发布时间排序':
            # print('按发布时间排序')
            self.model.setFilter('title like "%%密码%" or title like "%%安全%" or title like "%security%"')
            self.model.setSort(6, Qt.DescendingOrder)#按发布时间降序
            self.model.select()
        else:
            self.model.setFilter('url like "%%"')
            self.model.select()

            # QMessageBox.critical(NULL, "critical", "Content", QMessageBox.Yes, QMessageBox.Yes) #带按键


    def add_college(self):  #添加学校网页
        url=self.lineEdit_7.text()
        college=self.lineEdit.text()
        nextpage=self.lineEdit_2.text()
        url_xpath=self.lineEdit_3.text()
        text_xpath=self.lineEdit_4.text()
        notify_time=self.lineEdit_5.text()

        self.spider.set_college_url(url)
        self.spider.set_college(college)
        self.spider.set_next_xpath(nextpage)
        self.spider.set_url_xpath(url_xpath)
        self.spider.set_text_xpath(text_xpath)
        self.spider.set_notify_time_xpath(notify_time)
        self.spider.set_title_word()
        self.spider.insert_seed(self.session)

    def update_college(self):
        list_college=self.session.query(Seed).all()
        num=self.comboBox_2.count()
        colleges=[]
        for i in range(num):
            colleges.append(self.comboBox_2.itemText(i))
        for row in list_college:
            if row.college not in colleges:
                self.comboBox_2.addItem(row.college)

    def link_collegeurl(self,text):
        college=self.session.query(Seed).filter(Seed.college==text).first()
        if college!=None:
            self.lineEdit_6.setText(college.start_url)
            self.model.setFilter('college="%s"'%(text))
            self.model.select()
        else:
            self.lineEdit_6.setText('')
            self.model.select()
    def spiders_info(self):
        self.spider.universities_spider()
        MESSAGE = "更新/爬取学术信息完成"
        msgBox = QMessageBox(QMessageBox.Question,
                             "提示", MESSAGE,
                             QMessageBox.NoButton, self)
        msgBox.addButton("确定", QMessageBox.AcceptRole)
        msgBox.exec_()

    def spider_info(self):
        text=self.comboBox_2.currentText()
        college = self.session.query(Seed).filter(Seed.college == text).first()
        self.spider.university_spider(college)
        MESSAGE = "更新/爬取学术信息完成"
        msgBox = QMessageBox(QMessageBox.Question,
                             "提示", MESSAGE,
                             QMessageBox.NoButton, self)
        msgBox.addButton("确定", QMessageBox.AcceptRole)
        msgBox.exec_()
示例#28
0
class manageMembers(QMainWindow):
    def __init__(self):
        super(manageMembers, self).__init__()
        self.setWindowTitle("Tagok kezelése")
        widget = QWidget()
        main_layout = QHBoxLayout()
        widget.setLayout(main_layout)

        self.setCentralWidget(widget)
        # self.client = MysqlClient()
        self.table_view = QTableView()  #####################################
        # self.model = TableModel(self.table_name, fejlec)
        self.model = QSqlTableModel(
            db=db)  #####################################
        # a megjelenített tábla neve
        # self.table_name = "members"
        self.table_view.setModel(
            self.model)  ####################################
        self.model.setTable("members")  ####################################
        self.model.select()  ####################################
        main_layout.addWidget(self.table_view)
        ####fejlec = ['id', "Vezetéknév", "Utónév", "Született", "Ir.szám", "Helység", "Cím", "Telefon", "E-mail",
        ####          "Tagság kezdete", 'Aktív']

        # self.model = TableModel(self.table_name)
        # print(self.model)

        ###self.table_view.setModel(self.model)
        ####self.table_view.setSortingEnabled(True)
        # Az első oszlop (id) elrejtése
        ####self.table_view.hideColumn(0)
        ####self.table_view.resizeColumnsToContents()

        gomb_layout = QVBoxLayout()
        main_layout.addLayout(gomb_layout)

        self.delete_button = QPushButton("&Tag törlése")
        self.add_button = QPushButton("&Új tag")
        self.modify_button = QPushButton("Tag &módosítása")

        gomb_layout.addWidget(self.delete_button)
        gomb_layout.addWidget(self.add_button)
        gomb_layout.addWidget(self.modify_button)
        self.space = QSpacerItem(0, 0, QSizePolicy.Minimum,
                                 QSizePolicy.Expanding)
        gomb_layout.addItem(self.space)

        # self.resize(320, 200)
        self.setFixedSize(1000, 800)
        # self.showMaximized()
        # self.setWindowFlags(Qt.Window|Qt.WindowTitleHint)
        tb = self.addToolBar("File")

        exit = QAction(QIcon("images/door--arrow.png"), "Kilépés", self)
        tb.addAction(exit)

        excel = QAction(QIcon("images/excel.png"), "Excel", self)
        tb.addAction(excel)

        tb.actionTriggered[QAction].connect(self.toolbarpressed)

        # self.delete_button.clicked.connect(lambda: self.model.delete(self.table_view.selectedIndexes()[0]))
        self.delete_button.clicked.connect(self.tag_torles)
        ###self.add_button.clicked.connect(self.model.add)
        self.modify_button.clicked.connect(self.tag_modositas)

    def tag_torles(self):
        if len(self.table_view.selectedIndexes()) > 0:
            self.model.delete(self.table_view.selectedIndexes()[0])
        else:
            reply = QMessageBox.question(None, 'Hiba!',
                                         'Törlés előtt jelöljön ki egy sort!',
                                         QMessageBox.Ok)

    def tag_modositas(self):
        if len(self.table_view.selectedIndexes()) > 0:
            self.model.modify(self.table_view.selectedIndexes()[0])
        else:
            reply = QMessageBox.question(
                None, 'Hiba!', 'Módosítás előtt jelöljön ki egy sort!',
                QMessageBox.Ok)

    def toolbarpressed(self, a):
        # print("Pressed:", a.text())
        if a.text() == "Kilépés":
            self.close()
        if a.text() == "Excel":
            # print("Indulhat az excel exportálás")
            self.adatok = self.client.get_all(self.table_name)
            self._data = self.adatok[0]
            # print(self._data)
            p.save_as(array=self._data, dest_file_name="tagok.xlsx")
示例#29
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        hlayout = QHBoxLayout()

        layout = QVBoxLayout()

        self.filtert = QLineEdit()
        self.filtert.setPlaceholderText("Search...")
        self.table = QTableView()

        vlayout = QVBoxLayout()
        vlayout.addWidget(self.filtert)
        vlayout.addWidget(self.table)

        # Left/right pane.
        hlayout.addLayout(vlayout)
        hlayout.addLayout(layout)

        form = QFormLayout()

        self.track_id = QSpinBox()
        self.track_id.setDisabled(True)
        self.track_id.setRange(0, 2147483647)
        self.name = QLineEdit()
        self.album = QComboBox()
        self.media_type = QComboBox()
        self.genre = QComboBox()
        self.composer = QLineEdit()

        self.milliseconds = QSpinBox()
        self.milliseconds.setRange(0, 2147483647)
        self.milliseconds.setSingleStep(1)

        self.bytes = QSpinBox()
        self.bytes.setRange(0, 2147483647)
        self.bytes.setSingleStep(1)

        self.unit_price = QDoubleSpinBox()
        self.unit_price.setRange(0, 999)
        self.unit_price.setSingleStep(0.01)
        self.unit_price.setPrefix("$")

        form.addRow(QLabel("Track ID"), self.track_id)
        form.addRow(QLabel("Track name"), self.name)
        form.addRow(QLabel("Composer"), self.composer)
        form.addRow(QLabel("Milliseconds"), self.milliseconds)
        form.addRow(QLabel("Bytes"), self.bytes)
        form.addRow(QLabel("Unit Price"), self.unit_price)

        self.model = QSqlTableModel(db=db)

        self.proxy_model = QSortFilterProxyModel()
        self.proxy_model.setSourceModel(self.model)
        self.proxy_model.sort(1, Qt.AscendingOrder)
        self.proxy_model.setFilterKeyColumn(-1)  # all columns
        self.table.setModel(self.proxy_model)

        # Update search when filter changes.
        self.filtert.textChanged.connect(self.proxy_model.setFilterFixedString)

        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.proxy_model)

        self.mapper.addMapping(self.track_id, 0)
        self.mapper.addMapping(self.name, 1)
        self.mapper.addMapping(self.composer, 5)
        self.mapper.addMapping(self.milliseconds, 6)
        self.mapper.addMapping(self.bytes, 7)
        self.mapper.addMapping(self.unit_price, 8)

        self.model.setTable("Track")
        self.model.select()

        # Change the mapper selection using the table.
        self.table.selectionModel().currentRowChanged.connect(
            self.mapper.setCurrentModelIndex)

        self.mapper.toFirst()

        # tag::controls[]
        self.setMinimumSize(QSize(800, 400))

        controls = QHBoxLayout()

        prev_rec = QPushButton("Previous")
        prev_rec.clicked.connect(self.mapper.toPrevious)

        next_rec = QPushButton("Next")
        next_rec.clicked.connect(self.mapper.toNext)

        save_rec = QPushButton("Save Changes")
        save_rec.clicked.connect(self.mapper.submit)

        controls.addWidget(prev_rec)
        controls.addWidget(next_rec)
        controls.addWidget(save_rec)

        layout.addLayout(form)
        layout.addLayout(controls)

        widget = QWidget()
        widget.setLayout(hlayout)
        self.setCentralWidget(widget)