示例
功能
功能是参照本地资源管理器
- 按键盘字母,自动选中文件名开头对应的字母
- 列表视图和图标视图按住ctrl滚轮切换
- 排序
- 重命名
- shift多选
- ctrl单选反选
列表视图
使用了QTableView,QAbstractTableModel,QStyledItemDelegate
图标视图
使用了QListView,QAbstractListModel,QStyledItemDelegate
功能具体实现
按键盘字母选中
列表视图和图标视图做法一样,复写keyPressEvent方法
// 键盘接收到的字母
const QString key = event->text();
// 前置过滤,如果没有前置过滤,下面的while循环则会无限循环
// 作用是判断出当前界面中有对应字母开头的名字
const auto it = std::find_if(items_.begin(), items_.end(), [key](const PathInfo& item) {
return item.name.left(1).toLower() == key;
});
if (it == items_.end()) {
return;
}
// 清空所有选中
restore();
// 从最后一个选中开始检索
int index = delegate_->getLastSelectedIndex() + 1;
int nextIndex = -1;
while (true) {
bool keep = false;
// 如果找到了,则跳出循环
// 如果没找到,则从头开始找,直到找到为止
for (int i = index; i < items_.size(); i++) {
if (items_[i].name.left(1).toLower() == key) {
keep = true;
nextIndex = i;
break;
}
}
if (keep) {
break;
}
index = 0;
}
// 选中找到的目标
selectRow(nextIndex);
// 跳转到对应目标
scrollTo(model_->index(nextIndex, 0));
按住ctrl滚轮切换视图
两个视图分别复现eventFilter方法
// 列表视图
if (watched == verticalScrollBar() && event->type() == QEvent::Wheel) {
const auto wheelEvent = dynamic_cast<QWheelEvent*>(event);
// 按住ctrl,并且滚轮滑动距离大于0,切换图标视图
if (wheelEvent && wheelEvent->modifiers() == Qt::ControlModifier) {
if (wheelEvent->delta() > 0) {
emit switchIconMode();
}
return true;
}
}
// 图标视图
const auto wheelEvent = dynamic_cast<QWheelEvent*>(event);
if (wheelEvent && wheelEvent->modifiers() == Qt::ControlModifier) {
if (wheelEvent->delta() < 0) {
// 如果图标尺寸到达显示的最小值(这里是100),则切换成列表模式
if (delegate_->getIconWidth() == 100) {
emit switchListMode();
return QListView::eventFilter(watched, event);
}
// 动态设置图标尺寸,这样delegate在绘制的时候,根据动态尺寸来进行绘制
delegate_->setIconWidth(delegate_->getIconWidth() - 5);
}
else {
// 如果图标尺寸到达显示的最大值(这里是234),则再滚动就没变化
if (delegate_->getIconWidth() >= 234) {
return QListView::eventFilter(watched, event);
}
delegate_->setIconWidth(delegate_->getIconWidth() + 5);
}
// 获取当前所有选中的图标名称
// 需要在重新绘制后重新选中,不然在绘制后会全部取消
const auto items = getSelectedItems();
QList<QString> names;
for(const auto & item : items) {
names << item.name;
}
// 重新绘制
model_->load();
selectItems(names);
}
// switchIconMode和switchListMode实现,则是将两个控件hide和show的操作
排序
列表模式表头排序使用了QTableView的特性
// 表头设置允许排序
horizontalHeader()->setSortIndicatorShown(true);
// 监听表头排序
connect(horizontalHeader(), &QHeaderView::sortIndicatorChanged, this, &xxxxx::xxxxx);