CopperSpice Experiments – Pt. 17

I’m putting this here because I discovered it while trying to fix a rather horrible “busy” dialog in the Advanced Search portion of Diamond. I had to create a GUI “Hello World” application to test this out so I could file a “simple” bug report. According to the doc animated GIF is supported on all platforms. The code for Linux is a tad behind the documentation.

#include <QApplication>
#include "mainwindow.h"

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

    MainWindow *mw = new MainWindow();

    mw->show();

    return a.exec();
}
#include <QMainWindow>
#include <QMainWindow>
#include <QLabel>
#include <QVBoxLayout>
#include <QMovie>
#include <QByteArray>

class MainWindow : public QMainWindow
{
    CS_OBJECT( MainWindow )
public:
    MainWindow( QWidget *parent=0 );
    ~MainWindow();

private:

    QLabel         *m_hello;
    QLabel         *m_movieLabel;
    QVBoxLayout    *m_layout;
    QWidget        *m_widget;
    QMovie         *m_movie;

};
#include "mainwindow.h"

MainWindow::MainWindow( QWidget *parent ) :
    QMainWindow( parent )
{
    qDebug() << "supported formats: " << QMovie::supportedFormats();

    m_hello         = new QLabel( "Hello World!" );
    m_movieLabel    = new QLabel();
    m_movie         = new QMovie( "://animations/spinning-red-diamond-4.gif" );
    m_layout        = new QVBoxLayout();
    m_widget        = new QWidget();

    m_movieLabel->setMovie( m_movie );

    m_layout->addWidget( m_hello );
    m_layout->addWidget( m_movieLabel );

    m_widget->setLayout( m_layout );

    setCentralWidget( m_widget );
}

MainWindow::~MainWindow()
{
    delete m_widget;
    delete m_layout;
    //delete m_movie;
    //delete m_movieLabel;
    //delete m_hello;
}

When I build and run this on Ubuntu 20.04 LTS I see the following:

No supported formats

A sad sad day indeed.

What this means is the cool animated GIF Icons8 let me create now has to be busted up into frames. Well fine. I just didn’t have anything to do that installed on this system and didn’t want to take the time to learn how to do it in some graphics package because the odds of me having to do it again were slim to none.

A bit of Web searching turned up a really cool site. I didn’t bother to read any of their retention policy, etc. because this was something OpenSource I generated at Icons8. If you have some trade secret images then you have to read that or not use the site.

ezgif.com

Once you upload you choose your split options and apparently can do other things.

after upload

Once you click the split button you are quickly greeted with the following:

After split

What is really cool is how they name the files inside of the zip.

files inside of zip

They provide you the decimal number of seconds for each frame. This means you can easily set up your millisecond driven timer. If your brain happens to be too thick to slide the decimal on its own you can just key in

milliseconds to seconds

for the DuckDuckGo search term and you are greeted with:

converter

So, I unzipped into a directory I created called image-work-4. Now I need to fix the file names. I want to get rid of the delay time and prepend “red_diamond_”. In a terminal I cd to the directory and type the following:

rename 's/_delay-0.11s//;' *

This leaves me with a bunch of frame_nn.gif files. There are probably cleaner ways to do the prepend, but here is what I did.

find -L . -type f -name "*.gif" -exec bash -c 'echo "mv $0" "${0%/*}/red_diamond_${0##*/}"' {} \;

That outputs a list of mv commands having both file names with ./ in front of them. I didn’t even try to see if that would work. I just screen scraped them into an editor and replace “./” with “” then scraped the lines from the editor and pasted them into the terminal. After creating a directory underneath my project resources directory I copied in the files.

the files

Honestly I’m created this post because I want to remember the commands. No, rename isn’t a built-in Linux command. It is in the Ubuntu repositories though. That’s a command line ability not all platforms have.

Why am I doing this?

I want to finish this phase of the project. Creating your own animation out of a series of images is very old school. I’ve done it with earlier versions of Qt and even Zinc. It’s actually mandatory on systems without a GPU because most graphics libraries supporting animation require a GPU be present. All you need to know is the value to put in the timer. Every time it fires you move to the next image in the list. After the last image you go back to the first.

When you need to both block the UI and perform a potentially long running task, you toss up a modal dialog with some kind of QFuture or other thread mechanism. Ideally your dialog is frameless with a transparent background so it looks like just your animation is there. When your threaded task ends you connect its ending to the removal of the dialog. Don’t forget to kill off your timer.

<Previous-part Next-part>

CopperSpice Experiments – Pt. 15

I do apologize for the burstiness of these posts and sometimes skipping around. I don’t have much free time so I write these posts when something tends to piss me off or befuddle me. Today it was an animated gif.

I got that gif from Icons8. Yes, a site generating nice simple “loading” and/or “busy” animated gifs that are free to use and even has a little tool on the site that allows you to customize them before downloading is getting a plug. Just how cool is that?

So, I went the “standard” path of stuffing a QMovie into a QLabel like we’ve done for years in Qt. No love. Just a black box. This is when it hit me I was going to have to create a cs_gui_hello application. First I needed to verify I wasn’t suffering from old age and the effects of years of Chardonnay at night. I hop over to a Ubuntu 20.04 LTS machine and load whatever QtCreator was installed on it using whatever Qt version that it found.

Yes, many of you would just have a VM if you had that. I have multiple machines with multiple desks and some of the machines have multiple VMs. It’s how I roll. Honestly, it is because that is the way work comes in.

The tiger I bought when I was in college, deal with it. Whatever type of photography was in vogue then had a market and this looked cool. This is actually cleaned up office. Over the past year or so I’ve thrown out about four machines or so.

When clients want a custom Debian package that will install on N releases of Ubuntu but they are using high end features of library X so it can’t go in a Snap or any other low end container, you have to throw hardware at it. Finding the right combination of options and libraries to thread that needle can take weeks. It was even more fun when they wanted a .deb that would install on either 32-bit or 64-bit versions. Been there, done that, got the T-shirt.

So, first I need a GUI “Hello World” to verify what I believe to be true. After starting QtCreator I tell it to create a new project for me, Qt Widgets based. I put a File->Exit option on the main menu and endure the incredibly slow signal-slot editor connecting exit up to MainWindow::close(). I add two labels, one with “Hello World!” text and another big empty label I called movie_label.

Labels in the designer

Okay, I took the screenshot before I filled the menu in.

Took longer for this editor than the entire rest of the project

Adding a Resource File

This part is for the new people. Maybe you’ve only done QML so you don’t know Qt at all? Maybe you are new to the world of programming or just new to the world of Qt. I’m taking you down this detailed journey because even I had to poke a tiny bit. As more and more worthless (&()&* gets added to QtCreator (QML, Java, Python, etc.) it becomes harder and harder to find things.

Right Click and choose add new

I usually right click on the “Forms” in the window on the right. Theoretically you can right click on any of those entries for this. That wasn’t always the case or at least I remember a time that it wouldn’t work everywhere.

Resource file is underneath Qt
Add it to your project
After adding a prefix

I never like the default prefix. Half of the time I just enter “/” but this time I chose “/animations.” After that I choose “Add Files” then navigated to a series of gif files with different colors and speeds.

Save and close the resource file once you have added your images or whatever.

Note: Just about anything can be in your resource file. For this Diamond editor I’m working on I stuck HTML help files in there. You kids who’ve never been more than six feet from an Internet connection need to learn the concepts of air-gapped and stand-alone. Machines on air-gapped networks have no Internet access. If you want help, all of the help has to be installed with the editor/IDE/whatever. The same is true for stand-alone because those machines aren’t even on a network.

Our Application

The code

Code wise, there isn’t much. I have always been a bit perturbed about parenting of QMovie objects. You either have to provide an empty QByteArray for the format to parent one or you have to construct the object with just a parent then assign the movie in another step. It would seem the could provide a constructor having a non-optional first parameter of parent. What is important is the QDebug statement.

output of application

You will note that this installation pulled from the Ubuntu repos only supports gif. Why this is important will be the subject of my next post.

To play the video below on my Ubuntu 20.04 LTS desktop I had to issue the following from the command line.

sudo apt install libdvdnav4 libdvdread7 gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly libdvd-pkg ubuntu-restricted-extras

Some browsers have their own codecs and such so might play video just fine. I was trying to look at the video locally before uploading to the post. If you can’t see it, then I guess you know what to try. It will also prompt you to run this command once.

sudo dpkg-reconfigure libdvd-pkg
The test application running

<Previous-part Next-part>