class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.view = QTableView()
        self.view.horizontalHeader().hide()
        self.view.verticalHeader().hide()
        self.view.setGridStyle(Qt.NoPen)

        delegate = PreviewDelegate()
        self.view.setItemDelegate(delegate)
        self.model = PreviewModel()
        self.view.setModel(self.model)

        self.setCentralWidget(self.view)

        # Add a bunch of images.
        image_files = glob.glob("*.jpg")
        for n, fn in enumerate(image_files):
            image = QImage(fn)
            item = preview(n, fn, image)
            self.model.previews.append(item)
        self.model.layoutChanged.emit()

        self.view.resizeRowsToContents()
        self.view.resizeColumnsToContents()
Exemple #2
0
class DebugBreakpointsWidget(QWidget, DockContextHandler):
	def __init__(self, parent, name, data):
		if not type(data) == binaryninja.binaryview.BinaryView:
			raise Exception('expected widget data to be a BinaryView')

		self.bv = data
		
		QWidget.__init__(self, parent)
		DockContextHandler.__init__(self, self, name)
		self.actionHandler = UIActionHandler()
		self.actionHandler.setupActionHandler(self)

		self.table = QTableView(self)
		self.model = DebugBreakpointsListModel(self.table, data)
		self.table.setModel(self.model)

		self.item_delegate = DebugBreakpointsItemDelegate(self)
		self.table.setItemDelegate(self.item_delegate)

		# self.table.setSortingEnabled(True)
		self.table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
		self.table.setSelectionMode(QAbstractItemView.ExtendedSelection)

		self.table.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
		self.table.verticalHeader().setVisible(False)

		self.table.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
		self.table.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)

		self.table.resizeColumnsToContents()
		self.table.resizeRowsToContents()

		for i in range(len(self.model.columns)):
			self.table.setColumnWidth(i, self.item_delegate.sizeHint(self.table.viewOptions(), self.model.index(-1, i, QModelIndex())).width())
		self.table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)

		layout = QVBoxLayout()
		layout.setContentsMargins(0, 0, 0, 0)
		layout.setSpacing(0)
		layout.addWidget(self.table)
		self.setLayout(layout)

	def notifyOffsetChanged(self, offset):
		pass

	def notifyBreakpointsChanged(self, new_rows):
		self.model.update_rows(new_rows)

	def contextMenuEvent(self, event):
		self.m_contextMenuManager.show(self.m_menu, self.actionHandler)

	def shouldBeVisible(self, view_frame):
		if view_frame is None:
			return False
		else:
			return True
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
Exemple #4
0
    def table_insert(self, TableModel: TableModel,
                     TableView: QtWidgets.QTableView):
        print('Inserting a row into table.')
        # get selected row index
        selected_indexes = TableView.selectionModel().selectedIndexes()
        selected_row_index = selected_indexes[-1].row()
        print(f'row index {selected_row_index}.')
        # insert
        TableModel.insertRow(selected_row_index)

        print(TableView == self.ui.tableView_emitters)
        TableView.model().layoutChanged.emit()
        TableView.resizeRowsToContents()
        self.repaint()
Exemple #5
0
    def table_remove(self, TableModel: TableModel,
                     TableView: QtWidgets.QTableView):
        if TableModel.rowCount(TableView) <= 1:
            raise ValueError('Not enough rows to delete.')

        # get selected row index
        selected_indexes = TableView.selectionModel().selectedIndexes()
        if len(selected_indexes) > 1:
            selected_row_index = selected_indexes[-1].row()
        else:
            selected_row_index = selected_indexes[0].row()
        # remove
        TableModel.removeRow(selected_row_index)
        TableView.model().layoutChanged.emit()
        TableView.resizeRowsToContents()
        self.repaint()
Exemple #6
0
def test():
    class XTest( XBase ):
        def __init__( self ):
            XBase.__init__( self )
            self.name = ""
            self.vorname = ""
            self.alter = 0
            self.haarfarbe = ""
            self.schuhgroesse = 0
            self.bemerkung = ""

    x1 = XTest()
    x1.name = "Kendel"
    x1.vorname = "Martin"
    x1.alter = 66
    x1.haarfarbe = "grau"
    x1.schuhgroesse = 44
    x1.bemerkung = "Das ist alles \nein riesengroßer Irrtum"

    x2 = XTest()
    x2.name = "Haaretz"
    x2.vorname = "Yosh"
    x2.alter = 56
    x2.haarfarbe = "schwarz"
    x2.schuhgroesse = 42

    tm = DefaultIccTableModel( (x1, x2 ) )
    tm.setSortable( True )
    tm.setKeyHeaderMappings( { "Nachname": "name", "Vorname": "vorname", "Alter": "alter", "Bemerkung": "bemerkung" } )
    tm.setNumColumnsIndexes( (2,) )

    from PySide2.QtWidgets import QApplication
    app = QApplication()

    tv = QTableView( )
    tv.setModel( tm )
    tv.setAlternatingRowColors( True )
    tv.setSortingEnabled( True )
    tv.resizeColumnsToContents()
    tv.resizeRowsToContents()
    tm.layoutChanged.connect( tv.resizeRowsToContents ) ## <======== WICHTIG bei mehrzeiligem Text in einer Zelle!
    tv.show()

    app.exec_()
class DebugThreadsWidget(QWidget, DockContextHandler):
	def __init__(self, parent, name, data):
		if not type(data) == BinaryView:
			raise Exception('expected widget data to be a BinaryView')

		self.bv = data

		QWidget.__init__(self, parent)
		DockContextHandler.__init__(self, self, name)
		self.actionHandler = UIActionHandler()
		self.actionHandler.setupActionHandler(self)

		self.table = QTableView(self)
		self.model = DebugThreadsListModel(self.table)
		self.table.setModel(self.model)
		self.table.clicked.connect(self.threadRowClicked)

		self.item_delegate = DebugThreadsItemDelegate(self)
		self.table.setItemDelegate(self.item_delegate)

		# self.table.setSortingEnabled(True)
		self.table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
		self.table.setSelectionMode(QAbstractItemView.ExtendedSelection)

		self.table.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
		self.table.verticalHeader().setVisible(False)

		self.table.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
		self.table.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)

		self.table.resizeColumnsToContents()
		self.table.resizeRowsToContents()

		for i in range(len(self.model.columns)):
			self.table.setColumnWidth(i, self.item_delegate.sizeHint(self.table.viewOptions(), self.model.index(-1, i, QModelIndex())).width())
		self.table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)

		layout = QVBoxLayout()
		layout.setContentsMargins(0, 0, 0, 0)
		layout.setSpacing(0)
		layout.addWidget(self.table)
		self.setLayout(layout)

	def notifyOffsetChanged(self, offset):
		pass

	# called from QTableView's clicked signal
	# index: QModelIndex
	def threadRowClicked(self, index):
		index = self.model.createIndex(index.row(), 0)
		tid_str = self.model.data(index, Qt.DisplayRole)
		#print('clicked to change to thread %s' % tid_str)
		stateObj = binjaplug.get_state(self.bv)
		if stateObj.connected and not stateObj.running:
			tid = int(tid_str, 16)
			stateObj.threads.current = tid
			stateObj.ui.context_display()
			stateObj.ui.on_step()
		else:
			print('cannot set thread in current state')

	# called from plugin's context_display() function
	def notifyThreadsChanged(self, new_threads):
		idx_selected = self.model.update_rows(new_threads)
		if idx_selected:
			self.table.setCurrentIndex(idx_selected)

	def contextMenuEvent(self, event):
		self.m_contextMenuManager.show(self.m_menu, self.actionHandler)

	def shouldBeVisible(self, view_frame):
		if view_frame is None:
			return False
		else:
			return True
Exemple #8
0
class TreeCard(QDialog):
    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)

    def viewPerson(self):
        select = self.table.selectionModel()
        pid_list = [
            index.data()
            for index in self.table.selectionModel().selection().indexes()
            if index.column() == 0
        ]
        if len(pid_list) == 1:
            self.pid = int(pid_list[0])
            print(int(pid_list[0]))
            self.accept()
        return 0

    def button_pressed(self):
        #sender = self.sender()
        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)
        #print(self.proxy_model.filterKeyColumn())

        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()
Exemple #9
0
class DebugModulesWidget(QWidget, DockContextHandler):
    def __init__(self, parent, name, data):
        if not type(data) == binaryninja.binaryview.BinaryView:
            raise Exception('expected widget data to be a BinaryView')

        self.bv = data

        QWidget.__init__(self, parent)
        DockContextHandler.__init__(self, self, name)
        self.actionHandler = UIActionHandler()
        self.actionHandler.setupActionHandler(self)

        self.table = QTableView(self)
        self.model = DebugModulesListModel(self.table, data)
        self.table.setModel(self.model)

        self.item_delegate = DebugModulesItemDelegate(self)
        self.table.setItemDelegate(self.item_delegate)

        # self.table.setSortingEnabled(True)
        self.table.setSelectionBehavior(
            QAbstractItemView.SelectionBehavior.SelectRows)
        self.table.setSelectionMode(QAbstractItemView.ExtendedSelection)

        self.table.verticalHeader().setSectionResizeMode(
            QHeaderView.ResizeToContents)
        self.table.verticalHeader().setVisible(False)

        self.table.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
        self.table.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)

        self.table.resizeColumnsToContents()
        self.table.resizeRowsToContents()

        for i in range(len(self.model.columns)):
            self.table.setColumnWidth(
                i,
                self.item_delegate.sizeHint(
                    self.table.viewOptions(),
                    self.model.index(-1, i, QModelIndex())).width())

        update_layout = QHBoxLayout()
        update_layout.setContentsMargins(0, 0, 0, 0)

        update_label = QLabel("Data is Stale")
        update_button = QPushButton("Refresh")
        update_button.clicked.connect(lambda: self.refresh())

        update_layout.addWidget(update_label)
        update_layout.addStretch(1)
        update_layout.addWidget(update_button)

        self.update_box = QWidget()
        self.update_box.setLayout(update_layout)

        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(0)
        self.layout.addWidget(self.table)
        self.setLayout(self.layout)

    def notifyOffsetChanged(self, offset):
        pass

    def refresh(self):
        debug_state = binjaplug.get_state(self.bv)
        debug_state.ui.update_modules()

    def notifyModulesChanged(self, new_modules):
        self.model.update_rows(new_modules)
        self.table.resizeColumnsToContents()
        self.layout.removeWidget(self.update_box)
        self.update_box.setVisible(False)

    def mark_dirty(self):
        self.layout.addWidget(self.update_box)
        self.update_box.setVisible(True)

    def contextMenuEvent(self, event):
        self.m_contextMenuManager.show(self.m_menu, self.actionHandler)

    def shouldBeVisible(self, view_frame):
        if view_frame is None:
            return False
        else:
            return True
