Beispiel #1
0
def main():
    global screen
    print("Nerd Tabu")
    # Parse command line
    parser = argparse.ArgumentParser()
    parser.add_argument('quizfile', type=argparse.FileType('r'), help='Name of the quiz file')
    parser.add_argument('teamA', nargs='?', metavar='teamname_A', default='Team A', help='Name of team A')
    parser.add_argument('teamB', nargs='?', metavar='teamname_B', default='Team B', help='Name of team B')
    parser.add_argument('-d', '--datadir', default='.', help='Resource directory')
    parser.add_argument('-f', '--fullscreen', help='Run fullscreen', action='store_true')
    args = parser.parse_args()
    # Update settings
    settings = Settings(args.quizfile, args.datadir)
    settings.teams = [ args.teamA, args.teamB ]
    theme = Theme(args.datadir)
    # Initial game data
    cards = settings.get_random_cards()
    current_team = 0
    # Main game loop
    pygame.init()
    if args.fullscreen:
        # screen = pygame.display.set_mode(theme.screen_size, pygame.FULLSCREEN)
        screen = pygame.display.set_mode(theme.screen_size, pygame.RESIZABLE | pygame.NOFRAME)
    else:
        screen = pygame.display.set_mode(theme.screen_size)
    theme.load_data()
    while len(cards)>0:
        team_get_ready(theme, settings, current_team)
        play_round(theme, settings, current_team, cards)
        current_team = (current_team + 1) % len(settings.teams)
    show_final_scores(theme, settings)
    pygame.quit()
Beispiel #2
0
    def read_config(self, path):
        """parse alot's config file from path"""
        spec = os.path.join(DEFAULTSPATH, 'alot.rc.spec')
        newconfig = read_config(path, spec,
                                checks={'mail_container': mail_container,
                                        'force_list': force_list,
                                        'align': align_mode,
                                        'attrtriple': attr_triple,
                                        'gpg_key_hint': gpg_key})
        self._config.merge(newconfig)

        hooks_path = os.path.expanduser(self._config.get('hooksfile'))
        try:
            self.hooks = imp.load_source('hooks', hooks_path)
        except:
            logging.debug('unable to load hooks file:%s' % hooks_path)
        if 'bindings' in newconfig:
            newbindings = newconfig['bindings']
            if isinstance(newbindings, Section):
                self._bindings.merge(newbindings)
        # themes
        themestring = newconfig['theme']
        themes_dir = self._config.get('themes_dir')
        if themes_dir:
            themes_dir = os.path.expanduser(themes_dir)
        else:
            configdir = os.environ.get('XDG_CONFIG_HOME',
                                       os.path.expanduser('~/.config'))
            themes_dir = os.path.join(configdir, 'alot', 'themes')
        logging.debug(themes_dir)

        # if config contains theme string use that
        if themestring:
            if not os.path.isdir(themes_dir):
                err_msg = 'cannot find theme %s: themes_dir %s is missing'
                raise ConfigError(err_msg % (themestring, themes_dir))
            else:
                theme_path = os.path.join(themes_dir, themestring)
                try:
                    self._theme = Theme(theme_path)
                except ConfigError as e:
                    err_msg = 'Theme file %s failed validation:\n'
                    raise ConfigError((err_msg % themestring) + e.message)

        # if still no theme is set, resort to default
        if self._theme is None:
            theme_path = os.path.join(DEFAULTSPATH, 'default.theme')
            self._theme = Theme(theme_path)

        self._accounts = self._parse_accounts(self._config)
        self._accountmap = self._account_table(self._accounts)
Beispiel #3
0
    def __init__(self, group, class_group=None,
                 desktop_entry=None, identifier=None):
        self.dockbar_r = weakref.ref(group.dockbar_r())
        self.theme = Theme()
        self.globals = Globals()
        connect(self.globals, "color-changed", self.reset_surfaces)
        self.desktop_entry = desktop_entry
        self.identifier = identifier
        self.class_group = class_group

        # Setting size to something other than zero to
        # avoid crashes if surface_update() is runned
        # before the size is set.
        self.size = 15

        self.icon = None
        self.surfaces = {}

        self.average_color = None

        self.max_win_nr = self.theme.get_windows_cnt()
        self.types_in_theme = 0
        for type in self.theme.get_types():
            if not type in self.TYPE_DICT:
                continue
            self.types_in_theme = self.types_in_theme | self.TYPE_DICT[type]
Beispiel #4
0
 def __init__(self):
   """
   Attributes
   ----------
   metadata: dict
     presentation metadata; each element of the dictionary if a dict with ['value', 'user'] items: value contains
     the metadata value and user indicates if the value comes from user (if True) or from defaults (if False).
   """
   self.reset()
   self.metadata = {'title': Metadata(name='title', value=''),
                    'subtitle': Metadata(name='subtitle', value=''),
                    'authors': Metadata(name='authors', value=[]),
                    'authors_short': Metadata(name='authors_short', value=[]),
                    'emails': Metadata(name='emails', value=[]),
                    'affiliations': Metadata(name='affiliations', value=[]),
                    'affiliations_short': Metadata(name='affiliations_short', value=[]),
                    'logo': Metadata(name='logo', value=''),
                    'timer': Metadata(name='timer', value=''),
                    'location': Metadata(name='location', value=''),
                    'location_short': Metadata(name='location_short', value=''),
                    'date': Metadata(name='date', value=''),
                    'conference': Metadata(name='conference', value=''),
                    'conference_short': Metadata(name='conference_short', value=''),
                    'session': Metadata(name='session', value=''),
                    'session_short': Metadata(name='session_short', value=''),
                    'max_time': Metadata(name='max_time', value='25'),
                    'total_slides_number': Metadata(name='total_slides_number', value=''),
                    'dirs_to_copy': Metadata(name='dirs_to_copy', value=[]),
                    'toc': Metadata(name='toc', value=OrderedDict()),
                    'toc_depth': Metadata(name='toc_depth', value='2'),
                    'chaptertitle': Metadata(name='chaptertitle', value=''),
                    'chapternumber': Metadata(name='chapternumber', value=''),
                    'sectiontitle': Metadata(name='sectiontitle', value=''),
                    'sectionnumber': Metadata(name='sectionnumber', value=''),
                    'subsectiontitle': Metadata(name='subsectiontitle', value=''),
                    'subsectionnumber': Metadata(name='subsectionnumber', value=''),
                    'slidetitle': Metadata(name='slidetitle', value=''),
                    'slidenumber': Metadata(name='slidenumber', value=''),
                    'css_overtheme': Metadata(name='css_overtheme', value=[]),
                    'custom': Metadata(name='custom-[0-9]*', value='')}
   self.theme = Theme()
   self.parser = Parser()
   self.chapters = []
   self.position = Position()
   return
Beispiel #5
0
 def __init__(self, number, position=None, title=None, contents=None):
   """"
   Paramters
   ---------
   number: int
     slide global numeration
   position: dict
     position dictionary containing {'x': posx, 'y': posy, 'z': posz, 'rotx': rotx, 'roty': roty, 'rotz': rotz, 'scale': scaling}
   title: str
   contents: str
   """
   self.number = number
   self.position = None
   self.set_position(position)
   self.title = title
   self.contents = contents
   self.overtheme = Theme()
   return
Beispiel #6
0
    def __init__(self, liststore):
        self.liststore = liststore

        self.gui = gui = Gtk.Builder()
        gui.add_from_file(SHARED_DATA_FILE("gfeedline.glade"))

        self.window = window = gui.get_object("main_window")
        self.column = MultiColumnDict(gui)  # multi-columns for Notebooks
        self.theme = Theme()
        self.font = FontSet()
        self.notification = StatusNotification(liststore)

        dnd_list = [Gtk.TargetEntry.new("text/uri-list", 0, 1), Gtk.TargetEntry.new("text/x-moz-url", 0, 4)]
        window.drag_dest_set(Gtk.DestDefaults.ALL, dnd_list, Gdk.DragAction.COPY)

        target = Gtk.TargetList.new([])
        target.add(Gdk.Atom.intern("text/x-moz-url", False), 0, 4)
        target.add(Gdk.Atom.intern("text/uri-list", False), 0, 1)

        window.drag_dest_set_target_list(target)
        window.connect("drag-data-received", self.on_drag_data_received)

        SETTINGS.connect("changed::window-sticky", self.on_settings_sticky_change)
        self.on_settings_sticky_change(SETTINGS, "window-sticky")

        SETTINGS_VIEW.connect("changed::theme", self.on_settings_theme_change)
        self.on_settings_theme_change(SETTINGS_VIEW, "theme")

        is_multi_column = SETTINGS_VIEW.get_boolean("multi-column")
        menuitem_multicolumn = gui.get_object("menuitem_multicolumn")
        menuitem_multicolumn.set_active(is_multi_column)

        menuitem_update = MenuItemUpdate(gui, liststore)

        x, y, w, h = self._get_geometry_from_settings()
        #        window.show() # for wrong position when auto-start

        if x >= 0 and y >= 0:
            window.move(x, y)

        window.resize(w, h)
        window.show()

        gui.connect_signals(self)
Beispiel #7
0
    def __init__(self, parent, connection):
        BasePane.__init__(
            self, parent, connection, style=wx.TE_AUTO_URL | wx.TE_READONLY | wx.TE_NOHIDESEL | wx.TE_MULTILINE
        )

        # state toggles for ANSI processing
        self.intensity = ""
        self.inverse = False

        self.theme = Theme()

        # TODO - this probably should be a preference, but for now, this is the
        # least-bad default behavior.
        self.Bind(wx.EVT_SIZE, self.on_size)
        self.Bind(wx.EVT_SET_FOCUS, self.focus_input)
        self.Bind(wx.EVT_TEXT_URL, self.process_url_click)
        self.Bind(wx.EVT_MIDDLE_DOWN, self.connection.input_pane.paste_from_selection)
        self.Bind(rtc.EVT_RICHTEXT_SELECTION_CHANGED, self.copy_from_selection)
        self.Bind(EVT_ROW_COL_CHANGED, self.on_row_col_changed)
Beispiel #8
0
    def __init__(self, alot_rc=None, notmuch_rc=None, theme=None):
        """
        :param alot_rc: path to alot's config file
        :type alot_rc: str
        :param notmuch_rc: path to notmuch's config file
        :type notmuch_rc: str
        :theme: path to initially used theme file
        :type theme: str
        """
        self.hooks = None
        self._mailcaps = mailcap.getcaps()

        theme_path = theme or os.path.join(DEFAULTSPATH, 'default.theme')
        self._theme = Theme(theme_path)
        bindings_path = os.path.join(DEFAULTSPATH, 'default.bindings')
        self._bindings = ConfigObj(bindings_path)
        self._config = ConfigObj()
        self._accounts = None
        self._accountmap = None
        self.read_config(alot_rc)
        self.read_notmuch_config(notmuch_rc)
Beispiel #9
0
        def _get_viewers ( self ):
            from theme              import Theme
            from image_slice_viewer import ImageSliceViewer

            slicer = self.slicer
            theme  = Theme.decode_image_slice( slicer.encoded, slicer.image )
            result = [
                ImageSliceViewer(
                    name        = name,
                    image_slice = info.image_slice )
                for name, info in (
                    ( ( 'Bottom Label', 'Top Label' )[ theme.on_top ],
                      theme.horizontal ),
                    ( ( 'Right Label', 'Left Label' )[ theme.on_left ],
                      theme.vertical ),
                    ( 'Body', theme.body ) )
                if info is not None
            ]
            result.insert( 0, ImageSliceViewer( name  = 'Original',
                                                image = slicer.image ) )

            return result
Beispiel #10
0
	def __init__(self, parent=None):
		super(MyElement, self).__init__()
		self.setObjectName('mainObject')
		self._users = []
		self._index = 0
		self._myTheme = Theme()
		self._myColor = self._myTheme.getTheme() 
		self.mainProc = QProcess()
		self.secondProc = QProcess()
		self.mainProc.finished.connect(self.finishProc)
		self.mainProc.started.connect(self.startProc)
		self.secondProc.finished.connect(self.secondFinishProc)
		self.secondProc.started.connect(self.startProc)
		self.auth = Auth()
		self._isiPesan = ""
		self._judulPesan = "Error"
		self._overlay = ""
		self._isLock = False
		self._hasRegister = False
		self._hasLogin = False
		self._hasError = False
		self._userListData = UserItemModel()
		self._userListData.addRootElement()
		self.addNewUser()
Beispiel #11
0
class Presentation(object):
    """
  Presentation object.

  Attributes
  ----------
  chapters_number: int
  """
    chapters_number = 0

    @classmethod
    def reset(cls):
        """Reset to default state."""
        cls.chapters_number = 0
        Theme.reset()
        Chapter.reset()

    def __init__(self):
        """
    Attributes
    ----------
    metadata: dict
      presentation metadata; each element of the dictionary if a dict with ['value', 'user'] items: value contains
      the metadata value and user indicates if the value comes from user (if True) or from defaults (if False).
    """
        self.reset()
        self.metadata = {
            'title': Metadata(name='title', value=''),
            'subtitle': Metadata(name='subtitle', value=''),
            'authors': Metadata(name='authors', value=[]),
            'authors_short': Metadata(name='authors_short', value=[]),
            'emails': Metadata(name='emails', value=[]),
            'affiliations': Metadata(name='affiliations', value=[]),
            'affiliations_short': Metadata(name='affiliations_short',
                                           value=[]),
            'logo': Metadata(name='logo', value=''),
            'timer': Metadata(name='timer', value=''),
            'location': Metadata(name='location', value=''),
            'location_short': Metadata(name='location_short', value=''),
            'date': Metadata(name='date', value=''),
            'conference': Metadata(name='conference', value=''),
            'conference_short': Metadata(name='conference_short', value=''),
            'session': Metadata(name='session', value=''),
            'session_short': Metadata(name='session_short', value=''),
            'max_time': Metadata(name='max_time', value='25'),
            'total_slides_number': Metadata(name='total_slides_number',
                                            value=''),
            'dirs_to_copy': Metadata(name='dirs_to_copy', value=[]),
            'toc': Metadata(name='toc', value=OrderedDict()),
            'toc_depth': Metadata(name='toc_depth', value='2'),
            'chaptertitle': Metadata(name='chaptertitle', value=''),
            'chapternumber': Metadata(name='chapternumber', value=''),
            'sectiontitle': Metadata(name='sectiontitle', value=''),
            'sectionnumber': Metadata(name='sectionnumber', value=''),
            'subsectiontitle': Metadata(name='subsectiontitle', value=''),
            'subsectionnumber': Metadata(name='subsectionnumber', value=''),
            'slidetitle': Metadata(name='slidetitle', value=''),
            'slidenumber': Metadata(name='slidenumber', value=''),
            'css_overtheme': Metadata(name='css_overtheme', value=[]),
            'custom': Metadata(name='custom-[0-9]*', value='')
        }
        self.theme = Theme()
        self.parser = Parser()
        self.chapters = []
        self.position = Position()
        return

    def __str__(self):
        strings = ['Chapters number ' + str(Presentation.chapters_number)]
        strings.append('Sections number ' + str(Chapter.sections_number))
        strings.append('Subsections number ' + str(Section.subsections_number))
        strings.append('Slides number ' + str(Subsection.slides_number))
        for chapter in self.chapters:
            strings.append(str(chapter))
        return '\n'.join(strings)

    def __update_toc(self):
        """Update TOC after a new chapter (the last one) has been added."""
        self.metadata['toc'].value[
            self.chapters[-1].title] = self.chapters[-1].toc

    def __get_metadata(self, source):
        """
    Get metadata from source stream.

    Parameters
    ----------
    source: str
    """
        codeblocks = self.parser.tokenizer(
            source=source, re_search=self.parser.regexs['codeblock'])
        yamlblocks = self.parser.tokenizer(
            source=source,
            re_search=self.parser.regexs['yamlblock'],
            exclude=codeblocks)
        try:
            for block in yamlblocks:
                for data in load_all(block['match'].group().strip('---')):
                    if 'metadata' in data:
                        for element in data['metadata']:
                            for key in element:
                                if key in self.metadata:
                                    self.metadata[key].update_value(
                                        value=element[key])
        except YAMLError:
            print('No valid definition of metadata has been found')

    def __get_theme(self, source):
        """
    Get theme from source stream.

    Parameters
    ----------
    source: str
    """
        codeblocks = self.parser.tokenizer(
            source=source, re_search=self.parser.regexs['codeblock'])
        yamlblocks = self.parser.tokenizer(
            source=source,
            re_search=self.parser.regexs['yamlblock'],
            exclude=codeblocks)
        self.theme.get(''.join(
            [block['match'].group().strip('---') for block in yamlblocks]))

    def __add_chapter(self, chapter):
        """
    Add a chapter to the pesentation.

    Parameters
    ----------
    chapter: Chapter
    """
        Presentation.chapters_number += 1
        self.chapters.append(chapter)
        self.__update_toc()
        return

    def __check_bad_sectioning(self, tokens):
        """Check if the presentation has a bad sectioning.

    Parameters
    ----------
    tokens: Parser.tokens
    source: str
    """
        if '$titlepage' not in tokens['slides'][0]['match'].group().lower():
            if tokens['slides'][0]['start'] < tokens['subsections'][0][
                    'start'] or tokens['slides'][0]['start'] < tokens[
                        'sections'][0]['start'] or tokens['slides'][0][
                            'start'] < tokens['chapters'][0]['start']:
                print('Warning: found bad presentation sectioning!')
                print('The slide definition:')
                print(tokens['slides'][0]['match'].group() + "\n")
                print(
                    'is placed before the first defined chapter/section/subsection.'
                )
                print(
                    'All contents before the first defined chapter/section/subsection is omitted!'
                )
                print()
        return

    def __put_html_tag_head(self, doc, tag, text, config):
        """Put head tag into html doc.

    Parameters
    ----------
    doc: Doc()
    tag: Tag()
    config : MatisseConfig
      MaTiSSe configuration
    """
        with tag('head'):
            doc.stag('meta', charset='utf-8')
            doc.stag('meta',
                     author=' and '.join(self.metadata['authors'].value))
            with tag('title'):
                text(self.metadata['title'].value)
            doc.stag('meta', subtitle=self.metadata['subtitle'].value)
            doc.stag('link', rel='stylesheet', href='css/normalize.css')
            doc.stag('link', rel='stylesheet', href='css/matisse_defaults.css')
            doc.stag('link',
                     rel='stylesheet',
                     href='css/matisse_defaults_printing.css')
            if config.highlight:
                doc.stag('link',
                         rel='stylesheet',
                         href='js/highlight/styles/' + config.highlight_style)
            doc.stag('link', rel='stylesheet', href='css/theme.css')
            for css in self.metadata['css_overtheme'].value:
                doc.stag('link', rel='stylesheet', href=css)
            for chapter in self.chapters:
                for section in chapter.sections:
                    for subsection in section.subsections:
                        for slide in subsection.slides:
                            if slide.overtheme.custom:
                                doc.stag('link',
                                         rel='stylesheet',
                                         href='css/slide-' +
                                         str(slide.number) + '-overtheme.css')

    def __put_html_tags_scripts(self, doc, tag, config):
        """Put final tags for scripts into html doc.

    Parameters
    ----------
    doc: Doc()
    tag: Tag()
    config : MatisseConfig
      MaTiSSe configuration
    """
        with tag('script'):
            doc.attr(src='js/countDown.js')
        with tag('script'):
            doc.attr(src='js/impress.js')
        if not config.pdf:
            with tag('script'):
                doc.asis('impress().init();')
        if config.online_mathjax:
            with tag('script'):
                doc.attr(('type', 'text/javascript'))
                doc.attr(
                    src=
                    'http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'
                )
        else:
            with tag('script'):
                doc.attr(('type', 'text/x-mathjax-config'))
                doc.text("""
          MathJax.Hub.Config({
            extensions: ["tex2jax.js"],
            jax: ["input/TeX", "output/HTML-CSS"],
            tex2jax: {
              inlineMath: [ ['$','$'] ],
              displayMath: [ ['$$','$$'] ],
              processEscapes: true
            },
            "HTML-CSS": { availableFonts: ["Neo-Euler"] }
          });
        """)
            with tag('script'):
                doc.attr(('type', 'text/javascript'))
                doc.attr(src='js/MathJax/MathJax.js')
        if config.highlight:
            with tag('script'):
                doc.attr(src='js/highlight/highlight.pack.js')
            with tag('script'):
                doc.text("""hljs.initHighlightingOnLoad();""")

    def __put_html_slide_decorators(self,
                                    tag,
                                    doc,
                                    decorator,
                                    position=None,
                                    overtheme=None,
                                    current=None):
        """Put html data of headers, footers and sidebars.

    Parameters
    ----------
    doc: Doc
    tag: tag
    decorator: {header, footer, sidebar}
    position: {'L','R'}
      sidebars position, L => left, R => right
    current: list
    """
        if overtheme is not None and overtheme.custom:
            theme = overtheme
        else:
            theme = self.theme
        # decorators = getattr(self.theme, 'slide_' + decorator)
        decorators = getattr(theme, 'slide_' + decorator)
        for decor in sorted(decorators):
            insert = True
            # position check for sidebars
            if decorator == 'sidebar' and position is not None:
                for css in decorators[decor]:
                    for key in css:
                        if 'position' in key.lower():
                            pos = css[key]
                            break
                insert = pos.lower() == position.lower()
            # active check
            for css in decorators[decor]:
                for key in css:
                    if 'active' in key.lower():
                        insert = insert and css[key].lower() == 'yes'
            if insert:
                # placeholders = self.theme.get_slide_decorators_metadata(decorator=decorator, name=decor)
                placeholders = theme.get_slide_decorators_metadata(
                    decorator=decorator, name=decor)
                for metadata in self.metadata:
                    placeholders = self.metadata[metadata].parse(
                        parser=self.parser,
                        source=placeholders,
                        toc_depth=self.metadata['toc_depth'].value,
                        max_time=self.metadata['max_time'].value,
                        current=current)
                with tag('div', klass='slide-' + decor):
                    doc.asis(placeholders)

    def parse(self, config, source):
        """Parse presentation from source stream.

    Parameters
    ----------
    config : MatisseConfig
      MaTiSSe configuration
    source: str
    """
        complete_source = self.parser.includes(source=source)
        self.__get_metadata(source=complete_source)
        self.__get_theme(source=complete_source)
        new_theme = Theme()
        new_theme.set_from(other=self.theme)
        tokens = self.parser.tokenize(source=complete_source)
        self.__check_bad_sectioning(tokens=tokens)
        chapters_number = 0
        sections_number = 0
        subsections_number = 0
        slides_number = 0
        titlepage_inserted = False
        for chap in tokens['chapters']:
            chapters_number += 1
            slide_local_numbers = [0, 0, 0]
            if chap['match'].group('expr'):
                chapter = Chapter(number=chapters_number,
                                  title=chap['match'].group('expr'))
            else:
                chapter = Chapter(number=chapters_number, title='')
            for sec in tokens['sections']:
                if sec['start'] >= chap['start'] and sec['start'] <= chap[
                        'end_next']:
                    sections_number += 1
                    slide_local_numbers[1] = 0
                    slide_local_numbers[2] = 0
                    section = Section(number=sections_number,
                                      title=sec['match'].group('expr'))
                    for subsec in tokens['subsections']:
                        if subsec['start'] >= sec['start'] and subsec[
                                'start'] <= sec['end_next']:
                            subsections_number += 1
                            slide_local_numbers[2] = 0
                            subsection = Subsection(
                                number=subsections_number,
                                title=subsec['match'].group('expr'))
                            for sld in tokens['slides']:
                                if '$titlepage' in sld['match'].group().lower(
                                ) and not titlepage_inserted:
                                    slide = Slide(
                                        number=0,
                                        title='titlepage',
                                        contents=complete_source[
                                            sld['end']:sld['end_next']])
                                    slide.get_overtheme(parser=self.parser)
                                    if slide.overtheme.copy_from_theme is not None and slide.overtheme.copy_from_theme:
                                        slide.overtheme.copy_from(
                                            other=self.theme)
                                    self.position.update_position(
                                        presentation_theme=self.theme,
                                        overtheme=slide.overtheme)
                                    slide.set_position(
                                        position=self.position.position)
                                    subsection.add_slide(slide=slide)
                                    titlepage_inserted = True
                                else:
                                    if sld['start'] >= subsec['start'] and sld[
                                            'start'] <= subsec['end_next']:
                                        slide_local_numbers[0] += 1
                                        slide_local_numbers[1] += 1
                                        slide_local_numbers[2] += 1
                                        if slide_local_numbers[
                                                0] == 1 and config.toc_at_chap_beginning is not None:
                                            slides_number += 1
                                            self.position.update_position(
                                                presentation_theme=self.theme)
                                            subsection.add_slide(slide=Slide(
                                                number=slides_number,
                                                position=self.position.
                                                position,
                                                title='Table of Contents',
                                                contents='$toc[depth:' +
                                                str(config.
                                                    toc_at_chap_beginning) +
                                                ']'))
                                        if slide_local_numbers[
                                                1] == 1 and config.toc_at_sec_beginning is not None:
                                            slides_number += 1
                                            self.position.update_position(
                                                presentation_theme=self.theme)
                                            subsection.add_slide(slide=Slide(
                                                number=slides_number,
                                                position=self.position.
                                                position,
                                                title='Table of Contents',
                                                contents='$toc[depth:' +
                                                str(config.toc_at_sec_beginning
                                                    ) + ']'))
                                        if slide_local_numbers[
                                                2] == 1 and config.toc_at_subsec_beginning is not None:
                                            slides_number += 1
                                            self.position.update_position(
                                                presentation_theme=self.theme)
                                            subsection.add_slide(slide=Slide(
                                                number=slides_number,
                                                position=self.position.
                                                position,
                                                title='Table of Contents',
                                                contents='$toc[depth:' +
                                                str(config.
                                                    toc_at_subsec_beginning) +
                                                ']'))
                                        slides_number += 1
                                        slide = Slide(
                                            number=slides_number,
                                            title=sld['match'].group('expr'),
                                            contents=complete_source[
                                                sld['end']:sld['end_next']])
                                        slide.get_overtheme(parser=self.parser)
                                        if slide.overtheme.copy_from_theme is not None and slide.overtheme.copy_from_theme:
                                            slide.overtheme.copy_from(
                                                other=self.theme)
                                        self.position.update_position(
                                            presentation_theme=self.theme,
                                            overtheme=slide.overtheme)
                                        slide.set_position(
                                            position=self.position.position)
                                        subsection.add_slide(slide=slide)
                            section.add_subsection(subsection=subsection)
                    chapter.add_section(section=section)
            self.__add_chapter(chapter=chapter)
            self.metadata['total_slides_number'].update_value(
                value=str(Subsection.slides_number))

    def to_html(self, config):
        """Generate a html stream of the whole presentation.

    Parameters
    ----------
    config : MatisseConfig
      MaTiSSe configuration
    """
        doc, tag, text = Doc().tagtext()
        doc.asis('<!DOCTYPE html>')
        with tag('html'):
            # doc.attr(title=self.metadata['title'].value)
            self.__put_html_tag_head(doc=doc,
                                     tag=tag,
                                     text=text,
                                     config=config)
            with tag('body',
                     onload="resetCountdown(" +
                     str(self.metadata['max_time'].value) + ");"):
                doc.attr(klass='impress-not-supported')
                with tag('div', id='impress'):
                    # numbering: [local_chap, local_sec, local_subsec, local_slide]
                    current = [0, 0, 0, 0]
                    for chapter in self.chapters:
                        current[0] += 1
                        current[1] = 0
                        current[2] = 0
                        current[3] = 0
                        self.metadata['chaptertitle'].update_value(
                            value=chapter.title)
                        self.metadata['chapternumber'].update_value(
                            value=chapter.number)
                        for section in chapter.sections:
                            current[1] += 1
                            current[2] = 0
                            current[3] = 0
                            self.metadata['sectiontitle'].update_value(
                                value=section.title)
                            self.metadata['sectionnumber'].update_value(
                                value=section.number)
                            for subsection in section.subsections:
                                current[2] += 1
                                current[3] = 0
                                self.metadata['subsectiontitle'].update_value(
                                    value=subsection.title)
                                self.metadata['subsectionnumber'].update_value(
                                    value=subsection.number)
                                for slide in subsection.slides:
                                    current[3] += 1
                                    self.metadata['slidetitle'].update_value(
                                        value=slide.title)
                                    self.metadata['slidenumber'].update_value(
                                        value=slide.number)
                                    with doc.tag('div'):
                                        chapter.put_html_attributes(doc=doc)
                                        section.put_html_attributes(doc=doc)
                                        subsection.put_html_attributes(doc=doc)
                                        slide.put_html_attributes(doc=doc)
                                        self.__put_html_slide_decorators(
                                            tag=tag,
                                            doc=doc,
                                            decorator='header',
                                            current=current,
                                            overtheme=slide.overtheme)
                                        self.__put_html_slide_decorators(
                                            tag=tag,
                                            doc=doc,
                                            decorator='sidebar',
                                            position='L',
                                            current=current,
                                            overtheme=slide.overtheme)
                                        slide.to_html(doc=doc,
                                                      parser=self.parser,
                                                      metadata=self.metadata,
                                                      theme=self.theme,
                                                      current=current)
                                        self.__put_html_slide_decorators(
                                            tag=tag,
                                            doc=doc,
                                            decorator='sidebar',
                                            position='R',
                                            current=current,
                                            overtheme=slide.overtheme)
                                        self.__put_html_slide_decorators(
                                            tag=tag,
                                            doc=doc,
                                            decorator='footer',
                                            current=current,
                                            overtheme=slide.overtheme)
                self.__put_html_tags_scripts(doc=doc, tag=tag, config=config)
        # source = re.sub(r"<li>(?P<item>.*)</li>", r"<li><span>\g<item></span></li>", source)
        html = indent(doc.getvalue())
        return html

    def save(self, config, output):
        """Save the html form of presentation into external file.

    Parameters
    ----------
    config : MatisseConfig
      MaTiSSe configuration
    output : str
      output path
    """

        if not os.path.exists(output):
            os.makedirs(output)
        with open(os.path.join(output, 'index.html'), 'w') as html:
            html.write(self.to_html(config=config))
        # copy user defined directories if set
        if len(self.metadata['dirs_to_copy'].value) > 0:
            for data in self.metadata['dirs_to_copy'].value:
                sync_logger = logging.getLogger('sync_logger')
                sync(data,
                     os.path.join(output, data),
                     'sync',
                     create=True,
                     logger=sync_logger)
        # css files
        with open(os.path.join(output, 'css/theme.css'), 'w') as css_theme:
            css_theme.writelines(self.theme.css)
        for chapter in self.chapters:
            for section in chapter.sections:
                for subsection in section.subsections:
                    for slide in subsection.slides:
                        if slide.overtheme.custom:
                            with open(
                                    os.path.join(
                                        output, 'css/slide-' +
                                        str(slide.number) + '-overtheme.css'),
                                    'w') as css_theme:
                                css_theme.writelines(slide.overtheme.css)
        return
