/* * Author: Andrew Mann, Marc Prüßmeier * * Copyright (C) 2004 Atomic Blue (info@planeshift.it, http://www.atomicblue.org) * * * 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 (version 2 of the License) * 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. * */ /* PAWS File Navigation widget This widget provides file navigation controls similar to the file->open dialog on many applications. The widget uses an iVFS interface to navigate through the file system. |-----------------------------------------------------| |[..] [New Directory] | [New File] | |-----------------------------------------------------| | DIRECTORY |/\| file1.bmp |/\| | zipfile.zip.dir | | file2.gif | | | | | zipfile.zip | | | | | | | | | | | | | | | | | | |\/| |\/| |-----------------------------------------------------| |Filename: Action | | Cancel | |-----------------------------------------------------| |-----------------------------------------------------| |(Button) (Button) | (Button) | |-----------------------------------------------------| | (Listbox with |/\| (Listbox with |/\| | scrollbar) | | scrollbar) | | | | | | | | | | | | | | | | | | | | | | | |\/| |\/| |-----------------------------------------------------| |Filename: (texteditbox) (Button)| | (Button)| |-----------------------------------------------------| */ #include #include #include #include "pawsfilenavigation.h" #include "iutil/string.h" #include "paws/pawsmanager.h" #include "pawsmainwidget.h" #include "paws/pawsbutton.h" #include "paws/pawstextbox.h" #include "paws/pawslistbox.h" #include "paws/pawscombo.h" pawsFileNavigation::pawsFileNavigation() { iObjectRegistry *object_reg = PawsManager::GetSingleton().GetObjectRegistry(); if (object_reg) vfs = CS_QUERY_REGISTRY (object_reg, iVFS); current_path="/"; zip_mounts.DeleteAll(); filelistbox=NULL; dirlistbox=NULL; fullpathandfilename=NULL; action=NULL; } pawsFileNavigation::~pawsFileNavigation() { delete[] fullpathandfilename; } bool pawsFileNavigation::PostSetup() { pawsListBox *dirlistbox=(pawsListBox *)FindWidget("dirlist"); if (dirlistbox) { dirlistbox->SetSortingFunc(0,textBoxSortFunc); dirlistbox->SetSortedColumn(0); } pawsListBox *filelistbox=(pawsListBox *)FindWidget("filelist"); if (filelistbox) { filelistbox->SetSortingFunc(0,textBoxSortFunc); filelistbox->SetSortedColumn(0); } pawsComboBox *filetypetb=(pawsComboBox *)FindWidget("filetype"); if (filetypetb) { filetypetb->SetFilename("test"); } SetAlwaysOnTop(true); return true; } bool pawsFileNavigation::OnButtonPressed(int mouseButton, int keyModifier, pawsWidget* widget) { if (!widget) return false; if (widget == FindWidget("uppath")) { if (UpOnePath()) FillFileList(); } if (widget == FindWidget("windowclose") || widget == FindWidget("cancel")) { if (action) { delete action; action = NULL; } parent->DeleteChild(this); // destructs itself return true; } if (widget == FindWidget("perform")) { if (action) { action->Execute(GetFullPathFilename()); delete action; action = NULL; } parent->DeleteChild(this); // destructs itself return true; } return true; } bool pawsFileNavigation::OnChange(pawsWidget * widget) { return true; } bool pawsFileNavigation::FillFileList() { csRef filelist; csString currpathname = GetCurrentPath(); csString filetype = ""; size_t i; pawsComboBox *filetypetb=(pawsComboBox *)FindWidget("filetype"); if (filetypetb) filetype=filetypetb->GetSelectedRowString(); if (!dirlistbox) dirlistbox=(pawsListBox *)FindWidget("dirlist"); if (!dirlistbox) return false; if (!filelistbox) filelistbox=(pawsListBox *)FindWidget("filelist"); if (!filelistbox) return false; if (!vfs) return false; csString ZipTestPath = currpathname; while (ZipTestPath.Length()>1) { csString ZipTestValue = ZipTestPath; csString ZipFileType = ""; ZipTestPath.Truncate(ZipTestPath.FindLast('/')); ZipTestPath.SubString(ZipTestValue,ZipTestPath.FindLast('/')+1,ZipTestPath.Length()-ZipTestPath.FindLast('/')); ZipTestValue.SubString(ZipFileType,ZipTestValue.FindLast('.'),ZipTestValue.Length()-ZipTestValue.FindLast('/')); if (ZipFileType.Downcase()==".zip") { vfs->Unmount(ZipTestPath+"/",NULL); csRef xrpath = vfs->GetRealPath(ZipTestPath); char * xpath=xrpath->GetData(); vfs->Mount(ZipTestPath+"/",xpath); } ZipTestPath.Truncate(ZipTestPath.FindLast('/')+1); } size_t j=zip_mounts.Length(); for (i=0;iUnmount(zipfile,NULL); zip_mounts.DeleteIndex(i); i--;j--; } } // Fill in the path text pawsComboBox *pathcombobox=(pawsComboBox *)FindWidget("pathtext"); if (pathcombobox) { if(pathcombobox->GetRowCount()>10) { } if (current_path.Length() > 60) { csString pathtext; pathtext="..."; pathtext.Append(current_path.GetData() + current_path.Length()-27); pathcombobox->NewOption(pathtext); } else pathcombobox->NewOption(current_path); } dirlistbox->Clear(); filelistbox->Clear(); csString current_path_filter = current_path; for (int z=0;z<2;z++) { if (z) current_path_filter += "/" + filetype; filelist=vfs->FindFiles(current_path_filter); if (!z && current_path!="/" && current_path!="\\" && current_path.Length()>0) { if (strcmp(current_path.GetData(),"\\")>0) { pawsListBoxRow *lbrow=dirlistbox->NewRow(); if (lbrow) { pawsTextBox *filetb=(pawsTextBox *)lbrow->GetColumn(0); if (filetb) filetb->SetText("\\.."); } } if (strcmp(current_path.GetData(),"/")>0) { pawsListBoxRow *lbrow=dirlistbox->NewRow(); if (lbrow) { pawsTextBox *filetb=(pawsTextBox *)lbrow->GetColumn(0); if (filetb) filetb->SetText("/.."); } } } for (size_t i=0;iLength();i++) { const char *filename=filelist->Get(i); if (filename) { // Remove leading path from the filename, as VFS will add if (strlen(filename) >= current_path.Length()) { if (!strncmp(filename,current_path.GetData(),current_path.Length())) { filename+=current_path.Length(); if (filename[0]==0x00) continue; } } if (RelativeIsFile(filename)) { if ((strrchr(filename,'.')>filename)&& !strcmp((char *)strrchr(filename,'.'),".zip")) { // ZIP File csString fullfilename = filelist->Get(i); csString fulldirname = fullfilename + "/"; if (!strstr(currpathname,".zip")) if (!vfs->Exists(fulldirname)) { pawsListBoxRow *lbrow=dirlistbox->NewRow(); if (lbrow) { csString corrdirname = filename; corrdirname+="/"; pawsTextBox *filetb=(pawsTextBox *)lbrow->GetColumn(0); if (filetb) filetb->SetText(corrdirname); csRef xrpath = vfs->GetRealPath(fullfilename); char * xpath=xrpath->GetData(); vfs->Unmount(fulldirname,NULL); vfs->Mount(fulldirname,xpath); zip_mounts.Insert(0,fullfilename); } } } // FILE if (z) { pawsListBoxRow *lbrow=filelistbox->NewRow(); if (lbrow) { pawsTextBox *filetb=(pawsTextBox *)lbrow->GetColumn(0); if (filetb) filetb->SetText(filename); } } } else // DIR { if (!z) { pawsListBoxRow *lbrow=dirlistbox->NewRow(); if (lbrow) { pawsTextBox *filetb=(pawsTextBox *)lbrow->GetColumn(0); if (filetb) filetb->SetText(filename); } } } } } } filelistbox->SortRows(); dirlistbox->SortRows(); return true; } bool pawsFileNavigation::UpOnePath() { int position; position=(int)current_path.Length()-1; if (position<0) return false; if (current_path.GetAt(position) == '/' || current_path.GetAt(position) == '\\') position--; if (position<=0) return false; while (position>0 && current_path.GetAt(position) != '/' && current_path.GetAt(position) != '\\') position--; // Don't trim off the trailing slash current_path.Truncate(position+1); return true; } bool pawsFileNavigation::DownOnePath(const char *pathstring,int pathlen) { if (pathlen<=0) return false; size_t current_len; // Append a delimiter if needed current_len=current_path.Length(); if (current_len==0 || (current_path.GetAt(current_len-1) != '/' && current_path.GetAt(current_len-1) != '\\')) current_path.Append("/"); current_path.Append(pathstring,pathlen); return true; } bool pawsFileNavigation::SmartAppendPath(const char *append) { csString previous_path=current_path; while (append[0] != 0x00) { // Remove preceding slashes while (append[0] == '/' || append[0] == '\\') append++; // Handle ../ in path if (!strncmp(append,"..",2)) { if (append[2] == 0x00 || append[2] == '/' || append[2] == '\\') { if (!UpOnePath()) { current_path=previous_path; return false; } if (append[2] == 0x00) break; append+=3; continue; } } // Handle ./ in path if (append[0] == '.' && (append[1] == '/' || append[1] == '\\')) { append+=2; continue; } // Find the next segment int segment_length=0; while (append[segment_length] != 0x00 && append[segment_length] != '/' && append[segment_length] != '\\') segment_length++; if (!DownOnePath(append,segment_length)) { current_path=previous_path; return false; } append+=segment_length; if (append[0] != 0x00) append++; } // Add a trailing slash if necessary if (current_path.Length() == 0 || ( current_path.GetAt(current_path.Length()-1) != '/' && current_path.GetAt(current_path.Length()-1) != '\\')) { current_path.Append("/"); } if (!vfs->Exists(current_path)) { current_path=previous_path; return false; } return true; } bool pawsFileNavigation::SmartSetPath(const char *path) { if (path[0] == '/' || path[0] == '\\') { if(!strcmp(path,"/")||!strcmp(path,"\\")) { current_path=path; return true; } csString previous_path=current_path; current_path=""; if (!SmartAppendPath(path+1)) { current_path=previous_path; return false; } return true; } return SmartAppendPath(path); } bool pawsFileNavigation::RelativeIsFile(const char *filename) { size_t filename_len; if (!filename) return false; filename_len=strlen(filename); if (filename[filename_len-1] == '/' || filename[filename_len-1] == '\\') return false; return true; } void pawsFileNavigation::OnListAction( pawsListBox* selected, int status ) { if (!filelistbox) filelistbox=(pawsListBox *)FindWidget("filelist"); if (!dirlistbox) dirlistbox=(pawsListBox *)FindWidget("dirlist"); if (selected==FindWidget("filetype")->FindWidget("ComboListBox")) { FillFileList(); return; } if (selected==FindWidget("pathtext")->FindWidget("ComboListBox")) { pawsComboBox * boxtb=(pawsComboBox *)FindWidget("pathtext"); csString pathtext = boxtb->GetSelectedRowString(); current_path=pathtext; FillFileList(); return; } if (!dirlistbox || !filelistbox || (selected != dirlistbox && selected != filelistbox) ) return; if (status == LISTBOX_SELECTED) { pawsListBoxRow *lbrow=selected->GetSelectedRow(); if (lbrow) { pawsTextBox *filetb=(pawsTextBox *)lbrow->GetColumn(0); if (filetb) { const char *filename=filetb->GetText(); if (filename) { if (!strcmp(filename,"\\..") || !strcmp(filename,"/..")) { UpOnePath(); FillFileList(); return; } if (RelativeIsFile(filename)) { // Handle selected a file SetSelectedFilename(filename); } else { if (SmartAppendPath(filename)) FillFileList(); } } } } } } bool pawsFileNavigation::SetSelectedFilename(const char *filename) { pawsEditTextBox *filenametb=(pawsEditTextBox *)FindWidget("fileedit"); if (!filenametb) return false; filenametb->SetText(filename); return true; } bool pawsFileNavigation::SetFileFilters(const char *filetype) { pawsComboBox *filetypetb=(pawsComboBox *)FindWidget("filetype"); if (!filetypetb) return false; filetypetb->Clear(); csString Filter = filetype; csString FilterValue = ""; if (Filter.FindFirst('|') == (size_t)-1) { SetFilterForSelection(Filter); pawsComboBox *filetypetb=(pawsComboBox *)FindWidget("filetype"); filetypetb->Select(Filter); } else { while (Filter.Length() > 0) { Filter.SubString(FilterValue,Filter.FindLast('|')+1,Filter.Length()-Filter.FindLast('|')); SetFilterForSelection(FilterValue.Downcase()); Filter.Truncate(Filter.FindLast('|')); } } return true; } bool pawsFileNavigation::SetFilterForSelection(const char *filetype) { pawsComboBox *filetypetb=(pawsComboBox *)FindWidget("filetype"); if (!filetypetb) return false; filetypetb->NewOption(filetype); return true; } const char *pawsFileNavigation::GetFilterForSelection() { const char *filetype = NULL; pawsComboBox *filetypetb=(pawsComboBox *)FindWidget("filetype"); if (!filetypetb) return NULL; filetype=filetypetb->GetSelectedRowString(); if (!filetype) return NULL; return filetype; } const char *pawsFileNavigation::GetFullPathFilename() { size_t length; const char *filename; pawsEditTextBox *filenametb=(pawsEditTextBox *)FindWidget("fileedit"); if (!filenametb) return NULL; filename=filenametb->GetText(); if (!filename) return NULL; length=current_path.Length() + strlen(filename); delete[] fullpathandfilename; fullpathandfilename = new char[length+1]; if (fullpathandfilename) sprintf(fullpathandfilename,"%s%s",current_path.GetData(),filename); return fullpathandfilename; } const char *pawsFileNavigation::GetCurrentPath() { return current_path.GetData(); } void pawsFileNavigation::SetActionButtonText(const char *actiontext) { pawsButton *actionbutton=(pawsButton *)FindWidget("perform"); if (!actionbutton || !actiontext) return; actionbutton->SetText(actiontext); } int pawsFileNavigation::GetSelectionState() { return selection_state; } void pawsFileNavigation::Show() { // Call the parent widget show logic pawsWidget::Show(); FillFileList(); } bool pawsFileNavigation::OnKeyDown( int keyCode, int key, int modifiers ) { if (keyCode==CSKEY_ENTER) { const char *filetext; pawsEditTextBox *filenametb=(pawsEditTextBox *)FindWidget("fileedit"); if (!filenametb) return false; filetext=filenametb->GetText(); if (!filetext || filetext[0] == 0x00) return false; // Handle the case where the text field is a path specificiation if (SmartSetPath(filetext)) { FillFileList(); filenametb->SetText(""); return true; } // Otherwise interpret this as an action request if (action) { action->Execute(GetFullPathFilename()); delete action; } action = NULL; parent->DeleteChild(this); // destructs itself } return false; } pawsFileNavigation * pawsFileNavigation::Create( const csString & filename, const csString & filter, iOnFileSelectedAction * action, const char * xmlWidget) { pawsFileNavigation * window_filenav = NULL; if (PawsManager::GetSingleton().LoadWidget(xmlWidget)) { window_filenav=(pawsFileNavigation *)PawsManager::GetSingleton().FindWidget("filenavigation"); if (window_filenav) { window_filenav->Hide(); PawsManager::GetSingleton().GetMainWidget()->AddChild(window_filenav); window_filenav->SetActionButtonText("Load"); window_filenav->SetName("Open File"); window_filenav->MoveTo(200,50); window_filenav->Initialize(filename, filter, action); } else { // csReport(object_reg, CS_REPORTER_SEVERITY_NOTIFY, APP_NAME, // "Warning: Couldn't find filenavigation widget."); } } else { // csReport(object_reg, CS_REPORTER_SEVERITY_NOTIFY, APP_NAME, // "Warning: Couldn't load filenavigation widget."); } return window_filenav; } void pawsFileNavigation::Initialize(const csString & filename,const csString & filter, iOnFileSelectedAction * action) { SetSelectedFilename(filename); SetFileFilters(filter); this->action = action; Show(); }