Keeping translations when moving source strings - qt

I have a single translator.cpp source file containing a lot of strings. These have been been translated to various languages using Qt Linguist. Now I want to split the single file into multiple files:
Old structure:
class Translator
{
QString str1 = tr("");
QString str2 = tr("");
QString str3 = tr("");
};
New structure:
class Translator1
{
QString str1 = tr("");
};
class Translator2
{
QString str2 = tr("");
};
class Translator3
{
QString str3 = tr("");
};
After splitting the translations are lost. What is the fastest way to split the class while keeping the existing translations?
Regards,

Related

QIconProvider's icon method is called for files that are not in the filter

I am trying to populate a QListWidget (in icon view) with a QFileSystemModel. I want to list folders and only files with specific extension. I want to show the preview of my files as their thumbnail, so I am subclassing QIconProvider class and I am setting this to my model.
Before setting my QIconProvider to the model I have already filtered the files that I want on my model, icon(const QFileInfo & info) is called for every file that exists in the listed directory.
I have found a work around checking the extension of the file before returning my custom icon, but I am wondering if thre is a way to avoid this.
m_itemsModel = new QFileSystemModel(this);
m_itemsModel->setFilter(QDir::AllEntries | QDir::NoDotAndDotDot);
m_itemsModel->setRootPath(QDir::homePath());
QStringList filters = formatsList();
m_itemsModel->setNameFilters(filters);
m_itemsModel->setNameFilterDisables(false);
ui.listView->setModel(m_itemsModel);
m_itemsModel->setIconProvider(new ThumbnailIconProvider(QRect(0, 0, 50, 50)));
my QIconProvider:
ThumbnailIconProvider::ThumbnailIconProvider(const QRect &rect)
: QFileIconProvider() {
m_rect = rect;
}
QIcon ThumbnailIconProvider::icon(const QFileInfo & info) const {
static QStringList filters = formatsList();
QString fileName = info.fileName();
QString extension = "*" + fileName.right(fileName.length() - fileName.lastIndexOf("."));
if (info.isFile() && filters.contains(extension)) {
QString path = info.absoluteFilePath();
FileDetails details = fileDetailsFromPathForRect(path, m_rect);
QPixmap pixmap = QPixmap::fromImage(details.image);
QIcon icon(pixmap);
return icon;
}
else
return QFileIconProvider::icon(info);
}
Any ideas please?

Tree map not sorting in order

So my code so far reads in lines from a file, stores them in two separate ArrayLists. Now I'm going to have to make each node in a doubly Linked List contain the line's string and the corresponding integer, but since I cant put two ArrayLists in the declaration for a Linked List, I tried making a Tree map where the key is the string and the value is the corresponding integer. Here's the relevant code
public class FileReaderProgram
{
public static void main(String[] args) throws IOException
{
ArrayList<String> words = new ArrayList<String>();
ArrayList<Integer> numbers = new ArrayList<Integer>();
String stringComponent = " ";
int integerComponent = 0;
Scanner in = new Scanner(System.in);
System.out.println("Enter the absolute path of the file");
String fileName = in.next(); //Gets the file from the user
File inFile = new File(fileName);
**Map<String,Integer> lineCombo = new TreeMap<String,Integer>();**
try
{
Scanner fileReader = new Scanner(inFile); //Constructs Scanner for reading the file
fileReader.useDelimiter("\\n");
while (fileReader.hasNextLine())
{
String line = fileReader.nextLine(); //Gets line from the file
Scanner lineScanner = new Scanner(line); //Constructs new scanner to analyize the line
lineScanner.useDelimiter(",");
stringComponent = lineScanner.next(); //Read first word
while (!lineScanner.hasNextInt())
{
stringComponent = stringComponent + " " + lineScanner.next(); //Checks if more than one word part of string
}
integerComponent = lineScanner.nextInt(); //Read in integer
words.add(stringComponent); //Array of Strings, element number corresponding to the line it came from
numbers.add(integerComponent); //Array of Ints, same thing as above
**lineCombo.put(stringComponent, integerComponent);**
}
}
So when I run the file:
example string,1
another example,42
data,200
final,150
it prints out {another example=42, data=200, example string=1, final=150}
Why is it putting the strings in the wrong order?

How to implement clipboard actions for custom mime-types?

I am trying to implement copy/cut/paste in a complex application.
I have a QGraphicsScene that can contain QGraphicsItem subtypes of varied subtypes, fairly complex (with Item as a second parent storing custom properties).
I would copy/cut selected items, and paste them back in place.
I already have implemented it using a local version: a list of items.
void copyItemsActionOld()
{
foreach(QGraphicsItem* qItem, selectedItems())
{
Item* newItem = (dynamic_cast<Item*>(qItem))->createItemCopy();
m_itemClipboard.append(newItem);
}
}
On paste, I make a copy of all items in clipboard and add them to the scene. So simple.....
BUT
I need to implement it using the global system clipboard.
I saw that creating a custom mime type is as simple as calling setData on a QMimeData object, after I make up a format name... (I hope that is true)
static const QString _mimeType("application/myItem");
void copyItemsAction()
{
QMimeData* _mimeData = new QMimeData;
2 QByteArray _itemData = ?????;
_mimeData->setData(_mimeType, _itemData);
QClipboard* _clipboard = QApplication::clipboard();
_clipboard->clear();
_clipboard->setMimeData(_mimeData);
}
void pasteItemsAction()
{
QClipboard* _clipboard = QApplication::clipboard();
const QMimeData* _mimeData = _clipboard->mimeData();
QStringList _formats = _mimeData->formats();
foreach (QString _format, _formats)
{
if (_format == _mimeType)
{
QByteArray _itemData = _mimeData->data(_mimeType);
3 // then do what ? How do I parse it ?
}
}
}
My questions
1) Are the above fragments for copyItemsAction and pasteItemsAction anywhere close to how clipboard actions should work ?
2) How can I put item data in the QByteArray ?
3) How do I parse the data in QByteArray ?
4) Do I need to register the custom mime-type anywhere else ? (other than what I just did in my two functions); and will it be multi-platform ?
I have already implemented save and load functionality for all items. Something like...
void Item::saveItem(QDataStream &outFile)
{
outFile << type;
outFile << width;
outFile << color.name();
}
Can I use this to place the items data in the QByteArray ? (How ?)
I was on the right track, and I kept adding code to my question until I found how to make it work:
static const QString _mimeType("application/myItem");
void copyItemsAction()
{
QByteArray _itemData;
QDataStream outData(&_itemData, QIODevice::WriteOnly);
outData << selectedItems().size();
foreach(QGraphicsItem* qItem, selectedItems())
{
Item* item = dynamic_cast<Item*>(qItem);
item->saveItem(outData);
}
QMimeData* _mimeData = new QMimeData;
_mimeData->setData(_mimeType, _itemData);
_mimeData->setText("My Items");
QClipboard* _clipboard = QApplication::clipboard();
_clipboard->clear();
_clipboard->setMimeData(_mimeData);
}
void pasteItemsAction()
{
QClipboard* _clipboard = QApplication::clipboard();
const QMimeData* _mimeData = _clipboard->mimeData();
QStringList _formats = _mimeData->formats();
foreach (QString _format, _formats)
{
if (_format == _mimeType)
{
QByteArray _itemData = _mimeData->data(_mimeType);
QDataStream inData(&_itemData, QIODevice::ReadOnly);
int itemsSize;
inData >> itemsSize;
for (int i = 0; i < itemsSize; ++i)
{
Item* item = ...
item->loadItem(inData);
}
}
}
}
So, for question 1, yes I was on the right track;
For questions 2 and 3 - I was able to use a QDataStream to serialize info to/from the QByteArray.
If there is a better / more effective / faster way, I would love to know...
For question 4 - it seems that I can use just about any string, if all I want is to copy/paste within a single instance of my application.
It is also true if I want to use it between multiple applications, multiple instances of my application, or for drag-and-drop - on most platforms. (It does not seem to work between multiple applications/instances in the embedded platform I target.)
Caveat - it fails frequently when another clipboard using application is open, in windows.

Reading and writing classes with pointers to binary files in c++

I've been trying to write some data to a binary file in c++ using fstream and most examples go like this:
#include <fstream>
class Person{
public:
int age;
char name[50];
}
int main(){
Person joe;
joe.age = 50;
strncpy(joe.name, "Joe Jones");
fstream file("filename.dat", ios_base::binary);
file.write((char*)joe, sizeof(joe));
file.close();
}
This works just as expected but the problem arises when I try to write a more complex structure, mainly one with pointers instead of the actual data.
class Person{
public:
int age;
int *friendsAges;
Person(int friends){
friendsAges = new int[friends];
}
}
When I write the data like before
Person joe(10);
/* Initialize rest of joe */
file.write((char*)joe, sizeof(joe));
the resulting file has 8 bytes of data, 4 for the age and 4 for the address of the friendsAges array or so it seems.
How could I go about writing the actual data that is stored in the array? I have also had this problem when my classes have other classes as members such as a Person having a Car or something like that.
For starters, add a method to your class that will perform the file I/O then you can just call it like so:
Person joe();
Person sally();
fstream file("filename.dat", ios_base::out | ios_base::binary);
joe.serialize(file, true);//writes itself to the file being passed in
sally.serialize(file, true); //write another class to file after joe
file.close();
Then later you could read that same file to populate the class instance:
fstream file("filename.dat", ios_base::in | ios_base::binary);
joe.serialize(file, false); //reads from file and fills in info
sally.serialize(file, false); //reads from file too
file.close();
The method in the class would look something like this:
Person::serialize(fstream &fs, bool bWrite)
{
int ages_length;
if (bWrite) {
fs.write(&age, sizeof(age));
ages_length = ...; //you need to know how long the friendsAges array is
fs.write(&ages_length, sizeof(ages_length)); //write the length to file
fs.write(&friendsAges[0], sizeof(int)*ages_length); //write the variable-sized array to file
fs.write(&name[0], sizeof(char)*50); //write a string of length 50 to file
}
else {
fs.read(&age, sizeof(age));
fs.read(&ages_length, sizeof(ages_length)); //read length of array from file
//TODO: you will need to malloc some space for *friendsAges here
fs.read(&friendsAges[0], sizeof(int)*ages_length); //read-in the variable length array
fs.read(&name[0], sizeof(char)*50); //this only works if string length is always fixed at 50
}
}

QVector: no match for 'operator+'

I am passing a QVector from one window to another, I want to append the value present in QVector from previous window to a QString in present window. I get the error when I perform the addition no match for 'operator+'.
Here is my code:
Window1.cpp
void SelectOS::processNextButton()
{
if(ui->win32->isChecked()){
QString path;
path = qApp->applicationDirPath()+"/WIN/32Bit";
so->osName.push_back(path);
SelectSoftware *ss = new SelectSoftware();
this->hide();
ss->show();
}
}
QVector<QString> SelectOS::getosName(){
so = new SelectOS();
return so->osName;
}
Window2.cpp
void SelectSoftware::getSoftwareDetails()
{
SelectOS *so = new SelectOS();
SelectSoftware *ss = new SelectSoftware();
ss->os = so->getosName();
QString fileName = ss->os + "/" +SOFTWARELIST; // Here I get the error...
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)){
QString msg = "Could not find the file " + fileName;
errorExit(msg);
}
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
processLine(line.toLower());
}
}
Help me, thanks ...
Assuming SOFTWARELIST is a simple QString:
QString fileName = QString( "%1/%2" )
.arg( ss->os.last() )
.arg( SOFTWARELIST );
This means you are creating a QString with placeholders %1 and %2 where %1 will be replaced by the result of ss->os.last() which returns the last item in the vector and %2 will be replaced by whatever SOFTWARELIST is.
If SOFTWARELIST is a vector as well, you will need to call e.g. .last() on it as well.
QVector is a container class, which holds set of something. In your example set of QString's. So then you try to form a fileName which is a QString you obviously cannot add to a fileName QString list of other Qstring's. (truly saying you can, but not with '+' operator and slightly different code).
Honestly I didn't got straight away why you actually passing QVector if you only need an application path I would suggest to use just QString.

Resources