03 июля | 2024г. | 07:15:25


АвторТема: Пишем плагин сами или случайные уроки по python  (Прочитано 83303 раз)

0 Пользователей и 3 Гостей смотрят эту тему.

Оффлайн ака УчкунАвтор темы

  • Рыцарь Джедай
  • *****
  • Забанен!
  • Сообщений: 1098
  • Поблагодарили: 4787
  • Уважение: +49
Продолжаем.

Напоминаю полученный на этот момент код плагина

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.      
Ну и кроме того, коды по сохранению настроек и применению настроек, которые мы в самом начале разработали, держим пока в уме (они сохранены на диске)......

Из этого кода например из части действий нажатия кнопок думаю вы поняли, что вот эти три ключа "cancel", "back", "red" это разновидности красной кнопки в разных имиджах и в разных ресах. В некоторых ресах есть еще и кнопка "назад" например........

Разработаем конструкцию самого окна-меню плагина.
В принципе это уже не питон.
Это уже xml.
То есть нужно разработать окно-Screen этого плагина для скина.
Это уже чисто построение каркаса в скиностроении.
Поэтому подробно показывать как построил каркас на основе уже готовых виджетов в инструкции __init__ не буду. Как строить каркасы в скинах читайте в другом FAQ здесь FAQ: Переделка скина для начинающих
Поясню только основное.
Каркас для скина размещается в самом начале класса, то есть сразу за заглавием класса
class NimSettings(Screen):
и синтаксис такой: переменной skin присваивается весь текст-каркас этого окна.
Ну то есть
skin = каркас_скина
Только так как каркас скина это многострочный текст, по правилам питона он берется в тройные кавычки
"""каркас_скина_в_виде_многострочного_текста"""

Вобщем создаем каркас окна-Screen с названием точно таким же как название класса (это обязательно), title можем пустой оставить или написать что угодно(все равно применится self.setTitle), атрибуты (размер скина, расположение на экране) придумываем как нам нужно, и добавляем все виджеты (красную кнопку, виджет меню, виджет текст) из инструкции  __init__
Я обычно строю каркас плагина в окне e2skinner.
Беру какой-нибудь похожий каркас и меняю там виджеты на свои.
Здесь главное не ошибится например в сурчах.
Вот к примеру кнопку можно оформить как через компонент Label, то есть так (как в нашем примере):
Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.а можно и через сурч StaticText, то есть так:
Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
В первом случае сам виджет в каркасе будет выглядеть так, просто через name =...:
Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.А во втором случае это будет через source и через рендер, так:
Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
Тонкости совсем несложные, думаю быстро разберетесь.
А меню само будем строить через рендер ListBox и с помощью TemplatedMultiContent
Вобщем итого получаем такой код вместе с хмл, то есть с каркасом:

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.

Спойлер   :
На самом деле конечно, здесь очень много нюансов, как впрочем вообще в плагиностроении.....
Этот самый каркас, разработанный нами, не обязательно будет применен в имидже.
Для парсера в имидже, более приоритетное значение имеет текущий скин.
То есть если текущем скине есть окно-Screen с этим названием (с названием этого класса), то будет применено
именно окно-Screen из текущего скина.
Также можно вообще не разрабатывать окно-Screen, а воспользоваться одним из универсальных
окон-Screen. Например универсальное окно Setup в имидже Пли, в котором даже есть description
как знаете. В том случае естественно нужно название виджетов привести в соответствии с
тим окном Setup. Но мы в нашем случае никак не могли воспользоваться этим окном Setup,
так как там меню конфиговое, а у нас нет......


      
Пришла очередь разработать функции self.cancel, self.action, self.createList.
Сначала createList, то есть меню плагина, оно пока пустое.
С помощью встроенного атрибута append добавляем в этот пустой список два пункта, а затем
этот уже непустой список передаем в качестве аргумента методу setList модуля List (чтобы понять, изучите
импортированный нами List из папки Sources), то есть так:

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.   
Разберем каждую строчку снова.
nashemenu = []     # Просто присвоили (снова) пустой список переменной nashemenu
nashemenu.append((_("Save tuner settings"), "save"))  # добавили один элемент списка, то есть попросту первую строчку меню.

