Browse Source

improve some gui elements

pull/130/head
DenioD 4 years ago
parent
commit
74aaa0482f
  1. 5
      application.qrc
  2. BIN
      res/lock.png
  3. 7
      res/lock.svg
  4. 7
      res/lock_blue.svg
  5. 7
      res/lock_green.svg
  6. 7
      res/unlocked.svg
  7. 11
      src/Chat/Chat.cpp
  8. 72
      src/Chat/Helper/ChatDelegator.h
  9. 7
      src/DataStore/ChatDataStore.cpp
  10. 39
      src/Model/ChatItem.cpp
  11. 10
      src/Model/ChatItem.h
  12. 1
      src/addressbook.cpp
  13. 3
      src/chatmodel.h
  14. 1
      src/contactmodel.cpp
  15. 4
      src/controller.cpp
  16. 1
      src/mainwindow.cpp

5
application.qrc

@ -36,6 +36,11 @@
<file>res/upload.png</file>
<file>res/upload.svg</file>
<file>res/message-icon.svg</file>
<file>res/lock.svg</file>
<file>res/lock.png</file>
<file>res/lock_green.svg</file>
<file>res/lock_blue.svg</file>
<file>res/unlocked.svg</file>
</qresource>
<qresource prefix="/img">
<file>res/hushdlogo.gif</file>

BIN
res/lock.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

7
res/lock.svg

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
<g><path d="M500,10C229.4,10,10,229.4,10,500c0,270.6,219.4,490,490,490c270.6,0,490-219.4,490-490C990,229.4,770.6,10,500,10z M500,947.4C252.9,947.4,52.6,747.1,52.6,500C52.6,252.9,252.9,52.6,500,52.6c247.1,0,447.4,200.3,447.4,447.4C947.4,747.1,747.1,947.4,500,947.4z"/><path d="M452.1,392.4c0-24.5,6.4-83.1,69.2-83.1c59.7,0,69.2,52.2,69.2,83.1v18.1h52.2v-18.1c0-81-46.9-133.2-120.4-133.2c-73.5,0-120.4,52.2-120.4,133.2v18.1h52.2v-18.1H452.1z M641.7,427.6H400.9c-28.8,0-52.2,22.4-52.2,51.1V647c0,27.7,23.4,51.1,52.2,51.1h240.7c28.8,0,52.2-22.4,52.2-51.1V478.7C693.9,451,670.4,427.6,641.7,427.6L641.7,427.6z M538.3,575.6V614c0,9.6-7.5,17-17,17c-9.6,0-17-7.5-17-17v-38.3c-10.7-5.3-17-17-17-28.8c0-18.1,14.9-34.1,34.1-34.1s34.1,14.9,34.1,34.1C555.4,558.6,549,569.2,538.3,575.6L538.3,575.6z"/></g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

7
res/lock_blue.svg

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg fill="#46a2da" width="16px" height="16px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
<g><path d="M500,10C229.4,10,10,229.4,10,500c0,270.6,219.4,490,490,490c270.6,0,490-219.4,490-490C990,229.4,770.6,10,500,10z M500,947.4C252.9,947.4,52.6,747.1,52.6,500C52.6,252.9,252.9,52.6,500,52.6c247.1,0,447.4,200.3,447.4,447.4C947.4,747.1,747.1,947.4,500,947.4z"/><path d="M452.1,392.4c0-24.5,6.4-83.1,69.2-83.1c59.7,0,69.2,52.2,69.2,83.1v18.1h52.2v-18.1c0-81-46.9-133.2-120.4-133.2c-73.5,0-120.4,52.2-120.4,133.2v18.1h52.2v-18.1H452.1z M641.7,427.6H400.9c-28.8,0-52.2,22.4-52.2,51.1V647c0,27.7,23.4,51.1,52.2,51.1h240.7c28.8,0,52.2-22.4,52.2-51.1V478.7C693.9,451,670.4,427.6,641.7,427.6L641.7,427.6z M538.3,575.6V614c0,9.6-7.5,17-17,17c-9.6,0-17-7.5-17-17v-38.3c-10.7-5.3-17-17-17-28.8c0-18.1,14.9-34.1,34.1-34.1s34.1,14.9,34.1,34.1C555.4,558.6,549,569.2,538.3,575.6L538.3,575.6z"/></g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

