def create_stage(self, argv): style = Mx.Style.get_default() style.load_from_file(res.get("style.css")) script = Clutter.Script() script.load_from_file(res.get("script.json")) print(script.list_objects()) return script.get_object("stage")
def get_json_path(app, view, content='default'): """ Get a json file responsible for building one of the views of the given application. Shape of the view is described by 'content' parameter. Hierarchy of directories being scanned in search for the proper file is as follows: first the pisak directory in user's home, then json directory in res for the specific content and finally json directory in res for the default content. Structure of json related directories: in pisak folder in user's home - 'json' folder with subfolders for different applications, each named as the corresponding application, then in each of them subfolders for specific 'content' with 'json' extended files inside; in res directory - the same as for the home. :param app: name of the application :param view: name of the view :param content: name of the content of the view or None for default content :returns: path to the json file """ # check home pisak dir view_path = os.path.join(HOME_JSON_DIR, app, content, view) + ".json" # if none has been found look in res directory: if not os.path.isfile(view_path): json_dir = res.get(os.path.join("json", app, content)) view_path = os.path.join(json_dir, view) + ".json" if not os.path.isfile(view_path) and content is not "default": default_json_dir = res.get(os.path.join("json", app, "default")) view_path = os.path.join(default_json_dir, view) + ".json" if not os.path.isfile(view_path): msg = "Default json for '{}' view of the '{}' not " \ "found in the res directory." raise FileNotFoundError(msg.format(view, app)) return view_path
def _load_image(self): pixbuf = GdkPixbuf.Pixbuf.new_from_file(res.get(self.image_res_path)) self.background_image.set_data(pixbuf.get_pixels(), Cogl.PixelFormat.RGBA_8888, pixbuf.get_width(), pixbuf.get_height(), pixbuf.get_rowstride())
def find_path(folder1, folder2, file_name, with_raise=False, custom_msg=''): """ Helper function to check if the file is in one folder or the other. :param folder1: str, full path to user folder to check :param folder2: str, name of folder in PISAK res folder in which to check :param file_name: str, name of the file :param with_raise: bool, whether to raise an error or log a warning :param custom_msg: str, custom_msg for the error, should contain two '{}' specifying the places for the file paths :return: path to the found file or None """ msg = custom_msg or 'No such file found as {} or {}.' path = path1 = os.path.join(folder1, file_name) if not os.path.isfile(path1): path = path2 = os.path.join(res.get(folder2), file_name) if not os.path.isfile(path2): msg = msg.format(path1, path2) path = None if with_raise: raise FileNotFoundError(msg) else: _LOG.warning(msg) return path
def get_css_path(skin='default'): """ Get css file with the global style description for the whole program. Hierarchy of directories being scanned in search for the proper file is as follows: first the pisak directory in user's home, then css folder in res. Structure of style related directories: in pisak folder in user's home - 'css' folder with css files named the same as the given skin; in res directory - the same as in the home. :param skin: name of the skin or None for default css :returns: path to css file """ css_path = os.path.join(HOME_STYLE_DIR, skin) + ".css" if not os.path.isfile(css_path): style_dir = res.get("css") css_path = os.path.join(style_dir, skin) + ".css" if not os.path.isfile(css_path) and skin is not "default": css_path = os.path.join(style_dir, "default") + ".css" if not os.path.isfile(css_path): msg = "Default css not found in the res directory." raise FileNotFoundError(msg) return css_path
def _initialize_style(self): # load default style self.style = Mx.Style.get_default() style_path = res.get(self.CSS_RES_PATH) try: self.style.load_from_file(style_path) except GObject.GError: raise Exception("Failed to load default style")
def _configure(self): self.apply_props() self.sound_effects_enabled = self.config.as_bool("sound_effects_enabled") self.sound_effects_volume = self.config.as_float("sound_effects_volume") self.style = dirs.get_css_path(self.config.get("skin")) self.sound_effects = {} for k, v in self.config.get("sound_effects").items(): self.sound_effects[k] = res.get(v)
def get_blog_css_path(): """ Get css file to style Blog posts. """ css_path = HOME_BLOG_STYLE if not os.path.isfile(css_path): css_path = os.path.join(res.get('css'), os.path.split(HOME_BLOG_STYLE)[1]) if not os.path.isfile(css_path): msg = "CSS style file for blog post was not found." raise FileNotFoundError(msg) return css_path
def get_json_path( view, layout='default', app='', ): """ Get a json file responsible for building one of the views of the given application. Shape of the view is described by 'layout' parameter. Hierarchy of directories being scanned in search for the proper file is as follows: first the pisak directory in user's home, then json directory in res for the specific layout and finally json directory in res for the default layout. Structure of json related directories: in pisak folder in user's home - 'json' folder with subfolders for different applications, each named as the corresponding application, then in each of them subfolders for specific 'layout' with 'json' extended files inside; in res directory - the same as for the home. :param view: name of the view :param layout: name of the layout of the view or None for default layout :param app: name of the application or None, when None then general jsons are looked for. :returns: path to the json file """ # check home pisak dir view_path = os.path.join(HOME_JSON_DIR, app, layout, view) + ".json" # if none has been found look in res directory: if not os.path.isfile(view_path): json_dir = res.get(os.path.join("json", app, layout)) view_path = os.path.join(json_dir, view) + ".json" if not os.path.isfile(view_path) and layout is not "default": default_json_dir = res.get(os.path.join("json", app, "default")) view_path = os.path.join(default_json_dir, view) + ".json" if not os.path.isfile(view_path): msg = "Default json for '{}' view of the '{}' application not " \ "found in the res directory." raise FileNotFoundError(msg.format(view, app)) return view_path
def get_general_configs(): """ Get paths to files with general configuration. :returns: list of configuration files, from the most default to the most custom one """ configs = [] default = res.get(os.path.join('configs', 'general.ini')) if os.path.isfile(default): configs.append(default) else: raise FileNotFoundError( "Default general config not found in the res directory.") if os.path.isfile(HOME_MAIN_CONFIG): configs.append(HOME_MAIN_CONFIG) return configs
def get_icon_path(name): """ Get path to an icon with the given name. First look for a custom one in user home directory, if nothing found, then look for a default one in res directory. Accepted file format is SVG. :param name: name of the icon, that is a name of the file containing the icon without an extension. Accepted file format is SVG. :returns: path to the icon or None if nothing was found """ icon_path = os.path.join(HOME_ICONS_DIR, name) + ".svg" if not os.path.isfile(icon_path): icon_path = os.path.join(res.get('icons'), name) + ".svg" if not os.path.isfile(icon_path): msg = "Default icon for '{}' not found in the res directory." raise FileNotFoundError(msg.format(name)) return icon_path
REQUEST_TIMEOUT = 5 # web request duration limit in seconds MESSAGES = widgets.ERROR_MESSAGES ELEMENTS = { "new_message": message.SimpleMessage(), "address_book": address_book.AddressBook(), "imap_client": imap_client.IMAPClient() } VIEWS_MAP = {"new_message_initial_view": "email/speller_message_subject"} BUILTIN_CONTACTS = [{ "name": "PISAK", "address": "*****@*****.**", "photo": res.get("logo_pisak.png") }] def internet_on(): try: response = urllib.request.urlopen('http://216.58.209.67', timeout=1) return True except urllib.error.URLError as err: return False def prepare_main_view(app, window, script, data): """ View preparator.
HOME_EMAIL_ADDRESS_BOOK = os.path.join(HOME_PISAK_DATABASES, "email_address_book.db") """ Database with info about text files generated by the 'speller' application. """ HOME_TEXT_DOCUMENTS_DB = os.path.join(HOME_PISAK_DATABASES, 'documents.db') # ---------------------------------------------------------------------- # Files and folders from the resources directory in the PISAK repository # ---------------------------------------------------------------------- """ Default main configuration file. """ RES_MAIN_CONFIG = res.get(os.path.join('configs', 'default_config.ini')) # --------------------------- # Default system directories # --------------------------- """ Dictionary with paths to various file system default directories. """ USER_FOLDERS = { "desktop": GLib.USER_DIRECTORY_DESKTOP, "documents": GLib.USER_DIRECTORY_DOCUMENTS, "downloads": GLib.USER_DIRECTORY_DOWNLOAD, "music": GLib.USER_DIRECTORY_MUSIC, "pictures": GLib.USER_DIRECTORY_PICTURES,
class CalibrationLabel(widgets.Label, properties.PropertyAdapter): __gtype_name__ = "PisakOBCICalibrationLabel" __gproperties__ = { "with_target": ( GObject.TYPE_BOOLEAN, "", "", False, GObject.PARAM_READWRITE) } FACE_PATH = res.get('piesel.png') def __init__(self): super().__init__() self._non_targets_left = 0 self._previous_targets = 0 self._face = None self._with_target = False self.connect("notify::size", lambda *_: self._rescale_face()) def _rescale_face(self): if self._face is not None: self._face.set_size(*self.get_size()) def _now_target(self): if self._previous_targets > 0: self._previous_targets -= 1 if self._previous_targets == 0: self._non_targets_left = random.randint(0, 5) return False elif self._non_targets_left > 0: self._non_targets_left -= 1 return False else: now_target = random.randint(0, 1) if now_target: self._previous_targets = 2 return True else: return False @property def with_target(self): return self._with_target @with_target.setter def with_target(self, value): self._with_target = value if value and self._face is None: self._face = Mx.Image() self._face.set_from_file(self.FACE_PATH) self._face.set_scale_mode(Mx.ImageScaleMode.FIT) self._face.hide() self.get_parent().add_child(self._face) def enable_hilite(self): self.style_pseudo_class_add('hilited') if self._with_target and self._now_target(): self._face.show() return True else: return False def disable_hilite(self): self.style_pseudo_class_remove('hilited') if self.with_target: self._face.hide()
""" Database with info about text files generated by the 'speller' application. """ HOME_TEXT_DOCUMENTS_DB = os.path.join(HOME_PISAK_DATABASES,'documents.db') # ---------------------------------------------------------------------- # Files and folders from the resources directory in the PISAK repository # ---------------------------------------------------------------------- """ Default main configuration file. """ RES_MAIN_CONFIG = res.get(os.path.join('configs', 'default_config.ini')) # --------------------------- # Default system directories # --------------------------- """ Dictionary with paths to various file system default directories. """ USER_FOLDERS = { "desktop": GLib.USER_DIRECTORY_DESKTOP, "documents": GLib.USER_DIRECTORY_DOCUMENTS, "downloads": GLib.USER_DIRECTORY_DOWNLOAD,
import os from pisak import res from pisak.symboler import database_manager SYMBOLS_DIR = res.get("symbols") def load_all_linear(): symbols = [] for current, _subdirs, files in os.walk(SYMBOLS_DIR): for symbol_path in [os.path.join(current, name) for name in files]: symbols.append(symbol_path) database_manager.insert_many_symbols(symbols)
Paint application main module """ import os import logging from pisak import launcher, res from pisak.paint import widgets, handlers # @UnusedImport def prepare_paint_main_view(stage, script, data): easel = script.get_object("easel") button_start = script.get_object("button_start") if button_start is not None and isinstance(button_start, widgets.Button): button_start.connect("clicked", easel.clean_up) button_start.connect( "clicked", lambda *_: stage.load_view("main_panel/main", None)) VIEWS = { "paint/main": (res.get("json/paint/main.json"), prepare_paint_main_view) } if __name__ == "__main__": logging.basicConfig(level=logging.DEBUG) _paint_app = { "views": VIEWS, "initial-view": "paint/main", "initial-data": None } launcher.run(_paint_app)
_LOG = logger.getLogger(__name__) ELEMENTS = { "new_message": message.SimpleMessage(), "address_book": address_book.AddressBook(), "imap_client": imap_client.IMAPClient() } BUILTIN_CONTACTS = [ { "name": "PISAK", "address": "*****@*****.**", "photo": res.get("logo_pisak.png") } ] def prepare_main_view(app, script, data): handlers.button_to_view(app, script, "button_exit") handlers.button_to_view(app, script, "button_inbox", "email/inbox") handlers.button_to_view(app, script, "button_sent", "email/sent") handlers.button_to_view(app, script, "button_drafts", "email/drafts") handlers.button_to_view( app, script, "button_address_book", "email/address_book") handlers.button_to_view( app, script, "button_new_message", "email/speller_message_subject") for contact in BUILTIN_CONTACTS:
application's views takes place here. """ from pisak import launcher, res from pisak.symboler import data_loader import pisak.symboler.widgets # @UnusedImport import pisak.symboler.handlers # @UnusedImport def prepare_symboler_view(stage, script, data): exit_button = script.get_object("button_exit") if exit_button is not None: exit_button.connect("clicked", lambda *_: stage.load_view( "main_panel/main", None)) VIEWS = { "symboler/main": (res.get("json/symboler/main.json"), prepare_symboler_view) } if __name__ == "__main__": _symboler_app = { "views": VIEWS, "initial-view": "symboler/main", "initial-data": None } data_loader.load_all_linear() launcher.run(_symboler_app)
from pisak import launcher, res def button_to_view(stage, script, button_name, stage_to_load, data=None): button = script.get_object(button_name) if button is not None: button.connect("clicked", lambda *_: stage.load_view(stage_to_load, data)) def prepare_main_panel_view(stage, script, data): button_to_view(stage, script, "button_speller", "speller/main", None) button_to_view(stage, script, "button_viewer", "viewer/library", None) button_to_view(stage, script, "button_paint", "paint/main", None) button_to_view(stage, script, "button_symboler", "symboler/main", None) VIEWS = { "main_panel/main": (res.get("json/main_panel/main.json"), prepare_main_panel_view) } if __name__ == "__main__": _main_panel_app = { "views": VIEWS, "initial-view": "main_panel/main", "initial-data": None } launcher.run(_main_panel_app)
MESSAGES = widgets.ERROR_MESSAGES ELEMENTS = { "new_message": message.SimpleMessage(), "address_book": address_book.AddressBook(), "imap_client": imap_client.IMAPClient(), } VIEWS_MAP = {"new_message_initial_view": "email/speller_message_subject"} BUILTIN_CONTACTS = [{"name": "PISAK", "address": "*****@*****.**", "photo": res.get("logo_pisak.png")}] def prepare_main_view(app, window, script, data): handlers.button_to_view(window, script, "button_exit") handlers.button_to_view(window, script, "button_inbox", "email/inbox") handlers.button_to_view(window, script, "button_sent", "email/sent") handlers.button_to_view(window, script, "button_drafts", "email/drafts") handlers.button_to_view(window, script, "button_address_book", "email/address_book") handlers.button_to_view(window, script, "button_new_message", VIEWS_MAP["new_message_initial_view"]) for contact in BUILTIN_CONTACTS: try: app.box["address_book"].add_contact(contact) except address_book.AddressBookError as e: pass # TODO: notify the user
Main module of the symboler application. Launching and managing all the application's views takes place here. """ from pisak import launcher, res from pisak.symboler import data_loader import pisak.symboler.widgets # @UnusedImport import pisak.symboler.handlers # @UnusedImport def prepare_symboler_view(stage, script, data): exit_button = script.get_object("button_exit") if exit_button is not None: exit_button.connect( "clicked", lambda *_: stage.load_view("main_panel/main", None)) VIEWS = { "symboler/main": (res.get("json/symboler/main.json"), prepare_symboler_view) } if __name__ == "__main__": _symboler_app = { "views": VIEWS, "initial-view": "symboler/main", "initial-data": None } data_loader.load_all_linear() launcher.run(_symboler_app)
from pisak import launcher, res def prepare_speller_view(stage, script, data): exit_button = script.get_object("button_exit") if exit_button is not None: exit_button.connect( "clicked", lambda *_: stage.load_view("main_panel/main", None)) VIEWS = { "speller/main": (res.get("json/speller/combined.json"), prepare_speller_view) } if __name__ == "__main__": _speller_app = { "views": VIEWS, "initial-view": "speller/main", "initial-data": None } launcher.run(_speller_app)
""" import os import logging from pisak import launcher, res from pisak.paint import widgets, handlers # @UnusedImport def prepare_paint_main_view(stage, script, data): easel = script.get_object("easel") button_start = script.get_object("button_start") if button_start is not None and isinstance (button_start, widgets.Button): button_start.connect("clicked", easel.clean_up) button_start.connect("clicked", lambda *_: stage.load_view( "main_panel/main", None)) VIEWS = { "paint/main": (res.get("json/paint/main.json"), prepare_paint_main_view) } if __name__ == "__main__": logging.basicConfig(level=logging.DEBUG) _paint_app = { "views": VIEWS, "initial-view": "paint/main", "initial-data": None } launcher.run(_paint_app)
def _generate_sounds(self): loc = res.get(os.path.join("sounds", "dj", self.category)) for file in os.listdir(loc): self.sounds.append(self.sound_type(os.path.join(loc, file), os.path.splitext(file)[0]))
library_data = script.get_object("library_data") library_data.tiles_handler = lambda tile, album: stage.load_view( "viewer/album", {"album_id": album}) button_to_stage(stage, script, "button_start", "main_panel/main") def prepare_photo_editing_view(stage, script, data): photo = script.get_object("slide") photo.photo_path = data[0].slide.photo_path button_to_stage(stage, script, "button_photo", "viewer/photo", {"photo_id": data[2], "album_id": data[1]}) button_to_stage(stage, script, "button_start", "main_panel/main") VIEWS = { "viewer/photo": (res.get("json/viewer/photo.json"), prepare_photo_view), "viewer/album": (res.get("json/viewer/album.json"), prepare_album_view), "viewer/library": (res.get("json/viewer/library.json"), prepare_library_view), "viewer/photo_editing": (res.get("json/viewer/photo_editing.json"), prepare_photo_editing_view) } if __name__ == "__main__": logging.basicConfig(level=logging.DEBUG) _viewer_app = { "views": VIEWS, "initial-view": "viewer/library", "initial-data": None } launcher.run(_viewer_app)
#!/usr/bin/python3 # -*- coding: utf-8 -*- import platform import pressagio.callback import pressagio try: import configparser except ImportError: import ConfigParser as configparser from pisak import res _DB_PATH = res.get("n_grams.sqlite") _CONFIG_FILE = res.get("configs/predictor.ini") _CONFIG_PARSER = configparser.ConfigParser() _CONFIG_PARSER.read(_CONFIG_FILE) _CONFIG_PARSER["Database"]["database"] = _DB_PATH def get_predictions(string): callback = CallbackClass(string) predictions = pressagio.Pressagio(callback, _CONFIG_PARSER).predict() if string.rstrip().split()[-1][0].isupper( ) and string[-1] != ' ': # capital letters are handled here
import os import configobj import ezodf from pisak import res, logger from pisak.libs import dirs _LOG = logger.getLogger(__name__) SYMBOLS_DIR = res.get("symbols") def create_model(): """ Extract information about all files with symbols from the default symbols directory. Every symbol will be represented as a list consisting of a path to the symbol file and a text assigned to it. Create or update file with their specification and hierarchy. Any changes applied previously to the records in the spec file will not be overwritten. """ model = configobj.ConfigObj(dirs.HOME_SYMBOLS_MODEL, encoding='UTF8') items = model.keys() if "ALL" not in items: model["ALL"] = {} main_section_items = model["ALL"].keys() for current, _subdirs, files in os.walk(SYMBOLS_DIR): if current is not SYMBOLS_DIR:
""" Module for managing database with symbols. """ from contextlib import contextmanager from sqlalchemy import Column, String, Table, ForeignKey, Integer, \ create_engine from sqlalchemy import orm from sqlalchemy.ext.declarative import declarative_base from pisak import res _SYMBOLS_DB_PATH = res.get("symbols.db") _ENGINE_URL = "sqlite:///" + _SYMBOLS_DB_PATH _Base = declarative_base() class Symbol(_Base): __tablename__ = "symbols" id = Column(Integer, primary_key=True) path = Column(String, unique=True, nullable=False) text = Column(String, nullable=True) categories = orm.relationship("Category", secondary="symbol_category_link", collection_class=set, backref=orm.backref( "categories", lazy='noload', passive_updates=False))
import os import platform import pressagio.callback import pressagio try: import configparser except ImportError: import ConfigParser as configparser from pisak import res _DB_PATH = res.get("n_grams.sqlite") _CONFIG_FILE = res.get("configs/predictor.ini") _CONFIG_PARSER = configparser.ConfigParser() _CONFIG_PARSER.read(_CONFIG_FILE) _CONFIG_PARSER["Database"]["database"] = _DB_PATH def get_predictions(string): callback = CallbackClass(string) predictions = pressagio.Pressagio(callback, _CONFIG_PARSER).predict() if string.rstrip().split()[-1][0].isupper() and string[-1] != ' ': # capital letters are handled here predictions = [p[0].upper() + p[1:] for p in predictions] if string in predictions:
""" Module for managing database with symbols. """ from contextlib import contextmanager from sqlalchemy import Column, String, Table, ForeignKey, Integer, \ create_engine from sqlalchemy import orm from sqlalchemy.ext.declarative import declarative_base from pisak import res _SYMBOLS_DB_PATH = res.get("symbols.db") _ENGINE_URL = "sqlite:///" + _SYMBOLS_DB_PATH _Base = declarative_base() class Symbol(_Base): __tablename__ = "symbols" id = Column(Integer, primary_key=True) path = Column(String, unique=True, nullable=False) text = Column(String, nullable=True) categories = orm.relationship("Category", secondary="symbol_category_link", collection_class=set, backref=orm.backref("categories", lazy='noload', passive_updates=False))
""" Module with widgets specific to pisak main panel """ import os.path from gi.repository import Mx from pisak import widgets, res LOGO_PATH = res.get("logo_pisak.png") class Button(widgets.Button): """ Main panel button that can be styled by CSS. """ __gtype_name__ = "PisakMainPanelButton" class PisakLogo(Mx.Image): """ Widget displaying PISAK project logo. """ __gtype_name__ = "PisakLogo" def __init__(self): super().__init__() self.set_from_file(LOGO_PATH)
from pisak import launcher, res def prepare_speller_view(stage, script, data): exit_button = script.get_object("button_exit") if exit_button is not None: exit_button.connect("clicked", lambda *_: stage.load_view( "main_panel/main", None)) VIEWS = { "speller/main": (res.get("json/speller/combined.json"), prepare_speller_view) } if __name__ == "__main__": _speller_app = { "views": VIEWS, "initial-view": "speller/main", "initial-data": None } launcher.run(_speller_app)