#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: Bertrand256 # Created on: 2017-09 from PyQt5 import QtWidgets, QtCore from PyQt5.QtCore import QSize, pyqtSlot from PyQt5.QtGui import QPixmap from PyQt5.QtWidgets import QDialog, QLayout, QStyle from typing import List from ui import ui_columns_cfg_dlg from wnd_utils import WndUtils class ColumnsConfigDlg(QDialog, ui_columns_cfg_dlg.Ui_ColumnsConfigDlg, WndUtils): def __init__(self, parent, columns: List): QDialog.__init__(self, parent) ui_columns_cfg_dlg.Ui_ColumnsConfigDlg.__init__(self) WndUtils.__init__(self, None) self.columns: List = columns self.initialized = False self.setupUi() def setupUi(self): ui_columns_cfg_dlg.Ui_ColumnsConfigDlg.setupUi(self, self) self.setWindowTitle("Columns") self.setIcon(self.btnMoveBegin, "first-page@16px.png", rotate=90) self.setIcon(self.btnMoveEnd, "first-page@16px.png", rotate=-90) self.setIcon(self.btnMoveUp, "arrow-downward@16px.png", rotate=-180) self.setIcon(self.btnMoveDown, "arrow-downward@16px.png") self.tableWidget.verticalHeader().setSectionsMovable(True) self.tableWidget.verticalHeader().setDefaultSectionSize( self.tableWidget.verticalHeader().fontMetrics().height() + 8) self.tableWidget.verticalHeader().sectionMoved.connect(self.on_tableRowMoved) self.tableWidget.setRowCount(len(self.columns)) for col_idx, col in enumerate(self.columns): item = QtWidgets.QTableWidgetItem() item.setText(' ') self.tableWidget.setVerticalHeaderItem(col_idx, item) visible = col[1] item = QtWidgets.QTableWidgetItem() item.setText(col[0]) self.tableWidget.setItem(col_idx, 0, item) item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled) item.setCheckState(QtCore.Qt.Checked if visible else QtCore.Qt.Unchecked) self.update_buttons_state() self.initialized = True def on_tableRowMoved(self, logicalIndex, oldVisualIndex, newVisualIndex): self.columns.insert(newVisualIndex, self.columns.pop(oldVisualIndex)) @pyqtSlot(QtWidgets.QTableWidgetItem) def on_tableWidget_itemChanged(self, item): if not self.initialized: return row = self.tableWidget.row(item) if row >= 0: row = self.tableWidget.visualRow(row) self.columns[row][1] = item.checkState() == QtCore.Qt.Checked @pyqtSlot() def on_tableWidget_itemSelectionChanged(self): self.update_buttons_state() def update_buttons_state(self): up_enabled = False down_enabled = False items = sorted(self.tableWidget.selectedItems(), key=lambda x: self.tableWidget.visualRow(x.row())) last_row = -1 first_selected_row = -1 last_selected_row = len(items) was_gap = False for item in items: row = self.tableWidget.visualRow(item.row()) if last_row >= 0 and last_row < row - 1: was_gap = True if first_selected_row < 0: first_selected_row = row last_selected_row = row last_row = row if first_selected_row > 0 or was_gap: up_enabled = True if last_selected_row < len(self.columns) - 1 or was_gap: down_enabled = True self.btnMoveBegin.setEnabled(up_enabled) self.btnMoveEnd.setEnabled(down_enabled) self.btnMoveUp.setEnabled(up_enabled) self.btnMoveDown.setEnabled(down_enabled) @pyqtSlot() def on_btnMoveUp_clicked(self): # sort selected item to move lower-indexed items first items = sorted(self.tableWidget.selectedItems(), key=lambda x: self.tableWidget.visualRow(x.row())) last_row_index = -1 moved = False for item in items: row = self.tableWidget.visualRow(item.row()) if row > 0: if last_row_index + 1 < row: self.tableWidget.verticalHeader().moveSection(row, row-1) last_row_index = row - 1 moved = True else: last_row_index = row else: last_row_index = row if moved: self.update_buttons_state() self.tableWidget.scrollToItem(items[0]) @pyqtSlot() def on_btnMoveBegin_clicked(self): items = sorted(self.tableWidget.selectedItems(), key=lambda x: self.tableWidget.visualRow(x.row())) moved = False for new_row_idx, item in enumerate(items): cur_row_idx = self.tableWidget.visualRow(item.row()) if cur_row_idx != new_row_idx: self.tableWidget.verticalHeader().moveSection(cur_row_idx, new_row_idx) moved = True if moved: self.update_buttons_state() self.tableWidget.scrollToItem(items[0]) @pyqtSlot() def on_btnMoveDown_clicked(self): # sort selected item to move higher-indexed items first items = sorted(self.tableWidget.selectedItems(), key=lambda x: self.tableWidget.visualRow(x.row()), reverse=True) last_row_index = None moved = False for item in items: row = self.tableWidget.visualRow(item.row()) if row < len(self.columns) - 1: if last_row_index is None or row + 1 < last_row_index: self.tableWidget.verticalHeader().moveSection(row, row+1) last_row_index = row + 1 moved = True else: last_row_index = row else: last_row_index = row if moved: self.update_buttons_state() self.tableWidget.scrollToItem(items[0]) @pyqtSlot() def on_btnMoveEnd_clicked(self): items = sorted(self.tableWidget.selectedItems(), key=lambda x: self.tableWidget.visualRow(x.row()), reverse=True) moved = False for idx, item in enumerate(items): cur_row_idx = self.tableWidget.visualRow(item.row()) new_row_idx = len(self.columns) - idx - 1 if cur_row_idx != new_row_idx: self.tableWidget.verticalHeader().moveSection(cur_row_idx, new_row_idx) moved = True if moved: self.update_buttons_state() self.tableWidget.scrollToItem(items[0])