diff options
| -rw-r--r-- | src/downloadmanager.cpp | 214 | ||||
| -rw-r--r-- | src/downloadmanager.h | 81 | ||||
| -rw-r--r-- | src/javascriptinterface.cpp | 60 | ||||
| -rw-r--r-- | src/javascriptinterface.h | 50 | ||||
| -rw-r--r-- | src/loggerengine.cpp | 67 | ||||
| -rw-r--r-- | src/loggerengine.h | 53 | ||||
| -rw-r--r-- | src/sysinfo.cpp | 109 | ||||
| -rw-r--r-- | src/sysinfo.h | 43 |
8 files changed, 677 insertions, 0 deletions
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp new file mode 100644 index 0000000..47582c8 --- /dev/null +++ b/src/downloadmanager.cpp @@ -0,0 +1,214 @@ +#include "downloadmanager.h" +#include "fbgui.h" + +int DownloadManager::downloaded = 0; +// ---------------------------------------------------------------------------------------- +DownloadManager::DownloadManager(){ + qxtLog->debug() << "Initializing download manager..."; + checkDownloadDirectory(); + qnam = new QNetworkAccessManager(); + dip = false; +} +// ---------------------------------------------------------------------------------------- +void DownloadManager::checkDownloadDirectory() +{ + // check if downloadPath exists, if not create it. + downloadDir = QDir(downloadPath); + if (!downloadDir.exists()){ + qxtLog->debug() << "Download directory: " << downloadDir.path() << " doesn't exist."; + QDir::current().mkdir(downloadPath); + if (downloadDir.exists()){ + qxtLog->debug() << "Created download directory: " << downloadDir.path(); + } + else { + qxtLog->debug() << "Failed to create directory: " << downloadDir.path(); + // try to save to /tmp/fbgui + downloadDir.setPath(QDir::tempPath () + "/fbgui"); + if (!downloadDir.exists()){ + QDir::current().mkdir(QDir::tempPath () + "/fbgui"); + if (!downloadDir.exists()){ + // TODO: dont exit, this shouldn't happen anyway (right?) + qxtLog->debug() << "Fatal, no target for downloads. Exiting..."; + exit(EXIT_FAILURE); + } + } + qxtLog->debug() << "Saving downloads to: " << downloadDir.absolutePath(); + } + } + else qxtLog->debug() << "Download directory: " << downloadDir.path() << " exists."; +} +// ---------------------------------------------------------------------------------------- +void DownloadManager::downloadFile(const QString& filename) +{ + QUrl fileUrl(baseURL.resolved(QUrl(filename))); + this->processDownloadRequest(fileUrl); +} +// ---------------------------------------------------------------------------------------- +void DownloadManager::downloadFile(const QUrl& fileUrl) +{ + this->processDownloadRequest(fileUrl); +} +// ---------------------------------------------------------------------------------------- +void DownloadManager::processDownloadRequest(const QUrl& url) +{ + if (url.isEmpty()){ + qxtLog->debug() << "No URL specified for download."; + return; + } + // if download in progress, enqueue file and return. + if (dip){ + dlQ.enqueue(url); + qxtLog->debug() << "Download in progress! Queued:" << url.toString() + << "(" << dlQ.size() << " in queue)"; + return; + } + // no running downloads: enqueue and start next download. + dlQ.enqueue(url); + qxtLog->debug() << "Enqueueing:" << url.toString(); + startNextDownload(); +} +// ---------------------------------------------------------------------------------------- +void DownloadManager::startNextDownload() +{ + if (dlQ.isEmpty()){ + emit downloadQueueEmpty(); + qxtLog->debug() << "Download manager ready. (1)"; + return; + } + qxtLog->debug() << "Starting next download: " << dlQ.head().toString() + << " (" << dlQ.size() - 1 << " in queue.)"; + + // dequeue next URL to download. + QUrl url = dlQ.dequeue(); + + // get filename from URL. + QString tmp = url.path(); + tmp.remove(0, tmp.lastIndexOf(QChar('/')) + 1); + + // check if filename exists on target file system + if (downloadDir.exists(tmp)){ + qxtLog->debug() << "File already exists: " << downloadDir.absoluteFilePath(tmp); + outfile.setFileName(QString(downloadDir.absolutePath() + "/" + tmp + ".\%1").arg(downloaded)); + } + else + outfile.setFileName(downloadDir.absoluteFilePath(tmp)); + qxtLog->debug() << "Saving to: " << outfile.fileName(); + + // try to open for writing + if (!outfile.open(QIODevice::WriteOnly)){ + qxtLog->debug() << "No write access to " << outfile.fileName() << " . Skipping download..."; + return; + } + + // send the request for the file + QNetworkRequest request(url); + currentDownload = qnam->get(request); + lastProgress = 0; + currentProgress = 0; + dip = true; + dltime.start(); + QObject::connect(currentDownload, SIGNAL(readyRead()), this, SLOT(downloadReady())); + QObject::connect(currentDownload, SIGNAL(metaDataChanged()), this, SLOT(processMetaInfo())); + QObject::connect(currentDownload, SIGNAL(downloadProgress(qint64, qint64)), + this, SLOT(downloadProgress(qint64, qint64))); + QObject::connect(currentDownload, SIGNAL(finished()), this, SLOT(downloadFinished())); +} +// ---------------------------------------------------------------------------------------- +// Private slots to process downloads +// ---------------------------------------------------------------------------------------- +void DownloadManager::processMetaInfo() +{ + // fetch filesize from header & filename from URL (for now) + const QByteArray cltag = "Content-Length"; + QByteArray clinfo = currentDownload->rawHeader(cltag); + QFileInfo fi(outfile); + emit downloadInfo(outfile.fileName(), clinfo.toDouble()); +} +// ---------------------------------------------------------------------------------------- +void DownloadManager::downloadReady() +{ + // data ready, save it + outfile.write(currentDownload->readAll()); +} +// ---------------------------------------------------------------------------------------- +void DownloadManager::downloadProgress(qint64 bytesIn, qint64 bytesTotal) +{ + if (bytesIn > bytesTotal) return; + // calculate current speed + double speed = bytesIn * 1000 / dltime.elapsed(); + QString unit; + if (speed < 1024) { + unit = "bytes/sec"; + } + else if (speed < 1024*1024) { + speed /= 1024; + unit = "KB/s"; + } + else { + speed /= 1024*1024; + unit = "MB/s"; + } + // update progress only if difference higher than the updateInterval setting + currentProgress = ((bytesIn * 100) / bytesTotal); + if (currentProgress - lastProgress >= updateInterval){ + lastProgress = currentProgress; + emit updateProgress(currentProgress, speed, unit); + qxtLog->debug() << "Download progress of " << currentDownload->url().toString() + << ": " << bytesIn << "/" << bytesTotal << "(" << currentProgress << "\%)"; + } + return; +} +// ---------------------------------------------------------------------------------------- +void DownloadManager::downloadFinished() +{ + // check for errors + if (currentDownload->error()){ + currentDownload->deleteLater(); + outfile.remove(); + int statusCode = currentDownload->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + qxtLog->debug() << "Download of " << currentDownload->url().toString() + << " failed with HTTP error code: " << statusCode; + emit notify(QString("Download failed! HTTP Status Code: %1").arg(statusCode)); + } + else{ + // end download + currentDownload->deleteLater(); + outfile.close(); + downloaded++; + qxtLog->debug() << "Download of " << currentDownload->url().toString() + << " finished. (downloaded = "<< downloaded << ")"; + emit notify(QString("Successfully downloaded %1").arg(currentDownload->url().toString())); + } + dip = false; + // process next in queue + if (dlQ.isEmpty()){ + emit downloadQueueEmpty(); + qxtLog->debug() << "Download manager ready. (2)"; + return; + } + startNextDownload(); +} +/******************************************************************************************************** +* + ** dead code: Header filename fetching & renaming ** + +const QByteArray cd = "Content-Disposition"; +QByteArray cdc = currentDownload->rawHeader(cd); +int x = cdc.indexOf("filename=\"") + 10; +cdc.remove(0, x).chop(1); +if (!cdc.isEmpty()) + currentTargetFilename = cdc; +else + currentTargetFilename = QString("download.\%1").arg(downloaded); + +QString tmp = outfile.fileName(); +tmp.remove(0, tmp.lastIndexOf(QChar('/')) + 1); +qDebug() << "Trying to rename " << tmp << " to --> " << currentTargetFilename; + +if (outfile.rename(downloadPath + "/" + currentTargetFilename)) { + qxtLog->debug() << "Renamed file!"; +} +else { + qxtLog->debug() << "Failure to rename file!"; +} +*/ diff --git a/src/downloadmanager.h b/src/downloadmanager.h new file mode 100644 index 0000000..0cc1a35 --- /dev/null +++ b/src/downloadmanager.h @@ -0,0 +1,81 @@ +/* +# Copyright (c) 2010,2011 - RZ Uni Freiburg +# Copyright (c) 2010,2011 - OpenSLX Project +# +# This program/file is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your feedback to feedback@openslx.org +# +# General information about OpenSLX can be found under http://openslx.org +# +# +# Helper class managing downloads. +# +*/ + +#ifndef DOWNLOADMANAGER_H +#define DOWNLOADMANAGER_H + +#include "fbgui.h" + +extern bool debug; +extern QUrl baseURL; +extern QString binPath; +extern QString downloadPath; +extern int updateInterval; + + +class DownloadManager : public QObject +{ + Q_OBJECT + +public: + DownloadManager(); + +private: + // checks for valid download directory, ran once in constructor + void checkDownloadDirectory(); + // private control function for queueing mechanism. + void processDownloadRequest(const QUrl& url); + + // base objects for downloading + QNetworkAccessManager* qnam; + QQueue<QUrl> dlQ; + QNetworkReply* currentDownload; + QFile outfile; + QDir downloadDir; + // download progress variables + QTime dltime; + int currentProgress, lastProgress; + // download in progress flag + bool dip; + // static counter + static int downloaded; + +signals: + // notify sends a message to the javascript interface. + void notify(const QString& msg); + // downloadInfo sends static information (name, size) to the interface. + void downloadInfo(const QString& filename, const double& filesize); + // updateProgress sends download progress information to the interface. + void updateProgress(const int& percent, const double& speed, const QString& unit); + // signal emitted when download queue is empty. + void downloadQueueEmpty(); + +public slots: + // public slots to receive download requests. + void downloadFile(const QUrl& fileUrl); + void downloadFile(const QString& fileUrl); + +private slots: + // private slots to manage the downloading process + void startNextDownload(); + void processMetaInfo(); + void downloadReady(); + void downloadProgress(qint64 bytesIn, qint64 bytesTotal); + void downloadFinished(); +}; + +#endif // DOWNLOADMANAGER_H diff --git a/src/javascriptinterface.cpp b/src/javascriptinterface.cpp new file mode 100644 index 0000000..7f1b949 --- /dev/null +++ b/src/javascriptinterface.cpp @@ -0,0 +1,60 @@ +#include "fbgui.h" +#include "javascriptinterface.h" +#include "sysinfo.h" + + +//------------------------------------------------------------------------------------------------------- +JavascriptInterface::JavascriptInterface(QWebFrame *parent){ + qxtLog->debug() << "Initializing javascript interface..."; + _parent = parent; +} +//------------------------------------------------------------------------------------------------------- +JavascriptInterface::~JavascriptInterface() {} +//------------------------------------------------------------------------------------------------------- +const QString JavascriptInterface::getSysInfo(const QString& info){ + SysInfo si; + return si.getInfo(info); +} +//------------------------------------------------------------------------------------------------------- +void JavascriptInterface::attachToDOM(){ + _parent->addToJavaScriptWindowObject(QString("fbgui"), this); +} +//------------------------------------------------------------------------------------------------------- +void JavascriptInterface::startDownload(const QString& filename){ + // ignore if empty filename + if (filename.isEmpty()){ + _parent->evaluateJavaScript("alert(\"No filename!\")"); + return; + } + emit requestFile(filename); +} +//------------------------------------------------------------------------------------------------------- +void JavascriptInterface::downloadInfo(const QString& filename, const double& filesize){ + QString code = QString("downloadInfo('\%1', \%2)").arg(filename).arg(filesize); + _parent->evaluateJavaScript(code); +} +//------------------------------------------------------------------------------------------------------- +void JavascriptInterface::notify(const QString& msg){ + + QString code = QString("notify('\%1')").arg(msg); + _parent->evaluateJavaScript(code); +} +//------------------------------------------------------------------------------------------------------- +void JavascriptInterface::updateProgressBar(const int& percent, const double& speed, const QString& unit){ + if (percent == 0) return; + QString code = QString("updateProgress(\%1, \%2, '\%3')").arg(percent).arg(speed).arg(unit); + _parent->evaluateJavaScript(code); +} +//------------------------------------------------------------------------------------------------------- +void JavascriptInterface::setCallbackOnDlQueueFinished(QString& jsFunction){ + _callBackOnDownloadsFinished = jsFunction; +} +//------------------------------------------------------------------------------------------------------- +void JavascriptInterface::callbackOnDlQueueFinished(){ + QString code = QString("\%1").arg(_callBackOnDownloadsFinished); + _parent->evaluateJavaScript(code); +} +//------------------------------------------------------------------------------------------------------- +void JavascriptInterface::quit(){ + emit quitFbgui(); +} diff --git a/src/javascriptinterface.h b/src/javascriptinterface.h new file mode 100644 index 0000000..9b4303c --- /dev/null +++ b/src/javascriptinterface.h @@ -0,0 +1,50 @@ +/* +# Copyright (c) 2010,2011 - RZ Uni Freiburg +# Copyright (c) 2010,2011 - OpenSLX Project +# +# This program/file is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your feedback to feedback@openslx.org +# +# General information about OpenSLX can be found under http://openslx.org +# +# +# Interface for javascript. +# +*/ + +#ifndef JAVASCRIPTINTERFACE_H_ +#define JAVASCRIPTINTERFACE_H_ + +#include "fbgui.h" + +class JavascriptInterface : public QObject +{ + Q_OBJECT +private: + QWebFrame* _parent; + QString _callBackOnDownloadsFinished; + +public: + JavascriptInterface(QWebFrame* parent); + ~JavascriptInterface(); + +signals: + void requestFile(const QString& filename); + void quitFbgui(); + +public slots: + void attachToDOM(); + void startDownload(const QString& filename); + void setCallbackOnDlQueueFinished(QString& fctOnDownloadsFinished); + void callbackOnDlQueueFinished(); + void updateProgressBar(const int& percent, const double& speed, const QString& unit); + void downloadInfo(const QString& filename, const double& filesize); + void notify(const QString& msg); + const QString getSysInfo(const QString& info); + void quit(); +}; + +#endif // JAVASCRIPTINTERFACE_H_ diff --git a/src/loggerengine.cpp b/src/loggerengine.cpp new file mode 100644 index 0000000..5638908 --- /dev/null +++ b/src/loggerengine.cpp @@ -0,0 +1,67 @@ +#include "loggerengine.h" + +// -------------------------------------------------------------------------------------------------- +// Custom Logger Engine for debugging on framebuffer +//--------------------------------------------------------------------------------------------------- +LoggerEngine_fb::LoggerEngine_fb(QTextEdit *parent) : QxtLoggerEngine(){ + // TODO: silly parent storing ... to change! + _debugConsole = parent; + _initialized = false; + setLogLevelsEnabled(QxtLogger::DebugLevel); + enableLogging(); +} +LoggerEngine_fb::~LoggerEngine_fb(){} + +void LoggerEngine_fb::initLoggerEngine(){ + _initialized = true; + return; +} + +void LoggerEngine_fb::killLoggerEngine(){return;} + +void LoggerEngine_fb::setLogLevelEnabled(QxtLogger::LogLevels level, bool enable){ + QxtLoggerEngine::setLogLevelsEnabled(level, enable); + if (!enable) QxtLoggerEngine::setLogLevelsEnabled(QxtLogger::DebugLevel); +} +bool LoggerEngine_fb::isInitialized() const{ + return _initialized; +} + +void LoggerEngine_fb::writeFormatted(QxtLogger::LogLevel level, const QList<QVariant> & msgs){ + // TODO: handle different log levels + if (msgs.isEmpty()) return; + Q_FOREACH(const QVariant& out, msgs) + { + if (!out.isNull()) + _debugConsole->insertPlainText(out.toString()); + } + _debugConsole->insertPlainText(QString("\n")); + // autoscroll + QTextCursor c = _debugConsole->textCursor(); + c.movePosition(QTextCursor::End); + _debugConsole->setTextCursor(c); +} +//--------------------------------------------------------------------------------------------------- +// Modified QxtBasicSTDLoggerEngine +//--------------------------------------------------------------------------------------------------- +LoggerEngine_std::LoggerEngine_std() : QxtBasicSTDLoggerEngine(){} + +LoggerEngine_std::~LoggerEngine_std(){} + +void LoggerEngine_std::writeToStdErr(const QString& str_level, const QList<QVariant> &msgs){ + if (msgs.isEmpty()) return; + QString header = '[' + QTime::currentTime().toString("hh:mm:ss.zzz") + "] "; + QTextStream* errstream = stdErrStream(); + Q_ASSERT(errstream); + *errstream << header; + Q_FOREACH(const QVariant& out, msgs) + { + if (!out.isNull()) + *errstream << out.toString(); + } + *errstream << endl; +} +void LoggerEngine_std::writeToStdOut(const QString& level, const QList<QVariant> & msgs){ + // reimplementing this is needed for compiling, + // we only need write to std::err, so this function is not needed +} diff --git a/src/loggerengine.h b/src/loggerengine.h new file mode 100644 index 0000000..5d93644 --- /dev/null +++ b/src/loggerengine.h @@ -0,0 +1,53 @@ +/* +# Copyright (c) 2010,2011 - RZ Uni Freiburg +# Copyright (c) 2010,2011 - OpenSLX Project +# +# This program/file is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your feedback to feedback@openslx.org +# +# General information about OpenSLX can be found under http://openslx.org +# +# +# Custom logger engines based on Qxt library. +# +*/ +#ifndef LOGGERENGINE_H_ +#define LOGGERENGINE_H_ + +#include <QxtCore> +#include <QTime> +#include <QTextEdit> +//--------------------------------------------------------------------------------------------------- +// custom engine feeding the debug console widget +//--------------------------------------------------------------------------------------------------- +class LoggerEngine_fb : public QxtLoggerEngine { +public: + LoggerEngine_fb(QTextEdit* parent); + ~LoggerEngine_fb(); + QTextEdit *_debugConsole; + bool _initialized; + + // reimplemented virtual functions of QxtLoggerEngine + void initLoggerEngine(); + void killLoggerEngine(); + void writeFormatted(QxtLogger::LogLevel level, const QList<QVariant> & messages); + void setLogLevelEnabled(QxtLogger::LogLevels level, bool enable = true); + bool isInitialized() const; + +}; +//--------------------------------------------------------------------------------------------------- +// minor changes to QxtBasicSTDLoggerEngine +//--------------------------------------------------------------------------------------------------- +class LoggerEngine_std : public QxtBasicSTDLoggerEngine { +public: + LoggerEngine_std(); + ~LoggerEngine_std(); + // reimplemented virtual functions of QxtBasicSTDLoggerEngineqqq + void writeToStdOut(const QString& level, const QList<QVariant> &msgs); + void writeToStdErr(const QString& str_level, const QList<QVariant> &msgs); +}; + +#endif // LOGGERENGINE_H_ diff --git a/src/sysinfo.cpp b/src/sysinfo.cpp new file mode 100644 index 0000000..1c8bc8d --- /dev/null +++ b/src/sysinfo.cpp @@ -0,0 +1,109 @@ +#include "sysinfo.h" + + +// ------------------------------------------------------------------------------------------------ +SysInfo::SysInfo(){} +// ------------------------------------------------------------------------------------------------ +SysInfo::~SysInfo(){} +// ------------------------------------------------------------------------------------------------ +const QString SysInfo::getInfo(const QString& infoName){ + qxtLog->debug() << "[sysInfo] requested " << infoName; + if (infoName == QString("mac")) + return getMACAddress(); + else if (infoName == QString("ip")) + return getIPAddress(); + else if (infoName == QString("all")) + return getAllInfos(); + else if (infoName == QString("json")) + return getNames(); + /* unknown code */ + return "info_error"; +} +// ------------------------------------------------------------------------------------------------ +const QString SysInfo::getMACAddress(){ + // Returns MAC address of eth0 for now + QNetworkInterface qni = QNetworkInterface::interfaceFromName(QString("eth0")); + if (!qni.isValid()){ + qxtLog->debug() << "No interface matching \"eth0\" found."; + return "no_eth0"; + } + //eth0_index = qni.index(); + return qni.hardwareAddress(); +} +// ------------------------------------------------------------------------------------------------ +const QString SysInfo::getIPAddress(){ + // Again for eth0 only at the moment. + // TODO: this doesn't quite work yet... + QNetworkInterface qni = QNetworkInterface::interfaceFromName(QString("eth0")); + QList<QHostAddress> addrlist = qni.allAddresses(); + // This is does not return the right IP atm... + foreach(QHostAddress addr, addrlist){ + if (addr.protocol() == QAbstractSocket::IPv4Protocol && addr != QHostAddress::LocalHost){ + return addr.toString(); + } + } + // still here? + qxtLog->debug() << "ip_error"; + return "ip_error"; +} +// ------------------------------------------------------------------------------------------------ +const QByteArray SysInfo::getNames(){ + + QVariantMap foo; + foo.insert("name", "foo"); + foo.insert("type", 123); + + QVariantMap fooo; + fooo.insert("name", "boo"); + fooo.insert("type", 321); + + QVariantList jsonV; + jsonV << foo << fooo; + + QJson::Serializer serializer; + QByteArray json = serializer.serialize(jsonV); + + qxtLog->debug() << json; + return json; + +} +// ------------------------------------------------------------------------------------------------ +QString SysInfo::getAllInfos(){ + QVariantMap infos; + infos.insert("mac", getMACAddress()); + infos.insert("ip", getIPAddress()); + infos.insert("whoami", getScriptOutput("whoami")); + //infos.insert("pwd", getScriptOutput("pwd")); + + //QJson::Serializer serializer; + QByteArray json = serializer.serialize(infos); + + qxtLog->debug() << json; + return json; +} +// ------------------------------------------------------------------------------------------------ +QString SysInfo::getScriptOutput(QString cmd) +{ + QProcess *process = new QProcess(); + qDebug()<<"try to open: "<<cmd; + process->start(cmd, QIODevice::ReadOnly); + + if (!process->waitForStarted() ) + qDebug()<<"process couldn't get opened"; + + QString output; + process->waitForFinished(); + + QTextStream *txt_stream = new QTextStream(process); + + while(!txt_stream->atEnd() ) + { + qDebug()<<"read output: "; + QString tmp_str = txt_stream->readLine(); + output += tmp_str; + qDebug()<<tmp_str; + } + qDebug()<<"process finished: "; + return output; +} + diff --git a/src/sysinfo.h b/src/sysinfo.h new file mode 100644 index 0000000..cbb002e --- /dev/null +++ b/src/sysinfo.h @@ -0,0 +1,43 @@ +/* +# Copyright (c) 2010,2011 - RZ Uni Freiburg +# Copyright (c) 2010,2011 - OpenSLX Project +# +# This program/file is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your feedback to feedback@openslx.org +# +# General information about OpenSLX can be found under http://openslx.org +# +# +# Helper class to get system information. +# +*/ + +#ifndef SYSINFO_H +#define SYSINFO_H + +#include "fbgui.h" +#include <qjson/serializer.h> + +class SysInfo { +public: + SysInfo(); + ~SysInfo(); + // public access, valid infoName: "mac", "ip", ... + const QString getInfo(const QString& infoName); + +private: + // private system information readers + const QString getMACAddress(); + const QString getIPAddress(); + QString getAllInfos(); + QString getScriptOutput(QString cmd); + + // JSon testing + QJson::Serializer serializer; + const QByteArray getNames(); +}; + +#endif // SYSTINFO_H |
