Browse Source

Fixed Downloader class & almost completed news widget

Ivan Arkhipov 5 years ago
parent
commit
31cb190df0

+ 4 - 4
Legacy_v2.pro

@@ -32,26 +32,26 @@ SOURCES += \
         src/menuentry.cpp \
         src/legacyapp.cpp \
         src/filesystem.cpp \
-        src/filedownloader.cpp \
     gui/statuswidget.cpp \
     gui/rusificationwidget.cpp \
     gui/settingswidget.cpp \
     gui/newswidget.cpp \
     gui/helpwidget.cpp \
-    src/rusificationtreeelement.cpp
+    src/rusificationtreeelement.cpp \
+    src/networkdownloader.cpp
 
 HEADERS += \
         gui/mainwindow.h \
         include/menuentry.h \
         include/legacyapp.h \
         include/filesystem.h \
-        include/filedownloader.h \
     gui/statuswidget.h \
     gui/rusificationwidget.h \
     gui/settingswidget.h \
     gui/newswidget.h \
     gui/helpwidget.h \
-    include/rusificationtreeelement.h
+    include/rusificationtreeelement.h \
+    include/networkdownloader.h
 
 FORMS += \
         gui/mainwindow.ui \

+ 126 - 1
gui/newswidget.cpp

@@ -1,15 +1,140 @@
 #include "gui\newswidget.h"
 #include "ui_newswidget.h"
 
+#include "networkdownloader.h"
+#include "legacyapp.h"
+#include <QtConcurrent/QtConcurrent>
+#include <QLabel>
+
 NewsWidget::NewsWidget(LegacyApp *_app, QWidget *parent) :
     QWidget(parent),
     ui(new Ui::NewsWidget),
-    app(_app)
+    app(_app), news_downloader(this)
 {
     ui->setupUi(this);
+    news_downloader.targetBytearray = &news_data;
+    news_downloader.setUrl(QUrl("http://translate.lotros.ru/groupware/launcher_news"));
+
+    connect(&news_update_timer, &QTimer::timeout, &news_downloader, &NetworkDownloader::start);
+    connect(&news_downloader, &NetworkDownloader::downloadFinished, this, &NewsWidget::updateNews);
+    emit news_downloader.start();
+    news_update_timer.setInterval(1000 * 60); // 10 minutes;
+    news_update_timer.start();
 }
 
 NewsWidget::~NewsWidget()
 {
+    news_update_timer.stop();
     delete ui;
 }
+
+void NewsWidget::updateNews()
+{
+    QStringList news_list = QString(news_data).split(":::");
+    news_data.clear();
+
+    for (int i = 0; i < news_list.size(); i++) {
+        QStringList news_piece = news_list[i].split("|");
+
+        QString img_src = news_piece[0];
+        QString news_title = news_piece[1];
+        QString news_desrc = news_piece[2];
+        QString news_src = news_piece[3];
+
+        constructNewsPiece(i, news_title, news_desrc, news_src);
+
+        QtConcurrent::run([i, this, img_src](){
+            NetworkDownloader img_dwnld;
+            QByteArray img;
+            img_dwnld.setUrl(QUrl(img_src));
+            img_dwnld.targetBytearray = &img;
+            img_dwnld.start();
+            img_dwnld.waitForDownloaded();
+            QPixmap img_pixmap;
+            img_pixmap.loadFromData(img);
+            setImgToNewsPiece(i, img_pixmap);
+        });
+    }
+}
+
+void NewsWidget::constructNewsPiece(int piece_id, QString title, QString text, QString news_src)
+{
+    QWidget* old_piece = findChild<QWidget*>("news_piece_" + QString::number(piece_id));
+
+    if (old_piece) {
+        ui->news_layout->removeWidget(old_piece);
+        old_piece->deleteLater();
+    }
+
+    QWidget* news_piece = new QWidget(this);
+
+    news_piece->setObjectName(QStringLiteral("news_piece_") + QString::number(piece_id));
+    QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+    sizePolicy.setHorizontalStretch(0);
+    sizePolicy.setVerticalStretch(0);
+    sizePolicy.setHeightForWidth(news_piece->sizePolicy().hasHeightForWidth());
+    news_piece->setSizePolicy(sizePolicy);
+    news_piece->setStyleSheet(QLatin1String("QWidget{\n"
+                                            "border-radius: 20px;\n"
+                                            "background-color: rgba(30, 0, 0, 100);\n"
+                                            "color: white;\n"
+                                            "}\n"
+                                            "\n"
+                                            "QLabel{\n"
+                                            "border-radius: 2px;\n"
+                                            "background-color:rgba(0,0,0,0);\n"
+                                            "}"));
+
+    QGridLayout* news_piece_layout = new QGridLayout(news_piece);
+    news_piece_layout->setObjectName(QStringLiteral("news_piece_layout"));
+
+    QLabel* iconLabel = new QLabel(news_piece);
+    iconLabel->setObjectName(QStringLiteral("news_icon_") + QString::number(piece_id));
+    QSizePolicy sizePolicy1(QSizePolicy::Fixed, QSizePolicy::Fixed);
+    sizePolicy1.setHorizontalStretch(0);
+    sizePolicy1.setVerticalStretch(0);
+    sizePolicy1.setHeightForWidth(iconLabel->sizePolicy().hasHeightForWidth());
+    iconLabel->setSizePolicy(sizePolicy1);
+    iconLabel->setMinimumSize(QSize(60, 60));
+    iconLabel->setMaximumSize(QSize(60, 60));
+    iconLabel->setPixmap(QPixmap(QString::fromUtf8(":/assets/appicon.ico")).scaled(60, 60));
+
+    news_piece_layout->addWidget(iconLabel, 0, 0, 2, 1);
+
+    QLabel* titleLabel = new QLabel(news_piece);
+    titleLabel->setObjectName(QStringLiteral("titleLabel_title"));
+    sizePolicy.setHeightForWidth(titleLabel->sizePolicy().hasHeightForWidth());
+    titleLabel->setSizePolicy(sizePolicy);
+    QFont font;
+    font.setFamily(QStringLiteral("Trebuchet MS"));
+    font.setPointSize(11);
+    font.setBold(true);
+
+    titleLabel->setFont(font);
+    titleLabel->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter);
+    titleLabel->setWordWrap(true);
+    titleLabel->setText("<a style=\"color: white; text-decoration:none;\" href = '" + news_src + "'>" + title + "</a>");
+    titleLabel->setOpenExternalLinks(true);
+
+    news_piece_layout->addWidget(titleLabel, 0, 1, 1, 1);
+
+    QLabel* contentLabel = new QLabel(news_piece);
+    contentLabel->setObjectName(QStringLiteral("contentLabel_common"));
+    contentLabel->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop);
+    contentLabel->setWordWrap(true);
+    contentLabel->setText(text);
+
+    news_piece_layout->addWidget(contentLabel, 1, 1, 1, 1);
+
+    app->window.changeFontSizeRecursive(app->properties.value("settings/ui_scale", 100).toInt(), news_piece);
+
+    ui->news_layout->addWidget(news_piece);
+}
+
+void NewsWidget::setImgToNewsPiece(int piece_id, QPixmap img)
+{
+    QLabel* old_piece = findChild<QLabel*>("news_icon_" + QString::number(piece_id));
+    if (!old_piece)
+        return;
+    old_piece->setPixmap(img.scaled(60, 60));
+}

+ 12 - 0
gui/newswidget.h

@@ -2,6 +2,8 @@
 #define NEWSWIDGET_H
 
 #include <QWidget>
+#include <QTimer>
+#include "networkdownloader.h"
 
 namespace Ui {
 class NewsWidget;
@@ -17,9 +19,19 @@ public:
     explicit NewsWidget(LegacyApp *_app, QWidget *parent = 0);
     ~NewsWidget();
 
+public slots:
+    void updateNews();
+
+private:
+    void constructNewsPiece(int piece_id, QString title, QString text, QString news_src);
+    void setImgToNewsPiece(int piece_id, QPixmap img);
+
 private:
     Ui::NewsWidget *ui;
     LegacyApp *app;
+    QTimer news_update_timer;
+    QByteArray news_data;
+    NetworkDownloader news_downloader;
 };
 
 #endif // NEWSWIDGET_H

+ 213 - 16
gui/newswidget.ui

@@ -6,35 +6,232 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>640</width>
-    <height>480</height>
+    <width>728</width>
+    <height>446</height>
    </rect>
   </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
   <property name="windowTitle">
    <string>Form</string>
   </property>
-  <layout class="QGridLayout" name="gridLayout">
-   <item row="0" column="0">
-    <widget class="QLabel" name="label_supertitle">
-     <property name="font">
-      <font>
-       <family>Arial</family>
-       <pointsize>18</pointsize>
-      </font>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QScrollArea" name="scrollArea">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="autoFillBackground">
+      <bool>true</bool>
      </property>
      <property name="styleSheet">
-      <string notr="true">color: white;</string>
+      <string notr="true">QScrollArea{
+	background: transparent;
+} 
+
+QScrollBar:vertical {
+     border: 0px solid grey;
+     background: transparent;
+     width: 10px;
+     margin: 22px 0 22px 0;
+ }
+
+ QScrollBar::handle:vertical {
+	background-color: rgba(129, 129, 129, 150);	
+    min-height: 10px;
+	border-radius: 5px;
+ }
+ QScrollBar::add-line:vertical {
+     border: 0px solid grey;
+     background: transparent;
+     height: 1px;
+     subcontrol-position: bottom;
+     subcontrol-origin: margin;
+ }
+
+ QScrollBar::sub-line:vertical {
+     border: 0px solid grey;
+     background: transparent;
+     height: 1px;
+     subcontrol-position: top;
+     subcontrol-origin: margin;
+ }
+ QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {
+     border: 0px;
+     width: 3px;
+     height: 3px;
+     background: transparent;
+ }
+
+ QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
+     background: none;
+ }</string>
+     </property>
+     <property name="frameShape">
+      <enum>QFrame::NoFrame</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Plain</enum>
+     </property>
+     <property name="lineWidth">
+      <number>0</number>
      </property>
-     <property name="text">
-      <string>Окно &quot;Новости&quot;</string>
+     <property name="sizeAdjustPolicy">
+      <enum>QAbstractScrollArea::AdjustToContents</enum>
      </property>
-     <property name="alignment">
-      <set>Qt::AlignCenter</set>
+     <property name="widgetResizable">
+      <bool>true</bool>
      </property>
+     <widget class="QWidget" name="scrollAreaWidgetContents">
+      <property name="geometry">
+       <rect>
+        <x>0</x>
+        <y>0</y>
+        <width>710</width>
+        <height>403</height>
+       </rect>
+      </property>
+      <layout class="QGridLayout" name="gridLayout_2">
+       <property name="leftMargin">
+        <number>11</number>
+       </property>
+       <property name="topMargin">
+        <number>11</number>
+       </property>
+       <property name="rightMargin">
+        <number>11</number>
+       </property>
+       <property name="bottomMargin">
+        <number>11</number>
+       </property>
+       <property name="spacing">
+        <number>7</number>
+       </property>
+       <item row="0" column="0">
+        <layout class="QVBoxLayout" name="news_layout">
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QWidget" name="test_news_piece" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">QWidget{
+border-radius: 20px;
+background-color: rgba(30, 0, 0, 100);
+color: white;
+}
+
+QLabel{
+border-radius: 2px;
+background-color:rgba(0,0,0,0);
+}</string>
+           </property>
+           <layout class="QGridLayout" name="news_piece_layout">
+            <item row="0" column="0" rowspan="2">
+             <widget class="QLabel" name="iconLabel">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimumSize">
+               <size>
+                <width>60</width>
+                <height>60</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>60</width>
+                <height>60</height>
+               </size>
+              </property>
+              <property name="text">
+               <string/>
+              </property>
+              <property name="pixmap">
+               <pixmap resource="../res.qrc">:/assets/appicon.ico</pixmap>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="1">
+             <widget class="QLabel" name="titleLabel_title">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="font">
+               <font>
+                <family>Trebuchet MS</family>
+                <pointsize>11</pointsize>
+               </font>
+              </property>
+              <property name="styleSheet">
+               <string notr="true">color: white;
+text-decoration: none;</string>
+              </property>
+              <property name="text">
+               <string>Тестовая новость - Название</string>
+              </property>
+              <property name="alignment">
+               <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+              </property>
+              <property name="wordWrap">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="1">
+             <widget class="QLabel" name="contentLabel">
+              <property name="text">
+               <string>Контент контент контент контент контент контент контент контент контент контент контент контент</string>
+              </property>
+              <property name="alignment">
+               <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+              </property>
+              <property name="wordWrap">
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </widget>
     </widget>
    </item>
   </layout>
  </widget>
- <resources/>
+ <resources>
+  <include location="../res.qrc"/>
+ </resources>
  <connections/>
 </ui>

+ 3 - 0
gui/settingswidget.cpp

@@ -22,6 +22,7 @@ SettingsWidget::SettingsWidget(LegacyApp *_app, QWidget *parent) :
 
 SettingsWidget::~SettingsWidget()
 {
+    ui_update_timer.stop();
     delete ui;
 }
 
@@ -77,6 +78,8 @@ void SettingsWidget::on_interface_scale_combobox_common_currentIndexChanged(cons
     int value = arg1.left(arg1.length() - 1).toInt();
     app->window.changeFontSizeRecursive(value, &app->window);
     app->window.resize(900 * value / 100, 650 * value / 100);
+    app->properties.setValue("settings/ui_scale", value);
+    app->properties.sync();
 }
 
 void SettingsWidget::on_change_folder_button_clicked()

+ 0 - 29
include/filedownloader.h

@@ -1,29 +0,0 @@
-#ifndef INCLUDEILEDOWNLOADER_H
-#define INCLUDEILEDOWNLOADER_H
-
-#include <QObject>
-#include <QByteArray>
-#include <QNetworkAccessManager>
-#include <QNetworkRequest>
-#include <QNetworkReply>
-
-class FileDownloader : public QObject
-{
-    Q_OBJECT
-public:
-    explicit FileDownloader(QUrl url, QObject *parent = 0);
-    virtual ~FileDownloader();
-    QByteArray DownloadedData() const;
-
-signals:
-    void downloaded();
-
-private slots:
-    void FileDownloaded(QNetworkReply* pReply);
-
-private:
-    QNetworkAccessManager m_WebCtrl;
-    QByteArray m_DownloadedData;
-};
-
-#endif // INCLUDEILEDOWNLOADER_H

+ 2 - 2
include/legacyapp.h

@@ -11,7 +11,7 @@
 #include <LotroDat.h>
 
 class MainWindow;
-class FileDownloader;
+class NetworkDownloader;
 
 class LegacyApp : public QObject
 {
@@ -40,7 +40,7 @@ public:
 
     QSettings properties;
 
-    FileDownloader* dowloader;
+    NetworkDownloader* dowloader;
     std::queue<std::pair<QString, QString>> download_queue;
 };
 

+ 49 - 0
include/networkdownloader.h

@@ -0,0 +1,49 @@
+#ifndef INCLUDEILEDOWNLOADER_H
+#define INCLUDEILEDOWNLOADER_H
+
+#include <QObject>
+#include <QNetworkAccessManager>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QFile>
+#include <QByteArray>
+
+class NetworkDownloader : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit NetworkDownloader(QObject *parent = 0);
+    virtual ~NetworkDownloader();
+
+    QUrl getUrl();
+    void setUrl(const QUrl& _url);
+    void waitForDownloaded();
+
+signals:
+    void downloadFinished();
+    void progressChanged(qint64 bytesReceived, qint64 bytesTotal);
+
+public slots:
+    void start();
+    void updateDownloadSpeedLimit(int bytes_per_sec);
+    void stop();
+
+private slots:
+    void onDownloadFinished(QNetworkReply* pReply);
+    void onReadyRead();
+
+public:
+    QFile* targetFile {nullptr};
+    QByteArray* targetBytearray {nullptr};
+
+private:
+    bool busy;
+    QUrl url;
+    QNetworkReply* m_CurrentReply {nullptr};
+    QNetworkAccessManager m_WebCtrl;
+
+    unsigned download_speed_limit {0};
+};
+
+#endif // INCLUDEILEDOWNLOADER_H

+ 0 - 21
src/filedownloader.cpp

@@ -1,21 +0,0 @@
-#include "filedownloader.h"
-
-FileDownloader::FileDownloader(QUrl Url, QObject *parent) :QObject(parent)
-{
-    connect(&m_WebCtrl, SIGNAL(finished(QNetworkReply*)), this, SLOT(FileDownloaded(QNetworkReply*)));
-    QNetworkRequest request(Url);
-    m_WebCtrl.get(request);
-}
-
-FileDownloader::~FileDownloader() {}
-
-void FileDownloader::FileDownloaded(QNetworkReply* pReply) {
-    m_DownloadedData = pReply->readAll();
-    //emit a signal
-    pReply->deleteLater();
-    emit downloaded();
-}
-
-QByteArray FileDownloader::DownloadedData() const {
-    return m_DownloadedData;
-}

+ 70 - 0
src/networkdownloader.cpp

@@ -0,0 +1,70 @@
+#include "networkdownloader.h"
+#include <QEventLoop>
+
+NetworkDownloader::NetworkDownloader(QObject *parent) :QObject(parent), busy(false)
+{
+    connect(&m_WebCtrl, SIGNAL(finished(QNetworkReply*)), this, SLOT(onDownloadFinished(QNetworkReply*)));
+}
+
+NetworkDownloader::~NetworkDownloader() {
+}
+
+QUrl NetworkDownloader::getUrl()
+{
+    return url;
+}
+
+void NetworkDownloader::setUrl(const QUrl &_url)
+{
+    url = _url;
+}
+
+void NetworkDownloader::waitForDownloaded()
+{
+    QEventLoop loop;
+    connect(this, &NetworkDownloader::downloadFinished, &loop, &QEventLoop::quit);
+    loop.exec();
+}
+
+void NetworkDownloader::start()
+{
+    if (busy) {
+        qDebug() << "Cannot download " << url << ", downloader is busy!";
+        return;
+    }
+    qDebug() << "Starting download " << url;
+
+    busy = true;
+    QNetworkRequest request(url);
+    m_CurrentReply = m_WebCtrl.get(request);
+    m_CurrentReply->setReadBufferSize(download_speed_limit);
+    connect(m_CurrentReply, &QNetworkReply::readyRead, this, &NetworkDownloader::onReadyRead);
+    connect(m_CurrentReply, &QNetworkReply::downloadProgress, this, &NetworkDownloader::progressChanged);
+}
+
+void NetworkDownloader::updateDownloadSpeedLimit(int bytes_per_sec)
+{
+    download_speed_limit = bytes_per_sec;
+    if (m_CurrentReply)
+        m_CurrentReply->setReadBufferSize(bytes_per_sec);
+}
+
+void NetworkDownloader::stop()
+{
+    m_CurrentReply->abort();
+    busy = false;
+}
+
+void NetworkDownloader::onDownloadFinished(QNetworkReply*) {
+    busy = false;
+    emit downloadFinished();
+}
+
+void NetworkDownloader::onReadyRead()
+{
+    QByteArray readdata = m_CurrentReply->readAll();
+    if (targetFile && targetFile->isWritable())
+        targetFile->write(readdata);
+    if (targetBytearray)
+        targetBytearray->append(readdata);
+}