作者:小 琛
欢迎转载,请标明出处
需求场景
思路描述
- 利用Qt提供的类:QListWidget、QListWidgetItem,其中QListWidget为列表类,QListWidgetItem可以理解为每一项的数据类
- 原生的QListWidget一定不能满足我们的需求,因此我们构建一个类继承自QListWidget,在子类中重新定义ui风格
- 在2中,我们做到了自定义列表,但列表内的具体每一项内容仍然是原生的,因此我们可以自定义一个QWidget,这个widget可以根据我们具体的场景绘制,在插入的时候,使用我们的自定义QWidget作为每一项内容
- QListWidgetItem是列表插入必不可少的,并且我们制作列表时,一定会用到一些数据,也可以用它来存储
Qt模块
QListWidget
下面是一些QListWidget的常见用法:
- 添加列表项
可以使用addItem()方法添加一个列表项,可以设置列表项的文本和图标:
QListWidget *listWidget = new QListWidget(this);
// 添加纯文本列表项
listWidget->addItem("Item 1");
// 添加带图标的列表项
QListWidgetItem *item2 = new QListWidgetItem(QIcon(":/images/icon.png"), "Item 2");
listWidget->addItem(item2);
// 添加自定义控件
QLabel *label = new QLabel("Item 3");
QListWidgetItem *item3 = new QListWidgetItem();
listWidget->addItem(item3);
listWidget->setItemWidget(item3, label);
- 获取当前选中的列表项
可以使用currentItem()方法获取当前选中的列表项:
QListWidgetItem *item = listWidget->currentItem();
if (item) {
qDebug() << "Selected item: " << item->text();
}
- 设置列表项的状态
可以使用setCheckState()方法设置列表项的状态,使得列表项可以被选中或未选中:
QListWidgetItem *item = new QListWidgetItem("Item 1");
item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // 开启用户可选中的标志
item->setCheckState(Qt::Unchecked); // 初始为未选中状态
listWidget->addItem(item);
- 删除列表项
可以使用takeItem()方法删除一个列表项:
QListWidgetItem *item = listWidget->currentItem();
if (item) {
listWidget->takeItem(listWidget->row(item)); // 删除当前选中的列表项
}
QListWidgetItem
下面是一些常见的QListWidgetItem的用法:
- 设置列表项的文本和图标
可以使用setText()方法和setIcon()方法设置列表项的文本和图标:
QListWidgetItem *item = new QListWidgetItem();
item->setText("Item 1");
item->setIcon(QIcon(":/images/icon.png"));
listWidget->addItem(item);
- 获取列表项的文本和图标
可以使用text()方法和icon()方法获取列表项的文本和图标:
QListWidgetItem *item = listWidget->currentItem();
if (item) {
QString text = item->text();
QIcon icon = item->icon();
}
- 设置列表项的状态
可以使用setCheckState()方法设置列表项的状态,使得列表项可以被选中或未选中:
QListWidgetItem *item = new QListWidgetItem();
item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // 开启用户可选中的标志
item->setCheckState(Qt::Unchecked); // 初始为未选中状态
listWidget->addItem(item);
- 获取列表项的状态
可以使用checkState()方法获取列表项的状态,返回值为Qt::CheckState枚举类型,表示列表项的选中状态:
QListWidgetItem *item = listWidget->currentItem();
if (item) {
Qt::CheckState state = item->checkState();
}
- 自定义列表项
可以使用QListWidgetItem的方法setItemWidget()方法设置自定义控件作为列表项:
QLabel *label = new QLabel("Custom Item");
QListWidgetItem *item = new QListWidgetItem();
listWidget->addItem(item);
listWidget->setItemWidget(item, label);
自定义QWidget配合QListWidget
例子:实现一个json文件管理窗口
注意的点:
- 下面的例子,并不能直接运行,因为包含了很多我自定义的控件,仅限于了解整个结构
- 整个设计:JsonItemWidget是我的自定义widget,里面包含了我定义每一项的具体内容,其中的控件被触发时绑定信号,JsonItemWidget再绑定widget中的信号,实现事件的抛;JsonListWidget是列表项,修改了很多属性来实现我想要的ui效果;JsonListWidgetItem是自定义的Item,其中预留了operate >,该接口可以完成自定义排序功能;插入的时候,调用setItemWidget接口完成
JsonListWidget.h
#pragma once
#include <QListWidget>
#include "JsonItemDataDef.h"
class JsonListItem;
class QListWidgetItem;
class JsonListWidget : public QListWidget {
Q_OBJECT
public:
explicit JsonListWidget(QWidget* parent);
~JsonListWidget();
void addJson(const JsonItemData& JsonData);
void addJsonWithFlicker(const JsonItemData& JsonData);
void updateJsonName(const QString& oldName, const QString& newName);
void updateJsonInfo(const QString& name, const JsonItemData& data);
void deleteJsonWithName(const QString& name);
bool haveJsonByName(const QString& name);
private:
QListWidgetItem* findWidgetItemByName(const QString& name);
signals:
void sigOpenJsonFileFolder();
void sigJsonRun(const QString& name);
void sigItemNameChanged(const QString& oldName, const QString& newName);
void sigItemDelete(const QString& name);
void sigItemSetting(const QString& name);
protected:
virtual bool eventFilter(QObject* object, QEvent* event) override;
};
JsonListWidget.cpp
#include "JsonListWidget.h"
#include "JsonListItem.h"
#include "NemuColor.h"
#include "AppUtil.h"
#include <QPainter>
#include <QDateTime>
#include <QEvent>
#include <QTimer>
enum ItemRole {
kRoleIndex = Qt::UserRole + 1,
kRoleName,
kRoleDate,
kRoleTime,
kRoleScreen,
};
JsonListWidget::JsonListWidget(QWidget *parent) : QListWidget(parent) {
setFrameShape(QFrame::NoFrame);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
viewport()->setContentsMargins(0, 0, 0, 0);
setStyleSheet(
QString("QListWidget{background-color:%1;border: 1px solid %2; border-bottom-left-radius: %3px; "
"border-bottom-right-radius: %4px; outline:0px;}"
"QListWidget::item:hover{background-color:%5;}"
"QListWidget::item:selected{border:none;}"
"QScrollBar:vertical{width:4px; background:transparent; padding:0px; border:0px;}"
"QScrollBar::handle:vertical:hover,QScrollBar::handle:vertical:pressed{background:%7;}"
"QScrollBar::add-page:vertical,QScrollBar::sub-page:vertical{background:transparent;border:0px;}"
"QScrollBar::add-line:vertical,QScrollBar::sub-line:vertical{background:transparent;border:0px;}")
.arg(NemuUiLib::NemuColor::getGrey8().name(QColor::HexArgb))
.arg(AppUtil::isWin11() ? "#44464b" : "#192027")
.arg(AppUtil::isWin11() ? 8 : 0)
.arg(AppUtil::isWin11() ? 8 : 0)
.arg(NemuUiLib::NemuColor::getFill1().name(QColor::HexArgb))
.arg(NemuUiLib::NemuColor::getFill2().name(QColor::HexArgb))
.arg(NemuUiLib::NemuColor::getGrey3().name(QColor::HexArgb)));
if (auto widget = findChild<QWidget *>("qt_scrollarea_vcontainer")) {
widget->installEventFilter(this);
}
setViewMode(ListMode);
}
JsonListWidget::~JsonListWidget() {}
void JsonListWidget::addJson(const JsonItemData &JsonData) {
if (haveJsonByName(JsonData.name_)) {
return;
}
JsonListItem *item = new JsonListItem(this);
connect(item, &JsonListItem::sigItemOpenJsonFileFolder, this, &JsonListWidget::sigOpenJsonFileFolder);
connect(item, &JsonListItem::sigItemJsonRun, this, &JsonListWidget::sigJsonRun);
connect(item, &JsonListItem::sigNameChanged, this, &JsonListWidget::sigItemNameChanged);
connect(item, &JsonListItem::sigDeleteButtonClicked, this, &JsonListWidget::sigItemDelete);
connect(item, &JsonListItem::sigSettingButtonClicked, this, &JsonListWidget::sigItemSetting);
item->setJsonName(JsonData.name_);
item->setJsonTime(JsonData.time_);
item->setJsonDate(JsonData.date_);
item->setJsonScreen(JsonData.screen_);
auto listItem = new QListWidgetItem(this);
listItem->setData(kRoleIndex, JsonData.index_);
listItem->setData(kRoleName, JsonData.name_);
listItem->setData(kRoleScreen, JsonData.screen_);
listItem->setData(kRoleTime, JsonData.time_);
listItem->setData(kRoleDate, JsonData.date_);
listItem->setSizeHint(item->size());
insertItem(0, listItem);
setItemWidget(listItem, item);
}
void JsonListWidget::addJsonWithFlicker(const JsonItemData &JsonData) {
if (haveJsonByName(JsonData.name_)) {
return;
}
JsonListItem *item = new JsonListItem(this);
connect(item, &JsonListItem::sigItemOpenJsonFileFolder, this, &JsonListWidget::sigOpenJsonFileFolder);
connect(item, &JsonListItem::sigItemJsonRun, this, &JsonListWidget::sigJsonRun);
connect(item, &JsonListItem::sigNameChanged, this, &JsonListWidget::sigItemNameChanged);
connect(item, &JsonListItem::sigDeleteButtonClicked, this, &JsonListWidget::sigItemDelete);
connect(item, &JsonListItem::sigSettingButtonClicked, this, &JsonListWidget::sigItemSetting);
item->setJsonName(JsonData.name_);
item->setJsonTime(JsonData.time_);
item->setJsonDate(JsonData.date_);
item->setJsonScreen(JsonData.screen_);
auto listItem = new QListWidgetItem();
listItem->setData(kRoleIndex, JsonData.index_);
listItem->setData(kRoleName, JsonData.name_);
listItem->setData(kRoleScreen, JsonData.screen_);
listItem->setData(kRoleTime, JsonData.time_);
listItem->setData(kRoleDate, JsonData.date_);
listItem->setSizeHint(item->size());
insertItem(0, listItem);
setItemWidget(listItem, item);
update();
listItem->setBackgroundColor(NemuUiLib::NemuColor::getFill1());
QTimer::singleShot(1000, [listItem]() { listItem->setBackgroundColor(NemuUiLib::NemuColor::getGrey8()); });
}
bool JsonListWidget::haveJsonByName(const QString& name) {
bool ret = false;
for (int row = 0; row < count(); ++row) {
auto widgetItem = item(row);
if (!widgetItem) {
continue;
}
if (name != widgetItem->data(kRoleName).toString()) {
continue;
}
ret = true;
break;
}
return ret;
}
void JsonListWidget::deleteJsonWithName(const QString& name) {
int listCount = count();
for (int row = 0; row < listCount; ++row) {
auto widgetItem = item(row);
if (!widgetItem) {
continue;
}
if (name != widgetItem->data(kRoleName).toString()) {
continue;
}
takeItem(row);
break;
}
}
void JsonListWidget::updateJsonName(const QString &oldName, const QString &newName) {
if (auto widgeItem = findWidgetItemByName(oldName)) {
widgeItem->setData(kRoleName, newName);
if (auto widget = qobject_cast<JsonListItem *>(itemWidget(widgeItem))) {
widget->setJsonName(newName);
}
}
}
void JsonListWidget::updateJsonInfo(const QString &name, const JsonItemData &data) {
if (auto widgeItem = findWidgetItemByName(name)) {
widgeItem->setData(kRoleIndex, data.index_);
widgeItem->setData(kRoleName, name);
widgeItem->setData(kRoleDate, data.date_);
widgeItem->setData(kRoleTime, data.time_);
widgeItem->setData(kRoleTime, data.screen_);
if (auto widget = qobject_cast<JsonListItem *>(itemWidget(widgeItem))) {
widget->setIndex(data.index_);
widget->setJsonName(name);
widget->setJsonDate(data.date_);
widget->setJsonTime(data.time_);
widget->setJsonScreen(data.screen_);
}
}
}
QListWidgetItem *JsonListWidget::findWidgetItemByName(const QString &name) {
int listCount = count();
for (int row = 0; row < listCount; ++row) {
auto widgetItem = item(row);
if (!widgetItem) {
continue;
}
if (name != widgetItem->data(kRoleName).toString()) {
continue;
}
return widgetItem;
}
return nullptr;
}
bool JsonListWidget::eventFilter(QObject *object, QEvent *event) {
// scrollbar设置位置的时机比较多,无法全面覆盖,只能在产生move事件之后再进行调整
auto widget = findChild<QWidget *>("qt_scrollarea_vcontainer");
if (widget && widget == object && event->type() == QEvent::Move) {
QPoint pos = widget->pos();
if (pos.x() && (pos.x() == rect().width() - widget->width())) {
QRect rc1 = widget->geometry();
pos -= QPoint(4, 0);
widget->move(pos);
}
}
return QListWidget::eventFilter(object, event);
}
JsonItemWidget.h
#pragma once
#include <QWidget>
#include "JsonItemDataDef.h"
class QStackedWidget;
class QStackedLayout;
class QLabel;
class QLineEdit;
class QVBoxLayout;
class QPushButton;
class RecorderPushButton18;
class RecorderTextLabel;
class JsonListItem : public QWidget {
Q_OBJECT
public:
explicit JsonListItem(QWidget* parent);
~JsonListItem();
void setIndex(const QString& index);
void setScriptName(const QString& name);
void setScriptDate(const QString& date);
void setScriptTime(const QString& time);
void setScriptScreen(const QString& screen);
void setModifyTime(quint64 time);
signals:
void sigCheckStateChanged(const QString& index, Qt::CheckState state);
void sigItemOpenScriptFileFolder();
void sigItemScriptRun(const QString& name);
void sigNameChanged(const QString& oldName, const QString& newName);
void sigDeleteButtonClicked(const QString& name);
void sigSettingButtonClicked(const QString& name);
protected:
virtual void enterEvent(QEvent* event) override;
virtual void leaveEvent(QEvent* event) override;
virtual void focusOutEvent(QFocusEvent* event) override;
bool eventFilter(QObject* object, QEvent* event) override;
private:
QWidget* initLeftInfoWidget();
QWidget* initRightButtonWidget();
void ensureRenameEdit();
void elidedName(NemuUiLib::NemuRichText1* label, const QString& name);
void showNameLabel();
void showRenameEdit();
private:
QString index_;
QString name_;
QString time_;
QString screen_;
QLable* nameLabel_;
QLable* dateLabel_;
QLabel* timeLabel_;
QLbale* screenLabel_;
QLineEdit* renameEdit_;
QPushButton* openFolderButton_;
QPushButton* settingButton_;
QPushButton* deleteButton_;
QVBoxLayout* centerLayout_;
bool mouseEntered_;
QPushButton* operatorButton_;
};
JsonItemWidget.cpp
#include "JsonListItem.h"
#include "../../common/RecorderPushButton.h"
#include "../../common/RecorderTextLabel.h"
#include "nemu-ui-lib/control/NemuImage.h"
#include "nemu-ui-lib/control/NemuRichText.h"
#include "nemu-ui-lib/control/NemuCheckBox.h"
#include "nemu-ui-lib/control/NemuLine.h"
#include "nemu-ui-lib/control/NemuLineEdit.h"
#include "nemu-ui-lib/font/NemuFont.h"
#include "nemu-ui-lib/color/NemuColor.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QLineEdit>
#include <QStackedWidget>
#include <QStackedLayout>
#include <QEvent>
#include <QMouseEvent>
#include <QValidator>
#include <QRegularExpression>
JsonListItem::JsonListItem(QWidget* parent)
: QWidget(parent),
nameLabel_(nullptr),
renameEdit_(nullptr),
openFolderButton_(nullptr),
settingButton_(nullptr),
deleteButton_(nullptr),
operatorButton_(nullptr),
mouseEntered_(false) {
setFixedSize(800, 80);
centerLayout_ = new QVBoxLayout(this);
centerLayout_->setAlignment(Qt::AlignCenter);
centerLayout_->setSpacing(0);
centerLayout_->setContentsMargins(0, 0, 0, 0);
auto mainLayout = new QHBoxLayout();
mainLayout->setContentsMargins(40, 18, 40, 16);
mainLayout->setAlignment(Qt::AlignCenter);
mainLayout->setSpacing(0);
installEventFilter(this);
mainLayout->addWidget(initLeftInfoWidget());
mainLayout->addWidget(initRightButtonWidget(), 0, Qt::AlignVCenter);
const auto line = new Line2({720, 1}, {40, 0, 40, 0}, this);
//centerLayout_->addStretch();
centerLayout_->addLayout(mainLayout);
//centerLayout_->addStretch();
centerLayout_->addWidget(line, 0, Qt::AlignBottom);
adjustSize();
}
JsonListItem::~JsonListItem() {
if (renameEdit_) {
renameEdit_->removeEventFilter(this);
}
removeEventFilter(this);
}
QWidget* JsonListItem::initLeftInfoWidget() {
auto widget = new QWidget(this);
auto centerLayout = new QVBoxLayout(widget);
centerLayout->setAlignment(Qt::AlignTop);
centerLayout->setSpacing(0);
centerLayout->setContentsMargins(0, 0, 0, 0);
nameLabel_ = new NemuUiLib::NemuRichText1(300, getFont14(), QString(), widget);
//nameLabel_->installEventFilter(this);
nameLabel_->setFixedHeight(24);
nameLabel_->document()->setDocumentMargin(0);
nameLabel_->setStyleSheet(
QString("QTextBrowser{color: %1; border: none; background-color: transparent}").arg(getWhite1().name(QColor::HexArgb)));
centerLayout->addWidget(nameLabel_, 0, Qt::AlignTop | Qt::AlignLeft);
QSpacerItem* spacer = new QSpacerItem(0, 4, QSizePolicy::Expanding, QSizePolicy::Fixed);
centerLayout->addItem(spacer);
auto dateAndScrenLayout = new QHBoxLayout();
dateAndScrenLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
dateAndScrenLayout->setSpacing(0);
dateAndScrenLayout->setContentsMargins(0, 0, 0, 0);
auto dataImage = new Image1(QSize(16, 16), ":/resources/images/ic_calendar.svg", widget);
dateAndScrenLayout->addWidget(dataImage);
dateAndScrenLayout->addSpacing(2);
dateLabel_ = new RichText2(QString(), getFont12(), widget);
dateAndScrenLayout->addWidget(dateLabel_);
dateAndScrenLayout->addSpacing(4);
timeLabel_ = new Text2(QString(), getFont12(), widget);
dateAndScrenLayout->addWidget(timeLabel_);
dateAndScrenLayout->addSpacing(16);
auto screenImage = new NemuImage1(QSize(16, 16), ":/resources/images/ic_resolution.svg", widget);
dateAndScrenLayout->addWidget(screenImage);
dateAndScrenLayout->addSpacing(2);
screenLabel_ = new RichText2(QString(), getFont12(), widget);
screenLabel_->setFixedWidth(55);
dateAndScrenLayout->addWidget(screenLabel_);
centerLayout->addLayout(dateAndScrenLayout);
return widget;
}
QWidget* JsonListItem::initRightButtonWidget() {
auto operatorWidget = new QWidget(this);
auto operatorLayout = new QHBoxLayout(operatorWidget);
operatorLayout->setContentsMargins(6, 0, 0, 0);
operatorLayout->setSpacing(20);
openFolderButton_ = new QPushButton(this);
openFolderButton_->setFixedSize(16, 16);
openFolderButton_->setToolTip(tr("File location"));
openFolderButton_->setStyleSheet(
QString("QPushButton{border-image: url(:/resources/images/ic_folder location_normal.svg);}\
QPushButton:hover{border-image: url(:/resources/images/ic_folder location_hover.svg);}\
QPushButton:pressed{border-image: url(:/resources/images/ic_folder location_press.svg);}\
QPushButton:disabled{border-image: url(:/resources/images/ic_folder location_disable.svg);}"
"QToolTip {"
"color: %1;"
"background-color: %2;"
"qproperty-shadow: none;"
"border: 0px solid #2A82DA;"
"}")
.arg(getWhite1().name(QColor::HexArgb))
.arg(getGrey10().name(QColor::HexArgb)));
connect(openFolderButton_, &QPushButton::clicked, this, [this]() {
emit sigItemOpenJsonFileFolder();
});
operatorLayout->addWidget(openFolderButton_);
settingButton_ = new QPushButton(this);
settingButton_->setFixedSize(16, 16);
settingButton_->setToolTip(tr("execution setting"));
settingButton_->setStyleSheet(QString("QPushButton{border-image: url(:/resources/images/ic_setting_normal.svg);}\
QPushButton:hover{border-image: url(:/resources/images/ic_setting_hover.svg);}\
QPushButton:pressed{border-image: url(:/resources/images/ic_setting_pressed.svg);}\
QPushButton:disabled{border-image: url(:/resources/images/ic_setting_disabled.svg);}"
"QToolTip {"
"qproperty-shadow: none;"
"color: %1;"
"background-color: %2;"
"border: 0px solid #2A82DA;"
"}")
.arg(getWhite1().name(QColor::HexArgb))
.arg(getGrey10().name(QColor::HexArgb)));
connect(settingButton_, &QPushButton::clicked, this, [this]() { emit sigSettingButtonClicked(name_); });
operatorLayout->addWidget(settingButton_);
deleteButton_ = new QPushButton(this);
deleteButton_->setFixedSize(16, 16);
deleteButton_->setToolTip(tr("delete"));
deleteButton_->setStyleSheet(QString("QPushButton{border-image: url(:/resources/images/ic_delete_normal.svg);}\
QPushButton:hover{border-image: url(:/resources/images/ic_delete_hover.svg);}\
QPushButton:pressed{border-image: url(:/resources/images/ic_delete_pressed.svg);}\
QPushButton:disabled{border-image: url(:/resources/images/ic_delete_disabled.svg);}"
"QToolTip {"
"color: %1;"
"background-color: %2;"
"qproperty-shadow: none;"
"border: 0px solid #2A82DA;"
"}")
.arg(getWhite1().name(QColor::HexArgb))
.arg(getGrey10().name(QColor::HexArgb)));
connect(deleteButton_, &QPushButton::clicked, this, [this]() { emit sigDeleteButtonClicked(name_); });
operatorLayout->addWidget(deleteButton_);
operatorButton_ = new RecorderPushButton18(this);
operatorButton_->setFixedSize(48, 24);
operatorButton_->setIcon(QIcon(":/resources/images//ic_start_up.svg"));
operatorButton_->setStateColor(NemuUiLib::NemuColor::getBrand1(), getBrand2(),
NemuUiLib::NemuColor::getBrand1());
operatorButton_->setToolTip(tr("execute"));
operatorButton_->setStyleSheet(QString("QToolTip {"
"color: %1;"
"background-color: %2;"
"border: 0px solid #2A82DA;"
"}")
.arg(getWhite1().name(QColor::HexArgb))
.arg(getGrey10().name(QColor::HexArgb)));
operatorButton_->setVisible(true);
connect(operatorButton_, &QPushButton::clicked, this, [this]() { sigItemJsonRun(name_);
});
operatorLayout->addWidget(operatorButton_);
return operatorWidget;
}
void JsonListItem::setIndex(const QString& index) { index_ = index; }
void JsonListItem::setJsonName(const QString& name) {
name_ = name;
if (renameEdit_ && renameEdit_->isVisible()) {
return;
}
elidedName(nameLabel_, name);
}
void JsonListItem::setJsonDate(const QString& date) {
time_ = date;
const auto dateHtmlText = QString("<p align=\"left\" style=\"color: %1;\">%2</p>")
.arg(getGrey2().name(QColor::HexArgb))
.arg(date);
dateLabel_->updateText(dateHtmlText);
dateLabel_->setFixedWidth(dateLabel_->adaptiveWidth(date, getFont12()));
}
void JsonListItem::setJsonTime(const QString& time) {
time_ = time;
const auto dateHtmlText = QString("<p align=\"left\" style=\"color: %1;\">%2</p>")
.arg(NemuUiLib::NemuColor::getGrey2().name(QColor::HexArgb))
.arg(time);
timeLabel_->updateText(dateHtmlText);
timeLabel_->setFixedWidth(timeLabel_->adaptiveWidth(time, getFont12()));
}
void JsonListItem::setJsonScreen(const QString& screen) {
screen_ = screen;
const auto screenHtmlText = QString("<p align=\"left\" style=\"color: %1;\">%2</p>")
.arg(getGrey2().name(QColor::HexArgb))
.arg(screen_);
screenLabel_->updateText(screenHtmlText);
screenLabel_->setFixedWidth(timeLabel_->adaptiveWidth(screen, getFont12()));
}
void JsonListItem::setModifyTime(quint64 time) {}
void JsonListItem::enterEvent(QEvent* event) {
QWidget::enterEvent(event);
}
void JsonListItem::leaveEvent(QEvent* event) {
if (renameEdit_ && renameEdit_->isVisible()) {
if (!renameEdit_->hasFocus()) {
renameEdit_->setVisible(false);
elidedName(nameLabel_, name_);
}
}
QWidget::leaveEvent(event);
}
void JsonListItem::focusOutEvent(QFocusEvent* event) {
if (renameEdit_) {
renameEdit_->setVisible(false);
}
QWidget::focusOutEvent(event);
}
void JsonListItem::showNameLabel() {
renameEdit_->setVisible(false);
elidedName(nameLabel_, name_);
}
void JsonListItem::showRenameEdit() {
nameLabel_->clear();
auto pos = nameLabel_->geometry();
ensureRenameEdit();
QSize sz = renameEdit_->size();
renameEdit_->setGeometry(pos.x() + 40, pos.y() + 18, sz.width(), sz.height());
renameEdit_->setText(name_);
renameEdit_->setVisible(true);
}
bool JsonListItem::eventFilter(QObject* object, QEvent* event) {
if (object == renameEdit_) {
if (event->type() == QEvent::FocusOut && !mouseEntered_) {
showNameLabel();
}
} else if (object == this) {
if (event->type() == QEvent::Enter) {
mouseEntered_ = true;
if (renameEdit_ && renameEdit_->isVisible()) {
if (!renameEdit_->hasFocus()) {
showNameLabel();
}
} else {
showRenameEdit();
}
} else if (event->type() == QEvent::Leave) {
mouseEntered_ = false;
if (renameEdit_ && !renameEdit_->hasFocus()) {
showNameLabel();
}
}
} else if (object != renameEdit_) {
if (renameEdit_ && !renameEdit_->hasFocus()) {
showNameLabel();
}
}
return QWidget::eventFilter(object, event);
}
void JsonListItem::ensureRenameEdit() {
if (renameEdit_) {
return;
}
renameEdit_ = new QLineEdit(this);
renameEdit_->setContextMenuPolicy(Qt::NoContextMenu);
renameEdit_->setMaxLength(40);
renameEdit_->setValidator(
new QRegularExpressionValidator(QRegularExpression("^((?!\\\\|\\/|:|\\*|\\?|\"|<|>|\\|).)*$"), this));
renameEdit_->setFixedSize(300, 24);
renameEdit_->setFont(NemuUiLib::NemuFont::getFont12());
renameEdit_->installEventFilter(this);
renameEdit_->setStyleSheet(
QString("QLineEdit{border-width:1px; border-style:solid; border-color:%1; padding-left:8px; padding-right:8px;"
"background-color: %1; color: %2; border-radius:2px;}"
"QLineEdit:hover{border-width:1px; border-style:solid; border-color:%3; background-color:%3;}"
"QLineEdit:focus{border-width:1px; border-style:solid; border-color:%4; background-color:%5; }")
.arg(getFill1().name(QColor::HexArgb))
.arg(getWhite1().name(QColor::HexArgb))
.arg(getFill2().name(QColor::HexArgb))
.arg(getBrand1().name(QColor::HexArgb))
.arg(getFill5().name(QColor::HexArgb)));
connect(renameEdit_, &QLineEdit::editingFinished, this, [this]() {
QString newName = renameEdit_->text();
if (!newName.isEmpty() && newName != name_) {
emit sigNameChanged(name_, newName);
}
});
connect(renameEdit_, &QLineEdit::returnPressed, this, [this]() {
QString newName = renameEdit_->text();
if (!newName.isEmpty() && newName != name_) {
emit sigNameChanged(name_, newName);
}
renameEdit_->setVisible(false);
elidedName(nameLabel_, name_);
});
}
void JsonListItem::elidedName(QLabel* label, const QString& name) {
QFontMetrics fontWidth(label->font());
int contentWidth = label->width() - label->document()->documentMargin() * 2;
label->setText(fontWidth.elidedText(name, Qt::ElideRight, contentWidth));
label->setFixedHeight(24);
}
JsonListWidgetItem.h
#pragma once
#include <QListWidgetItem>
enum ItemRole {
kRoleId = Qt::UserRole + 1,
kRoleIndex,
kRoleNumber,
kRoleMainFlag,
kRoleStatus,
kRoleErrorCode,
kRoleTime,
kRoleName,
};
class JsonWidgetItem : public QListWidgetItem {
public:
virtual bool operator<(const QListWidgetItem &other) const override;
private:
bool checked_;
};
JsonListWidgetItem.cpp
#include "JsonWidgetItem.h"
#include "JsonWidget.h"
#include <QListWidget>
#include <shlwapi.h>
#include "PlayerItemDataDef.h"
JsonWidgetItem::JsonWidgetItem(QListWidget *listview) : QListWidgetItem(listview), checked_(false) {}
JsonWidgetItem::~JsonWidgetItem() {}
bool JsonWidgetItem::operator<(const QListWidgetItem &other) const {
if (auto listView = qobject_cast<JsonWidget *>(listWidget())) {
if (listView->sortFactor() == kFactorNumber) {
return data(kRoleNumber).toInt() < other.data(kRoleNumber).toInt();
} else if (listView->sortFactor() == kFactorName) {
return StrCmpLogicalW((PCWSTR)data(kRoleName).toString().utf16(),
(PCWSTR)other.data(kRoleName).toString().utf16()) == -1;
} else if (listView->sortFactor() == kFactorTime) {
if (data(kRoleMainFlag).toBool()) {
return true;
} else if (other.data(kRoleMainFlag).toBool()) {
return false;
} else {
return data(kRoleTime).toULongLong() < other.data(kRoleTime).toULongLong();
}
}
}
return data(kRoleNumber).toString().compare(other.data(kRoleNumber).toString()) < 0;
}