Jump to content

How do I make this program work on Linux and Mac?

38034580
from tkinter import *
from tkinter import messagebox
from tkinter.ttk import *
from tk_tools import *
from os import system
from time import sleep as wait
import platform
notify_avail=1
try:
    from win10toast import ToastNotifier
except:
    notify_avail=0
    messagebox.showerror('Load Error', 'Failed to load Win32 API. Notifications are not available.')
isUnix=False
state1=NORMAL
state2=NORMAL
# path to notification window icon
ICON_PATH = "shutdown.ico"
root=Tk()
HUD=Tk()
root.action=IntVar()
root.iconbitmap('shutdown.ico')
HUD.iconbitmap('shutdown.ico')
root.minutes=0
root.seconds=0
root.action.set(1)
if platform.system()=='Windows':
    font='Segoe UI'
elif platform.system=='Darwin':
    font='San Fransisco'
else:
    font='Ubuntu'
HUD.title('Display-PC Autoshutdown v1.1 ©sserver')
root.title('Config-PC Autoshutdown v1.1 ©sserver')
root.settingTime=False
HUD.images=True
root.resizable(False, False)
HUD.resizable(False, False)
HUD.config(bg='black')
root.clockState=False
try:
    HUD.actionGif=PhotoImage(file='action.gif')
    HUD.img=Label(HUD, background='black', image=HUD.actionGif)
    HUD.img.grid(column=0, row=1)
except:
    root.images=False
    HUD.img=Label(HUD, background='black', foreground='#00ff00', text='', font=(font, 25))
    HUD.img.place(x=0, y=110)
    HUD.geometry('240x160')
def clock():
    if root.clockState:
        if root.seconds<=0:
            root.minutes-=1
            root.seconds=59
        else:
            root.seconds-=1
        if root.minutes<=0 and root.seconds<=0:
            HUD.title('0')
            secondLabel.set_value('0')
            HUD.update()
            if root.action.get()==1:
                system('rundll32.exe powrprof.dll,SetSuspendState 0,1,0')
            elif root.action.get()==2:
                if root.force.instate(['selected']):
                    system('shutdown -s -f -t 0')
                else:
                    system('shutdown -s -t 0')
            elif root.action.get()==3:
                if root.force.instate(['selected']):
                    system('shutdown -r -f -t 0')
                else:
                    system('shutdown -r -t 0')
            root.clockState=False
            minuteLabel.set_value('')
            secondLabel.set_value('')
            if root.images:
                HUD.actionGif=PhotoImage(file='action.gif')
                HUD.img.config(image=HUD.actionGif)
            else:
                HUD.img.config(text='')
            HUD.title('Display-PC Autoshutdown v1.1 ©sserver')
            HUD.iconphoto('shutdown.ico')
            return
        if root.images:
            HUD.actionGif=PhotoImage(file='action-'+str(root.action.get())+'.gif')
            HUD.img.config(image=HUD.actionGif)
        elif root.action.get()==1:
            HUD.img.config(text='Suspend')
            x='Suspend'
        elif root.action.get()==2:
            HUD.img.config(text='Power off')
            x='Power off'
        elif root.action.get()==3:
            HUD.img.config(text='Restart')
            x='Restart'
        if root.minutes>0:
            minuteLabel.set_value(str(root.minutes))
        else:
            minuteLabel.set_value('')
        if root.seconds<10 and root.minutes>0:
            secondLabel.set_value('0'+str(root.seconds))
        else:
            secondLabel.set_value(str(root.seconds))
        if root.seconds<10 and root.minutes>0:
            HUD.title(str(root.minutes)+':0'+str(root.seconds))
        else:
            if root.minutes<=0:
                HUD.title(str(root.seconds))
            else:
                HUD.title(str(root.minutes)+':'+str(root.seconds))
        if alerts.instate(['selected']):
            if root.minutes==1 and root.seconds==0:
                try:
                    n = ToastNotifier()
                    n.show_toast(platform.system()+" will "+x.lower()+' soon', x+" in 1 minute", duration = 10,
icon_path ="shutdown.ico", threaded=True)
                except:
                    alerts.state(['!selected'])
            if root.minutes==0 and root.seconds==30:
                try:
                    n = ToastNotifier()
                    n.show_toast(platform.system()+" will "+x.lower()+' soon', x+" in 30 seconds", duration = 10,
icon_path ="shutdown.ico", threaded=True)
                except:
                    alerts.state(['!selected'])
            if root.minutes==5 and root.seconds==0:
                try:
                    n = ToastNotifier()
                    n.show_toast(platform.system()+" will "+x.lower()+' soon', x+" in 5 minutes", duration = 10,
icon_path ="shutdown.ico", threaded=True)
                except:
                    alerts.state(['!selected'])
        HUD.update()
        root.after(980, clock)
def set_time():
        if root.clockState:
            minuteEntry.config(state=NORMAL)
            secondEntry.config(state=NORMAL)
            setTimeButton.config(text='Start')
            minuteLabel.set_value('')
            secondLabel.set_value('')
            HUD.title('Display-PC Autoshutdown v1.1 ©sserver')
            HUD.iconbitmap('shutdown.ico')
            if root.images:
                HUD.actionGif=PhotoImage(file='action.gif')
                HUD.img.config(image=HUD.actionGif)
            else:
                HUD.img.config(text='')
                root.clockState=False
        else:
            try:
                if int(minuteEntry.get())>99 or int(minuteEntry.get())<0 or int(secondEntry.get())>59 or int(secondEntry.get())<0 or (int(secondEntry.get())<=0 and int(minuteEntry.get())<=0):
                    messagebox.showerror('Error', 'Value(s) are invalid')
                else:
                    root.minutes=int(minuteEntry.get())
                    root.seconds=int(secondEntry.get())
                    root.tenths=0
                    setTimeButton.config(text='Cancel')
                    root.clockState=True
                    minuteEntry.config(state=DISABLED)
                    secondEntry.config(state=DISABLED)
                    if root.minutes>0:
                        minuteLabel.set_value(str(root.minutes))
                    else:
                        minuteLabel.set_value('')
                    if root.seconds<10 and root.minutes>0:
                        secondLabel.set_value('0'+str(root.seconds))
                        HUD.title(str(root.minutes)+':0'+str(root.seconds))
                    else:
                        secondLabel.set_value(str(root.seconds))
                    if root.minutes<=0:
                        HUD.title(str(root.seconds))
                    else:
                        HUD.title(str(root.minutes)+':'+str(root.seconds))
                    if root.images:
                        HUD.actionGif=PhotoImage(file='action-'+str(root.action.get())+'.gif')
                        HUD.img.config(image=HUD.actionGif)
                    elif root.action.get()==1:
                        HUD.img.config(text='Suspend')
                    elif root.action.get()==2:
                        HUD.img.config(text='Power off')
                    elif root.action.get()==3:
                        HUD.img.config(text='Restart')
                    root.clockState=True
                    root.update()
                    wait(1)
                    clock()
            except ValueError:
                messagebox.showerror('Error', 'Value(s) are invalid')
        HUD.update()
def close():
    root.clockState=False
    root.destroy()
    HUD.destroy()
root.protocol('WM_DELETE_WINDOW', close)
HUD.protocol('WM_DELETE_WINDOW', close)
minuteLabel=SevenSegmentDigits(HUD, background='black', digit_color='#00ff00', height=100, digits=2)
minuteLabel.grid(column=1, row=1)
secondLabel=SevenSegmentDigits(HUD, background='black', digit_color='#00ff00', height=100, digits=2)
secondLabel.grid(column=3, row=1)
Radiobutton(root, 
               text="Suspend",
               variable=root.action, 
               value=1, state=state1).pack()
Radiobutton(root, 
               text="Power Off",
               variable=root.action, 
               value=2, state=state1).pack()
Radiobutton(root, 
               text="Restart",
               variable=root.action, 
               value=3, state=state1).pack()
root.force=Checkbutton(root, text='Force apps to close')
root.force.pack()
timeColon=Label(HUD, background='black', text=':', foreground='#00ff00', font=('Century Gothic', 75))
timeColon.grid(column=2, row=1)
HUD.call('wm', 'attributes', '.', '-topmost', True)
minuteEntry=Spinbox(root, from_=0, to=99)
minuteEntry.pack()
secondEntry=Spinbox(root, from_=0, to=59)
secondEntry.pack()
setTimeButton=Button(root, text='Start', command=set_time, state=NORMAL)
setTimeButton.pack()
alerts=Checkbutton(root, text='Countdown Alerts')
alerts.pack()
if notify_avail==0:
    alerts.state(['!selected'])
    alerts.config(state=DISABLED)
else:
    alerts.state(['selected'])
alerts.state(['!alternate'])
root.force.state(['!alternate'])
HUD.mainloop()

This program is supposed to shutdown a computer after a certain amount of time. Since this only works on Windows, how do I make this compatible for Linux and Mac?

Link to comment
Share on other sites

Link to post
Share on other sites

Link to comment
Share on other sites

Link to post
Share on other sites

For Linux you can try detecting the distribution and/or init system that's in use. For example if you find systemd is being used, you can call either "systemctl reboot" or "systemctl shutdown" (both of which might need root permission).

 

For a distribution like Debian (and derivatives), there would also be commands like "poweroff" and "shutdown -h" as possible alternatives.

 

Making something that works on most common distributions is going to require some searching around and testing in VMs.

Remember to either quote or @mention others, so they are notified of your reply

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, Eigenvektor said:

For Linux you can try detecting the distribution and/or init system that's in use. For example if you find systemd is being used, you can call either "systemctl reboot" or "systemctl shutdown" (both of which might need root permission).

 

For a distribution like Debian (and derivatives), there would also be commands like "poweroff" and "shutdown -h" as possible alternatives.

 

Making something that works on most common distributions is going to require some searching around and testing in VMs.

I need to access tk_tools even with root permission. How do I access imported modules with root permission?

Link to comment
Share on other sites

Link to post
Share on other sites

7 hours ago, 38034580 said:

I need to access tk_tools even with root permission. How do I access imported modules with root permission?

If your script needs to run stuff with root permissions, then the script itself needs to be run with root permissions (e.g. using sudo).

 

Scripts that require root typically check whether they have permission. If they don't, they ask the user to re-run them with sudo. Alternatively the script can restart itself with sudo, which will prompt the user to enter their password. Here's an example: https://stackoverflow.com/a/5222710

Remember to either quote or @mention others, so they are notified of your reply

Link to comment
Share on other sites

Link to post
Share on other sites

On 10/30/2021 at 3:24 PM, 38034580 said:

if root.force.instate(['selected']): system('shutdown -s -f -t 0') else: system('shutdown -s -t 0') elif root.action.get()==3: if root.force.instate(['selected']): system('shutdown -r -f -t 0') else: system('shutdown -r -t 0')

Your problem is a bit more fundamental than some other comments have let on.

 

The shutdown command on linux and macOS just don't accept the same arguments as cmd on Windows. Your script isn't just written for Windows, it's written to call a cmd environment since this would also not work in PowerShell.

 

What you need is a library, so that from your script you call myCoolShutdownFunction("now please"). The function does all the fancy work of detecting the os, shell environment, etc and piping in the command via os.system. This kind of stuff is too complicated to put in your main script, it'll just make it harder to read.

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×