Exemplo n.º 1
0
class TilesEditor(ChildWindow):

    def __init__(self):
        super(TilesEditor, self).__init__()
        self.config = Config()
        self.setWindowTitle('Tiles Editor')
        self.setFixedSize(640, 480)
        self._tab_widget = QtGui.QTabWidget(self)
        self._tab_widget.setGeometry(0, 0, 640, 480)
        self.subscribe('menu.trigger.import_tileset', self.on_import_tileset)
        self.subscribe('picture.mousemove', self.on_picture_mouse_move)
        self.subscribe('new_project', self.on_new_file)
        self.subscribe('open_project', self.on_open_file)
        self._workspaces = []

    def on_new_file(self, message):
        self._workspaces = []
        self._tab_widget.clear()

    def on_open_file(self, message):
        self.current_file = self.config.current_file()
        for tileset in self.current_file.get('tilesets', []):
            workspace = TileSetWorkspace(
                self, self.current_file['pathes'][tileset], self._queue
            )
            workspace.show()
            self._tab_widget.addTab(workspace, workspace.base_name())
            self._workspaces.append(workspace)
            self.send('tileset_editor.new_tileset', {
                'tileset': workspace.base_name()
            })
            self.send('tileset.update', {
                'tileset': workspace.base_name()
            })
            workspace.read_tilesets_config()
        self.send('open_maps')

    def on_import_tileset(self, message):
        file_name = QtGui.QFileDialog.getOpenFileName(
            self, filter='Tilesets (*.png)',
            directory=self.config.get(
                'tilesets_images_dir', os.path.expanduser('~')
            )
        )
        if file_name:
            self.config.set(
                'tilesets_images_dir',
                os.path.dirname(str(file_name))
            )
            self.send('config.save')
            workspace = TileSetWorkspace(
                self, str(file_name), self._queue
            )
            workspace.show()
            self._tab_widget.addTab(workspace, workspace.base_name())
            self._workspaces.append(workspace)
            self.send('tileset_editor.new_tileset', {
                'tileset': workspace.base_name()
            })

    def on_picture_mouse_move(self, message):
        for workspace in self._workspaces:
            workspace.on_picture_mouse_move(message)

    def remove_current(self):
        self._workspaces.pop(self._tab_widget.currentIndex())
        self._tab_widget.removeTab(self._tab_widget.currentIndex())
class FightEnvironmentWorkspace(QtGui.QFrame):

    LAYERS = ('screen', 'background3', 'background2', 'background1')

    def __init__(self, name):
        super(FightEnvironmentWorkspace, self).__init__()
        self._name = name
        self._height_ratio = 1.0
        self.config = Config()
        self.setGeometry(0, 0, 320, 220)
        self._layers = {}
        self._buttons = []
        self._current_conf = Config().current_file()['fightenv'][name]
        for layer_name in self.LAYERS:
            self._layers[layer_name] = self.new_layer()
        self._layers['screen'].setStyleSheet(
            'QLabel {'
            'background-color: black;'
            'border: 3px solid #ccccff;'
            '}'
        )
        self.new_button('Set background 1', 2, self.on_choose_background1, False)
        self.new_button('Set background 2', 104, self.on_choose_background2, False)
        self.new_button('Set background 3', 206, self.on_choose_background3)
        self._play_animation = IconButton(self, 'play_animation', 30, 30)
        self._play_animation.setGeometry(145, 182, 30, 30)
        self._play_animation.clicked.connect(self.on_play_animation)

    def on_play_animation(self):
        self._preview = FightEnvironmentPreview(self._name)
        self._preview.show()

    def name(self):
        return self._name

    def read_conf(self):
        for layer_name in self.LAYERS:
            if layer_name in self._current_conf:
                path = Config().current_file()['pathes'][self._current_conf[layer_name]]
                pixmap = QtGui.QPixmap(path)
                self.show_background(pixmap, layer_name)

    def show_background(self, pixmap, name):
        height = self._layers[name].height()
        width = (pixmap.width() * height) / pixmap.height()
        self._height_ratio = float(height) / pixmap.height()
        self._layers[name].setPixmap(pixmap.scaled(width, height))
        for button in self._buttons:
            button.setEnabled(True)

    def on_choose_background3(self):
        pixmap = self.choose_and_save_image('background3')
        if pixmap:
            self.show_background(pixmap, 'background3')

    def on_choose_background2(self):
        pixmap = self.choose_and_save_image('background2')
        if pixmap:
            self.show_background(pixmap, 'background2')

    def on_choose_background1(self):
        pixmap = self.choose_and_save_image('background1')
        if pixmap:
            self.show_background(pixmap, 'background1')

    def choose_and_save_image(self, image_name):
        file_name = QtGui.QFileDialog.getOpenFileName(
            self, filter='Image (*.png)',
            directory=self.config.get(
                'fightenv_image_dir', os.path.expanduser('~')
            )
        )
        if file_name:
            from mqme.mainwindow import MainWindow
            file_name = unicode(file_name)
            self.config.set('fightenv_image_dir', os.path.dirname(file_name))
            MainWindow.queue.put({'name': 'config.save'})
            if not 'pathes' in Config().current_file():
                Config().current_file()['pathes'] = {}
            image_id = str(uuid.uuid1())
            Config().current_file()['pathes'][image_id] = file_name
            self._current_conf[image_name] = image_id
            return QtGui.QPixmap(file_name)

    def new_button(self, name, x, callback, enabled=True):
        button = QtGui.QPushButton(name, self)
        button.setGeometry(x, 155, 100, 20)
        button.clicked.connect(callback)
        button.setEnabled(enabled)
        button.setStyleSheet(
            'QPushButton {'
            'font-size: 10px;'
            '}'
        )
        button.show()
        self._buttons.append(button)

    def new_layer(self):
        layer = QtGui.QLabel(self)
        layer.setGeometry(7, 0, 300, 150)
        layer.show()
        return layer
Exemplo n.º 3
0
class MainWindow(QtGui.QMainWindow):

    resources_directories = (
        'fightenv', 'images', 'maps', 'sprites', 'tiles'
    )

    queue = Queue.Queue()

    CHILDREN = (
        TilesEditor, MapEditor,
        LayersDialog, SpritesEditor,
        FightEnvironmentEditor
    )

    def __init__(self, resolution, title):
        super(MainWindow, self).__init__()
        self.config = Config()
        self.config.init_from_file(settings.CONFIG_FILE_PATH)
        self._timer = QtCore.QTimer(self)
        self.setWindowIcon(QtGui.QIcon(os.path.join(
            settings.IMAGES_PATH, 'mqme.png'
        )))
        MainWindow._subscriptions = {
            'config.save': self.on_save_config_request,
            'menu.trigger.save_project': self.on_save_project_request,
            'menu.trigger.new_project': self.on_new_project_request,
            'menu.trigger.open_project': self.on_open_project_request,
            'menu.trigger.export_to_resources': self.on_export_request
        }
        self.connect(self._timer, QtCore.SIGNAL("timeout()"), self.update)
        self.workspace = QtGui.QWorkspace()
        width, height = resolution
        self.resize(width, height)
        self.setWindowTitle(title)
        self.setCentralWidget(self.workspace)
        self.setMenuBar(MenuBar(self, self.on_menu_triggered))
        self._children = []
        for child_type in self.CHILDREN:
            child = child_type()
            self.workspace.addWindow(child)
            child.set_queue(MainWindow.queue)
            self._children.append(child)
        self._timer.start(settings.QUEUE_READ_LOOP_DELAY)

    def keyPressEvent(self, event):
        super(MainWindow, self).keyPressEvent(event)
        self.send('key_press', {'key': event.key()})

    def keyReleaseEvent(self, event):
        super(MainWindow, self).keyReleaseEvent(event)
        self.send('key_release', {'key': event.key()})

    def send(self, name, body=None):
        message = {'name': name}
        if body is not None:
            message.update(body)
        MainWindow.queue.put(message)

    @staticmethod
    def subscribe(message_name, callback):
        MainWindow._subscriptions[message_name] = callback

    def receive(self, message):
        name = message.get('name')
        if name in MainWindow._subscriptions:
            MainWindow._subscriptions[name](message)

    def on_menu_triggered(self, menu_name):
        self.send('menu.trigger.%s' % menu_name)

    def update(self):
        try:
            index = 0
            while index < settings.QUEUE_READ_LOOP_DELAY:
                message = MainWindow.queue.get_nowait()
                self.receive(message)
                for child in self._children:
                    child.receive(message)
                index += 1
        except Queue.Empty:
            pass

    def on_save_config_request(self, message):
        self.config.save(settings.CONFIG_FILE_PATH)

    def on_save_project_request(self, message):
        file_name = QtGui.QFileDialog.getSaveFileName(
            self, filter='MQME Projects (*.mqp)',
            directory=self.config.get(
                'project_dir', os.path.expanduser('~')
            )
        )
        if file_name:
            file_name = unicode(file_name)
            self.config.set(
                'project_dir', os.path.dirname(file_name)
            )
            self.config.save(settings.CONFIG_FILE_PATH)
            self.config.save_current_file(file_name)

    def on_open_project_request(self, message):
        file_name = QtGui.QFileDialog.getOpenFileName(
            self, filter='MQME Projects (*.mqp)',
            directory=self.config.get(
                'project_dir', os.path.expanduser('~')
            )
        )
        if file_name:
            self.send('new_project')
            file_name = unicode(file_name)
            self.config.set(
                'project_dir', os.path.dirname(file_name)
            )
            self.config.save(settings.CONFIG_FILE_PATH)
            self.config.read_current_file(file_name)
            self.send('open_project')

    def on_new_project_request(self, message):
        self.config.reset_current_file()
        self.send('new_project')

    def on_export_request(self, message):
        if self.config.has_changed():
            msg_box = QtGui.QMessageBox(self)
            msg_box.setWindowTitle('Config has changed')
            msg_box.setText(
                'You need to save the project before exporting'
            )
            msg_box.setDefaultButton(QtGui.QMessageBox.Cancel)
            msg_box.exec_()
            return
        current_file = self.config.current_file()
        directory = None
        if 'pathes' in current_file:
            directory = current_file['pathes'].get('resources_dir', None)
        if directory is None:
            directory = QtGui.QFileDialog.getExistingDirectory(
                self, directory=self.config.get(
                    'resources_dir', os.path.expanduser('~')
                )
            )
        if directory is not None:
            directory = str(directory)
            if not 'pathes' in current_file:
                current_file['pathes'] = {}
            current_file['pathes']['resources_dir'] = directory
            self.config.set('resources_dir', directory)
            self.config.save(settings.CONFIG_FILE_PATH)
            for sub_directory in self.resources_directories:
                subpath = os.path.join(directory, sub_directory)
                if not os.path.exists(subpath):
                    os.makedirs(subpath)
            self.export_maps(directory)
            self.export_tilesets(directory)
            self.export_sprites(directory)
            self.export_fight_environments(directory)
            msg_box = QtGui.QMessageBox(self)
            msg_box.setWindowTitle('Export')
            msg_box.setText(
                'Project exported successfully !'
            )
            msg_box.setDefaultButton(QtGui.QMessageBox.Cancel)
            msg_box.exec_()

    def export_physics(self, sps_obj, id, directory):
        svg_path = os.path.join(directory, id + '.svg')
        if os.path.exists(svg_path):
            with open(svg_path) as raw_file:
                dom = parse(raw_file)
                root = dom.getElementsByTagName('svg')[0]
                image = root.getElementsByTagName('image')[0]
                width = float(image.getAttribute('width'))
                height = float(image.getAttribute('height'))
                x = float(image.getAttribute('x'))
                y = float(image.getAttribute('y'))
                for rect in root.getElementsByTagName('rect'):
                    physics_type = rect.getAttribute('id').split('_')[0]
                    if physics_type != 'platform':
                        physics_type = 'ground'
                    sps_obj['physics'][id].append({
                        'x': (float(rect.getAttribute('x')) - x) / width,
                        'y': (float(rect.getAttribute('y')) - y) / height,
                        'width': float(rect.getAttribute('width')) / width,
                        'height': float(rect.getAttribute('height')) / height,
                        'type': physics_type
                    })
                for circle in root.getElementsByTagName('path'):
                    sodipodi_type = circle.getAttribute('sodipodi:type')
                    if sodipodi_type == 'arc':
                        cx = float(circle.getAttribute('sodipodi:cx'))
                        transform_raw = circle.getAttribute('transform')
                        transform_raw = transform_raw.replace('translate(', '').replace(')', '')
                        foe_x = float(transform_raw.split(',')[0]) + cx
                        sps_obj['foes'][id].append({
                            'x': (foe_x - x) / width
                        })
                        if id.find('town_d') > -1:
                            print cx, transform_raw, foe_x, x, (foe_x - x) / width

    def export_fight_environments(self, directory):
        fightenv_directory = os.path.join(directory, 'fightenv')
        environments = self.config.current_file().get('fightenv', {})
        layers = ('background3', 'background2')
        for name, fight_env in environments.items():
            sps_obj = {'backgrounds': [], 'physics': {}, 'foes': {}}
            max_width = 0
            max_height = 0
            images = {}
            bg1_path = self.config.current_file()['pathes'][
                fight_env['background1']
            ]
            bg1_key = os.path.basename(bg1_path).split('_')[0]
            bg1_directory = os.path.dirname(bg1_path)
            for image_name in os.listdir(bg1_directory):
                if image_name.startswith(bg1_key) and image_name.endswith('.png'):
                    image_id = image_name.split('_', 1)[1].split('.')[0]
                    image_path = os.path.join(bg1_directory, image_name)
                    sps_obj['physics'][name + '_' + image_id] = []
                    sps_obj['foes'][name + '_' + image_id] = []
                    self.export_physics(
                        sps_obj, name + '_' + image_id, os.path.dirname(image_path)
                    )
                    image = utils.get_resized_image(image_path)    
                    output_path = os.path.join(
                        fightenv_directory,
                        name + '_' + image_id + '.png'
                    )
                    image.save(output_path)
                    sps_obj['backgrounds'].append('fightenv/' + name + '_' + image_id)
            for layer_index in (2, 3):
                image = utils.get_resized_image(
                    self.config.current_file()['pathes'][
                        fight_env['background' + str(layer_index)]
                    ]
                )
                output_path = os.path.join(
                    fightenv_directory,
                    name + '_bg' + str(layer_index) + '.png'
                )
                image.save(output_path)
                sps_obj['backgrounds'].append(
                    'fightenv/' + name + '_bg' + str(layer_index)
                )
            base_path = os.path.join(fightenv_directory, name)
            with open(base_path + '.sps', 'w') as sps:
                sps.write(json.dumps(sps_obj))

    def export_sprites(self, directory):
        sprites_directory = os.path.join(directory, 'sprites')
        actors = self.config.current_file().get('actors', {})
        for actor_name in actors:
            SpritesGenerator(actor_name).save(sprites_directory)

    def export_maps(self, directory):
        maps = self.config.current_file().get('maps', {})
        for map_name, map_obj in maps.items():
            path = os.path.join(directory, 'maps', map_name + '.map')
            map_obj['camera'] = [
                map_obj['camera_width'],
                map_obj['camera_height']
            ]
            map_obj['size'] = [
                map_obj['width'],
                map_obj['height']
            ]
            x = 0
            for matrix_line in map_obj['specials']:
                y = 0
                for special_conf in matrix_line:
                    if special_conf['class_name'] == 'start_pos':
                        map_obj['start_pos'] = [x, y]
                    y += 1
                x += 1
            with open(path, 'w') as map_file:
                map_file.write(json.dumps(map_obj, sort_keys=True, indent=4))

    def export_tilesets(self, directory):
        tilesets = self.config.current_file().get('tilesets', {})
        for tileset_name, tileset_obj in tilesets.items():
            path = os.path.join(directory, 'tiles', tileset_name + '.sps')
            with open(path, 'w') as tileset_file:
                tileset_file.write(json.dumps(
                    tileset_obj, sort_keys=True, indent=4
                ))
