Esempio n. 1
0
    def _get_widget_path_at_line(self, lineno, root_lineno=0):
        '''To get widget path of widget at line
        '''

        if self.text == '':
            return []

        text = self.text
        # Remove all comments
        text = re.sub(r'#.+', '', text)

        lines = text.splitlines()
        line = lines[lineno]

        # Search for the line containing widget's name
        _lineno = lineno

        while line.find(':') != -1 and \
                line.strip().find(':') != len(line.strip()) - 1:
            lineno -= 1
            line = lines[lineno]

        path = []
        child_count = 0
        # From current line go above and
        # fill number of children above widget's rule
        while _lineno >= root_lineno and lines[_lineno].strip() != "" and \
                get_indentation(lines[lineno]) != 0:
            _lineno = lineno - 1
            diff_indent = get_indentation(lines[lineno]) - \
                get_indentation(lines[_lineno])

            while _lineno >= root_lineno and (lines[_lineno].strip() == ''
                                              or diff_indent <= 0):
                if lines[_lineno].strip() != '' and diff_indent == 0 and \
                    'canvas' not in lines[_lineno] and \
                        (lines[_lineno].find(':') == -1 or
                         lines[_lineno].find(':') ==
                         len(lines[_lineno].rstrip()) - 1):
                    child_count += 1

                _lineno -= 1
                diff_indent = get_indentation(lines[lineno]) - \
                    get_indentation(lines[_lineno])

            lineno = _lineno

            if _lineno > root_lineno:
                _lineno += 1

            if 'canvas' not in lines[_lineno] and \
                    lines[_lineno].strip().find(':') == \
                    len(lines[_lineno].strip()) - 1:

                path.insert(0, child_count)
                child_count = 0

        return path
Esempio n. 2
0
    def _get_widget_path_at_line(self, lineno, root_lineno=0):
        '''To get widget path of widget at line
        '''

        if self.text == '':
            return []

        text = self.text
        # Remove all comments
        text = re.sub(r'#.+', '', text)

        lines = text.splitlines()
        line = lines[lineno]

        # Search for the line containing widget's name
        _lineno = lineno

        while line.find(':') != -1 and \
                line.strip().find(':') != len(line.strip()) - 1:
            lineno -= 1
            line = lines[lineno]

        path = []
        child_count = 0
        # From current line go above and
        # fill number of children above widget's rule
        while _lineno >= root_lineno and lines[_lineno].strip() != "" and \
                get_indentation(lines[lineno]) != 0:
            _lineno = lineno - 1
            diff_indent = get_indentation(lines[lineno]) - \
                get_indentation(lines[_lineno])

            while _lineno >= root_lineno and (lines[_lineno].strip() == ''
                                              or diff_indent <= 0):
                if lines[_lineno].strip() != '' and diff_indent == 0 and \
                    'canvas' not in lines[_lineno] and \
                        (lines[_lineno].find(':') == -1 or
                         lines[_lineno].find(':') ==
                         len(lines[_lineno].rstrip()) - 1):
                    child_count += 1

                _lineno -= 1
                diff_indent = get_indentation(lines[lineno]) - \
                    get_indentation(lines[_lineno])

            lineno = _lineno

            if _lineno > root_lineno:
                _lineno += 1

            if 'canvas' not in lines[_lineno] and \
                    lines[_lineno].strip().find(':') == \
                    len(lines[_lineno].strip()) - 1:

                path.insert(0, child_count)
                child_count = 0

        return path
Esempio n. 3
0
    def _get_widget_path_at_line(self, lineno, root_lineno=0):
        """To get widget path of widget at line
        """

        if self.text == "":
            return []

        text = self.text
        # Remove all comments
        text = re.sub(r"#.+", "", text)

        lines = text.splitlines()
        line = lines[lineno]

        # Search for the line containing widget's name
        _lineno = lineno

        while line.find(":") != -1 and line.strip().find(":") != len(line.strip()) - 1:
            lineno -= 1
            line = lines[lineno]

        path = []
        child_count = 0
        # From current line go above and
        # fill number of children above widget's rule
        while _lineno >= root_lineno and lines[_lineno].strip() != "" and get_indentation(lines[lineno]) != 0:
            _lineno = lineno - 1
            diff_indent = get_indentation(lines[lineno]) - get_indentation(lines[_lineno])

            while _lineno >= root_lineno and (lines[_lineno].strip() == "" or diff_indent <= 0):
                if (
                    lines[_lineno].strip() != ""
                    and diff_indent == 0
                    and "canvas" not in lines[_lineno]
                    and (lines[_lineno].find(":") == -1 or lines[_lineno].find(":") == len(lines[_lineno].rstrip()) - 1)
                ):
                    child_count += 1

                _lineno -= 1
                diff_indent = get_indentation(lines[lineno]) - get_indentation(lines[_lineno])

            lineno = _lineno

            if _lineno > root_lineno:
                _lineno += 1

            if "canvas" not in lines[_lineno] and lines[_lineno].strip().find(":") == len(lines[_lineno].strip()) - 1:

                path.insert(0, child_count)
                child_count = 0

        return path
Esempio n. 4
0
    def _find_widget_place(self, path, lines, total_lines, lineno, indent=4):
        '''To find the line where widget is declared according to path
        '''

        child_count = 0
        path_index = 1
        path_length = len(path)
        # From starting line go down to find the widget's rule according to path
        while lineno < total_lines and path_index < path_length:
            line = lines[lineno]
            _indent = get_indentation(line)
            colon_pos = line.find(':')
            if _indent == indent and line.strip() != '':
                if colon_pos != -1:
                    line = line.rstrip()
                    if colon_pos == len(line) - 1 and 'canvas' not in line:
                        line = line[:colon_pos].lstrip()
                        if child_count == path[path_index]:
                            path_index += 1
                            indent = _indent + 4
                            child_count = 0
                        else:
                            child_count += 1
                else:
                    child_count += 1

            lineno += 1

        return lineno - 1
Esempio n. 5
0
    def _find_widget_place(self, path, lines, total_lines, lineno, indent=4):
        '''To find the line where widget is declared according to path
        '''

        child_count = 0
        path_index = 1
        path_length = len(path)
        # From starting line go down to find the widget's rule according to path
        while lineno < total_lines and path_index < path_length:
            line = lines[lineno]
            _indent = get_indentation(line)
            colon_pos = line.find(':')
            if _indent == indent and line.strip() != '':
                if colon_pos != -1:
                    line = line.rstrip()
                    if colon_pos == len(line) - 1 and 'canvas' not in line:
                        line = line[:colon_pos].lstrip()
                        if child_count == path[path_index]:
                            path_index += 1
                            indent = _indent + 4
                            child_count = 0
                        else:
                            child_count += 1
                else:
                    child_count += 1

            lineno += 1

        return lineno - 1
Esempio n. 6
0
    def get_widget_text_pos_from_kv(self,
                                    widget,
                                    parent=None,
                                    path_to_widget=None):
        '''To get start and end pos of widget's rule in kv text
        :param path_to_widget: array with widget path
        :param parent: parent of widget
        :param widget: widget to find the kv text
        '''
        if not path_to_widget:
            path_to_widget = self.get_widget_path(widget)
            path_to_widget.reverse()

        # Go to widget's rule's line and determines all its rule's
        # and it's child if any. Then delete them
        text = re.sub(r'#.+', '', self.text)
        lines = text.splitlines()
        total_lines = len(lines)
        root_lineno = 0
        root_name = self.playground.root_name
        for lineno, line in enumerate(lines):
            pos = line.find(root_name)
            if pos != -1 and get_indentation(line) == 0:
                root_lineno = lineno
                break

        widget_lineno = self._find_widget_place(path_to_widget, lines,
                                                total_lines, root_lineno + 1)
        widget_line = lines[widget_lineno]
        indent = len(widget_line) - len(widget_line.lstrip())
        lineno = widget_lineno
        _indent = indent + 1
        line = widget_line
        while line.strip() == '' or _indent > indent:
            lineno += 1
            if lineno >= total_lines:
                break
            line = lines[lineno]
            _indent = len(line) - len(line.lstrip())

        delete_until_line = lineno - 1
        line = lines[delete_until_line]
        while line.strip() == '':
            delete_until_line -= 1
            line = lines[delete_until_line]

        widget_line_pos = get_line_start_pos(self.text, widget_lineno)
        delete_until_line_pos = -1
        if delete_until_line == total_lines - 1:
            delete_until_line_pos = len(self.text)
        else:
            delete_until_line_pos = get_line_end_pos(self.text,
                                                     delete_until_line)

        self._reload = False

        return widget_line_pos, delete_until_line_pos
Esempio n. 7
0
    def get_widget_text_pos_from_kv(self, widget, parent=None,
                                    path_to_widget=None):
        '''To get start and end pos of widget's rule in kv text
        :param path_to_widget: array with widget path
        :param parent: parent of widget
        :param widget: widget to find the kv text
        '''
        if not path_to_widget:
            path_to_widget = self.get_widget_path(widget)
            path_to_widget.reverse()

        # Go to widget's rule's line and determines all its rule's
        # and it's child if any. Then delete them
        text = re.sub(r'#.+', '', self.text)
        lines = text.splitlines()
        total_lines = len(lines)
        root_lineno = 0
        root_name = self.playground.root_name
        for lineno, line in enumerate(lines):
            pos = line.find(root_name)
            if pos != -1 and get_indentation(line) == 0:
                root_lineno = lineno
                break

        widget_lineno = self._find_widget_place(path_to_widget, lines,
                                                total_lines, root_lineno + 1)
        widget_line = lines[widget_lineno]
        indent = len(widget_line) - len(widget_line.lstrip())
        lineno = widget_lineno
        _indent = indent + 1
        line = widget_line
        while line.strip() == '' or _indent > indent:
            lineno += 1
            if lineno >= total_lines:
                break
            line = lines[lineno]
            _indent = len(line) - len(line.lstrip())

        delete_until_line = lineno - 1
        line = lines[delete_until_line]
        while line.strip() == '':
            delete_until_line -= 1
            line = lines[delete_until_line]

        widget_line_pos = get_line_start_pos(self.text, widget_lineno)
        delete_until_line_pos = -1
        if delete_until_line == total_lines - 1:
            delete_until_line_pos = len(self.text)
        else:
            delete_until_line_pos = get_line_end_pos(self.text,
                                                     delete_until_line)

        self._reload = False

        return widget_line_pos, delete_until_line_pos
Esempio n. 8
0
    def get_class_str_from_text(self, class_name, _file_str, is_class=True):
        '''To return the full class rule of class_name from _file_str
        '''
        _file_str += '\n'
        start_pos = -1
        # Find the start position of class_name
        if is_class:
            start_pos = _file_str.find('<' + class_name + '>:')
        else:
            while True:
                start_pos = _file_str.find(class_name, start_pos + 1)
                if start_pos == 0 or not (_file_str[start_pos - 1].isalnum() and
                                          _file_str[start_pos - 1] != ''):
                    break

        _line = 0
        _line_pos = 0
        _line_pos = _file_str.find('\n', _line_pos + 1)
        while _line_pos != -1 and _line_pos < start_pos:
            _line_pos = _file_str.find('\n', _line_pos + 1)
            _line += 1

        # Find the end position of class_name, where indentation becomes 0
        # or file ends
        _line += 1
        lines = _file_str.splitlines()
        _total_lines = len(lines)

        hash_pos = 0
        while hash_pos == 0 and _line < _total_lines:
            hash_pos = lines[_line].find('#')
            if hash_pos == 0:
                _line_pos += 1 + len(lines[_line])
                _line += 1

        while _line < _total_lines and (lines[_line].strip() == '' or
                                        get_indentation(lines[_line]) != 0):
            _line_pos = _file_str.find('\n', _line_pos + 1)
            _line += 1
            hash_pos = 0
            while hash_pos == 0 and _line < _total_lines:
                hash_pos = lines[_line].find('#')
                if hash_pos == 0:
                    _line += 1

        end_pos = _line_pos

        old_str = _file_str[start_pos: end_pos]
        return old_str
Esempio n. 9
0
    def add_custom_widget(self, py_path):
        '''This function is used to add a custom widget given path to its
           py file.
        '''

        f = open(py_path, 'r')
        py_string = f.read()
        f.close()

        # Find path to kv. py file will have Builder.load_file('path/to/kv')
        _r = re.findall(r'Builder\.load_file\s*\(\s*.+\s*\)', py_string)
        if _r == []:
            raise ProjectLoaderException('Cannot find widget\'s kv file.')

        py_string = py_string.replace(_r[0], '')
        kv_path = _r[0][_r[0].find('(') + 1: _r[0].find(')')]
        py_string = py_string.replace(kv_path, '')
        kv_path = kv_path.replace("'", '').replace('"', '')

        f = open(kv_path, 'r')
        kv_string = f.read()
        f.close()

        # Remove all the 'app' lines
        for app_str in re.findall(r'.+app+.+', kv_string):
            kv_string = kv_string.replace(
                app_str,
                app_str[:get_indentation(app_str)] + '#' + app_str.lstrip())

        Builder.load_string(kv_string)

        sys.path.insert(0, os.path.dirname(kv_path))

        _to_check = []

        # Get all the class_rules
        for class_str in re.findall(r'<+([\w_]+)>', kv_string):
            if re.search(r'\bclass\s+%s+.+:' % class_str, py_string):
                module = imp.new_module('CustomWidget')
                exec py_string in module.__dict__
                sys.modules['AppModule'] = module
                class_rule = CustomWidgetRule(class_str, kv_path, py_path)
                class_rule.file = py_path
                class_rule.module = module
                self.custom_widgets.append(class_rule)
Esempio n. 10
0
    def shift_widget(self, widget, from_index):
        '''This function will shift widget's kv str from one position
           to another.
           :param from_index: original index of widget before moving
           :param widget: shifted widget
        '''
        self._reload = False

        path = self.get_widget_path(widget)
        path.reverse()
        # copies the original path
        prev_path = list(path)
        # get the path before shifting the widget
        prev_path[-1] = len(widget.parent.children) - from_index - 1
        start_pos, end_pos = self.get_widget_text_pos_from_kv(
            widget, widget.parent, path_to_widget=prev_path)

        widget_text = self.text[start_pos:end_pos]

        if widget.parent.children.index(widget) == 0:
            self.text = self.text[:start_pos] + self.text[end_pos:]
            self.add_widget_to_parent(widget, widget.parent,
                                      kv_str=widget_text)

        else:
            self.text = self.text[:start_pos] + self.text[end_pos:]
            text = re.sub(r'#.+', '', self.text)
            lines = text.splitlines()
            total_lines = len(lines)
            root_lineno = 0
            root_name = self.playground.root_name
            for lineno, line in enumerate(lines):
                pos = line.find(root_name)
                if pos != -1 and get_indentation(line) == 0:
                    root_lineno = lineno
                    break

            next_widget_path = path
            lineno = self._find_widget_place(next_widget_path, lines,
                                             total_lines,
                                             root_lineno + 1)

            self.cursor = (0, lineno)
            self.insert_text(widget_text + '\n')
Esempio n. 11
0
    def shift_widget(self, widget, from_index):
        '''This function will shift widget's kv str from one position
           to another.
           :param from_index: original index of widget before moving
           :param widget: shifted widget
        '''
        self._reload = False

        path = self.get_widget_path(widget)
        path.reverse()
        # copies the original path
        prev_path = list(path)
        # get the path before shifting the widget
        prev_path[-1] = len(widget.parent.children) - from_index - 1
        start_pos, end_pos = self.get_widget_text_pos_from_kv(
            widget, widget.parent, path_to_widget=prev_path)

        widget_text = self.text[start_pos:end_pos]

        if widget.parent.children.index(widget) == 0:
            self.text = self.text[:start_pos] + self.text[end_pos:]
            self.add_widget_to_parent(widget,
                                      widget.parent,
                                      kv_str=widget_text)

        else:
            self.text = self.text[:start_pos] + self.text[end_pos:]
            text = re.sub(r'#.+', '', self.text)
            lines = text.splitlines()
            total_lines = len(lines)
            root_lineno = 0
            root_name = self.playground.root_name
            for lineno, line in enumerate(lines):
                pos = line.find(root_name)
                if pos != -1 and get_indentation(line) == 0:
                    root_lineno = lineno
                    break

            next_widget_path = path
            lineno = self._find_widget_place(next_widget_path, lines,
                                             total_lines, root_lineno + 1)

            self.cursor = (0, lineno)
            self.insert_text(widget_text + '\n')
Esempio n. 12
0
    def get_root_str(self, kv_str=''):
        '''This function will get the root widgets rule from either kv_str
           or if it is empty string then from the kv file of root widget
        '''

        if kv_str == '':
            f = open(self.root_rule.kv_file, 'r')
            kv_str = f.read()
            f.close()

        # Find the start position of root_rule
        start_pos = kv_str.find(self.root_rule.name)
        if start_pos == -1:
            raise ProjectLoaderException(
                'Cannot find root rule in its file')

        # Get line for start_pos
        _line = 0
        _line_pos = 0
        _line_pos = kv_str.find('\n', _line_pos + 1)
        while _line_pos != -1 and _line_pos < start_pos:
            _line_pos = kv_str.find('\n', _line_pos + 1)
            _line += 1

        # Find the end position of root_rule, where indentation becomes 0
        # or file ends
        _line += 1
        lines = kv_str.splitlines()
        _total_lines = len(lines)
        while _line < _total_lines and (lines[_line].strip() == '' or
                                        get_indentation(lines[_line]) != 0):
            _line_pos = kv_str.find('\n', _line_pos + 1)
            _line += 1

        end_pos = _line_pos

        root_old_str = kv_str[start_pos: end_pos]

        for _rule in self.class_rules:
            if _rule.name == self.root_rule.name:
                root_old_str = "<" + root_old_str

        return root_old_str
Esempio n. 13
0
    def shift_widget(self, widget, from_index):
        '''This function will shift widget's kv str from one position
           to another.
        '''
        self._reload = False

        path = self._get_widget_path(widget)
        path.reverse()
        prev_path = [x for x in path]
        prev_path[-1] = len(widget.parent.children) - from_index - 1
        start_pos, end_pos = self.get_widget_text_pos_from_kv(widget,
                                                              widget.parent,
                                                              path_to_widget=
                                                              prev_path)
        widget_text = self.text[start_pos:end_pos]

        if widget.parent.children.index(widget) == 0:
            self.text = self.text[:start_pos] + self.text[end_pos:]
            self.add_widget_to_parent(widget, widget.parent,
                                      kv_str=widget_text)

        else:
            self.text = self.text[:start_pos] + self.text[end_pos:]
            text = re.sub(r'#.+', '', self.text)
            lines = text.splitlines()
            total_lines = len(lines)
            root_lineno = 0
            root_name = self.project_loader.root_rule.name
            for lineno, line in enumerate(lines):
                pos = line.find(root_name)
                if pos != -1 and get_indentation(line) == 0:
                    root_lineno = lineno
                    break

            next_widget_path = path
            lineno = self._find_widget_place(next_widget_path, lines,
                                             total_lines,
                                             root_lineno + 1)

            self.cursor = (0, lineno)
            self.insert_text(widget_text+'\n')
Esempio n. 14
0
    def shift_widget(self, widget, from_index):
        '''This function will shift widget's kv str from one position
           to another.
        '''
        self._reload = False

        path = self._get_widget_path(widget)
        path.reverse()
        prev_path = [x for x in path]
        prev_path[-1] = len(widget.parent.children) - from_index - 1
        start_pos, end_pos = self.get_widget_text_pos_from_kv(
            widget, widget.parent, path_to_widget=prev_path)

        widget_text = self.text[start_pos:end_pos]

        if widget.parent.children.index(widget) == 0:
            self.text = self.text[:start_pos] + self.text[end_pos:]
            self.add_widget_to_parent(widget,
                                      widget.parent,
                                      kv_str=widget_text)

        else:
            self.text = self.text[:start_pos] + self.text[end_pos:]
            text = re.sub(r'#.+', '', self.text)
            lines = text.splitlines()
            total_lines = len(lines)
            root_lineno = 0
            root_name = self.project_loader.root_rule.name
            for lineno, line in enumerate(lines):
                pos = line.find(root_name)
                if pos != -1 and get_indentation(line) == 0:
                    root_lineno = lineno
                    break

            next_widget_path = path
            lineno = self._find_widget_place(next_widget_path, lines,
                                             total_lines, root_lineno + 1)

            self.cursor = (0, lineno)
            self.insert_text(widget_text + '\n')
Esempio n. 15
0
    def add_widget_to_parent(self, widget, target, kv_str=''):
        '''This function is called when widget is added to target.
           It will search for line where parent is defined in text and will add
           widget there.
        '''
        text = re.sub(r'#.+', '', self.text)
        lines = text.splitlines()
        total_lines = len(lines)
        if total_lines == 0:
            return

        self._reload = False

        # If target is not none then widget is not root widget
        if target:
            path_to_widget = self.get_widget_path(target)

            path_to_widget.reverse()

            root_lineno = 0
            root_name = self.playground.root_name
            for lineno, line in enumerate(lines):
                pos = line.find(root_name)
                if pos != -1 and get_indentation(line) == 0:
                    root_lineno = lineno
                    break

            parent_lineno = self._find_widget_place(path_to_widget, lines,
                                                    total_lines,
                                                    root_lineno + 1)

            if parent_lineno >= total_lines:
                return

            # Get text of parents line
            parent_line = lines[parent_lineno]
            if not parent_line.strip():
                return

            insert_after_line = -1

            if parent_line.find(':') == -1:
                # If parent_line doesn't contain ':' then insert it
                # Also insert widget's rule after its properties
                insert_after_line = parent_lineno
                _line = 0
                _line_pos = -1
                _line_pos = self.text.find('\n', _line_pos + 1)

                while _line <= insert_after_line:
                    _line_pos = self.text.find('\n', _line_pos + 1)
                    _line += 1

                self.text = self.text[:_line_pos] + ':' + self.text[_line_pos:]
                indent = len(parent_line) - len(parent_line.lstrip())

            else:
                # If ':' in parent_line then,
                # find a place to insert widget's rule
                indent = len(parent_line) - len(parent_line.lstrip())
                lineno = parent_lineno
                _indent = indent + 1
                line = parent_line
                while (line.strip() == '' or _indent > indent):
                    lineno += 1
                    if lineno >= total_lines:
                        break
                    line = lines[lineno]
                    _indent = len(line) - len(line.lstrip())

                insert_after_line = lineno - 1
                line = lines[insert_after_line]
                while line.strip() == '':
                    insert_after_line -= 1
                    line = lines[insert_after_line]

            to_insert = ''
            # counts indentation in the beginning of the string
            extra_indent = len(kv_str) - len(kv_str.lstrip())
            if kv_str == '':
                to_insert = type(widget).__name__ + ':'
            else:
                to_insert = kv_str

            if insert_after_line == total_lines - 1:
                # if inserting at the last line
                _line_pos = len(self.text) - 1
                indent = get_indent_str(indent + 4 - extra_indent)
                to_add = ''
                for line in to_insert.splitlines():
                    to_add += '\n' + indent + line
                self.text = self.text[:_line_pos + 1] + to_add
            else:
                # inserting somewhere else
                insert_after_line -= 1
                _line = 0
                _line_pos = -1
                _line_pos = self.text.find('\n', _line_pos + 1)
                while _line <= insert_after_line:
                    _line_pos = self.text.find('\n', _line_pos + 1)
                    _line += 1

                self.text = self.text[:_line_pos] + '\n' + \
                    get_indent_str(indent + 4) + to_insert + \
                    self.text[_line_pos:]

        else:
            # widget is a root widget
            parent_lineno = 0
            self.cursor = (0, 0)
            type_name = type(widget).__name__
            is_class = False
            app_widgets = get_current_project().app_widgets
            for rule_name in app_widgets:
                if rule_name == type_name:
                    is_class = True
                    break

            if not is_class:
                self.insert_text(type_name + ':\n')

            self.playground.load_widget(type_name)
Esempio n. 16
0
    def _load_project(self, kv_path):
        '''Pivate function to load any project given by kv_path
        '''

        if os.path.isdir(kv_path):
            self.proj_dir = kv_path
        else:
            self.proj_dir = os.path.dirname(kv_path)

        parent_proj_dir = os.path.dirname(self.proj_dir)
        sys.path.insert(0, parent_proj_dir)

        self.class_rules = []
        all_files_loaded = True
        _file = None

        for _file in os.listdir(self.proj_dir):
            # Load each kv file in the directory
            _file = os.path.join(self.proj_dir, _file)
            if _file[_file.rfind('.'):] != '.kv':
                continue

            self.kv_file_list.append(_file)

            f = open(_file, 'r')
            kv_string = f.read()
            f.close()

            # Remove all the 'app' lines
            for app_str in re.findall(r'.+app+.+', kv_string):
                kv_string = kv_string.replace(
                    app_str,
                    app_str[:get_indentation(app_str)] +
                    '#' + app_str.lstrip())

            # Get all the class_rules
            for class_str in re.findall(r'<+([\w_]+)>', kv_string):
                class_rule = ClassRule(class_str)
                class_rule.kv_file = _file
                self.class_rules.append(class_rule)

            try:
                root_name = re.findall(r'^([\w\d_]+)\:', kv_string,
                                       re.MULTILINE)

                if root_name != []:
                    # It will occur when there is a root rule and it can't
                    # be loaded by Builder because the its file
                    # has been imported
                    root_name = root_name[0]
                    if not hasattr(Factory, root_name):
                        match = re.search(r'^([\w\d_]+)\:', kv_string,
                                          re.MULTILINE)
                        kv_string = kv_string[:match.start()] + \
                            '<' + root_name + '>:' + kv_string[match.end():]
                        self.root_rule = RootRule(root_name, None)
                        self.root_rule.kv_file = _file
                        self._root_rule = self.root_rule
                        self._is_root_already_in_factory = False

                    else:
                        self._is_root_already_in_factory = True
                else:
                    self._is_root_already_in_factory = False

                root_rule = Builder.load_string(re.sub(r'\s+on_\w+:\w+',
                                                       '', kv_string))
                if root_rule:
                    self.root_rule = RootRule(root_rule.__class__.__name__,
                                              root_rule)
                    self.root_rule.kv_file = _file
                    self._root_rule = self.root_rule

            except Exception as e:
                all_files_loaded = False

        if not all_files_loaded:
            raise ProjectLoaderException('Cannot load file "%s"' % (_file))

        if os.path.exists(os.path.join(self.proj_dir, KV_PROJ_FILE_NAME)):
            projdir_mtime = os.path.getmtime(self.proj_dir)

            f = open(os.path.join(self.proj_dir, KV_PROJ_FILE_NAME), 'r')
            proj_str = f.read()
            f.close()

            _file_is_valid = True
            # Checking if the file is valid
            if proj_str == '' or\
                    proj_str.count('<files>') != proj_str.count('</files>') or\
                    proj_str.count('<file>') != proj_str.count('</file>') or\
                    proj_str.count('<class>') != proj_str.count('</class>'):
                _file_is_valid = False

            if _file_is_valid:
                projdir_time = proj_str[
                    proj_str.find('<time>') + len('<time>'):
                    proj_str.find('</time>')]

                projdir_time = float(projdir_time.strip())

            if _file_is_valid and projdir_mtime <= projdir_time:
                # Project Directory folder hasn't been modified,
                # file list will remain same
                self.file_list = []
                un_modified_files = []
                start_pos = proj_str.find('<files>')
                end_pos = proj_str.find('</files>')
                if start_pos != -1 and end_pos != -1:
                    start_pos = proj_str.find('<file>', start_pos)
                    end_pos1 = proj_str.find('</file>', start_pos)
                    while start_pos < end_pos and start_pos != -1:
                        _file = proj_str[
                            start_pos + len('<file>'):end_pos1].strip()
                        self.file_list.append(_file)
                        if os.path.getmtime(_file) <= projdir_time:
                            un_modified_files.append(_file)

                        start_pos = proj_str.find('<file>', end_pos1)
                        end_pos1 = proj_str.find('</file>', start_pos)

                    for _file in self.file_list:
                        _dir = os.path.dirname(_file)
                        if _dir not in sys.path:
                            sys.path.insert(0, _dir)

                # Reload information for app
                start_pos = proj_str.find('<app>')
                end_pos = proj_str.find('</app>')
                if start_pos != -1 and end_pos != -1:
                    self._app_class = proj_str[
                        proj_str.find('<class>', start_pos) + len('<class>'):
                        proj_str.find('</class>', start_pos)].strip()
                    self._app_file = proj_str[
                        proj_str.find('<file>', start_pos) + len('<file>'):
                        proj_str.find('</file>', start_pos)].strip()
                    f = open(self._app_file, 'r')
                    self._app_module = self._import_module(f.read(),
                                                           self._app_file)
                    f.close()

                # Reload information for the files which haven't been modified
                start_pos = proj_str.find('<classes>')
                end_pos = proj_str.find('</classes>')

                if start_pos != -1 and end_pos != -1:
                    while start_pos < end_pos and start_pos != -1:
                        start_pos = proj_str.find('<class>', start_pos) +\
                            len('<class>')
                        end_pos1 = proj_str.find('</class>', start_pos)
                        _file = proj_str[
                            proj_str.find('<file>', start_pos) + len('<file>'):
                            proj_str.find('</file>', start_pos)].strip()

                        if _file in un_modified_files:
                            # If _file is un modified then assign it to
                            # class rule with _name
                            _name = proj_str[
                                proj_str.find('<name>', start_pos) +
                                len('<name>'):
                                proj_str.find('</name>', start_pos)].strip()

                            for _rule in self.class_rules:
                                if _name == _rule.name:
                                    _rule.file = _file
                                    f = open(_file, 'r')
                                    _rule.module = self._import_module(
                                        f.read(), _file, _fromlist=[_name])
                                    f.close()

                        start_pos = proj_str.find('<class>', start_pos)
                        end_pos1 = proj_str.find('</class>', start_pos)

        if self.file_list == []:
            self.file_list = self._get_file_list(self.proj_dir)

        # Get all files corresponding to each class
        self._get_class_files()

        # If root widget is not created but root class is known
        # then create widget
        if self.root_rule and not self.root_rule.widget and \
                self.root_rule.name:
            self.root_rule.widget = self.get_widget_of_class(
                self.root_rule.name)

        self.load_proj_config()
Esempio n. 17
0
    def save_project(self, proj_dir=''):
        '''To save project to proj_dir. If proj_dir is not empty string then
           project is saved to a new directory other than its
           current directory and otherwise it is saved to the
           current directory.
        '''

        # To stop ProjectWatcher from emitting event when project is saved
        self.proj_watcher.allow_event_dispatch = False
        proj_dir_changed = False

        if self.new_project:
            # Create dir and copy new_proj.kv and new_proj.py to new directory
            if not os.path.exists(proj_dir):
                os.mkdir(proj_dir)

            kivy_designer_dir = get_kivy_designer_dir()
            kivy_designer_new_proj_dir = os.path.join(kivy_designer_dir,
                                                      "new_proj")
            for _file in os.listdir(kivy_designer_new_proj_dir):
                old_file = os.path.join(kivy_designer_new_proj_dir, _file)
                new_file = os.path.join(proj_dir, _file)
                if os.path.isdir(old_file):
                    shutil.copytree(old_file, new_file)
                else:
                    shutil.copy(old_file, new_file)

            self.file_list = self._get_file_list(proj_dir)

            new_kv_file = os.path.join(proj_dir, "main.kv")
            new_py_file = os.path.join(proj_dir, "main.py")

            self.proj_dir = proj_dir
            if self.root_rule:
                self.root_rule.kv_file = new_kv_file
                self.root_rule.py_file = new_py_file

            if self.class_rules:
                self.class_rules[0].py_file = new_py_file
                self.class_rules[0].kv_file = new_kv_file

            self.new_project = False

        else:
            if proj_dir != '' and proj_dir != self.proj_dir:
                proj_dir_changed = True

                # Remove previous project directories from sys.path
                for _dir in self._dir_list:
                    try:
                        sys.path.remove(_dir)
                    except:
                        pass

                # if proj_dir and self.proj_dir differs then user wants to save
                # an already opened project to somewhere else
                # Copy all the files
                if not os.path.exists(proj_dir):
                    os.mkdir(proj_dir)

                for _file in os.listdir(self.proj_dir):
                    old_file = os.path.join(self.proj_dir, _file)
                    new_file = os.path.join(proj_dir, _file)
                    if os.path.isdir(old_file):
                        shutil.copytree(old_file, new_file)
                    else:
                        shutil.copy(old_file, new_file)

                self.file_list = self._get_file_list(proj_dir)

                # Change the path of all files in the class rules,
                # root rule and app
                relative_path = self._app_file[
                    self._app_file.find(self.proj_dir):]
                self._app_file = os.path.join(proj_dir, relative_path)

                f = open(self._app_file, 'r')
                s = f.read()
                f.close()

                self._import_module(s, self._app_file,
                                    _fromlist=[self._app_class])

                for _rule in self.class_rules:
                    relative_path = _rule.kv_file[
                        _rule.kv_file.find(self.proj_dir):]
                    _rule.kv_file = os.path.join(proj_dir, relative_path)

                    relative_path = _rule.file[_rule.file.find(self.proj_dir):]
                    _rule.file = os.path.join(proj_dir, relative_path)

                    f = open(_rule.file, 'r')
                    s = f.read()
                    f.close()
                    self._import_module(s, _rule.file, _fromlist=[_rule.name])

                relative_path = self.root_rule.kv_file[
                    self.root_rule.kv_file.find(self.proj_dir):]
                self.root_rule.kv_file = os.path.join(proj_dir, relative_path)

                relative_path = self.root_rule.file[
                    self.root_rule.file.find(self.proj_dir):]
                self.root_rule.file = os.path.join(proj_dir, relative_path)

                self.proj_dir = proj_dir

        # For custom widgets copy py and kv file to project directory
        for widget in self.custom_widgets:
            custom_kv = os.path.join(self.proj_dir,
                                     os.path.basename(widget.kv_file))
            if not os.path.exists(custom_kv):
                shutil.copy(widget.kv_file, custom_kv)

            custom_py = os.path.join(self.proj_dir,
                                     os.path.basename(widget.py_file))
            if not os.path.exists(custom_py):
                shutil.copy(widget.py_file, custom_py)

        # Saving all opened py files and also reimport them
        for _code_input in self.tab_pannel.list_py_code_inputs:
            path = os.path.join(self.proj_dir, _code_input.rel_file_path)
            f = open(path, 'w')
            f.write(_code_input.text)
            f.close()
            _from_list = []
            for rule in self.class_rules:
                if rule.file == path:
                    _from_list.append(rule.file)

            if not self.is_root_a_class_rule():
                if self.root_rule.file == path:
                    _from_list.append(self.root_rule.name)

            # Ignore all types that are not .py
            if path.endswith(".py"):
                self._import_module(_code_input.text, path,
                                    _fromlist=_from_list)

        # Save all class rules
        text = self.kv_code_input.text
        for _rule in self.class_rules:
            # Get the kv text from KVLangArea and write it to class rule's file
            f = open(_rule.kv_file, 'r')
            _file_str = f.read()
            f.close()

            old_str = self.get_class_str_from_text(_rule.name, _file_str)
            new_str = self.get_class_str_from_text(_rule.name, text)

            f = open(_rule.kv_file, 'w')
            _file_str = _file_str.replace(old_str, new_str)
            f.write(_file_str)
            f.close()

        # If root widget is not changed
        if self._root_rule.name == self.root_rule.name:
            # Save root widget's rule
            is_root_class = False
            for _rule in self.class_rules:
                if _rule.name == self.root_rule.name:
                    is_root_class = True
                    break

            if not is_root_class:
                f = open(self.root_rule.kv_file, 'r')
                _file_str = f.read()
                f.close()

                old_str = self.get_class_str_from_text(self.root_rule.name,
                                                       _file_str,
                                                       is_class=False)
                new_str = self.get_class_str_from_text(self.root_rule.name,
                                                       text, is_class=False)

                f = open(self.root_rule.kv_file, 'w')
                _file_str = _file_str.replace(old_str, new_str)
                f.write(_file_str)
                f.close()

        else:
            # If root widget is changed
            # Root Widget changes, there can be these cases:
            root_name = self.root_rule.name
            f = open(self._app_file, 'r')
            file_str = f.read()
            f.close()
            self._root_rule = self.root_rule

            if self.is_root_a_class_rule() and self._app_file:
                # Root Widget's class rule is a custom class
                # and its rule is class rule. So, it already have been saved
                # the string of App's build() function will be changed to
                # return new root widget's class

                if self._app_class != 'runTouchApp':
                    s = re.search(r'class\s+%s.+:' % self._app_class, file_str)
                    if s:
                        build_searchiter = None
                        for searchiter in re.finditer(
                                r'[ \ \t]+def\s+build\s*\(\s*self.+\s*:',
                                file_str):
                            if searchiter.start() > s.start():
                                build_searchiter = searchiter
                                break

                        if build_searchiter:
                            indent = get_indentation(build_searchiter.group(0))
                            file_str = file_str[:build_searchiter.end()] +\
                                '\n' + get_indent_str(2 * indent) + "return " +\
                                root_name + "()\n" + \
                                file_str[build_searchiter.end():]

                        else:
                            file_str = file_str[:s.end()] + \
                                "\n    def build(self):\n        return " + \
                                root_name + '()\n' + file_str[s.end():]

                else:
                    file_str = re.sub(r'runTouchApp\s*\(.+\)',
                                      'runTouchApp(' + root_name + '())',
                                      file_str)

                f = open(self._app_file, 'w')
                f.write(file_str)
                f.close()

            else:
                # Root Widget's rule is not a custom class
                # and its rule is root rule
                # Its kv_file should be of App's class name
                # and App's build() function should be cleared
                if not self.root_rule.kv_file:
                    s = self._app_class.replace('App', '').lower()
                    root_file = None
                    for _file in self.kv_file_list:
                        if os.path.basename(_file).find(s) == 0:
                            self.root_rule.kv_file = _file
                            break

                f = open(self.root_rule.kv_file, 'r')
                _file_str = f.read()
                f.close()

                new_str = self.get_class_str_from_text(self.root_rule.name,
                                                       text, False)

                f = open(self.root_rule.kv_file, 'a')
                f.write(new_str)
                f.close()

                if self._app_class != 'runTouchApp':
                    s = re.search(r'class\s+%s.+:' % self._app_class, file_str)
                    if s:
                        build_searchiter = None
                        for searchiter in re.finditer(
                                r'[ \ \t]+def\s+build\s*\(\s*self.+\s*:',
                                file_str):
                            if searchiter.start() > s.start():
                                build_searchiter = searchiter
                                break

                        if build_searchiter:
                            lines = file_str.splitlines()
                            total_lines = len(lines)
                            indent = get_indentation(build_searchiter.group(0))

                            _line = 0
                            _line_pos = -1
                            _line_pos = file_str.find('\n', _line_pos + 1)
                            while _line_pos <= build_searchiter.start():
                                _line_pos = file_str.find('\n', _line_pos + 1)
                                _line += 1

                            _line += 1

                            while _line < total_lines:
                                if lines[_line].strip() != '' and\
                                        get_indentation(lines[_line]) <= \
                                        indent:
                                    break

                                _line += 1

                            _line -= 1
                            end = get_line_start_pos(file_str, _line)
                            start = build_searchiter.start()
                            file_str = file_str.replace(file_str[start:end],
                                                        '    pass')

                            f = open(self._app_file, 'w')
                            f.write(file_str)
                            f.close()

        # Allow Project Watcher to emit events
        Clock.schedule_once(self._allow_proj_watcher_dispatch, 1)