Exemple #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()
Exemple #11
0
class DataOpenDialog(QDialog):
    def __init__(
        self,
        expected_columns,
        obligatory_columns,
        all_columns=None,
        parent: typing.Optional[PySide2.QtWidgets.QWidget] = None,
    ):
        super().__init__(parent)
        self.file = None
        self.allcolumns = all_columns if all_columns else expected_columns
        self.columns = expected_columns
        self.obligatorycolumns = obligatory_columns
        self.setWindowTitle('Open Data File')
        self.filename = QLineEdit()
        self.filename.setReadOnly(True)
        self.filename.setMinimumWidth(150)
        self.loadbutton = QPushButton("Load...")
        self.loadbutton.clicked.connect(self.file_dialog)

        layout_left = QVBoxLayout()
        filebox = QGroupBox('File')
        layoutf = QFormLayout()
        layoutf.addRow('File', self.filename)
        layoutf.addRow('', self.loadbutton)
        filebox.setLayout(layoutf)
        layout_left.addWidget(filebox)
        self.columnsbox = ColumnsGroupBox('Columns order',
                                          expected_columns=expected_columns,
                                          all_columns=all_columns)
        self.columnsbox.columns_changes.connect(self.on_columns_order_changed)
        layout_left.addWidget(self.columnsbox)
        layout_left.addStretch()

        layout_right = QVBoxLayout()
        previewbox = QGroupBox('File 10 lines preview')
        previewboxlayout = QVBoxLayout()
        self.preview = QTextEdit()
        self.preview.setReadOnly(True)
        self.preview.setLineWrapMode(QTextEdit.NoWrap)
        self.preview.setMinimumWidth(500)
        self.preview.setMinimumHeight(170)
        previewboxlayout.addWidget(self.preview)
        previewbox.setLayout(previewboxlayout)
        layout_right.addWidget(previewbox)

        self.tablemodel = PandasDataFrameModel(df=pd.DataFrame())
        self.tableview = QTableView()
        self.tableview.setModel(self.tablemodel)
        tablebox = QGroupBox('Data preview')
        tableboxlayout = QVBoxLayout()
        self.tableview.setMinimumWidth(500)
        self.tableview.setMinimumHeight(250)
        self.tableview.setWordWrap(False)
        self.tableview.setShowGrid(False)
        tableboxlayout.addWidget(self.tableview)
        tablebox.setLayout(tableboxlayout)
        layout_right.addWidget(tablebox)

        layout = QHBoxLayout()
        layout.addLayout(layout_left)
        layout.addLayout(layout_right)

        layoutmain = QVBoxLayout()
        layoutmain.addLayout(layout)

        self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        self.buttonbox.accepted.connect(self.accept)
        self.buttonbox.rejected.connect(self.reject)
        layoutmain.addWidget(self.buttonbox)
        self.setLayout(layoutmain)
        self.update_ok()

    @property
    def df(self):
        return self.tablemodel.df

    def file_dialog(self):
        filedialog = QFileDialog(caption='Select Data File')
        filedialog.setFileMode(QFileDialog.ExistingFile)
        if filedialog.exec():
            self.file = filedialog.selectedFiles()[0]
            self.filename.setText(self.file)
            lines = []
            with open(self.file) as fd:
                for _ in range(10):
                    lines.append(fd.readline())
            self.preview.setText(''.join(lines))
            reader = DataFrameReader(self.file)
            self.tablemodel.set_df(reader.df)
            self.tablemodel.set_columns(self.columnsbox.columns)
            self.tableview.resizeRowsToContents()
        self.update_ok()

    @Slot()
    def on_columns_order_changed(self):
        self.tablemodel.set_columns(self.columnsbox.columns)
        self.update_ok()

    def is_ok(self):
        columns = set(self.tablemodel.df.columns)
        for c in self.obligatorycolumns:
            if not isinstance(c, tuple):
                c = (c, )
            c = set(c)
            if c.isdisjoint(columns):
                return False
        return True

    def update_ok(self):
        self.buttonbox.button(QDialogButtonBox.Ok).setEnabled(self.is_ok())