Beispiel #12
0
class Presentation(object):
  """
  Presentation object.

  Attributes
  ----------
  chapters_number: int
  """
  chapters_number = 0

  @classmethod
  def reset(cls):
    """Reset to default state."""
    cls.chapters_number = 0
    Theme.reset()
    Chapter.reset()

  def __init__(self):
    """
    Attributes
    ----------
    metadata: dict
      presentation metadata; each element of the dictionary if a dict with ['value', 'user'] items: value contains
      the metadata value and user indicates if the value comes from user (if True) or from defaults (if False).
    """
    self.reset()
    self.metadata = {'title': Metadata(name='title', value=''),
                     'subtitle': Metadata(name='subtitle', value=''),
                     'authors': Metadata(name='authors', value=[]),
                     'authors_short': Metadata(name='authors_short', value=[]),
                     'emails': Metadata(name='emails', value=[]),
                     'affiliations': Metadata(name='affiliations', value=[]),
                     'affiliations_short': Metadata(name='affiliations_short', value=[]),
                     'logo': Metadata(name='logo', value=''),
                     'timer': Metadata(name='timer', value=''),
                     'location': Metadata(name='location', value=''),
                     'location_short': Metadata(name='location_short', value=''),
                     'date': Metadata(name='date', value=''),
                     'conference': Metadata(name='conference', value=''),
                     'conference_short': Metadata(name='conference_short', value=''),
                     'session': Metadata(name='session', value=''),
                     'session_short': Metadata(name='session_short', value=''),
                     'max_time': Metadata(name='max_time', value='25'),
                     'total_slides_number': Metadata(name='total_slides_number', value=''),
                     'dirs_to_copy': Metadata(name='dirs_to_copy', value=[]),
                     'toc': Metadata(name='toc', value=OrderedDict()),
                     'toc_depth': Metadata(name='toc_depth', value='2'),
                     'chaptertitle': Metadata(name='chaptertitle', value=''),
                     'chapternumber': Metadata(name='chapternumber', value=''),
                     'sectiontitle': Metadata(name='sectiontitle', value=''),
                     'sectionnumber': Metadata(name='sectionnumber', value=''),
                     'subsectiontitle': Metadata(name='subsectiontitle', value=''),
                     'subsectionnumber': Metadata(name='subsectionnumber', value=''),
                     'slidetitle': Metadata(name='slidetitle', value=''),
                     'slidenumber': Metadata(name='slidenumber', value=''),
                     'css_overtheme': Metadata(name='css_overtheme', value=[]),
                     'custom': Metadata(name='custom-[0-9]*', value='')}
    self.theme = Theme()
    self.parser = Parser()
    self.chapters = []
    self.position = Position()
    return

  def __str__(self):
    strings = ['Chapters number ' + str(Presentation.chapters_number)]
    strings.append('Sections number ' + str(Chapter.sections_number))
    strings.append('Subsections number ' + str(Section.subsections_number))
    strings.append('Slides number ' + str(Subsection.slides_number))
    for chapter in self.chapters:
      strings.append(str(chapter))
    return '\n'.join(strings)

  def __update_toc(self):
    """Update TOC after a new chapter (the last one) has been added."""
    self.metadata['toc'].value[self.chapters[-1].title] = self.chapters[-1].toc

  def __get_metadata(self, source):
    """
    Get metadata from source stream.

    Parameters
    ----------
    source: str
    """
    codeblocks = self.parser.tokenizer(source=source, re_search=self.parser.regexs['codeblock'])
    yamlblocks = self.parser.tokenizer(source=source, re_search=self.parser.regexs['yamlblock'], exclude=codeblocks)
    try:
      for block in yamlblocks:
        for data in load_all(block['match'].group().strip('---')):
          if 'metadata' in data:
            for element in data['metadata']:
              for key in element:
                if key in self.metadata:
                  self.metadata[key].update_value(value=element[key])
    except YAMLError:
      print('No valid definition of metadata has been found')

  def __get_theme(self, source):
    """
    Get theme from source stream.

    Parameters
    ----------
    source: str
    """
    codeblocks = self.parser.tokenizer(source=source, re_search=self.parser.regexs['codeblock'])
    yamlblocks = self.parser.tokenizer(source=source, re_search=self.parser.regexs['yamlblock'], exclude=codeblocks)
    self.theme.get(''.join([block['match'].group().strip('---') for block in yamlblocks]))

  def __add_chapter(self, chapter):
    """
    Add a chapter to the pesentation.

    Parameters
    ----------
    chapter: Chapter
    """
    Presentation.chapters_number += 1
    self.chapters.append(chapter)
    self.__update_toc()
    return

  def __check_bad_sectioning(self, tokens):
    """Check if the presentation has a bad sectioning.

    Parameters
    ----------
    tokens: Parser.tokens
    source: str
    """
    if '$titlepage' not in tokens['slides'][0]['match'].group().lower():
      if tokens['slides'][0]['start'] < tokens['subsections'][0]['start'] or tokens['slides'][0]['start'] < tokens['sections'][0]['start'] or tokens['slides'][0]['start'] < tokens['chapters'][0]['start']:
        print('Warning: found bad presentation sectioning!')
        print('The slide definition:')
        print(tokens['slides'][0]['match'].group() + "\n")
        print('is placed before the first defined chapter/section/subsection.')
        print('All contents before the first defined chapter/section/subsection is omitted!')
        print()
    return

  def __put_html_tag_head(self, doc, tag, text, config):
    """Put head tag into html doc.

    Parameters
    ----------
    doc: Doc()
    tag: Tag()
    config : MatisseConfig
      MaTiSSe configuration
    """
    with tag('head'):
      doc.stag('meta', charset='utf-8')
      doc.stag('meta', author=' and '.join(self.metadata['authors'].value))
      with tag('title'):
        text(self.metadata['title'].value)
      doc.stag('meta', subtitle=self.metadata['subtitle'].value)
      doc.stag('link', rel='stylesheet', href='css/normalize.css')
      doc.stag('link', rel='stylesheet', href='css/matisse_defaults.css')
      doc.stag('link', rel='stylesheet', href='css/matisse_defaults_printing.css')
      if config.highlight:
        doc.stag('link', rel='stylesheet', href='js/highlight/styles/' + config.highlight_style)
      doc.stag('link', rel='stylesheet', href='css/theme.css')
      for css in self.metadata['css_overtheme'].value:
        doc.stag('link', rel='stylesheet', href=css)
      for chapter in self.chapters:
        for section in chapter.sections:
          for subsection in section.subsections:
            for slide in subsection.slides:
              if slide.overtheme.custom:
                doc.stag('link', rel='stylesheet', href='css/slide-' + str(slide.number) + '-overtheme.css')

  def __put_html_tags_scripts(self, doc, tag, config):
    """Put final tags for scripts into html doc.

    Parameters
    ----------
    doc: Doc()
    tag: Tag()
    config : MatisseConfig
      MaTiSSe configuration
    """
    with tag('script'):
      doc.attr(src='js/countDown.js')
    with tag('script'):
      doc.attr(src='js/impress.js')
    if not config.pdf:
      with tag('script'):
        doc.asis('impress().init();')
    if config.online_mathjax:
      with tag('script'):
        doc.attr(('type', 'text/javascript'))
        doc.attr(src='http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML')
    else:
      with tag('script'):
        doc.attr(('type', 'text/x-mathjax-config'))
        doc.text("""
          MathJax.Hub.Config({
            extensions: ["tex2jax.js"],
            jax: ["input/TeX", "output/HTML-CSS"],
            tex2jax: {
              inlineMath: [ ['$','$'] ],
              displayMath: [ ['$$','$$'] ],
              processEscapes: true
            },
            "HTML-CSS": { availableFonts: ["Neo-Euler"] }
          });
        """)
      with tag('script'):
        doc.attr(('type', 'text/javascript'))
        doc.attr(src='js/MathJax/MathJax.js')
    if config.highlight:
      with tag('script'):
        doc.attr(src='js/highlight/highlight.pack.js')
      with tag('script'):
        doc.text("""hljs.initHighlightingOnLoad();""")

  def __put_html_slide_decorators(self, tag, doc, decorator, position=None, overtheme=None, current=None):
    """Put html data of headers, footers and sidebars.

    Parameters
    ----------
    doc: Doc
    tag: tag
    decorator: {header, footer, sidebar}
    position: {'L','R'}
      sidebars position, L => left, R => right
    current: list
    """
    if overtheme is not None and overtheme.custom:
      theme = overtheme
    else:
      theme = self.theme
    # decorators = getattr(self.theme, 'slide_' + decorator)
    decorators = getattr(theme, 'slide_' + decorator)
    for decor in sorted(decorators):
      insert = True
      # position check for sidebars
      if decorator == 'sidebar' and position is not None:
        for css in decorators[decor]:
          for key in css:
            if 'position' in key.lower():
              pos = css[key]
              break
        insert = pos.lower() == position.lower()
      # active check
      for css in decorators[decor]:
        for key in css:
          if 'active' in key.lower():
            insert = insert and css[key].lower() == 'yes'
      if insert:
        # placeholders = self.theme.get_slide_decorators_metadata(decorator=decorator, name=decor)
        placeholders = theme.get_slide_decorators_metadata(decorator=decorator, name=decor)
        for metadata in self.metadata:
          placeholders = self.metadata[metadata].parse(parser=self.parser, source=placeholders, toc_depth=self.metadata['toc_depth'].value, max_time=self.metadata['max_time'].value, current=current)
        with tag('div', klass='slide-' + decor):
          doc.asis(placeholders)

  def parse(self, config, source):
    """Parse presentation from source stream.

    Parameters
    ----------
    config : MatisseConfig
      MaTiSSe configuration
    source: str
    """
    complete_source = self.parser.includes(source=source)
    self.__get_metadata(source=complete_source)
    self.__get_theme(source=complete_source)
    new_theme = Theme()
    new_theme.set_from(other=self.theme)
    tokens = self.parser.tokenize(source=complete_source)
    self.__check_bad_sectioning(tokens=tokens)
    chapters_number = 0
    sections_number = 0
    subsections_number = 0
    slides_number = 0
    titlepage_inserted = False
    for chap in tokens['chapters']:
      chapters_number += 1
      slide_local_numbers = [0, 0, 0]
      if chap['match'].group('expr'):
        chapter = Chapter(number=chapters_number, title=chap['match'].group('expr'))
      else:
        chapter = Chapter(number=chapters_number, title='')
      for sec in tokens['sections']:
        if sec['start'] >= chap['start'] and sec['start'] <= chap['end_next']:
          sections_number += 1
          slide_local_numbers[1] = 0
          slide_local_numbers[2] = 0
          section = Section(number=sections_number, title=sec['match'].group('expr'))
          for subsec in tokens['subsections']:
            if subsec['start'] >= sec['start'] and subsec['start'] <= sec['end_next']:
              subsections_number += 1
              slide_local_numbers[2] = 0
              subsection = Subsection(number=subsections_number, title=subsec['match'].group('expr'))
              for sld in tokens['slides']:
                if '$titlepage' in sld['match'].group().lower() and not titlepage_inserted:
                  slide = Slide(number=0,
                                title='titlepage',
                                contents=complete_source[sld['end']:sld['end_next']])
                  slide.get_overtheme(parser=self.parser)
                  if slide.overtheme.copy_from_theme is not None and slide.overtheme.copy_from_theme:
                    slide.overtheme.copy_from(other=self.theme)
                  self.position.update_position(presentation_theme=self.theme, overtheme=slide.overtheme)
                  slide.set_position(position=self.position.position)
                  subsection.add_slide(slide=slide)
                  titlepage_inserted = True
                else:
                  if sld['start'] >= subsec['start'] and sld['start'] <= subsec['end_next']:
                    slide_local_numbers[0] += 1
                    slide_local_numbers[1] += 1
                    slide_local_numbers[2] += 1
                    if slide_local_numbers[0] == 1 and config.toc_at_chap_beginning is not None:
                      slides_number += 1
                      self.position.update_position(presentation_theme=self.theme)
                      subsection.add_slide(slide=Slide(number=slides_number,
                                                       position=self.position.position,
                                                       title='Table of Contents',
                                                       contents='$toc[depth:' + str(config.toc_at_chap_beginning) + ']'))
                    if slide_local_numbers[1] == 1 and config.toc_at_sec_beginning is not None:
                      slides_number += 1
                      self.position.update_position(presentation_theme=self.theme)
                      subsection.add_slide(slide=Slide(number=slides_number,
                                                       position=self.position.position,
                                                       title='Table of Contents',
                                                       contents='$toc[depth:' + str(config.toc_at_sec_beginning) + ']'))
                    if slide_local_numbers[2] == 1 and config.toc_at_subsec_beginning is not None:
                      slides_number += 1
                      self.position.update_position(presentation_theme=self.theme)
                      subsection.add_slide(slide=Slide(number=slides_number,
                                                       position=self.position.position,
                                                       title='Table of Contents',
                                                       contents='$toc[depth:' + str(config.toc_at_subsec_beginning) + ']'))
                    slides_number += 1
                    slide = Slide(number=slides_number,
                                  title=sld['match'].group('expr'),
                                  contents=complete_source[sld['end']:sld['end_next']])
                    slide.get_overtheme(parser=self.parser)
                    if slide.overtheme.copy_from_theme is not None and slide.overtheme.copy_from_theme:
                      slide.overtheme.copy_from(other=self.theme)
                    self.position.update_position(presentation_theme=self.theme, overtheme=slide.overtheme)
                    slide.set_position(position=self.position.position)
                    subsection.add_slide(slide=slide)
              section.add_subsection(subsection=subsection)
          chapter.add_section(section=section)
      self.__add_chapter(chapter=chapter)
      self.metadata['total_slides_number'].update_value(value=str(Subsection.slides_number))

  def to_html(self, config):
    """Generate a html stream of the whole presentation.

    Parameters
    ----------
    config : MatisseConfig
      MaTiSSe configuration
    """
    doc, tag, text = Doc().tagtext()
    doc.asis('<!DOCTYPE html>')
    with tag('html'):
      # doc.attr(title=self.metadata['title'].value)
      self.__put_html_tag_head(doc=doc, tag=tag, text=text, config=config)
      with tag('body', onload="resetCountdown(" + str(self.metadata['max_time'].value) + ");"):
        doc.attr(klass='impress-not-supported')
        with tag('div', id='impress'):
          # numbering: [local_chap, local_sec, local_subsec, local_slide]
          current = [0, 0, 0, 0]
          for chapter in self.chapters:
            current[0] += 1
            current[1] = 0
            current[2] = 0
            current[3] = 0
            self.metadata['chaptertitle'].update_value(value=chapter.title)
            self.metadata['chapternumber'].update_value(value=chapter.number)
            for section in chapter.sections:
              current[1] += 1
              current[2] = 0
              current[3] = 0
              self.metadata['sectiontitle'].update_value(value=section.title)
              self.metadata['sectionnumber'].update_value(value=section.number)
              for subsection in section.subsections:
                current[2] += 1
                current[3] = 0
                self.metadata['subsectiontitle'].update_value(value=subsection.title)
                self.metadata['subsectionnumber'].update_value(value=subsection.number)
                for slide in subsection.slides:
                  current[3] += 1
                  self.metadata['slidetitle'].update_value(value=slide.title)
                  self.metadata['slidenumber'].update_value(value=slide.number)
                  with doc.tag('div'):
                    chapter.put_html_attributes(doc=doc)
                    section.put_html_attributes(doc=doc)
                    subsection.put_html_attributes(doc=doc)
                    slide.put_html_attributes(doc=doc)
                    self.__put_html_slide_decorators(tag=tag, doc=doc, decorator='header', current=current, overtheme=slide.overtheme)
                    self.__put_html_slide_decorators(tag=tag, doc=doc, decorator='sidebar', position='L', current=current, overtheme=slide.overtheme)
                    slide.to_html(doc=doc, parser=self.parser, metadata=self.metadata, theme=self.theme, current=current)
                    self.__put_html_slide_decorators(tag=tag, doc=doc, decorator='sidebar', position='R', current=current, overtheme=slide.overtheme)
                    self.__put_html_slide_decorators(tag=tag, doc=doc, decorator='footer', current=current, overtheme=slide.overtheme)
        self.__put_html_tags_scripts(doc=doc, tag=tag, config=config)
    # source = re.sub(r"<li>(?P<item>.*)</li>", r"<li><span>\g<item></span></li>", source)
    html = indent(doc.getvalue())
    return html

  def save(self, config, output):
    """Save the html form of presentation into external file.

    Parameters
    ----------
    config : MatisseConfig
      MaTiSSe configuration
    output : str
      output path
    """

    if not os.path.exists(output):
      os.makedirs(output)
    with open(os.path.join(output, 'index.html'), 'w') as html:
      html.write(self.to_html(config=config))
    # copy user defined directories if set
    if len(self.metadata['dirs_to_copy'].value) > 0:
      for data in self.metadata['dirs_to_copy'].value:
        sync_logger = logging.getLogger('sync_logger')
        sync(data, os.path.join(output, data), 'sync', create=True, logger=sync_logger)
    # css files
    with open(os.path.join(output, 'css/theme.css'), 'w') as css_theme:
      css_theme.writelines(self.theme.css)
    for chapter in self.chapters:
      for section in chapter.sections:
        for subsection in section.subsections:
          for slide in subsection.slides:
            if slide.overtheme.custom:
              with open(os.path.join(output, 'css/slide-' + str(slide.number) + '-overtheme.css'), 'w') as css_theme:
                css_theme.writelines(slide.overtheme.css)
    return
Beispiel #13
0
 def reset(cls):
   """Reset to default state."""
   cls.chapters_number = 0
   Theme.reset()
   Chapter.reset()
class IconFactory():
    """IconFactory takes care of finding the right icon for a program and prepares the cairo surface."""
    icon_theme = gtk.icon_theme_get_default()
    # Constants
    # Icon types
    SOME_MINIMIZED = 1<<4
    ALL_MINIMIZED = 1<<5
    LAUNCHER = 1<<6
    # Icon effects
    MOUSE_OVER = 1<<7
    MOUSE_BUTTON_DOWN = 1<<8
    NEEDS_ATTENTION = 1<<9
    BLINK  = 1<<10
    # ACTIVE_WINDOW
    ACTIVE = 1<<11
    LAUNCH_EFFECT = 1<<12
    # Double width/height icons for drag and drop situations.
    DRAG_DROPP = 1<<13
    TYPE_DICT = {'some_minimized':SOME_MINIMIZED,
                 'all_minimized':ALL_MINIMIZED,
                 'launcher':LAUNCHER,
                 'mouse_over':MOUSE_OVER,
                 'needs_attention':NEEDS_ATTENTION,
                 'blink':BLINK,
                 'active':ACTIVE,
                 'launching':LAUNCH_EFFECT,
                 'mouse_button_down':MOUSE_BUTTON_DOWN}

    def __init__(self, class_group=None,
                 desktop_entry=None, identifier=None):
        self.theme = Theme()
        self.globals = Globals()
        self.globals.connect('color-changed', self.reset_surfaces)
        self.desktop_entry = desktop_entry
        self.identifier = identifier
        self.class_group = class_group

        # Setting size to something other than zero to
        # avoid crashes if surface_update() is runned
        # before the size is set.
        self.size = 15

        self.icon = None
        self.surfaces = {}

        self.average_color = None

        self.max_win_nr = self.theme.get_windows_cnt()
        self.types_in_theme = 0
        for type in self.theme.get_types():
            if not type in self.TYPE_DICT:
                continue
            self.types_in_theme = self.types_in_theme | self.TYPE_DICT[type]

    def remove(self):
        del self.desktop_entry
        del self.class_group
        del self.icon
        del self.surfaces
        del self.theme

    def set_desktop_entry(self, desktop_entry):
        self.desktop_entry = desktop_entry
        self.surfaces = {}
        del self.icon
        self.icon = None

    def set_class_group(self, class_group):
        if not self.desktop_entry and not self.class_group:
            self.surfaces = {}
            del self.icon
            self.icon = None
        self.class_group = class_group

    def set_size(self, size):
        if size <= 0:
            # To avoid chrashes.
            size = 15
        self.size = size
        self.surfaces = {}
        self.average_color = None

    def get_size(self):
        return self.size

    def reset_surfaces(self, arg=None):
        self.surfaces = {}
        self.average_color = None


    def surface_update(self, type = 0):
        # Checks if the requested pixbuf is already
        # drawn and returns it if it is.
        # Othervice the surface is drawn, saved and returned.

        #The first four bits of type is for telling the number of windows
        self.win_nr = min(type & 15, self.max_win_nr)
        # Remove all types that are not used by the theme (saves memory)
        dnd = type & self.DRAG_DROPP
        type = type & self.types_in_theme
        type += self.win_nr
        if type in self.surfaces:
            surface = self.surfaces[type]
        else:
            self.temp = {}
            surface = None
            commands = self.theme.get_icon_dict()
            self.ar = self.theme.get_aspect_ratio()
            self.type = type
            for command, args in commands.items():
                try:
                    f = getattr(self,"command_%s"%command)
                except:
                    raise
                else:
                    surface = f(surface, **args)
            # Todo: add size correction.
            self.surfaces[type] = surface
            del self.temp
            gc.collect()
        if dnd:
            surface = self.dd_highlight(surface, self.globals.orient)
            gc.collect()
        return surface


    def dd_highlight(self, surface, direction = 'h'):
        w = surface.get_width()
        h = surface.get_height()
        # Make a background almost twice as wide or high
        # as the surface depending on panel orientation.
        if direction == 'v':
            h = h + 4
        else:
            w = w + 4
        bg = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(bg)

        # Put arrow pointing to the empty part on it.
        if direction == 'v':
            ctx.move_to(1, h - 1.5)
            ctx.line_to(w - 1, h - 1.5)
            ctx.set_source_rgba(1, 1, 1, 0.2)
            ctx.set_line_width(2)
            ctx.stroke()
            ctx.move_to(2, h - 1.5)
            ctx.line_to(w - 2, h - 1.5)
            ctx.set_source_rgba(0, 0, 0, 0.7)
            ctx.set_line_width(1)
            ctx.stroke()
        else:
            ctx.move_to(w - 1.5, 1)
            ctx.line_to(w - 1.5, h - 1)
            ctx.set_source_rgba(1, 1, 1, 0.2)
            ctx.set_line_width(2)
            ctx.stroke()
            ctx.move_to(w - 1.5, 2)
            ctx.line_to(w - 1.5, h - 2)
            ctx.set_source_rgba(0, 0, 0, 0.7)
            ctx.set_line_width(1)
            ctx.stroke()


        # And put the surface on the left/upper half of it.
        ctx.set_source_surface(surface, 0, 0)
        ctx.paint()
        return bg

    def get_color(self, color):
        if color == "active_color":
            color = 'color5'
        if color in ['color%s'%i for i in range(1, 9)]:
            color = self.globals.colors[color]
        if color == "icon_average":
            color = self.get_average_color()
        else:
            try:
                if len(color) != 7:
                    raise ValueError('The string has the wrong lenght')
                t = int(color[1:], 16)
            except:
                print "Theme error: the color attribute for a theme command"+ \
                      " should be a six digit hex string eg. \"#FFFFFF\" or"+ \
                      " the a dockbarx color (\"color1\"-\"color8\")."
                color = "#000000"
        return color

    def get_alpha(self, alpha):
        # Transparency
        if alpha == "active_opacity":
            # For backwards compability
            alpha = "color5"

        for i in range(1, 9):
            if alpha in ('color%s'%i, 'opacity%s'%i):
                if self.globals.colors.has_key('color%s_alpha'%i):
                    a = float(self.globals.colors['color%s_alpha'%i])/255
                else:
                    print "Theme error: The theme has no" + \
                          " opacity option for color%s."%i
                    a = 1.0
                break
        else:
            try:
                a = float(alpha)/100
                if a > 1.0 or a < 0:
                    raise
            except:
                print 'Theme error: The opacity attribute of a theme ' + \
                      'command should be a number between "0" ' + \
                      ' and "100" or "color1" to "color8".'
                a = 1.0
        return a

    def get_average_color(self):
        if self.average_color is not None:
            return self.average_color
        r = 0
        b = 0
        g = 0
        i = 0
        pb = self.surface2pixbuf(self.icon)
        for row in pb.get_pixels_array():
            for pix in row:
                if pix[3] > 30:
                    i += 1
                    r += pix[0]
                    g += pix[1]
                    b += pix[2]
        if i > 0:
            r = int(float(r) / i + 0.5)
            g = int(float(g) / i + 0.5)
            b = int(float(b) / i + 0.5)
        r = ("0%s"%hex(r)[2:])[-2:]
        g = ("0%s"%hex(g)[2:])[-2:]
        b = ("0%s"%hex(b)[2:])[-2:]
        self.average_color = "#"+r+g+b
        del pb
        return self.average_color


    #### Flow commands
    def command_if(self, surface, type=None, windows=None,
                   size=None, content=None):
        if content is None:
            return surface
        # TODO: complete this
##        l = []
##        splits = ['!', '(', ')', '&', '|']
##        for c in type:
##            if c in splits:
##                l.append(c)
##            elif l[-1] in splits:
##                l.append(c)
##            elif not l:
##                l.append(c)
##            else:
##                l[-1] += c
        # Check if the type condition is satisfied
        if type is not None:
            negation = False
            if type[0] == "!" :
                type = type[1:]
                negation = True
            is_type = bool(type in self.TYPE_DICT \
                      and self.type & self.TYPE_DICT[type])
            if not (is_type ^ negation):
                return surface

        #Check if the window number condition is satisfied
        if windows is not None:
            arg = windows
            negation = False
            if arg[0] == "!" :
                arg = windows[1:]
                negation = True
            if arg[0] == ":":
                arg = "0" + arg
            elif arg[-1] == ":":
                arg = arg +"15"
            l = arg.split(":", 1)
            try:
                l = [int(n) for n in l]
            except ValueError:
                print 'Theme Error: The windows attribute of ' + \
                      'an <if> statement can\'t look like this:' + \
                      ' "%s". See Theming HOWTO for more information'%windows
                return surface
            if len(l) == 1:
                if not ((l[0] == self.win_nr) ^ negation):
                    return surface
            else:
                if not ((l[0]<=self.win_nr and self.win_nr<=l[1]) ^ negation):
                    return surface

        #Check if the icon size condition is satisfied
        if size is not None:
            arg = size
            negation = False
            if arg[0] == "!" :
                arg = size[1:]
                negation = True
            if arg[0] == ":":
                arg = "0" + arg
            elif arg[-1] == ":":
                arg = arg +"200"
            l = arg.split(":", 1)
            try:
                l = [int(n) for n in l]
            except ValueError:
                print 'Theme Error: The size attribute of ' + \
                      'an <if> statement can\'t look like this:' + \
                      ' "%s". See Theming HOWTO for more information'%size
                return surface
            if len(l) == 1:
                if not ((l[0] == self.win_nr) ^ negation):
                    return surface
            else:
                if not ((l[0]<=self.size and self.size<=l[1]) ^ negation):
                    return surface

        # All tests passed, proceed.
        for command, args in content.items():
            try:
                f = getattr(self,"command_%s"%command)
            except:
                raise
            else:
                surface = f(surface, **args)
        return surface

    def command_pixmap_from_self(self, surface, name, content=None):
        if not name:
            print "Theme Error: no name given for pixmap_from_self"
            raise Exeption
        w = int(surface.get_width())
        h = int(surface.get_height())
        self.temp[name] = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(self.temp[name])
        ctx.set_source_surface(surface)
        ctx.paint()
        if content is None:
            return surface
        for command,args in content.items():
            try:
                f = getattr(self,"command_%s"%command)
            except:
                raise
            else:
                self.temp[name] = f(self.temp[name], **args)
        return surface

    def command_pixmap(self, surface, name, content=None, size=None):
        if size is not None:
            # TODO: Fix for different height and width
            w = h = self.size + int(size)
        elif surface is None:
            w = h = self.size
        else:
            w = surface.get_width()
            h = surface.get_height()
        self.temp[name] = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        if content is None:
            return surface
        for command,args in content.items():
            try:
                f = getattr(self,"command_%s"%command)
            except:
                raise
            else:
                self.temp[name] = f(self.temp[name], **args)
        return surface


    #### Get icon
    def command_get_icon(self,surface=None, size=0):
        size = int(size)
        size = self.size + size
        if size <= 0:
            # To avoid chrashes.
            size = 15
        if self.icon \
        and self.icon.get_width() == size \
        and self.icon.get_height() == size:
            return self.icon
        del self.icon
        self.icon = None
        pb = self.find_icon_pixbuf(size)
        if pb.get_width() != pb.get_height():
            if pb.get_width() < pb.get_height():
                h = size
                w = pb.get_width() * size/pb.get_height()
            elif pb.get_width() > pb.get_height():
                w = size
                h = pb.get_height() * size/pb.get_width()
            self.icon = cairo.ImageSurface(cairo.FORMAT_ARGB32, size, size)
            ctx = gtk.gdk.CairoContext(cairo.Context(self.icon))
            pbs = pb.scale_simple(w, h, gtk.gdk.INTERP_BILINEAR)
            woffset = int(float(size - w) / 2 + 0.5)
            hoffset = int(float(size - h) / 2 + 0.5)
            ctx.set_source_pixbuf(pb, woffset, hoffset)
            ctx.paint()
            del pb
            del pbs
        elif pb.get_width() != size:
            pbs = pb.scale_simple(size, size, gtk.gdk.INTERP_BILINEAR)
            self.icon = self.pixbuf2surface(pbs)
            del pb
            del pbs
        else:
            self.icon = self.pixbuf2surface(pb)
            del pb
        return self.icon


    def find_icon_pixbuf(self, size):
        # Returns the icon pixbuf for the program. Uses the following metods:

        # 1) If it is a launcher, return the icon from the
        #    launcher's desktopfile
        # 2) Get the icon from the gio app
        # 3) Check if the res_class fits an themed icon.
        # 4) Search in path after a icon matching reclass.
        # 5) Use the mini icon for the class

        pixbuf = None
        icon_name = None
        if self.desktop_entry:
            icon_name = self.desktop_entry.getIcon()
            if os.path.isfile(icon_name):
                pixbuf = self.icon_from_file_name(icon_name, size)
                if pixbuf is not None:
                    return pixbuf

        if not icon_name:
            if self.identifier:
                icon_name = self.identifier.lower()
            elif self.class_group:
                icon_name = self.class_group.get_res_class().lower()
            else:
                icon_name = ""

            # Special cases
            if icon_name.startswith('openoffice'):
                # Makes sure openoffice gets a themed icon
                icon_name = "ooo-writer"

        if self.icon_theme.has_icon(icon_name):
            return self.icon_theme.load_icon(icon_name,size,0)

        if icon_name[-4:] in (".svg", ".png", ".xpm"):
            if self.icon_theme.has_icon(icon_name[:-4]):
                pixbuf = self.icon_theme.load_icon(icon_name[:-4],size,0)
                if pixbuf is not None:
                    return pixbuf

        pixbuf = self.icon_search_in_data_path(icon_name, size)
        if pixbuf is not None:
            return pixbuf

        if self.class_group:
            return self.class_group.get_icon().copy()


        # If no pixbuf has been found (can only happen for an unlaunched
        # launcher), make an empty pixbuf and show a warning.
        if self.icon_theme.has_icon('application-default-icon'):
            pixbuf = self.icon_theme.load_icon('application-default-icon',
                                                size, 0)
        else:
            pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, size,size)
            pixbuf.fill(0x00000000)
        if self.desktop_entry:
            name = self.desktop_entry.getName()
        else:
            name = None
##        dialog = gtk.MessageDialog(
##                    parent=None,
##                    flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
##                    type=gtk.MESSAGE_WARNING,
##                    buttons=gtk.BUTTONS_OK,
##                    message_format= (_("Cannot load icon for %s")%name))
##        dialog.set_title('DockBarX')
##        dialog.run()
##        dialog.destroy()
        return pixbuf

    def icon_from_file_name(self, icon_name, icon_size = -1):
        if os.path.isfile(icon_name):
            try:
                return gtk.gdk.pixbuf_new_from_file_at_size(icon_name, -1,
                                                            icon_size)
            except:
                pass
        return None

    def icon_search_in_data_path(self, icon_name, icon_size):
        data_folders = None

        if os.environ.has_key("XDG_DATA_DIRS"):
            data_folders = os.environ["XDG_DATA_DIRS"]

        if not data_folders:
            data_folders = "/usr/local/share/:/usr/share/"

        for data_folder in data_folders.split(':'):
            #The line below line used datafolders instead of datafolder.
            #I changed it because I suspect it was a bug.
            paths = (os.path.join(data_folder, "pixmaps", icon_name),
                     os.path.join(data_folder, "icons", icon_name))
            for path in paths:
                if os.path.isfile(path):
                    icon = self.icon_from_file_name(path, icon_size)
                    if icon:
                        return icon
        return None


    #### Other commands
    def command_get_pixmap(self, surface, name, size=0):
        if surface is None:
            if self.globals.orient == 'h':
                width = int(self.size * ar)
                height = self.size
            else:
                width = self.size
                height = int(self.size * ar)
        else:
            width = surface.get_width()
            height = surface.get_height()
        if self.theme.has_surface(name):
            surface = self.resize_surface(self.theme.get_surface(name),
                                          width, height)
        else:
            print "theme error: pixmap %s not found"%name
        return surface

    def command_fill(self, surface, color, opacity=100):
        w = surface.get_width()
        h = surface.get_height()
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_surface(surface)
        ctx.paint()

        alpha = self.get_alpha(opacity)
        c = self.get_color(color)
        r = float(int(c[1:3], 16))/255
        g = float(int(c[3:5], 16))/255
        b = float(int(c[5:7], 16))/255
        ctx.set_source_rgba(r, g, b)
        ctx.set_operator(cairo.OPERATOR_SOURCE)
        ctx.paint_with_alpha(alpha)
        return new


    def command_combine(self, surface, pix1, pix2, degrees=90):
        # Combines left half of surface with right half of surface2.
        # The transition between the two halves are soft.
        w = surface.get_width()
        h = surface.get_height()
        if pix1=="self":
            p1 = surface
        elif pix1 in self.temp:
            p1 = self.temp[pix1]
        elif self.theme.has_surface(pix1):
            w = surface.get_width()
            h = surface.get_height()
            p1 = self.resize_surface(self.theme.get_surface(bg), w, h)
        else:
            print "theme error: pixmap %s not found"%pix1
        if pix2=="self":
            p2 = surface
        elif pix2 in self.temp:
            p2 = self.temp[pix2]
        elif self.theme.has_surface(pix2):
            w = surface.get_width()
            h = surface.get_height()
            p2 = self.resize_surface(self.theme.get_surface(bg), w, h)
        else:
            print "theme error: pixmap %s not found"%pix2

        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
                                     p1.get_width(), p1.get_height())
        ctx = cairo.Context(surface)

        linear = cairo.LinearGradient(0, 0, p1.get_width(), 0)
        linear.add_color_stop_rgba(0.4, 0, 0, 0, 0.5)
        linear.add_color_stop_rgba(0.6, 0, 0, 0, 1)
        ctx.set_source_surface(p2, 0, 0)
        #ctx.mask(linear)
        ctx.paint()

        linear = cairo.LinearGradient(0, 0, p1.get_width(), 0)
        linear.add_color_stop_rgba(0.4, 0, 0, 0, 1)
        linear.add_color_stop_rgba(0.6, 0, 0, 0, 0)
        ctx.set_source_surface(p1, 0, 0)
        ctx.mask(linear)
        try:
            del pb
            del pbs
        except:
            pass
        return surface

    def command_transp_sat(self, surface, opacity=100, saturation=100):
        # Makes the icon desaturized and/or transparent.
        w = surface.get_width()
        h = surface.get_height()
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = gtk.gdk.CairoContext(cairo.Context(new))
        alpha = self.get_alpha(opacity)
        # Todo: Add error check for saturation
        if int(saturation) < 100:
            sio = StringIO()
            surface.write_to_png(sio)
            sio.seek(0)
            loader = gtk.gdk.PixbufLoader()
            loader.write(sio.getvalue())
            loader.close()
            sio.close()
            pixbuf = loader.get_pixbuf()
            saturation = min(1.0, float(saturation)/100)
            pixbuf.saturate_and_pixelate(pixbuf, saturation, False)
            ctx.set_source_pixbuf(pixbuf, 0, 0)
            ctx.paint_with_alpha(alpha)
            del loader
            del sio
            del pixbuf
            gc.collect()
        else:
            ctx.set_source_surface(surface)
            ctx.paint_with_alpha(alpha)
        return new

    def command_composite(self, surface, bg, fg,
                          opacity=100, xoffset=0, yoffset=0):
        if fg=="self":
            foreground = surface
        elif fg in self.temp:
            foreground = self.temp[fg]
        elif self.theme.has_surface(fg):
            w = surface.get_width()
            h = surface.get_height()
            foreground = self.resize_surface(self.theme.get_surface(fg), w, h)
        else:
            print "theme error: pixmap %s not found"%fg
            return surface

        if bg=="self":
            background = surface
        elif bg in self.temp:
            w = self.temp[bg].get_width()
            h = self.temp[bg].get_height()
            background = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
            ctx = cairo.Context(background)
            ctx.set_source_surface(self.temp[bg])
            ctx.paint()
        elif self.theme.has_surface(bg):
            w = surface.get_width()
            h = surface.get_height()
            background = self.resize_surface(self.theme.get_surface(bg), w, h)
        else:
            print "theme error: pixmap %s not found"%bg
            return surface

        opacity = self.get_alpha(opacity)
        xoffset = float(xoffset)
        yoffset = float(yoffset)
        ctx = cairo.Context(background)
        ctx.set_source_surface(foreground, xoffset, yoffset)
        ctx.paint_with_alpha(opacity)
        return background

    def command_shrink(self, surface, percent=0, pixels=0):
        w0 = surface.get_width()
        h0 = surface.get_height()
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w0, h0)
        ctx = cairo.Context(new)

        w = int(((100-int(percent)) * w0)/100)-int(pixels)
        h = int(((100-int(percent)) * h0)/100)-int(pixels)
        shrinked = self.resize_surface(surface, w, h)
        x = int(float(w0 - w) / 2 + 0.5)
        y = int(float(h0 - h) / 2 + 0.5)
        ctx.set_source_surface(shrinked, x, y)
        ctx.paint()
        del shrinked
        return new

    def command_correct_size(self, surface):
        if surface is None:
            return
        if self.globals.orient == 'v':
            width = self.size
            height = int(self.size * self.ar)
        else:
            width = int(self.size * self.ar)
            height = self.size
        if surface.get_width() == width and surface.get_height() == height:
            return surface
        woffset = int(float(width - surface.get_width()) / 2 + 0.5)
        hoffset = int(float(height - surface.get_height()) / 2 + 0.5)
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
        ctx = cairo.Context(new)
        ctx.set_source_surface(surface, woffset, hoffset)
        ctx.paint()
        return new

    def command_glow(self, surface, color, opacity=100):
        # Adds a glow around the parts of the surface
        # that isn't completely transparent.

        alpha = self.get_alpha(opacity)
        # Thickness (pixels)
        tk = 1.5


        # Prepare the glow that should be put behind the icon
        cs = self.command_colorize(surface, color)
        w = surface.get_width()
        h = surface.get_height()
        glow = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(glow)
        tk1 = tk/2.0
        for x, y in ((-tk1,-tk1), (-tk1,tk1), (tk1,-tk1), (tk1,tk1)):
            ctx.set_source_surface(cs, x, y)
            ctx.paint_with_alpha(0.66)
        for x, y in ((-tk,-tk), (-tk,tk), (tk,-tk), (tk,tk)):
            ctx.set_source_surface(cs, x, y)
            ctx.paint_with_alpha(0.27)

        # Add glow and icon to a new canvas
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_surface(glow)
        ctx.paint_with_alpha(alpha)
        ctx.set_source_surface(surface)
        ctx.paint()
        return new

    def command_colorize(self, surface, color):
        # Changes the color of all pixels to color.
        # The pixels alpha values are unchanged.

        # Convert color hex-string (format '#FFFFFF')to int r, g, b
        color = self.get_color(color)
        r = int(color[1:3], 16)/255.0
        g = int(color[3:5], 16)/255.0
        b = int(color[5:7], 16)/255.0

        w = surface.get_width()
        h = surface.get_height()
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_rgba(r,g,b,1.0)
        ctx.mask_surface(surface)
        return new


    def command_bright(self, surface, strength = None, strenght = None):
        if strength is None and strenght is not None:
            # For compability with older themes.
            strength = strenght
        alpha = self.get_alpha(strength)
        w = surface.get_width()
        h = surface.get_height()
        # Colorize white
        white = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(white)
        ctx.set_source_rgba(1.0, 1.0, 1.0, 1.0)
        ctx.mask_surface(surface)
        # Apply the white version over the icon
        # with the chosen alpha value
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_surface(surface)
        ctx.paint()
        ctx.set_source_surface(white)
        ctx.paint_with_alpha(alpha)
        return new

    def command_alpha_mask(self, surface, mask):
        if mask in self.temp:
            mask = self.temp[mask]
        elif self.theme.has_surface(mask):
            m = self.surface2pixbuf(self.theme.get_surface(mask))
            m = m.scale_simple(surface.get_width(), surface.get_height(),
                               gtk.gdk.INTERP_BILINEAR)
            mask = self.pixbuf2surface(m)
        w = surface.get_width()
        h = surface.get_height()
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_surface(surface)
        ctx.mask_surface(mask)
        return new

#### Format conversions
    def pixbuf2surface(self, pixbuf):
        if pixbuf is None:
            return None
        w = pixbuf.get_width()
        h = pixbuf.get_height()
        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = gtk.gdk.CairoContext(cairo.Context(surface))
        ctx.set_source_pixbuf(pixbuf, 0, 0)
        ctx.paint()
        del pixbuf
        return surface

    def surface2pixbuf(self, surface):
        if surface is None:
            return None
        sio = StringIO()
        surface.write_to_png(sio)
        sio.seek(0)
        loader = gtk.gdk.PixbufLoader()
        loader.write(sio.getvalue())
        loader.close()
        sio.close()
        pixbuf = loader.get_pixbuf()
        return pixbuf

    def surface2pil(self, surface):
        w = surface.get_width()
        h = surface.get_height()
        return Image.frombuffer("RGBA", (w, h), surface.get_data(),
                                "raw", "RGBA", 0,1)


    def pil2surface(self, im):
        imgd = im.tostring("raw","RGBA",0,1)
        a = array.array('B',imgd)
        w = im.size[0]
        h = im.size[1]
        stride = im.size[0] * 4
        surface = cairo.ImageSurface.create_for_data (a, cairo.FORMAT_ARGB32,
                                                      w, h, stride)
        return surface

    def resize_surface(self, surface, w, h):
        im = self.surface2pil(surface)
        im = im.resize((w, h), Image.ANTIALIAS)
        return self.pil2surface(im)
Beispiel #15
0
 def get_context_data(self, **kwargs):
     context = super(HomeView, self).get_context_data(**kwargs)
     theme = Theme.get_random_theme()
     context['banner_class'] = theme.css_class
     context['iama_form'] = IamaForm(initial={'weapon':theme.weapon, 'gender':theme.gender})
     return context
