2022-08-25 18:37:24 +08:00
|
|
|
|
#include "tools.h"
|
|
|
|
|
#include "cfg.h"
|
|
|
|
|
#include "globaldefine.h"
|
|
|
|
|
#include "wProgramManager/pagelistitem.h"
|
2022-10-27 15:07:45 +08:00
|
|
|
|
#include "base/x_uimsgboxok.h"
|
2022-08-25 18:37:24 +08:00
|
|
|
|
#include <QMediaPlayer>
|
|
|
|
|
#include <QSettings>
|
|
|
|
|
#include <QProcess>
|
|
|
|
|
#include <QBuffer>
|
|
|
|
|
#include <QJsonArray>
|
|
|
|
|
extern "C"{
|
|
|
|
|
#include <libavformat/avformat.h>
|
|
|
|
|
#include <libswscale/swscale.h>
|
2022-10-27 15:07:45 +08:00
|
|
|
|
#include <libavutil/imgutils.h>
|
2022-08-25 18:37:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Tools::timerEvent(QTimerEvent *event) {
|
|
|
|
|
if(timer_id==event->timerId()) emit sTick();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Tools* Tools::getInstance() {
|
|
|
|
|
static const auto ins = new Tools(qApp);
|
|
|
|
|
return ins;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QRectF Tools::centerRect(qreal width, qreal height, int maxW, int maxH) {
|
|
|
|
|
if(maxW < width || maxH < height) {
|
|
|
|
|
auto rate = qMin(maxW / width, maxH / height);
|
|
|
|
|
width *= rate;
|
|
|
|
|
height *= rate;
|
|
|
|
|
}
|
|
|
|
|
return QRectF((maxW - width) / 2, (maxH - height) / 2, width, height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Tools::addSufix(QString path) {
|
|
|
|
|
int i = path.lastIndexOf('.');
|
|
|
|
|
QString prefix = path, sufix;
|
|
|
|
|
if(i > 0 && i > path.lastIndexOf('/')+1 && i >= path.length()-9) {
|
|
|
|
|
prefix = path.left(i);
|
|
|
|
|
sufix = path.mid(i);
|
|
|
|
|
}
|
|
|
|
|
i = 1;
|
|
|
|
|
while(QFileInfo::exists(path = prefix+QString::number(i)+sufix)) i++;
|
|
|
|
|
return path;
|
|
|
|
|
}
|
|
|
|
|
QString Tools::videoInfo(QByteArray url, QImage &img, int64_t *dur, AVCodecID *codec_id) {
|
|
|
|
|
AVFormatContext *fmt_ctx = avformat_alloc_context();
|
|
|
|
|
QString err;
|
|
|
|
|
{
|
|
|
|
|
if(avformat_open_input(&fmt_ctx, url.constData(), nullptr, nullptr) != 0) {
|
|
|
|
|
err = "Couldn't open input stream";
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
if(avformat_find_stream_info(fmt_ctx, nullptr) < 0) {
|
|
|
|
|
err = "Couldn't find stream information";
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
if(dur!=nullptr) *dur = fmt_ctx->duration;
|
|
|
|
|
int vi_idx = -1;
|
|
|
|
|
for(uint ss=0; ss<fmt_ctx->nb_streams; ss++) if(fmt_ctx->streams[ss]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) vi_idx = ss;
|
|
|
|
|
if(vi_idx == -1) {
|
|
|
|
|
err = "Didn't find a Video Stream";
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
auto codecpar = fmt_ctx->streams[vi_idx]->codecpar;
|
|
|
|
|
if(codec_id!=nullptr) *codec_id = codecpar->codec_id;
|
|
|
|
|
qDebug()<<"codec_id"<<codecpar->codec_id<<avcodec_get_name(codecpar->codec_id);
|
|
|
|
|
if(av_seek_frame(fmt_ctx, -1, 1000000, AVSEEK_FLAG_BACKWARD) < 0) {
|
|
|
|
|
err = "av_seek_frame fail";
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
const AVCodec *decoder = avcodec_find_decoder(codecpar->codec_id);
|
|
|
|
|
if(decoder==nullptr) {
|
|
|
|
|
err = "Could not found Video Decoder";
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
auto vcCtx = avcodec_alloc_context3(decoder);
|
|
|
|
|
avcodec_parameters_to_context(vcCtx, codecpar);
|
|
|
|
|
if(avcodec_open2(vcCtx, decoder, nullptr) < 0) {
|
|
|
|
|
err = "Could not open Video Codec Ctx";
|
|
|
|
|
avcodec_free_context(&vcCtx);
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
2022-10-27 15:07:45 +08:00
|
|
|
|
auto sws_ctx = sws_getContext(vcCtx->width, vcCtx->height, vcCtx->pix_fmt, vcCtx->width, vcCtx->height, AV_PIX_FMT_RGB32, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
|
2022-08-25 18:37:24 +08:00
|
|
|
|
auto packet = av_packet_alloc();
|
|
|
|
|
auto frm = av_frame_alloc();
|
|
|
|
|
while(1) {
|
|
|
|
|
if(av_read_frame(fmt_ctx, packet) < 0) break;
|
|
|
|
|
if(packet->stream_index != vi_idx) continue;
|
|
|
|
|
int res = avcodec_send_packet(vcCtx, packet);
|
|
|
|
|
if(res < 0) break;
|
|
|
|
|
while((res = avcodec_receive_frame(vcCtx, frm)) != AVERROR(EAGAIN)) {
|
|
|
|
|
if(res < 0) goto free2;
|
2022-10-27 15:07:45 +08:00
|
|
|
|
img = QImage(vcCtx->width, vcCtx->height, QImage::Format_ARGB32);
|
2022-08-25 18:37:24 +08:00
|
|
|
|
uint8_t *dst[4]{img.bits()};
|
|
|
|
|
int dstStride[4]{img.bytesPerLine()};
|
|
|
|
|
sws_scale(sws_ctx, frm->data, frm->linesize, 0, vcCtx->height, dst, dstStride);
|
|
|
|
|
goto free2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
free2:
|
|
|
|
|
av_frame_free(&frm);
|
|
|
|
|
av_packet_free(&packet);
|
|
|
|
|
avcodec_free_context(&vcCtx);
|
|
|
|
|
sws_freeContext(sws_ctx);
|
|
|
|
|
}
|
|
|
|
|
free:
|
|
|
|
|
avformat_close_input(&fmt_ctx);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
2022-10-27 15:07:45 +08:00
|
|
|
|
QString trans(int sw, int sh, int dw, int dh, int cnt, QPointF pos, QByteArray file) {
|
|
|
|
|
AVFormatContext *in_fmt = avformat_alloc_context(), *out_fmt = 0;
|
|
|
|
|
AVCodecContext *de_ctx = 0, *en_ctx = 0;
|
|
|
|
|
QString err;
|
|
|
|
|
char buf[AV_ERROR_MAX_STRING_SIZE];
|
|
|
|
|
int ret;
|
|
|
|
|
{
|
|
|
|
|
if((ret = avformat_open_input(&in_fmt, file.constData(), nullptr, nullptr)) < 0) {
|
|
|
|
|
err = QString("Couldn't open input stream. ")+av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE);
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
if((ret = avformat_find_stream_info(in_fmt, nullptr)) < 0) {
|
|
|
|
|
err = QString("Couldn't find stream information. ")+av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE);
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
auto outfile = file+"-square.mp4";
|
|
|
|
|
if((ret = avformat_alloc_output_context2(&out_fmt, 0, "mp4", outfile.constData())) < 0) {
|
|
|
|
|
err = QString("avformat_alloc_output_context2 fail. ")+av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE);
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
int vi_idx = -1;
|
|
|
|
|
for(int ss=0; ss<in_fmt->nb_streams; ss++) {
|
|
|
|
|
AVStream *stream = in_fmt->streams[ss];
|
|
|
|
|
AVStream *newStream = avformat_new_stream(out_fmt, 0);
|
|
|
|
|
if((ret = avcodec_parameters_copy(newStream->codecpar, stream->codecpar)) < 0) {
|
|
|
|
|
err = QString("avcodec_parameters_copy fail. ") + av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE);
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
//LOGD("fourcc %s",av_fourcc2str(newStream->codecpar->codec_tag));
|
|
|
|
|
if(vi_idx == -1 && stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) vi_idx = ss;
|
|
|
|
|
}
|
|
|
|
|
if(vi_idx == -1) {
|
|
|
|
|
err = "Didn't find a Video Stream";
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto codecpar = in_fmt->streams[vi_idx]->codecpar;
|
|
|
|
|
qDebug()<<"codec_id"<<codecpar->codec_id<<avcodec_get_name(codecpar->codec_id);
|
|
|
|
|
|
|
|
|
|
auto decoder = avcodec_find_decoder(codecpar->codec_id);
|
|
|
|
|
if(decoder==0) {
|
|
|
|
|
err = "Could not found Video Decoder";
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
de_ctx = avcodec_alloc_context3(decoder);
|
|
|
|
|
avcodec_parameters_to_context(de_ctx, codecpar);
|
|
|
|
|
if(avcodec_open2(de_ctx, decoder, 0) < 0) {
|
|
|
|
|
err = "Could not open Video Codec Ctx";
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
auto sws_ctx = sws_getContext(de_ctx->width, de_ctx->height, de_ctx->pix_fmt, sw, sh, AV_PIX_FMT_ARGB, SWS_FAST_BILINEAR, 0, 0, 0);
|
|
|
|
|
|
|
|
|
|
auto encoder = avcodec_find_encoder(AV_CODEC_ID_H264);
|
|
|
|
|
if(encoder==0) {
|
|
|
|
|
fprintf(stderr, "Codec not found\n");
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
en_ctx = avcodec_alloc_context3(encoder);
|
|
|
|
|
avcodec_parameters_to_context(en_ctx, codecpar);
|
|
|
|
|
if(avcodec_open2(en_ctx, encoder, 0) < 0) {
|
|
|
|
|
err = "Could not open Video Codec Ctx";
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
en_ctx->pix_fmt = AV_PIX_FMT_ARGB;
|
|
|
|
|
en_ctx->bit_rate = dw*dh/150000; //码率 清晰度有关
|
|
|
|
|
en_ctx->width = dw;
|
|
|
|
|
en_ctx->height = dh;
|
|
|
|
|
qDebug()<<"gop_size"<<en_ctx->gop_size;
|
|
|
|
|
qDebug()<<"max_b_frames"<<en_ctx->max_b_frames;
|
|
|
|
|
if (avcodec_open2(en_ctx, encoder, 0) < 0) {
|
|
|
|
|
fprintf(stderr, "Could not open codec\n");
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
avcodec_parameters_from_context(out_fmt->streams[vi_idx]->codecpar, en_ctx);
|
|
|
|
|
|
|
|
|
|
if(out_fmt->flags & AVFMT_NOFILE) qDebug()<<"AVFMT_NOFILE";
|
|
|
|
|
else if((ret = avio_open(&out_fmt->pb, outfile.constData(), AVIO_FLAG_WRITE)) < 0) {
|
|
|
|
|
err = QString("avio_open fail. ")+av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE);
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
if((ret = avformat_write_header(out_fmt, 0)) < 0) {
|
|
|
|
|
err = QString("avformat_write_header fail. ")+av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE);
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto packet = av_packet_alloc();
|
|
|
|
|
auto frm = av_frame_alloc();
|
|
|
|
|
while(1) {
|
|
|
|
|
if((ret = av_read_frame(in_fmt, packet)) < 0) {
|
|
|
|
|
if(ret!=AVERROR_EOF) {
|
|
|
|
|
err = QString("Read packet fail: ")+av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
ret = avcodec_send_packet(de_ctx, 0);
|
|
|
|
|
} else {
|
|
|
|
|
if(packet->stream_index != vi_idx) {
|
|
|
|
|
av_write_frame(out_fmt, packet);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
ret = avcodec_send_packet(de_ctx, packet);
|
|
|
|
|
}
|
|
|
|
|
if(ret < 0) break;
|
|
|
|
|
while((ret = avcodec_receive_frame(de_ctx, frm)) != AVERROR(EAGAIN)) {
|
|
|
|
|
if(ret < 0) {
|
|
|
|
|
if(ret!=AVERROR_EOF) {
|
|
|
|
|
err = QString("Receive frame fail: ")+av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE);
|
|
|
|
|
goto free2;
|
|
|
|
|
}
|
|
|
|
|
ret = avcodec_send_frame(en_ctx, 0);
|
|
|
|
|
} else {
|
|
|
|
|
QImage img(sw, sh, QImage::Format_ARGB32);
|
|
|
|
|
uint8_t *dst[4]{img.bits()};
|
|
|
|
|
int dstStride[4]{img.bytesPerLine()};
|
|
|
|
|
sws_scale(sws_ctx, frm->data, frm->linesize, 0, de_ctx->height, dst, dstStride);
|
|
|
|
|
auto out_frm = av_frame_alloc();
|
|
|
|
|
av_image_alloc(out_frm->data, out_frm->linesize, dw, dh, AV_PIX_FMT_ARGB, 8);
|
|
|
|
|
av_frame_copy_props(out_frm, frm);
|
|
|
|
|
out_frm->width = dw;
|
|
|
|
|
out_frm->height = dh;
|
|
|
|
|
out_frm->format = AV_PIX_FMT_ARGB;
|
|
|
|
|
QImage out_img(out_frm->data[0], dw, dh, out_frm->linesize[0], QImage::Format_ARGB32);
|
|
|
|
|
QPainter painter(&out_img);
|
|
|
|
|
painter.drawImage(pos, img);
|
|
|
|
|
for(int i=1; i<cnt; i++) {
|
|
|
|
|
pos.rx() -= dw;
|
|
|
|
|
pos.ry() += sh;
|
|
|
|
|
painter.drawImage(pos, img);
|
|
|
|
|
}
|
|
|
|
|
ret = avcodec_send_frame(en_ctx, out_frm);
|
|
|
|
|
}
|
|
|
|
|
if(ret < 0) break;
|
|
|
|
|
while((ret = avcodec_receive_packet(en_ctx, packet)) != AVERROR(EAGAIN)) {
|
|
|
|
|
if(ret < 0) {
|
|
|
|
|
if(ret!=AVERROR_EOF) err = QString("Receive frame fail: ")+av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE);
|
|
|
|
|
else {
|
|
|
|
|
av_interleaved_write_frame(out_fmt, 0);
|
|
|
|
|
av_write_trailer(out_fmt);
|
|
|
|
|
}
|
|
|
|
|
goto free2;
|
|
|
|
|
} else av_interleaved_write_frame(out_fmt, packet);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
free2:
|
|
|
|
|
av_frame_free(&frm);
|
|
|
|
|
av_packet_free(&packet);
|
|
|
|
|
sws_freeContext(sws_ctx);
|
|
|
|
|
}
|
|
|
|
|
free:
|
|
|
|
|
avcodec_free_context(&de_ctx);
|
|
|
|
|
avcodec_free_context(&en_ctx);
|
|
|
|
|
avformat_close_input(&in_fmt);
|
|
|
|
|
if(out_fmt) avformat_free_context(out_fmt);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
2022-08-25 18:37:24 +08:00
|
|
|
|
QString Tools::audioInfo(QByteArray url, int64_t *dur) {
|
|
|
|
|
AVFormatContext *fmt_ctx = avformat_alloc_context();
|
|
|
|
|
QString err;
|
|
|
|
|
{
|
|
|
|
|
if(avformat_open_input(&fmt_ctx, url.constData(), nullptr, nullptr) != 0) {
|
|
|
|
|
err = "Couldn't open input stream";
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
if(avformat_find_stream_info(fmt_ctx, nullptr) < 0) {
|
|
|
|
|
err = "Couldn't find stream information";
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
if(dur!=nullptr) *dur = fmt_ctx->duration;
|
|
|
|
|
}
|
|
|
|
|
free:
|
|
|
|
|
avformat_close_input(&fmt_ctx);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
QString Tools::readErrStr(QImageReader::ImageReaderError err) {
|
|
|
|
|
if(err==QImageReader::UnknownError) return "UnknownError";
|
|
|
|
|
if(err==QImageReader::FileNotFoundError) return "FileNotFoundError";
|
|
|
|
|
if(err==QImageReader::DeviceError) return "DeviceError";
|
|
|
|
|
if(err==QImageReader::UnsupportedFormatError) return "UnsupportedFormatError";
|
|
|
|
|
if(err==QImageReader::InvalidDataError) return "InvalidDataError";
|
|
|
|
|
return QString::number(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Tools::fileMd5(QString filePath) {
|
|
|
|
|
QFile file(filePath);
|
|
|
|
|
if(! file.open(QFile::ReadOnly)) return QString();
|
|
|
|
|
QCryptographicHash cryptoHash(QCryptographicHash::Md5);
|
|
|
|
|
if(! cryptoHash.addData(&file)) {
|
|
|
|
|
file.close();
|
|
|
|
|
return QString();
|
|
|
|
|
}
|
|
|
|
|
file.close();
|
|
|
|
|
return QString::fromLatin1(cryptoHash.result().toHex());
|
|
|
|
|
}
|
|
|
|
|
void Tools::mergeFormat(QTextEdit *textEdit, const QTextCharFormat &format) {
|
|
|
|
|
QTextCursor cursor = textEdit->textCursor();
|
|
|
|
|
if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor);
|
|
|
|
|
cursor.mergeCharFormat(format);
|
|
|
|
|
textEdit->mergeCurrentCharFormat(format);
|
|
|
|
|
}
|
|
|
|
|
void Tools::saveImg(const QString& dir, const QFontMetrics& metric, const QFont& font, const QColor& color, QJsonObject& imgs, const QString& str, const QString& name) {
|
|
|
|
|
if(str.isEmpty()) return;
|
|
|
|
|
QImage img(metric.horizontalAdvance(str), metric.lineSpacing(), QImage::Format_ARGB32);
|
|
|
|
|
img.fill(Qt::transparent);
|
|
|
|
|
QPainter painter(&img);
|
|
|
|
|
painter.setFont(font);
|
|
|
|
|
painter.setPen(color);
|
|
|
|
|
QTextOption opt(Qt::AlignCenter);
|
|
|
|
|
opt.setWrapMode(QTextOption::NoWrap);
|
|
|
|
|
painter.drawText(QRectF(0, 0, img.width(), img.height()), str, opt);
|
|
|
|
|
QBuffer buf;
|
|
|
|
|
if(! img.save(&buf, "PNG")) return;
|
|
|
|
|
QCryptographicHash cryptoHash(QCryptographicHash::Md5);
|
|
|
|
|
cryptoHash.addData(buf.data());
|
|
|
|
|
auto md5 = QString::fromLatin1(cryptoHash.result().toHex());
|
|
|
|
|
QFile file(dir+"/"+md5);
|
|
|
|
|
if(! file.open(QFile::WriteOnly)) return;
|
|
|
|
|
file.write(buf.data());
|
|
|
|
|
file.close();
|
|
|
|
|
imgs.insert(name, md5);
|
|
|
|
|
}
|
|
|
|
|
void Tools::saveImg2(const QString& dir, const QFontMetrics& metric, const QFont& font, const QColor& color, QJsonArray& imgs, const QString& str, const QString& name) {
|
|
|
|
|
QJsonObject obj{
|
|
|
|
|
{"name", name},
|
|
|
|
|
{"mime", "image/png"}
|
|
|
|
|
};
|
|
|
|
|
if(! str.isEmpty()) {
|
|
|
|
|
QImage img(metric.horizontalAdvance(str), metric.lineSpacing(), QImage::Format_ARGB32);
|
|
|
|
|
img.fill(Qt::transparent);
|
|
|
|
|
QPainter painter(&img);
|
|
|
|
|
painter.setFont(font);
|
|
|
|
|
painter.setPen(color);
|
|
|
|
|
QTextOption opt(Qt::AlignCenter);
|
|
|
|
|
opt.setWrapMode(QTextOption::NoWrap);
|
|
|
|
|
painter.drawText(QRectF(0, 0, img.width(), img.height()), str, opt);
|
|
|
|
|
QBuffer buf;
|
|
|
|
|
if(img.save(&buf, "PNG")) {
|
|
|
|
|
obj.insert("picWidth", img.width());
|
|
|
|
|
obj.insert("picHeight", img.height());
|
|
|
|
|
QCryptographicHash cryptoHash(QCryptographicHash::Md5);
|
|
|
|
|
cryptoHash.addData(buf.data());
|
|
|
|
|
auto md5 = QString::fromLatin1(cryptoHash.result().toHex());
|
|
|
|
|
QFile file(dir+"/"+md5);
|
|
|
|
|
if(file.open(QFile::WriteOnly)) {
|
|
|
|
|
file.write(buf.data());
|
|
|
|
|
file.close();
|
|
|
|
|
obj.insert("id", md5);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
imgs.append(obj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QBrush Tools::getBrush(const QColor& color) {
|
|
|
|
|
return color.alpha()==0 ? Qt::NoBrush : QBrush(color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Tools::color2Int(const QColor& color) {
|
|
|
|
|
int res = 0;
|
|
|
|
|
res |= (color.red() & 0xFF) << 24;
|
|
|
|
|
res |= (color.green() & 0xFF) << 16;
|
|
|
|
|
res |= (color.blue() & 0xFF) << 8;
|
|
|
|
|
res |= (color.alpha() & 0xFF);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QColor Tools::int2Color(int value) {
|
|
|
|
|
QColor res;
|
|
|
|
|
res.setRed ((value >> 24) & 0xFF);
|
|
|
|
|
res.setGreen((value >> 16) & 0xFF);
|
|
|
|
|
res.setBlue ((value >> 8) & 0xFF);
|
|
|
|
|
res.setAlpha((value ) & 0xFF);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Tools::selectStr(bool f, const QString &s0, const QString &s1) {
|
|
|
|
|
return f ? s0 : s1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Tools::convertFileSize(const qint64 & bytes){
|
|
|
|
|
float num = bytes;
|
|
|
|
|
QStringList list;
|
|
|
|
|
list << "KB" << "MB" << "GB" << "TB";
|
|
|
|
|
|
|
|
|
|
QStringListIterator i(list);
|
|
|
|
|
QString unit("bytes");
|
|
|
|
|
|
|
|
|
|
while(num >= 1024.0 && i.hasNext())
|
|
|
|
|
{
|
|
|
|
|
unit = i.next();
|
|
|
|
|
num /= 1024.0;
|
|
|
|
|
}
|
|
|
|
|
return QString().setNum(num,'f',2)+" "+unit;
|
|
|
|
|
}
|
|
|
|
|
QString Tools::styleSheet() {
|
|
|
|
|
QStringList qsses = QDir(":/qss").entryList(QStringList{"*.css"});
|
|
|
|
|
std::sort(qsses.begin(), qsses.end(), [](const QString &a, const QString &b) {
|
|
|
|
|
return a < b;
|
|
|
|
|
});
|
|
|
|
|
QString qss;
|
|
|
|
|
foreach(QString qss_name, qsses) {
|
|
|
|
|
QFile f(":/qss/" + qss_name);
|
|
|
|
|
if(f.exists() && f.open(QFile::ReadOnly)) {
|
|
|
|
|
qss += f.readAll();
|
|
|
|
|
f.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return qss;
|
|
|
|
|
}
|