Пример #1
0
 def setup_data(self,
                event_params_model_data=[],
                tasks_params_model_data=[],
                tasks_quantity=0,
                events_quantity=0,
                use3mark_system=False):
     events_params_title = [
         'Нач. событие', 'Кон. событие', 'Оптим.', 'Пессим.'
     ]
     if use3mark_system:
         events_params_title.append('Наиб. вероятное')
     self.ui.tasksParamsTable.setModel(
         TableModel(tasks_params_model_data, events_params_title))
     self.ui.eventsParamsTable.setModel(
         TableModel(event_params_model_data, ['Директ. срок']))
     self.ui.timeReservesTable.setModel(
         TableModel([], ['Номера событий', 'Полный резерв времени']))
     self.ui.timeReservesTable.resizeColumnsToContents()
     self.ui.eventsResultsTable.setModel(TableModel([], []))
     self.ui.tasksResultsTable.setModel(TableModel([], []))
     self.ui.tasksQuantitySpinBox.setValue(tasks_quantity)
     self.ui.eventsQuantitySpinBox.setValue(events_quantity)
     if use3mark_system:
         self.ui.mark3SysRadio.setChecked(True)
     else:
         self.ui.mark2SysRadio.setChecked(True)
Пример #2
0
    def __init__(self, parent=None):
        """ Initialize the AddressWidget. """
        super(AddressWidget, self).__init__(parent)

        self.tableModel = TableModel()
        self.newAddressTab = NewAddressTab()
        self.newAddressTab.sendDetails.connect(self.addEntry)

        self.addTab(self.newAddressTab, "Address Book")

        self.setupTabs()
Пример #3
0
    def __init__(self, db=0, mode=0):
        super().__init__()

        layout = QGridLayout()
        #self.central_widget.setLayout(layout)
        self.resize(800, self.height())
        self.lb_find = QInvisibleButton('Поиск')
        self.lb_find.setFont(mainfont)
        self.te_find = QLineEdit()
        self.te_find.setFont(mainfont)
        self.pid = 0

        layout.addWidget(self.te_find, 0, 0, 1, 1)
        layout.addWidget(self.lb_find, 0, 0, 1, 1)
        #if mode:
        #   te.setReadOnly(False)
        self.lb_find.clicked.connect(self.button_pressed)
        self.te_find.returnPressed.connect(self.line_edit_return_pressed)

        self.database = db

        self.table = QTableView()  # Создаём таблицу
        self.table.doubleClicked.connect(self.viewPerson)
        #self.table = table

        self.model = TableModel(self.database.get_peoples())
        self.table.setModel(self.model)
        self.table.resizeRowsToContents()
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        #self.table.setSelectionMode(QAbstractItemView.SingleSelection);
        self.model.dataChanged.connect(self.table.update)

        layout.addWidget(self.table)
        self.setLayout(layout)
Пример #4
0
    def line_edit_return_pressed(self):
        print(self.te_find.text())

        self.model = TableModel(self.database.get_peoples())

        self.proxy_model = QSortFilterProxyModel(self.model)
        self.proxy_model.setSourceModel(self.model)
        self.proxy_model.setFilterFixedString(self.te_find.text())
        self.proxy_model.setFilterKeyColumn(-1)

        self.table.setModel(self.proxy_model)
        self.table.update()
        self.table.resizeRowsToContents()

        #sender = self.sender()
        self.te_find.stackUnder(self.lb_find)
        self.lb_find.setFocus()
Пример #5
0
    def __init__(self, parent=None):
        """ Initialize the AddressWidget. """
        super(AddressWidget, self).__init__(parent)

        self.tableModel = TableModel()
        self.newAddressTab = NewAddressTab()
        self.newAddressTab.sendDetails.connect(self.addEntry)

        self.addTab(self.newAddressTab, "Address Book")

        self.setupTabs()
Пример #6
0
    def openDataset(self):
        file_name = QtWidgets.QFileDialog.getOpenFileName(
            self, 'Open Dataset', QDir.homePath(),
            "CSV and Excel(*.xls *.xlsx *.csv);;Excel files (*.xls *.xlsx);;CSV Files(*.csv)"
        )

        # jika cancel
        if file_name[0] == '' or file_name == None:
            return

        self.tableModel = TableModel.open_dataset(file_name[0])

        # self.columnModel = ColumnModel(self.tableModel.dataset)
        # self.ui.columnQuickWidget.rootContext().setContextProperty('columnModel', self.columnModel)
        # self.columnModelInited.emit()

        if self.tableModel != None:
            self.ui.tableView.setModel(self.tableModel)
            self.ui.stackedWidget.setCurrentIndex(1)
