2025-03-14 15:23:08 +08:00
|
|
|
|
#include "mediapanel.h"
|
|
|
|
|
#include "main.h"
|
|
|
|
|
#include <QApplication>
|
|
|
|
|
#include <QMessageBox>
|
|
|
|
|
#include <QStandardPaths>
|
|
|
|
|
#include <QProgressBar>
|
|
|
|
|
#include <QFileDialog>
|
|
|
|
|
#include <QLineEdit>
|
|
|
|
|
#include <QProcess>
|
|
|
|
|
#include <QInputDialog>
|
|
|
|
|
#include <QDropEvent>
|
|
|
|
|
#include <QMediaPlayer>
|
|
|
|
|
#include <QVideoWidget>
|
|
|
|
|
#include <QVideoSink>
|
|
|
|
|
#include <QVideoFrame>
|
|
|
|
|
|
2025-05-06 18:28:05 +08:00
|
|
|
|
MediaTree *gMediaTree;
|
|
|
|
|
|
2025-03-14 15:23:08 +08:00
|
|
|
|
MediaPanel::MediaPanel(QWidget *parent) : QWidget(parent) {
|
|
|
|
|
auto vBox = new VBox(this);
|
|
|
|
|
vBox->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
vBox->setSpacing(0);
|
|
|
|
|
auto hBox = new HBox(vBox);
|
|
|
|
|
|
2025-05-06 18:28:05 +08:00
|
|
|
|
auto bnAdd = new QPushButton("🞥");
|
|
|
|
|
bnAdd->setMaximumWidth(50);
|
|
|
|
|
hBox->addWidget(bnAdd);
|
|
|
|
|
connect(bnAdd, &QPushButton::clicked, this, [this] {
|
2025-03-14 15:23:08 +08:00
|
|
|
|
auto file = QFileDialog::getOpenFileName(this, 0, gFileHome);
|
|
|
|
|
if(file.isEmpty()) return;
|
|
|
|
|
QFileInfo info(file);
|
|
|
|
|
auto dir = info.absolutePath();
|
|
|
|
|
auto name = info.fileName();
|
|
|
|
|
gFileHome = dir;
|
|
|
|
|
auto suffix = info.suffix().toLower();
|
|
|
|
|
MediaItem *item = 0;
|
|
|
|
|
if(suffix.startsWith("mp")) {
|
|
|
|
|
auto player = new QMediaPlayer;
|
|
|
|
|
player->setSource(QUrl::fromLocalFile(file));
|
2025-05-06 18:28:05 +08:00
|
|
|
|
item = new MediaItem(file, gMediaTree);
|
2025-03-14 15:23:08 +08:00
|
|
|
|
item->setText("type", "Video");
|
|
|
|
|
auto videoWgt = new QVideoWidget;
|
|
|
|
|
player->setVideoOutput(videoWgt);
|
|
|
|
|
auto videoSink = videoWgt->videoSink();
|
|
|
|
|
connect(videoSink, &QVideoSink::videoFrameChanged, player, [=](const QVideoFrame &frame) {
|
|
|
|
|
disconnect(videoSink, &QVideoSink::videoFrameChanged, player, 0);
|
|
|
|
|
player->stop();
|
|
|
|
|
player->deleteLater();
|
|
|
|
|
videoWgt->deleteLater();
|
2025-05-06 18:28:05 +08:00
|
|
|
|
qDebug()<<"pixelFormat"<<frame.pixelFormat();
|
|
|
|
|
item->setText("size", QString("%1×%2").arg(frame.width()).arg(frame.height()));
|
2025-03-14 15:23:08 +08:00
|
|
|
|
item->setText("dur", QTime::fromMSecsSinceStartOfDay(player->duration()).toString("hh:mm:ss.zzz"));
|
|
|
|
|
item->profile = frame.toImage().scaledToHeight(60, Qt::SmoothTransformation);
|
|
|
|
|
auto edProfile = new QLabel;
|
|
|
|
|
edProfile->setPixmap(QPixmap::fromImage(item->profile));
|
|
|
|
|
edProfile->setScaledContents(true);
|
|
|
|
|
edProfile->setMaximumHeight(24);
|
|
|
|
|
item->setCellWidget("profile", edProfile);
|
|
|
|
|
});
|
|
|
|
|
player->play();
|
|
|
|
|
} else if(suffix == "png" || suffix.startsWith("jp") || suffix == "gif") {
|
|
|
|
|
QImageReader reader(file);
|
|
|
|
|
reader.setAutoTransform(true);
|
|
|
|
|
auto img = reader.read();
|
|
|
|
|
if(img.isNull()) {
|
|
|
|
|
QMessageBox::critical(this, "Image Read Error", QString::number(reader.error())+" "+reader.errorString());
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-05-06 18:28:05 +08:00
|
|
|
|
item = new MediaItem(file, gMediaTree);
|
2025-03-14 15:23:08 +08:00
|
|
|
|
item->setText("type", "Image");
|
|
|
|
|
item->setText("dur", "00:10:00.000");
|
2025-05-06 18:28:05 +08:00
|
|
|
|
item->setText("size", QString("%1×%2").arg(img.width()).arg(img.height()));
|
2025-03-14 15:23:08 +08:00
|
|
|
|
item->profile = img.scaledToHeight(60, Qt::SmoothTransformation);
|
|
|
|
|
auto edProfile = new QLabel;
|
|
|
|
|
edProfile->setPixmap(QPixmap::fromImage(item->profile));
|
|
|
|
|
edProfile->setScaledContents(true);
|
|
|
|
|
edProfile->setMaximumHeight(24);
|
|
|
|
|
item->setCellWidget("profile", edProfile);
|
|
|
|
|
}
|
|
|
|
|
if(item) {
|
|
|
|
|
item->setText("name", name);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2025-05-06 18:28:05 +08:00
|
|
|
|
auto bnDelet = new QPushButton("🗑");
|
|
|
|
|
bnDelet->setMaximumWidth(50);
|
|
|
|
|
hBox->addWidget(bnDelet);
|
|
|
|
|
connect(bnDelet, &QPushButton::clicked, this, [=] {
|
2025-03-14 15:23:08 +08:00
|
|
|
|
// for(int i=0; i<tree->topLevelItemCount(); i++) if(tree->item(i)->checkState("check") == Qt::Checked) {
|
|
|
|
|
// auto item = (MediaItem*) tree->topLevelItem(i--);
|
|
|
|
|
// item->del();
|
|
|
|
|
// delete item;
|
|
|
|
|
// }
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
hBox->addStretch();
|
|
|
|
|
|
|
|
|
|
auto fdSearch = new QLineEdit;
|
|
|
|
|
fdSearch->setMinimumWidth(100);
|
|
|
|
|
auto search = new QAction;
|
|
|
|
|
search->setIcon(QIcon(":/res/program/bnSearch.png"));
|
|
|
|
|
fdSearch->addAction(search, QLineEdit::LeadingPosition);
|
|
|
|
|
fdSearch->setClearButtonEnabled(true);
|
|
|
|
|
//fdSearch->setStyleSheet("border: 1px solid #888;");
|
2025-05-06 18:28:05 +08:00
|
|
|
|
connect(fdSearch, &QLineEdit::textChanged, this, [](const QString &text) {
|
|
|
|
|
auto cnt = gMediaTree->topLevelItemCount();
|
2025-03-14 15:23:08 +08:00
|
|
|
|
for(int i=0; i<cnt; i++) {
|
2025-05-06 18:28:05 +08:00
|
|
|
|
auto item = gMediaTree->item(i);
|
2025-03-14 15:23:08 +08:00
|
|
|
|
item->setHidden(! (text.isEmpty() || item->text("name").contains(text) || item->text("resolution").contains(text)));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
hBox->addWidget(fdSearch);
|
|
|
|
|
|
2025-05-06 18:28:05 +08:00
|
|
|
|
gMediaTree = new MediaTree;
|
|
|
|
|
gMediaTree->addCol("#", "", 20);
|
|
|
|
|
gMediaTree->addCol("profile", "", 42);
|
|
|
|
|
gMediaTree->addCol("name", "", 140);
|
|
|
|
|
gMediaTree->addCol("type", "", 45);
|
|
|
|
|
gMediaTree->addCol("size", "", 60);
|
|
|
|
|
gMediaTree->addCol("dur", "", 80);
|
|
|
|
|
gMediaTree->setDefs()->setHeaderAlignC();
|
|
|
|
|
gMediaTree->minRowHeight = 26;
|
|
|
|
|
gMediaTree->setSortingEnabled(true);
|
|
|
|
|
gMediaTree->setDragEnabled(true);
|
|
|
|
|
gMediaTree->setAcceptDrops(true);
|
|
|
|
|
gMediaTree->setDropIndicatorShown(true);
|
|
|
|
|
vBox->addWidget(gMediaTree);
|
2025-03-14 15:23:08 +08:00
|
|
|
|
|
|
|
|
|
auto dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
|
|
|
|
if(mProgsDir.isEmpty()) return;
|
2025-05-06 18:28:05 +08:00
|
|
|
|
gMediaTree->clear();
|
2025-03-14 15:23:08 +08:00
|
|
|
|
// for(auto &progName : progNames) {
|
|
|
|
|
// auto file = mProgsDir + "/" + progName + "/pro.json";
|
|
|
|
|
// QFile qFile(file);
|
|
|
|
|
// if(! qFile.exists()) continue;
|
|
|
|
|
// if(! qFile.open(QIODevice::ReadOnly)) continue;
|
|
|
|
|
// auto data = qFile.readAll();
|
|
|
|
|
// qFile.close();
|
|
|
|
|
// QString error;
|
|
|
|
|
// auto json = JFrom(data, &error);
|
|
|
|
|
// if(! error.isEmpty()) continue;
|
|
|
|
|
// auto item = new MediaItem(tree);
|
|
|
|
|
// item->dir = dir;
|
|
|
|
|
// item->setText("name", name);
|
|
|
|
|
// item->setText("resolution", QString("%1 x %2").arg(mWidth).arg(mHeight));
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
QSettings settings;
|
2025-05-06 18:28:05 +08:00
|
|
|
|
gMediaTree->sortByColumn(settings.value("MediaSortColumn").toInt(), (Qt::SortOrder)settings.value("MediaSortOrder").toInt());
|
2025-03-14 15:23:08 +08:00
|
|
|
|
|
|
|
|
|
transUi();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MediaPanel::changeEvent(QEvent *event) {
|
|
|
|
|
QWidget::changeEvent(event);
|
|
|
|
|
if(event->type() == QEvent::LanguageChange) transUi();
|
|
|
|
|
}
|
|
|
|
|
void MediaPanel::transUi() {
|
2025-05-06 18:28:05 +08:00
|
|
|
|
gMediaTree->headerItem()->setText("name"**gMediaTree, tr("Name"));
|
|
|
|
|
gMediaTree->headerItem()->setText("type"**gMediaTree, tr("Type"));
|
|
|
|
|
gMediaTree->headerItem()->setText("size"**gMediaTree, tr("Size"));
|
|
|
|
|
gMediaTree->headerItem()->setText("dur"**gMediaTree, tr("Duration"));
|
2025-03-14 15:23:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MediaTree::dropEvent(QDropEvent *event) {
|
|
|
|
|
if(MediaTree::OnItem==dropIndicatorPosition()) {
|
|
|
|
|
event->ignore();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
TreeWidget::dropEvent(event);
|
|
|
|
|
}
|