bsnes/hiro/qt/widget/list-view.cpp

396 lines
12 KiB
C++

namespace phoenix {
void pListView::appendColumn() {
orphan();
}
void pListView::appendItem() {
lock();
auto item = new QTreeWidgetItem(qtListView);
for(unsigned column = 0; column < listView.columns(); column++) {
auto& state = listView.state.columns[column];
if(state.backgroundColor) {
item->setBackground(column, QColor(
state.backgroundColor->red, state.backgroundColor->green, state.backgroundColor->blue
));
}
if(state.font) {
item->setFont(column, pFont::create(*state.font));
}
if(state.foregroundColor) {
item->setForeground(column, QColor(
state.foregroundColor->red, state.foregroundColor->green, state.foregroundColor->blue
));
}
item->setTextAlignment(column, calculateAlignment(
state.horizontalAlignment, state.verticalAlignment
));
}
if(listView.state.checkable) item->setCheckState(0, Qt::Unchecked);
unlock();
}
void pListView::removeColumn(unsigned position) {
orphan();
}
void pListView::removeItem(unsigned position) {
lock();
if(auto item = qtListView->topLevelItem(position)) {
delete item;
}
unlock();
}
void pListView::reset() {
lock();
qtListView->clear();
unlock();
}
void pListView::resizeColumns() {
}
//todo: this doesn't work ...
void pListView::setActiveColumn(unsigned column) {
if(column >= listView.columns()) return;
qtListView->header()->setSortIndicator(column, Qt::DescendingOrder);
}
void pListView::setBackgroundColor(Color color) {
QPalette palette = qtListView->palette();
palette.setColor(QPalette::Base, QColor(color.red, color.green, color.blue));
palette.setColor(QPalette::AlternateBase, QColor(max(0, (signed)color.red - 17), max(0, (signed)color.green - 17), max(0, (signed)color.blue - 17)));
qtListView->setPalette(palette);
qtListView->setAutoFillBackground(true);
}
void pListView::setCheckable(bool checkable) {
lock();
if(checkable) {
for(unsigned n = 0; n < qtListView->topLevelItemCount(); n++) {
if(auto item = qtListView->topLevelItem(n)) {
item->setCheckState(0, Qt::Unchecked);
}
}
}
unlock();
}
void pListView::setChecked(unsigned position, bool checked) {
lock();
if(auto item = qtListView->topLevelItem(position)) {
item->setCheckState(0, checked ? Qt::Checked : Qt::Unchecked);
}
unlock();
}
void pListView::setChecked(const vector<unsigned>& selections) {
lock();
setCheckedNone();
for(auto& position : selections) setChecked(position, true);
unlock();
}
void pListView::setCheckedAll() {
lock();
for(unsigned n = 0; n < qtListView->topLevelItemCount(); n++) {
if(auto item = qtListView->topLevelItem(n)) {
item->setCheckState(0, Qt::Checked);
}
}
unlock();
}
void pListView::setCheckedNone() {
lock();
for(unsigned n = 0; n < qtListView->topLevelItemCount(); n++) {
if(auto item = qtListView->topLevelItem(n)) {
item->setCheckState(0, Qt::Unchecked);
}
}
unlock();
}
void pListView::setColumnBackgroundColor(unsigned column, maybe<Color> color) {
for(unsigned row = 0; row < listView.items(); row++) {
if(auto item = qtListView->topLevelItem(row)) {
item->setBackground(column, color ? QColor(color->red, color->green, color->blue) : QBrush());
}
}
}
void pListView::setColumnEditable(unsigned column, bool editable) {
}
void pListView::setColumnFont(unsigned column, maybe<string> font) {
auto qtFont = pFont::create(font ? *font : widget.state.font);
for(unsigned row = 0; row < listView.items(); row++) {
if(auto item = qtListView->topLevelItem(row)) {
item->setFont(column, qtFont);
}
}
}
void pListView::setColumnForegroundColor(unsigned column, maybe<Color> color) {
for(unsigned row = 0; row < listView.items(); row++) {
if(auto item = qtListView->topLevelItem(row)) {
item->setForeground(column, color ? QColor(color->red, color->green, color->blue) : QBrush());
}
}
}
void pListView::setColumnHorizontalAlignment(unsigned column, double alignment) {
qtListView->headerItem()->setTextAlignment(column, calculateAlignment(alignment, 0.5));
for(unsigned row = 0; row < listView.items(); row++) {
if(auto item = qtListView->topLevelItem(row)) {
auto& state = listView.state.columns[column];
item->setTextAlignment(column, calculateAlignment(state.horizontalAlignment, state.verticalAlignment));
}
}
}
void pListView::setColumnResizable(unsigned column, bool resizable) {
qtListView->header()->setResizeMode(column, resizable ? QHeaderView::Interactive : QHeaderView::Fixed);
}
void pListView::setColumnSortable(unsigned column, bool sortable) {
bool clickable = false;
for(auto& column : listView.state.columns) clickable |= column.sortable;
qtListView->header()->setClickable(clickable);
}
void pListView::setColumnText(unsigned column, const string& text) {
qtListView->headerItem()->setText(column, QString::fromUtf8(text));
}
void pListView::setColumnVerticalAlignment(unsigned column, double alignment) {
for(unsigned row = 0; row < listView.items(); row++) {
if(auto item = qtListView->topLevelItem(row)) {
auto& state = listView.state.columns[column];
item->setTextAlignment(column, calculateAlignment(state.horizontalAlignment, state.verticalAlignment));
}
}
}
void pListView::setColumnVisible(unsigned column, bool visible) {
if(column >= listView.columns()) return;
qtListView->setColumnHidden(column, !visible);
}
void pListView::setColumnWidth(unsigned column, signed width) {
if(column >= listView.columns()) return;
resizeColumns();
}
void pListView::setForegroundColor(Color color) {
QPalette palette = qtListView->palette();
palette.setColor(QPalette::Text, QColor(color.red, color.green, color.blue));
qtListView->setPalette(palette);
}
void pListView::setGridVisible(bool visible) {
qtListView->repaint();
}
void pListView::setHeaderVisible(bool visible) {
qtListView->setHeaderHidden(!visible);
resizeColumns();
}
void pListView::setImage(unsigned row, unsigned column, const nall::image& image) {
if(auto item = qtListView->topLevelItem(row)) {
item->setIcon(column, CreateIcon(image));
}
}
void pListView::setSelected(unsigned position, bool selected) {
lock();
if(auto item = qtListView->topLevelItem(position)) {
item->setSelected(selected);
}
unlock();
}
void pListView::setSelected(const vector<unsigned>& selections) {
lock();
setSelectedNone();
if(selections.size()) {
if(auto item = qtListView->topLevelItem(selections[0])) {
qtListView->setCurrentItem(item);
}
for(auto& position : selections) setSelected(position, true);
}
unlock();
}
void pListView::setSelectedAll() {
lock();
qtListView->selectAll();
unlock();
}
void pListView::setSelectedNone() {
lock();
qtListView->clearSelection();
unlock();
}
void pListView::setSingleSelection(bool singleSelection) {
lock();
qtListView->setSelectionMode(singleSelection ? QAbstractItemView::SingleSelection : QAbstractItemView::ExtendedSelection);
unlock();
}
void pListView::setText(unsigned row, unsigned column, string text) {
lock();
if(auto item = qtListView->topLevelItem(row)) {
item->setText(column, QString::fromUtf8(text));
}
unlock();
}
void pListView::constructor() {
qtWidget = qtListView = new QtTreeWidget(*this);
qtListView->setAllColumnsShowFocus(true);
qtListView->setAlternatingRowColors(listView.columns() >= 2);
qtListView->setColumnCount(max(1u, listView.columns()));
qtListView->setContextMenuPolicy(Qt::CustomContextMenu);
qtListView->setRootIsDecorated(false);
qtListView->header()->setMovable(false);
qtListViewDelegate = new QtTreeWidgetDelegate(*this);
qtListView->setItemDelegate(qtListViewDelegate);
connect(qtListView, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(onActivate()));
connect(qtListView, SIGNAL(itemSelectionChanged()), SLOT(onChange()));
connect(qtListView, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(onContext()));
connect(qtListView->header(), SIGNAL(sectionClicked(int)), SLOT(onSort(int)));
connect(qtListView, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(onToggle(QTreeWidgetItem*)));
pWidget::synchronizeState();
for(unsigned column = 0; column < listView.columns(); column++) {
auto& state = listView.state.columns[column];
setColumnBackgroundColor(column, state.backgroundColor);
setColumnEditable(column, state.editable);
setColumnFont(column, state.font);
setColumnForegroundColor(column, state.foregroundColor);
//setColumnHorizontalAlignment(column, state.horizontalAlignment);
setColumnResizable(column, state.resizable);
setColumnSortable(column, state.sortable);
setColumnText(column, state.text);
//setColumnVerticalAlignment(column, state.verticalAlignment);
setColumnVisible(column, state.visible);
//setColumnWidth(column, state.width);
qtListView->headerItem()->setTextAlignment(column, calculateAlignment(state.horizontalAlignment, 0.5));
}
setActiveColumn(listView.state.activeColumn);
setCheckable(listView.state.checkable);
//setGridVisible(listView.state.gridVisible);
setHeaderVisible(listView.state.headerVisible);
setSingleSelection(listView.state.singleSelection);
for(unsigned row = 0; row < listView.items(); row++) {
appendItem();
setSelected(row, listView.state.items[row].selected);
if(listView.state.checkable) {
setChecked(row, listView.state.items[row].checked);
}
for(unsigned column = 0; column < listView.columns(); column++) {
setImage(row, column, listView.state.items[row].image(column, {}));
setText(row, column, listView.state.items[row].text(column, ""));
}
}
resizeColumns();
}
void pListView::destructor() {
delete qtListViewDelegate;
delete qtListView;
qtWidget = qtListView = nullptr;
qtListViewDelegate = nullptr;
}
void pListView::orphan() {
destructor();
constructor();
}
void pListView::onActivate() {
if(!locked() && listView.onActivate) listView.onActivate();
}
void pListView::onChange() {
for(auto& item : listView.state.items) item.selected = false;
for(unsigned position = 0; position < qtListView->topLevelItemCount(); position++) {
if(auto item = qtListView->topLevelItem(position)) {
if(item->isSelected()) listView.state.items[position].selected = true;
}
}
if(!locked() && listView.onChange) listView.onChange();
}
void pListView::onContext() {
if(!locked() && listView.onContext) listView.onContext();
}
void pListView::onSort(int column) {
if(column >= listView.columns()) return;
if(listView.state.columns[column].sortable) {
if(!locked() && listView.onSort) listView.onSort(column);
}
}
void pListView::onToggle(QTreeWidgetItem* item) {
maybe<unsigned> row;
for(unsigned position = 0; position < qtListView->topLevelItemCount(); position++) {
if(auto topLevelItem = qtListView->topLevelItem(position)) {
if(topLevelItem == item) {
row = position;
break;
}
}
}
if(row) {
listView.state.items[*row].checked = (item->checkState(0) == Qt::Checked);
if(!locked() && listView.onToggle) listView.onToggle(*row);
}
}
int pListView::calculateAlignment(double horizontal, double vertical) {
int alignment = 0;
if(horizontal < 0.333) alignment |= Qt::AlignLeft;
else if(horizontal > 0.666) alignment |= Qt::AlignRight;
else alignment |= Qt::AlignCenter;
if(vertical < 0.333) alignment |= Qt::AlignTop;
else if(vertical > 0.666) alignment |= Qt::AlignBottom;
else alignment |= Qt::AlignVCenter;
return alignment;
}
void pListView::QtTreeWidget::mousePressEvent(QMouseEvent* event) {
QTreeWidget::mousePressEvent(event);
if(event->button() == Qt::RightButton) {
self.onContext();
}
}
pListView::QtTreeWidget::QtTreeWidget(pListView& self) : self(self) {
}
void pListView::QtTreeWidgetDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const {
QStyledItemDelegate::paint(painter, option, index);
if(self.listView.state.gridVisible) {
QPen pen;
pen.setColor(QColor(192, 192, 192));
pen.setWidth(1);
painter->setPen(pen);
painter->drawRect(option.rect);
}
}
pListView::QtTreeWidgetDelegate::QtTreeWidgetDelegate(pListView& self) : QStyledItemDelegate(self.qtListView), self(self) {
}
}