Selecting files recursively using QFileDialog - c++

I have a use case in an application using C++ and Qt (on windows 10). The application uses 7zip.exe as a subprocess to uncompress the files in a selected folder. The files are selected when a root folder is selected using a code snippet as shown below.
void MainWindow::on_browseButton_clicked()
{
QDir directory = QFileDialog::getExistingDirectory(this);
zipFiles = directory.entryList(QStringList() << "*.zip", QDir::Files);
foreach(QString filename3, zipFiles) {
qDebug() << filename3;
}
}
This works fine for normal files (.zip files with no other inner .zip file inside them). But I have a use case in which I need to select inner .zip files inside a zip file. How can I achieve this using the above code snippet.

Related

Selecting files with folder using QFileDialog

I have a use case in an application using C++ and Qt (on windows 10). The application uses 7zip.exe as a subprocess to uncompress the files in a selected folder. I need to use QFileDialog to select a folder, and get all the files with extension .zip and .7z, to be selected automatically and then uncompress them using QProcess and display them in the output.
I came up with this code snippet. For selecting the files with selected folders.
void MainWindow::on_browseButton_clicked()
{
QFileDialog d(this);
d.setFileMode(QFileDialog::Directory);
d.setNameFilter("*.zip");
if (d.exec())
qDebug () << d.selectedFiles();
}
but this code does not run, and it displays just the folder name not with no files selected. Could anyone suggest where I am doing wrong.
it displays just the folder name not with no files selected.
That is what it is supposed to return. You asked it to display a dialog to select a folder, so that is all you can select. selectedFiles() will return the path to the selected folder, per the documentation:
https://doc.qt.io/qt-5/qfiledialog.html#FileMode-enum
Constant
Value
Description
QFileDialog::Directory
2
The name of a directory. Both files and directories are displayed. However, the native Windows file dialog does not support displaying files in the directory chooser.
https://doc.qt.io/qt-5/qfiledialog.html#selectedFiles
Returns a list of strings containing the absolute paths of the selected files in the dialog. If no files are selected, or the mode is not ExistingFiles or ExistingFile, selectedFiles() contains the current path in the viewport.
After the dialog has closed and exec() has returned, you will then need to iterate that folder yourself to discover .zip and .7z files in it.
An easier way to handle the dialog is to use QFileDialog::getExistingDirectory() instead. You can construct a QDir from the selected folder, and then use the QDir::entryList() method to search for zip files in the folder.
See How to read all files from a selected directory and use them one by one?.
For example:
void MainWindow::on_browseButton_clicked()
{
QDir directory = QFileDialog::getExistingDirectory(this);
QStringList zipFiles = directory.entryList(QStringList() << "*.zip" << "*.7z", QDir::Files);
foreach(QString filename, zipFiles) {
// do whatever you need to do
}
}

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.

How to change the default C++ template file?

I'm using Visual Studio 2019, and whenever I create a new C++ project it gives me a default file with the following code:
// Template Test.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
// Debug program: F5 or Debug > Start Debugging menu
// Tips for Getting Started:
// 1. Use the Solution Explorer window to add/manage files
// 2. Use the Team Explorer window to connect to source control
// 3. Use the Output window to see build output and other messages
// 4. Use the Error List window to view errors
// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file
This is so much unnecessary information and it takes a minute to change it to what I really want;
// Template Test.cpp : This file contains the 'main' function. Program execution begins and ends there.
#include <iostream>
using namespace std;
int main() {
cout << "Hello World!\n";
}
It doesn't take very much time, but I have to do it every time I create a new C++ console project in VS 19.
After doing a quick search on my computer I found a folder called 'Templates' at the following location:
C:\Users\yale\Documents\Visual Studio 2019\Templates
This file has subdirectories that would lead me to think it's the right place, but none of the folders have any template files as I can see.
How can I modify the template files for different projects in C++ with Visual Studio 2019?
There are two ways you can choose any of them.
Use the Export Template Wizard:
Visual Studio provides an Export Template Wizard that can be used to update an existing template:
Choose File > New > Project from the menu bar.
Select the template that you want to update and continue through the
steps to create the new project.
Modify the project in Visual Studio. For example, change the output
type or add a new file to the project.
On the Project menu, choose Export Template.
The Export Template Wizard opens.
Follow the prompts in the wizard to export the template as a .zip
file.
(Optional) Place the .zip file in the following directory:
%USERPROFILE%\Documents\Visual Studio
\Templates\ProjectTemplates to make it available for
selection. You'll need to perform this step if you did not select the
option Automatically import the template into Visual Studio in the
Export Template Wizard.
Delete the old template .zip file.
To manually update an existing template:
Locate the .zip file that contains the template. User project
templates are located at %USERPROFILE%\Documents\Visual Studio
\Templates\ProjectTemplates.
Extract the .zip file.
Modify or delete the current template files, or add new files to the
template.
Open, modify, and save the .vstemplate XML file to handle updated
behavior or new files.
Select the files in your template, and from the right-click or
context menu, and choose Send to > Compressed (zipped) folder. The
files that you selected are compressed into a .zip file.
Put the new .zip file in the same directory as the old .zip file.
Delete the extracted template files and the old template .zip file.
Also, you can visit the source page for more details.

Why isn't my file opening, C++? XCode and Visual Studio

This is happening in both Visual Studio and XCode
#include <fstream>
#include <iostream>
using namespace std;
int main() {
ifstream input;
input.open ("matrices.txt");
if (!input.is_open()) {
cout << "not open!";
} else {
cout << "open!";
}
input.close();
return 0;
}
My file is not opening. The text file matrices.txt is in the same directory.
What is "same directory" in this context?
For a file to open like this, it has to be in the working directory of the executable when run in the debugger.
For Xcode; this means adding the files to the Copy Files build phase (accessible by editing the executable's target); and adding it to the Products Directory, selected from the dropdown.
In Xcode if you want to work with a file you have to put it in a folder called DeriverData. You can navigate to it by doing the following:
Xcode > preferences > click on Locations.
this brings up the following window
you can click on the small arrow to the right of the path: /Users/dulybon1/Library/Developer/Xcode/DerivedData
It will open the directory containing a list of all your Xcode projects. Find your project and navigate to: build > products > debug
as seen below:
Then you can put your files there. "a1.txt" and "a2.txt" are files that I have put there to work with. And I think the file needs to exist before it can be opened, so just create blank files if you are planning of using them. Hope that helps

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

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.