add bins/folders, fix listbox bad wdw ref, hide vicons fix, remove sort by time
authorGood Guy <good1.2guy@gmail.com>
Thu, 16 Aug 2018 19:11:00 +0000 (13:11 -0600)
committerGood Guy <good1.2guy@gmail.com>
Thu, 16 Aug 2018 19:11:00 +0000 (13:11 -0600)
46 files changed:
cinelerra-5.1/cinelerra/Makefile
cinelerra-5.1/cinelerra/asset.C
cinelerra-5.1/cinelerra/assetpopup.C
cinelerra-5.1/cinelerra/assetpopup.h
cinelerra-5.1/cinelerra/assetpopup.inc
cinelerra-5.1/cinelerra/awindow.C
cinelerra-5.1/cinelerra/awindow.h
cinelerra-5.1/cinelerra/awindowgui.C
cinelerra-5.1/cinelerra/awindowgui.h
cinelerra-5.1/cinelerra/batchrender.C
cinelerra-5.1/cinelerra/binfolder.C [new file with mode: 0644]
cinelerra-5.1/cinelerra/binfolder.h [new file with mode: 0644]
cinelerra-5.1/cinelerra/binfolder.inc [new file with mode: 0644]
cinelerra-5.1/cinelerra/brender.h
cinelerra-5.1/cinelerra/clippopup.C
cinelerra-5.1/cinelerra/edl.C
cinelerra-5.1/cinelerra/edl.h
cinelerra-5.1/cinelerra/edl.inc
cinelerra-5.1/cinelerra/edlsession.C
cinelerra-5.1/cinelerra/folderlistmenu.C
cinelerra-5.1/cinelerra/folderlistmenu.h
cinelerra-5.1/cinelerra/indexable.C
cinelerra-5.1/cinelerra/localsession.C
cinelerra-5.1/cinelerra/localsession.h
cinelerra-5.1/cinelerra/mainsession.C
cinelerra-5.1/cinelerra/mainsession.h
cinelerra-5.1/cinelerra/messages.C
cinelerra-5.1/cinelerra/mwindow.h
cinelerra-5.1/cinelerra/mwindowedit.C
cinelerra-5.1/cinelerra/newfolder.C [deleted file]
cinelerra-5.1/cinelerra/newfolder.h [deleted file]
cinelerra-5.1/cinelerra/newfolder.inc [deleted file]
cinelerra-5.1/cinelerra/pluginclient.h
cinelerra-5.1/cinelerra/pluginmessages.C
cinelerra-5.1/cinelerra/pluginmessages.h
cinelerra-5.1/cinelerra/pluginserver.h
cinelerra-5.1/cinelerra/proxypopup.C
cinelerra-5.1/cinelerra/recordmonitor.h
cinelerra-5.1/cinelerra/renderfarmclient.C
cinelerra-5.1/guicast/bclistbox.C
cinelerra-5.1/guicast/bclistbox.h
cinelerra-5.1/guicast/bcwindowbase.C
cinelerra-5.1/guicast/bcwindowbase.h
cinelerra-5.1/guicast/bcwindowevents.h
cinelerra-5.1/guicast/vicon.C
cinelerra-5.1/guicast/vicon.h

index 18590e3a99095c45e628328959ded3b14f0667be..5f7bcbdb2a46af20e765cafb5e37c1a45e961c6b 100644 (file)
@@ -44,6 +44,7 @@ OBJS := \
        $(OBJDIR)/batch.o \
        $(OBJDIR)/batchrender.o \
        $(OBJDIR)/bdcreate.o \
+       $(OBJDIR)/binfolder.o \
        $(OBJDIR)/bitspopup.o \
        $(OBJDIR)/brender.o \
        $(OBJDIR)/browsebutton.o \
@@ -187,7 +188,6 @@ OBJS := \
        $(OBJDIR)/mwindowgui.o \
        $(OBJDIR)/mwindowmove.o \
        $(OBJDIR)/mwindow.o \
-       $(OBJDIR)/newfolder.o \
        $(OBJDIR)/new.o \
        $(OBJDIR)/overlaydirect.o \
        $(OBJDIR)/overlayframe.o \
index 4b42feff174dc601e3ceef53908c89d335158b0e..ec82d0e9e6ead12eb2d7e245f161a5579303b35b 100644 (file)
@@ -459,9 +459,7 @@ int Asset::read(FileXML *file,
                        else
                        if(file->tag.title_is("FOLDER"))
                        {
-                               const char *string = file->tag.get_property("NUMBER");
-                               awindow_folder = string ? atoi(string) :
-                                       AWindowGUI::folder_number(file->read_text());
+                               awindow_folder = file->tag.get_property("NUMBER", AW_MEDIA_FOLDER);
                        }
                        else
                        if(file->tag.title_is("VIDEO"))
index 59357d184851754ac3c031c508e95c92f0aac12a..953a794bed6267ebcdb4fc87761b434d8657ff4b 100644 (file)
@@ -76,10 +76,7 @@ void AssetPopup::create_objects()
        BC_SubMenu *submenu;
        add_item(info = new AssetPopupInfo(mwindow, this));
        add_item(format = new AWindowListFormat(mwindow, gui));
-       add_item(menu_item = new BC_MenuItem(_("Sort...")));
-       menu_item->add_submenu(submenu = new BC_SubMenu());
-       submenu->add_submenuitem(new AssetPopupSortNames(mwindow, this));
-       submenu->add_submenuitem(new AssetPopupSortTimes(mwindow, this));
+       add_item(new AssetPopupSort(mwindow, this));
        add_item(index = new AssetPopupBuildIndex(mwindow, this));
        add_item(view = new AssetPopupView(mwindow, this));
        add_item(view_window = new AssetPopupViewWindow(mwindow, this));
@@ -200,37 +197,20 @@ int AssetPopupBuildIndex::handle_event()
 }
 
 
-AssetPopupSortNames::AssetPopupSortNames(MWindow *mwindow, AssetPopup *popup)
- : BC_MenuItem(_("Sort names"))
-{
-       this->mwindow = mwindow;
-       this->popup = popup;
-}
-
-AssetPopupSortNames::~AssetPopupSortNames()
-{
-}
-
-int AssetPopupSortNames::handle_event()
-{
-       mwindow->awindow->gui->sort_assets(0);
-       return 1;
-}
-
-AssetPopupSortTimes::AssetPopupSortTimes(MWindow *mwindow, AssetPopup *popup)
- : BC_MenuItem(_("Sort times"))
+AssetPopupSort::AssetPopupSort(MWindow *mwindow, AssetPopup *popup)
+ : BC_MenuItem(_("Sort"))
 {
        this->mwindow = mwindow;
        this->popup = popup;
 }
 
-AssetPopupSortTimes::~AssetPopupSortTimes()
+AssetPopupSort::~AssetPopupSort()
 {
 }
 
-int AssetPopupSortTimes::handle_event()
+int AssetPopupSort::handle_event()
 {
-       mwindow->awindow->gui->sort_assets(1);
+       mwindow->awindow->gui->sort_assets();
        return 1;
 }
 
index 0720d9d2b57d5143e546ed00121cbf5312fbaef1..129cd335f0ff29e44c67db6098b4577512c90195 100644 (file)
@@ -71,23 +71,11 @@ public:
        AssetPopup *popup;
 };
 
-class AssetPopupSortNames : public BC_MenuItem
+class AssetPopupSort : public BC_MenuItem
 {
 public:
-       AssetPopupSortNames(MWindow *mwindow, AssetPopup *popup);
-       ~AssetPopupSortNames();
-
-       int handle_event();
-
-       MWindow *mwindow;
-       AssetPopup *popup;
-};
-
-class AssetPopupSortTimes : public BC_MenuItem
-{
-public:
-       AssetPopupSortTimes(MWindow *mwindow, AssetPopup *popup);
-       ~AssetPopupSortTimes();
+       AssetPopupSort(MWindow *mwindow, AssetPopup *popup);
+       ~AssetPopupSort();
 
        int handle_event();
 
index ba60f99c3e0f9bbf1c78410e125690ef73448bec..aeeb5d3fd4b70a09f313cc05edcc6f46db9578ec 100644 (file)
@@ -38,7 +38,6 @@ class AssetPopupSort;
 class AssetPopupBuildIndex;
 class AssetPopupView;
 class AssetPopupViewWindow;
-class AssetPopupLoadFile;
 class AssetPopupMixer;
 class AssetPopupPaste;
 class AssetMatchSize;
@@ -47,6 +46,7 @@ class AssetMatchAll;
 class AssetPopupProjectRemove;
 class AssetPopupDiskRemove;
 class AssetListMenu;
+class AssetPopupLoadFile;
 class AssetListCopy;
 class AssetCopyDialog;
 class AssetCopyWindow;
index d5f3204cc93df3a146c31bff7c7a976c9c9e1f0a..53d72903204311b21d4198f9f33f8cdb2b7b98c7 100644 (file)
@@ -33,7 +33,6 @@ AWindow::AWindow(MWindow *mwindow)
  : Thread(1, 0, 0)
 {
        this->mwindow = mwindow;
-       current_folder[0] = 0;
        asset_remove = 0;
        clip_edit = 0;
        label_edit = 0;
index 40410b537f9a428facaf5c507f608f15fa561a9f..6691e5ec1ae6202d9a1ef62bf93ebedb42929df8 100644 (file)
@@ -47,8 +47,6 @@ public:
        int load_defaults(BC_Hash *defaults);
        int save_defaults(BC_Hash *defaults);
 
-       char current_folder[BCTEXTLEN];
-
        AWindowGUI *gui;
        MWindow *mwindow;
        ArrayList<AssetEdit*> asset_editors;
index 4b9a912d3fd8774f77b23ef2cd38393d156560e2..fceeb04c3459361ecba4e9601fecb74c104ad38e 100644 (file)
@@ -30,6 +30,7 @@
 #include "bccmodels.h"
 #include "bcsignals.h"
 #include "bchash.h"
+#include "binfolder.h"
 #include "cache.h"
 #include "cstrdup.h"
 #include "clip.h"
@@ -54,7 +55,6 @@
 #include "mainsession.h"
 #include "mwindowgui.h"
 #include "mwindow.h"
-#include "newfolder.h"
 #include "preferences.h"
 #include "proxy.h"
 #include "proxypopup.h"
@@ -333,6 +333,17 @@ AssetPicon::AssetPicon(MWindow *mwindow,
        persistent = persist;
 }
 
+AssetPicon::AssetPicon(MWindow *mwindow,
+       AWindowGUI *gui, int folder, const char *title)
+ : BC_ListBoxItem(title, gui->folder_icon)
+{
+       reset();
+       foldernum = folder;
+       this->mwindow = mwindow;
+       this->gui = gui;
+       persistent = 0;
+}
+
 AssetPicon::AssetPicon(MWindow *mwindow,
        AWindowGUI *gui, PluginServer *plugin)
  : BC_ListBoxItem()
@@ -421,11 +432,12 @@ void AssetPicon::reset()
        indexable = 0;
        edl = 0;
        foldernum = AW_NO_FOLDER;
+       sort_key = -1;
        icon = 0;
        icon_vframe = 0;
        vicon = 0;
        in_use = 1;
-       mtime = 0;
+       comments_time = 0;
        id = 0;
        persistent = 0;
 }
@@ -612,7 +624,7 @@ void AssetPicon::create_objects()
 
                }
                struct stat st;
-               mtime = !stat(asset->path, &st) ? st.st_mtime : 0;
+               comments_time = !stat(asset->path, &st) ? st.st_mtime : 0;
        }
        else
        if( indexable && !indexable->is_asset ) {
@@ -838,7 +850,6 @@ AWindowGUI::AWindowGUI(MWindow *mwindow, AWindow *awindow)
        veffect_vframe = 0;             veffect_icon = 0;
 
        plugin_visibility = ((uint64_t)1<<(8*sizeof(uint64_t)-1))-1;
-       newfolder_thread = 0;
        asset_menu = 0;
        effectlist_menu = 0;
        assetlist_menu = 0;
@@ -854,6 +865,8 @@ AWindowGUI::AWindowGUI(MWindow *mwindow, AWindow *awindow)
        vicon_audio = 0;
        vicon_drawing = 1;
        displayed_folder = AW_NO_FOLDER;
+       new_folder_thread = 0;
+       modify_folder_thread = 0;
        folder_lock = new Mutex("AWindowGUI::folder_lock");
 }
 
@@ -868,9 +881,10 @@ AWindowGUI::~AWindowGUI()
        labellist.remove_all_objects();
        displayed_assets[1].remove_all_objects();
 
+       delete new_folder_thread;
+       delete modify_folder_thread;
        delete vicon_thread;
        delete vicon_audio;
-       delete newfolder_thread;
 
        delete search_text;
        delete temp_picon;
@@ -1023,6 +1037,8 @@ void AWindowGUI::create_objects()
 
        mwindow->theme->get_awindow_sizes(this);
        load_defaults(mwindow->defaults);
+       new_folder_thread = new NewFolderThread(this);
+       modify_folder_thread = new ModifyFolderThread(this);
 
        int x1 = mwindow->theme->alist_x, y1 = mwindow->theme->alist_y;
        int w1 = mwindow->theme->alist_w, h1 = mwindow->theme->alist_h;
@@ -1059,9 +1075,6 @@ void AWindowGUI::create_objects()
        //int x = mwindow->theme->abuttons_x;
        //int y = mwindow->theme->abuttons_y;
 
-
-       newfolder_thread = new NewFolderThread(mwindow, this);
-
        add_subwindow(asset_menu = new AssetPopup(mwindow, this));
        asset_menu->create_objects();
        add_subwindow(clip_menu = new ClipPopup(mwindow, this));
@@ -1185,15 +1198,17 @@ int AWindowGUI::close_event()
 void AWindowGUI::start_vicon_drawing()
 {
        if( !vicon_drawing ) return;
-       if( mwindow->edl->session->awindow_folder != AW_MEDIA_FOLDER ) return;
-       switch( mwindow->edl->session->assetlist_format ) {
-       case ASSETS_ICONS:
-       case ASSETS_ICONS_PACKED:
-       case ASSETS_ICON_LIST:
-               vicon_thread->start_drawing();
-               break;
-       default:
-               break;
+       if( mwindow->edl->session->awindow_folder == AW_MEDIA_FOLDER ||
+           mwindow->edl->session->awindow_folder >= AWINDOW_USER_FOLDERS ) {
+               switch( mwindow->edl->session->assetlist_format ) {
+               case ASSETS_ICONS:
+               case ASSETS_ICONS_PACKED:
+               case ASSETS_ICON_LIST:
+                       vicon_thread->start_drawing();
+                       break;
+               default:
+                       break;
+               }
        }
 }
 
@@ -1392,7 +1407,7 @@ int AWindowGUI::create_custom_xatoms()
        UpdateAssetsXAtom = create_xatom("CWINDOWGUI_UPDATE_ASSETS");
        return 0;
 }
-int AWindowGUI::recieve_custom_xatoms(xatom_event *event)
+int AWindowGUI::receive_custom_xatoms(xatom_event *event)
 {
        if( event->message_type == UpdateAssetsXAtom ) {
                update_assets();
@@ -1418,12 +1433,12 @@ void AWindowGUI::update_folder_list()
 
 // Search assets for folders
        for( int i = 0; i < mwindow->edl->folders.total; i++ ) {
-               const char *folder = mwindow->edl->folders.values[i];
+               BinFolder *bin_folder = mwindow->edl->folders[i];
                int exists = 0;
 
                for( int j = 0; j < folders.total; j++ ) {
-                       AssetPicon *picon = (AssetPicon*)folders.values[j];
-                       if( !strcasecmp(picon->get_text(), folder) ) {
+                       AssetPicon *picon = (AssetPicon*)folders[j];
+                       if( !strcasecmp(picon->get_text(), bin_folder->title) ) {
                                exists = 1;
                                picon->in_use = 1;
                                break;
@@ -1431,12 +1446,11 @@ void AWindowGUI::update_folder_list()
                }
 
                if( !exists ) {
-                       int aw_folder = folder_number(folder);
-                       if( aw_folder >= 0 ) {
-                               AssetPicon *picon = new AssetPicon(mwindow, this, aw_folder, 1);
-                               picon->create_objects();
-                               folders.append(picon);
-                       }
+                       const char *title = bin_folder->title;
+                       int folder = bin_folder->awindow_folder;
+                       AssetPicon *picon = new AssetPicon(mwindow, this, folder, title);
+                       picon->create_objects();
+                       folders.append(picon);
                }
        }
 
@@ -1578,9 +1592,11 @@ void AWindowGUI::update_asset_list()
                        assets.remove_number(i);
                        continue;
                }
-               if( !picon->indexable || !picon->indexable->is_asset ) continue;
-               struct stat st;
-               picon->mtime = !stat(picon->indexable->path, &st) ? st.st_mtime : 0;
+               if( picon->indexable && picon->indexable->is_asset ) {
+                       struct stat st;
+                       picon->comments_time = !stat(picon->indexable->path, &st) ?
+                               st.st_mtime : 0;
+               }
        }
 }
 
@@ -1607,7 +1623,7 @@ void AWindowGUI::update_picon(Indexable *indexable)
        }
 }
 
-void AWindowGUI::sort_assets(int use_mtime)
+void AWindowGUI::sort_assets()
 {
        folder_lock->lock("AWindowGUI::sort_assets");
        switch( mwindow->edl->session->awindow_folder ) {
@@ -1627,7 +1643,7 @@ void AWindowGUI::sort_assets(int use_mtime)
                sort_picons(&labellist);
                break;
        default:
-               sort_picons(&assets, use_mtime);
+               sort_picons(&assets);
                break;
        }
 // reset xyposition
@@ -1677,6 +1693,7 @@ EDL *AWindowGUI::collect_proxy(Indexable *indexable)
                if( current->data_type != TRACK_AUDIO ) continue;
                current->insert_asset(unproxy_asset, 0, length, 0, atrack++);
        }
+       proxy_edl->awindow_folder = AW_PROXY_FOLDER;
        return proxy_edl;
 }
 
@@ -1714,14 +1731,25 @@ void AWindowGUI::copy_picons(ArrayList<BC_ListBoxItem*> *dst,
 
 // Create new pointers
        for( int i = 0; i < src->total; i++ ) {
+               int visible = folder < 0 ? 1 : 0;
                AssetPicon *picon = (AssetPicon*)src->values[i];
-               if( folder < 0 ||
-                   (picon->indexable && picon->indexable->awindow_folder == folder) ||
-                   (picon->edl && picon->edl->local_session->awindow_folder == folder) ) {
+               picon->sort_key = -1;
+               if( !visible && folder >= AWINDOW_USER_FOLDERS && picon->indexable ) {
+                       picon->sort_key = mwindow->edl->folders.matches_indexable(folder, picon->indexable);
+                       if( picon->sort_key >= 0 ) visible = 1;
+               }
+               if( !visible && picon->indexable && picon->indexable->awindow_folder == folder )
+                       visible = 1;
+               if( !visible && picon->edl && picon->edl->awindow_folder == folder )
+                       visible = 1;
+               if( visible ) {
                        const char *text = search_text->get_text();
-                       int hidden = text && text[0] && !bstrcasestr(picon->get_text(), text);
-                       if( picon->vicon ) picon->vicon->hidden = hidden;
-                       if( hidden ) continue;
+                       if( text && text[0] )
+                               visible = bstrcasestr(picon->get_text(), text) ? 1 : 0;
+               }
+               if( picon->vicon )
+                       picon->vicon->hidden = !visible ? 1 : 0;
+               if( visible ) {
                        BC_ListBoxItem *item2, *item1;
                        dst[0].append(item1 = picon);
                        if( picon->edl )
@@ -1729,9 +1757,9 @@ void AWindowGUI::copy_picons(ArrayList<BC_ListBoxItem*> *dst,
                        else
                        if( picon->label )
                                dst[1].append(item2 = new BC_ListBoxItem(picon->label->textstr));
-                       else if( picon->mtime ) {
+                       else if( picon->comments_time ) {
                                char date_time[BCSTRLEN];
-                               struct tm stm;  localtime_r(&picon->mtime, &stm);
+                               struct tm stm;  localtime_r(&picon->comments_time, &stm);
                                sprintf(date_time,"%04d.%02d.%02d %02d:%02d:%02d",
                                         stm.tm_year+1900, stm.tm_mon+1, stm.tm_mday,
                                         stm.tm_hour, stm.tm_min, stm.tm_sec);
@@ -1745,7 +1773,7 @@ void AWindowGUI::copy_picons(ArrayList<BC_ListBoxItem*> *dst,
        }
 }
 
-void AWindowGUI::sort_picons(ArrayList<BC_ListBoxItem*> *src, int use_mtime)
+void AWindowGUI::sort_picons(ArrayList<BC_ListBoxItem*> *src)
 {
        int done = 0, changed = 0;
        while( !done ) {
@@ -1753,12 +1781,20 @@ void AWindowGUI::sort_picons(ArrayList<BC_ListBoxItem*> *src, int use_mtime)
                for( int i=0; i<src->total-1; ++i ) {
                        AssetPicon *item1 = (AssetPicon *)src->values[i];
                        AssetPicon *item2 = (AssetPicon *)src->values[i + 1];
-                       if( use_mtime ? item1->mtime > item2->mtime :
-                           strcmp(item1->get_text(), item2->get_text()) > 0 ) {
-                               src->values[i + 1] = item1;
-                               src->values[i] = item2;
-                               done = 0;  changed = 1;
+                       double v = item2->sort_key - item1->sort_key;
+                       if( v > 0 ) continue;
+                       if( v == 0 ) {
+                               const char *cp1 = item1->get_text();
+                               const char *bp1 = strrchr(cp1, '/');
+                               if( bp1 ) cp1 = bp1 + 1;
+                               const char *cp2 = item2->get_text();
+                               const char *bp2 = strrchr(cp2, '/');
+                               if( bp2 ) cp2 = bp2 + 1;
+                               if( strcmp(cp2, cp1) >= 0 ) continue;
                        }
+                       src->values[i + 1] = item1;
+                       src->values[i] = item2;
+                       done = 0;  changed = 1;
                }
        }
        if( changed ) {
@@ -1770,7 +1806,6 @@ void AWindowGUI::sort_picons(ArrayList<BC_ListBoxItem*> *src, int use_mtime)
        }
 }
 
-
 void AWindowGUI::filter_displayed_assets()
 {
        //allow_iconlisting = 1;
@@ -1822,6 +1857,7 @@ void AWindowGUI::update_assets()
 
        if( displayed_folder != mwindow->edl->session->awindow_folder )
                search_text->clear();
+       vicon_thread->hide_vicons();
        filter_displayed_assets();
        folder_lock->unlock();
 
@@ -1868,14 +1904,6 @@ void AWindowGUI::update_effects()
        create_persistent_folder(&vtransitions, 0, 1, 0, 1);
 }
 
-int AWindowGUI::folder_number(const char *name)
-{
-       for( int i = 0; i < AWINDOW_FOLDERS; i++ ) {
-               if( !strcasecmp(name, folder_names[i]) ) return i;
-       }
-       return AW_NO_FOLDER;
-}
-
 int AWindowGUI::drag_motion()
 {
        if( get_hidden() ) return 0;
@@ -2025,10 +2053,25 @@ int AWindowFolders::button_press_event()
        return result;
 }
 
-
-
-
-
+int AWindowFolders::drag_stop()
+{
+       int result = 0;
+       if( get_hidden() ) return 0;
+       if( mwindow->session->current_operation == DRAG_ASSET &&
+           gui->folder_list->cursor_above() ) { // check user folder
+               int item_no = gui->folder_list->get_cursor_item();
+               AssetPicon *picon = (AssetPicon *)(item_no < 0 ? 0 : gui->folders[item_no]);
+               if( picon && picon->foldernum >= AWINDOW_USER_FOLDERS ) {
+                       BinFolder *folder = mwindow->edl->get_folder(picon->foldernum);
+                       ArrayList<Indexable *> *drags = mwindow->session->drag_assets;
+                       if( folder && drags ) folder->add_patterns(drags);
+                       mwindow->session->current_operation = ::NO_OPERATION;
+                       flicker(1,30);
+                       result = 1;
+               }
+       }
+       return result;
+}
 
 
 AWindowAssets::AWindowAssets(MWindow *mwindow, AWindowGUI *gui, int x, int y, int w, int h)
@@ -2086,10 +2129,12 @@ int AWindowAssets::button_press_event()
                        gui->proxylist_menu->update();
                        gui->proxylist_menu->activate_menu();
                        break;
-               case AW_MEDIA_FOLDER:
-                       gui->assetlist_menu->update_titles(folder==AW_MEDIA_FOLDER);
+               default:
+               case AW_MEDIA_FOLDER: {
+                       int shots =  folder==AW_MEDIA_FOLDER || folder>=AWINDOW_USER_FOLDERS;
+                       gui->assetlist_menu->update_titles(shots);
                        gui->assetlist_menu->activate_menu();
-                       break;
+                       break; }
                }
                result = 1;
        }
@@ -2186,11 +2231,10 @@ void AWindowAssets::draw_background()
        clear_box(0,0,get_w(),get_h(),get_bg_surface());
        set_color(BC_WindowBase::get_resources()->audiovideo_color);
        set_font(LARGEFONT);
-       int aw_folder = mwindow->edl->session->awindow_folder;
-       if( aw_folder < 0 ) return;
-       const char *aw_name = _(AWindowGUI::folder_names[aw_folder]);
-       draw_text(get_w() - get_text_width(LARGEFONT, aw_name) - 4, 30,
-               aw_name, -1, get_bg_surface());
+       int folder = mwindow->edl->session->awindow_folder;
+       const char *title = mwindow->edl->get_folder_name(folder);
+       draw_text(get_w() - get_text_width(LARGEFONT, title) - 4, 30,
+               title, -1, get_bg_surface());
 }
 
 int AWindowAssets::drag_start_event()
@@ -2272,6 +2316,18 @@ int AWindowAssets::drag_motion_event()
        mwindow->cwindow->gui->unlock_window();
 
        lock_window("AWindowAssets::drag_motion_event");
+       if( mwindow->session->current_operation == DRAG_ASSET &&
+           gui->folder_list->cursor_above() ) { // highlight user folder
+               int item_no = gui->folder_list->get_cursor_item();
+               if( item_no >= 0 ) {
+                       AssetPicon *folder = (AssetPicon *)gui->folders[item_no];
+                       if( folder->foldernum < AWINDOW_USER_FOLDERS ) item_no = -1;
+               }
+               int folder_xposition = gui->folder_list->get_xposition();
+               int folder_yposition = gui->folder_list->get_yposition();
+               gui->folder_list->update(&gui->folders, 0, 0, 1,
+                       folder_xposition, folder_yposition, item_no, 0, 1);
+       }
        return 0;
 }
 
@@ -2311,6 +2367,10 @@ int AWindowAssets::drag_stop_event()
        }
 
        lock_window("AWindowAssets::drag_stop_event");
+       if( !result ) {
+               result = gui->folder_list->drag_stop();
+       }
+
 
        if( result )
                get_drag_popup()->set_animation(0);
@@ -2405,50 +2465,6 @@ void AWindowSearchText::clear()
        text_box->update("");
 }
 
-AWindowNewFolder::AWindowNewFolder(MWindow *mwindow, AWindowGUI *gui, int x, int y)
- : BC_Button(x, y, mwindow->theme->newbin_data)
-{
-       this->mwindow = mwindow;
-       this->gui = gui;
-       set_tooltip(_("New bin"));
-}
-
-int AWindowNewFolder::handle_event()
-{
-       gui->newfolder_thread->start_new_folder();
-       return 1;
-}
-
-AWindowDeleteFolder::AWindowDeleteFolder(MWindow *mwindow, AWindowGUI *gui, int x, int y)
- : BC_Button(x, y, mwindow->theme->deletebin_data)
-{
-       this->mwindow = mwindow;
-       this->gui = gui;
-       set_tooltip(_("Delete bin"));
-}
-
-int AWindowDeleteFolder::handle_event()
-{
-       if( gui->folder_list->get_selection(0, 0) ) {
-               BC_ListBoxItem *folder = gui->folder_list->get_selection(0, 0);
-               mwindow->delete_folder(folder->get_text());
-       }
-       return 1;
-}
-
-AWindowRenameFolder::AWindowRenameFolder(MWindow *mwindow, AWindowGUI *gui, int x, int y)
- : BC_Button(x, y, mwindow->theme->renamebin_data)
-{
-       this->mwindow = mwindow;
-       this->gui = gui;
-       set_tooltip(_("Rename bin"));
-}
-
-int AWindowRenameFolder::handle_event()
-{
-       return 1;
-}
-
 AWindowDeleteDisk::AWindowDeleteDisk(MWindow *mwindow, AWindowGUI *gui, int x, int y)
  : BC_Button(x, y, mwindow->theme->deletedisk_data)
 {
@@ -2688,7 +2704,7 @@ AWindowListSort::AWindowListSort(MWindow *mwindow, AWindowGUI *gui)
 
 int AWindowListSort::handle_event()
 {
-       gui->sort_assets(0);
+       gui->sort_assets();
        return 1;
 }
 
index 61ad3d77715132bf9300723d6efe579d4580c134..f768b586758138eada265f6786d94915b3cd1bac 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "arraylist.h"
 #include "bcdialog.h"
+#include "binfolder.inc"
 #include "assetpopup.inc"
 #include "asset.inc"
 #include "assets.inc"
@@ -41,7 +42,6 @@
 #include "indexable.inc"
 #include "mwindow.inc"
 #include "mutex.inc"
-#include "newfolder.inc"
 #include "pluginserver.inc"
 #include "proxypopup.inc"
 #include "renderengine.inc"
@@ -56,6 +56,7 @@ public:
        AssetPicon(MWindow *mwindow, AWindowGUI *gui, PluginServer *plugin);
        AssetPicon(MWindow *mwindow, AWindowGUI *gui, Label *plugin);
        AssetPicon(MWindow *mwindow, AWindowGUI *gui, int folder, int persist);
+       AssetPicon(MWindow *mwindow, AWindowGUI *gui, int folder, const char *title);
        virtual ~AssetPicon();
 
        void create_objects();
@@ -83,9 +84,9 @@ public:
        EDL *edl;
 
        int in_use;
-       time_t mtime;
-
        int persistent;
+       time_t comments_time;
+       double sort_key;
        PluginServer *plugin;
        Label *label;
        VIcon *vicon;
@@ -173,10 +174,9 @@ public:
        int keypress_event();
        void async_update_assets();     // Sends update asset event
        void update_effects();
-       void sort_assets(int use_mtime);
+       void sort_assets();
        void sort_folders();
        void reposition_objects();
-       static int folder_number(const char *name);
 // Call back for MWindow entry point
        int drag_motion();
        int drag_stop();
@@ -191,7 +191,7 @@ public:
        void create_label_folder();
        void copy_picons(ArrayList<BC_ListBoxItem*> *dst,
                ArrayList<BC_ListBoxItem*> *src, int folder);
-       void sort_picons(ArrayList<BC_ListBoxItem*> *src, int use_mtime=0);
+       void sort_picons(ArrayList<BC_ListBoxItem*> *src);
 // Return the selected asset in asset_list
        Indexable* selected_asset();
        PluginServer* selected_plugin();
@@ -262,8 +262,6 @@ public:
        BC_Pixmap *ff_aud_icon;       VFrame *ff_aud_vframe;
        BC_Pixmap *ff_vid_icon;       VFrame *ff_vid_vframe;
 
-       NewFolderThread *newfolder_thread;
-
 // Popup menus
        AssetPopup *asset_menu;
        ClipPopup *clip_menu;
@@ -290,9 +288,11 @@ public:
 
 // Create custom atoms to be used for async messages between windows
        int create_custom_xatoms();
-// Function to overload to recieve customly defined atoms
-       virtual int recieve_custom_xatoms(xatom_event *event);
+// Function to overload to receive customly defined atoms
+       virtual int receive_custom_xatoms(xatom_event *event);
        static const char *folder_names[];
+       NewFolderThread *new_folder_thread;
+       ModifyFolderThread *modify_folder_thread;
 
 private:
        void update_folder_list();
@@ -346,6 +346,7 @@ public:
 
        int selection_changed();
        int button_press_event();
+       int drag_stop();
 
        MWindow *mwindow;
        AWindowGUI *gui;
@@ -380,36 +381,6 @@ public:
        BC_TextBox *text_box;
 };
 
-class AWindowNewFolder : public BC_Button
-{
-public:
-       AWindowNewFolder(MWindow *mwindow, AWindowGUI *gui, int x, int y);
-       int handle_event();
-       MWindow *mwindow;
-       AWindowGUI *gui;
-       int x, y;
-};
-
-class AWindowDeleteFolder : public BC_Button
-{
-public:
-       AWindowDeleteFolder(MWindow *mwindow, AWindowGUI *gui, int x, int y);
-       int handle_event();
-       MWindow *mwindow;
-       AWindowGUI *gui;
-       int x, y;
-};
-
-class AWindowRenameFolder : public BC_Button
-{
-public:
-       AWindowRenameFolder(MWindow *mwindow, AWindowGUI *gui, int x, int y);
-       int handle_event();
-       MWindow *mwindow;
-       AWindowGUI *gui;
-       int x, y;
-};
-
 class AWindowDeleteDisk : public BC_Button
 {
 public:
index 4ac168f910891fd59e545b1043f3e2f1400deff1..4f685c285357de71bc0224ca23989c52080362b8 100644 (file)
@@ -1242,6 +1242,7 @@ int BatchRenderList::drag_stop_event()
                        thread->move_batch(src, dst);
                }
                BC_ListBox::drag_stop_event();
+               dragging_item = 0;
        }
        return 0;
 }
diff --git a/cinelerra-5.1/cinelerra/binfolder.C b/cinelerra-5.1/cinelerra/binfolder.C
new file mode 100644 (file)
index 0000000..f8d7943
--- /dev/null
@@ -0,0 +1,2163 @@
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "awindowgui.h"
+#include "bchash.h"
+#include "binfolder.h"
+#include "cstrdup.h"
+#include "edl.h"
+#include "filexml.h"
+#include "guicast.h"
+#include "indexable.h"
+#include "language.h"
+#include "mainerror.h"
+#include "mainsession.h"
+#include "mutex.h"
+#include "mwindow.h"
+
+#include <time.h>
+
+const char *BinFolderEnabled::types[] = {
+       N_("Off"),
+       N_("And"),
+       N_("Or"),
+       N_("And Not"),
+       N_("Or Not"),
+};
+
+const char *BinFolderTarget::types[] = {
+       N_("Patterns"),
+       N_("Filesize"),
+       N_("Time"),
+       N_("Track type"),
+       N_("Width"),
+       N_("Height"),
+       N_("Framerate"),
+       N_("Samplerate"),
+       N_("Channels"),
+       N_("Duration"),
+};
+
+const char *BinFolderOp::types[] = {
+       N_("Around"),
+       N_("Eq"),
+       N_("Ge"),
+       N_("Gt"),
+       N_("Ne"),
+       N_("Le"),
+       N_("Lt"),
+       N_("Matches"),
+};
+
+static const struct {
+       const char *sfx, *sfxs;
+       double radix;
+} scan_ranges[] = {
+       { N_("min"),   N_("mins"),   60, },
+       { N_("hour"),  N_("hours"),  60*60, },
+       { N_("day"),   N_("days"),   24*60*60, },
+       { N_("week"),  N_("weeks"),  24*60*60*7, },
+       { N_("month"), N_("months"), 24*60*60*31, },
+       { N_("year"),  N_("years"),  24*60*60*365.25, },
+};
+#define SCAN_RANGE_DAYS 2
+#define DBL_INF 9007199254740991.
+
+static int scan_inf(const char *cp, char *&bp)
+{
+       bp = (char *)cp;
+       const char *inf = _("inf");
+       const int linf = strlen(inf);
+       if( strncasecmp(cp,inf,linf) ) return 0;
+       bp = (char *)(cp + linf);
+       return 1;
+}
+
+static double scan_no(const char *cp, char *&bp)
+{
+       while( *cp == ' ' ) ++cp;
+       if( scan_inf(cp, bp) ) return DBL_INF;
+       if( *cp == '+' ) return 0;
+       double v = strtod(cp, &bp);
+       switch( *bp ) {
+       case 'T': v *= 1099511627776.;  break;
+       case 't': v *= 1e12;            break;
+       case 'G': v *= 1073741824.;     break;
+       case 'g': v *= 1e9;             break;
+       case 'M': v *= 1048576.;        break;
+       case 'm': v *= 1e6;             break;
+       case 'K': v *= 1024.;           break;
+       case 'k': v *= 1e3;             break;
+       default:  return v;
+       }
+       ++bp;
+       return v;
+}
+
+static void scan_around(const char *cp, char *&bp, double &v, double &a)
+{
+       v = 0;  a = -1;
+       double sv = scan_no(cp, bp);
+       if( bp > cp ) v = sv;
+       if( *bp == '+' ) {
+               double sa = scan_no(cp=bp+1, bp);
+               if( bp > cp ) a = sa;
+       }
+}
+
+static void show_no(double v, char *&cp, char *ep, const char *fmt="%0.0f")
+{
+       if( v == DBL_INF ) {
+               cp += snprintf(cp, ep-cp, "%s", _("inf"));
+               return;
+       }
+       const char *sfx = 0;
+       static const struct { double radix; const char *sfx; } sfxs[] = {
+               { 1024.,          "K" }, { 1e3,  "k" },
+               { 1048576.,       "M" }, { 1e6,  "m" },
+               { 1073741824.,    "G" }, { 1e9,  "g" },
+               { 1099511627776., "T" }, { 1e12, "t" },
+       };
+       for( int i=sizeof(sfxs)/sizeof(sfxs[0]); --i>=0; ) {
+               if( v < sfxs[i].radix ) continue;
+               if( fmod(v, sfxs[i].radix) == 0 ) {
+                       v /= sfxs[i].radix;
+                       sfx = sfxs[i].sfx;
+                       break;
+               }
+       }
+       cp += snprintf(cp, ep-cp, fmt, v);
+       if( sfx ) cp += snprintf(cp, ep-cp, "%s", sfx);
+}
+
+static double scan_duration(const char *cp, char *&bp)
+{
+       if( scan_inf(cp, bp) ) return DBL_INF;
+       double secs = 0;
+       while( *cp ) {
+               double v = strtod(cp, &bp);
+               if( cp >= bp ) break;
+               int k = sizeof(scan_ranges)/sizeof(scan_ranges[0]);
+               while( --k >= 0 ) {
+                       const char *tsfx  = _(scan_ranges[k].sfx);
+                       int lsfx  = strlen(tsfx), msfx  = strncasecmp(bp, tsfx,  lsfx);
+                       const char *tsfxs = _(scan_ranges[k].sfxs);
+                       int lsfxs = strlen(tsfxs), msfxs = strncasecmp(bp, tsfxs, lsfxs);
+                       int len = !msfx && !msfxs ? (lsfx > lsfxs ? lsfx : lsfxs) :
+                               !msfx ? lsfx : !msfxs ? lsfxs : -1;
+                       if( len >= 0 ) {
+                               secs += v * scan_ranges[k].radix;
+                               bp += len;
+                               break;
+                       }
+               }
+               if( k < 0 ) {
+                       int hour = 0, mins = 0;
+                       if( *bp == ':' && v == (int)v ) {
+                               mins = v;
+                               v = strtod(cp=bp+1, &bp);
+                               if( *bp == ':' && v == (int)v ) {
+                                       hour = mins;  mins = v;
+                                       v = strtod(cp=bp+1, &bp);
+                               }
+                       }
+                       secs += hour*3600 + mins*60 + v;
+               }
+               while( *bp && (*bp<'0' || *bp>'9') ) ++bp;
+               cp = bp;
+       }
+       return secs;
+}
+
+static void show_duration(double v, char *&cp, char *ep)
+{
+       if( v == DBL_INF ) {
+               cp += snprintf(cp, ep-cp, "%s", _("inf"));
+               return;
+       }
+       double secs = v;  char *bp = cp;
+       int k = sizeof(scan_ranges)/sizeof(scan_ranges[0]);
+       while( --k >= SCAN_RANGE_DAYS ) {
+               if( secs >= scan_ranges[k].radix ) {
+                       int v = secs/scan_ranges[k].radix;
+                       secs -= v * scan_ranges[k].radix;
+                       cp += snprintf(cp, ep-cp,"%d%s", v,
+                               v > 1 ? _(scan_ranges[k].sfxs) : _(scan_ranges[k].sfx));
+               }
+       }
+       if( secs > 0 ) {
+               if( cp > bp && cp < ep ) *cp++ = ' ';
+               int64_t n = secs; int hour = n/3600, min = (n/60)%60, sec = n%60;
+               if( hour > 0 ) cp += snprintf(cp, ep-cp, "%d:", hour);
+               if( hour > 0 || min > 0 ) cp += snprintf(cp, ep-cp, "%02d:", min);
+               cp += snprintf(cp, ep-cp, n>=10 ? "%02d" : "%d", sec);
+       }
+}
+
+static int64_t scan_date(const char *cp, char *&bp)
+{
+       double year=0, mon=1, day=1;
+       double hour=0, min=0;
+       bp = (char *)cp;
+       while( *bp == ' ' ) ++bp;
+       if( *bp == '+' ) return 0;
+       double secs = strtod(cp=bp, &bp);
+       if( *bp == '/' && secs == (int)secs ) {
+               year = secs;  secs = 0;
+               mon = strtod(cp=bp+1, &bp);
+               if( *bp == '/' && mon == (int)mon ) {
+                       day = strtod(cp=bp+1, &bp);
+                       while( *bp == ' ' ) ++bp;
+                       secs = *bp != '+' ? strtod(cp=bp, &bp) : 0;
+               }
+       }
+       if( *bp == ':' && secs == (int)secs ) {
+               hour = secs;  secs = 0;
+               min = strtod(cp=bp+1, &bp);
+               if( *bp == ':' && min == (int)min ) {
+                       secs = strtod(cp=bp+1, &bp);
+               }
+       }
+       struct tm ttm;  memset(&ttm, 0, sizeof(ttm));
+       ttm.tm_year = year-1900;  ttm.tm_mon = mon-1;  ttm.tm_mday = day;
+       ttm.tm_hour = hour;       ttm.tm_min = min;    ttm.tm_sec = secs;
+       ttm.tm_wday = ttm.tm_yday = 0;  ttm.tm_isdst = daylight; /* tzset in main */
+       time_t t = mktime(&ttm);
+       return (int64_t)t;
+}
+
+static void show_date(time_t t, char *&cp, char *ep)
+{
+       struct tm tm;  localtime_r(&t, &tm);
+       cp += snprintf(cp, ep-cp, "%04d/%02d/%02d %02d:%02d:%02d",
+               tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
+               tm.tm_hour, tm.tm_min, tm.tm_sec);
+}
+
+double BinFolder::matches_indexable(Indexable *idxbl)
+{
+       double result = -1;
+       for( int i=0; i<filters.size(); ++i ) {
+               BinFolderFilter *filter = filters[i];
+               double ret = filter->op->test(filter->target, idxbl);
+               switch( filter->enabled->type ) {
+               case FOLDER_ENABLED_OR: {
+                       if( result < 0 ) result = ret;
+                       break; }
+               case FOLDER_ENABLED_AND: {
+                       if( ret < 0 ) result = -1;
+                       break; }
+               case FOLDER_ENABLED_OR_NOT: {
+                       if( ret < 0 ) result = 1;
+                       break; }
+               case FOLDER_ENABLED_AND_NOT: {
+                       if( ret >= 0 ) result = -1;
+                       break; }
+               }
+       }
+       return result;
+}
+
+
+BinFolder::BinFolder(int awindow_folder, const char *title)
+{
+       this->awindow_folder = awindow_folder;
+       char *bp = this->title;
+       int len = sizeof(this->title);
+       while( --len>0 && *title ) *bp++ = *title++;
+       *bp = 0;
+}
+
+BinFolder::BinFolder(BinFolder &that)
+{
+       copy_from(&that);
+}
+
+void BinFolder::copy_from(BinFolder *that)
+{
+       strcpy(title, that->title);
+       awindow_folder = that->awindow_folder;
+       filters.copy_from(&that->filters);
+}
+
+BinFolder::~BinFolder()
+{
+}
+
+void BinFolder::save_xml(FileXML *file)
+{
+       file->tag.set_title("FOLDER");
+       file->tag.set_property("TITLE", title);
+       file->tag.set_property("AWINDOW_FOLDER", awindow_folder);
+       file->append_tag();
+       file->append_newline();
+       for( int i=0; i<filters.size(); ++i )
+               filters[i]->save_xml(file);
+       file->tag.set_title("/FOLDER");
+       file->append_tag();
+       file->append_newline();
+}
+
+int BinFolder::load_xml(FileXML *file)
+{
+       title[0] = 0;
+       file->tag.get_property("TITLE", title);
+       awindow_folder = file->tag.get_property("AWINDOW_FOLDER", -1);
+       filters.remove_all_objects();
+
+       int ret = 0;
+       while( !(ret=file->read_tag()) ) {
+               if( file->tag.title_is("/FOLDER") ) break;
+               if( file->tag.title_is("FILTER") ) {
+                       BinFolderFilter *filter = new BinFolderFilter();
+                       filter->load_xml(file);
+                       filters.append(filter);
+               }
+       }
+       return ret;
+}
+
+void BinFolder::add_patterns(ArrayList<Indexable*> *drag_assets)
+{
+       int n = drag_assets->size();
+       if( n > 0 ) {
+               int len = 1;
+               for( int i=0; i<n; ++i )
+                       len += strlen(drag_assets->get(i)->path) + 1;
+               char *pats = new char[len], *bp = pats;
+               const char *cp = drag_assets->get(0)->path;
+               while( *cp ) *bp++ = *cp++;
+               for( int i=1; i<n; ++i ) {
+                       *bp++ = '\n';
+                       cp = drag_assets->get(i)->path;
+                       while( *cp ) *bp++ = *cp++;
+               }
+               *bp = 0;
+// new pattern filter
+               BinFolderFilter *filter = new BinFolderFilter();
+               filter->update_enabled(FOLDER_ENABLED_OR);
+               filter->update_target(FOLDER_TARGET_PATTERNS);
+               filter->update_op(FOLDER_OP_MATCHES);
+               BinFolderTargetPatterns *patterns = (BinFolderTargetPatterns *)(filter->target);
+               patterns->update(pats);
+               filters.append(filter);
+       }
+}
+
+
+double BinFolders::matches_indexable(int folder, Indexable *idxbl)
+{
+       int k = size();
+       while( --k>=0 && get(k)->awindow_folder!=folder );
+       return k < 0 ? 0 : get(k)->matches_indexable(idxbl);
+}
+
+void BinFolders::save_xml(FileXML *file)
+{
+       file->tag.set_title("FOLDERS");
+       file->append_tag();
+       file->append_newline();
+       for( int i=0; i<size(); ++i )
+               get(i)->save_xml(file);
+       file->tag.set_title("/FOLDERS");
+       file->append_tag();
+       file->append_newline();
+}
+
+int BinFolders::load_xml(FileXML *file)
+{
+       clear();
+       int ret = 0;
+       while( !(ret=file->read_tag()) ) {
+               if( file->tag.title_is("/FOLDERS") ) break;
+               if( file->tag.title_is("FOLDER") ) {
+                       BinFolder *folder = new BinFolder(-1, "folder");
+                       folder->load_xml(file);
+                       append(folder);
+               }
+       }
+       return ret;
+}
+
+void BinFolders::copy_from(BinFolders *that)
+{
+       clear();
+       for( int i=0; i<that->size(); ++i )
+               append(new BinFolder(*that->get(i)));
+}
+
+
+BinFolderFilter::BinFolderFilter()
+{
+       enabled = 0;
+       target = 0;
+       op = 0;
+       value = 0;
+}
+BinFolderFilter::~BinFolderFilter()
+{
+       delete enabled;
+       delete target;
+       delete op;
+       delete value;
+}
+
+void BinFolderFilter::update_enabled(int type)
+{
+       if( !enabled )
+               enabled = new BinFolderEnabled(this, type);
+       else
+               enabled->update(type);
+}
+
+void BinFolderFilter::update_target(int type)
+{
+       if( target ) {
+               if( target->type == type ) return;
+               delete target;  target = 0;
+       }
+       switch( type ) {
+       case FOLDER_TARGET_PATTERNS:    target = new BinFolderTargetPatterns(this);    break;
+       case FOLDER_TARGET_FILE_SIZE:   target = new BinFolderTargetFileSize(this);    break;
+       case FOLDER_TARGET_MOD_TIME:    target = new BinFolderTargetTime(this);        break;
+       case FOLDER_TARGET_TRACK_TYPE:  target = new BinFolderTargetTrackType(this);   break;
+       case FOLDER_TARGET_WIDTH:       target = new BinFolderTargetWidth(this);       break;
+       case FOLDER_TARGET_HEIGHT:      target = new BinFolderTargetHeight(this);      break;
+       case FOLDER_TARGET_FRAMERATE:   target = new BinFolderTargetFramerate(this);   break;
+       case FOLDER_TARGET_SAMPLERATE:  target = new BinFolderTargetSamplerate(this);  break;
+       case FOLDER_TARGET_CHANNELS:    target = new BinFolderTargetChannels(this);    break;
+       case FOLDER_TARGET_DURATION:    target = new BinFolderTargetDuration(this);    break;
+       }
+}
+
+void BinFolderFilter::update_op(int type)
+{
+       if( op ) {
+               if( op->type == type ) return;
+               delete op;  op = 0;
+       }
+       switch( type ) {
+       case FOLDER_OP_AROUND:  op = new BinFolderOpAround(this);  break;
+       case FOLDER_OP_EQ:      op = new BinFolderOpEQ(this);      break;
+       case FOLDER_OP_GE:      op = new BinFolderOpGE(this);      break;
+       case FOLDER_OP_GT:      op = new BinFolderOpGT(this);      break;
+       case FOLDER_OP_NE:      op = new BinFolderOpNE(this);      break;
+       case FOLDER_OP_LE:      op = new BinFolderOpLE(this);      break;
+       case FOLDER_OP_LT:      op = new BinFolderOpLT(this);      break;
+       case FOLDER_OP_MATCHES: op = new BinFolderOpMatches(this); break;
+       }
+}
+
+void BinFolderFilter::update_value(const char *text)
+{
+       if( !value )
+               value = new BinFolderValue(this, text);
+       else
+               value->update(text);
+}
+
+void BinFolderFilter::save_xml(FileXML *file)
+{
+       file->tag.set_title("FILTER");
+       file->tag.set_property("ENABLED", enabled->type);
+       file->tag.set_property("OP", op->type);
+       file->tag.set_property("TARGET", target->type);
+       target->save_xml(file);
+       file->append_tag();
+       if( target->type == FOLDER_TARGET_PATTERNS )
+               file->append_text(((BinFolderTargetPatterns *)target)->text);
+       file->tag.set_title("/FILTER");
+       file->append_tag();
+       file->append_newline();
+}
+
+int BinFolderFilter::load_xml(FileXML *file)
+{
+       int enabled_type = file->tag.get_property("ENABLED", FOLDER_ENABLED_AND);
+       int op_type = file->tag.get_property("OP", FOLDER_OP_MATCHES);
+       int target_type = file->tag.get_property("TARGET", FOLDER_TARGET_PATTERNS);
+       char data[0x40000];
+       file->read_text_until("/FILTER", data, sizeof(data), 0);
+       update_enabled(enabled_type);
+       update_target(target_type);
+       update_op(op_type);
+       target->load_xml(file);
+       if( target->type == FOLDER_TARGET_PATTERNS )
+               ((BinFolderTargetPatterns *)target)->update(data);
+       return 0;
+}
+
+void BinFolderFilters::copy_from(BinFolderFilters *that)
+{
+       clear();
+       for( int i=0; i<that->size(); ++i ) {
+               BinFolderFilter *filter = new BinFolderFilter();
+               BinFolderFilter *tp = that->get(i);
+               filter->update_enabled(tp->enabled->type);
+               filter->update_target(tp->target->type);
+               filter->update_op(tp->op->type);
+               filter->target->copy_from(tp->target);
+               filter->op->copy_from(tp->op);
+               append(filter);
+       }
+}
+
+double BinFolderOp::around(double v, double a)
+{
+       if( type != FOLDER_OP_AROUND || a <= 0 ) return v;
+       if( (v=fabs(v)) > a ) return -1;
+       return v / a;
+}
+
+// string theory: Feynman, Einstein and Schrodinger string compare
+//   Feynman: try all possible matches, weight the outcomes
+//   Schrodinger: it may be there several ways at the same time
+//   Einstein: the more matches there are, the heavier it is
+double BinFolderOp::around(const char *ap, const char *bp)
+{
+       int64_t v = 0, vmx = 0;
+       int alen = strlen(ap), blen = strlen(bp);
+       if( alen > blen ) {
+               const char *cp = ap;  ap = bp;  bp = cp;
+               int clen = alen;  alen = blen;  blen = clen;
+       }
+// 4 level loop (with strncmp), don't try long strings
+       for( int n=0; ++n<=alen; ) {
+               int64_t nn = n*n;
+               int an = alen-n+1, bn = blen-n+1;
+               for( int i=an; --i>=0; ) {
+                       for( int j=bn; --j>=0; ) {
+                               if( !strncmp(ap+i, bp+j, n) ) v += nn;
+                       }
+               }
+               vmx += an*bn*nn;
+       }
+       return !vmx ? -1 : 1 - v / (double)vmx;
+}
+
+
+double BinFolderOp::compare(BinFolderTarget *target, Indexable *idxbl)
+{
+       double v = -1;
+       switch( target->type ) {
+       case FOLDER_TARGET_PATTERNS: {
+               BinFolderTargetPatterns *tgt = (BinFolderTargetPatterns *)target;
+               switch( type ) {
+               case FOLDER_OP_AROUND: {
+                       const char *cp = idxbl->path;
+                       const char *bp = strrchr(cp, '/');
+                       if( bp ) cp = bp + 1;
+                       v = around(cp, tgt->text);
+                       break; }
+               case FOLDER_OP_EQ:  case FOLDER_OP_GT:  case FOLDER_OP_GE:
+               case FOLDER_OP_NE:  case FOLDER_OP_LT:  case FOLDER_OP_LE: {
+                       const char *cp = idxbl->path;
+                       const char *bp = strrchr(cp, '/');
+                       if( bp ) cp = bp + 1;
+                       v = strcmp(cp, tgt->text);
+                       break; }
+               case FOLDER_OP_MATCHES: {
+                       v = -1;
+                       char *cp = tgt->text;
+                       while( v < 0 && *cp ) {
+                               char pattern[BCTEXTLEN], *bp = pattern, ch;
+                               while( *cp && (ch=*cp++)!='\n' ) *bp++ = ch;
+                               *bp = 0;
+                               if( bp > pattern &&
+                                   !FileSystem::test_filter(idxbl->path, pattern) )
+                                       v = 1;
+                       }
+                       break; }
+               }
+               break; }
+       case FOLDER_TARGET_FILE_SIZE: {
+               BinFolderTargetFileSize *tgt = (BinFolderTargetFileSize *)target;
+               int64_t file_size = !idxbl->is_asset ? -1 :
+                       FileSystem::get_size(idxbl->path);
+               v = around(file_size - tgt->file_size, tgt->around);
+               break; }
+       case FOLDER_TARGET_MOD_TIME: {
+               BinFolderTargetTime *tgt = (BinFolderTargetTime *)target;
+               struct stat st;
+               if( stat(idxbl->path, &st) ) break;
+               v = around(st.st_mtime - tgt->mtime, tgt->around);
+               break; }
+       case FOLDER_TARGET_TRACK_TYPE: {
+               BinFolderTargetTrackType *tgt = (BinFolderTargetTrackType *)target;
+               int want_audio = (tgt->data_types&(1<<TRACK_AUDIO)) ? 1 : 0;
+               int has_audio = idxbl->have_audio();
+               if( want_audio != has_audio ) break;
+               int want_video = (tgt->data_types&(1<<TRACK_VIDEO)) ? 1 : 0;
+               int has_video = idxbl->have_video();
+               if( want_video != has_video ) break;
+               v = 1;
+               break; }
+       case FOLDER_TARGET_WIDTH: {
+               BinFolderTargetWidth *tgt = (BinFolderTargetWidth *)target;
+               int w = idxbl->get_w();
+               v = around(w - tgt->width, tgt->around);
+               break; }
+       case FOLDER_TARGET_HEIGHT: {
+               BinFolderTargetHeight *tgt = (BinFolderTargetHeight *)target;
+               int h = idxbl->get_h();
+               v = around(h - tgt->height, tgt->around);
+               break; }
+       case FOLDER_TARGET_FRAMERATE: {
+               BinFolderTargetFramerate *tgt = (BinFolderTargetFramerate *)target;
+               double rate = idxbl->get_frame_rate();
+               v = around(rate - tgt->framerate, tgt->around);
+               break; }
+       case FOLDER_TARGET_SAMPLERATE: {
+               BinFolderTargetSamplerate *tgt = (BinFolderTargetSamplerate *)target;
+               double rate = idxbl->get_sample_rate();
+               v = around(rate - tgt->samplerate, tgt->around);
+               break; }
+       case FOLDER_TARGET_CHANNELS: {
+               BinFolderTargetChannels *tgt = (BinFolderTargetChannels *)target;
+               double chs = idxbl->get_audio_channels();
+               v = around(chs - tgt->channels, tgt->around);
+               break; }
+       case FOLDER_TARGET_DURATION: {
+               BinFolderTargetDuration *tgt = (BinFolderTargetDuration *)target;
+               double len = 0;
+               double video_rate = !idxbl->have_video() ? 0 : idxbl->get_frame_rate();
+               if( video_rate > 0 ) {
+                       double video_length = idxbl->get_video_frames() / video_rate;
+                       if( video_length > len ) len = video_length;
+               }
+               double audio_rate = !idxbl->have_audio() ? 0 : idxbl->get_sample_rate();
+               if( audio_rate > 0 ) {
+                       double audio_length = idxbl->get_audio_samples() / audio_rate;
+                       if( audio_length > len ) len = audio_length;
+               }
+               v = around(len - tgt->duration, tgt->around);
+               break; }
+       }
+
+       return v;
+}
+
+BinFolderEnabled::BinFolderEnabled(BinFolderFilter *filter, int type)
+ : BC_ListBoxItem(_(types[type]))
+{
+       this->filter = filter;
+       this->type = type;
+}
+
+BinFolderEnabled::~BinFolderEnabled()
+{
+}
+
+void BinFolderEnabled::update(int type)
+{
+       this->type = type;
+       set_text(_(types[type]));
+}
+
+BinFolderEnabledType::BinFolderEnabledType(int no)
+ : BC_MenuItem(_(BinFolderEnabled::types[no]))
+{
+       this->no = no;
+}
+BinFolderEnabledType::~BinFolderEnabledType()
+{
+}
+
+int BinFolderEnabledType::handle_event()
+{
+       BinFolderEnabledPopup *enabled_popup = (BinFolderEnabledPopup *)get_popup_menu();
+       BinFolderList *folder_list = enabled_popup->folder_list;
+       int i = folder_list->get_selection_number(FOLDER_COLUMN_ENABLE, 0);
+       if( i >= 0 ) {
+               BinFolder *folder = folder_list->folder;
+               BinFolderFilter *filter = folder->filters[i];
+               filter->update_enabled(no);
+               folder_list->create_list();
+       }
+       return 1;
+}
+
+BinFolderEnabledPopup::BinFolderEnabledPopup(BinFolderList *folder_list)
+ : BC_PopupMenu(0, 0, 0, "", 0)
+{
+       this->folder_list = folder_list;
+       enabled = 0;
+}
+
+void BinFolderEnabledPopup::create_objects()
+{
+       add_item(new BinFolderEnabledType(FOLDER_ENABLED_OFF));
+       add_item(new BinFolderEnabledType(FOLDER_ENABLED_AND));
+       add_item(new BinFolderEnabledType(FOLDER_ENABLED_OR));
+       add_item(new BinFolderEnabledType(FOLDER_ENABLED_AND_NOT));
+       add_item(new BinFolderEnabledType(FOLDER_ENABLED_OR_NOT));
+}
+
+void BinFolderEnabledPopup::activate_menu(BC_ListBoxItem *item)
+{
+       this->enabled = (BinFolderEnabled *)item;
+       BC_PopupMenu::activate_menu();
+}
+
+BinFolderTarget::BinFolderTarget(BinFolderFilter *filter, int type)
+ : BC_ListBoxItem(_(types[type]))
+{
+       this->filter = filter;
+       this->type = type;
+       around = -1;
+}
+
+BinFolderTarget::~BinFolderTarget()
+{
+}
+
+BC_Window *BinFolderTarget::new_gui(ModifyTargetThread *thread)
+{
+       ModifyTargetGUI *window = new ModifyTargetGUI(thread);
+       window->create_objects();
+       return window;
+}
+
+BinFolderTargetType::BinFolderTargetType(int no)
+ : BC_MenuItem(_(BinFolderTarget::types[no]))
+{
+       this->no = no;
+}
+BinFolderTargetType::~BinFolderTargetType()
+{
+}
+
+int BinFolderTargetType::handle_event()
+{
+       BinFolderTargetPopup *target_popup = (BinFolderTargetPopup *)get_popup_menu();
+       BinFolderList *folder_list = target_popup->folder_list;
+       int i = folder_list->get_selection_number(FOLDER_COLUMN_TARGET, 0);
+       if( i >= 0 ) {
+               BinFolder *folder = folder_list->folder;
+               BinFolderFilter *filter = folder->filters[i];
+               filter->update_target(no);
+               folder_list->create_list();
+       }
+       return 1;
+}
+
+BinFolderTargetPopup::BinFolderTargetPopup(BinFolderList *folder_list)
+ : BC_PopupMenu(0, 0, 0, "", 0)
+{
+       this->folder_list = folder_list;
+       target = 0;
+}
+
+void BinFolderTargetPopup::create_objects()
+{
+       add_item(new BinFolderTargetType(FOLDER_TARGET_PATTERNS));
+       add_item(new BinFolderTargetType(FOLDER_TARGET_FILE_SIZE));
+       add_item(new BinFolderTargetType(FOLDER_TARGET_MOD_TIME));
+       add_item(new BinFolderTargetType(FOLDER_TARGET_TRACK_TYPE));
+       add_item(new BinFolderTargetType(FOLDER_TARGET_WIDTH));
+       add_item(new BinFolderTargetType(FOLDER_TARGET_HEIGHT));
+       add_item(new BinFolderTargetType(FOLDER_TARGET_FRAMERATE));
+       add_item(new BinFolderTargetType(FOLDER_TARGET_SAMPLERATE));
+       add_item(new BinFolderTargetType(FOLDER_TARGET_CHANNELS));
+       add_item(new BinFolderTargetType(FOLDER_TARGET_DURATION));
+}
+
+void BinFolderTargetPopup::activate_menu(BC_ListBoxItem *item)
+{
+       this->target = (BinFolderTarget *)item;
+       BC_PopupMenu::activate_menu();
+}
+
+
+BinFolderTargetPatterns::BinFolderTargetPatterns(BinFolderFilter *filter)
+ : BinFolderTarget(filter, FOLDER_TARGET_PATTERNS)
+{
+       text = 0;
+       update("*");
+}
+BinFolderTargetPatterns::~BinFolderTargetPatterns()
+{
+       delete [] text;
+}
+void BinFolderTargetPatterns::save_xml(FileXML *file) {}
+void BinFolderTargetPatterns::load_xml(FileXML *file) {}
+
+void BinFolderTargetPatterns::copy_from(BinFolderTarget *that)
+{
+       BinFolderTargetPatterns *tp = (BinFolderTargetPatterns*)that;
+       update(tp->text);
+}
+
+void BinFolderTargetPatterns::update(const char *text)
+{
+       delete [] this->text;
+       this->text = cstrdup(text);
+       filter->update_value(text);
+}
+
+BC_Window *BinFolderTargetPatterns::new_gui(ModifyTargetThread *thread)
+{
+       return new ModifyTargetPatternsGUI(thread);
+}
+
+
+BinFolderTargetFileSize::BinFolderTargetFileSize(BinFolderFilter *filter)
+ : BinFolderTarget(filter, FOLDER_TARGET_FILE_SIZE)
+{
+       file_size = 0;
+       update(file_size, -1);
+}
+BinFolderTargetFileSize::~BinFolderTargetFileSize()
+{
+}
+
+void BinFolderTargetFileSize::save_xml(FileXML *file)
+{
+       file->tag.set_property("FILE_SIZE", file_size);
+       file->tag.set_property("AROUND", around);
+}
+
+void BinFolderTargetFileSize::load_xml(FileXML *file)
+{
+       int64_t file_size = file->tag.get_property("FILE_SIZE", this->file_size);
+       double around = file->tag.get_property("AROUND", this->around);
+       update(file_size, around);
+}
+
+void BinFolderTargetFileSize::copy_from(BinFolderTarget *that)
+{
+       BinFolderTargetFileSize *tp = (BinFolderTargetFileSize *)that;
+       update(tp->file_size, tp->around);
+}
+
+void BinFolderTargetFileSize::update(int64_t file_size, double around)
+{
+       this->file_size = file_size;
+       this->around = around;
+       char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
+       show_no(file_size, cp, ep);
+       if( around >= 0 && filter->op->type == FOLDER_OP_AROUND ) {
+               if( cp < ep ) *cp++ = '+';
+               show_no(around, cp, ep);
+       }
+       *cp = 0;
+       filter->update_value(txt);
+}
+
+BC_Window *BinFolderTargetFileSize::new_gui(ModifyTargetThread *thread)
+{
+       return new ModifyTargetFileSizeGUI(thread);
+}
+
+
+BinFolderTargetTime::BinFolderTargetTime(BinFolderFilter *filter)
+ : BinFolderTarget(filter, FOLDER_TARGET_MOD_TIME)
+{
+       time_t t;  time(&t);
+       mtime = (int64_t)t;
+       update(mtime, -1);
+}
+BinFolderTargetTime::~BinFolderTargetTime()
+{
+}
+
+void BinFolderTargetTime::save_xml(FileXML *file)
+{
+       file->tag.set_property("MTIME", mtime);
+       file->tag.set_property("AROUND", around);
+}
+
+void BinFolderTargetTime::load_xml(FileXML *file)
+{
+       int64_t mtime = file->tag.get_property("MTIME", this->mtime);
+       double around = file->tag.get_property("AROUND", this->around);
+       update(mtime, around);
+}
+
+void BinFolderTargetTime::copy_from(BinFolderTarget *that)
+{
+       BinFolderTargetTime *tp = (BinFolderTargetTime *)that;
+       update(tp->mtime, tp->around);
+}
+
+void BinFolderTargetTime::update(int64_t mtime, double around)
+{
+       this->mtime = mtime;
+       this->around = around;
+       char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
+       show_date(mtime, cp, ep);
+       if( around >= 0 && filter->op->type == FOLDER_OP_AROUND ) {
+               if( cp < ep ) *cp++ = '+';
+               show_duration(around, cp, ep);
+       }
+       *cp = 0;
+       filter->update_value(txt);
+}
+
+BC_Window *BinFolderTargetTime::new_gui(ModifyTargetThread *thread)
+{
+       return new ModifyTargetTimeGUI(thread);
+}
+
+
+BinFolderTargetTrackType::BinFolderTargetTrackType(BinFolderFilter *filter)
+ : BinFolderTarget(filter, FOLDER_TARGET_TRACK_TYPE)
+{
+       data_types = (1<<TRACK_AUDIO);
+       update(data_types);
+}
+BinFolderTargetTrackType::~BinFolderTargetTrackType()
+{
+}
+
+void BinFolderTargetTrackType::save_xml(FileXML *file)
+{
+       file->tag.set_property("DATA_TYPES", data_types);
+}
+
+void BinFolderTargetTrackType::load_xml(FileXML *file)
+{
+       int data_types = file->tag.get_property("DATA_TYPES", this->data_types);
+       update(data_types);
+}
+
+void BinFolderTargetTrackType::copy_from(BinFolderTarget *that)
+{
+       BinFolderTargetTrackType *tp = (BinFolderTargetTrackType *)that;
+       update(tp->data_types);
+}
+
+void BinFolderTargetTrackType::update(int data_types)
+{
+       this->data_types = data_types;
+       this->around = -1;
+       char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
+       if( data_types & (1<<TRACK_AUDIO) ) {
+               if( cp > txt && cp < ep ) *cp++ = ' ';
+               cp += snprintf(cp, ep-cp, "%s",_("audio"));
+       }
+       if( data_types & (1<<TRACK_VIDEO) ) {
+               if( cp > txt && cp < ep ) *cp++ = ' ';
+               cp += snprintf(cp, ep-cp, "%s",_("video"));
+       }
+       *cp = 0;
+       filter->update_value(txt);
+}
+
+BC_Window *BinFolderTargetTrackType::new_gui(ModifyTargetThread *thread)
+{
+       return new ModifyTargetTrackTypeGUI(thread);
+}
+
+
+BinFolderTargetWidth::BinFolderTargetWidth(BinFolderFilter *filter)
+ : BinFolderTarget(filter, FOLDER_TARGET_WIDTH)
+{
+       width = 0;
+       update(width, -1);
+}
+BinFolderTargetWidth::~BinFolderTargetWidth()
+{
+}
+
+void BinFolderTargetWidth::save_xml(FileXML *file)
+{
+       file->tag.set_property("WIDTH", width);
+       file->tag.set_property("AROUND", around);
+}
+void BinFolderTargetWidth::load_xml(FileXML *file)
+{
+       int width = file->tag.get_property("WIDTH", this->width);
+       double around = file->tag.get_property("AROUND", this->around);
+       update(width, around);
+}
+
+void BinFolderTargetWidth::copy_from(BinFolderTarget *that)
+{
+       BinFolderTargetWidth *tp = (BinFolderTargetWidth *)that;
+       update(tp->width, tp->around);
+}
+
+void BinFolderTargetWidth::update(int width, double around)
+{
+       this->width = width;
+       this->around = around;
+       char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
+       show_no(width, cp, ep);
+       if( around >= 0 && filter->op->type == FOLDER_OP_AROUND ) {
+               if( cp < ep ) *cp++ = '+';
+               show_no(around, cp, ep);
+       }
+       *cp = 0;
+       filter->update_value(txt);
+}
+
+BC_Window *BinFolderTargetWidth::new_gui(ModifyTargetThread *thread)
+{
+       return new ModifyTargetWidthGUI(thread);
+}
+
+
+BinFolderTargetHeight::BinFolderTargetHeight(BinFolderFilter *filter)
+ : BinFolderTarget(filter, FOLDER_TARGET_HEIGHT)
+{
+       height = 0;
+       update(height, -1);
+}
+BinFolderTargetHeight::~BinFolderTargetHeight()
+{
+}
+
+void BinFolderTargetHeight::save_xml(FileXML *file)
+{
+       file->tag.set_property("HEIGHT", height);
+       file->tag.set_property("AROUND", around);
+}
+void BinFolderTargetHeight::load_xml(FileXML *file)
+{
+       int height = file->tag.get_property("HEIGHT", this->height);
+       double around = file->tag.get_property("AROUND", this->around);
+       update(height, around);
+}
+
+void BinFolderTargetHeight::copy_from(BinFolderTarget *that)
+{
+       BinFolderTargetHeight *tp = (BinFolderTargetHeight *)that;
+       update(tp->height, tp->around);
+}
+
+void BinFolderTargetHeight::update(int height, double around)
+{
+       this->height = height;
+       this->around = around;
+       char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
+       show_no(height, cp, ep);
+       if( around >= 0 && filter->op->type == FOLDER_OP_AROUND ) {
+               if( cp < ep ) *cp++ = '+';
+               show_no(around, cp, ep);
+       }
+       *cp = 0;
+       filter->update_value(txt);
+}
+
+BC_Window *BinFolderTargetHeight::new_gui(ModifyTargetThread *thread)
+{
+       return new ModifyTargetHeightGUI(thread);
+}
+
+
+BinFolderTargetFramerate::BinFolderTargetFramerate(BinFolderFilter *filter)
+ : BinFolderTarget(filter, FOLDER_TARGET_FRAMERATE)
+{
+       framerate = 0;
+       update(framerate, -1);
+}
+BinFolderTargetFramerate::~BinFolderTargetFramerate()
+{
+}
+
+void BinFolderTargetFramerate::save_xml(FileXML *file)
+{
+       file->tag.set_property("FRAMERATE", framerate);
+       file->tag.set_property("AROUND", around);
+}
+
+void BinFolderTargetFramerate::load_xml(FileXML *file)
+{
+       double framerate = file->tag.get_property("FRAMERATE", this->framerate);
+       double around = file->tag.get_property("AROUND", this->around);
+       update(framerate, around);
+}
+
+void BinFolderTargetFramerate::copy_from(BinFolderTarget *that)
+{
+       BinFolderTargetFramerate *tp = (BinFolderTargetFramerate *)that;
+       update(tp->framerate, tp->around);
+}
+
+void BinFolderTargetFramerate::update(double framerate, double around)
+{
+       this->framerate = framerate;
+       this->around = around;
+       char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
+       show_no(framerate, cp, ep, "%0.3f");
+       if( around >= 0 && filter->op->type == FOLDER_OP_AROUND ) {
+               if( cp < ep ) *cp++ = '+';
+               show_no(around, cp, ep, "%0.3f");
+       }
+       *cp = 0;
+       filter->update_value(txt);
+}
+
+BC_Window *BinFolderTargetFramerate::new_gui(ModifyTargetThread *thread)
+{
+       return new ModifyTargetFramerateGUI(thread);
+}
+
+
+BinFolderTargetSamplerate::BinFolderTargetSamplerate(BinFolderFilter *filter)
+ : BinFolderTarget(filter, FOLDER_TARGET_SAMPLERATE)
+{
+       samplerate = 0;
+       update(samplerate, -1);
+}
+
+BinFolderTargetSamplerate::~BinFolderTargetSamplerate()
+{
+}
+
+void BinFolderTargetSamplerate::save_xml(FileXML *file)
+{
+       file->tag.set_property("SAMPLERATE", samplerate);
+       file->tag.set_property("AROUND", around);
+}
+
+void BinFolderTargetSamplerate::load_xml(FileXML *file)
+{
+       double samplerate = file->tag.get_property("SAMPLERATE", this->samplerate);
+       double around = file->tag.get_property("AROUND", this->around);
+       update(samplerate, around);
+}
+
+void BinFolderTargetSamplerate::copy_from(BinFolderTarget *that)
+{
+       BinFolderTargetSamplerate *tp = (BinFolderTargetSamplerate *)that;
+       update(tp->samplerate, tp->around);
+}
+
+void BinFolderTargetSamplerate::update(int samplerate, double around)
+{
+       this->samplerate = samplerate;
+       this->around = around;
+       char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
+       show_no(samplerate, cp, ep);
+       if( around >= 0 && filter->op->type == FOLDER_OP_AROUND ) {
+               if( cp < ep ) *cp++ = '+';
+               show_no(around, cp, ep);
+       }
+       *cp = 0;
+       filter->update_value(txt);
+}
+
+BC_Window *BinFolderTargetSamplerate::new_gui(ModifyTargetThread *thread)
+{
+       return new ModifyTargetSamplerateGUI(thread);
+}
+
+
+BinFolderTargetChannels::BinFolderTargetChannels(BinFolderFilter *filter)
+ : BinFolderTarget(filter, FOLDER_TARGET_CHANNELS)
+{
+       channels = 0;
+       update(channels, -1);
+}
+BinFolderTargetChannels::~BinFolderTargetChannels()
+{
+}
+
+void BinFolderTargetChannels::save_xml(FileXML *file)
+{
+       file->tag.set_property("CHANNELS", channels);
+       file->tag.set_property("AROUND", around);
+}
+
+void BinFolderTargetChannels::load_xml(FileXML *file)
+{
+       int channels = file->tag.get_property("CHANNELS", this->channels);
+       double around = file->tag.get_property("AROUND", this->around);
+       update(channels, around);
+}
+
+void BinFolderTargetChannels::copy_from(BinFolderTarget *that)
+{
+       BinFolderTargetChannels *tp = (BinFolderTargetChannels *)that;
+       update(tp->channels, tp->around);
+}
+
+void BinFolderTargetChannels::update(int channels, double around)
+{
+       this->channels = channels;
+       this->around = around;
+       char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
+       show_no(channels, cp, ep);
+       if( around >= 0 && filter->op->type == FOLDER_OP_AROUND ) {
+               if( cp < ep ) *cp++ = '+';
+               show_no(around, cp, ep);
+       }
+       *cp = 0;
+       filter->update_value(txt);
+}
+
+BC_Window *BinFolderTargetChannels::new_gui(ModifyTargetThread *thread)
+{
+       return new ModifyTargetChannelsGUI(thread);
+}
+
+
+BinFolderTargetDuration::BinFolderTargetDuration(BinFolderFilter *filter)
+ : BinFolderTarget(filter, FOLDER_TARGET_DURATION)
+{
+       duration = 0;
+       update(duration, -1);
+}
+BinFolderTargetDuration::~BinFolderTargetDuration()
+{
+}
+
+void BinFolderTargetDuration::save_xml(FileXML *file)
+{
+       file->tag.set_property("DURATION", duration);
+       file->tag.set_property("AROUND", around);
+}
+
+void BinFolderTargetDuration::load_xml(FileXML *file)
+{
+       int64_t duration = file->tag.get_property("DURATION", this->duration);
+       double around = file->tag.get_property("AROUND", this->around);
+       update(duration, around);
+}
+
+void BinFolderTargetDuration::copy_from(BinFolderTarget *that)
+{
+       BinFolderTargetDuration *tp = (BinFolderTargetDuration *)that;
+       update(tp->duration, tp->around);
+}
+
+void BinFolderTargetDuration::update(int64_t duration, double around)
+{
+       this->duration = duration;
+       this->around = around;
+       char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
+       show_duration(duration, cp, ep);
+       if( around >= 0 && filter->op->type == FOLDER_OP_AROUND ) {
+               if( cp < ep ) *cp++ = '+';
+               show_duration(around, cp, ep);
+       }
+       *cp = 0;
+       filter->update_value(txt);
+}
+
+BC_Window *BinFolderTargetDuration::new_gui(ModifyTargetThread *thread)
+{
+       return new ModifyTargetDurationGUI(thread);
+}
+
+
+BinFolderOp::BinFolderOp(BinFolderFilter *filter, int type)
+ : BC_ListBoxItem(_(types[type]))
+{
+       this->filter = filter;
+       this->type = type;
+}
+
+BinFolderOp::~BinFolderOp()
+{
+}
+
+void BinFolderOp::copy_from(BinFolderOp *that)
+{
+       type = that->type;
+}
+
+BinFolderOpType::BinFolderOpType(int no)
+ : BC_MenuItem(_(BinFolderOp::types[no]))
+{
+       this->no = no;
+}
+BinFolderOpType::~BinFolderOpType()
+{
+}
+
+int BinFolderOpType::handle_event()
+{
+       BinFolderOpPopup *op_popup = (BinFolderOpPopup *)get_popup_menu();
+       BinFolderList *folder_list = op_popup->folder_list;
+       int i = folder_list->get_selection_number(FOLDER_COLUMN_OP, 0);
+       if( i >= 0 ) {
+               BinFolder *folder = folder_list->folder;
+               BinFolderFilter *filter = folder->filters[i];
+               filter->update_op(no);
+               folder_list->create_list();
+       }
+       return 1;
+}
+
+BinFolderOpPopup::BinFolderOpPopup(BinFolderList *folder_list)
+ : BC_PopupMenu(0, 0, 0, "", 0)
+{
+       this->folder_list = folder_list;
+       op = 0;
+}
+
+void BinFolderOpPopup::create_objects()
+{
+       add_item(new BinFolderOpType(FOLDER_OP_AROUND));
+       add_item(new BinFolderOpType(FOLDER_OP_EQ));
+       add_item(new BinFolderOpType(FOLDER_OP_GE));
+       add_item(new BinFolderOpType(FOLDER_OP_GT));
+       add_item(new BinFolderOpType(FOLDER_OP_NE));
+       add_item(new BinFolderOpType(FOLDER_OP_LE));
+       add_item(new BinFolderOpType(FOLDER_OP_LT));
+       add_item(new BinFolderOpType(FOLDER_OP_MATCHES));
+}
+
+void BinFolderOpPopup::activate_menu(BC_ListBoxItem *item)
+{
+       this->op = (BinFolderOp *)item;
+       BC_PopupMenu::activate_menu();
+}
+
+double BinFolderOp::test(BinFolderTarget *target, Indexable *idxbl)
+{
+       return -1;
+}
+
+double BinFolderOpEQ::test(BinFolderTarget *target, Indexable *idxbl)
+{
+       double v = compare(target, idxbl);
+       return v == 0 ? 1 : -1;
+}
+
+double BinFolderOpGT::test(BinFolderTarget *target, Indexable *idxbl)
+{
+       double v = compare(target, idxbl);
+       return v > 0 ? 1 : -1;
+}
+
+double BinFolderOpGE::test(BinFolderTarget *target, Indexable *idxbl)
+{
+       double v = compare(target, idxbl);
+       return v >= 0 ? 1 : -1;
+}
+
+double BinFolderOpNE::test(BinFolderTarget *target, Indexable *idxbl)
+{
+       double v = compare(target, idxbl);
+       return v != 0 ? 1 : -1;
+}
+
+double BinFolderOpLT::test(BinFolderTarget *target, Indexable *idxbl)
+{
+       double v = compare(target, idxbl);
+       return v < 0 ? 1 : -1;
+}
+
+double BinFolderOpLE::test(BinFolderTarget *target, Indexable *idxbl)
+{
+       double v = compare(target, idxbl);
+       return v <= 0 ? 1 : -1;
+}
+
+double BinFolderOpMatches::test(BinFolderTarget *target, Indexable *idxbl)
+{
+       double v = compare(target, idxbl);
+       return v;
+}
+
+double BinFolderOpAround::test(BinFolderTarget *target, Indexable *idxbl)
+{
+       double v = compare(target, idxbl);
+       return v;
+}
+
+BinFolderValue::BinFolderValue(BinFolderFilter *filter, const char *text)
+ : BC_ListBoxItem()
+{
+       this->filter = filter;
+       update(text);
+}
+
+BinFolderValue::~BinFolderValue()
+{
+}
+
+
+void BinFolderValue::update(const char *text)
+{
+       const char *cp = text;
+       char txt[BCSTRLEN], *tp = txt;
+       for( int i=sizeof(txt); --i>0 && *cp!=0 && *cp!='\n'; ++tp,++cp ) *tp = *cp;
+       *tp = 0;
+       set_text(txt);
+}
+
+
+BinFolderList::BinFolderList(BinFolder *folder, MWindow *mwindow,
+               ModifyFolderGUI *window, int x, int y, int w, int h)
+ : BC_ListBox(x, y, w, h, LISTBOX_TEXT, 0,
+       0, 0, 1, 0, 0, LISTBOX_SINGLE, ICON_LEFT, 1)
+{
+       this->folder = folder;
+       this->mwindow = mwindow;
+       this->window = window;
+       dragging_item = 0;
+       set_process_drag(1);
+       enabled_popup = 0;
+       op_popup = 0;
+       target_popup = 0;
+       modify_target = 0;
+}
+
+BinFolderList::~BinFolderList()
+{
+       save_defaults(mwindow->defaults);
+       delete modify_target;
+}
+
+void BinFolderList::create_objects()
+{
+       list_titles[FOLDER_COLUMN_ENABLE] = _("Enable");
+       list_titles[FOLDER_COLUMN_TARGET] = _("Target");
+       list_titles[FOLDER_COLUMN_OP]     = _("Op");
+       list_titles[FOLDER_COLUMN_VALUE]  = _("Value");
+       list_width[FOLDER_COLUMN_ENABLE]  = 80;
+       list_width[FOLDER_COLUMN_TARGET]  = 80;
+       list_width[FOLDER_COLUMN_OP]      = 50;
+       list_width[FOLDER_COLUMN_VALUE]   = 180;
+       load_defaults(mwindow->defaults);
+       create_list();
+       add_subwindow(enabled_popup = new BinFolderEnabledPopup(this));
+       enabled_popup->create_objects();
+       add_subwindow(op_popup = new BinFolderOpPopup(this));
+       op_popup->create_objects();
+       add_subwindow(target_popup = new BinFolderTargetPopup(this));
+       target_popup->create_objects();
+
+       modify_target = new ModifyTargetThread(this);
+}
+
+void BinFolderList::create_list()
+{
+       for( int i=0; i<FOLDER_COLUMNS; ++i )
+               list_items[i].remove_all();
+       for( int i=0; i<folder->filters.size(); ++i ) {
+               BinFolderFilter *filter = folder->filters[i];
+               list_items[FOLDER_COLUMN_ENABLE].append(filter->enabled);
+               list_items[FOLDER_COLUMN_TARGET].append(filter->target);
+               list_items[FOLDER_COLUMN_OP].append(filter->op);
+               list_items[FOLDER_COLUMN_VALUE].append(filter->value);
+       }
+       update(list_items, list_titles, list_width, FOLDER_COLUMNS,
+               get_xposition(), get_yposition(), get_highlighted_item(),
+               1, 1);
+}
+
+int BinFolderList::handle_event()
+{
+       return 1;
+}
+
+int BinFolderList::selection_changed()
+{
+       if( !cursor_above() ) return 0;
+       int no = get_selection_number(0, 0);
+       if( no < 0 ) return 0;
+       BinFolderFilter *filter = folder->filters[no];
+       if( get_button_down() && get_buttonpress() == 3 ) {
+               int cx = get_cursor_x(), col = -1;
+               for( int i=0; col<0 && i<FOLDER_COLUMNS; ++i ) {
+                       int ofs = get_column_offset(i);
+                       if( cx >= ofs && cx < ofs+get_column_width(i) ) {
+                               col = i;  break;
+                       }
+               }
+               BC_ListBoxItem *item = col >= 0 ? get_selection(col, 0) : 0;
+               if( item ) {
+                       deactivate_selection();
+                       switch( col ) {
+                       case FOLDER_COLUMN_ENABLE:
+                               enabled_popup->activate_menu(item);
+                               break;
+                       case FOLDER_COLUMN_TARGET:
+                               target_popup->activate_menu(item);
+                               break;
+                       case FOLDER_COLUMN_OP:
+                               op_popup->activate_menu(item);
+                               break;
+                       case FOLDER_COLUMN_VALUE: {
+                               modify_target->close_window();
+                               int cw = filter->target->type == FOLDER_TARGET_PATTERNS ? 400 : 320;
+                               int ch = filter->target->type == FOLDER_TARGET_PATTERNS ? 300 : 120;
+                               int cx, cy;  get_abs_cursor(cx, cy);
+                               if( (cx-=cw/2) < 50 ) cx = 50;
+                               if( (cy-=ch/2) < 50 ) cy = 50;
+                               modify_target->start(filter->target, cx, cy, cw, ch);
+                               break; }
+                       }
+               }
+       }
+       return 1;
+}
+
+int BinFolderList::column_resize_event()
+{
+       for( int i = 0; i < FOLDER_COLUMNS; i++ ) {
+               list_width[i] = get_column_width(i);
+       }
+       return 1;
+}
+
+int BinFolderList::drag_start_event()
+{
+       if( BC_ListBox::drag_start_event() ) {
+               dragging_item = 1;
+               return 1;
+       }
+
+       return 0;
+}
+
+int BinFolderList::drag_motion_event()
+{
+       if( BC_ListBox::drag_motion_event() ) {
+               return 1;
+       }
+       return 0;
+}
+
+int BinFolderList::drag_stop_event()
+{
+       if( dragging_item ) {
+               int src = get_selection_number(0, 0);
+               int dst = get_highlighted_item();
+               if( src != dst ) {
+                       move_filter(src, dst);
+               }
+               BC_ListBox::drag_stop_event();
+               dragging_item = 0;
+       }
+       return 0;
+}
+
+void BinFolderList::move_filter(int src, int dst)
+{
+       BinFolderFilters &filters = folder->filters;
+       BinFolderFilter *src_filter = filters[src];
+       if( dst < 0 ) dst = filters.size()-1;
+
+       if( dst != src ) {
+               for( int i=src; i<filters.size()-1; ++i )
+                       filters[i] = filters[i+1];
+               for( int i=filters.size(); --i>dst; )
+                       filters[i] = filters[i-1];
+               filters[dst] = src_filter;
+       }
+}
+
+void BinFolderList::save_defaults(BC_Hash *defaults)
+{
+       defaults->update("BIN_FOLDER_ENA", list_width[FOLDER_COLUMN_ENABLE]);
+       defaults->update("BIN_FOLDER_TGT", list_width[FOLDER_COLUMN_TARGET]);
+       defaults->update("BIN_FOLDER_OPR", list_width[FOLDER_COLUMN_OP]);
+       defaults->update("BIN_FOLDER_VAL", list_width[FOLDER_COLUMN_VALUE]);
+}
+void BinFolderList::load_defaults(BC_Hash *defaults)
+{
+       list_width[FOLDER_COLUMN_ENABLE] = defaults->get("BIN_FOLDER_ENA", list_width[FOLDER_COLUMN_ENABLE]);
+       list_width[FOLDER_COLUMN_TARGET] = defaults->get("BIN_FOLDER_TGT", list_width[FOLDER_COLUMN_TARGET]);
+       list_width[FOLDER_COLUMN_OP]     = defaults->get("BIN_FOLDER_OPR", list_width[FOLDER_COLUMN_OP]);
+       list_width[FOLDER_COLUMN_VALUE]  = defaults->get("BIN_FOLDER_VAL", list_width[FOLDER_COLUMN_VALUE]);
+}
+
+BinFolderAddFilter::BinFolderAddFilter(BinFolderList *folder_list, int x, int y)
+ : BC_GenericButton(x, y, _("Add"))
+{
+       this->folder_list = folder_list;
+}
+BinFolderAddFilter::~BinFolderAddFilter()
+{
+}
+
+int BinFolderAddFilter::handle_event()
+{
+       folder_list->modify_target->close_window();
+// default new filter
+       BinFolderFilter *filter = new BinFolderFilter();
+       filter->update_enabled(FOLDER_ENABLED_OR);
+       filter->update_target(FOLDER_TARGET_PATTERNS);
+       filter->update_op(FOLDER_OP_MATCHES);
+       BinFolderTargetPatterns *patterns = (BinFolderTargetPatterns *)(filter->target);
+       filter->update_value(patterns->text);
+       folder_list->folder->filters.append(filter);
+       folder_list->create_list();
+       return 1;
+}
+
+BinFolderDelFilter::BinFolderDelFilter(BinFolderList *folder_list, int x, int y)
+ : BC_GenericButton(x, y, _("Del"))
+{
+       this->folder_list = folder_list;
+}
+BinFolderDelFilter::~BinFolderDelFilter()
+{
+}
+
+int BinFolderDelFilter::handle_event()
+{
+       folder_list->modify_target->close_window();
+       int no = folder_list->get_selection_number(0, 0);
+       if( no >= 0 ) {
+               folder_list->folder->filters.remove_object_number(no);
+               folder_list->create_list();
+       }
+       return 1;
+}
+
+
+NewFolderGUI::NewFolderGUI(NewFolderThread *thread, int x, int y, int w, int h)
+ : BC_Window(_(PROGRAM_NAME ": New folder"),
+               x, y, w, h, -1, -1, 0, 0, 1)
+{
+       this->thread = thread;
+}
+
+NewFolderGUI::~NewFolderGUI()
+{
+}
+
+void NewFolderGUI::create_objects()
+{
+       lock_window("NewFolderGUI::create_objects");
+       int x = 10, y = 10;
+       BC_Title *title;
+       add_subwindow(title = new BC_Title(x, y, _("Enter the name of the folder:")));
+       y += title->get_h() + 5;
+       add_subwindow(text_box = new BC_TextBox(x, y, 300, 1, _("Untitled")));
+       add_subwindow(new BC_OKButton(this));
+       add_subwindow(new BC_CancelButton(this));
+       show_window();
+       unlock_window();
+}
+
+const char* NewFolderGUI::get_text()
+{
+       return text_box->get_text();
+}
+
+
+NewFolderThread::NewFolderThread(AWindowGUI *agui)
+ : BC_DialogThread()
+{
+       this->agui = agui;
+}
+
+NewFolderThread::~NewFolderThread()
+{
+       close_window();
+}
+
+void NewFolderThread::start(int x, int y, int w, int h)
+{
+       close_window();
+       wx = x;  wy = y;
+       ww = w;  wh = h;
+       Thread::start();
+}
+
+BC_Window *NewFolderThread::new_gui()
+{
+       window = new NewFolderGUI(this, wx, wy, ww, wh);
+       window->create_objects();
+       return window;
+}
+
+void NewFolderThread::handle_done_event(int result)
+{
+       if( !result ) {
+               const char *text = window->get_text();
+               agui->mwindow->new_folder(text);
+       }
+}
+
+void NewFolderThread::handle_close_event(int result)
+{
+}
+
+ModifyFolderGUI::ModifyFolderGUI(ModifyFolderThread *thread, int x, int y, int w, int h)
+ : BC_Window(_(PROGRAM_NAME ": Modify folder"), x, y, w, h, 320, 200, 1, 0, 1)
+{
+       this->thread = thread;
+}
+
+ModifyFolderGUI::~ModifyFolderGUI()
+{
+}
+
+int ModifyFolderGUI::receive_custom_xatoms(xatom_event *event)
+{
+       if( event->message_type == modify_folder_xatom ) {
+               update_filters();
+               return 1;
+       }
+       return 0;
+}
+
+void ModifyFolderGUI::async_update_filters()
+{
+        xatom_event event;
+        event.message_type = modify_folder_xatom;
+        send_custom_xatom(&event);
+}
+
+
+void ModifyFolderGUI::create_objects()
+{
+       lock_window("ModifyFolderGUI::create_objects");
+       modify_folder_xatom = create_xatom("CWINDOWGUI_UPDATE_FILTERS");
+       int x = 10, y = 10;
+       add_tool(new BC_Title(x, y, _("Enter the name of the folder:")));
+       y += 20;
+       add_subwindow(text_box = new BC_TextBox(x, y, 300, 1, thread->folder->title));
+       y += 30;
+       int lh = get_h() - y - BC_OKButton::calculate_h() - 30;
+       int lw = get_w() - x - 120;
+       add_subwindow(folder_list =
+               new BinFolderList(thread->folder, thread->agui->mwindow, this, x, y, lw, lh));
+       folder_list->create_objects();
+       int x1 = x + folder_list->get_w() + 15, y1 = y;
+       add_subwindow(add_filter = new BinFolderAddFilter(folder_list, x1, y1));
+       y1 += add_filter->get_h() + 10;
+       add_subwindow(del_filter = new BinFolderDelFilter(folder_list, x1, y1));
+       add_subwindow(ok_button = new BC_OKButton(this));
+       add_subwindow(cancel_button = new BC_CancelButton(this));
+       show_window();
+       unlock_window();
+}
+
+int ModifyFolderGUI::resize_event(int w, int h)
+{
+       MWindow *mwindow = thread->agui->mwindow;
+       mwindow->session->bwindow_w = w;
+       mwindow->session->bwindow_h = h;
+       int lx = folder_list->get_x();
+       int ly = folder_list->get_y();
+       int lh = h - ly - BC_OKButton::calculate_h() - 30;
+       int lw = w - lx - 120;
+       folder_list->reposition_window(lx, ly, lw, lh);
+       int x1 = lx + lw + 15;
+       add_filter->reposition_window(x1, add_filter->get_y());
+       del_filter->reposition_window(x1, del_filter->get_y());
+       ok_button->resize_event(w, h);
+       cancel_button->resize_event(w, h);
+       return 1;
+}
+
+const char* ModifyFolderGUI::get_text()
+{
+       return text_box->get_text();
+}
+
+void ModifyFolderGUI::update_filters()
+{
+       folder_list->create_list();
+}
+
+
+ModifyFolderThread::ModifyFolderThread(AWindowGUI *agui)
+ : BC_DialogThread()
+{
+       this->agui = agui;
+       original = 0;
+       folder = 0;
+}
+
+ModifyFolderThread::~ModifyFolderThread()
+{
+       close_window();
+       delete folder;
+}
+
+void ModifyFolderThread::start(BinFolder *folder, int x, int y, int w, int h)
+{
+       close_window();
+       this->original = folder;
+       agui->mwindow->edl->add_user();
+       this->folder = new BinFolder(*folder);
+       wx = x;  wy = y;
+       ww = w;  wh = h;
+       Thread::start();
+}
+
+BC_Window *ModifyFolderThread::new_gui()
+{
+       window = new ModifyFolderGUI(this, wx, wy, ww, wh);
+       window->create_objects();
+       return window;
+}
+
+void ModifyFolderThread::handle_done_event(int result)
+{
+       if( !result ) {
+               const char *title = window->get_text();
+               if( strcmp(folder->title, title) ) {
+                       if( agui->mwindow->edl->get_folder_number(title) >= 0 ) {
+                               eprintf("folder already exists: %s", title);
+                               result = 1;
+                       }
+                       else
+                               strncpy(folder->title, title,sizeof(folder->title));
+               }
+       }
+       if( !result ) {
+               original->copy_from(folder);
+               agui->async_update_assets();
+       }
+       delete folder;  folder = 0;
+       original = 0;
+       agui->mwindow->edl->remove_user();
+}
+
+void ModifyFolderThread::handle_close_event(int result)
+{
+}
+
+
+ModifyTargetThread::ModifyTargetThread(BinFolderList *folder_list)
+ : BC_DialogThread()
+{
+       this->folder_list = folder_list;
+       target = 0;
+}
+
+ModifyTargetThread::~ModifyTargetThread()
+{
+       close_window();
+}
+
+void ModifyTargetThread::start(BinFolderTarget *target, int x, int y, int w, int h)
+{
+       this->target = target;
+       wx = x;  wy = y;
+       ww = w;  wh = h;
+       Thread::start();
+}
+
+BC_Window *ModifyTargetThread::new_gui()
+{
+       window = (ModifyTargetGUI *)target->new_gui(this);
+       window->create_objects();
+       return window;
+}
+
+void ModifyTargetThread::handle_done_event(int result)
+{
+       if( !result ) {
+               window->update();
+               folder_list->window->async_update_filters();
+       }
+}
+
+void ModifyTargetThread::handle_close_event(int result)
+{
+       target = 0;
+}
+
+ModifyTargetGUI::ModifyTargetGUI(ModifyTargetThread *thread)
+ : BC_Window(_(PROGRAM_NAME ": Modify target"),
+               thread->wx, thread->wy, thread->ww, thread->wh,
+               -1, -1, 0, 0, 1)
+{
+       this->thread = thread;
+}
+
+ModifyTargetGUI::~ModifyTargetGUI()
+{
+}
+
+void ModifyTargetGUI::create_objects(BC_TextBox *&text_box)
+{
+       lock_window("ModifyTargetGUI::create_objects");
+       int x = 10, y = 10;
+       const char *text = thread->target->filter->value->get_text();
+       add_subwindow(text_box = new BC_TextBox(x, y, get_w()-20, 1, text));
+       add_subwindow(new BC_OKButton(this));
+       add_subwindow(new BC_CancelButton(this));
+       show_window();
+       unlock_window();
+}
+
+ModifyTargetPatternsGUI::ModifyTargetPatternsGUI(ModifyTargetThread *thread)
+ : ModifyTargetGUI(thread)
+{
+       this->thread = thread;
+       scroll_text_box = 0;
+}
+
+ModifyTargetPatternsGUI::~ModifyTargetPatternsGUI()
+{
+       delete scroll_text_box;
+}
+
+void ModifyTargetPatternsGUI::create_objects()
+{
+       lock_window("ModifyTargetPatternsGUI::create_objects");
+       BinFolderTargetPatterns *target = (BinFolderTargetPatterns *)thread->target;
+       int x = 10, y = 10;
+       int text_font = MEDIUMFONT;
+       int text_rowsz = get_text_ascent(text_font)+1 + get_text_descent(text_font)+1;
+       int th = get_h() - BC_OKButton::calculate_h() - y - 10;
+       int rows = th / text_rowsz;
+       scroll_text_box = new BC_ScrollTextBox(this, x, y, get_w()-20, rows, target->text);
+       scroll_text_box->create_objects();
+       add_subwindow(new BC_OKButton(this));
+       add_subwindow(new BC_CancelButton(this));
+       show_window();
+       unlock_window();
+}
+
+void ModifyTargetPatternsGUI::update()
+{
+       BinFolderTargetPatterns *target = (BinFolderTargetPatterns *)thread->target;
+       const char *cp = scroll_text_box->get_text();
+       target->update(cp);
+}
+
+
+ModifyTargetFileSizeGUI::ModifyTargetFileSizeGUI(ModifyTargetThread *thread)
+ : ModifyTargetGUI(thread)
+{
+}
+
+ModifyTargetFileSizeGUI::~ModifyTargetFileSizeGUI()
+{
+}
+
+void ModifyTargetFileSizeGUI::create_objects()
+{
+       ModifyTargetGUI::create_objects(text_box);
+}
+
+void ModifyTargetFileSizeGUI::update()
+{
+       BinFolderTargetFileSize *target = (BinFolderTargetFileSize *)thread->target;
+       double file_size = target->file_size, around = target->around;
+       const char *cp = text_box->get_text();  char *bp = 0;
+       scan_around(cp, bp, file_size, around);
+       target->update(file_size, around);
+}
+
+
+ModifyTargetTimeGUI::ModifyTargetTimeGUI(ModifyTargetThread *thread)
+ : ModifyTargetGUI(thread)
+{
+}
+
+ModifyTargetTimeGUI::~ModifyTargetTimeGUI()
+{
+}
+
+void ModifyTargetTimeGUI::create_objects()
+{
+       ModifyTargetGUI::create_objects(text_box);
+}
+
+void ModifyTargetTimeGUI::update()
+{
+       BinFolderTargetTime *target = (BinFolderTargetTime *)thread->target;
+       int64_t mtime = target->mtime;  double around = target->around;
+       const char *cp = text_box->get_text(); char *bp = 0;
+       int64_t v = scan_date(cp, bp);
+       if( bp > cp ) {
+               mtime = v;
+               if( *bp == '+' ) {
+                       v = scan_duration(cp=bp+1, bp);
+                       if( bp > cp ) around = v;
+               }
+       }
+       target->update(mtime, around);
+}
+
+
+ModifyTargetTrackTypeGUI::ModifyTargetTrackTypeGUI(ModifyTargetThread *thread)
+ : ModifyTargetGUI(thread)
+{
+}
+
+ModifyTargetTrackTypeGUI::~ModifyTargetTrackTypeGUI()
+{
+}
+
+void ModifyTargetTrackTypeGUI::create_objects()
+{
+       ModifyTargetGUI::create_objects(text_box);
+}
+
+void ModifyTargetTrackTypeGUI::update()
+{
+       BinFolderTargetTrackType *target = (BinFolderTargetTrackType *)thread->target;
+       const char *cp = text_box->get_text();
+       int data_types = 0;
+       if( bstrcasestr(cp, _("audio")) ) data_types |= (1<<TRACK_AUDIO);
+       if( bstrcasestr(cp, _("video")) ) data_types |= (1<<TRACK_VIDEO);
+       target->update(data_types);
+}
+
+
+ModifyTargetWidthGUI::ModifyTargetWidthGUI(ModifyTargetThread *thread)
+ : ModifyTargetGUI(thread)
+{
+}
+
+ModifyTargetWidthGUI::~ModifyTargetWidthGUI()
+{
+}
+
+void ModifyTargetWidthGUI::create_objects()
+{
+       ModifyTargetGUI::create_objects(text_box);
+}
+
+void ModifyTargetWidthGUI::update()
+{
+       BinFolderTargetWidth *target = (BinFolderTargetWidth *)thread->target;
+       double width = target->width, around = target->around;
+       const char *cp = text_box->get_text();  char *bp = 0;
+       scan_around(cp, bp, width, around);
+       target->update(width, around);
+}
+
+
+ModifyTargetHeightGUI::ModifyTargetHeightGUI(ModifyTargetThread *thread)
+ : ModifyTargetGUI(thread)
+{
+}
+
+ModifyTargetHeightGUI::~ModifyTargetHeightGUI()
+{
+}
+
+void ModifyTargetHeightGUI::create_objects()
+{
+       ModifyTargetGUI::create_objects(text_box);
+}
+
+void ModifyTargetHeightGUI::update()
+{
+       BinFolderTargetHeight *target = (BinFolderTargetHeight *)thread->target;
+       double height = target->height, around = target->around;
+       const char *cp = text_box->get_text();  char *bp = 0;
+       scan_around(cp, bp, height, around);
+       target->update(height, around);
+}
+
+
+ModifyTargetFramerateGUI::ModifyTargetFramerateGUI(ModifyTargetThread *thread)
+ : ModifyTargetGUI(thread)
+{
+}
+
+ModifyTargetFramerateGUI::~ModifyTargetFramerateGUI()
+{
+}
+
+void ModifyTargetFramerateGUI::create_objects()
+{
+       ModifyTargetGUI::create_objects(text_box);
+}
+
+void ModifyTargetFramerateGUI::update()
+{
+       BinFolderTargetFramerate *target = (BinFolderTargetFramerate *)thread->target;
+       double framerate = target->framerate, around = target->around;
+       const char *cp = text_box->get_text();  char *bp = 0;
+       scan_around(cp, bp, framerate, around);
+       target->update(framerate, around);
+}
+
+
+ModifyTargetSamplerateGUI::ModifyTargetSamplerateGUI(ModifyTargetThread *thread)
+ : ModifyTargetGUI(thread)
+{
+}
+
+ModifyTargetSamplerateGUI::~ModifyTargetSamplerateGUI()
+{
+}
+
+void ModifyTargetSamplerateGUI::create_objects()
+{
+       ModifyTargetGUI::create_objects(text_box);
+}
+
+void ModifyTargetSamplerateGUI::update()
+{
+       BinFolderTargetSamplerate *target = (BinFolderTargetSamplerate *)thread->target;
+       double samplerate = target->samplerate, around = target->around;
+       const char *cp = text_box->get_text();  char *bp = 0;
+       scan_around(cp, bp, samplerate, around);
+       target->update(samplerate, around);
+}
+
+
+ModifyTargetChannelsGUI::ModifyTargetChannelsGUI(ModifyTargetThread *thread)
+ : ModifyTargetGUI(thread)
+{
+}
+
+ModifyTargetChannelsGUI::~ModifyTargetChannelsGUI()
+{
+}
+
+void ModifyTargetChannelsGUI::create_objects()
+{
+       ModifyTargetGUI::create_objects(text_box);
+}
+
+void ModifyTargetChannelsGUI::update()
+{
+       BinFolderTargetChannels *target = (BinFolderTargetChannels *)thread->target;
+       double channels = target->channels, around = target->around;
+       const char *cp = text_box->get_text();  char *bp = 0;
+       scan_around(cp, bp, channels, around);
+       target->update(channels, around);
+}
+
+
+ModifyTargetDurationGUI::ModifyTargetDurationGUI(ModifyTargetThread *thread)
+ : ModifyTargetGUI(thread)
+{
+}
+
+ModifyTargetDurationGUI::~ModifyTargetDurationGUI()
+{
+}
+
+void ModifyTargetDurationGUI::create_objects()
+{
+       ModifyTargetGUI::create_objects(text_box);
+}
+
+void ModifyTargetDurationGUI::update()
+{
+       BinFolderTargetDuration *target = (BinFolderTargetDuration *)thread->target;
+       int64_t duration = target->duration, around = target->around;
+       const char *cp = text_box->get_text();  char *bp = 0;
+       int64_t v = scan_duration(cp, bp);
+       if( bp > cp ) {
+               duration = v;
+               if( *bp == '+' ) {
+                       v = scan_duration(cp=bp+1, bp);
+                       if( bp > cp ) around = v;
+               }
+       }
+       target->update(duration, around);
+}
+
diff --git a/cinelerra-5.1/cinelerra/binfolder.h b/cinelerra-5.1/cinelerra/binfolder.h
new file mode 100644 (file)
index 0000000..cf0c943
--- /dev/null
@@ -0,0 +1,729 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef NEWFOLDER_H
+#define NEWFOLDER_H
+
+#include "arraylist.h"
+#include "awindowgui.inc"
+#include "binfolder.inc"
+#include "datatype.h"
+#include "filesystem.h"
+#include "guicast.h"
+#include "indexable.h"
+#include "mutex.h"
+#include "mwindow.inc"
+
+enum {
+       FOLDER_COLUMN_ENABLE,
+       FOLDER_COLUMN_TARGET,
+       FOLDER_COLUMN_OP,
+       FOLDER_COLUMN_VALUE,
+       FOLDER_COLUMNS
+};
+
+enum {
+       FOLDER_ENABLED_OFF,
+       FOLDER_ENABLED_AND,
+       FOLDER_ENABLED_OR,
+       FOLDER_ENABLED_AND_NOT,
+       FOLDER_ENABLED_OR_NOT,
+};
+enum {
+       FOLDER_TARGET_PATTERNS,
+       FOLDER_TARGET_FILE_SIZE,
+       FOLDER_TARGET_MOD_TIME,
+       FOLDER_TARGET_TRACK_TYPE,
+       FOLDER_TARGET_WIDTH,
+       FOLDER_TARGET_HEIGHT,
+       FOLDER_TARGET_FRAMERATE,
+       FOLDER_TARGET_SAMPLERATE,
+       FOLDER_TARGET_CHANNELS,
+       FOLDER_TARGET_DURATION,
+};
+enum {
+       FOLDER_OP_AROUND,
+       FOLDER_OP_EQ, FOLDER_OP_GE, FOLDER_OP_GT,
+       FOLDER_OP_NE, FOLDER_OP_LE, FOLDER_OP_LT,
+       FOLDER_OP_MATCHES,
+};
+
+class BinFolderFilters : public ArrayList<BinFolderFilter *>
+{
+public:
+       BinFolderFilters() {}
+       ~BinFolderFilters() { remove_all_objects(); }
+       void copy_from(BinFolderFilters *filters);
+       void clear() { remove_all_objects(); }
+};
+
+class BinFolder
+{
+public:
+       BinFolder(int awindow_folder, const char *title);
+       BinFolder(BinFolder &that);
+       ~BinFolder();
+
+       BinFolderFilters filters;
+       void save_xml(FileXML *file);
+       int load_xml(FileXML *file);
+       double matches_indexable(Indexable *idxbl);
+       void copy_from(BinFolder *that);
+       void add_patterns(ArrayList<Indexable*> *drag_assets);
+
+       char title[BCSTRLEN];
+       int awindow_folder;
+};
+
+class BinFolders : public ArrayList<BinFolder *>
+{
+public:
+       BinFolders() {}
+       ~BinFolders() {}
+       void save_xml(FileXML *file);
+       int load_xml(FileXML *file);
+       double matches_indexable(int folder, Indexable *idxbl);
+       void copy_from(BinFolders *that);
+       void clear() { remove_all_objects(); }
+};
+
+class BinFolderFilter
+{
+public:
+       BinFolderFilter();
+       ~BinFolderFilter();
+
+       void update_enabled(int type);
+       void update_target(int type);
+       void update_op(int type);
+       void update_value(const char *text);
+       void save_xml(FileXML *file);
+       int load_xml(FileXML *file);
+
+       BinFolderEnabled *enabled;
+       BinFolderTarget *target;
+       BinFolderOp *op;
+       BinFolderValue *value;
+};
+
+class BinFolderEnabled : public BC_ListBoxItem
+{
+public:
+       BinFolderEnabled(BinFolderFilter *filter, int type);
+       virtual ~BinFolderEnabled();
+       void update(int type);
+
+       BinFolderFilter *filter;
+       int type;
+       static const char *types[];
+};
+
+class BinFolderEnabledType : public BC_MenuItem
+{
+public:
+       BinFolderEnabledType(int no);
+       ~BinFolderEnabledType();
+       int no;
+       int handle_event();
+};
+class BinFolderEnabledPopup : public BC_PopupMenu
+{
+public:
+       BinFolderEnabledPopup(BinFolderList *folder_list);
+       void create_objects();
+       void activate_menu(BC_ListBoxItem *item);
+
+       BinFolderList *folder_list;
+       BinFolderEnabled *enabled;
+};
+
+class BinFolderTarget : public BC_ListBoxItem
+{
+public:
+       BinFolderTarget(BinFolderFilter *filter, int type);
+       virtual ~BinFolderTarget();
+
+       virtual void save_xml(FileXML *file) = 0;
+       virtual void load_xml(FileXML *file) = 0;
+       virtual void copy_from(BinFolderTarget *that) = 0;
+       virtual BC_Window *new_gui(ModifyTargetThread *thread) = 0;
+
+       BinFolderFilter *filter;
+       int type;
+       double around;
+       static const char *types[];
+};
+
+class BinFolderTargetPatterns : public BinFolderTarget
+{
+public:
+       BinFolderTargetPatterns(BinFolderFilter *filter);
+       ~BinFolderTargetPatterns();
+
+       void save_xml(FileXML *file);
+       void load_xml(FileXML *file);
+       void copy_from(BinFolderTarget *that);
+       BC_Window *new_gui(ModifyTargetThread *thread);
+       void update(const char *text);
+
+       char *text;
+};
+
+class BinFolderTargetFileSize : public BinFolderTarget
+{
+public:
+       BinFolderTargetFileSize(BinFolderFilter *filter);
+       ~BinFolderTargetFileSize();
+
+       void save_xml(FileXML *file);
+       void load_xml(FileXML *file);
+       void copy_from(BinFolderTarget *that);
+       BC_Window *new_gui(ModifyTargetThread *thread);
+       void update(int64_t file_size, double around);
+
+       int64_t file_size;
+};
+
+class BinFolderTargetTime : public BinFolderTarget
+{
+public:
+       BinFolderTargetTime(BinFolderFilter *filter);
+       ~BinFolderTargetTime();
+
+       void save_xml(FileXML *file);
+       void load_xml(FileXML *file);
+       void copy_from(BinFolderTarget *that);
+       BC_Window *new_gui(ModifyTargetThread *thread);
+       void update(int64_t mtime, double around);
+
+       int64_t mtime;
+};
+
+class BinFolderTargetTrackType : public BinFolderTarget
+{
+public:
+       BinFolderTargetTrackType(BinFolderFilter *filter);
+       ~BinFolderTargetTrackType();
+
+       void save_xml(FileXML *file);
+       void load_xml(FileXML *file);
+       void copy_from(BinFolderTarget *that);
+       BC_Window *new_gui(ModifyTargetThread *thread);
+       void update(int data_types);
+
+       int data_types;
+};
+
+class BinFolderTargetWidth : public BinFolderTarget
+{
+public:
+       BinFolderTargetWidth(BinFolderFilter *filter);
+       ~BinFolderTargetWidth();
+
+       void save_xml(FileXML *file);
+       void load_xml(FileXML *file);
+       void copy_from(BinFolderTarget *that);
+       BC_Window *new_gui(ModifyTargetThread *thread);
+       void update(int width, double around);
+
+       int width;
+};
+
+class BinFolderTargetHeight : public BinFolderTarget
+{
+public:
+       BinFolderTargetHeight(BinFolderFilter *filter);
+       ~BinFolderTargetHeight();
+
+       void save_xml(FileXML *file);
+       void load_xml(FileXML *file);
+       void copy_from(BinFolderTarget *that);
+       BC_Window *new_gui(ModifyTargetThread *thread);
+       void update(int height, double around);
+
+       int height;
+};
+
+class BinFolderTargetFramerate : public BinFolderTarget
+{
+public:
+       BinFolderTargetFramerate(BinFolderFilter *filter);
+       ~BinFolderTargetFramerate();
+
+       void save_xml(FileXML *file);
+       void load_xml(FileXML *file);
+       void copy_from(BinFolderTarget *that);
+       BC_Window *new_gui(ModifyTargetThread *thread);
+       void update(double framerate, double around);
+
+       double framerate;
+};
+
+class BinFolderTargetSamplerate : public BinFolderTarget
+{
+public:
+       BinFolderTargetSamplerate(BinFolderFilter *filter);
+       ~BinFolderTargetSamplerate();
+
+       void save_xml(FileXML *file);
+       void load_xml(FileXML *file);
+       void copy_from(BinFolderTarget *that);
+       BC_Window *new_gui(ModifyTargetThread *thread);
+       void update(int samplerate, double around);
+
+       int samplerate;
+};
+
+class BinFolderTargetChannels : public BinFolderTarget
+{
+public:
+       BinFolderTargetChannels(BinFolderFilter *filter);
+       ~BinFolderTargetChannels();
+
+       void save_xml(FileXML *file);
+       void load_xml(FileXML *file);
+       void copy_from(BinFolderTarget *that);
+       BC_Window *new_gui(ModifyTargetThread *thread);
+       void update(int channels, double around);
+
+       int channels;
+};
+
+class BinFolderTargetDuration : public BinFolderTarget
+{
+public:
+       BinFolderTargetDuration(BinFolderFilter *filter);
+       ~BinFolderTargetDuration();
+
+       void save_xml(FileXML *file);
+       void load_xml(FileXML *file);
+       void copy_from(BinFolderTarget *that);
+       BC_Window *new_gui(ModifyTargetThread *thread);
+       void update(int64_t duration, double around);
+
+       int64_t duration;
+};
+
+class BinFolderTargetType : public BC_MenuItem
+{
+public:
+       BinFolderTargetType(int no);
+       ~BinFolderTargetType();
+       int no;
+       int handle_event();
+};
+
+class BinFolderTargetPopup : public BC_PopupMenu
+{
+public:
+       BinFolderTargetPopup(BinFolderList *folder_list);
+       void create_objects();
+       void activate_menu(BC_ListBoxItem *item);
+
+       BinFolderList *folder_list;
+       BinFolderTarget *target;
+};
+
+
+class BinFolderOp : public BC_ListBoxItem
+{
+public:
+       BinFolderOp(BinFolderFilter *filter, int type);
+       virtual ~BinFolderOp();
+
+       double compare(BinFolderTarget *target, Indexable *idxbl);
+       virtual double test(BinFolderTarget *target, Indexable *idxbl);
+       double around(double v, double a);
+       double around(const char *ap, const char *bp);
+
+       void copy_from(BinFolderOp *that);
+
+       BinFolderFilter *filter;
+       int type;
+       static const char *types[];
+};
+
+class BinFolderOpType : public BC_MenuItem
+{
+public:
+       BinFolderOpType(int no);
+       ~BinFolderOpType();
+       int no;
+       int handle_event();
+};
+
+class BinFolderOpPopup : public BC_PopupMenu
+{
+public:
+       BinFolderOpPopup(BinFolderList *folder_list);
+       void create_objects();
+       void activate_menu(BC_ListBoxItem *item);
+
+       BinFolderList *folder_list;
+       BinFolderOp *op;
+};
+
+
+class BinFolderOpAround : public BinFolderOp
+{
+public:
+       BinFolderOpAround(BinFolderFilter *filter)
+        : BinFolderOp(filter, FOLDER_OP_AROUND) {}
+       ~BinFolderOpAround() {}
+       double test(BinFolderTarget *target, Indexable *idxbl);
+};
+
+class BinFolderOpEQ : public BinFolderOp
+{
+public:
+       BinFolderOpEQ(BinFolderFilter *filter)
+        : BinFolderOp(filter, FOLDER_OP_EQ) {}
+       ~BinFolderOpEQ() {}
+       double test(BinFolderTarget *target, Indexable *idxbl);
+};
+
+class BinFolderOpGT : public BinFolderOp
+{
+public:
+       BinFolderOpGT(BinFolderFilter *filter)
+        : BinFolderOp(filter, FOLDER_OP_GT) {}
+       ~BinFolderOpGT() {}
+       double test(BinFolderTarget *target, Indexable *idxbl);
+};
+
+class BinFolderOpGE : public BinFolderOp
+{
+public:
+       BinFolderOpGE(BinFolderFilter *filter)
+        : BinFolderOp(filter, FOLDER_OP_GE) {}
+       ~BinFolderOpGE() {}
+       double test(BinFolderTarget *target, Indexable *idxbl);
+};
+
+class BinFolderOpNE : public BinFolderOp
+{
+public:
+       BinFolderOpNE(BinFolderFilter *filter)
+        : BinFolderOp(filter, FOLDER_OP_NE) {}
+       ~BinFolderOpNE() {}
+       double test(BinFolderTarget *target, Indexable *idxbl);
+};
+
+class BinFolderOpLT : public BinFolderOp
+{
+public:
+       BinFolderOpLT(BinFolderFilter *filter)
+        : BinFolderOp(filter, FOLDER_OP_LT) {}
+       ~BinFolderOpLT() {}
+       double test(BinFolderTarget *target, Indexable *idxbl);
+};
+
+class BinFolderOpLE : public BinFolderOp
+{
+public:
+       BinFolderOpLE(BinFolderFilter *filter)
+        : BinFolderOp(filter, FOLDER_OP_LE) {}
+       ~BinFolderOpLE() {}
+       double test(BinFolderTarget *target, Indexable *idxbl);
+};
+
+class BinFolderOpMatches : public BinFolderOp
+{
+public:
+       BinFolderOpMatches(BinFolderFilter *filter)
+        : BinFolderOp(filter, FOLDER_OP_MATCHES) {}
+       ~BinFolderOpMatches() {}
+       double test(BinFolderTarget *target, Indexable *idxbl);
+};
+
+class BinFolderValue : public BC_ListBoxItem
+{
+public:
+       BinFolderValue(BinFolderFilter *filter, const char *text);
+       virtual ~BinFolderValue();
+
+       void update(const char *text);
+
+       BinFolderFilter *filter;
+};
+
+
+class BinFolderList : public BC_ListBox
+{
+public:
+       BinFolderList(BinFolder *folder, MWindow *mwindow,
+               ModifyFolderGUI *window, int x, int y, int w, int h);
+       ~BinFolderList();
+       void create_objects();
+
+       int handle_event();
+       int handle_event(int column);
+       int selection_changed();
+       int column_resize_event();
+       void create_list();
+       void save_defaults(BC_Hash *defaults);
+       void load_defaults(BC_Hash *defaults);
+       void move_filter(int src, int dst);
+
+       int drag_start_event();
+       int drag_motion_event();
+       int drag_stop_event();
+       int dragging_item;
+
+       BinFolder *folder;
+       MWindow *mwindow;
+       ModifyFolderGUI *window;
+       ArrayList<BC_ListBoxItem *>list_items[FOLDER_COLUMNS];
+       const char *list_titles[FOLDER_COLUMNS];
+       int list_width[FOLDER_COLUMNS];
+
+       BinFolderEnabledPopup *enabled_popup;
+       BinFolderOpPopup *op_popup;
+       BinFolderTargetPopup *target_popup;
+
+       ModifyTargetThread *modify_target;
+};
+
+class BinFolderAddFilter : public BC_GenericButton
+{
+public:
+       BinFolderAddFilter(BinFolderList *folder_list, int x, int y);
+       ~BinFolderAddFilter();
+       int handle_event();
+       BinFolderList *folder_list;
+};
+
+class BinFolderDelFilter : public BC_GenericButton
+{
+public:
+       BinFolderDelFilter(BinFolderList *folder_list, int x, int y);
+       ~BinFolderDelFilter();
+       int handle_event();
+       BinFolderList *folder_list;
+};
+
+class NewFolderGUI : public BC_Window
+{
+public:
+       NewFolderGUI(NewFolderThread *thread, int x, int y, int w, int h);
+       ~NewFolderGUI();
+       void create_objects();
+       const char *get_text();
+
+       NewFolderThread *thread;
+       BinFolderList *folder_list;
+       BC_TextBox *text_box;
+};
+
+class NewFolderThread : public BC_DialogThread
+{
+public:
+       NewFolderThread(AWindowGUI *agui);
+       ~NewFolderThread();
+       BC_Window *new_gui();
+       void handle_done_event(int result);
+       void handle_close_event(int result);
+       void start(int x, int y, int w, int h);
+
+       int wx, wy, ww, wh;
+       AWindowGUI *agui;
+       NewFolderGUI *window;
+};
+
+
+class ModifyFolderGUI : public BC_Window
+{
+public:
+       ModifyFolderGUI(ModifyFolderThread *thread, int x, int y, int w, int h);
+       ~ModifyFolderGUI();
+       void create_objects();
+       int resize_event(int w, int h);
+       const char *get_text();
+       int receive_custom_xatoms(xatom_event *event);
+       void async_update_filters();
+       void update_filters();
+
+       ModifyFolderThread *thread;
+       BinFolderList *folder_list;
+       BinFolderAddFilter *add_filter;
+       BinFolderDelFilter *del_filter;
+       BC_TextBox *text_box;
+       Atom modify_folder_xatom;
+       BC_OKButton *ok_button;
+       BC_CancelButton *cancel_button;
+};
+
+class ModifyFolderThread : public BC_DialogThread
+{
+public:
+       ModifyFolderThread(AWindowGUI *agui);
+       ~ModifyFolderThread();
+       BC_Window *new_gui();
+       void handle_done_event(int result);
+       void handle_close_event(int result);
+       void start(BinFolder *folder, int x, int y, int w, int h);
+
+       int wx, wy, ww, wh;
+       AWindowGUI *agui;
+       BinFolder *original, *folder;
+       ModifyFolderGUI *window;
+};
+
+
+class ModifyTargetGUI : public BC_Window
+{
+public:
+       ModifyTargetGUI(ModifyTargetThread *thread);
+       ~ModifyTargetGUI();
+       virtual void create_objects() {}
+       virtual void update() {}
+       void create_objects(BC_TextBox *&text_box);
+
+       ModifyTargetThread *thread;
+};
+
+class ModifyTargetThread : public BC_DialogThread
+{
+public:
+       ModifyTargetThread(BinFolderList *folder_list);
+       ~ModifyTargetThread();
+       BC_Window *new_gui();
+       void handle_done_event(int result);
+       void handle_close_event(int result);
+       void start(BinFolderTarget *target, int x, int y, int w, int h);
+
+       int wx, wy, ww, wh;
+       BinFolderList *folder_list;
+       BinFolderTarget *target;
+       ModifyTargetGUI *window;
+};
+
+class ModifyTargetPatternsGUI : public ModifyTargetGUI
+{
+public:
+       ModifyTargetPatternsGUI(ModifyTargetThread *thread);
+       ~ModifyTargetPatternsGUI();
+       void create_objects();
+       void update();
+
+       BC_ScrollTextBox *scroll_text_box;
+};
+
+class ModifyTargetFileSizeGUI : public ModifyTargetGUI
+{
+public:
+       ModifyTargetFileSizeGUI(ModifyTargetThread *thread);
+       ~ModifyTargetFileSizeGUI();
+       void create_objects();
+       void update();
+
+       BC_TextBox *text_box;
+};
+
+class ModifyTargetTimeGUI : public ModifyTargetGUI
+{
+public:
+       ModifyTargetTimeGUI(ModifyTargetThread *thread);
+       ~ModifyTargetTimeGUI();
+       void create_objects();
+       void update();
+
+       BC_TextBox *text_box;
+};
+
+class ModifyTargetTrackTypeGUI : public ModifyTargetGUI
+{
+public:
+       ModifyTargetTrackTypeGUI(ModifyTargetThread *thread);
+       ~ModifyTargetTrackTypeGUI();
+       void create_objects();
+       void update();
+
+       BC_TextBox *text_box;
+};
+
+class ModifyTargetWidthGUI : public ModifyTargetGUI
+{
+public:
+       ModifyTargetWidthGUI(ModifyTargetThread *thread);
+       ~ModifyTargetWidthGUI();
+       void create_objects();
+       void update();
+
+       BC_TextBox *text_box;
+};
+
+class ModifyTargetHeightGUI : public ModifyTargetGUI
+{
+public:
+       ModifyTargetHeightGUI(ModifyTargetThread *thread);
+       ~ModifyTargetHeightGUI();
+       void create_objects();
+       void update();
+
+       BC_TextBox *text_box;
+};
+
+class ModifyTargetFramerateGUI : public ModifyTargetGUI
+{
+public:
+       ModifyTargetFramerateGUI(ModifyTargetThread *thread);
+       ~ModifyTargetFramerateGUI();
+       void create_objects();
+       void update();
+
+       BC_TextBox *text_box;
+};
+
+class ModifyTargetSamplerateGUI : public ModifyTargetGUI
+{
+public:
+       ModifyTargetSamplerateGUI(ModifyTargetThread *thread);
+       ~ModifyTargetSamplerateGUI();
+       void create_objects();
+       void update();
+
+       BC_TextBox *text_box;
+};
+
+class ModifyTargetChannelsGUI : public ModifyTargetGUI
+{
+public:
+       ModifyTargetChannelsGUI(ModifyTargetThread *thread);
+       ~ModifyTargetChannelsGUI();
+       void create_objects();
+       void update();
+
+       BC_TextBox *text_box;
+};
+
+class ModifyTargetDurationGUI : public ModifyTargetGUI
+{
+public:
+       ModifyTargetDurationGUI(ModifyTargetThread *thread);
+       ~ModifyTargetDurationGUI();
+       void create_objects();
+       void update();
+
+       BC_TextBox *text_box;
+};
+
+#endif
diff --git a/cinelerra-5.1/cinelerra/binfolder.inc b/cinelerra-5.1/cinelerra/binfolder.inc
new file mode 100644 (file)
index 0000000..6aeddc4
--- /dev/null
@@ -0,0 +1,77 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef NEWFOLDER_INC
+#define NEWFOLDER_INC
+
+class BinFolderFilters;
+class BinFolder;
+class BinFolders;
+class BinFolderFilter;
+class BinFolderEnabled;
+class BinFolderEnabledType;
+class BinFolderEnabledPopup;
+class BinFolderTarget;
+class BinFolderTargetPatterns;
+class BinFolderTargetFileSize;
+class BinFolderTargetTime;
+class BinFolderTargetTrackType;
+class BinFolderTargetWidth;
+class BinFolderTargetHeight;
+class BinFolderTargetFramerate;
+class BinFolderTargetSamplerate;
+class BinFolderTargetChannels;
+class BinFolderTargetDuration;
+class BinFolderTargetType;
+class BinFolderTargetPopup;
+class BinFolderOp;
+class BinFolderOpType;
+class BinFolderOpPopup;
+class BinFolderOpEQ;
+class BinFolderOpGT;
+class BinFolderOpGE;
+class BinFolderOpNE;
+class BinFolderOpLT;
+class BinFolderOpLE;
+class BinFolderOpMatches;
+class BinFolderOpAround;
+class BinFolderValue;
+class BinFolderList;
+class BinFolderAddFilter;
+class BinFolderDelFilter;
+class NewFolderGUI;
+class NewFolderThread;
+class ModifyFolderGUI;
+class ModifyFolderThread;
+class ModifyTargetGUI;
+class ModifyTargetThread;
+class ModifyTargetPatternsGUI;
+class ModifyTargetFileSizeGUI;
+class ModifyTargetTimeGUI;
+class ModifyTargetTrackTypeGUI;
+class ModifyTargetWidthGUI;
+class ModifyTargetHeightGUI;
+class ModifyTargetFramerateGUI;
+class ModifyTargetSamplerateGUI;
+class ModifyTargetChannelsGUI;
+class ModifyTargetDurationGUI;
+
+#endif
index f63d1124f9f487a1d46b29aff092dcbf61787961..1d0b3beab4fbda73b7de8704c04c06aeb890667d 100644 (file)
@@ -38,7 +38,7 @@
 // rendering or foreground rendering can be happening but not both.
 
 // A BRenderThread client runs in the background and a BRender object
