App icons

This will explain app icons and how to create them for Linux apps.

It is mostly about the icons used in the desktop metaphor, to represent apps and the documents that apps create/understand.

This blog is a log of many websites I visited, tilting at windmills, trying to make sense of ever changing chaos.

App icons defined

App icons are a set of icons (AppIconSet) that represents an app and its documents to a user of an OS that uses the desktop metaphor.

An AppIconSet can be an improper set: having only one image.  The same image CAN be used for AppIcons and MimeTypeIcons. A user can usually distinguish the two uses: in one use the icon has the app name beneath it, and in the other use, the icon has a document name beneath it.  This gets into politics, when  an app and the mimetypes it creates are proprietary, the same icon could be used, but once the mimetype becomes a standard, one app should not put its icon on documents.

Icon meaning

One definition of the word icon is: an image that represents.

In this context, an icon as a displayed image means a bitmap image, and a smallish one, a few centimeters, and a few tens of pixels in resolution.  Icons as displayed may be generated from vector graphic images.  It is important to distinguish icon as a source file of displayed images.  This post itself does not always keep the distinction clear.

A quick summary is: modern OS’s and their desktops need a scaleable image as a source file of displayed image icons.  That is, SVG is built into the OS and desktop.  ‘Modern’ means in the last few years.  SVG in KDE describes KDE’s new support for scaling icons.

User Interface Guidelines

These documents are mostly about graphic designing icon images, with some mentions of responsibilities for app installations.

Apple’s guidelines for app icons

Gnome’s guidelines for app icons

Icon Subclasses

Icon subclasses:

  • FreestandingIcons: higher resolution, more realistic
  • WidgetIcons

WidgetIcon subclasses:

  • ToolbarIcons: in toolbars, simplified (outline)
  • SidebarIcons: in sidebars, simplified (outline), and invertible
  • Button icons: in buttons, having images for states of the button

FreestandingIcons subclasses:

  • AppIcons: applications
  • MimeTypeIcons: documents, with badges
  • PlaceIcons: disk, trash, Web, etc.

These are subclasses in the sense that the behaviour is different, at least to a user, if not to a programmer.

In this document, I use app icon to mean AppIcons and MimeTypeIcons: the installation of a document viewing or editing application is often responsible for both (when an app establishes its own mimetype.)  But I am excluding WidgetIcons, the icons that an app uses internally, that is, the icons that an app provides as resources for its own toolbars, sidebars, and other widgets.

AppIcon and MimeTypeIcon images can share drawing elements or motifs:

  • for branding purposes, in the case of proprietary apps
  • as a user interface strategy to show relations between an app and the documents it creates or understands

For example, the same motif of a music note can appear in related AppIcon and MimeTypeIcon.

App icons and GUI Frameworks e.g. Qt

It is NOT the responsibility of the framework to provide FreestandingIcons; that is the responsibility of the packaging.

In Qt, QWindow.setWindowIcon() puts a ToolbarIcon in the window’s title bar.   This is for main (top) windows only, so that in an application that has many top windows, a user can know which app the window belongs to? This is the responsibility of the app.  This is optional, since the text of the titlebar may serve the same purpose?

Qt has other functions for getting WidgetIcons, including ‘standard’, cross-platform icons, and themed icons.  (Beyond the scope.)

App icons as sets

OS’s usually require OR allow (of a program to be installed) a set of icon images, at different resolutions (and corresponding use in different displayed real sizes.)

It would be nice if an OS required only one icon image and generated displayed icon instances of different resolutions.  To some extent, this is possible.

However, to algorithmically generate low resolution images, i.e. icons or thumbnails, from high resolution bitmaps, is a hard problem in computer graphics algorithms.  (Search under “summarizing visual data”.)  Also, much has been written (enough to clog the search for the topic of this post) about how to manually create an icon set of bitmaps, tweaking pixels of each icon.

It is NOT so a hard problem to generate low resolution bitmap images from scalable images, and this is what modern OS and desktops do.

OSX accepts icons in PDF and generates icons of higher resolution from them.

The Freedesktop org spec for icon themes also specifies (vaguely) how to use scalable graphics for icons.

