ソースを参照

Изменен список видео

Вадим Королёв 1 年間 前
コミット
ec1266712f
3 ファイル変更133 行追加12 行削除
  1. 84 11
      src/YTMPV/MainWindow.cpp
  2. 41 0
      src/YTMPV/core.cpp
  3. 8 1
      src/YTMPV/core.hpp

+ 84 - 11
src/YTMPV/MainWindow.cpp

@@ -149,12 +149,56 @@ namespace components {
 
     void MainWindow::onVideoSetup(const Glib::RefPtr<Gtk::ListItem>& list_item)
     {
-        auto box_main = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL);
+        // Главный контейнер
+        auto layout = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL);
+
+        // Превью
         auto thumbnail = Gtk::make_managed<Gtk::Picture>();
-        auto label = Gtk::make_managed<Gtk::Label>("", Gtk::Align::START);
-        box_main->append(*thumbnail);
-        box_main->append(*label);
-        list_item->set_child(*box_main);
+
+        // Контейнер деталей видео
+        auto details = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL);
+
+        // Название
+        auto title = Gtk::make_managed<Gtk::Label>("", Gtk::Align::START);
+
+        // Контейнер для времени, канала и кол-ва просмотров
+        auto info = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL);
+
+        // Надпись: время публикации
+        auto published_at_label = Gtk::make_managed<Gtk::Label>();
+
+        // Надпись: название канала
+        auto channel_label = Gtk::make_managed<Gtk::Label>();
+
+        // Надпись: количество просмотров
+        auto views_count_label = Gtk::make_managed<Gtk::Label>();
+
+        // Контейнер для кнопок
+        auto buttons = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL);
+
+        // Кнопка "Воспроизвести"
+        auto play_button = Gtk::make_managed<Gtk::Button>();
+        play_button->set_icon_name("media-playlist-play");
+
+        // Кнопка "Добавить в очередь"
+        auto queue_button = Gtk::make_managed<Gtk::Button>();
+        queue_button->set_icon_name("playlist-queue");
+
+        info->append(*published_at_label);
+        info->append(*channel_label);
+        info->append(*views_count_label);
+
+        buttons->append(*play_button);
+        buttons->append(*queue_button);
+
+        details->append(*title);
+        details->append(*info);
+        details->append(*buttons);
+
+        layout->append(*thumbnail);
+        layout->append(*details);
+        
+        list_item->set_child(*layout);
     }
 
     void MainWindow::onVideoBind(const Glib::RefPtr<Gtk::ListItem>& list_item)
@@ -164,16 +208,41 @@ namespace components {
         auto item = m_video_storage->get_item(pos);
         auto obj = item->m_obj;
         
-        auto box_main = dynamic_cast<Gtk::Box*>(list_item->get_child());
-        if (!box_main) return;
+        auto layout = dynamic_cast<Gtk::Box*>(list_item->get_child());
+        if (!layout) return;
 
-        auto thumbnail = dynamic_cast<Gtk::Picture*>(box_main->get_first_child());
+        auto thumbnail = dynamic_cast<Gtk::Picture*>(layout->get_first_child());
         if (!thumbnail) return;
 
-        auto lbl_title = dynamic_cast<Gtk::Label*>(thumbnail->get_next_sibling());
-        if (!lbl_title) return;
+        auto details = dynamic_cast<Gtk::Box*>(thumbnail->get_next_sibling());
+        if (!details) return;
+
+        auto title = dynamic_cast<Gtk::Label*>(details->get_first_child());
+        if (!title) return;
+
+        auto info = dynamic_cast<Gtk::Box*>(title->get_next_sibling());
+        if (!info) return;
+
+        auto published_at_label = dynamic_cast<Gtk::Label*>(info->get_first_child());
+        if (!published_at_label) return;
+
+        auto channel_label = dynamic_cast<Gtk::Label*>(published_at_label->get_next_sibling());
+        if (!channel_label) return;
+
+        auto views_count_label = dynamic_cast<Gtk::Label*>(channel_label->get_next_sibling());
+        if (!views_count_label) return;
+
+        auto buttons = dynamic_cast<Gtk::Box*>(info->get_next_sibling());
+        if (!buttons) return;
+
+        auto play_button = dynamic_cast<Gtk::Button*>(buttons->get_first_child());
+        if (!play_button) return;
+
+        auto queue_button = dynamic_cast<Gtk::Button*>(play_button->get_next_sibling());
+        if (!queue_button) return;
 
         // Загрузка изображения превью видео с диска
+        // TODO: ~/.cache/ytmpv/thumbnails -- брать из appcore
         std::string thumbnail_path = "thumbnails/default/" + obj.ytid + ".jpg";
         Glib::RefPtr<Gdk::Pixbuf> thumbnail_pixbuf;
         try {
@@ -197,7 +266,11 @@ namespace components {
         thumbnail->set_can_shrink(false);
         thumbnail->set_content_fit(Gtk::ContentFit::COVER);
 
-        lbl_title->set_text(obj.title);
+        title->set_text(obj.title);
+
+        published_at_label->set_text(m_appcore->getDateText(obj.published_at));
+        channel_label->set_text(obj.author_obj.name);
+        views_count_label->set_text(m_appcore->getNumberGrouped(obj.views_count));
     }
 
     void MainWindow::onVideoChanged()

+ 41 - 0
src/YTMPV/core.cpp

@@ -1,6 +1,7 @@
 #include "core.hpp"
 #include <nlohmann/json.hpp>
 #include <Database/database.hpp>
+#include <format>
 
 using json = nlohmann::json;
 
@@ -218,4 +219,44 @@ namespace core {
     {
         m_apikey = value;
     }
+
+    std::string Core::getNumberGrouped(int n)
+    {
+        float value;
+        std::string suffix;
+        
+        if (n > 1000000) {
+            value = (float)n / 1000000.0);
+            suffix = "M";
+
+        } else if (n > 1000) {
+            value = (float)n / 1000.0);
+            suffix = "K";
+
+        } else {
+            value = n;
+            suffix = "";
+        } 
+
+        // Округление до тысячных: https://stackoverflow.com/a/14369745
+        value = std::round(value * 1000) / 1000.0;
+
+        return std::format("{}{}", value, suffix);
+    }
+
+    std::string Core::getDateText(std::string date)
+    {
+        // 1. Получить информацию о времени
+        std::tm t;
+        std::istringstream ss(date);
+        ss >> std::get_time(&t, "%Y-%m-%d%H:%M:%SZ");
+        if (ss.fail()) {
+            return "<couldn't format date>";
+        }
+
+        // 2. Сконструировать текст
+        std::stringstream output;
+        output << std::put_time(&t, "%c");
+        return output.str();
+    }
 }

+ 8 - 1
src/YTMPV/core.hpp

@@ -3,9 +3,10 @@
 #include <YoutubeApi/youtubeapi.hpp>
 #include <Database/entities.hpp>
 #include <fstream>
-#include <iostream>
+#include <sstream>
 #include <string>
 #include <vector>
+#include <chrono>
 
 // Реализация приложения без графики
 // Содержит функции и переменные, которые необходимы во всех компонентах
@@ -118,6 +119,12 @@ namespace core
             // Возвращает путь к большому превью видео по его ytid
             std::string getLargeThumbnailByYTID(std::string ytid);
 
+            // Возвращает сгруппированое число прописью
+            std::string getNumberGrouped(int n);
+
+            // Возвращает unix-время от времени публикации видео
+            std::string getDateText(std::string date);
+
         protected:
             // ключ API
             std::string m_apikey;