diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1d9e75e --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/venv +/.idea +/build +/dist +Calc3D.spec \ No newline at end of file diff --git a/Calc3D.py b/Calc3D.py new file mode 100644 index 0000000..e1e3340 --- /dev/null +++ b/Calc3D.py @@ -0,0 +1,122 @@ +import datetime +import json +import os +import PySimpleGUI as Sgi +import gettext +import requests + +from calculating import calculating, amortization, cost_prise +from setts import window_setts, language, currency_setts +from texts import calc, about, new_marge, ver, not_connect +from update import upd_check + +now = datetime.datetime.now() + + +lang = gettext.translation('locale', localedir='locale', languages=[language()]) +lang.install() +_ = lang.gettext + + +def create_window(): + with open(os.path.expanduser('setts.json')) as f: + theme = json.load(f)['settings']['theme'] + Sgi.theme(theme) + menu_def = [ + [_('Файл'), [_('Настройки')], [_('Выход')]], + [_('Помощь'), [_('Как рассчитывается стоимость'), _('Обо мне'), _('Проверить обновления')]], + ] + + layout = [ + [Sgi.Menu(menu_def)], + [Sgi.Txt('_' * 46)], + [Sgi.Text('0', size=(7, 1), font=('Consolas', 32), + text_color='white', key='result', auto_size_text=True, justification='right', expand_x=True), + Sgi.Text(currency_setts(), font=('Consolas', 32), text_color='white', key='result')], + [Sgi.Text(_('Себестоимость:'), font=12, text_color='white'), + Sgi.Text('0', size=(7, 1), font=12, text_color='white', key='cost', auto_size_text=True, + justification='right', expand_x=True), + Sgi.Text(currency_setts(), font=('Consolas', 12), text_color='white', key='cost')], + [Sgi.Txt('_' * 46, pad=(10, 5))], + [Sgi.Text(_('Время печати')), Sgi.Push(), Sgi.InputText('0', size=(5, 20)), Sgi.Text(_('ч.')), + Sgi.InputText('0', size=(5, 0)), Sgi.Text(_('мин. '))], + [Sgi.Text(_('Масса детали')), Sgi.Push(), Sgi.InputText('0', size=(10, 20), justification='right', ), + Sgi.Text(_('г. '))], + [Sgi.Text(_('Количество экземпляров')), Sgi.Push(), Sgi.InputText('1', size=(10, 20), justification='right', ), + Sgi.Text(_('шт. '))], + [Sgi.Txt('_' * 46)], + [Sgi.Text(_('Моделирование')), Sgi.Push(), Sgi.InputText('0', size=(10, 20), justification='right', ), + Sgi.Text(f'{currency_setts()} ')], + [Sgi.Text(_('Постобработка')), Sgi.Push(), Sgi.InputText('0', size=(10, 20), justification='right', ), + Sgi.Text(f'{currency_setts()} ')], + [Sgi.Txt('_' * 46)], + [Sgi.Txt(' ' * 15), Sgi.ReadFormButton(_('Рассчитать'), size=(10, 2)), Sgi.Cancel(_('Выход'), size=(10, 2))] + + ] + return Sgi.Window(f'Calc3D by Risen ver.{ver}', layout, icon='logo.ico') + + +def main(): + window = create_window() + + while True: + event, values = window.read() + + if event == _("Настройки"): + window_setts() + window.close() + window = create_window() + + elif event == _("Как рассчитывается стоимость"): + Sgi.popup_ok(calc) + + elif event == _("Обо мне"): + Sgi.popup(about) + + elif event == "Проверить обновления": + try: + upd_check() + except requests.exceptions.ConnectionError: + Sgi.popup_ok(not_connect) + + elif event == _('Рассчитать'): + with open(os.path.expanduser('setts.json')) as f: + params = json.load(f)["settings"] + try: + hours = float(values[1]) + except ValueError: + hours = 0 + try: + minutes = float(values[2]) + except ValueError: + minutes = 0 + + if minutes > 60: + hours = hours + minutes // 60 + minutes = minutes % 60 + t = hours * 60 + minutes + + try: + md = values[3] + except ValueError: + md = 0 + + am = amortization(params['a'], t, params['spi'], now.year) # a, t, spi, year + + cost = cost_prise(params['p'], t, params['h'], md, params['d'], params['st'], params['mk'], am, + values[6], values[4]) # p, t, h, md, d, st, mk, am, post, x + + try: + result = calculating(abs(cost), values[5], params['marge']) # cost, mod, marg + except KeyError: + Sgi.popup_ok(new_marge) + result = 0 + window.find_element('result').Update(result) + window.find_element('cost').Update(cost) + + elif event in (Sgi.WIN_CLOSED, _('Выход')): + break + + +if __name__ == "__main__": + main() diff --git a/Calc3D.spec b/Calc3D.spec new file mode 100644 index 0000000..629cf79 --- /dev/null +++ b/Calc3D.spec @@ -0,0 +1,38 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['Calc3D.py'], + pathex=[], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='Calc3D', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, + icon=['test.ico'], +) diff --git a/LICENSE b/LICENSE index 23321a8..229ca4a 100644 --- a/LICENSE +++ b/LICENSE @@ -6,4 +6,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 645239d..e69de29 100644 --- a/README.md +++ b/README.md @@ -1,2 +0,0 @@ -# Calc3D_by_Risen - diff --git a/calculating.py b/calculating.py new file mode 100644 index 0000000..877fd0f --- /dev/null +++ b/calculating.py @@ -0,0 +1,49 @@ +def cost_prise(p, t, h, md, d, st, mk, am, post, x): + p = int(p) # номинальная мощность принтера + t = int(t) # время печати, в минутах!!! + h = float(h) # тариф электроэнергии + md = float(md) # вес детали + if float(d) < 1: + d = 1 + else: + d = float(d) # коэффициент выбраковки + st = float(st) # стоимость катушки + mk = float(mk) # вес катушки + am = float(am) # амортизация + try: + post = float(post) # постобработка + except ValueError: + post = 0 + try: + x = int(x) # количество экземпляров + except ValueError: + x = 1 + result = ((abs(p) / 1000) * (abs(t) / 60) * abs(h) * abs(x)) + (abs(md) * abs(d) * (abs(st) / abs(mk) * abs(x)) + abs(am) + abs(post) * abs(x)) + return round(result, 2) + + +def calculating(cost, mod, marg): + try: + mod = float(mod) # моделирование + except ValueError: + mod = 0 + try: + margin = float(marg) # процент наценки + except ValueError: + margin = 0 + result = (cost / 100 * margin + cost) + mod + return round(result, 2) + + +def amortization(a, t, spi, year): + if (year % 400 == 0) or (year % 100 != 0) and (year % 4 == 0): + minutes_in_year = 527040 / 2 + else: + minutes_in_year = 525600 / 2 + try: + year_norm = 100 / float(spi) + except ZeroDivisionError: + year_norm = 100 / 1 + year_am = float(a) / 100 * round(year_norm, 1) + am_per_minute = year_am / minutes_in_year * t + return round(am_per_minute, 2) diff --git a/lists.py b/lists.py new file mode 100644 index 0000000..868fe5c --- /dev/null +++ b/lists.py @@ -0,0 +1,26 @@ +themes_list = ['Black', 'BlueMono', 'BluePurple', 'BrightColors', 'BrownBlue', 'Dark', 'Dark2', 'DarkAmber', + 'DarkBlack', 'DarkBlack1', 'DarkBlue', 'DarkBlue1', 'DarkBlue10', 'DarkBlue11', 'DarkBlue12', + 'DarkBlue13', 'DarkBlue14', 'DarkBlue15', 'DarkBlue16', 'DarkBlue17', 'DarkBlue2', 'DarkBlue3', + 'DarkBlue4', 'DarkBlue5', 'DarkBlue6', 'DarkBlue7', 'DarkBlue8', 'DarkBlue9', 'DarkBrown', + 'DarkBrown1', 'DarkBrown2', 'DarkBrown3', 'DarkBrown4', 'DarkBrown5', 'DarkBrown6', 'DarkBrown7', + 'DarkGreen', 'DarkGreen1', 'DarkGreen2', 'DarkGreen3', 'DarkGreen4', 'DarkGreen5', 'DarkGreen6', + 'DarkGreen7', 'DarkGrey', 'DarkGrey1', 'DarkGrey10', 'DarkGrey11', 'DarkGrey12', 'DarkGrey13', + 'DarkGrey14', 'DarkGrey15', 'DarkGrey2', 'DarkGrey3', 'DarkGrey4', 'DarkGrey5', 'DarkGrey6', + 'DarkGrey7', 'DarkGrey8', 'DarkGrey9', 'DarkPurple', 'DarkPurple1', 'DarkPurple2', 'DarkPurple3', + 'DarkPurple4', 'DarkPurple5', 'DarkPurple6', 'DarkPurple7', 'DarkRed', 'DarkRed1', 'DarkRed2', + 'DarkTanBlue', 'DarkTeal', 'DarkTeal1', 'DarkTeal10', 'DarkTeal11', 'DarkTeal12', 'DarkTeal2', + 'DarkTeal3', 'DarkTeal4', 'DarkTeal5', 'DarkTeal6', 'DarkTeal7', 'DarkTeal8', 'DarkTeal9', 'Default', + 'Default1', 'DefaultNoMoreNagging', 'GrayGrayGray', 'Green', 'GreenMono', 'GreenTan', 'HotDogStand', + 'Kayak', 'LightBlue', 'LightBlue1', 'LightBlue2', 'LightBlue3', 'LightBlue4', 'LightBlue5', + 'LightBlue6', 'LightBlue7', 'LightBrown', 'LightBrown1', 'LightBrown10', 'LightBrown11', + 'LightBrown12', 'LightBrown13', 'LightBrown2', 'LightBrown3', 'LightBrown4', 'LightBrown5', + 'LightBrown6', 'LightBrown7', 'LightBrown8', 'LightBrown9', 'LightGray1', 'LightGreen', + 'LightGreen1', 'LightGreen10', 'LightGreen2', 'LightGreen3', 'LightGreen4', 'LightGreen5', + 'LightGreen6', 'LightGreen7', 'LightGreen8', 'LightGreen9', 'LightGrey', 'LightGrey1', 'LightGrey2', + 'LightGrey3', 'LightGrey4', 'LightGrey5', 'LightGrey6', 'LightPurple', 'LightTeal', 'LightYellow', + 'Material1', 'Material2', 'NeutralBlue', 'Purple', 'Python', 'PythonPlus', 'Reddit', 'Reds', + 'SandyBeach', 'SystemDefault', 'SystemDefault1', 'SystemDefaultForReal', 'Tan', 'TanBlue', + 'TealMono', 'Topanga'] +lang_list = ['Русский', 'English'] + +currency_list = ['руб.', '$', '€'] diff --git a/locale/en_US/LC_MESSAGES/locale.mo b/locale/en_US/LC_MESSAGES/locale.mo new file mode 100644 index 0000000..2e8bc0a Binary files /dev/null and b/locale/en_US/LC_MESSAGES/locale.mo differ diff --git a/locale/ru_RU/LC_MESSAGES/locale.mo b/locale/ru_RU/LC_MESSAGES/locale.mo new file mode 100644 index 0000000..1715104 Binary files /dev/null and b/locale/ru_RU/LC_MESSAGES/locale.mo differ diff --git a/logo.ico b/logo.ico new file mode 100644 index 0000000..14c2dbf Binary files /dev/null and b/logo.ico differ diff --git a/setts.json b/setts.json new file mode 100644 index 0000000..4c2ccf0 --- /dev/null +++ b/setts.json @@ -0,0 +1,15 @@ +{ + "settings": { + "theme": "Dark", + "p": "270", + "h": "3", + "d": "0", + "st": "1500", + "mk": "1000", + "a": "0", + "spi": "0", + "marge": "0", + "locale": "Ru", + "currency": "\u0440\u0443\u0431." + } +} \ No newline at end of file diff --git a/setts.py b/setts.py new file mode 100644 index 0000000..e389deb --- /dev/null +++ b/setts.py @@ -0,0 +1,174 @@ +import json +import PySimpleGUI as Sgi +import gettext +import os + +from texts import amortization_calc, new_sets +from lists import themes_list, lang_list, currency_list + + +def language(): + with open(os.path.expanduser('setts.json')) as file: + old_data = json.load(file) + if old_data['settings']["locale"] == 'English': + locale = 'en_US' + else: + locale = 'ru_RU' + return locale + + +lang = gettext.translation('locale', localedir='locale', languages=[language()]) +lang.install() +_ = lang.gettext + + +def currency_setts(): + with open('setts.json') as file: + old_data = json.load(file) + try: + if old_data['settings']["currency"] == 'руб.': + currency = 'руб.' + elif old_data['settings']["currency"] == '$': + currency = '$' + else: + currency = '€' + + except KeyError: + if old_data['settings']["locale"] == "рус.": + currency = 'руб.' + else: + currency = '$' + return currency + + +def window_setts(): + with open('setts.json') as file: + old_data = json.load(file) + theme = old_data["settings"]["theme"] + p = old_data["settings"]["p"] + h = old_data["settings"]["h"] + d = old_data["settings"]["d"] + st = old_data["settings"]["st"] + mk = old_data["settings"]["mk"] + a = old_data["settings"]["a"] + locale = old_data['settings']["locale"] + try: + currency = old_data['settings']["currency"] + except KeyError: + currency = "руб." + try: + spi = old_data["settings"]["spi"] + except KeyError: + Sgi.popup_ok(new_sets) + spi = 0 + try: + marg = old_data["settings"]["marge"] + except KeyError: + marg = 0 + + layout1 = [ + [Sgi.Text(_("ВНИМАНИЕ! Перед установкой параметра\n'Коэффициент выбраковки' прочитайте раздел\n" + "Help, с описанием формулы расчета!\n"), text_color="red")], + [Sgi.Text(_('Мощность принтера, Вт')), Sgi.Push(), Sgi.InputText(p, size=(10, 10), justification='right')], + [Sgi.Text(_('Тариф электроэнергии, кВт/ч')), Sgi.Push(), + Sgi.InputText(h, size=(10, 10), justification='right')], + [Sgi.Text(_('Коэффициент выбраковки')), Sgi.Push(), Sgi.InputText(d, size=(10, 10), justification='right')], + [Sgi.Text(_('Стоимость катушки, ')+f'{currency_setts()}'), Sgi.Push(), + Sgi.InputText(st, size=(10, 10), justification='right')], + [Sgi.Text(_('Вес катушки, гр.')), Sgi.Push(), + Sgi.Combo(['225', '250', '450', '500', '750', '850', '1000', '2250', + '2500'], size=(8, 20), default_value=mk)], + [Sgi.Text(_('Наценка, %.')), Sgi.Push(), Sgi.InputText(marg, size=(10, 10), justification='right')], + [Sgi.Text('')] + ] + layout2 = [ + [Sgi.Text(_('Стоимость вашего принтера, ')+f'{currency_setts()}'), Sgi.Push(), Sgi.InputText(a, size=(10, 10), + justification='right')], + [Sgi.Text(_('Срок полезного использования, лет.')), Sgi.Push(), Sgi.InputText(spi, size=(10, 10), + justification='right')], + [Sgi.Text('_' * 45)], [Sgi.Text(amortization_calc)], + [Sgi.Text('')] + ] + layout3 = [ + [Sgi.Text(_('Оформление'))], + [Sgi.Text(_("Выбор темы")), Sgi.Push(), Sgi.Combo(themes_list, size=(20, 20), default_value=theme)], + [Sgi.Text(_("Язык")), Sgi.Push(), Sgi.Combo(lang_list, size=(20, 20), default_value=locale)], + [Sgi.Text(_("Валюта")), Sgi.Push(), Sgi.Combo(currency_list, size=(20, 20), default_value=currency_setts())], + ] + + tab_group = [ + [Sgi.TabGroup( + [[Sgi.Tab(_('Основные настройки'), layout1), Sgi.Tab(_('Амортизация'), layout2), + Sgi.Tab(_('Оформление'), layout3)]] + ), [Sgi.Push(), Sgi.Button(_('Применить'))]]] + + window = Sgi.Window(_("Настройки"), tab_group, modal=True) + while True: + event, values = window.read() + if event == _('Применить'): + if values[8] == theme: + new_theme = theme + else: + new_theme = values[8] + if values[9] == locale: + new_locale = locale + else: + new_locale = values[9] + if values[10] == currency: + new_currency = currency + else: + new_currency = values[10] + if values[0] == p: + new_p = p + else: + new_p = values[0] + if values[1] == h: + new_h = h + else: + new_h = values[1].replace(',', '.') + if values[2] == d: + new_d = d + else: + new_d = values[2].replace(',', '.') + if values[3] == st: + new_st = st + else: + new_st = values[3] + if values[4] == mk: + new_mk = mk + else: + new_mk = values[4] + if values[5] == marg: + new_marg = marg + else: + new_marg = values[5].replace(',', '.') + if values[6] == a: + new_a = a + else: + new_a = values[6] + if values[7] == spi: + new_spi = spi + else: + new_spi = values[7] + + with open('setts.json', 'w') as file: + data = {"settings": {"theme": new_theme, + "p": new_p, + "h": new_h, + "d": new_d, + "st": new_st, + "mk": new_mk, + "a": new_a, + "spi": new_spi, + "marge": new_marg, + "locale": new_locale, + "currency": new_currency + + } + } + json.dump(data, file, indent=2) + + window.close() + + if event == "Exit" or event == Sgi.WIN_CLOSED: + break diff --git a/texts.py b/texts.py new file mode 100644 index 0000000..4cb6843 --- /dev/null +++ b/texts.py @@ -0,0 +1,76 @@ +import gettext +import json +import os + +if not os.path.isfile('setts.json'): + with open('setts.json', 'w') as file: + data = {"settings": {"theme": "Dark", + "p": "270", + "h": "3", + "d": "1.5", + "st": "1500", + "mk": "1000", + "a": "0", + "spi": "3", + "marg": "0", + "locale": "Ru", + "currency": "руб."}} + json.dump(data, file, indent=2) + +with open('setts.json') as file: + old_data = json.load(file) + if old_data['settings']["locale"] == 'English': + locale = 'en_US' + else: + locale = 'ru_RU' + +lang = gettext.translation('locale', localedir='locale', languages=[locale]) +lang.install() +_ = lang.gettext + +calc = (_("Формула расчета стоимости печати выглядит так:\n\n" + "S = ((p/1000*t/60*h)+(md*d*st/mk)+am+post))*x+mod\n\n" + "где:\n" + "S - стоимость печати, руб.\n" + "p - мощность принтера, Вт\n" + "t - время печати, мин.\n" + "h - тариф на электроэнергию, кВт/ч\n" + "md - вес детали, гр.\n" + "st - стоимость катушки пластика, руб.\n" + "mk - вес пластика в катушке, гр.\n" + "d - коэффициент выбраковки\n" + "am - амортизация, руб.\n" + "post - стоимость постобработки, руб.\n" + "х - количество печатаемых дубликатов, шт.\n" + "mod - стоимость моделирования, руб.\n\n" + "При этом в расчете вес детали, умножается на 1.5,\n" + "это сделано для выбраковки и тестовой печати," + "т.е. при калькуляции вес одной детали для печати\n" + "считается как 1,5 детали " + "Можете изменить этот пункт в настройках.\n\n")) + +about = (_("По вопросам и предложениям писать в телеграм на @RisenYT\n\n")) + +amortization_calc = (_('Как считается амортизация:\n\n' + 'Отчисления записываются \n' + 'частями в зависимости от времени \n' + 'печати конкретного изделия\n' + 'Рекомендую задавать СПИ (это время\n' + 'окупаемости принтера) 3 года.\n' + 'Калькулятор считает амортизацию в\n' + 'минуту и умножает на количество минут,\n' + 'которые принтер будет печатать.')) + +not_connect = (_('Невозможно проверить обновление.\n\n' + 'Отсутствует подключение к интернету\n' + 'или программа заблокирована фаерволом.\n\n' + 'Для продолжения работы нажмите "Ok"')) + +new_sets = (_('Задайте стоимость принтера, \n' + 'срок полезного использования\n' + 'в настройках амортизации\n')) + +new_marge = (_('Задайте процент желаемой наценки\n' + 'в настройках (можно просто проставить ноль)')) + +ver = '0.6.4' diff --git a/update.py b/update.py new file mode 100644 index 0000000..6d21427 --- /dev/null +++ b/update.py @@ -0,0 +1,90 @@ +import requests +import webbrowser +import json +import PySimpleGUI as Sgi +import gettext + +from texts import ver +from setts import language + + +lang = gettext.translation('locale', localedir='locale', languages=[language()]) +lang.install() +_ = lang.gettext + + +def upd_check(): + with open('setts.json') as json_file: + data = json.load(json_file) + set_theme = data["settings"]["theme"] + + version_new = requests.get('https://risenhome.xyz/feed/Risen.json').json()["version"]["ver"] + version_old = ver + + if version_new > version_old: + + Sgi.theme(set_theme) + layout = [ + [Sgi.Text(_("Обновление"))], + [Sgi.Text(_("Вышла новая версия программы\nНужно обновиться"))], + [Sgi.Button(_(' Скачать ')), Sgi.Push(), Sgi.Button(_(' Отмена '))] + ] + + window = Sgi.Window(_("Проверка обновления"), layout, modal=True) + + while True: + event, button = window.read() + if event == _(' Скачать '): + webbrowser.open('https://risenhome.xyz/calc.html', new=2, autoraise=True) + window.close() + elif event == _(' Отмена '): + window.close() + elif event == "Exit" or event == Sgi.WIN_CLOSED: + break + else: + Sgi.theme(set_theme) + layout = [ + [Sgi.Text(_('Последняя версия: ')+f'{version_new}'+_('\nВаша версия: ')+f'{version_old}'+_('\n\n' + 'Обновление не' + ' требуется'))], + [Sgi.Button(_(' Закрыть '))] + ] + + window = Sgi.Window(_("Проверка обновления"), layout, modal=True) + + while True: + event, button = window.read() + if event == _(' Закрыть '): + window.close() + elif event == "Exit" or event == Sgi.WIN_CLOSED: + break + + +# def upd_start(): +# with open('setts.json') as json_file: +# data = json.load(json_file) +# set_theme = data["settings"]["theme"] +# +# version_new = requests.get('https://risenhome.xyz/feed/Risen.json').json()["version"]["ver"] +# version_old = ver +# +# if version_new > version_old: +# +# Sgi.theme(set_theme) +# layout = [ +# [Sgi.Text(_("Обновление"))], +# [Sgi.Text(_("Вышла новая версия программы\nНужно обновиться"))], +# [Sgi.Button(_(' Скачать ')), Sgi.Push(), Sgi.Button(' Отмена ')] +# ] +# +# window = Sgi.Window(_("Вышла новая версия!"), layout, modal=True) +# +# while True: +# event, button = window.read() +# if event == _(' Скачать '): +# webbrowser.open('https://risenhome.xyz', new=2, autoraise=True) +# window.close() +# elif event == _(' Отмена '): +# window.close() +# elif event == "Exit" or event == Sgi.WIN_CLOSED: +# break