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
5e36ee5f
Commit
5e36ee5f
authored
May 06, 2015
by
Don Gagne
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cleanup FileManager
- Download working again - Fixed lots of bad error handling
parent
2e3088b8
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
201 additions
and
263 deletions
+201
-263
FileManagerTest.h
src/qgcunittest/FileManagerTest.h
+5
-11
FileManager.cc
src/uas/FileManager.cc
+77
-55
FileManager.h
src/uas/FileManager.h
+20
-29
QGCUASFileView.cc
src/ui/QGCUASFileView.cc
+85
-152
QGCUASFileView.h
src/ui/QGCUASFileView.h
+14
-16
No files found.
src/qgcunittest/FileManagerTest.h
View file @
5e36ee5f
...
...
@@ -53,13 +53,11 @@ private slots:
void
cleanup
(
void
);
// Test cases
#if 0
void
_ackTest
(
void
);
void
_noAckTest
(
void
);
void
_resetTest
(
void
);
void
_listTest
(
void
);
void
_readDownloadTest
(
void
);
#endif
void
_streamDownloadTest
(
void
);
// Connected to FileManager listEntry signal
...
...
@@ -70,19 +68,15 @@ private:
enum
{
listEntrySignalIndex
=
0
,
listCompleteSignalIndex
,
downloadFileLengthSignalIndex
,
downloadFileCompleteSignalIndex
,
errorMessageSignalIndex
,
commandCompleteSignalIndex
,
commandErrorSignalIndex
,
maxSignalIndex
};
enum
{
listEntrySignalMask
=
1
<<
listEntrySignalIndex
,
listCompleteSignalMask
=
1
<<
listCompleteSignalIndex
,
downloadFileLengthSignalMask
=
1
<<
downloadFileLengthSignalIndex
,
downloadFileCompleteSignalMask
=
1
<<
downloadFileCompleteSignalIndex
,
errorMessageSignalMask
=
1
<<
errorMessageSignalIndex
,
listEntrySignalMask
=
1
<<
listEntrySignalIndex
,
commandCompleteSignalMask
=
1
<<
commandCompleteSignalIndex
,
commandErrorSignalMask
=
1
<<
errorMessageSignalIndex
,
};
static
const
uint8_t
_systemIdQGC
=
255
;
...
...
src/uas/FileManager.cc
View file @
5e36ee5f
...
...
@@ -48,20 +48,22 @@ FileManager::FileManager(QObject* parent, UASInterface* uas, uint8_t unitTestSys
Q_ASSERT
(
sizeof
(
RequestHeader
)
==
12
);
}
///
@brief Respond to the Ack associated with the Open command with the next R
ead command.
///
Respond to the Ack associated with the Open command with the next r
ead command.
void
FileManager
::
_openAckResponse
(
Request
*
openAck
)
{
Q_ASSERT
(
_currentOperation
==
kCOOpenRead
||
_currentOperation
==
kCOOpenStream
);
qCDebug
(
FileManagerLog
)
<<
QString
(
"_openAckResponse: _currentOperation(%1) _readFileLength(%2)"
).
arg
(
_currentOperation
).
arg
(
openAck
->
openFileLength
);
Q_ASSERT
(
_currentOperation
==
kCOOpenRead
||
_currentOperation
==
kCOOpenBurst
);
_currentOperation
=
_currentOperation
==
kCOOpenRead
?
kCORead
:
kCOBurst
;
_activeSession
=
openAck
->
hdr
.
session
;
// File length comes back in data
Q_ASSERT
(
openAck
->
hdr
.
size
==
sizeof
(
uint32_t
));
emit
downloadFileLength
(
openAck
->
openFileLength
)
;
_downloadFileSize
=
openAck
->
openFileLength
;
// Start the sequence of read commands
_downloadOffset
=
0
;
// Start reading at beginning of file
_downloadOffset
=
0
;
// Start reading at beginning of file
_readFileAccumulator
.
clear
();
// Start with an empty file
Request
request
;
...
...
@@ -74,10 +76,14 @@ void FileManager::_openAckResponse(Request* openAck)
_sendRequest
(
&
request
);
}
///
@brief Closes out a re
ad session by writing the file and doing cleanup.
///
Closes out a downlo
ad session by writing the file and doing cleanup.
/// @param success true: successful download completion, false: error during download
void
FileManager
::
_closeDownloadSession
(
bool
success
)
{
qCDebug
(
FileManagerLog
)
<<
QString
(
"_closeDownloadSession: success(%1)"
).
arg
(
success
);
_currentOperation
=
kCOIdle
;
if
(
success
)
{
QString
downloadFilePath
=
_readFileDownloadDir
.
absoluteFilePath
(
_readFileDownloadFilename
);
...
...
@@ -95,11 +101,31 @@ void FileManager::_closeDownloadSession(bool success)
}
file
.
close
();
emit
downloadFile
Complete
();
emit
command
Complete
();
}
// If !success error is emitted elsewhere
// Close the open session
_sendTerminateCommand
();
_sendResetCommand
();
}
/// Closes out an upload session doing cleanup.
/// @param success true: successful upload completion, false: error during download
void
FileManager
::
_closeUploadSession
(
bool
success
)
{
qCDebug
(
FileManagerLog
)
<<
QString
(
"_closeUploadSession: success(%1)"
).
arg
(
success
);
_currentOperation
=
kCOIdle
;
_writeFileAccumulator
.
clear
();
_writeFileSize
=
0
;
if
(
success
)
{
emit
commandComplete
();
}
// Close the open session
_sendResetCommand
();
}
/// Respond to the Ack associated with the Read or Stream commands.
...
...
@@ -107,15 +133,13 @@ void FileManager::_closeDownloadSession(bool success)
void
FileManager
::
_downloadAckResponse
(
Request
*
readAck
,
bool
readFile
)
{
if
(
readAck
->
hdr
.
session
!=
_activeSession
)
{
_currentOperation
=
kCOIdle
;
_readFileAccumulator
.
clear
();
_closeDownloadSession
(
false
/* failure */
);
_emitErrorMessage
(
tr
(
"Download: Incorrect session returned"
));
return
;
}
if
(
readAck
->
hdr
.
offset
!=
_downloadOffset
)
{
_currentOperation
=
kCOIdle
;
_readFileAccumulator
.
clear
();
_closeDownloadSession
(
false
/* failure */
);
_emitErrorMessage
(
tr
(
"Download: Offset returned (%1) differs from offset requested/expected (%2)"
).
arg
(
readAck
->
hdr
.
offset
).
arg
(
_downloadOffset
));
return
;
}
...
...
@@ -124,7 +148,10 @@ void FileManager::_downloadAckResponse(Request* readAck, bool readFile)
_downloadOffset
+=
readAck
->
hdr
.
size
;
_readFileAccumulator
.
append
((
const
char
*
)
readAck
->
data
,
readAck
->
hdr
.
size
);
emit
downloadFileProgress
(
_readFileAccumulator
.
length
());
if
(
_downloadFileSize
!=
0
)
{
emit
commandProgress
(
100
*
((
float
)
_readFileAccumulator
.
length
()
/
(
float
)
_downloadFileSize
));
}
if
(
readAck
->
hdr
.
size
==
sizeof
(
readAck
->
data
))
{
if
(
readFile
||
readAck
->
hdr
.
burstComplete
)
{
...
...
@@ -143,7 +170,6 @@ void FileManager::_downloadAckResponse(Request* readAck, bool readFile)
}
}
else
if
(
readFile
)
{
// We only receieved a partial buffer back. These means we are at EOF
_currentOperation
=
kCOIdle
;
_closeDownloadSession
(
true
/* success */
);
}
}
...
...
@@ -198,7 +224,7 @@ void FileManager::_listAckResponse(Request* listAck)
// Directory is empty, we're done
Q_ASSERT
(
listAck
->
hdr
.
opcode
==
kRspAck
);
_currentOperation
=
kCOIdle
;
emit
list
Complete
();
emit
command
Complete
();
}
else
{
// Possibly more entries to come, need to keep trying till we get EOF
_currentOperation
=
kCOList
;
...
...
@@ -210,14 +236,16 @@ void FileManager::_listAckResponse(Request* listAck)
/// @brief Respond to the Ack associated with the create command.
void
FileManager
::
_createAckResponse
(
Request
*
createAck
)
{
qCDebug
(
FileManagerLog
)
<<
"_createAckResponse"
;
_currentOperation
=
kCOWrite
;
_activeSession
=
createAck
->
hdr
.
session
;
// Start the sequence of
read commands
// Start the sequence of
write commands from the beginning of the file
_writeOffset
=
0
;
// Start writing at beginning of file
_writeOffset
=
0
;
_writeSize
=
0
;
_writeFileDatablock
();
}
...
...
@@ -225,37 +253,30 @@ void FileManager::_createAckResponse(Request* createAck)
void
FileManager
::
_writeAckResponse
(
Request
*
writeAck
)
{
if
(
_writeOffset
+
_writeSize
>=
_writeFileSize
){
_writeFileAccumulator
.
clear
();
_writeFileSize
=
0
;
_currentOperation
=
kCOIdle
;
emit
uploadFileComplete
();
_closeUploadSession
(
true
/* success */
);
}
if
(
writeAck
->
hdr
.
session
!=
_activeSession
)
{
_currentOperation
=
kCOIdle
;
_writeFileAccumulator
.
clear
();
_closeUploadSession
(
false
/* failure */
);
_emitErrorMessage
(
tr
(
"Write: Incorrect session returned"
));
return
;
}
if
(
writeAck
->
hdr
.
offset
!=
_writeOffset
)
{
_currentOperation
=
kCOIdle
;
_writeFileAccumulator
.
clear
();
_closeUploadSession
(
false
/* failure */
);
_emitErrorMessage
(
tr
(
"Write: Offset returned (%1) differs from offset requested (%2)"
).
arg
(
writeAck
->
hdr
.
offset
).
arg
(
_writeOffset
));
return
;
}
if
(
writeAck
->
hdr
.
size
!=
sizeof
(
uint32_t
))
{
_currentOperation
=
kCOIdle
;
_writeFileAccumulator
.
clear
();
_closeUploadSession
(
false
/* failure */
);
_emitErrorMessage
(
tr
(
"Write: Returned invalid size of write size data"
));
return
;
}
if
(
writeAck
->
writeFileLength
!=
_writeSize
){
_currentOperation
=
kCOIdle
;
_writeFileAccumulator
.
clear
();
if
(
writeAck
->
writeFileLength
!=
_writeSize
)
{
_closeUploadSession
(
false
/* failure */
);
_emitErrorMessage
(
tr
(
"Write: Size returned (%1) differs from size requested (%2)"
).
arg
(
writeAck
->
writeFileLength
).
arg
(
_writeSize
));
return
;
}
...
...
@@ -266,12 +287,8 @@ void FileManager::_writeAckResponse(Request* writeAck)
/// @brief Send next write file data block.
void
FileManager
::
_writeFileDatablock
(
void
)
{
/// @brief Maximum data size in RequestHeader::data
// static const uint8_t kMaxDataLength = MAVLINK_MSG_FILE_TRANSFER_PROTOCOL_FIELD_PAYLOAD_LEN - sizeof(RequestHeader);
// static const uint8_t kMaxDataLength = Request.data;
if
(
_writeOffset
+
_writeSize
>=
_writeFileSize
){
_sendTerminateCommand
();
if
(
_writeOffset
+
_writeSize
>=
_writeFileSize
){
_closeUploadSession
(
true
/* success */
);
return
;
}
...
...
@@ -373,15 +390,13 @@ void FileManager::receiveMessage(LinkInterface* link, mavlink_message_t message)
if
(
request
->
hdr
.
req_opcode
==
kCmdListDirectory
&&
errorCode
==
kErrEOF
)
{
// This is not an error, just the end of the list loop
emit
list
Complete
();
emit
command
Complete
();
return
;
}
else
if
((
request
->
hdr
.
req_opcode
==
kCmdReadFile
||
request
->
hdr
.
req_opcode
==
kCmdBurstReadFile
)
&&
errorCode
==
kErrEOF
)
{
// This is not an error, just the end of the download loop
_closeDownloadSession
(
true
/* success */
);
return
;
}
else
if
(
request
->
hdr
.
req_opcode
==
kCmdCreateFile
)
{
// End a failed create file operation
_sendTerminateCommand
();
_emitErrorMessage
(
tr
(
"Nak received creating file, error: %1"
).
arg
(
errorString
(
request
->
data
[
0
])));
return
;
}
else
{
...
...
@@ -389,6 +404,9 @@ void FileManager::receiveMessage(LinkInterface* link, mavlink_message_t message)
if
(
request
->
hdr
.
req_opcode
==
kCmdReadFile
||
request
->
hdr
.
req_opcode
==
kCmdBurstReadFile
)
{
// Nak error during download loop, download failed
_closeDownloadSession
(
false
/* failure */
);
}
else
if
(
request
->
hdr
.
req_opcode
==
kCmdWriteFile
)
{
// Nak error during upload loop, upload failed
_closeUploadSession
(
false
/* failure */
);
}
_emitErrorMessage
(
tr
(
"Nak received, error: %1"
).
arg
(
errorString
(
request
->
data
[
0
])));
}
...
...
@@ -468,7 +486,7 @@ void FileManager::_downloadWorker(const QString& from, const QDir& downloadDir,
i
++
;
// move past slash
_readFileDownloadFilename
=
from
.
right
(
from
.
size
()
-
i
);
_currentOperation
=
readFile
?
kCOOpenRead
:
kCOOpen
Stream
;
_currentOperation
=
readFile
?
kCOOpenRead
:
kCOOpen
Burst
;
Request
request
;
request
.
hdr
.
session
=
0
;
...
...
@@ -493,8 +511,9 @@ void FileManager::uploadPath(const QString& toPath, const QFileInfo& uploadFile)
return
;
}
if
(
!
uploadFile
.
isReadable
()){
if
(
!
uploadFile
.
isReadable
()){
_emitErrorMessage
(
tr
(
"File (%1) is not readable for upload"
).
arg
(
uploadFile
.
path
()));
return
;
}
QFile
file
(
uploadFile
.
absoluteFilePath
());
...
...
@@ -607,35 +626,38 @@ void FileManager::_ackTimeout(void)
case
kCORead
:
case
kCOBurst
:
_closeDownloadSession
(
false
/* failure */
);
_currentOperation
=
kCOAck
;
_emitErrorMessage
(
tr
(
"Timeout waiting for ack: Sending Terminate command"
));
_emitErrorMessage
(
tr
(
"Timeout waiting for ack: Download failed"
));
break
;
case
kCOOpenRead
:
case
kCOOpenBurst
:
_currentOperation
=
kCOIdle
;
_emitErrorMessage
(
tr
(
"Timeout waiting for ack: Download failed"
));
_sendResetCommand
();
break
;
case
kCOCreate
:
_currentOperation
=
kCOAck
;
_writeFileAccumulator
.
clear
();
_emitErrorMessage
(
tr
(
"Timeout waiting for ack: Sending Terminate command"
));
_sendTerminateCommand
();
_currentOperation
=
kCOIdle
;
_emitErrorMessage
(
tr
(
"Timeout waiting for ack: Upload failed"
));
_sendResetCommand
();
break
;
case
kCOWrite
:
_currentOperation
=
kCOAck
;
_writeFileAccumulator
.
clear
();
_emitErrorMessage
(
tr
(
"Timeout waiting for ack: Sending Terminate command"
));
_closeUploadSession
(
false
/* failure */
);
_emitErrorMessage
(
tr
(
"Timeout waiting for ack: Upload failed"
));
break
;
default:
_currentOperation
=
kCOIdle
;
_emitErrorMessage
(
QString
(
"Timeout waiting for ack:
operation
(%1)"
).
arg
(
_currentOperation
));
_emitErrorMessage
(
QString
(
"Timeout waiting for ack:
Command failed
(%1)"
).
arg
(
_currentOperation
));
break
;
}
}
void
FileManager
::
_send
Terminate
Command
(
void
)
void
FileManager
::
_send
Reset
Command
(
void
)
{
Request
request
;
request
.
hdr
.
session
=
_activeSession
;
request
.
hdr
.
opcode
=
kCmdTerminateSession
;
request
.
hdr
.
opcode
=
kCmdResetSessions
;
request
.
hdr
.
size
=
0
;
_sendRequest
(
&
request
);
}
...
...
@@ -643,7 +665,7 @@ void FileManager::_sendTerminateCommand(void)
void
FileManager
::
_emitErrorMessage
(
const
QString
&
msg
)
{
qCDebug
(
FileManagerLog
)
<<
"Error:"
<<
msg
;
emit
errorMessage
(
msg
);
emit
commandError
(
msg
);
}
void
FileManager
::
_emitListEntry
(
const
QString
&
entry
)
...
...
src/uas/FileManager.h
View file @
5e36ee5f
...
...
@@ -35,6 +35,7 @@ Q_DECLARE_LOGGING_CATEGORY(FileManagerLog)
class
FileManager
:
public
QObject
{
Q_OBJECT
public:
FileManager
(
QObject
*
parent
,
UASInterface
*
uas
,
uint8_t
unitTestSystemIdQGC
=
0
);
...
...
@@ -65,38 +66,23 @@ public:
void
uploadPath
(
const
QString
&
toPath
,
const
QFileInfo
&
uploadFile
);
signals:
/// @brief Signalled whenever an error occurs during the listDirectory or downloadPath methods.
void
errorMessage
(
const
QString
&
msg
);
// Signals associated with the listDirectory method
///
@brief
Signalled to indicate a new directory entry was received.
/// Signalled to indicate a new directory entry was received.
void
listEntry
(
const
QString
&
entry
);
/// @brief Signalled after listDirectory completes. If an error occurs during directory listing this signal will not be emitted.
void
listComplete
(
void
);
// Signals associated with all commands
// Signals associated with the downloadPath method
/// Signalled after a command has completed
void
commandComplete
(
void
);
/// @brief Signalled after downloadPath is called to indicate length of file being downloaded
void
downloadFileLength
(
unsigned
int
length
);
/// Signalled when an error occurs during a command. In this case a commandComplete signal will
/// not be sent.
void
commandError
(
const
QString
&
msg
);
/// @brief Signalled during file download to indicate download progress
/// @param bytesReceived Number of bytes currently received from file
void
downloadFileProgress
(
unsigned
int
bytesReceived
);
/// @brief Signaled to indicate completion of file download. If an error occurs during download this signal will not be emitted.
void
downloadFileComplete
(
void
);
/// @brief Signalled after createFile acknowledge is returned to indicate length of file being downloaded
void
uploadFileLength
(
unsigned
int
length
);
/// @brief Signalled during file upload to indicate progress
/// @param bytesReceived Number of bytes currently transmitted to file
void
uploadFileProgress
(
unsigned
int
bytesReceived
);
/// @brief Signaled to indicate completion of file upload. If an error occurs during download this signal will not be emitted.
void
uploadFileComplete
(
void
);
/// Signalled during a lengthy command to show progress
/// @param value Amount of progress: 0.0 = none, 1.0 = complete
void
commandProgress
(
int
value
);
public
slots
:
void
receiveMessage
(
LinkInterface
*
link
,
mavlink_message_t
message
);
...
...
@@ -184,7 +170,7 @@ private:
kCOAck
,
// waiting for an Ack
kCOList
,
// waiting for List response
kCOOpenRead
,
// waiting for Open response followed by Read download
kCOOpen
Stream
,
// waiting for Open response, followed by Stream
download
kCOOpen
Burst
,
// waiting for Open response, followed by Burst
download
kCORead
,
// waiting for Read response
kCOBurst
,
// waiting for Burst response
kCOWrite
,
// waiting for Write response
...
...
@@ -205,8 +191,9 @@ private:
void
_writeAckResponse
(
Request
*
writeAck
);
void
_writeFileDatablock
(
void
);
void
_sendListCommand
(
void
);
void
_send
Terminate
Command
(
void
);
void
_send
Reset
Command
(
void
);
void
_closeDownloadSession
(
bool
success
);
void
_closeUploadSession
(
bool
success
);
void
_downloadWorker
(
const
QString
&
from
,
const
QDir
&
downloadDir
,
bool
readFile
);
static
QString
errorString
(
uint8_t
errorCode
);
...
...
@@ -222,15 +209,19 @@ private:
QString
_listPath
;
///< path for the current List operation
uint8_t
_activeSession
;
///< currently active session, 0 for none
uint32_t
_readOffset
;
///< current read offset
uint32_t
_writeOffset
;
///< current write offset
uint32_t
_writeSize
;
///< current write data size
uint32_t
_writeFileSize
;
///< current write file size
uint32_t
_writeFileSize
;
///< Size of file being uploaded
QByteArray
_writeFileAccumulator
;
///< Holds file being uploaded
uint32_t
_downloadOffset
;
///< current download offset
QByteArray
_readFileAccumulator
;
///< Holds file being downloaded
QByteArray
_writeFileAccumulator
;
///< Holds file being uploaded
QDir
_readFileDownloadDir
;
///< Directory to download file to
QString
_readFileDownloadFilename
;
///< Filename (no path) for download file
uint32_t
_downloadFileSize
;
///< Size of file being downloaded
uint8_t
_systemIdQGC
;
///< System ID for QGC
uint8_t
_systemIdServer
;
///< System ID for server
...
...
src/ui/QGCUASFileView.cc
View file @
5e36ee5f
...
...
@@ -22,7 +22,7 @@
======================================================================*/
#include "QGCUASFileView.h"
#include "
uas/
FileManager.h"
#include "FileManager.h"
#include "QGCFileDialog.h"
#include <QFileDialog>
...
...
@@ -32,62 +32,64 @@
QGCUASFileView
::
QGCUASFileView
(
QWidget
*
parent
,
FileManager
*
manager
)
:
QWidget
(
parent
),
_manager
(
manager
),
_listInProgress
(
false
),
_downloadInProgress
(
false
),
_uploadInProgress
(
false
)
_currentCommand
(
commandNone
)
{
_ui
.
setupUi
(
this
);
// Progress bar is only visible while a download is in progress
_ui
.
progressBar
->
setVisible
(
false
);
bool
success
;
Q_UNUSED
(
success
);
// Silence retail unused variable error
_ui
.
progressBar
->
reset
();
// Connect UI signals
success
=
connect
(
_ui
.
listFilesButton
,
SIGNAL
(
clicked
()),
this
,
SLOT
(
_refreshTree
()));
Q_ASSERT
(
success
);
success
=
connect
(
_ui
.
downloadButton
,
SIGNAL
(
clicked
()),
this
,
SLOT
(
_downloadFile
()));
Q_ASSERT
(
success
);
success
=
connect
(
_ui
.
uploadButton
,
SIGNAL
(
clicked
()),
this
,
SLOT
(
_uploadFile
()));
Q_ASSERT
(
success
);
success
=
connect
(
_ui
.
treeWidget
,
SIGNAL
(
currentItemChanged
(
QTreeWidgetItem
*
,
QTreeWidgetItem
*
)),
this
,
SLOT
(
_currentItemChanged
(
QTreeWidgetItem
*
,
QTreeWidgetItem
*
)));
Q_ASSERT
(
success
);
connect
(
_ui
.
listFilesButton
,
&
QPushButton
::
clicked
,
this
,
&
QGCUASFileView
::
_refreshTree
);
connect
(
_ui
.
downloadButton
,
&
QPushButton
::
clicked
,
this
,
&
QGCUASFileView
::
_downloadFile
);
connect
(
_ui
.
uploadButton
,
&
QPushButton
::
clicked
,
this
,
&
QGCUASFileView
::
_uploadFile
);
connect
(
_ui
.
treeWidget
,
&
QTreeWidget
::
currentItemChanged
,
this
,
&
QGCUASFileView
::
_currentItemChanged
);
// Connect signals from FileManager
connect
(
_manager
,
&
FileManager
::
commandProgress
,
this
,
&
QGCUASFileView
::
_commandProgress
);
connect
(
_manager
,
&
FileManager
::
commandComplete
,
this
,
&
QGCUASFileView
::
_commandComplete
);
connect
(
_manager
,
&
FileManager
::
commandError
,
this
,
&
QGCUASFileView
::
_commandError
);
connect
(
_manager
,
&
FileManager
::
listEntry
,
this
,
&
QGCUASFileView
::
_listEntryReceived
);
}
/// @brief Downloads the file currently selected in the tree view
void
QGCUASFileView
::
_downloadFile
(
void
)
{
Q_ASSERT
(
!
_downloadInProgress
);
if
(
_currentCommand
!=
commandNone
)
{
qWarning
()
<<
QString
(
"Download attempted while another command was in progress: _currentCommand(%1)"
).
arg
(
_currentCommand
);
return
;
}
_ui
.
statusText
->
clear
();
QString
downloadToHere
=
QGCFileDialog
::
getExistingDirectory
(
this
,
tr
(
"Download Directory"
),
QDir
::
homePath
()
,
QGCFileDialog
::
ShowDirsOnly
|
QGCFileDialog
::
DontResolveSymlinks
);
QString
downloadToHere
=
QGCFileDialog
::
getExistingDirectory
(
this
,
"Download Directory"
,
QDir
::
homePath
(),
QGCFileDialog
::
ShowDirsOnly
|
QGCFileDialog
::
DontResolveSymlinks
);
// And now download to this location
QString
path
;
QString
downloadFilename
;
QTreeWidgetItem
*
item
=
_ui
.
treeWidget
->
currentItem
();
if
(
item
&&
item
->
type
()
==
_typeFile
)
{
_downloadFilename
.
clear
();
do
{
QString
name
=
item
->
text
(
0
).
split
(
"
\t
"
)[
0
];
// Strip off file sizes
// If this is the file name and not a directory keep track of the download file name
if
(
_
downloadFilename
.
isEmpty
())
{
_
downloadFilename
=
name
;
if
(
downloadFilename
.
isEmpty
())
{
downloadFilename
=
name
;
}
path
.
prepend
(
"/"
+
name
);
item
=
item
->
parent
();
}
while
(
item
);
_ui
.
downloadButton
->
setEnabled
(
false
);
_downloadInProgress
=
true
;
_connectDownloadSignals
();
_setAllButtonsEnabled
(
false
);
_currentCommand
=
commandDownload
;
_ui
.
statusText
->
setText
(
QString
(
"Downloading: %1"
).
arg
(
downloadFilename
));
_manager
->
streamPath
(
path
,
QDir
(
downloadToHere
));
}
}
...
...
@@ -95,7 +97,10 @@ void QGCUASFileView::_downloadFile(void)
/// @brief uploads a file into the currently selected directory the tree view
void
QGCUASFileView
::
_uploadFile
(
void
)
{
Q_ASSERT
(
!
_uploadInProgress
);
if
(
_currentCommand
!=
commandNone
)
{
qWarning
()
<<
QString
(
"Upload attempted while another command was in progress: _currentCommand(%1)"
).
arg
(
_currentCommand
);
return
;
}
_ui
.
statusText
->
clear
();
...
...
@@ -113,83 +118,41 @@ void QGCUASFileView::_uploadFile(void)
item
=
item
->
parent
();
}
while
(
item
);
QString
uploadFromHere
=
QGCFileDialog
::
getOpenFileName
(
this
,
tr
(
"Upload File"
),
QDir
::
homePath
());
QString
uploadFromHere
=
QGCFileDialog
::
getOpenFileName
(
this
,
"Upload File"
,
QDir
::
homePath
());
_ui
.
statusText
->
setText
(
QString
(
"Uploading: %1"
).
arg
(
uploadFromHere
));
qDebug
()
<<
"Upload: "
<<
uploadFromHere
<<
"to path"
<<
path
;
_setAllButtonsEnabled
(
false
);
_currentCommand
=
commandUpload
;
_manager
->
uploadPath
(
path
,
uploadFromHere
);
}
/// @brief Called when length of file being downloaded is known.
void
QGCUASFileView
::
_downloadLength
(
unsigned
int
length
)
{
Q_ASSERT
(
_downloadInProgress
);
// Setup the progress bar
QProgressBar
*
bar
=
_ui
.
progressBar
;
bar
->
setMinimum
(
0
);
bar
->
setMaximum
(
length
);
bar
->
setValue
(
0
);
bar
->
setVisible
(
true
);
_ui
.
downloadButton
->
setEnabled
(
true
);
_downloadStartTime
.
start
();
_ui
.
statusText
->
setText
(
tr
(
"Downloading: %1"
).
arg
(
_downloadFilename
));
}
/// @brief Called to update the progress of the download.
/// @param bytesReceived Current count of bytes received for current download
void
QGCUASFileView
::
_downloadProgress
(
unsigned
int
bytesReceived
)
{
static
uint
lastSecsReported
=
0
;
Q_ASSERT
(
_downloadInProgress
);
_ui
.
progressBar
->
setValue
(
bytesReceived
);
// Calculate and display download rate. Only update once per second.
uint
kbReceived
=
bytesReceived
/
1024
;
uint
secs
=
_downloadStartTime
.
elapsed
()
/
1000
;
if
(
secs
!=
0
)
{
uint
kbPerSec
=
kbReceived
/
secs
;
if
(
kbPerSec
!=
0
&&
secs
!=
lastSecsReported
)
{
lastSecsReported
=
secs
;
_ui
.
statusText
->
setText
(
tr
(
"Downloading: %1 %2 KB/sec"
).
arg
(
_downloadFilename
).
arg
(
kbPerSec
));
}
}
}
/// @brief Called when the download associated with the FileManager::downloadPath command completes.
void
QGCUASFileView
::
_downloadComplete
(
void
)
/// @param value Progress bar value
void
QGCUASFileView
::
_commandProgress
(
int
value
)
{
Q_ASSERT
(
_downloadInProgress
);
_ui
.
downloadButton
->
setEnabled
(
true
);
_ui
.
progressBar
->
setVisible
(
false
);
_downloadInProgress
=
false
;
_disconnectDownloadSignals
();
_ui
.
statusText
->
setText
(
tr
(
"Download complete: %1"
).
arg
(
_downloadFilename
));
_ui
.
progressBar
->
setValue
(
value
);
}
/// @brief Called when an error occurs during a download.
/// @param msg Error message
void
QGCUASFileView
::
_
downloadErrorMessage
(
const
QString
&
msg
)
void
QGCUASFileView
::
_
commandError
(
const
QString
&
msg
)
{
if
(
_downloadInProgress
)
{
_ui
.
downloadButton
->
setEnabled
(
true
);
_ui
.
progressBar
->
setVisible
(
false
);
_downloadInProgress
=
false
;
_disconnectDownloadSignals
();
_ui
.
statusText
->
setText
(
tr
(
"Error: "
)
+
msg
);
}
_setAllButtonsEnabled
(
true
);
_currentCommand
=
commandNone
;
_ui
.
statusText
->
setText
(
QString
(
"Error: %1"
).
arg
(
msg
));
}
/// @brief Refreshes the directory list tree.
void
QGCUASFileView
::
_refreshTree
(
void
)
{
Q_ASSERT
(
!
_listInProgress
);
if
(
_currentCommand
!=
commandNone
)
{
qWarning
()
<<
QString
(
"List attempted while another command was in progress: _currentCommand(%1)"
).
arg
(
_currentCommand
);
return
;
}
_ui
.
treeWidget
->
clear
();
_ui
.
statusText
->
clear
();
...
...
@@ -199,10 +162,8 @@ void QGCUASFileView::_refreshTree(void)
_walkIndexStack
.
append
(
0
);
_walkItemStack
.
append
(
_ui
.
treeWidget
->
invisibleRootItem
());
// Don't queue up more than once
_ui
.
listFilesButton
->
setEnabled
(
false
);
_listInProgress
=
true
;
_connectListSignals
();
_setAllButtonsEnabled
(
false
);
_currentCommand
=
commandList
;
_requestDirectoryList
(
"/"
);
}
...
...
@@ -210,7 +171,10 @@ void QGCUASFileView::_refreshTree(void)
/// @brief Adds the specified directory entry to the tree view.
void
QGCUASFileView
::
_listEntryReceived
(
const
QString
&
entry
)
{
Q_ASSERT
(
_listInProgress
);
if
(
_currentCommand
!=
commandList
)
{
qWarning
()
<<
QString
(
"List entry received while no list command in progress: _currentCommand(%1)"
).
arg
(
_currentCommand
);
return
;
}
int
type
;
if
(
entry
.
startsWith
(
"F"
))
{
...
...
@@ -232,22 +196,29 @@ void QGCUASFileView::_listEntryReceived(const QString& entry)
item
->
setText
(
0
,
entry
.
right
(
entry
.
size
()
-
1
));
}
/// @brief Called when an error occurs during a directory listing.
/// @param msg Error message
void
QGCUASFileView
::
_listErrorMessage
(
const
QString
&
msg
)
/// @brief Called when a command completes successfully
void
QGCUASFileView
::
_commandComplete
(
void
)
{
if
(
_listInProgress
)
{
_ui
.
listFilesButton
->
setEnabled
(
true
);
_listInProgress
=
false
;
_disconnectListSignals
();
_ui
.
statusText
->
setText
(
tr
(
"Error: "
)
+
msg
);
QString
statusText
;
if
(
_currentCommand
==
commandDownload
)
{
_currentCommand
=
commandNone
;
_setAllButtonsEnabled
(
true
);
statusText
=
"Download complete"
;
}
else
if
(
_currentCommand
==
commandDownload
)
{
_currentCommand
=
commandNone
;
_setAllButtonsEnabled
(
true
);
statusText
=
"Upload complete"
;
}
else
if
(
_currentCommand
==
commandList
)
{
_listComplete
();
}
_ui
.
statusText
->
setText
(
statusText
);
_ui
.
progressBar
->
reset
();
}
void
QGCUASFileView
::
_listComplete
(
void
)
{
Q_ASSERT
(
_listInProgress
);
// Walk the current items, traversing down into directories
Again:
...
...
@@ -287,9 +258,8 @@ Again:
if
(
_walkIndexStack
.
count
()
!=
0
)
{
goto
Again
;
}
else
{
_ui
.
listFilesButton
->
setEnabled
(
true
);
_listInProgress
=
false
;
_disconnectListSignals
();
_setAllButtonsEnabled
(
true
);
_currentCommand
=
commandNone
;
}
}
}
...
...
@@ -297,7 +267,7 @@ Again:
void
QGCUASFileView
::
_currentItemChanged
(
QTreeWidgetItem
*
current
,
QTreeWidgetItem
*
previous
)
{
Q_UNUSED
(
previous
);
// FIXME: Should not enable when downloading
_ui
.
downloadButton
->
setEnabled
(
current
?
(
current
->
type
()
==
_typeFile
)
:
false
);
_ui
.
uploadButton
->
setEnabled
(
current
?
(
current
->
type
()
==
_typeDir
)
:
false
);
}
...
...
@@ -307,51 +277,14 @@ void QGCUASFileView::_requestDirectoryList(const QString& dir)
_manager
->
listDirectory
(
dir
);
}
/// @brief Connects to the signals associated with the FileManager::downloadPath method. We only leave these signals connected
/// while a download because there may be multiple UAS, which in turn means multiple QGCUASFileView instances. We only want the signals
/// connected to the active FileView which is doing the current download.
void
QGCUASFileView
::
_connectDownloadSignals
(
void
)
void
QGCUASFileView
::
_setAllButtonsEnabled
(
bool
enabled
)
{
bool
success
;
Q_UNUSED
(
success
);
// Silence retail unused variable error
success
=
connect
(
_manager
,
SIGNAL
(
downloadFileLength
(
unsigned
int
)),
this
,
SLOT
(
_downloadLength
(
unsigned
int
)));
Q_ASSERT
(
success
);
success
=
connect
(
_manager
,
SIGNAL
(
downloadFileProgress
(
unsigned
int
)),
this
,
SLOT
(
_downloadProgress
(
unsigned
int
)));
Q_ASSERT
(
success
);
success
=
connect
(
_manager
,
SIGNAL
(
downloadFileComplete
(
void
)),
this
,
SLOT
(
_downloadComplete
(
void
)));
Q_ASSERT
(
success
);
success
=
connect
(
_manager
,
SIGNAL
(
errorMessage
(
const
QString
&
)),
this
,
SLOT
(
_downloadErrorMessage
(
const
QString
&
)));
Q_ASSERT
(
success
);
}
void
QGCUASFileView
::
_disconnectDownloadSignals
(
void
)
{
disconnect
(
_manager
,
SIGNAL
(
downloadFileLength
(
unsigned
int
)),
this
,
SLOT
(
_downloadLength
(
unsigned
int
)));
disconnect
(
_manager
,
SIGNAL
(
downloadFileProgress
(
unsigned
int
)),
this
,
SLOT
(
_downloadProgress
(
unsigned
int
)));
disconnect
(
_manager
,
SIGNAL
(
downloadFileComplete
(
void
)),
this
,
SLOT
(
_downloadComplete
(
void
)));
disconnect
(
_manager
,
SIGNAL
(
errorMessage
(
const
QString
&
)),
this
,
SLOT
(
_downloadErrorMessage
(
const
QString
&
)));
}
/// @brief Connects to the signals associated with the FileManager::listDirectory method. We only leave these signals connected
/// while a download because there may be multiple UAS, which in turn means multiple QGCUASFileView instances. We only want the signals
/// connected to the active FileView which is doing the current download.
void
QGCUASFileView
::
_connectListSignals
(
void
)
{
bool
success
;
Q_UNUSED
(
success
);
// Silence retail unused variable error
_ui
.
treeWidget
->
setEnabled
(
enabled
);
_ui
.
downloadButton
->
setEnabled
(
enabled
);
_ui
.
listFilesButton
->
setEnabled
(
enabled
);
_ui
.
uploadButton
->
setEnabled
(
enabled
);
success
=
connect
(
_manager
,
SIGNAL
(
listEntry
(
const
QString
&
)),
this
,
SLOT
(
_listEntryReceived
(
const
QString
&
)));
Q_ASSERT
(
success
);
success
=
connect
(
_manager
,
SIGNAL
(
listComplete
(
void
)),
this
,
SLOT
(
_listComplete
(
void
)));
Q_ASSERT
(
success
);
success
=
connect
(
_manager
,
SIGNAL
(
errorMessage
(
const
QString
&
)),
this
,
SLOT
(
_listErrorMessage
(
const
QString
&
)));
Q_ASSERT
(
success
);
}
void
QGCUASFileView
::
_disconnectListSignals
(
void
)
{
disconnect
(
_manager
,
SIGNAL
(
listEntry
(
const
QString
&
)),
this
,
SLOT
(
_listEntryReceived
(
const
QString
&
)));
disconnect
(
_manager
,
SIGNAL
(
listComplete
(
void
)),
this
,
SLOT
(
_listComplete
(
void
)));
disconnect
(
_manager
,
SIGNAL
(
errorMessage
(
const
QString
&
)),
this
,
SLOT
(
_listErrorMessage
(
const
QString
&
)));
if
(
enabled
)
{
_currentItemChanged
(
_ui
.
treeWidget
->
currentItem
(),
NULL
);
}
}
src/ui/QGCUASFileView.h
View file @
5e36ee5f
...
...
@@ -41,26 +41,22 @@ protected:
FileManager
*
_manager
;
private
slots
:
void
_refreshTree
(
void
);
void
_listEntryReceived
(
const
QString
&
entry
);
void
_listErrorMessage
(
const
QString
&
msg
);
void
_listComplete
(
void
);
void
_refreshTree
(
void
);
void
_downloadFile
(
void
);
void
_uploadFile
(
void
);
void
_downloadLength
(
unsigned
int
length
);
void
_
downloadProgress
(
unsigned
int
length
);
void
_
downloadErrorMessage
(
const
QString
&
msg
);
void
_
downloa
dComplete
(
void
);
void
_
commandProgress
(
int
value
);
void
_
commandError
(
const
QString
&
msg
);
void
_
comman
dComplete
(
void
);
void
_currentItemChanged
(
QTreeWidgetItem
*
current
,
QTreeWidgetItem
*
previous
);
private:
void
_connectDownloadSignals
(
void
);
void
_disconnectDownloadSignals
(
void
);
void
_connectListSignals
(
void
);
void
_disconnectListSignals
(
void
);
void
_listComplete
(
void
);
void
_requestDirectoryList
(
const
QString
&
dir
);
void
_setAllButtonsEnabled
(
bool
enabled
);
static
const
int
_typeFile
=
QTreeWidgetItem
::
UserType
+
1
;
static
const
int
_typeDir
=
QTreeWidgetItem
::
UserType
+
2
;
...
...
@@ -70,12 +66,14 @@ private:
QList
<
QTreeWidgetItem
*>
_walkItemStack
;
Ui
::
QGCUASFileView
_ui
;
QString
_downloadFilename
;
///< File currently being downloaded, not including path
QTime
_downloadStartTime
;
///< Time at which download started
enum
CommandState
{
commandNone
,
///< No command active
commandList
,
///< List command active
commandDownload
,
///< Download command active
commandUpload
///< Upload command active
};
bool
_listInProgress
;
///< Indicates that a listDirectory command is in progress
bool
_downloadInProgress
;
///< Indicates that a downloadPath command is in progress
bool
_uploadInProgress
;
///< Indicates that a upload command is in progress
CommandState
_currentCommand
;
///< Current active command
};
#endif // QGCUASFILEVIEW_H
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