作者:小 琛
欢迎转载,请标明出处
文章目录
- 需求场景
- 思路描述
- Qt模块
- QListWidget
- QListWidgetItem
- 自定义QWidget配合QListWidget
- 例子:实现一个json文件管理窗口
需求场景
因工作需要,开发一个文件管理窗口,要让使用者可以对若干文件进行一系列操作。本文着重讲述ui实现,如何作出一个漂亮的列表
思路描述
这里仅描述思路,如果你对Qt并不熟悉,大致了解一下即可,后文会描述具体用法
- 利用Qt提供的类:QListWidget、QListWidgetItem,其中QListWidget为列表类,QListWidgetItem可以理解为每一项的数据类
- 原生的QListWidget一定不能满足我们的需求,因此我们构建一个类继承自QListWidget,在子类中重新定义ui风格
- 在2中,我们做到了自定义列表,但列表内的具体每一项内容仍然是原生的,因此我们可以自定义一个QWidget,这个widget可以根据我们具体的场景绘制,在插入的时候,使用我们的自定义QWidget作为每一项内容
- QListWidgetItem是列表插入必不可少的,并且我们制作列表时,一定会用到一些数据,也可以用它来存储
Qt模块
QListWidget
QListWidget是一个列表控件,可以显示一个可滚动的列表,列表项可以是纯文本、图标或者自定义控件。QListWidget使用QListWidgetItem来表示列表项,每个QListWidgetItem可以设置列表项的文本、图标和状态。
下面是一些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是QListWidget中的列表项,每个QListWidget中的列表项都是一个QListWidgetItem对象。QListWidgetItem包含了列表项的文本、图标、状态等信息,可以通过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
在使用QListWidget时,有时需要自定义列表项的内容,此时可以使用QWidget作为列表项的内容。QWidget可以是任何自定义控件,例如QPushButton、QLabel等。也就是说,你可以自定义一个任意构建的widget,将其作为列表的每一项内容。
例子:实现一个json文件管理窗口
文件构造:
JsonListWidget.h+JsonListWidget.cpp
JsonListWidgetItem.h+JsonListWidgetItem.cpp
JsonItemWidget.h+JsonItemWidget.cpp
注意的点:
- 下面的例子,并不能直接运行,因为包含了很多我自定义的控件,仅限于了解整个结构
- 整个设计: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;
}