Beispiel #16
0
class Slide(object):
  """
  Slide object.
  """

  @classmethod
  def reset(cls):
    """Reset to default state."""
    return

  def __init__(self, number, position=None, title=None, contents=None):
    """"
    Paramters
    ---------
    number: int
      slide global numeration
    position: dict
      position dictionary containing {'x': posx, 'y': posy, 'z': posz, 'rotx': rotx, 'roty': roty, 'rotz': rotz, 'scale': scaling}
    title: str
    contents: str
    """
    self.number = number
    self.position = None
    self.set_position(position)
    self.title = title
    self.contents = contents
    self.overtheme = Theme()
    return

  def __str__(self):
    strings = [str(self.title)]
    strings.append(str(self.contents))
    return ''.join(strings)

  def get_overtheme(self, parser):
    """Get eventaul overtheme definition.

    Parameters
    ----------
    parser: Parser
    """
    codeblocks = parser.tokenizer(source=self.contents, re_search=parser.regexs['codeblock'])
    yamlblocks = parser.tokenizer(source=self.contents, re_search=parser.regexs['yamlblock'], exclude=codeblocks)
    if len(yamlblocks) > 0:
      self.overtheme.get(source=''.join([block['match'].group().strip('---') for block in yamlblocks]),
                         name='overtheme',
                         div_id='slide-' + str(self.number))
      purged_contents = self.contents[:yamlblocks[0]['start']]
      for b, yamlblock in enumerate(yamlblocks[:-1]):
        purged_contents += self.contents[yamlblock['end']:yamlblocks[b + 1]['start']]
      purged_contents += self.contents[yamlblocks[-1]['end']:]
      self.contents = purged_contents

  def set_position(self, position):
    """Set slide position.

    Parameters
    ----------
    position: dict
      position dictionary containing {'x': posx, 'y': posy, 'z': posz, 'rotx': rotx, 'roty': roty, 'rotz': rotz, 'scale': scaling}
    """
    if position is not None:
      self.position = {}
      for key in position:
        self.position[key] = position[key]

  def put_html_attributes(self, doc):
    """Put html attibutes of the slide.

    Parameters
    ----------
    doc: Doc
    """
    doc.attr(('id', 'slide-' + str(self.number)))
    # doc.attr(('title', str(self.title)))
    doc.attr(('class', 'step slide'))
    doc.attr(('data-x', str(self.position['x'])))
    doc.attr(('data-y', str(self.position['y'])))
    doc.attr(('data-z', str(self.position['z'])))
    doc.attr(('data-scale', str(self.position['scale'])))
    doc.attr(('data-rotate-x', str(self.position['rotx'])))
    doc.attr(('data-rotate-y', str(self.position['roty'])))
    doc.attr(('data-rotate-z', str(self.position['rotz'])))
    return

  def to_html(self, doc, parser, metadata, theme, current):
    """Generate html from self.

    Parameters
    ----------
    doc: Doc
    parser: Parser
    metatadata: dict
      presentation metadata
    theme: Theme()
      presentation theme
    current: list
    """
    def _parse_env(Env, re_search, source):
      codeblocks = parser.tokenizer(source=source, re_search=parser.regexs['codeblock'])
      codes = parser.tokenizer(source=source, re_search=parser.regexs['code'], exclude=codeblocks)
      yamlblocks = parser.tokenizer(source=source, re_search=parser.regexs['yamlblock'], exclude=codeblocks + codes)
      envs = parser.tokenizer(source=source, re_search=re_search, exclude=codeblocks + yamlblocks + codes)
      if len(envs) > 0:
        parsed_source = source[:envs[0]['start']]
        for e, env in enumerate(envs[:-1]):
          current = Env(source=env['match'].group())
          parsed_source += current.to_html() + source[env['end']:envs[e + 1]['start']]
        if Env is Video:
          if self.overtheme.custom:
            current = Env(source=envs[-1]['match'].group(), theme=self.overtheme)
          else:
            current = Env(source=envs[-1]['match'].group(), theme=theme)
        else:
          current = Env(source=envs[-1]['match'].group())
        parsed_source += current.to_html() + source[envs[-1]['end']:]
        return parsed_source
      return source

    html = self.contents
    for meta in metadata:
      html = metadata[meta].parse(parser=parser, source=html, toc_depth=metadata['toc_depth'].value, max_time=metadata['max_time'].value, current=current)
    html = _parse_env(Env=Box, re_search=Box.regexs['box'], source=html)
    html = _parse_env(Env=Note, re_search=Note.regexs['note'], source=html)
    html = _parse_env(Env=Figure, re_search=Figure.regexs['figure'], source=html)
    html = _parse_env(Env=Table, re_search=Table.regexs['table'], source=html)
    html = _parse_env(Env=Video, re_search=Video.regexs['video'], source=html)
    html = _parse_env(Env=Columns, re_search=Columns.regexs['columns'], source=html)
    with doc.tag('div', klass='slide-content'):
      doc.asis(markdown2html(source=html))
    return
Beispiel #17
0
class SettingsManager(object):
    """Organizes user settings"""
    def __init__(self, alot_rc=None, notmuch_rc=None):
        """
        :param alot_rc: path to alot's config file
        :type alot_rc: str
        :param notmuch_rc: path to notmuch's config file
        :type notmuch_rc: str
        :theme: path to initially used theme file
        :type theme: str
        """
        self.hooks = None
        self._mailcaps = mailcap.getcaps()
        self._config = ConfigObj()
        self._notmuchconfig = None
        self._theme = None
        self._accounts = None
        self._accountmap = None
        bindings_path = os.path.join(DEFAULTSPATH, 'default.bindings')
        self._bindings = ConfigObj(bindings_path)
        if alot_rc is not None:
            self.read_config(alot_rc)
        if notmuch_rc is not None:
            self.read_notmuch_config(notmuch_rc)

    def read_notmuch_config(self, path):
        """parse notmuch's config file from path"""
        spec = os.path.join(DEFAULTSPATH, 'notmuch.rc.spec')
        self._notmuchconfig = read_config(path, spec)

    def read_config(self, path):
        """parse alot's config file from path"""
        spec = os.path.join(DEFAULTSPATH, 'alot.rc.spec')
        newconfig = read_config(path, spec,
                                checks={'mail_container': mail_container,
                                        'force_list': force_list,
                                        'align': align_mode,
                                        'attrtriple': attr_triple,
                                        'gpg_key_hint': gpg_key})
        self._config.merge(newconfig)

        hooks_path = os.path.expanduser(self._config.get('hooksfile'))
        try:
            self.hooks = imp.load_source('hooks', hooks_path)
        except:
            logging.debug('unable to load hooks file:%s' % hooks_path)
        if 'bindings' in newconfig:
            newbindings = newconfig['bindings']
            if isinstance(newbindings, Section):
                self._bindings.merge(newbindings)
        # themes
        themestring = newconfig['theme']
        themes_dir = self._config.get('themes_dir')
        if themes_dir:
            themes_dir = os.path.expanduser(themes_dir)
        else:
            configdir = os.environ.get('XDG_CONFIG_HOME',
                                       os.path.expanduser('~/.config'))
            themes_dir = os.path.join(configdir, 'alot', 'themes')
        logging.debug(themes_dir)

        # if config contains theme string use that
        if themestring:
            if not os.path.isdir(themes_dir):
                err_msg = 'cannot find theme %s: themes_dir %s is missing'
                raise ConfigError(err_msg % (themestring, themes_dir))
            else:
                theme_path = os.path.join(themes_dir, themestring)
                try:
                    self._theme = Theme(theme_path)
                except ConfigError as e:
                    err_msg = 'Theme file %s failed validation:\n'
                    raise ConfigError((err_msg % themestring) + e.message)

        # if still no theme is set, resort to default
        if self._theme is None:
            theme_path = os.path.join(DEFAULTSPATH, 'default.theme')
            self._theme = Theme(theme_path)

        self._accounts = self._parse_accounts(self._config)
        self._accountmap = self._account_table(self._accounts)

    def _parse_accounts(self, config):
        """
        read accounts information from config

        :param config: valit alot config
        :type config: `configobj.ConfigObj`
        :returns: list of accounts
        """
        accounts = []
        if 'accounts' in config:
            for acc in config['accounts'].sections:
                accsec = config['accounts'][acc]
                args = dict(config['accounts'][acc])

                # create abook for this account
                abook = accsec['abook']
                logging.debug('abook defined: %s' % abook)
                if abook['type'] == 'shellcommand':
                    cmd = abook['command']
                    regexp = abook['regexp']
                    if cmd is not None and regexp is not None:
                        args['abook'] = MatchSdtoutAddressbook(cmd,
                                                               match=regexp)
                    else:
                        msg = 'underspecified abook of type \'shellcommand\':'
                        msg += '\ncommand: %s\nregexp:%s' % (cmd, regexp)
                        raise ConfigError(msg)
                elif abook['type'] == 'abook':
                    contacts_path = abook['abook_contacts_file']
                    args['abook'] = AbookAddressBook(contacts_path, ignorecase=abook['ignorecase'])
                else:
                    del(args['abook'])

                cmd = args['sendmail_command']
                del(args['sendmail_command'])
                newacc = SendmailAccount(cmd, **args)
                accounts.append(newacc)
        return accounts

    def _account_table(self, accounts):
        """
        creates a lookup table (emailaddress -> account) for a given list of
        accounts

        :param accounts: list of accounts
        :type accounts: list of `alot.account.Account`
        :returns: hashtable
        :rvalue: dict (str -> `alot.account.Account`)
        """
        accountmap = {}
        for acc in accounts:
            accountmap[acc.address] = acc
            for alias in acc.aliases:
                accountmap[alias] = acc
        return accountmap

    def get(self, key, fallback=None):
        """
        look up global config values from alot's config

        :param key: key to look up
        :type key: str
        :param fallback: fallback returned if key is not present
        :type fallback: str
        :returns: config value with type as specified in the spec-file
        """
        value = None
        if key in self._config:
            value = self._config[key]
            if isinstance(value, Section):
                value = None
        if value is None:
            value = fallback
        return value

    def set(self, key, value):
        """
        setter for global config values

        :param key: config option identifise
        :type key: str
        :param value: option to set
        :type value: depends on the specfile :file:`alot.rc.spec`
        """
        self._config[key] = value

    def get_notmuch_setting(self, section, key, fallback=None):
        """
        look up config values from notmuch's config

        :param section: key is in
        :type section: str
        :param key: key to look up
        :type key: str
        :param fallback: fallback returned if key is not present
        :type fallback: str
        :returns: config value with type as specified in the spec-file
        """
        value = None
        if section in self._notmuchconfig:
            if key in self._notmuchconfig[section]:
                value = self._notmuchconfig[section][key]
        if value is None:
            value = fallback
        return value

    def get_theming_attribute(self, mode, name, part=None):
        """
        looks up theming attribute

        :param mode: ui-mode (e.g. `search`,`thread`...)
        :type mode: str
        :param name: identifier of the atttribute
        :type name: str
        :rtype: urwid.AttrSpec
        """
        colours = int(self._config.get('colourmode'))
        return self._theme.get_attribute(colours, mode, name, part)

    def get_threadline_theming(self, thread):
        """
        looks up theming info a threadline displaying a given thread. This
        wraps around :meth:`~alot.settings.theme.Theme.get_threadline_theming`,
        filling in the current colour mode.

        :param thread: thread to theme
        :type thread: alot.db.thread.Thread
        """
        colours = int(self._config.get('colourmode'))
        return self._theme.get_threadline_theming(thread, colours)

    def get_tagstring_representation(self, tag, onebelow_normal=None,
                                     onebelow_focus=None):
        """
        looks up user's preferred way to represent a given tagstring.

        :param tag: tagstring
        :type tag: str
        :param onebelow_normal: attribute that shines through if unfocussed
        :type onebelow_normal: urwid.AttrSpec
        :param onebelow_focus: attribute that shines through if focussed
        :type onebelow_focus: urwid.AttrSpec

        If `onebelow_normal` or `onebelow_focus` is given these attributes will
        be used as fallbacks for fg/bg values '' and 'default'.

        This returns a dictionary mapping
            :normal: to :class:`urwid.AttrSpec` used if unfocussed
            :focussed: to :class:`urwid.AttrSpec` used if focussed
            :translated: to an alternative string representation
        """
        colourmode = int(self._config.get('colourmode'))
        theme = self._theme
        cfg = self._config
        colours = [1, 16, 256]

        def colourpick(triple):
            """ pick attribute from triple (mono,16c,256c) according to current
            colourmode"""
            if triple is None:
                return None
            return triple[colours.index(colourmode)]

        # global default attributes for tagstrings.
        # These could contain values '' and 'default' which we interpret as
        # "use the values from the widget below"
        default_normal = theme.get_attribute(colourmode, 'global', 'tag')
        default_focus = theme.get_attribute(colourmode, 'global', 'tag_focus')

        # local defaults for tagstring attributes. depend on next lower widget
        fallback_normal = resolve_att(onebelow_normal, default_normal)
        fallback_focus = resolve_att(onebelow_focus, default_focus)

        for sec in cfg['tags'].sections:
            if re.match('^' + sec + '$', tag):
                normal = resolve_att(colourpick(cfg['tags'][sec]['normal']),
                                     fallback_normal)
                focus = resolve_att(colourpick(cfg['tags'][sec]['focus']),
                                    fallback_focus)

                translated = cfg['tags'][sec]['translated']
                if translated is None:
                    translated = tag
                translation = cfg['tags'][sec]['translation']
                if translation:
                    translated = re.sub(translation[0], translation[1], tag)
                break
        else:
            normal = fallback_normal
            focus = fallback_focus
            translated = tag

        return {'normal': normal, 'focussed': focus, 'translated': translated}

    def get_hook(self, key):
        """return hook (`callable`) identified by `key`"""
        if self.hooks:
            if key in self.hooks.__dict__:
                return self.hooks.__dict__[key]
        return None

    def get_mapped_input_keysequences(self, mode=None, prefix=u''):
        candidates = self._bindings.scalars
        if mode is not None:
            candidates = candidates + self._bindings[mode].scalars
        return [s for s in candidates if s.startswith(prefix)]

    def get_keybinding(self, mode, key):
        """look up keybinding from `MODE-maps` sections

        :param mode: mode identifier
        :type mode: str
        :param key: urwid-style key identifier
        :type key: str
        :returns: a command line to be applied upon keypress
        :rtype: str
        """
        cmdline = None
        bindings = self._bindings
        if key in bindings.scalars:
            cmdline = bindings[key]
        if mode in bindings.sections:
            if key in bindings[mode].scalars:
                value = bindings[mode][key]
                if value:
                    cmdline = value
        # Workaround for ConfigObj misbehaviour. cf issue #500
        # this ensures that we get at least strings only as commandlines
        if isinstance(cmdline, list):
            cmdline = ','.join(cmdline)
        return cmdline

    def get_accounts(self):
        """
        returns known accounts

        :rtype: list of :class:`Account`
        """
        return self._accounts

    def get_account_by_address(self, address):
        """
        returns :class:`Account` for a given email address (str)

        :param address: address to look up
        :type address: string
        :rtype:  :class:`Account` or None
        """

        for myad in self.get_addresses():
            if myad in address:
                return self._accountmap[myad]
        return None

    def get_main_addresses(self):
        """returns addresses of known accounts without its aliases"""
        return [a.address for a in self._accounts]

    def get_addresses(self):
        """returns addresses of known accounts including all their aliases"""
        return self._accountmap.keys()

    def get_addressbooks(self, order=[], append_remaining=True):
        """returns list of all defined :class:`AddressBook` objects"""
        abooks = []
        for a in order:
            if a:
                if a.abook:
                    abooks.append(a.abook)
        if append_remaining:
            for a in self._accounts:
                if a.abook and a.abook not in abooks:
                    abooks.append(a.abook)
        return abooks

    def mailcap_find_match(self, *args, **kwargs):
        """
        Propagates :func:`mailcap.find_match` but caches the mailcap (first
        argument)
        """
        return mailcap.findmatch(self._mailcaps, *args, **kwargs)

    def represent_datetime(self, d):
        """
        turns a given datetime obj into a unicode string representation.
        This will:

        1) look if a fixed 'timestamp_format' is given in the config
        2) check if a 'timestamp_format' hook is defined
        3) use :func:`~alot.helper.pretty_datetime` as fallback
        """

        fixed_format = self.get('timestamp_format')
        if fixed_format:
            rep = string_decode(d.strftime(fixed_format), 'UTF-8')
        else:
            format_hook = self.get_hook('timestamp_format')
            if format_hook:
                rep = string_decode(format_hook(d), 'UTF-8')
            else:
                rep = pretty_datetime(d)
        return rep
Beispiel #18
0
	def __init__(self):
		Theme.__init__(self)
Beispiel #19
0
	def setupTheme(self):
		Theme.setupTheme(self)
Beispiel #20
0
class DockBar():
    def __init__(self, applet=None, as_awn_applet=False):
        print "Dockbarx init"
        self.applet = applet
        self.groups = None
        self.windows = None
        self.container = None
        self.theme = None

        self.gkeys = {
                        'gkeys_select_next_group': None,
                        'gkeys_select_previous_group': None,
                        'gkeys_select_next_window': None,
                        'gkeys_select_previous_window': None
                     }

        wnck.set_client_type(wnck.CLIENT_TYPE_PAGER)
        self.screen = wnck.screen_get_default()
        self.root_xid = int(gtk.gdk.screen_get_default().get_root_window().xid)
        self.screen.force_update()

        self.globals = Globals()
        self.globals.connect('theme-changed', self.reload)


        #--- Applet / Window container
        if self.applet is not None:
            self.applet.set_applet_flags(
                            gnomeapplet.HAS_HANDLE|gnomeapplet.EXPAND_MINOR)
            if self.applet.get_orient() == gnomeapplet.ORIENT_DOWN \
            or applet.get_orient() == gnomeapplet.ORIENT_UP:
                self.globals.orient = "h"
                self.container = gtk.HBox()
            else:
                self.globals.orient = "v"
                self.container = gtk.VBox()
            self.applet.add(self.container)
            self.pp_menu_xml = """
           <popup name="button3">
           <menuitem name="About Item" verb="About" stockid="gtk-about" />
           <menuitem name="Preferences" verb="Pref" stockid="gtk-properties" />
           <menuitem name="Reload" verb="Reload" stockid="gtk-refresh" />
           </popup>
            """

            self.pp_menu_verbs = [("About", self.on_ppm_about),
                                  ("Pref", self.on_ppm_pref),
                                  ("Reload", self.reload)]
            self.applet.setup_menu(self.pp_menu_xml, self.pp_menu_verbs,None)
            self.applet_origin_x = -1000
            self.applet_origin_y = -1000
            # background bug workaround
            self.applet.set_background_widget(applet)
            self.applet.show_all()
        else:
            self.container = gtk.HBox()
            self.globals.orient = "h"

        # Wait until the container is realized before adding anything to it.
        if not as_awn_applet:
            gobject.timeout_add(10, self.reload_on_realized)

        if self.applet is not None:
            self.applet.connect("size-allocate",self.on_applet_size_alloc)
            self.applet.connect("change_background", self.on_change_background)
            self.applet.connect("change-orient",self.on_change_orient)
            self.applet.connect("delete-event",self.cleanup)

        self.on_gkeys_changed(dialog=False)
        self.globals.connect('gkey-changed', self.on_gkeys_changed)

    def reload_on_realized(self):
        if self.container.window is None:
            return True
        self.reload()
        return False


    def reload(self, event=None, data=None):
        # Remove all old groupbuttons from container.
        for child in self.container.get_children():
            self.container.remove(child)
        if self.windows:
            # Removes windows and unpinned group buttons
            for win in self.screen.get_windows():
                self.on_window_closed(None, win)
        if self.groups is not None:
            # Removes pinned group buttons
            for group in self.groups:
                group.hide_list()
                group.icon_factory.remove()

        del self.groups
        del self.windows
        if self.theme:
            self.theme.remove()
        gc.collect()

        print "Dockbarx reload"
        self.groups = GroupList()
        self.windows = {}
        # Get the monitor on which dockbarx is.
        gdk_screen = gtk.gdk.screen_get_default()
        win = self.container.window
        if win is not None:
            self.monitor = gdk_screen.get_monitor_at_window(win)
        #--- Generate Gio apps
        self.apps_by_id = {}
        self.app_ids_by_exec = {}
        self.app_ids_by_name = {}
        self.app_ids_by_longname = {}
        self.wine_app_ids_by_program = {}
        for app in gio.app_info_get_all():
            id = app.get_id()
            id = id[:id.rfind('.')].lower()
            name = u""+app.get_name().lower()
            exe = app.get_executable()
            if exe:
                self.apps_by_id[id] = app
                if id[:5] == 'wine-':
                    try:
                        cmd = u""+app.get_commandline().lower()
                    except AttributeError:
                        # Older versions of gio doesn't have get_comandline.
                        cmd = u""
                    if cmd.find('.exe') > 0:
                        program = cmd[:cmd.rfind('.exe')+4]
                        program = program[program.rfind('\\')+1:]
                        self.wine_app_ids_by_program[program] = id
                if name.find(' ')>-1:
                    self.app_ids_by_longname[name] = id
                else:
                    self.app_ids_by_name[name] = id
                if exe not in ('sudo','gksudo',
                                'java','mono',
                                'ruby','python'):
                    if exe[0] == '/':
                        exe = exe[exe.rfind('/')+1:]
                        self.app_ids_by_exec[exe] = id
                    else:
                        self.app_ids_by_exec[exe] = id



        try:
            if self.theme is None:
                self.theme = Theme()
            else:
                self.theme.on_theme_changed()
        except NoThemesError, details:
            print details
            sys.exit(1)

        self.container.set_spacing(self.theme.get_gap())
        self.container.show()

        #--- Initiate launchers
        self.desktop_entry_by_id = {}
        self.d_e_ids_by_exec = {}
        self.d_e_ids_by_name = {}
        self.d_e_ids_by_longname = {}
        self.d_e_ids_by_wine_program = {}

        gconf_pinned_apps = self.globals.get_pinned_apps_from_gconf()


        # Initiate launcher group buttons
        for launcher in gconf_pinned_apps:
            identifier, path = launcher.split(';')
            # Fix for launchers made in previous version of dockbarx
            identifier = identifier.lower()
            if identifier == '':
                identifier = None
            self.add_launcher(identifier, path)
        # Update pinned_apps list to remove any pinned_app that are faulty.
        self.update_pinned_apps_list()

        #--- Initiate windows
        # Initiate group buttons with windows
        for window in self.screen.get_windows():
            self.on_window_opened(self.screen, window)

        self.screen.connect("window-opened", self.on_window_opened)
        self.screen.connect("window-closed", self.on_window_closed)
        self.screen.connect("active-window-changed",
                            self.on_active_window_changed)
        self.screen.connect("viewports-changed",
                            self.on_desktop_changed)
        self.screen.connect("active-workspace-changed",
                            self.on_desktop_changed)

        self.on_active_window_changed(self.screen, None)
Beispiel #21
0
from PyQt5.QtWebEngineWidgets import QWebEngineView
from ui.settings import Settings
from ui.about import About
from ui.notes_project import CreateNotesProject
from config import Config
from utils import basedir
from theme import Theme
from components.editor import CodeEditor
from components.HTMLPreview import HTMLPreview
from components.markdown_preview import MarkdownPreview
from components.note_graph import NotesGraph
from components.statusbar import Statusbar

app = QApplication(sys.argv)
config = Config(os.path.expanduser('~/.kettle/'), 'config.ini')
themes = Theme(app, config)


