I want to replace an element in a QString - QT - C++ - c++

I have following problem:
I saved in a QString an XMLStart.
QString f = "<class=\"go\">\n"
"<number>2</number>\n"
"<column>3</column>\n"
"<row>4</row>";
I want to change for example the value of row with 7 in this String by for example using replace or something like that.
f.replace();
How can i achive that ? Is that possible?
Regards

I'm not familiar with XML in Qt and I'm sure that there is a more elegant way that hopefully someone will post after me, but this is an easy way to do your replacement.
Of course you'll have to provide the string values in a better way...
QString xml = "<class=\"go\">\n"
"<number>2</number>\n"
"<column>3</column>\n"
"<row>4</row>";
QString tag = "row";
QString val = "7";
QByteArray exp("<%1>%2</%1>");
QString rex = QString(exp).arg(tag, ".*");
QString rep = QString(exp).arg(tag, val);
xml.replace(QRegExp(rex), rep);

Related

Issue when searching QTableWidget using wildcards

In my Qt C++ application I have several items in a qtablewidget. A QLineEdit along with a button are used by me in order to search the QTableWidget when a particular word is given to the line edit and the search button is clicked. Following is my code:
bool found=false;
QString Line= ui->search->text();
for(int i=0;i<100;i++){
if(ui->tableWidget->item(i,0)->text()== Line){
found = true;
break;
}
}
if(found){
ui->tableWidget->clear();
ui->tableWidget->setItem(0,0,new QTableWidgetItem(Line));
}
else{
QMessageBox::warning(this, tr("Application Name"), tr("The word you are searching does not exist!") );
}
This code works if an exact word in the table widget is given but if I use
ui->tableWidget->item(i,0)->text()=="%"+ Line+"%";
It won't work for the wild card scenario so that I can search even part of a word is given. How can I correct this issue?
The == operator compare two strings and return true if they are exacly equals.
If you want to use wildcards, I suggest to use QRegExp and use QRegExp::Wildcard as pattern syntax.
Example 1:
QString line = "aaaaLINEbbbb";
QRegExp rx("*LINE*");
rx.setPatternSyntax(QRegExp::Wildcard);
rx.exactMatch(line); //should return true
However, if you want to test only if a string contains a substring, I suggest to use bool QString::contains(const QString &str, Qt::CaseSensitivity cs) that can be faster.
Example 2:
QString line = "aaaaLINEbbbb";
QString searchWord = "LINE";
line.contains(searchWord); //should return true
See:
QRegExp
QRegExp::PatternSyntax
Wildcard Matching
QString::contains

How do I get the value of text inside of the file using Qt?

The data of my file.txt is as below:
Student_ID=0001
Student_Name=joseph
Student_GradeLevel=2
How do I get the value, let say I want to get the Student_ID using Qt.
Thanks.
Take a look at this function, it can be used to find any value you want in your input file, where all lines are in the format you've posted above (key=value). If the key is not found, it returns an empty QString() object.
QString findValueInFile(QString key, QString filename) {
QFile file(filename);
if(file.open(QIODevice::ReadOnly)) {
QTextStream txtStr(&file);
QStringList fileContent = txtStr.readAll().split('\n');
for(auto &&line : fileContent) {
if(line.contains(key)) return line.split(QChar('='))[1];
}
file.close();
}
return QString(); // not found
}
Now you call it somewhere, e.g.:
qDebug() << findValueInFile("Student_ID", "file.txt");
qDebug() << findValueInFile("Student_Name", "file.txt");
This function can be easily modified if you replace your = sign with other delimiter e.g. => or sth else. However for key=value format there is a special QSettings class (mentioned by sebastian) that can allow you to read those values even easier:
QSettings file("file.txt", QSettings::IniFormat);
qDebug() << file.value("Student_Name").toString(); // et voila!
You can probably also use QSettings, as they are able to read ini files.
There are some caveats though regarding backslashes which might be important to you (though they aren't for the example you posted): http://doc.qt.io/qt-4.8/qsettings.html#Format-enum
QSettings iniFile("myfile.txt", QSettings::IniFormat);
// now get the values by their key
auto studentId = iniFile.value("Student_ID").toString().toInt();
I'm more of a PyQt user, so: apologies if I got some C++ specifics wrong...

Removing extension of a file name in Qt

I'm using Qt to get a file name from the user:
QString fileName = QFileDialog::getOpenFileName(this,tr("Select an image file"),"d:\\",tr("Image files(*.tiff *.tif )"));
It works, but I need the file name without its extension, is it possible in Qt??
whenn I try :
QString f = QFileInfo(fileName).fileName();
f is like "filename.tif", but I want it to be "filename".
QFileInfo has two functions for this:
QString QFileInfo::completeBaseName () const
Returns file name with shortest extension removed (file.tar.gz -> file.tar)
QString QFileInfo::baseName () const
Returns file name with longest extension removed (file.tar.gz -> file)
To cope with filenames containing multiple dots, look for the last one and take the substring until that one.
int lastPoint = fileName.lastIndexOf(".");
QString fileNameNoExt = fileName.left(lastPoint);
Of course this can (and should) be written as a helper function for reuse:
inline QString withoutExtension(const QString & fileName) {
return fileName.left(fileName.lastIndexOf("."));
}
You can split fileName with "." as separator like this:
QString croped_fileName=fileName.split(".",QString::SkipEmptyParts).at(0);
or use section function of QString to take the first part before "." like this:
QString croped_fileName=fileName.section(".",0,0);
You can use QString::split and use the . as the place where to split it.
QStringList list1 = str.split(".");
That will return a QStringList with {"filename", "extenstion"}. Now you can get your filename without the extension.
To get absolute path without extension for QFileInfo fileInfo("/a/path/to/foo.tar.gz") you can use:
QDir(file_info.absolutePath()).filePath(file_info.baseName());
to get "/a/path/to/foo" or
QDir(file_info.absolutePath()).filePath(file_info.completeBaseName());
to get "/a/path/to/foo.tar"

How to get enumeration type value from MS Word 2007?

I need to get current page in my document, with set range. I found that it is possible to do by:
Range.Information(wdActiveEndPageNumber) //example in C#
but i have problem with that. In documentation, information is visible as property. So when i use
QString number = myRange->property("Information(wdActiveEndPageNumber)").toString()
i'm getting nothing. I also tried dynamicCall, but either doesn't work. Simple properties as Text or Start works perfectly fine, but i have no idea what to do with these enumerations.
Whole code:
QAxObject *word, *doc;
word = new QAxObject("Word.Application", this);
word->setProperty("DisplayAlerts", false);
word->setProperty("Visible", true);
doc = word->querySubObject("Documents");
doc->dynamicCall("Open(const QString&)", "path to file");
QAxObject *act = word->querySubObject("ActiveDocument");
QAxObject *next = act->querySubObject("Content");
next->dynamicCall("Select()");
next->dynamicCall("Copy()");
QClipboard *clip = QApplication::clipboard();
myTextEdit->setText(clip->text());
QString number = next->property("Information(3)").toString();
QMessageBox::information(this, tr("cos"), tr("%1").arg(number)); //here i need to know how many pages i've got
Okay, after much research, I found that there is no possibility yet to take value from Information enum. Maybe in future version of Qt, but nowadays I had to create library in Visual Basic and invoke functions from C++ code.
Just found a really cool answer to this question here:
http://www.qtforum.org/article/31970/how-do-i-get-use-the-ienumerable-interface-in-qt.html
Here the answer again.
With returnList containing your enum..
QAxObject *enum1 = returnList->querySubObject("_NewEnum");
IEnumVARIANT* enumInterface; //to get this, include <windows.h>
enum1->queryInterface(IID_IEnumVARIANT, (void**)&enumInterface);
enumInterface->Reset(); //start at the beginning of the list.
for (int i=0;i<returnList->dynamicCall("Count").toInt();i++)
{
VARIANT *theItem;
enumInterface->Next(1,theItem,NULL);
QAxObject *item = new QAxObject((IUnknown *)theItem->punkVal);
qDebug() << item->dynamicCall("Caption");
}

How do I get the correct case of a path?

I have a small but itching problem. How do I get the correct case for a Windows path in Qt?
Let's say i have a path c:\documents and settings\wolfgang\documents stored in a QString str and i want to know the correct case, here C:\Document and Settings\Wolfgang\Documents. QDir(str).absolutePath() doesn't get me the path with correct case.
Any suggestions, since I have no clue what else i could try?
Thank you for your time!
There isn't a simple way to do this, but you can try doing a QDir.entryList, and then do a case insensitive search on the results. This will provide you with the correct filename. You'll then need to get the absolutePath for that result.
This should give you the preserved-case for the path/filename.
I think the solution currently accepted by the OP, with listing all children items on each directory level of the path, is really inefficient, quick and dirty. There must be a better way. Because this problem with case-correct path relates only to Windows (other platforms are case-sensitive, AFAIK), I think it is perfectly correct to use #ifdef and call to Windows API and write something like this:
#if defined(Q_OS_WIN32)
#include <Windows.h>
// Returns case-correct absolute path. The path must exist.
// If it does not exist, returns empty string.
QString getCaseCorrectPath(QString path)
{
if (path.isEmpty())
return QString();
// clean-up the path
path = QFileInfo(path).canonicalFilePath();
// get individual parts of the path
QStringList parts = path.split('/');
if (parts.isEmpty())
return QString();
// we start with the drive path
QString correctPath = parts.takeFirst().toUpper() + '\\';
// now we incrementally add parts one by one
for (const QString &part : qAsConst(parts))
{
QString tempPath = correctPath + '\\' + part;
WIN32_FIND_DATA data = {};
HANDLE sh = FindFirstFile(LPCWSTR(tempPath.utf16()), &data);
if (sh == INVALID_HANDLE_VALUE)
return QString();
FindClose(sh);
// add the correct name
correctPath += QString::fromWCharArray(data.cFileName);
}
return correctPath;
}
#endif
I have not tested it, there might be some minor issues. Please let me know if it does not work.
You can use QFileInfo for that and the function
QString QFileInfo::absoluteFilePath () const will return the absolute file path.
E.g:
QFileInfo yourFileInfo(yourPath);
QString correctedCasePath = yourFileInfo.absoluteFilePath ();
Another advantage is that, yourPath can be a QFile or QString so that you can use it directly with the handle currently you are having. Besides these, there are other operations are also available through QFileInfo that can obtain useful information about the file being referred to..
Hope it helps..