0000952: Download manager
This commit is contained in:
parent
2e31e177a8
commit
3db10284b1
|
@ -99,6 +99,8 @@ set(Gui_MOC_HDRS
|
|||
Control.h
|
||||
DemoMode.h
|
||||
DownloadDialog.h
|
||||
DownloadItem.h
|
||||
DownloadManager.h
|
||||
DlgActionsImp.h
|
||||
DlgActivateWindowImp.h
|
||||
DlgCommandsImp.h
|
||||
|
@ -220,6 +222,8 @@ SET(Gui_UIC_SRCS
|
|||
DlgTreeWidget.ui
|
||||
DlgLocationAngle.ui
|
||||
DlgLocationPos.ui
|
||||
DownloadManager.ui
|
||||
DownloadItem.ui
|
||||
MouseButtons.ui
|
||||
SceneInspector.ui
|
||||
InputVector.ui
|
||||
|
@ -282,6 +286,8 @@ SET(Dialog_CPP_SRCS
|
|||
TextureMapping.cpp
|
||||
Transform.cpp
|
||||
DownloadDialog.cpp
|
||||
DownloadItem.cpp
|
||||
DownloadManager.cpp
|
||||
)
|
||||
|
||||
SET(Dialog_HPP_SRCS
|
||||
|
@ -307,6 +313,8 @@ SET(Dialog_HPP_SRCS
|
|||
TextureMapping.h
|
||||
Transform.h
|
||||
DownloadDialog.h
|
||||
DownloadItem.h
|
||||
DownloadManager.h
|
||||
)
|
||||
|
||||
SET(Dialog_SRCS
|
||||
|
@ -327,6 +335,8 @@ SET(Dialog_SRCS
|
|||
DlgProjectUtility.ui
|
||||
DlgTipOfTheDay.ui
|
||||
DlgTreeWidget.ui
|
||||
DownloadManager.ui
|
||||
DownloadItem.ui
|
||||
MouseButtons.ui
|
||||
InputVector.ui
|
||||
Placement.ui
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>304</width>
|
||||
<height>189</height>
|
||||
<width>284</width>
|
||||
<height>128</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
|
536
src/Gui/DownloadItem.cpp
Normal file
536
src/Gui/DownloadItem.cpp
Normal file
|
@ -0,0 +1,536 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2013 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <QAuthenticator>
|
||||
#include <QFileInfo>
|
||||
#include <QNetworkDiskCache>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkProxy>
|
||||
#include <QSettings>
|
||||
#include <QMetaObject>
|
||||
#include <QDesktopServices>
|
||||
#include <QFileDialog>
|
||||
#include <QHeaderView>
|
||||
#include <QDebug>
|
||||
#include <QKeyEvent>
|
||||
#include <QTextDocument>
|
||||
|
||||
#include <App/Document.h>
|
||||
|
||||
#include "DownloadItem.h"
|
||||
#include "DownloadManager.h"
|
||||
#include "Application.h"
|
||||
#include "Document.h"
|
||||
#include "MainWindow.h"
|
||||
#include "FileDialog.h"
|
||||
#include "ui_DlgAuthorization.h"
|
||||
|
||||
using namespace Gui::Dialog;
|
||||
|
||||
|
||||
EditTableView::EditTableView(QWidget *parent)
|
||||
: QTableView(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void EditTableView::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if ((event->key() == Qt::Key_Delete
|
||||
|| event->key() == Qt::Key_Backspace)
|
||||
&& model()) {
|
||||
removeOne();
|
||||
} else {
|
||||
QAbstractItemView::keyPressEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void EditTableView::removeOne()
|
||||
{
|
||||
if (!model() || !selectionModel())
|
||||
return;
|
||||
int row = currentIndex().row();
|
||||
model()->removeRow(row, rootIndex());
|
||||
QModelIndex idx = model()->index(row, 0, rootIndex());
|
||||
if (!idx.isValid())
|
||||
idx = model()->index(row - 1, 0, rootIndex());
|
||||
selectionModel()->select(idx, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
|
||||
}
|
||||
|
||||
void EditTableView::removeAll()
|
||||
{
|
||||
if (model())
|
||||
model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
SqueezeLabel::SqueezeLabel(QWidget *parent) : QLabel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void SqueezeLabel::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QFontMetrics fm = fontMetrics();
|
||||
if (fm.width(text()) > contentsRect().width()) {
|
||||
QString elided = fm.elidedText(text(), Qt::ElideMiddle, width());
|
||||
QString oldText = text();
|
||||
setText(elided);
|
||||
QLabel::paintEvent(event);
|
||||
setText(oldText);
|
||||
} else {
|
||||
QLabel::paintEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#define AUTOSAVE_IN 1000 * 3 // seconds
|
||||
#define MAXWAIT 1000 * 15 // seconds
|
||||
|
||||
AutoSaver::AutoSaver(QObject *parent) : QObject(parent)
|
||||
{
|
||||
Q_ASSERT(parent);
|
||||
}
|
||||
|
||||
AutoSaver::~AutoSaver()
|
||||
{
|
||||
if (m_timer.isActive())
|
||||
qWarning() << "AutoSaver: still active when destroyed, changes not saved.";
|
||||
}
|
||||
|
||||
void AutoSaver::changeOccurred()
|
||||
{
|
||||
if (m_firstChange.isNull())
|
||||
m_firstChange.start();
|
||||
|
||||
if (m_firstChange.elapsed() > MAXWAIT) {
|
||||
saveIfNeccessary();
|
||||
} else {
|
||||
m_timer.start(AUTOSAVE_IN, this);
|
||||
}
|
||||
}
|
||||
|
||||
void AutoSaver::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
if (event->timerId() == m_timer.timerId()) {
|
||||
saveIfNeccessary();
|
||||
} else {
|
||||
QObject::timerEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void AutoSaver::saveIfNeccessary()
|
||||
{
|
||||
if (!m_timer.isActive())
|
||||
return;
|
||||
m_timer.stop();
|
||||
m_firstChange = QTime();
|
||||
if (!QMetaObject::invokeMethod(parent(), "save", Qt::DirectConnection)) {
|
||||
qWarning() << "AutoSaver: error invoking slot save() on parent";
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
NetworkAccessManager::NetworkAccessManager(QObject *parent)
|
||||
: QNetworkAccessManager(parent)
|
||||
{
|
||||
connect(this, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
|
||||
SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
|
||||
connect(this, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)),
|
||||
SLOT(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)));
|
||||
|
||||
QNetworkDiskCache *diskCache = new QNetworkDiskCache(this);
|
||||
QString location = QDesktopServices::storageLocation(QDesktopServices::CacheLocation);
|
||||
diskCache->setCacheDirectory(location);
|
||||
setCache(diskCache);
|
||||
}
|
||||
|
||||
void NetworkAccessManager::authenticationRequired(QNetworkReply *reply, QAuthenticator *auth)
|
||||
{
|
||||
QWidget *mainWindow = Gui::getMainWindow();
|
||||
|
||||
QDialog dialog(mainWindow);
|
||||
dialog.setWindowFlags(Qt::Sheet);
|
||||
|
||||
Ui_DlgAuthorization passwordDialog;
|
||||
passwordDialog.setupUi(&dialog);
|
||||
dialog.adjustSize();
|
||||
|
||||
QString introMessage = tr("<qt>Enter username and password for \"%1\" at %2</qt>");
|
||||
introMessage = introMessage.arg(Qt::escape(reply->url().toString())).arg(Qt::escape(reply->url().toString()));
|
||||
passwordDialog.siteDescription->setText(introMessage);
|
||||
passwordDialog.siteDescription->setWordWrap(true);
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
auth->setUser(passwordDialog.username->text());
|
||||
auth->setPassword(passwordDialog.password->text());
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkAccessManager::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth)
|
||||
{
|
||||
QWidget *mainWindow = Gui::getMainWindow();
|
||||
|
||||
QDialog dialog(mainWindow);
|
||||
dialog.setWindowFlags(Qt::Sheet);
|
||||
|
||||
Ui_DlgAuthorization proxyDialog;
|
||||
proxyDialog.setupUi(&dialog);
|
||||
dialog.adjustSize();
|
||||
|
||||
QString introMessage = tr("<qt>Connect to proxy \"%1\" using:</qt>");
|
||||
introMessage = introMessage.arg(Qt::escape(proxy.hostName()));
|
||||
proxyDialog.siteDescription->setText(introMessage);
|
||||
proxyDialog.siteDescription->setWordWrap(true);
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
auth->setUser(proxyDialog.username->text());
|
||||
auth->setPassword(proxyDialog.password->text());
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
DownloadItem::DownloadItem(QNetworkReply *reply, bool requestFileName, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, m_reply(reply)
|
||||
, m_requestFileName(requestFileName)
|
||||
, m_bytesReceived(0)
|
||||
{
|
||||
setupUi(this);
|
||||
QPalette p = downloadInfoLabel->palette();
|
||||
p.setColor(QPalette::Text, Qt::darkGray);
|
||||
downloadInfoLabel->setPalette(p);
|
||||
progressBar->setMaximum(0);
|
||||
tryAgainButton->hide();
|
||||
connect(stopButton, SIGNAL(clicked()), this, SLOT(stop()));
|
||||
connect(openButton, SIGNAL(clicked()), this, SLOT(open()));
|
||||
connect(tryAgainButton, SIGNAL(clicked()), this, SLOT(tryAgain()));
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
void DownloadItem::init()
|
||||
{
|
||||
if (!m_reply)
|
||||
return;
|
||||
|
||||
// attach to the m_reply
|
||||
m_url = m_reply->url();
|
||||
m_reply->setParent(this);
|
||||
connect(m_reply, SIGNAL(readyRead()), this, SLOT(downloadReadyRead()));
|
||||
connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)),
|
||||
this, SLOT(error(QNetworkReply::NetworkError)));
|
||||
connect(m_reply, SIGNAL(downloadProgress(qint64, qint64)),
|
||||
this, SLOT(downloadProgress(qint64, qint64)));
|
||||
connect(m_reply, SIGNAL(metaDataChanged()),
|
||||
this, SLOT(metaDataChanged()));
|
||||
connect(m_reply, SIGNAL(finished()),
|
||||
this, SLOT(finished()));
|
||||
|
||||
// reset info
|
||||
downloadInfoLabel->clear();
|
||||
progressBar->setValue(0);
|
||||
getFileName();
|
||||
|
||||
// start timer for the download estimation
|
||||
m_downloadTime.start();
|
||||
|
||||
if (m_reply->error() != QNetworkReply::NoError) {
|
||||
error(m_reply->error());
|
||||
finished();
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadItem::getFileName()
|
||||
{
|
||||
QSettings settings;
|
||||
settings.beginGroup(QLatin1String("downloadmanager"));
|
||||
//QString defaultLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
|
||||
QString defaultLocation = Gui::FileDialog::getWorkingDirectory();
|
||||
QString downloadDirectory = settings.value(QLatin1String("downloadDirectory"), defaultLocation).toString();
|
||||
if (!downloadDirectory.isEmpty())
|
||||
downloadDirectory += QLatin1Char('/');
|
||||
|
||||
QString defaultFileName = saveFileName(downloadDirectory);
|
||||
QString fileName = defaultFileName;
|
||||
if (m_requestFileName) {
|
||||
fileName = QFileDialog::getSaveFileName(this, tr("Save File"), defaultFileName);
|
||||
if (fileName.isEmpty()) {
|
||||
m_reply->close();
|
||||
fileNameLabel->setText(tr("Download canceled: %1").arg(QFileInfo(defaultFileName).fileName()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_output.setFileName(fileName);
|
||||
fileNameLabel->setText(QFileInfo(m_output.fileName()).fileName());
|
||||
if (m_requestFileName)
|
||||
downloadReadyRead();
|
||||
}
|
||||
|
||||
QString DownloadItem::saveFileName(const QString &directory) const
|
||||
{
|
||||
// Move this function into QNetworkReply to also get file name sent from the server
|
||||
QString path = m_url.path();
|
||||
if (!m_fileName.isEmpty())
|
||||
path = m_fileName;
|
||||
QFileInfo info(path);
|
||||
QString baseName = info.completeBaseName();
|
||||
QString endName = info.suffix();
|
||||
|
||||
if (baseName.isEmpty()) {
|
||||
baseName = QLatin1String("unnamed_download");
|
||||
qDebug() << "DownloadManager:: downloading unknown file:" << m_url;
|
||||
}
|
||||
QString name = directory + baseName + QLatin1Char('.') + endName;
|
||||
if (QFile::exists(name)) {
|
||||
// already exists, don't overwrite
|
||||
int i = 1;
|
||||
do {
|
||||
name = directory + baseName + QLatin1Char('-') + QString::number(i++) + QLatin1Char('.') + endName;
|
||||
} while (QFile::exists(name));
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
void DownloadItem::stop()
|
||||
{
|
||||
setUpdatesEnabled(false);
|
||||
stopButton->setEnabled(false);
|
||||
stopButton->hide();
|
||||
tryAgainButton->setEnabled(true);
|
||||
tryAgainButton->show();
|
||||
setUpdatesEnabled(true);
|
||||
m_reply->abort();
|
||||
}
|
||||
|
||||
void DownloadItem::open()
|
||||
{
|
||||
QFileInfo info(m_output);
|
||||
QString selectedFilter;
|
||||
QStringList fileList;
|
||||
fileList << info.absoluteFilePath();
|
||||
SelectModule::Dict dict = SelectModule::importHandler(fileList, selectedFilter);
|
||||
|
||||
// load the files with the associated modules
|
||||
if (!dict.isEmpty()) {
|
||||
Gui::Document* doc = Gui::Application::Instance->activeDocument();
|
||||
if (doc) {
|
||||
for (SelectModule::Dict::iterator it = dict.begin(); it != dict.end(); ++it) {
|
||||
Gui::Application::Instance->importFrom(it.key().toUtf8(),
|
||||
doc->getDocument()->getName(), it.value().toAscii());
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (SelectModule::Dict::iterator it = dict.begin(); it != dict.end(); ++it) {
|
||||
Gui::Application::Instance->open(it.key().toUtf8(), it.value().toAscii());
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
QUrl url = QUrl::fromLocalFile(info.absolutePath());
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadItem::tryAgain()
|
||||
{
|
||||
if (!tryAgainButton->isEnabled())
|
||||
return;
|
||||
|
||||
tryAgainButton->setEnabled(false);
|
||||
tryAgainButton->setVisible(false);
|
||||
stopButton->setEnabled(true);
|
||||
stopButton->setVisible(true);
|
||||
progressBar->setVisible(true);
|
||||
|
||||
QNetworkReply *r = DownloadManager::getInstance()->networkAccessManager()->get(QNetworkRequest(m_url));
|
||||
if (m_reply)
|
||||
m_reply->deleteLater();
|
||||
if (m_output.exists())
|
||||
m_output.remove();
|
||||
m_reply = r;
|
||||
init();
|
||||
/*emit*/ statusChanged();
|
||||
}
|
||||
|
||||
void DownloadItem::downloadReadyRead()
|
||||
{
|
||||
if (m_requestFileName && m_output.fileName().isEmpty())
|
||||
return;
|
||||
if (!m_output.isOpen()) {
|
||||
// in case someone else has already put a file there
|
||||
if (!m_requestFileName)
|
||||
getFileName();
|
||||
if (!m_output.open(QIODevice::WriteOnly)) {
|
||||
downloadInfoLabel->setText(tr("Error opening save file: %1")
|
||||
.arg(m_output.errorString()));
|
||||
stopButton->click();
|
||||
/*emit*/ statusChanged();
|
||||
return;
|
||||
}
|
||||
/*emit*/ statusChanged();
|
||||
}
|
||||
if (-1 == m_output.write(m_reply->readAll())) {
|
||||
downloadInfoLabel->setText(tr("Error saving: %1")
|
||||
.arg(m_output.errorString()));
|
||||
stopButton->click();
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadItem::error(QNetworkReply::NetworkError)
|
||||
{
|
||||
qDebug() << "DownloadItem::error" << m_reply->errorString() << m_url;
|
||||
downloadInfoLabel->setText(tr("Network Error: %1").arg(m_reply->errorString()));
|
||||
tryAgainButton->setEnabled(true);
|
||||
tryAgainButton->setVisible(true);
|
||||
}
|
||||
|
||||
void DownloadItem::metaDataChanged()
|
||||
{
|
||||
if (m_reply->hasRawHeader(QByteArray("Content-Disposition"))) {
|
||||
QByteArray header = m_reply->rawHeader(QByteArray("Content-Disposition"));
|
||||
int index = header.indexOf("filename=");
|
||||
if (index > 0) {
|
||||
header = header.mid(index+9);
|
||||
m_fileName = QUrl::fromPercentEncoding(header);
|
||||
}
|
||||
else {
|
||||
index = header.indexOf("filename*=UTF-8''");
|
||||
if (index > 0) {
|
||||
header = header.mid(index+17);
|
||||
m_fileName = QUrl::fromPercentEncoding(header);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVariant statusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
||||
if (!statusCode.isValid())
|
||||
return;
|
||||
int status = statusCode.toInt();
|
||||
if (status != 200) {
|
||||
QString reason = m_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
|
||||
qDebug() << reason;
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadItem::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||
{
|
||||
m_bytesReceived = bytesReceived;
|
||||
if (bytesTotal == -1) {
|
||||
progressBar->setValue(0);
|
||||
progressBar->setMaximum(0);
|
||||
} else {
|
||||
progressBar->setValue(bytesReceived);
|
||||
progressBar->setMaximum(bytesTotal);
|
||||
}
|
||||
updateInfoLabel();
|
||||
}
|
||||
|
||||
void DownloadItem::updateInfoLabel()
|
||||
{
|
||||
if (m_reply->error() == QNetworkReply::NoError)
|
||||
return;
|
||||
|
||||
qint64 bytesTotal = progressBar->maximum();
|
||||
bool running = !downloadedSuccessfully();
|
||||
|
||||
// update info label
|
||||
double speed = m_bytesReceived * 1000.0 / m_downloadTime.elapsed();
|
||||
double timeRemaining = ((double)(bytesTotal - m_bytesReceived)) / speed;
|
||||
QString timeRemainingString = tr("seconds");
|
||||
if (timeRemaining > 60) {
|
||||
timeRemaining = timeRemaining / 60;
|
||||
timeRemainingString = tr("minutes");
|
||||
}
|
||||
timeRemaining = floor(timeRemaining);
|
||||
|
||||
// When downloading the eta should never be 0
|
||||
if (timeRemaining == 0)
|
||||
timeRemaining = 1;
|
||||
|
||||
QString info;
|
||||
if (running) {
|
||||
QString remaining;
|
||||
if (bytesTotal != 0)
|
||||
remaining = tr("- %4 %5 remaining")
|
||||
.arg(timeRemaining)
|
||||
.arg(timeRemainingString);
|
||||
info = QString(tr("%1 of %2 (%3/sec) %4"))
|
||||
.arg(dataString(m_bytesReceived))
|
||||
.arg(bytesTotal == 0 ? tr("?") : dataString(bytesTotal))
|
||||
.arg(dataString((int)speed))
|
||||
.arg(remaining);
|
||||
} else {
|
||||
if (m_bytesReceived == bytesTotal)
|
||||
info = dataString(m_output.size());
|
||||
else
|
||||
info = tr("%1 of %2 - Stopped")
|
||||
.arg(dataString(m_bytesReceived))
|
||||
.arg(dataString(bytesTotal));
|
||||
}
|
||||
downloadInfoLabel->setText(info);
|
||||
}
|
||||
|
||||
QString DownloadItem::dataString(int size) const
|
||||
{
|
||||
QString unit;
|
||||
if (size < 1024) {
|
||||
unit = tr("bytes");
|
||||
} else if (size < 1024*1024) {
|
||||
size /= 1024;
|
||||
unit = tr("kB");
|
||||
} else {
|
||||
size /= 1024*1024;
|
||||
unit = tr("MB");
|
||||
}
|
||||
return QString(QLatin1String("%1 %2")).arg(size).arg(unit);
|
||||
}
|
||||
|
||||
bool DownloadItem::downloading() const
|
||||
{
|
||||
return (progressBar->isVisible());
|
||||
}
|
||||
|
||||
bool DownloadItem::downloadedSuccessfully() const
|
||||
{
|
||||
return (stopButton->isHidden() && tryAgainButton->isHidden());
|
||||
}
|
||||
|
||||
void DownloadItem::finished()
|
||||
{
|
||||
progressBar->hide();
|
||||
stopButton->setEnabled(false);
|
||||
stopButton->hide();
|
||||
m_output.close();
|
||||
updateInfoLabel();
|
||||
/*emit*/ statusChanged();
|
||||
}
|
||||
|
||||
#include "moc_DownloadItem.cpp"
|
153
src/Gui/DownloadItem.h
Normal file
153
src/Gui/DownloadItem.h
Normal file
|
@ -0,0 +1,153 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2013 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef GUI_DIALOG_DOWNLOADITEM_H
|
||||
#define GUI_DIALOG_DOWNLOADITEM_H
|
||||
|
||||
#include <QBasicTimer>
|
||||
#include <QFile>
|
||||
#include <QTime>
|
||||
#include <QUrl>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QLabel>
|
||||
#include <QTableView>
|
||||
|
||||
class AutoSaver;
|
||||
class QFileIconProvider;
|
||||
|
||||
class EditTableView : public QTableView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EditTableView(QWidget *parent = 0);
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
|
||||
public Q_SLOTS:
|
||||
void removeOne();
|
||||
void removeAll();
|
||||
};
|
||||
|
||||
class SqueezeLabel : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SqueezeLabel(QWidget *parent = 0);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
This class will call the save() slot on the parent object when the parent changes.
|
||||
It will wait several seconds after changed() to combining multiple changes and
|
||||
prevent continuous writing to disk.
|
||||
*/
|
||||
class AutoSaver : public QObject {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AutoSaver(QObject *parent);
|
||||
~AutoSaver();
|
||||
void saveIfNeccessary();
|
||||
|
||||
public Q_SLOTS:
|
||||
void changeOccurred();
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *event);
|
||||
|
||||
private:
|
||||
QBasicTimer m_timer;
|
||||
QTime m_firstChange;
|
||||
|
||||
};
|
||||
|
||||
class NetworkAccessManager : public QNetworkAccessManager
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NetworkAccessManager(QObject *parent = 0);
|
||||
|
||||
private Q_SLOTS:
|
||||
void authenticationRequired(QNetworkReply *reply, QAuthenticator *auth);
|
||||
void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth);
|
||||
};
|
||||
|
||||
#include "ui_DownloadItem.h"
|
||||
|
||||
namespace Gui {
|
||||
namespace Dialog {
|
||||
class DownloadModel;
|
||||
|
||||
class DownloadItem : public QWidget, public Ui_DownloadItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_SIGNALS:
|
||||
void statusChanged();
|
||||
|
||||
public:
|
||||
DownloadItem(QNetworkReply *reply = 0, bool requestFileName = false, QWidget *parent = 0);
|
||||
bool downloading() const;
|
||||
bool downloadedSuccessfully() const;
|
||||
|
||||
QUrl m_url;
|
||||
QString m_fileName;
|
||||
|
||||
QFile m_output;
|
||||
QNetworkReply *m_reply;
|
||||
|
||||
private Q_SLOTS:
|
||||
void stop();
|
||||
void tryAgain();
|
||||
void open();
|
||||
|
||||
void downloadReadyRead();
|
||||
void error(QNetworkReply::NetworkError code);
|
||||
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||
void metaDataChanged();
|
||||
void finished();
|
||||
|
||||
private:
|
||||
void getFileName();
|
||||
void init();
|
||||
void updateInfoLabel();
|
||||
QString dataString(int size) const;
|
||||
|
||||
QString saveFileName(const QString &directory) const;
|
||||
|
||||
bool m_requestFileName;
|
||||
qint64 m_bytesReceived;
|
||||
QTime m_downloadTime;
|
||||
};
|
||||
|
||||
} // namespace Dialog
|
||||
} // namespace Gui
|
||||
|
||||
#endif // GUI_DIALOG_DOWNLOADITEM_H
|
141
src/Gui/DownloadItem.ui
Normal file
141
src/Gui/DownloadItem.ui
Normal file
|
@ -0,0 +1,141 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DownloadItem</class>
|
||||
<widget class="QWidget" name="DownloadItem">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>423</width>
|
||||
<height>98</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="fileIcon">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Ico</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="SqueezeLabel" name="fileNameLabel" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" stdset="0">
|
||||
<string>Filename</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="SqueezeLabel" name="downloadInfoLabel" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" stdset="0">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>17</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="tryAgainButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Icons/resource.qrc">
|
||||
<normaloff>:/icons/view-refresh.svg</normaloff>:/icons/view-refresh.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="stopButton">
|
||||
<property name="icon">
|
||||
<iconset resource="Icons/resource.qrc">
|
||||
<normaloff>:/icons/process-stop.svg</normaloff>:/icons/process-stop.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="openButton">
|
||||
<property name="icon">
|
||||
<iconset resource="Icons/resource.qrc">
|
||||
<normaloff>:/icons/document-open.svg</normaloff>:/icons/document-open.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>17</width>
|
||||
<height>5</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SqueezeLabel</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>DownloadItem.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="Icons/resource.qrc"/>
|
||||
<include location="../../../Imetric/FreeCAD/src/Mod/IScan3D/Gui/IScan3D.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
303
src/Gui/DownloadManager.cpp
Normal file
303
src/Gui/DownloadManager.cpp
Normal file
|
@ -0,0 +1,303 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2013 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QDockWidget>
|
||||
#include <QFileInfo>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QMetaEnum>
|
||||
#include <QSettings>
|
||||
#include <QFileIconProvider>
|
||||
#include <QWebSettings>
|
||||
|
||||
#include "DownloadItem.h"
|
||||
#include "DownloadManager.h"
|
||||
#include "ui_DownloadManager.h"
|
||||
#include "DockWindowManager.h"
|
||||
#include "MainWindow.h"
|
||||
|
||||
using namespace Gui::Dialog;
|
||||
|
||||
/* TRANSLATOR Gui::Dialog::DownloadManager */
|
||||
|
||||
DownloadManager* DownloadManager::self = 0;
|
||||
|
||||
DownloadManager* DownloadManager::getInstance()
|
||||
{
|
||||
if (!self)
|
||||
self = new DownloadManager(Gui::getMainWindow());
|
||||
return self;
|
||||
}
|
||||
|
||||
DownloadManager::DownloadManager(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, m_autoSaver(new AutoSaver(this))
|
||||
, m_manager(new NetworkAccessManager(this))
|
||||
, m_iconProvider(0)
|
||||
, m_removePolicy(Never)
|
||||
, ui(new Ui_DownloadManager())
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->downloadsView->setShowGrid(false);
|
||||
ui->downloadsView->verticalHeader()->hide();
|
||||
ui->downloadsView->horizontalHeader()->hide();
|
||||
ui->downloadsView->setAlternatingRowColors(true);
|
||||
ui->downloadsView->horizontalHeader()->setStretchLastSection(true);
|
||||
m_model = new DownloadModel(this);
|
||||
ui->downloadsView->setModel(m_model);
|
||||
connect(ui->cleanupButton, SIGNAL(clicked()), this, SLOT(cleanup()));
|
||||
load();
|
||||
|
||||
Gui::DockWindowManager* pDockMgr = Gui::DockWindowManager::instance();
|
||||
QDockWidget* dw = pDockMgr->addDockWindow(QT_TR_NOOP("Download Manager"),
|
||||
this, Qt::BottomDockWidgetArea);
|
||||
dw->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable);
|
||||
dw->show();
|
||||
}
|
||||
|
||||
DownloadManager::~DownloadManager()
|
||||
{
|
||||
m_autoSaver->changeOccurred();
|
||||
m_autoSaver->saveIfNeccessary();
|
||||
if (m_iconProvider)
|
||||
delete m_iconProvider;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
int DownloadManager::activeDownloads() const
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i < m_downloads.count(); ++i) {
|
||||
if (m_downloads.at(i)->stopButton->isEnabled())
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void DownloadManager::download(const QNetworkRequest &request, bool requestFileName)
|
||||
{
|
||||
if (request.url().isEmpty())
|
||||
return;
|
||||
handleUnsupportedContent(m_manager->get(request), requestFileName);
|
||||
}
|
||||
|
||||
void DownloadManager::handleUnsupportedContent(QNetworkReply *reply, bool requestFileName)
|
||||
{
|
||||
if (!reply || reply->url().isEmpty())
|
||||
return;
|
||||
QVariant header = reply->header(QNetworkRequest::ContentLengthHeader);
|
||||
bool ok;
|
||||
int size = header.toInt(&ok);
|
||||
if (ok && size == 0)
|
||||
return;
|
||||
|
||||
DownloadItem *item = new DownloadItem(reply, requestFileName, this);
|
||||
addItem(item);
|
||||
}
|
||||
|
||||
void DownloadManager::addItem(DownloadItem *item)
|
||||
{
|
||||
connect(item, SIGNAL(statusChanged()), this, SLOT(updateRow()));
|
||||
int row = m_downloads.count();
|
||||
m_model->beginInsertRows(QModelIndex(), row, row);
|
||||
m_downloads.append(item);
|
||||
m_model->endInsertRows();
|
||||
updateItemCount();
|
||||
show();
|
||||
ui->downloadsView->setIndexWidget(m_model->index(row, 0), item);
|
||||
QIcon icon = style()->standardIcon(QStyle::SP_FileIcon);
|
||||
item->fileIcon->setPixmap(icon.pixmap(48, 48));
|
||||
ui->downloadsView->setRowHeight(row, item->sizeHint().height());
|
||||
}
|
||||
|
||||
void DownloadManager::updateRow()
|
||||
{
|
||||
DownloadItem *item = qobject_cast<DownloadItem*>(sender());
|
||||
int row = m_downloads.indexOf(item);
|
||||
if (-1 == row)
|
||||
return;
|
||||
if (!m_iconProvider)
|
||||
m_iconProvider = new QFileIconProvider();
|
||||
QIcon icon = m_iconProvider->icon(item->m_output.fileName());
|
||||
if (icon.isNull())
|
||||
icon = style()->standardIcon(QStyle::SP_FileIcon);
|
||||
item->fileIcon->setPixmap(icon.pixmap(48, 48));
|
||||
ui->downloadsView->setRowHeight(row, item->minimumSizeHint().height());
|
||||
|
||||
bool remove = false;
|
||||
QWebSettings *globalSettings = QWebSettings::globalSettings();
|
||||
if (!item->downloading()
|
||||
&& globalSettings->testAttribute(QWebSettings::PrivateBrowsingEnabled))
|
||||
remove = true;
|
||||
|
||||
if (item->downloadedSuccessfully()
|
||||
&& removePolicy() == DownloadManager::SuccessFullDownload) {
|
||||
remove = true;
|
||||
}
|
||||
if (remove)
|
||||
m_model->removeRow(row);
|
||||
|
||||
ui->cleanupButton->setEnabled(m_downloads.count() - activeDownloads() > 0);
|
||||
}
|
||||
|
||||
DownloadManager::RemovePolicy DownloadManager::removePolicy() const
|
||||
{
|
||||
return m_removePolicy;
|
||||
}
|
||||
|
||||
void DownloadManager::setRemovePolicy(RemovePolicy policy)
|
||||
{
|
||||
if (policy == m_removePolicy)
|
||||
return;
|
||||
m_removePolicy = policy;
|
||||
m_autoSaver->changeOccurred();
|
||||
}
|
||||
|
||||
void DownloadManager::save() const
|
||||
{
|
||||
QSettings settings;
|
||||
settings.beginGroup(QLatin1String("downloadmanager"));
|
||||
QMetaEnum removePolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("RemovePolicy"));
|
||||
settings.setValue(QLatin1String("removeDownloadsPolicy"), QLatin1String(removePolicyEnum.valueToKey(m_removePolicy)));
|
||||
settings.setValue(QLatin1String("size"), size());
|
||||
if (m_removePolicy == Exit)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < m_downloads.count(); ++i) {
|
||||
QString key = QString(QLatin1String("download_%1_")).arg(i);
|
||||
settings.setValue(key + QLatin1String("url"), m_downloads[i]->m_url);
|
||||
settings.setValue(key + QLatin1String("location"), QFileInfo(m_downloads[i]->m_output).filePath());
|
||||
settings.setValue(key + QLatin1String("done"), m_downloads[i]->downloadedSuccessfully());
|
||||
}
|
||||
int i = m_downloads.count();
|
||||
QString key = QString(QLatin1String("download_%1_")).arg(i);
|
||||
while (settings.contains(key + QLatin1String("url"))) {
|
||||
settings.remove(key + QLatin1String("url"));
|
||||
settings.remove(key + QLatin1String("location"));
|
||||
settings.remove(key + QLatin1String("done"));
|
||||
key = QString(QLatin1String("download_%1_")).arg(++i);
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadManager::load()
|
||||
{
|
||||
QSettings settings;
|
||||
settings.beginGroup(QLatin1String("downloadmanager"));
|
||||
QSize size = settings.value(QLatin1String("size")).toSize();
|
||||
if (size.isValid())
|
||||
resize(size);
|
||||
QByteArray value = settings.value(QLatin1String("removeDownloadsPolicy"), QLatin1String("Never")).toByteArray();
|
||||
QMetaEnum removePolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("RemovePolicy"));
|
||||
m_removePolicy = removePolicyEnum.keyToValue(value) == -1 ?
|
||||
Never :
|
||||
static_cast<RemovePolicy>(removePolicyEnum.keyToValue(value));
|
||||
|
||||
int i = 0;
|
||||
QString key = QString(QLatin1String("download_%1_")).arg(i);
|
||||
while (settings.contains(key + QLatin1String("url"))) {
|
||||
QUrl url = settings.value(key + QLatin1String("url")).toUrl();
|
||||
QString fileName = settings.value(key + QLatin1String("location")).toString();
|
||||
bool done = settings.value(key + QLatin1String("done"), true).toBool();
|
||||
if (!url.isEmpty() && !fileName.isEmpty()) {
|
||||
DownloadItem *item = new DownloadItem(0, this);
|
||||
item->m_output.setFileName(fileName);
|
||||
item->fileNameLabel->setText(QFileInfo(item->m_output.fileName()).fileName());
|
||||
item->m_url = url;
|
||||
item->stopButton->setVisible(false);
|
||||
item->stopButton->setEnabled(false);
|
||||
item->tryAgainButton->setVisible(!done);
|
||||
item->tryAgainButton->setEnabled(!done);
|
||||
item->progressBar->setVisible(!done);
|
||||
addItem(item);
|
||||
}
|
||||
key = QString(QLatin1String("download_%1_")).arg(++i);
|
||||
}
|
||||
ui->cleanupButton->setEnabled(m_downloads.count() - activeDownloads() > 0);
|
||||
}
|
||||
|
||||
void DownloadManager::cleanup()
|
||||
{
|
||||
if (m_downloads.isEmpty())
|
||||
return;
|
||||
m_model->removeRows(0, m_downloads.count());
|
||||
updateItemCount();
|
||||
if (m_downloads.isEmpty() && m_iconProvider) {
|
||||
delete m_iconProvider;
|
||||
m_iconProvider = 0;
|
||||
}
|
||||
m_autoSaver->changeOccurred();
|
||||
}
|
||||
|
||||
void DownloadManager::updateItemCount()
|
||||
{
|
||||
int count = m_downloads.count();
|
||||
ui->itemCount->setText(count == 1 ? tr("1 Download") : tr("%1 Downloads").arg(count));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
DownloadModel::DownloadModel(DownloadManager *downloadManager, QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_downloadManager(downloadManager)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant DownloadModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.row() < 0 || index.row() >= rowCount(index.parent()))
|
||||
return QVariant();
|
||||
if (role == Qt::ToolTipRole)
|
||||
if (!m_downloadManager->m_downloads.at(index.row())->downloadedSuccessfully())
|
||||
return m_downloadManager->m_downloads.at(index.row())->downloadInfoLabel->text();
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int DownloadModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return (parent.isValid()) ? 0 : m_downloadManager->m_downloads.count();
|
||||
}
|
||||
|
||||
bool DownloadModel::removeRows(int row, int count, const QModelIndex &parent)
|
||||
{
|
||||
if (parent.isValid())
|
||||
return false;
|
||||
|
||||
int lastRow = row + count - 1;
|
||||
for (int i = lastRow; i >= row; --i) {
|
||||
if (m_downloadManager->m_downloads.at(i)->downloadedSuccessfully()
|
||||
|| m_downloadManager->m_downloads.at(i)->tryAgainButton->isEnabled()) {
|
||||
beginRemoveRows(parent, i, i);
|
||||
m_downloadManager->m_downloads.takeAt(i)->deleteLater();
|
||||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
m_downloadManager->m_autoSaver->changeOccurred();
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "moc_DownloadManager.cpp"
|
116
src/Gui/DownloadManager.h
Normal file
116
src/Gui/DownloadManager.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2013 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef GUI_DIALOG_DOWNLOADMANAGER_H
|
||||
#define GUI_DIALOG_DOWNLOADMANAGER_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QUrl>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
|
||||
class AutoSaver;
|
||||
class QFileIconProvider;
|
||||
|
||||
namespace Gui {
|
||||
namespace Dialog {
|
||||
class DownloadItem;
|
||||
class DownloadModel;
|
||||
class Ui_DownloadManager;
|
||||
|
||||
class GuiExport DownloadManager : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(RemovePolicy removePolicy READ removePolicy WRITE setRemovePolicy)
|
||||
Q_ENUMS(RemovePolicy)
|
||||
|
||||
public:
|
||||
enum RemovePolicy {
|
||||
Never,
|
||||
Exit,
|
||||
SuccessFullDownload
|
||||
};
|
||||
|
||||
static DownloadManager* getInstance();
|
||||
|
||||
private:
|
||||
DownloadManager(QWidget *parent = 0);
|
||||
~DownloadManager();
|
||||
|
||||
public:
|
||||
int activeDownloads() const;
|
||||
QNetworkAccessManager * networkAccessManager()
|
||||
{ return m_manager; }
|
||||
|
||||
RemovePolicy removePolicy() const;
|
||||
void setRemovePolicy(RemovePolicy policy);
|
||||
|
||||
public Q_SLOTS:
|
||||
void download(const QNetworkRequest &request, bool requestFileName = false);
|
||||
inline void download(const QUrl &url, bool requestFileName = false)
|
||||
{ download(QNetworkRequest(url), requestFileName); }
|
||||
void handleUnsupportedContent(QNetworkReply *reply, bool requestFileName = false);
|
||||
void cleanup();
|
||||
|
||||
private Q_SLOTS:
|
||||
void save() const;
|
||||
void updateRow();
|
||||
|
||||
private:
|
||||
void addItem(DownloadItem *item);
|
||||
void updateItemCount();
|
||||
void load();
|
||||
|
||||
AutoSaver *m_autoSaver;
|
||||
DownloadModel *m_model;
|
||||
QNetworkAccessManager *m_manager;
|
||||
QFileIconProvider *m_iconProvider;
|
||||
QList<DownloadItem*> m_downloads;
|
||||
RemovePolicy m_removePolicy;
|
||||
friend class DownloadModel;
|
||||
|
||||
private:
|
||||
Ui_DownloadManager* ui;
|
||||
static DownloadManager* self;
|
||||
};
|
||||
|
||||
class DownloadModel : public QAbstractListModel
|
||||
{
|
||||
friend class DownloadManager;
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DownloadModel(DownloadManager *downloadManager, QObject *parent = 0);
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
|
||||
|
||||
private:
|
||||
DownloadManager *m_downloadManager;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Dialog
|
||||
} // namespace Gui
|
||||
|
||||
#endif // GUI_DIALOG_DOWNLOADMANAGER_H
|
83
src/Gui/DownloadManager.ui
Normal file
83
src/Gui/DownloadManager.ui
Normal file
|
@ -0,0 +1,83 @@
|
|||
<ui version="4.0" >
|
||||
<class>Gui::Dialog::DownloadManager</class>
|
||||
<widget class="QDialog" name="Gui::Dialog::DownloadManager" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>332</width>
|
||||
<height>252</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Downloads</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="3" >
|
||||
<widget class="EditTableView" name="downloadsView" />
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" >
|
||||
<item>
|
||||
<widget class="QPushButton" name="cleanupButton" >
|
||||
<property name="enabled" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Clean up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0" >
|
||||
<size>
|
||||
<width>58</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLabel" name="itemCount" >
|
||||
<property name="text" >
|
||||
<string>0 Items</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" >
|
||||
<spacer name="horizontalSpacer" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0" >
|
||||
<size>
|
||||
<width>148</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>EditTableView</class>
|
||||
<extends>QTableView</extends>
|
||||
<header>DownloadItem.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
336
src/Gui/Icons/process-stop.svg
Normal file
336
src/Gui/Icons/process-stop.svg
Normal file
|
@ -0,0 +1,336 @@
|
|||
<?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:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="48.000000px"
|
||||
height="48.000000px"
|
||||
id="svg6361"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.46"
|
||||
sodipodi:docbase="/home/jimmac/gfx/ximian/tango-icon-theme/scalable/actions"
|
||||
sodipodi:docname="process-stop.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<defs
|
||||
id="defs3">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 24 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="48 : 24 : 1"
|
||||
inkscape:persp3d-origin="24 : 16 : 1"
|
||||
id="perspective52" />
|
||||
<linearGradient
|
||||
id="linearGradient2256">
|
||||
<stop
|
||||
style="stop-color:#ff0202;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2258" />
|
||||
<stop
|
||||
style="stop-color:#ff9b9b;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop2260" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2248">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2250" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2252" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient9647">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop9649" />
|
||||
<stop
|
||||
style="stop-color:#dbdbdb;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop9651" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient21644">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop21646" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop21648" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient21644"
|
||||
id="radialGradient21650"
|
||||
cx="25.125"
|
||||
cy="36.75"
|
||||
fx="25.125"
|
||||
fy="36.75"
|
||||
r="15.75"
|
||||
gradientTransform="matrix(1.000000,0.000000,0.000000,0.595238,-2.300678e-15,14.87500)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient7895">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop7897" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop7899" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4981">
|
||||
<stop
|
||||
style="stop-color:#cc0000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4983" />
|
||||
<stop
|
||||
style="stop-color:#b30000;stop-opacity:1.0000000;"
|
||||
offset="1.0000000"
|
||||
id="stop4985" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient15762"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop15764"
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop15766"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient14236">
|
||||
<stop
|
||||
id="stop14238"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#ed4040;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
id="stop14240"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#a40000;stop-opacity:1.0000000;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient11780">
|
||||
<stop
|
||||
style="stop-color:#ff8b8b;stop-opacity:1.0000000;"
|
||||
offset="0.0000000"
|
||||
id="stop11782" />
|
||||
<stop
|
||||
style="stop-color:#ec1b1b;stop-opacity:1.0000000;"
|
||||
offset="1.0000000"
|
||||
id="stop11784" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient11014">
|
||||
<stop
|
||||
style="stop-color:#a80000;stop-opacity:1.0000000;"
|
||||
offset="0.0000000"
|
||||
id="stop11016" />
|
||||
<stop
|
||||
style="stop-color:#c60000;stop-opacity:1.0000000;"
|
||||
offset="0.0000000"
|
||||
id="stop13245" />
|
||||
<stop
|
||||
style="stop-color:#e50000;stop-opacity:1.0000000;"
|
||||
offset="1.0000000"
|
||||
id="stop11018" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="9.6507530"
|
||||
x2="9.8940229"
|
||||
y1="5.3855424"
|
||||
x1="5.7365270"
|
||||
gradientTransform="matrix(-1.000000,0.000000,0.000000,-1.000000,31.72170,31.29079)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient15772"
|
||||
xlink:href="#linearGradient15762"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient11780"
|
||||
id="linearGradient2057"
|
||||
x1="15.737001"
|
||||
y1="12.503600"
|
||||
x2="53.570126"
|
||||
y2="47.374317"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0.000000,-2.000000)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4981"
|
||||
id="linearGradient4987"
|
||||
x1="23.995985"
|
||||
y1="20.105337"
|
||||
x2="41.047836"
|
||||
y2="37.959785"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0.000000,-2.000000)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient7895"
|
||||
id="linearGradient7901"
|
||||
x1="15.578875"
|
||||
y1="16.285088"
|
||||
x2="32.166405"
|
||||
y2="28.394291"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient9647"
|
||||
id="radialGradient2239"
|
||||
cx="24.30225"
|
||||
cy="33.30225"
|
||||
fx="24.30225"
|
||||
fy="33.30225"
|
||||
r="12.30225"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.693981,-5.775714e-16,5.775714e-16,1.693981,-16.86529,-25.11111)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4981"
|
||||
id="linearGradient2243"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="23.995985"
|
||||
y1="20.105337"
|
||||
x2="41.047836"
|
||||
y2="37.959785"
|
||||
gradientTransform="matrix(0.988373,0.000000,0.000000,0.988373,0.279002,0.278984)" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2248"
|
||||
id="radialGradient2254"
|
||||
cx="16.75"
|
||||
cy="10.666344"
|
||||
fx="16.75"
|
||||
fy="10.666344"
|
||||
r="21.25"
|
||||
gradientTransform="matrix(4.154957,-2.979206e-24,3.255657e-24,3.198723,-52.84553,-23.50921)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2256"
|
||||
id="linearGradient2262"
|
||||
x1="21.75"
|
||||
y1="15.80225"
|
||||
x2="24.30225"
|
||||
y2="35.05225"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0.000000,-2.000000)" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
inkscape:guide-bbox="true"
|
||||
showguides="true"
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="0.15294118"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="4"
|
||||
inkscape:cx="0.007276"
|
||||
inkscape:cy="7.0544576"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="786"
|
||||
inkscape:window-height="688"
|
||||
inkscape:window-x="488"
|
||||
inkscape:window-y="160"
|
||||
inkscape:showpageshadow="false" />
|
||||
<metadata
|
||||
id="metadata4">
|
||||
<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>Stop</dc:title>
|
||||
<dc:date>2005-10-16</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Andreas Nilsson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>stop</rdf:li>
|
||||
<rdf:li>halt</rdf:li>
|
||||
<rdf:li>error</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Steiner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/publicdomain/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:0.63068183;color:#000000;fill:url(#radialGradient21650);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
||||
id="path21642"
|
||||
sodipodi:cx="25.125"
|
||||
sodipodi:cy="36.75"
|
||||
sodipodi:rx="15.75"
|
||||
sodipodi:ry="9.375"
|
||||
d="M 40.875 36.75 A 15.75 9.375 0 1 1 9.375,36.75 A 15.75 9.375 0 1 1 40.875 36.75 z"
|
||||
transform="matrix(1.173803,0.000000,0.000000,0.600000,-5.265866,19.57500)" />
|
||||
<path
|
||||
style="fill:url(#linearGradient4987);fill-opacity:1;fill-rule:evenodd;stroke:#860000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 15.591006,0.4919213 L 32.676311,0.4919213 L 45.497585,13.586385 L 45.497585,31.48003 L 32.848986,43.496929 L 15.418649,43.496929 L 2.4943857,30.658264 L 2.4943857,13.464078 L 15.591006,0.4919213 z "
|
||||
id="path9480"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
<path
|
||||
style="opacity:0.81318683;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2057);stroke-width:1.00000024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
|
||||
d="M 16.020655,1.5003424 L 32.248563,1.5003424 L 44.496456,13.922717 L 44.496456,31.037001 L 32.638472,42.48783 L 15.870253,42.48783 L 3.5090792,30.208718 L 3.5090792,13.84561 L 16.020655,1.5003424 z "
|
||||
id="path9482"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
<path
|
||||
style="opacity:0.28977272;fill:url(#radialGradient2254);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 15.6875,0.75 L 2.75,13.5625 L 2.75,30.5625 L 5.6875,33.46875 C 22.450041,33.526299 22.164665,20.450067 45.25,21.59375 L 45.25,13.6875 L 32.5625,0.75 L 15.6875,0.75 z "
|
||||
id="path2241"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
<path
|
||||
style="fill:url(#radialGradient2239);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2262);stroke-width:0.99999958;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 16.767175,10.5 L 12.5,14.767175 L 20.035075,22.30225 L 12.5,29.837325 L 16.767175,34.104501 L 24.30225,26.569425 L 31.837325,34.104501 L 36.104501,29.837325 L 28.569425,22.30225 L 36.104501,14.767175 L 31.837325,10.5 L 24.30225,18.035075 L 16.767175,10.5 z "
|
||||
id="path2787" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 12 KiB |
|
@ -49,6 +49,7 @@
|
|||
<file>edit-edit.svg</file>
|
||||
<file>help-browser.svg</file>
|
||||
<file>preferences-system.svg</file>
|
||||
<file>process-stop.svg</file>
|
||||
<file>window-new.svg</file>
|
||||
<file>camera-photo.svg</file>
|
||||
<file>applications-accessories.svg</file>
|
||||
|
|
|
@ -64,6 +64,8 @@
|
|||
#include "MainWindow.h"
|
||||
#include "Application.h"
|
||||
#include "Assistant.h"
|
||||
#include "DownloadDialog.h"
|
||||
#include "DownloadManager.h"
|
||||
#include "WaitCursor.h"
|
||||
|
||||
#include "Action.h"
|
||||
|
@ -1543,6 +1545,12 @@ void MainWindow::loadUrls(App::Document* doc, const QList<QUrl>& url)
|
|||
(const char*)info.absoluteFilePath().toUtf8());
|
||||
}
|
||||
}
|
||||
else if (it->scheme().toLower() == QLatin1String("http")) {
|
||||
Gui::Dialog::DownloadManager::getInstance()->download(*it);
|
||||
}
|
||||
else if (it->scheme().toLower() == QLatin1String("ftp")) {
|
||||
Gui::Dialog::DownloadManager::getInstance()->download(*it);
|
||||
}
|
||||
}
|
||||
|
||||
const char *docName = doc ? doc->getName() : "Unnamed";
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include <Gui/DownloadDialog.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/OnlineDocumentation.h>
|
||||
#include <Gui/DownloadManager.h>
|
||||
|
||||
#include <Base/Parameter.h>
|
||||
#include <Base/Exception.h>
|
||||
|
@ -119,6 +120,8 @@ BrowserView::BrowserView(QWidget* parent)
|
|||
this, SLOT(onLinkClicked(const QUrl &)));
|
||||
connect(view->page(), SIGNAL(downloadRequested(const QNetworkRequest &)),
|
||||
this, SLOT(onDownloadRequested(const QNetworkRequest &)));
|
||||
connect(view->page(), SIGNAL(unsupportedContent(QNetworkReply*)),
|
||||
this, SLOT(onUnsupportedContent(QNetworkReply*)));
|
||||
}
|
||||
|
||||
/** Destroys the object and frees any allocated resources */
|
||||
|
@ -181,8 +184,12 @@ bool BrowserView::chckHostAllowed(const QString& host)
|
|||
|
||||
void BrowserView::onDownloadRequested(const QNetworkRequest & request)
|
||||
{
|
||||
Dialog::DownloadDialog dlg (request.url(),this);
|
||||
dlg.exec();
|
||||
Gui::Dialog::DownloadManager::getInstance()->download(request);
|
||||
}
|
||||
|
||||
void BrowserView::onUnsupportedContent(QNetworkReply* reply)
|
||||
{
|
||||
Gui::Dialog::DownloadManager::getInstance()->handleUnsupportedContent(reply);
|
||||
}
|
||||
|
||||
void BrowserView::load(const char* URL)
|
||||
|
|
|
@ -96,6 +96,7 @@ protected Q_SLOTS:
|
|||
void onLinkClicked (const QUrl& url);
|
||||
bool chckHostAllowed(const QString& host);
|
||||
void onDownloadRequested(const QNetworkRequest& request);
|
||||
void onUnsupportedContent(QNetworkReply* reply);
|
||||
|
||||
private:
|
||||
WebView* view;
|
||||
|
|
Loading…
Reference in New Issue
Block a user