class Kettle(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()
        self.filename = "untitled"

    def save_file(self):
        name = self.filename
        if not self.filename or self.filename == "untitled":
            name = QFileDialog.getSaveFileName(self, 'Save File')[0]
        file = open(name, 'wt')
        save_text = self.current_editor.toPlainText()
        file.write(save_text)
Beispiel #22
0
class Game:
	
	def __init__(self):
		
		self.ss = Size()
		
		self.theme = Theme()
		
		### CRAZY COULD BE:
			# 0 - Boring. Very boring. Classical pong
			# 1 - Better than prev. Buffs appeared 1 time a 30*250 ms
			# 2 - If you don't know what to choose, use it. Buffs appeared 1 time a 30*100 ms
			# 3 - <del>CRAZIEST</del> FUNNIEST CHOICE EVER. BUFFS APEARED 1 TIME A 0.3 S
			# 4 - epileptic
			
		self.CRAZY = PositionList(("Classic", "Soft", "Normal", "Best", "Hard"), 2) 

		# root window
		self.root = Tk()
		self.root.title("FPong")
		self.root.geometry("+0+0")
		self.root.iconphoto(False, PhotoImage(file="./images/window_icon.png"))
		self.root.resizable(False, False)
		
		# Create Canvas wit elements on it
		self.__init_canva()

		self.root.mainloop()
	
	def run(self, vs_bot):
		self.vs_bot = vs_bot
		self.left_pad.bot = vs_bot
		self._stop_cont_game()
		self.cur_menu = self.stop_menu
		self.main()
	
	def main(self):
		if not self.game_stopped:
			self.ball.move()
			self.right_pad.move(speed_up=self.buffs.r_pad_speed_up)
			self.buffs.update(self.ball.id)
			if self.vs_bot:
				self.left_pad.move(self.c.get_y_center(self.ball.id), \
									self.buffs.l_pad_speed_up)
			else:
				self.left_pad.move(speed_up=self.buffs.l_pad_speed_up)
		# recall himself every 30 ms
		self.after_id = self.root.after(30, self.main)
	
	def win(self):
		self._increase_score(self.player.id)
		self.ball.respawn_ball()
		
	def loose(self):
		self._increase_score(self.player.other.id)
		
	def _increase_score(self, player):
		if player == Player.LEFT:
			self.player.l_player.score += 1
			self.c.itemconfig(self.pl_l_text, text=self.player.l_player.score)
		else:
			self.player.r_player.score += 1
			self.c.itemconfig(self.pl_r_text, text=self.player.r_player.score)
			
			
	def _key_pressed(self, event):	
		if not self.game_stopped:
			# If ball and pads can move
			self.left_pad.button_press(event.keysym)
			self.right_pad.button_press(event.keysym)
			if event.keysym == "Escape":
				# Show/Hide menu window and stop/start game
				self._stop_cont_game()
		else:
			# Send this key to menu widget
			self.cur_menu.check_keys(event.keysym)

			
			
	def _key_released(self, event):
		if not self.game_stopped:
			self.left_pad.button_release(event.keysym)
			self.right_pad.button_release(event.keysym)

	def show_options_menu(self, hide=False):
		self.c.itemconfig(self.cur_menu.id, state=HIDDEN)
		if not hide:
			self.cur_menu = self.options_menu
		else:
			self.cur_menu = self.start_menu
		self.c.itemconfig(self.cur_menu.id, state=NORMAL)
		
	def update_size(self):
		new_w, new_h = self.ss.SCREEN_SIZES.get()
		xscale = new_w / self.ss.WIDTH
		yscale = new_h / self.ss.HEIGHT
		self._resize(xscale, yscale)
		
				
	def _resize(self, xscale, yscale):
		self.c.config(width=self.ss.WIDTH*xscale, height=self.ss.HEIGHT*yscale)
		self.c.scale(ALL, 0, 0, xscale, yscale)
		self.ss.scale(xscale, yscale)
		
	def update_crazy(self):
		self.buffs.init_buffs()
		
		
	def update_theme(self):
		if not self.theme.randomed:
			self.theme.choose_theme()
		self.rotate_colors()
		
	def rotate_colors(self):
		self.start_menu.rotate_colors()
		self.stop_menu.rotate_colors()
		self.options_menu.rotate_colors()
		self.theme.rotate_colors()
		
	def move_screen(self):
		left = 0
		right = self.root.winfo_screenwidth() - int(self.ss.WIDTH)
		top = 0
		bottom = self.root.winfo_screenheight() - int(self.ss.HEIGHT)
		new_x = randint(left, right)
		new_y = randint(top, bottom)
		self.root.geometry(f"+{new_x}+{new_y}")
		
	def _stop_cont_game(self):
		if self.game_stopped:
			self.c.itemconfig(self.cur_menu.id, state=HIDDEN)
		else:
			self.c.itemconfig(self.cur_menu.id, state=NORMAL)
		self.game_stopped = not self.game_stopped
	
			
	# Used for testing, shoud be changed	
	def print_help(self):
		# TODO!! Print it on main window
		print("Welkome to the F(unny)Pong")
		print()
		print("Controls: left player - W/S, right - key Up/Down")
		print("When playing against bot you are on the right")
		print("At the time of game you could press Esc to go to the menu")
		print()
		print("There are 5 modes: Classic, Soft, Normal, Best, Hard")
		print("\tClassic - Without buffs")
		print("\tSoft - Sometimes minor buffs appear(Speed_up, Slow_down, Enlarge, Shrink)(all about pad)")
		print("\tNormal - Buffs pops up more frequently, and to previous list added (Small_ball, Big_ball, Random)")
		print("\tBest - Frequency increases, added (Rotate, Die)")
		print("\t\t\tMaybe I played this game so many times(while debugging) so that all the previous modes became boring")
		print("\t\t\t<Best> is the best - In My Humble Oppinion")
		print("\tHard - Added (Teleport, Splash, Move)")
		print()
		print("Note: in most cases buffs affect the player who touched the ball last")
		print("Except some general (Small_ball, Big_ball, Teleport, Move)")
		print()
		print("Some non-intuitive buffs:")
		print("\tRandom - (question mark) execute random buff")
		print("\tRotate - change pad control keys (when you press Up, it moves down) and color to dark-green")
		print("\tTeleport - change balls position")
		print("\tSplash - (white, green, red, black stripes) Cause blinking in your area")
		print("\tMove - (four arrows) Screen moves several times")	
		
	
	def reinit(self):
		self.__init_canva()
		
	def __init_canva(self):
		# Canvas object
		self.c = ExCanvas(self.root, width=self.ss.WIDTH, 
							height=self.ss.HEIGHT, background=self.theme["bg"])
		self.c.pack()#expand=True)
		 
		# central line
		self.c.create_line(self.ss.WIDTH//2, 0, self.ss.WIDTH//2, 
							self.ss.HEIGHT, fill=self.theme["line"], tag="line")
							
		self.c.create_ball(self.ss.WIDTH//2, self.ss.HEIGHT//2, self.ss.BALL_RADIUS/2, 
							fill=self.theme["line"], width=0, tag="line")
		
		
		self.__init_players_score()
		
		# Work with Pads
		left_pad_id = self.c.create_rectangle(0, 0, self.ss.PAD_W, 
											self.ss.PAD_H, width=1, 
											fill=self.theme["l_pad"], tag="l_pad")
		 
		right_pad_id = self.c.create_rectangle(self.ss.WIDTH-self.ss.PAD_W, 0, self.ss.WIDTH, 
									  		self.ss.PAD_H, width=1, 
									  		fill=self.theme["r_pad"], tag="r_pad")
								  
		self.left_pad = Pad(left_pad_id, self.c, self.ss, ("w", "s"), Player.LEFT)
		self.right_pad = Pad(right_pad_id, self.c, self.ss, ("Up", "Down"), Player.RIGHT)
		
		self.player = Player(self.left_pad, self.right_pad)
		
		self.ball = Ball(self.c, self.player, self, self.ss, self.theme["ball"])
		
		
		self.buffs = Buffs(self.ss, self)
		
		# Menu creating
		stop_menu_id = self.c.create_window((self.ss.WIDTH/2, self.ss.HEIGHT/2))
		self.stop_menu = StopMenu(stop_menu_id, self)
		self.c.itemconfig(stop_menu_id, window=self.stop_menu, state=HIDDEN)
		
		options_menu_id = self.c.create_window((self.ss.WIDTH/2, self.ss.HEIGHT/2))
		self.options_menu = OptionMenu(options_menu_id, self)
		self.c.itemconfig(options_menu_id, window=self.options_menu, state=HIDDEN)
		
		start_menu_id = self.c.create_window((self.ss.WIDTH/2, self.ss.HEIGHT/2))
		self.start_menu = StartMenu(start_menu_id, self)
		self.c.itemconfig(start_menu_id, window=self.start_menu) 
		
		self.cur_menu = self.start_menu
										  
		self.c.focus_set()
		self.theme.set_canvas(self.c)
		
		self.c.bind("<KeyPress>", self._key_pressed)
		self.c.bind("<KeyRelease>", self._key_released)
		
		self.game_stopped = True
		
	def __init_players_score(self):
		# Show players score
		self.pl_r_text = self.c.create_text(self.ss.WIDTH*4/5, self.ss.PAD_H/3,
											text=0, fill="white",
											font="Colibri 25", tag="text")
		 
		self.pl_l_text = self.c.create_text(self.ss.WIDTH/5, self.ss.PAD_H/3,
											text=0, fill="white",
											font="Colibri 25", tag="text")
        Clock.schedule_once(lambda *__: Factory.UpdateRestartPopup().open(), 0)

    def _restart_for_update(self):
        # Dismiss popup and run update utility
        if hasattr(self, 'update_notif'):
            self.update_notif.dismiss()

        self.update_client.run_util()
        self.stop()

    def open_settings(self):
        self.root.goto_page(3)


Logger.info('Reading theme..')
theme = Theme(name=Config.get('theme', 'default'))

if __name__ == '__main__':
    Logger.info(f'System = {platform.system()}')
    Logger.info(f'Release = {platform.release()}')

    Window.clearcolor = theme.dark

    app = XtremeUpdaterApp()

    # set attributes required by the .kv file
    app.Config = Config
    app.version = __version__
    app.theme = theme
    app.as_admin = IS_ADMIN
Beispiel #24
0
    def reload(self, event=None, data=None):
        # Remove all old groupbuttons from container.
        for child in self.container.get_children():
            self.container.remove(child)
        if self.windows:
            # Removes windows and unpinned group buttons
            for win in self.screen.get_windows():
                self.on_window_closed(None, win)
        if self.groups is not None:
            # Removes pinned group buttons
            for group in self.groups:
                group.hide_list()
                group.icon_factory.remove()

        del self.groups
        del self.windows
        if self.theme:
            self.theme.remove()
        gc.collect()

        print "Dockbarx reload"
        self.groups = GroupList()
        self.windows = {}
        # Get the monitor on which dockbarx is.
        gdk_screen = gtk.gdk.screen_get_default()
        win = self.container.window
        if win is not None:
            self.monitor = gdk_screen.get_monitor_at_window(win)
        #--- Generate Gio apps
        self.apps_by_id = {}
        self.app_ids_by_exec = {}
        self.app_ids_by_name = {}
        self.app_ids_by_longname = {}
        self.wine_app_ids_by_program = {}
        for app in gio.app_info_get_all():
            id = app.get_id()
            id = id[:id.rfind('.')].lower()
            name = u""+app.get_name().lower()
            exe = app.get_executable()
            if exe:
                self.apps_by_id[id] = app
                if id[:5] == 'wine-':
                    try:
                        cmd = u""+app.get_commandline().lower()
                    except AttributeError:
                        # Older versions of gio doesn't have get_comandline.
                        cmd = u""
                    if cmd.find('.exe') > 0:
                        program = cmd[:cmd.rfind('.exe')+4]
                        program = program[program.rfind('\\')+1:]
                        self.wine_app_ids_by_program[program] = id
                if name.find(' ')>-1:
                    self.app_ids_by_longname[name] = id
                else:
                    self.app_ids_by_name[name] = id
                if exe not in ('sudo','gksudo',
                                'java','mono',
                                'ruby','python'):
                    if exe[0] == '/':
                        exe = exe[exe.rfind('/')+1:]
                        self.app_ids_by_exec[exe] = id
                    else:
                        self.app_ids_by_exec[exe] = id



        try:
            if self.theme is None:
                self.theme = Theme()
            else:
                self.theme.on_theme_changed()
        except NoThemesError, details:
            print details
            sys.exit(1)
Beispiel #25
0
    def parse(self, config, source):
        """Parse presentation from source stream.

    Parameters
    ----------
    config : MatisseConfig
      MaTiSSe configuration
    source: str
    """
        complete_source = self.parser.includes(source=source)
        self.__get_metadata(source=complete_source)
        self.__get_theme(source=complete_source)
        new_theme = Theme()
        new_theme.set_from(other=self.theme)
        tokens = self.parser.tokenize(source=complete_source)
        self.__check_bad_sectioning(tokens=tokens)
        chapters_number = 0
        sections_number = 0
        subsections_number = 0
        slides_number = 0
        titlepage_inserted = False
        for chap in tokens['chapters']:
            chapters_number += 1
            slide_local_numbers = [0, 0, 0]
            if chap['match'].group('expr'):
                chapter = Chapter(number=chapters_number,
                                  title=chap['match'].group('expr'))
            else:
                chapter = Chapter(number=chapters_number, title='')
            for sec in tokens['sections']:
                if sec['start'] >= chap['start'] and sec['start'] <= chap[
                        'end_next']:
                    sections_number += 1
                    slide_local_numbers[1] = 0
                    slide_local_numbers[2] = 0
                    section = Section(number=sections_number,
                                      title=sec['match'].group('expr'))
                    for subsec in tokens['subsections']:
                        if subsec['start'] >= sec['start'] and subsec[
                                'start'] <= sec['end_next']:
                            subsections_number += 1
                            slide_local_numbers[2] = 0
                            subsection = Subsection(
                                number=subsections_number,
                                title=subsec['match'].group('expr'))
                            for sld in tokens['slides']:
                                if '$titlepage' in sld['match'].group().lower(
                                ) and not titlepage_inserted:
                                    slide = Slide(
                                        number=0,
                                        title='titlepage',
                                        contents=complete_source[
                                            sld['end']:sld['end_next']])
                                    slide.get_overtheme(parser=self.parser)
                                    if slide.overtheme.copy_from_theme is not None and slide.overtheme.copy_from_theme:
                                        slide.overtheme.copy_from(
                                            other=self.theme)
                                    self.position.update_position(
                                        presentation_theme=self.theme,
                                        overtheme=slide.overtheme)
                                    slide.set_position(
                                        position=self.position.position)
                                    subsection.add_slide(slide=slide)
                                    titlepage_inserted = True
                                else:
                                    if sld['start'] >= subsec['start'] and sld[
                                            'start'] <= subsec['end_next']:
                                        slide_local_numbers[0] += 1
                                        slide_local_numbers[1] += 1
                                        slide_local_numbers[2] += 1
                                        if slide_local_numbers[
                                                0] == 1 and config.toc_at_chap_beginning is not None:
                                            slides_number += 1
                                            self.position.update_position(
                                                presentation_theme=self.theme)
                                            subsection.add_slide(slide=Slide(
                                                number=slides_number,
                                                position=self.position.
                                                position,
                                                title='Table of Contents',
                                                contents='$toc[depth:' +
                                                str(config.
                                                    toc_at_chap_beginning) +
                                                ']'))
                                        if slide_local_numbers[
                                                1] == 1 and config.toc_at_sec_beginning is not None:
                                            slides_number += 1
                                            self.position.update_position(
                                                presentation_theme=self.theme)
                                            subsection.add_slide(slide=Slide(
                                                number=slides_number,
                                                position=self.position.
                                                position,
                                                title='Table of Contents',
                                                contents='$toc[depth:' +
                                                str(config.toc_at_sec_beginning
                                                    ) + ']'))
                                        if slide_local_numbers[
                                                2] == 1 and config.toc_at_subsec_beginning is not None:
                                            slides_number += 1
                                            self.position.update_position(
                                                presentation_theme=self.theme)
                                            subsection.add_slide(slide=Slide(
                                                number=slides_number,
                                                position=self.position.
                                                position,
                                                title='Table of Contents',
                                                contents='$toc[depth:' +
                                                str(config.
                                                    toc_at_subsec_beginning) +
                                                ']'))
                                        slides_number += 1
                                        slide = Slide(
                                            number=slides_number,
                                            title=sld['match'].group('expr'),
                                            contents=complete_source[
                                                sld['end']:sld['end_next']])
                                        slide.get_overtheme(parser=self.parser)
                                        if slide.overtheme.copy_from_theme is not None and slide.overtheme.copy_from_theme:
                                            slide.overtheme.copy_from(
                                                other=self.theme)
                                        self.position.update_position(
                                            presentation_theme=self.theme,
                                            overtheme=slide.overtheme)
                                        slide.set_position(
                                            position=self.position.position)
                                        subsection.add_slide(slide=slide)
                            section.add_subsection(subsection=subsection)
                    chapter.add_section(section=section)
            self.__add_chapter(chapter=chapter)
            self.metadata['total_slides_number'].update_value(
                value=str(Subsection.slides_number))
Beispiel #26
0
class Slide(object):
    """
  Slide object.
  """
    @classmethod
    def reset(cls):
        """Reset to default state."""
        return

    def __init__(self, number, position=None, title=None, contents=None):
        """"
    Paramters
    ---------
    number: int
      slide global numeration
    position: dict
      position dictionary containing {'x': posx, 'y': posy, 'z': posz, 'rotx': rotx, 'roty': roty, 'rotz': rotz, 'scale': scaling}
    title: str
    contents: str
    """
        self.number = number
        self.position = None
        self.set_position(position)
        self.title = title
        self.contents = contents
        self.overtheme = Theme()
        return

    def __str__(self):
        strings = [str(self.title)]
        strings.append(str(self.contents))
        return ''.join(strings)

    def get_overtheme(self, parser):
        """Get eventaul overtheme definition.

    Parameters
    ----------
    parser: Parser
    """
        codeblocks = parser.tokenizer(source=self.contents,
                                      re_search=parser.regexs['codeblock'])
        yamlblocks = parser.tokenizer(source=self.contents,
                                      re_search=parser.regexs['yamlblock'],
                                      exclude=codeblocks)
        if len(yamlblocks) > 0:
            self.overtheme.get(source=''.join(
                [block['match'].group().strip('---') for block in yamlblocks]),
                               name='overtheme',
                               div_id='slide-' + str(self.number))
            purged_contents = self.contents[:yamlblocks[0]['start']]
            for b, yamlblock in enumerate(yamlblocks[:-1]):
                purged_contents += self.contents[
                    yamlblock['end']:yamlblocks[b + 1]['start']]
            purged_contents += self.contents[yamlblocks[-1]['end']:]
            self.contents = purged_contents

    def set_position(self, position):
        """Set slide position.

    Parameters
    ----------
    position: dict
      position dictionary containing {'x': posx, 'y': posy, 'z': posz, 'rotx': rotx, 'roty': roty, 'rotz': rotz, 'scale': scaling}
    """
        if position is not None:
            self.position = {}
            for key in position:
                self.position[key] = position[key]

    def put_html_attributes(self, doc):
        """Put html attibutes of the slide.

    Parameters
    ----------
    doc: Doc
    """
        doc.attr(('id', 'slide-' + str(self.number)))
        # doc.attr(('title', str(self.title)))
        doc.attr(('class', 'step slide'))
        doc.attr(('data-x', str(self.position['x'])))
        doc.attr(('data-y', str(self.position['y'])))
        doc.attr(('data-z', str(self.position['z'])))
        doc.attr(('data-scale', str(self.position['scale'])))
        doc.attr(('data-rotate-x', str(self.position['rotx'])))
        doc.attr(('data-rotate-y', str(self.position['roty'])))
        doc.attr(('data-rotate-z', str(self.position['rotz'])))
        return

    def to_html(self, doc, parser, metadata, theme, current):
        """Generate html from self.

    Parameters
    ----------
    doc: Doc
    parser: Parser
    metatadata: dict
      presentation metadata
    theme: Theme()
      presentation theme
    current: list
    """
        def _parse_env(Env, re_search, source):
            codeblocks = parser.tokenizer(source=source,
                                          re_search=parser.regexs['codeblock'])
            codes = parser.tokenizer(source=source,
                                     re_search=parser.regexs['code'],
                                     exclude=codeblocks)
            yamlblocks = parser.tokenizer(source=source,
                                          re_search=parser.regexs['yamlblock'],
                                          exclude=codeblocks + codes)
            envs = parser.tokenizer(source=source,
                                    re_search=re_search,
                                    exclude=codeblocks + yamlblocks + codes)
            if len(envs) > 0:
                parsed_source = source[:envs[0]['start']]
                for e, env in enumerate(envs[:-1]):
                    current = Env(source=env['match'].group())
                    parsed_source += current.to_html(
                    ) + source[env['end']:envs[e + 1]['start']]
                if Env is Video:
                    if self.overtheme.custom:
                        current = Env(source=envs[-1]['match'].group(),
                                      theme=self.overtheme)
                    else:
                        current = Env(source=envs[-1]['match'].group(),
                                      theme=theme)
                else:
                    current = Env(source=envs[-1]['match'].group())
                parsed_source += current.to_html() + source[envs[-1]['end']:]
                return parsed_source
            return source

        html = self.contents
        for meta in metadata:
            html = metadata[meta].parse(parser=parser,
                                        source=html,
                                        toc_depth=metadata['toc_depth'].value,
                                        max_time=metadata['max_time'].value,
                                        current=current)
        html = _parse_env(Env=Box, re_search=Box.regexs['box'], source=html)
        html = _parse_env(Env=Note, re_search=Note.regexs['note'], source=html)
        html = _parse_env(Env=Figure,
                          re_search=Figure.regexs['figure'],
                          source=html)
        html = _parse_env(Env=Table,
                          re_search=Table.regexs['table'],
                          source=html)
        html = _parse_env(Env=Video,
                          re_search=Video.regexs['video'],
                          source=html)
        html = _parse_env(Env=Columns,
                          re_search=Columns.regexs['columns'],
                          source=html)
        with doc.tag('div', klass='slide-content'):
            doc.asis(markdown2html(source=html))
        return
Beispiel #27
0
class IconFactory():
    """IconFactory finds the icon for a program and prepares the cairo surface."""
    icon_theme = gtk.icon_theme_get_default()
    # Constants
    # Icon types
    SOME_MINIMIZED = 1<<4
    ALL_MINIMIZED = 1<<5
    LAUNCHER = 1<<6
    # Icon effects
    MOUSE_OVER = 1<<7
    MOUSE_BUTTON_DOWN = 1<<8
    NEEDS_ATTENTION = 1<<9
    BLINK  = 1<<10
    # ACTIVE_WINDOW
    ACTIVE = 1<<11
    LAUNCH_EFFECT = 1<<12
    # Double width/height icons for drag and drop situations.
    DRAG_DROPP_START = 1<<13
    DRAG_DROPP_END = 1<<14
    TYPE_DICT = {"some_minimized":SOME_MINIMIZED,
                 "all_minimized":ALL_MINIMIZED,
                 "launcher":LAUNCHER,
                 "mouse_over":MOUSE_OVER,
                 "needs_attention":NEEDS_ATTENTION,
                 "blink":BLINK,
                 "active":ACTIVE,
                 "launching":LAUNCH_EFFECT,
                 "mouse_button_down":MOUSE_BUTTON_DOWN}

    def __init__(self, group, class_group=None,
                 desktop_entry=None, identifier=None):
        self.dockbar_r = weakref.ref(group.dockbar_r())
        self.theme = Theme()
        self.globals = Globals()
        connect(self.globals, "color-changed", self.reset_surfaces)
        self.desktop_entry = desktop_entry
        self.identifier = identifier
        self.class_group = class_group

        # Setting size to something other than zero to
        # avoid crashes if surface_update() is runned
        # before the size is set.
        self.size = 15

        self.icon = None
        self.surfaces = {}

        self.average_color = None

        self.max_win_nr = self.theme.get_windows_cnt()
        self.types_in_theme = 0
        for type in self.theme.get_types():
            if not type in self.TYPE_DICT:
                continue
            self.types_in_theme = self.types_in_theme | self.TYPE_DICT[type]

    def remove(self):
        del self.desktop_entry
        del self.class_group
        del self.icon
        del self.surfaces
        del self.theme

    def set_desktop_entry(self, desktop_entry):
        self.desktop_entry = desktop_entry
        self.surfaces = {}
        del self.icon
        self.icon = None

    def set_class_group(self, class_group):
        if not self.desktop_entry and not self.class_group:
            self.surfaces = {}
            del self.icon
            self.icon = None
        self.class_group = class_group

    def set_size(self, size):
        if size <= 0:
            # To avoid chrashes.
            size = 15
        self.size = size
        self.surfaces = {}
        self.average_color = None

    def get_size(self):
        return self.size

    def get_icon(self, size):
        return self.__find_icon_pixbuf(size)

    def reset_icon(self):
        self.icon = None

    def reset_surfaces(self, arg=None):
        self.surfaces = {}
        self.average_color = None


    def surface_update(self, type = 0):
        # Checks if the requested pixbuf is already
        # drawn and returns it if it is.
        # Othervice the surface is drawn, saved and returned.

        #The first four bits of type is for telling the number of windows
        self.win_nr = min(type & 15, self.max_win_nr)
        # Remove all types that are not used by the theme (saves memory)
        dnd = (type & self.DRAG_DROPP_START and "start") or \
              (type & self.DRAG_DROPP_END and "end")
        type = type & self.types_in_theme
        type += self.win_nr
        self.orient = self.dockbar_r().orient
        is_vertical = self.orient in ("left", "right")
        if type in self.surfaces:
            surface = self.surfaces[type]
        else:
            self.temp = {}
            surface = None
            commands = self.theme.get_icon_dict()
            self.ar = self.theme.get_aspect_ratio(is_vertical)
            self.type = type
            for command, args in commands.items():
                try:
                    f = getattr(self, "_IconFactory__command_%s"%command)
                except:
                    raise
                else:
                    surface = f(surface, **args)
            # Todo: add size correction.
            self.surfaces[type] = surface
            del self.temp
            gc.collect()
        if dnd:
            surface = self.__dd_highlight(surface, self.orient, dnd)
            gc.collect()
        return surface


    def __dd_highlight(self, surface, is_vertical, position="start"):
        w = surface.get_width()
        h = surface.get_height()
        if is_vertical:
            h = h + 4
        else:
            w = w + 4
        bg = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(bg)

        if is_vertical and position == "start":
            ctx.move_to(1, 1.5)
            ctx.line_to(w - 1, 1.5)
            ctx.set_source_rgba(1, 1, 1, 0.2)
            ctx.set_line_width(2)
            ctx.stroke()
            ctx.move_to(2, 1.5)
            ctx.line_to(w - 2, 1.5)
            ctx.set_source_rgba(0, 0, 0, 0.7)
            ctx.set_line_width(1)
            ctx.stroke()
        elif is_vertical:
            ctx.move_to(1, h - 1.5)
            ctx.line_to(w - 1, h - 1.5)
            ctx.set_source_rgba(1, 1, 1, 0.2)
            ctx.set_line_width(2)
            ctx.stroke()
            ctx.move_to(2, h - 1.5)
            ctx.line_to(w - 2, h - 1.5)
            ctx.set_source_rgba(0, 0, 0, 0.7)
            ctx.set_line_width(1)
            ctx.stroke()
        elif position == "start":
            ctx.move_to(1.5, 1)
            ctx.line_to(1.5, h - 1)
            ctx.set_source_rgba(1, 1, 1, 0.2)
            ctx.set_line_width(2)
            ctx.stroke()
            ctx.move_to(1.5, 2)
            ctx.line_to(1.5, h - 2)
            ctx.set_source_rgba(0, 0, 0, 0.7)
            ctx.set_line_width(1)
            ctx.stroke()
        else:
            ctx.move_to(w - 1.5, 1)
            ctx.line_to(w - 1.5, h - 1)
            ctx.set_source_rgba(1, 1, 1, 0.2)
            ctx.set_line_width(2)
            ctx.stroke()
            ctx.move_to(w - 1.5, 2)
            ctx.line_to(w - 1.5, h - 2)
            ctx.set_source_rgba(0, 0, 0, 0.7)
            ctx.set_line_width(1)
            ctx.stroke()

        x, y  = 0, 0
        if is_vertical and position == "start":
            y = 4
        elif position == "start":
            x = 4
        ctx.set_source_surface(surface, x, y)
        ctx.paint()
        return bg

    def __get_color(self, color):
        if color == "active_color":
            color = "color5"
        if color in ["color%s"%i for i in range(1, 9)]:
            color = self.globals.colors[color]
        if color == "icon_average":
            color = self.__get_average_color()
        else:
            try:
                if len(color) != 7:
                    raise ValueError("The string has the wrong lenght")
                t = int(color[1:], 16)
            except:
                logger.exception("Theme error: the color attribute " +
                      "for a theme command"+ \
                      " should be a six digit hex string eg. \"#FFFFFF\" or"+ \
                      " the a dockbarx color (\"color1\"-\"color8\").")
                color = "#000000"
        return color

    def __get_alpha(self, alpha):
        # Transparency
        if alpha == "active_opacity":
            # For backwards compability
            alpha = "color5"

        for i in range(1, 9):
            if alpha in ("color%s"%i, "opacity%s"%i):
                if self.globals.colors.has_key("color%s_alpha"%i):
                    a = float(self.globals.colors["color%s_alpha"%i])/255
                else:
                    logger.warning("Theme error: The theme has no" + \
                          " opacity option for color%s." % i)
                    a = 1.0
                break
        else:
            try:
                a = float(alpha)/100
                if a > 1.0 or a < 0:
                    raise
            except:
                logger.exception("Theme error: The opacity attribute of a theme " + \
                      "command should be a number between \"0\" " + \
                      " and \"100\" or \"color1\" to \"color8\".")
                a = 1.0
        return a

    def __get_average_color(self):
        if self.average_color is not None:
            return self.average_color
        r = 0
        b = 0
        g = 0
        i = 0
        im = self.__surface2pil(self.icon)
        pixels = im.load()
        width, height = im.size
        for x in range(width):
            for y in range(height):
                pix = pixels[x, y]
                if pix[3] > 30:
                    i += 1
                    r += pix[0]
                    g += pix[1]
                    b += pix[2]
        if i > 0:
            r = int(round(float(r) / i))
            g = int(round(float(g) / i))
            b = int(round(float(b) / i))
        r = ("0%s"%hex(r)[2:])[-2:]
        g = ("0%s"%hex(g)[2:])[-2:]
        b = ("0%s"%hex(b)[2:])[-2:]
        self.average_color = "#"+r+g+b
        return self.average_color


    #### Flow commands
    def __command_if(self, surface, type=None, windows=None,
                     size=None, orient=None, content=None):
        if content is None:
            return surface
        # TODO: complete this
##        l = []
##        splits = ["!", "(", ")", "&", "|"]
##        for c in type:
##            if c in splits:
##                l.append(c)
##            elif l[-1] in splits:
##                l.append(c)
##            elif not l:
##                l.append(c)
##            else:
##                l[-1] += c
        # Check if the type condition is satisfied
        if type is not None:
            negation = False
            if type[0] == "!" :
                type = type[1:]
                negation = True
            is_type = bool(type in self.TYPE_DICT \
                      and self.type & self.TYPE_DICT[type])
            if not (is_type ^ negation):
                return surface

        #Check if the window number condition is satisfied
        if windows is not None:
            arg = windows
            negation = False
            if arg[0] == "!" :
                arg = windows[1:]
                negation = True
            if arg[0] == ":":
                arg = "0" + arg
            elif arg[-1] == ":":
                arg = arg +"15"
            l = arg.split(":", 1)
            try:
                l = [int(n) for n in l]
            except ValueError:
                logger.exception("Theme Error: The windows attribute of " + \
                      "an <if> statement can\'t look like this:" + \
                      " \"%s\"." % windows + \
                      "See Theming HOWTO for more information")
                return surface
            if len(l) == 1:
                if not ((l[0] == self.win_nr) ^ negation):
                    return surface
            else:
                if not ((l[0]<=self.win_nr and self.win_nr<=l[1]) ^ negation):
                    return surface

        #Check if the icon size condition is satisfied
        if size is not None:
            arg = size
            negation = False
            if arg[0] == "!" :
                arg = size[1:]
                negation = True
            if arg[0] == ":":
                arg = "0" + arg
            elif arg[-1] == ":":
                arg = arg +"200"
            l = arg.split(":", 1)
            try:
                l = [int(n) for n in l]
            except ValueError:
                logger.exception("Theme Error: The size attribute of " + \
                      "an <if> statement can\'t look like this:" + \
                      " \"%s\". See Theming HOWTO for more information" % size)
                return surface
            us = int(round(self.__get_use_size()))
            if len(l) == 1:
                if not ((l[0] == self.win_nr) ^ negation):
                    return surface
            else:
                if not ((l[0]<=us and us<=l[1]) ^ negation):
                    return surface

        # Test if the orient condition is satisfied.
        if orient is not None:
            orients = orient.split(",")
            if not self.orient in orients:
                return surface

        # All tests passed, proceed.
        for command, args in content.items():
            try:
                f = getattr(self,"_IconFactory__command_%s"%command)
            except:
                raise
            else:
                surface = f(surface, **args)
        return surface

    def __command_pixmap_from_self(self, surface, name, content=None):
        if not name:
            logger.warning("Theme Error: no name given for pixmap_from_self")
            raise Exeption
        w = int(surface.get_width())
        h = int(surface.get_height())
        self.temp[name] = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(self.temp[name])
        ctx.set_source_surface(surface)
        ctx.paint()
        if content is None:
            return surface
        for command,args in content.items():
            try:
                f = getattr(self,"_IconFactory__command_%s"%command)
            except:
                raise
            else:
                self.temp[name] = f(self.temp[name], **args)
        return surface

    def __command_pixmap(self, surface, name, content=None, size=None):
        if size is not None:
            # TODO: Fix for different height and width
            w = h = int(round(self.__get_use_size() + \
                              self.__process_size(size)))
        elif surface is None:
            w = h = int(round(self.__get_use_size()))
        else:
            w = surface.get_width()
            h = surface.get_height()
        self.temp[name] = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        if content is None:
            return surface
        for command,args in content.items():
            try:
                f = getattr(self,"_IconFactory__command_%s"%command)
            except:
                raise
            else:
                self.temp[name] = f(self.temp[name], **args)
        return surface


    #### Get icon
    def __command_get_icon(self,surface=None, size="0"):
        size = int(self.__get_use_size() + self.__process_size(size))
        if size <= 0:
            # To avoid chrashes.
            size = 15
        if self.icon and\
           self.icon.get_width() == size and \
           self.icon.get_height() == size:
            return self.icon
        del self.icon
        self.icon = None
        pb = self.__find_icon_pixbuf(size)

        if pb.get_width() != pb.get_height():
            if pb.get_width() < pb.get_height():
                h = size
                w = pb.get_width() * size/pb.get_height()
            elif pb.get_width() > pb.get_height():
                w = size
                h = pb.get_height() * size/pb.get_width()
            self.icon = cairo.ImageSurface(cairo.FORMAT_ARGB32, size, size)
            ctx = gtk.gdk.CairoContext(cairo.Context(self.icon))
            pbs = pb.scale_simple(w, h, gtk.gdk.INTERP_BILINEAR)
            woffset = round((size - w) / 2.0)
            hoffset = round((size - h) / 2.0)
            ctx.set_source_pixbuf(pb, woffset, hoffset)
            ctx.paint()
            del pb
            del pbs
        elif pb.get_width() != size:
            pbs = pb.scale_simple(size, size, gtk.gdk.INTERP_BILINEAR)
            self.icon = self.__pixbuf2surface(pbs)
            del pb
            del pbs
        else:
            self.icon = self.__pixbuf2surface(pb)
            del pb
        return self.icon


    def __find_icon_pixbuf(self, size):
        # Returns the icon pixbuf for the program. Uses the following metods:

        # 1) If it is a launcher, return the icon from the
        #    launcher's desktopfile
        # 2) Get the icon from the gio app
        # 3) Check if the res_class fits an themed icon.
        # 4) Search in path after a icon matching reclass.
        # 5) Use the mini icon for the class

        pixbuf = None
        icon_name = None
        if self.desktop_entry:
            icon_name = self.desktop_entry.getIcon()
            if icon_name is not None and os.path.isfile(icon_name):
                pixbuf = self.__icon_from_file_name(icon_name, size)
                if pixbuf is not None:
                    return pixbuf

        if not icon_name:
            if self.identifier:
                icon_name = self.identifier.lower()
            elif self.class_group:
                icon_name = self.class_group.get_res_class().lower()
            else:
                icon_name = ""

            # Special cases
            if icon_name.startswith("openoffice"):
                icon_name = "ooo-writer"
            if icon_name.startswith("libreoffice"):
                icon_name = "libreoffice-writer"

        if self.icon_theme.has_icon(icon_name):
            return self.icon_theme.load_icon(icon_name,size,0)

        if icon_name[-4:] in (".svg", ".png", ".xpm"):
            if self.icon_theme.has_icon(icon_name[:-4]):
                pixbuf = self.icon_theme.load_icon(icon_name[:-4],size,0)
                if pixbuf is not None:
                    return pixbuf

        pixbuf = self.__icon_search_in_data_path(icon_name, size)
        if pixbuf is not None:
            return pixbuf

        if self.class_group:
            return self.class_group.get_icon().copy()


        # If no pixbuf has been found (can only happen for an unlaunched
        # launcher), make an empty pixbuf and show a warning.
        if self.icon_theme.has_icon("application-default-icon"):
            pixbuf = self.icon_theme.load_icon("application-default-icon",
                                                size, 0)
        else:
            pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, size,size)
            pixbuf.fill(0x00000000)
        if self.desktop_entry:
            name = self.desktop_entry.getName()
        else:
            name = None
        return pixbuf

    def __icon_from_file_name(self, icon_name, icon_size = -1):
        if os.path.isfile(icon_name):
            try:
                return gtk.gdk.pixbuf_new_from_file_at_size(icon_name, -1,
                                                            icon_size)
            except:
                pass
        return None

    def __icon_search_in_data_path(self, icon_name, icon_size):
        data_folders = None

        if os.environ.has_key("XDG_DATA_DIRS"):
            data_folders = os.environ["XDG_DATA_DIRS"]

        if not data_folders:
            data_folders = "/usr/local/share/:/usr/share/"

        for data_folder in data_folders.split(":"):
            #The line below line used datafolders instead of datafolder.
            #I changed it because I suspect it was a bug.
            paths = (os.path.join(data_folder, "pixmaps", icon_name),
                     os.path.join(data_folder, "icons", icon_name))
            for path in paths:
                if os.path.isfile(path):
                    icon = self.__icon_from_file_name(path, icon_size)
                    if icon:
                        return icon
        return None


    #### Other commands
    def __command_clear(self, surface):
        if self.dockbar_r().orient in ("left", "right"):
            w = self.size
            h = int(self.size * self.ar)
        else:
            w = int(self.size * self.ar)
            h = self.size
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_rgba(0, 0, 0)
        ctx.set_operator(cairo.OPERATOR_SOURCE)
        ctx.paint_with_alpha(0)
        return new

    def __command_get_pixmap(self, surface, name):
        if surface is None:
            if self.dockbar_r().orient in ("left", "right"):
                width = self.size
                height = int(self.size * self.ar)
            else:
                width = int(self.size * self.ar)
                height = self.size
        else:
            width = surface.get_width()
            height = surface.get_height()
        if self.theme.has_surface(name):
            surface = self.__resize_surface(self.theme.get_surface(name),
                                            width, height)
        else:
            logger.warning("theme error: pixmap %s not found" % name)
        return surface

    def __command_fill(self, surface, color, opacity="100"):
        w = surface.get_width()
        h = surface.get_height()
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_surface(surface)
        ctx.paint()

        alpha = self.__get_alpha(opacity)
        c = self.__get_color(color)
        r = float(int(c[1:3], 16))/255
        g = float(int(c[3:5], 16))/255
        b = float(int(c[5:7], 16))/255
        ctx.set_source_rgba(r, g, b)
        ctx.set_operator(cairo.OPERATOR_SOURCE)
        ctx.paint_with_alpha(alpha)
        return new


    def __command_combine(self, surface, pix1, pix2, degrees=None):
        # Combines left half of surface with right half of surface2.
        # The transition between the two halves are soft.

        # Degrees keyword are kept of compability reasons.
        w = surface.get_width()
        h = surface.get_height()
        if pix1=="self":
            p1 = surface
        elif pix1 in self.temp:
            p1 = self.temp[pix1]
        elif self.theme.has_surface(pix1):
            w = surface.get_width()
            h = surface.get_height()
            p1 = self.__resize_surface(self.theme.get_surface(bg), w, h)
        else:
            logger.warning("theme error: pixmap %s not found"%pix1)
        if pix2=="self":
            p2 = surface
        elif pix2 in self.temp:
            p2 = self.temp[pix2]
        elif self.theme.has_surface(pix2):
            w = surface.get_width()
            h = surface.get_height()
            p2 = self.__resize_surface(self.theme.get_surface(bg), w, h)
        else:
            logger.warning("theme error: pixmap %s not found" % pix2)

        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
                                     p1.get_width(), p1.get_height())
        ctx = cairo.Context(surface)

        linear = cairo.LinearGradient(0, 0, p1.get_width(), 0)
        linear.add_color_stop_rgba(0.4, 0, 0, 0, 0.5)
        linear.add_color_stop_rgba(0.6, 0, 0, 0, 1)
        ctx.set_source_surface(p2, 0, 0)
        #ctx.mask(linear)
        ctx.paint()

        linear = cairo.LinearGradient(0, 0, p1.get_width(), 0)
        linear.add_color_stop_rgba(0.4, 0, 0, 0, 1)
        linear.add_color_stop_rgba(0.6, 0, 0, 0, 0)
        ctx.set_source_surface(p1, 0, 0)
        ctx.mask(linear)
        try:
            del pb
            del pbs
        except:
            pass
        return surface

    def __command_transp_sat(self, surface, opacity="100", saturation="100"):
        # Makes the icon desaturized and/or transparent.
        alpha = self.__get_alpha(opacity)
        # Todo: Add error check for saturation
        sat = float(saturation)
        if sat != 100:
            im = self.__surface2pil(surface)
            w, h = im.size
            pixels = im.load()
            for x in range(w):
                for y in range(h):
                    r, g, b, a = pixels[x, y]
                    l = (r + g + b) / 3.0 * (100 - sat) / 100.0
                    r = int(r * sat / 100.0 + l)
                    g = int(g * sat / 100.0 + l)
                    b = int(b * sat / 100.0 + l)
                    a = int(a * alpha)
                    pixels[x, y] = (r, g, b, a)
            return self.__pil2surface(im)
        else:
            w = surface.get_width()
            h = surface.get_height()
            new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
            ctx = gtk.gdk.CairoContext(cairo.Context(new))
            ctx.set_source_surface(surface)
            ctx.paint_with_alpha(alpha)
            return new


    def __command_composite(self, surface, bg, fg, opacity="100",
                            xoffset="0", yoffset="0", angle="0"):
        if fg == "self":
            foreground = surface
            if angle and angle != "0":
                foreground = self.__command_rotate(foreground,
                                                   angle, True)
        elif fg in self.temp:
            foreground = self.temp[fg]
            if angle and angle != "0":
                foreground = self.__command_rotate(foreground,
                                                   angle, True)
        elif self.theme.has_surface(fg):
            foreground = self.theme.get_surface(fg)
            if angle and angle != "0":
                foreground = self.__command_rotate(foreground,
                                                   angle, True)
            w = surface.get_width()
            h = surface.get_height()
            foreground = self.__resize_surface(foreground, w, h)
        else:
            logger.warning("theme error: pixmap %s not found" % fg)
            return surface
        if bg == "self":
            background = surface
        elif bg in self.temp:
            w = self.temp[bg].get_width()
            h = self.temp[bg].get_height()
            background = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
            ctx = cairo.Context(background)
            ctx.set_source_surface(self.temp[bg])
            ctx.paint()
        elif self.theme.has_surface(bg):
            w = surface.get_width()
            h = surface.get_height()
            background = self.__resize_surface(self.theme.get_surface(bg), w, h)
        else:
            logger.warning("theme error: pixmap %s not found" % bg)
            return surface

        xoffset = self.__get_from_set(xoffset)
        yoffset = self.__get_from_set(yoffset)
        opacity = self.__get_alpha(opacity)
        xoffset = self.__process_size(xoffset)
        yoffset = self.__process_size(yoffset)
        ctx = cairo.Context(background)
        ctx.set_source_surface(foreground, xoffset, yoffset)
        ctx.paint_with_alpha(opacity)
        return background

    def __command_shrink(self, surface, percent="0", pixels="0"):
        w0 = surface.get_width()
        h0 = surface.get_height()
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w0, h0)
        ctx = cairo.Context(new)

        pixels = self.__get_from_set(pixels)
        percent = self.__get_from_set(percent)
        w = int(((100-int(percent)) * w0)/100)-int(pixels)
        h = int(((100-int(percent)) * h0)/100)-int(pixels)
        shrinked = self.__resize_surface(surface, w, h)
        x = round((w0 - w) / 2.0)
        y = round((h0 - h) / 2.0)
        ctx.set_source_surface(shrinked, x, y)
        ctx.paint()
        del shrinked
        return new

    def __command_rotate(self, surface, angle="0", resize="False"):
        w0 = surface.get_width()
        h0 = surface.get_height()
        # Check if the angle should be taken from a set.
        angle = self.__get_from_set(angle)
        a =  float(angle)/180*pi
        if not resize or resize in ("False", "0"):
            w = w0
            h = h0
        else:
            w = abs(int(round(cos(a) * w0 + sin(a) * h0)))
            h = abs(int(round(cos(a) * h0 + sin(a) * w0)))
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)

        ctx.translate(w/2.0, h/2.0)
        ctx.rotate(a)
        ctx.translate(-w0/2.0, -h0/2.0)
        ctx.set_source_surface(surface, 0,0)
        ctx.paint()
        return new

    def __command_correct_size(self, surface):
        if surface is None:
            return
        if self.dockbar_r().orient in ("left", "right"):
            width = self.size
            height = int(self.size * self.ar)
        else:
            width = int(self.size * self.ar)
            height = self.size
        if surface.get_width() == width and surface.get_height() == height:
            return surface
        woffset = round((width - surface.get_width()) / 2.0)
        hoffset = round((height - surface.get_height()) / 2.0)
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
        ctx = cairo.Context(new)
        ctx.set_source_surface(surface, woffset, hoffset)
        ctx.paint()
        return new

    def __command_glow(self, surface, color, opacity="100"):
        # Adds a glow around the parts of the surface
        # that isn't completely transparent.

        alpha = self.__get_alpha(opacity)
        # Thickness (pixels)
        tk = 1.5


        # Prepare the glow that should be put behind the icon
        cs = self.__command_colorize(surface, color)
        w = surface.get_width()
        h = surface.get_height()
        glow = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(glow)
        tk1 = tk/2.0
        for x, y in ((-tk1,-tk1), (-tk1,tk1), (tk1,-tk1), (tk1,tk1)):
            ctx.set_source_surface(cs, x, y)
            ctx.paint_with_alpha(0.66)
        for x, y in ((-tk,-tk), (-tk,tk), (tk,-tk), (tk,tk)):
            ctx.set_source_surface(cs, x, y)
            ctx.paint_with_alpha(0.27)

        # Add glow and icon to a new canvas
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_surface(glow)
        ctx.paint_with_alpha(alpha)
        ctx.set_source_surface(surface)
        ctx.paint()
        return new

    def __command_colorize(self, surface, color):
        # Changes the color of all pixels to color.
        # The pixels alpha values are unchanged.

        # Convert color hex-string (format "#FFFFFF")to int r, g, b
        color = self.__get_color(color)
        r = int(color[1:3], 16)/255.0
        g = int(color[3:5], 16)/255.0
        b = int(color[5:7], 16)/255.0

        w = surface.get_width()
        h = surface.get_height()
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_rgba(r,g,b,1.0)
        ctx.mask_surface(surface)
        return new


    def __command_bright(self, surface, strength = None, strenght = None):
        if strength is None and strenght is not None:
            # For compability with older themes.
            strength = strenght
        alpha = self.__get_alpha(strength)
        w = surface.get_width()
        h = surface.get_height()
        # Colorize white
        white = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(white)
        ctx.set_source_rgba(1.0, 1.0, 1.0, 1.0)
        ctx.mask_surface(surface)
        # Apply the white version over the icon
        # with the chosen alpha value
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_surface(surface)
        ctx.paint()
        ctx.set_source_surface(white)
        ctx.paint_with_alpha(alpha)
        return new

    def __command_alpha_mask(self, surface, mask, angle="0"):
        if mask in self.temp:
            mask = self.temp[mask]
            if angle and angle != "0":
                mask = self.__command_rotate(mask, angle, True)
        elif self.theme.has_surface(mask):
            mask = self.theme.get_surface(mask)
            if angle and angle != "0":
                mask = self.__command_rotate(mask, angle, True)
            w = surface.get_width()
            h = surface.get_height()
            mask = self.__resize_surface(mask, w, h)
        w = surface.get_width()
        h = surface.get_height()
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_surface(surface)
        ctx.mask_surface(mask)
        return new

#### Format conversions
    def __pixbuf2surface(self, pixbuf):
        if pixbuf is None:
            return None
        w = pixbuf.get_width()
        h = pixbuf.get_height()
        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = gtk.gdk.CairoContext(cairo.Context(surface))
        ctx.set_source_pixbuf(pixbuf, 0, 0)
        ctx.paint()
        del pixbuf
        return surface

    def __surface2pil(self, surface):
        w = surface.get_width()
        h = surface.get_height()
        return Image.frombuffer("RGBA", (w, h), surface.get_data(),
                                "raw", "BGRA", 0,1)

    def __pil2surface(self, im):
        """Transform a PIL Image into a Cairo ImageSurface."""

        # This function is only supposed to work with little endinan
        # systems. Could that be a problem ever?
        if im.mode != 'RGBA':
            im = im.convert('RGBA')

        s = im.tobytes('raw', 'BGRA')
        a = array.array('B', s)
        dest = cairo.ImageSurface(cairo.FORMAT_ARGB32,
                                  im.size[0], im.size[1])
        ctx = cairo.Context(dest)
        non_premult_src_wo_alpha = cairo.ImageSurface.create_for_data(
            a, cairo.FORMAT_RGB24, im.size[0], im.size[1])
        non_premult_src_alpha = cairo.ImageSurface.create_for_data(
            a, cairo.FORMAT_ARGB32, im.size[0], im.size[1])
        ctx.set_source_surface(non_premult_src_wo_alpha)
        ctx.mask_surface(non_premult_src_alpha)
        return dest

    def __process_size(self, size_str):
        us = self.__get_use_size()
        size = 0
        size_str = size_str.replace("-", "+-")
        for s in size_str.split("+"):
            if s=="":
                continue
            if s[-1] == "%":
                # Rounding to whole pixels to avoid uninteded bluring.
                size += round(float(s[:-1]) / 100 * us)
                continue
            if s.endswith("px"):
                s = s[:-2]
            # Here no rounding is done. Let's assume that the
            # theme maker knows what he is doing if he chooses
            # to use decimal pixel values.
            size += float(s)
        return size

    def __get_use_size(self):
        is_vertical = self.dockbar_r().orient in ("left", "right")
        if "aspect_ratio_v" in self.theme.theme["button_pixmap"] or \
           not is_vertical:
            us = self.size * self.ar if self.ar < 1 else self.size
        else:
            # For old vertical themes
            us = self.size
        return us

    def __get_from_set(self, setname):
        s = self.theme.get_from_set(setname, self.orient)
        if s is not None:
            return s
        else:
            return setname

    def __resize_surface(self, surface, w, h):
        im = self.__surface2pil(surface)
        im = im.resize((w, h), Image.ANTIALIAS)
        return self.__pil2surface(im)

    def __command_print_size(self, surface):
        w = surface.get_width()
        h = surface.get_height()
        print w, h
        return surface
Beispiel #28
0
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# This module *just* use for test module under dtk.ui

from skin_config import skin_config
from theme import Theme, ui_theme
from deepin_utils.file import get_parent_dir
import os

# Init skin config.
skin_config.init_skin(
    "01", os.path.join(get_parent_dir(__file__, 3), "skin"),
    os.path.expanduser("~/.config/deepin-demo/skin"),
    os.path.expanduser("~/.config/deepin-demo/skin_config.ini"),
    "deepin-media-player", "1.0")

# Create application theme.
app_theme = Theme(os.path.join(get_parent_dir(__file__, 3), "app_theme"),
                  os.path.expanduser("~/.config/deepin-demo/theme"))

