QFileDialog: How to open/select file/dir from package in osX - c++

I have googled a lot but dint find any relative solution for my problem.
PROBLEM: I want to open .MTS file and its working find if its available in any directory. But if its in any package then my QFileDialog is not able to look into that package and select those .MTS files.
CODE:
auto filePaths = QFileDialog::getOpenFileNames(this, "Open Video File", lastOpenedPath, "*.MTS;*.mov");
qDebug() << "File Paths " << filePaths;
Now the .MTS files created under AVCHD(Advanced Video Coding High Definition) package default in Sony & Panasonic HD Camera, and I want to import/select that .MTS files.
HINT: QFileDialog is able to import/select those .MTS files in Windows machine, but fail to import/select in mac machine.
Highly appreciated any thoughts.
Thanks.

Well, if I understand what you want to do properly, I'm not sure that it's possible in Qt alone.
It did turn out to be easier than I expected to simply call in to Cocoa and NSOpenPanel to achieve what I think you're looking for.
Sample project is at: https://github.com/NSGod/widgetsOpenFileDialogCocoa
Basically, I renamed mainwindow.cpp to mainwindow.mm, then added an #import <Cocoa/Cocoa.h>:
#import <Cocoa/Cocoa.h>
void MainWindow::on_openFileButton_clicked()
{
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel setAllowedFileTypes:[NSArray arrayWithObjects:#"mts", #"mov", nil]];
[openPanel setAllowsMultipleSelection:YES];
[openPanel setTreatsFilePackagesAsDirectories:YES];
[openPanel setTitle:#"Open Video File"];
NSInteger result = [openPanel runModal];
QStringList stringList;
if (result == NSFileHandlingPanelOKButton) {
NSArray *URLs = [openPanel URLs];
NSLog(#"URLs == %#", URLs);
for (NSURL *URL in URLs) {
stringList += QString::fromNSString(URL.path);
}
// do something with stringList
qDebug() << "filePaths == " << stringList;
}
}
Included in the project is a fakeBundle.component directory, which will be treated as a bundle (or "package") by OS X. But by setting treatsFilePackagesAsDirectories to YES, you can have the NSOpenPanel treat it as a directory (which it really is, of course).
Here is an image showing how the Finder treats this fakeBundle.component directory as if it were a single file:
And here in the NSOpenPanel, it's being treated as a directory:

An OSX package is a:
File system directory that is normally displayed to the user by the Finder as if it were a single file. Such a directory may be the top-level of a directory tree of objects stored as files, or it may be other archives of files or objects for various purposes, such as installer packages, or backup archives.
This is akin to an .mst or .msi file on Windows. Just as with OSX packages you would not be able to open your specified file within one of these packages. Your system open dialog is in fact doing you a disservice by allowing you to see into them, as you cannot open said files.
Your work around is to copy the file out of the package externally to the program then open the copy of the file.

Related

How to read a file on Hololens with C++

I am trying to read a file in a test/debug UWP application that is being deployed to Hololens. I can put the file on the device with the device portal, but am unable to find the correct path to open the file.
I am using the MSFT BasicXrApp_uwp example as a basis, and have included FileUtility which has a FindFileInAppFolder function. This is consistently failing to find the file, with the error:
"The file should be embeded in app folder in debug build.",
after letting me know the app folder is:
C:\Data\Users\DefaultAccount\AppData\Local\DevelopmentFiles\364f83f4-6e13-42e4-8253-71dd3040951cVS.Debug_ARM.mikeh\
The part 364f83f4-6e13-42e4-8253-71dd3040951cVS is recognisable in the device portal as the User Folders/LocalAppData folder, but the Debug_ARM.mikeh part is not visible on the portal.
I am using C++ and trying to do the file reading in a static, non uwp library if possible (pointing that out so I don't get suggestions to use UWP async stuff, if that is possible).
So, how do I embed my file in the app folder, or how do I place the file so I can read it?
This is because the folder path which FindFileInAppFolder method returns is the InstalledLocation of the current package, but what you checked in the device portal is LocalFolder/LocalCacheFolder, for more information about what different between them please see: File access permissions.
how do I embed my file in the app folder, or how do I place the file so I can read it?
You can place your file in the LocalState folder by Device Portal and get this folder path through ApplicationData.LocalFolder Property, the path should be like: C:\Data\Users\DefaultAccount\AppData\Local\Packages\364f83f4-6e13-42e4-8253-71dd3040951c\LocalState. For how to access the files via C++ you can use for example File access sample
I'm using an answer here as there's more room than a comment.
I found a few extra things useful. I added in the cppWinRT nuget package to my application.
I did need to use the "async stuff", for example:
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Storage;
StorageFolder storageFolder= KnownFolders::GetFolderForUserAsync(nullptr, KnownFolderId::PicturesLibrary).get();
This let me find a file I'd uploaded ot the Pictures Library. But I couldn't open it after passing the path to my existing library:
const auto sampleFile = storageFolder.GetFileAsync(fileName).get();
std::wstring path = sampleFile.Path();
MyLibraryCall(to_string(path));
MyLibraryCall would try and open an ifstream, and even using std::ifstream::in would fail.
So I copied the file to the temp directory, where I could open it and process it.
This is pretty hacky but it did what I needed, which is let me load an .obj file that was rejected by the 3D parts viewer.
The loop over all filenames is because storageFolder.GetFileAsync(fileName).get() throws an exception if it fails, which for me I could not catch properly.
StorageFolder tempFolder = Windows::Storage::ApplicationData::Current().TemporaryFolder();
std::wstring path;
auto files = tempFolder.GetFilesAsync().get();
for (auto file : files)
{
if (file.Name() == fileName) {
path = file.Path();
break;
}
}
if (!path.size()) {
// hasn't been copied into temp
StorageFile movedFile = sampleFile.CopyAsync(tempFolder).get();
path = movedFile.Path();
}
MyLibraryCall(to_string(path));
Anyway- not the greatest but that will hopefully help someone else looking for a quick and dirty way to process a file on a hololens/UWP app.

qt creator can not load icon

I am a beginer of QT, I tried to add an action to a toolbar and I wrote as follows:
toolbar->addAction(QIcon("/icons/new.png"), "New File");
However, the image can not be loaded. Is that related to my debug path? I can see the button, but no images.
those codes are in test.cpp and my icons folder is in the same path with test.cpp
Paths are interesting.
If you are on linux, you just specified that the root of the drive has a folder called icons, and inside it it has a file called new.png.
If you were using that kind of a path on a website, it would chop off everything to the left besides the domain and subdomain names.
example.com/path/to/some/folder/index.html, processes link to /icons/new.png, and you end up at: example.com/icons/new.png.
The best way to handle paths correctly is to use common notations for relative paths (in most cases... in some cases, absolute paths make sense).
./ means the folder that I am currently in aka the working directory.
../ means the folder above me.
A leading / means the highest folder possible or the root folder, on Unix systems. It is also akin to giving an absolute path for a file.
No leading . or .. or / means the same as ./, or from the working directory.
And there are even more rules about this. See the wiki entry:
http://en.wikipedia.org/wiki/Path_(computing)
In Qt there is also the resource system, that embeds files into the exe itself and can give you a harder-to-change image or graphic on your program.
The notation to access this is:
:/ means the root of the qresource system.
And if you do decide there is a reason to use a backslash, be sure to escape it. Normally Qt will take any input with backslashes and convert it for you on the fly to forward slashes.
So to double check that the file is there, use QFile file("icons/new.png"); followed by if(!file.exists()){ qDebug() << "File is not found!" << file.fileName(); }
Sometimes I find it helpful to see where my program is when this is happening. Either using system("dir"); or qDebug() << QDir::currentPath();
http://doc.qt.io/qt-5.5/qdir.html#currentPath
You can also see what your initial working directory is by looking at your project properties for the project in Qt Creator under:
Projects (tab) > Run (tab) > Run > Working directory:
Usually it is the root of where your source code is and where your .pro file is located.
Hope that helps.
If you are using Qt resources then you need a colon:
toolbar->addAction(QIcon(":/icons/new.png"), "New File");`
if you don't use resources then yuo should use relative path. Remember that Qt Creator uses by default "build in different place" so you must make sure that icon is deployed in respective directory.

OpenCV on IOS haar cascade xml file path issues from C++

So I have my code in C++ and I am able to run it fine on linux/OSX/Android. The problem now is ios. I am simply trying to load the haar cascade xml files via full path "/foo/blah/myapp.app/haar.xml" and having one heck of a time.
C++ can't confirm the file exists nor can opencv load it. I am new to ios and am aware that the myapp.app could be a compressed dir like the android .apk dir.
I have confirmed that I'm looking in the right place....or at least I hope I have! to check i use getcwd in c++ to get running directory and I confirm that with the file path to the xml file. It looks legit!
What can I do? The nice part about using C++ for the lib is that I can use one code base for desktop/android/ios. I really don't want to have to mix in Objective-C into my lib just for file paths.
Thanks in advance!
The code I'm using is the following:
std::ifstream fexists(face_haar_path.c_str());
if(!fexists.good()) {
std::cout << "Could not find any facehaar.xml" << std::endl;
return NO_FACE_HAAR_FILE;
}
face_haar.load(face_haar_path); //cv::CascadeClassifier face_haar
Adding reference to file location in iOS apps is quite different. First add the .xml files to your Xcode project and use the following lines of code for loading the haar-cascade. Please note that should not contain the extension .xml (Example: For face_frontal.xml file, your cascade name should be face_frontal)
NSString *faceCascadePath = [[NSBundle mainBundle]
pathForResource:#"<your_cascade_name>"
ofType:#"xml"];
const CFIndex CASCADE_NAME_LEN = 2048;
char *CASCADE_NAME = (char *) malloc(CASCADE_NAME_LEN);
CFStringGetFileSystemRepresentation( (CFStringRef)faceCascadePath,
CASCADE_NAME,
CASCADE_NAME_LEN);
if(!face_cascade.load(CASCADE_NAME)) {
cout << "Unable to load the face detector!!!!" << endl;
exit(-1);
}

Qt, windows cannot find file that Qt open file dialog can

So I have a Qt program that saves files among other things. I saved a few files in my C:/ directory. When I look for the file in windows explorer, cygwin, or my command prompt, I cannot find the file. I checked my folder options and those look fine. Despite not being able to find the file, when I need to load a file in my Qt program, the program is able to find the file. Only my program is able to find the file, windows cannot. I am logged in as an administrator, but could this possibly have something to do with permissions?
Also, it may be worth noting that when I save files in c:/users/me/Documents/folder/folder I don't seem to have an issue.
Code that saves file:
QString saveFileName = QFileDialog::getSaveFileName(this,"Select the file you wish to save to.","","");
QFile saveFile(saveFileName);
if(saveFile.open(QIODevice::WriteOnly))
{
QTextStream stream(&saveFile);
QString stringToSaveToFile;
stream << stringToSaveToFile;
saveFile.close();
}
else
{
QMessageBox::warning(this, "Error", "Cannot open file.");
}
Code that opens file:
QString selectedFile = QFileDialog::getOpenFileName(this, "Select a .pro file.", "", tr("Profile file (*.pro);;All (*.*)"));
QString fileContents;
QFile file(selectedFile);
if (file.open(QIODevice::ReadOnly) | (QIODevice::Text))
{
QTextStream in(&file);
fileContents = in.readAll();
}
else
{
QMessageBox::warning(this, "Error", "Unable to open file.");
}
Edit: Just tried this on a different computer. My computer has windows 8, the other computer had windows XP. I could not replicate the problem on the XP machine.
Edit:
I believe I have found what the issue is (http://answers.microsoft.com/en-us/windows/forum/windows_vista-files/windows-explorer-compatibility-files/5b377209-cfe4-4be6-959d-e1de4b8be16d), but I am still trying to find out how to resolve it.
The files I am trying to save to the c:/ directory are actually being saved in C:/users/username/AppData/Local/VirtualStore.
Is there a way to somehow override this?
For now my solution is to warn the user if they save in the C:/, C:/Program Files/, C:/Program Files (x86), or C:/Windows/ directories. All files saved in these directories actually get saved in C:/User/Current User/AppData/Local/VirtualStore/.
If anyone has a better solution let me know.
Even though you might be logged in as an administrator by default most programs are run in unelevated mode (basically, NOT as an administrator). Also by default unelevated programs do not have write access to the root directory on C: drive (same way they do not have permission to write in, for example, C:\Program Files\). This was not always the case - I do not remember exactly at the moment but I think write to program files was already protected in Windows XP, and C: became protected only afterwards, I think at least since Windows 7? Anyway, for compatibility reasons write to those protected directories is virtualized.
Try running your Qt application in elevated mode (right click -> Run as administrator, or right click -> Properties -> Compatibility -> Run this program as an administrator) if you want to write directly in C:\, but really, you shouldn't.
If you are really worried about users being confused by this, you can implement a check for write access - after user chooses location for the file, but before an actual write - and display a warning or let them choose another location.

Extracting .app on Mac with QuaZip

I'm basically trying to extract a Mac application from a zip file using QuaZip. The code I'm using is:
QuaZip zip("file.zip");
qDebug() << zip.open(QuaZip::mdUnzip);
QuaZipFile file(&zip);
QFile out("application.app");
out.open(QIODevice::WriteOnly);
for(bool f=zip.goToFirstFile(); f; f=zip.goToNextFile()) {
file.open(QIODevice::ReadOnly);
//same functionality as QIODevice::readData() -- data is a char*, maxSize is qint64
char c;
while (file.getChar(&c)) out.putChar(c);
file.close();
}
out.flush();
out.close();
zip.close();
If I try to start the extracted app, I get an error message saying I "can't open the Application, because the Classic-Environment is no longer supported." I tried to make the .app executable but it still didn't work. I don't know any other easy way to extract an application using Qt.
I extracted it with the normal archiver and the application worked.
I'm not super familiar with QuaZip, but it almost looks like you're trying to extract the whole archive to a single file called "application.app", which is pretty seriously wrong. Applications are actually folders, not files -- the Finder just displays the folder (which has a name ending in ".app") as if it were a single file.
If you can dig up an example of using QuaZip to extract a ZIP file, you should just be able to use that code largely unmodified (other than the __MACOSX metadata, possibly).
It may be easier to just call unzip from your app using QProcess or system().
unzip -q <path-to-zip> -d <path-to-destionation>