@@ -0,0 +1,2086 @@
+#!/usr/bin/env python3%0A%0A%22%22%22 Generate a %22loading%22 or %22waiting%22 animated gif. %22%22%22%0A%0Aimport math%0A%0Aimport PIL.Image%0Aimport PIL.ImageDraw%0A%0ASIZE = 16%0ATOTAL_DOTS = 8%0AVISUAL_DOTS = 4  # how many dots are visible in each frame.%0ADIAMETER = SIZE / 8.0%0ASECONDS = 1.25  # how long it takes to do a complete cycle.%0AOUTPUT = %22loading.gif%22%0A%0A%0Adef draw_dot(draw, i, color):%0A    %22%22%22 Draw a dot around a circle with a color. %22%22%22%0A    # Positions around the big circle.%0A    unit_x = 1 + math.sin(i/TOTAL_DOTS * 2*math.pi)%0A    unit_y = 1 - math.cos(i/TOTAL_DOTS * 2*math.pi)%0A%0A    # Scale to the desired size and circle diameter.%0A    x = round(((SIZE - DIAMETER)/2 - 1) * unit_x)%0A    y = round(((SIZE - DIAMETER)/2 - 1) * unit_y)%0A%0A    # Center the pixels for the library.  (Doesn't appear to have%0A    # any effect at 16x16, but might possibly matter if we add%0A    # some kind of filter.)%0A    x += 0.5%0A    y += 0.5%0A%0A    # These are drawn as rectangles in a 16x16 image, but if we%0A    # increase the size then they're circles.%0A    draw.ellipse((x, y, x + DIAMETER, y + DIAMETER), fill=color, width=1)%0A%0A%0Adef draw_frame(framenum):%0A    %22%22%22 Draw a frame of the animation. %22%22%22%0A    # Create new image and drawing surface.%0A    image = PIL.Image.new('LA', (SIZE, SIZE), (1, 255))%0A    draw = PIL.ImageDraw.Draw(image)%0A%0A    # Draw the dots.%0A    for i in range(VISUAL_DOTS):%0A        pos = ((framenum - i) %25 TOTAL_DOTS)%0A%0A        # The Qt background is (239,239,239) so this fades from 0%0A        # to 240 (but stops at 180).%0A        gray = round(240/4*i)%0A%0A        draw_dot(draw, pos, (gray, 0))%0A    return image%0A%0A%0Adef main(filename):%0A    %22%22%22 Generate the animation and save it to the filename. %22%22%22%0A    # Generate frames.%0A    images = %5B%5D%0A    for framenum in range(TOTAL_DOTS):%0A        image = draw_frame(framenum)%0A        images.append(image)%0A%0A    # Write gif.%0A    images%5B0%5D.save(filename, save_all=True, append_images=images%5B1:%5D,%0A                   duration=SECONDS / TOTAL_DOTS * 1000,%0A                   loop=0,%0A                   transparency=1,%0A                   disposal=2)%0A%0A%0Aif __name__ == %22__main__%22:%0A    main(OUTPUT)%0A

Add script to generate the "loading" animation