# Set theme.
skin_config.load_themes(ui_theme, app_theme)
Beispiel #29
0
class MainWindow(object):
    def __init__(self, liststore):
        self.liststore = liststore

        self.gui = gui = Gtk.Builder()
        gui.add_from_file(SHARED_DATA_FILE("gfeedline.glade"))

        self.window = window = gui.get_object("main_window")
        self.column = MultiColumnDict(gui)  # multi-columns for Notebooks
        self.theme = Theme()
        self.font = FontSet()
        self.notification = StatusNotification(liststore)

        dnd_list = [Gtk.TargetEntry.new("text/uri-list", 0, 1), Gtk.TargetEntry.new("text/x-moz-url", 0, 4)]
        window.drag_dest_set(Gtk.DestDefaults.ALL, dnd_list, Gdk.DragAction.COPY)

        target = Gtk.TargetList.new([])
        target.add(Gdk.Atom.intern("text/x-moz-url", False), 0, 4)
        target.add(Gdk.Atom.intern("text/uri-list", False), 0, 1)

        window.drag_dest_set_target_list(target)
        window.connect("drag-data-received", self.on_drag_data_received)

        SETTINGS.connect("changed::window-sticky", self.on_settings_sticky_change)
        self.on_settings_sticky_change(SETTINGS, "window-sticky")

        SETTINGS_VIEW.connect("changed::theme", self.on_settings_theme_change)
        self.on_settings_theme_change(SETTINGS_VIEW, "theme")

        is_multi_column = SETTINGS_VIEW.get_boolean("multi-column")
        menuitem_multicolumn = gui.get_object("menuitem_multicolumn")
        menuitem_multicolumn.set_active(is_multi_column)

        menuitem_update = MenuItemUpdate(gui, liststore)

        x, y, w, h = self._get_geometry_from_settings()
        #        window.show() # for wrong position when auto-start

        if x >= 0 and y >= 0:
            window.move(x, y)

        window.resize(w, h)
        window.show()

        gui.connect_signals(self)

    def on_drag_data_received(self, widget, context, x, y, selection, info, time):
        text, image_file = DnDSelection.parse(info, selection, True)

        if text or image_file:
            updatewindow = UpdateWindow(self)

            if text:
                updatewindow.text_buffer.set_text(text)
            else:
                updatewindow.set_upload_media(image_file)

    def get_notebook(self, group_name):
        if not SETTINGS_VIEW.get_boolean("multi-column"):
            group_name = "dummy for single column"

        if group_name in self.column:
            notebook = self.column.get(group_name)
        else:
            notebook = FeedNotebook(self.column, group_name, self.liststore)
            self.column.add(group_name, notebook)

        return notebook

    def toggle_multicolumn_mode(self):
        for row in self.liststore:
            notebook = self.get_notebook(row[Column.GROUP])
            view = row[Column.API].view
            view.force_remove()
            view.append(notebook, -1)

        reactor.callLater(0.1, self._jump_all_tabs_to_bottom, self.theme.is_ascending())

    def _jump_all_tabs_to_bottom(self, is_bottom=True):
        for notebook in self.column.values():
            notebook.jump_all_tabs_to_bottom(is_bottom)

    def change_font(self, font=None, size=None):
        for notebook in self.column.values():
            notebook.change_font(font, size)

    def delete_status(self, status_id):
        js = 'hideStatus("%s")' % status_id

        for notebook in self.column.values():
            notebook.exec_js_all_views(js)

    def _get_geometry_from_settings(self):
        x = SETTINGS_GEOMETRY.get_int("window-x")
        y = SETTINGS_GEOMETRY.get_int("window-y")
        w = SETTINGS_GEOMETRY.get_int("window-width")
        h = SETTINGS_GEOMETRY.get_int("window-height")
        return x, y, w, h

    def on_window_leave_notify_event(self, widget, event):
        ox, oy, ow, oh = self._get_geometry_from_settings()

        x, y = widget.get_position()
        w, h = widget.get_size()

        if x != ox or y != oy:
            SETTINGS_GEOMETRY.set_int("window-x", x)
            SETTINGS_GEOMETRY.set_int("window-y", y)

        if w != ow or h != oh:
            SETTINGS_GEOMETRY.set_int("window-width", w)
            SETTINGS_GEOMETRY.set_int("window-height", h)

    def on_stop(self, *args):
        for row in self.liststore:
            row[Column.OPTIONS]["last_id"] = row[Column.API].last_id
        self.liststore.save_settings()

        reactor.stop()
        # self.window.destroy()

    def on_menuitem_quit_activate(self, menuitem):
        self.on_stop()

    def on_menuitem_update_activate(self, menuitem):
        UpdateWindow(self.liststore)

    def on_menuitem_prefs_activate(self, menuitem):
        Preferences(self)

    def on_menuitem_multicolumn_toggled(self, menuitem):
        is_multi_column = menuitem.get_active()
        SETTINGS_VIEW.set_boolean("multi-column", is_multi_column)
        self.toggle_multicolumn_mode()

    def on_menuitem_about_activate(self, menuitem):
        AboutDialog(self.window)

    def on_menuitem_help_activate(self, menuitem):
        Gtk.show_uri(None, "http://code.google.com/p/gfeedline/wiki/Tips", Gdk.CURRENT_TIME)

    def on_menuitem_top_activate(self, menuitem=None):
        self._jump_all_tabs_to_bottom(False)

    def on_menuitem_bottom_activate(self, menuitem=None):
        self._jump_all_tabs_to_bottom()

    def on_menuitem_clear_activate(self, menuitem=None):
        for notebook in self.column.values():
            notebook.clear_all_tabs()

    def on_menuitem_fullscreen_activate(self, menuitem):
        if menuitem.get_active():
            self.window.fullscreen()
        else:
            self.window.unfullscreen()

    def on_menuitem_zoom_in_activate(self, menuitem):
        font_css = self.font.zoom_in()
        self.change_font(font_css)

    def on_menuitem_zoom_out_activate(self, menuitem):
        font_css = self.font.zoom_out()
        self.change_font(font_css)

    def on_menuitem_zoom_default_activate(self, menuitem):
        font_css = self.font.zoom_default()
        self.change_font(font_css)

    def on_settings_sticky_change(self, settings, key):
        if settings.get_boolean(key):
            self.window.stick()
        else:
            self.window.unstick()

    def on_settings_theme_change(self, settings, key):
        top = self.gui.get_object("menuitem_top")
        bottom = self.gui.get_object("menuitem_bottom")

        if not self.theme.is_ascending():
            top, bottom = bottom, top

        top.hide()
        bottom.show()