Esempio n. 18
0
    def add_widget_to_parent(self, widget, target, kv_str=''):
        '''This function is called when widget is added to target.
           It will search for line where parent is defined in text and will add
           widget there.
        '''
        text = re.sub(r'#.+', '', self.text)
        lines = text.splitlines()
        total_lines = len(lines)
        if total_lines == 0:
            return

        self._reload = False

        # If target is not none then widget is not root widget
        if target:
            path_to_widget = self.get_widget_path(target)

            path_to_widget.reverse()

            root_lineno = 0
            root_name = self.playground.root_name
            for lineno, line in enumerate(lines):
                pos = line.find(root_name)
                if pos != -1 and get_indentation(line) == 0:
                    root_lineno = lineno
                    break

            parent_lineno = self._find_widget_place(path_to_widget, lines,
                                                    total_lines,
                                                    root_lineno + 1)

            if parent_lineno >= total_lines:
                return

            # Get text of parents line
            parent_line = lines[parent_lineno]
            if not parent_line.strip():
                return

            insert_after_line = -1

            if parent_line.find(':') == -1:
                # If parent_line doesn't contain ':' then insert it
                # Also insert widget's rule after its properties
                insert_after_line = parent_lineno
                _line = 0
                _line_pos = -1
                _line_pos = self.text.find('\n', _line_pos + 1)

                while _line <= insert_after_line:
                    _line_pos = self.text.find('\n', _line_pos + 1)
                    _line += 1

                self.text = self.text[:_line_pos] + ':' + self.text[_line_pos:]
                indent = len(parent_line) - len(parent_line.lstrip())

            else:
                # If ':' in parent_line then,
                # find a place to insert widget's rule
                indent = len(parent_line) - len(parent_line.lstrip())
                lineno = parent_lineno
                _indent = indent + 1
                line = parent_line
                while (line.strip() == '' or _indent > indent):
                    lineno += 1
                    if lineno >= total_lines:
                        break
                    line = lines[lineno]
                    _indent = len(line) - len(line.lstrip())

                insert_after_line = lineno - 1
                line = lines[insert_after_line]
                while line.strip() == '':
                    insert_after_line -= 1
                    line = lines[insert_after_line]

            to_insert = ''
            # counts indentation in the beginning of the string
            extra_indent = len(kv_str) - len(kv_str.lstrip())
            if kv_str == '':
                to_insert = type(widget).__name__ + ':'
            else:
                to_insert = kv_str

            if insert_after_line == total_lines - 1:
                # if inserting at the last line
                _line_pos = len(self.text) - 1
                indent = get_indent_str(indent + 4 - extra_indent)
                to_add = ''
                for line in to_insert.splitlines():
                    to_add += '\n' + indent + line
                self.text = self.text[:_line_pos + 1] + to_add
            else:
                # inserting somewhere else
                insert_after_line -= 1
                _line = 0
                _line_pos = -1
                _line_pos = self.text.find('\n', _line_pos + 1)
                while _line <= insert_after_line:
                    _line_pos = self.text.find('\n', _line_pos + 1)
                    _line += 1

                self.text = self.text[:_line_pos] + '\n' + \
                    get_indent_str(indent + 4) + to_insert + \
                    self.text[_line_pos:]

        else:
            # widget is a root widget
            parent_lineno = 0
            self.cursor = (0, 0)
            type_name = type(widget).__name__
            is_class = False
            app_widgets = get_current_project().app_widgets
            for rule_name in app_widgets:
                if rule_name == type_name:
                    is_class = True
                    break

            if not is_class:
                self.insert_text(type_name + ':\n')

            self.playground.load_widget(type_name)
Esempio n. 19
0
    def set_property_value(self, widget, prop, value, proptype):
        '''To find and change the value of property of widget rule in text
        '''

        # Do not add property if value is empty and
        # property is not a string property

        self._reload = False
        if not isinstance(widget.properties()[prop], StringProperty) and\
                value == '':
            return

        path_to_widget = self.get_widget_path(widget)
        path_to_widget.reverse()

        # Go to the line where widget is declared
        lines = re.sub(r'#.+', '', self.text.rstrip()).splitlines()
        total_lines = len(lines)

        root_name = self.playground.root_name
        total_lines = len(lines)
        root_lineno = 0
        for lineno, line in enumerate(lines):
            pos = line.find(root_name)
            if pos != -1 and get_indentation(line) == 0:
                root_lineno = lineno
                break

        widget_lineno = self._find_widget_place(path_to_widget, lines,
                                                total_lines, root_lineno + 1)
        widget_line = lines[widget_lineno]
        if not widget_line.strip():
            return

        indent = get_indentation(widget_line)
        prop_found = False

        if ':' not in widget_line:
            # If cannot find ':' then insert it
            self.cursor = (len(lines[widget_lineno]), widget_lineno)
            lines[widget_lineno] += ':'
            self.insert_text(':')

        else:
            # Else find if property has already been declared with a value
            lineno = widget_lineno + 1
            # But if widget line is the last line in the text
            if lineno < total_lines:
                line = lines[lineno]
                _indent = get_indentation(line)
                colon_pos = -1
                while lineno < total_lines and (line.strip() == '' or
                                                _indent > indent):
                    line = lines[lineno]
                    _indent = get_indentation(line)
                    if line.strip() != '':
                        colon_pos = line.find(':')
                        if colon_pos == -1:
                            break

                        if colon_pos == len(line.rstrip()) - 1:
                            break

                        if prop == line[:colon_pos].strip():
                            prop_found = True
                            break

                    lineno += 1

        if prop_found:
            # if property found then change its value
            _pos_prop_value = get_line_start_pos(self.text, lineno) + \
                colon_pos + 2
            if lineno == total_lines - 1:
                _line_end_pos = len(self.text)
            else:
                _line_end_pos = get_line_end_pos(self.text, lineno)

            if proptype == 'StringProperty' or \
                    (proptype == 'OptionProperty' and
                         not isinstance(value, list)):
                value = "'{}'".format(value.replace("'", "\\'"))

            self.text = self.text[:_pos_prop_value] + ' ' + str(value) + \
                self.text[_line_end_pos:]

            self.cursor = (0, lineno)

        else:
            # if not found then add property after the widgets line
            _line_start_pos = get_line_start_pos(self.text, widget_lineno)
            _line_end_pos = get_line_end_pos(self.text, widget_lineno)
            if proptype == 'StringProperty' or \
                    (proptype == 'OptionProperty' and
                         not isinstance(value, list)):
                value = "'{}'".format(value.replace("'", "\\'"))

            indent_str = '\n'
            for i in range(indent + 4):
                indent_str += ' '

            self.cursor = (len(lines[widget_lineno]), widget_lineno)
            self.insert_text(indent_str + prop + ': ' + str(value))
Esempio n. 20
0
    def get_property_value(self, widget, prop):
        self._reload = False
        if prop[:3] != 'on_' and \
                not isinstance(widget.properties()[prop], StringProperty) and\
                value == '':
            return

        path_to_widget = self.get_widget_path(widget)
        path_to_widget.reverse()

        # Go to the line where widget is declared
        lines = re.sub(r'#.+', '', self.text).splitlines()
        total_lines = len(lines)

        root_name = self.playground.root_name
        total_lines = len(lines)
        root_lineno = 0
        for lineno, line in enumerate(lines):
            pos = line.find(root_name)
            if pos != -1 and get_indentation(line) == 0:
                root_lineno = lineno
                break

        widget_lineno = self._find_widget_place(path_to_widget, lines,
                                                total_lines, root_lineno + 1)
        widget_line = lines[widget_lineno]
        indent = get_indentation(widget_line)
        prop_found = False

        # Else find if property has already been declared with a value
        lineno = widget_lineno + 1
        # But if widget line is the last line in the text
        if lineno < total_lines:
            line = lines[lineno]
            _indent = get_indentation(line)
            colon_pos = -1
            while lineno < total_lines and (line.strip() == ''
                                            or _indent > indent):
                line = lines[lineno]
                _indent = get_indentation(line)
                if line.strip() != '':
                    colon_pos = line.find(':')
                    if colon_pos == -1:
                        break

                    if colon_pos == len(line.rstrip()) - 1:
                        break

                    if prop == line[:colon_pos].strip():
                        prop_found = True
                        break

                lineno += 1

        if prop_found:
            # if property found then change its value
            _pos_prop_value = get_line_start_pos(self.text, lineno) + \
                colon_pos + 2
            if lineno == total_lines - 1:
                _line_end_pos = len(self.text)
            else:
                _line_end_pos = get_line_end_pos(self.text, lineno)

            return self.text[_pos_prop_value:_line_end_pos]

        return ''
Esempio n. 21
0
    def set_property_value(self, widget, prop, value, proptype):
        '''To find and change the value of property of widget rule in text
        '''

        # Do not add property if value is empty and
        # property is not a string property

        self._reload = False
        if not isinstance(widget.properties()[prop], StringProperty) and\
                value == '':
            return

        path_to_widget = self.get_widget_path(widget)
        path_to_widget.reverse()

        # Go to the line where widget is declared
        lines = re.sub(r'#.+', '', self.text.rstrip()).splitlines()
        total_lines = len(lines)

        root_name = self.playground.root_name
        total_lines = len(lines)
        root_lineno = 0
        for lineno, line in enumerate(lines):
            pos = line.find(root_name)
            if pos != -1 and get_indentation(line) == 0:
                root_lineno = lineno
                break

        widget_lineno = self._find_widget_place(path_to_widget, lines,
                                                total_lines, root_lineno + 1)
        widget_line = lines[widget_lineno]
        if not widget_line.strip():
            return

        indent = get_indentation(widget_line)
        prop_found = False

        if ':' not in widget_line:
            # If cannot find ':' then insert it
            self.cursor = (len(lines[widget_lineno]), widget_lineno)
            lines[widget_lineno] += ':'
            self.insert_text(':')

        else:
            # Else find if property has already been declared with a value
            lineno = widget_lineno + 1
            # But if widget line is the last line in the text
            if lineno < total_lines:
                line = lines[lineno]
                _indent = get_indentation(line)
                colon_pos = -1
                while lineno < total_lines and (line.strip() == ''
                                                or _indent > indent):
                    line = lines[lineno]
                    _indent = get_indentation(line)
                    if line.strip() != '':
                        colon_pos = line.find(':')
                        if colon_pos == -1:
                            break

                        if colon_pos == len(line.rstrip()) - 1:
                            break

                        if prop == line[:colon_pos].strip():
                            prop_found = True
                            break

                    lineno += 1

        if prop_found:
            # if property found then change its value
            _pos_prop_value = get_line_start_pos(self.text, lineno) + \
                colon_pos + 2
            if lineno == total_lines - 1:
                _line_end_pos = len(self.text)
            else:
                _line_end_pos = get_line_end_pos(self.text, lineno)

            if proptype == 'StringProperty' or \
                    (proptype == 'OptionProperty' and
                         not isinstance(value, list)):
                value = "'{}'".format(value.replace("'", "\\'"))

            self.text = self.text[:_pos_prop_value] + ' ' + str(value) + \
                self.text[_line_end_pos:]

            self.cursor = (0, lineno)

        else:
            # if not found then add property after the widgets line
            _line_start_pos = get_line_start_pos(self.text, widget_lineno)
            _line_end_pos = get_line_end_pos(self.text, widget_lineno)
            if proptype == 'StringProperty' or \
                    (proptype == 'OptionProperty' and
                         not isinstance(value, list)):
                value = "'{}'".format(value.replace("'", "\\'"))

            indent_str = '\n'
            for i in range(indent + 4):
                indent_str += ' '

            self.cursor = (len(lines[widget_lineno]), widget_lineno)
            self.insert_text(indent_str + prop + ': ' + str(value))
Esempio n. 22
0
    def set_event_handler(self, widget, prop, value):
        self._reload = False

        path_to_widget = self.get_widget_path(widget)
        path_to_widget.reverse()

        # Go to the line where widget is declared
        lines = re.sub(r'#.+', '', self.text).splitlines()
        total_lines = len(lines)

        root_name = self.playground.root_name
        total_lines = len(lines)
        root_lineno = 0
        for lineno, line in enumerate(lines):
            pos = line.find(root_name)
            if pos != -1 and get_indentation(line) == 0:
                root_lineno = lineno
                break

        widget_lineno = self._find_widget_place(path_to_widget, lines,
                                                total_lines, root_lineno + 1)

        widget_line = lines[widget_lineno]
        indent = get_indentation(widget_line)
        prop_found = False

        if not widget_line.strip():
            return

        if ':' not in widget_line:
            # If cannot find ':' then insert it
            self.cursor = (len(lines[widget_lineno]), widget_lineno)
            lines[widget_lineno] += ':'
            self.insert_text(':')

        else:
            # Else find if property has already been declared with a value
            lineno = widget_lineno + 1
            # But if widget line is the last line in the text
            if lineno < total_lines:
                line = lines[lineno]
                _indent = get_indentation(line)
                colon_pos = -1
                while lineno < total_lines and (line.strip() == ''
                                                or _indent > indent):
                    line = lines[lineno]
                    _indent = get_indentation(line)
                    if line.strip() != '':
                        colon_pos = line.find(':')
                        if colon_pos == -1:
                            break

                        if colon_pos == len(line.rstrip()) - 1:
                            break

                        if prop == line[:colon_pos].strip():
                            prop_found = True
                            break

                    lineno += 1

        if prop_found:
            if lineno == total_lines - 1:
                _line_end_pos = len(self.text)
            else:
                _line_end_pos = get_line_end_pos(self.text, lineno)

            if value != '':
                # if property found then change its value
                _pos_prop_value = get_line_start_pos(self.text, lineno) + \
                    colon_pos + 2
                self.text = self.text[:_pos_prop_value] + ' ' + value + \
                    self.text[_line_end_pos:]

                self.cursor = (0, lineno)

            else:
                _line_start_pos = get_line_start_pos(self.text, widget_lineno)
                self.text = \
                    self.text[:get_line_start_pos(self.text, lineno)] + \
                    self.text[_line_end_pos:]

        elif value != '':
            # if not found then add property after the widgets line
            _line_end_pos = get_line_end_pos(self.text, widget_lineno)

            indent_str = '\n'
            for i in range(indent + 4):
                indent_str += ' '

            self.cursor = (len(lines[widget_lineno]), widget_lineno)
            self.insert_text(indent_str + prop + ': ' + str(value))
Esempio n. 23
0
    def get_property_value(self, widget, prop):
        self._reload = False
        if prop[:3] != 'on_' and \
                not isinstance(widget.properties()[prop], StringProperty) and\
                value == '':
            return

        path_to_widget = self.get_widget_path(widget)
        path_to_widget.reverse()

        # Go to the line where widget is declared
        lines = re.sub(r'#.+', '', self.text).splitlines()
        total_lines = len(lines)

        root_name = self.playground.root_name
        total_lines = len(lines)
        root_lineno = 0
        for lineno, line in enumerate(lines):
            pos = line.find(root_name)
            if pos != -1 and get_indentation(line) == 0:
                root_lineno = lineno
                break

        widget_lineno = self._find_widget_place(path_to_widget, lines,
                                                total_lines, root_lineno + 1)
        widget_line = lines[widget_lineno]
        indent = get_indentation(widget_line)
        prop_found = False

        # Else find if property has already been declared with a value
        lineno = widget_lineno + 1
        # But if widget line is the last line in the text
        if lineno < total_lines:
            line = lines[lineno]
            _indent = get_indentation(line)
            colon_pos = -1
            while lineno < total_lines and (line.strip() == '' or
                                            _indent > indent):
                line = lines[lineno]
                _indent = get_indentation(line)
                if line.strip() != '':
                    colon_pos = line.find(':')
                    if colon_pos == -1:
                        break

                    if colon_pos == len(line.rstrip()) - 1:
                        break

                    if prop == line[:colon_pos].strip():
                        prop_found = True
                        break

                lineno += 1

        if prop_found:
            # if property found then change its value
            _pos_prop_value = get_line_start_pos(self.text, lineno) + \
                colon_pos + 2
            if lineno == total_lines - 1:
                _line_end_pos = len(self.text)
            else:
                _line_end_pos = get_line_end_pos(self.text, lineno)

            return self.text[_pos_prop_value:_line_end_pos]

        return ''
Esempio n. 24
0
    def add_widget_to_parent(self, widget, target, kv_str=""):
        """This function is called when widget is added to target.
           It will search for line where parent is defined in text and will add
           widget there.
        """
        text = re.sub(r"#.+", "", self.text)
        lines = text.splitlines()
        total_lines = len(lines)
        if total_lines == 0:
            return

        self._reload = False

        # If target is not none then widget is not root widget
        if target:
            path_to_widget = self._get_widget_path(target)

            path_to_widget.reverse()

            root_lineno = 0
            root_name = self.playground.root_name
            for lineno, line in enumerate(lines):
                pos = line.find(root_name)
                if pos != -1 and get_indentation(line) == 0:
                    root_lineno = lineno
                    break

            parent_lineno = self._find_widget_place(path_to_widget, lines, total_lines, root_lineno + 1)

            if parent_lineno >= total_lines:
                return

            # Get text of parents line
            parent_line = lines[parent_lineno]
            if not parent_line.strip():
                return

            insert_after_line = -1

            if parent_line.find(":") == -1:
                # If parent_line doesn't contain ':' then insert it
                # Also insert widget's rule after its properties
                insert_after_line = parent_lineno
                _line = 0
                _line_pos = -1
                _line_pos = self.text.find("\n", _line_pos + 1)

                while _line <= insert_after_line:
                    _line_pos = self.text.find("\n", _line_pos + 1)
                    _line += 1

                self.text = self.text[:_line_pos] + ":" + self.text[_line_pos:]
                indent = len(parent_line) - len(parent_line.lstrip())

            else:
                # If ':' in parent_line then,
                # find a place to insert widget's rule
                indent = len(parent_line) - len(parent_line.lstrip())
                lineno = parent_lineno
                _indent = indent + 1
                line = parent_line
                while line.strip() == "" or _indent > indent:
                    lineno += 1
                    if lineno >= total_lines:
                        break
                    line = lines[lineno]
                    _indent = len(line) - len(line.lstrip())

                insert_after_line = lineno - 1
                line = lines[insert_after_line]
                while line.strip() == "":
                    insert_after_line -= 1
                    line = lines[insert_after_line]

            to_insert = ""
            if kv_str == "":
                to_insert = type(widget).__name__ + ":"
            else:
                to_insert = kv_str.strip()

            if insert_after_line == total_lines - 1:
                # if inserting at the last line
                _line_pos = len(self.text) - 1

                self.text = self.text[: _line_pos + 1] + "\n" + get_indent_str(indent + 4) + to_insert
            else:
                # inserting somewhere else
                insert_after_line -= 1
                _line = 0
                _line_pos = -1
                _line_pos = self.text.find("\n", _line_pos + 1)
                while _line <= insert_after_line:
                    _line_pos = self.text.find("\n", _line_pos + 1)
                    _line += 1

                self.text = (
                    self.text[:_line_pos] + "\n" + get_indent_str(indent + 4) + to_insert + self.text[_line_pos:]
                )

        else:
            # widget is a root widget
            parent_lineno = 0
            self.cursor = (0, 0)
            type_name = type(widget).__name__
            is_class = False
            app_widgets = get_current_project().app_widgets
            for rule_name in app_widgets:
                if rule_name == type_name:
                    is_class = True
                    break

            if not is_class:
                self.insert_text(type_name + ":\n")

            self.playground.load_widget(type_name)
Esempio n. 25
0
    def set_event_handler(self, widget, prop, value):
        self._reload = False

        path_to_widget = self.get_widget_path(widget)
        path_to_widget.reverse()

        # Go to the line where widget is declared
        lines = re.sub(r'#.+', '', self.text).splitlines()
        total_lines = len(lines)

        root_name = self.playground.root_name
        total_lines = len(lines)
        root_lineno = 0
        for lineno, line in enumerate(lines):
            pos = line.find(root_name)
            if pos != -1 and get_indentation(line) == 0:
                root_lineno = lineno
                break

        widget_lineno = self._find_widget_place(path_to_widget, lines,
                                                total_lines, root_lineno + 1)

        widget_line = lines[widget_lineno]
        indent = get_indentation(widget_line)
        prop_found = False

        if not widget_line.strip():
            return

        if ':' not in widget_line:
            # If cannot find ':' then insert it
            self.cursor = (len(lines[widget_lineno]), widget_lineno)
            lines[widget_lineno] += ':'
            self.insert_text(':')

        else:
            # Else find if property has already been declared with a value
            lineno = widget_lineno + 1
            # But if widget line is the last line in the text
            if lineno < total_lines:
                line = lines[lineno]
                _indent = get_indentation(line)
                colon_pos = -1
                while lineno < total_lines and (line.strip() == '' or
                                                _indent > indent):
                    line = lines[lineno]
                    _indent = get_indentation(line)
                    if line.strip() != '':
                        colon_pos = line.find(':')
                        if colon_pos == -1:
                            break

                        if colon_pos == len(line.rstrip()) - 1:
                            break

                        if prop == line[:colon_pos].strip():
                            prop_found = True
                            break

                    lineno += 1

        if prop_found:
            if lineno == total_lines - 1:
                _line_end_pos = len(self.text)
            else:
                _line_end_pos = get_line_end_pos(self.text, lineno)

            if value != '':
                # if property found then change its value
                _pos_prop_value = get_line_start_pos(self.text, lineno) + \
                    colon_pos + 2
                self.text = self.text[:_pos_prop_value] + ' ' + value + \
                    self.text[_line_end_pos:]

                self.cursor = (0, lineno)

            else:
                _line_start_pos = get_line_start_pos(self.text, widget_lineno)
                self.text = \
                    self.text[:get_line_start_pos(self.text, lineno)] + \
                    self.text[_line_end_pos:]

        elif value != '':
            # if not found then add property after the widgets line
            _line_end_pos = get_line_end_pos(self.text, widget_lineno)

            indent_str = '\n'
            for i in range(indent + 4):
                indent_str += ' '

            self.cursor = (len(lines[widget_lineno]), widget_lineno)
            self.insert_text(indent_str + prop + ': ' + str(value))