Exemple #12
0
class RemoverDialog(QDialog):
    def __init__(self, parent=None):
        super(RemoverDialog, self).__init__(parent)

        self.setupUi()

    def setupUi(self):
        self.menuBar = QMenuBar()
        self.menuBar.show()

        self.pathInputBox = QLineEdit(self)
        self.pathInputBox.setEnabled(False)
        self.pathInputBox.setToolTip(
            'Input a path or drag a directory here...')

        self.openPathButton = QPushButton('Open...', self)
        self.openPathButton.clicked.connect(self.openPath)

        inputLayout = QHBoxLayout()
        inputLayout.addWidget(QLabel('Path:', self))
        inputLayout.addWidget(self.pathInputBox)
        inputLayout.addWidget(self.openPathButton)

        self.filterFolderCheckBox = QCheckBox('Folders', self)
        self.filterFolderCheckBox.setChecked(True)
        self.filterFolderCheckBox.toggled.connect(self.filter)
        self.filterFileCheckBox = QCheckBox('Files', self)
        self.filterFileCheckBox.setChecked(True)
        self.filterFileCheckBox.toggled.connect(self.filter)
        self.filterSuffixCheckBox = QCheckBox('Suffixes', self)
        self.filterSuffixCheckBox.setChecked(True)
        self.filterSuffixCheckBox.toggled.connect(self.filter)

        filterLayout = QHBoxLayout()
        filterLayout.addWidget(self.filterFolderCheckBox)
        filterLayout.addWidget(self.filterFileCheckBox)
        filterLayout.addWidget(self.filterSuffixCheckBox)
        filterLayout.addStretch()

        self.trashButton = QPushButton('Trash', self)
        self.trashButton.clicked.connect(self.trash)
        self.deleteButton = QPushButton('Delete', self)
        self.deleteButton.clicked.connect(self.delete)

        confirmLayout = QHBoxLayout()
        confirmLayout.addStretch()
        confirmLayout.addWidget(self.trashButton)
        confirmLayout.addWidget(self.deleteButton)

        layout = QVBoxLayout()
        layout.addLayout(inputLayout)
        layout.addLayout(filterLayout)
        layout.addWidget(self.createResultView())
        layout.addLayout(confirmLayout)

        self.setAcceptDrops(True)
        self.setLayout(layout)
        self.setMinimumWidth(600)
        self.setWindowTitle('Remover')
        self.setWindowIcon(QApplication.style().standardIcon(
            QStyle.SP_DirIcon))

    def createResultView(self):
        self.resultModel = ResultModel(self)
        self.resultView = QTableView(self)
        self.resultView.setSortingEnabled(True)
        self.resultView.setShowGrid(False)
        self.resultView.setAlternatingRowColors(True)
        self.resultView.verticalHeader().hide()
        self.resultView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.resultView.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.sortFilterModel = SortFilterResultModel(self.resultModel, self)
        self.resultView.setModel(self.sortFilterModel)
        return self.resultView

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls() and len(event.mimeData().urls()) == 1:
            event.acceptProposedAction()

    def dropEvent(self, event):
        if event.mimeData().hasUrls() and len(event.mimeData().urls()) == 1:
            self.pathInputBox.setText(event.mimeData().urls()[0].toLocalFile())
            self.reloadPath(self.pathInputBox.text())

    def openPath(self):
        path = QFileDialog.getExistingDirectory(
            parent=self,
            caption='Open',
            options=QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks)
        if path:
            self.pathInputBox.setText(path)
            self.reloadPath(path)

    def filter(self):
        filters = []
        if self.filterFolderCheckBox.isChecked():
            filters.append('folder')
        if self.filterFileCheckBox.isChecked():
            filters.append('file')
        if self.filterSuffixCheckBox.isChecked():
            filters.append('suffix')
        self.sortFilterModel.setFilterRegularExpression('|'.join(filters))
        self.sortFilterModel.filterRegularExpression()
        self.resultView.resizeRowsToContents()

    def trash(self):
        folders, files = self.collectSelectedFolderFiles()

        try:
            for file in files:
                send2trash(file)
            for folder in folders:
                if QFile(folder).exists():
                    send2trash(folder)
        except:
            QMessageBox.warning(self, 'Failed',
                                'Failed to trash selected files/folders')
            return

        self.reloadPath(self.pathInputBox.text())

    def delete(self):
        folders, files = self.collectSelectedFolderFiles()

        try:
            for file in files:
                os.remove(file)
            for folder in folders:
                shutil.rmtree(folder)
        except:
            QMessageBox.warning(self, 'Failed',
                                'Failed to delete selected files/folders')
            return

        self.reloadPath(self.pathInputBox.text())

    def collectSelectedFolderFiles(self):
        folders, files, suffixes = [], [], []
        for index in self.resultView.selectedIndexes():
            if index.column() != 0:
                # 忽略第二列的selection
                continue
            item = self.sortFilterModel.data(index, Qt.UserRole)
            if 'folder' == item.type:
                folders.append(item.name)
            elif 'file' == item.type:
                files.append(item.name)
            elif 'suffix' == item.type:
                suffixes.append(item.name[2:])

        # 将后缀符合选中条件的文件添加到files中
        path = self.pathInputBox.text()
        iterator = QDirIterator(path,
                                filter=QDir.Files | QDir.Dirs | QDir.Hidden
                                | QDir.NoDotAndDotDot,
                                flags=QDirIterator.Subdirectories)
        folderPaths, filePaths = set(), set()
        while iterator.hasNext():
            file = iterator.next()
            if '.' == file[-1] or '..' == file[-2]:
                continue
            fileInfo = QFileInfo(file)
            if fileInfo.isDir():
                if fileInfo.fileName() in folders:
                    folderPaths.add(fileInfo.absoluteFilePath())
            if fileInfo.isFile():
                if fileInfo.fileName() in files:
                    filePaths.add(fileInfo.absoluteFilePath())
                if fileInfo.suffix() in suffixes:
                    filePaths.add(fileInfo.absoluteFilePath())
        return sorted(folderPaths), filePaths

    def reloadPath(self, path):
        self.resultModel.reload(path)
        self.resultView.horizontalHeader().setSectionResizeMode(
            0, QHeaderView.Stretch)
        self.resultView.horizontalHeader().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self.filter()
        self.resultView.sortByColumn(1, Qt.DescendingOrder)