kylin-connectivity/ui/filemanageview/fileview.cpp

545 lines
17 KiB
C++

#include "fileview.h"
#include <QDebug>
#include <QFileInfo>
#include <QApplication>
#include <QPainter>
#include <QScrollBar>
#include "generatetools.h"
#include "fileviewdelegate.h"
const int TAG_INFO = 100;
const int ICON_MODE_ICON_WIDTH = 64;
const int ICON_MODE_ICON_HEIGHT = 64;
const int LIST_MODE_ICON_WIDTH = 32;
const int LIST_MODE_ICON_HEIGHT = 32;
const int ICON_MODE_ITEM_WIDTH = 96;
const int ICON_MODE_ITEM_HEIGHT = 104;
const int LIST_MODE_ITEM_HEIGHT = 56;
const int ICON_MODE_SPACING = 16;
const int LIST_MODE_SPACING = 4;
const QString CONFIG_PATH = getenv("HOME") + QString("/.connectivitycache/") + QString("setting.ini");
const QString CONFIG_KEY = "LastFilePath";
const QString DEFAULT_DOWNLOAD_PATH = getenv("HOME") + QString("/下载");
FileView::FileView(QWidget *parent) : kdk::KListView(parent)
{
m_listItemHeight = LIST_MODE_ITEM_HEIGHT;
setContentsMargins(0, 0, 0, 0);
setStyleSheet("QListView{background:transparent;}");
// 自适应布局
setResizeMode(QListView::Adjust);
// 列表中的图标不可拖动
setMovement(QListView::Static);
// 去边框
setFrameShape(QListView::NoFrame);
// 不可编辑
setEditTriggers(QAbstractItemView::NoEditTriggers);
// 设置选中模式为选中行
setSelectionBehavior(QAbstractItemView::SelectRows);
// 设置滑动条
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
// 设置项大小相同
setUniformItemSizes(true);
// 设置右键菜单
setContextMenuPolicy(Qt::CustomContextMenu);
//设置接收鼠标拖进事件
setAcceptDrops(true);
setDragDropMode(QListView::DragDrop);
// 注册文件信息类型
FileInfo::registerMetaType();
m_listModel = new QStandardItemModel(this);
setModel(m_listModel);
FileViewDelegate *delegate = new FileViewDelegate(this);
setItemDelegate(delegate);
connect(this, &FileView::doubleClicked, this, &FileView::slotDoubleClicked);
connect(this, &FileView::clicked, this, &FileView::slotClicked);
connect(this, &FileView::customContextMenuRequested, this, &FileView::slotContextMenu);
}
void FileView::setViewMode(QListView::ViewMode mode)
{
m_viewModel = mode;
setIconSize(getIconSize());
if (m_viewModel == QListView::IconMode) {
setSpacing(ICON_MODE_SPACING);
} else {
setSpacing(LIST_MODE_SPACING);
}
updateViewMode();
kdk::KListView::setViewMode(m_viewModel);
update();
}
QListView::ViewMode FileView::getViewMode() const
{
return m_viewModel;
}
void FileView::setModelFlag(PublicAttributes::Model model)
{
m_model = model;
}
void FileView::setViewInfo(const QMap<QString, FileInfo> &map)
{
QMap<QString, FileInfo> dirMap; // 临时存储目录项
QMap<QString, FileInfo> fileMap; // 临时存储非目录项
for (FileInfo info : map) {
if (info.type() == FileInfo::FileType::Dir) {
dirMap.insert(info.name(), info);
} else {
// 不是文件夹
fileMap.insert(info.name(), info);
}
}
setInfo(dirMap);
setInfo(fileMap);
return;
}
void FileView::setViewInfo(const QList<FileInfo> &list)
{
QList<FileInfo> dirList; // 临时存储目录项
QList<FileInfo> fileList; // 临时存储非目录项
for (FileInfo info : list) {
if (info.type() == FileInfo::FileType::Dir) {
dirList.append(info);
} else {
// 不是文件夹
fileList.append(info);
}
}
setInfo(dirList);
setInfo(fileList);
return;
}
void FileView::setDownloadBtn(bool isShow)
{
if (isShow) {
if (m_downloadBtn != nullptr) {
return;
}
m_downloadBtn = new LevitationButton(this);
connect(m_downloadBtn, &LevitationButton::clicked, this, &FileView::slotDownloadBtnClicked);
m_downloadBtn->setIcon(":/filemanageview/download.svg");
m_downloadBtn->setText(tr("Download"));
m_downloadBtn->move(
QPoint(this->width() / 2 - m_downloadBtn->width() / 2, this->height() - 30 - m_downloadBtn->height()));
m_downloadBtn->changeFontSize(m_fontSize);
m_downloadBtn->show();
} else {
if (m_downloadBtn != nullptr) {
m_downloadBtn->deleteLater();
m_downloadBtn = nullptr;
}
}
}
void FileView::setTheme(PublicAttributes::Theme theme)
{
m_theme = theme;
update();
}
PublicAttributes::Theme FileView::getTheme() const
{
return m_theme;
}
void FileView::changeFontSize(double fontSize)
{
m_listItemHeight = m_listItemHeight + ((fontSize - m_fontSize) * 2);
m_fontSize = fontSize;
if (m_downloadBtn != nullptr) {
m_downloadBtn->changeFontSize(m_fontSize);
}
QFont font;
font.setPointSizeF(fontSize);
setFont(font);
updateViewMode();
}
double FileView::getFontSize() const
{
return m_fontSize;
}
void FileView::setItemMode(FileView::ItemSelectMode mode, bool isClear)
{
m_itemMode = mode;
if (isClear) {
clearSelection();
setDownloadBtn(false);
}
if (m_itemMode == ItemSelectMode::Default) {
QListView::setSelectionMode(QAbstractItemView::ExtendedSelection);
} else {
QListView::setSelectionMode(QAbstractItemView::MultiSelection);
}
update();
}
FileView::ItemSelectMode FileView::getItemMode() const
{
return m_itemMode;
}
void FileView::setThumbnailType(ThumbnailType type)
{
m_thumbnailType = type;
}
void FileView::setItemThumbnail(QString filePath)
{
if (m_itemMap.contains(filePath)) {
QPixmap thumbnail = QPixmap(filePath);
thumbnail = thumbnail.scaled(getIconSize(), Qt::KeepAspectRatio);
if (m_thumbnailType == ThumbnailType::Image) {
QIcon icon;
if (thumbnail.isNull()) {
icon = QIcon::fromTheme("image-x-generic");
} else {
icon = QIcon(thumbnail);
}
m_itemMap.find(filePath).value()->setIcon(icon);
} else if (m_thumbnailType == ThumbnailType::Video) {
QIcon icon;
if (thumbnail.isNull()) {
icon = QIcon(":/filemanageview/videodefault.svg");
} else {
QPixmap playPixmap(":/filemanageview/play.svg");
if (m_viewModel == QListView::IconMode) {
playPixmap = playPixmap.scaled(QSize(36, 36), Qt::KeepAspectRatio, Qt::SmoothTransformation);
} else {
playPixmap = playPixmap.scaled(QSize(24, 24), Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
QPainter imagepainter(&thumbnail);
imagepainter.setCompositionMode(QPainter::CompositionMode_SourceOver); //设置重叠效果
imagepainter.drawPixmap((thumbnail.width() - playPixmap.width()) / 2,
(thumbnail.height() - playPixmap.height()) / 2, playPixmap);
imagepainter.end();
icon = QIcon(thumbnail);
}
m_itemMap.find(filePath).value()->setIcon(icon);
}
}
}
void FileView::setAllowDrag(bool isAllowDrag)
{
m_isAllowDrag = isAllowDrag;
}
void FileView::mousePressEvent(QMouseEvent *event)
{
if (!indexAt(event->pos()).isValid()) {
if (QApplication::keyboardModifiers() != Qt::ControlModifier ||
event->source() != Qt::MouseEventSynthesizedByQt) {
clearSelection();
setDownloadBtn(false);
}
}
kdk::KListView::mousePressEvent(event);
}
void FileView::mouseReleaseEvent(QMouseEvent *event)
{
QModelIndexList list = selectionModel()->selectedIndexes();
if (list.size() >= 2) {
if (list.size() == m_listModel->rowCount()) {
Q_EMIT sigItemSelectAll(true);
} else {
Q_EMIT sigItemSelectAll(false);
}
setItemMode(FileView::ItemSelectMode::Edit);
setDownloadBtn(true);
} else {
if (m_itemMode == ItemSelectMode::Edit) {
Q_EMIT sigItemSelectAll(false);
}
}
kdk::KListView::mouseReleaseEvent(event);
}
void FileView::keyPressEvent(QKeyEvent *event)
{
if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_A)) {
Q_EMIT sigItemSelectAll(true);
setItemMode(FileView::ItemSelectMode::Edit);
setDownloadBtn(true);
Q_EMIT sigCtrlAClicked();
}
kdk::KListView::keyPressEvent(event);
}
void FileView::dragEnterEvent(QDragEnterEvent *event)
{
if (m_isAllowDrag && m_itemMode == ItemSelectMode::Default && event->mimeData()->hasUrls()) {
event->accept();
} else {
event->ignore();
}
}
void FileView::dragMoveEvent(QDragMoveEvent *event)
{
auto index = indexAt(event->pos());
if (index.isValid()) {
QHoverEvent he(QHoverEvent::HoverMove, event->posF(), event->posF());
viewportEvent(&he);
} else {
QHoverEvent he(QHoverEvent::HoverLeave, event->posF(), event->posF());
viewportEvent(&he);
}
event->accept();
}
void FileView::dropEvent(QDropEvent *event)
{
auto urls = event->mimeData()->urls();
qInfo() << "drag urls" << urls;
if (urls.isEmpty()) {
return;
}
QStringList localpath;
for (auto &url : urls) {
localpath << url.toLocalFile();
}
QString dirName = "";
QModelIndex index = indexAt(event->pos());
if (index.isValid()) {
FileInfo fileInfo = index.data(Qt::DisplayRole + TAG_INFO).value<FileInfo>();
if (fileInfo.type() == FileInfo::FileType::Dir) {
dirName = fileInfo.name();
}
}
Q_EMIT sigUploadFileInfo(dirName, localpath);
}
void FileView::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
if (m_downloadBtn != nullptr) {
m_downloadBtn->move(
QPoint(this->width() / 2 - m_downloadBtn->width() / 2, this->height() - 30 - m_downloadBtn->height()));
}
return kdk::KListView::resizeEvent(event);
}
void FileView::setInfo(const QMap<QString, FileInfo> &map)
{
for (FileInfo info : map) {
QStandardItem *item = new QStandardItem;
if (info.type() == FileInfo::FileType::Txt) {
item->setIcon(QIcon::fromTheme("text"));
} else if (info.type() == FileInfo::FileType::Video) {
item->setIcon(getVideoIcon(info.getThumbnailPath()));
} else if (info.type() == FileInfo::FileType::Image) {
item->setIcon(getPictureIcon(info.getThumbnailPath()));
} else if (info.type() == FileInfo::FileType::Audio) {
item->setIcon(QIcon::fromTheme("audio-x-generic"));
} else if (info.type() == FileInfo::FileType::Dir) {
item->setIcon(QIcon::fromTheme("folder"));
} else {
item->setIcon(QIcon::fromTheme(info.iconName(info.getContentType())));
}
// 设置文件名
item->setData(info.name(), Qt::DisplayRole);
// 标记文件信息
item->setData(info, Qt::DisplayRole + TAG_INFO);
item->setToolTip(info.name());
m_itemMap.insert(info.getThumbnailPath(), item);
m_listModel->appendRow(item);
}
}
void FileView::setInfo(const QList<FileInfo> &list)
{
for (FileInfo info : list) {
QStandardItem *item = new QStandardItem;
if (info.type() == FileInfo::FileType::Txt) {
item->setIcon(QIcon::fromTheme("text"));
} else if (info.type() == FileInfo::FileType::Video) {
item->setIcon(getVideoIcon(info.getThumbnailPath()));
} else if (info.type() == FileInfo::FileType::Image) {
item->setIcon(getPictureIcon(info.getThumbnailPath()));
} else if (info.type() == FileInfo::FileType::Audio) {
item->setIcon(QIcon::fromTheme("audio-x-generic"));
} else if (info.type() == FileInfo::FileType::Dir) {
item->setIcon(QIcon::fromTheme("folder"));
} else {
item->setIcon(QIcon::fromTheme(info.iconName(info.getContentType())));
}
// 设置文件名
item->setData(info.name(), Qt::DisplayRole);
// 标记文件信息
item->setData(info, Qt::DisplayRole + TAG_INFO);
item->setToolTip(info.name());
m_itemMap.insert(info.getThumbnailPath(), item);
m_listModel->appendRow(item);
}
}
void FileView::openFile(const QModelIndex &index)
{
FileInfo fileInfo = index.data(Qt::DisplayRole + TAG_INFO).value<FileInfo>();
Q_EMIT sigOpenFile(fileInfo.type(), fileInfo.getPath());
}
void FileView::sendDownloadInfo()
{
QSettings setting(CONFIG_PATH, QSettings::IniFormat);
QString lastPath = setting.value(CONFIG_KEY).toString();
if (lastPath.isEmpty()) {
lastPath = DEFAULT_DOWNLOAD_PATH;
}
QFileDialog fileDialog;
QString filePath = fileDialog.getExistingDirectory(this, tr("Choose folder"), lastPath); // Choose folder选择文件夹
if (!filePath.isEmpty()) {
setting.setValue(CONFIG_KEY, filePath);
} else {
return;
}
QList<FileInfo> fileList;
for (QModelIndex index : selectionModel()->selectedIndexes()) {
FileInfo fileInfo = index.data(Qt::DisplayRole + TAG_INFO).value<FileInfo>();
fileList.append(fileInfo);
}
Q_EMIT sigDownFileInfo(filePath, fileList);
}
void FileView::updateViewMode()
{
if (m_listModel->rowCount() == 0) {
return;
}
for (int i = 0; i < m_listModel->rowCount(); i++) {
QStandardItem *item = m_listModel->item(i, 0);
QModelIndex index = m_listModel->index(i, 0, QModelIndex());
if (m_viewModel == QListView::IconMode) {
item->setSizeHint(QSize(ICON_MODE_ITEM_WIDTH, ICON_MODE_ITEM_HEIGHT));
} else {
item->setSizeHint(QSize(width(), m_listItemHeight));
FileInfo fileInfo = index.data(Qt::DisplayRole + TAG_INFO).value<FileInfo>();
if (fileInfo.type() != FileInfo::FileType::Dir) {
QString sizeStr = GenerateTools::intSizeToString(fileInfo.size());
QVariant metaSize;
metaSize.setValue(sizeStr);
m_listModel->setData(index, metaSize, Qt::UserRole);
}
}
}
}
QSize FileView::getIconSize()
{
if (m_viewModel == QListView::IconMode) {
return QSize(ICON_MODE_ICON_WIDTH, ICON_MODE_ICON_HEIGHT);
} else {
return QSize(LIST_MODE_ICON_WIDTH, LIST_MODE_ICON_HEIGHT);
}
}
QIcon FileView::getPictureIcon(QString path)
{
if (path.isEmpty()) {
return QIcon::fromTheme("image-x-generic");
} else {
QFileInfo info(path);
if (!info.exists()) {
return QIcon::fromTheme("image-x-generic");
}
QPixmap thumbnail = QPixmap(path);
thumbnail = thumbnail.scaled(getIconSize(), Qt::KeepAspectRatio);
return QIcon(thumbnail);
}
}
QIcon FileView::getVideoIcon(QString path)
{
if (path.isEmpty()) {
return QIcon::fromTheme("video");
} else {
QFileInfo info(path);
if (!info.exists()) {
return QIcon(":/filemanageview/videodefault.svg");
}
QPixmap thumbnail = QPixmap(path);
thumbnail = thumbnail.scaled(getIconSize(), Qt::KeepAspectRatio);
QPixmap playPixmap(":/filemanageview/play.svg");
if (m_viewModel == QListView::IconMode) {
playPixmap = playPixmap.scaled(QSize(36, 36), Qt::KeepAspectRatio, Qt::SmoothTransformation);
} else {
playPixmap = playPixmap.scaled(QSize(24, 24), Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
QPainter imagepainter(&thumbnail); //新建画板
imagepainter.setCompositionMode(QPainter::CompositionMode_SourceOver); //设置重叠效果
imagepainter.drawPixmap((thumbnail.width() - playPixmap.width()) / 2,
(thumbnail.height() - playPixmap.height()) / 2, playPixmap);
imagepainter.end();
return QIcon(thumbnail);
}
}
void FileView::slotDoubleClicked(const QModelIndex &index)
{
openFile(index);
}
void FileView::slotClicked(const QModelIndex &index)
{
if (m_model == PublicAttributes::Model::Table && m_itemMode == ItemSelectMode::Default) {
openFile(index);
} else {
setDownloadBtn(true);
}
}
void FileView::slotDownloadBtnClicked()
{
sendDownloadInfo();
}
void FileView::slotContextMenu(const QPoint &pos)
{
setDownloadBtn(false);
QModelIndexList list = selectionModel()->selectedIndexes();
if (!list.empty()) {
QMenu *menu = new QMenu(this);
QAction *openAction = new QAction(QIcon::fromTheme("folder-open-symbolic"), tr("Open"), this);
connect(openAction, &QAction::triggered, this, &FileView::slotOpenTriggered);
QAction *downloadAction = new QAction(QIcon(":/filemanageview/download.svg"), tr("Download"), this);
connect(downloadAction, &QAction::triggered, this, &FileView::slotDownloadTriggered);
if (list.size() == 1) {
menu->addAction(openAction);
}
menu->addAction(downloadAction);
menu->exec(QCursor::pos()); // 在当前鼠标位置显示
clearSelection();
delete menu;
delete openAction;
delete downloadAction;
}
}
void FileView::slotOpenTriggered()
{
QModelIndex index = currentIndex();
openFile(index);
}
void FileView::slotDownloadTriggered()
{
sendDownloadInfo();
}