Changing current path of a Qt Application - c++

I am using Qt Library and I want to set the current path to the path contained in a QString oldConfigFileName and i am using setCurrent() but setCurrent is returning a false value indicating a failure in changing path.
Code:
QString path = QDir::currentPath();
std::string currentpath = path.toStdString();
std::string configPath = oldConfigFileName.toStdString();
bool res = QDir::setCurrent(oldConfigFileName);
if(res)
{
qDebug() << "Path Changed";
}
else
{
qDebug() << "Path not changed";
}

The problem is the path you are using is a full path to a config file containing the file name. When you try to change the directory to this path the command will fail because oldConfigFileName is a file not an existing folder. A simple way to fix this is to use QFileInfo to remove the filename part from the path then use that as the directory.
QFileInfo fi(oldConfigFileName);
bool res = QDir::setCurrent(fi.path());
if(res)
{
qDebug() << "Path Changed";
}
else
{
qDebug() << "Path not changed";
}

Without knowing an actual content of the oldConfigFileName, one reason for failure may be that the path does not exists. It may be good idea to check existance of the path before calling the QDir::setCurrent() -method.
if(!QDir(oldConfigFileName).exists())
{
qDebug() << "Path does not exists.";
// Path does not exists, if needed, it can be created by
// QDir().mkdir(oldConfigFileName);
}
Another reason for the failure may be that oldConfigFileName does not contain valid path string. To check that, I would change debug logs following way:
if(res)
{
qDebug() << "Path Changed";
}
else
{
qDebug() << "Path not changed. Path string = " << oldConfigFileName;
}

Related

How to deal with File Path thruogh slots in User Interface?

I want to build a simple interface to my offline Map Project (C++), how can I replace the Path passed to My Function loadFile("G:/QT/Projects/database/city.osm.pbf"); with Open File so The Function Load File takes the path from the map file I'm choosing ?
void MainWindow::on_action_Open_File_triggered()
{
QString FileName = QFileDialog::getOpenFileName(this,tr("Open File"),"C://","OSM File (*.pbf)" );
//cout << "File Name \t"<< FileName.toStdString() <<endl;
string FilePath2 = FileName.toStdString();
loadFile(FilePath2);
}

Qt: empty content of opened QFile for a .txt file from the project resources

I tried this in my project in mainwindow.cpp:
QString dir = ":/nodesDir/nodesDir/";
QFile baseFile(dir + "allNodeNames.txt");
qDebug() << baseFile.exists(); // true
qDebug() << baseFile.readAll(); // ""
but it is wrong, the content of the file is
plusOperator
Why does it say, that there would be nothing written in the file? Or What did I miss in my code?`
Thanks for answers!
In order to read the file you need to open it for it we use open () and we indicate the way we want it to open. We must also bear in mind that the files stored in the resources are read only, so they can not be modified.
QString dir = ":/nodesDir/nodesDir/";
QFile baseFile(dir + "allNodeNames.txt");
qDebug() << baseFile.exists(); // true
qDebug()<< baseFile.open(QFile::ReadOnly);
qDebug() << baseFile.readAll(); // ""
Output:
true
true
"plusOperator"

C++ Transfer Files From Qt to External USB Drive

I am new in Qt and I need help in transferring all files from a specific path of the local machine to an external USB Drive.
Copying a single file
You can use QFile::copy.
QFile::copy(srcPath, dstPath);
Note: this function doesn't overwrite files, so you must delete previous files if they exist:
if (QFile::exist(dstPath)) QFile::remove(dstPath);
If you need to show an user interface to get the source and destination paths, you can use QFileDialog's methods to do that. Example:
bool copyFiles() {
const QString srcPath = QFileDialog::getOpenFileName(this, "Source file", "",
"All files (*.*)");
if (srcPath.isNull()) return false; // QFileDialog dialogs return null if user canceled
const QString dstPath = QFileDialog::getSaveFileName(this, "Destination file", "",
"All files (*.*)"); // it asks the user for overwriting existing files
if (dstPath.isNull()) return false;
if (QFile::exist(dstPath))
if (!QFile::remove(dstPath)) return false; // couldn't delete file
// probably write-protected or insufficient privileges
return QFile::copy(srcPath, dstPath);
}
Copying the whole content of a directory
I'm extending the answer to the case srcPath is a directory. It must be done manually and recursively. Here is the code to do it, without error checking for simplicity. You must be in charge of choosing the right method (take a look at QFileInfo::isFile for some ideas.
void recursiveCopy(const QString& srcPath, const QString& dstPath) {
QDir().mkpath(dstPath); // be sure path exists
const QDir srcDir(srcPath);
Q_FOREACH (const auto& dirName, srcDir.entryList(QStringList(), QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name)) {
recursiveCopy(srcPath + "/" + dirName, dstPath + "/" + dirName);
}
Q_FOREACH (const auto& fileName, srcDir.entryList(QStringList(), QDir::Files, QDir::Name)) {
QFile::copy(srcPath + "/" + fileName, dstPath + "/" + fileName);
}
}
If you need to ask for the directory, you can use QFileDialog::getExistingDirectory.
Final remarks
Both methods assume srcPath exists. If you used the QFileDialog methods it is highly probable that it exists (highly probable because it is not an atomic operation and the directory or file may be deleted or renamed between the dialog and the copy operation, but this is a different issue).
I have solved the problem with the QStorageInfo::mountedVolumes() which return the list of the devices that are connected to the Machine. But all of them won't have a name except the Pendrive or HDD. So (!(storage.name()).isEmpty())) it will return the path to only those devices.
QString location;
QString path1= "/Report/1.txt";
QString locationoffolder="/Report";
foreach (const QStorageInfo &storage, QStorageInfo::mountedVolumes()) {
if (storage.isValid() && storage.isReady() && (!(storage.name()).isEmpty())) {
if (!storage.isReadOnly()) {
qDebug() << "path:" << storage.rootPath();
//WILL CREATE A FILE IN A BUILD FOLDER
location = storage.rootPath();
QString srcPath = "writable.txt";
//PATH OF THE FOLDER IN PENDRIVE
QString destPath = location+path1;
QString folderdir = location+locationoffolder;
//IF FOLDER IS NOT IN PENDRIVE THEN IT WILL CREATE A FOLDER NAME REPORT
QDir dir(folderdir);
if(!dir.exists()){
dir.mkpath(".");
}
qDebug() << "Usbpath:" <<destPath;
if (QFile::exists(destPath)) QFile::remove(destPath);
QFile::copy(srcPath,destPath);
qDebug("copied");
}
}
}
I had to create a folder as well as in USB because of my requirements and I have given a static name for the files. Then I just copied the data from file of the local machine to the file which I have created in USB with the help of QFile::copy(srcPath, dstPath). I hope it will help someone.

How to filter if a directory is root directory in windows/qt?

I am showing contents of folder (only show certain files) when user is typing path. I don't want to show content if its a root folder (c:\ drive) because it searches all sub directories and it would take too long and is not needed.
The problem is if I type "c:\\" in the edit box, it still searches the C:\ drive but QDir::isRoot() doesn't pick it up. How can I catch path accurately that could be root path or even program files path? I am using Windows 7.
void MainWindow::on_lineEditSourceFolder_textChanged(const QString &arg1)
{
//qDebug() << "edit text changed: " << arg1;
QDir dir( arg1 ) ;
if ( !dir.exists() )
{
model->clear();
return;
}
QString dirPath = dir.absolutePath();
if (dir.isRoot() )
{
qDebug() << arg1 << " is root";
return;
}
searchFiles( dirPath );
}
Looks like a bug in QT. Have a look at the source of QDir.isRoot() to be sure, then submit a bug report.
But the QT docs might show a workaround. Try changing this:
QString dirPath = dir.absolutePath();
into
QString dirPath = dir.canonicalPath();
Here's isRoot() behavior:
returns false on c
returns false on c:
returns true on c:\
So when you enter c:, isRoot() returns false and searchFiles() will be called. When you subsequently press \, isRoot() returns true, but you did not call model->clear() before returning. This gives the impression that c:\ still call searchFiles().
So you should do a clear before returning:
if (dir.isRoot() )
{
qDebug() << arg1 << " is root";
model->clear();
return;
}
If you don't want c: to search files too, append a \ to the directory before checking for root:
void MainWindow::on_lineEditSourceFolder_textChanged(const QString &arg1)
{
QString temp = arg1 + '\\';
QDir dir( temp ) ;
....

QDir::setCurrent vs QFileInfo::

I've come across a anomaly in Qt (v4.8.4) when re-assigning a new path to a pre-existing QDir object. Here is a reduced example demonstrating this:
QString path1("F:/"); //Path must exist...
QString path2("F:/Some/Valid/Path/For/You/"); //Path must exist...
//Set default...
QFileInfo fi1(path1);
QDir d(fi1.absoluteDir());
//CASE 1...
if(!d.setCurrent(path2)) {
qDebug() << QString("Cannot set path (%1)").arg(path2).toAscii().data();
return -1;
}
qDebug() << "CASE 1:";
qDebug() << QString("path2: %1").arg(path2).toAscii().data();
qDebug() << QString("d : %1").arg(d.absolutePath()).toAscii().data();
//END of CASE 1...
//CASE 2...
QFileInfo fi2(path2);
d = fi2.absoluteDir();
qDebug() << "CASE 2:";
qDebug() << QString("path2: %1").arg(path2).toAscii().data();
qDebug() << QString("d : %1").arg(d.absolutePath()).toAscii().data();
//END of CASE 2...
Even though the call to d.setCurrent(path2) returns true, the new path is not set in the QDir object. OTOH, assigning the new path 1st to a QFileInfo object, and then calling absoluteDir() on that object returns an updated QDir object.
You can then directly assign the returned object to a pre-existing QDir object (through the overridden assignment operator), and the path in the QDir object will be correctly updated.
Why does the CASE 1 not work?
QDir::setCurrent is a static function that sets the current path of the application. It doesn't modifiy any QDir instance.
You should use QDir::setPath to assign a new path (or assign the QString directly to QDir with the = operator, since the conversion is implicit).