f.gallery.cc (fotoxx-22.30) | : | f.gallery.cc (fotoxx-22.35) | ||
---|---|---|---|---|
skipping to change at line 27 | skipping to change at line 27 | |||
See the GNU General Public License for more details. | See the GNU General Public License for more details. | |||
******************************************************************************** * | ******************************************************************************** * | |||
Fotoxx image edit - folder navigation and thumbnail gallery functions | Fotoxx image edit - folder navigation and thumbnail gallery functions | |||
gallery create/update/search/paint an image gallery | gallery create/update/search/paint an image gallery | |||
navi:: | navi:: | |||
gallery_comp gallery sort compare function | gallery_comp gallery sort compare function | |||
filename_comp gallery sort file name compare function | ||||
gallery_paint paint thumbnail gallery, resizable thumbnails | gallery_paint paint thumbnail gallery, resizable thumbnails | |||
gallery_paintmeta same, metadata report from search function | gallery_paintmeta same, metadata report from search function | |||
gallery_paintmeta2 same, thumbnails with basic metadata | gallery_paintmeta2 same, thumbnails with basic metadata | |||
dir_filecount paint - get folder subdir and image file counts | dir_filecount paint - get folder subdir and image file counts | |||
draw_text paint - write text over thumbnail images | draw_text paint - write text over thumbnail images | |||
gallery_navibutts add folder navigation buttons | gallery_navibutts add folder navigation buttons | |||
menufuncx gallery menu: sort/zoom/scroll ... | menufuncx gallery menu: sort/zoom/scroll ... | |||
gallery_scroll scroll gallery in rows and pages | gallery_scroll scroll gallery in rows and pages | |||
navibutt_clicked open new gallery from clicked folder | navibutt_clicked open new gallery from clicked folder | |||
newtop open new gallery from clicked TOP entry | newtop open new gallery from clicked TOP entry | |||
newalbum open new gallery from clicked album entry | newalbum open new gallery from clicked album entry | |||
gallery_sort choose gallery sort order and sort gallery | ||||
mouse_event process gallery thumbnail clicks | mouse_event process gallery thumbnail clicks | |||
gallery_dragfile process thumbnail dragged | gallery_dragfile process thumbnail dragged | |||
gallery_dropfile process thumbnail dropped (add new file, arrange a lbum) | gallery_dropfile process thumbnail dropped (add new file, arrange a lbum) | |||
KBaction process gallery KB actions: zoom, page, top, end | KBaction process gallery KB actions: zoom, page, top, end | |||
gallery_memory save/recall gallery sort and position | gallery_memory save/recall gallery sort and position | |||
set_gwin_title update the gallery window title bar | set_gwin_title update the gallery window title bar | |||
prev_next_file get previous/next file from curr_file in current g allery | prev_next_file get previous/next file from curr_file in current g allery | |||
prev_next_gallery get gallery's previous or next gallery | prev_next_gallery get gallery's previous or next gallery | |||
file_position get gallery file position | file_position get gallery file position | |||
m_thumbview gallery thumbnail view | ||||
m_metaview gallery metadata view | ||||
m_recentfiles show gallery of recently viewed files | ||||
add_recent_file add an image file to the list of recent files | ||||
m_newfiles show gallery of newest image files | ||||
image_file_type determine file type (folder, image, RAW, thumbnail , other) | image_file_type determine file type (folder, image, RAW, thumbnail , other) | |||
thumb2imagefile get corresponding image file for given thumbnail f ile | thumb2imagefile get corresponding image file for given thumbnail f ile | |||
image2thumbfile get corresponding thumbnail file for given image f ile | image2thumbfile get corresponding thumbnail file for given image f ile | |||
thumbfile_OK check if thumbnail file missing or stale | thumbfile_OK check if thumbnail file missing or stale | |||
get_folder_pixbuf get 'folder' pixbuf image | get_folder_pixbuf get 'folder' pixbuf image | |||
get_broken_pixbuf get 'broken file' pixbuf image | get_broken_pixbuf get 'broken file' pixbuf image | |||
update_thumbfile refresh thumbnail file if missing or stale | update_thumbfile refresh thumbnail file if missing or stale | |||
thumbfile_set_mod_time set thumbnail file mod time from image file | thumbfile_set_mod_time set thumbnail file mod time from image file | |||
delete_thumbfile delete thumbnail disk file | delete_thumbfile delete thumbnail disk file | |||
init_cache_thumb initialize thumbnail cache | ||||
get_cache_thumb get thumbnail from cache, create and add if missin g | get_cache_thumb get thumbnail from cache, create and add if missin g | |||
check_cache_thumb test if a thumbnail is in the cache already | check_cache_thumb test if a thumbnail is in the cache already | |||
remove_cache_thumb remove thumbnail from cache | replace_cache_thumb replace cache thumb from updated thumbnail file | |||
preload_thumbs preload thumbnails beyond gallery into thumbnail c ache | preload_thumbs preload thumbnails beyond gallery into thumbnail c ache | |||
m_thumbframe set the video frame for a video thumbnail | ||||
gallery_popimage popup a larger image from a clicked thumbnail | gallery_popimage popup a larger image from a clicked thumbnail | |||
gallery_select1 single gallery file selection function and dialog | gallery_select1 single gallery file selection function and dialog | |||
gallery_select multiple gallery file selection function and dialo g | gallery_select multiple gallery file selection function and dialo g | |||
m_select_files select files for album and batch functions | ||||
m_thumbview gallery thumbnail view | ||||
m_metaview gallery metadata view | ||||
m_recentfiles show gallery of recently viewed files | ||||
add_recent_file add an image file to the list of recent files | ||||
m_newfiles show gallery of newest image files | ||||
m_gallery_sort sort gallery by file, date, size ... | ||||
m_gallery_screen screen gallery for newest, oldest, text match | ||||
m_source_folder set gallery to folder of current image file | ||||
m_allfolders folder tree view, expand/contract, click for galle | ||||
ry view | ||||
m_select_files select files for album and batch functions | ||||
m_rename_folder rename the current folder | m_rename_folder rename the current folder | |||
m_add_subfolder add subfolder to current gallery | m_add_subfolder add subfolder to current gallery | |||
m_source_folder set gallery to folder of current image file | ||||
m_alldirs folder tree view, expand/contract, click for galle | ||||
ry view | ||||
m_show_hidden dummy menu for KB shortcut "Show Hidden Files" | ||||
m_current_album dummy menu for KB shortcut "Current Album" | ||||
m_bookmarks goto selected bookmark, edit bookmarks | m_bookmarks goto selected bookmark, edit bookmarks | |||
m_edit_bookmarks edit bookmarks | m_edit_bookmarks edit bookmarks | |||
m_thumbframe set the video frame for a video thumbnail | ||||
m_show_hidden dummy menu for KB shortcut "Show Hidden Files" | ||||
m_current_album dummy menu for KB shortcut "Current Album" | ||||
******************************************************************************** */ | ******************************************************************************** */ | |||
#define EX extern // disable extern declarations | #define EX extern // disable extern declarations | |||
#include "fotoxx.h" // (variables in fotoxx.h are refs) | #include "fotoxx.h" // (variables in fotoxx.h are refs) | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
/*** gallery index in fotoxx.h | /*** gallery index in fotoxx.h | |||
typedef struct { current gallery file list in memory | typedef struct { current gallery file list in memory | |||
char *file; /folder.../filename | char *file; /folder.../filename | |||
skipping to change at line 149 | skipping to change at line 151 | |||
int genthumbs = 0; // count newly generated thumbnails | int genthumbs = 0; // count newly generated thumbnails | |||
int scrollposn = 0; // scroll position | int scrollposn = 0; // scroll position | |||
int maxscroll; // max. scroll position | int maxscroll; // max. scroll position | |||
char *drag_file = 0; // selected thumbnail (file) | char *drag_file = 0; // selected thumbnail (file) | |||
int drag_posn = -1; // drag from position | int drag_posn = -1; // drag from position | |||
int gallery_scrollgoal = -1; // gallery scroll goal position | int gallery_scrollgoal = -1; // gallery scroll goal position | |||
int gallery_scrollspeed = 0; // gallery scroll speed pixels/second | int gallery_scrollspeed = 0; // gallery scroll speed pixels/second | |||
// private functions | // private functions | |||
int gallery_comp(cchar *rec1, cchar *rec2); // gallery record compare for sort options | int gallery_comp(cchar *rec1, cchar *rec2); // gallery record compare for sort options | |||
int filenamecomp(char *file1, char *file2); // special file name compare function | int filename_comp(char *file1, char *file2); // special file name compare function | |||
int gallery_paint(GtkWidget *, cairo_t *); // gallery window paint, resizable thumbnails | int gallery_paint(GtkWidget *, cairo_t *); // gallery window paint, resizable thumbnails | |||
int gallery_paintmeta(GtkWidget *Gdrawin, cairo_t *cr); // same, metadata report from search func. | int gallery_paintmeta(GtkWidget *Gdrawin, cairo_t *cr); // same, metadata report from search func. | |||
int gallery_paintmeta2(GtkWidget *Gdrawin, cairo_t *cr); // same, thumbnails with basic metadata | int gallery_paintmeta2(GtkWidget *Gdrawin, cairo_t *cr); // same, thumbnails with basic metadata | |||
void dir_filecount(char *dirname, int &ndir, int &nfil); // get subdir and image file counts | void dir_filecount(char *dirname, int &ndir, int &nfil); // get subdir and image file counts | |||
void draw_text(cairo_t *cr, char *text, int x, int y, int ww); // draw text in gallery window | void draw_text(cairo_t *cr, char *text, int x, int y, int ww); // draw text in gallery window | |||
void gallery_navibutts(); // create navigation buttons in top panel | void gallery_navibutts(); // create navigation buttons in top panel | |||
void menufuncx(GtkWidget *, cchar *menu); // function for gallery window buttons | void menufuncx(GtkWidget *, cchar *menu); // function for gallery window buttons | |||
void gallery_scroll(int position, int speed); // start gallery slow scroll to position | void gallery_scroll(int position, int speed); // start gallery slow scroll to position | |||
int gallery_scrollfunc(void *); // gallery scroll timer function | int gallery_scrollfunc(void *); // gallery scroll timer function | |||
void navibutt_clicked(GtkWidget *, int *level); // set gallery via click navigation button | void navibutt_clicked(GtkWidget *, int *level); // set gallery via click navigation button | |||
void newtop(GtkWidget *widget, GdkEventButton *event); // function for [TOP] button | void newtop(GtkWidget *widget, GdkEventButton *event); // function for [TOP] button | |||
void newtop_menu_event(GtkWidget *, cchar *); // [TOP] menu response function | void newtop_menu_event(GtkWidget *, cchar *); // [TOP] menu response function | |||
void newalbum(GtkWidget *widget, GdkEventButton *event); // function for [Album] button | void newalbum(GtkWidget *widget, GdkEventButton *event); // function for [Album] button | |||
void newalbum_menu_event(GtkWidget *, cchar *); // [Album] menu response function | void newalbum_menu_event(GtkWidget *, cchar *); // [Album] menu response function | |||
void gallery_sort(); // choose sort order and sort gallery | ||||
int mouse_event(GtkWidget *widget, GdkEvent *event, void *); // gallery window mouse event function | int mouse_event(GtkWidget *widget, GdkEvent *event, void *); // gallery window mouse event function | |||
char * gallery_dragfile(); // start drag-drop, set the file | char * gallery_dragfile(); // start drag-drop, set the file | |||
void gallery_dropfile(int mousex, int mousey, char *file); // accept drag-drop file at position | void gallery_dropfile(int mousex, int mousey, char *file); // accept drag-drop file at position | |||
int KBpress(GtkWidget *, GdkEventKey *, void *); // gallery window key press event | int KBpress(GtkWidget *, GdkEventKey *, void *); // gallery window key press event | |||
} | } | |||
using namespace zfuncs; | using namespace zfuncs; | |||
using namespace navi; | using namespace navi; | |||
/******************************************************************************* * | /******************************************************************************* * | |||
skipping to change at line 242 | skipping to change at line 243 | |||
if (ftf) { | if (ftf) { | |||
ftf = 0; | ftf = 0; | |||
cc = maxgallery * sizeof(Gindex_t); | cc = maxgallery * sizeof(Gindex_t); | |||
Gindex = (Gindex_t *) zmalloc(cc,"gallery"); // allocate gallery index | Gindex = (Gindex_t *) zmalloc(cc,"gallery"); // allocate gallery index | |||
Gfiles = Gfolders = Gimages = 0; // no files yet | Gfiles = Gfolders = Gimages = 0; // no files yet | |||
} | } | |||
if (strmatchN(action,"init",4)) // init or initF | if (strmatchN(action,"init",4)) // init or initF | |||
{ | { | |||
if (! filez && gallerytype == GDIR) filez = galleryname; // null file: refresh current gallery | if (! filez && gallerytype == FOLDER) filez = galleryname; // null file: refresh current gallery | |||
if (! filez) goto return0; | if (! filez) goto return0; | |||
zstrcopy(galleryname,filez,"gallery"); // new gallery name | zstrcopy(galleryname,filez,"gallery"); // new gallery name | |||
NF = Gfiles; // current file count | NF = Gfiles; // current file count | |||
Gfiles = Gfolders = Gimages = 0; // no new files yet | Gfiles = Gfolders = Gimages = 0; // no new files yet | |||
for (ii = 0; ii < NF; ii++) { // free prior gallery index | for (ii = 0; ii < NF; ii++) { // free prior gallery index | |||
if (Gindex[ii].file) zfree(Gindex[ii].file); // memory leak 22.30 | if (Gindex[ii].file) zfree(Gindex[ii].file); // memory leak 22.30 | |||
if (Gindex[ii].mdata1) zfree(Gindex[ii].mdata1); | if (Gindex[ii].mdata1) zfree(Gindex[ii].mdata1); | |||
skipping to change at line 266 | skipping to change at line 267 | |||
} | } | |||
if (strmatch(action,"init")) // initz. from given file or folder | if (strmatch(action,"init")) // initz. from given file or folder | |||
{ | { | |||
if (! dirfile(galleryname)) { // bad folder? (may be member file) | if (! dirfile(galleryname)) { // bad folder? (may be member file) | |||
pp = (char *) strrchr(galleryname,'/'); // try parent folder | pp = (char *) strrchr(galleryname,'/'); // try parent folder | |||
if (pp) *pp = 0; | if (pp) *pp = 0; | |||
if (! dirfile(galleryname)) goto return0; // give up, empty file list | if (! dirfile(galleryname)) goto return0; // give up, empty file list | |||
} | } | |||
gallerytype = GDIR; // gallery type = folder | gallerytype = FOLDER; // gallery type = folder | |||
cc = strlen(galleryname) - 1; // remove trailing '/' | cc = strlen(galleryname) - 1; // remove trailing '/' | |||
if (cc > 1 && galleryname[cc] == '/') galleryname[cc] = 0; // but not if root folder '/' | if (cc > 1 && galleryname[cc] == '/') galleryname[cc] = 0; // but not if root folder '/' | |||
flags = 1 + 8; // images + folders, one level | flags = 1 + 8; // images + folders, one level | |||
if (Fshowhidden) flags += 4; // include hidden files | if (Fshowhidden) flags += 4; // include hidden files | |||
err = find_imagefiles(galleryname,flags,Flist,NF); // find all image files in folder | err = find_imagefiles(galleryname,flags,Flist,NF); // find all image files in folder | |||
if (err) { | if (err) { | |||
zmessageACK(Mwin,strerror(errno)); | zmessageACK(Mwin,strerror(errno)); | |||
skipping to change at line 389 | skipping to change at line 390 | |||
Gfiles -= kk; | Gfiles -= kk; | |||
Gimages -= kk; | Gimages -= kk; | |||
} | } | |||
gallerypainted = 0; | gallerypainted = 0; | |||
goto return0; | goto return0; | |||
} | } | |||
if (strmatch(action,"initF")) // gallery from given file list | if (strmatch(action,"initF")) // gallery from given file list | |||
{ | { | |||
if (gallerytype == TNONE || gallerytype == GDIR) // gallery type from caller: | if (gallerytype == TNONE || gallerytype == FOLDER) // gallery type from caller: | |||
zappcrash("gallery() initF gallerytype %d",gallerytype); // SEARCH META RECENT NEWEST ALBUM | zappcrash("gallery() initF gallerytype %d",gallerytype); // SEARCH META RECENT NEWEST ALBUM | |||
fid = fopen(galleryname,"r"); // open file | fid = fopen(galleryname,"r"); // open file | |||
if (! fid) goto return0; | if (! fid) goto return0; | |||
while (true) // read list of files | while (true) // read list of files | |||
{ | { | |||
file = fgets_trim(buff,XFCC-1,fid,1); | file = fgets_trim(buff,XFCC-1,fid,1); | |||
if (! file) break; | if (! file) break; | |||
skipping to change at line 574 | skipping to change at line 575 | |||
switch (gallerysort) { | switch (gallerysort) { | |||
case FNAME: { // file name | case FNAME: { // file name | |||
nn = strcasecmp(grec1->file,grec2->file); // ignore case | nn = strcasecmp(grec1->file,grec2->file); // ignore case | |||
if (nn) return nn; | if (nn) return nn; | |||
nn = strcmp(grec1->file,grec2->file); // if equal, use utf8 compare | nn = strcmp(grec1->file,grec2->file); // if equal, use utf8 compare | |||
return nn; | return nn; | |||
} | } | |||
case FNUMBER: { // file name/number 22.11 | case FNUMBER: { // file name/number 22.11 | |||
nn = filenamecomp(grec1->file,grec2->file); | nn = filename_comp(grec1->file,grec2->file); | |||
if (nn) return nn; | if (nn) return nn; | |||
nn = strcmp(grec1->file,grec2->file); // if equal, use utf8 compare | nn = strcmp(grec1->file,grec2->file); // if equal, use utf8 compare | |||
return nn; | return nn; | |||
} | } | |||
case FDATE: { // file mod date/time | case FDATE: { // file mod date/time | |||
nn = strcmp(grec1->fdate,grec2->fdate); | nn = strcmp(grec1->fdate,grec2->fdate); | |||
if (nn) return nn; | if (nn) return nn; | |||
goto tiebreak; | goto tiebreak; | |||
} | } | |||
skipping to change at line 658 | skipping to change at line 659 | |||
/**** | /**** | |||
compare function for sorting a list of file names with embedded numbers | compare function for sorting a list of file names with embedded numbers | |||
+ folder names are compared normally using strcmp() | + folder names are compared normally using strcmp() | |||
+ file base names are compared ignoring string case: 'a' = 'A' | + file base names are compared ignoring string case: 'a' = 'A' | |||
+ file base names with embedded numbers starting in the same position | + file base names with embedded numbers starting in the same position | |||
are compared arithmetically: '5' < '40' < '300' < '1000' | are compared arithmetically: '5' < '40' < '300' < '1000' | |||
****/ | ****/ | |||
int navi::filenamecomp(char *file1, char *file2) // 22.11 | int navi::filename_comp(char *file1, char *file2) // 22.11 | |||
{ | { | |||
char *pp1, *pp2; | char *pp1, *pp2; | |||
char ch1, ch2; | char ch1, ch2; | |||
int nn; | int nn; | |||
int64 nn1, nn2; | int64 nn1, nn2; | |||
pp1 = strrchr(file1,'/'); // get end of folders | pp1 = strrchr(file1,'/'); // get end of folders | |||
pp2 = strrchr(file2,'/'); | pp2 = strrchr(file2,'/'); | |||
if (pp1 && pp2) | if (pp1 && pp2) | |||
skipping to change at line 779 | skipping to change at line 780 | |||
} | } | |||
for (ii = 0; ii < thumbxx; ii++) // largest ... smallest thumb size | for (ii = 0; ii < thumbxx; ii++) // largest ... smallest thumb size | |||
if (thumbsize >= thumbx[ii]) break; | if (thumbsize >= thumbx[ii]) break; | |||
if (ii == thumbxx) ii = thumbxx-1; // (fix poss. bad parameter) | if (ii == thumbxx) ii = thumbxx-1; // (fix poss. bad parameter) | |||
thumbsize = thumbx[ii]; // thumbnail size | thumbsize = thumbx[ii]; // thumbnail size | |||
fontsize = appfontsize + fontx[ii]; // corresp. font size | fontsize = appfontsize + fontx[ii]; // corresp. font size | |||
if (! Findexvalid) textlines = 1; // file name only | if (! Findexvalid) textlines = 1; // file name only | |||
else textlines = 2; // file name + date + wwhh | else textlines = 2; // file name + date + wwhh | |||
if (gallerytype != GDIR) textlines++; // add folder name above file name | if (gallerytype != FOLDER) textlines++; // add folder name above file name | |||
texthh = textlines * 1.6 * fontsize + 4; // vertical space required | texthh = textlines * 1.6 * fontsize + 4; // vertical space required | |||
thumbW = thumbsize + 10; // thumbnail cell size | thumbW = thumbsize + 10; // thumbnail cell size | |||
thumbH = thumbsize + texthh + thumbsize/24 + 10; | thumbH = thumbsize + texthh + thumbsize/24 + 10; | |||
xwinW = gtk_widget_get_allocated_width(Gscroll); // drawing window size | xwinW = gtk_widget_get_allocated_width(Gscroll); // drawing window size | |||
xwinH = gtk_widget_get_allocated_height(Gscroll); | xwinH = gtk_widget_get_allocated_height(Gscroll); | |||
xrows = int(0.1 + 1.0 * xwinH / thumbH); // get thumbnail rows and cols that | xrows = int(0.1 + 1.0 * xwinH / thumbH); // get thumbnail rows and cols that | |||
xcols = int(0.1 + 1.0 * xwinW / thumbW); // (almost) fit in window | xcols = int(0.1 + 1.0 * xwinW / thumbW); // (almost) fit in window | |||
skipping to change at line 850 | skipping to change at line 851 | |||
fspec = Gindex[ii].file; // folder/file name | fspec = Gindex[ii].file; // folder/file name | |||
p0 = *fspec; // replace possible '!' with '/' | p0 = *fspec; // replace possible '!' with '/' | |||
*fspec = '/'; | *fspec = '/'; | |||
pp = strrchr(fspec,'/'); // get file name only | pp = strrchr(fspec,'/'); // get file name only | |||
if (pp) fname = pp + 1; | if (pp) fname = pp + 1; | |||
else fname = fspec; | else fname = fspec; | |||
strcpy(ffolder,"/"); | strcpy(ffolder,"/"); | |||
if (gallerytype != GDIR) { // files from mixed folders | if (gallerytype != FOLDER) { // files from mixed folders | |||
if (pp && pp > fspec) { | if (pp && pp > fspec) { | |||
for (ppd = pp-1; ppd >= fspec && *ppd != '/'; ppd--); // get last folder level | for (ppd = pp-1; ppd >= fspec && *ppd != '/'; ppd--); // get last folder level | |||
cc = pp - ppd + 1; // (include null to be added) | cc = pp - ppd + 1; // (include null to be added) | |||
if (cc > 60) cc = 60; | if (cc > 60) cc = 60; | |||
strncpy0(ffolder,ppd,cc); | strncpy0(ffolder,ppd,cc); | |||
} | } | |||
} | } | |||
thumx = col * thumbW + margin; // drawing area position | thumx = col * thumbW + margin; // drawing area position | |||
thumy = row * thumbH + margin; | thumy = row * thumbH + margin; | |||
skipping to change at line 917 | skipping to change at line 918 | |||
pdt[4] = pdt[7] = '-'; | pdt[4] = pdt[7] = '-'; | |||
if (thumbsize <= 256) pdt[10] = 0; // truncate date/time to date only | if (thumbsize <= 256) pdt[10] = 0; // truncate date/time to date only | |||
} | } | |||
ww = xxrec->ww; // width, height, file size | ww = xxrec->ww; // width, height, file size | |||
hh = xxrec->hh; | hh = xxrec->hh; | |||
fsize = xxrec->fsize; | fsize = xxrec->fsize; | |||
cc = 0; | cc = 0; | |||
if (gallerytype != GDIR) { // mixed folders (search results) | if (gallerytype != FOLDER) { // mixed folders (search results) | |||
snprintf(text,200,"%s\n",ffolder); // output folder name + \n | snprintf(text,200,"%s\n",ffolder); // output folder name + \n | |||
cc = strlen(text); | cc = strlen(text); | |||
} | } | |||
snprintf(text+cc,200-cc,"%s\n",fname); // output file name + \n | snprintf(text+cc,200-cc,"%s\n",fname); // output file name + \n | |||
cc = cc + strlen(fname) + 1; | cc = cc + strlen(fname) + 1; | |||
if (Findexvalid) { // valid index, metadata available | if (Findexvalid) { // valid index, metadata available | |||
snprintf(text+cc,200-cc,"%s",pdt); // output date [ time ] | snprintf(text+cc,200-cc,"%s",pdt); // output date [ time ] | |||
cc += strlen(pdt); | cc += strlen(pdt); | |||
skipping to change at line 1116 | skipping to change at line 1117 | |||
char fdate[20], pdate[20], *pp; | char fdate[20], pdate[20], *pp; | |||
char *rating, *tags, *title, *desc, *location, *country; | char *rating, *tags, *title, *desc, *location, *country; | |||
char wwhh[16], fsize[16]; | char wwhh[16], fsize[16]; | |||
char text[1000]; | char text[1000]; | |||
static int prows = 0; | static int prows = 0; | |||
thumbsize = 128; // thumbnail size | thumbsize = 128; // thumbnail size | |||
fontsize = appfontsize; | fontsize = appfontsize; | |||
textww = fontsize * 60; // text width limit for max. 60 chars. | textww = fontsize * 60; // text width limit for max. 60 chars. | |||
if (gallerytype != GDIR) textww = fontsize * 200; // more if full path is written | if (gallerytype != FOLDER) textww = fontsize * 200; // more if full path is written | |||
thumbW = thumbsize + 10 + textww; // thumbnail + text layout size | thumbW = thumbsize + 10 + textww; // thumbnail + text layout size | |||
thumbH = thumbsize + 20; | thumbH = thumbsize + 20; | |||
texthh = 6 * fontsize * 1.8 + 20; // space for 6 lines of metadata text | texthh = 6 * fontsize * 1.8 + 20; // space for 6 lines of metadata text | |||
if (texthh > thumbH) thumbH = texthh; | if (texthh > thumbH) thumbH = texthh; | |||
xwinW = gtk_widget_get_allocated_width(Gscroll); // drawing window size | xwinW = gtk_widget_get_allocated_width(Gscroll); // drawing window size | |||
xwinH = gtk_widget_get_allocated_height(Gscroll); | xwinH = gtk_widget_get_allocated_height(Gscroll); | |||
skipping to change at line 1184 | skipping to change at line 1185 | |||
for (col = 0; col < xcols; col++) // draw all columns in row | for (col = 0; col < xcols; col++) // draw all columns in row | |||
{ | { | |||
ii = row * xcols + col; // next file | ii = row * xcols + col; // next file | |||
if (ii >= Gfiles) goto endloops; // exit 2 nested loops | if (ii >= Gfiles) goto endloops; // exit 2 nested loops | |||
fspec = Gindex[ii].file; | fspec = Gindex[ii].file; | |||
p0 = *fspec; // replace possible ! with / | p0 = *fspec; // replace possible ! with / | |||
*fspec = '/'; | *fspec = '/'; | |||
fspec2 = fspec; | fspec2 = fspec; | |||
if (gallerytype == GDIR) { // folder gallery, write only | if (gallerytype == FOLDER) { // folder gallery, write only | |||
pp = strrchr(fspec,'/'); // base file names | pp = strrchr(fspec,'/'); // base file names | |||
if (pp) fspec2 = pp+1; | if (pp) fspec2 = pp+1; | |||
} | } | |||
thumx = col * thumbW + margin; // drawing area position | thumx = col * thumbW + margin; // drawing area position | |||
thumy = row * thumbH + margin; | thumy = row * thumbH + margin; | |||
pxbT = get_cache_thumb(fspec,0); // get thumbnail | pxbT = get_cache_thumb(fspec,0); // get thumbnail | |||
if (pxbT) { | if (pxbT) { | |||
gdk_cairo_set_source_pixbuf(cr,pxbT,thumx,thumy); // paint thumbnail | gdk_cairo_set_source_pixbuf(cr,pxbT,thumx,thumy); // paint thumbnail | |||
skipping to change at line 1416 | skipping to change at line 1417 | |||
if (gallerytype == RECENT) sprintf(labtext,"recent images"); // recent images | if (gallerytype == RECENT) sprintf(labtext,"recent images"); // recent images | |||
if (gallerytype == NEWEST) sprintf(labtext,"newest images"); // newest images | if (gallerytype == NEWEST) sprintf(labtext,"newest images"); // newest images | |||
if (gallerytype == ALBUM) { // album gallery | if (gallerytype == ALBUM) { // album gallery | |||
pp1 = strrchr(galleryname,'/'); | pp1 = strrchr(galleryname,'/'); | |||
if (pp1) pp1++; | if (pp1) pp1++; | |||
else pp1 = galleryname; | else pp1 = galleryname; | |||
snprintf(labtext,100,"album: %s",pp1); // album: album-name | snprintf(labtext,100,"album: %s",pp1); // album: album-name | |||
} | } | |||
if (gallerytype != GDIR) { // not a folder gallery | if (gallerytype != FOLDER) { // not a folder gallery | |||
gallerylabel = gtk_label_new(labtext); // show gallery label | gallerylabel = gtk_label_new(labtext); // show gallery label | |||
gtk_box_pack_start(GTK_BOX(Gpanel),gallerylabel,0,0,0); | gtk_box_pack_start(GTK_BOX(Gpanel),gallerylabel,0,0,0); | |||
gtk_widget_show_all(Gpanel); | gtk_widget_show_all(Gpanel); | |||
return; | return; | |||
} | } | |||
ii = 0; | ii = 0; | |||
pp1 = galleryname; | pp1 = galleryname; | |||
while (pp1 && *pp1) // construct new buttons | while (pp1 && *pp1) // construct new buttons | |||
skipping to change at line 1460 | skipping to change at line 1461 | |||
// - jump to new file or folder as requested | // - jump to new file or folder as requested | |||
void navi::menufuncx(GtkWidget *, cchar *menu) | void navi::menufuncx(GtkWidget *, cchar *menu) | |||
{ | { | |||
int ii, scroll1, scroll2; | int ii, scroll1, scroll2; | |||
if (FGWM != 'G') m_viewmode(0,"G"); | if (FGWM != 'G') m_viewmode(0,"G"); | |||
scrollposn = gtk_adjustment_get_value(Gadjust); // current scroll position | scrollposn = gtk_adjustment_get_value(Gadjust); // current scroll position | |||
if (strmatch(menu,"GoTo")) { | ||||
F1_help_topic = "bookmarks"; | ||||
m_bookmarks(0,0); | ||||
return; | ||||
} | ||||
if (strmatch(menu,"Sort")) { | ||||
// choose sort order and sort gallery | ||||
F1_help_topic = "sort gallery"; | ||||
gallery_sort(); | ||||
return; | ||||
} | ||||
if (strmatch(menu,"Zoom+")) // next bigger thumbnail size | if (strmatch(menu,"Zoom+")) // next bigger thumbnail size | |||
{ | { | |||
F1_help_topic = "zoom"; | F1_help_topic = "zoom"; | |||
if (Fthumbview != 1) return; // not resizable thumb view | if (Fthumbview != 1) return; // not resizable thumb view | |||
for (ii = 0; ii < thumbxx; ii++) // set next greater thumbnail size | for (ii = 0; ii < thumbxx; ii++) // set next greater thumbnail size | |||
if (thumbsize == thumbx[ii]) break; | if (thumbsize == thumbx[ii]) break; | |||
if (ii == 0) return; // already maximum, no change | if (ii == 0) return; // already maximum, no change | |||
thumbsize = thumbx[ii-1]; | thumbsize = thumbx[ii-1]; | |||
galleryposn = scrollposn / thumbH * xcols; // keep top row position | galleryposn = scrollposn / thumbH * xcols; // keep top row position | |||
gallery(0,"paint",-1); // paint gallery | gallery(0,"paint",-1); // paint gallery | |||
skipping to change at line 1530 | skipping to change at line 1519 | |||
} | } | |||
if (strmatch(menu,"Page Down")) { // scroll 1 page down | if (strmatch(menu,"Page Down")) { // scroll 1 page down | |||
scroll1 = scrollposn / thumbH * thumbH; | scroll1 = scrollposn / thumbH * thumbH; | |||
scroll2 = scroll1 + thumbH * xrows; | scroll2 = scroll1 + thumbH * xrows; | |||
if (scroll2 > maxscroll) scroll2 = maxscroll; | if (scroll2 > maxscroll) scroll2 = maxscroll; | |||
gallery_scroll(scroll2,1600); | gallery_scroll(scroll2,1600); | |||
return; | return; | |||
} | } | |||
if (strmatch(menu,"First")) { // jump to top | if (strmatch(menu,"Home")) { // jump to top | |||
gallery_scroll(-1,0); // stop scrolling | gallery_scroll(-1,0); // stop scrolling | |||
scrollposn = 0; | scrollposn = 0; | |||
galleryposn = scrollposn / thumbH * xcols; | galleryposn = scrollposn / thumbH * xcols; | |||
gallery(0,"paint",-1); | gallery(0,"paint",-1); | |||
return; | return; | |||
} | } | |||
if (strmatch(menu,"Last")) { // jump to bottom | if (strmatch(menu,"End")) { // jump to bottom | |||
gallery_scroll(-1,0); // stop scrolling | gallery_scroll(-1,0); // stop scrolling | |||
scrollposn = maxscroll; | scrollposn = maxscroll; | |||
galleryposn = scrollposn / thumbH * xcols; | galleryposn = scrollposn / thumbH * xcols; | |||
gallery(0,"paint",-1); | gallery(0,"paint",-1); | |||
return; | return; | |||
} | } | |||
Plog(1,"unknown gallery function: %s \n",menu); | Plog(0,"unknown gallery function: %s \n",menu); | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// private function | // private function | |||
// scroll gallery page up or down to goal scroll position | // scroll gallery page up or down to goal scroll position | |||
// position: N goal scroll position, 0 to maxscroll | // position: N goal scroll position, 0 to maxscroll | |||
// -1 stop scrolling immediately | // -1 stop scrolling immediately | |||
// speed: N scroll N pixels/second | // speed: N scroll N pixels/second | |||
skipping to change at line 1686 | skipping to change at line 1675 | |||
void navi::newtop_menu_event(GtkWidget *, cchar *menu) // menu event function | void navi::newtop_menu_event(GtkWidget *, cchar *menu) // menu event function | |||
{ | { | |||
char folder[200]; | char folder[200]; | |||
if (! menu) return; | if (! menu) return; | |||
strncpy0(folder,menu,200); | strncpy0(folder,menu,200); | |||
if (strmatch(menu,"ALL")) { | if (strmatch(menu,"ALL")) { | |||
m_alldirs(0,0); | m_allfolders(0,0); | |||
return; | return; | |||
} | } | |||
if (strmatch(menu,"recent images")) { | if (strmatch(menu,"recent images")) { | |||
m_recentfiles(0,0); | m_recentfiles(0,0); | |||
return; | return; | |||
} | } | |||
if (strmatch(menu,"newest images")) { | if (strmatch(menu,"newest images")) { | |||
m_newfiles(0,0); | m_newfiles(0,0); | |||
skipping to change at line 1790 | skipping to change at line 1779 | |||
} | } | |||
snprintf(albumfile,200,"%s/%s",albums_folder,menu); // show the album gallery | snprintf(albumfile,200,"%s/%s",albums_folder,menu); // show the album gallery | |||
album_show(albumfile); | album_show(albumfile); | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// private function | // private function | |||
// dialog to choose gallery sort order and sort the gallery | ||||
void navi::gallery_sort() | ||||
{ | ||||
zdialog *zd; | ||||
int zstat, nn; | ||||
char albumfile[200], *pp, *pp2; | ||||
cchar *resetmess = " Reset all galleries\n to file name ascending"; | ||||
/*** | ||||
________________________________ | ||||
| Gallery Sort | | ||||
| | | ||||
| (o) File Name | | ||||
| (o) File Name/Number | | ||||
| (o) File Mod Date/Time | | ||||
| (o) Photo Date/Time (EXIF) | | ||||
| (o) File Size (bytes) | | ||||
| (o) Image Size (pixels) | | ||||
| (o) Metadata from Search | | ||||
// 22.20 | ||||
| (o) ascending (o) descending | | ||||
| | | ||||
| [x] reset all galleries | | ||||
| to file name ascending | | ||||
| | | ||||
| [Apply] | | ||||
|________________________________| | ||||
***/ | ||||
zd = zdialog_new("Gallery Sort",Mwin,"Apply",null); | ||||
// user dialog | ||||
zdialog_add_widget(zd,"hbox","hb1","dialog"); | ||||
zdialog_add_widget(zd,"label","space","hb1",0,"space=2"); | ||||
zdialog_add_widget(zd,"vbox","vb1","hb1"); | ||||
zdialog_add_widget(zd,"radio","filename","vb1","File Name"); | ||||
zdialog_add_widget(zd,"radio","filenumber","vb1","File Name/Number"); | ||||
zdialog_add_widget(zd,"radio","filedate","vb1","File Mod Date/Time"); | ||||
zdialog_add_widget(zd,"radio","photodate","vb1","Photo Date/Time (EXIF)"); | ||||
zdialog_add_widget(zd,"radio","filesize","vb1","File Size (bytes)"); | ||||
zdialog_add_widget(zd,"radio","pixelsize","vb1","Image Size (pixels)"); | ||||
zdialog_add_widget(zd,"radio","metadata","vb1","Metadata from Search Function | ||||
"); | ||||
zdialog_add_widget(zd,"hbox","hb2","dialog",0,"space=5"); | ||||
zdialog_add_widget(zd,"radio","ascending","hb2","ascending","space=4"); | ||||
zdialog_add_widget(zd,"radio","descending","hb2","descending","space=2"); | ||||
zdialog_add_widget(zd,"hbox","hbreset","dialog",0,"space=5"); | ||||
zdialog_add_widget(zd,"check","reset","hbreset",resetmess,"space=4"); | ||||
zdialog_add_ttip(zd,"metadata","metadata from Search Function, metadata repor | ||||
t"); | ||||
zdialog_stuff(zd,"filename",0); | ||||
// all buttons off | ||||
zdialog_stuff(zd,"filenumber",0); | ||||
zdialog_stuff(zd,"filedate",0); | ||||
// GTK radio buttons not reliable | ||||
zdialog_stuff(zd,"photodate",0); | ||||
// (vbox works, hbox does not) | ||||
zdialog_stuff(zd,"filesize",0); | ||||
zdialog_stuff(zd,"pixelsize",0); | ||||
zdialog_stuff(zd,"metadata",0); | ||||
zdialog_stuff(zd,"metadata",0); | ||||
zdialog_stuff(zd,"descending",0); | ||||
zdialog_stuff(zd,"reset",0); | ||||
if (gallerysort == FNAME || gallerysort == SNONE) | ||||
zdialog_stuff(zd,"filename",1); | ||||
if (gallerysort == FNUMBER) | ||||
// 22.11 | ||||
zdialog_stuff(zd,"filenumber",1); | ||||
if (gallerysort == FDATE) | ||||
zdialog_stuff(zd,"filedate",1); | ||||
if (gallerysort == PDATE) | ||||
zdialog_stuff(zd,"photodate",1); | ||||
if (gallerysort == FSIZE) | ||||
zdialog_stuff(zd,"filesize",1); | ||||
if (gallerysort == PSIZE) | ||||
zdialog_stuff(zd,"pixelsize",1); | ||||
if (gallerysort == MDATA) | ||||
zdialog_stuff(zd,"metadata",1); | ||||
if (galleryseq == ASCEND || galleryseq == QNONE) | ||||
zdialog_stuff(zd,"ascending",1); | ||||
if (galleryseq == DESCEND) | ||||
zdialog_stuff(zd,"descending",1); | ||||
zdialog_set_modal(zd); | ||||
zdialog_run(zd,0,"mouse"); | ||||
// run dialog, wait for completion | ||||
zstat = zdialog_wait(zd); | ||||
if (zstat != 1) { | ||||
zdialog_free(zd); | ||||
return; | ||||
} | ||||
zdialog_fetch(zd,"filename",nn); | ||||
// get user sort type | ||||
if (nn) gallerysort = FNAME; | ||||
zdialog_fetch(zd,"filenumber",nn); | ||||
if (nn) gallerysort = FNUMBER; | ||||
zdialog_fetch(zd,"filedate",nn); | ||||
if (nn) gallerysort = FDATE; | ||||
zdialog_fetch(zd,"photodate",nn); | ||||
if (nn) gallerysort = PDATE; | ||||
zdialog_fetch(zd,"filesize",nn); | ||||
if (nn) gallerysort = FSIZE; | ||||
zdialog_fetch(zd,"pixelsize",nn); | ||||
if (nn) gallerysort = PSIZE; | ||||
zdialog_fetch(zd,"metadata",nn); | ||||
if (nn) gallerysort = MDATA; | ||||
zdialog_fetch(zd,"ascending",nn); | ||||
// get ascending/descending | ||||
if (nn) galleryseq = ASCEND; | ||||
else galleryseq = DESCEND; | ||||
zdialog_fetch(zd,"reset",nn); | ||||
// reset all gallery sort memory | ||||
if (nn) { | ||||
// (revert to file name ascending) | ||||
gallery_memory("reset"); | ||||
gallerysort = FNAME; | ||||
galleryseq = ASCEND; | ||||
} | ||||
zdialog_free(zd); | ||||
gallery(0,"sort",-1); | ||||
// sort the gallery | ||||
gallery(0,"paint",0); | ||||
// paint, position = 0 | ||||
if (gallerytype == ALBUM) | ||||
// an album was sorted | ||||
{ | ||||
pp = strrchr(galleryname,'/'); | ||||
// get album name | ||||
if (pp) pp++; | ||||
else pp = galleryname; | ||||
pp2 = strstr(pp,"-sorted"); | ||||
// append "-sorted" | ||||
if (pp2) *pp2 = 0; | ||||
// avoid "-sorted-sorted" | ||||
snprintf(albumfile,200,"%s/%s-sorted",albums_folder,pp); | ||||
album_create_from_gallery(albumfile); | ||||
// new album, oldname-sorted | ||||
album_show(albumfile); | ||||
} | ||||
return; | ||||
} | ||||
/******************************************************************************* | ||||
*/ | ||||
// private function | ||||
// mouse event function for gallery window - get selected thumbnail and file | // mouse event function for gallery window - get selected thumbnail and file | |||
// user function receives clicked file, which is subject for zfree() | // user function receives clicked file, which is subject for zfree() | |||
int navi::mouse_event(GtkWidget *widget, GdkEvent *event, void *) | int navi::mouse_event(GtkWidget *widget, GdkEvent *event, void *) | |||
{ | { | |||
GdkEventButton *eventB; | GdkEventButton *eventB; | |||
PIXBUF *pxbT; | PIXBUF *pxbT; | |||
int evtype, mousex, mousey, mousebutt; | int evtype, mousex, mousey, mousebutt; | |||
int row, col, nrows, tww, thh, marg; | int row, col, nrows, tww, thh, marg; | |||
int Nth, poswidth, posheight, err, ftype; | int Nth, poswidth, posheight, err, ftype; | |||
skipping to change at line 2112 | skipping to change at line 1955 | |||
void navi::gallery_dropfile(int mousex, int mousey, char *file) | void navi::gallery_dropfile(int mousex, int mousey, char *file) | |||
{ | { | |||
int err, top, mpos, speed; | int err, top, mpos, speed; | |||
int row, col, nrows, Nth, cc; | int row, col, nrows, Nth, cc; | |||
int poswidth, from_posn = -1; | int poswidth, from_posn = -1; | |||
char dragfile[200], buff[200]; | char dragfile[200], buff[200]; | |||
char *pp1, *pp2, *from_gallery = 0, *newfile; | char *pp1, *pp2, *from_gallery = 0, *newfile; | |||
FILE *fid; | FILE *fid; | |||
if (gallerytype != GDIR && gallerytype != ALBUM) return; // reject others (search, recent ...) | if (gallerytype != FOLDER && gallerytype != ALBUM) return; // reject others (search, recent ...) | |||
if (! file) // drag motion underway | if (! file) // drag motion underway | |||
{ | { | |||
if (! mousex) { // drag leave event | if (! mousex) { // drag leave event | |||
gallery_scroll(-1,0); // stop scroll | gallery_scroll(-1,0); // stop scroll | |||
return; | return; | |||
} | } | |||
top = gtk_adjustment_get_value(Gadjust); // mouse vertical posn in window | top = gtk_adjustment_get_value(Gadjust); // mouse vertical posn in window | |||
mpos = 100 * (mousey - top) / xwinH; // 0 - 100 | mpos = 100 * (mousey - top) / xwinH; // 0 - 100 | |||
skipping to change at line 2144 | skipping to change at line 1987 | |||
} | } | |||
if (mpos >= 15 && mpos <= 85) // stop scrolling in mid-window range | if (mpos >= 15 && mpos <= 85) // stop scrolling in mid-window range | |||
gallery_scroll(-1,0); | gallery_scroll(-1,0); | |||
return; | return; | |||
} | } | |||
gallery_scroll(-1,0); // stop scrolling | gallery_scroll(-1,0); // stop scrolling | |||
if (gallerytype == GDIR) // folder gallery, add new file | if (gallerytype == FOLDER) // folder gallery, add new file | |||
{ | { | |||
err = cp_copy(file,galleryname); | err = cp_copy(file,galleryname); | |||
if (err) { | if (err) { | |||
zfree(file); | zfree(file); | |||
zmessageACK(Mwin,strerror(err)); | zmessageACK(Mwin,strerror(err)); | |||
return; | return; | |||
} | } | |||
pp1 = strrchr(file+2,'/'); // isolate filename.ext | pp1 = strrchr(file+2,'/'); // isolate filename.ext | |||
if (! pp1) return; | if (! pp1) return; | |||
skipping to change at line 2206 | skipping to change at line 2049 | |||
return; | return; | |||
} | } | |||
pp1 = fgets_trim(buff,200,fid); // source gallery name | pp1 = fgets_trim(buff,200,fid); // source gallery name | |||
if (pp1) from_gallery = zstrdup(pp1,"navi-dropfile"); | if (pp1) from_gallery = zstrdup(pp1,"navi-dropfile"); | |||
pp2 = fgets_trim(buff,200,fid); // source gallery position | pp2 = fgets_trim(buff,200,fid); // source gallery position | |||
if (pp2) from_posn = atoi(pp2); | if (pp2) from_posn = atoi(pp2); | |||
fclose(fid); | fclose(fid); | |||
if (! pp1 || from_posn < 0) { | if (! pp1 || from_posn < 0) { | |||
Plog(1,"drag_from data not available \n"); | Plog(0,"drag_from data not available \n"); | |||
return; | return; | |||
} | } | |||
if (from_gallery && strmatch(galleryname,from_gallery)) { // drag-drop in same gallery | if (from_gallery && strmatch(galleryname,from_gallery)) { // drag-drop in same gallery | |||
album_move_file(from_posn,Nth); // move file position in gallery | album_move_file(from_posn,Nth); // move file position in gallery | |||
} | } | |||
else album_add_file(file,Nth); // insert new file at position | else album_add_file(file,Nth); // insert new file at position | |||
zfree(file); | zfree(file); | |||
if (from_gallery) zfree(from_gallery); | if (from_gallery) zfree(from_gallery); | |||
skipping to change at line 2259 | skipping to change at line 2102 | |||
if (strmatch(action,"Up")) { | if (strmatch(action,"Up")) { | |||
menufuncx(0,"Row Up"); | menufuncx(0,"Row Up"); | |||
return 1; | return 1; | |||
} | } | |||
if (strmatch(action,"Down")) { | if (strmatch(action,"Down")) { | |||
menufuncx(0,"Row Down"); | menufuncx(0,"Row Down"); | |||
return 1; | return 1; | |||
} | } | |||
if (strmatch(action,"First")) { | if (strmatch(action,"Home")) { | |||
menufuncx(0,"First"); | menufuncx(0,"Home"); | |||
return 1; | return 1; | |||
} | } | |||
if (strmatch(action,"Last")) { | if (strmatch(action,"End")) { | |||
menufuncx(0,"Last"); | menufuncx(0,"End"); | |||
return 1; | return 1; | |||
} | } | |||
if (strmatch(action,"Page_Up")) { | if (strmatch(action,"Page_Up")) { | |||
menufuncx(0,"Page Up"); | menufuncx(0,"Page Up"); | |||
return 1; | return 1; | |||
} | } | |||
if (strmatch(action,"Page_Down")) { | if (strmatch(action,"Page_Down")) { | |||
menufuncx(0,"Page Down"); | menufuncx(0,"Page Down"); | |||
skipping to change at line 2292 | skipping to change at line 2135 | |||
rowf = curr_file_posn / xcols; | rowf = curr_file_posn / xcols; | |||
if (rowf < row1) menufuncx(0,"Row Up"); | if (rowf < row1) menufuncx(0,"Row Up"); | |||
return 1; | return 1; | |||
} | } | |||
if (strmatch(action,"Right")) { // right arrow - next image | if (strmatch(action,"Right")) { // right arrow - next image | |||
m_next(0,0); | m_next(0,0); | |||
row1 = scrollposn / thumbH; | row1 = scrollposn / thumbH; | |||
row2 = row1 + xwinH / thumbH - 1; | row2 = row1 + xwinH / thumbH - 1; | |||
rowf = curr_file_posn / xcols; | rowf = curr_file_posn / xcols; | |||
if (rowf == 0) menufuncx(0,"First"); | if (rowf == 0) menufuncx(0,"Home"); | |||
if (rowf > row2) menufuncx(0,"Row Down"); | if (rowf > row2) menufuncx(0,"Row Down"); | |||
return 1; | return 1; | |||
} | } | |||
if (strmatch(action,"Delete")) { // delete key - delete/trash dialog | if (strmatch(action,"Delete")) { // delete key - delete/trash dialog | |||
m_delete_trash(0,0); | m_delete_trash(0,0); | |||
return 1; | return 1; | |||
} | } | |||
if (strmatch(action,"Show Hidden")) { | if (strmatch(action,"Show Hidden")) { | |||
skipping to change at line 2315 | skipping to change at line 2158 | |||
gallery(0,"paint",-1); | gallery(0,"paint",-1); | |||
return 1; | return 1; | |||
} | } | |||
// check for menu function KB shortcut | // check for menu function KB shortcut | |||
for (ii = 0; ii < Nkbsf; ii++) | for (ii = 0; ii < Nkbsf; ii++) | |||
if (strmatchcase(action,kbsftab[ii].menu)) break; | if (strmatchcase(action,kbsftab[ii].menu)) break; | |||
if (ii == Nkbsf) { | if (ii == Nkbsf) { | |||
Plog(1,"shortcut not found: %s \n",action); | Plog(0,"shortcut not found: %s \n",action); | |||
return 1; | return 1; | |||
} | } | |||
kbsftab[ii].func(0,kbsftab[ii].arg); // call the menu function | kbsftab[ii].func(0,kbsftab[ii].arg); // call the menu function | |||
return 1; | return 1; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// save and restore gallery sort and top file position | // save and restore gallery sort and top file position | |||
skipping to change at line 2415 | skipping to change at line 2258 | |||
{ | { | |||
for (ii = 0; ii < NGmem; ii++) // search for gallery in memory | for (ii = 0; ii < NGmem; ii++) // search for gallery in memory | |||
if (strmatch(galleryname,gallerymem[ii].galleryname)) break; | if (strmatch(galleryname,gallerymem[ii].galleryname)) break; | |||
if (ii < NGmem) { | if (ii < NGmem) { | |||
galleryposn = gallerymem[ii].galleryposn; // found, restore top file posn and sort | galleryposn = gallerymem[ii].galleryposn; // found, restore top file posn and sort | |||
gallerysort = (GSORT) gallerymem[ii].gallerysort; | gallerysort = (GSORT) gallerymem[ii].gallerysort; | |||
galleryseq = (GSEQ) gallerymem[ii].galleryseq; | galleryseq = (GSEQ) gallerymem[ii].galleryseq; | |||
} | } | |||
else { // not found, use defaults | else { // not found, use defaults | |||
if (gallerytype == GDIR) { | if (gallerytype == FOLDER) { | |||
gallerysort = FNAME; | gallerysort = FNAME; | |||
galleryseq = ASCEND; | galleryseq = ASCEND; | |||
galleryposn = 0; | galleryposn = 0; | |||
} | } | |||
else { | else { | |||
gallerysort = SNONE; | gallerysort = SNONE; | |||
galleryseq = QNONE; | galleryseq = QNONE; | |||
galleryposn = 0; | galleryposn = 0; | |||
} | } | |||
} | } | |||
skipping to change at line 2480 | skipping to change at line 2323 | |||
// set the window title for the gallery window | // set the window title for the gallery window | |||
// window title = gallery name | // window title = gallery name | |||
void set_gwin_title() | void set_gwin_title() | |||
{ | { | |||
char *pp, title[200]; | char *pp, title[200]; | |||
if (FGWM != 'G') return; | if (FGWM != 'G') return; | |||
if (gallerytype == GDIR) | if (gallerytype == FOLDER) | |||
snprintf(title,200,"%s FOLDER %s %d folders %d files", // use Frelease | snprintf(title,200,"%s FOLDER %s %d folders %d files", // use Frelease | |||
Frelease,galleryname,Gfolders,Gimages); | Frelease,galleryname,Gfolders,Gimages); | |||
else if (gallerytype == SEARCH || gallerytype == META) | else if (gallerytype == SEARCH || gallerytype == META) | |||
snprintf(title,200,"%s SEARCH RESULTS %d files",Frelease,Gimages); | snprintf(title,200,"%s SEARCH RESULTS %d files",Frelease,Gimages); | |||
else if (gallerytype == ALBUM) { | else if (gallerytype == ALBUM) { | |||
pp = strrchr(galleryname,'/'); | pp = strrchr(galleryname,'/'); | |||
if (! pp) pp = galleryname; | if (! pp) pp = galleryname; | |||
else pp++; | else pp++; | |||
skipping to change at line 2593 | skipping to change at line 2436 | |||
// Find the previous or next gallery from the current gallery. | // Find the previous or next gallery from the current gallery. | |||
// (previous/next defined by subfolder sequence in parent folder) | // (previous/next defined by subfolder sequence in parent folder) | |||
// returned gallery is subject for zfree(). | // returned gallery is subject for zfree(). | |||
char * prev_next_gallery(int index) | char * prev_next_gallery(int index) | |||
{ | { | |||
int nn, Nth; | int nn, Nth; | |||
char *parentdir = 0, *olddir = 0, *newdir = 0, *file = 0; | char *parentdir = 0, *olddir = 0, *newdir = 0, *file = 0; | |||
if (gallerytype != GDIR) goto errret; // gallery not a physical folder | if (gallerytype != FOLDER) goto errret; // gallery not a physical folder | |||
olddir = zstrdup(galleryname,"prev-next-gallery"); // olddir = current gallery / folder | olddir = zstrdup(galleryname,"prev-next-gallery"); // olddir = current gallery / folder | |||
if (! olddir) goto errret; | if (! olddir) goto errret; | |||
nn = strlen(olddir) - 1; | nn = strlen(olddir) - 1; | |||
if (olddir[nn] == '/') olddir[nn] = 0; | if (olddir[nn] == '/') olddir[nn] = 0; | |||
parentdir = zstrdup(olddir,"prev-next-gallery"); // get parent folder | parentdir = zstrdup(olddir,"prev-next-gallery"); // get parent folder | |||
for (NOP; nn && parentdir[nn] != '/'; nn--) | for (NOP; nn && parentdir[nn] != '/'; nn--) | |||
if (! nn) goto errret; | if (! nn) goto errret; | |||
parentdir[nn] = 0; | parentdir[nn] = 0; | |||
gallery(parentdir,"init",0); // gallery = parent | gallery(parentdir,"init",0); // gallery = parent | |||
skipping to change at line 2659 | skipping to change at line 2502 | |||
for (ii = Gfolders; ii < Gfiles; ii++) | for (ii = Gfolders; ii < Gfiles; ii++) | |||
if (strmatch(file,Gindex[ii].file)) break; | if (strmatch(file,Gindex[ii].file)) break; | |||
if (ii < Gfiles) return ii; | if (ii < Gfiles) return ii; | |||
return -1; | return -1; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// gallery menu, resizable thumbnail view | ||||
void m_thumbview(GtkWidget *, cchar *menu) | ||||
{ | ||||
F1_help_topic = "thumb view"; | ||||
Plog(1,"m_thumbview \n"); | ||||
Fthumbview = 1; | ||||
if (thumbsize < 256) thumbsize = 256; | ||||
m_viewmode(0,"G"); | ||||
gallery(0,"paint",-1); | ||||
return; | ||||
} | ||||
// gallery menu, thumbnail with basic metadata view | ||||
void m_metaview(GtkWidget *, cchar *menu) | ||||
{ | ||||
F1_help_topic = "meta view"; | ||||
Plog(1,"m_metaview \n"); | ||||
Fthumbview = 2; | ||||
m_viewmode(0,"G"); | ||||
gallery(0,"paint",-1); | ||||
return; | ||||
} | ||||
/******************************************************************************* | ||||
*/ | ||||
// Show recently viewed image files. | ||||
void m_recentfiles(GtkWidget *, cchar *menu) | ||||
{ | ||||
F1_help_topic = "recent"; | ||||
Plog(1,"m_recentfiles \n"); | ||||
if (Findexvalid == 0) { | ||||
zmessageACK(Mwin,"image index disabled"); | ||||
// no image index | ||||
return; | ||||
} | ||||
navi::gallerytype = RECENT; | ||||
// gallery type = recent files | ||||
gallery(recentfiles_file,"initF",0); | ||||
// generate gallery of recent files | ||||
gallery(0,"paint",0); | ||||
m_viewmode(0,"G"); | ||||
return; | ||||
} | ||||
// add a new file to the list of recent files, first position | ||||
// ( < 1 millisec. typical at 1000 file limit) | ||||
void add_recent_file(cchar *newfile) | ||||
{ | ||||
zlist_t *ZLfiles; | ||||
int ii; | ||||
ZLfiles = zlist_from_file(recentfiles_file); | ||||
if (! ZLfiles) ZLfiles = zlist_new(0); | ||||
ii = zlist_find(ZLfiles,newfile,0); | ||||
// if file already present, remove it | ||||
if (ii >= 0) zlist_remove(ZLfiles,ii); | ||||
zlist_insert(ZLfiles,newfile,0); | ||||
// insert in 1st position | ||||
zlist_clear(ZLfiles,200); | ||||
// truncate to 200 files | ||||
zlist_to_file(ZLfiles,recentfiles_file); | ||||
zlist_delete(ZLfiles); | ||||
return; | ||||
} | ||||
/******************************************************************************* | ||||
*/ | ||||
// Report the newest or most recently modified image files, | ||||
// based on EXIF photo date or file mod date. | ||||
namespace newfiles | ||||
{ | ||||
struct newfile_t { | ||||
// new file record | ||||
char *file; | ||||
// image file | ||||
char fdate[16]; | ||||
// date-time, yyyymmddhhmmss | ||||
}; | ||||
} | ||||
// menu function | ||||
void m_newfiles(GtkWidget *, cchar *menu) | ||||
{ | ||||
using namespace newfiles; | ||||
int newfile_comp(cchar *rec1, cchar *rec2); | ||||
cchar *mess = "Use EXIF photo date or \n file modification date?"; | ||||
int ii, jj, cc, sort, Nxrec; | ||||
xxrec_t *xxrec; | ||||
FILE *fid; | ||||
newfile_t *newfile = 0; | ||||
F1_help_topic = "newest"; | ||||
Plog(1,"m_newfiles \n"); | ||||
if (Findexvalid == 0) { | ||||
zmessageACK(Mwin,"image index disabled"); | ||||
// no image index | ||||
return; | ||||
} | ||||
if (Nxxrec == 0) { | ||||
zmessageACK(Mwin,"no files found"); | ||||
return; | ||||
} | ||||
cc = Nxxrec * sizeof(newfile_t); | ||||
// allocate memory | ||||
newfile = (newfile_t *) zmalloc(cc,"newfiles"); | ||||
if (menu && strmatch(menu,"EXIF")) sort = 1; | ||||
else if (menu && strmatch(menu,"file")) sort = 2; | ||||
else sort = zdialog_choose(Mwin,"mouse",mess,"EXIF","File",null); | ||||
if (sort < 1) return; | ||||
// cancel | ||||
for (ii = jj = 0; ii < Nxxrec; ii++) | ||||
// loop image index table | ||||
{ | ||||
xxrec = xxrec_tab[ii]; | ||||
newfile[jj].file = xxrec->file; | ||||
// image file | ||||
if (sort == 1) { | ||||
if (strmatch(xxrec->pdate,"null")) continue; | ||||
// use EXIF photo date | ||||
strncpy0(newfile[jj].fdate,xxrec->pdate,15); | ||||
// ignore images without photo date | ||||
} | ||||
else strncpy0(newfile[jj].fdate,xxrec->fdate,15); | ||||
// else use file mod date | ||||
jj++; | ||||
// selected files | ||||
} | ||||
Nxrec = jj; | ||||
// final count | ||||
if (Nxrec > 1) | ||||
// sort index recs. by file date | ||||
HeapSort((char *) newfile, sizeof(newfile_t), Nxrec, newfile_comp); | ||||
fid = fopen(searchresults_file,"w"); | ||||
// open output file | ||||
if (! fid) { | ||||
zmessageACK(Mwin,"file error: %s",strerror(errno)); | ||||
goto cleanup; | ||||
} | ||||
for (ii = 0; ii < 500 && ii < Nxrec; ii++) | ||||
// output newest 500 image files | ||||
fprintf(fid,"%s\n",newfile[ii].file); | ||||
fclose(fid); | ||||
cleanup: | ||||
zfree(newfile); | ||||
// free memory | ||||
navi::gallerytype = NEWEST; | ||||
// newest files | ||||
gallery(searchresults_file,"initF",0); | ||||
// generate gallery of files | ||||
gallery(0,"paint",0); | ||||
m_viewmode(0,"G"); | ||||
return; | ||||
} | ||||
// Compare 2 newfile records by file date-time | ||||
// return <0 =0 >0 for rec2 < = > rec1 (descending sequence) | ||||
using namespace newfiles; | ||||
int newfile_comp(cchar *rec1, cchar *rec2) | ||||
{ | ||||
char *date1 = ((newfile_t *) rec1)->fdate; | ||||
char *date2 = ((newfile_t *) rec2)->fdate; | ||||
return strcmp(date2,date1); | ||||
} | ||||
/******************************************************************************* | ||||
*/ | ||||
// popup a new window with a larger image of a clicked thumbnail | ||||
void gallery_popimage() | ||||
{ | ||||
static int ftf = 1, ii; | ||||
static char *popfiles[20]; | ||||
// last 20 files | ||||
int ftype; | ||||
if (ftf) { | ||||
ftf = 0; | ||||
// initz. empty file memory | ||||
for (ii = 0; ii < 20; ii++) | ||||
popfiles[ii] = 0; | ||||
ii = 0; | ||||
} | ||||
if (! clicked_file) return; | ||||
ftype = image_file_type(clicked_file); | ||||
// exclude RAW etc. | ||||
if (ftype != IMAGE) return; | ||||
ii++; | ||||
// use next file memory position | ||||
if (ii == 20) ii = 0; | ||||
if (popfiles[ii]) zfree(popfiles[ii]); | ||||
popfiles[ii] = clicked_file; | ||||
// save clicked_file persistently | ||||
clicked_file = 0; | ||||
// reset clicked_file | ||||
popup_image(popfiles[ii],MWIN,1,512); | ||||
// popup window with image | ||||
return; | ||||
} | ||||
/******************************************************************************* | ||||
*/ | ||||
// Determine if a file is a folder or a supported image file type | // Determine if a file is a folder or a supported image file type | |||
FTYPE image_file_type(cchar *file) | FTYPE image_file_type(cchar *file) | |||
{ | { | |||
int err, xcc, tcc; | int err, xcc, tcc; | |||
static int ftf = 1, tdcc = 0; | static int ftf = 1, tdcc = 0; | |||
cchar *ppx; | cchar *ppx; | |||
char ppx2[8], *ppt, *RP; | char ppx2[8], *ppt, *RP; | |||
STATB statB; | STATB statB; | |||
skipping to change at line 2967 | skipping to change at line 2607 | |||
// thumb folder: /thumb/folder | // thumb folder: /thumb/folder | |||
// thumb file: /thumb/folder/image/folder/file.xxx.jpeg | // thumb file: /thumb/folder/image/folder/file.xxx.jpeg | |||
char * thumb2imagefile(cchar *thumbfile) // simplified | char * thumb2imagefile(cchar *thumbfile) // simplified | |||
{ | { | |||
uint cc; | uint cc; | |||
char *imagefile; | char *imagefile; | |||
static int Fdone = 0; | static int Fdone = 0; | |||
if (! thumbfolder || *thumbfolder != '/') { | if (! thumbfolder || *thumbfolder != '/') { | |||
if (! Fdone) Plog(1,"%s \n","no thumbnail folder"); | if (! Fdone) Plog(0,"%s \n","no thumbnail folder"); | |||
Fdone++; | Fdone++; | |||
return 0; | return 0; | |||
} | } | |||
cc = strlen(thumbfolder); | cc = strlen(thumbfolder); | |||
if (cc > strlen(thumbfile) - 12) { // /thumbfolder/imagefolder/file.xxx.jpeg | if (cc > strlen(thumbfile) - 12) { // /thumbfolder/imagefolder/file.xxx.jpeg | |||
Plog(1,"invalid thumbfile: %s \n",thumbfile); | Plog(0,"invalid thumbfile: %s \n",thumbfile); | |||
return 0; | return 0; | |||
} | } | |||
imagefile = zstrdup(thumbfile+cc,"thumb2imagefile"); // /imagefolder/file.xxx.jpeg | imagefile = zstrdup(thumbfile+cc,"thumb2imagefile"); // /imagefolder/file.xxx.jpeg | |||
cc = strlen(imagefile); | cc = strlen(imagefile); | |||
imagefile[cc-5] = 0; // /imagefolder/file.xxx | imagefile[cc-5] = 0; // /imagefolder/file.xxx | |||
if (regfile(imagefile)) return imagefile; // return if exists | if (regfile(imagefile)) return imagefile; // return if exists | |||
zfree(imagefile); // not found | zfree(imagefile); // not found | |||
return 0; | return 0; | |||
} | } | |||
skipping to change at line 2997 | skipping to change at line 2637 | |||
// The filespec is returned whether or not the file exists. | // The filespec is returned whether or not the file exists. | |||
// Returned file is subject for zfree(). | // Returned file is subject for zfree(). | |||
char * image2thumbfile(cchar *imagefile) // simplified | char * image2thumbfile(cchar *imagefile) // simplified | |||
{ | { | |||
int cc1, cc2; | int cc1, cc2; | |||
char *RP, *thumbfile; | char *RP, *thumbfile; | |||
static int Fdone = 0; | static int Fdone = 0; | |||
if (! thumbfolder || *thumbfolder != '/') { | if (! thumbfolder || *thumbfolder != '/') { | |||
if (! Fdone++) Plog(1,"%s \n","no thumbnail folder"); | if (! Fdone++) Plog(0,"%s \n","no thumbnail folder"); | |||
return 0; | return 0; | |||
} | } | |||
RP = f_realpath(imagefile); // use real path | RP = f_realpath(imagefile); // use real path | |||
if (! RP) return 0; | if (! RP) return 0; | |||
if (! regfile(RP)) { zfree(RP); return 0; } | if (! regfile(RP)) { zfree(RP); return 0; } | |||
cc1 = strlen(thumbfolder); | cc1 = strlen(thumbfolder); | |||
cc2 = strlen(RP); | cc2 = strlen(RP); | |||
thumbfile = (char *) zmalloc(cc1+cc2+6,"image2thumbfile"); | thumbfile = (char *) zmalloc(cc1+cc2+6,"image2thumbfile"); | |||
strcpy(thumbfile,thumbfolder); // /thumb/folder | strcpy(thumbfile,thumbfolder); // /thumb/folder | |||
skipping to change at line 3027 | skipping to change at line 2667 | |||
int image2thumbfile2(cchar *imagefile, char *thumbfile) | int image2thumbfile2(cchar *imagefile, char *thumbfile) | |||
{ | { | |||
int cc1, cc2; | int cc1, cc2; | |||
char *RP; | char *RP; | |||
static int Fdone = 0; | static int Fdone = 0; | |||
*thumbfile = 0; | *thumbfile = 0; | |||
if (! thumbfolder || *thumbfolder != '/') { | if (! thumbfolder || *thumbfolder != '/') { | |||
if (! Fdone++) Plog(1,"no thumbnail folder\n"); | if (! Fdone++) Plog(0,"no thumbnail folder\n"); | |||
return 1; | return 1; | |||
} | } | |||
RP = f_realpath(imagefile); // use real path | RP = f_realpath(imagefile); // use real path | |||
if (! RP) return 1; | if (! RP) return 1; | |||
if (! regfile(RP)) { zfree(RP); return 1; } | if (! regfile(RP)) { zfree(RP); return 1; } | |||
cc1 = strlen(thumbfolder); | cc1 = strlen(thumbfolder); | |||
cc2 = strlen(RP); | cc2 = strlen(RP); | |||
strcpy(thumbfile,thumbfolder); // /thumb/folder | strcpy(thumbfile,thumbfolder); // /thumb/folder | |||
strcpy(thumbfile+cc1,RP); // .../image/folder/file.xxx | strcpy(thumbfile+cc1,RP); // .../image/folder/file.xxx | |||
skipping to change at line 3085 | skipping to change at line 2725 | |||
static PIXBUF *pixbuf = 0; | static PIXBUF *pixbuf = 0; | |||
static int psize = -1; | static int psize = -1; | |||
static char thumbfile[300] = ""; | static char thumbfile[300] = ""; | |||
GError *gerror = 0; | GError *gerror = 0; | |||
if (ftf) { | if (ftf) { | |||
ftf = 0; | ftf = 0; | |||
strncatv(thumbfile,300,zfuncs::zimagedir,"/folder.png",0); | strncatv(thumbfile,300,zfuncs::zimagedir,"/folder.png",0); | |||
bigpixbuf = gdk_pixbuf_new_from_file(thumbfile,&gerror); | bigpixbuf = gdk_pixbuf_new_from_file(thumbfile,&gerror); | |||
if (! bigpixbuf) { | if (! bigpixbuf) { | |||
Plog(1,"cannot make folder pixbuf: "); | Plog(0,"cannot make folder pixbuf: "); | |||
if (gerror) Plog(1,"%s",gerror->message); | if (gerror) Plog(0,"%s",gerror->message); | |||
Plog(1,"\n"); | Plog(0,"\n"); | |||
} | } | |||
} | } | |||
if (! bigpixbuf) return 0; | if (! bigpixbuf) return 0; | |||
if (thumbsize == psize) return pixbuf; | if (thumbsize == psize) return pixbuf; | |||
pixbuf = gdk_pixbuf_scale_simple(bigpixbuf,thumbsize,thumbsize,BILINEAR); | pixbuf = gdk_pixbuf_scale_simple(bigpixbuf,thumbsize,thumbsize,BILINEAR); | |||
psize = thumbsize; | psize = thumbsize; | |||
return pixbuf; | return pixbuf; | |||
} | } | |||
skipping to change at line 3113 | skipping to change at line 2753 | |||
static PIXBUF *pixbuf = 0; | static PIXBUF *pixbuf = 0; | |||
static int psize = -1; | static int psize = -1; | |||
static char thumbfile[300] = ""; | static char thumbfile[300] = ""; | |||
GError *gerror = 0; | GError *gerror = 0; | |||
if (ftf) { | if (ftf) { | |||
ftf = 0; | ftf = 0; | |||
strncatv(thumbfile,300,zfuncs::zimagedir,"/broken.png",0); | strncatv(thumbfile,300,zfuncs::zimagedir,"/broken.png",0); | |||
bigpixbuf = gdk_pixbuf_new_from_file(thumbfile,&gerror); | bigpixbuf = gdk_pixbuf_new_from_file(thumbfile,&gerror); | |||
if (! bigpixbuf) { | if (! bigpixbuf) { | |||
Plog(1,"cannot make broken pixbuf: "); | Plog(0,"cannot make broken pixbuf: "); | |||
if (gerror) Plog(1,"%s",gerror->message); | if (gerror) Plog(0,"%s",gerror->message); | |||
Plog(1,"\n"); | Plog(0,"\n"); | |||
} | } | |||
} | } | |||
if (! bigpixbuf) return 0; | if (! bigpixbuf) return 0; | |||
if (thumbsize == psize) return pixbuf; | if (thumbsize == psize) return pixbuf; | |||
pixbuf = gdk_pixbuf_scale_simple(bigpixbuf,thumbsize,thumbsize,BILINEAR); | pixbuf = gdk_pixbuf_scale_simple(bigpixbuf,thumbsize,thumbsize,BILINEAR); | |||
psize = thumbsize; | psize = thumbsize; | |||
return pixbuf; | return pixbuf; | |||
} | } | |||
skipping to change at line 3154 | skipping to change at line 2794 | |||
err = image2thumbfile2(imagefile,thumbfile); // get thumbnail file for image file | err = image2thumbfile2(imagefile,thumbfile); // get thumbnail file for image file | |||
if (err) { retstat = 2; goto returnx; } | if (err) { retstat = 2; goto returnx; } | |||
pp = strrchr(thumbfile+1,'/'); // folder | pp = strrchr(thumbfile+1,'/'); // folder | |||
if (! pp) { retstat = 2; goto returnx; } | if (! pp) { retstat = 2; goto returnx; } | |||
*pp = 0; | *pp = 0; | |||
if (! dirfile(thumbfile)) // create thumbnail folder if needed | if (! dirfile(thumbfile)) // create thumbnail folder if needed | |||
err = zshell(0,"mkdir -p -m 0750 \"%s\"",thumbfile); | err = zshell(0,"mkdir -p -m 0750 \"%s\"",thumbfile); | |||
*pp = '/'; | *pp = '/'; | |||
if (err && errno != EEXIST) { // happens, threads | if (err && errno != EEXIST) { // happens, threads | |||
Plog(0,"thumbnail mkdir failure: %s %s\n",thumbfile,strerror(errno)); | Plog(0,"thumbnail mkdir failure: %s\n %s\n",thumbfile,strerror(errno)); | |||
retstat = 2; | retstat = 2; | |||
goto returnx; | goto returnx; | |||
} | } | |||
pp = (char *) strrchr(imagefile,'.'); | pp = (char *) strrchr(imagefile,'.'); | |||
if (! pp) { retstat = 2; goto returnx; } | if (! pp) { retstat = 2; goto returnx; } | |||
size = thumbfilesize; | size = thumbfilesize; | |||
if (strcasestr(".jpg .jpeg",pp)) | if (strcasestr(".jpg .jpeg",pp)) | |||
skipping to change at line 3425 | skipping to change at line 3065 | |||
resource_unlock(TClock); // unlock thumbnail cache | resource_unlock(TClock); // unlock thumbnail cache | |||
return thumbtab[Tii].pxb->pixbuf; // return reference to cache | return thumbtab[Tii].pxb->pixbuf; // return reference to cache | |||
ret0: | ret0: | |||
resource_unlock(TClock); // unlock thumbnail cache | resource_unlock(TClock); // unlock thumbnail cache | |||
return 0; | return 0; | |||
bug0: | bug0: | |||
resource_unlock(TClock); // unlock thumbnail cache | resource_unlock(TClock); // unlock thumbnail cache | |||
Plog(1,"get_cache_thumb() indextab entry missing \n"); | Plog(0,"get_cache_thumb() indextab entry missing \n"); | |||
return get_broken_pixbuf(); // return ref. to 'broken' pixbuf | return get_broken_pixbuf(); // return ref. to 'broken' pixbuf | |||
bug1: | bug1: | |||
resource_unlock(TClock); | resource_unlock(TClock); | |||
Plog(1,"get_cache_thumb() indextab thumbtab no match \n"); | Plog(0,"get_cache_thumb() indextab thumbtab no match \n"); | |||
return get_broken_pixbuf(); | return get_broken_pixbuf(); | |||
bug2: | bug2: | |||
resource_unlock(TClock); | resource_unlock(TClock); | |||
Plog(1,"get_cache_thumb() hash table failure \n"); | Plog(0,"get_cache_thumb() hash table failure \n"); | |||
return get_broken_pixbuf(); | return get_broken_pixbuf(); | |||
bug3: | bug3: | |||
resource_unlock(TClock); | resource_unlock(TClock); | |||
Plog(1,"get_cache_thumb() purgefile not in filetab \n"); | Plog(0,"get_cache_thumb() purgefile not in filetab \n"); | |||
return get_broken_pixbuf(); | return get_broken_pixbuf(); | |||
} | } | |||
// check if thumbnail and thumbsize is currently in the thumbnail cache | // check if thumbnail and thumbsize is currently in the thumbnail cache | |||
// return 0 if not found | // return 0 if not found | |||
// return 1 if found, or not needed (not image, not found, folder) | // return 1 if found, or not needed (not image, not found, folder) | |||
// used by preload_thumbs() | // used by preload_thumbs() | |||
int check_cache_thumb(cchar *imagefile) | int check_cache_thumb(cchar *imagefile) | |||
{ | { | |||
skipping to change at line 3483 | skipping to change at line 3123 | |||
Fii += ii; // filetab entry | Fii += ii; // filetab entry | |||
Tii = indextab[Fii]; // corresp. thumbtab entry | Tii = indextab[Fii]; // corresp. thumbtab entry | |||
if (Tii == -1) goto bug0; // must exist | if (Tii == -1) goto bug0; // must exist | |||
if (! strmatch(imagefile,thumbtab[Tii].imagefile)) goto bug1; // must match | if (! strmatch(imagefile,thumbtab[Tii].imagefile)) goto bug1; // must match | |||
if (thumbsize != thumbtab[Tii].size) return 0; // thumbtab not current size | if (thumbsize != thumbtab[Tii].size) return 0; // thumbtab not current size | |||
if (mtime != thumbtab[Tii].mtime) return 0; // thumbtab is stale | if (mtime != thumbtab[Tii].mtime) return 0; // thumbtab is stale | |||
return 1; // thumbtab OK | return 1; // thumbtab OK | |||
bug0: | bug0: | |||
Plog(1,"check_cache_thumb() index tab entry missing \n"); | Plog(0,"check_cache_thumb() index tab entry missing \n"); | |||
return 0; | return 0; | |||
bug1: | bug1: | |||
Plog(1,"check_cache_thumb() indextab thumbtab no match \n"); | Plog(0,"check_cache_thumb() indextab thumbtab no match \n"); | |||
return 0; | return 0; | |||
} | } | |||
// replace current cached thumbnail from updated thumbnail file | // replace current cached thumbnail from updated thumbnail file | |||
int replace_cache_thumb(cchar *imagefile, PXB *thumbpxb) | int replace_cache_thumb(cchar *imagefile, PXB *thumbpxb) | |||
{ | { | |||
using namespace thumbnail_cache; | using namespace thumbnail_cache; | |||
int ii, Fii, Tii; | int ii, Fii, Tii; | |||
skipping to change at line 3532 | skipping to change at line 3172 | |||
if (! strmatch(imagefile,thumbtab[Tii].imagefile)) goto bug1; // must match | if (! strmatch(imagefile,thumbtab[Tii].imagefile)) goto bug1; // must match | |||
thumbpxb2 = PXB_resize(thumbpxb,thumbsize); // make curr. gallery thumb size | thumbpxb2 = PXB_resize(thumbpxb,thumbsize); // make curr. gallery thumb size | |||
PXB_free(thumbtab[Tii].pxb); // replace thumbnail PXB | PXB_free(thumbtab[Tii].pxb); // replace thumbnail PXB | |||
thumbtab[Tii].pxb = thumbpxb2; | thumbtab[Tii].pxb = thumbpxb2; | |||
thumbtab[Tii].size = thumbsize; // thumbnail size = current | thumbtab[Tii].size = thumbsize; // thumbnail size = current | |||
thumbtab[Tii].mtime = mtime; // thumbnail mod time = imagefile | thumbtab[Tii].mtime = mtime; // thumbnail mod time = imagefile | |||
return 1; // success | return 1; // success | |||
bug0: | bug0: | |||
Plog(1,"check_cache_thumb() index tab entry missing \n"); | Plog(0,"check_cache_thumb() index tab entry missing \n"); | |||
return 0; | return 0; | |||
bug1: | bug1: | |||
Plog(1,"check_cache_thumb() indextab thumbtab no match \n"); | Plog(0,"check_cache_thumb() indextab thumbtab no match \n"); | |||
return 0; | return 0; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// look ahead of gallery page and preload thumbnails into cache | // look ahead of gallery page and preload thumbnails into cache | |||
void preload_thumbs_start() // initialize, start the threads | void preload_thumbs_start() // initialize, start the threads | |||
{ | { | |||
void * preload_thumbs_thread(void *); | void * preload_thumbs_thread(void *); | |||
skipping to change at line 3617 | skipping to change at line 3257 | |||
get_cache_thumb(imagefile,thumbpxb); // add to thumbnail cache | get_cache_thumb(imagefile,thumbpxb); // add to thumbnail cache | |||
} | } | |||
resource_unlock(GFlock); | resource_unlock(GFlock); | |||
} | } | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// set the video frame for a video thumbnail | // popup a new window with a larger image of a clicked thumbnail | |||
void m_thumbframe(GtkWidget *, cchar *) | void gallery_popimage() | |||
{ | { | |||
zdialog *zd; | static int ftf = 1, ii; | |||
STATB statB; | static char *popfiles[20]; | |||
int ftype, zstat, err; | // last 20 files | |||
int minutes, seconds; | int ftype; | |||
char *pp, framefile[200]; | ||||
char *videofile = 0, thumbfile[XFCC]; | ||||
PXB *framepxb = 0, *thumbpxb = 0; | ||||
timeval thumbtimes[2]; | ||||
cchar *tip = "Play video and stop at desired frame \n" | ||||
"Note playback time in minutes and seconds"; | ||||
F1_help_topic = "video files"; | ||||
Plog(1,"m_thumbframe \n"); | ||||
if (clicked_file) { | ||||
// use clicked file if present | ||||
videofile = clicked_file; | ||||
clicked_file = 0; | ||||
} | ||||
else if (curr_file) | ||||
// else current file | ||||
videofile = zstrdup(curr_file,"thumbframe"); | ||||
else return; | ||||
ftype = image_file_type(videofile); | ||||
if (ftype != VIDEO) goto cleanup; | ||||
/** | ||||
____________________________________________ | ||||
| Set Video Thumbnail Frame | | ||||
| | | ||||
| Play video and stop at desired frame. | | ||||
| Playback time: minutes [__] seconds [__] | | ||||
| | | ||||
| [ OK ] [Cancel] | | ||||
|____________________________________________| | ||||
**/ | ||||
zd = zdialog_new("Set Video Thumbnail Frame",Mwin,"OK","Cancel",null); | ||||
zdialog_add_widget(zd,"label","labtip","dialog",tip); | ||||
zdialog_add_widget(zd,"hbox","hbtime","dialog",0,"space=3"); | ||||
zdialog_add_widget(zd,"label","labtime","hbtime","Playback time:","space=3"); | ||||
zdialog_add_widget(zd,"label","space","hbtime",0,"space=3"); | ||||
zdialog_add_widget(zd,"label","labmin","hbtime","minutes","space=3"); | ||||
zdialog_add_widget(zd,"zspin","minutes","hbtime","0|999|1|0","space=3|size=3" | ||||
); | ||||
zdialog_add_widget(zd,"label","space","hbtime",0,"space=3"); | ||||
zdialog_add_widget(zd,"label","labsec","hbtime","seconds","space=3"); | ||||
zdialog_add_widget(zd,"zspin","seconds","hbtime","0|59|1|0","space=3|size=3") | ||||
; | ||||
zdialog_run(zd,0,"parent"); | ||||
// run dialog and wait for completion | ||||
zstat = zdialog_wait(zd); | ||||
if (zstat != 1) { | ||||
// cancel | ||||
zdialog_free(zd); | ||||
goto cleanup; | ||||
} | ||||
zdialog_fetch(zd,"minutes",minutes); | ||||
// get playback time inputs | ||||
zdialog_fetch(zd,"seconds",seconds); | ||||
seconds = 60 * minutes + seconds; | ||||
zdialog_free(zd); | ||||
snprintf(framefile,200,"%s/videoframe.jpg",temp_folder); | ||||
// get frame file from ffmpeg | ||||
err = zshell(0,"ffmpeg -ss %d -i \"%s\" -v 8 -frames 1 -y \"%s\" ", | ||||
seconds, videofile, framefile); | ||||
if (err) { | ||||
zmessageACK(Mwin,"ffmpeg error: %s",strerror(errno)); | ||||
goto cleanup; | ||||
} | ||||
if (! regfile(framefile)) { | ||||
zmessageACK(Mwin,"cannot create frame file: %s",strerror(errno)); | ||||
goto cleanup; | ||||
} | ||||
err = image2thumbfile2(videofile,thumbfile); | ||||
// get thumbnail file for video file | ||||
if (err) { | ||||
zmessageACK(Mwin,"cannot create thumbnail file"); | ||||
goto cleanup; | ||||
} | ||||
pp = strrchr(thumbfile+1,'/'); | if (ftf) { | |||
*pp = 0; | ftf = 0; | |||
if (! dirfile(thumbfile)) { | // initz. empty file memory | |||
// create thumbnail folder if needed | for (ii = 0; ii < 20; ii++) | |||
err = zshell(0,"mkdir -p -m 0750 \"%s\"",thumbfile); | popfiles[ii] = 0; | |||
if (err) goto cleanup; | ii = 0; | |||
} | } | |||
*pp = '/'; | ||||
framepxb = PXB_load(framefile,1); | ||||
// video frame file >> PXB image | ||||
if (! framepxb) goto cleanup; | ||||
thumbpxb = PXB_resize(framepxb,thumbfilesize); | ||||
// resize PXB to thumbnail size | ||||
if (! thumbpxb) goto cleanup; | ||||
err = PXB_JPG_save(thumbpxb,thumbfile,80); | ||||
// save to JPEG thumbnail file | ||||
if (err) goto cleanup; | ||||
if (! regfile(videofile,&statB)) goto cleanup; // get video file mod time | if (! clicked_file) return; | |||
thumbtimes[0].tv_sec = thumbtimes[1].tv_sec = statB.st_mtim.tv_sec; | ftype = image_file_type(clicked_file); | |||
// thumbnail mod time | // exclude RAW etc. | |||
thumbtimes[0].tv_usec = thumbtimes[1].tv_usec = 0; | if (ftype != IMAGE) return; | |||
// = video file mod time | ||||
utimes(thumbfile,thumbtimes); | ||||
replace_cache_thumb(videofile,thumbpxb); | ii++; | |||
// replace cache thumbnail | // use next file memory position | |||
gallery(0,"paint",-1); | if (ii == 20) ii = 0; | |||
// repaint gallery | if (popfiles[ii]) zfree(popfiles[ii]); | |||
popfiles[ii] = clicked_file; | ||||
// save clicked_file persistently | ||||
clicked_file = 0; | ||||
// reset clicked_file | ||||
cleanup: | popup_image(popfiles[ii],MWIN,1,512); | |||
remove(framefile); | // popup window with image | |||
if (videofile) zfree(videofile); | ||||
if (framepxb) PXB_free(framepxb); | ||||
if (thumbpxb) PXB_free(thumbpxb); | ||||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// select one image file by clicking a gallery thumbnail | // select one image file by clicking a gallery thumbnail | |||
// returned file is subject for zfree() | // returned file is subject for zfree() | |||
char galsel1_filename[XFCC]; | char galsel1_filename[XFCC]; | |||
skipping to change at line 4364 | skipping to change at line 3914 | |||
cairo_set_source_rgb(cr,1,1,1); // white background only | cairo_set_source_rgb(cr,1,1,1); // white background only | |||
cairo_paint(cr); | cairo_paint(cr); | |||
} | } | |||
draw_context_destroy(draw_context); | draw_context_destroy(draw_context); | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// menu function to pre-select files for feeding album, batch and script functi ons | // gallery menu, resizable thumbnail view | |||
void m_select_files(GtkWidget *, cchar *) | void m_thumbview(GtkWidget *, cchar *menu) | |||
{ | { | |||
char albumfile[200]; | F1_help_topic = "thumb view"; | |||
FILE *fid; | Plog(1,"m_thumbview \n"); | |||
int err, ii; | Fthumbview = 1; | |||
if (thumbsize < 256) thumbsize = 256; | ||||
m_viewmode(0,"G"); | ||||
gallery(0,"paint",-1); | ||||
return; | ||||
} | ||||
F1_help_topic = "select image files"; | // gallery menu, thumbnail with basic metadata view | |||
Plog(1,"m_select_files \n"); | void m_metaview(GtkWidget *, cchar *menu) | |||
{ | ||||
F1_help_topic = "meta view"; | ||||
Plog(1,"m_metaview \n"); | ||||
Fthumbview = 2; | ||||
m_viewmode(0,"G"); | ||||
gallery(0,"paint",-1); | ||||
return; | ||||
} | ||||
snprintf(albumfile,200,"%s/selected_files",albums_folder); // "selected files" album | /******************************************************************************* */ | |||
err = gallery_select(); | // Show recently viewed image files. | |||
if (err || GScount == 0) { | ||||
remove(albumfile); | ||||
// nothing selected | ||||
return; | ||||
} | ||||
fid = fopen(albumfile,"w"); | void m_recentfiles(GtkWidget *, cchar *menu) | |||
// create "selected files" album | { | |||
if (! fid) { | F1_help_topic = "recent files"; | |||
zmessageACK(Mwin,strerror(errno)); | ||||
Plog(1,"m_recentfiles \n"); | ||||
if (Findexvalid == 0) { | ||||
zmessageACK(Mwin,"image index disabled"); | ||||
// no image index | ||||
return; | return; | |||
} | } | |||
for (ii = 0; ii < GScount; ii++) | navi::gallerytype = RECENT; | |||
// fill with selected files | // gallery type = recent files | |||
fprintf(fid,"%s\n",GSfiles[ii]); | gallery(recentfiles_file,"initF",0); | |||
// generate gallery of recent files | ||||
gallery(0,"paint",0); | ||||
m_viewmode(0,"G"); | ||||
return; | ||||
} | ||||
fclose(fid); | // add a new file to the list of recent files, first position | |||
// ( < 1 millisec. typical at 1000 file limit) | ||||
void add_recent_file(cchar *newfile) | ||||
{ | ||||
zlist_t *ZLfiles; | ||||
int ii; | ||||
ZLfiles = zlist_from_file(recentfiles_file); | ||||
if (! ZLfiles) ZLfiles = zlist_new(0); | ||||
ii = zlist_find(ZLfiles,newfile,0); | ||||
// if file already present, remove it | ||||
if (ii >= 0) zlist_remove(ZLfiles,ii); | ||||
zlist_insert(ZLfiles,newfile,0); | ||||
// insert in 1st position | ||||
zlist_clear(ZLfiles,200); | ||||
// truncate to 200 files | ||||
zlist_to_file(ZLfiles,recentfiles_file); | ||||
zlist_delete(ZLfiles); | ||||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// rename the current folder | // Report the newest or most recently modified image files, | |||
// based on EXIF photo date or file mod date. | ||||
void m_rename_folder(GtkWidget *, cchar *menu) // 22.15 | namespace newfiles | |||
{ | { | |||
int rename_folder_dialog_event(zdialog *zd, cchar *event); | struct newfile_t { | |||
// new file record | ||||
char *file; | ||||
// image file | ||||
char fdate[16]; | ||||
// date-time, yyyymmddhhmmss | ||||
}; | ||||
} | ||||
zdialog *zd; | // menu function | |||
int zstat, err; | ||||
char oldname[XFCC], newname[XFCC]; | ||||
F1_help_topic = "rename folder"; | void m_newfiles(GtkWidget *, cchar *menu) | |||
{ | ||||
using namespace newfiles; | ||||
Plog(1,"m_rename_folder \n"); | int newfile_comp(cchar *rec1, cchar *rec2); | |||
if (! galleryname) { | cchar *mess = "Use EXIF photo date or \n file modification date?"; | |||
zmessageACK(Mwin,"no current gallery"); | ||||
int ii, jj, cc, sort, Nxrec; | ||||
xxrec_t *xxrec; | ||||
FILE *fid; | ||||
newfile_t *newfile = 0; | ||||
F1_help_topic = "newest files"; | ||||
Plog(1,"m_newfiles \n"); | ||||
if (Findexvalid == 0) { | ||||
zmessageACK(Mwin,"image index disabled"); | ||||
// no image index | ||||
return; | return; | |||
} | } | |||
if (gallerytype != GDIR) { | if (Nxxrec == 0) { | |||
zmessageACK(Mwin,"current gallery is not a folder (file directory)"); | zmessageACK(Mwin,"no files found"); | |||
return; | return; | |||
} | } | |||
if (Fblock("rename folder","block")) return; | cc = Nxxrec * sizeof(newfile_t); | |||
// check pending, block | // allocate memory | |||
newfile = (newfile_t *) zmalloc(cc,"newfiles"); | ||||
strcpy(oldname,galleryname); | if (menu && strmatch(menu,"EXIF")) sort = 1; | |||
strcpy(newname,galleryname); | else if (menu && strmatch(menu,"file")) sort = 2; | |||
else sort = zdialog_choose(Mwin,"mouse",mess,"EXIF","File",null); | ||||
if (sort < 1) return; | ||||
// cancel | ||||
for (ii = jj = 0; ii < Nxxrec; ii++) | ||||
// loop image index table | ||||
{ | ||||
xxrec = xxrec_tab[ii]; | ||||
newfile[jj].file = xxrec->file; | ||||
// image file | ||||
if (sort == 1) { | ||||
if (strmatch(xxrec->pdate,"null")) continue; | ||||
// use EXIF photo date | ||||
strncpy0(newfile[jj].fdate,xxrec->pdate,15); | ||||
// ignore images without photo date | ||||
} | ||||
else strncpy0(newfile[jj].fdate,xxrec->fdate,15); | ||||
// else use file mod date | ||||
jj++; | ||||
// selected files | ||||
} | ||||
Nxrec = jj; | ||||
// final count | ||||
if (Nxrec > 1) | ||||
// sort index recs. by file date | ||||
HeapSort((char *) newfile, sizeof(newfile_t), Nxrec, newfile_comp); | ||||
fid = fopen(searchresults_file,"w"); | ||||
// open output file | ||||
if (! fid) { | ||||
zmessageACK(Mwin,"file error: %s",strerror(errno)); | ||||
goto cleanup; | ||||
} | ||||
for (ii = 0; ii < 1000 && ii < Nxrec; ii++) | ||||
// output newest 1000 image files 22.35 | ||||
fprintf(fid,"%s\n",newfile[ii].file); | ||||
fclose(fid); | ||||
cleanup: | ||||
zfree(newfile); | ||||
// free memory | ||||
navi::gallerytype = NEWEST; | ||||
// newest files | ||||
gallery(searchresults_file,"initF",0); | ||||
// generate gallery of files | ||||
gallery(0,"paint",0); | ||||
m_viewmode(0,"G"); | ||||
return; | ||||
} | ||||
// Compare 2 newfile records by file date-time | ||||
// return <0 =0 >0 for rec2 < = > rec1 (descending sequence) | ||||
using namespace newfiles; | ||||
int newfile_comp(cchar *rec1, cchar *rec2) | ||||
{ | ||||
char *date1 = ((newfile_t *) rec1)->fdate; | ||||
char *date2 = ((newfile_t *) rec2)->fdate; | ||||
return strcmp(date2,date1); | ||||
} | ||||
/******************************************************************************* | ||||
*/ | ||||
// menu function | ||||
// dialog to choose gallery sort order and sort the gallery | ||||
void m_gallery_sort(GtkWidget *, cchar *menu) | ||||
// 22.35 | ||||
{ | ||||
zdialog *zd; | ||||
int zstat, nn; | ||||
char albumfile[200], *pp, *pp2; | ||||
cchar *resetmess = " Reset all galleries\n to file name ascending"; | ||||
F1_help_topic = "gallery sort"; | ||||
Plog(1,"m_gallery_sort \n"); | ||||
/*** | /*** | |||
_________________________________________ | ________________________________ | |||
| Rename Folder | | | Gallery Sort | | |||
| | | | | | |||
| current folder [_____________________] | | | (o) File Name | | |||
| new name [_____________________] | | | (o) File Name/Number | | |||
| | | | (o) File Mod Date/Time | | |||
| [apply] [cancel] | | | (o) Photo Date/Time (EXIF) | | |||
|_________________________________________| | | (o) File Size (bytes) | | |||
| (o) Image Size (pixels) | | ||||
| (o) Metadata from Search | | ||||
// 22.20 | ||||
| (o) ascending (o) descending | | ||||
| | | ||||
| [x] reset all galleries | | ||||
| to file name ascending | | ||||
| | | ||||
| [Apply] | | ||||
|________________________________| | ||||
***/ | ***/ | |||
zd = zdialog_new("Rename Folder",Mwin,"Apply","Cancel",0); | zd = zdialog_new("Gallery Sort",Mwin,"Apply",null); | |||
zdialog_add_widget(zd,"hbox","hbcf","dialog",0,"space=3"); | // user dialog | |||
zdialog_add_widget(zd,"label","labcf","hbcf","current folder:","space=3"); | zdialog_add_widget(zd,"hbox","hb1","dialog"); | |||
zdialog_add_widget(zd,"label","oldname","hbcf",0,"space=3"); | zdialog_add_widget(zd,"label","space","hb1",0,"space=2"); | |||
zdialog_add_widget(zd,"hbox","hbnn","dialog",0,"space=3"); | zdialog_add_widget(zd,"vbox","vb1","hb1"); | |||
zdialog_add_widget(zd,"label","labnn","hbnn","new name","space=3"); | zdialog_add_widget(zd,"radio","filename","vb1","File Name"); | |||
zdialog_add_widget(zd,"zentry","newname","hbnn",0,"space=3|expand"); | zdialog_add_widget(zd,"radio","filenumber","vb1","File Name/Number"); | |||
zdialog_add_widget(zd,"radio","filedate","vb1","File Mod Date/Time"); | ||||
zdialog_add_widget(zd,"radio","photodate","vb1","Photo Date/Time (EXIF)"); | ||||
zdialog_add_widget(zd,"radio","filesize","vb1","File Size (bytes)"); | ||||
zdialog_add_widget(zd,"radio","pixelsize","vb1","Image Size (pixels)"); | ||||
zdialog_add_widget(zd,"radio","metadata","vb1","Metadata from Search Function | ||||
"); | ||||
zdialog_add_widget(zd,"hbox","hb2","dialog",0,"space=5"); | ||||
zdialog_add_widget(zd,"radio","ascending","hb2","ascending","space=4"); | ||||
zdialog_add_widget(zd,"radio","descending","hb2","descending","space=2"); | ||||
zdialog_add_widget(zd,"hbox","hbreset","dialog",0,"space=5"); | ||||
zdialog_add_widget(zd,"check","reset","hbreset",resetmess,"space=4"); | ||||
zdialog_stuff(zd,"oldname",oldname); | zdialog_add_ttip(zd,"metadata","metadata from Search Function, metadata repor | |||
// stuff current folder name | t"); | |||
zdialog_stuff(zd,"newname",newname); | ||||
// also basis for new name | ||||
zdialog_run(zd,rename_folder_dialog_event); | zdialog_stuff(zd,"filename",0); | |||
// all buttons off | ||||
zdialog_stuff(zd,"filenumber",0); | ||||
zdialog_stuff(zd,"filedate",0); | ||||
// GTK radio buttons not reliable | ||||
zdialog_stuff(zd,"photodate",0); | ||||
// (vbox works, hbox does not) | ||||
zdialog_stuff(zd,"filesize",0); | ||||
zdialog_stuff(zd,"pixelsize",0); | ||||
zdialog_stuff(zd,"metadata",0); | ||||
zdialog_stuff(zd,"metadata",0); | ||||
zdialog_stuff(zd,"descending",0); | ||||
zdialog_stuff(zd,"reset",0); | ||||
zstat = zdialog_wait(zd); | if (gallerysort == FNAME || gallerysort == SNONE) | |||
zdialog_stuff(zd,"filename",1); | ||||
Fblock("rename folder",0); | if (gallerysort == FNUMBER) | |||
// 22.11 | ||||
zdialog_stuff(zd,"filenumber",1); | ||||
zdialog_fetch(zd,"newname",newname,XFCC); | if (gallerysort == FDATE) | |||
// get new folder name | zdialog_stuff(zd,"filedate",1); | |||
zdialog_free(zd); | ||||
if (zstat != 1) return; | ||||
if (strmatch(oldname,newname)) { | if (gallerysort == PDATE) | |||
zmessageACK(Mwin,"name not changed"); | zdialog_stuff(zd,"photodate",1); | |||
return; | ||||
} | ||||
err = rename(oldname,newname); | if (gallerysort == FSIZE) | |||
// do folder rename | zdialog_stuff(zd,"filesize",1); | |||
if (err) { | ||||
zmessageACK(Mwin,"rename failed: %s",strerror(errno)); | if (gallerysort == PSIZE) | |||
zdialog_stuff(zd,"pixelsize",1); | ||||
if (gallerysort == MDATA) | ||||
zdialog_stuff(zd,"metadata",1); | ||||
if (galleryseq == ASCEND || galleryseq == QNONE) | ||||
zdialog_stuff(zd,"ascending",1); | ||||
if (galleryseq == DESCEND) | ||||
zdialog_stuff(zd,"descending",1); | ||||
zdialog_set_modal(zd); | ||||
zdialog_run(zd,0,"mouse"); | ||||
// run dialog, wait for completion | ||||
zstat = zdialog_wait(zd); | ||||
if (zstat != 1) { | ||||
zdialog_free(zd); | ||||
return; | return; | |||
} | } | |||
zmessageACK(Mwin,"folder renamed: \n %s",newname); | zdialog_fetch(zd,"filename",nn); | |||
// get user sort type | ||||
if (nn) gallerysort = FNAME; | ||||
zdialog_fetch(zd,"filenumber",nn); | ||||
if (nn) gallerysort = FNUMBER; | ||||
zdialog_fetch(zd,"filedate",nn); | ||||
if (nn) gallerysort = FDATE; | ||||
zdialog_fetch(zd,"photodate",nn); | ||||
if (nn) gallerysort = PDATE; | ||||
zdialog_fetch(zd,"filesize",nn); | ||||
if (nn) gallerysort = FSIZE; | ||||
zdialog_fetch(zd,"pixelsize",nn); | ||||
if (nn) gallerysort = PSIZE; | ||||
zdialog_fetch(zd,"metadata",nn); | ||||
if (nn) gallerysort = MDATA; | ||||
zmessage_post(Mwin,"parent",3,"updating index and albums"); | zdialog_fetch(zd,"ascending",nn); | |||
zmainsleep(3); | // get ascending/descending | |||
if (nn) galleryseq = ASCEND; | ||||
else galleryseq = DESCEND; | ||||
m_quick_index(0,0); | zdialog_fetch(zd,"reset",nn); | |||
// re-index after folder rename | // reset all gallery sort memory | |||
if (nn) { | ||||
// (revert to file name ascending) | ||||
gallery_memory("reset"); | ||||
gallerysort = FNAME; | ||||
galleryseq = ASCEND; | ||||
} | ||||
album_folder_rename(oldname,newname); | zdialog_free(zd); | |||
// update filenames in album files | ||||
gallery(0,"sort",-1); | ||||
// sort the gallery | ||||
gallery(0,"paint",0); | ||||
// paint, position = 0 | ||||
if (gallerytype == ALBUM) | ||||
// an album was sorted | ||||
{ | ||||
pp = strrchr(galleryname,'/'); | ||||
// get album name | ||||
if (pp) pp++; | ||||
else pp = galleryname; | ||||
pp2 = strstr(pp,"-sorted"); | ||||
// append "-sorted" | ||||
if (pp2) *pp2 = 0; | ||||
// avoid "-sorted-sorted" | ||||
snprintf(albumfile,200,"%s/%s-sorted",albums_folder,pp); | ||||
album_create_from_gallery(albumfile); | ||||
// new album, oldname-sorted | ||||
album_show(albumfile); | ||||
} | ||||
gallery(newname,"init",0); | ||||
// refresh gallery | ||||
gallery(0,"paint",-1); | ||||
return; | return; | |||
} | } | |||
// zdialog event and completion function | /******************************************************************************* */ | |||
int rename_folder_dialog_event(zdialog *zd, cchar *event) | // screen the current gallery for matching files | |||
// output matching files to album "gallery_screen" | ||||
namespace gallery_screen_names | ||||
{ | { | |||
if (zd->zstat) zdialog_destroy(zd); | int Foldest, Fnewest, Funedited, Finclude, Fexclude, Fkeep; | |||
return 1; | char includetext[100], excludetext[100]; | |||
} | } | |||
/******************************************************************************* | // menu function | |||
*/ | ||||
// create a new subfolder under the current folder | ||||
void m_add_subfolder(GtkWidget *, cchar *menu) // 22.11 | void m_gallery_screen(GtkWidget *, cchar *menu) // 22.35 | |||
{ | { | |||
int add_subfolder_dialog_event(zdialog *zd, cchar *event); | using namespace gallery_screen_names; | |||
zdialog *zd; | zdialog *zd; | |||
int zstat, err; | int zstat, ii, jj, Nfiles, nfl; | |||
char pathname[XFCC], subfolder[100]; | char albumfile[AFCC]; | |||
char *pp1, *pp2; | ||||
char *rootname, **filelist; | ||||
FTYPE ftype; | ||||
FILE *fid; | ||||
F1_help_topic = "add subfolder"; | int gallery_screen_dialog_event(zdialog *zd, cchar *event); | |||
Plog(1,"m_add_subfolder \n"); | F1_help_topic = "gallery screen"; | |||
if (! galleryname) { | Plog(1,"m_gallery_screen \n"); | |||
zmessageACK(Mwin,"no current gallery"); | ||||
if (gallerytype != FOLDER) { | ||||
zmessageACK(Mwin,"gallery must be a FOLDER gallery"); | ||||
return; | return; | |||
} | } | |||
if (gallerytype != GDIR) { | if (Gfiles < 1) { | |||
zmessageACK(Mwin,"current gallery is not a folder (file directory)"); | zmessageACK(Mwin,"gallery is empty"); | |||
return; | return; | |||
} | } | |||
gallery_memory("get"); | ||||
if (gallerysort != FNAME || galleryseq != ASCEND) { | ||||
gallerysort = FNAME; | ||||
// sort gallery by file name ascending | ||||
galleryseq = ASCEND; | ||||
gallery(0,"sort",-1); | ||||
gallery(0,"paint",0); | ||||
zmessage_post(Mwin,"20/20",4,"gallery resorted by file name ascending"); | ||||
} | ||||
/*** | /*** | |||
_________________________________________ | ______________________________________ | |||
| Add Subfolder | | | Gallery Screen | | |||
| | | | | | |||
| current folder [_____________________] | | | [_] oldest version | | |||
| new subfolder [_____________________] | | | [_] newest version | | |||
| | | | [_] unedited only | | |||
| [create] [cancel] | | | [_] include [_____________________] | | |||
|_________________________________________| | | [_] exclude [_____________________] | | |||
| | | ||||
| [OK] [Cancel] | | ||||
|______________________________________| | ||||
***/ | ***/ | |||
zd = zdialog_new("Add Subfolder",Mwin,"Create","Cancel"); | zd = zdialog_new("Gallery Screen",Mwin,"OK","Cancel",null); | |||
zdialog_add_widget(zd,"hbox","hbcf","dialog",0,"space=3"); | ||||
zdialog_add_widget(zd,"label","labcf","hbcf","current folder:","space=3"); | ||||
zdialog_add_widget(zd,"label","currfol","hbcf",0,"space=3"); | ||||
zdialog_add_widget(zd,"hbox","hbnsf","dialog",0,"space=3"); | ||||
zdialog_add_widget(zd,"label","labnsf","hbnsf","new subfolder","space=3"); | ||||
zdialog_add_widget(zd,"zentry","subfolder","hbnsf",0,"space=3|expand"); | ||||
zdialog_stuff(zd,"currfol",galleryname); | zdialog_add_widget(zd,"hbox","hb1","dialog"); | |||
zdialog_add_widget(zd,"check","oldest","hb1","oldest version"); | ||||
zdialog_run(zd,add_subfolder_dialog_event); | zdialog_add_widget(zd,"hbox","hb2","dialog"); | |||
zdialog_add_widget(zd,"check","newest","hb2","newest version"); | ||||
zdialog_add_widget(zd,"hbox","hb3","dialog"); | ||||
zdialog_add_widget(zd,"check","unedited","hb3","unedited only"); | ||||
zdialog_add_widget(zd,"hbox","hb4","dialog"); | ||||
zdialog_add_widget(zd,"check","include","hb4","include"); | ||||
zdialog_add_widget(zd,"zentry","includetext","hb4",0,"expand"); | ||||
zdialog_add_widget(zd,"hbox","hb5","dialog"); | ||||
zdialog_add_widget(zd,"check","exclude","hb5","exclude"); | ||||
zdialog_add_widget(zd,"zentry","excludetext","hb5",0,"expand"); | ||||
zdialog_restore_inputs(zd); | ||||
zdialog_resize(zd,300,0); | ||||
zdialog_run(zd,gallery_screen_dialog_event,"mouse"); | ||||
zstat = zdialog_wait(zd); | zstat = zdialog_wait(zd); | |||
if (zstat != 1) { | ||||
zdialog_free(zd); | ||||
return; | ||||
} | ||||
zdialog_fetch(zd,"subfolder",subfolder,100); | zdialog_fetch(zd,"oldest",Foldest); | |||
// include oldest versions only | ||||
zdialog_fetch(zd,"newest",Fnewest); | ||||
// include newest versions only | ||||
zdialog_fetch(zd,"unedited",Funedited); | ||||
// include unedited files only | ||||
zdialog_fetch(zd,"include",Finclude); | ||||
// include files matching string | ||||
zdialog_fetch(zd,"exclude",Fexclude); | ||||
zdialog_fetch(zd,"includetext",includetext,100); | ||||
zdialog_fetch(zd,"excludetext",excludetext,100); | ||||
zdialog_free(zd); | zdialog_free(zd); | |||
if (zstat != 1) return; | ||||
if (*subfolder < ' ' || strchr(subfolder,'/')) { | snprintf(albumfile,AFCC,"%s/gallery_screen",albums_folder); | |||
zmessageACK(Mwin,"subfolder name is invalid"); | // output to album "gallery_screen" | |||
fid = fopen(albumfile,"w"); | ||||
// open/write album file | ||||
if (! fid) { | ||||
zmessageACK(Mwin,strerror(errno)); | ||||
return; | return; | |||
} | } | |||
*pathname = 0; | Nfiles = 0; | |||
strncatv(pathname,XFCC,galleryname,"/",subfolder,0); | rootname = 0; | |||
filelist = 0; | ||||
for (ii = 0; ii < Gfiles; ii++) | ||||
// loop files in current gallery | ||||
{ | ||||
pp1 = gallery(0,"get",ii); | ||||
if (! pp1) break; | ||||
ftype = image_file_type(pp1); | ||||
// must be image type file | ||||
if (ftype != IMAGE && ftype != RAW && ftype != VIDEO) | ||||
continue; | ||||
err = mkdir(pathname,0764); | pp2 = file_rootname(pp1); | |||
if (err) { | // skip until new rootname found | |||
zmessageACK(Mwin,"create folder failed: %s",strerror(errno)); | if (rootname && strmatch(pp2,rootname)) { | |||
return; | zfree(pp2); | |||
continue; | ||||
} | ||||
if (rootname) zfree(rootname); | ||||
// next rootname | ||||
rootname = pp2; | ||||
if (filelist) { | ||||
// free prior file list | ||||
for (jj = 0; jj < nfl; jj++) | ||||
zfree(filelist[jj]); | ||||
zfree(filelist); | ||||
} | ||||
filelist = file_all_versions(pp1,nfl); | ||||
// get original and all versions | ||||
for (jj = 0; jj < nfl; jj++) | ||||
{ | ||||
pp1 = filelist[jj]; | ||||
// family member jj | ||||
Fkeep = 1; | ||||
if (Foldest && Fnewest) { | ||||
// exclude if not oldest | ||||
if (jj != 0 && jj != nfl-1) Fkeep = 0; | ||||
// or newest version | ||||
} | ||||
else if (Foldest && jj != 0) Fkeep = 0; | ||||
// exclude if not oldest version | ||||
else if (Fnewest && jj != nfl-1) Fkeep = 0; | ||||
// exclude if not newest version | ||||
if (Fkeep && Funedited && nfl > 1) Fkeep = 0; | ||||
// exclude if edited versions exist 22.35 | ||||
if (Fkeep && Funedited) { | ||||
// exclude if edited versions exist 22.35 | ||||
pp1 = filelist[0]; | ||||
pp2 = strrchr(pp1,'.'); | ||||
// /.../filename.vNN.ext | ||||
if (pp2 && strmatchN(pp2-4,".v",2)) Fkeep = 0; | ||||
// | | | ||||
} | ||||
// pp1 pp2 | ||||
if (Fkeep && Finclude) { | ||||
pp2 = strrchr(pp1,'/'); | ||||
if (! strcasestr(pp2,includetext)) Fkeep = 0; | ||||
// exclude if no text match | ||||
} | ||||
if (Fkeep && Fexclude) { | ||||
pp2 = strrchr(pp1,'/'); | ||||
if (strcasestr(pp2,excludetext)) Fkeep = 0; | ||||
// exclude if text match | ||||
} | ||||
if (Fkeep) | ||||
{ | ||||
fprintf(fid,"%s\n",pp1); | ||||
// screened output file | ||||
Nfiles++; | ||||
if (Nfiles == maxalbumfiles) { | ||||
zmessageACK(Mwin,"max. album files reached, results truncated"); | ||||
break; | ||||
} | ||||
} | ||||
} | ||||
} | } | |||
gallery(galleryname,"init",0); | fclose(fid); | |||
gallery(0,"paint",-1); | ||||
zmessageACK(Mwin,"new subfolder created: \n %s",pathname); | if (rootname) zfree(rootname); | |||
// free last rootname | ||||
if (filelist) { | ||||
// free last file list | ||||
for (jj = 0; jj < nfl; jj++) | ||||
zfree(filelist[jj]); | ||||
zfree(filelist); | ||||
} | ||||
zstrcopy(curr_album,albumfile,"albums"); | ||||
// make current album | ||||
zmessage_post(Mwin,"20/20",3,"new album created"); | ||||
album_show(); | ||||
return; | return; | |||
} | } | |||
// zdialog event and completion function | // dialog event and completion function | |||
int add_subfolder_dialog_event(zdialog *zd, cchar *event) | int gallery_screen_dialog_event(zdialog *zd, cchar *event) // 22.35 | |||
{ | { | |||
if (zd->zstat) zdialog_destroy(zd); | using namespace gallery_screen_names; | |||
zdialog_fetch(zd,"oldest",Foldest); | ||||
// include oldest versions only | ||||
zdialog_fetch(zd,"newest",Fnewest); | ||||
// include newest versions only | ||||
zdialog_fetch(zd,"unedited",Funedited); | ||||
// include unedited files only | ||||
if (strstr("oldest newest",event)) | ||||
// enforce mutual-exclusion | ||||
if (Foldest || Fnewest) zdialog_stuff(zd,"unedited",0); | ||||
if (strmatch(event,"unedited")) { | ||||
// enforce mutual-exclusion | ||||
if (Funedited) { | ||||
zdialog_stuff(zd,"oldest",0); | ||||
zdialog_stuff(zd,"newest",0); | ||||
} | ||||
} | ||||
return 1; | return 1; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// set the gallery from the current image file physical folder | // set the gallery from the current image file physical folder | |||
void m_source_folder(GtkWidget*, cchar *menu) | void m_source_folder(GtkWidget*, cchar *menu) | |||
{ | { | |||
F1_help_topic = "source folder"; | F1_help_topic = "source folder"; | |||
skipping to change at line 4599 | skipping to change at line 4476 | |||
curr_file_posn = file_position(curr_file,0); // file position in gallery list | curr_file_posn = file_position(curr_file,0); // file position in gallery list | |||
m_viewmode(0,"G"); | m_viewmode(0,"G"); | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// generate a clickable list of all image folders | // generate a clickable list of all image folders | |||
// show gallery for any folder clicked | // show gallery for any folder clicked | |||
namespace alldirs | namespace allfolders | |||
{ | { | |||
#define maxdirs 10000 | #define maxdirs 10000 | |||
int Nlines = 0, Fall = 0; | int Nlines = 0, Fall = 0; | |||
int currline = 0; | int currline = 0; | |||
zdialog *zd; | zdialog *zd; | |||
typedef struct { | typedef struct { | |||
char *name; // /dir1/dir2/.../dirN folder name | char *name; // /dir1/dir2/.../dirN folder name | |||
int Nsubs; // subfolder count 0-N | int Nsubs; // subfolder count 0-N | |||
skipping to change at line 4625 | skipping to change at line 4502 | |||
dlist_t *dlist; | dlist_t *dlist; | |||
int drecl = sizeof(dlist_t); | int drecl = sizeof(dlist_t); | |||
int compfunc(cchar *rec1, cchar *rec2); | int compfunc(cchar *rec1, cchar *rec2); | |||
void callbackfunc(GtkWidget *, int line, int pos, int kbkey); | void callbackfunc(GtkWidget *, int line, int pos, int kbkey); | |||
void writetext(); | void writetext(); | |||
} | } | |||
// menu function | // menu function | |||
void m_alldirs(GtkWidget *, cchar *) | void m_allfolders(GtkWidget *, cchar *) | |||
{ | { | |||
using namespace alldirs; | using namespace allfolders; | |||
int ii, jj, cc, pcc, NF, err; | int ii, jj, cc, pcc, NF, err; | |||
char *dir, *pdir, **Flist; | char *dir, *pdir, **Flist; | |||
F1_help_topic = "all folders"; | F1_help_topic = "all folders"; | |||
Plog(1,"m_alldirs \n"); | Plog(1,"m_allfolders \n"); | |||
/*** | /*** | |||
________________________________ | ________________________________ | |||
| All Folders | | | All Folders | | |||
| ____________________________ | | | ____________________________ | | |||
| | | | | | | | | | |||
| | [+] topdir1 | | | | | [+] topdir1 | | | |||
| | [-] topdir2 | | | | | [-] topdir2 | | | |||
| | subdir1 | | | | | subdir1 | | | |||
| | [+] subdir2 | | | | | [+] subdir2 | | | |||
skipping to change at line 4658 | skipping to change at line 4535 | |||
| |____________________________| | | | |____________________________| | | |||
| | | | | | |||
| [ OK ] | | | [ OK ] | | |||
|________________________________| | |________________________________| | |||
***/ | ***/ | |||
if (dlist) goto report; // already done | if (dlist) goto report; // already done | |||
cc = drecl * maxdirs; | cc = drecl * maxdirs; | |||
dlist = (dlist_t *) zmalloc(cc,"alldirs"); // memory for folder list | dlist = (dlist_t *) zmalloc(cc,"allfolders"); // memory for folder list | |||
Fall = 0; | Fall = 0; | |||
for (ii = 0; ii < Ntopfolders; ii++) // loop all top image folders | for (ii = 0; ii < Ntopfolders; ii++) // loop all top image folders | |||
{ | { | |||
dlist[Fall].name = topfolders[ii]; | dlist[Fall].name = topfolders[ii]; | |||
Fall++; | Fall++; | |||
if (Fall == maxdirs) break; | if (Fall == maxdirs) break; | |||
err = find_imagefiles(topfolders[ii],8+16,Flist,NF); // folders, all levels | err = find_imagefiles(topfolders[ii],8+16,Flist,NF); // folders, all levels | |||
if (err) { | if (err) { | |||
zmessageACK(Mwin,strerror(errno)); | zmessageACK(Mwin,strerror(errno)); | |||
continue; | continue; | |||
} | } | |||
for (jj = 0; jj < NF; jj++) // add to folders list | for (jj = 0; jj < NF; jj++) // add to folders list | |||
{ | { | |||
dlist[Fall].name = zstrdup(Flist[jj],"alldirs"); | dlist[Fall].name = zstrdup(Flist[jj],"allfolders"); | |||
Fall++; | Fall++; | |||
if (Fall == maxdirs) break; | if (Fall == maxdirs) break; | |||
} | } | |||
if (NF) zfree(Flist); | if (NF) zfree(Flist); | |||
if (Fall == maxdirs) break; | if (Fall == maxdirs) break; | |||
} | } | |||
if (Fall > 1) | if (Fall > 1) | |||
HeapSort((char *) dlist,drecl,Fall,compfunc); // sort alphabetically | HeapSort((char *) dlist,drecl,Fall,compfunc); // sort alphabetically | |||
skipping to change at line 4717 | skipping to change at line 4594 | |||
zd = popup_report_open("All Folders",Mwin,300,400,0,callbackfunc,"OK",0); // open report window 22.15 | zd = popup_report_open("All Folders",Mwin,300,400,0,callbackfunc,"OK",0); // open report window 22.15 | |||
writetext(); // write top folders to window | writetext(); // write top folders to window | |||
currline = 0; // first entry | currline = 0; // first entry | |||
return; | return; | |||
} | } | |||
// sort compare function | // sort compare function | |||
int alldirs::compfunc(cchar *rec1, cchar *rec2) | int allfolders::compfunc(cchar *rec1, cchar *rec2) | |||
{ | { | |||
dlist_t *dir1 = (dlist_t *) rec1; | dlist_t *dir1 = (dlist_t *) rec1; | |||
dlist_t *dir2 = (dlist_t *) rec2; | dlist_t *dir2 = (dlist_t *) rec2; | |||
int nn; | int nn; | |||
nn = strcasecmp(dir1->name,dir2->name); | nn = strcasecmp(dir1->name,dir2->name); | |||
if (nn) return nn; | if (nn) return nn; | |||
nn = strcmp(dir1->name,dir2->name); | nn = strcmp(dir1->name,dir2->name); | |||
return nn; | return nn; | |||
} | } | |||
// folder list mouse function | // folder list mouse function | |||
void alldirs::callbackfunc(GtkWidget *textwidget, int line, int pos, int kbkey) | void allfolders::callbackfunc(GtkWidget *textwidget, int line, int pos, int kbke y) | |||
{ | { | |||
using namespace alldirs; | using namespace allfolders; | |||
int ii; | int ii; | |||
char *pline, *pp; | char *pline, *pp; | |||
static int Fbusy = 0; | static int Fbusy = 0; | |||
if (Fbusy++) return; // stop re-entry 22.30 | if (Fbusy++) return; // stop re-entry 22.30 | |||
if (Fblock("alldirs","block edits")) goto returnx; // check pending, block | if (Fblock("allfolders","block edits")) goto returnx; // check pending, block | |||
if (line < 0) // KB key | if (line < 0) // KB key | |||
{ | { | |||
if (kbkey == GDK_KEY_F1) { // key F1 pressed, show help | if (kbkey == GDK_KEY_F1) { // key F1 pressed, show help | |||
showz_docfile(Mwin,"userguide",F1_help_topic); | showz_docfile(Mwin,"userguide",F1_help_topic); | |||
goto returnx; | goto returnx; | |||
} | } | |||
line = currline; | line = currline; | |||
if (kbkey == GDK_KEY_Up) line--; // KB arrow key navigation | if (kbkey == GDK_KEY_Up) line--; // KB arrow key navigation | |||
skipping to change at line 4796 | skipping to change at line 4673 | |||
} | } | |||
} | } | |||
m_viewmode(0,"G"); | m_viewmode(0,"G"); | |||
gallery(dlist[ii].name,"init",0); // folder name clicked | gallery(dlist[ii].name,"init",0); // folder name clicked | |||
gallery(0,"sort",-2); // recall sort and position | gallery(0,"sort",-2); // recall sort and position | |||
gallery(0,"paint",-1); // show gallery | gallery(0,"paint",-1); // show gallery | |||
returnx: | returnx: | |||
Fbusy = 0; | Fbusy = 0; | |||
Fblock("alldirs",0); | Fblock("allfolders",0); | |||
return; | return; | |||
} | } | |||
// write all visible folders to text window | // write all visible folders to text window | |||
void alldirs::writetext() | void allfolders::writetext() | |||
{ | { | |||
using namespace alldirs; | using namespace allfolders; | |||
int ii = 0, jj, line = 0; | int ii = 0, jj, line = 0; | |||
char *pp, indent[100]; | char *pp, indent[100]; | |||
cchar *expbutt; | cchar *expbutt; | |||
memset(indent,' ',100); | memset(indent,' ',100); | |||
popup_report_clear(zd); | popup_report_clear(zd); | |||
while (ii < Fall) // loop all folders | while (ii < Fall) // loop all folders | |||
skipping to change at line 4847 | skipping to change at line 4724 | |||
} | } | |||
ii = jj; | ii = jj; | |||
} | } | |||
Nlines = line; | Nlines = line; | |||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// dummy menu entry as target for "Show Hidden Files" KB shortcut | // menu function to pre-select files for feeding album, batch and script functi ons | |||
void m_show_hidden(GtkWidget *, cchar *) | void m_select_files(GtkWidget *, cchar *) | |||
{ | { | |||
Plog(1,"m_show_hidden \n"); | char albumfile[200]; | |||
KBaction("Show Hidden"); | FILE *fid; | |||
int err, ii; | ||||
F1_help_topic = "select image files"; | ||||
Plog(1,"m_select_files \n"); | ||||
snprintf(albumfile,200,"%s/selected_files",albums_folder); | ||||
// "selected files" album | ||||
err = gallery_select(); | ||||
if (err || GScount == 0) { | ||||
remove(albumfile); | ||||
// nothing selected | ||||
return; | ||||
} | ||||
fid = fopen(albumfile,"w"); | ||||
// create "selected files" album | ||||
if (! fid) { | ||||
zmessageACK(Mwin,strerror(errno)); | ||||
return; | ||||
} | ||||
for (ii = 0; ii < GScount; ii++) | ||||
// fill with selected files | ||||
fprintf(fid,"%s\n",GSfiles[ii]); | ||||
fclose(fid); | ||||
return; | return; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// dummy menu entry as target for "Current Album" KB shortcut | // rename the current folder | |||
void m_current_album(GtkWidget *, cchar *) | void m_rename_folder(GtkWidget *, cchar *menu) // 22.15 | |||
{ | { | |||
Plog(1,"m_current_album \n"); | int rename_folder_dialog_event(zdialog *zd, cchar *event); | |||
navi::newalbum_menu_event(0,0); | ||||
zdialog *zd; | ||||
int zstat, err; | ||||
char oldname[XFCC], newname[XFCC]; | ||||
F1_help_topic = "rename folder"; | ||||
Plog(1,"m_rename_folder \n"); | ||||
if (! galleryname) { | ||||
zmessageACK(Mwin,"no current gallery"); | ||||
return; | ||||
} | ||||
if (gallerytype != FOLDER) { | ||||
zmessageACK(Mwin,"current gallery is not a folder (file directory)"); | ||||
return; | ||||
} | ||||
if (Fblock("rename folder","block")) return; | ||||
// check pending, block | ||||
strcpy(oldname,galleryname); | ||||
strcpy(newname,galleryname); | ||||
/*** | ||||
_________________________________________ | ||||
| Rename Folder | | ||||
| | | ||||
| current folder [_____________________] | | ||||
| new name [_____________________] | | ||||
| | | ||||
| [apply] [cancel] | | ||||
|_________________________________________| | ||||
***/ | ||||
zd = zdialog_new("Rename Folder",Mwin,"Apply","Cancel",0); | ||||
zdialog_add_widget(zd,"hbox","hbcf","dialog",0,"space=3"); | ||||
zdialog_add_widget(zd,"label","labcf","hbcf","current folder:","space=3"); | ||||
zdialog_add_widget(zd,"label","oldname","hbcf",0,"space=3"); | ||||
zdialog_add_widget(zd,"hbox","hbnn","dialog",0,"space=3"); | ||||
zdialog_add_widget(zd,"label","labnn","hbnn","new name","space=3"); | ||||
zdialog_add_widget(zd,"zentry","newname","hbnn",0,"space=3|expand"); | ||||
zdialog_stuff(zd,"oldname",oldname); | ||||
// stuff current folder name | ||||
zdialog_stuff(zd,"newname",newname); | ||||
// also basis for new name | ||||
zdialog_run(zd,rename_folder_dialog_event); | ||||
zstat = zdialog_wait(zd); | ||||
Fblock("rename folder",0); | ||||
zdialog_fetch(zd,"newname",newname,XFCC); | ||||
// get new folder name | ||||
zdialog_free(zd); | ||||
if (zstat != 1) return; | ||||
if (strmatch(oldname,newname)) { | ||||
zmessageACK(Mwin,"name not changed"); | ||||
return; | ||||
} | ||||
err = rename(oldname,newname); | ||||
// do folder rename | ||||
if (err) { | ||||
zmessageACK(Mwin,"rename failed: %s",strerror(errno)); | ||||
return; | ||||
} | ||||
zmessageACK(Mwin,"folder renamed: \n %s",newname); | ||||
zmessage_post(Mwin,"parent",3,"updating index and albums"); | ||||
zmainsleep(3); | ||||
m_quick_index(0,0); | ||||
// re-index after folder rename | ||||
album_folder_rename(oldname,newname); | ||||
// update filenames in album files | ||||
gallery(newname,"init",0); | ||||
// refresh gallery | ||||
gallery(0,"paint",-1); | ||||
return; | return; | |||
} | } | |||
// zdialog event and completion function | ||||
int rename_folder_dialog_event(zdialog *zd, cchar *event) | ||||
{ | ||||
if (zd->zstat) zdialog_destroy(zd); | ||||
return 1; | ||||
} | ||||
/******************************************************************************* | ||||
*/ | ||||
// create a new subfolder under the current folder | ||||
void m_add_subfolder(GtkWidget *, cchar *menu) | ||||
// 22.11 | ||||
{ | ||||
int add_subfolder_dialog_event(zdialog *zd, cchar *event); | ||||
zdialog *zd; | ||||
int zstat, err; | ||||
char pathname[XFCC], subfolder[100]; | ||||
F1_help_topic = "add subfolder"; | ||||
Plog(1,"m_add_subfolder \n"); | ||||
if (! galleryname) { | ||||
zmessageACK(Mwin,"no current gallery"); | ||||
return; | ||||
} | ||||
if (gallerytype != FOLDER) { | ||||
zmessageACK(Mwin,"current gallery is not a folder (file directory)"); | ||||
return; | ||||
} | ||||
/*** | ||||
_________________________________________ | ||||
| Add Subfolder | | ||||
| | | ||||
| current folder [_____________________] | | ||||
| new subfolder [_____________________] | | ||||
| | | ||||
| [create] [cancel] | | ||||
|_________________________________________| | ||||
***/ | ||||
zd = zdialog_new("Add Subfolder",Mwin,"Create","Cancel"); | ||||
zdialog_add_widget(zd,"hbox","hbcf","dialog",0,"space=3"); | ||||
zdialog_add_widget(zd,"label","labcf","hbcf","current folder:","space=3"); | ||||
zdialog_add_widget(zd,"label","currfol","hbcf",0,"space=3"); | ||||
zdialog_add_widget(zd,"hbox","hbnsf","dialog",0,"space=3"); | ||||
zdialog_add_widget(zd,"label","labnsf","hbnsf","new subfolder","space=3"); | ||||
zdialog_add_widget(zd,"zentry","subfolder","hbnsf",0,"space=3|expand"); | ||||
zdialog_stuff(zd,"currfol",galleryname); | ||||
zdialog_run(zd,add_subfolder_dialog_event); | ||||
zstat = zdialog_wait(zd); | ||||
zdialog_fetch(zd,"subfolder",subfolder,100); | ||||
zdialog_free(zd); | ||||
if (zstat != 1) return; | ||||
if (*subfolder < ' ' || strchr(subfolder,'/')) { | ||||
zmessageACK(Mwin,"subfolder name is invalid"); | ||||
return; | ||||
} | ||||
*pathname = 0; | ||||
strncatv(pathname,XFCC,galleryname,"/",subfolder,0); | ||||
err = mkdir(pathname,0764); | ||||
if (err) { | ||||
zmessageACK(Mwin,"create folder failed: %s",strerror(errno)); | ||||
return; | ||||
} | ||||
gallery(galleryname,"init",0); | ||||
gallery(0,"paint",-1); | ||||
zmessageACK(Mwin,"new subfolder created: \n %s",pathname); | ||||
return; | ||||
} | ||||
// zdialog event and completion function | ||||
int add_subfolder_dialog_event(zdialog *zd, cchar *event) | ||||
{ | ||||
if (zd->zstat) zdialog_destroy(zd); | ||||
return 1; | ||||
} | ||||
/******************************************************************************* */ | /******************************************************************************* */ | |||
namespace bookmarknames | namespace bookmarknames | |||
{ | { | |||
#define maxbmks 50 | #define maxbmks 50 | |||
char *bookmarks[maxbmks]; // bookmark names and files | char *bookmarks[maxbmks]; // bookmark names and files | |||
int Nbmks; // count of entries | int Nbmks; // count of entries | |||
int bmkposn; // current entry, 0-last | int bmkposn; // current entry, 0-last | |||
zdialog *zd_bookmark; | zdialog *zd_bookmark; | |||
GtkWidget *textwidget; | GtkWidget *textwidget; | |||
skipping to change at line 5239 | skipping to change at line 5310 | |||
textwidget_clear(textwidget); // clear bookmarks list | textwidget_clear(textwidget); // clear bookmarks list | |||
for (int ii = 0; ii < Nbmks; ii++) { // write bookmarks list | for (int ii = 0; ii < Nbmks; ii++) { // write bookmarks list | |||
strncpy0(bookmarkline,bookmarks[ii],31); | strncpy0(bookmarkline,bookmarks[ii],31); | |||
cc = utf8len(bookmarkline); // compensate multibyte chars. | cc = utf8len(bookmarkline); // compensate multibyte chars. | |||
strncat(bookmarkline,blanks,32-cc); | strncat(bookmarkline,blanks,32-cc); | |||
strcat(bookmarkline,bookmarks[ii]+32); | strcat(bookmarkline,bookmarks[ii]+32); | |||
textwidget_append(textwidget,0,"%s\n",bookmarkline); | textwidget_append(textwidget,0,"%s\n",bookmarkline); | |||
} | } | |||
return; | return; | |||
} | } | |||
/******************************************************************************* | ||||
*/ | ||||
// set the video frame for a video thumbnail | ||||
// (video file popup menu) | ||||
void m_thumbframe(GtkWidget *, cchar *) | ||||
{ | ||||
zdialog *zd; | ||||
STATB statB; | ||||
int ftype, zstat, err; | ||||
int minutes, seconds; | ||||
char *pp, framefile[200]; | ||||
char *videofile = 0, thumbfile[XFCC]; | ||||
PXB *framepxb = 0, *thumbpxb = 0; | ||||
timeval thumbtimes[2]; | ||||
cchar *tip = "Play video and stop at desired frame \n" | ||||
"Note playback time in minutes and seconds"; | ||||
F1_help_topic = "video files"; | ||||
Plog(1,"m_thumbframe \n"); | ||||
if (clicked_file) { | ||||
// use clicked file if present | ||||
videofile = clicked_file; | ||||
clicked_file = 0; | ||||
} | ||||
else if (curr_file) | ||||
// else current file | ||||
videofile = zstrdup(curr_file,"thumbframe"); | ||||
else return; | ||||
ftype = image_file_type(videofile); | ||||
if (ftype != VIDEO) goto cleanup; | ||||
/** | ||||
____________________________________________ | ||||
| Set Video Thumbnail Frame | | ||||
| | | ||||
| Play video and stop at desired frame. | | ||||
| Playback time: minutes [__] seconds [__] | | ||||
| | | ||||
| [ OK ] [Cancel] | | ||||
|____________________________________________| | ||||
**/ | ||||
zd = zdialog_new("Set Video Thumbnail Frame",Mwin,"OK","Cancel",null); | ||||
zdialog_add_widget(zd,"label","labtip","dialog",tip); | ||||
zdialog_add_widget(zd,"hbox","hbtime","dialog",0,"space=3"); | ||||
zdialog_add_widget(zd,"label","labtime","hbtime","Playback time:","space=3"); | ||||
zdialog_add_widget(zd,"label","space","hbtime",0,"space=3"); | ||||
zdialog_add_widget(zd,"label","labmin","hbtime","minutes","space=3"); | ||||
zdialog_add_widget(zd,"zspin","minutes","hbtime","0|999|1|0","space=3|size=3" | ||||
); | ||||
zdialog_add_widget(zd,"label","space","hbtime",0,"space=3"); | ||||
zdialog_add_widget(zd,"label","labsec","hbtime","seconds","space=3"); | ||||
zdialog_add_widget(zd,"zspin","seconds","hbtime","0|59|1|0","space=3|size=3") | ||||
; | ||||
zdialog_run(zd,0,"parent"); | ||||
// run dialog and wait for completion | ||||
zstat = zdialog_wait(zd); | ||||
if (zstat != 1) { | ||||
// cancel | ||||
zdialog_free(zd); | ||||
goto cleanup; | ||||
} | ||||
zdialog_fetch(zd,"minutes",minutes); | ||||
// get playback time inputs | ||||
zdialog_fetch(zd,"seconds",seconds); | ||||
seconds = 60 * minutes + seconds; | ||||
zdialog_free(zd); | ||||
snprintf(framefile,200,"%s/videoframe.jpg",temp_folder); | ||||
// get frame file from ffmpeg | ||||
err = zshell("ack","ffmpeg -ss %d -i \"%s\" -v 8 -frames 1 -y \"%s\" ", | ||||
seconds, videofile, framefile); | ||||
if (err) goto cleanup; | ||||
if (! regfile(framefile)) { | ||||
zmessageACK(Mwin,"cannot create frame file: %s",strerror(errno)); | ||||
goto cleanup; | ||||
} | ||||
err = image2thumbfile2(videofile,thumbfile); | ||||
// get thumbnail file for video file | ||||
if (err) { | ||||
zmessageACK(Mwin,"cannot create thumbnail file"); | ||||
goto cleanup; | ||||
} | ||||
pp = strrchr(thumbfile+1,'/'); | ||||
*pp = 0; | ||||
if (! dirfile(thumbfile)) { | ||||
// create thumbnail folder if needed | ||||
err = zshell("ack","mkdir -p -m 0750 \"%s\"",thumbfile); | ||||
if (err) goto cleanup; | ||||
} | ||||
*pp = '/'; | ||||
framepxb = PXB_load(framefile,1); | ||||
// video frame file >> PXB image | ||||
if (! framepxb) goto cleanup; | ||||
thumbpxb = PXB_resize(framepxb,thumbfilesize); | ||||
// resize PXB to thumbnail size | ||||
if (! thumbpxb) goto cleanup; | ||||
err = PXB_JPG_save(thumbpxb,thumbfile,80); | ||||
// save to JPEG thumbnail file | ||||
if (err) goto cleanup; | ||||
if (! regfile(videofile,&statB)) goto cleanup; | ||||
// get video file mod time | ||||
thumbtimes[0].tv_sec = thumbtimes[1].tv_sec = statB.st_mtim.tv_sec; | ||||
// thumbnail mod time | ||||
thumbtimes[0].tv_usec = thumbtimes[1].tv_usec = 0; | ||||
// = video file mod time | ||||
utimes(thumbfile,thumbtimes); | ||||
replace_cache_thumb(videofile,thumbpxb); | ||||
// replace cache thumbnail | ||||
gallery(0,"paint",-1); | ||||
// repaint gallery | ||||
cleanup: | ||||
remove(framefile); | ||||
if (videofile) zfree(videofile); | ||||
if (framepxb) PXB_free(framepxb); | ||||
if (thumbpxb) PXB_free(thumbpxb); | ||||
return; | ||||
} | ||||
/******************************************************************************* | ||||
*/ | ||||
// dummy menu entry as target for "Show Hidden Files" KB shortcut | ||||
void m_show_hidden(GtkWidget *, cchar *) | ||||
{ | ||||
Plog(1,"m_show_hidden \n"); | ||||
KBaction("Show Hidden"); | ||||
return; | ||||
} | ||||
/******************************************************************************* | ||||
*/ | ||||
// dummy menu entry as target for "Current Album" KB shortcut | ||||
void m_current_album(GtkWidget *, cchar *) | ||||
{ | ||||
Plog(1,"m_current_album \n"); | ||||
navi::newalbum_menu_event(0,0); | ||||
return; | ||||
} | ||||
End of changes. 145 change blocks. | ||||
763 lines changed or deleted | 849 lines changed or added |