Pārlūkot izejas kodu

FileManager+LibGUI: Show thumbnail generation progress in the statusbar.

Andreas Kling 6 gadi atpakaļ
vecāks
revīzija
614dafea32

+ 19 - 10
Applications/FileManager/DirectoryModel.cpp

@@ -17,20 +17,29 @@ static HashMap<String, RetainPtr<GraphicsBitmap>>& thumbnail_cache()
     return *s_map;
     return *s_map;
 }
 }
 
 
-int thumbnail_thread(void* model)
+int thumbnail_thread(void* model_ptr)
 {
 {
+    auto& model = *(DirectoryModel*)model_ptr;
     for (;;) {
     for (;;) {
         sleep(1);
         sleep(1);
+        Vector<String> to_generate;
         for (auto& it : thumbnail_cache()) {
         for (auto& it : thumbnail_cache()) {
             if (it.value)
             if (it.value)
                 continue;
                 continue;
-            if (auto png_bitmap = GraphicsBitmap::load_from_file(it.key)) {
-                auto thumbnail = GraphicsBitmap::create(png_bitmap->format(), { 32, 32 });
-                Painter painter(*thumbnail);
-                painter.draw_scaled_bitmap(thumbnail->rect(), *png_bitmap, png_bitmap->rect());
-                it.value = move(thumbnail);
-                ((DirectoryModel*)model)->did_update();
-            }
+            to_generate.append(it.key);
+        }
+        for (int i = 0; i < to_generate.size(); ++i) {
+            auto& path = to_generate[i];
+            auto png_bitmap = GraphicsBitmap::load_from_file(path);
+            if (!png_bitmap)
+                continue;
+            auto thumbnail = GraphicsBitmap::create(png_bitmap->format(), { 32, 32 });
+            Painter painter(*thumbnail);
+            painter.draw_scaled_bitmap(thumbnail->rect(), *png_bitmap, png_bitmap->rect());
+            thumbnail_cache().set(path, move(thumbnail));
+            if (model.on_thumbnail_progress)
+                model.on_thumbnail_progress(i + 1, to_generate.size());
+            model.did_update();
         }
         }
     }
     }
 }
 }
@@ -109,7 +118,7 @@ GIcon DirectoryModel::icon_for(const Entry& entry) const
         return m_socket_icon;
         return m_socket_icon;
     if (entry.mode & S_IXUSR)
     if (entry.mode & S_IXUSR)
         return m_executable_icon;
         return m_executable_icon;
-    if (entry.name.ends_with(".png")) {
+    if (entry.name.to_lowercase().ends_with(".png")) {
         if (!entry.thumbnail) {
         if (!entry.thumbnail) {
             auto path = entry.full_path(*this);
             auto path = entry.full_path(*this);
             auto it = thumbnail_cache().find(path);
             auto it = thumbnail_cache().find(path);
@@ -286,7 +295,7 @@ void DirectoryModel::activate(const GModelIndex& index)
         return;
         return;
     }
     }
 
 
-    if (path.string().ends_with(".png")) {
+    if (path.string().to_lowercase().ends_with(".png")) {
         if (fork() == 0) {
         if (fork() == 0) {
             int rc = execl("/bin/qs", "/bin/qs", path.string().characters(), nullptr);
             int rc = execl("/bin/qs", "/bin/qs", path.string().characters(), nullptr);
             if (rc < 0)
             if (rc < 0)

+ 2 - 0
Applications/FileManager/DirectoryModel.h

@@ -33,6 +33,8 @@ public:
     void open(const String& path);
     void open(const String& path);
     size_t bytes_in_files() const { return m_bytes_in_files; }
     size_t bytes_in_files() const { return m_bytes_in_files; }
 
 
+    Function<void(int done, int total)> on_thumbnail_progress;
+
 private:
 private:
     DirectoryModel();
     DirectoryModel();
 
 

+ 5 - 0
Applications/FileManager/DirectoryTableView.cpp

@@ -29,6 +29,11 @@ DirectoryView::DirectoryView(GWidget* parent)
         }
         }
     };
     };
 
 
+    m_model->on_thumbnail_progress = [this] (int done, int total) {
+        if (on_thumbnail_progress)
+            on_thumbnail_progress(done, total);
+    };
+
     set_view_mode(ViewMode::Icon);
     set_view_mode(ViewMode::Icon);
 }
 }
 
 

+ 1 - 0
Applications/FileManager/DirectoryTableView.h

@@ -19,6 +19,7 @@ public:
 
 
     Function<void(const String&)> on_path_change;
     Function<void(const String&)> on_path_change;
     Function<void(String)> on_status_message;
     Function<void(String)> on_status_message;
+    Function<void(int done, int total)> on_thumbnail_progress;
 
 
     enum ViewMode { Invalid, List, Icon };
     enum ViewMode { Invalid, List, Icon };
     void set_view_mode(ViewMode);
     void set_view_mode(ViewMode);

