304 lines
8.9 KiB
C++
304 lines
8.9 KiB
C++
#include "QtWidgetsApplication4.h"
|
|
#include <QPainter>
|
|
#include <QApplication>
|
|
#include <QVBoxLayout>
|
|
#include <QMenu>
|
|
#include <QDate>
|
|
#include <QProcess>
|
|
#include <QDir>
|
|
#include <QDebug>
|
|
//#include <QTextCodec>
|
|
#include <QFileInfo>
|
|
|
|
CardData::CardData(const QString& name, const QString& date, const QString& description)
|
|
: name(name), date(date), description(description), activated(false)
|
|
{
|
|
}
|
|
|
|
CardItemDelegate::CardItemDelegate(QObject* parent)
|
|
: QStyledItemDelegate(parent)
|
|
{
|
|
}
|
|
|
|
void CardItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
|
|
const QModelIndex& index) const
|
|
{
|
|
painter->setRenderHint(QPainter::Antialiasing);
|
|
painter->save();
|
|
|
|
// 获取数据
|
|
CardData data = index.data(Qt::UserRole).value<CardData>();
|
|
|
|
// 绘制卡片背景
|
|
QRect rect = option.rect;
|
|
rect.adjust(8, 4, -8, -4);
|
|
|
|
// 创建圆角路径
|
|
QPainterPath path;
|
|
path.addRoundedRect(rect, 8, 8);
|
|
|
|
// 绘制阴影
|
|
QColor shadowColor(0, 0, 0, 30);
|
|
for (int i = 0; i < 5; ++i) {
|
|
QRect shadowRect = rect.adjusted(0, i, 0, i);
|
|
QPainterPath shadowPath;
|
|
shadowPath.addRoundedRect(shadowRect, 8, 8);
|
|
painter->fillPath(shadowPath, shadowColor);
|
|
}
|
|
|
|
// 绘制卡片背景
|
|
QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
|
|
if (data.activated) {
|
|
gradient.setColorAt(0, QColor(40, 70, 45));
|
|
gradient.setColorAt(1, QColor(45, 80, 50));
|
|
painter->fillPath(path, gradient);
|
|
painter->setPen(QPen(QColor(60, 180, 90), 2));
|
|
}
|
|
else if (option.state & QStyle::State_Selected) {
|
|
gradient.setColorAt(0, QColor(45, 45, 55));
|
|
gradient.setColorAt(1, QColor(55, 55, 65));
|
|
painter->fillPath(path, gradient);
|
|
painter->setPen(QPen(QColor(70, 130, 180), 2));
|
|
}
|
|
else {
|
|
painter->fillPath(path, QColor(35, 35, 40));
|
|
painter->setPen(QPen(QColor(60, 60, 65)));
|
|
}
|
|
|
|
painter->drawPath(path);
|
|
|
|
// 设置字体
|
|
QFont nameFont("Microsoft YaHei", 10);
|
|
nameFont.setBold(true);
|
|
|
|
QFont normalFont("Microsoft YaHei", 9);
|
|
|
|
// 计算文本区域
|
|
int padding = 15;
|
|
QRect nameRect = rect.adjusted(padding, padding, -padding, 0);
|
|
nameRect.setHeight(25);
|
|
|
|
QRect dateRect = nameRect;
|
|
dateRect.translate(0, nameRect.height());
|
|
|
|
QRect descRect = dateRect;
|
|
descRect.translate(0, dateRect.height());
|
|
descRect.setHeight(40);
|
|
|
|
// 绘制文本
|
|
painter->setFont(nameFont);
|
|
painter->setPen(Qt::white);
|
|
painter->drawText(nameRect, Qt::AlignLeft | Qt::AlignVCenter, data.name);
|
|
|
|
painter->setFont(normalFont);
|
|
painter->setPen(QColor(180, 180, 180));
|
|
painter->drawText(dateRect, Qt::AlignLeft | Qt::AlignVCenter, data.date);
|
|
|
|
painter->setPen(QColor(160, 160, 160));
|
|
painter->drawText(descRect, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap,
|
|
data.description);
|
|
|
|
painter->restore();
|
|
}
|
|
|
|
QSize CardItemDelegate::sizeHint(const QStyleOptionViewItem& option,
|
|
const QModelIndex& index) const
|
|
{
|
|
Q_UNUSED(option);
|
|
Q_UNUSED(index);
|
|
return QSize(380, 130);
|
|
}
|
|
|
|
MainWindow::MainWindow(QWidget* parent)
|
|
: QWidget(parent)
|
|
{
|
|
setupUI();
|
|
setupStyle();
|
|
|
|
// 添加示例数据
|
|
for (int i = 1; i <= 10; ++i) {
|
|
CardData data(
|
|
QString("项目 %1").arg(i),
|
|
QDate::currentDate().toString("yyyy-MM-dd"),
|
|
QString("这是项目 %1 的详细描述信息,可以包含多行文本内容。这是一个较长的描述,用于测试换行效果。").arg(i)
|
|
);
|
|
addCardItem(data);
|
|
}
|
|
}
|
|
|
|
void MainWindow::setupUI()
|
|
{
|
|
setWindowTitle(tr("卡片列表示例"));
|
|
resize(400, 600);
|
|
|
|
QVBoxLayout* layout = new QVBoxLayout(this);
|
|
layout->setContentsMargins(10, 10, 10, 10);
|
|
layout->setSpacing(0);
|
|
|
|
listWidget = new QListWidget(this);
|
|
listWidget->setSpacing(10);
|
|
listWidget->setResizeMode(QListWidget::Adjust);
|
|
listWidget->setUniformItemSizes(false);
|
|
listWidget->setViewMode(QListWidget::ListMode);
|
|
listWidget->setVerticalScrollMode(QListWidget::ScrollPerPixel);
|
|
listWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
|
|
CardItemDelegate* delegate = new CardItemDelegate(listWidget);
|
|
listWidget->setItemDelegate(delegate);
|
|
|
|
// 连接信号
|
|
connect(listWidget, &QListWidget::itemDoubleClicked,
|
|
this, &MainWindow::onItemDoubleClicked);
|
|
listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
connect(listWidget, &QListWidget::customContextMenuRequested,
|
|
this, &MainWindow::showContextMenu);
|
|
|
|
layout->addWidget(listWidget);
|
|
}
|
|
|
|
void MainWindow::setupStyle()
|
|
{
|
|
setStyleSheet("QWidget {"
|
|
" background-color: #1e1e1e;"
|
|
"}"
|
|
"QListWidget {"
|
|
" background-color: #1e1e1e;"
|
|
" border: none;"
|
|
" outline: none;"
|
|
"}"
|
|
"QListWidget::item {"
|
|
" background-color: transparent;"
|
|
" padding: 4px;"
|
|
"}"
|
|
"QListWidget::item:selected {"
|
|
" background-color: transparent;"
|
|
"}"
|
|
"QScrollBar:vertical {"
|
|
" border: none;"
|
|
" background: #1e1e1e;"
|
|
" width: 8px;"
|
|
" margin: 0px;"
|
|
"}"
|
|
"QScrollBar::handle:vertical {"
|
|
" background: #404040;"
|
|
" min-height: 20px;"
|
|
" border-radius: 4px;"
|
|
"}"
|
|
"QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {"
|
|
" height: 0px;"
|
|
"}"
|
|
"QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {"
|
|
" background: none;"
|
|
"}"
|
|
"QMenu {"
|
|
" background-color: #2d2d2d;"
|
|
" border: 1px solid #404040;"
|
|
" padding: 5px;"
|
|
"}"
|
|
"QMenu::item {"
|
|
" background-color: transparent;"
|
|
" padding: 6px 25px;"
|
|
" border-radius: 4px;"
|
|
" color: #ffffff;"
|
|
"}"
|
|
"QMenu::item:selected {"
|
|
" background-color: #404040;"
|
|
"}"
|
|
"QMenu::separator {"
|
|
" height: 1px;"
|
|
" background: #404040;"
|
|
" margin: 5px 0px;"
|
|
"}"
|
|
);
|
|
}
|
|
|
|
void MainWindow::addCardItem(const CardData& data)
|
|
{
|
|
QListWidgetItem* item = new QListWidgetItem(listWidget);
|
|
item->setData(Qt::UserRole, QVariant::fromValue(data));
|
|
item->setSizeHint(QSize(380, 120));
|
|
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
|
|
}
|
|
|
|
void MainWindow::onItemDoubleClicked(QListWidgetItem* item)
|
|
{
|
|
// 先将所有项目设置为未激活状态
|
|
for (int row = 0; row < listWidget->count(); ++row) {
|
|
QListWidgetItem* currentItem = listWidget->item(row);
|
|
CardData data = currentItem->data(Qt::UserRole).value<CardData>();
|
|
data.activated = false;
|
|
currentItem->setData(Qt::UserRole, QVariant::fromValue(data));
|
|
}
|
|
|
|
// 设置当前点击项目为激活状态
|
|
CardData data = item->data(Qt::UserRole).value<CardData>();
|
|
data.activated = true;
|
|
item->setData(Qt::UserRole, QVariant::fromValue(data));
|
|
|
|
listWidget->viewport()->update();
|
|
}
|
|
|
|
void MainWindow::showContextMenu(const QPoint& pos)
|
|
{
|
|
QListWidgetItem* item = listWidget->itemAt(pos);
|
|
if (!item) return;
|
|
|
|
QMenu menu(this);
|
|
|
|
QAction* sendAction = menu.addAction(tr("发送到设备"));
|
|
menu.addSeparator();
|
|
QAction* editAction = menu.addAction(tr("修改"));
|
|
QAction* deleteAction = menu.addAction(tr("删除"));
|
|
menu.addSeparator();
|
|
QAction* showInExplorerAction = menu.addAction(tr("在资源管理器中显示"));
|
|
|
|
// 设置图标
|
|
sendAction->setIcon(QIcon::fromTheme("document-send"));
|
|
editAction->setIcon(QIcon::fromTheme("document-edit"));
|
|
deleteAction->setIcon(QIcon::fromTheme("document-delete"));
|
|
showInExplorerAction->setIcon(QIcon::fromTheme("folder"));
|
|
|
|
QAction* action = menu.exec(listWidget->viewport()->mapToGlobal(pos));
|
|
if (!action) return;
|
|
|
|
if (action == sendAction)
|
|
sendToDevice(item);
|
|
else if (action == editAction)
|
|
editItem(item);
|
|
else if (action == deleteAction)
|
|
deleteItem(item);
|
|
else if (action == showInExplorerAction)
|
|
showInExplorer(item);
|
|
}
|
|
|
|
void MainWindow::sendToDevice(QListWidgetItem* item)
|
|
{
|
|
CardData data = item->data(Qt::UserRole).value<CardData>();
|
|
qDebug() << "发送到设备:" << data.name;
|
|
}
|
|
|
|
void MainWindow::editItem(QListWidgetItem* item)
|
|
{
|
|
CardData data = item->data(Qt::UserRole).value<CardData>();
|
|
qDebug() << "编辑项目:" << data.name;
|
|
}
|
|
|
|
void MainWindow::deleteItem(QListWidgetItem* item)
|
|
{
|
|
int row = listWidget->row(item);
|
|
delete listWidget->takeItem(row);
|
|
}
|
|
|
|
void MainWindow::showInExplorer(QListWidgetItem* item)
|
|
{
|
|
QString path = QDir::currentPath();
|
|
#ifdef Q_OS_WIN
|
|
QProcess::startDetached("explorer.exe", { "/select,", QDir::toNativeSeparators(path) });
|
|
#elif defined(Q_OS_MAC)
|
|
QProcess::startDetached("open", { "-R", path });
|
|
#else
|
|
QProcess::startDetached("xdg-open", { QFileInfo(path).path() });
|
|
#endif
|
|
}
|
|
|