The requirement for a set (of displayed bitmaps) is a user interface design issue:

  • freedom for users to choose a size
  • comfort for users, when higher resolution and larger size lets them recognize an icon (it fails as an icon if the user doesn’t recognize it.)

The requirement for a set is also a business and software system issue:

  • provided as a service at installation time by a software package to a package manager client
  • provided as a service by a package management system to desktop browser clients

Who is responsible for creating the set, especially from a single scalable image?  Recently, the answer has become: the OS and desktop are responsible for generating the set from a scalable image that you provide in the install package.

Vector graphics and icons

Scaleable vector graphics (SVG and PDF formats are both scalable) scale without loss of resolution.  However, an SVG and PDF file may contain (embed) a bitmap image that won’t scale without loss of resolution.  When a spec for icons says scalable graphic image, do they mean one with embedded bitmap?  I don’t think so.

When a spec for icons says a scalable graphic image of a certain size (say 64×64) , why the size requirement?  I think that is overspecifying.  After all, scalable means it can be rendered in any size.

What size icons does each Linux platform require in an icon set?  Icon Themes

Debian is not concerned with AppIcons.  They are only a concern of desktops.

The Freedesktop organization document entitled “Icon Theme Specification” defines the minimum requirements.  It is a ‘pseudo’ standard, a convention.

A user thinks of a theme like a graphic designer, and that document is largely about that kind of ‘theme’.  But the document describes a ‘default theme’ (name ‘hicolor’.)   An IconSet is a component of a theme, so this document describes the minimum requirement for app icons:

So, you’re an application author, and want to install application icons so that they work in the KDE and Gnome menus. Minimally you should install a 48×48 icon in the hicolor theme. This means installing a PNG file in $prefix/share/icons/hicolor/48×48/apps.

But it also vaguely talks about SVG files in this and other directories.

But the two competing desktops: Gnome and KDE, and value-adding distributors such as Ubuntu, may have further requirements.

Loading and installing icons in KDE

How does Ubuntu use the different sizes of icons?

The different sizes are used by different utility apps of the desktop (Launcher, Dash, Ubuntu Software Center, Nautilus).  But this doesn’t mean you as a packager must provide the icon set.

(I don’t know where a requirement is strictly specified.)

A brute force strategy for creating an icon set

If your goal is: a crude AppIconSet that works on most Linux platforms, even older distributions, then you can adopt this strategy:

  • create a scalable image that is is very simple, an outline and contours, black and white image
  • generate the set of icon bitmaps in resolutions (sizes) that covers all the platforms: 16, 22, 32, 48, 64, 128
  • put those icons in your package

You can use Inkscape for both creating the scalable and bitmap images.

You might use this strategy if you are very concerned about the quality of your displayed icons.

A simple,  modern strategy

If your goal is: the minimum work on your part to get some icon representing your app on the desktop:

  • create an SVG image (e.g. using Inkscape).
  • put that image in the default icon theme at /usr/share/icons/hicolor/scalable

The units and value of the size of the SVG image doesn’t seem to matter, but at least in Inkscape, the size DOES matter in this way:

  • your drawing should fill the size and be contained in the size
  • the shape should be symmetrical (e.g. a square or a circle)

(I think this is a flaw of Inkscape or the OS that displays the SVG as an AppIcon: the size of the area that the drawing elements cover (the bounding rect) should be determined at rendering time, not specified in the SVG.)

Advertisements

Creating new mime types in a shortcut Debian packaging

A short tutorial about installing your proprietary app’s own, new mimetype via a shortcut Debian packaging (on Linux.)

This is not about registering your application for existing mimetypes that other applications also create and understand.

Wiki on mimetypes

About Automating

This note is about automating:  making the Debian package install your mimetype when a user installs.

This is for a shortcut packaging done by you for limited distribution.  If your app is in the main distribution channels (Debian or Ubuntu) than a packager person might be doing this for you, in a different way.

The web is clogged with posts telling user’s how to fix mimetype icons manually (when installing an app fails to do it automatically.)  Those posts are relevant.

Adding Mime Types on Ubuntu

Gnome Adding Mime Types

About Registering with the IANA

I don’t know the benefits of registering your mimetype with an international standards organization.  I presume you may just start using a new mimetype, and register it when it becomes popular.  You might want to search the IANA site to see whether your mimetype is truly new (not registered by someone else.)

About mimetypes and file extensions on Linux

A mimetype is a Type in the object oriented sense.  A file instance has the type, meaning the file behaves a certain way under certain operations (mainly, reading by the owning application.)

The fact that the file has a certain type is not necessarily:

  • labeled on the outside of the file,  in the filename extension e.g.  ‘.bmp’
  • nor  in a header in the contents of the file (e.g. first three bytes ‘BMP’)
  • nor in separate metadata (resource fork?) associated with a file.

Linux actually uses a combination of those to determine a file’s mimetype.  Other OS’s differ.

Relationship between file extension and mimetype on Linux

The process

Overview:

  • define a mimetype: tell the OS how to recognize files having the mimetype
  • associate an icon: tell the OS what icon to display for said mimetype
  • register your application for the mimetype: tell the OS desktop what application understands the mimetype (what app to launch when a file is clicked.)

For this example:

  • application name: ‘helloworld’
  •  file extension: ‘.hlw’
  • mimetype name: ‘application/hlw’

Define a mimetype

In your Debian template directory create:  /usr/share/mime/packages/helloworld.xml.  (This will be copied to the computers’s filesystem at install time.)

(The name need not be helloworld.xml, as long as it is unique.  The OS reads all the XML files in this directory, no matter what they are named.  The contents of the XML file must match the mimetype.  It might be that the suffix of the file need not even be .xml, since the mimetype of the file: text/xml, might be determinable by the function in the OS that is reading them even without the suffix.)

<?xml version="1.0" encoding="utf-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
  <mime-type type="application/hlw">
     <glob pattern="*.hlw"/>
  </mime-type>
</mime-info>

Here:

  • ‘application/hlw’ is the name of the mimetype.
  • ‘.hlw’ is a filename extension that helps the OS recognize files having the mimetype

The second half of the mimetype name need not match the filename extension, but it usually does?  There might be other ways to get the OS to recognize files having a mimetype, for example, patching the algorithms used by the OS.  (Beyond the scope of this tutorial.)

Here, you might be able to substitute for ‘application’, for example ‘image’ or ‘text’.  The word ‘application’ might imply that the file is binary versus text?  If the OS thinks your file (before creating the mimetype) is of mimetype ‘application/octet-stream’?  (Beyond the scope of this tutorial.)

If you are doing this manually, create this file then run the command ‘sudo update-mime-database /usr/share/mime’.  But the installer should trigger this automatically at install time (or at computer restart.)
 

Associate an icon

Now  associate an icon with the MIME type. Create an SVG icon.   Name it “application-hlw.svg”  Note that the name of the file matches the mimetype name with slashes replaced by “-” and there are no capital letters.

Put the file in this directory in your Debian template directory:

/usr/share/icons/hicolor/scalable/mimetypes/application-hlw.svg

Here, hicolor is an icon theme, the default one for both Gnome and KDE. (Beyond the scope of this tutorial.)

Register your application for the mimetype

In your application’s desktop file at the following location in your Debian template directory:

/usr/share/applications/helloworld.desktop

Add this line:

MimeType=application/hlw

Testing

Rebuild your debian package, click on it, and choose ‘Reinstall’ (or similar.)

Test that:

  • in a file browser, a file created by your app displays your icon
  • when you click on the icon or file name, your app starts

Proprietary Python, PyInstaller apps using libraries licensed under LGPL

The LGPL lets your proprietary app use LGPL libraries as long as you (among other things) let users ‘recombine your software with modified libraries.’  The LGPL says you must provide ‘object code’ for your app.  (So users can keep using your proprietary software even as the libraries are improved, by bug fixes and other improvements.  So your proprietariness is not impeding progress in the libraries: users won’t be motivated to improve the libraries if they can’t use the improvements in their context.)

What if your app is interpreted Python, packaged with PyInstaller (or other freeze tool?)

PyInstaller bundles:

  • a bootstrap loader (dynamic)
  • the Python interpreter (executable, compiled to platform’s machine code)
  • executable  LGPL libraries (say, Qt and PySide)
  • other LGPL .pyc modules
  • your app’s .pyc files ( ! it doesn’t use the .py, this is a gotcha for naive PyInstaller users)

(What follows is supposition…)

Then you meet the terms of the LGPL since the way that PyInstaller bundles is well documented.  A motivated user could ‘recombine’ your software with modified libraries, by punching the libraries out of the PyInstaller bundle and filling the hole with new libraries. Or equivalently, extracting your proprietary object code and relinking (re-PyInstaller-ing) it with updated LGPL libraries.  I’m not sure what tools are available to do it, or whether the LGPL requires a tool to be available.  It might be that the LGPL requires you to ‘convey’ your app’s proprietary code as a directory tree of .pyc files?

In this case, both the executable LGPL libraries and the LGPL .pyc modules are ‘object’ files as defined by the LGPL.

Your proprietary code in the bundle is .pyc, which can be reverse engineered (but so can proprietary object code that is compiled real machine code.)  Distributing a directory tree of .pyc goes a long way in revealing your proprietary object model.  About the only ‘information’ omitted from they object .pyc code are the docstrings and other comments, which probably include your tests (which are a redundant specification of your program.)

A short Debian packaging case: GUI apps, GPL, PyInstaller

This is generally about Debian packaging.

It is specialized for a program that is:

  • an app (not a utility or a server)
  • a Python app frozen with PyInstaller
  • an app that creates documents with its own mimetype
  • a GUI app that uses the desktop metaphor
  • uses some open source software (GPL), but is itself proprietary

The goal is a Debian package which:

  • passes the lintian test and will install on most Linux distributions.
  • conforms to requirements for the desktop metaphor
  • protects your copyright and fulfils some of your obligation under GPL and LGPL

The goal is NOT a package that the Ubuntu or Debian organizations will necessarily accept for distribution.  In particular:

  • it will be missing  the changelog.
  • those organizations might prefer a traditional Linux packaging not using PyInstaller (and therefore smaller in size.)
  • those organizations prefer free software

Flaws in this post

This post is a work in progress… these things don’t work:

  • the copyright file in the debian input directory doesn’t work using these methods
  • When you click on the .deb package the installer opens and offers to install, or reinstall, and does succeed in installing.  However, later the installer (e.g. Ubuntu Software Center) fails to recognize the installed app IS installed (fails to offer to remove it).

Similar tutorials

How to create a basic .deb  (too simple, for a command line app)

Ubuntu Packaging Guide (too complex, for an app to be distributed in Ubuntu channels.)

Debian New Maintainers Guide (too complex, for packaging specialists.)

Deploying Proprietary Java Software on Ubuntu Linux most similar to this post (but it omits discussion of copyright and licensing, by a company that sells licensing software!)

Tools

We will use these command-line tools:

  • dpkg-deb  (the ‘packager.’)
  • dpkg  (the installer)
  • lintian (checks packages)
  • fakeroot

They are available free.  Just try to use them: if they are not installed, you will get a message that tells you how to install them.  Use your package manager (e.g. Ubuntu Software Center, or apt-get) to install them.

What the Debian packager does

The packager reads a directory of files ( the ‘input directory’) and produces a single package file ( .deb) which an package manger (installer) will read to install your app.

So the larger ‘packaging process’ is mostly creating the input directory.

The structure of the input directory

The input directory contains:

  • a subdirectory (DEBIAN) that controls the packager (also called metadata: data about your app)
  • a subdirectory (e.g. usr/share) that is a template of the installation on the target computer

The root of the directory is named the same as the package.

Details of the debian directory.

Naming a package

Debian package naming conventions (see section 7.3)

Example input directory

helloworld_1.0-1/
helloworld_1.0-1/DEBIAN
helloworld_1.0-1/DEBIAN/control
helloworld_1.0-1/usr/share/bin/helloworld.exe 
helloworld_1.0-1/usr/share/applications/helloworld.desktop
helloworld_1.0-1/usr/share/mime/packages/helloworld.xml
helloworld_1.0-1/usr/share/icons/hicolor/48x48/apps/helloworld.png
helloworld_1.0-1/usr/share/icons/hicolor/scalable/apps/helloworld.svg
helloworld_1.0-1/usr/share/icons/hicolor/scalable/mimetypes/application-hlw.svg
helloworld_1.0-1/usr/share/pixmaps/helloworld.png ** I think this is unnecessary, a fallback for older versions helloworld_1.0-1/DEBIAN/copyright ** Currently I can't get this to be recognized by dpkg-deb

Explanation of the example input directory

The DEBIAN subdirectory controls the packager.

Everything else below the root is a template.  (After your app is installed, all those files will exist on the target computer.)

In this example, there is only one executable file (…/bin/helloword.exe) since PyInstaller has hidden (bundled, or put in a self-extracting archive) the dependencies.

The control file

Package: helloworld
Version: 1.0-1
Section: Applications/Graphics
Priority: optional
Architecture: i386
Depends: 
Maintainer: John Doe <jdoe@example.com>
Installed-Size: 10000
Description: Classic example program doing nothing important! (synopsis)
 (Extended description) No dependencies or significant conflicts.
 Each line starting with a blank is part of a paragraph.
 This variation of helloworld creates a file with mimetype foo.

Note, ‘Depends’ is empty because PyInstaller has bundled the dependencies (subverted the usual Linux install strategy.)

Installed-Size is just an estimate, in kb, so a user can decide whether to install.

I think the architecture is i386 since PyInstaller includes a bootstrap loader compiled for this architecture?  The architecture ‘any’ would be for pure Python and Java apps, packaged in a different, non-shortcut way.

Checklists

There is no concise document describing a Debian package checklist, but the lintian utility effectively defines the checklist.

It requires a copyright (license) file.

Lintian does not check for desktop integration.

The Gnome checklist for desktop integration.

The desktop file

A desktop file ‘registers’ your app with the OS.  Its the glue that makes your app work with the desktop metaphor.

The Gnome guide to desktop files, for developers explains it, but the same also works for other desktops (e.g. KDE.)

[Desktop Entry]
Type=Application
Encoding=UTF-8
Name=helloworld
GenericName=a sample application
Comment=display greeting
MimeType=application/hlw
Exec=helloworld %f
Icon=helloworld
Terminal=false
Categories=Graphics;Application

Name: brand name e.g. Mozilla

GenericName: a noun, what kind or category of application e.g. web browser

Comment: a verb, a tooltip describing what app does for user e.g. surf web

MimeType: a string identifying a mimetype the app recognizes (reads) (so when a user clicks on a file, the app is a candidate for launching, i.e. ‘Open with.. ‘

The value for Exec and Icon are not absolute path names, so an OS uses a well-defined algorithm to search places for matching stuff. The package template puts that stuff in those places.

The %f in the Exec means the application takes a single argument which is a filename (necessary for click to open.)

Terminal: whether the app is launched directly, or launched from a terminal (console, which might display messages of interest to programmers.)

Files that define the mimetype

In the debian input directory, these files help to define a new mimetype (custom to your app):

  • helloworld_1.0-1/usr/share/mime/packages/helloworld.xml
  • helloworld_1.0-1/usr/share/icons/hicolor/scalable/mimetypes/application-hlw.svg

See Creating New Mimetypes in a Shortcut Debian Packaging

Also, the ‘MimeType’ field in the .desktop file associates your app with the mimetype.

The mimetype is only ‘defined’ on the installed on computer, not permanently defined in the sense that most of the world understands it.

The Icons

See a forthcoming post: App icons for Linux apps.

The copyright file.

See a forthcoming post: a Debian copyright file for a proprietary app using LGPL components

Building the package

>fakeroot dpkg-deb --build helloworld_1.0-1

That creates the file helloworld_1.0-1.deb, the package.

Checking the package

On a command line:

>lintian helloworld_1.0-1.deb

Pay particular attention to errors (lines beginning with ‘E’).

Common errors:

  • wrong-file-owner-uid-or-gid : you didn’t use fakeroot
  • unstripped-binary-or-object: you should have used the -s option to PyInstaller *
  • no-copyright-file: TODO
  • description-starts-with-package-name: you don’t need your apps name leading the description
  • backup-file-in-package: your editor left a hidden backup file that you should delete else it will be installed.
  • non-standard-dir-perm usr/ 0775 != 0755: I don’t understand, they look equal to me?

* using strip on the PyInstaller output is NOT correct.

Lintian does not check conformance to the Gnome checklist for desktop integration.  It will gladly assume that your app is a command line app.

Some documents say the Debian organization requires a man page, but lintian calls it a warning, not an error.

Note that errors are not necessarily fatal to an install.  For example, I have an unstripped binary, but it does install.

Iterating

Repeat:

  • futz with the input directory (structure or content files)
  • build the package
  • check the package

Until lintian reports no errors (warnings are OK.)

Actually installing

In a file browser, double click on the .deb file.  A package manager will start, for example Ubuntu Software Center.

Since this example is all about user-friendliness, you should do it this way (graphically) since that is what many users will do.  It might reveal other errors.

However, alternatively, on a command line:

>sudo dpkg -i helloworld_1.0-1.deb

The installer (dpkg) installs your app (moves the components of your app from the package to their place in the file system, does other initialization of the installation.)

Errors in installation

In one of my tests, Ubuntu Software Center showed a warning dialog saying “The package is of bad quality” and giving details ‘The package doesn’t provide a valid Installed-Size control field. See Debian Policy 5.6.20.’   This for a package that had passed lintian (except for the copyright) and which dpkg invoked from the command line did not complain about.

Testing the installation

At a minimum (for this example) your program’s icon should appear in your launcher (e.g. Ubuntu Dash.)

Complete testing is beyond the scope of this tutorial but would follow the checklists cited above.

Testing uninstall

Graphically:

  • Start the Ubuntu Software Center
  • Open the ‘All Software’ tab.  (It might not appear under the ‘Installed’ tab?  A problem in the package shown above? )
  • Enter your app name e.g. ‘helloworld’ in the search widget.  Your app should appear in the main view (a list of one item.) **
  • Select your app.  A ‘Remove’ button should appear.
  • Click the Remove button.  After a short wait, the ‘Remove’ button dissappears.

Note that Ubuntu now has forgotten the location of the package that you originally gave to install.

** I can’t get this to behave consistently.  For some reason, USC doesn’t show my app as installed, even though USC installed it without complaint and the app shows in the Dash.

However, alternatively, on a command line:

>sudo dpkg -r helloworld

Here you use the name of the app, not the name of the package file with suffix .deb .

A simple Debian packaging that wraps a Pyinstaller binary

Suppose you want to create an installer for the Linux platform for an app that you created using PyInstaller.  Your concern is user friendliness.

This is about the process in general.   (I intend to publish a followup with the specifics.)

A similar tutorial about short-cutting Debian packaging, is about a command line app, and not user-friendly.

This post is about getting your foot in the door: publishing an app outside the main channels of distribution, but that installs in a user-friendly way .

See also Strategies for packaging Python apps on a Linux platform

The ancient sense of ‘install’ software

It’s not user-friendly.  A user deeply understands the process of installing, and the OS.  The user uses a command line in a terminal or console.   The user downloads a binary and fiddles with system directories to copy the executable to some ‘bin’ directory.  The name of the program file is the command to execute it.  The app has no visual icon, no aliases.

Worse, ‘install’ could mean: download source code, compile it, and THEN install the binary.  That’s not necessarily hard: it is often reduced to three commands: .configure, make, and make install.  But that sometimes is a trip to ‘dependency hell’.  And it often yields only a command line app.

The modern, user-friendly sense of ‘install’ software

  • a user clicks a ‘Download’ button in a web page to start the process
  • the download automatically uncompresses itself (unzips) to a ‘package’ (a specialized archive of component files)
  • an installer automatically starts, or starts when a user clicks on the downloaded ‘package’
  • your app will be “integrated with the desktop”, that is, have a clickable icon in the usual places.
  • the OS will remember how to uninstall the app

Self-installer

A file that  installs an app.  The file is executable, and usually clickable to run.  A self-installer is both an ‘installer’ and a ‘package.’  As a file it comprises :  an installer and the package it installs.  When it runs,  its installer installs the package (which may involve uncompressing and unarchiving the package as well as other installing subprocesses.)

An app has resources

Resources are non-executable objects that an app needs to run, for example images (icons, etc.) and sounds.

Resources are packaged with the executable of an app.

Resources needed for packaging include:

  • resources the app needs to run (run resources)
  • resource the installer needs to install the app (install resources), the most important of which is the ‘app icon’

For command line apps, install resources might include man pages.

More generally, install resources are the objects that a user and the OS expects for a ‘well-behaved’ program.  What ‘install resources’ comprises, depends on the sophistication of the user and the OS.

PyInstaller is NOT an installer

As discussed in the PyInstaller FAQ

No, despite its name (which has more to do with its historical roots), PyInstaller is used to transform a Python program into a native executable form which does not require existing Python installations to run. Building an installer program is totally outside the scope of PyInstaller.

PyInstaller produces a binary with no dependencies.  A user can ‘install’ it in the ancient sense,  but no in the modern, user-friendly sense.  One goal of PyInstaller is to avoid ‘dependency hell.’

PyInstaller deals with run resources, but not install resources.

Package management

Package managment means the apps (tools) a user (in the system administrator role) uses to install and otherwise manage applications (more generally, software.)

A tutorial on RPM and YUM package management

A tutorial on Debian package management

There are competing ways of packaging and package management in the Linux world

There is no consensus, no standard.  Alternatives:

  • Debian packaging
  • RPM packaging
  • YUM packaging

Some Linux distributions understand several of the alternatives.

The Linux packaging process is hard

It’s for artisans, cognesceti, wizards.

This Debian packaging tutorial gives you the flavor of how hard.

But that is for programmers who want to become part of the community, or want their application to enter the mainstream of the community.

This post is about getting your foot in the door: publishing an app outside the main channels, but that installs in a user-friendly way .

Debian packages are clickable but not self-installers

Most Linux OS distributions understand Debian packages and start an installer when a Debian package file (.deb) is clicked.  For example, on Ubuntu, the ‘Ubuntu Software Center’ starts.

The Linux standard for well-behaved, desktop apps

The FreeDesktop organization promulgates ‘pseudo’ standards for this.  They don’t enforce them.

On Windows and OSX, corporations set and enforce the standards.

For our purposes, the Desktop Entry Specification  is pertinent.  It is about how the OS presents your app to the user, or program shortcuts (clickable icons.)

The Debian standard for packages

The Debian community is concerned with Linux as a command line OS, not with the desktop metaphor.

The Debian Policy Manual specifies the standard, and there is no concise specification.  You must read that document, looking for “package .*must have”.  That document doesn’t always tell you the consequences (for installing) of failing the requirements.  For example, it says if the man page is missing, it is considered a bug, but the package will still install.

Much of that document is concerned with version and dependency, that is, stuff a package manager needs.

Much of that document is concerned about ‘run resources’: bundling what the app needs.

From a brief skim, these ‘install resources’ are required:

  • a man page
  • a copyright and license

Next (Coming soon) : Creating app icons and desktop entries for Linux

Next (Coming soon): A shortcut Debian packaging process

Understanding Qt’s QUndoStack: clean and clear

“Clean” and “clear” are separate but related classes of states.

The clean state has getter isClean() and setter setClean().

The clear state has getter: count() <= 0, and setter clear().  (The getter method is not defined by Qt, but let’s name it “isClear”.)

“isClean” does not imply “isClear”.  A clean undo stack may still have commands that can be redone/undone.

“isClear” implies “isClean.”  A clear undo stack does not have any commands on it.

Typically, when you save a document (or open an existing one), you call clear().  At that point, your app behaves just as if the user newly opened the document: there is nothing to undo or redo.

Subsequently, if the user does something, but undoes it, the document is “clean”.  That is, in the same condition as is saved.  Typically, an app shows the unclean state in the title bar, for example by an asterisk in front of the document name.