mirror of
https://github.com/RGBCube/serenity
synced 2025-05-18 20:35:06 +00:00
FileManager+LibGUI: Show thumbnail generation progress in the statusbar.
This commit is contained in:
parent
32191b0d4b
commit
614dafea32
9 changed files with 63 additions and 11 deletions
|
@ -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)) {
|
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 });
|
auto thumbnail = GraphicsBitmap::create(png_bitmap->format(), { 32, 32 });
|
||||||
Painter painter(*thumbnail);
|
Painter painter(*thumbnail);
|
||||||
painter.draw_scaled_bitmap(thumbnail->rect(), *png_bitmap, png_bitmap->rect());
|
painter.draw_scaled_bitmap(thumbnail->rect(), *png_bitmap, png_bitmap->rect());
|
||||||
it.value = move(thumbnail);
|
thumbnail_cache().set(path, move(thumbnail));
|
||||||
((DirectoryModel*)model)->did_update();
|
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)
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 871 B After Width: | Height: | Size: 301 B |
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue