Example #1
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)
Example #2
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)
    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)
Example #4
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)