Something New

Non release banter
Jack
Contributor
Contributor
Posts: 1857
Joined: 09 Aug 2013, 14:25
Distribution: Porteus and Nemesis
Location: USA

Something New

Post#1 by Jack » 18 Feb 2024, 00:32

I tried something new can some tell i I am wrong?

Code: Select all

LABEL GRAPHICAL
MENU LABEL Graphics mode
KERNEL /boot/syslinux/vmlinuz
INITRD /boot/syslinux/initrd.xz
APPEND changes=/porteus
APPEND changes=/mnt/sdb1/porteussave.dat
TEXT HELP
    Run Porteus the best way we can.
    Try to autoconfigure graphics
    card and use the maximum allowed
    resolution. If booting from a
    non-posix (FAT/NTFS) drive,
    see the Saving Changes Help
    below for how to save changes.
ENDTEXT
I just like Slackware because I think it teach you about Linux to build packages where Ubuntu is like Windows you just install programs you want.

User avatar
Ed_P
Contributor
Contributor
Posts: 8374
Joined: 06 Feb 2013, 22:12
Distribution: Cinnamon 5.01 ISO
Location: Western NY, USA

Something New

Post#2 by Ed_P » 18 Feb 2024, 05:05

Well, only the bottom changes= cheatcode will be effective and it will direct your Porteus changes to be written to a save.dat file in the root of a drive on sdb1. Is that your plan? The top changes= cheatcode will be ignored and the line should be deleted.
Ed

Jack
Contributor
Contributor
Posts: 1857
Joined: 09 Aug 2013, 14:25
Distribution: Porteus and Nemesis
Location: USA

Something New

Post#3 by Jack » 18 Feb 2024, 05:18

What I used to do is setup my new install Porteus the way I like it and save the changes-02-17- 2024.xzm file. But I seem I can't do that any more. I wish I could.
I just like Slackware because I think it teach you about Linux to build packages where Ubuntu is like Windows you just install programs you want.

User avatar
Ed_P
Contributor
Contributor
Posts: 8374
Joined: 06 Feb 2013, 22:12
Distribution: Cinnamon 5.01 ISO
Location: Western NY, USA

Something New

Post#4 by Ed_P » 18 Feb 2024, 06:15

Jack wrote:
18 Feb 2024, 05:18
But I seem I can't do that any more.
Why not? :%)

Added in 14 minutes 13 seconds:
This script works for me creating my network connection module.

Code: Select all

#!/bin/sh

if [ `whoami` != "root" ]; then
   echo -e "Enter root's password\033[1;31m"
   su -c "sh $0 $1"
   exit
fi
echo -e "\033[0m"; echo -en "\033]0;Make a Mod\a" 

#set -x;

if [ -d /tmp/mod/ ]; then
   rm -rf /tmp/mod
fi
mkdir -p /tmp/mod

