Improve app logging
This commit is contained in:
parent
9fc7275bce
commit
5568885204
@ -393,10 +393,11 @@ void NymeaConnection::updateActiveBearers()
|
|||||||
}
|
}
|
||||||
// qDebug() << "Available bearers:" << availableBearerTypes;
|
// qDebug() << "Available bearers:" << availableBearerTypes;
|
||||||
if (m_availableBearerTypes != availableBearerTypes) {
|
if (m_availableBearerTypes != availableBearerTypes) {
|
||||||
|
|
||||||
qDebug() << "Available Bearer Types changed:" << availableBearerTypes;
|
qDebug() << "Available Bearer Types changed:" << availableBearerTypes;
|
||||||
m_availableBearerTypes = availableBearerTypes;
|
m_availableBearerTypes = availableBearerTypes;
|
||||||
emit availableBearerTypesChanged();
|
emit availableBearerTypesChanged();
|
||||||
|
} else {
|
||||||
|
qDebug() << "Available Bearer Types:" << availableBearerTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_currentHost) {
|
if (!m_currentHost) {
|
||||||
@ -419,7 +420,6 @@ void NymeaConnection::updateActiveBearers()
|
|||||||
qDebug() << "There's a host but no connection. Trying to connect now...";
|
qDebug() << "There's a host but no connection. Trying to connect now...";
|
||||||
connectInternal(m_currentHost);
|
connectInternal(m_currentHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -182,7 +182,7 @@ Connection *Connections::bestMatch(Connection::BearerTypes bearerTypes) const
|
|||||||
{
|
{
|
||||||
Connection *best = nullptr;
|
Connection *best = nullptr;
|
||||||
foreach (Connection *c, m_connections) {
|
foreach (Connection *c, m_connections) {
|
||||||
qDebug() << "have connection:" << bearerTypes << c->url() << c->bearerType() << bearerTypes.testFlag(c->bearerType());
|
// qDebug() << "have connection:" << bearerTypes << c->url() << c->bearerType() << bearerTypes.testFlag(c->bearerType());
|
||||||
if ((bearerTypes & c->bearerType()) == Connection::BearerTypeNone) {
|
if ((bearerTypes & c->bearerType()) == Connection::BearerTypeNone) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QClipboard>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
|
||||||
QtMessageHandler AppLogController::s_oldLogMessageHandler = nullptr;
|
QtMessageHandler AppLogController::s_oldLogMessageHandler = nullptr;
|
||||||
|
|
||||||
@ -23,14 +25,21 @@ AppLogController *AppLogController::instance()
|
|||||||
return thiz;
|
return thiz;
|
||||||
}
|
}
|
||||||
|
|
||||||
AppLogController::AppLogController(QObject *parent) : QObject(parent)
|
AppLogController::AppLogController(QObject *parent) : QAbstractListModel(parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
QString fileName = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/nymea-app.log";
|
QString fileName = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/nymea-app.log";
|
||||||
m_logFile.setFileName(fileName);
|
m_logFile.setFileName(fileName);
|
||||||
qDebug() << "App log file:" << fileName;
|
qDebug() << "App log file:" << fileName;
|
||||||
|
|
||||||
if (!m_logFile.open(QFile::ReadWrite)) {
|
if (QFile::exists(fileName)) {
|
||||||
|
if (QFile::exists(fileName + ".old")) {
|
||||||
|
QFile::remove(fileName + ".old");
|
||||||
|
}
|
||||||
|
QFile::rename(fileName, fileName + ".old");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_logFile.open(QFile::ReadWrite | QFile::Truncate)) {
|
||||||
qDebug() << "Cannot open logfile for writing";
|
qDebug() << "Cannot open logfile for writing";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -74,26 +83,62 @@ void AppLogController::setEnabled(bool enabled)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray AppLogController::content()
|
int AppLogController::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return m_buffer;
|
Q_UNUSED(parent)
|
||||||
|
return m_buffer.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant AppLogController::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
switch (role) {
|
||||||
|
case RoleText:
|
||||||
|
return m_buffer.at(index.row());
|
||||||
|
case RoleType:
|
||||||
|
return m_types.at(index.row());
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> AppLogController::roleNames() const
|
||||||
|
{
|
||||||
|
QHash<int, QByteArray> roles;
|
||||||
|
roles.insert(RoleText, "text");
|
||||||
|
roles.insert(RoleType, "type");
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppLogController::toClipboard()
|
||||||
|
{
|
||||||
|
m_logFile.seek(0);
|
||||||
|
QByteArray completeLog = m_logFile.readAll();
|
||||||
|
QGuiApplication::clipboard()->setText(completeLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppLogController::logMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message)
|
void AppLogController::logMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message)
|
||||||
{
|
{
|
||||||
s_oldLogMessageHandler(type, context, message);
|
s_oldLogMessageHandler(type, context, message);
|
||||||
|
instance()->append(message, type == QtWarningMsg ? TypeWarning : TypeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppLogController::append(const QString &message, AppLogController::Type type)
|
||||||
|
{
|
||||||
QString finalMessage = message + "\n";
|
QString finalMessage = message + "\n";
|
||||||
instance()->m_logFile.write(finalMessage.toUtf8());
|
m_logFile.write(finalMessage.toUtf8());
|
||||||
instance()->m_logFile.flush();
|
m_logFile.flush();
|
||||||
instance()->m_buffer.append(finalMessage);
|
|
||||||
|
|
||||||
int maxBuffer = 1024 * 1024;
|
beginInsertRows(QModelIndex(), m_buffer.count(), m_buffer.count());
|
||||||
if (instance()->m_buffer.size() > maxBuffer) {
|
m_buffer.append(message);
|
||||||
instance()->m_buffer.remove(0, instance()->m_buffer.size() - maxBuffer);
|
m_types.append(type);
|
||||||
|
endInsertRows();
|
||||||
|
|
||||||
|
int maxEntries = 1024;
|
||||||
|
if (m_buffer.size() > maxEntries) {
|
||||||
|
beginRemoveRows(QModelIndex(), 0, 0);
|
||||||
|
m_buffer.removeFirst();
|
||||||
|
m_types.removeFirst();
|
||||||
|
endRemoveRows();
|
||||||
}
|
}
|
||||||
emit instance()->contentChanged();
|
|
||||||
emit instance()->contentAdded(finalMessage.toUtf8());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppLogController::activate()
|
void AppLogController::activate()
|
||||||
|
|||||||
@ -4,15 +4,27 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QQmlEngine>
|
#include <QQmlEngine>
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
|
||||||
class AppLogController : public QObject
|
class AppLogController : public QAbstractListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool canWriteLogs READ canWriteLogs CONSTANT)
|
Q_PROPERTY(bool canWriteLogs READ canWriteLogs CONSTANT)
|
||||||
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
|
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
|
||||||
Q_PROPERTY(QByteArray content READ content NOTIFY contentChanged)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum Type {
|
||||||
|
TypeInfo,
|
||||||
|
TypeWarning
|
||||||
|
};
|
||||||
|
Q_ENUM(Type)
|
||||||
|
|
||||||
|
enum Roles {
|
||||||
|
RoleText,
|
||||||
|
RoleType
|
||||||
|
};
|
||||||
|
Q_ENUM(Roles)
|
||||||
|
|
||||||
static QObject* appLogControllerProvider(QQmlEngine *engine, QJSEngine *scriptEngine);
|
static QObject* appLogControllerProvider(QQmlEngine *engine, QJSEngine *scriptEngine);
|
||||||
static AppLogController* instance();
|
static AppLogController* instance();
|
||||||
|
|
||||||
@ -21,23 +33,29 @@ public:
|
|||||||
bool enabled() const;
|
bool enabled() const;
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
|
|
||||||
QByteArray content();
|
int rowCount(const QModelIndex &parent) const override;
|
||||||
|
QVariant data(const QModelIndex &parent, int role) const override;
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
|
||||||
|
Q_INVOKABLE void toClipboard();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void enabledChanged();
|
void enabledChanged();
|
||||||
void contentChanged();
|
|
||||||
void contentAdded(const QByteArray &newContent);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit AppLogController(QObject *parent = nullptr);
|
explicit AppLogController(QObject *parent = nullptr);
|
||||||
static QtMessageHandler s_oldLogMessageHandler;
|
static QtMessageHandler s_oldLogMessageHandler;
|
||||||
static void logMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message);
|
static void logMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message);
|
||||||
|
|
||||||
|
void append(const QString &message, Type type = TypeInfo);
|
||||||
|
|
||||||
void activate();
|
void activate();
|
||||||
void deactivate();
|
void deactivate();
|
||||||
|
|
||||||
QFile m_logFile;
|
QFile m_logFile;
|
||||||
QByteArray m_buffer;
|
QStringList m_buffer;
|
||||||
|
QList<Type> m_types;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // APPLOGCONTROLLER_H
|
#endif // APPLOGCONTROLLER_H
|
||||||
|
|||||||
@ -171,5 +171,6 @@
|
|||||||
<file>ui/images/powersocket.svg</file>
|
<file>ui/images/powersocket.svg</file>
|
||||||
<file>ui/images/dial.svg</file>
|
<file>ui/images/dial.svg</file>
|
||||||
<file>ui/images/ventilation.svg</file>
|
<file>ui/images/ventilation.svg</file>
|
||||||
|
<file>ui/images/edit-copy.svg</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@ -72,26 +72,25 @@ Page {
|
|||||||
text: qsTr("App log")
|
text: qsTr("App log")
|
||||||
backButtonVisible: true
|
backButtonVisible: true
|
||||||
onBackPressed: pageStack.pop()
|
onBackPressed: pageStack.pop()
|
||||||
|
HeaderButton {
|
||||||
|
imageSource: "../images/edit-copy.svg"
|
||||||
|
onClicked: AppLogController.toClipboard()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrollView {
|
ListView {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
TextArea {
|
ScrollBar.vertical: ScrollBar {}
|
||||||
id: logArea
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
readOnly: true
|
|
||||||
font.pixelSize: app.smallFont
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
model: AppLogController
|
||||||
text = AppLogController.content
|
delegate: Text {
|
||||||
}
|
width: parent.width
|
||||||
Connections {
|
maximumLineCount: 2
|
||||||
target: AppLogController
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
onContentAdded: {
|
text: model.text
|
||||||
logArea.append(newContent)
|
color: model.type === AppLogController.TypeWarning ? "red" : app.foregroundColor
|
||||||
}
|
font.pixelSize: app.smallFont
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
193
nymea-app/ui/images/edit-copy.svg
Normal file
193
nymea-app/ui/images/edit-copy.svg
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="96"
|
||||||
|
height="96"
|
||||||
|
id="svg4874"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.91+devel r"
|
||||||
|
viewBox="0 0 96 96.000001"
|
||||||
|
sodipodi:docname="edit-copy.svg">
|
||||||
|
<defs
|
||||||
|
id="defs4876" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="7.0249991"
|
||||||
|
inkscape:cx="32.704626"
|
||||||
|
inkscape:cy="51.594295"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="g4780"
|
||||||
|
showgrid="true"
|
||||||
|
showborder="true"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:bbox-paths="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:snap-bbox-edge-midpoints="true"
|
||||||
|
inkscape:snap-bbox-midpoints="true"
|
||||||
|
inkscape:object-paths="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
inkscape:object-nodes="true"
|
||||||
|
inkscape:snap-smooth-nodes="true"
|
||||||
|
inkscape:snap-midpoints="true"
|
||||||
|
inkscape:snap-object-midpoints="true"
|
||||||
|
inkscape:snap-center="true"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:snap-global="true">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid5451"
|
||||||
|
empspacing="8" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="8,-8.0000001"
|
||||||
|
id="guide4063" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="4,-8.0000001"
|
||||||
|
id="guide4065" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-8,88.000001"
|
||||||
|
id="guide4067" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-8,92.000001"
|
||||||
|
id="guide4069" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="104,4"
|
||||||
|
id="guide4071" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-5,8.0000001"
|
||||||
|
id="guide4073" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="92,-8.0000001"
|
||||||
|
id="guide4075" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="88,-8.0000001"
|
||||||
|
id="guide4077" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-8,84.000001"
|
||||||
|
id="guide4074" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="12,-8.0000001"
|
||||||
|
id="guide4076" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-5,12"
|
||||||
|
id="guide4078" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="84,-9.0000001"
|
||||||
|
id="guide4080" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="48,-8.0000001"
|
||||||
|
orientation="1,0"
|
||||||
|
id="guide4170" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="-8,48"
|
||||||
|
orientation="0,1"
|
||||||
|
id="guide4172" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata4879">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(67.857146,-78.50504)">
|
||||||
|
<g
|
||||||
|
transform="matrix(0,-1,-1,0,373.50506,516.50504)"
|
||||||
|
id="g4845"
|
||||||
|
style="display:inline">
|
||||||
|
<g
|
||||||
|
inkscape:export-ydpi="90"
|
||||||
|
inkscape:export-xdpi="90"
|
||||||
|
inkscape:export-filename="next01.png"
|
||||||
|
transform="matrix(-0.9996045,0,0,1,575.94296,-611.00001)"
|
||||||
|
id="g4778"
|
||||||
|
inkscape:label="Layer 1">
|
||||||
|
<g
|
||||||
|
transform="matrix(-1,0,0,1,575.99999,611)"
|
||||||
|
id="g4780"
|
||||||
|
style="display:inline">
|
||||||
|
<rect
|
||||||
|
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:4;marker:none;enable-background:accumulate"
|
||||||
|
id="rect4782"
|
||||||
|
width="96.037987"
|
||||||
|
height="96"
|
||||||
|
x="-438.00244"
|
||||||
|
y="345.36221"
|
||||||
|
transform="scale(-1,1)" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;marker:none;enable-background:accumulate"
|
||||||
|
d="m 409.9914,405.39134 -4.00158,0 0,-36.07722 4.00158,0 z"
|
||||||
|
id="path4212"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;marker:none;enable-background:accumulate"
|
||||||
|
d="m 397.98665,405.39134 -4.00158,0 0,-36.07722 4.00158,0 z"
|
||||||
|
id="path4210"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:none;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079107;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 345.9668,357.36133 0,59.98242 76.02929,0 0,-2 0,-57.98242 -76.02929,0 z m 4,4.00195 68.02929,0 0,51.97852 -68.02929,0 0,-51.97852 z"
|
||||||
|
id="rect4154"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||||
|
d="m 434.0756,429.44282 -6.29888,0 -69.80592,0 0,-4.0806 72.02849,0 0,-56.0481 4.07631,0 0,54.11584 z"
|
||||||
|
id="rect4156"
|
||||||
|
sodipodi:nodetypes="ccccccccc" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4214"
|
||||||
|
d="m 385.98189,405.39134 -4.00158,0 0,-24.02912 4.00158,0 z"
|
||||||
|
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;marker:none;enable-background:accumulate" />
|
||||||
|
<rect
|
||||||
|
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||||
|
id="rect4158"
|
||||||
|
width="4"
|
||||||
|
height="16.00633"
|
||||||
|
x="-373.36221"
|
||||||
|
y="-434.00085"
|
||||||
|
transform="matrix(0,-1,-1,0,0,0)" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 8.0 KiB |
Reference in New Issue
Block a user