2022-08-25 18:37:24 +08:00
|
|
|
#include "ephoto.h"
|
2024-08-07 18:18:37 +08:00
|
|
|
#include "main.h"
|
2022-08-25 18:37:24 +08:00
|
|
|
#include <QComboBox>
|
|
|
|
#include <QFileDialog>
|
|
|
|
#include <QLineEdit>
|
|
|
|
#include <QMessageBox>
|
|
|
|
#include <QPainter>
|
|
|
|
#include <QSpinBox>
|
|
|
|
|
2023-10-23 14:58:29 +08:00
|
|
|
EPhoto *EPhoto::create(const JObj &json, PageListItem *pageItem, EBase *multiWin) {
|
2022-08-25 18:37:24 +08:00
|
|
|
auto widget = json["widget"];
|
2024-02-21 18:08:50 +08:00
|
|
|
auto name = (widget.isNull() ? json["name"] : widget["file"]).toString();
|
2025-05-23 18:35:00 +08:00
|
|
|
auto file = pageItem->mPageDir + "/" + name;
|
2024-06-25 09:37:41 +08:00
|
|
|
QImageReader reader(file);
|
|
|
|
reader.setAutoTransform(true);
|
|
|
|
auto img = reader.read();
|
2024-02-21 18:08:50 +08:00
|
|
|
if(img.isNull()) return 0;
|
2025-05-23 18:35:00 +08:00
|
|
|
auto ins = new EPhoto(reader, img, pageItem->mPageDir, name, json, multiWin);
|
2022-08-25 18:37:24 +08:00
|
|
|
ins->setBaseAttr(json);
|
|
|
|
return ins;
|
|
|
|
}
|
|
|
|
|
2025-05-23 18:35:00 +08:00
|
|
|
EPhoto::EPhoto(QImageReader &reader, const QImage &img, const QString &dir, const QString &name, const JObj &json, EBase *multiWin) : EBase(multiWin), mDir(dir), mName(name) {
|
2024-02-21 18:08:50 +08:00
|
|
|
mType = EBase::Image;
|
2025-05-23 18:35:00 +08:00
|
|
|
auto cnt = reader.imageCount();
|
|
|
|
if(cnt<=1) this->img = img;
|
|
|
|
else {
|
|
|
|
frames.push_back({QPixmap::fromImage(img), reader.nextImageDelay()});
|
|
|
|
while((int)frames.size() < cnt) {
|
|
|
|
reader.jumpToNextImage();
|
|
|
|
frames.push_back({QPixmap::fromImage(reader.read()), reader.nextImageDelay()});
|
|
|
|
}
|
|
|
|
}
|
2025-05-06 18:28:05 +08:00
|
|
|
direct = json["direct"].toString();
|
|
|
|
speed = json["speed"].toInt();
|
|
|
|
tailSpacing = json["tailSpacing"].toInt();
|
2022-08-25 18:37:24 +08:00
|
|
|
}
|
2023-10-23 14:58:29 +08:00
|
|
|
JObj EPhoto::attrJson() const {
|
2024-02-21 18:08:50 +08:00
|
|
|
JObj json;
|
|
|
|
addBaseAttr(json);
|
2025-05-23 18:35:00 +08:00
|
|
|
json["elementType"] = frames.empty() ? "Image" : "Gif";
|
2024-02-21 18:08:50 +08:00
|
|
|
json["name"] = mName;
|
2025-05-06 18:28:05 +08:00
|
|
|
json["direct"] = direct;
|
|
|
|
json["speed"] = speed;
|
|
|
|
json["tailSpacing"] = tailSpacing;
|
2024-02-21 18:08:50 +08:00
|
|
|
return json;
|
2022-08-25 18:37:24 +08:00
|
|
|
}
|
|
|
|
void EPhoto::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
|
2025-05-23 18:35:00 +08:00
|
|
|
if(frames.empty()) painter->drawImage(innerRect(), img);
|
|
|
|
else {
|
|
|
|
painter->drawPixmap(innerRect(), frames[fi].img, QRectF());
|
|
|
|
if(timer==0) {
|
|
|
|
auto delay = frames[fi].dur;
|
|
|
|
if(delay) {
|
|
|
|
timer = new SyncTimer(delay);
|
|
|
|
connect(timer, &SyncTimer::timeout, this, &EPhoto::sltNext, Qt::BlockingQueuedConnection);
|
|
|
|
timer->start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-08-25 18:37:24 +08:00
|
|
|
EBase::paint(painter, option, widget);
|
|
|
|
}
|
2025-05-23 18:35:00 +08:00
|
|
|
void EPhoto::sltNext() {
|
|
|
|
if(isVisible() && ! frames.empty()) {
|
|
|
|
if(++fi==frames.size()) fi = 0;
|
|
|
|
timer->inter = frames[fi].dur;
|
|
|
|
update();
|
|
|
|
} else if(timer) {
|
|
|
|
timer->stop();
|
|
|
|
timer = 0;
|
|
|
|
}
|
2022-08-25 18:37:24 +08:00
|
|
|
}
|
2025-05-23 18:35:00 +08:00
|
|
|
|
2022-08-25 18:37:24 +08:00
|
|
|
bool EPhoto::save(const QString &pageDir) {
|
2025-05-23 18:35:00 +08:00
|
|
|
auto oldFile = mDir + PAGEDEL_SUFFIX + "/" + mName;
|
|
|
|
auto newName = mName;
|
|
|
|
auto newFile = pageDir + "/" + newName;
|
2022-08-25 18:37:24 +08:00
|
|
|
if(QFileInfo::exists(newFile)) {
|
2025-05-23 18:35:00 +08:00
|
|
|
newFile = AddSufix(newFile);
|
2022-08-25 18:37:24 +08:00
|
|
|
newName = QFileInfo(newFile).fileName();
|
|
|
|
}
|
|
|
|
if(QFileInfo::exists(oldFile)) QFile(oldFile).copy(newFile);
|
|
|
|
else if(pageDir!=mDir && QFileInfo::exists(oldFile = mDir + "/" + mName)) QFile(oldFile).copy(newFile);
|
|
|
|
else if(QFileInfo::exists(pageDir + "/" + mName)) newName = mName;
|
2025-05-23 18:35:00 +08:00
|
|
|
else return false;
|
2022-08-25 18:37:24 +08:00
|
|
|
mName = newName;
|
2025-05-23 18:35:00 +08:00
|
|
|
mDir = pageDir;
|
2022-08-25 18:37:24 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
QWidget* EPhoto::attrWgt() {
|
2024-02-21 18:08:50 +08:00
|
|
|
auto wgtAttr = new QWidget;
|
|
|
|
auto vBox = new VBox(wgtAttr);
|
2022-08-25 18:37:24 +08:00
|
|
|
vBox->setContentsMargins(6, 0, 6, 0);
|
2023-08-01 11:42:41 +08:00
|
|
|
if(mMultiWin) vBox->setSpacing(3);
|
2022-08-25 18:37:24 +08:00
|
|
|
|
|
|
|
addBaseAttrWgt(vBox);
|
|
|
|
|
2024-02-21 18:08:50 +08:00
|
|
|
auto hBox = new HBox(vBox);
|
2025-05-23 18:35:00 +08:00
|
|
|
hBox->addLabel(translate("","Basic Properties"));
|
2022-08-25 18:37:24 +08:00
|
|
|
|
|
|
|
auto line = new QFrame();
|
|
|
|
line->setFrameShape(QFrame::HLine);
|
|
|
|
line->setFrameShadow(QFrame::Sunken);
|
|
|
|
hBox->addWidget(line, 1);
|
|
|
|
|
2024-02-21 18:08:50 +08:00
|
|
|
hBox = new HBox(vBox);
|
2022-08-25 18:37:24 +08:00
|
|
|
hBox->addSpacing(6);
|
|
|
|
hBox->addWidget(new QLabel(tr("File")));
|
|
|
|
|
|
|
|
auto fdFile = new QLineEdit(mName);
|
|
|
|
fdFile->setReadOnly(true);
|
|
|
|
hBox->addWidget(fdFile);
|
|
|
|
|
|
|
|
auto bnSelectFile = new QPushButton("...");
|
|
|
|
bnSelectFile->setFixedWidth(30);
|
|
|
|
bnSelectFile->setObjectName("bnSelectFile");
|
2025-05-23 18:35:00 +08:00
|
|
|
auto wgtScroll = new QWidget;
|
2023-05-11 11:47:00 +08:00
|
|
|
connect(bnSelectFile, &QPushButton::clicked, wgtAttr, [=] {
|
2025-05-23 18:35:00 +08:00
|
|
|
auto home = mDir.startsWith(gProgItem->mProgDir) ? gFileHome : mDir;
|
|
|
|
auto file = QFileDialog::getOpenFileName(wgtAttr, translate("","Select File"), home, EPhoto::filters());
|
2022-09-13 23:16:36 +08:00
|
|
|
if(file.isEmpty()) return;
|
2022-08-25 18:37:24 +08:00
|
|
|
QImageReader reader(file);
|
2024-06-25 09:37:41 +08:00
|
|
|
reader.setAutoTransform(true);
|
|
|
|
auto aimg = reader.read();
|
2022-08-25 18:37:24 +08:00
|
|
|
if(aimg.isNull()) {
|
2025-05-23 18:35:00 +08:00
|
|
|
QMessageBox::critical(wgtAttr, tr("Image Read Error"), ImgErrStr(reader.error())+": "+reader.errorString()+"\n"+file);
|
2022-08-25 18:37:24 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
QFileInfo info(file);
|
2025-05-23 18:35:00 +08:00
|
|
|
gFileHome = mDir = info.absolutePath();
|
|
|
|
fdFile->setText(mName = info.fileName());
|
|
|
|
frames.clear();
|
|
|
|
fi = 0;
|
|
|
|
auto cnt = reader.imageCount();
|
|
|
|
if(cnt<=1) {
|
|
|
|
img = aimg;
|
|
|
|
wgtScroll->show();
|
|
|
|
} else {
|
|
|
|
img = QImage();
|
|
|
|
frames.push_back({QPixmap::fromImage(img), reader.nextImageDelay()});
|
|
|
|
while((int)frames.size() < cnt) {
|
|
|
|
reader.jumpToNextImage();
|
|
|
|
frames.push_back({QPixmap::fromImage(reader.read()), reader.nextImageDelay()});
|
|
|
|
}
|
|
|
|
wgtScroll->hide();
|
|
|
|
}
|
2022-08-25 18:37:24 +08:00
|
|
|
});
|
|
|
|
hBox->addWidget(bnSelectFile);
|
|
|
|
|
2025-05-23 18:35:00 +08:00
|
|
|
vBox->addWidget(wgtScroll);
|
|
|
|
wgtScroll->setVisible(frames.empty());
|
|
|
|
|
|
|
|
hBox = new HBox(wgtScroll);
|
|
|
|
hBox->setContentsMargins(0,0,0,0);
|
2025-05-06 18:28:05 +08:00
|
|
|
|
|
|
|
auto label = hBox->addLabel(tr("Scroll")+": "+tr("Direction"));
|
|
|
|
label->setMinimumWidth(80);
|
|
|
|
label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
|
|
|
|
|
|
|
|
auto edDirect = new QComboBox;
|
|
|
|
edDirect->addItem(tr("No"), "");
|
|
|
|
edDirect->addItem(tr("Right -> Left"), "left");
|
|
|
|
edDirect->addItem(tr("Bottom -> Top"), "top");
|
|
|
|
edDirect->addItem(tr("Left -> Right"), "right");
|
|
|
|
edDirect->addItem(tr("Top -> Bottom"), "bottom");
|
|
|
|
SetCurData(edDirect, direct);
|
|
|
|
connect(edDirect, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [=] {
|
|
|
|
direct = edDirect->currentData().toString();
|
|
|
|
});
|
|
|
|
hBox->addWidget(edDirect);
|
|
|
|
|
|
|
|
label = hBox->addLabel(tr("Speed"));
|
|
|
|
label->setMinimumWidth(80);
|
|
|
|
label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
|
|
|
|
|
|
|
|
auto fd = new QComboBox;
|
|
|
|
fd->setEditable(true);
|
|
|
|
fd->setMinimumWidth(50);
|
|
|
|
fd->addItem("600");
|
|
|
|
fd->addItem("540");
|
|
|
|
fd->addItem("480");
|
|
|
|
fd->addItem("420");
|
|
|
|
fd->addItem("360");
|
|
|
|
fd->addItem("300");
|
|
|
|
fd->addItem("240");
|
|
|
|
fd->addItem("180");
|
|
|
|
fd->addItem("120");
|
|
|
|
fd->addItem("60");
|
|
|
|
fd->addItem("30");
|
|
|
|
fd->setMaxVisibleItems(fd->count());
|
|
|
|
auto text = QString::number(speed);
|
|
|
|
if(SetCurText(fd, text)==-1) {
|
|
|
|
SetCurText(fd, "60");
|
|
|
|
fd->setCurrentText(text);
|
|
|
|
}
|
|
|
|
connect(fd, &QComboBox::editTextChanged, this, [=](const QString &text) {
|
|
|
|
bool ok;
|
|
|
|
auto speed = text.toInt(&ok);
|
|
|
|
if(ok) this->speed = speed;
|
|
|
|
});
|
|
|
|
hBox->addWidget(fd);
|
|
|
|
hBox->addLabel("px/s");
|
|
|
|
hBox->addStretch();
|
|
|
|
|
|
|
|
// hBox = new HBox(vBox);
|
|
|
|
// label = hBox->addLabel(tr("Tail Spacing"));
|
|
|
|
// label->setMinimumWidth(80);
|
|
|
|
// label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
|
|
|
|
|
|
|
|
// auto edTailSpacing = new QSpinBox;
|
|
|
|
// edTailSpacing->setRange(0, 9999);
|
|
|
|
// edTailSpacing->setValue(tailSpacing);
|
2025-05-23 18:35:00 +08:00
|
|
|
// connect(edTailSpacing, &QSpinBox::valueChanged, this, [this](int value) {
|
2025-05-06 18:28:05 +08:00
|
|
|
// tailSpacing = value;
|
|
|
|
// });
|
|
|
|
// hBox->addWidget(edTailSpacing);
|
|
|
|
// hBox->addStretch();
|
|
|
|
|
2024-02-21 18:08:50 +08:00
|
|
|
// hBox = new HBox(vBox);
|
|
|
|
// hBox->addWidget(new QLabel(tr("Play Properties")));
|
|
|
|
|
|
|
|
// line = new QFrame();
|
|
|
|
// line->setFrameShape(QFrame::HLine);
|
|
|
|
// line->setFrameShadow(QFrame::Sunken);
|
|
|
|
// hBox->addWidget(line, 1);
|
|
|
|
|
|
|
|
// hBox = new HBox(vBox);
|
|
|
|
// hBox->setSpacing(2);
|
|
|
|
// hBox->addSpacing(6);
|
|
|
|
// hBox->addWidget(new QLabel(tr("Entry Effect")));
|
|
|
|
|
|
|
|
// auto fdEntryEff = new QComboBox;
|
|
|
|
// fdEntryEff->addItem(tr("None"), "");
|
|
|
|
// fdEntryEff->addItem(tr("Move to left"), "moving_left");
|
|
|
|
// fdEntryEff->addItem(tr("Move to top"), "moving_top");
|
|
|
|
// fdEntryEff->addItem(tr("Move to right"), "moving_right");
|
|
|
|
// fdEntryEff->addItem(tr("Move to bottom"), "moving_bottom");
|
|
|
|
// fdEntryEff->addItem(tr("Alpha in"), "alpha_in");
|
|
|
|
// fdEntryEff->addItem(tr("Zoom in"), "zoom_in");
|
|
|
|
// fdEntryEff->addItem(tr("Zoom in from left-top"), "zoom_in_left_top");
|
|
|
|
// fdEntryEff->addItem(tr("Zoom in from right-top"), "zoom_in_right_top");
|
|
|
|
// fdEntryEff->addItem(tr("Zoom in from right-bottom"), "zoom_in_right_bottom");
|
|
|
|
// fdEntryEff->addItem(tr("Zoom in from left-bottom"), "zoom_in_left_bottom");
|
|
|
|
// fdEntryEff->addItem(tr("Rotate to right"), "rotate_right");
|
|
|
|
// fdEntryEff->addItem(tr("Rotate to left"), "rotate_left");
|
|
|
|
// fdEntryEff->addItem(tr("Random"), "Random");
|
|
|
|
// SetCurData(fdEntryEff, mEntryEffect);
|
|
|
|
// connect(fdEntryEff, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [=] {
|
|
|
|
// mEntryEffect = fdEntryEff->currentData().toString();
|
|
|
|
// });
|
|
|
|
// hBox->addWidget(fdEntryEff);
|
|
|
|
// hBox->addStretch();
|
|
|
|
|
|
|
|
// hBox->addLabel(tr("Dur"));
|
|
|
|
|
|
|
|
// auto fdEntryDur = new QSpinBox;
|
|
|
|
// fdEntryDur->setRange(1, 99);
|
|
|
|
// fdEntryDur->setValue(mEntryDur);
|
2025-05-23 18:35:00 +08:00
|
|
|
// connect(fdEntryDur, &QSpinBox::valueChanged, this, [=](int value) {
|
2024-02-21 18:08:50 +08:00
|
|
|
// mEntryDur = value;
|
|
|
|
// if(mDuration < value) {
|
|
|
|
// mDuration = value;
|
|
|
|
// fdDuration->setValue(value);
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
// hBox->addWidget(fdEntryDur);
|
|
|
|
// hBox->addLabel(tr("s"));
|
|
|
|
|
|
|
|
// hBox = new HBox(vBox);
|
|
|
|
// hBox->setSpacing(2);
|
|
|
|
// hBox->addSpacing(6);
|
|
|
|
// hBox->addWidget(new QLabel(tr("Exit Effect")));
|
|
|
|
|
|
|
|
// auto fdExitEff = new QComboBox;
|
|
|
|
// fdExitEff->addItem(tr("None"), "");
|
|
|
|
// fdExitEff->addItem(tr("Move to left"), "moving_left");
|
|
|
|
// fdExitEff->addItem(tr("Move to top"), "moving_top");
|
|
|
|
// fdExitEff->addItem(tr("Move to right"), "moving_right");
|
|
|
|
// fdExitEff->addItem(tr("Move to bottom"), "moving_bottom");
|
|
|
|
// fdExitEff->addItem(tr("Alpha out"), "alpha_out");
|
|
|
|
// fdExitEff->addItem(tr("Zoom out"), "zoom_out");
|
|
|
|
// fdExitEff->addItem(tr("Zoom out to left-top"), "zoom_out_left_top");
|
|
|
|
// fdExitEff->addItem(tr("Zoom out to right-top"), "zoom_out_right_top");
|
|
|
|
// fdExitEff->addItem(tr("Zoom out to right-bottom"), "zoom_out_right_bottom");
|
|
|
|
// fdExitEff->addItem(tr("Zoom out to left-bottom"), "zoom_out_left_bottom");
|
|
|
|
// fdExitEff->addItem(tr("Rotate to right"), "rotate_right");
|
|
|
|
// fdExitEff->addItem(tr("Rotate to left"), "rotate_left");
|
|
|
|
// fdExitEff->addItem(tr("Random"), "Random");
|
|
|
|
// SetCurData(fdExitEff, mExitEffect);
|
|
|
|
// connect(fdExitEff, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [=] {
|
|
|
|
// mExitEffect = fdExitEff->currentData().toString();
|
|
|
|
// });
|
|
|
|
// hBox->addWidget(fdExitEff);
|
|
|
|
// hBox->addStretch();
|
|
|
|
|
|
|
|
// hBox->addLabel(tr("Dur"));
|
|
|
|
|
|
|
|
// auto fdExitDur = new QSpinBox;
|
|
|
|
// fdExitDur->setRange(1, 99);
|
|
|
|
// fdExitDur->setValue(mExitDur);
|
2025-05-23 18:35:00 +08:00
|
|
|
// connect(fdExitDur, &QSpinBox::valueChanged, this, [=](int value) {
|
2024-02-21 18:08:50 +08:00
|
|
|
// mExitDur = value;
|
|
|
|
// if(mDuration < value) {
|
|
|
|
// mDuration = value;
|
|
|
|
// fdDuration->setValue(value);
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
// hBox->addWidget(fdExitDur);
|
|
|
|
// hBox->addLabel(tr("s"));
|
2022-08-25 18:37:24 +08:00
|
|
|
|
|
|
|
vBox->addStretch();
|
|
|
|
return wgtAttr;
|
|
|
|
}
|