cp -a -p --parents    /var/lib/NetworkManager/*                      /tmp/mod/
cp -a -p --parents    /etc/NetworkManager/system-connections/*       /tmp/mod/
ls -R                                                                /tmp/mod/
read

dir2xzm   /tmp/mod/                   /tmp/Dellautonet.xzm
rm  -rf   /tmp/mod/ && echo && ls -sh /tmp/*.xzm
read
Or are referring to the Porteus save-changes app?
Ed

Jack
Contributor
Contributor
Posts: 1857
Joined: 09 Aug 2013, 14:25
Distribution: Porteus and Nemesis
Location: USA

Something New

Post#5 by Jack » 18 Feb 2024, 07:01

@ed

I found the module and the name is Porteus Session Saver and it had the one in this version of Porteus Mate. I wish I new what the scripts are call I would add them to my Mate.
I just like Slackware because I think it teach you about Linux to build packages where Ubuntu is like Windows you just install programs you want.

User avatar
Ed_P
Contributor
Contributor
Posts: 8374
Joined: 06 Feb 2013, 22:12
Distribution: Cinnamon 5.01 ISO
Location: Western NY, USA

Something New

Post#6 by Ed_P » 18 Feb 2024, 07:15

In my Cinnamon system it is named save-session and is a python script in the /opt/porteus-scripts folder. Being python I believe it requires the 005-devel.xzm module to run.
Ed

Jack
Contributor
Contributor
Posts: 1857
Joined: 09 Aug 2013, 14:25
Distribution: Porteus and Nemesis
Location: USA

Something New

Post#7 by Jack » 18 Feb 2024, 07:48

Ed_P wrote:
18 Feb 2024, 07:15
In my Cinnamon system it is named save-session and is a python script in the /opt/porteus-scripts folder. Being python I believe it requires the 005-devel.xzm module to run.
I have 005-devel.xzm installed. I found save-session and ran it.

Code: Select all

guest@porteus:~$ su
Password: 
root@porteus:/home/guest# sh save-session
/usr/bin/save-session: line 9: import: command not found
/usr/bin/save-session: save-session: line 10: syntax error near unexpected token `'Gtk','
/usr/bin/save-session: save-session: line 10: `gi.require_version('Gtk', '3.0')'
root@porteus:/home/guest#
I just like Slackware because I think it teach you about Linux to build packages where Ubuntu is like Windows you just install programs you want.

User avatar
Ed_P
Contributor
Contributor
Posts: 8374
Joined: 06 Feb 2013, 22:12
Distribution: Cinnamon 5.01 ISO
Location: Western NY, USA

Something New

Post#8 by Ed_P » 18 Feb 2024, 18:08

Mine didn't work either but for a different reason than your's.

Code: Select all

guest@porteus:~$ save-session
You must be root to run this!
guest@porteus:~$ Save to file
Create a file
meta-data=/mnt/nvme0n1p7/Temp/porteussave.dat isize=512    agcount=4, agsize=32768 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=0 inobtcount=0
data     =                       bsize=4096   blocks=131072, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=1368, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
Create a file
Use existing file
x is 18
19
loop= /dev/loop19
Traceback (most recent call last):
  File "/usr/bin/save-session", line 345, in on_button1_clicked
    if has_space is False:
UnboundLocalError: local variable 'has_space' referenced before assignment
However, I can replicate your "import" error.

Code: Select all

guest@porteus:~$ 
guest@porteus:~$ import
bash: import: command not found
guest@porteus:~$ import
bash: import: command not found
guest@porteus:~$ su
Password: 
root@porteus:/home/guest# import
bash: import: command not found
root@porteus:/home/guest# 
And I do have the 005-devel.xzm module active.

Code: Select all

~#  ls -l /mnt/live/memory/images
000-kernel.xzm : Jan 14 04:14
001-core.xzm : Dec 28 22:50
002-xorg.xzm : Dec 28 22:56
002-xtra.xzm : Dec 28 22:58
003-cinnamon.xzm : Dec 29 00:05
05-devel.xzm : Feb 8 2022
07-printing-x86_64-2023-02-04.xzm : Feb 4 2023
Dell6.4.10-wifi.xzm : Aug 18 2023
Dellautonet.xzm : Dec 19 16:00
Dellsound.xzm : May 14 2022
firefox-122.0-x86_64-en-US.xzm : Jan 27 23:51
mychanges.xzm : Feb 18 02:38
Added in 20 minutes 27 seconds:
So, there is a bug in the save-session function but to get back to your situation Jack, you want a module with your changes added to the ISO you want to boot. Yes? An option you can do is create a save.dat file, make your changes, and reboot. Then rename your save.dat file to be save.dat.xzm and put it in your /modules folder. :good:

To use the save.dat when you boot change your porteus.cfg file's Graphic menu's APPEND line to look similar to the one I use:

Code: Select all

APPEND  changes=EXIT:UUID:C23A-6012/changes/50save.dat   extramod=UUID:C23A-6012/Modules 
I use the EXIT option to reduce the writes to the USB drive, faster, and the UUID code to ensure I'm accessing the correct drive.

hth :)
Ed

Jack
Contributor
Contributor
Posts: 1857
Joined: 09 Aug 2013, 14:25
Distribution: Porteus and Nemesis
Location: USA

Something New

Post#9 by Jack » 18 Feb 2024, 19:20

Ed_P wrote:
18 Feb 2024, 18:28

Code: Select all

~#  ls -l /mnt/live/memory/images
000-kernel.xzm : Jan 14 04:14
001-core.xzm : Dec 28 22:50
002-xorg.xzm : Dec 28 22:56
002-xtra.xzm : Dec 28 22:58
003-cinnamon.xzm : Dec 29 00:05
05-devel.xzm : Feb 8 2022
07-printing-x86_64-2023-02-04.xzm : Feb 4 2023
Dell6.4.10-wifi.xzm : Aug 18 2023
Dellautonet.xzm : Dec 19 16:00
Dellsound.xzm : May 14 2022
firefox-122.0-x86_64-en-US.xzm : Jan 27 23:51
mychanges.xzm : Feb 18 02:38
This file mychanges.xzm is the one I want so I save my changes. That way if I to delete the changes directory because I want to start over with a new changes directory I can. That way I have my mychanges.xzm that way I don't have redo everything.

Here is mine.

Code: Select all

root@porteus:/home/guest#  ls -l /mnt/live/memory/images
total 0
drwxr-xr-x  5 root root  61 Sep 23 15:38 000-kernel.xzm/
drwxr-xr-x 20 root root 305 Dec 29 03:50 001-core.xzm/
drwxr-xr-x 10 root root 154 Dec 29 03:56 002-xorg.xzm/
drwxr-xr-x  6 root root  72 Dec 29 03:58 002-xtra.xzm/
drwxr-xr-x 10 root root 129 Dec 30 06:09 003-mate.xzm/
drwxr-xr-x  5 root root  72 Feb  8 19:57 003-xtra.xzm/
drwxr-xr-x  4 root root  37 Feb  8 20:26 009-caches.xzm/
drwxr-xr-x  7 root root  84 Sep 22 07:56 05-devel.xzm/
drwxr-xr-x  5 root root  60 Sep 15 13:50 06-man.xzm/
drwxr-xr-x  5 root root  60 Sep 23 05:29 07-printing-mate-x86_64-2023-09-23.xzm/
drwxr-xr-x  7 root root  82 Sep 23 05:22 07-printing-x86_64-2023-09-23.xzm/
drwxr-xr-x  4 root root  37 Feb 10 10:57 abiword-3.0.5-x86_64-1gv.xzm/
drwxr-xr-x  4 root root  49 Feb 10 12:08 brasero-3.12.3-x86_64-1salix15.0.xzm/
drwxr-xr-x  4 root root  37 Dec 22 07:21 firefox-121.0-x86_64-en-US.xzm/
drwxr-xr-x  4 root root  37 Feb 10 11:01 gnumeric-1.12.51-x86_64-1gv.xzm/
drwxr-xr-x  5 root root  60 Feb 12 00:01 onboard-1.4.1-x86_64-1gv.xzm/
root@porteus:/home/guest# 
I just like Slackware because I think it teach you about Linux to build packages where Ubuntu is like Windows you just install programs you want.

User avatar
Ed_P
Contributor
Contributor
Posts: 8374
Joined: 06 Feb 2013, 22:12
Distribution: Cinnamon 5.01 ISO
Location: Western NY, USA

Something New

Post#10 by Ed_P » 18 Feb 2024, 20:04

To get a mychanges.xzm module you have two approaches.
One, rename your save.dat.xzm file that we discussed above to mychanges.xzm. :)
Two, create a xzm file of your changes similar to the network connection module script I posted above. The problem with this 2nd approach is knowing what files got changed so you know what files to make into a module. And this takes time and is tedious. I have over 100 files in my Cinnamon mychanges.xzm file. Many, many, ...

Code: Select all

# copy modified files

cp -a -p --parents    /home/guest/.config/dconf/*                    /tmp/mod/
cp -a -p --parents    /etc/resolv.conf                               /tmp/mod/

#                  -- locate updatedb --
cp -a -p --parents    /var/lib/mlocate/*                             /tmp/mod/

#                  -- File Manager - nemo - bookmarks --
cp -a -p --parents          /root/.config/nemo*                      /tmp/mod/
cp -a -p --parents          /root/.config/gtk-3.0/*                  /tmp/mod/
cp -a -p --parents    /home/guest/.config/nemo/*                     /tmp/mod/
cp -a -p --parents    /home/guest/.config/gtk-3.0/*                  /tmp/mod/

#                  -- File Manager - xed behavior, power settings & clock display --
cp -a -p --parents    /home/guest/.config/dconf/user                 /tmp/mod/

#                  -- My Home files --
cp -a -p --parents    /home/guest/*                                  /tmp/mod/
# https://forum.porteus.org/viewtopic.php?p=69449#p69449 Rava function
#cp -a -p --parents    /home/guest/.bashrc                            /tmp/mod/

#                  -- Browser - Firefox file associations --
cp -a -p --parents    /home/guest/.config/mimeapps.list              /tmp/mod/

#                  -- My machine tweaks --
cp -a -p --parents    /etc/localtime                                 /tmp/mod/
cp -a -p --parents    /etc/rc.d/rc.local*                            /tmp/mod/
cp -a -p --parents    /etc/xdg/autostart/Touchpad*                   /tmp/mod/
cp -a -p --parents    /etc/xdg/autostart/BootMode*                   /tmp/mod/
cp -a -p --parents    /etc/changes-exit.conf                         /tmp/mod/
cp -a -p --parents    /etc/porteus.conf                              /tmp/mod/
cp -a -p --parents    /etc/profile.d/DRV.sh                          /tmp/mod/
cp -a -p --parents    /opt/porteus-scripts/xpsinfo                   /tmp/mod/

#                  -- My menu tweaks --
cp -a -p --parents    /usr/share/applications/cups*                  /tmp/mod/
cp -a -p --parents    /usr/share/applications/*print*                /tmp/mod/
cp -a -p --parents    /usr/share/applications/*Flash*                /tmp/mod/
if [ -e               /usr/share/applications/sun_java* ]; then
   cp -a -p --parents /usr/share/applications/sun_java*              /tmp/mod/
fi

#                  -- My printer files --
cp -a -p --parents    /home/guest/.hplip/hplip.conf                  /tmp/mod/
cp -a -p --parents    /var/cache/cups/*                              /tmp/mod/
cp -a -p --parents    /etc/cups/ppd/*                                /tmp/mod/
cp -a -p --parents    /etc/cups/printers.conf                        /tmp/mod/
cp -a -p --parents    /etc/cups/subscriptions.conf                   /tmp/mod/
cp -a -p --parents    /etc/cups/cupsd.conf                           /tmp/mod/

#                  -- Cinnamom tweaks --
cp -a -p --parents    /home/guest/.cinnamon/configs/grouped-window-list@cinnamon.org/* /tmp/mod/
cp -a -p --parents    /home/guest/.cinnamon/configs/power@cinnamon.org/*               /tmp/mod/
And that's just some of them. :happy62:
Ed

Jack
Contributor
Contributor
Posts: 1857
Joined: 09 Aug 2013, 14:25
Distribution: Porteus and Nemesis
Location: USA

Something New

Post#11 by Jack » 18 Feb 2024, 21:19

My best way is to get Porteus Session Saver to work. Maybe get ncmprhnsbl to fix it since he is one that builds Porteus and maybe he don't know it don't work. I use it all the time when I use Porteus 4.0. When I started using Porteus 5.01 when I found out it didn't work.

In Nemesis I use Porteus Session Saver after I quit using Porteus 4.0 then I have a problem with Nemesis and then I start using Porteus again,
I just like Slackware because I think it teach you about Linux to build packages where Ubuntu is like Windows you just install programs you want.

User avatar
Ed_P
Contributor
Contributor
Posts: 8374
Joined: 06 Feb 2013, 22:12
Distribution: Cinnamon 5.01 ISO
Location: Western NY, USA

Something New

Post#12 by Ed_P » 18 Feb 2024, 21:52

Jack wrote:
18 Feb 2024, 21:19
My best way is to get Porteus Session Saver to work. Maybe get ncmprhnsbl to fix it
Not disagreeing that that is the best way but it won't be faster than what we have already discussed. Your choice. :)
Ed

User avatar
ncmprhnsbl
DEV Team
DEV Team
Posts: 3941
Joined: 20 Mar 2012, 03:42
Distribution: v5.0-64bit
Location: australia
Contact:

Something New

Post#13 by ncmprhnsbl » 19 Feb 2024, 02:14

Ed_P wrote:
18 Feb 2024, 07:15
Being python I believe it requires the 005-devel.xzm module to run.
nope.
not sure where that belief comes from (maybe you're thinking of perl), but since most of porteus gui scripts are python(-gobject) now, that'd be a problem.
the only reason to have 05-devel activated is to compile something.
basic operation is fine:

Code: Select all

root@porteus:/home/guest# save-session
Save to module
Parallel mksquashfs: Using 12 processors
Creating 4.0 filesystem on /mnt/nvme0n1p1/changes-2024-02-19.xzm, block size 131072.
[===============================================================\] 771/771 100%

Exportable Squashfs 4.0 filesystem, xz compressed, data block size 131072
	compressed data, compressed metadata, compressed fragments,
	compressed xattrs, compressed ids
	duplicates are removed
Filesystem size 13053.05 Kbytes (12.75 Mbytes)
	24.68% of uncompressed filesystem size (52887.94 Kbytes)
Inode table size 6402 bytes (6.25 Kbytes)
	26.23% of uncompressed inode table size (24409 bytes)
Directory table size 7136 bytes (6.97 Kbytes)
	46.10% of uncompressed directory table size (15478 bytes)
Number of duplicate files found 40
Number of inodes 705
Number of files 413
Number of fragments 33
Number of symbolic links 8
Number of device nodes 0
Number of fifo nodes 1
Number of socket nodes 0
Number of directories 283
Number of ids (unique uids + gids) 3
Number of uids 2
	root (0)
	guest (1000)
Number of gids 2
	root (0)
	users (100)
and

Code: Select all

root@porteus:/home/guest# save-session
Save to file
Create a file
meta-data=/mnt/nvme0n1p6/DEV/porteussave.dat isize=512    agcount=4, agsize=32768 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=0 inobtcount=0
data     =                       bsize=4096   blocks=131072, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=1368, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
both produced the expected saved_session.xzm and save_file.dat.

Jack:

Code: Select all

root@porteus:/home/guest# sh save-session
there's your problem, trying to run a python script through the shell interpreter won't work. just plain save-session (as root)
or Porteus Settings Centre>Save Settings(big down arrow)>Save Your Current Porteus Session

Ed:
in your case you've chosen to use an existing file to save to, and it seems there is a bug for that operation.
Forum Rules : https://forum.porteus.org/viewtopic.php?f=35&t=44

Jack
Contributor
Contributor
Posts: 1857
Joined: 09 Aug 2013, 14:25
Distribution: Porteus and Nemesis
Location: USA

Something New

Post#14 by Jack » 19 Feb 2024, 02:40

ncmprhnsbl wrote:
19 Feb 2024, 02:14
Jack:

Code: Select all

root@porteus:/home/guest# sh save-session
there's your problem, trying to run a python script through the shell interpreter.
Ed:
in your case you've chosen to use an existing file to save to, and it seems there is a bug for that operation.
Thanks ncmprhnsbl for your help. When I ran it in root Terminal it freezes up after I told where I wanted to put changes-date.xzm. It would be nice if it was in applications/System Tools.
I just like Slackware because I think it teach you about Linux to build packages where Ubuntu is like Windows you just install programs you want.

User avatar
ncmprhnsbl
DEV Team
DEV Team
Posts: 3941
Joined: 20 Mar 2012, 03:42
Distribution: v5.0-64bit
Location: australia
Contact:

Something New

Post#15 by ncmprhnsbl » 19 Feb 2024, 04:19

Jack wrote:
19 Feb 2024, 02:40
When I ran it in root Terminal it freeze up after I told where I wanted to put changes-date.xzm.
no ideas on that one.. does the destination have enough space? the script doesn't handle that scenario ... bit hard to know how big the module will be before making it. i mean, an estimate could be made: around 1/3 of the existing filesystem size for xz..
ncmprhnsbl wrote:
19 Feb 2024, 02:14
Ed:
in your case you've chosen to use an existing file to save to, and it seems there is a bug for that operation.
bugs ;)
had look at it and here's a version that seems to work if you want to test it:

Code: Select all

#! /usr/bin/python
##
## Script to save current Porteus changes to module
## or save file container
## Author: Brokenman <brokenman@porteus.org>
##
## ported to pygobject by ncmprhnsbl forum.porteus.org

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib
from subprocess import run, DEVNULL, Popen, PIPE
from tempfile import TemporaryDirectory
from os import getenv, getuid, path, stat, chmod, remove, mkdir, makedirs, system
from datetime import date
from shutil import rmtree

## Make sure we're in X
display = getenv('DISPLAY')
if display == None:
    print("This program requires an X session!")
    quit()

## prompt root password(gui psu) and re-execute? probly a bit dirty..
## using subprocess rather than os.system() to be script agnostic..
user = getuid()
if user != 0:
    print("You must be root to run this!")
    this_script = path.abspath(__file__)
    Popen(['psu', this_script])
    quit()

today = date.today().isoformat()
cmod = "/changes-" + today + ".xzm"
bootdev = getenv('BOOTDEV')
moddir = bootdev + "/porteus/modules"
tmp_dir = TemporaryDirectory()
exclude = tmp_dir.name + "/exclude"
mountpoint = "/mnt/loopsave"
cdir = "/mnt/live/memory/changes"
with open(exclude, "w") as fd:
    fd.write("tmp\ndev\nsys\nvar")

class GtkSaveSess(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title = "Porteus Save Session", border_width = 10, height_request = 300, width_request = 460, icon_name = "cdr")
        self.vb = Gtk.Box(spacing = 5, orientation = Gtk.Orientation.VERTICAL)

        self.l_header_txt = Gtk.Label()
        self.l_header_txt.set_markup("<span size=\"x-large\" weight=\"bold\">Porteus Save Session</span>")
        self.vb.pack_start(self.l_header_txt, False, False, 5)

        self.vb.pack_start(Gtk.Separator(), False, False, 5)

        self.text = Gtk.Label()
        self.text.set_markup("<span>This application can save your current Porteus session into a \nsingle module, save file or folder  that can be loaded everytime \nyou boot. You can create a new save file or use an existing one. \nEncrypted save files are supported which will require a password \nat boot time.</span>")
        self.vb.add(self.text)

        self.vb.pack_start(Gtk.Separator(), False, False, 10)

        self.hb = Gtk.Box(spacing = 10, orientation = Gtk.Orientation.HORIZONTAL, homogeneous = True)

        self.button1 = Gtk.Button.new_with_label("Save to module")
        self.button1.connect("clicked", self.on_button1_clicked)
        self.hb.add(self.button1)

        self.button2 = Gtk.Button.new_with_label("Save to a file")
        self.button2.connect("clicked", self.on_button2_clicked)
        self.hb.add(self.button2)

        self.button3 = Gtk.Button.new_with_label("Save to a folder")
        self.button3.connect("clicked", self.on_button3_clicked)
        self.hb.add(self.button3)

        self.vb.add(self.hb)

        self.hb_bottom = Gtk.Box(spacing = 5, homogeneous = False)
        self.help_button = Gtk.Button.new_with_label("Help")
        self.help_button.connect("clicked", self.on_help_clicked)
        self.hb_bottom.pack_start(self.help_button, False, False, 2)

        self.cancel_button = Gtk.Button.new_with_label("Exit")
        self.cancel_button.connect("clicked", self.on_cancel_clicked)
        self.hb_bottom.pack_end(self.cancel_button, False, False, 2)

        self.vb.pack_end(self.hb_bottom, False, False, 5)
        self.vb.pack_end(Gtk.Separator(), False, False, 10)
        self.add(self.vb)

    def on_button1_clicked(self, button):
        print('Save to module')
        smod_dialog = SaveModule(self)
        response = smod_dialog.run()
        if Gtk.ResponseType.OK == response:
            smodir = smod_dialog.entry.get_text()
            if smodir == "":
                smodir = moddir
            if self.is_file_in_aufs(smodir) is True:
                GtkDialog("Error", "Sorry, " + smodir + " is inside the live filesystem. You must save your changes module outside of aufs.", Gtk.MessageType.ERROR, 0)
            elif self.is_writable(smodir) is False:
                GtkDialog("Error", "Sorry, " + smodir + " is not writable. You must save your changes module some place that's writable.", Gtk.MessageType.ERROR, 0)
            #print(smodir)
            else:
                run(['mksquashfs', cdir, smodir + cmod, '-noappend', '-ef', exclude])
                GtkDialog("Success", "Your changes have been saved to " + smodir + cmod, Gtk.MessageType.INFO, 0)
        smod_dialog.destroy()

    def on_button2_clicked(self, button):
        print('Save to file')
        sfile1_dialog = SaveFile1(self)
        sfile1_dialog.run()
        sfile1_dialog.destroy()

    def on_button3_clicked(self, button):
        sfold_dialog = SaveFolder(self)
        response = sfold_dialog.run()
        if Gtk.ResponseType.OK == response:
            sfold = sfold_dialog.entry.get_text()
            if sfold == "":
                GtkDialog("Error", "You seem to have missed a setting. Start again.", Gtk.MessageType.ERROR, 0)
            elif self.is_writable(sfold) is False:
                GtkDialog("Error", "Sorry, " + sfold + " is not writable. Your changes folder must be some place that's writable.", Gtk.MessageType.ERROR, 0)
            elif self.is_posix(sfold) is False:
                GtkDialog("Error", "This is not a POSIX compatible file system. \nYou should choose a save file for this location instead.", Gtk.MessageType.ERROR, 0)
            elif self.is_file_in_aufs(sfold) is True:
                GtkDialog("Error", "Sorry, " + sfold + " is inside the live filesystem. Your changes folder must be outside of aufs.", Gtk.MessageType.ERROR, 0)
            elif self.has_space(sfold) is False:
                GtkDialog("Error", "There is not sufficient space on this partition!", Gtk.MessageType.ERROR, 0)
            else:
                remove_old_changes = sfold_dialog.rem_changes.get_active()
                if remove_old_changes == 1:
                    self.remove_dirs(sfold + "/changes")
                    GtkDialog(":)", "Old changes removed.", Gtk.MessageType.INFO, 1000)
                targ_sfold = sfold + "/changes"
                self.make_dir(targ_sfold)
                GtkDialog(":)", "Copying files..", Gtk.MessageType.INFO, 1000)
                run(['cp', '-a', cdir + '/.', targ_sfold], stdout=DEVNULL)
                run(['rm', '-rf', 'sys', 'dev', 'mnt', 'tmp'], cwd=targ_sfold)
                GtkDialog("Your files have been copied.", "You will need to open your porteus.cfg file \nand add: changes=" + sfold + "\nto your boot line.", Gtk.MessageType.INFO, 0)
        sfold_dialog.destroy()

    def on_help_clicked(self, button):
        print('Help')
        help_dialog = HelpDialog(self)
        help_dialog.run()
        help_dialog.destroy()

    def on_cancel_clicked(self, button):
        Gtk.main_quit()

    def is_file_in_aufs(self, filepath):
        p1 = Popen(['df', '-T', filepath], stdout=PIPE)
        p2 = Popen(['tail', '-n1'], stdin = p1.stdout, stdout=PIPE)
        if run(['awk', '{print$1}'], stdin = p2.stdout, stdout=PIPE).stdout.decode('utf-8').strip() == "aufs":
            return True
        return False

    def is_posix(self, fpath):
        tmp_prefix = "write_tester"
        count = 0
        filename = path.join(fpath, tmp_prefix)
        f = open(filename,"w")
        f.close()
        p1 = stat(filename).st_mode
        chmod(filename, mode=0o400)
        p2 = stat(filename).st_mode
        if p1 == p2:
            return False
        remove(filename)
        return True

    def is_writable(self, fpath):
        try:
            tmp_prefix = "write_tester"
            count = 0
            filename = path.join(fpath, tmp_prefix)
            while(path.exists(filename)):
                filename = "{}.{}".format(path.join(fpath, tmp_prefix),count)
                count = count + 1
            f = open(filename,"w")
            f.close()
            remove(filename)
            return True
        except Exception as e:
            print( "{}".format(e) )
            return False

    def has_space(self, fpath):
        p1 = Popen(['du', '-s', '-X', exclude, cdir], stdout=PIPE)
        sess_size = run(['awk', '{print$1}'], stdin = p1.stdout, stdout=PIPE).stdout.decode('utf-8').strip()
        p1 = Popen(['df', fpath], stdout=PIPE)
        p2 = Popen(['tail', '-n1'], stdin = p1.stdout, stdout=PIPE)
        targ_size = run(['awk', '{print$4}'], stdin = p2.stdout, stdout=PIPE).stdout.decode('utf-8').strip()
        if int(sess_size) > int(targ_size):
            return False
        return True

    def remove_dirs(self, fpath):
        if path.exists(fpath):
            rmtree(fpath)
        else:
            raise XXError("some exception")
        ## or simply:
        ##run(['rm', '-rf', fpath])

    def make_dir(self, fpath):
        if path.exists(fpath) is False:
            mkdir(fpath)

class SaveModule(Gtk.Dialog):
    def __init__(self, parent):
        Gtk.Dialog.__init__(self, "Save to Module", parent, 0)
        self.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK)

        self.set_default_size(400, 280)
        self.set_border_width(20)

        self.l_header_txt = Gtk.Label()
        self.l_header_txt.set_markup("<span size=\"x-large\" weight=\"bold\">Choose a destination folder</span>")
        self.vb = self.get_content_area()
        self.vb.pack_start(self.l_header_txt, False, False, 5)

        self.vb.pack_start(Gtk.Separator(), False, False, 5)

        self.text = Gtk.Label()
        self.text.set_markup("Your save session module will be saved to:\n\n" + moddir + " \n\nClick OK or choose a different folder.")
        self.vb.add(self.text)

        self.vb.pack_start(Gtk.Separator(), False, False, 10)

        self.grid = Gtk.Grid(column_spacing = 20)
        self.label = Gtk.Label(xalign = 0.0)
        self.label.set_markup("\tFolder:")
        self.grid.attach(self.label, 3, 0, 1, 1)
        self.entry = Gtk.Entry()
        self.grid.attach(self.entry, 4, 0, 4, 1)
        self.add_folder_button = Gtk.Button.new_from_icon_name("folder-new-symbolic", Gtk.IconSize.BUTTON)
        self.add_folder_button.connect("clicked", self.on_add_folder_button_clicked)
        self.grid.attach(self.add_folder_button, 8, 0, 1, 1)
        self.vb.add(self.grid)

        self.vb.pack_end(Gtk.Separator(), False, False, 10)
        self.show_all()

    def on_add_folder_button_clicked(self, button):
        dir_dialog = Gtk.FileChooserDialog(title = "Choose a folder to save your module to", parent = self, action = Gtk.FileChooserAction.SELECT_FOLDER)
        dir_dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, "Select", Gtk.ResponseType.OK)
        dir_dialog.set_default_size(400, 280)
        response = dir_dialog.run()
        if Gtk.ResponseType.OK == response:
            self.src_dir = dir_dialog.get_filename()
            self.entry.set_text(self.src_dir)
        dir_dialog.destroy()

class SaveFile1(Gtk.Dialog):
    def __init__(self, parent):
        Gtk.Dialog.__init__(self, "Save File", parent, 0)
        self.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)

        self.set_default_size(400, 280)
        self.set_border_width(20)
        self.header_txt = "<span size=\"large\" weight=\"bold\">Choose a save file option</span>"
        self.help_txt = "You may choose to save your current Porteus session to an \nexisting save file <i>(with option to empty it first)</i> or you can \ncreate a new save file container for your changes. \nEncrypted save files are supported."
        self.l_header_txt = Gtk.Label()
        self.l_header_txt.set_markup(self.header_txt)

        self.vb = self.get_content_area()
        self.vb.add(self.l_header_txt)

        self.l_help_txt = Gtk.Label()
        self.l_help_txt.set_markup(self.help_txt)
        self.vb.pack_start(self.l_help_txt, True, True, 5)

        self.vb.pack_start(Gtk.Separator(), False, False, 5)

        self.hb = Gtk.Box(spacing = 10, orientation = Gtk.Orientation.HORIZONTAL, homogeneous = True)
        self.button1 = Gtk.Button.new_with_label("Save to existing file")
        self.button1.connect("clicked", self.on_button1_clicked)
        self.hb.add(self.button1)

        self.button2 = Gtk.Button.new_with_label("Create a new file")
        self.button2.connect("clicked", self.on_button2_clicked)
        self.hb.add(self.button2)
        self.vb.add(self.hb)
        self.vb.pack_start(Gtk.Separator(), False, False, 5)
        self.show_all()

    def on_button1_clicked(self, button):
        print('Use existing file')
        sfile2_dialog = SaveFileEx(self)
        response = sfile2_dialog.run()
        if Gtk.ResponseType.OK == response:
            xfile = sfile2_dialog.entry.get_text()
            mpoint = "/mnt/vault"
            if xfile == "":
                GtkDialog("Error", "You seem to have missed a setting. Start again.", Gtk.MessageType.ERROR, 0)
            else:
                makedirs(mpoint, exist_ok=True)
                loop = self.check_loop()
                no_keep = sfile2_dialog.button2.get_active()
                if self.is_encrypted(xfile) is True:
                    pass_dialog = Passphrase(self)
                    response = pass_dialog.run()
                    if Gtk.ResponseType.OK == response:
                        passp1 = pass_dialog.pass_1_entry.get_text()
                        passp2 = pass_dialog.pass_2_entry.get_text()
                        if passp1 != passp2:
                            GtkDialog("Error", "Passwords do not match!", Gtk.MessageType.ERROR, 0)
                            response = pass_dialog.run()
                        elif passp1 == "" or passp2 == "":
                            GtkDialog("Error", "Blank passwords not allowed!", Gtk.MessageType.ERROR, 0)
                            response = pass_dialog.run()
                        else:
                            loop = self.check_loop()
                            run(['/sbin/losetup', loop, xfile])
                            try:
                                run(["cryptsetup luksOpen " + loop + " crypt <<< " + passp2], shell=True)
                                run(['mount', '/dev/mapper/crypt', mpoint])
                                if no_keep is True:
                                    run(['rm -rf ' + mpoint +'/*'],shell=True)
                                has_space = GtkSaveSess.has_space(self, mpoint)
                                if has_space is False:
                                    run(['umount', mpoint])
                                    run(['cryptsetup', 'luksClose', 'crypt'])
                                    run(['losetup', '-d', loop])
                                    GtkDialog("Error", "Your save file does not have sufficient space!", Gtk.MessageType.ERROR, 0)
                                else:
                                    GtkDialog("", "Copying session to file", Gtk.MessageType.INFO, 2000)
                                    run(['cp', '-a', cdir + '/.', mpoint + '/'])
                                    run(['rm', '-rf', 'sys', 'dev', 'mnt', 'tmp'], cwd=mpoint)
                                    GtkDialog("", "Unmounting savefile", Gtk.MessageType.INFO, 2000)
                                    run(['umount', mpoint])
                                    run(['cryptsetup', 'luksClose', 'crypt'])
                                    run(['losetup', '-d', loop])
                                    GtkDialog("Success", "Your session has been saved to " + xfile, Gtk.MessageType.INFO, 3000)
                            except Exception:
                                GtkDialog("Error", "No key available with this passphrase.", Gtk.MessageType.ERROR, 0)
                                response = pass_dialog.run()
                    pass_dialog.destroy()
                    print("do encrypted stuff")
                else:
                    run(['mount', '-t', 'auto', '-o', 'loop', xfile, mpoint])
                    if no_keep is True:
                        run(['rm -rf ' + mpoint +'/*'],shell=True)
                    has_space = GtkSaveSess.has_space(self, mpoint)
                    if has_space is False:
                        run(['umount', mpoint])
                        GtkDialog("Error", "Your save file does not have sufficient space!", Gtk.MessageType.ERROR, 0)
                    else:
                        GtkDialog("", "Copying session to file", Gtk.MessageType.INFO, 2000)
                        run(['cp', '-a', cdir + '/.', mpoint + '/'])
                        run(['rm', '-rf', 'sys', 'dev', 'mnt', 'tmp'], cwd=mpoint)
                        GtkDialog("", "Unmounting savefile", Gtk.MessageType.INFO, 2000)
                        run(['umount', mpoint])
                        GtkDialog("Success", "Your session has been saved to " + xfile, Gtk.MessageType.INFO, 3000)
                    print("mount,check space,copy changes minus excludes, unmount")

        sfile2_dialog.destroy()

    def is_encrypted(self, filepath):
        p1 = Popen(['/sbin/blkid', filepath], stdout=PIPE)
        p2 = run(['grep', '-o', '_LUKS'], stdin = p1.stdout, stdout=PIPE).stdout.decode('utf-8').strip()
        if p2 == "":
            return False
        else:
            return True
        print(p2)

    def check_loop(self):
        p1 = Popen(['ls -1 /dev/loop*'], shell=True, stdout=PIPE)
        p2 = Popen(['tr', '-d', '[:alpha:][:punct:]'], stdin = p1.stdout, stdout=PIPE)
        p3 = Popen(['sort', '-g'], stdin = p2.stdout, stdout=PIPE)
        x = run(['tail', '-n1'],  stdin = p3.stdout, stdout=PIPE).stdout.decode('utf-8').strip()
        print("x is " + x)
        if x != "":
            y = str(int(x) + 1)
            print(y)
            loop = "/dev/loop" + y
            print("loop=", loop)
            if not path.exists(loop):
                run(['mknod', loop, 'b', '7', y])
                return loop
        else:
            return False

    def on_button2_clicked(self, button):
        print('Create a file')
        system('/opt/porteus-scripts/make-changes')

class SaveFileEx(Gtk.Dialog):
    def __init__(self, parent):
        Gtk.Dialog.__init__(self, "Save to Existing File", parent, 0)
        self.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK)

        self.set_default_size(400, 280)
        self.set_border_width(20)

        self.header_txt = "<span size=\"large\" weight=\"bold\">Choose an Existing save file</span>"
        self.help_txt = "Select an existing save file container in which you will \nsave your current session. Choose whether to add to \nchanges or remove all previous changes first."
        self.l_header_txt = Gtk.Label()
        self.l_header_txt.set_markup(self.header_txt)

        self.vb = self.get_content_area()
        self.vb.add(self.l_header_txt)

        self.l_help_txt = Gtk.Label()
        self.l_help_txt.set_markup(self.help_txt)
        self.vb.pack_start(self.l_help_txt, True, True, 5)

        self.grid = Gtk.Grid(row_spacing = 10, column_spacing = 10)
        self.button1 = Gtk.RadioButton.new_with_label(None, "Add to changes file")
        self.button1.connect("clicked", self.on_button_toggled, "add")
        self.grid.attach(self.button1, 0, 0, 2, 1)

        self.button2 = Gtk.RadioButton.new_with_label_from_widget(self.button1, "Remove previous changes")
        self.button2.connect("clicked", self.on_button_toggled, "remove")
        self.grid.attach(self.button2, 3, 0, 1, 1)

        self.hb1 = Gtk.Box(spacing = 10, homogeneous = False)
        self.hb1.pack_start(Gtk.Label(label = "Folder: "), False, False, 5)
        self.label = Gtk.Label(xalign = 0.0)
        self.label.set_markup("\tFolder:")
        self.grid.attach(self.label, 0, 3, 1, 1)
        self.entry = Gtk.Entry()
        self.grid.attach(self.entry, 1, 3, 3, 1)
        self.add_folder_button = Gtk.Button.new_from_icon_name("folder-new-symbolic", Gtk.IconSize.BUTTON)
        self.add_folder_button.connect("clicked", self.on_add_folder_button_clicked)
        self.grid.attach(self.add_folder_button, 4, 3, 1, 1)
        self.vb.add(self.grid)


        self.vb.pack_start(Gtk.Separator(), False, False, 5)
        self.show_all()

    def on_button_toggled(self, button, name):
        if button.get_active():
            state = "on"
        else:
            state = "off"
        print("Button", name, "was turned", state)

    def on_add_folder_button_clicked(self, button):
        dialog = Gtk.FileChooserDialog(title = "Choose a file to save your session to", parent = self)
        dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, "Select", Gtk.ResponseType.OK)
        dialog.set_default_size(400, 280)
        response = dialog.run()
        if Gtk.ResponseType.OK == response:
            self.src_file = dialog.get_filename()
            self.entry.set_text(self.src_file)
        dialog.destroy()

class SaveFolder(Gtk.Dialog):
    def __init__(self, parent):
        Gtk.Dialog.__init__(self, "Save to Folder", parent, 0)
        self.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK)

        self.set_default_size(400, 280)
        self.set_border_width(20)

        self.l_header_txt = Gtk.Label()
        self.l_header_txt.set_markup("<span size=\"x-large\" weight=\"bold\">Choose a destination folder</span>")
        self.vb = self.get_content_area()
        self.vb.pack_start(self.l_header_txt, False, False, 5)

        self.vb.pack_start(Gtk.Separator(), False, False, 5)

        self.text = Gtk.Label()
        self.text.set_markup("You may choose to save your current Porteus session to \nan existing folder. \
\nA subfolder called <b>changes</b> will be created in your chosen \nfolder. \nAfter the process you will \
need to open your porteus.cfg \nfile and change the <b>changes=</b> section to point to your \ntarget folder.")
        self.vb.add(self.text)
        self.vb.pack_start(Gtk.Separator(), False, False, 5)

        self.grid = Gtk.Grid(column_spacing = 20, row_spacing = 20)
        self.rem_changes = Gtk.CheckButton(label = "Remove previous changes")
        self.rem_changes.connect("toggled", self.on_rem_change_checked, "1")
        self.grid.attach(self.rem_changes, 1, 0, 1, 1)
        self.label = Gtk.Label(xalign = 0.0)
        self.label.set_markup("\tFolder:")
        self.grid.attach(self.label, 0, 2, 1, 1)
        self.entry = Gtk.Entry()
        self.grid.attach(self.entry, 1, 2, 1, 1)
        self.add_folder_button = Gtk.Button.new_from_icon_name("folder-new-symbolic", Gtk.IconSize.BUTTON)
        self.add_folder_button.connect("clicked", self.on_add_folder_button_clicked)
        self.grid.attach(self.add_folder_button, 4, 2, 1, 1)
        self.vb.add(self.grid)

        self.vb.pack_start(Gtk.Separator(), False, False, 5)
        self.show_all()

    def on_rem_change_checked(self, button, name):
        None

    def on_add_folder_button_clicked(self, button):
        dir_dialog = Gtk.FileChooserDialog(title = "Choose a folder to save your session to", parent = self, action = Gtk.FileChooserAction.SELECT_FOLDER)
        dir_dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, "Select", Gtk.ResponseType.OK)
        dir_dialog.set_default_size(400, 280)
        response = dir_dialog.run()
        if Gtk.ResponseType.OK == response:
            self.src_dir = dir_dialog.get_filename()
            self.entry.set_text(self.src_dir)
        dir_dialog.destroy()

class HelpDialog(Gtk.Dialog):
    def __init__(self, parent):
        Gtk.Dialog.__init__(self, "Help", parent, 0)
        self.add_buttons(Gtk.STOCK_OK, Gtk.ResponseType.OK)

        self.set_default_size(400, 280)

        self.help_header_txt = "<span size=\"large\" weight=\"bold\">Save Session Help</span>"
        self.help_txt = "This application enables you to save your current \nporteus session to a module, \
save file container or folder. \n\nIf a module is chosen it should be placed into your \n<i>modules</i> folder \
for activation at boot time. \n\nIf a save file is chosen then your <i>porteus.cfg</i> file will need \nto be \
edited to point to the save file using the \n<b>changes=</b> cheatcode."
        self.l_header_txt = Gtk.Label()
        self.l_header_txt.set_markup(self.help_header_txt)

        self.vb = self.get_content_area()
        self.vb.add(self.l_header_txt)

        self.scrolledwindow = Gtk.ScrolledWindow(hexpand = True, vexpand = True)
        self.vb.pack_start(self.scrolledwindow, True, True, 5)

        self.l_help_txt = Gtk.Label()
        self.l_help_txt.set_markup(self.help_txt)

        self.scrolledwindow.add(self.l_help_txt)

        self.show_all()

class Passphrase(Gtk.Dialog):
    def __init__(self, parent):
        Gtk.Dialog.__init__(self, "Password", parent, 0)
        self.add_buttons(Gtk.STOCK_OK, Gtk.ResponseType.OK, Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)
        self.set_default_size(550, 200)
        self.set_border_width(20)

        self.vb = self.get_content_area()

        self.pass_txt =Gtk.Label(xalign = 0.0)
        self.pass_txt.set_markup("<span>Please provide a passphrase which be used to decrypt your savefile container</span>")

        self.vb.pack_start(self.pass_txt, False, False, 5)

        self.grid = Gtk.Grid(row_spacing = 10, column_spacing = 10, column_homogeneous = True)
        self.pass_1= Gtk.Label(xalign = 0.0)
        self.pass_1.set_markup("\tPassphrase:")
        self.grid.attach(self.pass_1, 1, 0, 1, 1)
        self.pass_1_entry = Gtk.Entry()
        self.pass_1_entry.set_visibility(0)
        self.grid.attach(self.pass_1_entry, 2, 0, 3, 1)
        self.pass_2 = Gtk.Label(xalign = 0.0)
        self.pass_2.set_markup("\tRepeat:")
        self.grid.attach(self.pass_2, 1, 2, 1, 1)
        self.pass_2_entry = Gtk.Entry()
        self.pass_2_entry.set_visibility(0)
        self.grid.attach(self.pass_2_entry, 2, 2, 3, 1)
        self.vb.pack_start(self.grid, False, False, 15)

        self.show_all()

class GtkDialog():
    def __init__(self, primary_text = "Message Header", secondary_text = "Message Text", dtype = Gtk.MessageType.INFO, timeout = 0):

        if timeout > 0 and dtype == Gtk.MessageType.INFO:
            self.timeout_id = GLib.timeout_add(timeout, self.on_timeout, None)
        self.dialog = PorteusDialog(primary_text, secondary_text, dtype, timeout)
        response = self.dialog.run()
        self.dialog.destroy()

    def on_timeout(self, *args, **kwargs):
        if self.dialog is not None:
            self.dialog.destroy()

class PorteusDialog(Gtk.Dialog):
    def __init__(self, primary_text, secondary_text, dtype, timeout):
        Gtk.Dialog.__init__(self, "Porteus Message", None, 0)

        self.set_default_size(250, 100)

        icon_name = "dialog-information"
        if timeout == 0:
            self.add_button(Gtk.STOCK_OK, Gtk.ResponseType.OK)
            self.set_default_size(250, 120)

        if dtype == Gtk.MessageType.QUESTION:
            self.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)
            icon_name = "dialog-question"
        elif dtype == Gtk.MessageType.ERROR:
            icon_name = "dialog-error"
        elif dtype == Gtk.MessageType.WARNING:
            icon_name = "dialog-warning"

        self.vb = self.get_content_area()

        self.hb = Gtk.Box(spacing = 5, homogeneous = False)

        self.grid = Gtk.Grid(row_spacing = 5, column_spacing = 10)
        self.img =  Gtk.Image.new_from_icon_name(icon_name, Gtk.IconSize.DIALOG)
        self.grid.attach(self.img, 0, 0, 1, 2)
        self.l_header = Gtk.Label(xalign = 0.0)
        self.l_header.set_markup("<span size=\"medium\" weight=\"bold\">" + primary_text + "</span>")
        self.grid.attach(self.l_header, 1, 0, 1, 1)
        self.l_txt = Gtk.Label(xalign = 0.0, label = secondary_text)

        self.grid.attach(self.l_txt, 1, 1, 1, 1)
        self.hb.pack_start(self.grid, False, False, 10)

        self.vb.pack_start(self.hb, False, False, 15)

        self.show_all()

class ProgressDialog(Gtk.Window):
    def __init__(self, header_text, text):
        Gtk.Window.__init__(self, type = 0, decorated = 1, skip_taskbar_hint = 1, window_position = 1, border_width = 20, default_width = 250)

        self.set_border_width(20)
        self.progress = 0.0

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self.add(vbox)

        self.header = Gtk.Label()
        self.header.set_markup("<span size=\"medium\" weight=\"bold\">" + header_text + "</span>")
        vbox.pack_start(self.header, True, True, 0)

        timeout_id = GLib.timeout_add(50, self.on_timeout, None)
        self.progressbar = Gtk.ProgressBar()
        self.progressbar.set_text(text)
        self.progressbar.set_show_text("show_text")
        vbox.pack_start(self.progressbar, True, True, 0)

        self.show_all()

    def on_timeout(self, user_data):
        self.progressbar.pulse()
        return True

win = GtkSaveSess()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

Forum Rules : https://forum.porteus.org/viewtopic.php?f=35&t=44

Post Reply