Exemplo n.º 4
0
class AnimationArea(QtGui.QFrame):

    FPS_VALUES = [40, 35, 30, 25, 20, 15, 10, 5, 2, 1]
    NB_MULTIPLIERS = 100

    def __init__(self, parent, actor_name, animation_name):
        super(AnimationArea, self).__init__(parent)
        self._parent = parent
        self.config = Config()
        self.current_conf = Config().current_file()[
            'actors'
        ][actor_name]['animations'][animation_name]
        self._current_frame = 0
        self._actor_name = actor_name
        self._animation_name = animation_name
        self.setGeometry(0, 0, 480, 450)
        self._frames_list = QtGui.QComboBox(self)
        self._frames_list.setGeometry(5, 420, 100, 20)
        self._frames_list.currentIndexChanged.connect(self.on_change_frame)
        self._add_frame_button = IconButton(self, 'add_frame', 50, 50)
        self._add_frame_button.setGeometry(110, 420, 20, 20)
        self._add_frame_button.clicked.connect(self.on_add_frame)
        self._remove_frame_button = IconButton(self, 'remove_frame', 50, 50)
        self._remove_frame_button.setGeometry(135, 420, 20, 20)
        self._remove_frame_button.clicked.connect(self.on_remove_frame)
        self._scroll_areas = {}
        self._add_picture_button = IconButton(self, 'add_picture', 50, 50)
        self._add_picture_button.setGeometry(402, 2, 50, 50)
        self._add_picture_button.clicked.connect(self.on_new_picture)
        self._remove_animation_button = IconButton(
            self, 'remove_animation', 50, 50
        )
        self._remove_animation_button.setGeometry(402, 54, 50, 50)
        self._remove_animation_button.clicked.connect(self.on_remove_animation)
        self._resize_button = QtGui.QRadioButton('Resize', self)
        self._resize_button.setGeometry(170, 420, 70, 20)
        self._move_button = QtGui.QRadioButton('Move', self)
        self._move_button.setGeometry(240, 420, 70, 20)
        self._move_button.setChecked(True)
        self._multiplier = QtGui.QComboBox(self)
        self._multiplier.setGeometry(402, 380, 50, 20)
        for multiplier in range(1, self.NB_MULTIPLIERS + 1):
            self._multiplier.addItem('x' + str(multiplier))
        self._pos_label = QtGui.QLabel(self)
        self._pos_label.setGeometry(402, 100, 50, 100)
        self._play_animation = IconButton(self, 'play_animation', 50, 50)
        self._play_animation.setGeometry(402, 210, 50, 50)
        self._play_animation.clicked.connect(self.on_play_animation)
        self._fps_choice = QtGui.QComboBox(self)
        self._fps_choice.setGeometry(310, 420, 150, 20)
        if not len(self.current_conf):
            self._scroll_areas[0] = QtGui.QScrollArea(self)
            self._scroll_areas[0].setGeometry(0, 0, 400, 400)
            self._scroll_areas[0].setWidget(SpriteGridWidget(self))
            self._frames_list.addItem('Frame 0')
            self.current_conf['fps'] = 40
        for value in self.FPS_VALUES:
            period = 1000 / value
            self._fps_choice.addItem('%d FPS - %d ms' % (value, period))
        self._fps_choice.setCurrentIndex(self.FPS_VALUES.index(
            self.current_conf['fps']
        ))
        self._fps_choice.currentIndexChanged.connect(self.on_change_fps)
        self._multiplier.currentIndexChanged.connect(self.on_change_multiplier)

    def on_change_multiplier(self):
        frame_key = 'frame_%d' % self._current_frame
        conf = None
        for elem in self.current_conf[frame_key]:
            if elem.get('type', None) == 'conf':
                conf = elem
                break
        if conf is None:
            conf = {'type': 'conf'}
            self.current_conf[frame_key].append(conf)
        multiplier = self._multiplier.currentIndex() + 1
        conf['multiplier'] = multiplier

    def on_play_animation(self):
        preview = AnimationPreview(
            self, self._actor_name, self._animation_name
        )
        preview.show()

    def read_conf(self):
        for index in range(len(self.current_conf) - 1):
            frame_key = 'frame_%d' % index
            self._scroll_areas[index] = QtGui.QScrollArea(self)
            self._scroll_areas[index].setGeometry(0, 0, 400, 400)
            self._scroll_areas[index].setWidget(SpriteGridWidget(self))
            for obj in self.current_conf[frame_key]:
                if obj.get('type', None) != 'conf':
                    frame_image = FrameImage(
                        self._scroll_areas[index].widget(),
                        self.config.current_file()['pathes'][obj['id']],
                        obj['id'], frame_key
                    )
                    frame_image.setGeometry(
                        200 + obj['x'] * 100,
                        200 + obj['y'] * 100,
                        obj['width'] * 100,
                        obj['height'] * 100,
                    )
                    frame_image.show()
                    self._frames_list.addItem('Frame %d' % index)
            self._scroll_areas[index].hide()
        self._current_frame = 0
        self._scroll_areas[0].show()
        self._frames_list.setCurrentIndex(0)
        frame_key = 'frame_%d' % self._current_frame
        conf = None
        for elem in self.current_conf[frame_key]:
            if elem.get('type', None) == 'conf':
                conf = elem
                break
        if conf is None:
            conf = {'type': 'conf'}
            self.current_conf[frame_key].append(conf)
        multiplier = conf.get('multiplier', 1)
        self._multiplier.setCurrentIndex(multiplier - 1)

    def remove_animation(self):
        animations = Config().current_file()[
            'actors'][self._actor_name]['animations']
        del animations[self._animation_name]

    def on_remove_animation(self):
        self._parent.remove_animation(self._animation_name)

    def on_change_fps(self):
        self.current_conf['fps'] = self.FPS_VALUES[
            self._fps_choice.currentIndex()
        ]

    def on_remove_frame(self):
        if len(self._scroll_areas) > 1:
            if self._current_frame == len(self._scroll_areas) - 1:
                frame_key = self.get_frame_key()
                if frame_key in self.current_conf:
                    del self.current_conf[frame_key]
                self._scroll_areas[self._current_frame].hide()
                del self._scroll_areas[self._current_frame]
                self._current_frame -= 1
                self._frames_list.setCurrentIndex(self._current_frame)
                self._frames_list.removeItem(len(self._scroll_areas))

    def move_image(self, image, gap):
        gap_x, gap_y = gap
        obj = None
        rect = image.geometry()
        for image_obj in self.current_conf[image.frame_key()]:
            if image_obj.get('type', None) != 'conf':
                if image_obj['id'] == image.image_id():
                    obj = image_obj
        if self._move_button.isChecked():
            x, y = rect.x() + gap_x, rect.y() + gap_y
            image.setGeometry(x, y, rect.width(), rect.height())
            obj['x'] = (x - 200.0) / 100.0
            obj['y'] = (y - 200.0) / 100.0
        else:
            width = rect.width() + gap_x
            height = width * rect.height() / rect.width()
            image.setGeometry(rect.x(), rect.y(), width, height)
            obj['width'] = width / 100.0
            obj['height'] = height / 100.0
        self.update_label(obj)

    def update_label(self, image_obj):
        self._pos_label.setText(
            'X : %s\nY : %s\nW : %s\nH : %s' % (
                str(image_obj['x']),
                str(image_obj['y']),
                str(image_obj['width']),
                str(image_obj['height'])
            )
        )

    def on_change_frame(self):
        self._scroll_areas[self._current_frame].hide()
        self._current_frame = self._frames_list.currentIndex()
        frame_key = 'frame_%d' % self._current_frame
        if frame_key in self.current_conf:
            conf = None
            for elem in self.current_conf.get(frame_key, []):
                if elem.get('type', None) == 'conf':
                    conf = elem
                    break
            if conf is None:
                conf = {'type': 'conf'}
                self.current_conf[frame_key].append(conf)
            multiplier = conf.get('multiplier', 1)
        else:
            multiplier = 1
        self._multiplier.setCurrentIndex(multiplier - 1)
        self._scroll_areas[self._current_frame].show()

    def on_add_frame(self):
        if self._current_frame == len(self._scroll_areas) - 1:
            self._scroll_areas[self._current_frame].hide()
            self._current_frame += 1
            frame_label = 'Frame %d' % self._current_frame
            self._scroll_areas[self._current_frame] = QtGui.QScrollArea(self)
            self._scroll_areas[self._current_frame].setGeometry(0, 0, 400, 400)
            self._scroll_areas[self._current_frame].setWidget(
                SpriteGridWidget(self)
            )
            self._frames_list.addItem(frame_label)
            self._frames_list.setCurrentIndex(self._current_frame)
            frame_key = self.get_frame_key()
            if not frame_key in self.current_conf:
                self.current_conf[frame_key] = []

    def get_frame_key(self):
        return 'frame_%d' % self._current_frame

    def remove_image(self, frame_image):
        frame_image.hide()
        index = 0

        for image_obj in self.current_conf[frame_image.frame_key()]:
            if not 'type' in image_obj or image_obj['type'] != 'conf':
                if image_obj['id'] == frame_image.image_id():
                    self.current_conf[frame_image.frame_key()].pop(index)
            index += 1

    def on_new_picture(self):
        file_name = QtGui.QFileDialog.getOpenFileName(
            self, filter='Image (*.png)',
            directory=self.config.get(
                'frame_image_dir', os.path.expanduser('~')
            )
        )
        if file_name:
            from mqme.mainwindow import MainWindow
            file_name = unicode(file_name)
            self.config.set('frame_image_dir', os.path.dirname(file_name))
            MainWindow.queue.put({'name': 'config.save'})
            if not 'pathes' in Config().current_file():
                Config().current_file()['pathes'] = {}
            image_id = str(uuid.uuid1())
            Config().current_file()['pathes'][image_id] = file_name
            frame_key = self.get_frame_key()
            if not frame_key in self.current_conf:
                self.current_conf[frame_key] = []
            frame_image = FrameImage(
                self._scroll_areas[self._current_frame].widget(),
                file_name, image_id, frame_key
            )
            frame_image.show()
            width, height = frame_image.ratio()
            x = 0.5 - (width / 2.0)
            y = 1.0 - height
            self.current_conf[frame_key].append({
                'id': image_id,
                'width': width, 'height': height,
                'x': x, 'y': y
            })
            frame_image.setGeometry(
                200 + x * 100, 200 + y * 100, width * 100, height * 100
            )