Commit eca7450b authored by captainwong's avatar captainwong

test qt headers ok

parent 780de4ef
#pragma once
#include "config.h"
#include <sys/types.h> // for off_t
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <assert.h>
#include <algorithm>
#include "cast.h"
#include "noncopyable.h"
#include "stringpiece.h"
namespace jlib
{
namespace FileUtil
{
//! file size < 64KB
class ReadSmallFile : noncopyable
{
public:
ReadSmallFile(StringArg filename)
: fd_(::fopen(filename.c_str(), "r"))
, err_(0)
{
buf_[0] = '\0';
if (fd_ < 0) {
err_ = errno;
}
}
~ReadSmallFile() {
if (fd_ >= 0) {
::fclose(fd_);
}
}
template <typename StringType>
int readToString(int maxSize, StringType* content, int64_t* fileSize, int64_t* modifyTime, int64_t* createTime) {
static_assert(sizeof(off_t) == 8, "sizeof(off_t) != 8");
assert(content);
int err = err_;
if (fd_ >= 0) {
content->clear();
if (fileSize) {
struct stat statbuf;
if (::fstat(fd_, &statbuf) == 0) {
if (S_IFREG & (statbuf.st_mode)) {
*fileSize = statbuf.st_size;
content->reserve(static_cast<int>(std::min(implicit_cast<int64_t>(maxSize), *fileSize)));
} else if (S_IFDIR & statbuf.st_mode) {
err = EISDIR;
}
if (modifyTime) {
*modifyTime = statbuf.st_mtime;
}
if (createTime) {
*createTime = statbuf.st_ctime;
}
} else {
err = errno
}
}
while (content->size() < implicit_cast<size_t>(maxSize)) {
size_t toRead = std::min(implicit_cast<size_t>(maxSize) - content->size(), sizeof(buf_));
size_t n = ::fread(buf_, 1, toRead, fd_);
if (n > 0) {
content->append(buf_, n);
} else {
if (n < 0) {
err = errno;
}
break;
}
}
}
return err;
}
int readToBuffer(int* size) {
int err = err_;
if (fd_ >= 0) {
size_t n = ::fread(buf_, 1, sizeof(buf_) - 1, fd_);
if (n >= 0) {
if (size) {
*size = static_cast<int>(n);
}
buf_[n] = '\0';
} else {
err = errno;
}
}
return err;
}
const char* buffer() const { return buf_; }
static constexpr int BUFFER_SIZE = 64 * 1024;
private:
int fd_;
int err_;
char buf_[BUFFER_SIZE];
};
template <typename String>
int readFile(StringArg filename, int maxSize, String* content, int64_t* fileSize = nullptr, int64_t* modifyTime = nullptr, int64_t* createTime = nullptr)
{
ReadSmallFile file(filename);
return file.readToString(maxSize, content, fileSize, modifyTime, createTime);
}
//! not thread safe
class AppendToFile : noncopyable
{
public:
explicit AppendToFile(StringArg filename)
{
}
static constexpr int BUFFER_SIZE = 64 * 1024;
private:
size_t write(const char* logLine, size_t len) {
}
FILE* fp_;
char buf_[BUFFER_SIZE];
off_t writtenBytes_;
};
}
}
#pragma once
#include "config.h"
#include "noncopyable.h"
#include <mutex>
#include <memory>
#include <string>
#include <assert.h>
#include <sys/types.h> // for off_t
namespace jlib
{
namespace FileUtil
{
class AppendFile;
}
class LogFile : noncopyable
{
public:
LogFile(const std::string& basename, off_t rollSize, bool threadSafe = true, int flushInterval = 3, int checkEveryN = 1024)
: basename_(basename)
, rollSize_(rollSize)
, flushInterval_(flushInterval)
, checkEveryN_(checkEveryN)
, count_(0)
, mutex_(threadSafe ? std::make_unique<std::mutex>() : nullptr)
, startOfPeriod_(0)
, lastRoll_(0)
, lastFlush_(0)
{
assert(basename_.find('/') == std::string::npos);
assert(basename_.find('\\') == std::string::npos);
rollFile();
}
~LogFile() = default;
void append(const char* logLine, int len) {
if (mutex_) {
std::lock_guard<std::mutex> lg(*mutex_);
appendUnlocked(logLine, len);
} else {
appendUnlocked(logLine, len);
}
}
void flush() {
if (mutex_) {
std::lock_guard<std::mutex> lg(*mutex_);
file_->flush();
} else {
file_->flush();
}
}
bool rollFile() {
}
protected:
void appendUnlocked(const char* logLine, int len) {
file_->append(logLine, len);
}
static std::string getLogFileName(const std::string& basename, time_t now) {
}
private:
const std::string basename_;
const off_t rollSize_;
const int flushInterval_;
const int checkEveryN_;
int count_;
std::unique_ptr<std::mutex> mutex_;
time_t startOfPeriod_;
time_t lastRoll_;
time_t lastFlush_;
std::unique_ptr<FileUtil::AppendFile> file_;
static constexpr int ROLL_PER_SECONDS = 24 * 60 * 60;
};
}
#include "ThreadCtrl.h"
JLIB_QT_NAMESPACE_BEGIN
ThreadCtrl::ThreadCtrl(QObject* parent, int proto_type)
: QThread(parent)
, proto_type_(proto_type)
{
}
ThreadCtrl::~ThreadCtrl()
{
}
void ThreadCtrl::run()
{
if (worker_) {
result_code_ = worker_();
}
emit sig_done(tag_, result_code_);
}
JLIB_QT_NAMESPACE_END
#pragma once
#include "../qt_global.h"
#include <QThread>
#include "../Model/ThreadModel.h"
#include <thread>
namespace jlib
{
namespace qt
{
JLIB_QT_NAMESPACE_BEGIN
class ThreadCtrl : public QThread
{
Q_OBJECT
public:
ThreadCtrl(QObject *parent, ThreadWorker worker)
: QThread(parent)
, worker_(worker)
{
}
ThreadCtrl(QObject* parent, int proto_type = -1);
~ThreadCtrl();
~ThreadCtrl() {}
void setWorker(ThreadWorker worker) { worker_ = worker; }
void set_worker(ThreadWorker worker) { worker_ = worker; }
void setParam(void* input = nullptr, void* output = nullptr) {
input_ = input;
output_ = output;
}
void set_tag(int tag) { tag_ = tag; }
int get_tag() const { return tag_; }
void setTag(int tag) { tag_ = tag; }
int getTag() const { return tag_; }
protected:
virtual void run() override {
std::error_code result;
if (worker_) {
result = worker_();
}
emit sig_ready(tag_, result);
}
virtual void run() override;
signals:
void sig_ready(int tag, std::error_code result);
void sig_progress(int tag, jlib::qt::ThreadProgress progress);
void sig_progress(int tag, ThreadProgress progress);
void sig_done(int tag, int result_code);
private:
ThreadWorker worker_ = {};
int proto_type_ = -1;
int result_code_ = -1;
void* input_ = nullptr;
void* output_ = nullptr;
int tag_ = 0;
int tag_ = -1;
};
}
}
JLIB_QT_NAMESPACE_END
#pragma once
//#include <system_error>
#include <QString>
#include <functional>
......@@ -8,8 +9,7 @@ namespace jlib
namespace qt
{
typedef std::function<std::error_code(void)> ThreadWorker;
typedef std::function<int(void)> ThreadWorker;
struct ThreadProgress {
int pos = 0;
......@@ -24,5 +24,5 @@ typedef std::function<void(ThreadProgress)> ThreadProgressCB;
}
}
Q_DECLARE_METATYPE(std::error_code)
//Q_DECLARE_METATYPE(std::error_code)
Q_DECLARE_METATYPE(jlib::qt::ThreadProgress)
QMAKE_CXX.INCDIRS = \
"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.24.28314\\ATLMFC\\include" \
"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.24.28314\\include" \
"C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8\\include\\um" \
"C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\ucrt" \
"C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\shared" \
"C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\um" \
"C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\winrt" \
"C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\cppwinrt"
QMAKE_CXX.LIBDIRS = \
"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.24.28314\\ATLMFC\\lib\\x86" \
"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.24.28314\\lib\\x86" \
"C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8\\lib\\um\\x86" \
"C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.18362.0\\ucrt\\x86" \
"C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.18362.0\\um\\x86"
QMAKE_CXX.QT_COMPILER_STDCXX = 199711L
QMAKE_CXX.QMAKE_MSC_VER = 1924
QMAKE_CXX.QMAKE_MSC_FULL_VER = 192428314
QMAKE_CXX.COMPILER_MACROS = \
QT_COMPILER_STDCXX \
QMAKE_MSC_VER \
QMAKE_MSC_FULL_VER
CONFIG += plugin debug_and_release
TARGET = $$qtLibraryTarget(barrulerplugin)
TEMPLATE = lib
HEADERS = barrulerplugin.h
SOURCES = barrulerplugin.cpp
RESOURCES = icons.qrc
LIBS += -L.
greaterThan(QT_MAJOR_VERSION, 4) {
QT += designer
} else {
CONFIG += designer
}
target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS += target
include(barruler.pri)
This diff is collapsed.
#include "barruler.h"
BarRuler::BarRuler(QWidget *parent) :
QWidget(parent)
{
}
#ifndef BARRULER_H
#define BARRULER_H
#include <QWidget>
#include "../../../util/micro_getter_setter.h"
class BarRuler : public QWidget
{
Q_OBJECT
Q_PROPERTY(double minValue READ getMinValue WRITE setMinValue)
Q_PROPERTY(double maxValue READ getMaxValue WRITE setMaxValue)
Q_PROPERTY(double value READ getValue WRITE setValue)
Q_PROPERTY(int precision READ getPrecision WRITE setPrecision)
Q_PROPERTY(int longStep READ getLongStep WRITE setLongStep)
Q_PROPERTY(int shortStep READ getShortStep WRITE setShortStep)
Q_PROPERTY(int space READ getSpace WRITE setSpace)
Q_PROPERTY(bool animation READ getAnimation WRITE setAnimation)
Q_PROPERTY(double animationStep READ getAnimationStep WRITE setAnimationStep)
Q_PROPERTY(QColor bgColorStart READ getBgColorStart WRITE setBgColorStart)
Q_PROPERTY(QColor bgColorEnd READ getBgColorEnd WRITE setBgColorEnd)
Q_PROPERTY(QColor lineColor READ getLineColor WRITE setLineColor)
Q_PROPERTY(QColor barBgColor READ getBarBgColor WRITE setBarBgColor)
Q_PROPERTY(QColor barColor READ getBarColor WRITE setBarColor)
//! 最小值
DECLARE_PRI_MDI_PUB_G(double, minValue, getMinValue)
//! 最大值
DECLARE_PRI_MDI_PUB_G(double, maxValue, getMaxValue)
//! 目标值
DECLARE_PRI_MDI_PUB_G(double, value, getValue)
//! 精度,小数点后几位
DECLARE_PRI_MDI_PUB_G(int, precision, getPrecision)
//! 长线条等分步长
DECLARE_PRI_MDI_PUB_G(int, longStep, getLongStep)
//! 短线条等分步长
DECLARE_PRI_MDI_PUB_G(int, shortStep, getShortStep)
//! 间距
DECLARE_PRI_MDI_PUB_G(int, space, getSpace)
//! 动画效果
DECLARE_PRI_MDI_PUB_G(bool, animation, getAnimation)
//! 动画步长
DECLARE_PRI_MDI_PUB_G(double, animationStep, getAnimationStep)
//! 背景渐变开始
DECLARE_PRI_MDI_PUB_G(QColor, bgColorStart, getBgColorStart)
//! 背景渐变结束
DECLARE_PRI_MDI_PUB_G(QColor, bgColorEnd, getBgColorEnd)
//! 线条颜色
DECLARE_PRI_MDI_PUB_G(QColor, lineColor, getLineColor)
//! 柱背景色
DECLARE_PRI_MDI_PUB_G(QColor, barBgColor, getBarBgColor)
//! 柱颜色
DECLARE_PRI_MDI_PUB_G(QColor, barColor, getBarColor)
public:
explicit BarRuler(QWidget *parent = 0);
signals:
void valueChanged(double value);
public slots:
//! 设置最大最小值-范围值
void setRange(double minValue, double maxValue);
void setRange(int minValue, int maxValue);
//! 设置最大最小值
void setMinValue(double minValue);
void setMaxValue(double maxValue);
//! 设置目标值
void setValue(double value);
void setValue(int value);
//! 设置精确度
void setPrecision(int precision);
//! 设置线条等分步长
void setLongStep(int longStep);
void setShortStep(int shortStep);
//! 设置间距
void setSpace(int space);
//! 设置是否启用动画显示
void setAnimation(bool animation);
//! 设置动画显示的步长
void setAnimationStep(double animationStep);
//! 设置背景颜色
void setBgColorStart(const QColor &bgColorStart);
void setBgColorEnd(const QColor &bgColorEnd);
//! 设置线条颜色
void setLineColor(const QColor &lineColor);
//! 设置柱状颜色
void setBarBgColor(const QColor &barBgColor);
void setBarColor(const QColor &barColor);
protected:
void paintEvent(QPaintEvent *);
void drawBg(QPainter *painter);
void drawRuler(QPainter *painter);
void drawBarBg(QPainter *painter);
void drawBar(QPainter *painter);
private slots:
void updateValue();
private:
//! 是否倒退
bool reverse;
//! 当前值
double currentValue;
//! 定时器绘制动画
QTimer *timer;
//! 柱状图区域
QRectF barRect;
};
#endif
HEADERS += barruler.h
SOURCES += barruler.cpp
#include "barruler.h"
#include "barrulerplugin.h"
#include <QtPlugin>
BarRulerPlugin::BarRulerPlugin(QObject *parent)
: QObject(parent)
{
m_initialized = false;
}
void BarRulerPlugin::initialize(QDesignerFormEditorInterface * /* core */)
{
if (m_initialized)
return;
// Add extension registrations, etc. here
m_initialized = true;
}
bool BarRulerPlugin::isInitialized() const
{
return m_initialized;
}
QWidget *BarRulerPlugin::createWidget(QWidget *parent)
{
return new BarRuler(parent);
}
QString BarRulerPlugin::name() const
{
return QLatin1String("BarRuler");
}
QString BarRulerPlugin::group() const
{
return QLatin1String("");
}
QIcon BarRulerPlugin::icon() const
{
return QIcon();
}
QString BarRulerPlugin::toolTip() const
{
return QLatin1String("");
}
QString BarRulerPlugin::whatsThis() const
{
return QLatin1String("");
}
bool BarRulerPlugin::isContainer() const
{
return false;
}
QString BarRulerPlugin::domXml() const
{
return QLatin1String("<widget class=\"BarRuler\" name=\"barRuler\">\n</widget>\n");
}
QString BarRulerPlugin::includeFile() const
{
return QLatin1String("barruler.h");
}
#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2(barrulerplugin, BarRulerPlugin)
#endif // QT_VERSION < 0x050000
#ifndef BARRULERPLUGIN_H
#define BARRULERPLUGIN_H
#include <QDesignerCustomWidgetInterface>
class BarRulerPlugin : public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface)
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface")
#endif // QT_VERSION >= 0x050000
public:
BarRulerPlugin(QObject *parent = 0);
bool isContainer() const;
bool isInitialized() const;
QIcon icon() const;
QString domXml() const;
QString group() const;
QString includeFile() const;
QString name() const;
QString toolTip() const;
QString whatsThis() const;
QWidget *createWidget(QWidget *parent);
void initialize(QDesignerFormEditorInterface *core);
private:
bool m_initialized;
};
#endif
This diff is collapsed.
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Generated Files">
<UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier>
<Extensions>cpp;c;cxx;moc;h;def;odl;idl;res;</Extensions>
</Filter>
<Filter Include="Generated Files">
<UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier>
<Extensions>cpp;c;cxx;moc;h;def;odl;idl;res;</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
<Extensions>qrc;*</Extensions>
<ParseFiles>false</ParseFiles>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
<Extensions>qrc;*</Extensions>
<ParseFiles>false</ParseFiles>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="barruler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="barrulerplugin.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="barruler.h">
<Filter>Header Files</Filter>
</CustomBuild>
<CustomBuild Include="barrulerplugin.h">
<Filter>Header Files</Filter>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<ClCompile Include="debug\moc_barruler.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="release\moc_barruler.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="debug\moc_barrulerplugin.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="release\moc_barrulerplugin.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
<CustomBuild Include="debug\moc_predefs.h.cbt">
<Filter>Generated Files</Filter>
</CustomBuild>
<CustomBuild Include="release\moc_predefs.h.cbt">
<Filter>Generated Files</Filter>
</CustomBuild>
<ClCompile Include="debug\qrc_icons.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="release\qrc_icons.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="icons.qrc">
<Filter>Resource Files</Filter>
</CustomBuild>
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerEnvironment>PATH=C:\Qt\Qt5.9.8\5.9.8\msvc2015\bin%3b$(PATH)</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LocalDebuggerEnvironment>PATH=C:\Qt\Qt5.9.8\5.9.8\msvc2015\bin%3b$(PATH)</LocalDebuggerEnvironment>
</PropertyGroup>
</Project>
\ No newline at end of file
<RCC>
<qresource prefix="/" >
</qresource>
</RCC>
QMAKE_CXX.INCDIRS = \
"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.16.27023\\ATLMFC\\include" \
"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.16.27023\\include" \
"C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.6.1\\include\\um" \
"C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\ucrt" \
"C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\shared" \
"C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\um" \
"C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\winrt" \
"C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\cppwinrt"
QMAKE_CXX.LIBDIRS = \
"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.16.27023\\ATLMFC\\lib\\x86" \
"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.16.27023\\lib\\x86" \
"C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.6.1\\lib\\um\\x86" \
"C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.18362.0\\ucrt\\x86" \
"C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.18362.0\\um\\x86"
QMAKE_CXX.QT_COMPILER_STDCXX = 199711L
QMAKE_CXX.QMAKE_MSC_VER = 1916
QMAKE_CXX.QMAKE_MSC_FULL_VER = 191627034
QMAKE_CXX.COMPILER_MACROS = \
QT_COMPILER_STDCXX \
QMAKE_MSC_VER \
QMAKE_MSC_FULL_VER
......@@ -6,9 +6,27 @@
#endif //_WIN32
#define QDEBUG_FILE_LINE_STREAM "[" << __FUNCTION__ << "ln" << __LINE__ << "]: "
#define QDEBUG_FILE_LINE_VER (QString("[") + __FUNCTION__ + " ln" + QString::number(__LINE__) + "]: ")
#define JLIBQT_QDEBUG_FILE_LINE_STREAM "[" << __FUNCTION__ << "ln" << __LINE__ << "]: "
#define JLIBQT_QDEBUG_FILE_LINE_VALUE (QString("[") + __FUNCTION__ + " ln" + QString::number(__LINE__) + "]: ")
#define MYQDEBUG qDebug() << QDEBUG_FILE_LINE_STREAM
#define MYQWARN qWarning() << QDEBUG_FILE_LINE_STREAM
#define MYQCRITICAL qCritical() << QDEBUG_FILE_LINE_STREAM
\ No newline at end of file
#define MYQDEBUG qDebug() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQWARN qWarning() << JLIBQT_QDEBUG_FILE_LINE_STREAM
#define MYQCRITICAL qCritical() << JLIBQT_QDEBUG_FILE_LINE_STREAM
//! 弹窗报告行号开关
#define JLIBQT_SHOW_LINE 0
//! 当行号大于下方定义的值时,弹窗报告行号,否则忽略。可在多个cpp文件分别定义不同的值。
// #define JLIBQT_SHOW_MSGBOX_AFTER_LINE 1
#if JLIBQT_SHOW_LINE
#ifdef JLIBQT_SHOW_MSGBOX_AFTER_LINE
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER if(__LINE__ >= SHOW_MSGBOX_AFTER_LINE) { MessageBoxW(nullptr, (std::wstring(__FILEW__) + L":" + std::to_wstring(__LINE__)).data(), L"Test", 0); }
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER_WITH_TITLE(title) if(__LINE__ >= SHOW_MSGBOX_AFTER_LINE) { MessageBoxW(nullptr, (std::wstring(__FILEW__) + L":" + std::to_wstring(__LINE__)).data(), title, 0); }
#else
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER { MessageBoxW(nullptr, (std::wstring(__FILEW__) + L":" + std::to_wstring(__LINE__)).data(), L"Test", 0); }
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER_WITH_TITLE(title) { MessageBoxW(nullptr, (std::wstring(__FILEW__) + L":" + std::to_wstring(__LINE__)).data(), title, 0); }
#endif
#else
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER
#define JLIBQT_SHOW_MSGBOX_LINE_NUMBER_WITH_TITLE(title)
#endif
#pragma once
#include "qt_global.h"
// if not defined, disable redirect
// if defined, you must include log2.h before include this file
#define REDIRECT_QT_OUTPUT_TO_LOG
// #define REDIRECT_QT_OUTPUT_TO_LOG
#ifdef REDIRECT_QT_OUTPUT_TO_LOG
#ifdef JLIBQT_REDIRECT_QT_OUTPUT_TO_JLOG
#ifndef JLIB_LOG2_ENABLED
#error 'You must include <jlib/log2.h> first!'
#else // has JLIB_LOG2_ENABLED
static inline void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
JLIBQT_NAMESPACE_BEGIN
static inline void JLIBQT_MessageOutputFunc(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
using namespace jlib;
QByteArray localMsg = msg.toLocal8Bit();
......@@ -37,5 +39,6 @@ static inline void myMessageOutput(QtMsgType type, const QMessageLogContext &con
break;
}
}
JLIBQT_NAMESPACE_END
#endif // JLIB_LOG2_ENABLED
#endif // REDIRECT_QT_OUTPUT_TO_LOG
#endif // JLIBQT_REDIRECT_QT_OUTPUT_TO_JLOG
#pragma once
#include "qt_global.h"
#include <QDir>
#include <QCoreApplication>
#include <QString>
#include <QDateTime>
#include <QStandardPaths>
namespace jlib {
namespace qt {
JLIBQT_NAMESPACE_BEGIN
static const auto FILE_TIME_FORMAT = "yyyy-MM-dd_hh-mm-ss";
static const auto JLIBQT_FILE_TIME_FORMAT = "yyyy-MM-dd_hh-mm-ss";
struct PathHelper
struct PathHelper
{
static inline bool mkpath(const QString& path) {
QDir dir;
return dir.exists(path) ? true : dir.mkpath(path);
QDir dir; return dir.exists(path) ? true : dir.mkpath(path);
}
static inline QString program() {
struct Helper {
Helper() {
QDir dir(QCoreApplication::applicationDirPath());
dir.cdUp();
path = dir.absolutePath();
}
QString path = {};
};
static Helper helper;
return helper.path;
static inline QString currentTimeString() {
return QDateTime::currentDateTime().toString(JLIBQT_FILE_TIME_FORMAT);
}
static inline QString bin() {
return program() + "/bin";
}
virtual ~PathHelper() {}
virtual QString program() const { return programPath_; }
virtual QString bin() const { return program() + "/bin"; }
virtual QString data() const { return program() + "/data"; }
virtual QString log() const { return program() + "/log"; }
virtual QString dumps() const { return program() + "/dumps"; }
virtual QString config() const { return data() + "/config"; }
virtual QString db() const { return data() + "/db"; }
static inline QString log() {
return program() + "/log";
}
protected:
// disable constructor
explicit PathHelper() {}
QString programPath_ = {};
};
static inline QString sdk() {
return program() + "/sdks";
struct AutoSwithToBin {
AutoSwithToBin(PathHelper* helper) : helper(helper) {}
AutoSwithToBin(PathHelper* helper, const QString& path) : helper(helper) {
QDir().setCurrent(path);
}
static inline QString data() {
return program() + "/data";
~AutoSwithToBin() {
if (helper) { QDir().setCurrent(helper->bin()); }
}
static inline QString config() {
return data() + "/config";
}
PathHelper* helper = nullptr;
};
static inline QString db() {
return data() + "/db";
/*
* @brief 路径辅助类,数据保存在安装目录,程序和dll在bin文件夹
* @note 大致结构树为:
* @note |-- program-install-dir
* @note | |-- bin
* @note | | |-- program.exe
* @note | | |-- *.dlls
* @note | |-- dumps
* @note | |-- log
* @note | |-- data
* @note | |-- config
* @note | |-- db
*/
struct PathHelperLocal : PathHelper
{
PathHelperLocal() : PathHelper() {
struct Helper {
Helper() {
QDir dir(QCoreApplication::applicationDirPath());
dir.cdUp(); path = dir.absolutePath();
}
QString path = {};
};
static Helper helper;
programPath_ = helper.path;
}
};
static inline QString pic() {
return data() + "/pic";
}
static inline QString rec() {
return data() + "/rec";
/*
* @brief 路径辅助类,数据保存在安装目录,程序和dll也在安装目录
* @note 大致结构树为:
* @note |-- program-install-dir
* @note | |-- dumps
* @note | |-- log
* @note | |-- data
* @note | | |-- config
* @note | | |-- db
* @note | |-- program.exe
* @note | |-- *.dlls
*/
struct PathHelperLocalWithoutBin : PathHelper
{
PathHelperLocalWithoutBin() : PathHelper() {
struct Helper {
Helper() {
QDir dir(QCoreApplication::applicationDirPath());
path = dir.absolutePath();
}
QString path = {};
};
static Helper helper;
programPath_ = helper.path;
}
static inline QString currentTimeString() {
return QDateTime::currentDateTime().toString(FILE_TIME_FORMAT);
}
virtual QString bin() const override { return program(); }
};
struct AutoSwithToBin {
AutoSwithToBin() {}
/*
* @brief 路径辅助类,数据保存在其他可写目录,如 C:/Users/[USER]/AppData/Roaming
* @note 在调用此类之前先调用 QCoreApplication::setOrganizationName("your-organization-name");
* @note 大致结构树为:
* @note |-- program-install-dir
* @note | |-- bin
* @note | | |-- program.exe
* @note | | |-- *.dlls
* @note
* @note |-- writable-dir
* @note | |-- your-organization-name
* @note | | |-- program-name
* @note | | |-- log
* @note | | |-- dumps
* @note | | |-- config
* @note | | |-- db
*/
struct PathHelperDataSeperated : PathHelperLocal
{
PathHelperDataSeperated() : PathHelperLocal() {}
AutoSwithToBin(const QString& path) {
QDir().setCurrent(path);
virtual QString data() const override {
return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
}
virtual QString log() const override { return data() + "/log"; }
virtual QString dumps() const override { return data() + "/dumps"; }
virtual QString config() const override { return data() + "/config"; }
virtual QString db() const override { return data() + "/db"; }
};
~AutoSwithToBin() {
QDir().setCurrent(PathHelper::bin());
/*
* @brief 路径辅助类,数据保存在其他可写目录,如 C:/Users/[USER]/AppData/Roaming
* @note 在调用此类之前先调用 QCoreApplication::setOrganizationName("your-organization-name");
* @note 大致结构树为:
* @note |-- program-install-dir
* @note | |-- program.exe
* @note | |-- *.dlls
* @note
* @note |-- writable-dir
* @note | |-- your-organization-name
* @note | | |-- program-name
* @note | | |-- log
* @note | | |-- dumps
* @note | | |-- config
* @note | | |-- db
*/
struct PathHelperDataSeperatedWithoutBin : PathHelperLocalWithoutBin
{
PathHelperDataSeperatedWithoutBin() : PathHelperLocalWithoutBin() {}
virtual QString data() const override {
return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
}
virtual QString log() const override { return data() + "/log"; }
virtual QString dumps() const override { return data() + "/dumps"; }
virtual QString config() const override { return data() + "/config"; }
virtual QString db() const override { return data() + "/db"; }
};
} // end of namespace qt
} // end of namespace jlib
JLIBQT_NAMESPACE_END
......@@ -353,6 +353,28 @@ QCheckBox::indicator:unchecked
}
)";
static const auto check_box_48px = R"(
QCheckBox
{
font-size: 16px;
color: white;
}
QCheckBox::indicator
{
width: 48px;
height: 48px;
}
QCheckBox::indicator:checked
{
image: url(:/Skin/checkbox/checked_checkbox_48px.png);
}
QCheckBox::indicator:unchecked
{
image: url(:/Skin/checkbox/unchecked_checkbox_48px.png);
}
)";
} // end of namespace def_style_sheets
......
......@@ -45,9 +45,9 @@ static inline void showInGraphicalShell(const QString &pathIn) {
static inline bool warn_if_load_pixmap_failed(QPixmap& pixmap, QString icon_path, QString file_line)
{
if (!QDir().isAbsolutePath(icon_path)) {
/*if (!QDir().isAbsolutePath(icon_path)) {
icon_path = PathHelper::program() + "/" + icon_path;
}
}*/
if (!pixmap.load(icon_path) && !pixmap.load(icon_path, "png")) {
qCritical() << file_line << "load pixmap failed: " << icon_path;
......@@ -57,7 +57,7 @@ static inline bool warn_if_load_pixmap_failed(QPixmap& pixmap, QString icon_path
return true;
}
#define LOAD_PIXMAP_EX(icon_path) jlib::qt::warn_if_load_pixmap_failed(pixmap, icon_path, QDEBUG_FILE_LINE_VER)
#define LOAD_PIXMAP_EX(icon_path) jlib::qt::warn_if_load_pixmap_failed(pixmap, icon_path, JLIBQT_QDEBUG_FILE_LINE_VALUE)
static QIcon icon_from_path(QString path, QSize icon_sz) {
QPixmap pixmap;
......
#include "BgColorBtn.h"
#include <jlib/qt/QtStylesheet.h>
namespace HBVideoPlatform {
namespace common {
BgColorBtn::BgColorBtn(QWidget *parent)
: QPushButton(parent)
{
connect(this, SIGNAL(clicked()), this, SLOT(slot_clicked()));
}
BgColorBtn::~BgColorBtn()
{
}
void BgColorBtn::set_btn_attr(QColor bg_normal, QColor bg_suspend, QColor font_color, unsigned int font_sz)
{
bg_normal_ = bg_normal;
bg_suspend_ = bg_suspend;
font_color_ = font_color;
font_sz_ = font_sz;
set_normal_attr();
}
void BgColorBtn::enterEvent(QEvent * e)
{
if (!isEnabled() || (parent() && !parentWidget()->isEnabled()))return;
set_mouse_enter_attr();
setCursor(QCursor(Qt::PointingHandCursor));
}
void BgColorBtn::leaveEvent(QEvent * e)
{
if (!isEnabled() || (parent() && !parentWidget()->isEnabled()))return;
set_normal_attr();
setCursor(QCursor(Qt::ArrowCursor));
}
void BgColorBtn::set_normal_attr()
{
set_attr(bg_normal_, font_color_, font_sz_);
}
void BgColorBtn::set_mouse_enter_attr()
{
set_attr(bg_suspend_, font_color_, font_sz_);
}
void BgColorBtn::set_attr(QColor bg_color, QColor font_color, unsigned int font_sz)
{
setStyleSheet(jlib::qt::build_style(bg_color, font_color, font_sz));
}
void BgColorBtn::slot_clicked()
{
if (tag_ != -1) {
emit sig_clicked(tag_);
}
}
}
}
#pragma once
#include <QPushButton>
#include "../QtStylesheet.h"
namespace jlib
{
namespace qt
{
namespace HBVideoPlatform {
namespace common {
class BgColorBtn : public QPushButton
{
Q_OBJECT
public:
BgColorBtn(QWidget *parent = nullptr)
: QPushButton(parent) {
connect(this, SIGNAL(clicked()), this, SLOT(slot_clicked()));
}
virtual ~BgColorBtn() {}
BgColorBtn(QWidget *parent = nullptr);
~BgColorBtn();
void set_btn_attr(QColor bg_normal, QColor bg_suspend, QColor font_color, unsigned int font_sz) {
bg_normal_ = bg_normal;
bg_suspend_ = bg_suspend;
font_color_ = font_color;
font_sz_ = font_sz;
set_normal_attr();
}
void set_btn_attr(QColor bg_normal, QColor bg_suspend, QColor font_color, unsigned int font_sz);
void set_tag(int tag) { tag_ = tag; }
int tag() const { return tag_; }
......@@ -39,28 +25,13 @@ private slots:
void slot_clicked();
protected:
virtual void enterEvent(QEvent* e) override {
if (!isEnabled() || (parent() && !parentWidget()->isEnabled()))return;
set_mouse_enter_attr();
setCursor(QCursor(Qt::PointingHandCursor));
}
virtual void leaveEvent(QEvent* e) override {
if (!isEnabled() || (parent() && !parentWidget()->isEnabled()))return;
set_normal_attr();
setCursor(QCursor(Qt::ArrowCursor));
}
virtual void enterEvent(QEvent* e) override;
virtual void leaveEvent(QEvent* e) override;
private:
void set_normal_attr() {
set_attr(bg_normal_, font_color_, font_sz_);
}
void set_mouse_enter_attr() {
set_attr(bg_suspend_, font_color_, font_sz_);
}
void set_attr(QColor bg_color, QColor font_color, unsigned int font_sz) {
setStyleSheet(build_style(bg_color, font_color, font_sz));
}
void set_normal_attr();
void set_mouse_enter_attr();
void set_attr(QColor bg_color, QColor font_color, unsigned int font_sz);
private:
QColor bg_normal_ = {};
......@@ -71,14 +42,5 @@ private:
int tag_ = -1;
};
inline void BgColorBtn::slot_clicked()
{
if (tag_ != -1) {
emit sig_clicked(tag_);
}
}
} // namespace qt
} // namespace jlib
}
#include "HttpDlg.h"
#include <qmovie.h>
#include <qnetworkaccessmanager.h>
#include <qnetworkreply.h>
#include <jlib/qt/QtPathHelper.h>
#include <jlib/qt/QtUtils.h>
#include <jlib/qt/QtStylesheet.h>
#include "../Model/HttpDlgErrorCode.h"
using namespace jlib::qt;
namespace HBVideoPlatform {
namespace common {
HttpDlg::HttpDlg(QWidget *parent, HttpDlgViewSize sz, int timeout)
: QDialog(parent)
, sz_(sz)
, time_out_sec_(timeout)
{
setWindowModality(Qt::WindowModal);
setWindowFlags(Qt::FramelessWindowHint);
if (!parent) {
setAttribute(Qt::WA_TranslucentBackground);
}
if (sz == sz_small) {
setFixedSize(200, 200);
} else {
setFixedSize(630, 637);
}
label_ = new QLabel(this);
label_->resize(width(), height());
label_->move(0, 0);
elapse_ = new QLabel(this);
elapse_->resize(180, 80);
elapse_->move((width() - elapse_->width()) / 2, (height() - elapse_->height()) / 2);
elapse_->setStyleSheet(build_style(Qt::darkYellow, 64));
elapse_->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
//elapse_->hide();
parent ? center_to_parent(this, parent) : center_to_desktop(this);
mgr = new QNetworkAccessManager(this);
}
HttpDlg::~HttpDlg()
{
}
void HttpDlg::get(const QUrl& url)
{
if (connection_) {
disconnect(connection_);
}
connection_ = connect(mgr, &QNetworkAccessManager::finished, this, &HttpDlg::onFinished);
reply_ = mgr->get(QNetworkRequest(url));
run();
}
void HttpDlg::post(const QUrl & url)
{
if (connection_) {
disconnect(connection_);
}
connection_ = connect(mgr, &QNetworkAccessManager::finished, this, &HttpDlg::onFinished);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
reply_ = mgr->post(request, QByteArray());
run();
}
void HttpDlg::post(const QNetworkRequest & request, const QByteArray & data)
{
if (connection_) {
disconnect(connection_);
}
connection_ = connect(mgr, &QNetworkAccessManager::finished, this, &HttpDlg::onFinished);
reply_ = mgr->post(request, data);
run();
}
void HttpDlg::run()
{
auto path = PathHelper::program();
path += sz_ == sz_small ? "/Skin/gif/ajax-loader-small.gif" : "/Skin/gif/preloader.gif";
auto movie = new QMovie(path);
label_->setMovie(movie);
movie->start();
timer_.start();
auto p = parentWidget();
if (p) {
p->setEnabled(false);
}
startTimer(1000);
QDialog::exec();
if (p) {
p->setEnabled(true);
}
movie->deleteLater();
}
void HttpDlg::timerEvent(QTimerEvent * e)
{
MYQDEBUG << time_out_sec_;
if (--time_out_sec_ > 0) {
elapse_->setText(QString::number(time_out_sec_));
} else {
MYQCRITICAL << "timeout";
disconnect(connection_);
result_ = HttpDlgErrorCode::NetworkError;
QDialog::reject();
}
}
void HttpDlg::onFinished(QNetworkReply * reply)
{
do {
if (!reply) {
MYQCRITICAL << "no reply";
result_ = HttpDlgErrorCode::NetworkError;
break;
}
if (QNetworkReply::NoError != reply->error()) {
httpReason_ = reply->errorString();
MYQCRITICAL << httpReason_;
result_ = HttpDlgErrorCode::NetworkError;
break;
}
QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
if (!statusCode.isValid()) {
MYQDEBUG << "statusCode is not valid";
break;
}
httpStatusCode_ = statusCode.toInt();
if (httpStatusCode_ != 200) {
result_ = HttpDlgErrorCode::NetworkError;
httpReason_ = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
MYQCRITICAL << httpStatusCode_ << httpReason_;
break;
}
auto res = reply->readAll();
Json::Reader reader;
root_.clear();
if (!reader.parse(res.constData(), root_)) {
//result_ = HttpDlgErrorCode::ParseJsonError;
//break;
}
MYQDEBUG << reply->url() << "reply:\n" << root_.toStyledString().data();
} while (false);
QDialog::accept();
reply->deleteLater();
}
}
}
......@@ -6,21 +6,13 @@
#include <QUrl>
#include <QNetworkRequest>
#include <QByteArray>
#include <qmovie.h>
#include <qnetworkaccessmanager.h>
#include <qnetworkreply.h>
#include <system_error>
#include "../QtPathHelper.h"
#include "../QtUtils.h"
#include "../QtStylesheet.h"
#include "HttpDlgErrorCode.h"
#include "../../3rdparty/json/jsoncpp/json.h"
namespace jlib
{
namespace qt
{
#include "../../Util/jsoncpp/json.h"
class QNetworkAccessManager;
class QNetworkReply;
namespace HBVideoPlatform {
namespace common {
class HttpDlg : public QDialog
{
......@@ -32,57 +24,14 @@ public:
sz_small,
};
HttpDlg(QWidget *parent = nullptr, HttpDlgViewSize sz = sz_big, int timeOut = 10)
: QDialog(parent)
, sz_(sz)
, time_out_sec_(timeOut)
{
setWindowModality(Qt::WindowModal);
setWindowFlags(Qt::FramelessWindowHint);
if (!parent) { setAttribute(Qt::WA_TranslucentBackground); }
if (sz == sz_small) { setFixedSize(200, 200);
} else { setFixedSize(630, 637); }
label_ = new QLabel(this); label_->resize(width(), height()); label_->move(0, 0);
elapse_ = new QLabel(this); elapse_->resize(180, 80);
elapse_->move((width() - elapse_->width()) / 2, (height() - elapse_->height()) / 2);
elapse_->setStyleSheet(build_style(Qt::darkYellow, 64));
elapse_->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
//elapse_->hide();
parent ? center_to_parent(this, parent) : center_to_desktop(this);
mgr = new QNetworkAccessManager(this);
}
~HttpDlg() {}
void get(const QUrl& url) {
if (connection_) { disconnect(connection_); }
connection_ = connect(mgr, &QNetworkAccessManager::finished, this, &HttpDlg::onFinished);
reply_ = mgr->get(QNetworkRequest(url));
run();
}
void post(const QUrl& url) {
if (connection_) { disconnect(connection_); }
connection_ = connect(mgr, &QNetworkAccessManager::finished, this, &HttpDlg::onFinished);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
reply_ = mgr->post(request, QByteArray());
run();
}
void post(const QNetworkRequest& request, const QByteArray& data) {
if (connection_) { disconnect(connection_); }
connection_ = connect(mgr, &QNetworkAccessManager::finished, this, &HttpDlg::onFinished);
reply_ = mgr->post(request, data);
run();
}
HttpDlg(QWidget *parent = nullptr, HttpDlgViewSize sz = sz_small, int timeOut = 10);
~HttpDlg();
void get(const QUrl& url);
void post(const QUrl& url);
void post(const QNetworkRequest& request, const QByteArray& data);
std::error_code get_result() const { return result_; }
Json::Value getRoot() const { return root_; }
bool getValue(const QString& name, Json::Value& value) {
......@@ -113,95 +62,27 @@ public:
int getHttpStatusCode() const { return httpStatusCode_; }
QString getHttpReason() const { return httpReason_; }
#define break_if_parse_int_value_failed(json, name, default_value) \
int name = default_value; \
if (!JsoncppHelper::safelyGetIntValue(json, #name, name)) { \
ec = HttpDlgErrorCode::ParseJsonError; \
ec = common::HttpDlgErrorCode::ParseJsonError; \
break; \
}
#define break_if_parse_string_value_failed(json, name, default_value) \
QString name = default_value; \
if (!JsoncppHelper::safelyGetStringValue(json, #name, name)) { \
ec = HttpDlgErrorCode::ParseJsonError; \
ec = common::HttpDlgErrorCode::ParseJsonError; \
break; \
}
protected:
void run() {
auto path = PathHelper::program();
path += sz_ == sz_small ? "/Skin/gif/ajax-loader-small.gif" : "/Skin/gif/preloader.gif";
auto movie = new QMovie(path);
label_->setMovie(movie);
movie->start();
timer_.start();
auto p = parentWidget();
if (p) { p->setEnabled(false); }
startTimer(1000);
QDialog::exec();
if (p) { p->setEnabled(true); }
movie->deleteLater();
}
virtual void timerEvent(QTimerEvent * e) override {
MYQDEBUG << time_out_sec_;
if (--time_out_sec_ > 0) {
elapse_->setText(QString::number(time_out_sec_));
} else {
MYQCRITICAL << "timeout";
disconnect(connection_);
result_ = HttpDlgErrorCode::NetworkError;
QDialog::reject();
}
}
void run();
virtual void timerEvent(QTimerEvent * e) override;
private slots:
void onFinished(QNetworkReply* reply) {
do {
if (!reply) {
MYQCRITICAL << "no reply";
result_ = HttpDlgErrorCode::NetworkError;
break;
}
if (QNetworkReply::NoError != reply->error()) {
httpReason_ = reply->errorString();
MYQCRITICAL << httpReason_;
result_ = HttpDlgErrorCode::NetworkError;
break;
}
QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
if (!statusCode.isValid()) { MYQDEBUG << "statusCode is not valid"; break; }
httpStatusCode_ = statusCode.toInt();
if (httpStatusCode_ != 200) {
result_ = HttpDlgErrorCode::NetworkError;
httpReason_ = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
MYQCRITICAL << httpStatusCode_ << httpReason_;
break;
}
auto res = reply->readAll();
Json::Reader reader;
root_.clear();
if (!reader.parse(res.constData(), root_)) {
//result_ = HttpDlgErrorCode::ParseJsonError;
//break;
}
MYQDEBUG << reply->url() << "reply:\n" << root_.toStyledString().data();
} while (false);
QDialog::accept();
reply->deleteLater();
}
void onFinished(QNetworkReply* reply);
private:
std::error_code result_ = {};
......
#include "IconBtn.h"
#include <QtGui/QMouseEvent>
#include <QtGui/QBitMap>
#include <QtGui/QPainter>
#include <QDebug>
#include <QTimer>
#include <jlib/qt/QtUtils.h>
namespace HBVideoPlatform {
namespace common {
IconBtn::IconBtn(QWidget *parent, QString icon_path, uint32_t state_set)
: QLabel(parent)
, icon_path_(icon_path)
, state_set_(state_set)
{
setAttribute(Qt::WA_TranslucentBackground, true);
long_press_timer_ = new QTimer(this);
connect(long_press_timer_, SIGNAL(timeout()), this, SLOT(slot_long_press_timeout()));
state_set_ |= IconStatus::status_normal;
set_icon_path(icon_path_);
}
IconBtn::~IconBtn()
{
}
void IconBtn::set_pos(const QPoint & pos)
{
move(pos);
}
void IconBtn::set_pos(int x, int y)
{
set_pos(QPoint(x, y));
}
void IconBtn::set_icon_path(const QString & icon_path)
{
icon_path_ = icon_path;
refresh_icon_status();
}
void IconBtn::set_enabled(bool enable)
{
is_enable_ = enable;
refresh_icon_status();
}
void IconBtn::set_ing_status(bool is_ing)
{
is_ing_status_ = is_ing;
refresh_icon_status();
}
void IconBtn::enterEvent(QEvent *)
{
if (!is_enable_) { return; }
setCursor(QCursor(Qt::PointingHandCursor));
is_mouse_hover_ = true;
refresh_icon_status();
emit sig_mouse_enter();
}
void IconBtn::leaveEvent(QEvent *)
{
setCursor(QCursor(Qt::ArrowCursor));
is_mouse_hover_ = false;
is_mouse_press_ = false;
refresh_icon_status();
emit sig_mouse_leave();
}
void IconBtn::mousePressEvent(QMouseEvent *)
{
if (!is_enable_) { return; }
is_mouse_press_ = true;
refresh_icon_status();
if (state_set_ & type_long_press) {
if (long_press_timer_->isActive()) {
long_press_timer_->stop();
}
long_press_timer_->setSingleShot(true);
long_press_timer_->start(450);
}
}
void IconBtn::mouseReleaseEvent(QMouseEvent * e)
{
if (!is_enable_) { return; }
if (long_press_timer_->isActive()) {
long_press_timer_->stop();
}
bool is_long_press = is_long_press_;
is_long_press_ = is_mouse_press_ = false;
refresh_icon_status();
if (Qt::LeftButton == e->button()) {
if (rect().contains(e->pos())) {
is_long_press ? emit long_press_trigger(false) : emit clicked();
}
}
}
void IconBtn::refresh_icon_status()
{
QString icon_path;
if (!is_enable_) {
if (!(state_set_ & status_disable)) { return; }
icon_path = icon_path_ + "_d.png";
} else if (is_mouse_press_) {
if (!(state_set_ & status_press)) { return; }
icon_path = icon_path_ + "_h.png";
} else if (is_ing_status_) {
if (!(state_set_ & status_ing)) { return; }
icon_path = icon_path_ + "_ing.png";
} else if (is_mouse_hover_) {
if (!(state_set_ & status_hover)) { return; }
icon_path = icon_path_ + "_p.png";
} else {
if (!(state_set_&status_normal)) { return; }
icon_path = icon_path_ + "_n.png";
}
QPixmap pixmap;
if (!LOAD_PIXMAP_EX(icon_path)) {
return;
}
setFixedSize(pixmap.size());
setPixmap(pixmap);
if (state_set_ & type_mask) {
setMask(pixmap.mask());
}
if (state_set_ & type_opaque_paint) {
setAttribute(Qt::WA_OpaquePaintEvent, true);
}
}
void IconBtn::slot_long_press_timeout()
{
is_long_press_ = true;
emit long_press_trigger(true);
}
}
}
#pragma once
#include <QLabel>
#include <QMouseEvent>
#include <QPixmap>
#include <QBitmap>
#include "../QtUtils.h"
namespace jlib
{
namespace qt
{
namespace HBVideoPlatform {
namespace common {
class IconBtn : public QLabel
{
......@@ -33,92 +27,21 @@ public:
status_default = status_normal | status_hover | status_press,
};
IconBtn(QWidget *parent, QString icon_path, uint32_t state_set = IconStatus::status_default)
: QLabel(parent)
, icon_path_(icon_path)
, state_set_(state_set)
{
setAttribute(Qt::WA_TranslucentBackground, true);
long_press_timer_ = new QTimer(this);
connect(long_press_timer_, SIGNAL(timeout()), this, SLOT(slot_long_press_timeout()));
state_set_ |= IconStatus::status_normal;
set_icon_path(icon_path_);
}
void set_pos(const QPoint& pos) { move(pos); }
void set_pos(int x, int y) { set_pos(QPoint(x, y)); }
void set_icon_path(const QString& icon_path) {
icon_path_ = icon_path;
refresh_icon_status();
}
void set_enabled(bool enable) {
is_enable_ = enable;
refresh_icon_status();
}
void set_ing_status(bool is_ing) {
is_ing_status_ = is_ing;
refresh_icon_status();
}
IconBtn(QWidget *parent, QString icon_path, uint32_t state_set = IconStatus::status_default);
~IconBtn();
void set_pos(const QPoint& pos);
void set_pos(int x, int y);
void set_icon_path(const QString& icon_path);
void set_enabled(bool enable);
void set_ing_status(bool is_ing);
bool is_ing_status() const { return is_ing_status_; }
protected:
virtual void enterEvent(QEvent*) override {
if (!is_enable_) { return; }
setCursor(QCursor(Qt::PointingHandCursor));
is_mouse_hover_ = true;
refresh_icon_status();
emit sig_mouse_enter();
}
virtual void leaveEvent(QEvent*) override {
setCursor(QCursor(Qt::ArrowCursor));
is_mouse_hover_ = false;
is_mouse_press_ = false;
refresh_icon_status();
emit sig_mouse_leave();
}
virtual void mousePressEvent(QMouseEvent*) override {
if (!is_enable_) { return; }
is_mouse_press_ = true;
refresh_icon_status();
if (state_set_ & type_long_press) {
if (long_press_timer_->isActive()) {
long_press_timer_->stop();
}
long_press_timer_->setSingleShot(true);
long_press_timer_->start(450);
}
}
virtual void mouseReleaseEvent(QMouseEvent* e) override {
if (!is_enable_) { return; }
if (long_press_timer_->isActive()) {
long_press_timer_->stop();
}
bool is_long_press = is_long_press_;
is_long_press_ = is_mouse_press_ = false;
refresh_icon_status();
if (Qt::LeftButton == e->button()) {
if (rect().contains(e->pos())) {
is_long_press ? emit long_press_trigger(false) : emit clicked();
}
}
}
virtual void enterEvent(QEvent*) override;
virtual void leaveEvent(QEvent*) override;
virtual void mousePressEvent(QMouseEvent*) override;
virtual void mouseReleaseEvent(QMouseEvent*) override;
signals:
void clicked();
......@@ -126,7 +49,7 @@ signals:
void sig_mouse_enter();
void sig_mouse_leave();
private slots:
private slots:
void slot_long_press_timeout();
private:
......@@ -139,50 +62,9 @@ private:
QTimer* long_press_timer_ = {};
bool is_long_press_ = false;
void refresh_icon_status() {
QString icon_path;
if (!is_enable_) {
if (!(state_set_ & status_disable)) { return; }
icon_path = icon_path_ + "_d.png";
} else if (is_mouse_press_) {
if (!(state_set_ & status_press)) { return; }
icon_path = icon_path_ + "_h.png";
} else if (is_ing_status_) {
if (!(state_set_ & status_ing)) { return; }
icon_path = icon_path_ + "_ing.png";
} else if (is_mouse_hover_) {
if (!(state_set_ & status_hover)) { return; }
icon_path = icon_path_ + "_p.png";
} else {
if (!(state_set_&status_normal)) { return; }
icon_path = icon_path_ + "_n.png";
}
QPixmap pixmap;
if (!LOAD_PIXMAP_EX(icon_path)) {
return;
}
setFixedSize(pixmap.size());
setPixmap(pixmap);
if (state_set_ & type_mask) {
setMask(pixmap.mask());
}
if (state_set_ & type_opaque_paint) {
setAttribute(Qt::WA_OpaquePaintEvent, true);
}
}
void refresh_icon_status();
};
inline void IconBtn::slot_long_press_timeout()
{
is_long_press_ = true;
emit long_press_trigger(true);
}
}
}
#include "LoadingView.h"
#include <qmovie.h>
#include <jlib/qt/QtUtils.h>
#include <jlib/qt/QtStylesheet.h>
#include <jlib/qt/QtPathHelper.h>
using namespace jlib::qt;
namespace HBVideoPlatform {
namespace common {
LoadingView::LoadingView(QWidget *parent, std::vector<ThreadCtrl*> threads, LoadingViewSize sz)
: QDialog(parent)
, threads_(threads)
, sz_(sz)
{
setWindowModality(Qt::WindowModal);
setWindowFlags(Qt::FramelessWindowHint);
if (!parent) {
setAttribute(Qt::WA_TranslucentBackground);
}
if (sz == sz_small) {
setFixedSize(200, 200);
} else {
setFixedSize(630, 637);
}
label_ = new QLabel(this);
label_->resize(width(), height());
label_->move(0, 0);
progress1_ = new QLabel(this);
progress1_->resize(180, 80);
progress2_ = new QLabel(this);
progress2_->resize(180, 50);
elapse_ = new QLabel(this);
elapse_->resize(180, 50);
progress1_->move((width() - progress1_->width()) / 2, (height() - progress1_->height() - progress2_->height() - elapse_->height()) / 2);
progress1_->setStyleSheet(build_style(Qt::green, 64));
progress1_->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
progress1_->hide();
progress2_->move(progress1_->x(), progress1_->y() + progress1_->height());
progress2_->setStyleSheet(build_style(Qt::blue, 32));
progress2_->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
progress2_->hide();
elapse_->move(progress1_->x(), progress2_->y() + progress2_->height());
elapse_->setStyleSheet(build_style(Qt::darkYellow, 48));
elapse_->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
elapse_->hide();
parent ? center_to_parent(this, parent) : center_to_desktop(this);
int tag = 0;
for (auto& thread_ : threads_) {
thread_->set_tag(tag++);
tp_.push_back(ThreadProgress(0, 1));
connect(thread_, SIGNAL(sig_ready(int, std::error_code)), this, SLOT(slot_ready(int, std::error_code)));
connect(thread_, SIGNAL(sig_progress(int, HBVideoPlatform::common::ThreadProgress)), this, SLOT(slot_progress(int, HBVideoPlatform::common::ThreadProgress)));
}
}
LoadingView::~LoadingView()
{
for (auto thread_ : threads_) {
thread_->deleteLater();
}
}
void LoadingView::run()
{
auto path = PathHelper::program();;
path += sz_ == sz_small ? "/Skin/gif/ajax-loader-small.gif" : "/Skin/gif/preloader.gif";
auto movie = new QMovie(path);
label_->setMovie(movie);
movie->start();
timer_.start();
for (auto thread_ : threads_) {
thread_->start();
}
auto p = parentWidget();
if (p) {
p->setEnabled(false);
}
if (!show_progress_) {
show_progress_ = true;
startTimer(1000);
}
QDialog::exec();
if (p) {
p->setEnabled(true);
}
}
void LoadingView::slot_progress(int tag, HBVideoPlatform::common::ThreadProgress progress)
{
tp_[tag].total = progress.total;
tp_[tag].pos = progress.pos;
int pos = 0; int total = 0;
for (auto tp : tp_) {
pos += tp.pos;
total += tp.total;
}
int percent = pos * 100 / total;
MYQDEBUG << "tag" << tag << "progress.pos" << progress.pos << "progress.total" << progress.total << "pos" << pos << "total" << total << "percent" << percent;
progress1_->setText(QString("%1%").arg(percent));
progress1_->show();
progress2_->setText(QString("%1/%2").arg(pos).arg(total));
progress2_->show();
int secs = timer_.elapsed() / 1000;
int mins = secs / 60;
secs %= 60;
elapse_->setText(QString().sprintf("%02d:%02d", mins, secs));
elapse_->show();
}
void LoadingView::timerEvent(QTimerEvent * e)
{
if (show_progress_) {
int secs = timer_.elapsed() / 1000;
int mins = secs / 60;
secs %= 60;
elapse_->setText(QString().sprintf("%02d:%02d", mins, secs));
elapse_->show();
}
}
void LoadingView::slot_ready(int tag, std::error_code result)
{
MYQDEBUG << "tag" << tag << "ready, code=" << result.value() << "msg=" << QString::fromLocal8Bit(result.message().data());
result_ = result;
if (show_progress_) {
progress1_->setText("100%");
progress1_->show();
}
for (auto iter = threads_.begin(); iter != threads_.end(); iter++) {
auto thread = *iter;
if (thread->get_tag() == tag) {
threads_.erase(iter);
break;
}
}
if (!threads_.empty()) { return; }
QDialog::accept();
}
}
}
......@@ -6,15 +6,9 @@
#include "../Model/ThreadModel.h"
#include <vector>
#include <qelapsedtimer.h>
#include <qmovie.h>
#include "../QtUtils.h"
#include "../QtStylesheet.h"
#include "../QtPathHelper.h"
namespace jlib
{
namespace qt
{
namespace HBVideoPlatform {
namespace common {
class LoadingView : public QDialog
{
......@@ -26,111 +20,18 @@ public:
sz_small,
};
LoadingView(QWidget *parent = nullptr, std::vector<ThreadCtrl*> threads = {}, LoadingViewSize sz = sz_big)
: QDialog(parent)
, threads_(threads)
, sz_(sz)
{
setWindowModality(Qt::WindowModal);
setWindowFlags(Qt::FramelessWindowHint);
if (!parent) {
setAttribute(Qt::WA_TranslucentBackground);
}
if (sz == sz_small) {
setFixedSize(200, 200);
} else {
setFixedSize(630, 637);
}
label_ = new QLabel(this);
label_->resize(width(), height());
label_->move(0, 0);
progress1_ = new QLabel(this);
progress1_->resize(180, 80);
progress2_ = new QLabel(this);
progress2_->resize(180, 50);
elapse_ = new QLabel(this);
elapse_->resize(180, 50);
progress1_->move((width() - progress1_->width()) / 2, (height() - progress1_->height() - progress2_->height() - elapse_->height()) / 2);
progress1_->setStyleSheet(build_style(Qt::green, 64));
progress1_->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
progress1_->hide();
progress2_->move(progress1_->x(), progress1_->y() + progress1_->height());
progress2_->setStyleSheet(build_style(Qt::blue, 32));
progress2_->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
progress2_->hide();
elapse_->move(progress1_->x(), progress2_->y() + progress2_->height());
elapse_->setStyleSheet(build_style(Qt::darkYellow, 48));
elapse_->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
elapse_->hide();
parent ? center_to_parent(this, parent) : center_to_desktop(this);
int tag = 0;
for (auto& thread_ : threads_) {
thread_->set_tag(tag++);
tp_.push_back(ThreadProgress(0, 1));
connect(thread_, SIGNAL(sig_ready(int, std::error_code)), this, SLOT(slot_ready(int, std::error_code)));
connect(thread_, SIGNAL(sig_progress(int, HBVideoPlatform::common::ThreadProgress)), this, SLOT(slot_progress(int, HBVideoPlatform::common::ThreadProgress)));
}
}
virtual ~LoadingView() {
for (auto thread_ : threads_) {
thread_->deleteLater();
}
}
void run() {
auto path = PathHelper::program();;
path += sz_ == sz_small ? "/Skin/gif/ajax-loader-small.gif" : "/Skin/gif/preloader.gif";
auto movie = new QMovie(path);
label_->setMovie(movie);
movie->start();
timer_.start();
for (auto thread_ : threads_) {
thread_->start();
}
auto p = parentWidget();
if (p) {
p->setEnabled(false);
}
if (!show_progress_) {
show_progress_ = true;
startTimer(1000);
}
QDialog::exec();
if (p) {
p->setEnabled(true);
}
}
LoadingView(QWidget *parent = nullptr, std::vector<ThreadCtrl*> threads = {}, LoadingViewSize sz = sz_big);
~LoadingView();
void run();
std::error_code get_result() const { return result_; }
private slots:
void slot_ready(int tag, std::error_code ec);
void slot_progress(int tag, jlib::qt::ThreadProgress progress);
void slot_progress(int tag, HBVideoPlatform::common::ThreadProgress progress);
protected:
virtual void timerEvent(QTimerEvent* e) override {
if (show_progress_) {
int secs = timer_.elapsed() / 1000;
int mins = secs / 60;
secs %= 60;
elapse_->setText(QString().sprintf("%02d:%02d", mins, secs));
elapse_->show();
}
}
virtual void timerEvent(QTimerEvent* e) override;
private:
std::error_code result_ = {};
......@@ -140,65 +41,12 @@ private:
QLabel* progress1_ = {};
QLabel* progress2_ = {};
QLabel* elapse_ = {};
std::vector<ThreadProgress> tp_ = {};
std::vector<HBVideoPlatform::common::ThreadProgress> tp_ = {};
bool show_progress_ = false;
LoadingViewSize sz_ = sz_big;
QElapsedTimer timer_ = {};
};
inline void LoadingView::slot_progress(int tag, jlib::qt::ThreadProgress progress)
{
tp_[tag].total = progress.total;
tp_[tag].pos = progress.pos;
int pos = 0; int total = 0;
for (auto tp : tp_) {
pos += tp.pos;
total += tp.total;
}
int percent = pos * 100 / total;
MYQDEBUG << "tag" << tag << "progress.pos" << progress.pos << "progress.total" << progress.total << "pos" << pos << "total" << total << "percent" << percent;
progress1_->setText(QString("%1%").arg(percent));
progress1_->show();
progress2_->setText(QString("%1/%2").arg(pos).arg(total));
progress2_->show();
int secs = timer_.elapsed() / 1000;
int mins = secs / 60;
secs %= 60;
elapse_->setText(QString().sprintf("%02d:%02d", mins, secs));
elapse_->show();
}
inline void LoadingView::slot_ready(int tag, std::error_code result)
{
MYQDEBUG << "tag" << tag << "ready, code=" << result.value() << "msg=" << QString::fromLocal8Bit(result.message().data());
result_ = result;
if (show_progress_) {
progress1_->setText("100%");
progress1_->show();
}
for (auto iter = threads_.begin(); iter != threads_.end(); iter++) {
auto thread = *iter;
if (thread->get_tag() == tag) {
threads_.erase(iter);
break;
}
}
if (!threads_.empty()) { return; }
QDialog::accept();
}
}
}
#include "RndButton.h"
#include <jlib/qt/QtStylesheet.h>
using namespace jlib::qt;
namespace HBVideoPlatform {
namespace common {
RndButton::RndButton(QWidget *parent)
: QWidget(parent)
{
txt_ = new QLabel(this);
txt_->setAlignment(Qt::AlignCenter);
txt_->hide();
}
RndButton::~RndButton()
{
}
void RndButton::set_attr(QString txt, QSize sz, int font_size)
{
font_sz_ = font_size;
txt_->setStyleSheet(build_style(Qt::white, font_size));
txt_->setText(txt);
setFixedSize(sz);
/*QPixmap pixmap;
LOAD_PIXMAP_EX(QString::fromLocal8Bit("Skin/Ӧÿ1.png"));
QSize pixSize = pixmap.size();
pixSize.scale(sz, Qt::KeepAspectRatio);
pixmap_ = pixmap.scaled(pixSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);*/
txt_->resize(size());
txt_->move(0, 0);
txt_->show();
bk_color_ = def_colors::control_bk;
update();
}
void RndButton::set_highlight(bool on)
{
is_highlighted_ = on;
bk_color_ = is_highlighted_ ? Qt::lightGray : def_colors::control_bk;
update();
}
void RndButton::paintEvent(QPaintEvent * e)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
QPainterPath path;
//int radius = std::min(rect().width() / 20, rect().height() / 20);
path.addRoundedRect(QRectF(0, 0, width(), height()), 10, 10);
QPen pen(Qt::black, 1);
painter.setPen(pen);
painter.fillPath(path, bk_color_);
painter.drawPath(path);
}
void RndButton::enterEvent(QEvent * e)
{
setCursor(QCursor(Qt::PointingHandCursor));
bk_color_ = Qt::darkGray;
update();
}
void RndButton::leaveEvent(QEvent * e)
{
setCursor(QCursor(Qt::ArrowCursor));
bk_color_ = is_highlighted_ ? Qt::lightGray : def_colors::control_bk;
update();
is_pressed_ = false;
}
void RndButton::mousePressEvent(QMouseEvent * e)
{
bk_color_ = def_colors::control_bk;
update();
is_pressed_ = true;
}
void RndButton::mouseReleaseEvent(QMouseEvent * e)
{
bk_color_ = Qt::darkGray;
update();
if (is_pressed_) {
emit clicked();
is_pressed_ = false;
}
}
}
}
This diff is collapsed.
#include "Toast.h"
#include <jlib/qt/QtStylesheet.h>
namespace HBVideoPlatform {
namespace common {
static Toast* prevToast = nullptr;
void Toast::makeToast(QWidget * context, const QString & msg, ToastLength length)
{
if (prevToast) {
prevToast->killTimer(prevToast->timerId);
} else {
prevToast = new Toast(context);
}
prevToast->length_ = length;
prevToast->setParent(context);
prevToast->buildMsg(msg);
prevToast->show();
prevToast->timerId = prevToast->startTimer(1000);
}
Toast::Toast(QWidget* parent)
: QLabel(parent)
{
//setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);
//label_ = new QLabel(this);
//label_->setFont(QFont(def_font_families::yahei, 24));
//setWordWrap(true);
setAlignment(Qt::AlignCenter);
setStyleSheet(jlib::qt::build_style(Qt::black, Qt::white, 12));
}
void Toast::buildMsg(const QString & msg)
{
auto rc = parentWidget()->rect();
resize(rc.size());
auto fm = fontMetrics();
int w = fm.width(msg) * 2 + 10;
w = w > rc.width() ? rc.width() : w;
//int h = fm.height();
int h = 50;
resize(w, h);
move((rc.width() - w) / 2, (rc.height() - h) / 2);
setText(msg);
}
void Toast::timerEvent(QTimerEvent * e)
{
if (length_-- == 0) {
hide();
deleteLater();
prevToast = nullptr;
}
}
}
}
This diff is collapsed.
This diff is collapsed.
#include "qt.h"
qt::qt()
{
}
#pragma once
#include "qt_global.h"
class QT_EXPORT qt
{
public:
qt();
};
This diff is collapsed.
This diff is collapsed.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment