play with some tint2conf code
git-svn-id: http://tint2.googlecode.com/svn/trunk@146 121b4492-b84c-0410-8b4c-0d4edfb3f3cc
This commit is contained in:
parent
b025cacc88
commit
3926a0026c
6 changed files with 1033 additions and 0 deletions
|
@ -1,3 +1,6 @@
|
||||||
|
2009-07-14
|
||||||
|
- play with some tint2conf code
|
||||||
|
|
||||||
2009-07-04
|
2009-07-04
|
||||||
- fixed 'defunct' process after fork
|
- fixed 'defunct' process after fork
|
||||||
|
|
||||||
|
|
54
src/tint2conf/main.cpp
Normal file
54
src/tint2conf/main.cpp
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Tint2conf
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Thierry lorthiois (lorthiois@bbsoft.fr)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <gtkmm.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "mainwin.h"
|
||||||
|
|
||||||
|
|
||||||
|
// g++ `pkg-config --libs --cflags gtkmm-2.4 --libs gthread-2.0` -o tint2conf main.cpp mainwin.cpp thumbview.cpp
|
||||||
|
|
||||||
|
int main (int argc, char ** argv)
|
||||||
|
{
|
||||||
|
// set up i18n
|
||||||
|
//bindtextdomain(PACKAGE, LOCALEDIR);
|
||||||
|
//bind_textdomain_codeset(PACKAGE, "UTF-8");
|
||||||
|
//textdomain(PACKAGE);
|
||||||
|
|
||||||
|
Gtk::Main kit(argc, argv);
|
||||||
|
Glib::thread_init();
|
||||||
|
|
||||||
|
MainWin window;
|
||||||
|
|
||||||
|
window.view.set_dir("");
|
||||||
|
window.view.load_dir();
|
||||||
|
|
||||||
|
// rig up idle/thread routines
|
||||||
|
Glib::Thread::create(sigc::mem_fun(window.view, &Thumbview::load_cache_images), true);
|
||||||
|
Glib::Thread::create(sigc::mem_fun(window.view, &Thumbview::create_cache_images), true);
|
||||||
|
|
||||||
|
//Shows the window and returns when it is closed.
|
||||||
|
Gtk::Main::run(window);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
140
src/tint2conf/mainwin.cpp
Normal file
140
src/tint2conf/mainwin.cpp
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
|
||||||
|
#include <gtkmm/stock.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include "mainwin.h"
|
||||||
|
|
||||||
|
|
||||||
|
MainWin::MainWin()
|
||||||
|
{
|
||||||
|
set_title("Tint2 config");
|
||||||
|
set_default_size(600, 350);
|
||||||
|
|
||||||
|
add(m_Box); // put a MenuBar at the top of the box and other stuff below it.
|
||||||
|
|
||||||
|
//Create actions for menus and toolbars:
|
||||||
|
m_refActionGroup = Gtk::ActionGroup::create();
|
||||||
|
|
||||||
|
//File menu:
|
||||||
|
m_refActionGroup->add(Gtk::Action::create("FileMenu", "File"));
|
||||||
|
//Sub-menu.
|
||||||
|
m_refActionGroup->add(Gtk::Action::create("FileOpen", Gtk::Stock::OPEN, "_Open", "Open config file"), sigc::mem_fun(*this, &MainWin::on_menu_file_new_generic));
|
||||||
|
m_refActionGroup->add(Gtk::Action::create("FileSaveAs", Gtk::Stock::SAVE_AS, "_Save As", "Save config as"), sigc::mem_fun(*this, &MainWin::on_menu_file_new_generic));
|
||||||
|
m_refActionGroup->add(Gtk::Action::create("FileRefreshAll", Gtk::Stock::REFRESH, "_Refresh all", "Refresh all config file"), sigc::mem_fun(*this, &MainWin::on_menu_file_new_generic));
|
||||||
|
m_refActionGroup->add(Gtk::Action::create("FileQuit", Gtk::Stock::QUIT), sigc::mem_fun(*this, &MainWin::on_menu_file_quit));
|
||||||
|
|
||||||
|
//Edit menu:
|
||||||
|
m_refActionGroup->add(Gtk::Action::create("EditMenu", "Edit"));
|
||||||
|
m_refActionGroup->add(Gtk::Action::create("EditProperties", Gtk::Stock::PROPERTIES, "_Properties...", "Show properties"), sigc::mem_fun(*this, &MainWin::on_menu_others));
|
||||||
|
m_refActionGroup->add(Gtk::Action::create("EditRename", "_Rename...", "Rename current config"), sigc::mem_fun(*this, &MainWin::on_menu_others));
|
||||||
|
m_refActionGroup->add(Gtk::Action::create("EditDelete", Gtk::Stock::DELETE), sigc::mem_fun(*this, &MainWin::on_menu_others));
|
||||||
|
m_refActionGroup->add(Gtk::Action::create("EditApply", Gtk::Stock::APPLY, "_Apply", "Apply current config"), sigc::mem_fun(*this, &MainWin::on_menu_others));
|
||||||
|
m_refActionGroup->add(Gtk::Action::create("EditRefresh", Gtk::Stock::REFRESH), sigc::mem_fun(*this, &MainWin::on_menu_others));
|
||||||
|
|
||||||
|
//Help menu:
|
||||||
|
m_refActionGroup->add( Gtk::Action::create("HelpMenu", "Help") );
|
||||||
|
m_refActionGroup->add( Gtk::Action::create("About", Gtk::Stock::ABOUT), sigc::mem_fun(*this, &MainWin::on_menu_about) );
|
||||||
|
|
||||||
|
m_refUIManager = Gtk::UIManager::create();
|
||||||
|
m_refUIManager->insert_action_group(m_refActionGroup);
|
||||||
|
|
||||||
|
add_accel_group(m_refUIManager->get_accel_group());
|
||||||
|
|
||||||
|
//Layout the actions in a menubar and toolbar:
|
||||||
|
Glib::ustring ui_info =
|
||||||
|
"<ui>"
|
||||||
|
" <menubar name='MenuBar'>"
|
||||||
|
" <menu action='FileMenu'>"
|
||||||
|
" <menuitem action='FileOpen'/>"
|
||||||
|
" <menuitem action='FileSaveAs'/>"
|
||||||
|
" <separator/>"
|
||||||
|
" <menuitem action='FileRefreshAll'/>"
|
||||||
|
" <separator/>"
|
||||||
|
" <menuitem action='FileQuit'/>"
|
||||||
|
" </menu>"
|
||||||
|
" <menu action='EditMenu'>"
|
||||||
|
" <menuitem action='EditProperties'/>"
|
||||||
|
" <menuitem action='EditRename'/>"
|
||||||
|
" <separator/>"
|
||||||
|
" <menuitem action='EditDelete'/>"
|
||||||
|
" <separator/>"
|
||||||
|
" <menuitem action='EditRefresh'/>"
|
||||||
|
" </menu>"
|
||||||
|
" <menu action='HelpMenu'>"
|
||||||
|
" <menuitem action='About'/>"
|
||||||
|
" </menu>"
|
||||||
|
" </menubar>"
|
||||||
|
" <toolbar name='ToolBar'>"
|
||||||
|
" <toolitem action='FileRefreshAll'/>"
|
||||||
|
" <separator/>"
|
||||||
|
" <toolitem action='EditProperties'/>"
|
||||||
|
" <toolitem action='EditApply'/>"
|
||||||
|
" </toolbar>"
|
||||||
|
"</ui>";
|
||||||
|
|
||||||
|
#ifdef GLIBMM_EXCEPTIONS_ENABLED
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_refUIManager->add_ui_from_string(ui_info);
|
||||||
|
}
|
||||||
|
catch(const Glib::Error& ex)
|
||||||
|
{
|
||||||
|
std::cerr << "building menus failed: " << ex.what();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::auto_ptr<Glib::Error> ex;
|
||||||
|
m_refUIManager->add_ui_from_string(ui_info, ex);
|
||||||
|
if(ex.get())
|
||||||
|
{
|
||||||
|
std::cerr << "building menus failed: " << ex->what();
|
||||||
|
}
|
||||||
|
#endif //GLIBMM_EXCEPTIONS_ENABLED
|
||||||
|
|
||||||
|
//Get the menubar and toolbar widgets, and add them to a container widget:
|
||||||
|
Gtk::Widget* pMenubar = m_refUIManager->get_widget("/MenuBar");
|
||||||
|
if(pMenubar)
|
||||||
|
m_Box.pack_start(*pMenubar, Gtk::PACK_SHRINK);
|
||||||
|
|
||||||
|
Gtk::Widget* pToolbar = m_refUIManager->get_widget("/ToolBar") ;
|
||||||
|
if(pToolbar)
|
||||||
|
m_Box.pack_start(*pToolbar, Gtk::PACK_SHRINK);
|
||||||
|
|
||||||
|
|
||||||
|
m_Box.add(view);
|
||||||
|
|
||||||
|
show_all_children();
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWin::~MainWin()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWin::on_menu_file_quit()
|
||||||
|
{
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWin::on_menu_file_new_generic()
|
||||||
|
{
|
||||||
|
std::cout << "A File|New menu item was selected." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWin::on_menu_others()
|
||||||
|
{
|
||||||
|
std::cout << "A menu item was selected." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWin::on_menu_about()
|
||||||
|
{
|
||||||
|
Glib::ustring message = "tint2conf " + Glib::ustring(VERSION);
|
||||||
|
Gtk::MessageDialog dialog(*this, message);
|
||||||
|
|
||||||
|
dialog.set_title("About tint2conf");
|
||||||
|
dialog.set_secondary_text("Config tool for tint2.\n\nCopyright (C) 2009 Thierry lorthiois. \nRefer to source code from Nitrogen\nby Dave Foster & Javeed Shaikh.");
|
||||||
|
|
||||||
|
dialog.run();
|
||||||
|
}
|
||||||
|
|
33
src/tint2conf/mainwin.h
Normal file
33
src/tint2conf/mainwin.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef TINT2CONF_MAINWIN_H
|
||||||
|
#define TINT2CONF_MAINWIN_H
|
||||||
|
|
||||||
|
#include <gtkmm.h>
|
||||||
|
#include "thumbview.h"
|
||||||
|
|
||||||
|
#define VERSION "0.2"
|
||||||
|
|
||||||
|
|
||||||
|
class MainWin : public Gtk::Window
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MainWin();
|
||||||
|
virtual ~MainWin();
|
||||||
|
|
||||||
|
Thumbview view;
|
||||||
|
protected:
|
||||||
|
//Signal handlers:
|
||||||
|
void on_menu_file_new_generic();
|
||||||
|
void on_menu_file_quit();
|
||||||
|
void on_menu_others();
|
||||||
|
void on_menu_about();
|
||||||
|
|
||||||
|
//Child widgets:
|
||||||
|
Gtk::VBox m_Box;
|
||||||
|
|
||||||
|
Glib::RefPtr<Gtk::UIManager> m_refUIManager;
|
||||||
|
Glib::RefPtr<Gtk::ActionGroup> m_refActionGroup;
|
||||||
|
Glib::RefPtr<Gtk::RadioAction> m_refChoiceOne, m_refChoiceTwo;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
641
src/tint2conf/thumbview.cpp
Normal file
641
src/tint2conf/thumbview.cpp
Normal file
|
@ -0,0 +1,641 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is from Nitrogen, an X11 background setter.
|
||||||
|
Copyright (C) 2006 Dave Foster & Javeed Shaikh
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#include "md5.h"
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
#include <png.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include "thumbview.h"
|
||||||
|
//#include "Config.h"
|
||||||
|
//#include "Util.h"
|
||||||
|
//#include "gcs-i18n.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the last modified time of a file.
|
||||||
|
* @param file The name of the file to get the modified time for.
|
||||||
|
*/
|
||||||
|
static time_t get_file_mtime(std::string file) {
|
||||||
|
struct stat buf;
|
||||||
|
if (stat(file.c_str(), &buf) == -1) return 0; // error
|
||||||
|
return buf.st_mtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the "tEXt::Thumb::MTime" key for fd.o style thumbs.
|
||||||
|
* @param pixbuf The pixbuf of the fd.o thumbnail.
|
||||||
|
*/
|
||||||
|
static time_t get_fdo_thumbnail_mtime(Glib::RefPtr<Gdk::Pixbuf> pixbuf) {
|
||||||
|
std::string mtime_str = pixbuf->get_option("tEXt::Thumb::MTime");
|
||||||
|
std::stringstream stream(mtime_str);
|
||||||
|
time_t mtime = 0;
|
||||||
|
stream >> mtime;
|
||||||
|
return mtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DelayLoadingStore::get_value_vfunc (const iterator& iter, int column, Glib::ValueBase& value) const
|
||||||
|
{
|
||||||
|
g_async_queue_ref(aqueue_loadthumbs);
|
||||||
|
Gtk::ListStore::get_value_vfunc(iter, column, value);
|
||||||
|
|
||||||
|
Gtk::TreeModel::Row row = *iter;
|
||||||
|
if (column == 0)
|
||||||
|
{
|
||||||
|
Glib::Value< Glib::RefPtr<Gdk::Pixbuf> > base;
|
||||||
|
Gtk::ListStore::get_value_vfunc(iter, column, base);
|
||||||
|
|
||||||
|
Glib::RefPtr<Gdk::Pixbuf> thumb = base.get();
|
||||||
|
|
||||||
|
if (thumb == thumbview->loading_image && !row[thumbview->record.LoadingThumb])
|
||||||
|
{
|
||||||
|
TreePair* tp = new TreePair();
|
||||||
|
tp->file = row[thumbview->record.Filename];
|
||||||
|
tp->iter = iter;
|
||||||
|
|
||||||
|
row[thumbview->record.LoadingThumb] = true;
|
||||||
|
|
||||||
|
//Util::program_log("Custom model: planning on loading %s\n", tp->file.c_str());
|
||||||
|
|
||||||
|
g_async_queue_push(aqueue_loadthumbs, (gpointer)tp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_async_queue_unref(aqueue_loadthumbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor, sets up gtk stuff, inits data and queues
|
||||||
|
*/
|
||||||
|
Thumbview::Thumbview() : dir("") {
|
||||||
|
set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
|
||||||
|
set_shadow_type (Gtk::SHADOW_IN);
|
||||||
|
|
||||||
|
// load map of setbgs (need this for add_file)
|
||||||
|
load_map_setbgs();
|
||||||
|
|
||||||
|
// make our async queues
|
||||||
|
this->aqueue_loadthumbs = g_async_queue_new();
|
||||||
|
this->aqueue_createthumbs = g_async_queue_new();
|
||||||
|
this->aqueue_donethumbs = g_async_queue_new();
|
||||||
|
|
||||||
|
// create store
|
||||||
|
store = DelayLoadingStore::create (record);
|
||||||
|
store->set_queue(aqueue_loadthumbs);
|
||||||
|
store->set_thumbview(this);
|
||||||
|
|
||||||
|
// setup view
|
||||||
|
view.set_model (store);
|
||||||
|
view.set_headers_visible (FALSE);
|
||||||
|
view.set_fixed_height_mode (TRUE);
|
||||||
|
view.set_rules_hint (TRUE);
|
||||||
|
|
||||||
|
// set cell renderer proprties
|
||||||
|
rend.property_ellipsize () = Pango::ELLIPSIZE_END;
|
||||||
|
rend.set_property ("ellipsize", Pango::ELLIPSIZE_END);
|
||||||
|
rend.property_weight () = Pango::WEIGHT_BOLD;
|
||||||
|
|
||||||
|
rend_img.set_fixed_size(105, 82);
|
||||||
|
|
||||||
|
// make treeviewcolumns
|
||||||
|
this->col_thumb = new Gtk::TreeViewColumn("thumbnail", this->rend_img);
|
||||||
|
this->col_desc = new Gtk::TreeViewColumn("description", this->rend);
|
||||||
|
|
||||||
|
col_thumb->add_attribute (rend_img, "pixbuf", record.Thumbnail);
|
||||||
|
col_thumb->set_sizing(Gtk::TREE_VIEW_COLUMN_FIXED);
|
||||||
|
col_thumb->set_fixed_width(105);
|
||||||
|
col_desc->add_attribute (rend, "markup", record.Description);
|
||||||
|
col_desc->set_sort_column (record.Filename);
|
||||||
|
col_desc->set_sort_indicator (true);
|
||||||
|
col_desc->set_sort_order (Gtk::SORT_ASCENDING);
|
||||||
|
col_desc->set_sizing(Gtk::TREE_VIEW_COLUMN_FIXED);
|
||||||
|
|
||||||
|
view.append_column (*col_thumb);
|
||||||
|
view.append_column (*col_desc);
|
||||||
|
|
||||||
|
// enable search
|
||||||
|
view.set_search_column (record.Description);
|
||||||
|
view.set_search_equal_func (sigc::mem_fun (this, &Thumbview::search_compare));
|
||||||
|
|
||||||
|
// load loading image, which not all themes seem to provide
|
||||||
|
try {
|
||||||
|
this->loading_image = Gtk::IconTheme::get_default()->load_icon("image-loading", 64, Gtk::ICON_LOOKUP_FORCE_SVG);
|
||||||
|
} catch (Gtk::IconThemeError e) {}
|
||||||
|
|
||||||
|
// init dispatcher
|
||||||
|
this->dispatch_thumb.connect(sigc::mem_fun(this, &Thumbview::handle_dispatch_thumb));
|
||||||
|
|
||||||
|
col_desc->set_expand ();
|
||||||
|
|
||||||
|
add (view);
|
||||||
|
|
||||||
|
view.show ();
|
||||||
|
show ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
|
Thumbview::~Thumbview() {
|
||||||
|
g_async_queue_unref(this->aqueue_loadthumbs);
|
||||||
|
g_async_queue_unref(this->aqueue_createthumbs);
|
||||||
|
g_async_queue_unref(this->aqueue_donethumbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the given file to the tree view and pushes it onto the thumbnail
|
||||||
|
* creation queue.
|
||||||
|
*
|
||||||
|
* @param filename The name of the file to add.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void Thumbview::add_file(std::string filename) {
|
||||||
|
Gtk::Window *window = dynamic_cast<Gtk::Window*>(get_toplevel());
|
||||||
|
Gtk::TreeModel::iterator iter = this->store->append ();
|
||||||
|
Gtk::TreeModel::Row row = *iter;
|
||||||
|
Glib::RefPtr<Gdk::Pixbuf> thumb = this->loading_image;
|
||||||
|
row[record.Thumbnail] = thumb;
|
||||||
|
row[record.Filename] = filename;
|
||||||
|
row[record.Description] = Glib::ustring(filename, filename.rfind ("/")+1);
|
||||||
|
|
||||||
|
for (std::map<Glib::ustring, Glib::ustring>::iterator i = map_setbgs.begin(); i!=map_setbgs.end(); i++)
|
||||||
|
{
|
||||||
|
if (filename == (*i).second)
|
||||||
|
{
|
||||||
|
row[record.CurBGOnDisp] = (*i).first;
|
||||||
|
// row[record.Description] = Util::make_current_set_string(window, filename, (*i).first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for modified time
|
||||||
|
row[record.Time] = get_file_mtime(filename);
|
||||||
|
|
||||||
|
// Util::program_log("add_file(): Adding file %s\n", filename.c_str());
|
||||||
|
|
||||||
|
// push it on the thumb queue
|
||||||
|
// TreePair *tp = new TreePair();
|
||||||
|
// tp->file = filename;
|
||||||
|
// tp->iter = iter;
|
||||||
|
|
||||||
|
// queue_thumbs.push(tp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the internal directory and starts reading files into the async queue.
|
||||||
|
*/
|
||||||
|
void Thumbview::load_dir(std::string dir) {
|
||||||
|
if (!dir.length()) dir = this->dir;
|
||||||
|
|
||||||
|
std::queue<Glib::ustring> subdirs;
|
||||||
|
Glib::Dir *dirhandle;
|
||||||
|
|
||||||
|
// push the initial dir back onto subdirs
|
||||||
|
subdirs.push(dir);
|
||||||
|
|
||||||
|
// loop it
|
||||||
|
while ( ! subdirs.empty() ) {
|
||||||
|
|
||||||
|
// pop first
|
||||||
|
Glib::ustring curdir = subdirs.front();
|
||||||
|
subdirs.pop();
|
||||||
|
|
||||||
|
try {
|
||||||
|
dirhandle = new Glib::Dir(curdir);
|
||||||
|
// Util::program_log("load_dir(): Opening dir %s\n", curdir.c_str());
|
||||||
|
|
||||||
|
} catch (Glib::FileError e) {
|
||||||
|
std::cerr << "Could not open dir" << " " << this->dir << ": " << e.what() << "\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_INOTIFY
|
||||||
|
|
||||||
|
// check if we're already monitoring this dir.
|
||||||
|
if (watches.find(curdir) == watches.end()) {
|
||||||
|
// this dir was successfully opened. monitor it for changes with inotify.
|
||||||
|
// the Watch will be cleaned up automatically if the dir is deleted.
|
||||||
|
Inotify::Watch * watch = Inotify::Watch::create(curdir);
|
||||||
|
if (watch) {
|
||||||
|
// no error occurred.
|
||||||
|
|
||||||
|
// emitted when a file is deleted in this dir.
|
||||||
|
watch->signal_deleted.connect(sigc::mem_fun(this,
|
||||||
|
&Thumbview::file_deleted_callback));
|
||||||
|
// emitted when a file is modified or created in this dir.
|
||||||
|
watch->signal_write_closed.connect(sigc::mem_fun(this,
|
||||||
|
&Thumbview::file_changed_callback));
|
||||||
|
// two signals that are emitted when a file is renamed in this dir.
|
||||||
|
// the best way to handle this IMO is to remove the file upon receiving
|
||||||
|
// 'moved_from', and then to add the file upon receiving 'moved_to'.
|
||||||
|
watch->signal_moved_from.connect(sigc::mem_fun(this,
|
||||||
|
&Thumbview::file_deleted_callback));
|
||||||
|
watch->signal_moved_to.connect(sigc::mem_fun(this,
|
||||||
|
&Thumbview::file_changed_callback));
|
||||||
|
watch->signal_created.connect(sigc::mem_fun(this,
|
||||||
|
&Thumbview::file_created_callback));
|
||||||
|
|
||||||
|
watches[curdir] = watch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (Glib::Dir::iterator i = dirhandle->begin(); i != dirhandle->end(); i++) {
|
||||||
|
Glib::ustring fullstr = curdir + Glib::ustring("/");
|
||||||
|
try {
|
||||||
|
fullstr += /*Glib::filename_to_utf8(*/*i;//);
|
||||||
|
} catch (Glib::ConvertError& error) {
|
||||||
|
std::cerr << "Invalid UTF-8 encountered. Skipping file" << " " << *i << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Glib::file_test(fullstr, Glib::FILE_TEST_IS_DIR) )
|
||||||
|
{
|
||||||
|
// if ( Config::get_instance()->get_recurse() )
|
||||||
|
// subdirs.push(fullstr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( this->is_image(fullstr) ) {
|
||||||
|
add_file(fullstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete dirhandle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the file to see if it is an image
|
||||||
|
* TODO: come up with less sux way of doing it than extension
|
||||||
|
*
|
||||||
|
* @param file The filename to test
|
||||||
|
* @return If its an image or not
|
||||||
|
*/
|
||||||
|
bool Thumbview::is_image(std::string file) {
|
||||||
|
if (file.find (".jpg") != std::string::npos ||
|
||||||
|
file.find (".JPG") != std::string::npos ||
|
||||||
|
file.find (".jpeg") != std::string::npos ||
|
||||||
|
file.find (".JPEG") != std::string::npos )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the full path to a cache file. Does all creation of dirs.
|
||||||
|
* TODO: should throw exception if we cannot create the dirs!
|
||||||
|
*
|
||||||
|
* @param file The file to convert, calls cache_name on it
|
||||||
|
* @return The full path to
|
||||||
|
*/
|
||||||
|
Glib::ustring Thumbview::cache_file(Glib::ustring file) {
|
||||||
|
|
||||||
|
Glib::ustring urifile = Glib::filename_to_uri(file);
|
||||||
|
/*
|
||||||
|
// compute md5 of file's uri
|
||||||
|
md5_state_t state;
|
||||||
|
md5_byte_t digest[16];
|
||||||
|
md5_init(&state);
|
||||||
|
md5_append(&state, (const md5_byte_t *)urifile.c_str(), strlen(urifile.c_str()));
|
||||||
|
md5_finish(&state, digest);
|
||||||
|
|
||||||
|
char *buf = new char[3];
|
||||||
|
char *full = new char[33];
|
||||||
|
full[0] = '\0';
|
||||||
|
|
||||||
|
for (int di = 0; di < 16; ++di) {
|
||||||
|
sprintf(buf, "%02x", digest[di]);
|
||||||
|
strcat(full, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
Glib::ustring md5file = Glib::ustring(full) + Glib::ustring(".png");
|
||||||
|
delete [] buf;
|
||||||
|
delete [] full;
|
||||||
|
|
||||||
|
// build dir paths
|
||||||
|
Glib::ustring halfref = Glib::build_filename(Glib::get_home_dir(),".thumbnails/");
|
||||||
|
halfref = Glib::build_filename(halfref, "normal/");
|
||||||
|
|
||||||
|
if ( !Glib::file_test(halfref, Glib::FILE_TEST_EXISTS) )
|
||||||
|
if ( g_mkdir_with_parents(halfref.c_str(), 0700) == -1)
|
||||||
|
// TODO: exception
|
||||||
|
return "FAIL";
|
||||||
|
|
||||||
|
// add and return
|
||||||
|
return Glib::build_filename(halfref, md5file);
|
||||||
|
*/
|
||||||
|
return urifile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates cache images that show up in its queue.
|
||||||
|
*/
|
||||||
|
void Thumbview::load_cache_images()
|
||||||
|
{
|
||||||
|
g_async_queue_ref(this->aqueue_loadthumbs);
|
||||||
|
g_async_queue_ref(this->aqueue_donethumbs);
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
// remove first item (blocks until an item occurs)
|
||||||
|
TreePair *p = (TreePair*)g_async_queue_pop(this->aqueue_loadthumbs);
|
||||||
|
|
||||||
|
Glib::ustring file = p->file;
|
||||||
|
Glib::ustring cachefile = this->cache_file(file);
|
||||||
|
|
||||||
|
// branch to see if we need to load or create cache file
|
||||||
|
if ( !Glib::file_test(cachefile, Glib::FILE_TEST_EXISTS) ) {
|
||||||
|
g_async_queue_push(this->aqueue_createthumbs,(gpointer)p);
|
||||||
|
} else {
|
||||||
|
// load thumb
|
||||||
|
Glib::RefPtr<Gdk::Pixbuf> pb = Gdk::Pixbuf::create_from_file(this->cache_file(file));
|
||||||
|
|
||||||
|
// resize if we need to
|
||||||
|
if (pb->get_width() > 100 || pb->get_height() > 80)
|
||||||
|
{
|
||||||
|
int pbwidth = pb->get_width();
|
||||||
|
int pbheight = pb->get_height();
|
||||||
|
float ratio = (float)pbwidth / (float)pbheight;
|
||||||
|
|
||||||
|
int newwidth, newheight;
|
||||||
|
|
||||||
|
if (abs(100 - pbwidth) > abs(80 - pbheight))
|
||||||
|
{
|
||||||
|
// cap to vertical
|
||||||
|
newheight = 80;
|
||||||
|
newwidth = newheight * ratio;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// cap to horiz
|
||||||
|
newwidth = 100;
|
||||||
|
newheight = newwidth / ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
pb = pb->scale_simple(newwidth, newheight, Gdk::INTERP_NEAREST);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_fdo_thumbnail_mtime(pb) < get_file_mtime(file)) {
|
||||||
|
// the thumbnail is old. we need to make a new one.
|
||||||
|
pb.clear();
|
||||||
|
g_async_queue_push(this->aqueue_createthumbs,(gpointer)p);
|
||||||
|
} else {
|
||||||
|
// display it
|
||||||
|
TreePair *sendp = new TreePair();
|
||||||
|
sendp->file = file;
|
||||||
|
sendp->iter = p->iter;
|
||||||
|
sendp->thumb = pb;
|
||||||
|
|
||||||
|
g_async_queue_push(this->aqueue_donethumbs, (gpointer)sendp);
|
||||||
|
|
||||||
|
this->dispatch_thumb.emit();
|
||||||
|
|
||||||
|
delete p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_async_queue_unref(this->aqueue_loadthumbs);
|
||||||
|
g_async_queue_unref(this->aqueue_donethumbs);
|
||||||
|
throw Glib::Thread::Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread function to create thumbnail cache images for those that do not exist.
|
||||||
|
*/
|
||||||
|
void Thumbview::create_cache_images()
|
||||||
|
{
|
||||||
|
Glib::RefPtr<Gdk::Pixbuf> thumb;
|
||||||
|
|
||||||
|
g_async_queue_ref(this->aqueue_createthumbs);
|
||||||
|
g_async_queue_ref(this->aqueue_donethumbs);
|
||||||
|
|
||||||
|
// always work!
|
||||||
|
while (1) {
|
||||||
|
|
||||||
|
// remove first item (blocks when no items occur)
|
||||||
|
TreePair *p = (TreePair*)g_async_queue_pop(this->aqueue_createthumbs);
|
||||||
|
|
||||||
|
// get filenames
|
||||||
|
Glib::ustring file = p->file;
|
||||||
|
Glib::ustring cachefile = this->cache_file(file);
|
||||||
|
|
||||||
|
// Util::program_log("create_cache_images(): Caching file %s\n", file.c_str());
|
||||||
|
|
||||||
|
// open image
|
||||||
|
try {
|
||||||
|
thumb = Gdk::Pixbuf::create_from_file(file);
|
||||||
|
} catch (...) {
|
||||||
|
// forget it, move on
|
||||||
|
delete p;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eliminate zero heights (due to really tiny images :/)
|
||||||
|
int height = (int)(100*((float)thumb->get_height()/(float)thumb->get_width()));
|
||||||
|
if (!height) height = 1;
|
||||||
|
|
||||||
|
// create thumb
|
||||||
|
thumb = thumb->scale_simple(100, height, Gdk::INTERP_TILES);
|
||||||
|
|
||||||
|
// create required fd.o png tags
|
||||||
|
std::list<Glib::ustring> opts, vals;
|
||||||
|
opts.push_back(Glib::ustring("tEXt::Thumb::URI"));
|
||||||
|
vals.push_back(Glib::filename_to_uri(file));
|
||||||
|
|
||||||
|
time_t mtime = get_file_mtime(file);
|
||||||
|
|
||||||
|
char *bufout = new char[20];
|
||||||
|
sprintf(bufout, "%d", mtime);
|
||||||
|
|
||||||
|
opts.push_back(Glib::ustring("tEXt::Thumb::MTime"));
|
||||||
|
vals.push_back(Glib::ustring(bufout));
|
||||||
|
|
||||||
|
delete [] bufout;
|
||||||
|
|
||||||
|
thumb->save(cachefile, "png", opts, vals);
|
||||||
|
|
||||||
|
// send it to the display
|
||||||
|
TreePair *sendp = new TreePair();
|
||||||
|
sendp->file = file;
|
||||||
|
sendp->iter = p->iter;
|
||||||
|
sendp->thumb = thumb;
|
||||||
|
g_async_queue_push(this->aqueue_donethumbs, (gpointer)sendp);
|
||||||
|
|
||||||
|
// emit dispatcher
|
||||||
|
this->dispatch_thumb.emit();
|
||||||
|
|
||||||
|
delete p;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_async_queue_unref(this->aqueue_createthumbs);
|
||||||
|
g_async_queue_unref(this->aqueue_donethumbs);
|
||||||
|
throw Glib::Thread::Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Thumbview::handle_dispatch_thumb() {
|
||||||
|
g_async_queue_ref(this->aqueue_donethumbs);
|
||||||
|
|
||||||
|
TreePair *donep = (TreePair*)g_async_queue_pop(this->aqueue_donethumbs);
|
||||||
|
this->update_thumbnail(donep->file, donep->iter, donep->thumb);
|
||||||
|
delete donep;
|
||||||
|
|
||||||
|
g_async_queue_unref(this->aqueue_donethumbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the treeview to show the passed in thumbnail.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void Thumbview::update_thumbnail(Glib::ustring file, Gtk::TreeModel::iterator iter, Glib::RefPtr<Gdk::Pixbuf> pb)
|
||||||
|
{
|
||||||
|
Gtk::TreeModel::Row row = *iter;
|
||||||
|
row[record.Thumbnail] = pb;
|
||||||
|
// desc
|
||||||
|
//row[record.Description] = Glib::ustring(file, file.rfind("/")+1);
|
||||||
|
|
||||||
|
// emit a changed signal
|
||||||
|
store->row_changed(store->get_path(iter), iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by GTK to see whether or not an iterator matches a search string.
|
||||||
|
*/
|
||||||
|
bool Thumbview::search_compare (const Glib::RefPtr<Gtk::TreeModel>& model, int column, const Glib::ustring& key, const Gtk::TreeModel::iterator& iter) {
|
||||||
|
Glib::ustring target = (*iter)[record.Description];
|
||||||
|
if (target.find (key) != Glib::ustring::npos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the sort mode. This tells the view how it should sort backgrounds.
|
||||||
|
*/
|
||||||
|
void Thumbview::set_sort_mode (Thumbview::SortMode mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case SORT_ALPHA:
|
||||||
|
store->set_sort_column (record.Description, Gtk::SORT_ASCENDING);
|
||||||
|
break;
|
||||||
|
case SORT_RALPHA:
|
||||||
|
store->set_sort_column (record.Description, Gtk::SORT_DESCENDING);
|
||||||
|
break;
|
||||||
|
case SORT_TIME:
|
||||||
|
store->set_sort_column (record.Time, Gtk::SORT_ASCENDING);
|
||||||
|
break;
|
||||||
|
case SORT_RTIME:
|
||||||
|
store->set_sort_column (record.Time, Gtk::SORT_DESCENDING);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the map of displays and their set bgs. Used to indicate which
|
||||||
|
* files are currently set as a background.
|
||||||
|
*/
|
||||||
|
void Thumbview::load_map_setbgs()
|
||||||
|
{
|
||||||
|
map_setbgs.clear();
|
||||||
|
|
||||||
|
std::vector<Glib::ustring> vecgroups;
|
||||||
|
bool ret = false;
|
||||||
|
// bool ret = Config::get_instance()->get_bg_groups(vecgroups);
|
||||||
|
if (!ret)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (std::vector<Glib::ustring>::iterator i = vecgroups.begin(); i!=vecgroups.end(); i++)
|
||||||
|
{
|
||||||
|
Glib::ustring file;
|
||||||
|
// SetBG::SetMode mode;
|
||||||
|
Gdk::Color bgcolor;
|
||||||
|
|
||||||
|
// ret = Config::get_instance()->get_bg(*i, file, mode, bgcolor);
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
std::cerr << "(load_map_setbgs) Could not get background stored info for " << *i << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
map_setbgs[*i] = file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_INOTIFY
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a file in a directory being monitored by inotify is deleted.
|
||||||
|
* Removes the file from the tree view.
|
||||||
|
*
|
||||||
|
* @param filename The name of the file to remove.
|
||||||
|
*/
|
||||||
|
void Thumbview::file_deleted_callback(std::string filename) {
|
||||||
|
if (watches.find(filename) != watches.end()) {
|
||||||
|
watches.erase(filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Gtk::TreeIter iter;
|
||||||
|
Gtk::TreeModel::Children children = store->children();
|
||||||
|
for (iter = children.begin(); iter != children.end(); iter++) {
|
||||||
|
Glib::ustring this_filename = (*iter)[record.Filename];
|
||||||
|
if (this_filename == filename) {
|
||||||
|
// remove this iter.
|
||||||
|
store->erase(iter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a file in a directory being monitored by inotify is modified
|
||||||
|
* or a new file is created. Adds the file to the tree view.
|
||||||
|
*
|
||||||
|
* @param filename The name of the file modified or created.
|
||||||
|
*/
|
||||||
|
void Thumbview::file_changed_callback(std::string filename) {
|
||||||
|
// first remove the old instance of this file.
|
||||||
|
file_deleted_callback(filename);
|
||||||
|
if ( Glib::file_test(filename, Glib::FILE_TEST_IS_DIR) ) {
|
||||||
|
// this is a directory; use load_dir() to set us up the bomb.
|
||||||
|
load_dir(filename);
|
||||||
|
} else if (is_image(filename)) {
|
||||||
|
// this is a file.
|
||||||
|
add_file(filename);
|
||||||
|
}
|
||||||
|
// restart the idle function
|
||||||
|
//Glib::signal_idle().connect(sigc::mem_fun(this, &Thumbview::load_cache_images));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a new file or directory is created in a directory being
|
||||||
|
* monitored. Discards the event for non-directories, because
|
||||||
|
* file_changed_callback will be called for those.
|
||||||
|
*
|
||||||
|
* @param filename The name of the file modified or created.
|
||||||
|
*/
|
||||||
|
void Thumbview::file_created_callback(std::string filename) {
|
||||||
|
if ( Glib::file_test(filename, Glib::FILE_TEST_IS_DIR) ) {
|
||||||
|
file_changed_callback(filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
162
src/tint2conf/thumbview.h
Normal file
162
src/tint2conf/thumbview.h
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is from Nitrogen, an X11 background setter.
|
||||||
|
Copyright (C) 2006 Dave Foster & Javeed Shaikh
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <gtkmm.h>
|
||||||
|
|
||||||
|
#ifdef USE_INOTIFY
|
||||||
|
//#include "Inotify.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct TreePair {
|
||||||
|
Glib::ustring file;
|
||||||
|
Gtk::TreeModel::iterator iter;
|
||||||
|
Glib::RefPtr<Gdk::Pixbuf> thumb;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Thumbview;
|
||||||
|
|
||||||
|
class DelayLoadingStore : public Gtk::ListStore
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static Glib::RefPtr<DelayLoadingStore> create(const Gtk::TreeModelColumnRecord& columns)
|
||||||
|
{
|
||||||
|
return Glib::RefPtr<DelayLoadingStore>(new DelayLoadingStore(columns));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
DelayLoadingStore() : Gtk::ListStore() {}
|
||||||
|
DelayLoadingStore(const Gtk::TreeModelColumnRecord& columns) : Gtk::ListStore(columns) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void get_value_vfunc (const iterator& iter, int column, Glib::ValueBase& value) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void set_queue(GAsyncQueue *queue) { aqueue_loadthumbs = queue; }
|
||||||
|
void set_thumbview(Thumbview *view) { thumbview = view; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
GAsyncQueue *aqueue_loadthumbs;
|
||||||
|
Thumbview *thumbview;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Column record for the Thumbview store.
|
||||||
|
*/
|
||||||
|
class ThumbviewRecord : public Gtk::TreeModelColumnRecord
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ThumbviewRecord()
|
||||||
|
{
|
||||||
|
add(Thumbnail);
|
||||||
|
add(Description);
|
||||||
|
add(Filename);
|
||||||
|
add(Time);
|
||||||
|
add(LoadingThumb);
|
||||||
|
add(CurBGOnDisp);
|
||||||
|
}
|
||||||
|
|
||||||
|
Gtk::TreeModelColumn<Glib::ustring> Filename;
|
||||||
|
Gtk::TreeModelColumn<Glib::ustring> Description;
|
||||||
|
Gtk::TreeModelColumn< Glib::RefPtr<Gdk::Pixbuf> > Thumbnail;
|
||||||
|
Gtk::TreeModelColumn<time_t> Time;
|
||||||
|
Gtk::TreeModelColumn<bool> LoadingThumb;
|
||||||
|
Gtk::TreeModelColumn<Glib::ustring> CurBGOnDisp;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class Thumbview : public Gtk::ScrolledWindow {
|
||||||
|
public:
|
||||||
|
Thumbview ();
|
||||||
|
~Thumbview ();
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SORT_ALPHA,
|
||||||
|
SORT_RALPHA,
|
||||||
|
SORT_TIME,
|
||||||
|
SORT_RTIME
|
||||||
|
} SortMode;
|
||||||
|
|
||||||
|
void set_dir(std::string indir) { this->dir = indir; }
|
||||||
|
|
||||||
|
Glib::RefPtr<DelayLoadingStore> store;
|
||||||
|
Gtk::TreeView view;
|
||||||
|
ThumbviewRecord record;
|
||||||
|
|
||||||
|
// dispatcher
|
||||||
|
Glib::Dispatcher dispatch_thumb;
|
||||||
|
|
||||||
|
// thread/idle funcs
|
||||||
|
void load_cache_images();
|
||||||
|
void create_cache_images();
|
||||||
|
void load_dir(std::string dir = "");
|
||||||
|
|
||||||
|
void set_sort_mode (SortMode mode);
|
||||||
|
// search compare function
|
||||||
|
bool search_compare (const Glib::RefPtr<Gtk::TreeModel>& model, int column, const Glib::ustring& key, const Gtk::TreeModel::iterator& iter);
|
||||||
|
|
||||||
|
// loading image
|
||||||
|
Glib::RefPtr<Gdk::Pixbuf> loading_image;
|
||||||
|
|
||||||
|
// "cache" of config - maps displays to full filenames
|
||||||
|
std::map<Glib::ustring, Glib::ustring> map_setbgs;
|
||||||
|
void load_map_setbgs();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
#ifdef USE_INOTIFY
|
||||||
|
void file_deleted_callback(std::string filename);
|
||||||
|
void file_changed_callback(std::string filename);
|
||||||
|
void file_created_callback(std::string filename);
|
||||||
|
std::map<std::string, Inotify::Watch*> watches;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void add_file(std::string filename);
|
||||||
|
void handle_dispatch_thumb();
|
||||||
|
|
||||||
|
Gtk::TreeViewColumn *col_thumb;
|
||||||
|
Gtk::TreeViewColumn *col_desc;
|
||||||
|
|
||||||
|
Gtk::CellRendererPixbuf rend_img;
|
||||||
|
Gtk::CellRendererText rend;
|
||||||
|
|
||||||
|
// utility functions
|
||||||
|
bool is_image(std::string file);
|
||||||
|
Glib::ustring cache_file(Glib::ustring file);
|
||||||
|
void update_thumbnail(Glib::ustring file, Gtk::TreeModel::iterator iter, Glib::RefPtr<Gdk::Pixbuf> pb);
|
||||||
|
|
||||||
|
// base dir
|
||||||
|
// TODO: remove when we get a proper db
|
||||||
|
std::string dir;
|
||||||
|
|
||||||
|
// load thumbnail queue
|
||||||
|
GAsyncQueue* aqueue_loadthumbs;
|
||||||
|
GAsyncQueue* aqueue_createthumbs;
|
||||||
|
GAsyncQueue* aqueue_donethumbs;
|
||||||
|
|
||||||
|
};
|
Loading…
Reference in a new issue