Qt is now UTF8 by default
Use of QString::fromUtf8 should be plainly deleted, as newer Qt
function by default on UTF8, which is nice.
Similarly, an error in specifying codecs:
no member
named 'setCodecForCStrings' in 'QTextCodec'
The use can just be removed.
Many places used const char * strings; for the most part, changing
these to QString did the trick.
no member named 'toAscii' in 'QString'
I changed these to toLocal8Bit() when the underlying code was about
file names or user names, and to toUtf8().data() otherwise. Static
ASCII strings work with these changes, at least, but the APIs in the
C-library should really be Unicode aware (by, for example, using UTF-8).
UPDATE 2017-03-07
Using str.toUtf8() creates a temporary QByteArray; its lifetime is
therefore tied to the lifetime of the variable it is assigned to. Using
it as someFunc(str.toUtf8().data()) seems therefore a little bit
undefined, as the returned array is only used for the duration of the
call to .data(). At the very least, if there were multiple calls,
like someFunc(foo.toUtf8().data(), bar.toUtf8().data()), the array
pointed to by the first argument would be pointing to freed memory and
therefore be gibberish. I would therefore not use the
foo.toUtf8().data() at all, but instead rewrite the example as
QByteArray fooArr = foo.toUtf8();
QByteArray barArr = bar.toUtf8();
someFunc(fooArr.data(), barArr.data())
Better yet, rewrite the interfaces to use QStrings to as low a level as
possible to avoid the string encodings altogether.
QStrings and QStringLists
Instead of
QStringList lst = QStringList::split(';', txt);
QStringList lst2 = QStringList::split("/", txt, true)
we should have
QStringList lst = txt.split(';');
QStringList lst2 = txt.split(';', QString::KeepEmptyParts);
Instead of QString upper and lower, we should use toUpper and
toLower.
Instead of
int idx = txt.find(".foo", 0, false);
we should have
int idx = txt.indexOf(".foo", 0, Qt::CaseInsensitive);
QString::stripWhiteSpace should be replaced with QString::trimmed.
QString->replace with third argument as a bool should use
Qt::CaseSensitive or Qt::CaseInsensitive instead.
Getting rid of Qt4 means ditching Q3* components
The project still used some components from the Qt3 stock. I guess
that's part of the reason for the continued use of on older version of
Qt4.
Some existing discussion on the removal of Qt3Support gave hope that
this is still doable in the time allotted. Additional help is available
in the official Qt3 to Qt4 porting guide.
Q3ListView -> QTreeWidget
QTreeWidget allows multiple selection. In cases where the
Q3ListView was used to give back a single item, and this is still
valid, use currentItem in the QTreeWidget. Properly handling
multiple selection may be useful later. In many places, the code
disabled sorting for a Q3ListView; this is not necessary with
QTreeWidget as it should not automatically sort.
Number of columns must be set with setColumnCount(), this might be
necessary to add later. Instead of tree->addColumn, the column
headers should be set with tree->setHeaderLabel or
tree->setHeaderLabels (the former just construct a list of single header).
Instead of Q3ListView::selectedItem, we should use
QTreeWidget::currentItem.
Instead of Q3ListView::setSelected, we should use
QTreeWidget::setCurrentItem.
Instead of Q3ListView::firstChild, we should use
QTreeWidget::topLevelItem(0).
Instead of Q3ListView::childCount, we should use
QTreeWidget::topLevelItemCount.
Instead of Q3ListView::setSortColumn(col), we should use
QTreeWidget::sortItems(col, Qt::AscendingOrder). I'm not sure whether
the semantics are exactly to same, and we might need a handler to sort
the the widget when new items are added. In case of
Q3ListView::setSortColumn(-1), we can just delete the call.
QTreeWidget has itemSelectionChanged() instead of
selectionChanged(item *). There are very likely similar issues in
other signals, luckily the program complains about misplaced slots and
signals on startup.
Iterating over all items in QTreeWidget (QTreeWidgetItemIterator doc):
QTreeWidgetItemIterator it(widget);
while (*it)
{
QTreeWidgetItem *item = *it;
// do something with item
it++;
}
Iterating over the first level of items:
for (int ii = 0; ii < widget->topLevelItemCount(); ii++)
{
QTreeWidgetItem *currItem = widget->topLevelItem(ii);
// do something.
}
Q3ListViewItem -> QTreeWidgetItem
Instead of Q3ListViewItem constructor with multiple arguments to stand
for the labels in the columns, QTreeWidgetItem takes a QStringList.
Unfortunately, when a preceding item is specified, the conveniency list
can't be passed, and the columns need to set manually with
item->setText(col, text).
QList<QString> list;
list << col1 << col2 << col3 << col4 << col5 << col6
<< col7 << col8;
QTreeWidgetItem *item = new QTreeWidgetItem(view, prev);
int idx = 0;
foreach(QString str, list) {
item->setText(idx++, str);
}
Previously the code had a pattern where the Q3ListViewItem objects were
initialized with this pattern:
if (lv->lastItem())
new QTreeWidgetItem(lv, lv_view->lastItem(), str);
else
new QTreeWidgetItem(lv, str);
With QTreeWidget objects, this should not be necessary, as the item gets
appended to the list of top-level items.
QTreeWidgetItem *item = new QTreeWidgetItem(tw);
item->setText(0, str);
Instead of Q3ListViewITem::setRenameEnabled() we should probably set
the flag Qt::ItemIsEditable. Catching the change in the data of the
item is still TODO. Probably we need to use itemChanged signal
instead of Q3ListViewITem::itemRenamed, and hope we do not encounter
problems getting those signals when we are modifying the tree ourselves.
Q3ListViewITem::sortChildItems(col, true) should be
QTreeWidgetItem::sortChildren(col, Qt::AscendingOrder).
Q3ListViewITem::setPixmap should be QTreeWidgetItem::setIcon.
Q3ListViewITem::setOpen should be QTreeWidgetItem::setExpanded.
Q3ListViewITem::listView should be QTreeWidgetItem::treeWidget.
Q3ListViewITem::startRename should be QTreeWidget::editItem.
Iterating over the children of a QTreeWidgetItem:
for (int ii = 0; ii < item->childCount(); ii++)
{
QTreeWidgetItem *currItem = item->child(ii);
// do something.
}
Deleting all children of QTreeWidgetItem:
qDeleteAll(item->takeChildren());
Instead of Q3ListViewITem::insertItem, we should use
QTreeWidgetItem::addChild.
Instead of Q3ListViewITem::takeItem, we should use
QTreeWidgetItem::removeChild.
Q3ComboBox to QComboBox
QComboBox insertItem() requires index of the inserted item as an
argument. Using container->count as argument should be ok, although
naturally the correct index works as well :)
QComboBox::currentItem should be replaced with
QComboBox::currentIndex.
QComboBox::text(i) should be replaced with QComboBox::itemText(i).
Layouts
no member named 'insert' in 'QGroupBox'
Instead of insert(), we should use addWidget() to a *Layout
object, and set that to the QGroupBox.
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(radio);
groupBox->setLayout(vbox);
Q3HBoxLayout *layout1 = new Q3HBoxLayout(0, 0, 6, "layout1")
The extra arguments can pretty safely be ignored. Spacing and margins
can be set with setters separately.
Other changes and renamings
Q3Frame to QFrame.
The documentation indicates that perhaps what will be missed is frame
around the butttons, and at this point this is not critical.
The Q3Frame took object name as a parameter, I guess this can be
safely deleted when moving it to QFrame. It can be set with
setObjectName() later, if necessary.
Q3TextEdit to QTextEdit.
Q3Table to QTableWidget
Error about missing member:
no member named
'GuiClient' in 'QApplication'
Type type = QApplication::GuiClient
Fix is pretty non-controversial, the type has been nuked as the
QApplication was split to QCoreApplication and QApplication, so
just delete use from the app.
no member named 'setPixmap' in 'QPushButton'
cip_left->setPixmap(QPixmap(":/left_arrow.png"));
From QIcon documentation, I think the following should be equivalent
button->setIcon(QIcon("open.xpm"));
container->label(i) should be replaced with container->tabText(i).
QWidget->setCaption should be replaced with QWidget->setWindowTitle.
QHeaderView->setMovable should be replaced with
QHeaderView->setSectionsMovable.
QHeaderView->setResizeMode should be replaced with
QHeaderView->setSectionResizeMode.
QSplitter::setResizeMode should be replaced with
QSplitter::setStretchFactor. Described in the QSplitter
compatibility document, also the QSplitter enums have disappeared,
so the semantics of the call are different.
splitter->setResizeMode(firstChild, QSplitter::KeepSize);
splitter->setResizeMode(secondChild, QSplitter::Stretch);
should be rewritten as
splitter->setStretchFactor(splitter->indexOf(firstChild), 0);
splitter->setStretchFactor(splitter->indexOf(secondChild), 1);
Instead of QDir::convertSeparators we should use
QDir::toNativeSeparators.
With
QMap<QTreeWidgetItem*, MyDataObject>::Iterator it;
we should use it.value() instead of it.data(), as described in the
Qt4 doc of QMap iterators.
new QPushButton(this, "help"); should be rewritten as new
QPushButton("help", this);, the text is now the first argument.
Use of setCentralWidget() in the app was weird, and caused the program
to have a really funky layout. I wonder why it was not a problem with
Qt4.