I'm new to Qt (previous experience is mostly Java) and am trying to find a good way of creating child directories and files given a QDir parent (and hold onto/create the QDir for the new child).
I've come up with a method to do this (I think!), but was unsure if this is the right way, or if there is already something built in that would do this for me.
Hope you can help.
QDir* MyClass::createChildDir(QDir* parent, QString dirName)
{
parent->mkdir(dirName);
QString newPath = parent->filePath(dirName);
QDir* newDir = new QDir(newPath);
return newDir;
}
Related
I have a problem with the QFileDialog class, namely with the setDirectory() and directory() methods. I need to make it so that after opening a file, my program remembers the directory in which the selected file is stored, and the next time QFileDialog is called, it automatically opens the directory that was used last. Here is a snippet of my code:
static QString _st_doc_last_directory;
void MainWindow::open()
{
if (!fileDialog)
{ fileDialog = new QFileDialog(this);
}
if (!_st_doc_last_directory.isEmpty()) fileDialog->setDirectory(_st_doc_last_directory);
QString fileName = fileDialog->getOpenFileName(this, tr("Open Document"), ".", tr("Compressed CAD Models (*.data)"));
if (!fileName.isEmpty())
{ _st_doc_last_directory = fileDialog->directory().dirName();
}
}
The crux of my problem is that when the setDirectory() or directory() method is called, my program crashes with a
"Segmentation fault"
message. How can I fix it, please advise. Thanks in advance.
Whenever you start this method, you have this as the start window: ".". (admittedly I don't know what's going on internally, but I think this leads to this problem).
You can query beforehand whether your defined string is empty. if so you set a path, otherwise you store one in your string. If you don't want to do this from the beginning every time you start the program, you can also use QSettings. This saves you the path in the registry (ie if you use windows).
With QFileInfo you can easily get the path
void MainWindow::open()
{
if(_st_doc_last_directory.isEmpty())
_st_doc_last_directory = QDir::homePath();
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Document"), _st_doc_last_directory, tr("Compressed CAD Models (*.data)"));
QFileInfo info(fileName);
if(!fileName.isEmpty())
_st_doc_last_directory = info.absolutePath();
}
I'm trying to create my own custom folder tree model using QStandardItemModel. I succeeded in making it using TreeWidget, but the correct address was not printed, so I used the QStandardItemModel where the index is stored.
However, I'm leaving a question because I'm stuck in many ways and I want to get some advice on this.
void QtWidgetsApplication1::AddDocTree(QStandardItem *DocItem, QString Path)
{
QString path = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
QDir* rootDir = new QDir(path);
QFileInfoList filesList = rootDir->entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
DocItem = TestModel->invisibleRootItem();
foreach(QFileInfo fileInfo, filesList)
{
if (fileInfo.isFile())
{
QIcon BasicIcon = mpIconProvider->icon(fileInfo);
child = new QStandardItem(BasicIcon, fileInfo.fileName());
child->setAccessibleDescription(fileInfo.filePath());
}
else
{
QIcon BasicIcon = mpIconProvider->icon(fileInfo);
child = new QStandardItem(BasicIcon, fileInfo.fileName());
child->setAccessibleDescription(fileInfo.filePath());
}
DocItem->appendRow(child);
AddDocTree(child, fileInfo.filePath());
DocItem = child;
}
}
I have a drive model that we've already created using the QFilesystemModel, but ultimately we have to create a folder tree that looks like a Windows File Explorer.
The TreeModel creation of the drive was successful using TreeWidget. However, when I clicked on a folder, the children of that folder kept being created, and I tried many times to prevent it, but it kept failing.
connect(ui->treeWidget, &QTreeWidget::itemClicked, this, &QtWidgetsApplication1::Addtree);
void QtWidgetsApplication1::Addtree(QTreeWidgetItem *root4, int column)
{
QDir* rootDir = new QDir(root4->text(2));
QDir test(root4->text(2));
QFileInfoList filesList = rootDir->entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
foreach(QFileInfo fileInfo, filesList)
{
QTreeWidgetItem* child = new QTreeWidgetItem();
child->setText(0, fileInfo.fileName());
if (fileInfo.isDir())
{
QIcon BasicIcon = mpIconProvider->icon(fileInfo);
child->setIcon(0, BasicIcon);
child->setText(2, fileInfo.filePath());
//child->setCheckState(1, Qt::Checked);
}
root4->addChild(child);
ui->treeWidget->addTopLevelItem(root4);
}
}
The code associated with itemClicked to create a child folder is as follows, and I'm not sure how to add it here to limit it to create it once.
Motivating example:
In a previous session, the application has stored some path selected
by the user. In the meantime that path may have been deleted, moved,
renamed or the drive unmounted. The application would now like to let
the user browse for a path via a QFileDialog and for the user's convenience, the previous path is passed as the
starting directory of the file dialog, as presumably the new
path is likely to be near the old path. Unfortunately, if
QFileDialog is given a starting path that does not exist, it
defaults to the current working directory, which is very unlikely to
be helpful to the user as it is typically the installation directory
of the application.
So we would like to preprocess the old path to point to a directory
that actually exists before passing it to QFileDialog. If the old
path doesn't exist, we'd like to replace it with the nearest directory
that does.
So how does one take a file path (which may or may not exist) and search "up" that path until one finds something that actually exists in the filesystem?
These are the two approaches I've come up with so far, but suggestions for improvement would be very much appreciated.
Searching upward until a path exists:
QString GetNearestExistingAncestorOfPath(const QString & path)
{
if(QFileInfo::exists(path)) return path;
QDir dir(path);
if(!dir.makeAbsolute()) return {};
do
{
dir.setPath(QDir::cleanPath(dir.filePath(QStringLiteral(".."))));
}
while(!dir.exists() && !dir.isRoot());
return dir.exists() ? dir.path() : QString{};
}
Searching downward until a path doesn't exist:
QString GetNearestExistingAncestorOfPath(const QString & path)
{
if(QFileInfo::exists(path)) return path;
auto segments = QDir::cleanPath(path).split('/');
QDir dir(segments.takeFirst() + '/');
if(!dir.exists()) return {};
for(const auto & segment : qAsConst(segments))
{
if(!dir.cd(segment)) break;
}
return dir.path();
}
Try the following code:
QString getNearestExistingPath(const QString &path)
{
QString existingPath(path);
while (!QFileInfo::exists(existingPath)) {
const QString previousPath(existingPath);
existingPath = QFileInfo(existingPath).dir().absolutePath();
if (existingPath == previousPath) {
return QString();
}
}
return existingPath;
}
This function utilizes the QFileInfo::dir() method which returns the parent directory for a specified path. The code is looped until the existing path is met or the paths in the two latest iterations are identical (this helps us to avoid the infinite loop).
From the QFileInfo::dir() docs:
Returns the path of the object's parent directory as a QDir object.
Note: The QDir returned always corresponds to the object's parent directory, even if the QFileInfo represents a directory.
I still recommend you to run some tests because I may be missing something.
I'm triying to get a folder size by doing:
var FolderFile:File = new File("file:///SomePath/Folder");
var FolderSize: FolderFile.size;
But this gives me a value of 0, how can I get the folder size? is there anyway to do this?
Tranks
No, there's no way to do it automagically. Getting the size of the directory is a complex and potentially painfully slow operation. There could be 10s of thousands of files in a directory, or a directory could be located on a (slow?) network, not to mention tape storage and similar scenarios.
The file systems themselves don't store directory size information, and the only way to know it is to calculate it file-by-file, there's no quick/easy shortcut. So, you will have to rely on the solution you posted above, and, yes, it is going to be slow.
I want to know the size of the folder (like 10mb). Sorry for the second line, I write it wrong, it's:
var Foldersize:Number = FolderFile.size;
I just made a new class wich executes this function:
public function GetFolderSize(Source:Array):Number
{
var TotalSizeInteger:Number = new Number();
for(var i:int = 0;i<Source.length;i++){
if(Source[i].isDirectory){
TotalSizeInteger += this.GetFoldersize(Source[i].getDirectoryListing());
}
else{
TotalSizeInteger += Source[i].size;
}
}
return TotalSizeInteger;
}
In "Source" you pass the FolderFile.getDirectoryListing(), something like this:
var CC:CustomClass = new CustomClass();
var FolderSize:Number = CustomClass.GetFolderSize(FolderFile.getDirectoryListing());
But this is a very slow method, is there a more quick and easy way to know the folder size?
Sorry for my grammar, i'm just learning english.
Thanks