Здесь нужно понять вот что. Встроенный метод списков append добавить в список первый атрибут, который мы ему передали,
то есть вот это _("Save tuner settings"), а второй атрибут в данном случае будет просто индексом.
Этот второй атрибут-индекс, в данном случае наша питоновская импровизация, для того чтобы впоследствии
именно по нему, по второму атрибуту-индексу определить собственно в какой строчке нажал кнопку ОК пользователь.
Это именно питоновская импровизация, вы же можете пойти другим путем и определить это дело по-другому,
использую другие богатые возможности питона.
Понимание этого потихоньку придет к вам, если будете вникать в смысл, а не тупо копировать.....
Пока же просто имейте ввиду, что именно по этим двум "словам"-индексам "save" и "restore" мы будем определять,
в какой строчке пользователь нажал кнопку ОК (то есть хочет сохранить настройки или наоборот применить ранее сохраненные).

self["menu"].setList(nashemenu) # Это опять-таки применение метода setList из импортированного модуля List

Чтобы не путаться, пишем снова весь код, который получили

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.      

Следующая функция, это действие, происходящее при нажатии красной кнопки (или exit), то есть функция self.cancel , так как это всего лишь закрытие окна, это самая простая функция:

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
Тут ничего объяснять не надо, close он и в африке close....

Осталась главная функция - это действие, которое будет происходит при нажатии кнопки ОК, то есть функция    self.action

Продолжение следует.....






Добавлено  08 декабря | 2013г. | 12:57:47  








Ну и теперь функция self.action, то есть обработчик событий при нажатии кнопки ОК.
Вот здесь наконец нам понадобится тот самый код, который мы в самом начале разработали.
Это главная функция, которая и составляет смысл нашего плагина.
В качестве аргумента функции, кроме собственно self, создадим аргумент для вычисления выбранного пункта меню и назовем по смыслу currentSelect и по умолчанию присвоим этому аргументу значение "Ложь", то есть так:

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
Попробую пояснить.
Если просто создать аргумент (не приравнивая его к значению "Ложь") и далее проверять какая эта строка, при первом прохождении функции (то есть при первой проверке, на каком пункте курсор) полученное значение будет присвоино этому аргументу и при следующей проверке(если вы это сделали до перезагрузки) поведение будет непредсказуемым, то есть окажется что курсор не на той строчке или на двух строчках сразу (так как предыдущее значение-то не сбросилось, а сохранилось).
Именно чтобы избежать этого, каждый раз при начале проверки, значение переменной-аргумента currentSelect обнуляется и сам код именно поэтому начнем с условия "Если нет выбора"- if currentSelect is None:

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
и высчитываем спокойно текущую строчку:

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
Тут очень просто self["menu"] это как известно из инструкции __init__ и есть импортированный модуль List, а у этого модуля есть метод для вычисления текущей строки getCurrent() (проверяйте это, открыв и изучив сам модуль List). А [1] - это как мы знаем по питону, простое "выдергивание" первого индекса из элемента. Также по питону знаем, что индексация начинается с нуля, то бишь элемент номер 1 - это на самом деле второй элемент, так как первым является нулевой элемент. То есть вышенаписанный код находит, что текущая строка это -(_("Save tuner settings"), "save")
Здесь индекс 0 - _("Save tuner settings"), а индекс 1 - "save".
Так как мы запросили индекс 1 (а не индекс 0), то есть [1], мы получаем строку "save"

Соответственно если курсор стоит на второй строчке, к нам вернется строка "restore".
Все логично и очень просто.


Спойлер   :
Вот для этого мы и придумывали индексы при добавлении строк к списку.
Но еще раз повторюсь, это импровизация, и это разумеется не единственный способ выяснить на какой строчке находится курсор. Если включите логику, можно симпровизировать и какой-нибудь другой, может еще более логичный способ сделать это. В любом случае в такой импровизации всегда гораздо больше логики, чем углубленных знаний питона на самом деле. Это еще один аргумент в пользу того, что в программировании логичность мышления программиста имеет первостепеннное значение.......

