レポジトリ種類: Mercurial
#include <FL/Fl.H>
#include <FL/Fl_PNG_Image.H>
#include <FL/Fl_JPEG_Image.H>
#include <algorithm>
#include <cctype>
#include <filesystem>
#include <iostream>
#include <mutex>
#include "thumbnail.hh"
#include "clickablebox.hh"
#include "misc.hh"
#include "widget.hh"
namespace fe {
Thumbnail::Thumbnail() : loadingDialog(nullptr) {}
Thumbnail::~Thumbnail() {
for (auto img : thumbs) {
delete img;
}
if (loadingDialog) {
delete loadingDialog;
}
}
void Thumbnail::createLoadingDialog() {
Fl_Window *mainWindow = Widget::getScroll()->window();
if (!mainWindow) return;
int w = 200;
int h = 100;
int sw = mainWindow->w();
int sh = mainWindow->h();
int sx = mainWindow->x();
int sy = mainWindow->y();
int x = sx + (sw - w) / 2;
int y = sy + (sh - h) / 2;
loadingDialog = new Fl_Window(x, y, w, h, "読み込み中");
loadingDialog->set_modal();
Fl_Box *box =
new Fl_Box(0, 0, w, h, "画像を読み込んでいます。\nお待ち下さい。");
box->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE);
loadingDialog->end();
loadingDialog->show();
loadingDialog->take_focus();
}
void Thumbnail::init() {
const char *home = getenv("HOME");
std::string homedir = "";
if (home) homedir = std::string(home) + "/.local/share/wallpapers";
std::string localdir = "/usr/local/share/wallpapers";
std::string sysdir = "/usr/share/wallpapers";
if (Misc::isExist(homedir)) {
std::vector<std::string> img = listImages(homedir);
imgfiles.insert(imgfiles.end(), img.begin(), img.end());
}
if (Misc::isExist(localdir)) {
std::vector<std::string> img = listImages(localdir);
imgfiles.insert(imgfiles.end(), img.begin(), img.end());
}
if (Misc::isExist(sysdir)) {
std::vector<std::string> img = listImages(sysdir);
imgfiles.insert(imgfiles.end(), img.begin(), img.end());
}
Widget::getScroll()->deactivate();
for (const auto &file : imgfiles) {
pending.push(file);
}
createLoadingDialog();
Fl::add_timeout(0.0, loadImagesCb, this);
}
void Thumbnail::loadImagesCb(void *v) {
Thumbnail *thumb = static_cast<Thumbnail *>(v);
thumb->loadNextImage();
}
void Thumbnail::loadNextImage() {
std::lock_guard<std::mutex> lock(mutex);
if (pending.empty()) {
if (loadingDialog) {
loadingDialog->hide();
delete loadingDialog;
loadingDialog = nullptr;
}
Widget::getScroll()->activate();
Widget::getScroll()->redraw();
return;
}
std::string filepath = pending.front();
pending.pop();
Fl_Image *img = nullptr;
std::string ext = filepath.substr(filepath.size() - 4);
if (ext == ".png") {
img = new Fl_PNG_Image(filepath.c_str());
} else if (ext == ".jpg") {
img = new Fl_JPEG_Image(filepath.c_str());
}
if (!img || img->w() <= 0 || img->h() <= 0) {
if (img) delete img;
if (!pending.empty()) Fl::add_timeout(0.0, loadImagesCb, this);
else {
if (loadingDialog) {
loadingDialog->hide();
delete loadingDialog;
loadingDialog = nullptr;
}
Widget::getScroll()->activate();
Widget::getScroll()->redraw();
}
return;
}
Fl_Image *thumb = img->copy(100, 100);
thumbs.push_back(thumb);
delete img;
ClickableBox *box = new ClickableBox(curX, curY, 100, 100);
box->image(thumb);
box->box(FL_FLAT_BOX);
box->setImagePath(filepath.c_str());
Widget::getScroll()->add(box);
Widget::getScroll()->redraw();
curX += 110;
if (curX + 110 > Widget::getScroll()->w()) {
curX = 10;
curY += 110;
}
if (!pending.empty()) Fl::add_timeout(0.01, loadImagesCb, this);
else {
if (loadingDialog) {
loadingDialog->hide();
delete loadingDialog;
loadingDialog = nullptr;
}
Widget::getScroll()->activate();
Widget::getScroll()->redraw();
}
}
std::vector<std::string> Thumbnail::listImages(const std::string &directory) {
std::vector<std::string> images;
std::filesystem::path dir(directory);
if (!std::filesystem::exists(dir) || !std::filesystem::is_directory(dir)) {
std::cerr << "ディレクトリを開くに失敗: " << directory << std::endl;
return images;
}
for (const auto &entry : std::filesystem::directory_iterator(dir)) {
if (!entry.is_regular_file()) continue;
std::string filename = entry.path().filename().string();
if (filename.size() <= 4) continue;
std::string ext = entry.path().extension().string();
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
if (ext == ".png" || ext == ".jpg") {
images.push_back(entry.path().string());
}
}
return images;
}
}