--- a/QTfrontend/binds.h Thu Jul 26 21:56:47 2012 +0400
+++ b/QTfrontend/binds.h Thu Jul 26 21:58:25 2012 +0400
@@ -21,7 +21,7 @@
#include <QString>
-#define BINDS_NUMBER 45
+#define BINDS_NUMBER 46
struct BindAction
{
--- a/QTfrontend/res/css/birthday.css Thu Jul 26 21:56:47 2012 +0400
+++ b/QTfrontend/res/css/birthday.css Thu Jul 26 21:58:25 2012 +0400
@@ -33,7 +33,7 @@
a { color:#c8c8ff; }
QLineEdit, QListWidget, QTableView, QTextBrowser, QSpinBox, QComboBox,
-QComboBox QAbstractItemView, QMenu::item {
+QComboBox QAbstractItemView, QPlainTextEdit, QMenu::item {
background-color: rgba(13, 5, 68, 70%);
}
@@ -42,7 +42,7 @@
}
QPushButton, QListWidget, QTableView, QLineEdit, QHeaderView,
-QTextBrowser, QSpinBox, QToolBox, QComboBox,
+QTextBrowser, QSpinBox, QToolBox, QComboBox, QPlainTextEdit,
QComboBox QAbstractItemView, IconedGroupBox,
.QGroupBox, GameCFGWidget, TeamSelWidget, SelWeaponWidget,
QTabWidget::pane, QTabBar::tab {
@@ -57,14 +57,14 @@
}
QLineEdit, QListWidget,QTableView, QTextBrowser,
-QSpinBox, QToolBox {
+QSpinBox, QToolBox, QPlainTextEdit {
border-radius: 10px;
}
QLineEdit, QLabel, QHeaderView, QListWidget, QTableView,
QSpinBox, QToolBox::tab, QComboBox, QComboBox QAbstractItemView,
IconedGroupBox, .QGroupBox, GameCFGWidget, TeamSelWidget,
-SelWeaponWidget, QCheckBox, QRadioButton, QPushButton {
+SelWeaponWidget, QCheckBox, QRadioButton, QPushButton, QPlainTextEdit {
font: bold 13px;
}
SelWeaponWidget QTabWidget::pane, SelWeaponWidget QTabBar::tab:selected {
--- a/QTfrontend/res/css/christmas.css Thu Jul 26 21:56:47 2012 +0400
+++ b/QTfrontend/res/css/christmas.css Thu Jul 26 21:58:25 2012 +0400
@@ -33,7 +33,7 @@
a { color:#c8c8ff; }
QLineEdit, QListWidget, QTableView, QTextBrowser, QSpinBox, QComboBox,
-QComboBox QAbstractItemView, QMenu::item {
+QComboBox QAbstractItemView, QPlainTextEdit, QMenu::item {
background-color: rgba(13, 5, 68, 70%);
}
@@ -42,7 +42,7 @@
}
QPushButton, QListWidget, QTableView, QLineEdit, QHeaderView,
-QTextBrowser, QSpinBox, QToolBox, QComboBox,
+QTextBrowser, QSpinBox, QToolBox, QComboBox, QPlainTextEdit,
QComboBox QAbstractItemView, IconedGroupBox,
.QGroupBox, GameCFGWidget, TeamSelWidget, SelWeaponWidget,
QTabWidget::pane, QTabBar::tab {
@@ -57,14 +57,14 @@
}
QLineEdit, QListWidget,QTableView, QTextBrowser,
-QSpinBox, QToolBox {
+QSpinBox, QToolBox, QPlainTextEdit {
border-radius: 10px;
}
QLineEdit, QLabel, QHeaderView, QListWidget, QTableView,
QSpinBox, QToolBox::tab, QComboBox, QComboBox QAbstractItemView,
IconedGroupBox, .QGroupBox, GameCFGWidget, TeamSelWidget,
-SelWeaponWidget, QCheckBox, QRadioButton, QPushButton {
+SelWeaponWidget, QCheckBox, QRadioButton, QPushButton, QPlainTextEdit {
font: bold 13px;
}
SelWeaponWidget QTabWidget::pane, SelWeaponWidget QTabBar::tab:selected {
--- a/QTfrontend/res/css/easter.css Thu Jul 26 21:56:47 2012 +0400
+++ b/QTfrontend/res/css/easter.css Thu Jul 26 21:58:25 2012 +0400
@@ -33,7 +33,7 @@
a { color:#c8c8ff; }
QLineEdit, QListWidget, QTableView, QTextBrowser, QSpinBox, QComboBox,
-QComboBox QAbstractItemView, QMenu::item {
+QComboBox QAbstractItemView, QPlainTextEdit, QMenu::item {
background-color: rgba(13, 5, 68, 70%);
}
@@ -42,7 +42,7 @@
}
QPushButton, QListWidget, QTableView, QLineEdit, QHeaderView,
-QTextBrowser, QSpinBox, QToolBox, QComboBox,
+QTextBrowser, QSpinBox, QToolBox, QComboBox, QPlainTextEdit,
QComboBox QAbstractItemView, IconedGroupBox,
.QGroupBox, GameCFGWidget, TeamSelWidget, SelWeaponWidget,
QTabWidget::pane, QTabBar::tab {
@@ -57,14 +57,14 @@
}
QLineEdit, QListWidget,QTableView, QTextBrowser,
-QSpinBox, QToolBox {
+QSpinBox, QToolBox, QPlainTextEdit {
border-radius: 10px;
}
QLineEdit, QLabel, QHeaderView, QListWidget, QTableView,
QSpinBox, QToolBox::tab, QComboBox, QComboBox QAbstractItemView,
IconedGroupBox, .QGroupBox, GameCFGWidget, TeamSelWidget,
-SelWeaponWidget, QCheckBox, QRadioButton, QPushButton {
+SelWeaponWidget, QCheckBox, QRadioButton, QPushButton, QPlainTextEdit {
font: bold 13px;
}
SelWeaponWidget QTabWidget::pane, SelWeaponWidget QTabBar::tab:selected {
--- a/QTfrontend/res/css/qt.css Thu Jul 26 21:56:47 2012 +0400
+++ b/QTfrontend/res/css/qt.css Thu Jul 26 21:58:25 2012 +0400
@@ -33,7 +33,7 @@
a { color:#c8c8ff; }
QLineEdit, QListWidget, QTableView, QTextBrowser, QSpinBox, QComboBox,
-QComboBox QAbstractItemView, QMenu::item {
+QComboBox QAbstractItemView, QPlainTextEdit, QMenu::item {
background-color: rgba(13, 5, 68, 70%);
}
@@ -42,7 +42,7 @@
}
QPushButton, QListWidget, QTableView, QLineEdit, QHeaderView,
-QTextBrowser, QSpinBox, QToolBox, QComboBox,
+QTextBrowser, QSpinBox, QToolBox, QComboBox, QPlainTextEdit,
QComboBox QAbstractItemView, IconedGroupBox,
.QGroupBox, GameCFGWidget, TeamSelWidget, SelWeaponWidget,
QTabWidget::pane, QTabBar::tab {
@@ -57,14 +57,14 @@
}
QLineEdit, QListWidget,QTableView, QTextBrowser,
-QSpinBox, QToolBox {
+QSpinBox, QToolBox, QPlainTextEdit {
border-radius: 10px;
}
QLineEdit, QLabel, QHeaderView, QListWidget, QTableView,
QSpinBox, QToolBox::tab, QComboBox, QComboBox QAbstractItemView,
IconedGroupBox, .QGroupBox, GameCFGWidget, TeamSelWidget,
-SelWeaponWidget, QCheckBox, QRadioButton, QPushButton {
+SelWeaponWidget, QCheckBox, QRadioButton, QPushButton, QPlainTextEdit {
font: bold 13px;
}
SelWeaponWidget QTabWidget::pane, SelWeaponWidget QTabBar::tab:selected {
--- a/QTfrontend/ui/dialog/ask_quit.cpp Thu Jul 26 21:56:47 2012 +0400
+++ b/QTfrontend/ui/dialog/ask_quit.cpp Thu Jul 26 21:58:25 2012 +0400
@@ -35,7 +35,7 @@
QVBoxLayout * layout = new QVBoxLayout(this);
QLabel * lbLabel = new QLabel(this);
- lbLabel->setText(QLabel::tr("There are videos that are currently being encoded.\n"
+ lbLabel->setText(QLabel::tr("There are videos that are currently being processed.\n"
"Exiting now will abort them.\n"
"Do yot really want to quit?"));
layout->addWidget(lbLabel);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/dialog/upload_video.cpp Thu Jul 26 21:58:25 2012 +0400
@@ -0,0 +1,245 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <QLineEdit>
+#include <QDialogButtonBox>
+#include <QPushButton>
+#include <QGridLayout>
+#include <QCheckBox>
+#include <QLabel>
+#include <QFrame>
+#include <QPlainTextEdit>
+#include <QSslError>
+#include <QUrl>
+#include <QNetworkAccessManager>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+
+#include "upload_video.h"
+#include "hwconsts.h"
+
+// User-agent string used in http requests.
+static const QByteArray UserAgent = ("Hedgewars-QtFrontend/" + *cVersionString).toAscii();
+
+// This is developer key obtained from http://code.google.com/apis/youtube/dashboard/
+// If you are reusing this code outside Hedgewars, don't use this developer key,
+// obtain you own at http://code.google.com/apis/youtube/dashboard/
+static const QByteArray devKey = "AI39si5pKjxR0XgNIlmrEFF-LyYD31rps4g2O5dZTxLgD0fvJ2rHxrMrNFY8FYTZrzeI3VlaFVQLKfFnSBugvdZmy8vFzRDefQ";
+
+HWUploadVideoDialog::HWUploadVideoDialog(QWidget* parent, const QString &filename, QNetworkAccessManager* netManager) : QDialog(parent)
+{
+ this->filename = filename;
+ this->netManager = netManager;
+
+ setWindowTitle(tr("Upload video"));
+
+ // Google requires us to display this, see https://developers.google.com/youtube/terms
+ QString GoogleNotice =
+ "By clicking 'upload,' you certify that you own all rights to the content or that\n"
+ "you are authorized by the owner to make the content publicly available on YouTube,\n"
+ "and that it otherwise complies with the YouTube Terms of Service located at\n"
+ "http://www.youtube.com/t/terms.";
+
+ QGridLayout * layout = new QGridLayout(this);
+
+ QLabel * lbLabel = new QLabel(this);
+ lbLabel->setText(QLabel::tr(
+ "Please provide either the YouTube account name\n"
+ "or the email address associated with the Google Account."));
+ layout->addWidget(lbLabel, 0, 0, 1, 2);
+
+ lbLabel = new QLabel(this);
+ lbLabel->setText(QLabel::tr("Account name (or email): "));
+ layout->addWidget(lbLabel, 1, 0);
+
+ leAccount = new QLineEdit(this);
+ layout->addWidget(leAccount, 1, 1);
+
+ lbLabel = new QLabel(this);
+ lbLabel->setText(QLabel::tr("Password: "));
+ layout->addWidget(lbLabel, 2, 0);
+
+ lePassword = new QLineEdit(this);
+ lePassword->setEchoMode(QLineEdit::Password);
+ layout->addWidget(lePassword, 2, 1);
+
+ cbSave = new QCheckBox(this);
+ cbSave->setText(QCheckBox::tr("Save account name and password"));
+ layout->addWidget(cbSave, 3, 0, 1, 2);
+
+ QFrame * hr = new QFrame(this);
+ hr->setFrameStyle(QFrame::HLine);
+ hr->setLineWidth(3);
+ hr->setFixedHeight(10);
+ layout->addWidget(hr, 4, 0, 1, 2);
+
+ lbLabel = new QLabel(this);
+ lbLabel->setText(QLabel::tr("Video title: "));
+ layout->addWidget(lbLabel, 5, 0);
+
+ leTitle = new QLineEdit(this);
+ leTitle->setText(filename);
+ layout->addWidget(leTitle, 5, 1);
+
+ lbLabel = new QLabel(this);
+ lbLabel->setText(QLabel::tr("Video description: "));
+ layout->addWidget(lbLabel, 6, 0, 1, 2);
+
+ teDescription = new QPlainTextEdit(this);
+ layout->addWidget(teDescription, 7, 0, 1, 2);
+
+ hr = new QFrame(this);
+ hr->setFrameStyle(QFrame::HLine);
+ hr->setLineWidth(3);
+ hr->setFixedHeight(10);
+ layout->addWidget(hr, 8, 0, 1, 2);
+
+ lbLabel = new QLabel(this);
+ lbLabel->setText(GoogleNotice);
+ layout->addWidget(lbLabel, 9, 0, 1, 2);
+
+ labelLog = new QLabel(this);
+ layout->addWidget(labelLog, 10, 0, 1, 2);
+
+ QDialogButtonBox* dbbButtons = new QDialogButtonBox(this);
+ btnUpload = dbbButtons->addButton(tr("Upload"), QDialogButtonBox::ActionRole);
+ QPushButton * pbCancel = dbbButtons->addButton(QDialogButtonBox::Cancel);
+ layout->addWidget(dbbButtons, 11, 0, 1, 2);
+
+ connect(btnUpload, SIGNAL(clicked()), this, SLOT(upload()));
+ connect(pbCancel, SIGNAL(clicked()), this, SLOT(reject()));
+}
+
+void HWUploadVideoDialog::log(const QString& text)
+{
+ labelLog->setText(labelLog->text() + text);
+}
+
+void HWUploadVideoDialog::setEditable(bool editable)
+{
+ leTitle->setEnabled(editable);
+ leAccount->setEnabled(editable);
+ lePassword->setEnabled(editable);
+ btnUpload->setEnabled(editable);
+}
+
+void HWUploadVideoDialog::upload()
+{
+ setEditable(false);
+
+ labelLog->clear();
+ log(tr("Authenticating at www.google.com... "));
+
+ // Documentation is at https://developers.google.com/youtube/2.0/developers_guide_protocol_clientlogin#ClientLogin_Authentication
+ QNetworkRequest request;
+ request.setUrl(QUrl("https://www.google.com/accounts/ClientLogin"));
+ request.setRawHeader("User-Agent", UserAgent);
+ request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
+
+ QString account(QUrl::toPercentEncoding(leAccount->text()));
+ QString pass(QUrl::toPercentEncoding(lePassword->text()));
+ QByteArray data = QString("Email=%1&Passwd=%2&service=youtube&source=Hedgewars").arg(account).arg(pass).toAscii();
+
+ QNetworkReply *reply = netManager->post(request, data);
+ connect(reply, SIGNAL(finished()), this, SLOT(authFinished()));
+}
+
+QString XmlEscape(const QString& str)
+{
+ QString str2 = str;
+ return "<![CDATA[" + str2.replace("]]>", "]]]]><![CDATA[>") + "]]>";
+}
+
+void HWUploadVideoDialog::authFinished()
+{
+ QNetworkReply *reply = (QNetworkReply*)sender();
+ reply->deleteLater();
+
+ QByteArray answer = reply->readAll();
+ QString authToken = "";
+ QList<QByteArray> lines = answer.split('\n');
+ foreach (const QByteArray& line, lines)
+ {
+ QString str(line);
+ if (!str.startsWith("Auth=", Qt::CaseInsensitive))
+ continue;
+ str.remove(0, 5);
+ authToken = str;
+ break;
+ }
+ if (authToken.isEmpty())
+ {
+ log(tr("failed\n"));
+ log(reply->errorString() + "\n");
+ setEditable(true);
+ return;
+ }
+ log(tr("Ok\n"));
+
+ log(tr("Sending metadata... "));
+
+ QByteArray auth = ("GoogleLogin auth=" + authToken).toAscii();
+
+ // We have authenticated, now we can send metadata and start upload
+ // Documentation is here: https://developers.google.com/youtube/2.0/developers_guide_protocol_resumable_uploads#Resumable_uploads
+ QByteArray body =
+ "<?xml version=\"1.0\"?>"
+ "<entry xmlns=\"http://www.w3.org/2005/Atom\" "
+ "xmlns:media=\"http://search.yahoo.com/mrss/\" "
+ "xmlns:yt=\"http://gdata.youtube.com/schemas/2007\">"
+ "<media:group>"
+ "<yt:incomplete/>"
+ "<media:category "
+ "scheme=\"http://gdata.youtube.com/schemas/2007/categories.cat\">Games"
+ "</media:category>"
+ "<media:title type=\"plain\">"
+ + XmlEscape(leTitle->text()).toUtf8() +
+ "</media:title>"
+ "</media:group>"
+ "</entry>";
+
+ QNetworkRequest request;
+ request.setUrl(QUrl("http://uploads.gdata.youtube.com/resumable/feeds/api/users/default/uploads"));
+ request.setRawHeader("User-Agent", UserAgent);
+ request.setRawHeader("Authorization", auth);
+ request.setRawHeader("GData-Version", "2");
+ request.setRawHeader("X-GData-Key", "key=" + devKey);
+ request.setRawHeader("Slug", filename.toUtf8());
+ request.setRawHeader("Content-Type", "application/atom+xml; charset=UTF-8");
+
+ reply = netManager->post(request, body);
+ connect(reply, SIGNAL(finished()), this, SLOT(startUpload()));
+}
+
+void HWUploadVideoDialog::startUpload()
+{
+ QNetworkReply *reply = (QNetworkReply*)sender();
+ reply->deleteLater();
+
+ location = QString::fromAscii(reply->rawHeader("Location"));
+ if (location.isEmpty())
+ {
+ log(tr("failed\n"));
+ log(reply->errorString() + "\n");
+ setEditable(true);
+ return;
+ }
+
+ log(tr("Ok\n"));
+ accept();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/dialog/upload_video.h Thu Jul 26 21:58:25 2012 +0400
@@ -0,0 +1,62 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef UPLOAD_VIDEO_H
+#define UPLOAD_VIDEO_H
+
+#include <QDialog>
+
+class QLineEdit;
+class QCheckBox;
+class QPlainTextEdit;
+class QLabel;
+class QNetworkAccessManager;
+
+class HWUploadVideoDialog : public QDialog
+{
+ Q_OBJECT
+ public:
+ HWUploadVideoDialog(QWidget* parent, const QString& filename, QNetworkAccessManager* netManager);
+
+ QLineEdit* leAccount;
+ QLineEdit* lePassword;
+ QCheckBox* cbSave;
+
+ QLineEdit* leTitle;
+ QPlainTextEdit* teDescription;
+
+ QPushButton* btnUpload;
+
+ QLabel* labelLog;
+
+ QString location;
+
+ private:
+ QNetworkAccessManager* netManager;
+ QString filename;
+
+ void log(const QString& text);
+ void setEditable(bool editable);
+
+ private slots:
+ void upload();
+ void authFinished();
+ void startUpload();
+};
+
+#endif // UPLOAD_VIDEO_H
--- a/QTfrontend/ui/page/pagevideos.cpp Thu Jul 26 21:56:47 2012 +0400
+++ b/QTfrontend/ui/page/pagevideos.cpp Thu Jul 26 21:58:25 2012 +0400
@@ -39,6 +39,9 @@
#include <QFileSystemWatcher>
#include <QDateTime>
#include <QRegExp>
+#include <QNetworkAccessManager>
+#include <QNetworkRequest>
+#include <QNetworkReply>
#include "hwconsts.h"
#include "pagevideos.h"
@@ -47,8 +50,9 @@
#include "gameuiconfig.h"
#include "recorder.h"
#include "ask_quit.h"
+#include "upload_video.h"
-const QSize ThumbnailSize(350, 350*3/5);
+static const QSize ThumbnailSize(350, 350*3/5);
// columns in table with list of video files
enum VideosColumns
@@ -70,7 +74,9 @@
QString name;
QString desc; // description
+ QString uploadReply;
HWRecorder * pRecorder; // non NULL if file is being encoded
+ QNetworkReply * pUploading; // non NULL if file is being uploaded
bool seen; // used when updating directory
float lastSizeUpdate;
float progress;
@@ -87,6 +93,7 @@
{
this->name = name;
pRecorder = NULL;
+ pUploading = NULL;
lastSizeUpdate = 0;
progress = 0;
}
@@ -217,6 +224,7 @@
filesTable->setColumnCount(vcNumColumns);
filesTable->setHorizontalHeaderLabels(columns);
filesTable->setSelectionBehavior(QAbstractItemView::SelectRows);
+ filesTable->setSelectionMode(QAbstractItemView::SingleSelection);
filesTable->setEditTriggers(QAbstractItemView::SelectedClicked);
filesTable->verticalHeader()->hide();
filesTable->setMinimumWidth(400);
@@ -272,6 +280,9 @@
btnDelete = new QPushButton(QPushButton::tr("Delete"), pDescGroup);
btnDelete->setEnabled(false);
pBottomDescLayout->addWidget(btnDelete);
+ btnToYouTube = new QPushButton(QPushButton::tr("Upload to YouTube"), pDescGroup);
+ btnToYouTube->setEnabled(false);
+ pBottomDescLayout->addWidget(btnToYouTube);
pDescLayout->addStretch(1);
pDescLayout->addLayout(pTopDescLayout, 0);
@@ -300,14 +311,16 @@
connect(filesTable, SIGNAL(currentCellChanged(int,int,int,int)), this, SLOT(currentCellChanged(int,int,int,int)));
connect(btnPlay, SIGNAL(clicked()), this, SLOT(playSelectedFile()));
connect(btnDelete, SIGNAL(clicked()), this, SLOT(deleteSelectedFiles()));
+ connect(btnToYouTube, SIGNAL(clicked()), this, SLOT(uploadToYouTube()));
connect(btnOpenDir, SIGNAL(clicked()), this, SLOT(openVideosDirectory()));
}
PageVideos::PageVideos(QWidget* parent) : AbstractPage(parent),
- config(0)
+ config(0), netManager(0)
{
nameChangedFromCode = false;
numRecorders = 0;
+ numUploads = 0;
initPage();
}
@@ -521,6 +534,14 @@
numRecorders++;
}
+void PageVideos::setProgress(int row, VideoItem* item, float value)
+{
+ QProgressBar * progressBar = (QProgressBar*)filesTable->cellWidget(row, vcProgress);
+ progressBar->setValue(value*10000);
+ progressBar->setFormat(QString("%1%").arg(value*100, 0, 'f', 2));
+ item->progress = value;
+}
+
void PageVideos::updateProgress(float value)
{
HWRecorder * pRecorder = (HWRecorder*)sender();
@@ -534,11 +555,7 @@
item->lastSizeUpdate = value;
}
- // update progress bar
- QProgressBar * progressBar = (QProgressBar*)filesTable->cellWidget(row, vcProgress);
- progressBar->setValue(value*10000);
- progressBar->setFormat(QString("%1%").arg(value*100, 0, 'f', 2));
- item->progress = value;
+ setProgress(row, item, value);
}
void PageVideos::encodingFinished(bool success)
@@ -674,11 +691,13 @@
clearThumbnail();
btnPlay->setEnabled(false);
btnDelete->setEnabled(false);
+ btnToYouTube->setEnabled(false);
return;
}
btnPlay->setEnabled(item->ready());
btnDelete->setEnabled(true);
+ btnToYouTube->setEnabled(item->ready());
QString desc = item->name + "\n\n";
QString thumbName = "";
@@ -701,6 +720,8 @@
desc.remove(prefixBegin, prefixEnd + 7 - prefixBegin);
thumbName = prefix;
}
+
+ desc += item->uploadReply;
}
else
desc += tr("(in progress...)");
@@ -823,12 +844,12 @@
bool PageVideos::tryQuit(HWForm * form)
{
bool quit = true;
- if (numRecorders != 0)
+ if (numRecorders != 0 || numUploads != 0)
{
// ask user what to do - abort or wait
HWAskQuitDialog * askd = new HWAskQuitDialog(this, form);
+ askd->deleteLater();
quit = askd->exec();
- delete askd;
}
if (quit)
clearTemp();
@@ -836,6 +857,10 @@
}
// returns multi-line string with list of videos in progress
+/* it will look like this:
+foo.avi (15.21% - encoding)
+bar.avi (18.21% - uploading)
+*/
QString PageVideos::getVideosInProgress()
{
QString list = "";
@@ -843,11 +868,17 @@
for (int i = 0; i < count; i++)
{
VideoItem * item = nameItem(i);
+ QString process;
+ if (!item->ready())
+ process = tr("encoding");
+ else if (item->pUploading)
+ process = tr("uploading");
+ else
+ continue;
float progress = 100*item->progress;
if (progress > 99.99)
progress = 99.99; // displaying 100% may be confusing
- if (!item->ready())
- list += item->name + " (" + QString::number(progress, 'f', 2) + "%)\n";
+ list += item->name + " (" + QString::number(progress, 'f', 2) + "% - " + process + ")\n";
}
return list;
}
@@ -880,3 +911,87 @@
addRecorder(pRecorder);
}
}
+
+void PageVideos::uploadProgress(qint64 bytesSent, qint64 bytesTotal)
+{
+ QNetworkReply* reply = (QNetworkReply*)sender();
+
+ VideoItem * item = NULL;
+ int row;
+ int count = filesTable->rowCount();
+ // find corresponding item (maybe there is a better wat to implement this?)
+ for (int i = 0; i < count; i++)
+ {
+ item = nameItem(i);
+ if (item->pUploading == reply)
+ {
+ row = i;
+ break;
+ }
+ }
+ Q_ASSERT(item);
+
+ setProgress(row, item, bytesSent*1.0/bytesTotal);
+}
+
+void PageVideos::uploadFinished()
+{
+ QNetworkReply* reply = (QNetworkReply*)sender();
+
+ VideoItem * item = NULL;
+ int row;
+ int count = filesTable->rowCount();
+ for (int i = 0; i < count; i++)
+ {
+ item = nameItem(i);
+ if (item->pUploading == reply)
+ {
+ row = i;
+ break;
+ }
+ }
+ Q_ASSERT(item);
+
+ item->pUploading = NULL;
+ QByteArray answer = reply->readAll();
+ item->uploadReply = QString::fromUtf8(answer.data());
+ // QMessageBox::information(this,"",item->uploadReply,0);
+ filesTable->setCellWidget(row, vcProgress, NULL); // remove progress bar
+ numUploads--;
+}
+
+void PageVideos::uploadToYouTube()
+{
+ int row = filesTable->currentRow();
+ VideoItem * item = nameItem(row);
+
+ if (!netManager)
+ netManager = new QNetworkAccessManager(this);
+
+ HWUploadVideoDialog* dlg = new HWUploadVideoDialog(this, item->name, netManager);
+ dlg->deleteLater();
+ if (!dlg->exec())
+ return;
+
+ QNetworkRequest request(QUrl(dlg->location));
+ request.setRawHeader("Content-Type", "application/octet-stream");
+
+ QFile * file = new QFile(item->path(), this);
+ if (!file->open(QIODevice::ReadOnly))
+ return;
+
+ // add progress bar
+ QProgressBar * progressBar = new QProgressBar(filesTable);
+ progressBar->setMinimum(0);
+ progressBar->setMaximum(10000);
+ progressBar->setValue(0);
+ // make it different from encoding progress-bar
+ progressBar->setStyleSheet("* {color: #00ccff; selection-background-color: #00ccff;}" );
+ filesTable->setCellWidget(row, vcProgress, progressBar);
+
+ QNetworkReply* reply = netManager->put(request, file);
+ item->pUploading = reply;
+ connect(reply, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(uploadProgress(qint64, qint64)));
+ connect(reply, SIGNAL(finished()), this, SLOT(uploadFinished()));
+ numUploads++;
+}
--- a/QTfrontend/ui/page/pagevideos.h Thu Jul 26 21:56:47 2012 +0400
+++ b/QTfrontend/ui/page/pagevideos.h Thu Jul 26 21:58:25 2012 +0400
@@ -20,9 +20,9 @@
#ifndef PAGE_VIDEOS_H
#define PAGE_VIDEOS_H
-#include <QPixmap>
#include "AbstractPage.h"
+class QNetworkAccessManager;
class GameUIConfig;
class HWRecorder;
class VideoItem;
@@ -41,7 +41,6 @@
QCheckBox *checkUseGameRes;
QCheckBox *checkRecordAudio;
-
QString format()
{ return comboAVFormats->itemData(comboAVFormats->currentIndex()).toString(); }
@@ -76,8 +75,10 @@
void updateDescription();
void clearTemp();
void clearThumbnail();
+ void setProgress(int row, VideoItem* item, float value);
GameUIConfig * config;
+ QNetworkAccessManager* netManager;
// options group
QComboBox *comboAVFormats;
@@ -90,7 +91,7 @@
QPushButton *btnOpenDir;
// description group
- QPushButton *btnPlay, *btnDelete;
+ QPushButton *btnPlay, *btnDelete, *btnToYouTube;
QLabel *labelDesc;
QLabel *labelThumbnail;
@@ -98,7 +99,7 @@
// (in signal cellChanged)
bool nameChangedFromCode;
- int numRecorders;
+ int numRecorders, numUploads;
private slots:
void changeAVFormat(int index);
@@ -114,6 +115,9 @@
void deleteSelectedFiles();
void openVideosDirectory();
void updateFileList(const QString & path);
+ void uploadToYouTube();
+ void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
+ void uploadFinished();
};
#endif // PAGE_VIDEOS_H
--- a/hedgewars/hwengine.pas Thu Jul 26 21:56:47 2012 +0400
+++ b/hedgewars/hwengine.pas Thu Jul 26 21:58:25 2012 +0400
@@ -32,6 +32,9 @@
uses SDLh, uMisc, uConsole, uGame, uConsts, uLand, uAmmos, uVisualGears, uGears, uStore, uWorld, uInputHandler, uSound,
uScript, uTeams, uStats, uIO, uLocale, uChat, uAI, uAIMisc, uRandom, uLandTexture, uCollisions,
SysUtils, uTypes, uVariables, uCommands, uUtils, uCaptions, uDebug, uCommandHandlers, uLandPainted
+ {$IFDEF USE_VIDEO_RECORDING}, uVideoRec {$ENDIF}
+ {$IFDEF SDL13}, uTouch{$ENDIF}{$IFDEF ANDROID}, GLUnit{$ENDIF}, uAILandMarks;
+
{$IFDEF HWLIBRARY}
procedure initEverything(complete:boolean);
--- a/hedgewars/uGame.pas Thu Jul 26 21:56:47 2012 +0400
+++ b/hedgewars/uGame.pas Thu Jul 26 21:58:25 2012 +0400
@@ -48,7 +48,7 @@
if (GameType = gmtDemo) then
if isSpeed then
- Lag:= Lag * 10
+ begin
i:= RealTicks-SpeedStart;
if i < 2000 then Lag:= Lag*5
else if i < 4000 then Lag:= Lag*10
--- a/hedgewars/uGearsHedgehog.pas Thu Jul 26 21:56:47 2012 +0400
+++ b/hedgewars/uGearsHedgehog.pas Thu Jul 26 21:58:25 2012 +0400
@@ -617,7 +617,6 @@
AddPickup(HH^.Hedgehog^, Gear^.AmmoType, Gear^.Power, hwRound(Gear^.X), hwRound(Gear^.Y));
end
else
- or (GameType = gmtDemo) then
begin
// Add spawning here...
AddRandomness(GameTicks);
--- a/project_files/hedgewars.pro Thu Jul 26 21:56:47 2012 +0400
+++ b/project_files/hedgewars.pro Thu Jul 26 21:58:25 2012 +0400
@@ -108,7 +108,8 @@
../QTfrontend/util/libav_iteraction.h \
../QTfrontend/ui/page/pagevideos.h \
../QTfrontend/net/recorder.h \
- ../QTfrontend/ui/dialog/ask_quit.h
+ ../QTfrontend/ui/dialog/ask_quit.h \
+ ../QTfrontend/ui/dialog/upload_video.h
SOURCES += ../QTfrontend/model/ammoSchemeModel.cpp \
../QTfrontend/model/MapModel.cpp \
@@ -194,7 +195,8 @@
../QTfrontend/util/libav_iteraction.cpp \
../QTfrontend/ui/page/pagevideos.cpp \
../QTfrontend/net/recorder.cpp \
- ../QTfrontend/ui/dialog/ask_quit.cpp
+ ../QTfrontend/ui/dialog/ask_quit.cpp \
+ ../QTfrontend/ui/dialog/upload_video.cpp
win32 {
SOURCES += ../QTfrontend/xfire.cpp