"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "f.gallery.cc" between
fotoxx-22.30.tar.gz and fotoxx-22.35.tar.gz

About: fotoxx is a program for photo editing and collection management.

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

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)