IGUIFileOpenDialog and changeWorkingDirectoryTo
-
- Posts: 1029
- Joined: Thu Apr 06, 2006 12:45 am
- Location: Tennesee, USA
- Contact:
IGUIFileOpenDialog and changeWorkingDirectoryTo
Well at least this time I searched through the docs...
How do I set file extension limitations on what shows up in the dialog?
If this isn't possible does anyone have any theories on what could be done?
Otherwise, how could I go about using the Windows file open dialog with Irrlicht using the IEventReceiver? (I think this is impossible.)
As for the changeWorking.. etc. etc.
For some reason if the folder that I want to change to is not found, it doesn't seem to return false. It still moves the working directory to that folder. This is kinda irritating as I was using that as the only way I could tell if the directory existed or not.
I'm using the latest SVN and D3D9. The tests were on XP and on Vista. The Documents and Settings folder wasn't on the Vista computer (Two different computers.) yet it still changed the working directory to it.
How do I set file extension limitations on what shows up in the dialog?
If this isn't possible does anyone have any theories on what could be done?
Otherwise, how could I go about using the Windows file open dialog with Irrlicht using the IEventReceiver? (I think this is impossible.)
As for the changeWorking.. etc. etc.
For some reason if the folder that I want to change to is not found, it doesn't seem to return false. It still moves the working directory to that folder. This is kinda irritating as I was using that as the only way I could tell if the directory existed or not.
I'm using the latest SVN and D3D9. The tests were on XP and on Vista. The Documents and Settings folder wasn't on the Vista computer (Two different computers.) yet it still changed the working directory to it.
Re: IGUIFileOpenDialog and changeWorkingDirectoryTo
Write a function that tells you if a filename matches a given pattern. I wrote one a long time ago that supports '*' and '?' like windows does. In the unix world there is a POSIX function named fnmatch() that you could use. You could write your own version of it in a hundred lines or so.monkeycracks wrote:Well at least this time I searched through the docs...
How do I set file extension limitations on what shows up in the dialog?
If this isn't possible does anyone have any theories on what could be done?
It is possible, but I wouldn't recommend it. I worked on an application that used CFileOpenDialog windows on top of a D3D9 application. There were often problems that would come up. The dialog would disappear, it would cause problems with the application window... It was a mess.moneycracks wrote:Otherwise, how could I go about using the Windows file open dialog with Irrlicht using the IEventReceiver? (I think this is impossible.)
You can see if a directory exists using the IFileList interface, or you could go down a level and use stat().moneycracks wrote:For some reason if the folder that I want to change to is not found, it doesn't seem to return false. It still moves the working directory to that folder. This is kinda irritating as I was using that as the only way I could tell if the directory existed or not.
Travis
Here is the code that I wrote for file pattern matching. It _should_ work for expressions with * and ?.
The documentation for fnmatch() can be found here.
Travis
Code: Select all
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
bool
simple_filename_match(const char* pat, const char* str)
{
// may recursively call self to do pattern matching
while (*pat && *str)
{
switch (*pat)
{
// match 0 or more characters
case '*':
while (*pat == '*')
++pat; // additional stars mean nothing
while ((str = strchr(str, *pat)) != 0)
{
if (simple_filename_match(pat, str++))
return true;
}
if (!str)
return false;
break;
// match any one character
case '?':
pat += 1;
str += 1;
break;
// match a character
default:
if (*pat++ != *str++)
return false;
break;
}
}
return !(*pat || *str);
}
Travis
-
- Posts: 1029
- Joined: Thu Apr 06, 2006 12:45 am
- Location: Tennesee, USA
- Contact:
Lost me a bit with that.. let me see if I get it..
const char* pat would be "*.jpg" and str would be the filepath?
if the filepath is a .jpg file, the bool returns true?
Orrr did I just miss that point completely..
Also, I'm targeting the Windows platform as I'm using some wininet and windows things.
Also, could you expound a bit on the IFileList thing, I understand that I'll want to use isDirectory, but how would I find the index number of said directory
const char* pat would be "*.jpg" and str would be the filepath?
if the filepath is a .jpg file, the bool returns true?
Orrr did I just miss that point completely..
Also, I'm targeting the Windows platform as I'm using some wininet and windows things.
Also, could you expound a bit on the IFileList thing, I understand that I'll want to use isDirectory, but how would I find the index number of said directory
Yes. It just tells you if the string str matches the pattern pat. If pat is "*.jpg", and str is "image.jpg", the function would return true. A quick change to the file dialog and its interface and you have file name filtering.monkeycracks wrote:const char* pat would be "*.jpg" and str would be the filepath?if the filepath is a .jpg file, the bool returns true?
I looked at the implementation of changeWorkingDirectoryTo(), and it uses chdir(). That function is documented to fail if the specified directory does not exist. So, you shouldn't need to do any workarounds. It should just work. Maybe you are running into a special case on Windows?moneycracks wrote:Also, could you expound a bit on the IFileList thing, I understand that I'll want to use isDirectory, but how would I find the index number of said directory
Travis
-
- Posts: 1029
- Joined: Thu Apr 06, 2006 12:45 am
- Location: Tennesee, USA
- Contact:
Well I can't be too sure on the Vista computer as I can't have a look myself, but the tester said he was pretty sure that he did not have a C:\Documents and Settings.
Thanks for clarifying on that, I'll try to get it implemented sometime later today. Do you think that something like "*.jpg\0 *.bmp\0 *.png" (similar to the windows file open dialog) would be possible or will I need to modify the code for that?
Edit: I just failed at attempting to modify the engine, can't for the life of me figure out what I've done wrong. I added setPattern(char* pattern) and a stringc inside CFileOpenDialog to hold it. I changed the code at Ln 326-336
from
to
('s' is a stringw)
It throws no compile errors but when I use d->addPattern("*.jpg");, nothing in the file list shows up at all. Not even the . and .. normally located to navigate through dirs.
My theory is that I should be using the addPattern in the constructor and not after its made and fillFileList() (it's in the constructor) is called. I'll look into that when I get home.
Thanks for clarifying on that, I'll try to get it implemented sometime later today. Do you think that something like "*.jpg\0 *.bmp\0 *.png" (similar to the windows file open dialog) would be possible or will I need to modify the code for that?
Edit: I just failed at attempting to modify the engine, can't for the life of me figure out what I've done wrong. I added setPattern(char* pattern) and a stringc inside CFileOpenDialog to hold it. I changed the code at Ln 326-336
from
Code: Select all
for (u32 i=0; i<FileList->getFileCount(); ++i)
{
s = FileList->getFileName(i);
FileBox->addItem(s.c_str(), skin->getIcon(FileList->isDirectory(i) ? EGDI_DIRECTORY : EGDI_FILE));
}
if (FileNameText)
{
s = FileSystem->getWorkingDirectory();
FileNameText->setText(s.c_str());
}
Code: Select all
for (u32 i=0; i<FileList->getFileCount(); ++i)
{
s = FileList->getFileName(i);
if(simple_filename_match(pattern.c_str(), stringc(s.c_str()).c_str()))
{
FileBox->addItem(s.c_str(), skin->getIcon(FileList->isDirectory(i) ? EGDI_DIRECTORY : EGDI_FILE));
}
}
if (FileNameText)
{
s = FileSystem->getWorkingDirectory();
FileNameText->setText(s.c_str());
}
It throws no compile errors but when I use d->addPattern("*.jpg");, nothing in the file list shows up at all. Not even the . and .. normally located to navigate through dirs.
My theory is that I should be using the addPattern in the constructor and not after its made and fillFileList() (it's in the constructor) is called. I'll look into that when I get home.
Yes, this could be done quite easily. You would need to write a short routine to check for matches on each of the patterns. This should do it.monkeycracks wrote:Do you think that something like "*.jpg\0 *.bmp\0 *.png" (similar to the windows file open dialog) would be possible or will I need to modify the code for that?
Code: Select all
bool simple_filename_match_many (const char* pat, const char* str)
{
// it is expected that pat is a null terminated string
// of null terminated strings. i.e. it ends with two nulls.
for (/**/; *pat; pat += strlen (pat) + 1)
{
if (simple_filename_match (pat, str))
return true;
}
return false;
}
Uh, well I think you want to filter filenames only. You probably don't want to filter directories.moneycracks wrote:I just failed at attempting to modify the engine, can't for the life of me figure out what I've done wrong...
Code: Select all
for (u32 i=0; i<FileList->getFileCount(); ++i)
{
const core::stringw s = FileList->getFileName(i);
if (FileList->isDirectory(i))
{
// always include directories
FileBox->addItem(s.c_str(), skin->getIcon(EGDI_DIRECTORY));
}
else if (!pattern.c_str())
{
// no pattern string, so show all files
FileBox->addItem(s.c_str(), skin->getIcon(EGDI_FILE));
}
else
{
// we have a pattern string, only include file if it matches one
// of the patterns
const core::stringc ss (s.c_str());
if (simple_filename_match_many(pattern.c_str(), ss.c_str()))
{
// only include files if they match pattern
FileBox->addItem(s.c_str(), skin->getIcon(EGDI_FILE));
}
}
}
If you want to do this, your setPattern() function has to be smart enough to capture the full null terminated list of null terminated strings, or the caller has to be smart enough to do the right thing to make sure that the embedded nulls are included in the length of the string. I would propose that you write one of the following. Remember that 's' must be double null terminated.
Code: Select all
void CGUIFileOpenDialog::setPattern (const c8* s, u32 n)
{
pattern = core::stringc (s, n);
fillListBox(); // refresh file list
}
void CGUIFileOpenDialog::setPattern (const core::stringc& s)
{
pattern = s;
fillListBox(); // refresh file list
}
You can easily modify the code I've provided to work with wchar_t so you don't have to do all of that conversion.moneycracks wrote:'s' is a stringw
The code I've provided above should not have that problem. If there is no pattern string, then all files are selected. If you set the pattern after the dialog is constructed, then the list box will be refreshed.moneycracks wrote:My theory is that I should be using the addPattern in the constructor and not after its made and fillFileList() (it's in the constructor) is called. I'll look into that when I get home.
Travis
-
- Posts: 1029
- Joined: Thu Apr 06, 2006 12:45 am
- Location: Tennesee, USA
- Contact:
Thanks vitek. I really appreciate all the help you're giving me on this. Everything works like a charm!
The only question I have remaining is
Thanks much again vitek. Strings always seem to give me troubles.
Edit:: sorry that may have not been clear enough, I want to get the index number based on the name of the directory if possible
Edit:: Sorry for bugging you again vitek, but would it be possible to have more than two patterns? As is I can only do "*.jpg\0*.bmp\0", anything past the second \0 gets ignored by the function and I'm not exactly sure how to make it consider more.
The only question I have remaining is
if anyone cares to answer it.Also, could you expound a bit on the IFileList thing, I understand that I'll want to use isDirectory, but how would I find the index number of said directory
Thanks much again vitek. Strings always seem to give me troubles.
Edit:: sorry that may have not been clear enough, I want to get the index number based on the name of the directory if possible
Edit:: Sorry for bugging you again vitek, but would it be possible to have more than two patterns? As is I can only do "*.jpg\0*.bmp\0", anything past the second \0 gets ignored by the function and I'm not exactly sure how to make it consider more.
Last edited by monkeycracks on Mon Mar 31, 2008 9:29 pm, edited 1 time in total.
-
- Posts: 1029
- Joined: Thu Apr 06, 2006 12:45 am
- Location: Tennesee, USA
- Contact:
Yes, you do exactly like I said. You iterate through the file list from 0 to fileList->getFileCount(). For every name in the list, you compare it against the name you are looking for. If you find a name that matches, then you know the index of that name.moneycracks wrote:I want to get the index number based on the name of the directory if possible
I've written enough code for you, so I'm not going to write this. It is a simple loop with a counter. It is no more than 5 lines of code.
I don't know what you're doing wrong, but the code I posted does not have this problem. If I had to guess, I'd say that the pattern string was cut short because you didn't initialize it in such a way that the embeded nulls are kept.moneycracks wrote:Sorry for bugging you again vitek, but would it be possible to have more than two patterns? As is I can only do "*.jpg\0*.bmp\0", anything past the second \0 gets ignored by the function and I'm not exactly sure how to make it consider more.
Travis
-
- Posts: 1029
- Joined: Thu Apr 06, 2006 12:45 am
- Location: Tennesee, USA
- Contact:
Didn't mean that part, sorry . I've got that mostly figured out.I've written enough code for you, so I'm not going to write this. It is a simple loop with a counter. It is no more than 5 lines of code.
As for the initializing it in a way that the null embeds aren't kept : I think c_str(); in the stringc and stringw does it. I'm not for sure but I'll look for a workaround and see if I can't find a way to avoid using them.
-
- Posts: 1029
- Joined: Thu Apr 06, 2006 12:45 am
- Location: Tennesee, USA
- Contact: