From 896d9c633feb6d148b9209ca409740db6217cc7f Mon Sep 17 00:00:00 2001 From: "YUChoe@ipageon" Date: Thu, 15 Jul 2021 11:34:30 +0900 Subject: [PATCH 1/2] Changed for current project --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index d4960a9..54bd090 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,10 @@ *.onefile-build venv .venv +.vscode + +*.cmd +*.sh +req.txt +config.json +*.exe \ No newline at end of file From 0d1f34750dcb4d1480f3509b91325dbdb56cdcfa Mon Sep 17 00:00:00 2001 From: "YUChoe@ipageon" Date: Thu, 15 Jul 2021 11:36:12 +0900 Subject: [PATCH 2/2] #1 #3 and many changed for v4 --- main.py | 169 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 129 insertions(+), 40 deletions(-) diff --git a/main.py b/main.py index 9bdaddd..c8d76a8 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,5 @@ import os -import time +# import time import datetime import random from enum import Enum @@ -13,23 +13,109 @@ import json """ -# AFKSaver +# AFKSaver +### v4 - 20200715 + - Save and Load config.json + - Smaller window 360*320 to 300*200 + - PEP8 + - RUN/STOP button has greenish/reddish colours """ _appname = 'ASKSaver' -_version = '3(20200710)' +_version = '4(20200710)' -notepad_hwnd = None -gkeypressed = False +# notepad_hwnd = None +# gkeypressed = False - -def todayAt (hr, min=0, sec=0, micros=0): +def todayAt(hr, min=0, sec=0, micros=0): now = datetime.datetime.now() return now.replace(hour=hr, minute=min, second=sec, microsecond=micros) +class ConfigJSON(dict): + def __setitem__(self, key, item): + self.__dict__[key] = item + + def __getitem__(self, key): + return self.__dict__[key] + + def __repr__(self): + return repr(self.__dict__) + + def __len__(self): + return len(self.__dict__) + + def __delitem__(self, key): + del self.__dict__[key] + + def clear(self): + return self.__dict__.clear() + + def copy(self): + return self.__dict__.copy() + + def has_key(self, k): + return k in self.__dict__ + + def update(self, *args, **kwargs): + return self.__dict__.update(*args, **kwargs) + + def keys(self): + return self.__dict__.keys() + + def values(self): + return self.__dict__.values() + + def items(self): + return self.__dict__.items() + + def pop(self, *args): + return self.__dict__.pop(*args) + + def __cmp__(self, dict_): + return self.__cmp__(self.__dict__, dict_) + + def __contains__(self, item): + return item in self.__dict__ + + def __iter__(self): + return iter(self.__dict__) + + def __init__(self, fn='config.json'): + if not os.path.isfile(fn): + self.__dict__ = self.init_config_file() + else: + with open(fn) as fp: + self.__dict__ = json.load(fp) + self.fn = fn + + def init_config_file(self): + c = self.__dict__ + c['interval'] = 10 + c['counter'] = 5 + c['time_start_working'] = '0800' + c['time_end_working'] = '2200' + c['window_geometry'] = '' + c['quote'] = "You cannot learn how to write drama without writing plays, putting it on in front of an audience and getting humiliated." # David Mamet + self.save_all() + return c + + def save(self, key, value): + self.__dict__[key] = value + self.save_all() + + def save_all(self): + with open(self.fn, "w") as json_file: + dict_to_save = self.__dict__.copy() + try: + del dict_to_save['fn'] + except AttributeError: + pass + json.dump(dict_to_save, json_file, indent=4, sort_keys=True) + + class APP_STATUS(Enum): STOPPED = 0 DEACTIVATED = 1 @@ -45,28 +131,21 @@ class Main_App(): conf = {} def __init__(self, version=_version): - self.app.title (f"{_appname} - v{_version}") - window_width = 360 - window_height = 320 + self.conf = ConfigJSON(fn='config.json') + + self.app.title(f"{_appname} - v{_version}") + window_width = 300 + window_height = 200 screen_width = self.app.winfo_screenwidth() screen_height = self.app.winfo_screenheight() - x_cordinate = int((screen_width / 2) - (window_width / 2)) y_cordinate = int((screen_height / 2) - (window_height / 2)) + # app_geo = f"{window_width}x{window_height}+{x_cordinate}+{y_cordinate}" + app_geo = self.conf['window_geometry'] if self.conf['window_geometry'] else f"{window_width}x{window_height}+{x_cordinate}+{y_cordinate}" - self.app.geometry(f"{window_width}x{window_height}+{x_cordinate}+{y_cordinate}") + self.app.geometry(app_geo) self.app.resizable(height=False, width=False) - # status label - # button start / stop - # textarea - # configuration - off time begin / finish - # - text to write - self.conf['interval'] = 10 - self.conf['counter'] = 5 - self.conf['time_start_working'] = None - self.conf['time_end_working'] = None - # init UI status_label = tk.Label(self.app, text='Stopped') status_label.pack(fill=tk.BOTH, expand=True) @@ -88,8 +167,14 @@ def __init__(self, version=_version): status_kbd.pack(side='left') self.ui['status_kbd'] = status_kbd - # opt_button = tk.Button(self.app, text='RUN', command=self.opt_button_handler) - opt_button = tk.Button(self.app, text='RUN') + frame2 = tk.Frame(self.app) + frame2.pack(anchor=tk.CENTER) + + worktime_txt = 'W[{} - {}]'.format(self.conf['time_start_working'], self.conf['time_end_working']) + worktime_lbl = tk.Label(frame2, text=worktime_txt) + worktime_lbl.pack() + + opt_button = tk.Button(self.app, text='RUN', bg='#41B199') opt_button.bind('', self.opt_button_handler) opt_button.bind('', self.opt_button_handler) opt_button.pack(fill=tk.BOTH, expand=True) @@ -99,25 +184,27 @@ def __init__(self, version=_version): notepad.pack(fill=tk.BOTH, expand=True) self.ui['notepad'] = notepad - # TODO: configuration UI - - def run(self): + self.app.protocol("WM_DELETE_WINDOW", self.on_closing) self.app.mainloop() + def on_closing(self): + self.conf.save('window_geometry', self.app.winfo_geometry()) # #3 + self.app.destroy() + def opt_button_handler(self, event): if self.status == APP_STATUS.STOPPED: self._thread_handler = MockingUser(self, conf=self.conf, sleep_interval=self.conf['interval']) self._thread_handler.start() self.set_status('deactivate') - self.ui['opt_button']['text'] = 'STOP' - # print(time.asctime(), 'started') + self.ui['opt_button']['text'] = 'STOP' + self.ui['opt_button']['bg'] = '#FF6F4F' else: self._thread_handler.kill() del self._thread_handler self.set_status('stop') - self.ui['opt_button']['text'] = 'RUN' - # print(time.asctime(), 'stopped') + self.ui['opt_button']['text'] = 'RUN' + self.ui['opt_button']['bg'] = '#41B199' def focus(self): self.app.focus_force() @@ -128,18 +215,17 @@ def focus(self): self.focused = True self.ui['notepad'].focus_set() - def press(self): txt = "You cannot learn how to write drama without writing plays, putting it on in front of an audience and getting humiliated." # David Mamet s = txt.strip().split() - word = s[random.randint(0, len(s)-1)] + word = s[random.randint(0, len(s) - 1)] # print(f'{time.asctime()} writing: {word}') self.ui['notepad'].delete(1.0, 'end') pyautogui.write(word, interval=0.25) pyautogui.write(' ') def set_status(self, status_str): - if status_str == 'activate' and self.status != APP_STATUS.ACTIVATED : + if status_str == 'activate' and self.status != APP_STATUS.ACTIVATED: self.ui['status_label']['text'] = 'Running - Activated' self.status = APP_STATUS.ACTIVATED # print(f'{time.asctime()} {status_str}') @@ -160,6 +246,7 @@ def update_cmk_status(self, c, m, k): self.ui['status_mouse']['text'] = f'M[{m}]' self.ui['status_kbd']['text'] = f'K[{k}]' + class MockingUser(threading.Thread): kpressed = False mmoved = False @@ -180,13 +267,14 @@ def key_on_press(self, key): self.kpressed = True def working_time(self): - self.conf['time_start_working'] = todayAt(hr=8, min=30) - self.conf['time_end_working'] = todayAt(hr=22, min=0) - if self.conf['time_start_working'] < datetime.datetime.now() < self.conf['time_end_working']: - # print("working_time", True, self.conf['time_start_working'], datetime.datetime.now(), self.conf['time_end_working']) + s = self.conf['time_start_working'] + e = self.conf['time_end_working'] + time_start_working = todayAt(hr=int(s[:2]), min=int(s[2:])) + time_end_working = todayAt(hr=int(e[:2]), min=int(e[2:])) + + if time_start_working < datetime.datetime.now() < time_end_working: return True else: - print("working_time", False, self.conf['time_start_working'], datetime.datetime.now(), self.conf['time_end_working']) return False def run(self): @@ -219,7 +307,8 @@ def run(self): def kill(self): self._kill.set() + if __name__ == '__main__': app = Main_App() app.run() - exit() \ No newline at end of file + exit()