Вот полученный код этой функции пока:

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.         
Далее еще проще. Если полученное значение "save", то понятное дело это означает что пользователь потребовал сохранения настроек(нажал кнопку ОК на пункте "Сохранить настройки").
Соответственно написав if selectEntry is "save": за ним пишем тот самый код (из начала урока) по сохранению настроек.
Но прежде чем написать это, рассмотрим варианты.
К примеру ведь может оказаться что пользователь уже сохранял настройки (в заранее указанную папку).
Либо пользователь случайно нажал кнопку ОК в этой строчке, а на самом деле хотел нажать на другой строчке. Конечно можем на все эти обстоятельства плюнуть и всегда сохранять настройки в файл (если уже есть перезапишется). Но это неумно и не защищает пользователя от ошибочного нажатия кнопки ОК.
Поэтому напишем код таким образом (просто добавится еще одно вложение - а существует ли файл уже):
if currentSelect is "save":
   if fileExists(путь_к_файлу + 'имя_файла'):

   
В коде появилось что-то новое. Разберем по порядку.
Здесь воспользовались методом fileExists, который мы не будем сами разрабатывать, а как всегда "одолжим" у существующего модуля в имидже Directories (из папки Tools).
Если интересно узнать (должно быть интересно, если хотим расти), как работает этот метод, идем по пути /usr/lib/enigma2/python/Tools/ и открывая модуль
Directories - изучаем там содержимое метода. Этот метод просто проверяет наличие или отстутвие файла, который ему передан в качестве аргумента.
Конечно обязательно импортируем модуль в начале кода плагина:
Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.Теперь самое время нам разобраться с этим
путь_к_файлу + 'имя_файла'
Определимся куда будем сохранять файл настроек. Для этого сначала придумаем название нашему плагу. Пусть будет по смыслу так - TunerSettingsRestore.
И создадим внутри плагина папку backup и сохраним туда настройки.
Плагин наш будет находится в папке Extensions, сам файл пусть как первоначально придумали назовем mysettings, соответственно получаем:
iВам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.   
Или весь код сначала с учетом импорта:

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
А код функции action пока приняла этот вид:

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
Итак, что же делать, если файл уже существует?
Надо предоставить пользователю выбор, либо вернуться в меню плагина, либо, если он хочет, перезаписать файл.
Для этого вызовем окно выбора с помощью встроенного метода openWithCallback и существующего в имидже модуля MessageBox.
Для начала выполним необходимый импорт нужного нам модуля.
Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.Первым аргументом у метода openWithCallback идет название функции (назовем saveset), которая будет выполнена при положительном ответе (при отрицательном просто выход из окна назад). а вторым аргументом мы ему передадим импортированный  MessageBox, а далее уже аргументы соответственно самого MessageBox.
Открываем модуль MessageBox по пути /usr/lib/enigma2/python/Screens/ и из его метода __init__ узнаем какие атрибуты ему нужны. Для наглядности приведу эти аргументы:
(self, session, text, type = TYPE_YESNO, timeout = -1, close_on_any_key = False, default = True, enable_input = True, msgBoxID = None, picon = None, simple = False, list = [])
Как видим ему обязательно нужно передать только сам собственно text, а остальные аргументы имеют значения по умолчанию и если мы не собираемся их менять, то можно их вообще не указывать.
По порядку:

а) Как text передадим _("Backup file is already exists!\nDo you want rewrite backup file?"), думаю понятно (знак \n - просто перенос строки)
б) type = TYPE_YESNO, нас вполне устраивает, нам нужен именно тип TYPE_YESNO, значит пропускаем.
в) timeout = -1, а вот это непорядок (-1 означает нет), ставим таймаут 6 секунд timeout = 6,
г) close_on_any_key = False, устраивает, мы не собираемся закрыть окно любой кнопкой
д) default = True, вот здесь надо подумать, True здесь означает, что курсор будет на строчке - "да", мы
поставим на строчку "нет" на всякий пожарный, чтобы уберечь пользователя от ошибок, то есть default = False,
е) остальные атрибуты вообще не трогаем и оставляем по умолчанию.