+ 16 - 0
Applications/FileManager/main.cpp

@@ -10,6 +10,7 @@
 #include <LibGUI/GLabel.h>
 #include <LibGUI/GLabel.h>
 #include <LibGUI/GInputBox.h>
 #include <LibGUI/GInputBox.h>
 #include <LibGUI/GMessageBox.h>
 #include <LibGUI/GMessageBox.h>
+#include <LibGUI/GProgressBar.h>
 #include <unistd.h>
 #include <unistd.h>
 #include <signal.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdio.h>
@@ -50,6 +51,11 @@ int main(int argc, char** argv)
     auto* directory_view = new DirectoryView(widget);
     auto* directory_view = new DirectoryView(widget);
     auto* statusbar = new GStatusBar(widget);
     auto* statusbar = new GStatusBar(widget);
 
 
+    auto* progressbar = new GProgressBar(statusbar);
+    progressbar->set_caption("Generating thumbnails: ");
+    progressbar->set_format(GProgressBar::Format::ValueSlashMax);
+    progressbar->set_visible(false);
+
     location_textbox->on_return_pressed = [directory_view] (auto& editor) {
     location_textbox->on_return_pressed = [directory_view] (auto& editor) {
         directory_view->open(editor.text());
         directory_view->open(editor.text());
     };
     };
@@ -138,6 +144,16 @@ int main(int argc, char** argv)
         statusbar->set_text(move(message));
         statusbar->set_text(move(message));
     };
     };
 
 
+    directory_view->on_thumbnail_progress = [&] (int done, int total) {
+        if (done == total) {
+            progressbar->set_visible(false);
+            return;
+        }
+        progressbar->set_range(0, total);
+        progressbar->set_value(done);
+        progressbar->set_visible(true);
+    };
+
     directory_view->open("/");
     directory_view->open("/");
     directory_view->set_focus(true);
     directory_view->set_focus(true);
 
 

BIN
Base/res/icons/32x32/filetype-image.png


+ 10 - 1
LibGUI/GProgressBar.cpp

@@ -1,5 +1,6 @@
 #include <LibGUI/GProgressBar.h>
 #include <LibGUI/GProgressBar.h>
 #include <SharedGraphics/Painter.h>
 #include <SharedGraphics/Painter.h>
+#include <AK/StringBuilder.h>
 
 
 GProgressBar::GProgressBar(GWidget* parent)
 GProgressBar::GProgressBar(GWidget* parent)
     : GWidget(parent)
     : GWidget(parent)
@@ -45,7 +46,15 @@ void GProgressBar::paint_event(GPaintEvent& event)
 
 
     // Then we draw the progress text over the gradient.
     // Then we draw the progress text over the gradient.
     // We draw it twice, once offset (1, 1) for a drop shadow look.
     // We draw it twice, once offset (1, 1) for a drop shadow look.
-    auto progress_text = String::format("%d%%", (int)(progress * 100));
+    StringBuilder builder;
+    builder.append(m_caption);
+    if (m_format == Format::Percentage)
+        builder.appendf("%d%%", (int)(progress * 100));
+    else if (m_format == Format::ValueSlashMax)
+        builder.appendf("%d/%d", m_value, m_max);
+
+    auto progress_text = builder.to_string();
+
     painter.draw_text(rect().translated(1, 1), progress_text, TextAlignment::Center, Color::Black);
     painter.draw_text(rect().translated(1, 1), progress_text, TextAlignment::Center, Color::Black);
     painter.draw_text(rect(), progress_text, TextAlignment::Center, Color::White);
     painter.draw_text(rect(), progress_text, TextAlignment::Center, Color::White);
 
 

+ 9 - 0
LibGUI/GProgressBar.h

@@ -12,11 +12,20 @@ public:
 
 
     int value() const { return m_value; }
     int value() const { return m_value; }
 
 
+    String caption() const { return m_caption; }
+    void set_caption(const String& caption) { m_caption = caption; }
+
+    enum Format { Percentage, ValueSlashMax };
+    Format format() const { return m_format; }
+    void set_format(Format format) { m_format = format; }
+
 protected:
 protected:
     virtual void paint_event(GPaintEvent&) override;
     virtual void paint_event(GPaintEvent&) override;
 
 
 private:
 private:
+    Format m_format { Percentage };
     int m_min { 0 };
     int m_min { 0 };
     int m_max { 100 };
     int m_max { 100 };
     int m_value { 0 };
     int m_value { 0 };
+    String m_caption;
 };
 };

+ 1 - 0
LibGUI/GWidget.cpp

@@ -336,6 +336,7 @@ void GWidget::invalidate_layout()
         return;
         return;
     if (!w->main_widget())
     if (!w->main_widget())
         return;
         return;
+    do_layout();
     w->main_widget()->do_layout();
     w->main_widget()->do_layout();
 }
 }