-// interfaces the main window.  The BRender client recieves commands to
+// interfaces the main window.  The BRender client receives commands to
 // restart, start, and stop background rendering on its own time to avoid
 // interrupting the main window.
 
index df439311dc32d95819f75335a8f11b0db4cad808..6806848151c5551abcd0f38a2670a776aa7820aa 100644 (file)
@@ -175,7 +175,7 @@ ClipPopupSort::~ClipPopupSort()
 
 int ClipPopupSort::handle_event()
 {
-       mwindow->awindow->gui->sort_assets(0);
+       mwindow->awindow->gui->sort_assets();
        return 1;
 }
 
index a114f3c995ec3df962b516caf2fe19f216ac7408..4411bf4bd0c652d0a065bb72f85e32ffbb7648f8 100644 (file)
@@ -24,7 +24,7 @@
 #include "atrack.h"
 #include "autoconf.h"
 #include "automation.h"
-#include "awindowgui.inc"
+#include "awindowgui.h"
 #include "bccmodels.h"
 #include "bchash.h"
 #include "bcsignals.h"
@@ -70,7 +70,6 @@ EDL::EDL(EDL *parent_edl)
        tracks = 0;
        labels = 0;
        local_session = 0;
-       folders.set_array_delete();
        id = next_id();
        path[0] = 0;
 }
@@ -87,7 +86,6 @@ EDL::~EDL()
                delete assets;
                delete session;
        }
-       folders.remove_all_objects();
 }
 
 
@@ -146,9 +144,7 @@ int EDL::create_default_tracks()
 int EDL::load_xml(FileXML *file, uint32_t load_flags)
 {
        int result = 0;
-
-// Clear objects
-       folders.remove_all_objects();
+       folders.clear();
 
        if( (load_flags & LOAD_ALL) == LOAD_ALL ) {
                remove_vwindow_edls();
@@ -237,10 +233,8 @@ int EDL::read_xml(FileXML *file, uint32_t load_flags)
                                        result = file->skip_tag();
                        }
                        else
-                       if( file->tag.title_is("FOLDER") ) {
-                               char folder[BCTEXTLEN];
-                               strcpy(folder, file->read_text());
-                               new_folder(folder);
+                       if( file->tag.title_is("FOLDERS") ) {
+                               result = folders.load_xml(file);
                        }
                        else
                        if( file->tag.title_is("MIXERS") ) {
@@ -408,11 +402,8 @@ void EDL::copy_session(EDL *edl, int session_only)
 
        if( !session_only ) {
                strcpy(this->path, edl->path);
-//printf("EDL::copy_session %p %s\n", this, this->path);
-
-               folders.remove_all_objects();
-               for( int i=0; i<edl->folders.size(); ++i )
-                       folders.append(cstrdup(edl->folders[i]));
+               awindow_folder = edl->awindow_folder;
+               folders.copy_from(&edl->folders);
        }
 
        if( !parent_edl ) {
@@ -548,16 +539,7 @@ int EDL::copy(double start, double end, int all,
                session->save_xml(file);
                session->save_video_config(file);
                session->save_audio_config(file);
-
-// Folders
-               for( int i=0; i<folders.size(); ++i ) {
-                       file->tag.set_title("FOLDER");
-                       file->append_tag();
-                       file->append_text(folders[i]);
-                       file->tag.set_title("/FOLDER");
-                       file->append_tag();
-                       file->append_newline();
-               }
+               folders.save_xml(file);
 
                if( !parent_edl )
                        copy_assets(start, end, file, all, output_path);
@@ -1214,18 +1196,58 @@ double EDL::align_to_frame(double position, int round)
 }
 
 
-void EDL::new_folder(const char *folder)
+BinFolder *EDL::get_folder(int no)
+{
+       for( int i=0; i<folders.size(); ++i ) {
+               BinFolder *fp = folders[i];
+               if( no == fp->awindow_folder ) return fp;
+       }
+       return 0;
+}
+
+int EDL::get_folder_number(const char *title)
 {
-       for( int i=0; i<folders.size(); ++i )
-               if( !strcasecmp(folders[i], folder) ) return;
-       folders.append(cstrdup(folder));
+       for( int i=0; i<AWINDOW_FOLDERS; ++i ) {
+               if( !strcmp(title, AWindowGUI::folder_names[i]) )
+                       return i;
+       }
+       for( int i=0; i<folders.size(); ++i ) {
+               if( !strcmp(title, folders[i]->title) )
+                       return folders[i]->awindow_folder;
+       }
+        return AW_NO_FOLDER;
+}
+
+const char *EDL::get_folder_name(int no)
+{
+       if( no >= 0 && no<AWINDOW_FOLDERS )
+               return AWindowGUI::folder_names[no];
+       BinFolder *fp = get_folder(no);
+       return !fp ? "" : fp->title;
+}
+
+int EDL::new_folder(const char *title)
+{
+       if( !title[0] ) return 1;
+       int ret = get_folder_number(title);
+       if( ret >= 0 ) return 1;
+       int idx = AWINDOW_FOLDERS;
+       for( int i=0; i<folders.size(); ++i ) {
+               BinFolder *fp = folders[i];
+               int no = fp->awindow_folder;
+               if( no >= idx ) idx = no+1;
+       }
+       folders.append(new BinFolder(idx, title));
+       return 0;
 }
 
-void EDL::delete_folder(const char *folder)
+int EDL::delete_folder(const char *title)
 {
-       int i = folders.size();
-       while( --i >= 0 && strcasecmp(folders[i], folder) );
-       if( i >= 0 ) folders.remove_number(i);
+       int k = folders.size();
+       while( --k >= 0 && strcmp(title, folders[k]->title) );
+       if( k >= 0 )
+               folders.remove_object_number(k);
+       return k;
 }
 
 int EDL::get_use_vconsole(VEdit* *playable_edit,
index 606dcead99d9f05015d1426a44beb014bf9c367a..e4b56e57ce4c9ac69f046ab877b39e8a70367c4b 100644 (file)
@@ -29,6 +29,7 @@
 #include "assets.inc"
 #include "autoconf.inc"
 #include "bchash.inc"
+#include "binfolder.h"
 #include "edit.inc"
 #include "edits.inc"
 #include "edl.inc"
@@ -160,9 +161,13 @@ public:
 // Debug
        int dump(FILE *fp=stdout);
        static int next_id();
-// Create a new folder if it doesn't exist already
-       void new_folder(const char *folder);
-       void delete_folder(const char *folder);
+// folders
+       BinFolder *get_folder(int no);
+       int get_folder_number(const char *title);
+       const char *get_folder_name(int no);
+       int new_folder(const char *title);
+       int delete_folder(const char *title);
+
        void modify_edithandles(double oldposition,
                double newposition,
                int currentend,
@@ -258,7 +263,7 @@ public:
                ArrayList<Indexable*> *orig_assets, ArrayList<Indexable*> *proxy_assets);
 
 // Titles of all subfolders
-       ArrayList<char*> folders;
+       BinFolders folders;
 // Clips, Nested EDLs
        ClipEDLs clips, nested_edls;
 // EDLs being shown in VWindows
index ee7a82481efa1db3f4e0259d2eaf3430923b8916..a01691b2c339be714addff85466e57dad10747cd 100644 (file)
@@ -64,6 +64,7 @@ class EDL;
 #define AW_MEDIA_FOLDER       6
 #define AW_PROXY_FOLDER       7
 #define AWINDOW_FOLDERS       8
+#define AWINDOW_USER_FOLDERS  8
 
 
 #define AWINDOW_MODES 2
index 9bdb6458192f00ed7811f44f43ef9db688fc8d45..1eb9b6b986752f07917ffba50b45a6bacb055746 100644 (file)
@@ -241,7 +241,7 @@ int EDLSession::load_defaults(BC_Hash *defaults)
        ruler_x2 = defaults->get("RULER_X2", 0.0);
        ruler_y1 = defaults->get("RULER_Y1", 0.0);
        ruler_y2 = defaults->get("RULER_Y2", 0.0);
-       awindow_folder = defaults->get("AWINDOW_FOLDER", awindow_folder);
+       awindow_folder = defaults->get("AWINDOW_FOLDER", AW_MEDIA_FOLDER);
        cursor_on_frames = defaults->get("CURSOR_ON_FRAMES", 1);
        typeless_keyframes = defaults->get("TYPELESS_KEYFRAMES", 0);
        cwindow_dest = defaults->get("CWINDOW_DEST", 0);
@@ -609,13 +609,7 @@ int EDLSession::load_xml(FileXML *file,
                ruler_y1 = file->tag.get_property("RULER_Y1", ruler_y1);
                ruler_x2 = file->tag.get_property("RULER_X2", ruler_x2);
                ruler_y2 = file->tag.get_property("RULER_Y2", ruler_y2);
-               string[0] = 0;
-               file->tag.get_property("CURRENT_FOLDER", string);
-               if( string[0] ) {
-                       awindow_folder = AWindowGUI::folder_number(string);
-                       if( awindow_folder < 0 ) awindow_folder = AW_MEDIA_FOLDER;
-               }
-               file->tag.get_property("AWINDOW_FOLDER", awindow_folder);
+               awindow_folder = file->tag.get_property("AWINDOW_FOLDER", AW_MEDIA_FOLDER);
                cursor_on_frames = file->tag.get_property("CURSOR_ON_FRAMES", cursor_on_frames);
                typeless_keyframes = file->tag.get_property("TYPELESS_KEYFRAMES", typeless_keyframes);
                cwindow_dest = file->tag.get_property("CWINDOW_DEST", cwindow_dest);
index 823c9f3105df2c85e5a53e40f161c6ac887642de..8f788272b99a7bfecd688228727f810d91c423de 100644 (file)
@@ -25,6 +25,7 @@
 #include "edl.h"
 #include "edlsession.h"
 #include "language.h"
+#include "mainsession.h"
 #include "mwindow.h"
 
 
@@ -41,8 +42,15 @@ FolderListMenu::~FolderListMenu()
 
 void FolderListMenu::create_objects()
 {
+       BC_MenuItem *menu_item;
+       BC_SubMenu *submenu;
        add_item(format = new FolderListFormat(mwindow, this));
        add_item(new FolderListSort(mwindow, this));
+       add_item(menu_item = new BC_MenuItem(_("Folder...")));
+       menu_item->add_submenu(submenu = new BC_SubMenu());
+       submenu->add_submenuitem(new FolderListNew(mwindow, this));
+       submenu->add_submenuitem(new FolderListModify(mwindow, this));
+       submenu->add_submenuitem(new FolderListDelete(mwindow, this));
        update_titles();
 }
 
@@ -92,3 +100,64 @@ int FolderListSort::handle_event()
        return 1;
 }
 
+FolderListNew::FolderListNew(MWindow *mwindow, FolderListMenu *menu)
+ : BC_MenuItem(_("New folder"))
+{
+       this->mwindow = mwindow;
+       this->menu = menu;
+}
+
+int FolderListNew::handle_event()
+{
+       int cx, cy, cw = 320, ch = 120;
+       menu->gui->get_abs_cursor(cx, cy);
+       if( (cx-=cw/2) < 50 ) cx = 50;
+       if( (cy-=ch/2) < 50 ) cy = 50;
+       menu->gui->new_folder_thread->start(cx, cy, cw, ch);
+       return 1;
+}
+
+FolderListModify::FolderListModify(MWindow *mwindow, FolderListMenu *menu)
+ : BC_MenuItem(_("Modify folder"))
+{
+       this->mwindow = mwindow;
+       this->menu = menu;
+}
+
+int FolderListModify::handle_event()
+{
+       int awindow_folder = mwindow->edl->session->awindow_folder;
+       BinFolder *folder = mwindow->edl->get_folder(awindow_folder);
+       if( folder ) {
+               int bw = mwindow->session->bwindow_w;
+               int bh = mwindow->session->bwindow_h;
+               int cx, cy;
+               menu->gui->get_abs_cursor(cx, cy);
+               if( (cx-=bw/2) < 50 ) cx = 50;
+               if( (cy-=bh/2) < 50 ) cy = 50;
+               menu->gui->modify_folder_thread->start(folder, cx, cy, bw, bh);
+       }
+       return 1;
+}
+
+FolderListDelete::FolderListDelete(MWindow *mwindow, FolderListMenu *menu)
+ : BC_MenuItem(_("Delete folder"))
+{
+       this->mwindow = mwindow;
+       this->menu = menu;
+}
+
+int FolderListDelete::handle_event()
+{
+       AssetPicon *picon = (AssetPicon *)menu->gui->folder_list->get_selection(0, 0);
+       if( picon && picon->foldernum >= AWINDOW_USER_FOLDERS ) {
+               int foldernum = picon->foldernum;
+               BinFolder *folder = mwindow->edl->get_folder(foldernum);
+               mwindow->delete_folder(folder->title);
+               if( mwindow->edl->session->awindow_folder == foldernum )
+                       mwindow->edl->session->awindow_folder = AW_MEDIA_FOLDER;
+               mwindow->awindow->gui->async_update_assets();
+       }
+       return 1;
+}
+
index 184e609249a3ec4ff393d551e796202199abdcda..753f86cdb7c1b19876fd98c096f104d08a33b213 100644 (file)
@@ -47,6 +47,36 @@ public:
        FolderListMenu *menu;
 };
 
+class FolderListNew : public BC_MenuItem
+{
+public:
+       FolderListNew(MWindow *mwindow, FolderListMenu *menu);
+
+       int handle_event();
+       MWindow *mwindow;
+       FolderListMenu *menu;
+};
+
+class FolderListModify : public BC_MenuItem
+{
+public:
+       FolderListModify(MWindow *mwindow, FolderListMenu *menu);
+
+       int handle_event();
+       MWindow *mwindow;
+       FolderListMenu *menu;
+};
+
+class FolderListDelete : public BC_MenuItem
+{
+public:
+       FolderListDelete(MWindow *mwindow, FolderListMenu *menu);
+
+       int handle_event();
+       MWindow *mwindow;
+       FolderListMenu *menu;
+};
+
 class FolderListMenu : public BC_PopupMenu
 {
 public:
index 3aacee67348734a697556c9b6f1e9af2266fb1b4..293d321ed567a6b971b3a1cb74df0433824b8dd5 100644 (file)
@@ -73,6 +73,7 @@ void Indexable::update_index(Indexable *src)
 void Indexable::copy_indexable(Indexable *src)
 {
        if( this == src ) return;
+       awindow_folder = src->awindow_folder;
        update_path(src->path);
        update_index(src);
 }
index 890ff0adceea4dd996aed3d3fab83deb1335e2ca..0c7e1d718b5efcc7fffb0e3552c6d7d429aef1f6 100644 (file)
@@ -60,7 +60,6 @@ LocalSession::LocalSession(EDL *edl)
 
        selectionstart = selectionend = 0;
        in_point = out_point = -1;
-       awindow_folder = AW_CLIP_FOLDER;
        sprintf(clip_title, _("Program"));
        strcpy(clip_notes, _("Hello world"));
        strcpy(clip_icon, "");
@@ -119,7 +118,6 @@ void LocalSession::copy_from(LocalSession *that)
        strcpy(clip_title, that->clip_title);
        strcpy(clip_notes, that->clip_notes);
        strcpy(clip_icon, that->clip_icon);
-       awindow_folder = that->awindow_folder;
        in_point = that->in_point;
        loop_playback = that->loop_playback;
        loop_start = that->loop_start;
@@ -169,7 +167,6 @@ void LocalSession::save_xml(FileXML *file, double start)
        file->tag.set_property("SELECTION_END", selectionend - start);
        file->tag.set_property("CLIP_TITLE", clip_title);
        file->tag.set_property("CLIP_ICON", clip_icon);
-       file->tag.set_property("AWINDOW_FOLDER", awindow_folder);
        file->tag.set_property("X_PANE", x_pane);
        file->tag.set_property("Y_PANE", y_pane);
 
@@ -265,12 +262,6 @@ void LocalSession::load_xml(FileXML *file, unsigned long load_flags)
                                        year, mon, mday, hour, min, sec);
                        }
                }
-               const char *folder = file->tag.get_property("FOLDER");
-               if( folder ) {
-                       awindow_folder = AWindowGUI::folder_number(folder);
-                       if( awindow_folder < 0 ) awindow_folder = AW_MEDIA_FOLDER;
-               }
-               awindow_folder = file->tag.get_property("AWINDOW_FOLDER", awindow_folder);
                loop_playback = file->tag.get_property("LOOP_PLAYBACK", 0);
                loop_start = file->tag.get_property("LOOP_START", (double)0);
                loop_end = file->tag.get_property("LOOP_END", (double)0);
index cd948aa323176e059895bbf8b20ebc18bc6a76b7..ecf48b620a259ee2f4aaaa0ea5bd59939c8c4ba5 100644 (file)
@@ -79,9 +79,6 @@ public:
        char clip_notes[BCTEXTLEN];
        char clip_icon[BCSTRLEN];
 
-// Folder in parent EDL of clip
-       int awindow_folder;
-
        int loop_playback;
        double loop_start, loop_end;
        double playback_start, playback_end;
index d919c55604d216e87573ce34d1e4cbcb822e57b1..251d82b706ffb81947f659f0cd82c666eb57df98 100644 (file)
@@ -85,6 +85,7 @@ MainSession::MainSession(MWindow *mwindow)
        cwindow_x = cwindow_y = cwindow_w = cwindow_h = 0;
        ctool_x = ctool_y = 0;
        awindow_x = awindow_y = awindow_w = awindow_h = 0;
+       bwindow_w = bwindow_h = 0;
        rmonitor_x = rmonitor_y = rmonitor_w = rmonitor_h = 0;
        rwindow_x = rwindow_y = rwindow_w = rwindow_h = 0;
        gwindow_x = gwindow_y = 0;
@@ -262,6 +263,9 @@ void MainSession::default_window_positions(int window_config)
        awindow_w = root_x + root_w - awindow_x - border_left - border_right;
        awindow_h = mwindow_h;
 
+       bwindow_w = 520;
+       bwindow_h = 340;
+
        ewindow_w = 640;
        ewindow_h = 240;
 
@@ -398,6 +402,10 @@ int MainSession::load_defaults(BC_Hash *defaults)
 
 // Other windows
        afolders_w = defaults->get("ABINS_W", 200);
+
+       bwindow_w = defaults->get("BWINDOW_W", bwindow_w);
+       bwindow_h = defaults->get("BWINDOW_H", bwindow_h);
+
        rwindow_x = defaults->get("RWINDOW_X", rwindow_x);
        rwindow_y = defaults->get("RWINDOW_Y", rwindow_y);
        rwindow_w = defaults->get("RWINDOW_W", rwindow_w);
@@ -489,6 +497,9 @@ int MainSession::save_defaults(BC_Hash *defaults)
        defaults->update("AWINDOW_W", awindow_w);
        defaults->update("AWINDOW_H", awindow_h);
 
+       defaults->update("BWINDOW_W", bwindow_w);
+       defaults->update("BWINDOW_H", bwindow_h);
+
        defaults->update("EWINDOW_W", ewindow_w);
        defaults->update("EWINDOW_H", ewindow_h);
 
index cc16c7375d271e623137438dd43432bbb25f6fa8..fd58d210dad1291a4adf3a4f2378eb138dfafdef 100644 (file)
@@ -137,6 +137,8 @@ public:
        int cswindow_x, cswindow_y, cswindow_w, cswindow_h;
 // subtitle
        int swindow_x, swindow_y, swindow_w, swindow_h;
+// binfolder filter window
+       int bwindow_w, bwindow_h;
 // error window
        int ewindow_w, ewindow_h;
 // Channel edit window
@@ -156,7 +158,6 @@ public:
        int use_hist_parade;
        int use_wave_parade;
 
-
        int afolders_w;
        int show_vwindow, show_awindow, show_cwindow, show_gwindow, show_lwindow;
        int plugindialog_w, plugindialog_h;
index 82a5baaaaf60f1ce6ad4cbb8c5378f747e17e019..1684d447da201bbf4b36c5bf3b9d94cb21cbfa95 100644 (file)
@@ -66,7 +66,7 @@ int Messages::read_message(char *text)
 
        if((msgrcv(msgid, (struct msgbuf*)&buffer, MESSAGESIZE, input_flag, 0)) < 0)
        {
-               printf(_("recieve message failed\n"));
+               printf(_("receive message failed\n"));
                sleep(1);     // don't flood the screen during the loop
                return -1;
        }
@@ -82,7 +82,7 @@ long Messages::read_message()
 
        if((msgrcv(msgid, (struct msgbuf*)&buffer, MESSAGESIZE, input_flag, 0)) < 0)
        {
-               printf(_("recieve message failed\n"));
+               printf(_("receive message failed\n"));
                sleep(1);
                return -1;
        }
@@ -103,7 +103,7 @@ char* Messages::read_message_raw()
 
        if((msgrcv(msgid, (struct msgbuf*)&buffer, MESSAGESIZE, input_flag, 0)) < 0)
        {
-               printf(_("recieve message failed\n"));
+               printf(_("receive message failed\n"));
                sleep(1);
                return "RECIEVE MESSAGE FAILED";
        }
index 8053f0ee61a1573dc6731dbdcc4c3c47b8bfa7d1..bbf89b975b9b7c5620973f95064ced7d936bcd68 100644 (file)
@@ -352,8 +352,6 @@ public:
 // Calculate defaults path
        static void create_defaults_path(char *string, const char *config_file);
 
-       void delete_folder(char *folder);
-
        void delete_track();
        void delete_track(Track *track);
        void delete_tracks();
@@ -416,6 +414,7 @@ public:
        void move_tracks_up();
        void mute_selection();
        void new_folder(const char *new_folder);
+       void delete_folder(char *folder);
 // For clipboard commands
        void paste();
 // For splice and overwrite
index 78b35f42acaa56c17830f78a387ed66f507297ca..65a2d916c97fdb0dc523a433a6f4917a484a0bb2 100644 (file)
@@ -2074,6 +2074,7 @@ void MWindow::save_clip(EDL *new_edl, const char *txt)
                "clip_%02d%02d%02d-%02d%02d%02d.png",
                dtm.tm_year+1900, dtm.tm_mon+1, dtm.tm_mday,
                dtm.tm_hour, dtm.tm_min, dtm.tm_sec);
+       new_edl->awindow_folder = AW_CLIP_FOLDER;
        edl->update_assets(new_edl);
        int cur_x, cur_y;
        gui->get_abs_cursor(cur_x, cur_y, 0);
@@ -2230,14 +2231,21 @@ void MWindow::undo_entry(BC_WindowBase *calling_window_gui)
 void MWindow::new_folder(const char *new_folder)
 {
        undo->update_undo_before();
-       edl->new_folder(new_folder);
+       if( edl->new_folder(new_folder) ) {
+               MainError::show_error(_("create new folder failed"));
+       }
        undo->update_undo_after(_("new folder"), LOAD_ALL);
        awindow->gui->async_update_assets();
 }
 
 void MWindow::delete_folder(char *folder)
 {
-//     undo->update_undo_after(_("delete folder"), LOAD_ALL);
+       undo->update_undo_before();
+       if( edl->delete_folder(folder) < 0 ) {
+               MainError::show_error(_("delete folder failed"));
+       }
+       undo->update_undo_after(_("del folder"), LOAD_ALL);
+       awindow->gui->async_update_assets();
 }
 
 void MWindow::select_point(double position)
diff --git a/cinelerra-5.1/cinelerra/newfolder.C b/cinelerra-5.1/cinelerra/newfolder.C
deleted file mode 100644 (file)
index 26ab5a1..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-
-/*
- * CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include "assets.h"
-#include "awindowgui.h"
-#include "edl.h"
-#include "mwindow.h"
-#include "newfolder.h"
-
-#include <string.h>
-
-#include <libintl.h>
-#define _(String) gettext(String)
-#define gettext_noop(String) String
-#define N_(String) gettext_noop (String)
-
-
-NewFolder::NewFolder(MWindow *mwindow, AWindowGUI *awindow, int x, int y)
- : BC_Window(_(PROGRAM_NAME ": New folder"),
-       x, y, 320, 120, 0, 0, 0, 0, 1)
-{
-       this->mwindow = mwindow;
-       this->awindow = awindow;
-}
-
-NewFolder::~NewFolder()
-{
-}
-
-
-void NewFolder::create_objects()
-{
-       lock_window("NewFolder::create_objects");
-       int x = 10, y = 10;
-       add_tool(new BC_Title(x, y, _("Enter the name of the folder:")));
-       y += 20;
-       add_subwindow(textbox = new BC_TextBox(x, y, 300, 1, _("Untitled")));
-       y += 30;
-       add_subwindow(new BC_OKButton(x, y));
-       x = get_w() - 100;
-       add_subwindow(new BC_CancelButton(x, y));
-       show_window();
-       unlock_window();
-}
-
-const char* NewFolder::get_text()
-{
-       return textbox->get_text();
-}
-
-
-NewFolderThread::NewFolderThread(MWindow *mwindow, AWindowGUI *awindow)
-{
-       this->mwindow = mwindow;
-       this->awindow = awindow;
-       active = 0;
-       set_synchronous(0);
-}
-
-NewFolderThread::~NewFolderThread()
-{
-}
-
-void NewFolderThread::run()
-{
-       int result = window->run_window();
-
-       if(!result)
-       {
-               mwindow->new_folder(window->get_text());
-       }
-
-       change_lock.lock("NewFolderThread::run");
-       active = 0;
-       change_lock.unlock();
-       delete window;
-       completion_lock.unlock();
-}
-
-int NewFolderThread::interrupt()
-{
-       change_lock.lock("NewFolderThread::interrupt");
-       if(active)
-       {
-               window->lock_window();
-               window->set_done(1);
-               window->unlock_window();
-       }
-
-       change_lock.unlock();
-
-       completion_lock.lock("NewFolderThread::interrupt");
-       completion_lock.unlock();
-       return 0;
-}
-
-int NewFolderThread::start_new_folder()
-{
-       window = new NewFolder(mwindow,
-               awindow,
-               awindow->get_abs_cursor_x(1),
-               awindow->get_abs_cursor_y(1) - 120);
-       window->create_objects();
-
-       change_lock.lock("NewFolderThread::start_new_folder");
-       active = 1;
-       change_lock.unlock();
-
-       Thread::start();
-
-       completion_lock.lock("NewFolderThread::start_new_folder");
-       return 0;
-}
diff --git a/cinelerra-5.1/cinelerra/newfolder.h b/cinelerra-5.1/cinelerra/newfolder.h
deleted file mode 100644 (file)
index 4116b3e..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-
-/*
- * CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef NEWFOLDER_H
-#define NEWFOLDER_H
-
-#include "awindowgui.inc"
-#include "guicast.h"
-#include "mutex.h"
-#include "mwindow.inc"
-
-class NewFolder : public BC_Window
-{
-public:
-       NewFolder(MWindow *mwindow, AWindowGUI *awindow, int x, int y);
-       ~NewFolder();
-
-       void create_objects();
-       const char* get_text();
-
-private:
-       BC_TextBox *textbox;
-       MWindow *mwindow;
-       AWindowGUI *awindow;
-};
-
-
-class NewFolderThread : public Thread
-{
-public:
-       NewFolderThread(MWindow *mwindow, AWindowGUI *awindow);
-       ~NewFolderThread();
-
-       void run();
-       int interrupt();
-       int start_new_folder();
-
-private:
-       Mutex change_lock, completion_lock;
-       int active;
-       MWindow *mwindow;
-       AWindowGUI *awindow;
-       NewFolder *window;
-};
-
-#endif
diff --git a/cinelerra-5.1/cinelerra/newfolder.inc b/cinelerra-5.1/cinelerra/newfolder.inc
deleted file mode 100644 (file)
index bf692f9..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-
-/*
- * CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef NEWFOLDER_INC
-#define NEWFOLDER_INC
-
-class NewFolder;
-class NewFolderThread;
-
-#endif
index 51a4ecc13ce97f4d063716bc6955c57401c22aef..b59d71fd40376a48b9c4852f41a904ae83d32ca8 100644 (file)
@@ -279,7 +279,7 @@ public:
        virtual void update_gui();
        virtual void save_data(KeyFrame *keyframe) {};    // write the plugin settings to text in text format
        virtual void read_data(KeyFrame *keyframe) {};    // read the plugin settings from the text
-       int send_hide_gui();                                    // should be sent when the GUI recieves a close event from the user
+       int send_hide_gui();                                    // should be sent when the GUI receives a close event from the user
 // Destroys the window but not the thread pointer.
        void hide_gui();
 
@@ -507,13 +507,13 @@ public:
        int interactive;                // for the progress bar plugin
        int success;
        int total_out_buffers;          // total send buffers allocated by the server
-       int total_in_buffers;           // total recieve buffers allocated by the server
+       int total_in_buffers;           // total receive buffers allocated by the server
        int wr, rd;                     // File permissions for fileio plugins.
 
 // These give the largest fragment the plugin is expected to handle.
 // size of a send buffer to the server
        int64_t out_buffer_size;
-// size of a recieve buffer from the server
+// size of a receive buffer from the server
        int64_t in_buffer_size;
 
 
index a71e826f9f8d8e05c6fb69017f616c9ad5fc06c5..0e8c742a26128a2be460c13e89e4c0591088d50a 100644 (file)
@@ -51,7 +51,7 @@ PluginMessages::send_message(char *text)
 {
 }
 
-PluginMessages::recieve_message(char *text)
+PluginMessages::receive_message(char *text)
 {
 }
 
@@ -73,23 +73,23 @@ PluginMessages::send_message(int command)
 }
 
 
-PluginMessages::recieve_message()
+PluginMessages::receive_message()
 {
 }
 
-PluginMessages::recieve_message(int *command, char *text)
+PluginMessages::receive_message(int *command, char *text)
 {
 }
 
-PluginMessages::recieve_message(int *command, long *value)
+PluginMessages::receive_message(int *command, long *value)
 {
 }
 
-PluginMessages::recieve_message(long *value1, long *value2)
+PluginMessages::receive_message(long *value1, long *value2)
 {
 }
 
-PluginMessages::recieve_message(int *command, long *value1, long *value2)
+PluginMessages::receive_message(int *command, long *value1, long *value2)
 {
 }
 
index 4407149b85f70769bacaacab1033d63acc4fecec..f45c9bd1c6489fa76ed4cf3f4b7aa037730123c9 100644 (file)
@@ -33,18 +33,18 @@ public:
        ~PluginMessages();
 
        send_message(char *text);
-       recieve_message(char *text);
+       receive_message(char *text);
 
        send_message(int command, char *text);
        send_message(long command, long value);
        send_message(long command, long value1, long value2);
        send_message(int command);
 
-       recieve_message();     // returns the command
-       recieve_message(int *command, char *text);
-       recieve_message(int *command, long *value);
-       recieve_message(long *value1, long *value2);
-       recieve_message(int *command, long *value1, long *value2);
+       receive_message();     // returns the command
+       receive_message(int *command, char *text);
+       receive_message(int *command, long *value);
+       receive_message(long *value1, long *value2);
+       receive_message(int *command, long *value1, long *value2);
 
        Messages *messages;
        int input_flag, output_flag;
index f2011af2488701440baefa5f278e0f3c1cf6c934..36447603bb0e1c0ad2f595d04e428be035e1a7f2 100644 (file)
@@ -349,7 +349,7 @@ public:
 
 // buffers
        int64_t out_buffer_size;   // size of a send buffer to the plugin
-       int64_t in_buffer_size;    // size of a recieve buffer from the plugin
+       int64_t in_buffer_size;    // size of a receive buffer from the plugin
        int total_in_buffers;
        int total_out_buffers;
 
index 583f6a57ecbde20baf34994345ca107dd286c8af..04a1bdae736bb02678d912d5730ca5499e7241f9 100644 (file)
@@ -140,7 +140,7 @@ ProxyPopupSort::~ProxyPopupSort()
 
 int ProxyPopupSort::handle_event()
 {
-       mwindow->awindow->gui->sort_assets(0);
+       mwindow->awindow->gui->sort_assets();
        return 1;
 }
 
index 65bf732d078bfaa2bbcb4e34c5e48fffd53d7ccf..d109aff5097d5649df5628d9131575a11d3646c4 100644 (file)
@@ -160,7 +160,7 @@ class RecordMonitorThread : public Thread
        void process_scope();
        void process_hist();
 
-       int ready;   // Ready to recieve the next frame
+       int ready;   // Ready to receive the next frame
        int done;
        RecVideoMJPGThread *jpeg_engine;
        RecVideoDVThread *dv_engine;
index 8b378ac1327887df78d9d7686e9de724374c4f98..b12b5225a77bd7482a6e96e6143dac4a4e4df4d6 100644 (file)
@@ -483,7 +483,7 @@ int RenderFarmClientThread::read_package(int socket_fd, RenderPackage *package)
 // Signifies end of session.
        if(!data)
        {
-//             printf(_("RenderFarmClientThread::read_package no output path recieved.\n"));
+//             printf(_("RenderFarmClientThread::read_package no output path received.\n"));
                unlock();
                return 1;
        }
index 320e98bc4d701269e2fa636f02556a2bc4c419c6..d983c7ac8cc22cd3526b2a875e3a06ed47f30296 100644 (file)
@@ -2135,6 +2135,14 @@ int BC_ListBox::get_cursor_item(ArrayList<BC_ListBoxItem*> *data, int cursor_x,
        return -1;
 }
 
+// short version
+int BC_ListBox::get_cursor_item()
+{
+       int rx, ry;
+       gui->get_relative_cursor(rx, ry);
+       return get_cursor_item(data, rx, ry, 0, 0);
+}
+
 int BC_ListBox::repeat_event(int64_t duration)
 {
        switch( current_operation ) {
@@ -2695,7 +2703,6 @@ int BC_ListBox::button_press_event()
 int BC_ListBox::button_release_event()
 {
        int result = 0;
-       int cursor_x, cursor_y;
        int do_event = 0;
        new_value = 0;
        unset_scroll_repeat();
@@ -2718,11 +2725,7 @@ int BC_ListBox::button_release_event()
 //printf("BC_ListBox::button_release_event 10\n");
                current_operation = NO_OPERATION;
                if( gui ) {
-                       translate_coordinates(top_level->event_win, gui->win,
-                               gui->get_cursor_x(), gui->get_cursor_y(),
-                               &cursor_x, &cursor_y);
-                       selection_number1 = selection_number =
-                               get_cursor_item(data, cursor_x, cursor_y);
+                       selection_number1 = selection_number = get_cursor_item();
 //printf("BC_ListBox::button_release_event %d %d\n", selection_number2, selection_number1);
                }
 
index b0e9c3e22b70a6d6ffef79870ec79670a4408d48..78c4315b79137e3d8da4e6fc2b8c579e6514834a 100644 (file)
@@ -324,6 +324,8 @@ public:
 // Draw the list items
        int draw_items(int flash, int bg_draw=0);
 
+       int get_cursor_item();
+
 private:
        void delete_columns();
        void set_columns(const char **column_titles,
index d7440bde39000d7499153dada1e0dbbda26fcb4e..a18d155944cce4b3b4267d89d2b2baee1e5913f7 100644 (file)
@@ -997,7 +997,7 @@ locking_message = event->xclient.message_type;
                        done = 1;
                        } else
                        { // We currently use X marshalling for xatom events, we can switch to something else later
-                               recieve_custom_xatoms((xatom_event *)ptr);
+                               receive_custom_xatoms((xatom_event *)ptr);
                }
                break;
 
@@ -1978,7 +1978,7 @@ int BC_WindowBase::arm_repeat(int64_t duration)
 }
 #endif
 
-int BC_WindowBase::recieve_custom_xatoms(xatom_event *event)
+int BC_WindowBase::receive_custom_xatoms(xatom_event *event)
 {
        return 0;
 }
index 5d17e5ee3064362c2cc23e73d3b11c91b1f2e1ad..a1f930de0889c010e95ffbb735f61191f95aefb2 100644 (file)
@@ -551,8 +551,8 @@ private:
        int get_screen();
        virtual int initialize();
        int get_atoms();
-// Function to overload to recieve customly defined atoms
-       virtual int recieve_custom_xatoms(xatom_event *event);
+// Function to overload to receive customly defined atoms
+       virtual int receive_custom_xatoms(xatom_event *event);
 
        void init_cursors();
        int init_colors();
index a7d9e00b2c9b584d8a1bf012cbde6026f94b0d50..22b611ff7e265d0d63ac41087c4aa6615b192b3c 100644 (file)
@@ -25,7 +25,7 @@
 // Thread running parallel to run_window which listens for X server events
 // only.  Hopefully, having it as the only thing calling the X server without
 // locks won't crash.  Previously, events were dispatched from BC_Repeater
-// asynchronous to the events recieved by XNextEvent.  BC_Repeater tended to
+// asynchronous to the events received by XNextEvent.  BC_Repeater tended to
 // lock up for no reason.
 
 
index d726265030e57ffb1c13adf536c9f193f3a8553e..b7fd0f6c70bd0dd8ce4e8d06b7fadd4b05cf83f7 100644 (file)
@@ -290,6 +290,11 @@ draw(VIcon *vicon)
        return 1;
 }
 
+void VIconThread::hide_vicons(int v)
+{
+       for( int i=0; i<t_heap.size(); ++i ) t_heap[i]->hidden = v;
+}
+
 void VIconThread::
 run()
 {
index 5e96f7117cabd93bbdb0eb0b4d22f5ccc61decf0..22cfd6f9a0af07349bad6b434748b31a233f9f06 100644 (file)
@@ -97,6 +97,7 @@ public:
        int keypress_event(int key);
        void set_drawing_area(int x0, int y0, int x1, int y1);
        void set_view_popup(VIcon *vicon);
+       void hide_vicons(int v=1);
 
        ViewPopup *new_view_window(VFrame *frame);
        virtual bool visible(VIcon *vicon, int x, int y);