7
res/lock_green.svg

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg fill="#32dc15" width="16px" height="16px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
<g><path d="M500,10C229.4,10,10,229.4,10,500c0,270.6,219.4,490,490,490c270.6,0,490-219.4,490-490C990,229.4,770.6,10,500,10z M500,947.4C252.9,947.4,52.6,747.1,52.6,500C52.6,252.9,252.9,52.6,500,52.6c247.1,0,447.4,200.3,447.4,447.4C947.4,747.1,747.1,947.4,500,947.4z"/><path d="M452.1,392.4c0-24.5,6.4-83.1,69.2-83.1c59.7,0,69.2,52.2,69.2,83.1v18.1h52.2v-18.1c0-81-46.9-133.2-120.4-133.2c-73.5,0-120.4,52.2-120.4,133.2v18.1h52.2v-18.1H452.1z M641.7,427.6H400.9c-28.8,0-52.2,22.4-52.2,51.1V647c0,27.7,23.4,51.1,52.2,51.1h240.7c28.8,0,52.2-22.4,52.2-51.1V478.7C693.9,451,670.4,427.6,641.7,427.6L641.7,427.6z M538.3,575.6V614c0,9.6-7.5,17-17,17c-9.6,0-17-7.5-17-17v-38.3c-10.7-5.3-17-17-17-28.8c0-18.1,14.9-34.1,34.1-34.1s34.1,14.9,34.1,34.1C555.4,558.6,549,569.2,538.3,575.6L538.3,575.6z"/></g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

7
res/unlocked.svg

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg fill="#EB4F38" width="16px" height="16px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
<g><g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"><path d="M4631.2,5015.7c-634.2-57.5-1212.8-212.7-1755.1-475.2c-546.1-264.4-894.8-513.5-1339.3-959.9c-446.4-446.4-676.4-766.4-948.4-1322.1c-231.8-469.4-367.9-914-454.1-1465.8c-46-308.5-46-1032.7,1.9-1341.2c90.1-586.3,239.5-1057.6,488.6-1548.1c254.8-496.3,494.3-822,912-1239.7c438.8-440.7,764.5-674.4,1302.9-938.9c343-168.6,567.1-252.9,915.9-344.9c1452.4-383.2,2981.4-76.6,4209.5,839.2c233.8,176.3,756.8,699.3,933.1,933.1C9909.8-1493,10170.4,202.7,9610.9,1779.6c-168.6,475.2-484.8,1032.7-812.4,1437c-187.8,231.8-609.3,640-837.3,810.5C7286.8,4532.9,6530,4849,5685,4979.3C5491.5,5008.1,4817,5033,4631.2,5015.7z M5483.8,4622.9C7206.3,4450.5,8697,3264.5,9273.7,1605.2C9540,836.9,9593.7-44.5,9419.3-855c-176.3-818.1-615.1-1615.2-1224.3-2222.6c-714.7-716.6-1619-1159.2-2630.7-1293.3c-293.2-38.3-845-38.3-1138.1,0C2906.7-4171.6,1600-3240.4,933.2-1880.1c-320,651.4-461.8,1272.2-461.8,2013.8c0,730,139.9,1331.6,461.8,1990.8C1370.1,3015.4,2102,3747.3,2993,4184.2C3788.1,4571.2,4583.3,4713,5483.8,4622.9z"/><path d="M4589,2237.5c-431.1-103.5-768.3-486.7-814.3-927.4c-13.4-136,9.6-197.3,92-231.8c107.3-44.1,208.8,40.2,208.8,172.4c0,151.4,107.3,373.6,243.3,502c208.8,197.3,513.5,258.7,791.3,162.9c180.1-63.2,385.1-268.2,452.2-452.2c24.9-63.2,34.5-172.4,42.2-406.2l7.7-321.9H4431.9H3249.7l-46-47.9l-47.9-46v-1439v-1438.9l47.9-46l46-47.9h1592.2h1592.2l46,47.9l47.9,46v1438.9v1439l-47.9,46c-44.1,46-55.6,47.9-302.7,47.9h-258.7l-9.6,341c-7.7,287.4-15.3,358.3-49.8,457.9c-97.7,272.1-298.9,498.2-548,618.9C5068,2270.1,4832.3,2296.9,4589,2237.5z M6221.5-797.5v-1226.2H4841.9H3462.4v1226.2V428.8h1379.5h1379.5V-797.5z"/><path d="M4688.6,97.3c-36.4-11.5-111.1-65.2-162.9-118.8c-136-134.1-174.4-279.7-120.7-454.1c26.8-92,145.6-231.8,226.1-264.4l57.5-23v-402.4c0-398.5,0-400.4,47.9-446.4c61.3-63.2,149.4-63.2,210.8,0c47.9,46,47.9,47.9,47.9,446.4V-763l57.5,23c80.5,32.6,199.3,172.4,226.1,264.4c53.6,174.4,15.3,320-120.7,454.1C5023.9,114.5,4866.8,152.9,4688.6,97.3z M4947.3-232.3c95.8-93.9,28.7-258.7-105.4-258.7c-36.4,0-76.6,17.3-105.4,47.9c-30.7,28.7-47.9,69-47.9,105.4c0,36.4,17.2,76.6,47.9,105.4c28.7,30.7,69,47.9,105.4,47.9S4918.6-201.6,4947.3-232.3z"/></g></g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

11
src/Chat/Chat.cpp

@ -1,3 +1,6 @@
// Copyright 2019-2020 The Hush developers
// GPLv3
#include "Chat.h"
#include "../addressbook.h"
#include "../DataStore/DataStore.h"
@ -23,9 +26,11 @@ void Chat::renderChatBox(Ui::MainWindow *ui, QListView *view)
{
QStandardItem *Items = new QStandardItem(c.second.toChatLine());
Items->setData("Outgoing", Qt::UserRole + 1);
Items->setData(OUTGOING, Qt::UserRole + 1);
chat->appendRow(Items);
ui->listChat->setModel(chat);
ui->listChat->setModel(chat);
}
else
{
@ -39,7 +44,7 @@ void Chat::renderChatBox(Ui::MainWindow *ui, QListView *view)
{
QStandardItem *Items1 = new QStandardItem(c.second.toChatLine());
Items1->setData("Incoming", Qt::UserRole + 1);
Items1->setData(INCOMING, Qt::UserRole + 1);
chat->appendRow(Items1);
ui->listChat->setModel(chat);
}

72
src/Chat/Helper/ChatDelegator.h

@ -1,3 +1,6 @@
// Copyright 2019-2020 The Hush developers
// GPLv3
#ifndef CHATDELEGATOR_H
#define CHATDELEGATOR_H
@ -6,6 +9,14 @@
#include <QAbstractItemDelegate>
#include <QPainter>
enum RenderType
{
OUTGOING=0,
INCOMING=1,
INDATE=2,
OUTDATE=3
};
class ListViewDelegate : public QAbstractItemDelegate
{
int d_radius;
@ -26,7 +37,7 @@ class ListViewDelegate : public QAbstractItemDelegate
inline QSize sizeHint(QStyleOptionViewItem const &option, QModelIndex const &index) const;
};
inline ListViewDelegate::ListViewDelegate(QObject *parent): QAbstractItemDelegate(parent), d_radius(5), d_toppadding(5), d_bottompadding(3), d_leftpadding(5), d_rightpadding(5), d_verticalmargin(15), d_horizontalmargin(10), d_pointerwidth(10), d_pointerheight(17), d_widthfraction(.7)
inline ListViewDelegate::ListViewDelegate(QObject *parent): QAbstractItemDelegate(parent), d_radius(5), d_toppadding(5), d_bottompadding(3), d_leftpadding(5), d_rightpadding(5), d_verticalmargin(5), d_horizontalmargin(10), d_pointerwidth(10), d_pointerheight(17), d_widthfraction(.6)
{
}
@ -43,7 +54,9 @@ inline void ListViewDelegate::paint(QPainter *painter, QStyleOptionViewItem cons
qreal contentswidth = option.rect.width() * d_widthfraction - d_horizontalmargin - d_pointerwidth - d_leftpadding - d_rightpadding;
bodydoc.setTextWidth(contentswidth);
qreal bodyheight = bodydoc.size().height();
bool outgoing = index.data(Qt::UserRole + 1).toString() == "Outgoing";
int outgoing = index.data(Qt::UserRole + 1).toInt();
int outdate = index.data(Qt::UserRole + 1).toInt();
int indate = index.data(Qt::UserRole + 1).toInt();
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
@ -53,10 +66,26 @@ inline void ListViewDelegate::paint(QPainter *painter, QStyleOptionViewItem cons
painter->translate(option.rect.left() + d_horizontalmargin, option.rect.top() + ((index.row() == 0) ? d_verticalmargin : 0));
// background color for chat bubble
QColor bgcolor("#535353");
if (outgoing)
bgcolor = "#eeeeee";
QColor bgcolor("#ffffff");
switch(outgoing)
{
case INDATE:
bgcolor = "transparent";
break;
case OUTDATE:
bgcolor = "transparent";
break;
case OUTGOING:
bgcolor = "#f8f9fa";
break;
default:
case INCOMING:
bgcolor = "#535353";
break;
}
// create chat bubble
QPainterPath pointie;
@ -85,7 +114,7 @@ inline void ListViewDelegate::paint(QPainter *painter, QStyleOptionViewItem cons
pointie.closeSubpath();
// rotate bubble for outgoing messages
if (outgoing)
if ((outgoing == OUTGOING) || (outdate == OUTDATE))
{
painter->translate(option.rect.width() - pointie.boundingRect().width() - d_horizontalmargin - d_pointerwidth, 0);
painter->translate(pointie.boundingRect().center());
@ -99,7 +128,7 @@ inline void ListViewDelegate::paint(QPainter *painter, QStyleOptionViewItem cons
painter->fillPath(pointie, QBrush(bgcolor));
// rotate back or painter is going to paint the text rotated...
if (outgoing)
if ((outgoing == OUTGOING) || (outdate == OUTDATE))
{
painter->translate(pointie.boundingRect().center());
painter->rotate(-180);
@ -108,13 +137,30 @@ inline void ListViewDelegate::paint(QPainter *painter, QStyleOptionViewItem cons
// set text color used to draw message body
QAbstractTextDocumentLayout::PaintContext ctx;
if (outgoing)
ctx.palette.setColor(QPalette::Text, QColor("black"));
else
ctx.palette.setColor(QPalette::Text, QColor("white"));
switch(outgoing)
{
case INDATE:
ctx.palette.setColor(QPalette::Text, QColor("Black"));
break;
case OUTDATE:
ctx.palette.setColor(QPalette::Text, QColor("Black"));
break;
case OUTGOING:
ctx.palette.setColor(QPalette::Text, QColor("Black"));
break;
default:
case INCOMING:
ctx.palette.setColor(QPalette::Text, QColor("whitesmoke"));
break;
}
// draw body text
painter->translate((outgoing ? 0 : d_pointerwidth) + d_leftpadding, 0);
painter->translate((outgoing == OUTGOING ? 0 : d_pointerwidth) + d_leftpadding, 0);
painter->translate((outdate == OUTDATE ? 0 : d_pointerwidth) + d_leftpadding, 0);
bodydoc.documentLayout()->draw(painter, ctx);
painter->restore();

7
src/DataStore/ChatDataStore.cpp

@ -1,3 +1,6 @@
// Copyright 2019-2020 The Hush developers
// GPLv3
#include "ChatDataStore.h"
ChatDataStore* ChatDataStore::getInstance()
@ -43,8 +46,8 @@ std::map<QString, ChatItem> ChatDataStore::getAllContactRequests()
for(auto &c: this->data)
{
if (
(c.second.getType() == "cont") &&
(c.second.isOutgoing() == false) &&
(c.second.isOutgoing() == false) &&
(c.second.getType() == "cont") &&
(c.second.getMemo().startsWith("{"))
)
{

39
src/Model/ChatItem.cpp

@ -1,8 +1,11 @@
// Copyright 2019-2020 The Hush developers
// GPLv3
#include "ChatItem.h"
ChatItem::ChatItem() {}
ChatItem::ChatItem(long timestamp, QString address, QString contact, QString memo, QString requestZaddr, QString type, QString cid, QString txid)
ChatItem::ChatItem(long timestamp, QString address, QString contact, QString memo, QString requestZaddr, QString type, QString cid, QString txid, int confirmations)
{
_timestamp = timestamp;
_address = address;
@ -12,10 +15,11 @@ ChatItem::ChatItem(long timestamp, QString address, QString contact, QString mem
_type = type;
_cid = cid;
_txid = txid;
_confirmations = confirmations;
_outgoing = false;
}
ChatItem::ChatItem(long timestamp, QString address, QString contact, QString memo, QString requestZaddr, QString type, QString cid, QString txid, bool outgoing)
ChatItem::ChatItem(long timestamp, QString address, QString contact, QString memo, QString requestZaddr, QString type, QString cid, QString txid, int confirmations, bool outgoing)
{
_timestamp = timestamp;
_address = address;
@ -25,6 +29,7 @@ ChatItem::ChatItem(long timestamp, QString address, QString contact, QString mem
_type = type;
_cid = cid;
_txid = txid;
_confirmations = confirmations;
_outgoing = outgoing;
}
@ -66,6 +71,10 @@ QString ChatItem::getTxid()
{
return _txid;
}
int ChatItem::getConfirmations()
{
return _confirmations;
}
bool ChatItem::isOutgoing()
{
@ -110,26 +119,38 @@ void ChatItem::setTxid(QString txid)
{
_txid = txid;
}
void ChatItem::setConfirmations(int confirmations)
{
_confirmations = confirmations;
}
void ChatItem::toggleOutgo()
{
_outgoing = true;
}
QString ChatItem::toChatLine()
{
QDateTime myDateTime;
QString lock;
myDateTime.setTime_t(_timestamp);
QString line = QString("[") + myDateTime.toString("d.M.yy hh:mm") + QString("] ");
line += QString("") + QString(_memo) + QString("\n\n");
if (_confirmations == 0){
lock = "<b> <img src=':/icons/res/unlocked.svg'><b>";
}else{
lock = "<b> <img src=':/icons/res/lock_green.svg'><b>";
}
QString line = QString("<small style='background: rgba(255,255,255,0.1);'>") + myDateTime.toString("dd.MM.yyyy hh:mm");
line += QString(lock) + QString("</small>");
line += QString("<p>") + _memo.toHtmlEscaped() + QString("</p>");
return line;
}
ChatItem::~ChatItem()
{
/*delete timestamp;
delete address;
delete contact;
delete memo;
delete outgoing;*/
}

10
src/Model/ChatItem.h

@ -1,3 +1,6 @@
// Copyright 2019-2020 The Hush developers
// GPLv3
#ifndef CHATITEM_H
#define CHATITEM_H
@ -14,12 +17,13 @@ class ChatItem
QString _type;
QString _cid;
QString _txid;
int _confirmations;
bool _outgoing = false;
public:
ChatItem();
ChatItem(long timestamp, QString address, QString contact, QString memo,QString requestZaddr, QString type, QString cid, QString txid);
ChatItem(long timestamp, QString address, QString contact, QString memo, QString requestZaddr, QString type, QString cid, QString txid, bool outgoing);
ChatItem(long timestamp, QString address, QString contact, QString memo,QString requestZaddr, QString type, QString cid, QString txid, int confirmations);
ChatItem(long timestamp, QString address, QString contact, QString memo, QString requestZaddr, QString type, QString cid, QString txid, int confirmations, bool outgoing);
long getTimestamp();
QString getAddress();
QString getContact();
@ -28,6 +32,7 @@ class ChatItem
QString getType();
QString getCid();
QString getTxid();
int getConfirmations();
bool isOutgoing();
void setTimestamp(long timestamp);
void setAddress(QString address);
@ -37,6 +42,7 @@ class ChatItem
void setType(QString type);
void setCid(QString cid);
void setTxid(QString txid);
void setConfirmations(int confirmations);
void toggleOutgo();
QString toChatLine();
~ChatItem();

1
src/addressbook.cpp

@ -1,5 +1,6 @@
// Copyright 2019-2020 The Hush developers
// GPLv3
#include "addressbook.h"
#include "ui_addressbook.h"
#include "ui_mainwindow.h"

3
src/chatmodel.h

@ -1,3 +1,6 @@
// Copyright 2019-2020 The Hush developers
// GPLv3
#ifndef CHATMODEL_H
#define CHATMODEL_H
#include <QString>

1
src/contactmodel.cpp

@ -1,5 +1,6 @@
// Copyright 2019-2020 The Hush developers
// GPLv3
#include "contactmodel.h"
#include "addressbook.h"
#include "mainwindow.h"

4
src/controller.cpp

@ -878,9 +878,11 @@ void Controller::refreshTransactions() {
QString(""),
cid,
txid,
confirmations,
true
);
qDebug()<<"Memo : " <<memo;
qDebug()<<"Confirmation :" << confirmations;
DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
@ -973,9 +975,11 @@ void Controller::refreshTransactions() {
type,
cid,
txid,
confirmations,
false
);
qDebug()<< "Position : " << position;
qDebug()<<"Confirmation :" << confirmations;
DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
}

1
src/mainwindow.cpp

@ -1,5 +1,6 @@
// Copyright 2019-2020 The Hush developers
// GPLv3
#include "mainwindow.h"
#include "addressbook.h"
#include "viewalladdresses.h"

Loading…
Cancel
Save