Beispiel #30
0
class DemoPrinter(object):
    def __init__(self):
        self.LV_HOR_RES = lv.scr_act().get_disp().driver.hor_res
        self.LV_VER_RES = lv.scr_act().get_disp().driver.ver_res
        # Bg positions
        self.LV_DEMO_PRINTER_BG_NONE = -self.LV_VER_RES
        self.LV_DEMO_PRINTER_BG_FULL = 0
        self.LV_DEMO_PRINTER_BG_NORMAL = -2 * (self.LV_VER_RES // 3)
        self.LV_DEMO_PRINTER_BG_SMALL = -5 * (self.LV_VER_RES // 6)

        # Animations
        self.LV_DEMO_PRINTER_ANIM_Y = self.LV_VER_RES // 20
        self.LV_DEMO_PRINTER_ANIM_DELAY = 40
        self.LV_DEMO_PRINTER_ANIM_TIME = 150
        self.LV_DEMO_PRINTER_ANIM_TIME_BG = 300

        self.LV_DEMO_PRINTER_BG_NORMAL = (-2 * (self.LV_VER_RES // 3))

        self.log = logging.getLogger("DemoPrinter")
        self.log.setLevel(logging.ERROR)

        self.icon_wifi_data = None
        self.icon_wifi_dsc = None
        self.icon_tel_data = None
        self.icon_tel_dsc = None
        self.icon_eco_data = None
        self.icon_eco_dsc = None
        self.icon_pc_data = None
        self.icon_pc_dsc = None

        self.img_btn_bg_1_data = None
        self.img_btn_bg_1_dsc = None
        self.img_btn_bg_2_data = None
        self.img_btn_bg_2_dsc = None
        self.img_btn_bg_3_data = None
        self.img_btn_bg_3_dsc = None
        self.img_btn_bg_4_data = None
        self.img_btn_bg_4_dsc = None

        self.img_copy_data = None
        self.img_copy_dsc = None
        self.img_print_data = None
        self.img_print_dsc = None
        self.img_scan_data = None
        self.img_scan_dsc = None
        self.img_setup_data = None
        self.img_setup_dsc = None

        self.scan_img = None
        self.bg_top = None
        self.bg_bottom = None

        self.bg_color_prev = LV_DEMO_PRINTER_BLUE
        self.bg_color_act = LV_DEMO_PRINTER_BLUE
        self.bg_top = lv.obj(lv.scr_act(), None)
        self.bg_top.set_size(self.LV_HOR_RES, self.LV_VER_RES)

        # read all the images fromm the raw image files

        (self.icon_wifi_data,
         self.icon_wifi_dsc) = self.get_icon("icon_wifi_48x34", 48, 34)
        (self.icon_tel_data,
         self.icon_tel_dsc) = self.get_icon("icon_tel_35x35", 35, 35)
        (self.icon_eco_data,
         self.icon_eco_dsc) = self.get_icon("icon_eco_38x34", 38, 34)
        (self.icon_pc_data,
         self.icon_pc_dsc) = self.get_icon("icon_pc_41x33", 41, 33)

        (self.icon_bright_data,
         self.icon_bright_dsc) = self.get_icon("icon_bright_29x29", 29, 29)
        (self.icon_hue_data,
         self.icon_hue_dsc) = self.get_icon("icon_hue_23x23", 23, 23)

        (self.img_btn_bg_1_data,
         self.img_btn_bg_1_dsc) = self.get_icon("img_btn_bg_1_174x215", 174,
                                                215)
        (self.img_btn_bg_2_data,
         self.img_btn_bg_2_dsc) = self.get_icon("img_btn_bg_2_174x215", 174,
                                                215)
        (self.img_btn_bg_3_data,
         self.img_btn_bg_3_dsc) = self.get_icon("img_btn_bg_3_174x215", 174,
                                                215)
        (self.img_btn_bg_4_data,
         self.img_btn_bg_4_dsc) = self.get_icon("img_btn_bg_4_174x215", 174,
                                                215)

        (self.img_copy_data,
         self.img_copy_dsc) = self.get_icon("img_copy_51x60", 51, 60)
        (self.img_print_data,
         self.img_print_dsc) = self.get_icon("img_print_65x64", 65, 64)
        (self.img_scan_data,
         self.img_scan_dsc) = self.get_icon("img_scan_51x61", 51, 61)
        (self.img_setup_data,
         self.img_setup_dsc) = self.get_icon("img_setup_63x64", 63, 64)

        (self.img_usb_data,
         self.img_usb_dsc) = self.get_icon("img_usb_62x61", 62, 61)
        (self.img_internet_data,
         self.img_internet_dsc) = self.get_icon("img_internet_65x64", 65, 64)
        (self.img_mobile_data,
         self.img_mobile_dsc) = self.get_icon("img_mobile_50x60", 50, 60)
        (self.img_wave_data,
         self.img_wave_dsc) = self.get_icon("img_wave_27x47", 27, 47)
        (self.img_phone_data,
         self.img_phone_dsc) = self.get_icon("img_phone_77x99", 77, 99)

        (self.img_ready,
         self.img_ready_dsc) = self.get_icon("img_ready_158x158", 158, 158)

        (self.img_printer2_data,
         self.img_printer2_dsc) = self.get_icon("img_printer2_107x104", 107,
                                                104)
        (self.img_no_internet_data,
         self.img_no_internet_dsc) = self.get_icon("img_no_internet_42x42", 42,
                                                   42)
        (self.img_cloud_data,
         self.img_cloud_dsc) = self.get_icon("img_cloud_93x59", 93, 59)

        (self.scan_example_data,
         self.scan_example_dsc) = self.get_icon("scan_example_522x340", 522,
                                                340)
        self.theme = Theme()

        self.home_open(0)

    def home_open(self, delay):

        self.bg_top.set_style_local_bg_opa(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                           lv.OPA.COVER)
        self.bg_top.set_style_local_bg_color(lv.obj.PART.MAIN,
                                             lv.STATE.DEFAULT,
                                             LV_DEMO_PRINTER_BLUE)
        self.bg_top.set_y(self.LV_DEMO_PRINTER_BG_NORMAL)

        self.cont = lv.cont(lv.scr_act(), None)
        self.cont.set_size(350, 80)
        self.cont.clean_style_list(lv.cont.PART.MAIN)
        self.cont.align(None, lv.ALIGN.IN_TOP_LEFT, 60, 0)

        icon = lv.img(self.cont, None)
        icon.set_src(self.icon_wifi_dsc)
        icon.align(None, lv.ALIGN.IN_TOP_LEFT, 20, 45)
        self.anim_in(icon, delay)

        icon = lv.img(self.cont, None)
        icon.set_src(self.icon_tel_dsc)
        icon.align(None, lv.ALIGN.IN_TOP_LEFT, 110, 45)
        self.anim_in(icon, delay)

        icon = lv.img(self.cont, None)
        icon.set_src(self.icon_eco_dsc)
        icon.align(None, lv.ALIGN.IN_TOP_LEFT, 200, 45)
        self.anim_in(icon, delay)

        icon = lv.img(self.cont, None)
        icon.set_src(self.icon_pc_dsc)
        icon.align(None, lv.ALIGN.IN_TOP_LEFT, 290, 45)
        self.anim_in(icon, delay)

        title = self.add_title("23 February 2021 20:13")
        title.align(None, lv.ALIGN.IN_TOP_RIGHT, -60,
                    LV_DEMO_PRINTER_TITLE_PAD)

        delay += self.LV_DEMO_PRINTER_ANIM_DELAY
        self.anim_in(title, delay)

        box_w = 720
        box = lv.obj(lv.scr_act(), None)
        box.set_size(box_w, 260)
        self.theme.apply(box, lv.THEME.CONT)

        box.align(None, lv.ALIGN.IN_TOP_MID, 0, 100)

        delay += self.LV_DEMO_PRINTER_ANIM_DELAY
        self.anim_in(box, delay)

        icon = self.add_icon(box, self.img_btn_bg_1_dsc, self.img_copy_dsc,
                             "COPY")
        icon.align(None, lv.ALIGN.IN_LEFT_MID, 1 * (box_w - 20) // 8 - 80, 0)
        icon.set_event_cb(self.copy_open_icon_event_cb)
        icon.fade_in(self.LV_DEMO_PRINTER_ANIM_TIME * 2,
                     delay + self.LV_DEMO_PRINTER_ANIM_TIME + 50)

        icon = self.add_icon(box, self.img_btn_bg_2_dsc, self.img_scan_dsc,
                             "SCAN")
        icon.align(None, lv.ALIGN.IN_LEFT_MID, 3 * (box_w - 20) // 8 - 80, 0)
        icon.fade_in(self.LV_DEMO_PRINTER_ANIM_TIME * 2,
                     delay + self.LV_DEMO_PRINTER_ANIM_TIME + 50)
        icon.set_event_cb(self.scan_open_icon_event_cb)

        icon = self.add_icon(box, self.img_btn_bg_3_dsc, self.img_print_dsc,
                             "PRINT")
        icon.align(None, lv.ALIGN.IN_LEFT_MID, 5 * (box_w - 20) // 8 - 80, 0)
        icon.fade_in(self.LV_DEMO_PRINTER_ANIM_TIME * 2,
                     delay + self.LV_DEMO_PRINTER_ANIM_TIME + 50)
        icon.set_event_cb(self.print_open_event_cb)

        icon = self.add_icon(box, self.img_btn_bg_4_dsc, self.img_setup_dsc,
                             "SETUP")
        icon.align(None, lv.ALIGN.IN_LEFT_MID, 7 * (box_w - 20) // 8 - 80, 0)
        icon.fade_in(self.LV_DEMO_PRINTER_ANIM_TIME * 2,
                     delay + self.LV_DEMO_PRINTER_ANIM_TIME + 50)
        icon.set_event_cb(self.setup_icon_event_cb)

        box = lv.obj(lv.scr_act(), None)
        box.set_size(500, 80)
        box.align(None, lv.ALIGN.IN_BOTTOM_LEFT, self.LV_HOR_RES // 20,
                  -self.LV_HOR_RES // 40)
        label = lv.label(box, None)
        label.set_text("What do you want to do today?")
        self.theme.apply(label, lv.THEME.LABEL)
        label.align(box, lv.ALIGN.CENTER, 0, 0)

        delay += self.LV_DEMO_PRINTER_ANIM_DELAY
        self.anim_in(box, delay)

        box = lv.obj(lv.scr_act(), None)
        box_w = 200
        box.set_size(box_w, 80)
        box.align(None, lv.ALIGN.IN_BOTTOM_RIGHT, -self.LV_HOR_RES // 20,
                  -self.LV_HOR_RES // 40)

        bar = lv.bar(box, None)
        bar.set_style_local_bg_color(lv.bar.PART.INDIC, lv.STATE.DEFAULT,
                                     lv.color_hex(0x01d3d4))
        bar.set_size(25, 50)
        bar.align(None, lv.ALIGN.IN_LEFT_MID, 1 * (box_w - 20) // 8 + 10, 0)
        bar.set_value(60, lv.ANIM.ON)

        bar = lv.bar(box, None)
        bar.set_style_local_bg_color(lv.bar.PART.INDIC, lv.STATE.DEFAULT,
                                     lv.color_hex(0xe600e6))
        bar.set_size(25, 50)
        bar.align(None, lv.ALIGN.IN_LEFT_MID, 3 * (box_w - 20) // 8 + 10, 0)
        bar.set_value(30, lv.ANIM.ON)

        bar = lv.bar(box, None)
        bar.set_style_local_bg_color(lv.bar.PART.INDIC, lv.STATE.DEFAULT,
                                     lv.color_hex(0xefef01))
        bar.set_size(25, 50)
        bar.align(None, lv.ALIGN.IN_LEFT_MID, 5 * (box_w - 20) // 8 + 10, 0)
        bar.set_value(80, lv.ANIM.ON)

        bar = lv.bar(box, None)
        bar.set_style_local_bg_color(lv.bar.PART.INDIC, lv.STATE.DEFAULT,
                                     lv.color_hex(0x1d1d25))
        bar.set_size(25, 50)
        bar.align(None, lv.ALIGN.IN_LEFT_MID, 7 * (box_w - 20) // 8 + 10, 0)
        bar.set_value(20, lv.ANIM.ON)

    #
    # get an icon
    #
    def get_icon(self, filename, xres, yres):

        try:
            sdl_filename = 'images/' + filename + "_argb8888.bin"
            self.log.debug('sdl filename: ' + sdl_filename)
            with open(sdl_filename, 'rb') as f:
                icon_data = f.read()
                self.log.debug(sdl_filename + " successfully read")
        except:
            self.log.error("Could not find image file: " + filename)
            return None

        icon_dsc = lv.img_dsc_t({
            "header": {
                "always_zero": 0,
                "w": xres,
                "h": yres,
                "cf": lv.img.CF.TRUE_COLOR_ALPHA
            },
            "data": icon_data,
            "data_size": len(icon_data),
        })
        return (icon_data, icon_dsc)

    def add_title(self, txt):
        title = lv.label(lv.scr_act(), None)
        self.theme.apply(title, LV_DEMO_PRINTER_THEME_TITLE)
        title.set_text(txt)
        title.align(None, lv.ALIGN.IN_TOP_MID, 0, LV_DEMO_PRINTER_TITLE_PAD)
        return title

    def add_icon(self, parent, src_bg_dsc, src_icon_dsc, txt):
        bg = lv.img(parent, None)
        bg.set_click(True)
        bg.set_src(src_bg_dsc)
        self.theme.apply(bg, LV_DEMO_PRINTER_THEME_ICON)
        bg.set_antialias(False)

        icon = lv.img(bg, None)
        icon.set_src(src_icon_dsc)
        icon.set_style_local_image_recolor_opa(lv.img.PART.MAIN,
                                               lv.STATE.DEFAULT, lv.OPA.TRANSP)
        icon.align(None, lv.ALIGN.IN_TOP_RIGHT, -30, 30)

        label = lv.label(bg, None)
        label.set_text(txt)
        label.align(None, lv.ALIGN.IN_BOTTOM_LEFT, 30, -30)
        self.theme.apply(label, lv.THEME.LABEL)
        return bg

    def copy_open_icon_event_cb(self, obj, evt):
        if evt == lv.EVENT.CLICKED:
            self.anim_out_all(lv.scr_act(), 0)
            self.log.debug("copy_open_icon_event_cb")
            self.scan_btn_txt = "NEXT"
            delay = 200
            self.anim_bg(150, LV_DEMO_PRINTER_BLUE,
                         self.LV_DEMO_PRINTER_BG_FULL)

            arc = self.add_loader(self.scan_anim_ready)
            arc.align(None, lv.ALIGN.CENTER, 0, -40)
            txt = lv.label(lv.scr_act(), None)
            txt.set_text("Scanning, please wait...")
            self.theme.apply(txt, LV_DEMO_PRINTER_THEME_LABEL_WHITE)
            txt.align(arc, lv.ALIGN.OUT_BOTTOM_MID, 0, 60)

            self.anim_in(arc, delay)
            delay += self.LV_DEMO_PRINTER_ANIM_DELAY
            self.anim_in(txt, delay)

            self.icon_generic_event_cb(obj, evt)

    def scan_open_icon_event_cb(self, obj, evt):
        if evt == lv.EVENT.CLICKED:
            self.log.debug("scan_open_icon_event_cb")
            self.scan_btn_txt = "SAVE"
            self.anim_out_all(lv.scr_act(), 0)
            delay = 200
            self.anim_bg(150, LV_DEMO_PRINTER_BLUE,
                         self.LV_DEMO_PRINTER_BG_FULL)
            arc = self.add_loader(self.scan_anim_ready)
            arc.align(None, lv.ALIGN.CENTER, 0, -40)

            txt = lv.label(lv.scr_act(), None)
            txt.set_text("Scanning, please wait...")
            self.theme.apply(txt, LV_DEMO_PRINTER_THEME_LABEL_WHITE)
            txt.align(arc, lv.ALIGN.OUT_BOTTOM_MID, 0, 60)

            self.anim_in(arc, delay)
            delay += self.LV_DEMO_PRINTER_ANIM_DELAY
            self.anim_in(txt, delay)

    def print_open_event_cb(self, obj, evt):
        if evt == lv.EVENT.CLICKED:
            self.anim_out_all(lv.scr_act(), 0)
            self.print_open(200)
            self.icon_generic_event_cb(obj, evt)

    def print_open(self, delay):
        back = self.add_back(self.back_to_home_event_cb)
        self.anim_in(back, delay)

        title = self.add_title("PRINT MENU")

        box_w = 720
        box = lv.obj(lv.scr_act(), None)
        box.set_size(box_w, 260)
        box.align(None, lv.ALIGN.IN_TOP_MID, 0, 100)

        delay += self.LV_DEMO_PRINTER_ANIM_DELAY
        self.anim_in(box, delay)

        icon = self.add_icon(box, self.img_btn_bg_2_dsc, self.img_usb_dsc,
                             "USB")
        icon.align(None, lv.ALIGN.IN_LEFT_MID, 1 * box_w // 7 - 40, 0)
        icon.set_event_cb(self.usb_icon_event_cb)
        icon.fade_in(self.LV_DEMO_PRINTER_ANIM_TIME * 2,
                     delay + self.LV_DEMO_PRINTER_ANIM_TIME + 50)

        icon = self.add_icon(box, self.img_btn_bg_3_dsc, self.img_mobile_dsc,
                             "MOBILE")
        icon.align(None, lv.ALIGN.IN_LEFT_MID, 3 * box_w // 7 - 40, 0)
        icon.set_event_cb(self.mobile_icon_event_cb)
        icon.fade_in(self.LV_DEMO_PRINTER_ANIM_TIME * 2,
                     delay + self.LV_DEMO_PRINTER_ANIM_TIME + 50)

        icon = self.add_icon(box, self.img_btn_bg_4_dsc, self.img_internet_dsc,
                             "INTERNET")
        icon.align(None, lv.ALIGN.IN_LEFT_MID, 5 * box_w // 7 - 40, 0)
        icon.set_event_cb(self.internet_icon_event_cb)
        icon.fade_in(self.LV_DEMO_PRINTER_ANIM_TIME * 2,
                     delay + self.LV_DEMO_PRINTER_ANIM_TIME + 50)

        box = lv.obj(lv.scr_act(), None)
        box.set_size(box_w, 80)
        box.align(None, lv.ALIGN.IN_BOTTOM_LEFT, self.LV_HOR_RES // 20,
                  -self.LV_HOR_RES // 40)
        label = lv.label(box, None)
        self.theme.apply(label, lv.THEME.LABEL)
        label.set_text("From where do you want to print?")
        label.align(box, lv.ALIGN.CENTER, 0, 0)

        delay += self.LV_DEMO_PRINTER_ANIM_DELAY
        self.anim_in(box, delay)

        self.anim_bg(0, LV_DEMO_PRINTER_BLUE, self.LV_DEMO_PRINTER_BG_NORMAL)

    def icon_generic_event_cb(self, obj, evt):
        if evt == lv.EVENT.PRESSED:
            img = obj.get_child_back(None)
            txt = obj.get_child(None)
            self.log.debug("icon_generic_event")

            a = lv.anim_t()
            a.init()
            a.set_time(100)

            a.set_var(img)
            a.set_custom_exec_cb(lambda a, val: self.set_x(img, val))
            # a.set_custom_exec_cb(lv_obj_set_x)
            a.set_values(img.get_x(), obj.get_width() - img.get_width() - 35)
            lv.anim_t.start(a)

            # a.set_custom_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y);
            a.set_custom_exec_cb(lambda a, val: self.set_y(img, val))
            a.set_values(img.get_y(), 35)
            lv.anim_t.start(a)

            a.set_var(txt)
            a.set_custom_exec_cb(lambda a, val: self.set_x(txt, val))
            a.set_values(txt.get_x(), 35)
            lv.anim_t.start(a)

            a.set_custom_exec_cb(lambda a, val: self.set_y(txt, val))
            a.set_values(txt.get_y(), obj.get_height() - txt.get_height() - 35)
            lv.anim_t.start(a)

    def setup_icon_event_cb(self, obj, evt):
        if evt == lv.EVENT.CLICKED:
            self.log.debug("setup_icon_event_cb")
            self.anim_out_all(lv.scr_act(), 0)

            self.anim_bg(0, LV_DEMO_PRINTER_RED, self.LV_DEMO_PRINTER_BG_FULL)
            delay = 200

            img = lv.img(lv.scr_act(), None)
            img.set_src(self.img_printer2_dsc)
            img.align(None, lv.ALIGN.CENTER, -90, 0)

            self.anim_in(img, delay)
            delay += self.LV_DEMO_PRINTER_ANIM_DELAY

            img = lv.img(lv.scr_act(), None)
            img.set_src(self.img_no_internet_dsc)
            img.align(None, lv.ALIGN.CENTER, 0, -40)

            self.anim_in(img, delay)
            delay += self.LV_DEMO_PRINTER_ANIM_DELAY

            img = lv.img(lv.scr_act(), None)
            img.set_src(self.img_cloud_dsc)
            img.align(None, lv.ALIGN.CENTER, 80, -80)

            self.anim_in(img, delay)
            delay += self.LV_DEMO_PRINTER_ANIM_DELAY

            self.info_bottom_create(
                "You have no permission to change the settings.", "BACK",
                self.back_to_home_event_cb, delay)

    def add_loader(self, end_cb):
        arc = lv.arc(lv.scr_act(), None)
        arc.set_bg_angles(0, 0)
        arc.set_start_angle(270)
        arc.set_size(220, 220)
        self.theme.apply(arc, lv.THEME.ARC)
        self.log.debug("Starting loader anim")
        a = lv.anim_t()
        a.init()
        a.set_custom_exec_cb(lambda a, val: self.loader_anim_cb(a, arc, val))
        a.set_values(0, 110)
        a.set_time(2000)
        a.set_ready_cb(end_cb)
        lv.anim_t.start(a)

        return arc

    def loader_anim_cb(self, a, arc, v):
        # self.log.debug("loader_anim_cb called with value: %d"%v)
        if v > 100:
            v = 100
        arc.set_end_angle(v * 360 // 100 + 270)
        percent_txt = "%d %%" % v
        arc.set_style_local_value_str(lv.arc.PART.BG, lv.STATE.DEFAULT,
                                      percent_txt)

    def anim_in(self, obj, delay):
        a = lv.anim_t()
        a.init()
        a.set_var(obj)
        a.set_time(self.LV_DEMO_PRINTER_ANIM_TIME)
        a.set_delay(delay)
        # a.set_exec_cb(obj.set_y)
        # a.set_values(obj.get_y() -  self.LV_DEMO_PRINTER_ANIM_Y, obj.get_y())
        # a.start()
        obj.fade_in(self.LV_DEMO_PRINTER_ANIM_TIME - 50, delay)

    def anim_out_all(self, obj, delay):
        self.log.debug("anim_out_all")
        child = obj.get_child_back(None)
        while child:
            if child != self.scan_img and child != self.bg_top and child != self.bg_bottom and child != lv.scr_act(
            ):
                a = lv.anim_t()
                a.init()
                a.set_var(child)
                a.set_time(self.LV_DEMO_PRINTER_ANIM_TIME)
                # a.set_exec_cb(lambda y: lv.obj.set_y(y))
                if child.get_y() < 80:
                    a.set_values(child.get_y(),
                                 child.get_y() - self.LV_DEMO_PRINTER_ANIM_Y)
                else:
                    a.set_values(child.get_y(),
                                 child.get_y() + self.LV_DEMO_PRINTER_ANIM_Y)
                    delay += self.LV_DEMO_PRINTER_ANIM_DELAY
                a.set_ready_cb(lv.obj.del_anim_ready_cb)
                lv.anim_t.start(a)
            child = obj.get_child_back(child)

    def scan_anim_ready(self, a):
        self.log.debug("scan_anim_ready")
        self.anim_out_all(lv.scr_act(), 0)
        self.scan1_open(self.scan_btn_txt)

    def scan1_open(self, btn_txt):
        self.log.debug("scan1_open " + btn_txt)
        self.anim_out_all(lv.scr_act(), 0)

        self.anim_bg(0, LV_DEMO_PRINTER_BLUE, self.LV_DEMO_PRINTER_BG_NORMAL)
        delay = 200
        back = self.add_back(self.back_to_home_event_cb)
        title = self.add_title("ADJUST IMAGE")

        self.scan_img = lv.img(lv.scr_act(), None)
        self.scan_img.set_src(self.scan_example_dsc)
        self.scan_img.align(None, lv.ALIGN.IN_TOP_LEFT, 40, 100)
        self.scan_img.set_style_local_radius(lv.img.PART.MAIN,
                                             lv.STATE.DEFAULT, 10)
        self.scan_img.set_style_local_clip_corner(lv.img.PART.MAIN,
                                                  lv.STATE.DEFAULT, True)
        self.scan_img.set_style_local_image_recolor_opa(
            lv.img.PART.MAIN, lv.STATE.DEFAULT, 80)

        box_w = 160
        settings_box = lv.obj(lv.scr_act(), None)
        settings_box.set_size(box_w, 245)
        settings_box.align(self.scan_img, lv.ALIGN.OUT_RIGHT_TOP, 40, 0)

        self.lightness_act = 0
        self.hue_act = 180

        slider = lv.slider(settings_box, None)
        slider.set_size(8, 160)
        slider.align(None, lv.ALIGN.IN_TOP_MID, -35, 65)
        slider.set_event_cb(self.lightness_slider_event_cb)
        slider.set_range(-80, 80)
        slider.set_value(0, lv.ANIM.OFF)
        slider.set_ext_click_area(30, 30, 30, 30)
        self.theme.apply(slider, lv.THEME.SLIDER)

        icon = lv.img(settings_box, None)
        icon.set_src(self.icon_bright_dsc)
        icon.align(slider, lv.ALIGN.OUT_TOP_MID, 0, -30)

        slider = lv.slider(settings_box, slider)
        slider.align(None, lv.ALIGN.IN_TOP_MID, 35, 65)
        slider.set_event_cb(self.hue_slider_event_cb)
        slider.set_range(0, 359)
        slider.set_value(180, lv.ANIM.OFF)
        self.theme.apply(slider, lv.THEME.SLIDER)

        icon = lv.img(settings_box, None)
        icon.set_src(self.icon_hue_dsc)
        icon.align(slider, lv.ALIGN.OUT_TOP_MID, 0, -30)

        self.scan_img_color_refr()

        next_btn = lv.btn(lv.scr_act(), None)
        self.theme.apply(next_btn, LV_DEMO_PRINTER_THEME_BTN_CIRCLE)
        next_btn.set_size(box_w, 60)
        next_btn.align(self.scan_img, lv.ALIGN.OUT_RIGHT_BOTTOM, 40, 0)
        if btn_txt == "NEXT":
            next_btn.set_event_cb(self.scan_next_event_cb)
            next_btn.set_style_local_value_str(lv.obj.PART.MAIN,
                                               lv.STATE.DEFAULT, "NEXT")
            next_btn.set_style_local_value_font(lv.obj.PART.MAIN,
                                                lv.STATE.DEFAULT,
                                                self.theme.get_font_subtitle())
        elif btn_txt == "SAVE":
            next_btn.set_event_cb(self.scan_save_event_cb)
            next_btn.set_style_local_value_str(lv.obj.PART.MAIN,
                                               lv.STATE.DEFAULT, "SAVE")
            next_btn.set_style_local_value_font(lv.obj.PART.MAIN,
                                                lv.STATE.DEFAULT,
                                                self.theme.get_font_subtitle())
            next_btn.set_style_local_bg_color(lv.obj.PART.MAIN,
                                              lv.STATE.DEFAULT,
                                              LV_DEMO_PRINTER_GREEN)
            next_btn.set_style_local_bg_color(
                lv.obj.PART.MAIN, lv.STATE.PRESSED,
                LV_DEMO_PRINTER_GREEN.color_darken(lv.OPA._20))

    def scan_save_event_cb(self, obj, evt):
        if evt == lv.EVENT.CLICKED:
            self.scan_img = None

            self.anim_out_all(lv.scr_act(), 0)
            self.anim_bg(0, LV_DEMO_PRINTER_GREEN,
                         self.LV_DEMO_PRINTER_BG_FULL)

            delay = 200

            img = lv.img(lv.scr_act(), None)
            img.set_src(self.img_ready_dsc)
            img.align(None, lv.ALIGN.CENTER, 0, -40)

            delay += self.LV_DEMO_PRINTER_ANIM_DELAY
            self.anim_in(img, delay)

            self.info_bottom_create("File saved", "CONTINUE",
                                    self.back_to_home_event_cb, delay)

    def scan_next_event_cb(self, obj, evt):
        LV_IMG_ZOOM_NONE = 250
        if evt == lv.EVENT.CLICKED:
            self.anim_out_all(lv.scr_act(), 0)

            delay = 400

            back = self.add_back(self.back_to_home_event_cb)
            self.anim_in(back, delay)

            title = self.add_title("ADJUST IMAGE")
            self.anim_in(title, delay)

            box_w = 400
            self.scan_img.set_pivot(0, 0)
            self.scan_img.set_antialias(False)

            a = lv.anim_t()
            a.init()
            a.set_var(self.scan_img)
            a.set_custom_exec_cb(
                lambda a, val: self.set_zoom(self.scan_img, val))
            a.set_values(LV_IMG_ZOOM_NONE, 190)
            a.set_time(200)
            a.set_delay(200)
            lv.anim_t.start(a)

            # self.scan_img = None    # To allow anim out

            dropdown_box = lv.obj(lv.scr_act(), None)
            dropdown_box.set_size(box_w, self.LV_VER_RES // 5)
            dropdown_box.align(None, lv.ALIGN.IN_BOTTOM_LEFT, 40, -20)

            dropdown = lv.dropdown(dropdown_box, None)
            dropdown.align(None, lv.ALIGN.IN_LEFT_MID, self.LV_HOR_RES // 60,
                           0)
            dropdown.set_max_height(self.LV_VER_RES // 3)
            dropdown.set_options_static("Best\nNormal\nDraft")
            dropdown.set_width((box_w - 3 * self.LV_HOR_RES // 60) // 2)
            self.theme.apply(dropdown, lv.THEME.DROPDOWN)

            dropdown = lv.dropdown(dropdown_box, dropdown)
            dropdown.align(None, lv.ALIGN.IN_RIGHT_MID, -self.LV_HOR_RES // 60,
                           0)
            dropdown.set_options_static(
                "72 DPI\n96 DPI\n150 DPI\n300 DPI\n600 DPI\n900 DPI\n1200 DPI")
            self.theme.apply(dropdown, lv.THEME.DROPDOWN)

            box_w = 320 - 40
            settings_box = lv.obj(lv.scr_act(), None)
            settings_box.set_size(box_w, self.LV_VER_RES // 2)
            settings_box.align(None, lv.ALIGN.IN_TOP_RIGHT, -40, 100)

            numbox = lv.cont(settings_box, None)
            self.theme.apply(numbox, LV_DEMO_PRINTER_THEME_BOX_BORDER)
            numbox.set_size(self.LV_HOR_RES // 7, self.LV_HOR_RES // 13)
            numbox.align(settings_box, lv.ALIGN.IN_TOP_MID, 0,
                         self.LV_VER_RES // 10)
            numbox.set_style_local_value_str(lv.obj.PART.MAIN,
                                             lv.STATE.DEFAULT, "Copies")
            numbox.set_style_local_value_align(lv.obj.PART.MAIN,
                                               lv.STATE.DEFAULT,
                                               lv.ALIGN.OUT_TOP_MID)
            numbox.set_style_local_value_ofs_y(lv.obj.PART.MAIN,
                                               lv.STATE.DEFAULT,
                                               -self.LV_VER_RES // 50)
            numbox.set_style_local_value_font(lv.obj.PART.MAIN,
                                              lv.STATE.DEFAULT,
                                              self.theme.get_font_subtitle())
            numbox.set_layout(lv.LAYOUT.CENTER)

            self.print_cnt = 1
            self.print_cnt_label = lv.label(numbox, None)
            self.print_cnt_label.set_text("1")
            self.print_cnt_label.set_style_local_text_font(
                lv.label.PART.MAIN, lv.STATE.DEFAULT,
                self.theme.get_font_subtitle())

            btn = lv.btn(settings_box, None)
            btn.set_size(self.LV_HOR_RES // 13, self.LV_HOR_RES // 13)
            btn.align(numbox, lv.ALIGN.OUT_LEFT_MID, -self.LV_VER_RES // 60, 0)
            btn.set_style_local_value_str(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                          lv.SYMBOL.DOWN)
            btn.set_style_local_value_font(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                           self.theme.get_font_subtitle())
            btn.set_event_cb(self.print_cnt_btn_event_cb)
            btn.set_ext_click_area(10, 10, 10, 10)
            self.theme.apply(btn, lv.THEME.BTN)

            sw = lv.switch(settings_box, None)
            sw.set_size(self.LV_HOR_RES // 10, self.LV_VER_RES // 12)
            sw.align(btn, lv.ALIGN.OUT_BOTTOM_LEFT, self.LV_HOR_RES // 50,
                     self.LV_VER_RES // 7)
            sw.set_style_local_value_ofs_y(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                           -self.LV_VER_RES // 50)
            sw.set_style_local_value_align(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                           lv.ALIGN.OUT_TOP_MID)
            sw.set_style_local_value_str(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                         "Color")
            sw.set_style_local_value_font(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                          self.theme.get_font_subtitle())
            self.theme.apply(sw, lv.THEME.SWITCH)

            btn = lv.btn(settings_box, btn)
            btn.align(numbox, lv.ALIGN.OUT_RIGHT_MID, self.LV_VER_RES // 60, 0)
            btn.set_style_local_value_str(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                          lv.SYMBOL.UP)
            btn.set_event_cb(self.print_cnt_btn_event_cb)
            self.theme.apply(btn, lv.THEME.BTN)

            sw = lv.switch(settings_box, sw)
            sw.align(btn, lv.ALIGN.OUT_BOTTOM_RIGHT, -self.LV_HOR_RES // 50,
                     self.LV_VER_RES // 7)
            sw.set_style_local_value_str(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                         "Vertical")

            print_btn = lv.btn(lv.scr_act(), None)
            self.theme.apply(print_btn, LV_DEMO_PRINTER_THEME_BTN_CIRCLE)
            print_btn.set_size(box_w, 60)
            print_btn.set_event_cb(self.print_start_event_cb)

            btn_ofs_y = (dropdown_box.get_height() -
                         print_btn.get_height()) // 2
            print_btn.align(settings_box, lv.ALIGN.OUT_BOTTOM_MID, 0,
                            self.LV_HOR_RES // 30 + btn_ofs_y)
            print_btn.set_style_local_value_str(lv.obj.PART.MAIN,
                                                lv.STATE.DEFAULT, "PRINT")
            print_btn.set_style_local_value_font(
                lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                self.theme.get_font_subtitle())
            print_btn.set_style_local_bg_color(lv.obj.PART.MAIN,
                                               lv.STATE.DEFAULT,
                                               LV_DEMO_PRINTER_GREEN)
            print_btn.set_style_local_bg_color(
                lv.obj.PART.MAIN, lv.STATE.PRESSED,
                LV_DEMO_PRINTER_GREEN.color_darken(lv.OPA._20))

            delay += self.LV_DEMO_PRINTER_ANIM_DELAY
            self.anim_in(settings_box, delay)

            delay += self.LV_DEMO_PRINTER_ANIM_DELAY
            self.anim_in(dropdown_box, delay)

            delay += self.LV_DEMO_PRINTER_ANIM_DELAY
            self.anim_in(print_btn, delay)

            self.anim_bg(0, LV_DEMO_PRINTER_BLUE,
                         self.LV_DEMO_PRINTER_BG_NORMAL)

    def anim_bg(self, delay, color, y_new):
        self.log.debug("anim_bg: new y: %d" % y_new)
        y_act = self.bg_top.get_y()
        act_color = self.bg_top.get_style_bg_color(lv.obj.PART.MAIN)
        self.log.debug("current y: %d" % y_act)
        if y_new != self.LV_DEMO_PRINTER_BG_NORMAL and y_new == y_act and act_color.full == color.full:
            return

        if (y_new == self.LV_DEMO_PRINTER_BG_NORMAL and y_new == y_act) or \
           (y_new == self.LV_DEMO_PRINTER_BG_NORMAL and y_act == self.LV_DEMO_PRINTER_BG_FULL):
            path = lv.anim_path_t()
            path.init()
            path.set_cb(self.triangle_path_cb)

            a = lv.anim_t()
            a.set_var(self.bg_top)
            a.set_time(self.LV_DEMO_PRINTER_ANIM_TIME_BG + 200)
            a.set_delay(delay)
            a.set_custom_exec_cb(lambda a, val: self.set_y(self.bg_top, val))
            a.set_values(y_act, y_new)
            a.set_path(path)
            lv.anim_t.start(a)
        else:
            a = lv.anim_t()
            a.set_var(self.bg_top)
            a.set_time(self.LV_DEMO_PRINTER_ANIM_TIME_BG)
            a.set_delay(delay)
            a.set_custom_exec_cb(lambda a, val: self.set_y(self.bg_top, val))
            a.set_values(self.bg_top.get_y(), y_new)
            lv.anim_t.start(a)

        color_anim = lv.anim_t()
        self.bg_color_prev = self.bg_color_act
        self.bg_color_act = color
        color_anim.set_custom_exec_cb(
            lambda color_anim, val: self.anim_bg_color_cb(val))
        color_anim.set_values(0, 255)
        color_anim.set_time(self.LV_DEMO_PRINTER_ANIM_TIME_BG)
        path = lv.anim_path_t()
        path.init()
        path.set_cb(lv.anim_path_t.linear)
        # a.set_path(lv.anim_t.path_def)
        lv.anim_t.start(color_anim)

    def triangle_path_cb(self, path, a):
        if a.time == a.act_time:
            return a.end
        if a.act_time < a.time // 2:
            step = a.act_time * 1024 // (a.time // 2)
            new_value = step * self.LV_DEMO_PRINTER_BG_SMALL - a.start
            new_value >>= 10
            new_value += a.start
            self.log.debug("triangle: new value: %d" % new_value)
            return new_value
        else:
            t = a.act_time - a.time // 2
            step = a.act_time * 1024 // (a.time // 2)
            new_value = step * (a.end - self.LV_DEMO_PRINTER_BG_SMALL)
            new_value >>= 10
            new_value += self.LV_DEMO_PRINTER_BG_SMALL
            self.log.debug("triangle: new value: %d" % new_value)
            return new_value

    def set_y(self, obj, new_y):
        self.log.debug("Setting y to %d" % new_y)
        obj.set_y(new_y)

    def set_x(self, obj, new_x):
        self.log.debug("Setting x to %d" % new_x)
        obj.set_x(new_x)

    def set_zoom(self, obj, new_size):
        self.log.debug("Setting zoom to %d" % new_size)
        obj.set_zoom(new_size)

    def anim_bg_color_cb(self, v):
        self.log.debug("anim_bg_color_cb: Mixing colors with value: %d" % v)
        c = self.bg_color_act.color_mix(self.bg_color_prev, v)
        self.bg_top.set_style_local_bg_color(lv.obj.PART.MAIN,
                                             lv.STATE.DEFAULT, c)

    def info_bottom_create(self, label_txt, btn_txt, btn_event_cb, delay):
        LV_DEMO_PRINTER_BTN_W = 200
        LV_DEMO_PRINTER_BTN_H = 50

        txt = lv.label(lv.scr_act(), None)
        txt.set_text(label_txt)
        self.theme.apply(txt, LV_DEMO_PRINTER_THEME_LABEL_WHITE)
        txt.align(None, lv.ALIGN.CENTER, 0, 100)

        btn = lv.btn(lv.scr_act(), None)
        self.theme.apply(btn, LV_DEMO_PRINTER_THEME_BTN_BORDER)
        btn.set_size(LV_DEMO_PRINTER_BTN_W, LV_DEMO_PRINTER_BTN_H)
        btn.align(txt, lv.ALIGN.OUT_BOTTOM_MID, 0, 60)

        btn.set_style_local_value_str(lv.btn.PART.MAIN, lv.STATE.DEFAULT,
                                      btn_txt)
        btn.set_style_local_value_font(lv.btn.PART.MAIN, lv.STATE.DEFAULT,
                                       self.theme.get_font_normal())
        btn.set_event_cb(btn_event_cb)

        self.anim_in(txt, delay)
        delay += self.LV_DEMO_PRINTER_ANIM_DELAY

        self.anim_in(btn, delay)
        delay += self.LV_DEMO_PRINTER_ANIM_DELAY

        self.anim_in(btn, delay)

    def back_to_home_event_cb(self, obj, evt):
        if evt == lv.EVENT.CLICKED:
            self.scan_img = None
            self.anim_out_all(lv.scr_act(), 0)
            self.home_open(200)
        pass

    def add_back(self, event_cb):
        btn = lv.btn(lv.scr_act(), None)
        self.theme.apply(btn, LV_DEMO_PRINTER_THEME_BTN_BACK)
        btn.set_size(80, 80)
        btn.set_pos(30, 10)
        btn.set_event_cb(event_cb)
        return btn

    def lightness_slider_event_cb(self, obj, evt):
        if evt == lv.EVENT.VALUE_CHANGED:
            self.lightness_act = obj.get_value()
            self.log.debug("lightness_slider_event: new slider value: %d" %
                           self.lightness_act)
            self.scan_img_color_refr()

    def hue_slider_event_cb(self, obj, evt):
        if evt == lv.EVENT.VALUE_CHANGED:
            self.hue_act = obj.get_value()
            self.log.debug("hue_slider_event: new slider value: %d" %
                           self.hue_act)
            self.scan_img_color_refr()

    def scan_img_color_refr(self):
        if self.lightness_act > 0:
            s = 100 - self.lightness_act
            v = 100
        else:
            s = 100
            v = 100 + self.lightness_act
        self.log.debug("scan_img_color_refr: hue, s, v: %d %d %d" %
                       (self.hue_act, s, v))

        c = lv.color_hsv_to_rgb(self.hue_act, s, v)
        self.scan_img.set_style_local_image_recolor(lv.img.PART.MAIN,
                                                    lv.STATE.DEFAULT, c)

    def internet_icon_event_cb(self, obj, evt):
        if evt == lv.EVENT.CLICKED:
            self.anim_out_all(lv.scr_act(), 0)
            self.anim_bg(0, LV_DEMO_PRINTER_RED, self.LV_DEMO_PRINTER_BG_FULL)

            delay = 200

            img = lv.img(lv.scr_act(), None)
            img.set_src(self.img_printer2_dsc)
            img.align(None, lv.ALIGN.CENTER, -90, 0)

            self.anim_in(img, delay)
            delay += self.LV_DEMO_PRINTER_ANIM_DELAY

            img = lv.img(lv.scr_act(), None)
            img.set_src(self.img_no_internet_dsc)
            img.align(None, lv.ALIGN.CENTER, 0, -40)

            self.anim_in(img, delay)
            delay += self.LV_DEMO_PRINTER_ANIM_DELAY

            img = lv.img(lv.scr_act(), None)
            img.set_src(self.img_cloud_dsc)
            img.align(None, lv.ALIGN.CENTER, 80, -80)

            self.anim_in(img, delay)
            delay += self.LV_DEMO_PRINTER_ANIM_DELAY

            self.info_bottom_create("No internet connection", "BACK",
                                    self.back_to_print_event_cb, delay)

        self.icon_generic_event_cb(obj, evt)

    def mobile_icon_event_cb(self, obj, evt):
        if evt == lv.EVENT.CLICKED:
            self.anim_out_all(lv.scr_act(), 0)

            self.anim_bg(0, LV_DEMO_PRINTER_BLUE, self.LV_DEMO_PRINTER_BG_FULL)

            delay = 200

            img = lv.img(lv.scr_act(), None)
            img.set_src(self.img_printer2_dsc)
            img.align(None, lv.ALIGN.CENTER, -90, 0)

            self.anim_in(img, delay)
            delay += self.LV_DEMO_PRINTER_ANIM_DELAY

            img = lv.img(lv.scr_act(), None)
            img.set_src(self.img_wave_dsc)
            img.align(None, lv.ALIGN.CENTER, 0, 0)

            self.anim_in(img, delay)
            delay += self.LV_DEMO_PRINTER_ANIM_DELAY

            img = lv.img(lv.scr_act(), None)
            img.set_src(self.img_phone_dsc)
            img.align(None, lv.ALIGN.CENTER, 80, 0)

            self.anim_in(img, delay)
            delay += self.LV_DEMO_PRINTER_ANIM_DELAY

            self.info_bottom_create("Put you phone near to the printer",
                                    "BACK", self.back_to_print_event_cb, delay)

        self.icon_generic_event_cb(obj, evt)

    def usb_icon_event_cb(self, obj, evt):
        if evt == lv.EVENT.CLICKED:
            self.anim_out_all(lv.scr_act(), 0)

            delay = 200

            back = self.add_back(self.back_to_print_event_cb)
            self.anim_in(back, delay)

            title = self.add_title("PRINTING FROM USB DRIVE")
            self.anim_in(title, delay)

            box_w = self.LV_HOR_RES * 5 // 10
            list = lv.list(lv.scr_act(), None)
            list.set_size(box_w, self.LV_VER_RES // 2)
            list.align(None, lv.ALIGN.IN_TOP_LEFT, self.LV_HOR_RES // 20,
                       self.LV_VER_RES // 5)

            dummy_file_list = [
                "Contract 12.pdf", "Scanned_05_21.pdf", "Photo_132210.jpg",
                "Photo_232141.jpg", "Photo_091640.jpg", "Photo_124019.jpg",
                "Photo_232032.jpg", "Photo_232033.jpg", "Photo_232034.jpg",
                "Monday schedule.pdf", "Email from John.txt", "New file.txt",
                "Untitled.txt", "Untitled (1).txt", "Gallery_40.jpg",
                "Gallery_41.jpg", "Gallery_42.jpg", "Gallery_43.jpg",
                "Gallery_44.jpg"
            ]

            for filename in dummy_file_list:
                btn = lv.btn.__cast__(list.add_btn(lv.SYMBOL.FILE, filename))
                btn.set_checkable(True)
                self.theme.apply(btn, lv.THEME.LIST_BTN)

            dropdown_box = lv.obj(lv.scr_act(), None)
            dropdown_box.set_size(box_w, self.LV_VER_RES // 5)
            dropdown_box.align(list, lv.ALIGN.OUT_BOTTOM_MID, 0,
                               self.LV_HOR_RES // 30)

            dropdown = lv.dropdown(dropdown_box, None)
            dropdown.align(None, lv.ALIGN.IN_LEFT_MID, self.LV_HOR_RES // 60,
                           0)
            dropdown.set_max_height(self.LV_VER_RES // 3)
            dropdown.set_options_static("Best\nNormal\nDraft")
            dropdown.set_width((box_w - 3 * self.LV_HOR_RES // 60) // 2)
            dropdown.set_ext_click_area(5, 5, 5, 5)
            self.theme.apply(dropdown, lv.THEME.DROPDOWN)

            dropdown = lv.dropdown(dropdown_box, dropdown)
            dropdown.align(None, lv.ALIGN.IN_RIGHT_MID, -self.LV_HOR_RES // 60,
                           0)
            # dropdown.set_options_static("100 DPI\n200 DPI\n300 DPI\n400 DPI\n500 DPI\n1500 DPI")
            dropdown.set_options_static("\n".join([
                "100 DPI", "200 DPI", "300 DPI", "400 DPI", "500 DPI",
                "1500 DPI"
            ]))
            self.theme.apply(dropdown, lv.THEME.DROPDOWN)

            box_w = 320 - 40
            settings_box = lv.obj(lv.scr_act(), None)
            settings_box.set_size(box_w, self.LV_VER_RES // 2)
            settings_box.align(list, lv.ALIGN.OUT_RIGHT_TOP,
                               self.LV_HOR_RES // 20, 0)

            self.print_cnt = 1
            numbox = lv.cont(settings_box, None)
            self.theme.apply(numbox, LV_DEMO_PRINTER_THEME_BOX_BORDER)
            numbox.set_size(self.LV_HOR_RES // 7, self.LV_HOR_RES // 13)
            numbox.align(settings_box, lv.ALIGN.IN_TOP_MID, 0,
                         self.LV_VER_RES // 10)
            numbox.set_style_local_value_str(lv.obj.PART.MAIN,
                                             lv.STATE.DEFAULT, "Copies")
            numbox.set_style_local_value_align(lv.obj.PART.MAIN,
                                               lv.STATE.DEFAULT,
                                               lv.ALIGN.OUT_TOP_MID)
            numbox.set_style_local_value_ofs_y(lv.obj.PART.MAIN,
                                               lv.STATE.DEFAULT,
                                               -self.LV_VER_RES // 50)
            numbox.set_style_local_value_font(lv.obj.PART.MAIN,
                                              lv.STATE.DEFAULT,
                                              self.theme.get_font_subtitle())
            numbox.set_layout(lv.LAYOUT.CENTER)

            self.print_cnt_label = lv.label(numbox, None)
            self.print_cnt_label.set_text("1")
            self.print_cnt_label.set_style_local_text_font(
                lv.label.PART.MAIN, lv.STATE.DEFAULT,
                self.theme.get_font_subtitle())

            btn = lv.btn(settings_box, None)
            btn.set_size(self.LV_HOR_RES // 13, self.LV_HOR_RES // 13)
            btn.align(numbox, lv.ALIGN.OUT_LEFT_MID, -self.LV_VER_RES // 60, 0)
            btn.set_style_local_value_str(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                          lv.SYMBOL.DOWN)
            btn.set_style_local_value_font(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                           self.theme.get_font_subtitle())
            btn.set_event_cb(self.print_cnt_btn_event_cb)
            btn.set_ext_click_area(10, 10, 10, 10)
            self.theme.apply(btn, lv.THEME.BTN)

            sw = lv.switch(settings_box, None)
            sw.set_size(self.LV_HOR_RES // 10, self.LV_VER_RES // 12)
            sw.align(btn, lv.ALIGN.OUT_BOTTOM_LEFT, self.LV_HOR_RES // 50,
                     self.LV_VER_RES // 7)
            sw.set_style_local_value_ofs_y(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                           -self.LV_VER_RES // 50)
            sw.set_style_local_value_align(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                           lv.ALIGN.OUT_TOP_MID)
            sw.set_style_local_value_str(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                         "Color")
            sw.set_style_local_value_font(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                          self.theme.get_font_subtitle())
            self.theme.apply(sw, lv.THEME.SWITCH)

            btn = lv.btn(settings_box, btn)
            btn.align(numbox, lv.ALIGN.OUT_RIGHT_MID, self.LV_VER_RES // 60, 0)
            btn.set_style_local_value_str(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                          lv.SYMBOL.UP)
            btn.set_style_local_value_font(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                           self.theme.get_font_subtitle())
            self.theme.apply(btn, lv.THEME.BTN)
            btn.set_event_cb(self.print_cnt_btn_event_cb)

            sw = lv.switch(settings_box, sw)
            sw.align(btn, lv.ALIGN.OUT_BOTTOM_RIGHT, -self.LV_HOR_RES // 50,
                     self.LV_VER_RES // 7)
            sw.set_style_local_value_str(lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                                         "Vertical")
            self.theme.apply(sw, lv.THEME.SWITCH)

            print_btn = lv.btn(lv.scr_act(), None)
            self.theme.apply(print_btn, LV_DEMO_PRINTER_THEME_BTN_CIRCLE)
            print_btn.set_size(box_w, 60)

            btn_ofs_y = (dropdown_box.get_height() -
                         print_btn.get_height()) // 2
            print_btn.align(settings_box, lv.ALIGN.OUT_BOTTOM_MID, 0,
                            self.LV_HOR_RES // 30 + btn_ofs_y)
            print_btn.set_style_local_value_str(lv.obj.PART.MAIN,
                                                lv.STATE.DEFAULT, "PRINT")
            print_btn.set_style_local_value_font(
                lv.obj.PART.MAIN, lv.STATE.DEFAULT,
                self.theme.get_font_subtitle())
            print_btn.set_style_local_bg_color(lv.obj.PART.MAIN,
                                               lv.STATE.DEFAULT,
                                               LV_DEMO_PRINTER_GREEN)
            print_btn.set_style_local_bg_color(
                lv.obj.PART.MAIN, lv.STATE.PRESSED,
                LV_DEMO_PRINTER_GREEN.color_darken(lv.OPA._20))
            print_btn.set_event_cb(self.print_start_event_cb)

            delay += self.LV_DEMO_PRINTER_ANIM_DELAY
            self.anim_in(list, delay)

            delay += self.LV_DEMO_PRINTER_ANIM_DELAY
            self.anim_in(settings_box, delay)

            delay += self.LV_DEMO_PRINTER_ANIM_DELAY
            self.anim_in(dropdown_box, delay)

            delay += self.LV_DEMO_PRINTER_ANIM_DELAY
            self.anim_in(print_btn, delay)

            self.anim_bg(0, LV_DEMO_PRINTER_BLUE,
                         self.LV_DEMO_PRINTER_BG_NORMAL)

    def print_cnt_btn_event_cb(self, obj, evt):
        if evt == lv.EVENT.CLICKED or evt == lv.EVENT.LONG_PRESSED_REPEAT:
            # if evt == lv.EVENT.CLICKED:
            txt = obj.get_style_value_str(lv.btn.PART.MAIN)
            if txt == lv.SYMBOL.DOWN:
                if self.print_cnt > 1:
                    self.print_cnt -= 1
            else:
                if self.print_cnt < 1000:
                    self.print_cnt += 1

            self.print_cnt_label.set_text(str(self.print_cnt))

    def print_start_event_cb(self, obj, evt):
        if evt == lv.EVENT.CLICKED:
            self.scan_img = None
            self.anim_out_all(lv.scr_act(), 0)
            delay = 200
            self.anim_bg(150, LV_DEMO_PRINTER_BLUE,
                         self.LV_DEMO_PRINTER_BG_FULL)

            arc = self.add_loader(lambda a: self.print_start_ready())
            arc.align(None, lv.ALIGN.CENTER, 0, -40)

            txt = lv.label(lv.scr_act(), None)
            txt.set_text("Printing, please wait...")
            self.theme.apply(txt, LV_DEMO_PRINTER_THEME_LABEL_WHITE)
            txt.align(arc, lv.ALIGN.OUT_BOTTOM_MID, 0, 60)

            self.anim_in(arc, delay)
            delay += self.LV_DEMO_PRINTER_ANIM_DELAY
            self.anim_in(txt, delay)

    def print_start_ready(self):
        self.anim_bg(0, LV_DEMO_PRINTER_GREEN, self.LV_DEMO_PRINTER_BG_FULL)
        self.anim_out_all(lv.scr_act(), 0)

        img = lv.img(lv.scr_act(), None)
        img.set_src(self.img_ready_dsc)
        img.align(None, lv.ALIGN.CENTER, 0, -40)

        delay = 200
        self.anim_in(img, delay)
        delay += self.LV_DEMO_PRINTER_ANIM_DELAY

        self.info_bottom_create("Printing finished", "CONTINUE",
                                self.back_to_home_event_cb, delay)

    def back_to_print_event_cb(self, obj, evt):
        if evt == lv.EVENT.CLICKED:
            self.anim_out_all(lv.scr_act(), 0)
            self.print_open(150)
Beispiel #31
0
def init_skin(
    project_name,
    project_version,
    skin_name,
    application_skin_dir,
    application_theme_dir=None,
):
    '''
    Initialize skin easily.

    @param project_name: Project name.
    @param project_version: Project version.
    @param skin_name: Default skin name.
    @param application_skin_dir: Application's skin directory in system level, user space skin directory at ~/.config/project_name/skin .
    @param application_skin_dir: Application's theme directory in system level, user space theme directory at ~/.config/project_name/theme, set as None if don't you just want use theme of deepin-ui.
    @return: Return application theme, return None if application_theme_dir is None.

    >>> from dtk.ui.init_skin import init_skin
    >>> from deepin_utils.file import get_parent_dir
    >>> import os
    >>>
    >>> app_theme = init_skin(
    >>>     "deepin-ui-demo",
    >>>     "1.0",
    >>>     "01",
    >>>     os.path.join(get_parent_dir(__file__), "skin"),
    >>>     os.path.join(get_parent_dir(__file__), "app_theme"),
    >>>     )

    Equal to below code:

    >>> from dtk.ui.skin_config import skin_config
    >>> from dtk.ui.theme import Theme, ui_theme
    >>> from deepin_utils.file import get_parent_dir
    >>> import os
    >>>
    >>> # Init skin config.
    >>> skin_config.init_skin(
    >>>     "01",
    >>>     os.path.join(get_parent_dir(__file__), "skin"),
    >>>     os.path.expanduser("~/.config/deepin-ui-demo/skin"),
    >>>     os.path.expanduser("~/.config/deepin-ui-demo/skin_config.ini"),
    >>>     "deepin-ui-demo",
    >>>     "1.0"
    >>>     )
    >>>
    >>> # Create application theme.
    >>> app_theme = Theme(
    >>>     os.path.join(get_parent_dir(__file__), "app_theme"),
    >>>     os.path.expanduser("~/.config/deepin-ui-demo/theme")
    >>>     )
    >>>
    >>> # Set theme.
    >>> skin_config.load_themes(ui_theme, app_theme)
    '''
    # Init skin config.
    skin_config.init_skin(
        skin_name,
        application_skin_dir,
        os.path.expanduser("~/.config/%s/skin" % (project_name)),
        os.path.expanduser("~/.config/%s/skin_config.ini" % (project_name)),
        project_name,
        project_version,
    )

    # Create application theme.
    if application_theme_dir != None:
        app_theme = Theme(
            application_theme_dir,
            os.path.expanduser("~/.config/%s/theme" % (project_name)))
    else:
        app_theme = None

    # Set theme.
    skin_config.load_themes(ui_theme, app_theme)

    return app_theme
Beispiel #32
0
    def __init__(self):
        self.LV_HOR_RES = lv.scr_act().get_disp().driver.hor_res
        self.LV_VER_RES = lv.scr_act().get_disp().driver.ver_res
        # Bg positions
        self.LV_DEMO_PRINTER_BG_NONE = -self.LV_VER_RES
        self.LV_DEMO_PRINTER_BG_FULL = 0
        self.LV_DEMO_PRINTER_BG_NORMAL = -2 * (self.LV_VER_RES // 3)
        self.LV_DEMO_PRINTER_BG_SMALL = -5 * (self.LV_VER_RES // 6)

        # Animations
        self.LV_DEMO_PRINTER_ANIM_Y = self.LV_VER_RES // 20
        self.LV_DEMO_PRINTER_ANIM_DELAY = 40
        self.LV_DEMO_PRINTER_ANIM_TIME = 150
        self.LV_DEMO_PRINTER_ANIM_TIME_BG = 300

        self.LV_DEMO_PRINTER_BG_NORMAL = (-2 * (self.LV_VER_RES // 3))

        self.log = logging.getLogger("DemoPrinter")
        self.log.setLevel(logging.ERROR)

        self.icon_wifi_data = None
        self.icon_wifi_dsc = None
        self.icon_tel_data = None
        self.icon_tel_dsc = None
        self.icon_eco_data = None
        self.icon_eco_dsc = None
        self.icon_pc_data = None
        self.icon_pc_dsc = None

        self.img_btn_bg_1_data = None
        self.img_btn_bg_1_dsc = None
        self.img_btn_bg_2_data = None
        self.img_btn_bg_2_dsc = None
        self.img_btn_bg_3_data = None
        self.img_btn_bg_3_dsc = None
        self.img_btn_bg_4_data = None
        self.img_btn_bg_4_dsc = None

        self.img_copy_data = None
        self.img_copy_dsc = None
        self.img_print_data = None
        self.img_print_dsc = None
        self.img_scan_data = None
        self.img_scan_dsc = None
        self.img_setup_data = None
        self.img_setup_dsc = None

        self.scan_img = None
        self.bg_top = None
        self.bg_bottom = None

        self.bg_color_prev = LV_DEMO_PRINTER_BLUE
        self.bg_color_act = LV_DEMO_PRINTER_BLUE
        self.bg_top = lv.obj(lv.scr_act(), None)
        self.bg_top.set_size(self.LV_HOR_RES, self.LV_VER_RES)

        # read all the images fromm the raw image files

        (self.icon_wifi_data,
         self.icon_wifi_dsc) = self.get_icon("icon_wifi_48x34", 48, 34)
        (self.icon_tel_data,
         self.icon_tel_dsc) = self.get_icon("icon_tel_35x35", 35, 35)
        (self.icon_eco_data,
         self.icon_eco_dsc) = self.get_icon("icon_eco_38x34", 38, 34)
        (self.icon_pc_data,
         self.icon_pc_dsc) = self.get_icon("icon_pc_41x33", 41, 33)

        (self.icon_bright_data,
         self.icon_bright_dsc) = self.get_icon("icon_bright_29x29", 29, 29)
        (self.icon_hue_data,
         self.icon_hue_dsc) = self.get_icon("icon_hue_23x23", 23, 23)

        (self.img_btn_bg_1_data,
         self.img_btn_bg_1_dsc) = self.get_icon("img_btn_bg_1_174x215", 174,
                                                215)
        (self.img_btn_bg_2_data,
         self.img_btn_bg_2_dsc) = self.get_icon("img_btn_bg_2_174x215", 174,
                                                215)
        (self.img_btn_bg_3_data,
         self.img_btn_bg_3_dsc) = self.get_icon("img_btn_bg_3_174x215", 174,
                                                215)
        (self.img_btn_bg_4_data,
         self.img_btn_bg_4_dsc) = self.get_icon("img_btn_bg_4_174x215", 174,
                                                215)

        (self.img_copy_data,
         self.img_copy_dsc) = self.get_icon("img_copy_51x60", 51, 60)
        (self.img_print_data,
         self.img_print_dsc) = self.get_icon("img_print_65x64", 65, 64)
        (self.img_scan_data,
         self.img_scan_dsc) = self.get_icon("img_scan_51x61", 51, 61)
        (self.img_setup_data,
         self.img_setup_dsc) = self.get_icon("img_setup_63x64", 63, 64)

        (self.img_usb_data,
         self.img_usb_dsc) = self.get_icon("img_usb_62x61", 62, 61)
        (self.img_internet_data,
         self.img_internet_dsc) = self.get_icon("img_internet_65x64", 65, 64)
        (self.img_mobile_data,
         self.img_mobile_dsc) = self.get_icon("img_mobile_50x60", 50, 60)
        (self.img_wave_data,
         self.img_wave_dsc) = self.get_icon("img_wave_27x47", 27, 47)
        (self.img_phone_data,
         self.img_phone_dsc) = self.get_icon("img_phone_77x99", 77, 99)

        (self.img_ready,
         self.img_ready_dsc) = self.get_icon("img_ready_158x158", 158, 158)

        (self.img_printer2_data,
         self.img_printer2_dsc) = self.get_icon("img_printer2_107x104", 107,
                                                104)
        (self.img_no_internet_data,
         self.img_no_internet_dsc) = self.get_icon("img_no_internet_42x42", 42,
                                                   42)
        (self.img_cloud_data,
         self.img_cloud_dsc) = self.get_icon("img_cloud_93x59", 93, 59)

        (self.scan_example_data,
         self.scan_example_dsc) = self.get_icon("scan_example_522x340", 522,
                                                340)
        self.theme = Theme()

        self.home_open(0)
Beispiel #33
0
    def _write_theme_file(self):
        # Write the theme xml file.
        theme = Theme()

        theme._set_xml_writer(self._filename('xl/theme/theme1.xml'))
        theme._assemble_xml_file()
Beispiel #34
0
class MyElement (QObject):

	hasLockChanged = pyqtSignal()
	hasLoginChanged = pyqtSignal()
	hasErrorChanged = pyqtSignal()
	hasRegisterChanged = pyqtSignal()
	varChanged = pyqtSignal()
	themeChanged = pyqtSignal()
	overlayChanged = pyqtSignal()
	
	def __init__(self, parent=None):
		super(MyElement, self).__init__()
		self.setObjectName('mainObject')
		self._users = []
		self._index = 0
		self._myTheme = Theme()
		self._myColor = self._myTheme.getTheme() 
		self.mainProc = QProcess()
		self.secondProc = QProcess()
		self.mainProc.finished.connect(self.finishProc)
		self.mainProc.started.connect(self.startProc)
		self.secondProc.finished.connect(self.secondFinishProc)
		self.secondProc.started.connect(self.startProc)
		self.auth = Auth()
		self._isiPesan = ""
		self._judulPesan = "Error"
		self._overlay = ""
		self._isLock = False
		self._hasRegister = False
		self._hasLogin = False
		self._hasError = False
		self._userListData = UserItemModel()
		self._userListData.addRootElement()
		self.addNewUser()
	
	@pyqtProperty(bool, notify=hasLockChanged)
	def isLock(self):
		return os.path.isfile("/var/ubezee/LOCKED")
		
	def finishProc(self, exitCode):
		if not exitCode:
			self.setError(True, "Proses Berhasil", "Proses buka/tutup kunci telah berhasil, silakan hidupkan ulang komputer anda untuk mengimplementasikan perubahan.")
			self._overlay = ""
			self.hasLockChanged.emit()
		else:
			self.setError(True, "Proses Gagal", "Terjadi kesalahan saat akan melakukan proses buka/tutup kunci, silakan coba lagi.")

	def secondFinishProc(self, exitCode):
		if not exitCode:
			self.setError(True, "Proses Berhasil", "Proses buka/tutup kunci pada pengguna telah berhasil, silakan hidupkan ulang komputer anda untuk mengimplementasikan perubahan.")
			self._overlay = ""
			h = self._userListData.index(self._index, 0)
			if self._userListData.itemFromIndex(h).data(5):
				self._userListData.itemFromIndex(h).setData(False, 5)
			else:
				self._userListData.itemFromIndex(h).setData(True, 5)
		else:
			self.setError(True, "Proses Gagal", "Terjadi kesalahan saat akan melakukan proses buka/tutup kunci, silakan coba lagi.")

		
	def startProc(self):
		self.setInfo("Harap Tunggu", "Proses buka/tutup pengunci sistem sedang berlangsung, mohon tunggu sebentar...")
		self.setOverlay("loading")
		
	@pyqtSlot(bool)
	def changeLock(self, todo):
		if todo:
			self.mainProc.start("bash locker.sh -l sistem")
		else:
			self.mainProc.start("bash locker.sh -u sistem")
			
	@pyqtSlot(int, str, bool)
	def lockUser(self, index, nama, locked):
		self._index = index
		if not locked:
			self.secondProc.start("bash locker.sh -l %s" % nama)
		else:
			self.secondProc.start("bash locker.sh -u %s" % nama)
	
	@pyqtProperty(bool, notify=hasLoginChanged)
	def hasLogin(self):
		return self._hasLogin
	
	@pyqtProperty(str, notify=themeChanged)
	def myColor1(self):
		return self._myColor[0]
	
	@pyqtProperty(str, notify=themeChanged)
	def myColor2(self):
		return self._myColor[1]
	
	@pyqtSlot(str)
	def setTheme(self, theme):
		self._myTheme.setTheme(theme)
		self.themeChanged.emit()
	
	@pyqtProperty(str, notify=varChanged)
	def isiPesan(self):
		return self._isiPesan
	
	@pyqtSlot(str, str)
	def setInfo(self, judul,isi):
		if self._isiPesan != isi:
			self._isiPesan = isi
		if self._judulPesan != judul:
			self._judulPesan = judul
		self.varChanged.emit()
	
	@pyqtProperty(str, notify=varChanged)
	def judulPesan(self):
		return self._judulPesan
	
	@pyqtProperty(str, notify=varChanged)
	def getPassword(self):
		return self.auth.get_password()
	
	@pyqtProperty(bool, notify=hasRegisterChanged)
	def hasRegister(self):
		return self.auth.check()
	
	def setRegister(self, register):
		if self._hasRegister != register:
			self._hasRegister = register			
			self.hasRegisterChanged.emit()
	
	@pyqtSlot(str, str)
	def doRegister(self, hint, userPass):
		if self.auth.set_password(userPass, hint):
			self.setError(True, "Proses Gagal", "Terjadi kesalahan pada proses pembuatan kata kunci baru.")
		else:
			self.setError(True, "Perubahan Berhasil", "Kata kunci anda berhasil dirubah dan disimpan.")
			self.setRegister(True)
	
	def setLogin(self, login):
		if self._hasLogin != login:
			self._hasLogin = login			
			self.hasLoginChanged.emit()
	
	@pyqtProperty(bool, notify=hasErrorChanged)
	def hasError(self):
		return self._hasError
	
	@pyqtProperty(str, notify=overlayChanged)
	def overlay(self):
		return self._overlay
	
	@pyqtSlot(str)
	def setOverlay(self, overlay):
		self._overlay = overlay			
		self.overlayChanged.emit()
		print(self._overlay)
	
	@pyqtSlot(bool, str, str)
	def setError(self, error, judul, isi):
		if self._hasError != error:
			self.setInfo(judul, isi)
			self._hasError = error
			self.hasErrorChanged.emit()
		
	@pyqtProperty(QStandardItemModel, constant=True)
	def userListData(self):
		return self._userListData	
			
	@pyqtSlot(str)
	def check_pass(self, password):
		if self.auth.checkAuth(str(password)):
			self.setLogin(True)
			self.setOverlay("")
		else:
			self.setError(True, "Gagal Masuk", "kata kunci yang anda masukkan salah, silakan coba lagi.")
			
	def addNewUser(self):
		self.getUsers()
		for i in self._users:
			user = MyUser(i[0],i[4],i[5])
			self._userListData.addUserItem(user.getName(), 
					user.getAvatar(),
					user.getHome(),
					user.getRealName(),
					user.getLock())
		
	def getUsers(self):
		for users in pwd.getpwall():
			if users[2] >= 1000:
				self._users.append(users)
Beispiel #35
0
# -*- coding: UTF-8 -*-

import OpenGL
from OpenGL import GLU
from OpenGL import GL
from OpenGL.GL import *
from OpenGL.GLU import *
from MenuCAIDViewer import MenuCAIDViewer
import numpy as np
from numpy import sin, pi, cos

from theme import theme as Theme

theme = Theme()

ALPHA = theme.alpha
BETA = theme.beta


class GLEvaluator():
    def __init__(self, nrb):
        self.nrb = nrb
        self.glID = gluNewNurbsRenderer()

    def __del__(self):
        gluDeleteNurbsRenderer(self.glID)

    def draw(self):
        pass

Beispiel #36
0
    def createFontPanel(self):
        fcp = wx.Panel(self.book)

        font = wx.Font(prefs.get('font'))

        fgcolour = prefs.get('fgcolour')
        bgcolour = prefs.get('bgcolour')

        # output sample/controls
        fcp.sample = ExpandoTextCtrl(fcp,
                                     style=wx.TE_READONLY | wx.TE_RICH
                                     | wx.TE_MULTILINE,
                                     size=wx.Size(400, -1))
        fcp.font_ctrl = wx.FontPickerCtrl(fcp,
                                          style=wx.FNTP_FONTDESC_AS_LABEL
                                          | wx.FNTP_USEFONT_FOR_LABEL,
                                          font=font)

        fcp.theme_picker = wx.Choice(fcp, choices=Theme.all_theme_names())

        fcp.ansi_checkbox = wx.CheckBox(fcp, -1, 'Use ANSI colors')
        fcp.ansi_blink_checkbox = wx.CheckBox(fcp, -1, 'Honor ANSI blink')
        # TODO - get and set these two at display time not create time
        fcp.theme = prefs.get('theme')
        fcp.theme_picker.SetSelection(fcp.theme_picker.FindString(fcp.theme))

        if prefs.get('use_ansi'):
            fcp.ansi_checkbox.SetValue(True)
            fcp.theme_picker.Enable()
        else:
            fcp.ansi_checkbox.SetValue(False)
            fcp.theme_picker.Disable()

        ansi_sizer = wx.BoxSizer(wx.HORIZONTAL)
        ansi_sizer.Add(fcp.ansi_checkbox, 0,
                       wx.ALL | wx.EXPAND | wx.ALIGN_CENTER)
        ansi_sizer.Add(fcp.ansi_blink_checkbox, 0,
                       wx.ALL | wx.EXPAND | wx.ALIGN_CENTER)
        ansi_sizer.Add(fcp.theme_picker, 0,
                       wx.ALL | wx.EXPAND | wx.ALIGN_CENTER)

        panel_sizer = wx.BoxSizer(wx.VERTICAL)
        panel_sizer.Add(fcp.sample, 0, wx.RIGHT | wx.LEFT | wx.EXPAND | wx.TOP,
                        10)
        panel_sizer.AddSpacer(10)
        panel_sizer.Add(fcp.font_ctrl, 0, wx.EXPAND, 0)
        panel_sizer.AddSpacer(10)
        panel_sizer.Add(ansi_sizer, 0, wx.RIGHT | wx.LEFT | wx.EXPAND, 10)

        self.Bind(wx.EVT_FONTPICKER_CHANGED, self.update_sample_text,
                  fcp.font_ctrl)
        self.Bind(wx.EVT_CHOICE, self.update_sample_text, fcp.theme_picker)
        self.Bind(wx.EVT_CHECKBOX, self.update_sample_text, fcp.ansi_checkbox)

        self.Bind(EVT_ETC_LAYOUT_NEEDED, self.resize_everything, fcp.sample)

        fcp.SetSizer(panel_sizer)

        fcp.Layout()

        return fcp
Beispiel #37
0
  def parse(self, config, source):
    """Parse presentation from source stream.

    Parameters
    ----------
    config : MatisseConfig
      MaTiSSe configuration
    source: str
    """
    complete_source = self.parser.includes(source=source)
    self.__get_metadata(source=complete_source)
    self.__get_theme(source=complete_source)
    new_theme = Theme()
    new_theme.set_from(other=self.theme)
    tokens = self.parser.tokenize(source=complete_source)
    self.__check_bad_sectioning(tokens=tokens)
    chapters_number = 0
    sections_number = 0
    subsections_number = 0
    slides_number = 0
    titlepage_inserted = False
    for chap in tokens['chapters']:
      chapters_number += 1
      slide_local_numbers = [0, 0, 0]
      if chap['match'].group('expr'):
        chapter = Chapter(number=chapters_number, title=chap['match'].group('expr'))
      else:
        chapter = Chapter(number=chapters_number, title='')
      for sec in tokens['sections']:
        if sec['start'] >= chap['start'] and sec['start'] <= chap['end_next']:
          sections_number += 1
          slide_local_numbers[1] = 0
          slide_local_numbers[2] = 0
          section = Section(number=sections_number, title=sec['match'].group('expr'))
          for subsec in tokens['subsections']:
            if subsec['start'] >= sec['start'] and subsec['start'] <= sec['end_next']:
              subsections_number += 1
              slide_local_numbers[2] = 0
              subsection = Subsection(number=subsections_number, title=subsec['match'].group('expr'))
              for sld in tokens['slides']:
                if '$titlepage' in sld['match'].group().lower() and not titlepage_inserted:
                  slide = Slide(number=0,
                                title='titlepage',
                                contents=complete_source[sld['end']:sld['end_next']])
                  slide.get_overtheme(parser=self.parser)
                  if slide.overtheme.copy_from_theme is not None and slide.overtheme.copy_from_theme:
                    slide.overtheme.copy_from(other=self.theme)
                  self.position.update_position(presentation_theme=self.theme, overtheme=slide.overtheme)
                  slide.set_position(position=self.position.position)
                  subsection.add_slide(slide=slide)
                  titlepage_inserted = True
                else:
                  if sld['start'] >= subsec['start'] and sld['start'] <= subsec['end_next']:
                    slide_local_numbers[0] += 1
                    slide_local_numbers[1] += 1
                    slide_local_numbers[2] += 1
                    if slide_local_numbers[0] == 1 and config.toc_at_chap_beginning is not None:
                      slides_number += 1
                      self.position.update_position(presentation_theme=self.theme)
                      subsection.add_slide(slide=Slide(number=slides_number,
                                                       position=self.position.position,
                                                       title='Table of Contents',
                                                       contents='$toc[depth:' + str(config.toc_at_chap_beginning) + ']'))
                    if slide_local_numbers[1] == 1 and config.toc_at_sec_beginning is not None:
                      slides_number += 1
                      self.position.update_position(presentation_theme=self.theme)
                      subsection.add_slide(slide=Slide(number=slides_number,
                                                       position=self.position.position,
                                                       title='Table of Contents',
                                                       contents='$toc[depth:' + str(config.toc_at_sec_beginning) + ']'))
                    if slide_local_numbers[2] == 1 and config.toc_at_subsec_beginning is not None:
                      slides_number += 1
                      self.position.update_position(presentation_theme=self.theme)
                      subsection.add_slide(slide=Slide(number=slides_number,
                                                       position=self.position.position,
                                                       title='Table of Contents',
                                                       contents='$toc[depth:' + str(config.toc_at_subsec_beginning) + ']'))
                    slides_number += 1
                    slide = Slide(number=slides_number,
                                  title=sld['match'].group('expr'),
                                  contents=complete_source[sld['end']:sld['end_next']])
                    slide.get_overtheme(parser=self.parser)
                    if slide.overtheme.copy_from_theme is not None and slide.overtheme.copy_from_theme:
                      slide.overtheme.copy_from(other=self.theme)
                    self.position.update_position(presentation_theme=self.theme, overtheme=slide.overtheme)
                    slide.set_position(position=self.position.position)
                    subsection.add_slide(slide=slide)
              section.add_subsection(subsection=subsection)
          chapter.add_section(section=section)
      self.__add_chapter(chapter=chapter)
      self.metadata['total_slides_number'].update_value(value=str(Subsection.slides_number))
Beispiel #38
0
class OutputPane(BasePane):
    def __init__(self, parent, connection):
        BasePane.__init__(
            self, parent, connection, style=wx.TE_AUTO_URL | wx.TE_READONLY | wx.TE_NOHIDESEL | wx.TE_MULTILINE
        )

        # state toggles for ANSI processing
        self.intensity = ""
        self.inverse = False

        self.theme = Theme()

        # TODO - this probably should be a preference, but for now, this is the
        # least-bad default behavior.
        self.Bind(wx.EVT_SIZE, self.on_size)
        self.Bind(wx.EVT_SET_FOCUS, self.focus_input)
        self.Bind(wx.EVT_TEXT_URL, self.process_url_click)
        self.Bind(wx.EVT_MIDDLE_DOWN, self.connection.input_pane.paste_from_selection)
        self.Bind(rtc.EVT_RICHTEXT_SELECTION_CHANGED, self.copy_from_selection)
        self.Bind(EVT_ROW_COL_CHANGED, self.on_row_col_changed)

    # EVENT HANDLERS #######################
    def on_row_col_changed(self, evt):
        pass
        # TODO - "if preferences dictate, send @linelength to self.connection"

    # This updates the widget's internal notion of "how big" it is in characters
    # it throws an event if the size *in chars* changes, nothing if the change in size was < 1 char
    def on_size(self, evt):

        font_width, font_height = self.font_size()
        self_width, self_height = self.GetSizeTuple()

        new_cols = math.floor(self_width / font_width) - 2  # "-2" to allow for margins
        new_rows = math.floor(self_height / font_height)

        if (new_cols != self.cols) or (new_rows != self.rows):
            self.cols = new_cols
            self.rows = new_rows
            rc_evt = RowColChangeEvent()
            wx.PostEvent(self, rc_evt)

        wx.CallAfter(self.ScrollIfAppropriate)
        evt.Skip()

    def copy_from_selection(self, evt):
        uxcp = prefs.get("use_x_copy_paste") == "True"
        if uxcp and platform == "linux":
            wx.TheClipboard.UsePrimarySelection(True)
        self.Copy()
        if uxcp and platform == "linux":
            wx.TheClipboard.UsePrimarySelection(False)

    def process_url_click(self, evt):
        url = evt.GetString()
        wx.BeginBusyCursor()
        if not re.match(r"^https?://", url):
            url = "http://" + url
        webbrowser.open(url)
        wx.EndBusyCursor()

    def focus_input(self, evt):
        self.connection.input_pane.SetFocus()

    ######################################
    def WriteText(self, rest):
        super(OutputPane, self).WriteText(rest)
        self.ScrollIfAppropriate()

    def is_at_bottom(self):
        return True

    def ScrollIfAppropriate(self):
        if self.is_at_bottom() or prefs.get("scroll_on_output") == "True":
            self.ShowPosition(self.GetLastPosition())
            self.Refresh()

    def Thaw(self):
        super(OutputPane, self).Thaw()
        self.ScrollIfAppropriate()

    def display(self, text):
        self.SetInsertionPointEnd()
        text = text.decode("latin-1")  # TODO - is this the right thing and/or place for this?
        # self.Freeze() # causing delay on last line - TODO: investigate
        for line in text.split("\n"):
            line = line + "\n"
            if prefs.get("use_mcp") == "True":
                line = self.connection.mcp.output_filter(line)
                if not line:
                    continue  # output_filter returns falsie if it handled it.

            # if (True or prefs.get('render_emoji') == 'True'):
            # TODO - preference?  "if (we detect an emoji)?"
            # line = emoji.emojize(line, use_aliases = True)

            if prefs.get("use_ansi") == "True":
                # Dear lord this is sorta ugly

                # snip and ring bells
                # TODO -- "if beep is enabled in the prefs"
                line, count = re.subn("\007", "", line)
                for b in range(0, count):
                    print("DEBUG: found an ANSI beep")
                    wx.Bell()

                # chop the line into text, ansi, text, ansi....
                bits = re.split("\033\[(\d+(?:;\d+)*)m", line)

                for idx, bit in enumerate(bits):
                    if bit == "":
                        continue

                    # if it's ansi...
                    if idx % 2:
                        # pick apart the ANSI stuff.
                        codes = [int(c) for c in bit.split(";")]
                        while codes:
                            command, payload = ansi_codes[codes.pop(0)]
                            if command == "control":
                                if payload == "normal":
                                    self.EndAllStyles()
                                    self.intensity = ""
                                    self.inverse = False
                                    self.fg_colour = prefs.get("fgcolour")
                                    self.bg_colour = prefs.get("bgcolour")
                                    self.set_current_colours()
                                elif payload == "bright":
                                    self.intensity = "bright"
                                    self.set_current_colours()
                                elif payload == "dim":
                                    self.intensity = "dim"
                                    self.set_current_colours()
                                elif payload == "italic":
                                    self.BeginItalic()
                                elif payload == "underline":
                                    self.BeginUnderline()
                                elif payload == "blink":
                                    print('Got an ANSI "blink"')
                                    # TODO - create timer
                                    # apply style name
                                    # periodically switch foreground color to background
                                elif payload == "inverse":
                                    self.inverse = True
                                    self.set_current_colours()
                                elif payload == "conceal":
                                    print('Got an ANSI "conceal"')
                                elif payload == "strike":
                                    font = self.GetFont()
                                    font.SetStrikethrough(True)
                                    self.BeginFont(font)
                                elif payload == "normal_weight":
                                    self.intensity = ""
                                    self.set_current_colours()
                                elif payload == "no_italic":
                                    self.EndItalic()
                                elif payload == "no_underline":
                                    self.EndUnderline()
                                elif payload == "no_blink":
                                    print('Got an ANSI "no_blink"')
                                    # TODO - remove blink-code-handles style
                                elif payload == "no_conceal":
                                    print('Got an ANSI "no_conceal"')
                                elif payload == "no_strike":
                                    font = self.GetFont()
                                    font.SetStrikethrough(False)
                                    self.BeginFont(font)

                                elif payload == "framed":
                                    print('Got an ANSI "framed"')
                                elif payload == "encircled":
                                    print('Got an ANSI "encircled"')
                                elif payload == "overline":
                                    print('Got an ANSI "overline"')

                                elif payload == "no_framed_encircled":
                                    print('Got an ANSI "no_framed_encircled"')
                                elif payload == "no_overline":
                                    print('Got an ANSI "no_overline"')

                            elif command == "foreground" or command == "background":
                                if payload == "extended":
                                    subtype = codes.pop(0)
                                    # 24-bit color
                                    if subtype == 2:
                                        colour = self.theme.rgb_to_hex((codes.pop(0), codes.pop(0), codes.pop(0)))
                                    # 256-color
                                    elif subtype == 5:
                                        colour = self.theme.index256_to_hex(codes.pop(0))
                                    else:
                                        print("Got an unknown fg/bg ANSI subtype: " + str(subtype))
                                else:
                                    colour = payload

                                if command == "foreground":
                                    self.fg_colour = colour
                                else:
                                    self.bg_colour = colour
                                self.set_current_colours()
                            else:
                                print("unknown ANSI command:", command)
                    else:
                        # is a text-only chunk, check for URLs
                        if prefs.get("highlight_urls") == "True":
                            matches = re.split(utility.URL_REGEX, bit)
                            for chunk in matches:
                                if chunk is None:
                                    continue
                                if re.match(utility.URL_REGEX, chunk):
                                    self.BeginURL(chunk)
                                    self.BeginUnderline()

                                    current_intensity = self.intensity
                                    self.intensity = "normal"
                                    self.BeginTextColour(self.lookup_colour("blue"))
                                    self.intensity = current_intensity

                                    self.WriteText(chunk)

                                    self.EndTextColour()
                                    self.EndUnderline()
                                    self.EndURL()
                                else:
                                    self.WriteText(chunk)
                        else:
                            self.WriteText(bit)
        # self.Thaw() # causing delay on last line - TODO investigate.

    def foreground_colour(self):
        return self.theme.Colour(self.fg_colour, self.intensity)

    def background_colour(self):
        return self.theme.Colour(self.bg_colour)

    def lookup_colour(self, color):
        return self.theme.Colour(color, self.intensity)

    def set_current_colours(self):
        current = rtc.RichTextAttr()
        if self.inverse:
            current.SetTextColour(self.background_colour())
            current.SetBackgroundColour(self.foreground_colour())
        else:
            current.SetTextColour(self.foreground_colour())
            current.SetBackgroundColour(self.background_colour())

        self.BeginStyle(current)

    def ansi_test(self):
        self.Freeze()
        self.display("")
        self.display("--- ANSI TEST BEGIN ---")
        self.display("System Colors:")

        fg_cube = bg_cube = ""

        for c in range(0, 7):
            fg_cube += "\033[3" + str(c) + "m*\033[0m"
            bg_cube += "\033[4" + str(c) + "m \033[0m"
        self.display(fg_cube + "    " + bg_cube)
        fg_cube = bg_cube = ""

        self.display("")
        self.display("Color cube, 6x6x6")
        for g in range(0, 6):
            for b in range(0, 6):
                for r in range(0, 6):
                    c = ((r * 36) + (g * 6) + b) + 16
                    fg_cube += "\033[38;5;" + str(c) + "m*\033[0m"
                    bg_cube += "\033[48;5;" + str(c) + "m \033[0m"
            self.display(fg_cube + "    " + bg_cube)
            fg_cube = bg_cube = ""

        self.display("")
        self.display("Greyscale ramp:")
        for c in range(232, 255):
            fg_cube += "\033[38;5;" + str(c) + "m*\033[0m"
            bg_cube += "\033[48;5;" + str(c) + "m \033[0m"
        self.display(fg_cube + "    " + bg_cube)
        fg_cube = bg_cube = ""

        self.display("")
        self.display("Some random 24-bit color samples:")
        from random import randint

        line = ""
        for i in range(0, 6):
            for j in range(0, 6):
                r = randint(0, 255)
                g = randint(0, 255)
                b = randint(0, 255)
                fg_bg = 48 if (j % 2) else 38

                line += "\033[" + ("%d;2;%d;%d;%dm (%3d,%3d,%3d) " % (fg_bg, r, g, b, r, g, b)) + "\033[0m"
            self.display(line)
            line = ""
        self.display("")
        self.display("--- ANSI TEST END ---")
        self.display("")
        self.Thaw()
Beispiel #39
0
Handles communication between Electron/Flask and the terminal code.
"""
from flask import Flask, render_template, request, send_from_directory
from term import Terminal
from theme import Theme
import os

# Global variables
THEMES = list()
TERMINAL = Terminal(name='main')

# Load themes
THEMES_DIR = os.getcwd() + '/themes/'
for root in os.walk(THEMES_DIR):
    for folder in root[1]:
        THEMES.append(Theme(path=THEMES_DIR + folder))

# Initialize flask app
if len(THEMES) > 0:
    APP = Flask(__name__, static_folder=THEMES_DIR + THEMES[0].name)
else:
    APP = Flask(__name__)
APP.debug = False


@APP.route('/')
def peyl_page():
    """Provides the main.html template"""
    return render_template('main.html')

Beispiel #40
0
    def update_sample_text(self, evt):
        fp = self.fonts_page

        theme = Theme.fetch(fp.theme_picker.GetStringSelection())

        fgcolour = theme.get('foreground')
        bgcolour = theme.get('background')
        font = fp.font_ctrl.GetSelectedFont()

        textattr = wx.TextAttr(fgcolour, bgcolour, font)

        fp.sample.SetBackgroundColour(bgcolour)
        fp.sample.SetValue("""
Emerson says, "This is what your window will look like."
Emerson waves around a brightly-colored banner.

It's super effective!

01234567 89ABCDEF
""")
        fp.sample.SetStyle(0, fp.sample.GetLastPosition(), textattr)

        # Mock up ANSI if ANSI pref is on
        # TODO - maybe actually just shove ANSI-code-ful stuff through the actual output_panel ANSIfier?
        if fp.ansi_checkbox.GetValue():
            textattr.SetTextColour(theme.Colour('blue'))
            fp.sample.SetStyle(1, 8, textattr)

            fp.sample.SetStyle(58, 66, textattr)
            textattr.SetTextColour(theme.Colour('red'))
            fp.sample.SetStyle(81, 89, textattr)
            textattr.SetTextColour(theme.Colour('yellow'))
            fp.sample.SetStyle(90, 97, textattr)
            textattr.SetTextColour(theme.Colour('green'))
            fp.sample.SetStyle(98, 104, textattr)
            fp.theme_picker.Enable()

            textattr.SetTextColour(theme.Colour('white'))
            textattr.SetFontWeight(wx.FONTWEIGHT_BOLD)
            fp.sample.SetStyle(107, 128, textattr)
            textattr.SetTextColour(theme.Colour('red', 'bright'))
            fp.sample.SetStyle(112, 117, textattr)

            textattr.SetFontWeight(wx.FONTWEIGHT_NORMAL)
            textattr.SetTextColour(theme.Colour('black'))
            fp.sample.SetStyle(130, 131, textattr)
            textattr.SetTextColour(theme.Colour('red'))
            fp.sample.SetStyle(131, 132, textattr)
            textattr.SetTextColour(theme.Colour('green'))
            fp.sample.SetStyle(132, 133, textattr)
            textattr.SetTextColour(theme.Colour('yellow'))
            fp.sample.SetStyle(133, 134, textattr)
            textattr.SetTextColour(theme.Colour('blue'))
            fp.sample.SetStyle(134, 135, textattr)
            textattr.SetTextColour(theme.Colour('magenta'))
            fp.sample.SetStyle(135, 136, textattr)
            textattr.SetTextColour(theme.Colour('cyan'))
            fp.sample.SetStyle(136, 137, textattr)
            textattr.SetTextColour(theme.Colour('white'))
            fp.sample.SetStyle(137, 138, textattr)

            textattr.SetTextColour(fgcolour)
            textattr.SetBackgroundColour(theme.Colour('black'))
            fp.sample.SetStyle(139, 140, textattr)
            textattr.SetBackgroundColour(theme.Colour('red'))
            fp.sample.SetStyle(140, 141, textattr)
            textattr.SetBackgroundColour(theme.Colour('green'))
            fp.sample.SetStyle(141, 142, textattr)
            textattr.SetBackgroundColour(theme.Colour('yellow'))
            fp.sample.SetStyle(142, 143, textattr)
            textattr.SetBackgroundColour(theme.Colour('blue'))
            fp.sample.SetStyle(143, 144, textattr)
            textattr.SetBackgroundColour(theme.Colour('magenta'))
            fp.sample.SetStyle(144, 145, textattr)
            textattr.SetBackgroundColour(theme.Colour('cyan'))
            fp.sample.SetStyle(145, 146, textattr)
            textattr.SetBackgroundColour(theme.Colour('white'))
            fp.sample.SetStyle(146, 147, textattr)
        else:
            fp.theme_picker.Disable()

        if evt: evt.Skip()
Beispiel #41
0
 def reset(cls):
     """Reset to default state."""
     cls.chapters_number = 0
     Theme.reset()
     Chapter.reset()
Beispiel #42
0
class MainWindow(object):
    def __init__(self, liststore):
        self.liststore = liststore

        self.gui = gui = Gtk.Builder()
        gui.add_from_file(SHARED_DATA_FILE('gfeedline.glade'))

        self.window = window = gui.get_object('main_window')
        self.column = MultiColumnDict(gui)  # multi-columns for Notebooks
        self.theme = Theme()
        self.font = FontSet()
        self.notification = StatusNotification(liststore)

        dnd_list = [
            Gtk.TargetEntry.new("text/uri-list", 0, 1),
            Gtk.TargetEntry.new("text/x-moz-url", 0, 4),
        ]
        window.drag_dest_set(Gtk.DestDefaults.ALL, dnd_list,
                             Gdk.DragAction.COPY)

        target = Gtk.TargetList.new([])
        target.add(Gdk.Atom.intern("text/x-moz-url", False), 0, 4)
        target.add(Gdk.Atom.intern("text/uri-list", False), 0, 1)

        window.drag_dest_set_target_list(target)
        window.connect("drag-data-received", self.on_drag_data_received)

        SETTINGS.connect("changed::window-sticky",
                         self.on_settings_sticky_change)
        self.on_settings_sticky_change(SETTINGS, 'window-sticky')

        SETTINGS_VIEW.connect("changed::theme", self.on_settings_theme_change)
        self.on_settings_theme_change(SETTINGS_VIEW, 'theme')

        is_multi_column = SETTINGS_VIEW.get_boolean('multi-column')
        menuitem_multicolumn = gui.get_object('menuitem_multicolumn')
        menuitem_multicolumn.set_active(is_multi_column)

        menuitem_update = MenuItemUpdate(gui, liststore)

        x, y, w, h = self._get_geometry_from_settings()
        #        window.show() # for wrong position when auto-start

        if x >= 0 and y >= 0:
            window.move(x, y)

        window.resize(w, h)
        window.show()

        gui.connect_signals(self)

    def on_drag_data_received(self, widget, context, x, y, selection, info,
                              time):
        text, image_file = DnDSelection.parse(info, selection, True)

        if text or image_file:
            updatewindow = UpdateWindow(self)

            if text:
                updatewindow.text_buffer.set_text(text)
            else:
                updatewindow.set_upload_media(image_file)

    def get_notebook(self, group_name):
        if not SETTINGS_VIEW.get_boolean('multi-column'):
            group_name = 'dummy for single column'

        if group_name in self.column:
            notebook = self.column.get(group_name)
        else:
            notebook = FeedNotebook(self.column, group_name, self.liststore)
            self.column.add(group_name, notebook)

        return notebook

    def toggle_multicolumn_mode(self):
        for row in self.liststore:
            notebook = self.get_notebook(row[Column.GROUP])
            view = row[Column.API].view
            view.force_remove()
            view.append(notebook, -1)

        reactor.callLater(0.1, self._jump_all_tabs_to_bottom,
                          self.theme.is_ascending())

    def _jump_all_tabs_to_bottom(self, is_bottom=True):
        for notebook in self.column.values():
            notebook.jump_all_tabs_to_bottom(is_bottom)

    def change_font(self, font=None, size=None):
        for notebook in self.column.values():
            notebook.change_font(font, size)

    def delete_status(self, status_id):
        js = 'hideStatus(\"%s\")' % status_id

        for notebook in self.column.values():
            notebook.exec_js_all_views(js)

    def _get_geometry_from_settings(self):
        x = SETTINGS_GEOMETRY.get_int('window-x')
        y = SETTINGS_GEOMETRY.get_int('window-y')
        w = SETTINGS_GEOMETRY.get_int('window-width')
        h = SETTINGS_GEOMETRY.get_int('window-height')
        return x, y, w, h

    def on_window_leave_notify_event(self, widget, event):
        ox, oy, ow, oh = self._get_geometry_from_settings()

        x, y = widget.get_position()
        w, h = widget.get_size()

        if x != ox or y != oy:
            SETTINGS_GEOMETRY.set_int('window-x', x)
            SETTINGS_GEOMETRY.set_int('window-y', y)

        if w != ow or h != oh:
            SETTINGS_GEOMETRY.set_int('window-width', w)
            SETTINGS_GEOMETRY.set_int('window-height', h)

    def on_stop(self, *args):
        for row in self.liststore:
            row[Column.OPTIONS]['last_id'] = row[Column.API].last_id
        self.liststore.save_settings()

        reactor.stop()
        #self.window.destroy()

    def on_menuitem_quit_activate(self, menuitem):
        self.on_stop()

    def on_menuitem_update_activate(self, menuitem):
        UpdateWindow(self.liststore)

    def on_menuitem_prefs_activate(self, menuitem):
        Preferences(self)

    def on_menuitem_multicolumn_toggled(self, menuitem):
        is_multi_column = menuitem.get_active()
        SETTINGS_VIEW.set_boolean('multi-column', is_multi_column)
        self.toggle_multicolumn_mode()

    def on_menuitem_about_activate(self, menuitem):
        AboutDialog(self.window)

    def on_menuitem_help_activate(self, menuitem):
        Gtk.show_uri(None, 'http://code.google.com/p/gfeedline/wiki/Tips',
                     Gdk.CURRENT_TIME)

    def on_menuitem_top_activate(self, menuitem=None):
        self._jump_all_tabs_to_bottom(False)

    def on_menuitem_bottom_activate(self, menuitem=None):
        self._jump_all_tabs_to_bottom()

    def on_menuitem_clear_activate(self, menuitem=None):
        for notebook in self.column.values():
            notebook.clear_all_tabs()

    def on_menuitem_fullscreen_activate(self, menuitem):
        if menuitem.get_active():
            self.window.fullscreen()
        else:
            self.window.unfullscreen()

    def on_menuitem_zoom_in_activate(self, menuitem):
        font_css = self.font.zoom_in()
        self.change_font(font_css)

    def on_menuitem_zoom_out_activate(self, menuitem):
        font_css = self.font.zoom_out()
        self.change_font(font_css)

    def on_menuitem_zoom_default_activate(self, menuitem):
        font_css = self.font.zoom_default()
        self.change_font(font_css)

    def on_settings_sticky_change(self, settings, key):
        if settings.get_boolean(key):
            self.window.stick()
        else:
            self.window.unstick()

    def on_settings_theme_change(self, settings, key):
        top = self.gui.get_object('menuitem_top')
        bottom = self.gui.get_object('menuitem_bottom')

        if not self.theme.is_ascending():
            top, bottom = bottom, top

        top.hide()
        bottom.show()
Beispiel #43
0
class IconFactory():
    """IconFactory finds the icon for a program and prepares the cairo surface."""
    icon_theme = gtk.icon_theme_get_default()
    # Constants
    # Icon types
    SOME_MINIMIZED = 1 << 4
    ALL_MINIMIZED = 1 << 5
    LAUNCHER = 1 << 6
    # Icon effects
    MOUSE_OVER = 1 << 7
    MOUSE_BUTTON_DOWN = 1 << 8
    NEEDS_ATTENTION = 1 << 9
    BLINK = 1 << 10
    # ACTIVE_WINDOW
    ACTIVE = 1 << 11
    LAUNCH_EFFECT = 1 << 12
    # Double width/height icons for drag and drop situations.
    DRAG_DROPP_START = 1 << 13
    DRAG_DROPP_END = 1 << 14
    TYPE_DICT = {
        "some_minimized": SOME_MINIMIZED,
        "all_minimized": ALL_MINIMIZED,
        "launcher": LAUNCHER,
        "mouse_over": MOUSE_OVER,
        "needs_attention": NEEDS_ATTENTION,
        "blink": BLINK,
        "active": ACTIVE,
        "launching": LAUNCH_EFFECT,
        "mouse_button_down": MOUSE_BUTTON_DOWN
    }

    def __init__(self,
                 group,
                 class_group=None,
                 desktop_entry=None,
                 identifier=None):
        self.dockbar_r = weakref.ref(group.dockbar_r())
        self.theme = Theme()
        self.globals = Globals()
        connect(self.globals, "color-changed", self.reset_surfaces)
        self.desktop_entry = desktop_entry
        self.identifier = identifier
        self.class_group = class_group

        # Setting size to something other than zero to
        # avoid crashes if surface_update() is runned
        # before the size is set.
        self.size = 15

        self.icon = None
        self.surfaces = {}

        self.average_color = None

        self.max_win_nr = self.theme.get_windows_cnt()
        self.types_in_theme = 0
        for type in self.theme.get_types():
            if not type in self.TYPE_DICT:
                continue
            self.types_in_theme = self.types_in_theme | self.TYPE_DICT[type]

    def remove(self):
        del self.desktop_entry
        del self.class_group
        del self.icon
        del self.surfaces
        del self.theme

    def set_desktop_entry(self, desktop_entry):
        self.desktop_entry = desktop_entry
        self.surfaces = {}
        del self.icon
        self.icon = None

    def set_class_group(self, class_group):
        if not self.desktop_entry and not self.class_group:
            self.surfaces = {}
            del self.icon
            self.icon = None
        self.class_group = class_group

    def set_size(self, size):
        if size <= 0:
            # To avoid chrashes.
            size = 15
        self.size = size
        self.surfaces = {}
        self.average_color = None

    def get_size(self):
        return self.size

    def get_icon(self, size):
        return self.__find_icon_pixbuf(size)

    def reset_icon(self):
        self.icon = None

    def reset_surfaces(self, arg=None):
        self.surfaces = {}
        self.average_color = None

    def surface_update(self, type=0):
        # Checks if the requested pixbuf is already
        # drawn and returns it if it is.
        # Othervice the surface is drawn, saved and returned.

        #The first four bits of type is for telling the number of windows
        self.win_nr = min(type & 15, self.max_win_nr)
        # Remove all types that are not used by the theme (saves memory)
        dnd = (type & self.DRAG_DROPP_START and "start") or \
              (type & self.DRAG_DROPP_END and "end")
        type = type & self.types_in_theme
        type += self.win_nr
        self.orient = self.dockbar_r().orient
        is_vertical = self.orient in ("left", "right")
        if type in self.surfaces:
            surface = self.surfaces[type]
        else:
            self.temp = {}
            surface = None
            commands = self.theme.get_icon_dict()
            self.ar = self.theme.get_aspect_ratio(is_vertical)
            self.type = type
            for command, args in commands.items():
                try:
                    f = getattr(self, "_IconFactory__command_%s" % command)
                except:
                    raise
                else:
                    surface = f(surface, **args)
            # Todo: add size correction.
            self.surfaces[type] = surface
            del self.temp
            gc.collect()
        if dnd:
            surface = self.__dd_highlight(surface, self.orient, dnd)
            gc.collect()
        return surface

    def __dd_highlight(self, surface, is_vertical, position="start"):
        w = surface.get_width()
        h = surface.get_height()
        if is_vertical:
            h = h + 4
        else:
            w = w + 4
        bg = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(bg)

        if is_vertical and position == "start":
            ctx.move_to(1, 1.5)
            ctx.line_to(w - 1, 1.5)
            ctx.set_source_rgba(1, 1, 1, 0.2)
            ctx.set_line_width(2)
            ctx.stroke()
            ctx.move_to(2, 1.5)
            ctx.line_to(w - 2, 1.5)
            ctx.set_source_rgba(0, 0, 0, 0.7)
            ctx.set_line_width(1)
            ctx.stroke()
        elif is_vertical:
            ctx.move_to(1, h - 1.5)
            ctx.line_to(w - 1, h - 1.5)
            ctx.set_source_rgba(1, 1, 1, 0.2)
            ctx.set_line_width(2)
            ctx.stroke()
            ctx.move_to(2, h - 1.5)
            ctx.line_to(w - 2, h - 1.5)
            ctx.set_source_rgba(0, 0, 0, 0.7)
            ctx.set_line_width(1)
            ctx.stroke()
        elif position == "start":
            ctx.move_to(1.5, 1)
            ctx.line_to(1.5, h - 1)
            ctx.set_source_rgba(1, 1, 1, 0.2)
            ctx.set_line_width(2)
            ctx.stroke()
            ctx.move_to(1.5, 2)
            ctx.line_to(1.5, h - 2)
            ctx.set_source_rgba(0, 0, 0, 0.7)
            ctx.set_line_width(1)
            ctx.stroke()
        else:
            ctx.move_to(w - 1.5, 1)
            ctx.line_to(w - 1.5, h - 1)
            ctx.set_source_rgba(1, 1, 1, 0.2)
            ctx.set_line_width(2)
            ctx.stroke()
            ctx.move_to(w - 1.5, 2)
            ctx.line_to(w - 1.5, h - 2)
            ctx.set_source_rgba(0, 0, 0, 0.7)
            ctx.set_line_width(1)
            ctx.stroke()

        x, y = 0, 0
        if is_vertical and position == "start":
            y = 4
        elif position == "start":
            x = 4
        ctx.set_source_surface(surface, x, y)
        ctx.paint()
        return bg

    def __get_color(self, color):
        if color == "active_color":
            color = "color5"
        if color in ["color%s" % i for i in range(1, 9)]:
            color = self.globals.colors[color]
        if color == "icon_average":
            color = self.__get_average_color()
        else:
            try:
                if len(color) != 7:
                    raise ValueError("The string has the wrong lenght")
                t = int(color[1:], 16)
            except:
                logger.exception("Theme error: the color attribute " +
                      "for a theme command"+ \
                      " should be a six digit hex string eg. \"#FFFFFF\" or"+ \
                      " the a dockbarx color (\"color1\"-\"color8\").")
                color = "#000000"
        return color

    def __get_alpha(self, alpha):
        # Transparency
        if alpha == "active_opacity":
            # For backwards compability
            alpha = "color5"

        for i in range(1, 9):
            if alpha in ("color%s" % i, "opacity%s" % i):
                if self.globals.colors.has_key("color%s_alpha" % i):
                    a = float(self.globals.colors["color%s_alpha" % i]) / 255
                else:
                    logger.warning("Theme error: The theme has no" + \
                          " opacity option for color%s." % i)
                    a = 1.0
                break
        else:
            try:
                a = float(alpha) / 100
                if a > 1.0 or a < 0:
                    raise
            except:
                logger.exception("Theme error: The opacity attribute of a theme " + \
                      "command should be a number between \"0\" " + \
                      " and \"100\" or \"color1\" to \"color8\".")
                a = 1.0
        return a

    def __get_average_color(self):
        if self.average_color is not None:
            return self.average_color
        r = 0
        b = 0
        g = 0
        i = 0
        im = self.__surface2pil(self.icon)
        pixels = im.load()
        width, height = im.size
        for x in range(width):
            for y in range(height):
                pix = pixels[x, y]
                if pix[3] > 30:
                    i += 1
                    r += pix[0]
                    g += pix[1]
                    b += pix[2]
        if i > 0:
            r = int(round(float(r) / i))
            g = int(round(float(g) / i))
            b = int(round(float(b) / i))
        r = ("0%s" % hex(r)[2:])[-2:]
        g = ("0%s" % hex(g)[2:])[-2:]
        b = ("0%s" % hex(b)[2:])[-2:]
        self.average_color = "#" + r + g + b
        return self.average_color

    #### Flow commands
    def __command_if(self,
                     surface,
                     type=None,
                     windows=None,
                     size=None,
                     orient=None,
                     content=None):
        if content is None:
            return surface
        # TODO: complete this
##        l = []
##        splits = ["!", "(", ")", "&", "|"]
##        for c in type:
##            if c in splits:
##                l.append(c)
##            elif l[-1] in splits:
##                l.append(c)
##            elif not l:
##                l.append(c)
##            else:
##                l[-1] += c
# Check if the type condition is satisfied
        if type is not None:
            negation = False
            if type[0] == "!":
                type = type[1:]
                negation = True
            is_type = bool(type in self.TYPE_DICT \
                      and self.type & self.TYPE_DICT[type])
            if not (is_type ^ negation):
                return surface

        #Check if the window number condition is satisfied
        if windows is not None:
            arg = windows
            negation = False
            if arg[0] == "!":
                arg = windows[1:]
                negation = True
            if arg[0] == ":":
                arg = "0" + arg
            elif arg[-1] == ":":
                arg = arg + "15"
            l = arg.split(":", 1)
            try:
                l = [int(n) for n in l]
            except ValueError:
                logger.exception("Theme Error: The windows attribute of " + \
                      "an <if> statement can\'t look like this:" + \
                      " \"%s\"." % windows + \
                      "See Theming HOWTO for more information")
                return surface
            if len(l) == 1:
                if not ((l[0] == self.win_nr) ^ negation):
                    return surface
            else:
                if not (
                    (l[0] <= self.win_nr and self.win_nr <= l[1]) ^ negation):
                    return surface

        #Check if the icon size condition is satisfied
        if size is not None:
            arg = size
            negation = False
            if arg[0] == "!":
                arg = size[1:]
                negation = True
            if arg[0] == ":":
                arg = "0" + arg
            elif arg[-1] == ":":
                arg = arg + "200"
            l = arg.split(":", 1)
            try:
                l = [int(n) for n in l]
            except ValueError:
                logger.exception("Theme Error: The size attribute of " + \
                      "an <if> statement can\'t look like this:" + \
                      " \"%s\". See Theming HOWTO for more information" % size)
                return surface
            us = int(round(self.__get_use_size()))
            if len(l) == 1:
                if not ((l[0] == self.win_nr) ^ negation):
                    return surface
            else:
                if not ((l[0] <= us and us <= l[1]) ^ negation):
                    return surface

        # Test if the orient condition is satisfied.
        if orient is not None:
            orients = orient.split(",")
            if not self.orient in orients:
                return surface

        # All tests passed, proceed.
        for command, args in content.items():
            try:
                f = getattr(self, "_IconFactory__command_%s" % command)
            except:
                raise
            else:
                surface = f(surface, **args)
        return surface

    def __command_pixmap_from_self(self, surface, name, content=None):
        if not name:
            logger.warning("Theme Error: no name given for pixmap_from_self")
            raise Exeption
        w = int(surface.get_width())
        h = int(surface.get_height())
        self.temp[name] = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(self.temp[name])
        ctx.set_source_surface(surface)
        ctx.paint()
        if content is None:
            return surface
        for command, args in content.items():
            try:
                f = getattr(self, "_IconFactory__command_%s" % command)
            except:
                raise
            else:
                self.temp[name] = f(self.temp[name], **args)
        return surface

    def __command_pixmap(self, surface, name, content=None, size=None):
        if size is not None:
            # TODO: Fix for different height and width
            w = h = int(round(self.__get_use_size() + \
                              self.__process_size(size)))
        elif surface is None:
            w = h = int(round(self.__get_use_size()))
        else:
            w = surface.get_width()
            h = surface.get_height()
        self.temp[name] = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        if content is None:
            return surface
        for command, args in content.items():
            try:
                f = getattr(self, "_IconFactory__command_%s" % command)
            except:
                raise
            else:
                self.temp[name] = f(self.temp[name], **args)
        return surface

    #### Get icon
    def __command_get_icon(self, surface=None, size="0"):
        size = int(self.__get_use_size() + self.__process_size(size))
        if size <= 0:
            # To avoid chrashes.
            size = 15
        if self.icon and\
           self.icon.get_width() == size and \
           self.icon.get_height() == size:
            return self.icon
        del self.icon
        self.icon = None
        pb = self.__find_icon_pixbuf(size)

        if pb.get_width() != pb.get_height():
            if pb.get_width() < pb.get_height():
                h = size
                w = pb.get_width() * size / pb.get_height()
            elif pb.get_width() > pb.get_height():
                w = size
                h = pb.get_height() * size / pb.get_width()
            self.icon = cairo.ImageSurface(cairo.FORMAT_ARGB32, size, size)
            ctx = gtk.gdk.CairoContext(cairo.Context(self.icon))
            pbs = pb.scale_simple(w, h, gtk.gdk.INTERP_BILINEAR)
            woffset = round((size - w) / 2.0)
            hoffset = round((size - h) / 2.0)
            ctx.set_source_pixbuf(pb, woffset, hoffset)
            ctx.paint()
            del pb
            del pbs
        elif pb.get_width() != size:
            pbs = pb.scale_simple(size, size, gtk.gdk.INTERP_BILINEAR)
            self.icon = self.__pixbuf2surface(pbs)
            del pb
            del pbs
        else:
            self.icon = self.__pixbuf2surface(pb)
            del pb
        return self.icon

    def __find_icon_pixbuf(self, size):
        # Returns the icon pixbuf for the program. Uses the following metods:

        # 1) If it is a launcher, return the icon from the
        #    launcher's desktopfile
        # 2) Get the icon from the gio app
        # 3) Check if the res_class fits an themed icon.
        # 4) Search in path after a icon matching reclass.
        # 5) Use the mini icon for the class

        pixbuf = None
        icon_name = None
        if self.desktop_entry:
            icon_name = self.desktop_entry.getIcon()
            if icon_name is not None and os.path.isfile(icon_name):
                pixbuf = self.__icon_from_file_name(icon_name, size)
                if pixbuf is not None:
                    return pixbuf

        if not icon_name:
            if self.identifier:
                icon_name = self.identifier.lower()
            elif self.class_group:
                icon_name = self.class_group.get_res_class().lower()
            else:
                icon_name = ""

            # Special cases
            if icon_name.startswith("openoffice"):
                icon_name = "ooo-writer"
            if icon_name.startswith("libreoffice"):
                icon_name = "libreoffice-writer"

        if self.icon_theme.has_icon(icon_name):
            return self.icon_theme.load_icon(icon_name, size, 0)

        if icon_name[-4:] in (".svg", ".png", ".xpm"):
            if self.icon_theme.has_icon(icon_name[:-4]):
                pixbuf = self.icon_theme.load_icon(icon_name[:-4], size, 0)
                if pixbuf is not None:
                    return pixbuf

        pixbuf = self.__icon_search_in_data_path(icon_name, size)
        if pixbuf is not None:
            return pixbuf

        if self.class_group:
            return self.class_group.get_icon().copy()

        # If no pixbuf has been found (can only happen for an unlaunched
        # launcher), make an empty pixbuf and show a warning.
        if self.icon_theme.has_icon("application-default-icon"):
            pixbuf = self.icon_theme.load_icon("application-default-icon",
                                               size, 0)
        else:
            pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, size,
                                    size)
            pixbuf.fill(0x00000000)
        if self.desktop_entry:
            name = self.desktop_entry.getName()
        else:
            name = None
        return pixbuf

    def __icon_from_file_name(self, icon_name, icon_size=-1):
        if os.path.isfile(icon_name):
            try:
                return gtk.gdk.pixbuf_new_from_file_at_size(
                    icon_name, -1, icon_size)
            except:
                pass
        return None

    def __icon_search_in_data_path(self, icon_name, icon_size):
        data_folders = None

        if os.environ.has_key("XDG_DATA_DIRS"):
            data_folders = os.environ["XDG_DATA_DIRS"]

        if not data_folders:
            data_folders = "/usr/local/share/:/usr/share/"

        for data_folder in data_folders.split(":"):
            #The line below line used datafolders instead of datafolder.
            #I changed it because I suspect it was a bug.
            paths = (os.path.join(data_folder, "pixmaps", icon_name),
                     os.path.join(data_folder, "icons", icon_name))
            for path in paths:
                if os.path.isfile(path):
                    icon = self.__icon_from_file_name(path, icon_size)
                    if icon:
                        return icon
        return None

    #### Other commands
    def __command_clear(self, surface):
        if self.dockbar_r().orient in ("left", "right"):
            w = self.size
            h = int(self.size * self.ar)
        else:
            w = int(self.size * self.ar)
            h = self.size
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_rgba(0, 0, 0)
        ctx.set_operator(cairo.OPERATOR_SOURCE)
        ctx.paint_with_alpha(0)
        return new

    def __command_get_pixmap(self, surface, name):
        if surface is None:
            if self.dockbar_r().orient in ("left", "right"):
                width = self.size
                height = int(self.size * self.ar)
            else:
                width = int(self.size * self.ar)
                height = self.size
        else:
            width = surface.get_width()
            height = surface.get_height()
        if self.theme.has_surface(name):
            surface = self.__resize_surface(self.theme.get_surface(name),
                                            width, height)
        else:
            logger.warning("theme error: pixmap %s not found" % name)
        return surface

    def __command_fill(self, surface, color, opacity="100"):
        w = surface.get_width()
        h = surface.get_height()
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_surface(surface)
        ctx.paint()

        alpha = self.__get_alpha(opacity)
        c = self.__get_color(color)
        r = float(int(c[1:3], 16)) / 255
        g = float(int(c[3:5], 16)) / 255
        b = float(int(c[5:7], 16)) / 255
        ctx.set_source_rgba(r, g, b)
        ctx.set_operator(cairo.OPERATOR_SOURCE)
        ctx.paint_with_alpha(alpha)
        return new

    def __command_combine(self, surface, pix1, pix2, degrees=None):
        # Combines left half of surface with right half of surface2.
        # The transition between the two halves are soft.

        # Degrees keyword are kept of compability reasons.
        w = surface.get_width()
        h = surface.get_height()
        if pix1 == "self":
            p1 = surface
        elif pix1 in self.temp:
            p1 = self.temp[pix1]
        elif self.theme.has_surface(pix1):
            w = surface.get_width()
            h = surface.get_height()
            p1 = self.__resize_surface(self.theme.get_surface(bg), w, h)
        else:
            logger.warning("theme error: pixmap %s not found" % pix1)
        if pix2 == "self":
            p2 = surface
        elif pix2 in self.temp:
            p2 = self.temp[pix2]
        elif self.theme.has_surface(pix2):
            w = surface.get_width()
            h = surface.get_height()
            p2 = self.__resize_surface(self.theme.get_surface(bg), w, h)
        else:
            logger.warning("theme error: pixmap %s not found" % pix2)

        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, p1.get_width(),
                                     p1.get_height())
        ctx = cairo.Context(surface)

        linear = cairo.LinearGradient(0, 0, p1.get_width(), 0)
        linear.add_color_stop_rgba(0.4, 0, 0, 0, 0.5)
        linear.add_color_stop_rgba(0.6, 0, 0, 0, 1)
        ctx.set_source_surface(p2, 0, 0)
        #ctx.mask(linear)
        ctx.paint()

        linear = cairo.LinearGradient(0, 0, p1.get_width(), 0)
        linear.add_color_stop_rgba(0.4, 0, 0, 0, 1)
        linear.add_color_stop_rgba(0.6, 0, 0, 0, 0)
        ctx.set_source_surface(p1, 0, 0)
        ctx.mask(linear)
        try:
            del pb
            del pbs
        except:
            pass
        return surface

    def __command_transp_sat(self, surface, opacity="100", saturation="100"):
        # Makes the icon desaturized and/or transparent.
        alpha = self.__get_alpha(opacity)
        # Todo: Add error check for saturation
        sat = float(saturation)
        if sat != 100:
            im = self.__surface2pil(surface)
            w, h = im.size
            pixels = im.load()
            for x in range(w):
                for y in range(h):
                    r, g, b, a = pixels[x, y]
                    l = (r + g + b) / 3.0 * (100 - sat) / 100.0
                    r = int(r * sat / 100.0 + l)
                    g = int(g * sat / 100.0 + l)
                    b = int(b * sat / 100.0 + l)
                    a = int(a * alpha)
                    pixels[x, y] = (r, g, b, a)
            return self.__pil2surface(im)
        else:
            w = surface.get_width()
            h = surface.get_height()
            new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
            ctx = gtk.gdk.CairoContext(cairo.Context(new))
            ctx.set_source_surface(surface)
            ctx.paint_with_alpha(alpha)
            return new

    def __command_composite(self,
                            surface,
                            bg,
                            fg,
                            opacity="100",
                            xoffset="0",
                            yoffset="0",
                            angle="0"):
        if fg == "self":
            foreground = surface
            if angle and angle != "0":
                foreground = self.__command_rotate(foreground, angle, True)
        elif fg in self.temp:
            foreground = self.temp[fg]
            if angle and angle != "0":
                foreground = self.__command_rotate(foreground, angle, True)
        elif self.theme.has_surface(fg):
            foreground = self.theme.get_surface(fg)
            if angle and angle != "0":
                foreground = self.__command_rotate(foreground, angle, True)
            w = surface.get_width()
            h = surface.get_height()
            foreground = self.__resize_surface(foreground, w, h)
        else:
            logger.warning("theme error: pixmap %s not found" % fg)
            return surface
        if bg == "self":
            background = surface
        elif bg in self.temp:
            w = self.temp[bg].get_width()
            h = self.temp[bg].get_height()
            background = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
            ctx = cairo.Context(background)
            ctx.set_source_surface(self.temp[bg])
            ctx.paint()
        elif self.theme.has_surface(bg):
            w = surface.get_width()
            h = surface.get_height()
            background = self.__resize_surface(self.theme.get_surface(bg), w,
                                               h)
        else:
            logger.warning("theme error: pixmap %s not found" % bg)
            return surface

        xoffset = self.__get_from_set(xoffset)
        yoffset = self.__get_from_set(yoffset)
        opacity = self.__get_alpha(opacity)
        xoffset = self.__process_size(xoffset)
        yoffset = self.__process_size(yoffset)
        ctx = cairo.Context(background)
        ctx.set_source_surface(foreground, xoffset, yoffset)
        ctx.paint_with_alpha(opacity)
        return background

    def __command_shrink(self, surface, percent="0", pixels="0"):
        w0 = surface.get_width()
        h0 = surface.get_height()
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w0, h0)
        ctx = cairo.Context(new)

        pixels = self.__get_from_set(pixels)
        percent = self.__get_from_set(percent)
        w = int(((100 - int(percent)) * w0) / 100) - int(pixels)
        h = int(((100 - int(percent)) * h0) / 100) - int(pixels)
        shrinked = self.__resize_surface(surface, w, h)
        x = round((w0 - w) / 2.0)
        y = round((h0 - h) / 2.0)
        ctx.set_source_surface(shrinked, x, y)
        ctx.paint()
        del shrinked
        return new

    def __command_rotate(self, surface, angle="0", resize="False"):
        w0 = surface.get_width()
        h0 = surface.get_height()
        # Check if the angle should be taken from a set.
        angle = self.__get_from_set(angle)
        a = float(angle) / 180 * pi
        if not resize or resize in ("False", "0"):
            w = w0
            h = h0
        else:
            w = abs(int(round(cos(a) * w0 + sin(a) * h0)))
            h = abs(int(round(cos(a) * h0 + sin(a) * w0)))
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)

        ctx.translate(w / 2.0, h / 2.0)
        ctx.rotate(a)
        ctx.translate(-w0 / 2.0, -h0 / 2.0)
        ctx.set_source_surface(surface, 0, 0)
        ctx.paint()
        return new

    def __command_correct_size(self, surface):
        if surface is None:
            return
        if self.dockbar_r().orient in ("left", "right"):
            width = self.size
            height = int(self.size * self.ar)
        else:
            width = int(self.size * self.ar)
            height = self.size
        if surface.get_width() == width and surface.get_height() == height:
            return surface
        woffset = round((width - surface.get_width()) / 2.0)
        hoffset = round((height - surface.get_height()) / 2.0)
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
        ctx = cairo.Context(new)
        ctx.set_source_surface(surface, woffset, hoffset)
        ctx.paint()
        return new

    def __command_glow(self, surface, color, opacity="100"):
        # Adds a glow around the parts of the surface
        # that isn't completely transparent.

        alpha = self.__get_alpha(opacity)
        # Thickness (pixels)
        tk = 1.5

        # Prepare the glow that should be put behind the icon
        cs = self.__command_colorize(surface, color)
        w = surface.get_width()
        h = surface.get_height()
        glow = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(glow)
        tk1 = tk / 2.0
        for x, y in ((-tk1, -tk1), (-tk1, tk1), (tk1, -tk1), (tk1, tk1)):
            ctx.set_source_surface(cs, x, y)
            ctx.paint_with_alpha(0.66)
        for x, y in ((-tk, -tk), (-tk, tk), (tk, -tk), (tk, tk)):
            ctx.set_source_surface(cs, x, y)
            ctx.paint_with_alpha(0.27)

        # Add glow and icon to a new canvas
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_surface(glow)
        ctx.paint_with_alpha(alpha)
        ctx.set_source_surface(surface)
        ctx.paint()
        return new

    def __command_colorize(self, surface, color):
        # Changes the color of all pixels to color.
        # The pixels alpha values are unchanged.

        # Convert color hex-string (format "#FFFFFF")to int r, g, b
        color = self.__get_color(color)
        r = int(color[1:3], 16) / 255.0
        g = int(color[3:5], 16) / 255.0
        b = int(color[5:7], 16) / 255.0

        w = surface.get_width()
        h = surface.get_height()
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_rgba(r, g, b, 1.0)
        ctx.mask_surface(surface)
        return new

    def __command_bright(self, surface, strength=None, strenght=None):
        if strength is None and strenght is not None:
            # For compability with older themes.
            strength = strenght
        alpha = self.__get_alpha(strength)
        w = surface.get_width()
        h = surface.get_height()
        # Colorize white
        white = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(white)
        ctx.set_source_rgba(1.0, 1.0, 1.0, 1.0)
        ctx.mask_surface(surface)
        # Apply the white version over the icon
        # with the chosen alpha value
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_surface(surface)
        ctx.paint()
        ctx.set_source_surface(white)
        ctx.paint_with_alpha(alpha)
        return new

    def __command_alpha_mask(self, surface, mask, angle="0"):
        if mask in self.temp:
            mask = self.temp[mask]
            if angle and angle != "0":
                mask = self.__command_rotate(mask, angle, True)
        elif self.theme.has_surface(mask):
            mask = self.theme.get_surface(mask)
            if angle and angle != "0":
                mask = self.__command_rotate(mask, angle, True)
            w = surface.get_width()
            h = surface.get_height()
            mask = self.__resize_surface(mask, w, h)
        w = surface.get_width()
        h = surface.get_height()
        new = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = cairo.Context(new)
        ctx.set_source_surface(surface)
        ctx.mask_surface(mask)
        return new

#### Format conversions

    def __pixbuf2surface(self, pixbuf):
        if pixbuf is None:
            return None
        w = pixbuf.get_width()
        h = pixbuf.get_height()
        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
        ctx = gtk.gdk.CairoContext(cairo.Context(surface))
        ctx.set_source_pixbuf(pixbuf, 0, 0)
        ctx.paint()
        del pixbuf
        return surface

    def __surface2pil(self, surface):
        w = surface.get_width()
        h = surface.get_height()
        return Image.frombuffer("RGBA", (w, h), surface.get_data(), "raw",
                                "BGRA", 0, 1)

    def __pil2surface(self, im):
        """Transform a PIL Image into a Cairo ImageSurface."""

        # This function is only supposed to work with little endinan
        # systems. Could that be a problem ever?
        if im.mode != 'RGBA':
            im = im.convert('RGBA')

        s = im.tobytes('raw', 'BGRA')
        a = array.array('B', s)
        dest = cairo.ImageSurface(cairo.FORMAT_ARGB32, im.size[0], im.size[1])
        ctx = cairo.Context(dest)
        non_premult_src_wo_alpha = cairo.ImageSurface.create_for_data(
            a, cairo.FORMAT_RGB24, im.size[0], im.size[1])
        non_premult_src_alpha = cairo.ImageSurface.create_for_data(
            a, cairo.FORMAT_ARGB32, im.size[0], im.size[1])
        ctx.set_source_surface(non_premult_src_wo_alpha)
        ctx.mask_surface(non_premult_src_alpha)
        return dest

    def __process_size(self, size_str):
        us = self.__get_use_size()
        size = 0
        size_str = size_str.replace("-", "+-")
        for s in size_str.split("+"):
            if s == "":
                continue
            if s[-1] == "%":
                # Rounding to whole pixels to avoid uninteded bluring.
                size += round(float(s[:-1]) / 100 * us)
                continue
            if s.endswith("px"):
                s = s[:-2]
            # Here no rounding is done. Let's assume that the
            # theme maker knows what he is doing if he chooses
            # to use decimal pixel values.
            size += float(s)
        return size

    def __get_use_size(self):
        is_vertical = self.dockbar_r().orient in ("left", "right")
        if "aspect_ratio_v" in self.theme.theme["button_pixmap"] or \
           not is_vertical:
            us = self.size * self.ar if self.ar < 1 else self.size
        else:
            # For old vertical themes
            us = self.size
        return us

    def __get_from_set(self, setname):
        s = self.theme.get_from_set(setname, self.orient)
        if s is not None:
            return s
        else:
            return setname

    def __resize_surface(self, surface, w, h):
        im = self.__surface2pil(surface)
        im = im.resize((w, h), Image.ANTIALIAS)
        return self.__pil2surface(im)

    def __command_print_size(self, surface):
        w = surface.get_width()
        h = surface.get_height()
        print w, h
        return surface
Beispiel #44
0
class Graphics:

    screen = None
    theme = None

    def start(self):
        self.screen = curses.initscr()
        curses.noecho()
        curses.cbreak()
        curses.curs_set(0)
        curses.start_color()
        self.screen.nodelay(1)

        # Needs to be done after `initscr()` call
        self.theme = Theme()

    def draw_tile(self, x, y, tile='', color=None):
        color = color or self.theme.get_color('default')

        x = x * 2 + stage.padding[3] * 2 + stage.width / 2
        y += stage.padding[0] + stage.height / 2

        self.screen.addstr(y, x, tile, color)
        if (len(tile) < 2):
            self.screen.addstr(y, x + 1, tile, color)

    def draw_game_over(self):
        self.draw_tile(-4, -1, ' GAME OVER ', self.theme.get_color('text'))
        self.draw_tile(-7, 1, ' Press ENTER to restart ',
                       self.theme.get_color('text'))

    def draw_score(self):
        score_formatted = str(game.score).zfill(2)

        self.draw_tile((stage.width / 2) - 1, (-stage.height / 2) - 1,
                       score_formatted, self.theme.get_color('text'))

    def draw_lives(self):
        posx = (-stage.width / 2) + 3

        for x in xrange(1, game.lives + 1):
            posx += 1
            self.draw_tile(posx, (-stage.height / 2) - 1,
                           self.theme.get_tile('lives'),
                           self.theme.get_color('lives'))
            posx += 1
            self.draw_tile(posx, (-stage.height / 2) - 1,
                           self.theme.get_tile('border-h'),
                           self.theme.get_color('border'))

    def draw_snake(self):
        for part in game.snake:
            self.draw_tile(part[0], part[1], self.theme.get_tile('snake-body'),
                           self.theme.get_color('snake'))

        # Clean last tile
        self.draw_tile(game.lastPos[0], game.lastPos[1],
                       self.theme.get_tile('bg'), self.theme.get_color('bg'))

    def draw_apples(self):
        for apple in game.apples:
            self.draw_tile(apple[0], apple[1], self.theme.get_tile('apple'),
                           self.theme.get_color('apple'))

    def draw_game(self):
        for y in range(stage.boundaries['top'], stage.boundaries['bottom']):
            for x in range(stage.boundaries['left'],
                           stage.boundaries['right']):
                self.draw_tile(x, y, self.theme.get_tile('bg'),
                               self.theme.get_color('bg'))

        self.draw_borders()
        self.draw_text()

    def draw_borders(self):
        tile_v = self.theme.get_tile('border-v')
        tile_h = self.theme.get_tile('border-h')
        tile_c = self.theme.get_tile('border-c')
        color = self.theme.get_color('border')

        x_left = stage.boundaries['left']
        x_right = stage.boundaries['right']

        y_top = stage.boundaries['top']
        y_bottom = stage.boundaries['bottom']

        for y in xrange(y_top, y_bottom):
            self.draw_tile(x_left - 1, y, tile_v, color)
            self.draw_tile(x_right, y, tile_v, color)

        for x in xrange(x_left, x_right):
            self.draw_tile(x, y_top - 1, tile_h, color)
            self.draw_tile(x, y_bottom, tile_h, color)

        self.draw_tile(x_left - 1, y_top - 1, tile_c, color)
        self.draw_tile(x_left - 1, y_bottom, tile_c, color)
        self.draw_tile(x_right, y_top - 1, tile_c, color)
        self.draw_tile(x_right, y_bottom, tile_c, color)

    def draw_text(self):
        color = self.theme.get_color('text')

        self.draw_tile((stage.width / 2) - 4, (-stage.height / 2) - 1,
                       'score:', color)
        self.draw_tile((-stage.width / 2), (-stage.height / 2) - 1, 'lives:',
                       color)
        self.draw_tile(-5, (stage.height / 2), ' Press Q to quit ', color)

    def update(self):
        self.draw_snake()
        self.draw_apples()
        self.draw_score()
        self.draw_lives()

    def exit(self):
        self.screen.clear()
        self.screen.keypad(0)
        curses.echo()
        curses.nocbreak()
        curses.endwin()
Beispiel #45
0
 def process_request(self, request):
     if not settings.INSTALLED_THEMES:
         raise ValueError('There are no themes installed!')
     request.theme = Theme(settings.INSTALLED_THEMES[0])
Beispiel #46
0
class SettingsManager(object):
    """Organizes user settings"""
    def __init__(self, alot_rc=None, notmuch_rc=None):
        """
        :param alot_rc: path to alot's config file
        :type alot_rc: str
        :param notmuch_rc: path to notmuch's config file
        :type notmuch_rc: str
        """
        self.hooks = None
        self._mailcaps = mailcap.getcaps()
        self._config = ConfigObj()
        self._notmuchconfig = None
        self._theme = None
        self._accounts = None
        self._accountmap = None
        bindings_path = os.path.join(DEFAULTSPATH, 'default.bindings')
        self._bindings = ConfigObj(bindings_path)
        if alot_rc is not None:
            self.read_config(alot_rc)
        if notmuch_rc is not None:
            self.read_notmuch_config(notmuch_rc)

    def read_notmuch_config(self, path):
        """parse notmuch's config file from path"""
        spec = os.path.join(DEFAULTSPATH, 'notmuch.rc.spec')
        self._notmuchconfig = read_config(path, spec)

    def read_config(self, path):
        """parse alot's config file from path"""
        spec = os.path.join(DEFAULTSPATH, 'alot.rc.spec')
        newconfig = read_config(path, spec,
                                checks={'mail_container': mail_container,
                                        'force_list': force_list,
                                        'align': align_mode,
                                        'attrtriple': attr_triple,
                                        'gpg_key_hint': gpg_key})
        self._config.merge(newconfig)

        hooks_path = os.path.expanduser(self._config.get('hooksfile'))
        try:
            self.hooks = imp.load_source('hooks', hooks_path)
        except:
            logging.debug('unable to load hooks file:%s' % hooks_path)
        if 'bindings' in newconfig:
            newbindings = newconfig['bindings']
            if isinstance(newbindings, Section):
                self._bindings.merge(newbindings)
        # themes
        themestring = newconfig['theme']
        themes_dir = self._config.get('themes_dir')
        if themes_dir:
            themes_dir = os.path.expanduser(themes_dir)
        else:
            configdir = os.environ.get('XDG_CONFIG_HOME',
                                       os.path.expanduser('~/.config'))
            themes_dir = os.path.join(configdir, 'alot', 'themes')
        logging.debug(themes_dir)

        # if config contains theme string use that
        if themestring:
            if not os.path.isdir(themes_dir):
                err_msg = 'cannot find theme %s: themes_dir %s is missing'
                raise ConfigError(err_msg % (themestring, themes_dir))
            else:
                theme_path = os.path.join(themes_dir, themestring)
                try:
                    self._theme = Theme(theme_path)
                except ConfigError as e:
                    err_msg = 'Theme file %s failed validation:\n'
                    raise ConfigError((err_msg % themestring) + str(e.message))

        # if still no theme is set, resort to default
        if self._theme is None:
            theme_path = os.path.join(DEFAULTSPATH, 'default.theme')
            self._theme = Theme(theme_path)

        self._accounts = self._parse_accounts(self._config)
        self._accountmap = self._account_table(self._accounts)

    def _parse_accounts(self, config):
        """
        read accounts information from config

        :param config: valit alot config
        :type config: `configobj.ConfigObj`
        :returns: list of accounts
        """
        accounts = []
        if 'accounts' in config:
            for acc in config['accounts'].sections:
                accsec = config['accounts'][acc]
                args = dict(config['accounts'][acc])

                # create abook for this account
                abook = accsec['abook']
                logging.debug('abook defined: %s' % abook)
                if abook['type'] == 'shellcommand':
                    cmd = abook['command']
                    regexp = abook['regexp']
                    if cmd is not None and regexp is not None:
                        args['abook'] = MatchSdtoutAddressbook(cmd,
                                                               match=regexp)
                    else:
                        msg = 'underspecified abook of type \'shellcommand\':'
                        msg += '\ncommand: %s\nregexp:%s' % (cmd, regexp)
                        raise ConfigError(msg)
                elif abook['type'] == 'abook':
                    contacts_path = abook['abook_contacts_file']
                    args['abook'] = AbookAddressBook(
                        contacts_path, ignorecase=abook['ignorecase'])
                else:
                    del(args['abook'])

                cmd = args['sendmail_command']
                del(args['sendmail_command'])
                newacc = SendmailAccount(cmd, **args)
                accounts.append(newacc)
        return accounts

    def _account_table(self, accounts):
        """
        creates a lookup table (emailaddress -> account) for a given list of
        accounts

        :param accounts: list of accounts
        :type accounts: list of `alot.account.Account`
        :returns: hashtable
        :rvalue: dict (str -> `alot.account.Account`)
        """
        accountmap = {}
        for acc in accounts:
            accountmap[acc.address] = acc
            for alias in acc.aliases:
                accountmap[alias] = acc
        return accountmap

    def get(self, key, fallback=None):
        """
        look up global config values from alot's config

        :param key: key to look up
        :type key: str
        :param fallback: fallback returned if key is not present
        :type fallback: str
        :returns: config value with type as specified in the spec-file
        """
        value = None
        if key in self._config:
            value = self._config[key]
            if isinstance(value, Section):
                value = None
        if value is None:
            value = fallback
        return value

    def set(self, key, value):
        """
        setter for global config values

        :param key: config option identifise
        :type key: str
        :param value: option to set
        :type value: depends on the specfile :file:`alot.rc.spec`
        """
        self._config[key] = value

    def get_notmuch_setting(self, section, key, fallback=None):
        """
        look up config values from notmuch's config

        :param section: key is in
        :type section: str
        :param key: key to look up
        :type key: str
        :param fallback: fallback returned if key is not present
        :type fallback: str
        :returns: config value with type as specified in the spec-file
        """
        value = None
        if section in self._notmuchconfig:
            if key in self._notmuchconfig[section]:
                value = self._notmuchconfig[section][key]
        if value is None:
            value = fallback
        return value

    def get_theming_attribute(self, mode, name, part=None):
        """
        looks up theming attribute

        :param mode: ui-mode (e.g. `search`,`thread`...)
        :type mode: str
        :param name: identifier of the atttribute
        :type name: str
        :rtype: urwid.AttrSpec
        """
        colours = int(self._config.get('colourmode'))
        return self._theme.get_attribute(colours, mode, name, part)

    def get_threadline_theming(self, thread):
        """
        looks up theming info a threadline displaying a given thread. This
        wraps around :meth:`~alot.settings.theme.Theme.get_threadline_theming`,
        filling in the current colour mode.

        :param thread: thread to theme
        :type thread: alot.db.thread.Thread
        """
        colours = int(self._config.get('colourmode'))
        return self._theme.get_threadline_theming(thread, colours)

    def get_tagstring_representation(self, tag, onebelow_normal=None,
                                     onebelow_focus=None):
        """
        looks up user's preferred way to represent a given tagstring.

        :param tag: tagstring
        :type tag: str
        :param onebelow_normal: attribute that shines through if unfocussed
        :type onebelow_normal: urwid.AttrSpec
        :param onebelow_focus: attribute that shines through if focussed
        :type onebelow_focus: urwid.AttrSpec

        If `onebelow_normal` or `onebelow_focus` is given these attributes will
        be used as fallbacks for fg/bg values '' and 'default'.

        This returns a dictionary mapping
            :normal: to :class:`urwid.AttrSpec` used if unfocussed
            :focussed: to :class:`urwid.AttrSpec` used if focussed
            :translated: to an alternative string representation
        """
        colourmode = int(self._config.get('colourmode'))
        theme = self._theme
        cfg = self._config
        colours = [1, 16, 256]

        def colourpick(triple):
            """ pick attribute from triple (mono,16c,256c) according to current
            colourmode"""
            if triple is None:
                return None
            return triple[colours.index(colourmode)]

        # global default attributes for tagstrings.
        # These could contain values '' and 'default' which we interpret as
        # "use the values from the widget below"
        default_normal = theme.get_attribute(colourmode, 'global', 'tag')
        default_focus = theme.get_attribute(colourmode, 'global', 'tag_focus')

        # local defaults for tagstring attributes. depend on next lower widget
        fallback_normal = resolve_att(onebelow_normal, default_normal)
        fallback_focus = resolve_att(onebelow_focus, default_focus)

        for sec in cfg['tags'].sections:
            if re.match('^' + sec + '$', tag):
                normal = resolve_att(colourpick(cfg['tags'][sec]['normal']),
                                     fallback_normal)
                focus = resolve_att(colourpick(cfg['tags'][sec]['focus']),
                                    fallback_focus)

                translated = cfg['tags'][sec]['translated']
                if translated is None:
                    translated = tag
                translation = cfg['tags'][sec]['translation']
                if translation:
                    translated = re.sub(translation[0], translation[1], tag)
                break
        else:
            normal = fallback_normal
            focus = fallback_focus
            translated = tag

        return {'normal': normal, 'focussed': focus, 'translated': translated}

    def get_hook(self, key):
        """return hook (`callable`) identified by `key`"""
        if self.hooks:
            if key in self.hooks.__dict__:
                return self.hooks.__dict__[key]
        return None

    def get_mapped_input_keysequences(self, mode='global', prefix=u''):
        candidates = self._bindings.scalars
        if mode != 'global':
            candidates = candidates + self._bindings[mode].scalars
        if prefix is not None:
            prefixs = prefix + ' '
            cand = filter(lambda x: x.startswith(prefixs), candidates)
            if prefix in candidates:
                candidates = cand + [prefix]
            else:
                candidates = cand
        return candidates

    def get_keybinding(self, mode, key):
        """look up keybinding from `MODE-maps` sections

        :param mode: mode identifier
        :type mode: str
        :param key: urwid-style key identifier
        :type key: str
        :returns: a command line to be applied upon keypress
        :rtype: str
        """
        cmdline = None
        bindings = self._bindings
        if key in bindings.scalars:
            cmdline = bindings[key]
        if mode in bindings.sections:
            if key in bindings[mode].scalars:
                value = bindings[mode][key]
                if value:
                    cmdline = value
        # Workaround for ConfigObj misbehaviour. cf issue #500
        # this ensures that we get at least strings only as commandlines
        if isinstance(cmdline, list):
            cmdline = ','.join(cmdline)
        return cmdline

    def get_accounts(self):
        """
        returns known accounts

        :rtype: list of :class:`Account`
        """
        return self._accounts

    def get_account_by_address(self, address):
        """
        returns :class:`Account` for a given email address (str)

        :param address: address to look up
        :type address: string
        :rtype:  :class:`Account` or None
        """

        for myad in self.get_addresses():
            if myad in address:
                return self._accountmap[myad]
        return None

    def get_main_addresses(self):
        """returns addresses of known accounts without its aliases"""
        return [a.address for a in self._accounts]

    def get_addresses(self):
        """returns addresses of known accounts including all their aliases"""
        return self._accountmap.keys()

    def get_addressbooks(self, order=[], append_remaining=True):
        """returns list of all defined :class:`AddressBook` objects"""
        abooks = []
        for a in order:
            if a:
                if a.abook:
                    abooks.append(a.abook)
        if append_remaining:
            for a in self._accounts:
                if a.abook and a.abook not in abooks:
                    abooks.append(a.abook)
        return abooks

    def mailcap_find_match(self, *args, **kwargs):
        """
        Propagates :func:`mailcap.find_match` but caches the mailcap (first
        argument)
        """
        return mailcap.findmatch(self._mailcaps, *args, **kwargs)

    def represent_datetime(self, d):
        """
        turns a given datetime obj into a unicode string representation.
        This will:

        1) look if a fixed 'timestamp_format' is given in the config
        2) check if a 'timestamp_format' hook is defined
        3) use :func:`~alot.helper.pretty_datetime` as fallback
        """

        fixed_format = self.get('timestamp_format')
        if fixed_format:
            rep = string_decode(d.strftime(fixed_format), 'UTF-8')
        else:
            format_hook = self.get_hook('timestamp_format')
            if format_hook:
                rep = string_decode(format_hook(d), 'UTF-8')
            else:
                rep = pretty_datetime(d)
        return rep
Beispiel #47
0
maximum_device = components['audioLoader'].get_device_count()

# List all the devices supported by the Host API.
# Selection is not avialable due to regressions (would be fixed later).
for device_index in range(maximum_device):
    device_info = components['audioLoader'].get_device_info_by_index(
        device_index)

    print("[%d %s%s] %s" %
          (device_info['index'], green('I') if device_info['maxInputChannels']
           else str(), red('O') if device_info['maxOutputChannels'] else str(),
           device_info['name']))

# Intialize the component theme. And get the color
# palette to draw on the screen.
components['themeLoader'] = Theme(CONFIG_FILES[1])
_theme = components['themeLoader'].getPalette()


def _process_audio(frames, nFrames, timeInfo, status):
    audio_buffer = list(
        map(lambda sample: sample[0],
            components['pcmUnpacker'].iter_unpack(frames)))

    # Draw each buffer recieved from the callback.
    # In the Backend SDL does all the work.
    isClosed = components['visualiser'] \
    .draw(audio_buffer, (
        _theme['background'],
        _theme['foreground']
    ))
Beispiel #48
0
from gameDriver import GameDriver
from theme import Theme
import pygame, sys

dim = (15, 10)
if dim[0] < 4 or dim[1] <= 0:
    print("Invalid Squares Per Row/Column")
    sys.exit(0)

width = 50
if width <= 0:
    print("Invalid Square Width")
    sys.exit(0)

# Bomb img, flag img, font name
normal = Theme("explosion.png", "flag_0.png", "Arial", width)
american = Theme("firework.png", "flag_1.png", "Comic Sans", width)
traditional = Theme("bomb_2.png", "flag_2.png", "Times New Roman", width)

driver = GameDriver(dim, width, traditional)

playing = True
old_time = pygame.time.get_ticks()
while True:
    dt = pygame.time.get_ticks() - old_time
    old_time = pygame.time.get_ticks()

    events = pygame.event.get()

    if playing:
        playing = driver.playGame(dim, width, events, dt)