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
{
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();
static inline QString currentTimeString() {
return QDateTime::currentDateTime().toString(JLIBQT_FILE_TIME_FORMAT);
}
QString path = {};
};
virtual ~PathHelper() {}
static Helper helper;
return helper.path;
}
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 bin() {
return program() + "/bin";
}
protected:
// disable constructor
explicit PathHelper() {}
QString programPath_ = {};
};
static inline QString log() {
return program() + "/log";
struct AutoSwithToBin {
AutoSwithToBin(PathHelper* helper) : helper(helper) {}
AutoSwithToBin(PathHelper* helper, const QString& path) : helper(helper) {
QDir().setCurrent(path);
}
static inline QString sdk() {
return program() + "/sdks";
~AutoSwithToBin() {
if (helper) { QDir().setCurrent(helper->bin()); }
}
static inline QString data() {
return program() + "/data";
}
PathHelper* helper = nullptr;
};
static inline QString config() {
return data() + "/config";
/*
* @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();
}
static inline QString db() {
return data() + "/db";
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();
}
static inline QString currentTimeString() {
return QDateTime::currentDateTime().toString(FILE_TIME_FORMAT);
QString path = {};
};
static Helper helper;
programPath_ = helper.path;
}
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) {
......@@ -117,91 +66,23 @@ public:
#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.
#include "../../jlib/base/logfile.h"
#include "../../jlib/base/logging.h"
int main()
{
}
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