И получаем такой вызов окна:

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.Обратите внимание, мы вообще не указали тип окна YESNO или другой, просто в данном случае нам нужен именно YESNO, а он применется по умолчанию, если нужен другой тип окна, тогда нужно указывать...
Дополнительную нужную функцию self.saveset разработаем после того, как закончим с функцией action.

То есть понятно, выведя окно сообщения, мы спросили у пользователя, что настройки бекапа уже существуют, нужно ли их перезаписать, и по умолчанию поставили курсор на ответе "нет", на всякий случай.....
При ответе "да" будет запущена функция self.saveset, которая перезапишет настройки (разработаем впоследствии), при ответе "нет" возврат в предыдущее окно.

Полученный код функции:

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
Далее код, если файл не существует. Здесь за условием else: (то бишь если файл не существует) запишем какраз таки от самый код сохранения настроек, который мы разрабатывали  самом начале, то есть так:

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
Только естественно теперь указали путь сохранения настроек туда, куда нам надо, то есть /usr/lib/enigma2/python/Plugins/Extensions/TunerSettingsRestore/backup/
               
И далее, восстановление настроек, то есть если нажата ОК в строчке с сохранением настроек, то есть с индексом "restore", то есть:

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
Здесь тоже нужно придумать часть (которую программисты называют "защитой от дураков"), например для случая, если собственно сохраненного файла настроек-то нет, а также, в случае если даже и есть такие настройки, еще раз спросить пользователя, дейчтвительно ли хочет....
Как вы понимаете, если файла настроек нет, то и нечего восстанавливать.
Поэтому проверим наличие файла и при отсутствии оного, просто покажем сообщение, что этого файла нет и вернемся в предыдущее окно.
Воспользуемся другим встроенным методом текущей сессии open и также тем же модулем MessageBox.
Метод open текущей сессии требует только аргумент с названием окна (MessageBox) и далее также управление передается собственно модулю MessageBox.
И так как на этот раз нам нужен другой тип окна TYPE_INFO(а не который по умолчанию), на этот раз явно укажем этот тип. И получим такой код вызова окна сообщения:

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
Спойлер   :
Этот код звучит так: "Если нажата кнопка ОК в строчке восстановления, и если файла бекапа не существует, то вывести сообщение что этого файла нет и все"

Далее если тот файл есть выводим сообщение, что сейчас будет имидж остановлен (тем самым скриптом), и перезапущен с новыми настройками, но пользователь может отменить и передумать.
То есть это будет опять метод openWithCallback, функцию, которую он запустить при положительном ответе, назовем self.restoreset, остальное вы уже по типу пройденного поймете:

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
Функция self.restoreset будет находиться за пределами функции self.action, поэтому разработаем ее после.

Итого, теперь весь полученный нами код нашего плагина на этот момент:

Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
               
Остается в классе разработать дополнительно появившиеся функции self.saveset и self.restoreset.

Продолжение следует....

 


  • vu+ultimo 9995
Мои авторские работы  нельзя редактировать для выкладывания на паблик.
Но их можно выкладывать неизмененными на любых ресурсах с указанием авторства
Мои кошельки:
WMZ     Z356196865451 WMR     R105983132832

Теги:
 

Похожие темы

  Тема / Автор Ответов Последний ответ
9 Ответов
16062 Просмотров
Последний ответ 14 февраля | 2019г. | 10:01:39
от drakon71
27 Ответов
25738 Просмотров
Последний ответ 04 апреля | 2022г. | 06:06:17
от тихон
1 Ответов
9246 Просмотров
Последний ответ 20 марта | 2014г. | 00:40:50
от Taapat
0 Ответов
3469 Просмотров
Последний ответ 07 апреля | 2014г. | 00:52:47
от 2boom
4 Ответов
4844 Просмотров
Последний ответ 03 апреля | 2016г. | 16:49:33
от Corwin



X

Добро пожаловать!

Мы заметили, что у Вас установлено расширение AdBlock или ему подобное. Пожалуйста добавьте наш Клуб в белый список, внесите этим посильную лепту в его развитие. Спасибо!