commit 5c04a7368c1e4e12005925ae79a9ab0a3b7a91b3 Author: taynpg <taynpg@163.com> Date: Sun May 5 22:55:58 2024 +0800 初版转成cmake工程版本 diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..18fbbc4 --- /dev/null +++ b/.clang-format @@ -0,0 +1,38 @@ +# .clang-format + +# 风格格式化 +BasedOnStyle: LLVM +# 4 空格缩进 +IndentWidth: 4 +# 连续对齐变量的声明 +AlignConsecutiveDeclarations: true +# 指针左侧对齐 +PointerAlignment: Left +# 访问说明符(public、private等)的偏移 +AccessModifierOffset: -4 +# 大括号 +BreakBeforeBraces: Custom +BraceWrapping: + # 函数定义后面大括号在新行 + AfterFunction: true + # class定义后面 + AfterClass: true + +# 去除C++11的列表初始化的大括号{后和}前的空格 +Cpp11BracedListStyle: true +# 允许重新排版注释 +ReflowComments: true +# 允许排序#include +SortIncludes: true +# 在尾随的评论前添加的空格数(只适用于//) +SpacesBeforeTrailingComments: 3 +# tab宽度 +TabWidth: 4 +# 构造函数的初始化列表要么都在同一行,要么都各自一行 +ConstructorInitializerAllOnOneLineOrOnePerLine: true +# 每行字符的限制,0表示没有限制 +ColumnLimit: 150 +# 允许短的块放在同一行 +AllowShortBlocksOnASingleLine: false +# 是否允许短函数在一行 +AllowShortFunctionsOnASingleLine: InlineOnly \ No newline at end of file diff --git a/.clangd b/.clangd new file mode 100644 index 0000000..11d6e06 --- /dev/null +++ b/.clangd @@ -0,0 +1,12 @@ +Hover: + ShowAKA: Yes +Diagnostics: + UnusedIncludes: None # 禁用未使用头文件提示 + Suppress: [ + anon_type_definition, # 禁用匿名的typedef提示 + unused-variable, # 禁用未使用变量提示 + unused-function, # 禁用未使用函数提示 + unused-includes, # 禁用未使用的头文件提示 + ] + ClangTidy: + Remove: misc-unused-alias-decls diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ff8bda6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +build +.vs +.cache \ No newline at end of file diff --git a/.vscode/qt5.natvis b/.vscode/qt5.natvis new file mode 100644 index 0000000..7d18567 --- /dev/null +++ b/.vscode/qt5.natvis @@ -0,0 +1,814 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--************************************************************************************************ + Copyright (C) 2023 The Qt Company Ltd. + SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +*************************************************************************************************--> + +<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> + + <Type Name="QUuid"> + <DisplayString>{{{data1,Xb}-{data2,Xb}-{data3,Xb}-{(data4[0]),nvoXb}{(data4[1]),nvoXb}-{(data4[2]),nvoXb}{(data4[3]),nvoXb}{(data4[4]),nvoXb}{(data4[5]),nvoXb}{(data4[6]),nvoXb}{(data4[7]),nvoXb}}}</DisplayString> + </Type> + + <Type Name="QPoint"> + <AlternativeType Name="QPointF"/> + <DisplayString>{{ x = {xp}, y = {yp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + </Expand> + </Type> + + <Type Name="QRect"> + <DisplayString>{{ x = {x1}, y = {y1}, width = {x2 - x1 + 1}, height = {y2 - y1 + 1} }}</DisplayString> + <Expand> + <Item Name="[x]">x1</Item> + <Item Name="[y]">y1</Item> + <Item Name="[width]">x2 - x1 + 1</Item> + <Item Name="[height]">y2 - y1 + 1</Item> + </Expand> + </Type> + + <Type Name="QRectF"> + <DisplayString>{{ x = {xp}, y = {yp}, width = {w}, height = {h} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[width]">w</Item> + <Item Name="[height]">h</Item> + </Expand> + </Type> + + <Type Name="QSize"> + <AlternativeType Name="QSizeF"/> + <DisplayString>{{ width = {wd}, height = {ht} }}</DisplayString> + <Expand> + <Item Name="[width]">wd</Item> + <Item Name="[height]">ht</Item> + </Expand> + </Type> + + <Type Name="QLine"> + <AlternativeType Name="QLineF"/> + <DisplayString>{{ start point = {pt1}, end point = {pt2} }}</DisplayString> + <Expand> + <Synthetic Name="[start point]"> + <DisplayString>{pt1}</DisplayString> + <Expand> + <ExpandedItem>pt1</ExpandedItem> + </Expand> + </Synthetic> + <Synthetic Name="[end point]"> + <DisplayString>{pt2}</DisplayString> + <Expand> + <ExpandedItem>pt2</ExpandedItem> + </Expand> + </Synthetic> + + </Expand> + </Type> + + <Type Name="QPolygon"> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>(QPoint*)((reinterpret_cast<char*>(d)) + d->offset)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QPolygonF"> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <Item Name="[closed]"> + d->size > 0 + && ((((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[0]).xp + == (((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[d->size - 1]).xp) + && ((((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[0]).yp + == (((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[d->size - 1]).yp) + </Item> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>(QPointF*)((reinterpret_cast<char*>(d)) + d->offset)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name ="QVector2D"> + <DisplayString>{{ x = {xp}, y = {yp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + </Expand> + </Type> + + <Type Name ="QVector3D"> + <DisplayString>{{ x = {xp}, y = {yp}, z = {zp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[z]">zp</Item> + </Expand> + </Type> + + <Type Name ="QVector4D"> + <DisplayString>{{ x = {xp}, y = {yp}, z = {zp}, w = {wp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[z]">zp</Item> + <Item Name="[w]">wp</Item> + </Expand> + </Type> + + <Type Name ="QMatrix"> + <DisplayString> + {{ m11 = {_m11}, m12 = {_m12}, m21 = {_m21}, m22 = {_m22}, ... }} + </DisplayString> + <Expand> + <Item Name="[m11]">_m11</Item> + <Item Name="[m12]">_m12</Item> + <Item Name="[m21]">_m21</Item> + <Item Name="[m22]">_m22</Item> + <Item Name="[dx]">_dx</Item> + <Item Name="[dy]">_dy</Item> + </Expand> + </Type> + + <Type Name ="QMatrix4x4"> + <DisplayString> + {{ m11 = {m[0][0]}, m12 = {m[1][0]}, m13 = {m[2][0]}, m14 = {m[3][0]}, ... }} + </DisplayString> + <Expand> + <Item Name="[m11]">m[0][0]</Item> + <Item Name="[m12]">m[1][0]</Item> + <Item Name="[m13]">m[2][0]</Item> + <Item Name="[m14]">m[3][0]</Item> + <Item Name="[m21]">m[0][1]</Item> + <Item Name="[m22]">m[1][1]</Item> + <Item Name="[m23]">m[2][1]</Item> + <Item Name="[m24]">m[3][1]</Item> + <Item Name="[m31]">m[0][2]</Item> + <Item Name="[m32]">m[1][2]</Item> + <Item Name="[m33]">m[2][2]</Item> + <Item Name="[m34]">m[3][2]</Item> + <Item Name="[m41]">m[0][3]</Item> + <Item Name="[m42]">m[1][3]</Item> + <Item Name="[m43]">m[2][3]</Item> + <Item Name="[m44]">m[3][3]</Item> + </Expand> + </Type> + + <Type Name="QSizePolicy"> + <DisplayString> + {{ horizontal = {static_cast<Policy>(bits.horPolicy)}, vertical = {static_cast<Policy>(bits.verPolicy)}, type = {ControlType(1 << bits.ctype)} }} + </DisplayString> + <Expand> + <Synthetic Name="[vertical policy]"> + <DisplayString>QSizePolicy::Policy::{static_cast<Policy>(bits.verPolicy)}</DisplayString> + </Synthetic> + <Synthetic Name="[horizontal policy]"> + <DisplayString>QSizePolicy::Policy::{static_cast<Policy>(bits.horPolicy)}</DisplayString> + </Synthetic> + <Synthetic Name="[control type]"> + <DisplayString>QSizePolicy::ControlType::{ControlType(1 << bits.ctype)}</DisplayString> + </Synthetic> + <Synthetic Name="[expanding directions]"> + <DisplayString + Condition="(static_cast<Policy>(bits.verPolicy) & ExpandFlag)"> + Qt::Vertical (2) + </DisplayString> + <DisplayString + Condition="(static_cast<Policy>(bits.horPolicy) & ExpandFlag)"> + Qt::Horizontal (1) + </DisplayString> + </Synthetic> + <Item Name="[vertical stretch]">static_cast<int>(bits.verStretch)</Item> + <Item Name="[horizontal stretch]">static_cast<int>(bits.horStretch)</Item> + <Item Name="[has height for width]">bits.hfw == 1</Item> + <Item Name="[has width for height]">bits.wfh == 1</Item> + </Expand> + </Type> + + <Type Name="QChar"> + <DisplayString>{ucs,c}</DisplayString> + <StringView>ucs,c</StringView> + <Expand> + <Item Name="[latin 1]">ucs > 0xff ? '\0' : char(ucs),c</Item> + <Item Name="[unicode]">ucs,c</Item> + </Expand> + </Type> + + <Type Name="QString"> + <DisplayString>{((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),sub}</DisplayString> + <StringView>((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),sub</StringView> + <Expand> + <Item Name="[size]">d->size</Item> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),c</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QStringRef"> + <Intrinsic Name="offset" Expression="(reinterpret_cast<char16_t*>(m_string->d)) + + m_string->d->offset / 2" /> + <DisplayString Condition="m_string == nullptr">{m_string,[m_size]} u""</DisplayString> + <DisplayString Condition="m_string != nullptr">{offset() + m_position,[m_size]}</DisplayString> + <Expand> + <Item Name="[position]" ExcludeView="simple">m_position</Item> + <Item Name="[size]" ExcludeView="simple">m_size</Item> + <ArrayItems Condition="m_string != nullptr"> + <Size>m_size</Size> + <ValuePointer>offset()+m_position</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QStringView"> + <DisplayString>{m_data,[m_size]}</DisplayString> + <StringView>m_data,[m_size]</StringView> + <Expand> + <Item Name="[size]" ExcludeView="simple">m_size</Item> + <ArrayItems> + <Size>m_size</Size> + <ValuePointer>m_data</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QByteArray"> + <DisplayString>{((reinterpret_cast<char*>(d)) + d->offset),sb}</DisplayString> + <StringView>((reinterpret_cast<char*>(d)) + d->offset),sb</StringView> + <Expand> + <Item Name="[size]">d->size</Item> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>((reinterpret_cast<char*>(d)) + d->offset),c</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QUrl"> + <Intrinsic Name="isEmpty" Expression="size==0"> + <Parameter Name="size" Type="int"/> + </Intrinsic> + <Intrinsic Name="memberOffset" Expression="sizeof(QAtomicInt) + sizeof(int) + (sizeof(QString) * count)"> + <Parameter Name="count" Type="int"/> + </Intrinsic> + <Intrinsic Name="scheme" Expression="*((QString*)(((char*)(d) + memberOffset(0))))" /> + <Intrinsic Name="username" Expression="*((QString*)(((char*)(d) + memberOffset(1))))" /> + <Intrinsic Name="password" Expression="*((QString*)(((char*)(d) + memberOffset(2))))" /> + <Intrinsic Name="host" Expression="*((QString*)(((char*)(d) + memberOffset(3))))" /> + <Intrinsic Name="path" Expression="*((QString*)(((char*)(d) + memberOffset(4))))" /> + <Intrinsic Name="query" Expression="*((QString*)(((char*)(d) + memberOffset(5))))" /> + <Intrinsic Name="fragment" Expression="*((QString*)(((char*)(d) + memberOffset(6))))" /> + + <DisplayString Condition="!isEmpty(scheme().d->size)">{scheme()}://{host()}{path()}</DisplayString> + <DisplayString Condition="isEmpty(scheme().d->size)">{path()}</DisplayString> + <Expand> + <Item Name="[scheme]">scheme()</Item> + <Item Name="[username]">username()</Item> + <Item Name="[password]">password()</Item> + <Item Name="[host]">host()</Item> + <Item Name="[path]">path()</Item> + <Item Name="[query]">query()</Item> + <Item Name="[fragment]">fragment()</Item> + </Expand> + </Type> + + <Type Name="QBitArray"> + <DisplayString>{{ size = {(d.d->size << 3) - *((reinterpret_cast<char*>(d.d)) + d.d->offset)} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d.d->ref.atomic._q_value</Item> + <IndexListItems> + <Size>(d.d->size << 3) - *((reinterpret_cast<char*>(d.d)) + d.d->offset)</Size> + <ValueNode> + (*(reinterpret_cast<const unsigned char*>((reinterpret_cast<char*>(d.d)) + d.d->offset) + 1 + + ($i >> 3)) & (1 << ($i & 7))) != 0 + </ValueNode> + </IndexListItems> + </Expand> + </Type> + + <Type Name="QVarLengthArray<*>"> + <AlternativeType Name="QVarLengthArray<*, int>"/> + <DisplayString>{{ size = {s} }}</DisplayString> + <Expand> + <Item Name="[capacity]">a</Item> + <ArrayItems> + <Size>s</Size> + <ValuePointer>ptr</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QDate"> + <DisplayString>{{ julian day = {jd} }}</DisplayString> + <Expand></Expand> + </Type> + + <Type Name="QTime"> + <DisplayString + Condition="mds == 1">{{ millisecond = {mds} }}</DisplayString> + <DisplayString + Condition="mds != 1">{{ milliseconds = {mds} }}</DisplayString> + <Expand> + <Item Name="[hour]" + Condition="(mds / 3600000) == 1">mds / 3600000, d</Item> + <Item Name="[hours]" + Condition="(mds / 3600000) != 1">mds / 3600000, d</Item> + <Item Name="[minute]" + Condition="((mds % 3600000) / 60000) == 1">(mds % 3600000) / 60000, d</Item> + <Item Name="[minutes]" + Condition="((mds % 3600000) / 60000) != 1">(mds % 3600000) / 60000, d</Item> + <Item Name="[second]" + Condition="((mds / 1000) % 60) == 1">(mds / 1000) % 60, d</Item> + <Item Name="[seconds]" + Condition="((mds / 1000) % 60) != 1">(mds / 1000) % 60, d</Item> + <Item Name="[millisecond]" + Condition="(mds % 1000) == 1">mds % 1000, d</Item> + <Item Name="[milliseconds]" + Condition="(mds % 1000) != 1">mds % 1000, d</Item> + </Expand> + </Type> + + <Type Name="QRegularExpression"> + <DisplayString>{d.pattern}</DisplayString> + </Type> + + <Type Name="QSharedData"> + <Expand> + <Item Name="[referenced]">ref._q_value</Item> + </Expand> + </Type> + + <Type Name="QSharedPointer<*>"> + <DisplayString>strong reference to shared pointer of type {"$T1"}</DisplayString> + <Expand> + <Item Name="[is null]">value == 0</Item> + <Item Name="[weak referenced]">d->weakref._q_value</Item> + <Item Name="[strong referenced]">d->strongref._q_value</Item> + </Expand> + </Type> + + <Type Name="QSharedDataPointer<*>"> + <DisplayString>pointer to implicit shared object of type {"$T1"}</DisplayString> + <Expand> + <ExpandedItem>d</ExpandedItem> + </Expand> + </Type> + + <Type Name="QExplicitlySharedDataPointer<*>"> + <DisplayString>pointer to explicit shared object of type {"$T1"}</DisplayString> + <Expand> + <ExpandedItem>d</ExpandedItem> + </Expand> + </Type> + + <Type Name="QPointer<*>"> + <DisplayString>guarded pointer to subclass of QObject of type {"$T1"}</DisplayString> + <Expand> + <Item Name="[is null]">wp.d == 0 || wp.d->strongref._q_value == 0 || wp.value == 0</Item> + </Expand> + </Type> + + <Type Name="QWeakPointer<*>"> + <DisplayString>weak reference to shared pointer of type {"$T1"}</DisplayString> + <Expand> + <Item Name="[is null]">d == 0 || d->strongref._q_value == 0 || value == 0</Item> + <Item Name="[weak referenced]">d->weakref._q_value</Item> + <Item Name="[strong referenced]">d->strongref._q_value</Item> + </Expand> + </Type> + + <Type Name="QScopedPointer<*>"> + <DisplayString>scoped pointer to a dynamically allocated object of type {"$T1"}</DisplayString> + <Expand> + <Item Name="[is null]">!d</Item> + </Expand> + </Type> + + <Type Name="QScopedArrayPointer<*>"> + <DisplayString>scoped pointer to dynamically allocated array of objects of type {"$T1"}</DisplayString> + <Expand> + <Item Name="[is null]">!d</Item> + </Expand> + </Type> + + <Type Name="QPair<*,*>"> + <DisplayString>({first}, {second})</DisplayString> + <Expand> + <Item Name="[first]">first</Item> + <Item Name="[second]">second</Item> + </Expand> + </Type> + + <Type Name="QVector<*>"> + <AlternativeType Name="QStack<*>"></AlternativeType> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>($T1*)((reinterpret_cast<char*>(d)) + d->offset)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QList<*>"> + <AlternativeType Name="QQueue<*>"></AlternativeType> + <DisplayString>{{ size = {d->end - d->begin} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <IndexListItems> + <Size>d->end - d->begin</Size> + <ValueNode>*reinterpret_cast<$T1*>((sizeof($T1) > sizeof(void*)) + ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v + : reinterpret_cast<$T1*>(d->array + d->begin + $i)) + </ValueNode> + </IndexListItems> + </Expand> + </Type> + + <Type Name="QStringList"> + <DisplayString>{{ size = {d->end - d->begin} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <IndexListItems> + <Size>d->end - d->begin</Size> + <ValueNode> + *reinterpret_cast<QString*>((sizeof(QString) > sizeof(void*)) + ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v + : reinterpret_cast<QString*>(d->array + d->begin + $i)) + </ValueNode> + </IndexListItems> + </Expand> + </Type> + + <Type Name="QList<QVariant>"> + <DisplayString>{{ size = {d->end - d->begin} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <IndexListItems> + <Size>d->end - d->begin</Size> + <ValueNode> + *reinterpret_cast<QVariant*>((sizeof(QVariant) > sizeof(void*)) + ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v + : reinterpret_cast<QVariant*>(d->array + d->begin + $i)) + </ValueNode> + </IndexListItems> + </Expand> + </Type> + + <Type Name="QLinkedList<*>"> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <LinkedListItems> + <Size>d->size</Size> + <HeadPointer>d->n</HeadPointer> + <NextPointer>n</NextPointer> + <ValueNode>(*(QLinkedListNode<$T1>*)this).t</ValueNode> + </LinkedListItems> + </Expand> + </Type> + + <Type Name="QMapNode<*,*>"> + <DisplayString>({key}, {value})</DisplayString> + <Expand> + <Item Name="[key]">key</Item> + <Item Name="[value]">value</Item> + </Expand> + </Type> + + <Type Name="QMap<*,*>"> + <AlternativeType Name="QMultiMap<*,*>"/> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <TreeItems> + <Size>d->size</Size> + <HeadPointer>d->header.left</HeadPointer> + <LeftPointer>left</LeftPointer> + <RightPointer>right</RightPointer> + <ValueNode>*((QMapNode<$T1,$T2>*)this)</ValueNode> + </TreeItems> + </Expand> + </Type> + + <Type Name="QHashNode<*,*>"> + <DisplayString Condition="next == 0">(empty)</DisplayString> + <DisplayString Condition="next != 0">({key}, {value})</DisplayString> + <Expand> + <Item Name="[key]" Condition="next != 0">key</Item> + <Item Name="[value]" Condition="next != 0">value</Item> + <Item Name="[next]" Condition="next != 0">next</Item> + </Expand> + </Type> + + <Type Name="QHash<*,*>"> + <AlternativeType Name="QMultiHash<*,*>"/> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <ArrayItems IncludeView="buckets"> + <Size>d->numBuckets</Size> + <ValuePointer>reinterpret_cast<Node **>(d->buckets)</ValuePointer> + </ArrayItems> + <CustomListItems ExcludeView="buckets"> + <Variable Name="n" InitialValue="d->numBuckets"/> + <Variable Name="bucket" InitialValue="d->buckets"/> + <Variable Name="node" InitialValue="d->buckets[0]"/> + <Variable Name="keyValuePair" InitialValue="reinterpret_cast<Node *>(0)"/> + <Size>d->size</Size> + <Loop> + <Break Condition="n == 0"/> + <Exec>node = *(bucket++)</Exec> + <Exec>--n</Exec> + <Loop> + <Break Condition="!node || !node->next"/> + <Exec>keyValuePair = reinterpret_cast<Node *>(node)</Exec> + <Item Name="[{keyValuePair->key}]">keyValuePair->value</Item> + <Exec>node = node->next</Exec> + </Loop> + </Loop> + </CustomListItems> + </Expand> + </Type> + + <Type Name="QHashNode<*,QHashDummyValue>"> + <DisplayString Condition="next == 0">(empty)</DisplayString> + <DisplayString Condition="next != 0">({key})</DisplayString> + <Expand> + <Item Name="[key]" Condition="next != 0">key</Item> + </Expand> + </Type> + + <Type Name="QSet<*>"> + <DisplayString>{{ size = {q_hash.d->size} }}</DisplayString> + <Expand> + <ExpandedItem>q_hash</ExpandedItem> + </Expand> + </Type> + + <Type Name="QCache<*,*>::Node"> + <DisplayString>({*keyPtr}, {*t})</DisplayString> + <Expand> + <Item Name="[key]">*keyPtr</Item> + <Item Name="[value]">*t</Item> + </Expand> + </Type> + + <Type Name="QCache<*,*>"> + <DisplayString>{{ size = {hash.d->size} }}</DisplayString> + <Expand> + <Item Name="[max coast]">mx</Item> + <Item Name="[total coast]">total</Item> + <Item Name="[referenced]">hash.d->ref.atomic._q_value</Item> + <LinkedListItems> + <Size>hash.d->size</Size> + <HeadPointer>f</HeadPointer> + <NextPointer>n</NextPointer> + <ValueNode>*((Node*)this)</ValueNode> + </LinkedListItems> + </Expand> + </Type> + + <Type Name="QStandardItemPrivate"> + <Intrinsic Name="memberOffset" Expression="sizeof(QStandardItemModel *) + + sizeof(QStandardItem *) + + sizeof(int *) + + sizeof(int *) + + (sizeof(int) * count)"> + <Parameter Name="count" Type="int"/> + </Intrinsic> + <Intrinsic Name="rows" Expression="*((int*)(((char*)(this)) + memberOffset(0)))" /> + <Intrinsic Name="columns" Expression="*((int*)(((char*)(this)) + memberOffset(1)))" /> + </Type> + + <Type Name="QStandardItem"> + <DisplayString>{{ row count = {(*d_ptr.d).rows()}, column count = {(*d_ptr.d).columns()} }}</DisplayString> + <Expand> + <Item Name="[d]">d_ptr.d,!</Item> + <Item Name="[row count]">(*d_ptr.d).rows()</Item> + <Item Name="[column count]">(*d_ptr.d).columns()</Item> + </Expand> + </Type> + + <Type Name="QVariant"> + <!--Region DisplayString QVariant--> + + <DisplayString Condition="d.type == QMetaType::UnknownType">Invalid</DisplayString> + <DisplayString Condition="d.type == QMetaType::Bool">{d.data.b}</DisplayString> + <DisplayString Condition="d.type == QMetaType::Int">{d.data.i}</DisplayString> + <DisplayString Condition="d.type == QMetaType::UInt">{d.data.u}</DisplayString> + <DisplayString Condition="d.type == QMetaType::LongLong">{d.data.ll}</DisplayString> + <DisplayString Condition="d.type == QMetaType::ULongLong">{d.data.ull}</DisplayString> + <DisplayString Condition="d.type == QMetaType::Double">{d.data.d}</DisplayString> + <DisplayString Condition="d.type == QMetaType::QChar">{d.data.c}</DisplayString> + <DisplayString Condition="d.type == QMetaType::QVariantMap"> + {*((QMap<QString,QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QVariantList"> + {*((QList<QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QString"> + {*((QString*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QStringList"> + {*((QStringList*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QByteArray"> + {*((QByteArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QBitArray"> + {*((QBitArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QDate"> + {*((QDate*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QTime"> + {*((QTime*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QDateTime">DateTime</DisplayString> + <DisplayString Condition="d.type == QMetaType::QUrl">Url</DisplayString> + <DisplayString Condition="d.type == QMetaType::QLocale">Locale</DisplayString> + <DisplayString Condition="d.type == QMetaType::QRect"> + {*((QRect*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QRectF"> + {*((QRectF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QSize"> + {*((QSize*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QSizeF"> + {*((QSizeF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QLine"> + {*((QLine*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QLineF"> + {*((QLineF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QPoint"> + {*((QPoint*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QPointF"> + {*((QPointF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QRegExp">RegExp</DisplayString> + <DisplayString Condition="d.type == QMetaType::QRegularExpression">RegularExpression</DisplayString> + <DisplayString Condition="d.type == QMetaType::QVariantHash"> + {*((QHash<QString,QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QEasingCurve">EasingCurve</DisplayString> + <DisplayString Condition="d.type == QMetaType::QUuid">Uuid</DisplayString> + <DisplayString Condition="d.type == QMetaType::QModelIndex">ModelIndex</DisplayString> + <DisplayString Condition="d.type == QMetaType::LastCoreType">LastCoreType</DisplayString> + <DisplayString Condition="d.type == QMetaType::QFont">Font</DisplayString> + <DisplayString Condition="d.type == QMetaType::QPixmap">Pixmap</DisplayString> + <DisplayString Condition="d.type == QMetaType::QBrush">Brush</DisplayString> + <DisplayString Condition="d.type == QMetaType::QColor">Color</DisplayString> + <DisplayString Condition="d.type == QMetaType::QPalette">Palette</DisplayString> + <DisplayString Condition="d.type == QMetaType::QImage">Image</DisplayString> + <DisplayString Condition="d.type == QMetaType::QPolygon">Polygon</DisplayString> + <DisplayString Condition="d.type == QMetaType::QRegion">Region</DisplayString> + <DisplayString Condition="d.type == QMetaType::QBitmap">Bitmap</DisplayString> + <DisplayString Condition="d.type == QMetaType::QCursor">Cursor</DisplayString> + <DisplayString Condition="d.type == QMetaType::QKeySequence">KeySequence</DisplayString> + <DisplayString Condition="d.type == QMetaType::QPen">Pen</DisplayString> + <DisplayString Condition="d.type == QMetaType::QTextLength">TextLength</DisplayString> + <DisplayString Condition="d.type == QMetaType::QTextFormat">TextFormat</DisplayString> + <DisplayString Condition="d.type == QMetaType::QMatrix">Matrix</DisplayString> + <DisplayString Condition="d.type == QMetaType::QTransform">Transform</DisplayString> + <DisplayString Condition="d.type == QMetaType::QMatrix4x4">Matrix4x4</DisplayString> + <DisplayString Condition="d.type == QMetaType::QVector2D">Vector2D</DisplayString> + <DisplayString Condition="d.type == QMetaType::QVector3D">Vector3D</DisplayString> + <DisplayString Condition="d.type == QMetaType::QVector4D">Vector4D</DisplayString> + <DisplayString Condition="d.type == QMetaType::QQuaternion">Quaternion</DisplayString> + <DisplayString Condition="d.type == QMetaType::QPolygonF">PolygonF</DisplayString> + <DisplayString Condition="d.type == QMetaType::QIcon">Icon</DisplayString> + <DisplayString Condition="d.type == QMetaType::LastGuiType">LastGuiType</DisplayString> + <DisplayString Condition="d.type == QMetaType::QSizePolicy">SizePolicy</DisplayString> + <DisplayString Condition="d.type == QMetaType::User">UserType</DisplayString> + <DisplayString Condition="d.type == 0xffffffff">LastType</DisplayString> + + <!--End region DisplayString QVariant--> + + <!--Region DisplayView QVariant--> + + <StringView Condition="d.type == QMetaType::QChar">d.data.c</StringView> + + <StringView Condition="d.type == QMetaType::QString"> + *((QString*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </StringView> + + <StringView Condition="d.type == QMetaType::QByteArray"> + *((QByteArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </StringView> + + <!--End region DisplayView QVariant--> + + <!--Region Expand QVariant--> + + <Expand> + <ExpandedItem Condition="d.type == QMetaType::QVariantMap"> + *((QMap<QString,QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QVariantList"> + *((QList<QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QString"> + *((QString*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QStringList"> + *((QStringList*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QByteArray"> + *((QByteArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QBitArray"> + *((QBitArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QDate"> + *((QDate*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QTime"> + *((QTime*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QRect"> + *((QRect*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QRectF"> + *((QRectF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QSize"> + *((QSize*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QSizeF"> + *((QSizeF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QLine"> + *((QLine*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QLineF"> + *((QLineF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QPoint"> + *((QPoint*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QPointF"> + *((QPointF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QVariantHash"> + *((QHash<QString,QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + </Expand> + + <!--End region Expand QVariant--> + </Type> + +</AutoVisualizer> diff --git a/.vscode/qt6.natvis b/.vscode/qt6.natvis new file mode 100644 index 0000000..94c2260 --- /dev/null +++ b/.vscode/qt6.natvis @@ -0,0 +1,735 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--************************************************************************************************ + Copyright (C) 2023 The Qt Company Ltd. + SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +*************************************************************************************************--> + +<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> + + <Type Name="QPropertyData<*>"> + <DisplayString>{val}</DisplayString> + <Expand> + <Item Name="[value]">val</Item> + </Expand> + </Type> + + <Type Name="QQuickItemPrivate"> + <Intrinsic Name="_hasExtraData" Expression="extra.d.d != 0" /> + <Intrinsic Name="_extraData" Expression="(*(ExtraData*)extra.d.d)" /> + <Intrinsic Name="_objectName" Expression="(extraData->objectName).val.d.ptr" /> + <DisplayString Condition="_hasExtraData()">{{ x = {x,g}, y = {y,g}, z = {_extraData().z,g}, width = {width,g}, height = {height,g} }}</DisplayString> + <DisplayString>{{ x = {x,g}, y = {y,g}, width = {width,g}, height = {height,g} }}</DisplayString> + <Expand> + <Item Name="x">x</Item> + <Item Name="y">y</Item> + <Item Name="z" Condition="_hasExtraData()">_extraData().z</Item> + <Item Name="scale" Condition="_hasExtraData()">_extraData().scale</Item> + <Item Name="rotation" Condition="_hasExtraData()">_extraData().rotation</Item> + <Item Name="opacity" Condition="_hasExtraData()">_extraData().opacity</Item> + <Item Name="width">width</Item> + <Item Name="height">height</Item> + <Item Name="implicitWidth">implicitWidth</Item> + <Item Name="implicitHeight">implicitHeight</Item> + <Item Name="visible">effectiveVisible</Item> + <Item Name="enabled">explicitEnable</Item> + <Item Name="objectName" Condition="_objectName() != 0">_objectName(),na</Item> + <Item Name="parentItem">parentItem</Item> + <Item Name="childItems">childItems, nr</Item> + </Expand> + </Type> + + <Type Name="QQuickItem"> + <DisplayString>{d_ptr.d,na}</DisplayString> + <Expand> + <ExpandedItem>d_ptr.d</ExpandedItem> + </Expand> + </Type> + + <Type Name="QUuid"> + <DisplayString>{{{data1,Xb}-{data2,Xb}-{data3,Xb}-{(data4[0]),nvoXb}{(data4[1]),nvoXb}-{(data4[2]),nvoXb}{(data4[3]),nvoXb}{(data4[4]),nvoXb}{(data4[5]),nvoXb}{(data4[6]),nvoXb}{(data4[7]),nvoXb}}}</DisplayString> + </Type> + + <Type Name="QSpecialInteger<*>"> + <DisplayString>{val}</DisplayString> + <Expand> + <Item Name="[value]">val</Item> + </Expand> + </Type> + + <Type Name="QBasicAtomicInteger<*>"> + <DisplayString>{_q_value}</DisplayString> + <Expand> + <Item Name="[value]">_q_value</Item> + </Expand> + </Type> + + <Type Name="QBasicAtomicPointer<*>"> + <Intrinsic Name="isNull" Expression="value()==0" /> + <Intrinsic Name="value" Expression="_q_value.value()" /> + <DisplayString Condition="isNull()">empty</DisplayString> + <DisplayString Condition="!isNull()">{_q_value}</DisplayString> + <Expand> + <Item Name=" " Condition="!isNull()">*value()</Item> + </Expand> + </Type> + + <Type Name="QPoint"> + <AlternativeType Name="QPointF"/> + <DisplayString>{{ x = {xp}, y = {yp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + </Expand> + </Type> + + <Type Name="QRect"> + <DisplayString>{{ x = {x1}, y = {y1}, width = {x2 - x1 + 1}, height = {y2 - y1 + 1} }}</DisplayString> + <Expand> + <Item Name="[x]">x1</Item> + <Item Name="[y]">y1</Item> + <Item Name="[width]">x2 - x1 + 1</Item> + <Item Name="[height]">y2 - y1 + 1</Item> + </Expand> + </Type> + + <Type Name="QRectF"> + <DisplayString>{{ x = {xp}, y = {yp}, width = {w}, height = {h} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[width]">w</Item> + <Item Name="[height]">h</Item> + </Expand> + </Type> + + <Type Name="QSize"> + <AlternativeType Name="QSizeF"/> + <DisplayString>{{ width = {wd}, height = {ht} }}</DisplayString> + <Expand> + <Item Name="[width]">wd</Item> + <Item Name="[height]">ht</Item> + </Expand> + </Type> + + <Type Name="QLine"> + <AlternativeType Name="QLineF"/> + <DisplayString>{{ start point = {pt1}, end point = {pt2} }}</DisplayString> + <Expand> + <Synthetic Name="[start point]"> + <DisplayString>{pt1}</DisplayString> + <Expand> + <ExpandedItem>pt1</ExpandedItem> + </Expand> + </Synthetic> + <Synthetic Name="[end point]"> + <DisplayString>{pt2}</DisplayString> + <Expand> + <ExpandedItem>pt2</ExpandedItem> + </Expand> + </Synthetic> + + </Expand> + </Type> + + <Type Name="QPolygon"> + <DisplayString>{{ size={d->size} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>(QPoint*)((reinterpret_cast<char*>(d)) + d->offset)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QPolygonF"> + <DisplayString>{{ size={d->size} }}</DisplayString> + <Expand> + <Item Name="[closed]"> + d->size > 0 + && ((((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[0]).xp + == (((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[d->size - 1]).xp) + && ((((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[0]).yp + == (((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[d->size - 1]).yp) + </Item> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>(QPointF*)((reinterpret_cast<char*>(d)) + d->offset)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QVector2D"> + <DisplayString>{{ x = {xp}, y = {yp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + </Expand> + </Type> + + <Type Name="QVector3D"> + <DisplayString>{{ x = {xp}, y = {yp}, z = {zp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[z]">zp</Item> + </Expand> + </Type> + + <Type Name="QVector4D"> + <DisplayString>{{ x = {xp}, y = {yp}, z = {zp}, w = {wp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[z]">zp</Item> + <Item Name="[w]">wp</Item> + </Expand> + </Type> + + <Type Name="QMatrix"> + <DisplayString> + {{ m11 = {_m11}, m12 = {_m12}, m21 = {_m21}, m22 = {_m22}, ... }} + </DisplayString> + <Expand> + <Item Name="[m11]">_m11</Item> + <Item Name="[m12]">_m12</Item> + <Item Name="[m21]">_m21</Item> + <Item Name="[m22]">_m22</Item> + <Item Name="[dx]">_dx</Item> + <Item Name="[dy]">_dy</Item> + </Expand> + </Type> + + <Type Name="QMatrix4x4"> + <DisplayString> + {{ m11 = {m[0][0]}, m12 = {m[1][0]}, m13 = {m[2][0]}, m14 = {m[3][0]}, ... }} + </DisplayString> + <Expand> + <Item Name="[m11]">m[0][0]</Item> + <Item Name="[m12]">m[1][0]</Item> + <Item Name="[m13]">m[2][0]</Item> + <Item Name="[m14]">m[3][0]</Item> + <Item Name="[m21]">m[0][1]</Item> + <Item Name="[m22]">m[1][1]</Item> + <Item Name="[m23]">m[2][1]</Item> + <Item Name="[m24]">m[3][1]</Item> + <Item Name="[m31]">m[0][2]</Item> + <Item Name="[m32]">m[1][2]</Item> + <Item Name="[m33]">m[2][2]</Item> + <Item Name="[m34]">m[3][2]</Item> + <Item Name="[m41]">m[0][3]</Item> + <Item Name="[m42]">m[1][3]</Item> + <Item Name="[m43]">m[2][3]</Item> + <Item Name="[m44]">m[3][3]</Item> + </Expand> + </Type> + + <Type Name="QSizePolicy"> + <DisplayString> + {{ horizontal = {static_cast<Policy>(bits.horPolicy)}, vertical = {static_cast<Policy>(bits.verPolicy)}, type = {ControlType(1 << bits.ctype)} }} + </DisplayString> + <Expand> + <Synthetic Name="[vertical policy]"> + <DisplayString>QSizePolicy::Policy::{static_cast<Policy>(bits.verPolicy)}</DisplayString> + </Synthetic> + <Synthetic Name="[horizontal policy]"> + <DisplayString>QSizePolicy::Policy::{static_cast<Policy>(bits.horPolicy)}</DisplayString> + </Synthetic> + <Synthetic Name="[control type]"> + <DisplayString>QSizePolicy::ControlType::{ControlType(1 << bits.ctype)}</DisplayString> + </Synthetic> + <Synthetic Name="[expanding directions]"> + <DisplayString + Condition="(static_cast<Policy>(bits.verPolicy) & ExpandFlag)"> + Qt::Vertical (2) + </DisplayString> + <DisplayString + Condition="(static_cast<Policy>(bits.horPolicy) & ExpandFlag)"> + Qt::Horizontal (1) + </DisplayString> + </Synthetic> + <Item Name="[vertical stretch]">static_cast<int>(bits.verStretch)</Item> + <Item Name="[horizontal stretch]">static_cast<int>(bits.horStretch)</Item> + <Item Name="[has height for width]">bits.hfw == 1</Item> + <Item Name="[has width for height]">bits.wfh == 1</Item> + </Expand> + </Type> + + <Type Name="QChar"> + <DisplayString>{ucs,c}</DisplayString> + <StringView>ucs,c</StringView> + <Expand> + <Item Name="[latin 1]">ucs > 0xff ? '\0' : char(ucs),c</Item> + <Item Name="[unicode]">ucs,c</Item> + </Expand> + </Type> + + <Type Name="QString"> + <DisplayString>"{(reinterpret_cast<unsigned short*>(d.ptr)),sub}"</DisplayString> + <StringView>(reinterpret_cast<unsigned short*>(d.ptr)),sub</StringView> + <Expand> + <Item Name="[size]">d.size</Item> + <ArrayItems> + <Size>d.size</Size> + <ValuePointer>d.ptr</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QStringRef"> + <DisplayString Condition="m_string == nullptr">{m_string,[m_size]} u""</DisplayString> + <DisplayString Condition="m_string != nullptr">{m_string->d.ptr+m_position,[m_size]}</DisplayString> + <StringView Condition="m_string == nullptr">""</StringView> + <StringView Condition="m_string != nullptr">m_string,[m_position+m_size]</StringView> + <Expand> + <Item Name="[position]" ExcludeView="simple">m_position</Item> + <Item Name="[size]" ExcludeView="simple">m_size</Item> + <ArrayItems Condition="m_string != nullptr"> + <Size>m_size</Size> + <ValuePointer>m_string->d.ptr+m_position</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QStringView"> + <DisplayString>{m_data,[m_size]}</DisplayString> + <StringView>m_data,[m_size]</StringView> + <Expand> + <Item Name="[size]" ExcludeView="simple">m_size</Item> + <ArrayItems> + <Size>m_size</Size> + <ValuePointer>m_data</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QByteArray"> + <DisplayString>"{((reinterpret_cast<char*>(d.ptr))),sb}"</DisplayString> + <StringView>((reinterpret_cast<char*>(d.ptr))),sb</StringView> + <Expand> + <Item Name="[size]">d.size</Item> + <ArrayItems> + <Size>d.size</Size> + <ValuePointer>d.ptr</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QUrl"> + <Intrinsic Name="isEmpty" Expression="size==0"> + <Parameter Name="size" Type="int"/> + </Intrinsic> + <Intrinsic Name="memberOffset" Expression="sizeof(QAtomicInt) + sizeof(int) + (sizeof(QString) * count)"> + <Parameter Name="count" Type="int"/> + </Intrinsic> + <Intrinsic Name="scheme" Expression="*((QString*)(((char*)(d) + memberOffset(0))))" /> + <Intrinsic Name="username" Expression="*((QString*)(((char*)(d) + memberOffset(1))))" /> + <Intrinsic Name="password" Expression="*((QString*)(((char*)(d) + memberOffset(2))))" /> + <Intrinsic Name="host" Expression="*((QString*)(((char*)(d) + memberOffset(3))))" /> + <Intrinsic Name="path" Expression="*((QString*)(((char*)(d) + memberOffset(4))))" /> + <Intrinsic Name="query" Expression="*((QString*)(((char*)(d) + memberOffset(5))))" /> + <Intrinsic Name="fragment" Expression="*((QString*)(((char*)(d) + memberOffset(6))))" /> + + <DisplayString Condition="!isEmpty(scheme().d->size)">{scheme()}://{host()}{path()}</DisplayString> + <DisplayString Condition="isEmpty(scheme().d->size)">{path()}</DisplayString> + <Expand> + <Item Name="[scheme]">scheme()</Item> + <Item Name="[username]">username()</Item> + <Item Name="[password]">password()</Item> + <Item Name="[host]">host()</Item> + <Item Name="[path]">path()</Item> + <Item Name="[query]">query()</Item> + <Item Name="[fragment]">fragment()</Item> + </Expand> + </Type> + + <Type Name="QDate"> + <DisplayString>{{ julian day = {jd} }}</DisplayString> + </Type> + + <Type Name="QTime"> + <Intrinsic Name="hour" Expression="mds / 3600000" /> + <Intrinsic Name="minute" Expression="(mds % 3600000) / 60000" /> + <Intrinsic Name="second" Expression="(mds / 1000) % 60" /> + <Intrinsic Name="millisecond" Expression="mds % 1000" /> + <DisplayString Condition="mds == 1">{{ millisecond = {mds} }}</DisplayString> + <DisplayString Condition="mds != 1">{{ milliseconds = {mds} }}</DisplayString> + <Expand> + <Item Name="[hour]" + Condition="(mds / 3600000) == 1">hour(), d</Item> + <Item Name="[hours]" + Condition="(mds / 3600000) != 1">hour(), d</Item> + <Item Name="[minute]" + Condition="((mds % 3600000) / 60000) == 1">minute(), d</Item> + <Item Name="[minutes]" + Condition="((mds % 3600000) / 60000) != 1">minute(), d</Item> + <Item Name="[second]" + Condition="((mds / 1000) % 60) == 1">second(), d</Item> + <Item Name="[seconds]" + Condition="((mds / 1000) % 60) != 1">second(), d</Item> + <Item Name="[millisecond]" + Condition="(mds % 1000) == 1">millisecond(), d</Item> + <Item Name="[milliseconds]" + Condition="(mds % 1000) != 1">millisecond(), d</Item> + </Expand> + </Type> + + <Type Name="QPair<*,*>"> + <DisplayString>({first}, {second})</DisplayString> + <Expand> + <Item Name="[first]">first</Item> + <Item Name="[second]">second</Item> + </Expand> + </Type> + + <Type Name="QList<*>"> + <AlternativeType Name="QVector<*>"/> + <DisplayString>{{ size={d.size} }}</DisplayString> + <Expand> + <ArrayItems> + <Size>d.size</Size> + <ValuePointer>reinterpret_cast<$T1*>(d.ptr)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QVarLengthArray<*>"> + <DisplayString>{{ size={s} }}</DisplayString> + <Expand> + <Item Name="[capacity]">a</Item> + <ArrayItems> + <Size>s</Size> + <ValuePointer>ptr</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QMap<*,*>"> + <AlternativeType Name="QMultiMap<*,*>"/> + <DisplayString>{{ size={d.d->m._Mypair._Myval2._Myval2._Mysize} }}</DisplayString> + <Expand> + <TreeItems> + <Size>d.d->m._Mypair._Myval2._Myval2._Mysize</Size> + <HeadPointer>d.d->m._Mypair._Myval2._Myval2._Myhead->_Parent</HeadPointer> + <LeftPointer>_Left</LeftPointer> + <RightPointer>_Right</RightPointer> + <ValueNode Condition="_Isnil == 0" Name="[{_Myval.first}]">_Myval,view(MapHelper)</ValueNode> + </TreeItems> + </Expand> + </Type> + + <Type Name="std::pair<*, *>" IncludeView="MapHelper"> + <DisplayString>{second}</DisplayString> + </Type> + + <Type Name="QHashPrivate::Node<*,*>"> + <DisplayString>{value}</DisplayString> + <Expand> + <Item Name="key">key</Item> + <Item Name="value">value</Item> + </Expand> + </Type> + + <Type Name="QHashPrivate::MultiNode<*,*>"> + <DisplayString Condition="value->next == 0">{value->value}</DisplayString> + <DisplayString Condition="value->next != 0 && value->next->next == 0">({value->value}, {value->next->value})</DisplayString> + <DisplayString Condition="value->next != 0 && value->next->next != 0">({value->value}, {value->next->value}, ...)</DisplayString> + <Expand> + <LinkedListItems> + <HeadPointer>value</HeadPointer> + <NextPointer>next</NextPointer> + <ValueNode>value</ValueNode> + </LinkedListItems> + </Expand> + </Type> + + <Type Name="QHash<*,*>"> + <AlternativeType Name="QMultiHash<*,*>"/> + <Intrinsic Name="getOffset" Category="Method" Expression="d->spans[span].offsets[offset]"> + <Parameter Name="span" Type="int" /> + <Parameter Name="offset" Type="int" /> + </Intrinsic> + <Intrinsic Name="getKey" Category="Method" Expression="((Node*)(char *)&(d->spans[span].entries[d->spans[span].offsets[offset]].storage))->key"> + <Parameter Name="span" Type="int" /> + <Parameter Name="offset" Type="int" /> + </Intrinsic> + <Intrinsic Name="getNode" Category="Method" Expression="*((Node*)(char *)&(d->spans[span].entries[d->spans[span].offsets[offset]].storage))"> + <Parameter Name="span" Type="int" /> + <Parameter Name="offset" Type="int" /> + </Intrinsic> + + <DisplayString>{{ size={d->size} }}</DisplayString> + <Expand> + <CustomListItems MaxItemsPerView="5000"> + <Variable Name="iSpan" InitialValue="0" /> + <Variable Name="spanCount" InitialValue="d->numBuckets" /> + <Size>d->size</Size> + <Loop> + <If Condition="iSpan != spanCount"> + <Item Name="[{getKey(iSpan, 0)}]" Condition="getOffset(iSpan, 0) != 255">getNode(iSpan, 0)</Item> + <Item Name="[{getKey(iSpan, 1)}]" Condition="getOffset(iSpan, 1) != 255">getNode(iSpan, 1)</Item> + <Item Name="[{getKey(iSpan, 2)}]" Condition="getOffset(iSpan, 2) != 255">getNode(iSpan, 2)</Item> + <Item Name="[{getKey(iSpan, 3)}]" Condition="getOffset(iSpan, 3) != 255">getNode(iSpan, 3)</Item> + <Item Name="[{getKey(iSpan, 4)}]" Condition="getOffset(iSpan, 4) != 255">getNode(iSpan, 4)</Item> + <Item Name="[{getKey(iSpan, 5)}]" Condition="getOffset(iSpan, 5) != 255">getNode(iSpan, 5)</Item> + <Item Name="[{getKey(iSpan, 6)}]" Condition="getOffset(iSpan, 6) != 255">getNode(iSpan, 6)</Item> + <Item Name="[{getKey(iSpan, 7)}]" Condition="getOffset(iSpan, 7) != 255">getNode(iSpan, 7)</Item> + <Item Name="[{getKey(iSpan, 8)}]" Condition="getOffset(iSpan, 8) != 255">getNode(iSpan, 8)</Item> + <Item Name="[{getKey(iSpan, 9)}]" Condition="getOffset(iSpan, 9) != 255">getNode(iSpan, 9)</Item> + <Item Name="[{getKey(iSpan, 10)}]" Condition="getOffset(iSpan, 10) != 255">getNode(iSpan, 10)</Item> + <Item Name="[{getKey(iSpan, 11)}]" Condition="getOffset(iSpan, 11) != 255">getNode(iSpan, 11)</Item> + <Item Name="[{getKey(iSpan, 12)}]" Condition="getOffset(iSpan, 12) != 255">getNode(iSpan, 12)</Item> + <Item Name="[{getKey(iSpan, 13)}]" Condition="getOffset(iSpan, 13) != 255">getNode(iSpan, 13)</Item> + <Item Name="[{getKey(iSpan, 14)}]" Condition="getOffset(iSpan, 14) != 255">getNode(iSpan, 14)</Item> + <Item Name="[{getKey(iSpan, 15)}]" Condition="getOffset(iSpan, 15) != 255">getNode(iSpan, 15)</Item> + <Item Name="[{getKey(iSpan, 16)}]" Condition="getOffset(iSpan, 16) != 255">getNode(iSpan, 16)</Item> + <Item Name="[{getKey(iSpan, 17)}]" Condition="getOffset(iSpan, 17) != 255">getNode(iSpan, 17)</Item> + <Item Name="[{getKey(iSpan, 18)}]" Condition="getOffset(iSpan, 18) != 255">getNode(iSpan, 18)</Item> + <Item Name="[{getKey(iSpan, 19)}]" Condition="getOffset(iSpan, 19) != 255">getNode(iSpan, 19)</Item> + <Item Name="[{getKey(iSpan, 20)}]" Condition="getOffset(iSpan, 20) != 255">getNode(iSpan, 20)</Item> + <Item Name="[{getKey(iSpan, 21)}]" Condition="getOffset(iSpan, 21) != 255">getNode(iSpan, 21)</Item> + <Item Name="[{getKey(iSpan, 22)}]" Condition="getOffset(iSpan, 22) != 255">getNode(iSpan, 22)</Item> + <Item Name="[{getKey(iSpan, 23)}]" Condition="getOffset(iSpan, 23) != 255">getNode(iSpan, 23)</Item> + <Item Name="[{getKey(iSpan, 24)}]" Condition="getOffset(iSpan, 24) != 255">getNode(iSpan, 24)</Item> + <Item Name="[{getKey(iSpan, 25)}]" Condition="getOffset(iSpan, 25) != 255">getNode(iSpan, 25)</Item> + <Item Name="[{getKey(iSpan, 26)}]" Condition="getOffset(iSpan, 26) != 255">getNode(iSpan, 26)</Item> + <Item Name="[{getKey(iSpan, 27)}]" Condition="getOffset(iSpan, 27) != 255">getNode(iSpan, 27)</Item> + <Item Name="[{getKey(iSpan, 28)}]" Condition="getOffset(iSpan, 28) != 255">getNode(iSpan, 28)</Item> + <Item Name="[{getKey(iSpan, 29)}]" Condition="getOffset(iSpan, 29) != 255">getNode(iSpan, 29)</Item> + <Item Name="[{getKey(iSpan, 30)}]" Condition="getOffset(iSpan, 30) != 255">getNode(iSpan, 30)</Item> + <Item Name="[{getKey(iSpan, 31)}]" Condition="getOffset(iSpan, 31) != 255">getNode(iSpan, 31)</Item> + <Item Name="[{getKey(iSpan, 32)}]" Condition="getOffset(iSpan, 32) != 255">getNode(iSpan, 32)</Item> + <Item Name="[{getKey(iSpan, 33)}]" Condition="getOffset(iSpan, 33) != 255">getNode(iSpan, 33)</Item> + <Item Name="[{getKey(iSpan, 34)}]" Condition="getOffset(iSpan, 34) != 255">getNode(iSpan, 34)</Item> + <Item Name="[{getKey(iSpan, 35)}]" Condition="getOffset(iSpan, 35) != 255">getNode(iSpan, 35)</Item> + <Item Name="[{getKey(iSpan, 36)}]" Condition="getOffset(iSpan, 36) != 255">getNode(iSpan, 36)</Item> + <Item Name="[{getKey(iSpan, 37)}]" Condition="getOffset(iSpan, 37) != 255">getNode(iSpan, 37)</Item> + <Item Name="[{getKey(iSpan, 38)}]" Condition="getOffset(iSpan, 38) != 255">getNode(iSpan, 38)</Item> + <Item Name="[{getKey(iSpan, 39)}]" Condition="getOffset(iSpan, 39) != 255">getNode(iSpan, 39)</Item> + <Item Name="[{getKey(iSpan, 40)}]" Condition="getOffset(iSpan, 40) != 255">getNode(iSpan, 40)</Item> + <Item Name="[{getKey(iSpan, 41)}]" Condition="getOffset(iSpan, 41) != 255">getNode(iSpan, 41)</Item> + <Item Name="[{getKey(iSpan, 42)}]" Condition="getOffset(iSpan, 42) != 255">getNode(iSpan, 42)</Item> + <Item Name="[{getKey(iSpan, 43)}]" Condition="getOffset(iSpan, 43) != 255">getNode(iSpan, 43)</Item> + <Item Name="[{getKey(iSpan, 44)}]" Condition="getOffset(iSpan, 44) != 255">getNode(iSpan, 44)</Item> + <Item Name="[{getKey(iSpan, 45)}]" Condition="getOffset(iSpan, 45) != 255">getNode(iSpan, 45)</Item> + <Item Name="[{getKey(iSpan, 46)}]" Condition="getOffset(iSpan, 46) != 255">getNode(iSpan, 46)</Item> + <Item Name="[{getKey(iSpan, 47)}]" Condition="getOffset(iSpan, 47) != 255">getNode(iSpan, 47)</Item> + <Item Name="[{getKey(iSpan, 48)}]" Condition="getOffset(iSpan, 48) != 255">getNode(iSpan, 48)</Item> + <Item Name="[{getKey(iSpan, 49)}]" Condition="getOffset(iSpan, 49) != 255">getNode(iSpan, 49)</Item> + <Item Name="[{getKey(iSpan, 50)}]" Condition="getOffset(iSpan, 50) != 255">getNode(iSpan, 50)</Item> + <Item Name="[{getKey(iSpan, 51)}]" Condition="getOffset(iSpan, 51) != 255">getNode(iSpan, 51)</Item> + <Item Name="[{getKey(iSpan, 52)}]" Condition="getOffset(iSpan, 52) != 255">getNode(iSpan, 52)</Item> + <Item Name="[{getKey(iSpan, 53)}]" Condition="getOffset(iSpan, 53) != 255">getNode(iSpan, 53)</Item> + <Item Name="[{getKey(iSpan, 54)}]" Condition="getOffset(iSpan, 54) != 255">getNode(iSpan, 54)</Item> + <Item Name="[{getKey(iSpan, 55)}]" Condition="getOffset(iSpan, 55) != 255">getNode(iSpan, 55)</Item> + <Item Name="[{getKey(iSpan, 56)}]" Condition="getOffset(iSpan, 56) != 255">getNode(iSpan, 56)</Item> + <Item Name="[{getKey(iSpan, 57)}]" Condition="getOffset(iSpan, 57) != 255">getNode(iSpan, 57)</Item> + <Item Name="[{getKey(iSpan, 58)}]" Condition="getOffset(iSpan, 58) != 255">getNode(iSpan, 58)</Item> + <Item Name="[{getKey(iSpan, 59)}]" Condition="getOffset(iSpan, 59) != 255">getNode(iSpan, 59)</Item> + <Item Name="[{getKey(iSpan, 60)}]" Condition="getOffset(iSpan, 60) != 255">getNode(iSpan, 60)</Item> + <Item Name="[{getKey(iSpan, 61)}]" Condition="getOffset(iSpan, 61) != 255">getNode(iSpan, 61)</Item> + <Item Name="[{getKey(iSpan, 62)}]" Condition="getOffset(iSpan, 62) != 255">getNode(iSpan, 62)</Item> + <Item Name="[{getKey(iSpan, 63)}]" Condition="getOffset(iSpan, 63) != 255">getNode(iSpan, 63)</Item> + <Item Name="[{getKey(iSpan, 64)}]" Condition="getOffset(iSpan, 64) != 255">getNode(iSpan, 64)</Item> + <Item Name="[{getKey(iSpan, 65)}]" Condition="getOffset(iSpan, 65) != 255">getNode(iSpan, 65)</Item> + <Item Name="[{getKey(iSpan, 66)}]" Condition="getOffset(iSpan, 66) != 255">getNode(iSpan, 66)</Item> + <Item Name="[{getKey(iSpan, 67)}]" Condition="getOffset(iSpan, 67) != 255">getNode(iSpan, 67)</Item> + <Item Name="[{getKey(iSpan, 68)}]" Condition="getOffset(iSpan, 68) != 255">getNode(iSpan, 68)</Item> + <Item Name="[{getKey(iSpan, 69)}]" Condition="getOffset(iSpan, 69) != 255">getNode(iSpan, 69)</Item> + <Item Name="[{getKey(iSpan, 70)}]" Condition="getOffset(iSpan, 70) != 255">getNode(iSpan, 70)</Item> + <Item Name="[{getKey(iSpan, 71)}]" Condition="getOffset(iSpan, 71) != 255">getNode(iSpan, 71)</Item> + <Item Name="[{getKey(iSpan, 72)}]" Condition="getOffset(iSpan, 72) != 255">getNode(iSpan, 72)</Item> + <Item Name="[{getKey(iSpan, 73)}]" Condition="getOffset(iSpan, 73) != 255">getNode(iSpan, 73)</Item> + <Item Name="[{getKey(iSpan, 74)}]" Condition="getOffset(iSpan, 74) != 255">getNode(iSpan, 74)</Item> + <Item Name="[{getKey(iSpan, 75)}]" Condition="getOffset(iSpan, 75) != 255">getNode(iSpan, 75)</Item> + <Item Name="[{getKey(iSpan, 76)}]" Condition="getOffset(iSpan, 76) != 255">getNode(iSpan, 76)</Item> + <Item Name="[{getKey(iSpan, 77)}]" Condition="getOffset(iSpan, 77) != 255">getNode(iSpan, 77)</Item> + <Item Name="[{getKey(iSpan, 78)}]" Condition="getOffset(iSpan, 78) != 255">getNode(iSpan, 78)</Item> + <Item Name="[{getKey(iSpan, 79)}]" Condition="getOffset(iSpan, 79) != 255">getNode(iSpan, 79)</Item> + <Item Name="[{getKey(iSpan, 80)}]" Condition="getOffset(iSpan, 80) != 255">getNode(iSpan, 80)</Item> + <Item Name="[{getKey(iSpan, 81)}]" Condition="getOffset(iSpan, 81) != 255">getNode(iSpan, 81)</Item> + <Item Name="[{getKey(iSpan, 82)}]" Condition="getOffset(iSpan, 82) != 255">getNode(iSpan, 82)</Item> + <Item Name="[{getKey(iSpan, 83)}]" Condition="getOffset(iSpan, 83) != 255">getNode(iSpan, 83)</Item> + <Item Name="[{getKey(iSpan, 84)}]" Condition="getOffset(iSpan, 84) != 255">getNode(iSpan, 84)</Item> + <Item Name="[{getKey(iSpan, 85)}]" Condition="getOffset(iSpan, 85) != 255">getNode(iSpan, 85)</Item> + <Item Name="[{getKey(iSpan, 86)}]" Condition="getOffset(iSpan, 86) != 255">getNode(iSpan, 86)</Item> + <Item Name="[{getKey(iSpan, 87)}]" Condition="getOffset(iSpan, 87) != 255">getNode(iSpan, 87)</Item> + <Item Name="[{getKey(iSpan, 88)}]" Condition="getOffset(iSpan, 88) != 255">getNode(iSpan, 88)</Item> + <Item Name="[{getKey(iSpan, 89)}]" Condition="getOffset(iSpan, 89) != 255">getNode(iSpan, 89)</Item> + <Item Name="[{getKey(iSpan, 90)}]" Condition="getOffset(iSpan, 90) != 255">getNode(iSpan, 90)</Item> + <Item Name="[{getKey(iSpan, 91)}]" Condition="getOffset(iSpan, 91) != 255">getNode(iSpan, 91)</Item> + <Item Name="[{getKey(iSpan, 92)}]" Condition="getOffset(iSpan, 92) != 255">getNode(iSpan, 92)</Item> + <Item Name="[{getKey(iSpan, 93)}]" Condition="getOffset(iSpan, 93) != 255">getNode(iSpan, 93)</Item> + <Item Name="[{getKey(iSpan, 94)}]" Condition="getOffset(iSpan, 94) != 255">getNode(iSpan, 94)</Item> + <Item Name="[{getKey(iSpan, 95)}]" Condition="getOffset(iSpan, 95) != 255">getNode(iSpan, 95)</Item> + <Item Name="[{getKey(iSpan, 96)}]" Condition="getOffset(iSpan, 96) != 255">getNode(iSpan, 96)</Item> + <Item Name="[{getKey(iSpan, 97)}]" Condition="getOffset(iSpan, 97) != 255">getNode(iSpan, 97)</Item> + <Item Name="[{getKey(iSpan, 98)}]" Condition="getOffset(iSpan, 98) != 255">getNode(iSpan, 98)</Item> + <Item Name="[{getKey(iSpan, 99)}]" Condition="getOffset(iSpan, 99) != 255">getNode(iSpan, 99)</Item> + <Item Name="[{getKey(iSpan, 100)}]" Condition="getOffset(iSpan, 100) != 255">getNode(iSpan, 100)</Item> + <Item Name="[{getKey(iSpan, 101)}]" Condition="getOffset(iSpan, 101) != 255">getNode(iSpan, 101)</Item> + <Item Name="[{getKey(iSpan, 102)}]" Condition="getOffset(iSpan, 102) != 255">getNode(iSpan, 102)</Item> + <Item Name="[{getKey(iSpan, 103)}]" Condition="getOffset(iSpan, 103) != 255">getNode(iSpan, 103)</Item> + <Item Name="[{getKey(iSpan, 104)}]" Condition="getOffset(iSpan, 104) != 255">getNode(iSpan, 104)</Item> + <Item Name="[{getKey(iSpan, 105)}]" Condition="getOffset(iSpan, 105) != 255">getNode(iSpan, 105)</Item> + <Item Name="[{getKey(iSpan, 106)}]" Condition="getOffset(iSpan, 106) != 255">getNode(iSpan, 106)</Item> + <Item Name="[{getKey(iSpan, 107)}]" Condition="getOffset(iSpan, 107) != 255">getNode(iSpan, 107)</Item> + <Item Name="[{getKey(iSpan, 108)}]" Condition="getOffset(iSpan, 108) != 255">getNode(iSpan, 108)</Item> + <Item Name="[{getKey(iSpan, 109)}]" Condition="getOffset(iSpan, 109) != 255">getNode(iSpan, 109)</Item> + <Item Name="[{getKey(iSpan, 110)}]" Condition="getOffset(iSpan, 110) != 255">getNode(iSpan, 110)</Item> + <Item Name="[{getKey(iSpan, 111)}]" Condition="getOffset(iSpan, 111) != 255">getNode(iSpan, 111)</Item> + <Item Name="[{getKey(iSpan, 112)}]" Condition="getOffset(iSpan, 112) != 255">getNode(iSpan, 112)</Item> + <Item Name="[{getKey(iSpan, 113)}]" Condition="getOffset(iSpan, 113) != 255">getNode(iSpan, 113)</Item> + <Item Name="[{getKey(iSpan, 114)}]" Condition="getOffset(iSpan, 114) != 255">getNode(iSpan, 114)</Item> + <Item Name="[{getKey(iSpan, 115)}]" Condition="getOffset(iSpan, 115) != 255">getNode(iSpan, 115)</Item> + <Item Name="[{getKey(iSpan, 116)}]" Condition="getOffset(iSpan, 116) != 255">getNode(iSpan, 116)</Item> + <Item Name="[{getKey(iSpan, 117)}]" Condition="getOffset(iSpan, 117) != 255">getNode(iSpan, 117)</Item> + <Item Name="[{getKey(iSpan, 118)}]" Condition="getOffset(iSpan, 118) != 255">getNode(iSpan, 118)</Item> + <Item Name="[{getKey(iSpan, 119)}]" Condition="getOffset(iSpan, 119) != 255">getNode(iSpan, 119)</Item> + <Item Name="[{getKey(iSpan, 120)}]" Condition="getOffset(iSpan, 120) != 255">getNode(iSpan, 120)</Item> + <Item Name="[{getKey(iSpan, 121)}]" Condition="getOffset(iSpan, 121) != 255">getNode(iSpan, 121)</Item> + <Item Name="[{getKey(iSpan, 122)}]" Condition="getOffset(iSpan, 122) != 255">getNode(iSpan, 122)</Item> + <Item Name="[{getKey(iSpan, 123)}]" Condition="getOffset(iSpan, 123) != 255">getNode(iSpan, 123)</Item> + <Item Name="[{getKey(iSpan, 124)}]" Condition="getOffset(iSpan, 124) != 255">getNode(iSpan, 124)</Item> + <Item Name="[{getKey(iSpan, 125)}]" Condition="getOffset(iSpan, 125) != 255">getNode(iSpan, 125)</Item> + <Item Name="[{getKey(iSpan, 126)}]" Condition="getOffset(iSpan, 126) != 255">getNode(iSpan, 126)</Item> + <Item Name="[{getKey(iSpan, 127)}]" Condition="getOffset(iSpan, 127) != 255">getNode(iSpan, 127)</Item> + <Exec>iSpan++</Exec> + </If> + </Loop> + </CustomListItems> + </Expand> + </Type> + + <Type Name="QSet<*>"> + <DisplayString>{{ size={q_hash.d->size} }}</DisplayString> + <Expand> + <ExpandedItem>q_hash</ExpandedItem> + </Expand> + </Type> + + <Type Name="QVariant"> + <Intrinsic Name="typeId" Expression="*(int*)(&((const QtPrivate::QMetaTypeInterface *)(d.packedType << 2))->typeId)"> + </Intrinsic> + <Intrinsic Name="dataStar" Expression="(&(d.data.data))"> + </Intrinsic> + <Intrinsic Name="sharedDataStar" Expression="(d.is_shared ? reinterpret_cast<const void *>((size_t)(d.data.shared) + d.data.shared->offset) : (&(d.data.data)))"> + </Intrinsic> + + <DisplayString Condition="d.is_null">(null)</DisplayString> + + <!-- Static core pointers --> + <DisplayString Condition="typeId() == QMetaType::QObjectStar">QObject*</DisplayString> + + <!-- Static core template classes --> + <DisplayString Condition="typeId() == QMetaType::QVariantMap">{*(QMap<QString,QVariant>*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QVariantList">{*(QList<QVariant>*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QVariantHash">{*(QHash<QString,QVariant>*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QVariantPair">QVariantPair</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QByteArrayList">{*(QList<QByteArray>*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QStringList">{*(QList<QString>*) sharedDataStar()}</DisplayString> + + <!-- Static primitives--> + <DisplayString Condition="typeId() == QMetaType::Bool">{*(bool*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::Int">{*(int*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::UInt">{*(unsigned int*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::LongLong">{*(long long*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::ULongLong">{*(unsigned long long*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::Double">{*(double*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::VoidStar">{*(void**) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::Long">{*(long*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::Short">{*(short*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::Char">{*(char*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::Char16">{*(char16_t*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::Char32">{*(char32_t*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::ULong">{*(unsigned long*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::UShort">{*(unsigned short*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::UChar">{*(unsigned char*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::Float">{*(float*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::SChar">{*(signed char*) dataStar()}</DisplayString> + + <!-- Static core classes --> + <DisplayString Condition="typeId() == QMetaType::QChar">{*(QChar*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QString">{*(QString*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QByteArray">{*(QByteArray*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QDate">{*(QDate*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QTime">{*(QTime*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QDateTime">QDateTime</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QUrl">QUrl</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QLocale">QLocale</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QRect">{*(QRect*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QRectF">{*(QRectF*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QSize">{*(QSize*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QSizeF">{*(QSizeF*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QLine">{*(QLine*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QLineF">{*(QLineF*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QPoint">{*(QPoint*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QPointF">{*(QPointF*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QEasingCurve">EasingCurve</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QUuid">Uuid</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QRegularExpression">RegularExpression</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QJsonValue">QJsonValue</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QJsonObject">QJsonObject</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QJsonArray">QJsonArray</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QJsonDocument">QJsonDocument</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QCborValue">QCborValue</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QCborArray">QCborArray</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QCborMap">QCborMap</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QModelIndex">ModelIndex</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QPersistentModelIndex">QPersistentModelIndex</DisplayString> + + <!-- Static gui classes --> + <DisplayString Condition="typeId() == QMetaType::QFont">QFont</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QPixmap">QPixmap</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QBrush">QBrush</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QColor">QColor</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QPalette">QPalette</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QIcon">QIcon</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QImage">QImage</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QPolygon">QPolygon</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QRegion">QRegion</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QBitmap">QBitmap</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QCursor">QCursor</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QKeySequence">QKeySequence</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QPen">QPen</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QTextLength">QTextLength</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QTextFormat">QTextFormat</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QTransform">QTransform</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QMatrix4x4">QMatrix4x4</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QVector2D">QVector2D</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QVector3D">QVector3D</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QVector4D">QVector4D</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QQuaternion">QQuaternion</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QPolygonF">QPolygonF</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QColorSpace">QColorSpace</DisplayString> + + <!-- Static widget classes --> + <DisplayString Condition="typeId() == QMetaType::QSizePolicy">QSizePolicy</DisplayString> + + <!-- Unhandled : display the typeId--> + <DisplayString>QMetaType::Type ({typeId()})</DisplayString> + + <Expand> + <ExpandedItem Condition="typeId() == QMetaType::QString">*(QString*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QByteArray">*(QByteArray*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QDate">*(QDate*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QTime">*(QTime*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QRect">*(QRect*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QRectF">*(QRectF*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QSize">*(QSize*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QSizeF">*(QSizeF*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QLine">*(QLine*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QLineF">*(QLineF*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QPoint">*(QPoint*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QPointF">*(QPointF*) sharedDataStar()</ExpandedItem> + + <ExpandedItem Condition="typeId() == QMetaType::QVariantMap">*(QMap<QString,QVariant>*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QVariantList">*(QList<QVariant>*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QVariantHash">*(QHash<QString,QVariant>*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QByteArrayList">*(QList<QByteArray>*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QStringList">*(QList<QString>*) sharedDataStar()</ExpandedItem> + </Expand> + </Type> + +</AutoVisualizer> diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..067b8fd --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,38 @@ +{ + "files.autoSave": "onFocusChange", + "editor.fontSize": 15, + "editor.fontFamily": "'Operator Mono Lig', 'Operator Mono Lig', 'Operator Mono Lig'", + "cmake.configureOnOpen": true, + "cmake.debugConfig": { + "console": "integratedTerminal", + "visualizerFile": "${workspaceRoot}/.vscode/qt5.natvis" + }, + "cmake.environment": { + "PATH": "${env:PATH};/bin" + }, + "cmake.configureSettings": { + "CMAKE_TOOLCHAIN_FILE": "${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + }, + "cmake.options.statusBarVisibility": "visible", + "cmake.generator": "Ninja", + "C_Cpp.intelliSenseEngine": "disabled", + "clangd.arguments": [ + "--header-insertion=never", + "--all-scopes-completion", + "--completion-style=detailed", + "--clang-tidy", + "-j=4", + "--pch-storage=memory", + "--compile-commands-dir=build", + "--background-index", + "--ranking-model=heuristics", + "--function-arg-placeholders=false", + "--query-driver=repaceE" + ], + "editor.inlayHints.enabled": "off", + "editor.unicodeHighlight.allowedLocales": { + "ja": true, + "zh-hant": true, + "zh-hans": true + } +} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..5172148 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,83 @@ +cmake_minimum_required(VERSION 3.5) + +project(FTPTrans VERSION 0.1 LANGUAGES CXX) + +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) +find_package(CURL REQUIRED) +find_path(SIMPLEINI_INCLUDE_DIRS ")ConvertUTF.c") + +if (MSVC) + if(${QT_VERSION_MAJOR} LESS 6) + add_compile_options(/source-charset:utf-8) + endif() + add_compile_options(/EHsc) + add_compile_options(-D_CRT_SECURE_NO_WARNINGS) +endif() + +set(PROJECT_SOURCES + src/main.cpp + src/ConfigOpr.cpp src/ConfigOpr.h + src/FTPTrans.h src/FTPTrans.cpp + src/FTPTrans.qrc src/FTPTrans.rc + src/FTPTrans.ui +) + +if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) + qt_add_executable(FTPTrans + MANUAL_FINALIZATION + ${PROJECT_SOURCES} + ) +# Define target properties for Android with Qt 6 as: +# set_property(TARGET FTPTrans APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR +# ${CMAKE_CURRENT_SOURCE_DIR}/android) +# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation +else() + if(ANDROID) + add_library(FTPTrans SHARED + ${PROJECT_SOURCES} + ) +# Define properties for Android with Qt 5 after find_package() calls as: +# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") + else() + add_executable(FTPTrans + ${PROJECT_SOURCES} + ) + endif() +endif() + +target_link_libraries(FTPTrans PRIVATE Qt${QT_VERSION_MAJOR}::Widgets) +target_link_libraries(FTPTrans PRIVATE CURL::libcurl) +#target_include_directories(FTPTrans PRIVATE ${SIMPLEINI_INCLUDE_DIRS}) + +# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. +# If you are developing for iOS or macOS you should consider setting an +# explicit, fixed bundle identifier manually though. +if(${QT_VERSION} VERSION_LESS 6.1.0) + set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.FTPTrans) +endif() +set_target_properties(FTPTrans PROPERTIES + ${BUNDLE_ID_OPTION} + MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} + MACOSX_BUNDLE TRUE + WIN32_EXECUTABLE TRUE +) + +include(GNUInstallDirs) +install(TARGETS FTPTrans + BUNDLE DESTINATION . + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +if(QT_VERSION_MAJOR EQUAL 6) + qt_finalize_executable(FTPTrans) +endif() diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1770a61 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# FTPTrans + +## 介绍 + +传输文件的FTP工具。 + +## 构建说明 + +- 使用VCPKG,使用`cmake`生成时指定`CMAKE_TOOLCHAIN_FILE`。 + +使用组件有:`curl(8.7.1)`、`simpleini(4.22)`、`qt(5.15.13)`,括号版本是实际在用的版本。 + +```shell +-DCMAKE_TOOLCHAIN_FILE=${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake +``` + +或者 + +```shell +-DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%/scripts/buildsystems/vcpkg.cmake +``` diff --git a/src/ConfigOpr.cpp b/src/ConfigOpr.cpp new file mode 100644 index 0000000..48de184 --- /dev/null +++ b/src/ConfigOpr.cpp @@ -0,0 +1,161 @@ +#include "ConfigOpr.h" +#include <cassert> + +constexpr const char* KEY_PWD = "Password"; +constexpr const char* KEY_IP = "IP"; +constexpr const char* KEY_ITEMCNT = "ItemCnt"; +constexpr const char* KEY_USERNAME = "Username"; +constexpr const char* KEY_PORT = "Port"; +constexpr const char* HEAD_BASIC = "Basic"; +constexpr const char* HEAD_ITEM = "Item"; +constexpr const char* KEY_SOURCE = "Source"; +constexpr const char* KEY_DES = "Des"; +constexpr const char* KEY_ENABLE = "Enable"; + +ConfigOpr::ConfigOpr() +{ + std::string home = get_home(); + fs::path config_dir = fs::path(home).append(".config").append("FTPTrans"); + auto ini_path = fs::path(config_dir).append("config.ini"); + std::snprintf(ini_path_, sizeof(ini_path_), "%s", ini_path.string().c_str()); + + if (!fs::exists(config_dir)) { + fs::create_directories(config_dir); + } + if (!fs::exists(ini_path_)) { + generate_default(); + return; + } +} + +void ConfigOpr::push(const ItemContent& item) +{ + check_open(); + + std::string new_name(HEAD_ITEM); + new_name += std::to_string(item.id); + + ini_.SetValue(new_name.c_str(), KEY_SOURCE, item.source.c_str()); + ini_.SetValue(new_name.c_str(), KEY_DES, item.des.c_str()); + ini_.SetBoolValue(new_name.c_str(), KEY_ENABLE, true); + + save(); +} + +bool ConfigOpr::update(int id, const ItemContent* ptem, bool enable) +{ + check_open(); + + long cnt = ini_.GetLongValue(HEAD_BASIC, KEY_ITEMCNT); + if (id > cnt) { + return false; + } + + std::string new_name(HEAD_ITEM); + new_name += std::to_string(id); + + if (!enable) { + bool ret = ini_.SetBoolValue(new_name.c_str(), KEY_ENABLE, false) == SI_UPDATED; + assert(ret); + save(); + return true; + } + + if (!ptem) { + return false; + } + + ini_.SetValue(new_name.c_str(), KEY_SOURCE, ptem->source.c_str()); + ini_.SetValue(new_name.c_str(), KEY_DES, ptem->des.c_str()); + ini_.SetBoolValue(new_name.c_str(), KEY_ENABLE, true); + + save(); + + return true; +} + +long ConfigOpr::get_count() +{ + check_open(); + + long cnt = ini_.GetLongValue(HEAD_BASIC, KEY_ITEMCNT); + return cnt; +} + +bool ConfigOpr::get_content(int id, ItemContent& item) +{ + check_open(); + + long cnt = ini_.GetLongValue(HEAD_BASIC, KEY_ITEMCNT); + if (id > cnt) { + return false; + } + std::string new_name(HEAD_ITEM); + new_name += std::to_string(id); + + item.enable = ini_.GetBoolValue(new_name.c_str(), KEY_ENABLE); + item.des = ini_.GetValue(new_name.c_str(), KEY_DES); + item.source = ini_.GetValue(new_name.c_str(), KEY_SOURCE); + item.id = id; + return true; +} + +bool ConfigOpr::get_base(ItemBase& base) +{ + check_open(); + base.cnt = ini_.GetLongValue(HEAD_BASIC, KEY_ITEMCNT); + base.ip.append(ini_.GetValue(HEAD_BASIC, KEY_IP)); + base.port = std::stoi(ini_.GetValue(HEAD_BASIC, KEY_PORT)); + base.pwd.append(ini_.GetValue(HEAD_BASIC, KEY_PWD)); + base.user.append(ini_.GetValue(HEAD_BASIC, KEY_USERNAME)); + return true; +} + +bool ConfigOpr::set_base(const ItemBase& base) +{ + check_open(); + ini_.SetLongValue(HEAD_BASIC, KEY_ITEMCNT, base.cnt); + ini_.SetValue(HEAD_BASIC, KEY_IP, base.ip.c_str()); + ini_.SetLongValue(HEAD_BASIC, KEY_PORT, base.port); + ini_.SetValue(HEAD_BASIC, KEY_USERNAME, base.user.c_str()); + ini_.SetValue(HEAD_BASIC, KEY_PWD, base.pwd.c_str()); + save(); + return true; +} + +std::string ConfigOpr::get_home() +{ +#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__) + return std::getenv("USERPROFILE"); +#else + const char* homedir = getenv("HOME"); + if (homedir) { + return std::string(homedir); + } + return ""; +#endif +} + +void ConfigOpr::generate_default() +{ + ini_.SetLongValue(HEAD_BASIC, KEY_ITEMCNT, 0); + ini_.SetValue(HEAD_BASIC, KEY_IP, "192.168.0.9"); + ini_.SetLongValue(HEAD_BASIC, KEY_PORT, 21); + ini_.SetValue(HEAD_BASIC, KEY_USERNAME, "lebo"); + ini_.SetValue(HEAD_BASIC, KEY_PWD, "123456"); + ini_.SaveFile(ini_path_); +} + +void ConfigOpr::check_open() +{ + if (ini_.IsEmpty()) { + bool ret = (ini_.LoadFile(ini_path_) == SI_OK); + assert(ret); + } +} + +void ConfigOpr::save() +{ + bool ret = ini_.SaveFile(ini_path_) == SI_OK; + assert(ret); +} diff --git a/src/ConfigOpr.h b/src/ConfigOpr.h new file mode 100644 index 0000000..2a67b47 --- /dev/null +++ b/src/ConfigOpr.h @@ -0,0 +1,50 @@ +#pragma once + +#include <string> +#include <filesystem> +#include <SimpleIni.h> + +namespace fs = std::filesystem; + +struct ItemBase { + std::string ip{}; + int port{}; + long cnt{}; + std::string user{}; + std::string pwd{}; +}; + +struct ItemContent +{ + int id{}; + bool enable{ false }; + std::string source{}; + std::string des{}; + std::string des_full{}; +}; + +class ConfigOpr +{ +public: + ConfigOpr(); + ~ConfigOpr() = default; + +public: + void push(const ItemContent& item); + bool update(int id, const ItemContent* ptem, bool enable = true); + long get_count(); + bool get_content(int id, ItemContent& item); + bool get_base(ItemBase& base); + bool set_base(const ItemBase& base); + +private: + std::string get_home(); + void generate_default(); + void check_open(); + void save(); + +private: + char ini_path_[512]{}; + CSimpleIniA ini_{}; +}; + diff --git a/src/FTPTrans.cpp b/src/FTPTrans.cpp new file mode 100644 index 0000000..5bdb817 --- /dev/null +++ b/src/FTPTrans.cpp @@ -0,0 +1,232 @@ +#include "FTPTrans.h" +#include <curl/curl.h> + +FTPTrans::FTPTrans(QWidget* parent) : QWidget(parent) +{ + ui.setupUi(this); + + ini_opr_ = new ConfigOpr(); + + setWindowTitle("FTPTrans v1.0.2"); + + init(); + + connect(ui.btnSave, &QPushButton::clicked, this, [&]() { save(true); }); + connect(ui.btnAdd, &QPushButton::clicked, [&]() { handle_table_add(); }); + connect(ui.btnUpdate, &QPushButton::clicked, [&]() { Trans(); }); + connect(ui.btnDown, &QPushButton::clicked, [&]() { Trans(false); }); +} + +void FTPTrans::save(bool is_notify) +{ + ini_base_.ip = ui.edIP->text().toStdString(); + ini_base_.port = ui.edPort->text().toInt(); + ini_base_.pwd = ui.edPwd->text().toStdString(); + ini_base_.user = ui.edUserName->text().toStdString(); + ini_base_.cnt = ui.tableWidget->rowCount(); + + ini_opr_->set_base(ini_base_); + + for (int i = 0; i < ini_base_.cnt; ++i) { + ItemContent content; + content.id = ui.tableWidget->item(i, 0)->text().toInt(); + content.source.append(ui.tableWidget->item(i, 1)->text().toLocal8Bit()); + content.des.append(ui.tableWidget->item(i, 2)->text().toLocal8Bit()); + ini_opr_->update(content.id, &content); + } + + if (is_notify) { + QMessageBox::information(this, u8"提示", u8"已存储"); + } +} + +FTPTrans::~FTPTrans() +{ + delete ini_opr_; +} + +size_t readFunc(void* ptr, size_t size, size_t nmemb, FILE* stream) +{ + return fread(ptr, size, nmemb, stream); +} + +size_t writeFunc(void* ptr, size_t size, size_t nmemb, FILE* stream) +{ + return fwrite(ptr, size, nmemb, stream); +} + +void FTPTrans::Trans(bool is_up) +{ + if (is_up) { + if (!is_ok(this, u8"确认上传同步吗?")) { + return; + } + } else { + if (!is_ok(this, u8"确认下载同步吗?")) { + return; + } + } + + CURL* curl = nullptr; + + QList<QTableWidgetItem*> selectedItems = ui.tableWidget->selectedItems(); + if (selectedItems.size() != 3) { + QMessageBox::information(this, u8"提示", u8"未有选中数据"); + return; + } + + std::string source(selectedItems[1]->text().toLocal8Bit()); + std::string des(selectedItems[2]->text().toLocal8Bit()); + std::string user(ui.edUserName->text().toStdString()); + std::string pwd(ui.edPwd->text().toStdString()); + + try { + curl_global_init(CURL_GLOBAL_ALL); + + std::uintmax_t file_size{}; + if (is_up) { + fs::path source_file(source); + if (!fs::exists(source_file)) { + QMessageBox::information(this, u8"提示", QString::fromStdString(u8"文件不存在:" + source_file.string())); + return; + } + file_size = fs::file_size(source_file); + } + + curl = curl_easy_init(); + if (curl == nullptr) { + QMessageBox::information(this, u8"提示", u8"curl_easy_init 初始化失败"); + return; + } + + FILE* fd = nullptr; + if (is_up) { + fd = fopen(source.c_str(), "rb"); + } else { + fd = fopen(source.c_str(), "wb"); + } + + if (!fd) { + QMessageBox::information(this, u8"提示", QString::fromStdString(u8"文件打开失败:" + source)); + return; + } + + if (is_up) { + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); + } + + curl_easy_setopt(curl, CURLOPT_URL, des.c_str()); + curl_easy_setopt(curl, CURLOPT_USERNAME, user.c_str()); + curl_easy_setopt(curl, CURLOPT_PASSWORD, pwd.c_str()); + + if (is_up) { + curl_easy_setopt(curl, CURLOPT_READFUNCTION, readFunc); + curl_easy_setopt(curl, CURLOPT_READDATA, fd); + } else { + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeFunc); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, fd); + } + + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + + if (is_up) { + curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, file_size); + } + + if (10) { + curl_easy_setopt(curl, CURLOPT_FTP_RESPONSE_TIMEOUT, 10); + } + + CURLcode r = curl_easy_perform(curl); + fclose(fd); + + if (r != CURLE_OK) { + QMessageBox::information(this, u8"错误提示", QString::fromLocal8Bit(curl_easy_strerror(r))); + return; + } + } catch (...) { + QMessageBox::information(this, u8"异常", u8"产生了异常"); + return; + } + + if (curl) { + curl_easy_cleanup(curl); + } + curl_global_cleanup(); + save(false); + QMessageBox::information(this, u8"提示", u8"完成"); +} + +void FTPTrans::init() +{ + ini_opr_->get_base(ini_base_); + ui.edIP->setText(QString::fromStdString(ini_base_.ip)); + ui.edPort->setText(QString::number(ini_base_.port)); + ui.edPwd->setText(QString::fromStdString(ini_base_.pwd)); + ui.edUserName->setText(QString::fromStdString(ini_base_.user)); + + QStringList headers; + headers << u8"标识号" << u8"源位置(本地)" << u8"目的位置(FTP位置)"; + ui.tableWidget->setColumnCount(headers.size()); + ui.tableWidget->setHorizontalHeaderLabels(headers); + + ui.tableWidget->setColumnWidth(0, 80); + ui.tableWidget->setColumnWidth(1, 450); + ui.tableWidget->horizontalHeader()->setStretchLastSection(true); + ui.tableWidget->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection); + ui.tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + ui.tableWidget->verticalHeader()->setVisible(false); + + ui.btnAdd->setMinimumHeight(35); + ui.btnDown->setMinimumHeight(35); + ui.btnSave->setMinimumHeight(35); + ui.btnUpdate->setMinimumHeight(35); + + handle_table_read(); +} + +void FTPTrans::handle_table_read() +{ + int cnt = ini_opr_->get_count(); + for (int i = 1; i < cnt + 1; ++i) { + ItemContent content; + ini_opr_->get_content(i, content); + int rowCnt = ui.tableWidget->rowCount(); + ui.tableWidget->insertRow(rowCnt); + QTableWidgetItem* item0 = new QTableWidgetItem(QString::number(content.id)); + item0->setFlags(item0->flags() & ~Qt::ItemIsEditable); + ui.tableWidget->setItem(rowCnt, 0, item0); + QTableWidgetItem* item1 = new QTableWidgetItem(QString::fromLocal8Bit(content.source.c_str())); + ui.tableWidget->setItem(rowCnt, 1, item1); + QTableWidgetItem* item2 = new QTableWidgetItem(QString::fromLocal8Bit(content.des.c_str())); + ui.tableWidget->setItem(rowCnt, 2, item2); + } +} + +void FTPTrans::handle_table_add() +{ + int rowCnt = ui.tableWidget->rowCount(); + ui.tableWidget->insertRow(rowCnt); + QTableWidgetItem* item0 = new QTableWidgetItem(QString::number(rowCnt + 1)); + item0->setFlags(item0->flags() & ~Qt::ItemIsEditable); + ui.tableWidget->setItem(rowCnt, 0, item0); + QTableWidgetItem* item1 = new QTableWidgetItem(""); + ui.tableWidget->setItem(rowCnt, 1, item1); + QTableWidgetItem* item2 = new QTableWidgetItem(""); + ui.tableWidget->setItem(rowCnt, 2, item2); +} + +bool FTPTrans::is_ok(QWidget* parent, const QString& content) +{ + QMessageBox questionBox(parent); + questionBox.setText(content); + questionBox.setWindowTitle(u8"提示"); + questionBox.setIcon(QMessageBox::Question); + questionBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + int result = questionBox.exec(); + if (result != QMessageBox::Yes) { + return false; + } else { + return true; + } +} diff --git a/src/FTPTrans.h b/src/FTPTrans.h new file mode 100644 index 0000000..0667d5e --- /dev/null +++ b/src/FTPTrans.h @@ -0,0 +1,29 @@ +#pragma once + +#include <QtWidgets/QWidget> +#include "ui_FTPTrans.h" +#include "ConfigOpr.h" +#include <QMessageBox> + +class FTPTrans : public QWidget +{ + Q_OBJECT + +public: + FTPTrans(QWidget *parent = nullptr); + ~FTPTrans(); + +public: + void Trans(bool is_up = true); + void init(); + void handle_table_read(); + void handle_table_add(); + void save(bool is_notify = false); + +private: + bool is_ok(QWidget* parent, const QString& content); +private: + Ui::FTPTransClass ui; + ConfigOpr* ini_opr_{}; + ItemBase ini_base_{}; +}; diff --git a/src/FTPTrans.ico b/src/FTPTrans.ico new file mode 100644 index 0000000..1c4fb80 Binary files /dev/null and b/src/FTPTrans.ico differ diff --git a/src/FTPTrans.qrc b/src/FTPTrans.qrc new file mode 100644 index 0000000..c62a9e9 --- /dev/null +++ b/src/FTPTrans.qrc @@ -0,0 +1,4 @@ +<RCC> + <qresource prefix="FTPTrans"> + </qresource> +</RCC> diff --git a/src/FTPTrans.rc b/src/FTPTrans.rc new file mode 100644 index 0000000..24a265a --- /dev/null +++ b/src/FTPTrans.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "FTPTrans.ico" diff --git a/src/FTPTrans.ui b/src/FTPTrans.ui new file mode 100644 index 0000000..af21ecd --- /dev/null +++ b/src/FTPTrans.ui @@ -0,0 +1,156 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>FTPTransClass</class> + <widget class="QWidget" name="FTPTransClass"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1461</width> + <height>605</height> + </rect> + </property> + <property name="windowTitle"> + <string>FTPTrans</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>FTP基本信息</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="1"> + <widget class="QLineEdit" name="edIP"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>用户名:</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>IP:</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>端口:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="edUserName"/> + </item> + <item row="1" column="2"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>密码:</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="QLineEdit" name="edPort"/> + </item> + <item row="1" column="3"> + <widget class="QLineEdit" name="edPwd"/> + </item> + <item row="0" column="4"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="4"> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>文件传输(远端暂不支持中文路径)</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QTableWidget" name="tableWidget"/> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="btnAdd"> + <property name="text"> + <string>添加</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btnUpdate"> + <property name="text"> + <string>上传同步</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btnDown"> + <property name="text"> + <string>下载同步</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btnSave"> + <property name="text"> + <string>保存</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <layoutdefault spacing="6" margin="11"/> + <resources> + <include location="FTPTrans.qrc"/> + </resources> + <connections/> +</ui> diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..84db3dc --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,14 @@ +#include "FTPTrans.h" +#include <QtWidgets/QApplication> + +int main(int argc, char *argv[]) +{ +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif + QApplication a(argc, argv); + a.setStyle("windows xp"); + FTPTrans w; + w.show(); + return a.exec(); +}