Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qgroundcontrol
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Valentin Platzgummer
qgroundcontrol
Commits
6daa362e
Commit
6daa362e
authored
Apr 27, 2015
by
Don Gagne
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
No longer supported, use MockLink instead
parent
5a21eeae
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
0 additions
and
654 deletions
+0
-654
MockQGCUASParamManager.cc
src/qgcunittest/MockQGCUASParamManager.cc
+0
-116
MockQGCUASParamManager.h
src/qgcunittest/MockQGCUASParamManager.h
+0
-110
MockUAS.cc
src/qgcunittest/MockUAS.cc
+0
-54
MockUAS.h
src/qgcunittest/MockUAS.h
+0
-191
MockUASManager.cc
src/qgcunittest/MockUASManager.cc
+0
-57
MockUASManager.h
src/qgcunittest/MockUASManager.h
+0
-126
No files found.
src/qgcunittest/MockQGCUASParamManager.cc
deleted
100644 → 0
View file @
5a21eeae
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include "MockQGCUASParamManager.h"
#include "mavlink.h"
#include "QGCLoggingCategory.h"
#include <QTest>
#include <QDebug>
QGC_LOGGING_CATEGORY
(
MockQGCUASParamManagerLog
,
"MockQGCUASParamManagerLog"
)
MockQGCUASParamManager
::
MockQGCUASParamManager
(
void
)
{
_loadParams
();
}
bool
MockQGCUASParamManager
::
getParameterValue
(
int
component
,
const
QString
&
parameter
,
QVariant
&
value
)
const
{
Q_UNUSED
(
component
);
if
(
_mapParams
.
contains
(
parameter
))
{
value
=
_mapParams
[
parameter
];
return
true
;
}
qCDebug
(
MockQGCUASParamManagerLog
)
<<
QString
(
"getParameterValue: parameter not found %1"
).
arg
(
parameter
);
return
false
;
}
void
MockQGCUASParamManager
::
setParameter
(
int
component
,
QString
parameterName
,
QVariant
value
)
{
qCDebug
(
MockQGCUASParamManagerLog
)
<<
QString
(
"setParameter: component(%1) parameter(%2) value(%3)"
).
arg
(
component
).
arg
(
parameterName
).
arg
(
value
.
toString
());
_mapParams
[
parameterName
]
=
value
;
emit
parameterUpdated
(
_defaultComponentId
,
parameterName
,
value
);
}
void
MockQGCUASParamManager
::
_loadParams
(
void
)
{
QFile
paramFile
(
":/unittest/MockLink.params"
);
bool
success
=
paramFile
.
open
(
QFile
::
ReadOnly
);
Q_UNUSED
(
success
);
Q_ASSERT
(
success
);
QTextStream
paramStream
(
&
paramFile
);
while
(
!
paramStream
.
atEnd
())
{
QString
line
=
paramStream
.
readLine
();
if
(
line
.
startsWith
(
"#"
))
{
continue
;
}
QStringList
paramData
=
line
.
split
(
"
\t
"
);
Q_ASSERT
(
paramData
.
count
()
==
5
);
QString
paramName
=
paramData
.
at
(
2
);
QString
valStr
=
paramData
.
at
(
3
);
uint
paramType
=
paramData
.
at
(
4
).
toUInt
();
QVariant
paramValue
;
switch
(
paramType
)
{
case
MAV_PARAM_TYPE_REAL32
:
paramValue
=
QVariant
(
valStr
.
toFloat
());
break
;
case
MAV_PARAM_TYPE_UINT32
:
paramValue
=
QVariant
(
valStr
.
toUInt
());
break
;
case
MAV_PARAM_TYPE_INT32
:
paramValue
=
QVariant
(
valStr
.
toInt
());
break
;
case
MAV_PARAM_TYPE_INT8
:
paramValue
=
QVariant
((
unsigned
char
)
valStr
.
toUInt
());
break
;
default:
Q_ASSERT
(
false
);
break
;
}
Q_ASSERT
(
!
_mapParams
.
contains
(
paramName
));
_mapParams
[
paramName
]
=
paramValue
;
}
}
QList
<
int
>
MockQGCUASParamManager
::
getComponentForParam
(
const
QString
&
parameter
)
const
{
if
(
_mapParams
.
contains
(
parameter
))
{
QList
<
int
>
list
;
list
<<
50
;
return
list
;
}
else
{
return
QList
<
int
>
();
}
}
src/qgcunittest/MockQGCUASParamManager.h
deleted
100644 → 0
View file @
5a21eeae
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#ifndef MOCKQGCUASPARAMMANAGER_H
#define MOCKQGCUASPARAMMANAGER_H
#include <QLoggingCategory>
#include "QGCUASParamManagerInterface.h"
Q_DECLARE_LOGGING_CATEGORY
(
MockQGCUASParamManagerLog
)
/// @file
/// @brief This is a mock implementation of QGCUASParamManager for writing Unit Tests.
///
/// @author Don Gagne <don@thegagnes.com>
class
MockQGCUASParamManager
:
public
QGCUASParamManagerInterface
{
Q_OBJECT
signals:
// The following QGCSUASParamManagerInterface signals are supported
void
parameterListUpToDate
();
// You can connect to this signal, but it will never be emitted
void
parameterUpdated
(
int
compId
,
QString
paramName
,
QVariant
value
);
public:
// Implemented QGCSUASParamManager overrides
virtual
bool
getParameterValue
(
int
component
,
const
QString
&
parameter
,
QVariant
&
value
)
const
;
virtual
int
getDefaultComponentId
(
void
)
{
return
_defaultComponentId
;
}
virtual
int
countOnboardParams
(
void
)
{
return
_mapParams
.
count
();
}
public
slots
:
// Implemented QGCSUASParamManager overrides
void
setParameter
(
int
component
,
QString
parameterName
,
QVariant
value
);
virtual
void
setPendingParam
(
int
componentId
,
const
QString
&
key
,
const
QVariant
&
value
,
bool
forceSend
=
false
)
{
Q_UNUSED
(
forceSend
);
setParameter
(
componentId
,
key
,
value
);
}
virtual
void
sendPendingParameters
(
bool
persistAfterSend
=
false
,
bool
forceSend
=
false
)
{
Q_UNUSED
(
persistAfterSend
);
Q_UNUSED
(
forceSend
);
}
virtual
bool
parametersReady
(
void
)
{
return
true
;
}
public:
// MockQGCUASParamManager methods
MockQGCUASParamManager
(
void
);
/// QMap of parameters, QString key is paremeter name, QVariant value is parameter value
typedef
QMap
<
QString
,
QVariant
>
ParamMap_t
;
/// Sets current set of parameters to support calls like getParameterValue
void
setMockParameters
(
ParamMap_t
&
map
)
{
_mapParams
=
map
;
}
/// Returns the parameters which were set by calls to setParameter calls
ParamMap_t
getMockSetParameters
(
void
)
{
return
_mapParams
;
}
/// Clears the set of parameters set by setParameter calls
void
clearMockSetParameters
(
void
)
{
_mapParams
.
clear
();
}
public:
// Unimplemented QGCUASParamManagerInterface overrides
virtual
QList
<
int
>
getComponentForParam
(
const
QString
&
parameter
)
const
;
virtual
void
setParamDescriptions
(
const
QMap
<
QString
,
QString
>&
paramDescs
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
paramDescs
);
}
virtual
int
countPendingParams
()
{
Q_ASSERT
(
false
);
return
0
;
}
virtual
UASParameterDataModel
*
dataModel
()
{
Q_ASSERT
(
false
);
return
NULL
;
}
public
slots
:
// Unimplemented QGCUASParamManagerInterface overrides
virtual
void
requestParameterList
()
{
Q_ASSERT
(
false
);
}
virtual
void
requestParameterListIfEmpty
()
{
Q_ASSERT
(
false
);
}
virtual
void
clearAllPendingParams
()
{
Q_ASSERT
(
false
);
}
virtual
void
requestParameterUpdate
(
int
component
,
const
QString
&
parameter
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
component
);
Q_UNUSED
(
parameter
);
}
virtual
void
writeOnboardParamsToStream
(
QTextStream
&
stream
,
const
QString
&
uasName
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
stream
);
Q_UNUSED
(
uasName
);
}
virtual
void
readPendingParamsFromStream
(
QTextStream
&
stream
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
stream
);
}
virtual
void
requestRcCalibrationParamsUpdate
()
{
Q_ASSERT
(
false
);
}
virtual
void
copyVolatileParamsToPersistent
()
{
Q_ASSERT
(
false
);
}
virtual
void
copyPersistentParamsToVolatile
()
{
Q_ASSERT
(
false
);
}
private:
void
_loadParams
(
void
);
ParamMap_t
_mapParams
;
static
const
int
_defaultComponentId
=
50
;
// Bogus variables used for return types of NYI methods
QList
<
int
>
_bogusQListInt
;
};
#endif
\ No newline at end of file
src/qgcunittest/MockUAS.cc
deleted
100644 → 0
View file @
5a21eeae
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include "MockUAS.h"
QString
MockUAS
::
_bogusStaticString
;
MockUAS
::
MockUAS
(
void
)
:
_systemType
(
MAV_TYPE_QUADROTOR
),
_systemId
(
1
),
_mavlinkPlugin
(
NULL
)
{
}
void
MockUAS
::
setMockParametersAndSignal
(
MockQGCUASParamManager
::
ParamMap_t
&
map
)
{
_paramManager
.
setMockParameters
(
map
);
QMapIterator
<
QString
,
QVariant
>
i
(
map
);
while
(
i
.
hasNext
())
{
i
.
next
();
emit
parameterChanged
(
_systemId
,
0
,
i
.
key
(),
i
.
value
());
}
}
void
MockUAS
::
sendMessage
(
mavlink_message_t
message
)
{
if
(
!
_mavlinkPlugin
)
{
Q_ASSERT
(
false
);
}
_mavlinkPlugin
->
sendMessage
(
message
);
}
\ No newline at end of file
src/qgcunittest/MockUAS.h
deleted
100644 → 0
View file @
5a21eeae
This diff is collapsed.
Click to expand it.
src/qgcunittest/MockUASManager.cc
deleted
100644 → 0
View file @
5a21eeae
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include "MockUASManager.h"
MockUASManager
::
MockUASManager
(
void
)
:
UASManagerInterface
(
NULL
),
_mockUAS
(
NULL
)
{
}
UASInterface
*
MockUASManager
::
getActiveUAS
(
void
)
{
return
_mockUAS
;
}
void
MockUASManager
::
setMockActiveUAS
(
MockUAS
*
mockUAS
)
{
// Signal components that the last UAS is no longer active.
if
(
_mockUAS
!=
NULL
)
{
emit
activeUASStatusChanged
(
_mockUAS
,
false
);
emit
activeUASStatusChanged
(
_mockUAS
->
getUASID
(),
false
);
}
_mockUAS
=
mockUAS
;
// And signal that a new UAS is.
emit
activeUASSet
(
_mockUAS
);
if
(
_mockUAS
)
{
// We don't support swiching between different UAS
//_mockUAS->setSelected();
emit
activeUASStatusChanged
(
_mockUAS
,
true
);
emit
activeUASStatusChanged
(
_mockUAS
->
getUASID
(),
true
);
}
}
src/qgcunittest/MockUASManager.h
deleted
100644 → 0
View file @
5a21eeae
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#ifndef MOCKUASMANAGER_H
#define MOCKUASMANAGER_H
#include "UASManagerInterface.h"
#include "MockUAS.h"
/// @file
/// @brief This is a mock implementation of a UASManager used for writing Unit Tests. In order
/// to use it you must call UASManager::setMockUASManager which will then cause all further
/// calls to UASManager::instance to return the mock UASManager instead of the normal one.
///
/// @author Don Gagne <don@thegagnes.com>
class
MockUASManager
:
public
UASManagerInterface
{
Q_OBJECT
signals:
// The following signals from UASManager interface are supported:
// void activeUASSet(UASInterface* UAS);
// void activeUASStatusChanged(UASInterface* UAS, bool active);
// void activeUASStatusChanged(int systemId, bool active);
public:
// Implemented UASManagerInterface overrides
virtual
UASInterface
*
getActiveUAS
(
void
);
public:
// MockUASManager methods
MockUASManager
(
void
);
// Does not support singleton deletion
virtual
void
deleteInstance
(
void
)
{
Q_ASSERT
(
false
);
}
/// Sets the currently active mock UAS
/// @param mockUAS new mock uas, NULL for no active UAS
void
setMockActiveUAS
(
MockUAS
*
mockUAS
);
public:
// Unimplemented UASManagerInterface overrides
virtual
UASWaypointManager
*
getActiveUASWaypointManager
()
{
Q_ASSERT
(
false
);
return
NULL
;
}
virtual
UASInterface
*
silentGetActiveUAS
()
{
Q_ASSERT
(
false
);
return
NULL
;
}
virtual
UASInterface
*
getUASForId
(
int
id
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
id
);
return
NULL
;
}
virtual
QList
<
UASInterface
*>
getUASList
()
{
Q_ASSERT
(
false
);
return
_bogusQListUASInterface
;
}
virtual
double
getHomeLatitude
()
const
{
Q_ASSERT
(
false
);
return
std
::
numeric_limits
<
double
>::
quiet_NaN
();
}
virtual
double
getHomeLongitude
()
const
{
Q_ASSERT
(
false
);
return
std
::
numeric_limits
<
double
>::
quiet_NaN
();
}
virtual
double
getHomeAltitude
()
const
{
Q_ASSERT
(
false
);
return
std
::
numeric_limits
<
double
>::
quiet_NaN
();
}
virtual
int
getHomeFrame
()
const
{
Q_ASSERT
(
false
);
return
0
;
}
virtual
Eigen
::
Vector3d
wgs84ToEcef
(
const
double
&
latitude
,
const
double
&
longitude
,
const
double
&
altitude
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
latitude
);
Q_UNUSED
(
longitude
);
Q_UNUSED
(
altitude
);
return
_bogusEigenVector3d
;
}
virtual
Eigen
::
Vector3d
ecefToEnu
(
const
Eigen
::
Vector3d
&
ecef
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
ecef
);
return
_bogusEigenVector3d
;
}
virtual
void
wgs84ToEnu
(
const
double
&
lat
,
const
double
&
lon
,
const
double
&
alt
,
double
*
east
,
double
*
north
,
double
*
up
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
lat
);
Q_UNUSED
(
lon
);
Q_UNUSED
(
alt
);
Q_UNUSED
(
east
);
Q_UNUSED
(
north
);
Q_UNUSED
(
up
);
}
virtual
void
enuToWgs84
(
const
double
&
x
,
const
double
&
y
,
const
double
&
z
,
double
*
lat
,
double
*
lon
,
double
*
alt
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
x
);
Q_UNUSED
(
y
);
Q_UNUSED
(
z
);
Q_UNUSED
(
lat
);
Q_UNUSED
(
lon
);
Q_UNUSED
(
alt
);
}
virtual
void
nedToWgs84
(
const
double
&
x
,
const
double
&
y
,
const
double
&
z
,
double
*
lat
,
double
*
lon
,
double
*
alt
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
x
);
Q_UNUSED
(
y
);
Q_UNUSED
(
z
);
Q_UNUSED
(
lat
);
Q_UNUSED
(
lon
);
Q_UNUSED
(
alt
);
}
virtual
void
getLocalNEDSafetyLimits
(
double
*
x1
,
double
*
y1
,
double
*
z1
,
double
*
x2
,
double
*
y2
,
double
*
z2
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
x1
);
Q_UNUSED
(
y1
);
Q_UNUSED
(
z1
);
Q_UNUSED
(
x2
);
Q_UNUSED
(
y2
);
Q_UNUSED
(
z2
);
}
virtual
bool
isInLocalNEDSafetyLimits
(
double
x
,
double
y
,
double
z
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
x
);
Q_UNUSED
(
y
);
Q_UNUSED
(
z
);
return
false
;
}
public
slots
:
// Unimplemented UASManagerInterface overrides
virtual
void
setActiveUAS
(
UASInterface
*
UAS
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
UAS
);
}
virtual
void
addUAS
(
UASInterface
*
UAS
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
UAS
);
}
virtual
void
removeUAS
(
UASInterface
*
uas
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
uas
);}
virtual
bool
launchActiveUAS
()
{
Q_ASSERT
(
false
);
return
false
;
}
virtual
bool
haltActiveUAS
()
{
Q_ASSERT
(
false
);
return
false
;
}
virtual
bool
continueActiveUAS
()
{
Q_ASSERT
(
false
);
return
false
;
}
virtual
bool
returnActiveUAS
()
{
Q_ASSERT
(
false
);
return
false
;
}
virtual
bool
stopActiveUAS
()
{
Q_ASSERT
(
false
);
return
false
;
}
virtual
bool
killActiveUAS
()
{
Q_ASSERT
(
false
);
return
false
;
}
virtual
bool
shutdownActiveUAS
()
{
Q_ASSERT
(
false
);
return
false
;
}
virtual
bool
setHomePosition
(
double
lat
,
double
lon
,
double
alt
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
lat
);
Q_UNUSED
(
lon
);
Q_UNUSED
(
alt
);
return
false
;
}
virtual
bool
setHomePositionAndNotify
(
double
lat
,
double
lon
,
double
alt
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
lat
);
Q_UNUSED
(
lon
);
Q_UNUSED
(
alt
);
return
false
;
}
virtual
void
setLocalNEDSafetyBorders
(
double
x1
,
double
y1
,
double
z1
,
double
x2
,
double
y2
,
double
z2
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
x1
);
Q_UNUSED
(
y1
);
Q_UNUSED
(
z1
);
Q_UNUSED
(
x2
);
Q_UNUSED
(
y2
);
Q_UNUSED
(
z2
);
}
virtual
void
uavChangedHomePosition
(
int
uav
,
double
lat
,
double
lon
,
double
alt
)
{
Q_ASSERT
(
false
);
Q_UNUSED
(
uav
);
Q_UNUSED
(
lat
);
Q_UNUSED
(
lon
);
Q_UNUSED
(
alt
);
}
virtual
void
loadSettings
()
{
Q_ASSERT
(
false
);
}
virtual
void
storeSettings
()
{
Q_ASSERT
(
false
);
}
virtual
void
_shutdown
(
void
)
{
Q_ASSERT
(
false
);
}
private:
MockUAS
*
_mockUAS
;
// Bogus variables used for return types of NYI methods
QList
<
UASInterface
*>
_bogusQListUASInterface
;
Eigen
::
Vector3d
_bogusEigenVector3d
;
public:
/* Need to align struct pointer to prevent a memory assertion:
* See http://eigen.tuxfamily.org/dox-devel/TopicUnalignedArrayAssert.html
* for details
*/
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
#endif
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment