Wednesday, November 16, 2016

New print option for QtWebEngine in Qt 5.8

Beta version of Qt 5.8 version is out now and list of new features is available here .

For QWebEnginePage a new print option was added. As soon as in Qt 5.7 printing to PDF was already available, now printing through QPrinter also works:

void print(QPrinter *printer, 
       FunctorOrLambda resultCallback);

This is actually implemented by saving web content into temporary PDF file and then printing it out. When saving PDF file, settings of QPrinter are applied.

We can easily find an example of this function usage in demobrowser (Qt installation, Examples folder). resultCallback takes boolean as parameter which indicates whether printing is successful or not.

m_currentPrinter = new QPrinter();
QScopedPointer dialog(new QPrintDialog(m_currentPrinter, this));
dialog->setWindowTitle(tr("Print Document"));
if (dialog->exec() != QDialog::Accepted) {
    slotHandlePagePrinted(false);
    return;
}
page->print(m_currentPrinter, invoke(this, &BrowserMainWindow::slotHandlePagePrinted));
void BrowserMainWindow::slotHandlePagePrinted(bool result)
{
    Q_UNUSED(result);

    delete m_currentPrinter;
    m_currentPrinter = nullptr;
}

Tuesday, May 31, 2016

New method QHostAddress::isMulticast() in Qt 5.6

Among new features of Qt 5.6 new method was added for QHostAddress:

QHostAddress::isMulticast

This bool method returns true if IPv4 or IPv6 address is multicast.

From wikipedia a multicast address is a logical identifier for a group of hosts in a network available to process datagrams or frames intended to be multicast for a network service.

Here is the test program which shows the output for different IPv4 addresses:

#include <QCoreApplication> 
#include <QDebug>
#include <QHostAddress>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QHostAddress ipv4false("127.0.0.1");
    qDebug() << ipv4false.isMulticast(); // false
    // The All Hosts multicast group addresses all 
    // hosts on the same network segment.
    
    QHostAddress ipv4true("224.0.0.1");
    qDebug() << ipv4true.isMulticast(); // true

    return a.exec();
}

It works the same way for IPv6 addresses.

Tuesday, May 24, 2016

QtWebEngine: Printing to PDF

Among new features in Qt 5.7 for QtWebEngine there is printing to PDF. There are several samples which are available for QtWebEngine you can start from this folder in your Qt installation:

c:\Qt\Qt5.7.0\Examples\Qt-5.7\qtwebengine\webenginewidgets\

We will look at demobrowser sample. Let's start from BrowserMainWindow::slotFilePrintToPDF(). Unfortunately Qt still has problem with QPrintDialog not working on Windows described here:

https://bugreports.qt.io/browse/QTBUG-28822
http://www.qtcentre.org/threads/56992-Printer-problem

So for sample purposes we will remove QPrintDialog and just hardcode filename:

void BrowserMainWindow::slotFilePrintToPDF()
{    
#ifndef QT_NO_PRINTER
    if (!currentTab())
        return;    

    QPrinter printer;
    printer.setOutputFileName("test.pdf");
    if (printer.outputFileName().isEmpty() || 
        !m_printerOutputFileName.isEmpty())
        return;
    m_printerOutputFileName = printer.outputFileName();
    currentTab()->page()->printToPdf(printer.pageLayout(), 
                                     invoke(this, &BrowserMainWindow::slotHandlePdfPrinted));
#endif // QT_NO_PRINTER
}

void BrowserMainWindow::slotHandlePdfPrinted(const QByteArray& result)
{
    if (!result.size())
        return;

    QFile file(m_printerOutputFileName);
    m_printerOutputFileName.clear();
    if (!file.open(QFile::WriteOnly))
        return;
    file.write(result.data(), result.size());
    file.close();
} 

So what was actually added in Qt 5.7?

Two overloads of printToPdf() function for QWebEnginePage are here.

They allow to render page content into a PDF document.

Monday, May 16, 2016

QDir::listSeparator

In Qt 5.6 there is a new feature in Qt Core: QDir::listSeparator

    QChar QDir::listSeparator

It returns ';' on Windows and ':' on Unix systems, this is native path list separator, i.e symbol which separates paths in a list.

The aim of introducing this QDir::listSeparator is to replace possible ifdefs in your code and maintain good-looking code on various platforms.

Thursday, February 18, 2016

Google is closing Picasa

On February 12, 2016 Google announced that it is closing Picasa from March 15, 2016. Picasa Web Albums will be closed from May 1, 2016.

Here Google says that:

> The API will still support other functions, including reading photos, reading albums, reading photos in albums, and uploading new photos. Although these operations will continue to be supported and the protocol will remain the same, the content included in the responses and the operation behavior may change. We'll update the documentation on this site with specifics on the changes in March.

Picasa Web Albums will be replaced by Google Photos, a photo and video sharing service of Google.

Since we are using Picasa Web Albums in our free product Wallpaper Updater, we announce we will still support Picasa as long as Google will support reading albums and photos from albums.

Next versions of Wallpaper Updater will also support Google Photos and Flickr. If you have any suggestions or questions about Wallpaper Updater functionality, please share them here.


Saturday, February 6, 2016

Debugging of NUnit tests in Visual Studio

If you using NUnit 2.6 version, you may have a problem with debugging your tests in Visual Studio in case your target framework is .NET Framework 4.0 or 4.5. Here is the simple way to solve this problem.

In NUnit 2.6.x\bin\ folder there is a file nunit.exe.config. It has the following structure:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <!--
   The GUI only runs under .NET 2.0 or higher. The
   useLegacyV2RuntimeActivationPolicy setting only
   applies under .NET 4.0 and permits use of mixed
   mode assemblies, which would otherwise not load
   correctly.
  -->
    <startup useLegacyV2RuntimeActivationPolicy="true"> 
    </startup>
    <runtime>
        <!-- Ensure that test exceptions don't crash NUnit -->
        <legacyUnhandledExceptionPolicy enabled="1"/>
        <!-- Run partial trust V2 assemblies in full trust under .NET 4.0 -->
        <loadFromRemoteSources enabled="true"/>
        <!-- Look for addins in the addins directory for now -->
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <probing privatePath="lib;addins"/>
        </assemblyBinding>
    </runtime>
</configuration>
To enable debugging of tests for .NET Framework 4.0 and 4.5 you need to modify this config file (admin privileges are required for that since it is in Program Files):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <!--
   The GUI only runs under .NET 2.0 or higher. The
   useLegacyV2RuntimeActivationPolicy setting only
   applies under .NET 4.0 and permits use of mixed
   mode assemblies, which would otherwise not load
   correctly.
  -->
    <startup useLegacyV2RuntimeActivationPolicy="true">       
        <supportedRuntime version="v4.0.30319" />
    </startup>
    <runtime>
        <!-- Ensure that test exceptions don't crash NUnit -->
        <legacyUnhandledExceptionPolicy enabled="1"/>
        <!-- Run partial trust V2 assemblies in full trust under .NET 4.0 -->
        <loadFromRemoteSources enabled="true"/>
        <!-- Look for addins in the addins directory for now -->
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <probing privatePath="lib;addins"/>
        </assemblyBinding>
    </runtime>
</configuration> 
That's all, after this modification you will be able to debug the tests in Visual Studio.

Tuesday, December 22, 2015

Reverse Iterators in Qt 5.6

Reverse iterators are among new features of Qt 5.6 release (Qt 5.6 beta was released last week). Now they are supported for all Qt sequential containers (QList, QLinkedList, QVector, QStack and QQueue).

If we look at C++ standard library and its sequence containers (array, vector, list, forward_list, deque) we will notice that these containers support both iterators (begin, end) and reverse iterators (rbegin, rend). Well, ok, except forward_list, special alternative to list when reverse iteration not needed.

Now we will solve a simple task like iterating a QList backwards with a new means available (similar to this http://stackoverflow.com/questions/16441447/iterating-over-a-qlist-backwards):
#include <QCoreApplication>
#include <iostream>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QList<int> list = {1, 2, 3, 4};
    QList<int>::const_reverse_iterator cIter;
    cIter = list.crbegin();
    while(cIter != list.crend()) {
      std::cout << *cIter << std::endl;
      ++cIter;
    }
    return a.exec();
}

Output from this program is: 4 3 2 1

QList::crbegin() points to the first item in the list in the reverse order. It returns const_reverse_iterator.

QList::crend() points to the last item in the list in the reverse order. It also returns const_reverse_iterator.

reverse_iterators and const_reverse_iterators are working well with auto C++11 keyword. Here is the example:

#include <QCoreApplication>
#include <QVector>
#include <iostream>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QVector<int> qVector = {1, 2, 3, 4, 5};
    for (auto it = qVector.rbegin(); it != qVector.rend(); ++it)
    {
        std::cout << *it << std::endl;
    }
    return a.exec();
}
As you may guess, the output from this simple program is: 5 4 3 2 1