Пример #7
0
class AddressWidget(QTabWidget):
    """ The central widget of the application. Most of the addressbook's
        functionality is contained in this class.
    """

    selectionChanged = Signal(QItemSelection)

    def __init__(self, parent=None):
        """ Initialize the AddressWidget. """
        super(AddressWidget, self).__init__(parent)

        self.tableModel = TableModel()
        self.newAddressTab = NewAddressTab()
        self.newAddressTab.sendDetails.connect(self.addEntry)

        self.addTab(self.newAddressTab, "Address Book")

        self.setupTabs()

    def addEntry(self, name=None, address=None):
        """ Add an entry to the addressbook. """
        if name is None and address is None:
            addDialog = AddDialogWidget()

            if addDialog.exec_():
                name = addDialog.name
                address = addDialog.address

        address = {"name": name, "address": address}
        addresses = self.tableModel.addresses[:]

        # The QT docs for this example state that what we're doing here
        # is checking if the entered name already exists. What they
        # (and we here) are actually doing is checking if the whole
        # name/address pair exists already - ok for the purposes of this
        # example, but obviously not how a real addressbook application
        # should behave.
        try:
            addresses.remove(address)
            QMessageBox.information(self, "Duplicate Name",
                                    "The name \"%s\" already exists." % name)
        except ValueError:
            # The address didn't already exist, so let's add it to the model.

            # Step 1: create the  row
            self.tableModel.insertRows(0)

            # Step 2: get the index of the newly created row and use it.
            # to set the name
            ix = self.tableModel.index(0, 0, QModelIndex())
            self.tableModel.setData(ix, address["name"], Qt.EditRole)

            # Step 3: lather, rinse, repeat for the address.
            ix = self.tableModel.index(0, 1, QModelIndex())
            self.tableModel.setData(ix, address["address"], Qt.EditRole)

            # Remove the newAddressTab, as we now have at least one
            # address in the model.
            self.removeTab(self.indexOf(self.newAddressTab))

            # The screenshot for the QT example shows nicely formatted
            # multiline cells, but the actual application doesn't behave
            # quite so nicely, at least on Ubuntu. Here we resize the newly
            # created row so that multiline addresses look reasonable.
            tableView = self.currentWidget()
            tableView.resizeRowToContents(ix.row())

    def editEntry(self):
        """ Edit an entry in the addressbook. """
        tableView = self.currentWidget()
        proxyModel = tableView.model()
        selectionModel = tableView.selectionModel()

        # Get the name and address of the currently selected row.
        indexes = selectionModel.selectedRows()

        for index in indexes:
            row = proxyModel.mapToSource(index).row()
            ix = self.tableModel.index(row, 0, QModelIndex())
            name = self.tableModel.data(ix, Qt.DisplayRole)
            ix = self.tableModel.index(row, 1, QModelIndex())
            address = self.tableModel.data(ix, Qt.DisplayRole)

        # Open an addDialogWidget, and only allow the user to edit the address.
        addDialog = AddDialogWidget()
        addDialog.setWindowTitle("Edit a Contact")

        addDialog.nameText.setReadOnly(True)
        addDialog.nameText.setText(name)
        addDialog.addressText.setText(address)

        # If the address is different, add it to the model.
        if addDialog.exec_():
            newAddress = addDialog.address
            if newAddress != address:
                ix = self.tableModel.index(row, 1, QModelIndex())
                self.tableModel.setData(ix, newAddress, Qt.EditRole)

    def removeEntry(self):
        """ Remove an entry from the addressbook. """
        tableView = self.currentWidget()
        proxyModel = tableView.model()
        selectionModel = tableView.selectionModel()

        # Just like editEntry, but this time remove the selected row.
        indexes = selectionModel.selectedRows()

        for index in indexes:
            row = proxyModel.mapToSource(index).row()
            self.tableModel.removeRows(row)

        # If we've removed the last address in the model, display the
        # newAddressTab
        if self.tableModel.rowCount() == 0:
            self.insertTab(0, self.newAddressTab, "Address Book")

    def setupTabs(self):
        """ Setup the various tabs in the AddressWidget. """
        groups = ["ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VW", "XYZ"]

        for group in groups:
            proxyModel = QSortFilterProxyModel(self)
            proxyModel.setSourceModel(self.tableModel)
            proxyModel.setDynamicSortFilter(True)

            tableView = QTableView()
            tableView.setModel(proxyModel)
            tableView.setSortingEnabled(True)
            tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
            tableView.horizontalHeader().setStretchLastSection(True)
            tableView.verticalHeader().hide()
            tableView.setEditTriggers(QAbstractItemView.NoEditTriggers)
            tableView.setSelectionMode(QAbstractItemView.SingleSelection)

            # This here be the magic: we use the group name (e.g. "ABC") to
            # build the regex for the QSortFilterProxyModel for the group's
            # tab. The regex will end up looking like "^[ABC].*", only
            # allowing this tab to display items where the name starts with
            # "A", "B", or "C". Notice that we set it to be case-insensitive.
            reFilter = "^[%s].*" % group

            proxyModel.setFilterRegExp(QRegExp(reFilter, Qt.CaseInsensitive))
            proxyModel.setFilterKeyColumn(0)  # Filter on the "name" column
            proxyModel.sort(0, Qt.AscendingOrder)

            #tableView.selectionModel().selectionChanged.connect(self.selectionChanged)

            self.addTab(tableView, group)

    # Note: the QT example uses a QDataStream for the saving and loading.
    # Here we're using a python dictionary to store the addresses, which
    # can't be streamed using QDataStream, so we just use cpickle for this
    # example.
    def readFromFile(self, filename):
        """ Read contacts in from a file. """
        try:
            f = open(filename, "rb")
            addresses = pickle.load(f)
        except IOError:
            QMessageBox.information(self, "Unable to open file: %s" % filename)
        finally:
            f.close()

        if len(addresses) == 0:
            QMessageBox.information(self, "No contacts in file: %s" % filename)
        else:
            for address in addresses:
                self.addEntry(address["name"], address["address"])

    def writeToFile(self, filename):
        """ Save all contacts in the model to a file. """
        try:
            f = open(filename, "wb")
            pickle.dump(self.tableModel.addresses, f)

        except IOError:
            QMessageBox.information(self, "Unable to open file: %s" % filename)
        finally:
            f.close()
Пример #8
0
class AddressWidget(QTabWidget):
    """ The central widget of the application. Most of the addressbook's
        functionality is contained in this class.
    """

    selectionChanged = Signal(QItemSelection)

    def __init__(self, parent=None):
        """ Initialize the AddressWidget. """
        super(AddressWidget, self).__init__(parent)

        self.tableModel = TableModel()
        self.newAddressTab = NewAddressTab()
        self.newAddressTab.sendDetails.connect(self.addEntry)

        self.addTab(self.newAddressTab, "Address Book")

        self.setupTabs()

    def addEntry(self, name=None, address=None):
        """ Add an entry to the addressbook. """
        if name is None and address is None:
            addDialog = AddDialogWidget()

            if addDialog.exec_():
                name = addDialog.name
                address = addDialog.address

        address = {"name": name, "address": address}
        addresses = self.tableModel.addresses[:]

        # The QT docs for this example state that what we're doing here
        # is checking if the entered name already exists. What they
        # (and we here) are actually doing is checking if the whole
        # name/address pair exists already - ok for the purposes of this
        # example, but obviously not how a real addressbook application
        # should behave.
        try:
            addresses.remove(address)
            QMessageBox.information(self, "Duplicate Name",
                                    "The name \"%s\" already exists." % name)
        except ValueError:
            # The address didn't already exist, so let's add it to the model.

            # Step 1: create the  row
            self.tableModel.insertRows(0)

            # Step 2: get the index of the newly created row and use it.
            # to set the name
            ix = self.tableModel.index(0, 0, QModelIndex())
            self.tableModel.setData(ix, address["name"], Qt.EditRole)

            # Step 3: lather, rinse, repeat for the address.
            ix = self.tableModel.index(0, 1, QModelIndex())
            self.tableModel.setData(ix, address["address"], Qt.EditRole)

            # Remove the newAddressTab, as we now have at least one
            # address in the model.
            self.removeTab(self.indexOf(self.newAddressTab))

            # The screenshot for the QT example shows nicely formatted
            # multiline cells, but the actual application doesn't behave
            # quite so nicely, at least on Ubuntu. Here we resize the newly
            # created row so that multiline addresses look reasonable.
            tableView = self.currentWidget()
            tableView.resizeRowToContents(ix.row())

    def editEntry(self):
        """ Edit an entry in the addressbook. """
        tableView = self.currentWidget()
        proxyModel = tableView.model()
        selectionModel = tableView.selectionModel()

        # Get the name and address of the currently selected row.
        indexes = selectionModel.selectedRows()

        for index in indexes:
            row = proxyModel.mapToSource(index).row()
            ix = self.tableModel.index(row, 0, QModelIndex())
            name = self.tableModel.data(ix, Qt.DisplayRole)
            ix = self.tableModel.index(row, 1, QModelIndex())
            address = self.tableModel.data(ix, Qt.DisplayRole)

        # Open an addDialogWidget, and only allow the user to edit the address.
        addDialog = AddDialogWidget()
        addDialog.setWindowTitle("Edit a Contact")

        addDialog.nameText.setReadOnly(True)
        addDialog.nameText.setText(name)
        addDialog.addressText.setText(address)

        # If the address is different, add it to the model.
        if addDialog.exec_():
            newAddress = addDialog.address
            if newAddress != address:
                ix = self.tableModel.index(row, 1, QModelIndex())
                self.tableModel.setData(ix, newAddress, Qt.EditRole)

    def removeEntry(self):
        """ Remove an entry from the addressbook. """
        tableView = self.currentWidget()
        proxyModel = tableView.model()
        selectionModel = tableView.selectionModel()

        # Just like editEntry, but this time remove the selected row.
        indexes = selectionModel.selectedRows()

        for index in indexes:
            row = proxyModel.mapToSource(index).row()
            self.tableModel.removeRows(row)

        # If we've removed the last address in the model, display the
        # newAddressTab
        if self.tableModel.rowCount() == 0:
            self.insertTab(0, self.newAddressTab, "Address Book")

    def setupTabs(self):
        """ Setup the various tabs in the AddressWidget. """
        groups = ["ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VW", "XYZ"]

        for group in groups:
            proxyModel = QSortFilterProxyModel(self)
            proxyModel.setSourceModel(self.tableModel)
            proxyModel.setDynamicSortFilter(True)

            tableView = QTableView()
            tableView.setModel(proxyModel)
            tableView.setSortingEnabled(True)
            tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
            tableView.horizontalHeader().setStretchLastSection(True)
            tableView.verticalHeader().hide()
            tableView.setEditTriggers(QAbstractItemView.NoEditTriggers)
            tableView.setSelectionMode(QAbstractItemView.SingleSelection)

            # This here be the magic: we use the group name (e.g. "ABC") to
            # build the regex for the QSortFilterProxyModel for the group's
            # tab. The regex will end up looking like "^[ABC].*", only
            # allowing this tab to display items where the name starts with
            # "A", "B", or "C". Notice that we set it to be case-insensitive.
            reFilter = "^[%s].*" % group

            proxyModel.setFilterRegExp(QRegExp(reFilter, Qt.CaseInsensitive))
            proxyModel.setFilterKeyColumn(0) # Filter on the "name" column
            proxyModel.sort(0, Qt.AscendingOrder)

            # This prevents an application crash (see: http://www.qtcentre.org/threads/58874-QListView-SelectionModel-selectionChanged-Crash)
            viewselectionmodel = tableView.selectionModel()
            tableView.selectionModel().selectionChanged.connect(self.selectionChanged)

            self.addTab(tableView, group)

    # Note: the QT example uses a QDataStream for the saving and loading.
    # Here we're using a python dictionary to store the addresses, which
    # can't be streamed using QDataStream, so we just use cpickle for this
    # example.
    def readFromFile(self, filename):
        """ Read contacts in from a file. """
        try:
            f = open(filename, "rb")
            addresses = pickle.load(f)
        except IOError:
            QMessageBox.information(self, "Unable to open file: %s" % filename)
        finally:
            f.close()

        if len(addresses) == 0:
            QMessageBox.information(self, "No contacts in file: %s" % filename)
        else:
            for address in addresses:
                self.addEntry(address["name"], address["address"])

    def writeToFile(self, filename):
        """ Save all contacts in the model to a file. """
        try:
            f = open(filename, "wb")
            pickle.dump(self.tableModel.addresses, f)

        except IOError:
            QMessageBox.information(self, "Unable to open file: %s" % filename)
        finally:
            f.close()
