mediaView = new MediaView(this);
views->addWidget(mediaView);
- // lazy initialized views
+ // lazily initialized views
aboutView = 0;
settingsView = 0;
toolbarSearch = new SearchLineEdit(this);
toolbarSearch->setFont(qApp->font());
- // toolbarSearch->setMinimumWidth(200);
connect(toolbarSearch, SIGNAL(search(const QString&)), searchView, SLOT(watch(const QString&)));
// build ui
showWidget(searchView);
setCentralWidget(views);
-
- // top dock widget
- /*
- QLabel* message = new QLabel(this);
- message->setText(QString("A new version of %1 is available.").arg(Constants::APP_NAME));
- message->setMargin(10);
- message->setAlignment(Qt::AlignCenter);
- QPalette palette;
- message->setBackgroundRole(QPalette::ToolTipBase);
- message->setForegroundRole(QPalette::ToolTipText);
- message->setAutoFillBackground(true);
- QDockWidget *dockWidget = new QDockWidget("", this, 0);
- dockWidget->setTitleBarWidget(0);
- dockWidget->setWidget(message);
- dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
- addDockWidget(Qt::TopDockWidgetArea, dockWidget);
- */
-
}
MainWindow::~MainWindow() {
backAct = new QAction(QIcon(":/images/go-previous.png"), tr("&Back"), this);
backAct->setEnabled(false);
- backAct->setShortcut(tr("Alt+Left"));
+ backAct->setShortcut(QKeySequence(Qt::ALT + Qt::Key_Left));
backAct->setStatusTip(tr("Go to the previous view"));
actions->insert("back", backAct);
connect(backAct, SIGNAL(triggered()), this, SLOT(goBack()));
stopAct = new QAction(QtIconLoader::icon("media-stop", QIcon(":/images/stop.png")), tr("&Stop"), this);
stopAct->setStatusTip(tr("Stop playback and go back to the search view"));
- stopAct->setShortcut(tr("Esc"));
+ stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop));
actions->insert("stop", stopAct);
connect(stopAct, SIGNAL(triggered()), this, SLOT(stop()));
skipAct = new QAction(QtIconLoader::icon("media-skip-forward", QIcon(":/images/skip.png")), tr("S&kip"), this);
skipAct->setStatusTip(tr("Skip to the next video"));
- skipAct->setShortcut(tr("Ctrl+Right"));
+ skipAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_Right) << QKeySequence(Qt::Key_MediaNext));
skipAct->setEnabled(false);
actions->insert("skip", skipAct);
connect(skipAct, SIGNAL(triggered()), mediaView, SLOT(skip()));
pauseAct = new QAction(QtIconLoader::icon("media-pause", QIcon(":/images/pause.png")), tr("&Pause"), this);
pauseAct->setStatusTip(tr("Pause playback"));
- pauseAct->setShortcut(tr("Space"));
+ pauseAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Space) << QKeySequence(Qt::Key_MediaPlay));
pauseAct->setEnabled(false);
actions->insert("pause", pauseAct);
connect(pauseAct, SIGNAL(triggered()), mediaView, SLOT(pause()));
fullscreenAct = new QAction(QtIconLoader::icon("view-fullscreen", QIcon(":/images/view-fullscreen.png")), tr("&Full Screen"), this);
fullscreenAct->setStatusTip(tr("Go full screen"));
- fullscreenAct->setShortcut(tr("Alt+Return"));
+ fullscreenAct->setShortcut(QKeySequence(Qt::ALT + Qt::Key_Return));
fullscreenAct->setShortcutContext(Qt::ApplicationShortcut);
actions->insert("fullscreen", fullscreenAct);
connect(fullscreenAct, SIGNAL(triggered()), this, SLOT(fullscreen()));
+ compactViewAct = new QAction(tr("&Compact mode"), this);
+ compactViewAct->setStatusTip(tr("Hide the playlist and the toolbar"));
+ compactViewAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return));
+ compactViewAct->setCheckable(true);
+ compactViewAct->setChecked(false);
+ compactViewAct->setEnabled(false);
+ actions->insert("compactView", compactViewAct);
+ connect(compactViewAct, SIGNAL(toggled(bool)), this, SLOT(compactView(bool)));
+
/*
// icon should be document-save but it is ugly
downloadAct = new QAction(QtIconLoader::icon("go-down", QIcon(":/images/go-down.png")), tr("&Download"), this);
downloadAct->setStatusTip(tr("Download this video"));
downloadAct->setShortcut(tr("Ctrl+S"));
- actions.insert("download", downloadAct);
+ downloadAct->setEnabled(false);
+ actions->insert("download", downloadAct);
connect(downloadAct, SIGNAL(triggered()), this, SLOT(download()));
*/
webPageAct = new QAction(QtIconLoader::icon("internet-web-browser", QIcon(":/images/internet-web-browser.png")), tr("&YouTube"), this);
webPageAct->setStatusTip(tr("Open the YouTube video page"));
- webPageAct->setShortcut(tr("Ctrl+Y"));
+ webPageAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Y));
webPageAct->setEnabled(false);
actions->insert("webpage", webPageAct);
connect(webPageAct, SIGNAL(triggered()), mediaView, SLOT(openWebPage()));
removeAct = new QAction(tr("&Remove"), this);
removeAct->setStatusTip(tr("Remove the selected videos from the playlist"));
- QList<QKeySequence> shortcuts;
- shortcuts << QKeySequence("Del") << QKeySequence("Backspace");
- removeAct->setShortcuts(shortcuts);
+ removeAct->setShortcuts(QList<QKeySequence>() << QKeySequence("Del") << QKeySequence("Backspace"));
removeAct->setEnabled(false);
actions->insert("remove", removeAct);
connect(removeAct, SIGNAL(triggered()), mediaView, SLOT(removeSelected()));
moveUpAct = new QAction(QtIconLoader::icon("go-up", QIcon(":/images/go-up.png")), tr("Move &Up"), this);
moveUpAct->setStatusTip(tr("Move up the selected videos in the playlist"));
- moveUpAct->setShortcut(tr("Ctrl+Up"));
+ moveUpAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Up));
moveUpAct->setEnabled(false);
actions->insert("moveUp", moveUpAct);
connect(moveUpAct, SIGNAL(triggered()), mediaView, SLOT(moveUpSelected()));
moveDownAct = new QAction(QtIconLoader::icon("go-down", QIcon(":/images/go-down.png")), tr("Move &Down"), this);
moveDownAct->setStatusTip(tr("Move down the selected videos in the playlist"));
- moveDownAct->setShortcut(tr("Ctrl+Down"));
+ moveDownAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Down));
moveDownAct->setEnabled(false);
actions->insert("moveDown", moveDownAct);
connect(moveDownAct, SIGNAL(triggered()), mediaView, SLOT(moveDownSelected()));
siteAct = new QAction(tr("&Website"), this);
siteAct->setShortcut(QKeySequence::HelpContents);
- siteAct->setStatusTip(tr("Minitube on the Web"));
+ siteAct->setStatusTip(tr("%1 on the Web").arg(Constants::APP_NAME));
actions->insert("site", siteAct);
connect(siteAct, SIGNAL(triggered()), this, SLOT(visitSite()));
actions->insert("about", aboutAct);
connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
- searchFocusAct = new QAction(tr("&Search"), this);
+ // Invisible actions
+
+ searchFocusAct = new QAction(this);
searchFocusAct->setShortcut(QKeySequence::Find);
actions->insert("search", searchFocusAct);
connect(searchFocusAct, SIGNAL(triggered()), this, SLOT(searchFocus()));
addAction(searchFocusAct);
+ volumeUpAct = new QAction(this);
+ volumeUpAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Plus));
+ actions->insert("volume-up", volumeUpAct);
+ connect(volumeUpAct, SIGNAL(triggered()), this, SLOT(volumeUp()));
+ addAction(volumeUpAct);
+
+ volumeDownAct = new QAction(this);
+ volumeDownAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Minus));
+ actions->insert("volume-down", volumeDownAct);
+ connect(volumeDownAct, SIGNAL(triggered()), this, SLOT(volumeDown()));
+ addAction(volumeDownAct);
+
+ volumeMuteAct = new QAction(this);
+ volumeMuteAct->setShortcut(tr("Ctrl+M"));
+ actions->insert("volume-mute", volumeMuteAct);
+ connect(volumeMuteAct, SIGNAL(triggered()), this, SLOT(volumeMute()));
+ addAction(volumeMuteAct);
+
// common action properties
foreach (QAction *action, actions->values()) {
+
+ // add actions to the MainWindow so that they work
+ // when the menu is hidden
+ addAction(action);
+
// never autorepeat.
// unexperienced users tend to keep keys pressed for a "long" time
action->setAutoRepeat(false);
action->setToolTip(action->statusTip());
+ // show keyboard shortcuts in the status bar
+ if (!action->shortcut().isEmpty())
+ action->setStatusTip(action->statusTip() + " (" + action->shortcut().toString() + ")");
+
+ // make the actions work when video is fullscreen
+ action->setShortcutContext(Qt::ApplicationShortcut);
+
#ifdef Q_WS_MAC
// OSX does not use icons in menus
action->setIconVisibleInMenu(false);
fileMenu = menuBar()->addMenu(tr("&Application"));
// menus->insert("file", fileMenu);
- /*
- fileMenu->addAction(settingsAct);
+ // fileMenu->addAction(settingsAct);
fileMenu->addSeparator();
- */
fileMenu->addAction(quitAct);
playlistMenu = menuBar()->addMenu(tr("&Playlist"));
viewMenu->addSeparator();
viewMenu->addAction(webPageAct);
viewMenu->addSeparator();
+ // viewMenu->addAction(downloadAct);
+ viewMenu->addAction(compactViewAct);
viewMenu->addAction(fullscreenAct);
helpMenu = menuBar()->addMenu(tr("&Help"));
seekSlider = new Phonon::SeekSlider(this);
seekSlider->setIconVisible(false);
- // seekSlider->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
- mainToolBar->addWidget(new Spacer(mainToolBar, seekSlider));
+ Spacer *seekSliderSpacer = new Spacer(mainToolBar, seekSlider);
+ seekSliderSpacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ mainToolBar->addWidget(seekSliderSpacer);
volumeSlider = new Phonon::VolumeSlider(this);
- // this makes the volume slider smaller...
- volumeSlider->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+ // this makes the volume slider smaller
+ volumeSlider->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
mainToolBar->addWidget(new Spacer(mainToolBar, volumeSlider));
- // mainToolBar->addSeparator();
- // mainToolBar->addAction(downloadAct);
- // mainToolBar->addAction(webPageAct);
-
- // toolbarSearch->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
mainToolBar->addWidget(new Spacer(mainToolBar, toolbarSearch));
addToolBar(mainToolBar);
}
void MainWindow::createStatusBar() {
+ currentTime = new QLabel(this);
+ statusBar()->addPermanentWidget(currentTime);
+
+ totalTime = new QLabel(this);
+ statusBar()->addPermanentWidget(totalTime);
+
+ // remove ugly borders on OSX
+ statusBar()->setStyleSheet("::item{border:0 solid}");
+
statusBar()->show();
- statusBar()->setBackgroundRole(QPalette::Dark);
- // statusBar()->setAutoFillBackground(true);
}
void MainWindow::readSettings() {
}
void MainWindow::writeSettings() {
+ // do not save geometry when in full screen
+ if (m_fullscreen)
+ return;
QSettings settings;
settings.setValue("geometry", saveGeometry());
}
void MainWindow::showWidget ( QWidget* widget ) {
+ setUpdatesEnabled(false);
+
// call hide method on the current view
View* oldView = dynamic_cast<View *> (views->currentWidget());
if (oldView != NULL) {
if (windowTitle.length())
windowTitle += " - ";
setWindowTitle(windowTitle + Constants::APP_NAME);
- setStatusTip(metadata.value("description").toString());
+ statusBar()->showMessage((metadata.value("description").toString()));
+
}
// backAct->setEnabled(history->size() > 1);
+ // settingsAct->setEnabled(widget != settingsView);
stopAct->setEnabled(widget == mediaView);
fullscreenAct->setEnabled(widget == mediaView);
+ compactViewAct->setEnabled(widget == mediaView);
webPageAct->setEnabled(widget == mediaView);
- // settingsAct->setEnabled(widget != settingsView);
aboutAct->setEnabled(widget != aboutView);
- // toolbar only for the mediaView
- // This is cool on the Mac
- // But does not respect layouts, maybe it's a Qt bug
+ /*
+ // this is not the best place to enable downloads, but the user is informed
+ // if there really is no video is playing
+ downloadAct->setEnabled(widget == mediaView);
+ */
+
+ // cool toolbar on the Mac
// setUnifiedTitleAndToolBarOnMac(widget == mediaView);
- mainToolBar->setVisible(widget == mediaView);
+ // toolbar only for the mediaView
+ mainToolBar->setVisible(widget == mediaView && !compactViewAct->isChecked());
history->push(widget);
+
+#ifdef Q_WS_MAC
+ // crossfade only on OSX
+ // where we can be sure of video performance
fadeInWidget(views->currentWidget(), widget);
+#endif
+
views->setCurrentWidget(widget);
+ setUpdatesEnabled(true);
}
void MainWindow::fadeInWidget(QWidget *oldWidget, QWidget *newWidget) {
void MainWindow::showSearch() {
showWidget(searchView);
+ currentTime->clear();
+ totalTime->clear();
}
void MainWindow::showMedia(QString query) {
case Phonon::ErrorState:
if (mediaObject->errorType() == Phonon::FatalError) {
- setStatusTip("Something went REALLY wrong: " + mediaObject->errorString());
+ statusBar()->showMessage(tr("Fatal error: %1").arg(mediaObject->errorString()));
} else {
- setStatusTip("Something went wrong: " + mediaObject->errorString());
+ statusBar()->showMessage(tr("Error: %1").arg(mediaObject->errorString()));
}
break;
pauseAct->setEnabled(true);
pauseAct->setIcon(QtIconLoader::icon("media-pause", QIcon(":/images/pause.png")));
pauseAct->setText(tr("&Pause"));
- pauseAct->setStatusTip(tr("Pause playback"));
+ pauseAct->setStatusTip(tr("Pause playback") + " (" + pauseAct->shortcut().toString() + ")");
skipAct->setEnabled(true);
break;
pauseAct->setEnabled(true);
pauseAct->setIcon(QtIconLoader::icon("media-play", QIcon(":/images/play.png")));
pauseAct->setText(tr("&Play"));
- pauseAct->setStatusTip(tr("Resume playback"));
+ pauseAct->setStatusTip(tr("Resume playback") + " (" + pauseAct->shortcut().toString() + ")");
break;
case Phonon::BufferingState:
case Phonon::LoadingState:
skipAct->setEnabled(true);
pauseAct->setEnabled(false);
+ currentTime->clear();
+ totalTime->clear();
break;
default:
}
void MainWindow::fullscreen() {
+
+ setUpdatesEnabled(false);
+
if (m_fullscreen) {
- mediaView->exitFullscreen();
- fullscreenAct->setShortcut(tr("Alt+Return"));
+ // use setShortucs instead of setShortcut
+ // the latter seems not to work
+ fullscreenAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::ALT + Qt::Key_Return));
fullscreenAct->setText(tr("&Full Screen"));
- stopAct->setShortcut(tr("Esc"));
+ stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop));
+ if (m_maximized) showMaximized();
+ else showNormal();
} else {
- mediaView->fullscreen();
- stopAct->setShortcut(tr(""));
- fullscreenAct->setShortcut(tr("Esc"));
+ stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_MediaStop));
+ fullscreenAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::ALT + Qt::Key_Return));
fullscreenAct->setText(tr("Exit &Full Screen"));
+ m_maximized = isMaximized();
+
+ // save geometry now, if the user quits when in full screen
+ // geometry won't be saved
+ writeSettings();
+
+ showFullScreen();
}
+
+ // No compact view action when in full screen
+ compactViewAct->setVisible(m_fullscreen);
+ // Also no Youtube action since it opens a new window
+ webPageAct->setVisible(m_fullscreen);
+
+ // Hide anything but the video
+ mediaView->setPlaylistVisible(m_fullscreen);
+ mainToolBar->setVisible(m_fullscreen);
+ statusBar()->setVisible(m_fullscreen);
+ menuBar()->setVisible(m_fullscreen);
+
m_fullscreen = !m_fullscreen;
+
+ setUpdatesEnabled(true);
+}
+
+void MainWindow::compactView(bool enable) {
+
+ setUpdatesEnabled(false);
+
+ // setUnifiedTitleAndToolBarOnMac(!enable);
+ mediaView->setPlaylistVisible(!enable);
+ mainToolBar->setVisible(!enable);
+ statusBar()->setVisible(!enable);
+
+ // ensure focus does not end up to the search box
+ // as it would steal the Space shortcut
+ toolbarSearch->setEnabled(!enable);
+
+ if (enable) {
+ stopAct->setShortcut(QString(""));
+ QList<QKeySequence> shortcuts;
+ // for some reason it is important that ESC comes first
+ shortcuts << QKeySequence(Qt::CTRL + Qt::Key_Return) << QKeySequence(Qt::Key_Escape);
+ compactViewAct->setShortcuts(shortcuts);
+ } else {
+ compactViewAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return));
+ stopAct->setShortcut(QKeySequence(Qt::Key_Escape));
+ }
+
+ setUpdatesEnabled(true);
}
void MainWindow::searchFocus() {
if (mediaObject) delete mediaObject;
if (audioOutput) delete audioOutput;
mediaObject = new Phonon::MediaObject(this);
+ mediaObject->setTickInterval(100);
connect(mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
this, SLOT(stateChanged(Phonon::State, Phonon::State)));
+ connect(mediaObject, SIGNAL(tick(qint64)), this, SLOT(tick(qint64)));
+ connect(mediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(totalTimeChanged(qint64)));
seekSlider->setMediaObject(mediaObject);
audioOutput = new Phonon::AudioOutput(Phonon::VideoCategory, this);
+ connect(audioOutput, SIGNAL(volumeChanged(qreal)), this, SLOT(volumeChanged(qreal)));
+ connect(audioOutput, SIGNAL(mutedChanged(bool)), this, SLOT(volumeMutedChanged(bool)));
volumeSlider->setAudioOutput(audioOutput);
Phonon::createPath(mediaObject, audioOutput);
}
+
+void MainWindow::tick(qint64 time) {
+ if (time <= 0) {
+ currentTime->clear();
+ return;
+ }
+ QTime displayTime(0, (time / 60000) % 60, (time / 1000) % 60);
+ currentTime->setText(displayTime.toString("mm:ss"));
+ // qDebug() << "currentTime" << time << displayTime.toString("mm:ss");
+}
+
+void MainWindow::totalTimeChanged(qint64 time) {
+ if (time <= 0) {
+ totalTime->clear();
+ return;
+ }
+ QTime displayTime(0, (time / 60000) % 60, (time / 1000) % 60);
+ totalTime->setText(displayTime.toString("/ mm:ss"));
+ // qDebug() << "totalTime" << time << displayTime.toString("mm:ss");
+}
+
+void MainWindow::volumeUp() {
+ qreal newVolume = volumeSlider->audioOutput()->volume() + .1;
+ if (newVolume > volumeSlider->maximumVolume())
+ newVolume = volumeSlider->maximumVolume();
+ volumeSlider->audioOutput()->setVolume(newVolume);
+}
+
+void MainWindow::volumeDown() {
+ qreal newVolume = volumeSlider->audioOutput()->volume() - .1;
+ if (newVolume < 0)
+ newVolume = 0;
+ volumeSlider->audioOutput()->setVolume(newVolume);
+}
+
+void MainWindow::volumeMute() {
+ volumeSlider->audioOutput()->setMuted(!volumeSlider->audioOutput()->isMuted());
+}
+
+void MainWindow::volumeChanged(qreal newVolume) {
+ // automatically unmute when volume changes
+ if (volumeSlider->audioOutput()->isMuted())
+ volumeSlider->audioOutput()->setMuted(false);
+ statusBar()->showMessage(tr("Volume at %1%").arg(newVolume*100));
+}
+
+void MainWindow::volumeMutedChanged(bool muted) {
+ if (muted)
+ statusBar()->showMessage(tr("Volume is muted"));
+ else
+ statusBar()->showMessage(tr("Volume is unmuted"));
+}
+
+/*
+void MainWindow::abortDownload() {
+ QProgressDialog* dlg = dynamic_cast<QProgressDialog*>(this->sender());
+ QMap<QNetworkReply*, DownloadResource>::iterator cur;
+ QMap<QNetworkReply*, DownloadResource>::iterator end;
+ // locate the DownloadResource by its dialog address and trigger abortion
+ for(cur=m_downloads.begin(), end=m_downloads.end(); cur!=end; cur++){
+ if(cur.value().dialog == dlg) cur.key()->abort();
+ }
+}
+
+void MainWindow::download() {
+ if(mediaObject == NULL || mediaObject->currentSource().url().isEmpty()){
+ // complain unless video source apperas to be valid
+ QMessageBox::critical(this, tr("No Video playing"), tr("You must first play the video you intent to download !"));
+ return;
+ }
+ QString filename = QFileDialog::getSaveFileName(this,
+ tr("Save video as..."),
+ tr("minitube video.mp4"),
+ "Video File(*.avi *.mp4)"
+ );
+ if(!filename.isNull()) {
+ // open destination file and initialize download
+ DownloadResource res;
+ res.file = new QFile(filename);
+ if(res.file->open(QFile::WriteOnly) == true) {
+ res.dialog = new QProgressDialog(tr("Downloading: ") + res.file->fileName(),
+ tr("Abort Download"), 0, 100, this);
+ connect(res.dialog, SIGNAL(canceled()), this, SLOT(abortDownload()));
+ download(mediaObject->currentSource().url(), res);
+ }else{
+ QMessageBox::critical(this, tr("File creation failed"), res.file->errorString());
+ delete res.file;
+ }
+ }
+}
+
+void MainWindow::download(const QUrl& url, const DownloadResource& res) {
+ // create and store request and connect the reply signals
+ QNetworkReply *r = The::networkAccessManager()->get(QNetworkRequest(url));
+ m_downloads.insert(r, res);
+ connect(r, SIGNAL(finished()), this, SLOT(replyFinished()));
+ connect(r, SIGNAL(readyRead()), this, SLOT(replyReadyRead()));
+ connect(r, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(replyError(QNetworkReply::NetworkError)));
+ connect(r, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(replyDownloadProgress(qint64,qint64)));
+ connect(r, SIGNAL(metaDataChanged()), this, SLOT(replyMetaDataChanged()));
+}
+
+void MainWindow::replyReadyRead() {
+ QNetworkReply* r = dynamic_cast<QNetworkReply*>(this->sender());
+ m_downloads[r].file->write(r->readAll());
+}
+
+void MainWindow::replyDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
+ QNetworkReply* r = dynamic_cast<QNetworkReply*>(this->sender());
+ if (bytesTotal > 0 && bytesReceived >0)
+ m_downloads[r].dialog->setValue( double(100.0/bytesTotal)*bytesReceived ); // pssst :-X
+}
+
+void MainWindow::replyError(QNetworkReply::NetworkError code) {
+ QNetworkReply* r = dynamic_cast<QNetworkReply*>(this->sender());
+ QMessageBox::critical(this, tr("Download failed"), r->errorString());
+}
+
+void MainWindow::replyFinished() {
+ QNetworkReply* r = dynamic_cast<QNetworkReply*>(this->sender());
+ m_downloads[r].dialog->close();
+ m_downloads[r].file->close();
+ delete m_downloads[r].file;
+ m_downloads.remove(r);
+}
+
+void MainWindow::replyMetaDataChanged() {
+ QNetworkReply* r = dynamic_cast<QNetworkReply*>(this->sender());
+ QUrl url = r->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
+ if(url.isValid()) {
+ // redirect - request new url, but keep the resources
+ qDebug() << "redirecting to: " << url.toString();
+ download(url, m_downloads[r]);
+ m_downloads.remove(r);
+ }
+}
+
+*/