Пример #9
0
    def async_init(self):
        self.database = AllTables('database/objects')

        self.model = TableModel(self.database.get_peoples())
        self.table.setModel(self.model)
        self.table.resizeRowsToContents()
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.model.dataChanged.connect(self.table.update)

        # Работаем с выпадающим меню
        def openMenu(position):
            menu = QMenu()
            relAction = menu.addAction('Связи')
            menu.addSeparator()
            albAction = menu.addAction('Альбомы')
            menu.addSeparator()
            miniatureAction = menu.addAction('Миниатюра')
            menu.addSeparator()
            viewAction = menu.addAction('Просмотреть')
            addAction = menu.addAction('Добавить')
            editAction = menu.addAction('Редактировать')
            delAction = menu.addAction('Удалить')
            menu.addSeparator()
            drawGraphAction = menu.addAction('Построить дерево')
            menu.addSeparator()
            quitAction = menu.addAction('Выход')
            action = menu.exec_(self.table.mapToGlobal(position))

            if action == viewAction:
                self.viewPerson()

            if action == miniatureAction:
                p = self.get_selected_people()
                print('p = ' + str(p))
                if p is not None:
                    photo_ids = self.database.get_all_photo_ids(p['pid'])
                    path = 0
                    if photo_ids and type(photo_ids) == type(
                        []) and len(photo_ids) > 0:
                        path = self.database.get_photo_path(
                            p['pid'], photo_ids[0])
                    gm = GalleryMiniature(p['pid'], path)
                    gm.exec()

            if action == albAction:
                p = self.get_selected_people()
                if p is not None:
                    self.albuns = AlbumViewer(p['pid'], self.database, 1)
                    self.albuns.show()

            if action == addAction:
                self.personal_card = PersonalCard(
                    self.database.get_people(self.database.add_people({})),
                    self.database, 1)
                self.personal_card.exec_()

                self.line_edit_return_pressed()

            if action == editAction:
                p = self.get_selected_people()
                if p is not None:
                    self.personal_card = PersonalCard(p, self.database, 1)
                    self.personal_card.exec_()

                    self.line_edit_return_pressed()

            if action == delAction:
                res = QMessageBox.question(
                    self, 'ВНИМАНИЕ!!!',
                    "Вы действительно хотите выполнить удаление?",
                    QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
                if res == QMessageBox.Yes:
                    select = self.table.selectionModel()
                    if select.hasSelection():
                        id_list = [
                            index.data() for index in
                            self.table.selectionModel().selection().indexes()
                            if index.column() == 0
                        ]
                        print(id_list)
                        self.database.del_people(id_list)
                        self.database.peoples.save()
                        for pid in id_list:
                            print('remove = ' + str(self.model.removeRow(pid)))

                    self.line_edit_return_pressed()

            if action == relAction:
                pid = self.get_selected_pid()
                backup_relations = copy.deepcopy(self.database.relations)
                self.relation_card = RelationCard(pid, self.database, 2)
                if not self.relation_card.exec_():
                    self.database.relations = backup_relations

            if action == drawGraphAction:
                print('draw graph')
                #dialog = MyDialog()
                #dialog.exec_()
                #engine = dialog.engine
                engine = 'dot'
                self.gd = GraphDrawer(self.database, engine)

            if action == quitAction:
                qApp.quit()

        self.table.setContextMenuPolicy(Qt.CustomContextMenu)
        self.table.customContextMenuRequested.connect(openMenu)
Пример #10
0
class TdisMainForm(QMainWindow):
    def __init__(self, parent=None):
        super().__init__()
        self.setWindowTitle("Родословная")
        self.resize(800, self.height())
        self.distance = 1000

        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)

        layout = QGridLayout()
        self.central_widget.setLayout(layout)

        self.lb_find = QInvisibleButton('Поиск')
        self.lb_find.setFont(mainfont)
        self.te_find = QLineEdit()
        self.te_find.setFont(mainfont)

        layout.addWidget(self.te_find, 0, 0, 1, 1)
        layout.addWidget(self.lb_find, 0, 0, 1, 1)
        #if mode:
        #   te.setReadOnly(False)
        self.lb_find.clicked.connect(self.button_pressed)
        self.te_find.returnPressed.connect(self.line_edit_return_pressed)

        self.table = QTableView()  # Создаём таблицу
        self.table.doubleClicked.connect(self.viewPerson)
        layout.addWidget(self.table)
        self.table.setFocus()
        timer = QTimer(self)
        timer.singleShot(0, self.async_init)

    def async_init(self):
        self.database = AllTables('database/objects')

        self.model = TableModel(self.database.get_peoples())
        self.table.setModel(self.model)
        self.table.resizeRowsToContents()
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.model.dataChanged.connect(self.table.update)

        # Работаем с выпадающим меню
        def openMenu(position):
            menu = QMenu()
            relAction = menu.addAction('Связи')
            menu.addSeparator()
            albAction = menu.addAction('Альбомы')
            menu.addSeparator()
            miniatureAction = menu.addAction('Миниатюра')
            menu.addSeparator()
            viewAction = menu.addAction('Просмотреть')
            addAction = menu.addAction('Добавить')
            editAction = menu.addAction('Редактировать')
            delAction = menu.addAction('Удалить')
            menu.addSeparator()
            drawGraphAction = menu.addAction('Построить дерево')
            menu.addSeparator()
            quitAction = menu.addAction('Выход')
            action = menu.exec_(self.table.mapToGlobal(position))

            if action == viewAction:
                self.viewPerson()

            if action == miniatureAction:
                p = self.get_selected_people()
                print('p = ' + str(p))
                if p is not None:
                    photo_ids = self.database.get_all_photo_ids(p['pid'])
                    path = 0
                    if photo_ids and type(photo_ids) == type(
                        []) and len(photo_ids) > 0:
                        path = self.database.get_photo_path(
                            p['pid'], photo_ids[0])
                    gm = GalleryMiniature(p['pid'], path)
                    gm.exec()

            if action == albAction:
                p = self.get_selected_people()
                if p is not None:
                    self.albuns = AlbumViewer(p['pid'], self.database, 1)
                    self.albuns.show()

            if action == addAction:
                self.personal_card = PersonalCard(
                    self.database.get_people(self.database.add_people({})),
                    self.database, 1)
                self.personal_card.exec_()

                self.line_edit_return_pressed()

            if action == editAction:
                p = self.get_selected_people()
                if p is not None:
                    self.personal_card = PersonalCard(p, self.database, 1)
                    self.personal_card.exec_()

                    self.line_edit_return_pressed()

            if action == delAction:
                res = QMessageBox.question(
                    self, 'ВНИМАНИЕ!!!',
                    "Вы действительно хотите выполнить удаление?",
                    QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
                if res == QMessageBox.Yes:
                    select = self.table.selectionModel()
                    if select.hasSelection():
                        id_list = [
                            index.data() for index in
                            self.table.selectionModel().selection().indexes()
                            if index.column() == 0
                        ]
                        print(id_list)
                        self.database.del_people(id_list)
                        self.database.peoples.save()
                        for pid in id_list:
                            print('remove = ' + str(self.model.removeRow(pid)))

                    self.line_edit_return_pressed()

            if action == relAction:
                pid = self.get_selected_pid()
                backup_relations = copy.deepcopy(self.database.relations)
                self.relation_card = RelationCard(pid, self.database, 2)
                if not self.relation_card.exec_():
                    self.database.relations = backup_relations

            if action == drawGraphAction:
                print('draw graph')
                #dialog = MyDialog()
                #dialog.exec_()
                #engine = dialog.engine
                engine = 'dot'
                self.gd = GraphDrawer(self.database, engine)

            if action == quitAction:
                qApp.quit()

        self.table.setContextMenuPolicy(Qt.CustomContextMenu)
        self.table.customContextMenuRequested.connect(openMenu)

    def get_selected_pid(self):
        pid_list = [
            index.data()
            for index in self.table.selectionModel().selection().indexes()
            if index.column() == 0
        ]
        if len(pid_list) == 1:
            return int(pid_list[0])
        return None

    def get_selected_people(self):
        pid_list = [
            index.data()
            for index in self.table.selectionModel().selection().indexes()
            if index.column() == 0
        ]
        if len(pid_list) == 1:
            return self.database.get_people(int(pid_list[0]))
        return None

    def viewPerson(self):
        p = self.get_selected_people()
        if p is not None:
            self.personal_card = PersonalCard(p, self.database, 0)
            self.personal_card.show()

    def button_pressed(self):
        self.lb_find.stackUnder(self.te_find)
        self.te_find.setFocus()

    def line_edit_return_pressed(self):
        print(self.te_find.text())

        self.model = TableModel(self.database.get_peoples())

        self.proxy_model = QSortFilterProxyModel(self.model)
        self.proxy_model.setSourceModel(self.model)
        self.proxy_model.setFilterFixedString(self.te_find.text())
        self.proxy_model.setFilterKeyColumn(-1)

        self.table.setModel(self.proxy_model)
        self.table.update()
        self.table.resizeRowsToContents()

        #sender = self.sender()
        self.te_find.stackUnder(self.lb_find)
        self.lb_find.setFocus()
Пример #11
0
    def __init__(self, parent=None):
        super(ImageSimilarity, self).__init__(parent)

        #Build window
        self.setWindowTitle('Image Similarity Search')
        self.radio_pca = QRadioButton('PCA')
        self.radio_pca.setChecked(True)
        self.radio_deep = QRadioButton('Convolutional')
        self.button_load_weights = QPushButton('Load Weights')
        self.button_build_DB = QPushButton('Build Database')
        self.button_save_DB = QPushButton('Save Database')
        self.button_load_DB = QPushButton('Load Database')
        self.button_load_img = QPushButton('Load Image')
        self.button_search = QPushButton('Search')
        self.button_search.setEnabled(False)
        self.button_save_result = QPushButton('Save Result')
        self.button_save_result.setEnabled(False)
        self.spinbox = QSpinBox()
        self.spinbox.setMinimum(-1)
        self.spinbox.setMaximum(99999)
        self.spinbox.setValue(0)
        self.spinboxlabel = QLabel('Max. Distance:')
        self.spinboxlabel.setAlignment(Qt.AlignRight)
        self.searchlabel = QLabel('Query Image:')
        self.countlabel = QLabel('# of Hits:')
        self.table = QTableView()
        #self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.table.horizontalHeader().setStretchLastSection(True)
        self.model = TableModel(parent=self)
        self.table.setModel(self.model)
        self.table.setSortingEnabled(True)
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)

        hbox_radio = QHBoxLayout()
        hbox_radio.addWidget(self.radio_pca)
        hbox_radio.addWidget(self.radio_deep)
        hbox_radio.addWidget(self.button_load_weights)

        hbox_buttons = QHBoxLayout()
        hbox_buttons.addWidget(self.button_build_DB)
        hbox_buttons.addWidget(self.button_load_DB)
        hbox_buttons.addWidget(self.button_save_DB)
        hbox_buttons.addWidget(self.button_load_img)
        hbox_buttons.addWidget(self.button_search)
        hbox_buttons.addWidget(self.spinboxlabel)
        hbox_buttons.addWidget(self.spinbox)

        radio_widget = QWidget()
        radio_widget.setLayout(hbox_radio)

        button_widget = QWidget()
        button_widget.setLayout(hbox_buttons)

        external_layout = QVBoxLayout()
        external_layout.addWidget(radio_widget)
        external_layout.addWidget(button_widget)
        external_layout.addWidget(self.searchlabel)
        external_layout.addWidget(self.countlabel)
        external_layout.addWidget(self.table)
        external_layout.addWidget(self.button_save_result)

        self.setLayout(external_layout)

        #Connect signals and slots
        self.radio_pca.toggled.connect(lambda: self.switch_NN(self.radio_pca))
        self.radio_deep.toggled.connect(
            lambda: self.switch_NN(self.radio_deep))
        self.button_load_weights.clicked.connect(self.load_weights)
        self.button_build_DB.clicked.connect(self.build_DB)
        self.button_load_DB.clicked.connect(self.load_DB)
        self.button_save_DB.clicked.connect(self.save_DB)
        self.button_load_img.clicked.connect(self.load_image)
        self.button_search.clicked.connect(self.search)
        self.button_save_result.clicked.connect(self.save_search)

        #Build neural network
        self.encoder = build_pca_autoencoder()

        #See if a database already exists
        if not os.path.isfile(os.path.join(application_path, 'std_db_pca.db')):
            self.firstTimeStart(os.path.join(application_path,
                                             'std_db_pca.db'))
        else:
            self.database = load_database(
                os.path.join(application_path, 'std_db_pca.db'))
Пример #12
0
class ImageSimilarity(QWidget):
    """
    Main class
    """
    def __init__(self, parent=None):
        super(ImageSimilarity, self).__init__(parent)

        #Build window
        self.setWindowTitle('Image Similarity Search')
        self.radio_pca = QRadioButton('PCA')
        self.radio_pca.setChecked(True)
        self.radio_deep = QRadioButton('Convolutional')
        self.button_load_weights = QPushButton('Load Weights')
        self.button_build_DB = QPushButton('Build Database')
        self.button_save_DB = QPushButton('Save Database')
        self.button_load_DB = QPushButton('Load Database')
        self.button_load_img = QPushButton('Load Image')
        self.button_search = QPushButton('Search')
        self.button_search.setEnabled(False)
        self.button_save_result = QPushButton('Save Result')
        self.button_save_result.setEnabled(False)
        self.spinbox = QSpinBox()
        self.spinbox.setMinimum(-1)
        self.spinbox.setMaximum(99999)
        self.spinbox.setValue(0)
        self.spinboxlabel = QLabel('Max. Distance:')
        self.spinboxlabel.setAlignment(Qt.AlignRight)
        self.searchlabel = QLabel('Query Image:')
        self.countlabel = QLabel('# of Hits:')
        self.table = QTableView()
        #self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.table.horizontalHeader().setStretchLastSection(True)
        self.model = TableModel(parent=self)
        self.table.setModel(self.model)
        self.table.setSortingEnabled(True)
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)

        hbox_radio = QHBoxLayout()
        hbox_radio.addWidget(self.radio_pca)
        hbox_radio.addWidget(self.radio_deep)
        hbox_radio.addWidget(self.button_load_weights)

        hbox_buttons = QHBoxLayout()
        hbox_buttons.addWidget(self.button_build_DB)
        hbox_buttons.addWidget(self.button_load_DB)
        hbox_buttons.addWidget(self.button_save_DB)
        hbox_buttons.addWidget(self.button_load_img)
        hbox_buttons.addWidget(self.button_search)
        hbox_buttons.addWidget(self.spinboxlabel)
        hbox_buttons.addWidget(self.spinbox)

        radio_widget = QWidget()
        radio_widget.setLayout(hbox_radio)

        button_widget = QWidget()
        button_widget.setLayout(hbox_buttons)

        external_layout = QVBoxLayout()
        external_layout.addWidget(radio_widget)
        external_layout.addWidget(button_widget)
        external_layout.addWidget(self.searchlabel)
        external_layout.addWidget(self.countlabel)
        external_layout.addWidget(self.table)
        external_layout.addWidget(self.button_save_result)

        self.setLayout(external_layout)

        #Connect signals and slots
        self.radio_pca.toggled.connect(lambda: self.switch_NN(self.radio_pca))
        self.radio_deep.toggled.connect(
            lambda: self.switch_NN(self.radio_deep))
        self.button_load_weights.clicked.connect(self.load_weights)
        self.button_build_DB.clicked.connect(self.build_DB)
        self.button_load_DB.clicked.connect(self.load_DB)
        self.button_save_DB.clicked.connect(self.save_DB)
        self.button_load_img.clicked.connect(self.load_image)
        self.button_search.clicked.connect(self.search)
        self.button_save_result.clicked.connect(self.save_search)

        #Build neural network
        self.encoder = build_pca_autoencoder()

        #See if a database already exists
        if not os.path.isfile(os.path.join(application_path, 'std_db_pca.db')):
            self.firstTimeStart(os.path.join(application_path,
                                             'std_db_pca.db'))
        else:
            self.database = load_database(
                os.path.join(application_path, 'std_db_pca.db'))

    def firstTimeStart(self, savename):
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Information)
        msg.setText(
            "Please select a directory to search for images in. This will then build the search database."
        )
        msg.setWindowTitle("Setup")
        msg.setStandardButtons(QMessageBox.Ok)
        if msg.exec_():
            dir = None
            while not dir:
                dir = QFileDialog.getExistingDirectory(
                    self, 'Choose Search Root', QDir.homePath(),
                    QFileDialog.ShowDirsOnly)
            paths = get_image_paths(dir)
            self.progresswindow = self.make_progress_window(len(paths))
            self.progresswindow.show()
            graph = tf.get_default_graph()
            build_thread = Build_Thread(self.encoder, paths, graph, self)
            build_thread.processed.connect(self.update_progress)
            build_thread.finished.connect(self.set_database)
            build_thread.finished.connect(
                lambda db: save_database(db, savename))
            build_thread.close.connect(self.progresswindow.close)
            build_thread.close.connect(lambda: self.build_message(savename))
            build_thread.start()

    def build_message(self, savename=None):
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Information)
        msg.setText("Database complete!")
        if not savename:
            msg.setInformativeText(
                "Don't forget to save your database to avoid having to rebuild it upon program restart."
            )
        else:
            msg.setInformativeText(
                "The database was saved as {} and will be loaded as default on all subsequent program starts."
                .format(savename))
        msg.setWindowTitle("Completed")
        msg.setStandardButtons(QMessageBox.Ok)
        msg.exec_()

    def make_progress_window(self, max):
        window = QDialog(self)
        window.setWindowTitle("Building Search Database")
        self.progress = QProgressBar(window)
        self.progress.setMaximum(max)
        self.progresslabel = QLabel(window)
        self.progresslabel.setText("Processed: 0 of {}".format(max))
        layout = QVBoxLayout()
        window.setLayout(layout)
        layout.addWidget(self.progresslabel)
        layout.addWidget(self.progress)
        window.setModal(Qt.ApplicationModal)
        return window

    def update_progress(self, prog, max):
        self.progresslabel.setText("Processed: {} of {}".format(prog, max))
        self.progress.setValue(prog)

    def set_database(self, db):
        self.database = db

    def load_image(self):
        f, _ = QFileDialog.getOpenFileName(
            self, 'Load Image', QDir.homePath(),
            "Image Files (*.jpg *.jpeg *.png *.tga *.bmp)")
        if f:
            self.search_img_path = f
            self.searchlabel.setText('Query Image: {}'.format(
                os.path.basename(f)))
            if not self.button_search.isEnabled():
                self.button_search.setEnabled(True)

    def search(self):
        if self.search_img_path:
            #start = timer()
            self.lastSearchQuery = self.search_img_path
            if not self.button_save_result.isEnabled():
                self.button_save_result.setEnabled(True)
            hits = similarity_search(self.search_img_path, self.database,
                                     self.encoder, self.spinbox.value())
            self.countlabel.setText('# of hits: {}'.format(str(len(hits))))
            #Update Table Model
            self.model.removeRows(0, self.model.rowCount())
            for hit in hits:
                if b'name' in hit.keys():
                    row = {
                        "name": hit[b'name'],
                        "path": hit[b'path'],
                        "distance": hit['distance']
                    }
                else:
                    row = {
                        "name": hit['name'],
                        "path": hit['path'],
                        "distance": hit['distance']
                    }
                self.model.appendRow(row)
            #end = timer()
            #print('Search Time: {} seconds'.format(end - start))

    def save_search(self):
        filename, _ = QFileDialog.getSaveFileName(self, 'Save Result',
                                                  QDir.currentPath(),
                                                  'Text files (*.txt)')
        if filename:
            with open(filename, "w") as file:
                file.write("Query image: {}\n\n".format(self.lastSearchQuery))
                for i in range(self.model.rowCount()):
                    file.write("Name: {}, Path: {}, Distance: {}\n".format(
                        self.model.results[i]['name'],
                        self.model.results[i]['path'],
                        self.model.results[i]['distance']))

    def switch_NN(self, b):
        if b.text() == 'PCA' and b.isChecked():
            reset_tf_session()
            self.encoder = build_pca_autoencoder()
            self.database = load_database(
                os.path.join(application_path, 'std_db_pca.db'))
            self.search_img_path = None
            self.searchlabel.setText('Query Image:')
            self.button_search.setEnabled(False)
        elif b.text() == 'Convolutional' and b.isChecked():
            reset_tf_session()
            self.encoder = build_deep_autoencoder()
            if os.path.isfile(os.path.join(application_path,
                                           'std_db_deep.db')):
                self.database = load_database(
                    os.path.join(application_path, 'std_db_deep.db'))
            else:
                self.firstTimeStart(
                    os.path.join(application_path, 'std_db_deep.db'))
            self.search_img_path = None
            self.searchlabel.setText('Query Image:')
            self.button_search.setEnabled(False)
        else:
            pass

    def load_weights(self):
        filename, _ = QFileDialog.getOpenFileName(
            self, 'Load Weights', QDir.currentPath(),
            'Neural Network Weights (*.h5)')
        if filename:
            load_NN_weights(self.encoder, filename)

    def build_DB(self):
        dlg = QFileDialog()
        dlg.setFileMode(QFileDialog.Directory)
        if dlg.exec_():
            #start = timer()
            dirs = dlg.selectedFiles()
            paths = get_image_paths(dirs[0])
            self.progresswindow = self.make_progress_window(len(paths))
            self.progresswindow.show()
            graph = tf.get_default_graph()
            build_thread = Build_Thread(self.encoder, paths, graph, self)
            build_thread.processed.connect(self.update_progress)
            build_thread.finished.connect(self.set_database)
            build_thread.close.connect(self.progresswindow.close)
            build_thread.close.connect(self.build_message)
            #build_thread.close.connect(lambda : print(timer() - start))
            build_thread.start()

    def load_DB(self):
        dbname, _ = QFileDialog.getOpenFileName(self, 'Load Database',
                                                QDir.currentPath(),
                                                "Database files (*.db)")
        if dbname:
            self.database = load_database(dbname)

    def save_DB(self):
        filename, _ = QFileDialog.getSaveFileName(self, 'Save Database',
                                                  QDir.currentPath(),
                                                  'Database files (*.db)')
        if filename:
            save_database(self.database, filename, True)