Esempio n. 1
0
    def rename(self):
        """renames the selected file or folder"""
        index = self.selectionModel().currentIndex()
        path = self.model.filePath(index)
        if path:
            file_info = QFileInfo(path)

            if file_info.isFile():
                filename = self.rename_dialog("file")

                if filename:
                    q_file = QFile(path)
                    file_info.absolutePath()
                    new_path = os.path.join(file_info.absolutePath(),
                                            str(filename))
                    q_file.rename(new_path)

            elif file_info.isDir():
                filename = self.rename_dialog("directory")

                if filename:
                    directory = QDir(path)
                    file_info.absolutePath()
                    new_path = os.path.join(file_info.absolutePath(),
                                            str(filename))
                    directory.rename(path, new_path)
Esempio n. 2
0
    def fromfile(cls, path):
        """Read a bloom filter from file-object `f' serialized with
        ``BloomFilter.tofile''. """
        f = QFile(path)
        if not f.open(QIODevice.ReadOnly):
            raise ValueError("unable to open file " + path)

        data = QDataStream(f)
        file_fmt = data.readBytes()
        if file_fmt != cls.FILE_FMT:
            raise ValueError('unexpected file format')

        error_rate = data.readFloat()
        num_slices = data.readInt()
        bits_per_slice = data.readInt()
        capacity = data.readInt()
        count = data.readInt()
        bitarray = QBitArray()

        filter = cls(1)  # Bogus instantiation, we will `_setup'.
        filter._setup(error_rate, num_slices, bits_per_slice, capacity, count)
        filter.bitarray = QBitArray()
        data >> filter.bitarray

        return filter
Esempio n. 3
0
    def saveFileAs(self):
        open_file = QFile(str(STATUS.file))
        if open_file == None:
            return

        save_file = self.save_as_dialog(open_file.fileName())
        self.saveFile(save_file)
Esempio n. 4
0
 def reload_dark_style(self):
     f = QFile(":/dark_theme.qss")
     f.open(QFile.ReadOnly | QFile.Text)
     ts = QTextStream(f)
     qss = ts.readAll()
     # f = open(Config.get_resource_path('dark_theme.qss', 'resources/ui'), 'r')
     # qss = f.read()
     self.app.setStyleSheet(qss)
Esempio n. 5
0
def _load_stylesheet(qt_api=''):
    """
    Load the stylesheet based on QtPy abstraction layer environment variable.

    If the argument is not passed, it uses the current QT_API environment
    variable to make the imports of Qt bindings. If passed, it sets this
    variable then make the imports.

    Args:
        qt_api (str): qt binding name to set QT_API environment variable.
                      Default is ''. Possible values are pyside, pyside2
                      pyqt4, pyqt5. Not case sensitive.

    Note:
        - Note that the variable QT_API is read when first imported. So,
          pay attention to the import order.
        - If you are using another abstraction layer, i.e PyQtGraph to do
          imports on Qt things you must set both to use the same Qt
          binding (PyQt, PySide).
        - OS, binding and binding version number, and application specific
          patches are applied in this order.

    Returns:
        str: stylesheet string (css).
    """

    if qt_api:
        os.environ['QT_API'] = qt_api

    # Import is made after setting QT_API
    from qtpy.QtCore import QCoreApplication, QFile, QTextStream
    from qtpy.QtGui import QColor, QPalette

    # Then we import resources - binary qrc content
    from qdarkstyle import style_rc

    # Thus, by importing the binary we can access the resources
    package_dir = os.path.basename(PACKAGE_PATH)
    qss_rc_path = ":" + os.path.join(package_dir, QSS_FILE)

    # It gets the qss file from compiled style_rc that was import
    # not from the file QSS as we are using resources
    qss_file = QFile(qss_rc_path)

    if qss_file.exists():
        qss_file.open(QFile.ReadOnly | QFile.Text)
        text_stream = QTextStream(qss_file)
        stylesheet = text_stream.readAll()
    else:
        stylesheet = ""
        # Todo: check this raise type and add to docs
        raise FileNotFoundError("Unable to find QSS file '{}' "
                                "in resources.".format(qss_rc_path))

    # 4. Apply palette fix. See issue #139
    _apply_application_patches(QCoreApplication, QPalette, QColor)

    return stylesheet
Esempio n. 6
0
    def save(self):
        save_file = QFile(self.filename)

        result = save_file.open(QFile.WriteOnly)
        if result:
            save_stream = QTextStream(save_file)
            save_stream << self.text()

            save_file.close()
    def test_qInitResources(self):
        """
        Test qInitResources.

        qInitResources is run during module import, but might be closed by another test so setup call it.
        """

        icon_file = QFile(':/oi/svg/document.svg')
        self.assertTrue(icon_file.exists())
Esempio n. 8
0
 def save_settings(self) -> None:
     """Save Pyslvs settings (auto save when close event)."""
     if self.prefer.not_save_option:
         f = QFile(self.settings.fileName())
         if f.exists():
             f.remove()
         return
     self.settings.setValue("ENV", self.env)
     for field in fields(self.prefer):  # type: Field
         self.settings.setValue(field.name, getattr(self.prefer, field.name))
Esempio n. 9
0
 def reload_light_style(self):
     if CONFIG['light_theme_is_native']:
         self.set_style_to_stock()
         return
     f = QFile(":/light_theme.qss")
     f.open(QFile.ReadOnly | QFile.Text)
     ts = QTextStream(f)
     qss = ts.readAll()
     # f = open(Config.get_resource_path('light_theme.qss', 'resources/ui'), 'r')
     # qss = f.read()
     self.app.setStyleSheet(qss)
Esempio n. 10
0
    def save(self):
        self.filename = str(STATUS.file)

        save_file = QFile(self.filename)

        result = save_file.open(QFile.WriteOnly)
        if result:
            save_stream = QTextStream(save_file)
            save_stream << self.text()
            save_file.close()
        else:
            print("save error")
Esempio n. 11
0
    def newFile(self):
        """Create a new empty file"""
        path = self.model.filePath(self.rootIndex())
        new_file_path = os.path.join(path, "New File.ngc")

        count = 1
        while os.path.exists(new_file_path):
            new_file_path = os.path.join(path, "New File {}.ngc".format(count))
            count += 1

        new_file = QFile(new_file_path)
        new_file.open(QIODevice.ReadWrite)
Esempio n. 12
0
    def save(self):
        save_file = QFile(self.filename)

        result = save_file.open(QFile.WriteOnly)
        if result:
            LOG.debug("---self.text(): {}".format(self.text()))
            save_stream = QTextStream(save_file)
            save_stream << self.text()
            save_file.close()
            self.text_before_edit = ''
            self.somethingHasChanged.emit(False)
        else:
            LOG.debug("---save error")
Esempio n. 13
0
    def load_file_list(self):
        self.file_list_widget.clear()

        for image_dir in self.file_dirs:
            if not QFile.exists(image_dir):
                continue
            item = QListWidgetItem(image_dir)
            item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
            label_dir = os.path.splitext(image_dir)[0] + '.json'
            if QFile.exists(label_dir):
                item.setCheckState(Qt.Checked)
            else:
                item.setCheckState(Qt.Unchecked)
            self.file_list_widget.addItem(item)
Esempio n. 14
0
    def deleteItem(self):
        """Delete the selected item (either a file or folder)."""
        # ToDo: use Move2Trash, instead of deleting the file
        index = self.selectionModel().currentIndex()
        path = self.model.filePath(index)
        if path:
            file_info = QFileInfo(path)
            if file_info.isFile():
                if not self.ask_dialog("Do you wan't to delete the selected file?"):
                    return
                q_file = QFile(path)
                q_file.remove()

            elif file_info.isDir():
                if not self.ask_dialog("Do you wan't to delete the selected directory?"):
                    return
                directory = QDir(path)
                directory.removeRecursively()
Esempio n. 15
0
    def saveAs(self):
        file_name = self.save_as_dialog(self.filename)

        if file_name is False:
            return

        original_file = QFileInfo(self.filename)
        path = original_file.path()

        new_absolute_path = os.path.join(path, file_name)
        new_file = QFile(new_absolute_path)

        result = new_file.open(QFile.WriteOnly)
        if result:
            save_stream = QTextStream(new_file)
            save_stream << self.text()

            new_file.close()
Esempio n. 16
0
    def saveAs(self):
        file_name = self.save_as_dialog(self.filename)

        if file_name is False:
            print("saveAs file name error")
            return
        self.filename = str(STATUS.file)

        original_file = QFileInfo(self.filename)
        path = original_file.path()

        new_absolute_path = os.path.join(path, file_name)
        new_file = QFile(new_absolute_path)

        result = new_file.open(QFile.WriteOnly)
        if result:
            save_stream = QTextStream(new_file)
            save_stream << self.text()
            new_file.close()
        self.text_before_edit = ''
        self.somethingHasChanged.emit(False)
Esempio n. 17
0
    def saveAs(self):
        #file_name = self.save_as_dialog(self.filename)
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        file_name, _ = QFileDialog.getSaveFileName(self,"Save As","","All Files (*);;NGC Files (*.ngc)", options=options)

        if file_name is False:
            print("saveAs file name error")
            return
        self.filename = str(STATUS.file)

        original_file = QFileInfo(self.filename)
        path = original_file.path()

        new_absolute_path = os.path.join(path, file_name)
        new_file = QFile(new_absolute_path)

        result = new_file.open(QFile.WriteOnly)
        if result:
            save_stream = QTextStream(new_file)
            save_stream << self.text()
            new_file.close()
Esempio n. 18
0
    def updateFrameSheet(self):
        if globals.applied_style == 'light':
            f = QFile(':/frameless-light.qss')
        elif globals.applied_style == 'dark':
            f = QFile(':/frameless-dark.qss')
        else:
            raise RuntimeError(
                'Set the app style theme before instantiating ModernWindow')
        f.open(QIODevice.ReadOnly | QIODevice.Text)
        text = QTextStream(f)
        text.setCodec('UTF-8')
        text = text.readAll()

        self.setStyleSheet(text)
        f.close()
Esempio n. 19
0
    def save(self):
        reload_file = True
        self.filename = str(STATUS.file)
        # determine of have a file name
        if self.filename == '':
            reload_file = False
            self.filename = '/tmp/gcode_tmp.ngc'

        # save out the file
        save_file = QFile(self.filename)
        result = save_file.open(QFile.WriteOnly)
        if result:
            save_stream = QTextStream(save_file)
            save_stream << self.text()
            save_file.close()
            # file save worked, now either load fresh or reload
            if reload_file:
                reLoadProgram()
            else:
                loadProgram(self.filename)

        else:
            print("save error")
Esempio n. 20
0
    def saveFile(self, save_file_name=None):
        if save_file_name == None:
            save_file = QFile(str(STATUS.file))
        else:
            save_file = QFile(str(save_file_name))

        result = save_file.open(QFile.WriteOnly)
        if result:
            LOG.debug(f'---Save file: {save_file.fileName()}')
            save_stream = QTextStream(save_file)
            save_stream << self.toPlainText()
            save_file.close()
        else:
            LOG.debug("---save error")
Esempio n. 21
0
    def transferFile(self, src_path):
        dest_path = self.model.filePath(self.rootIndex())

        src_file = QFile()
        src_file.setFileName(src_path)

        src_file_info = QFileInfo(src_path)

        dst_path = os.path.join(dest_path, src_file_info.fileName())

        src_file.copy(dst_path)
    def test_qCleanupResources(self):
        """
        Test qCleanupResources.
        """

        file_before = QFile(':/oi/svg/document.svg')
        self.assertTrue(file_before.exists())

        qCleanupResources()

        file_after = QFile(':/oi/svg/document.svg')
        self.assertFalse(file_after.exists())
Esempio n. 23
0
 def tofile(self, path):
     """Write the bloom filter to file object `f'. Underlying bits
     are written as machine values. This is much more space
     efficient than pickling the object."""
     # f.write(pack(self.FILE_FMT, self.error_rate, self.num_slices,
     #              self.bits_per_slice, self.capacity, self.count))
     # f.write(self.bitarray.bits)
     f = QFile(path)
     if f.open(QIODevice.WriteOnly):
         out = QDataStream(f)
         out.writeBytes(self.FILE_FMT)
         out.writeFloat(self.error_rate)
         out.writeInt(self.num_slices)
         out.writeInt(self.bits_per_slice)
         out.writeInt(self.capacity)
         out.writeInt(self.count)
         out << self.bitarray
         f.flush()
         f.close()
Esempio n. 24
0
    def load_file(self, image_dir):
        self.reset()
        self.pixmap = QPixmap(image_dir)
        self.cv2_image = cv2.imread(image_dir)
        self.label_dir = os.path.splitext(image_dir)[0] + '.json'
        if QFile.exists(self.label_dir):
            with open(self.label_dir) as json_file:
                data = json.load(json_file)
                self.objects = []
                for obj in data['objects']:
                    points = []
                    for point in obj['points']:
                        points.append(QPointF(point['x'], point['y']))
                    if (obj['type'] == 'rectangle'):
                        self.objects.append(Rectangle(points, obj['label']))
                    elif (obj['type'] == 'polygon'):
                        self.objects.append(Polygon(points, obj['label']))
                self.cur_object = len(self.objects) - 1
                self.parent.load_object_list(self.objects)
                self.parent.object_list_widget.setCurrentRow(self.cur_object)

        self.repaint()
Esempio n. 25
0
    def copyRecursively(self, src, tgt):
        src_info = QFileInfo(src)
        if src_info.isDir():
            tgt_dir = QDir(tgt)
            if not tgt_dir.mkdir(src_info.fileName()):
                return False
            src_dir = QDir(src)
            fnames = src_dir.entryList(QDir.Files | QDir.Dirs
                                       | QDir.NoDotAndDotDot | QDir.Hidden
                                       | QDir.System)
            for fname in fnames:
                new_src = os.path.join(src, fname)
                new_tgt = os.path.join(tgt, src_info.fileName())
                if not self.copyRecursively(new_src, new_tgt):
                    return False

        elif src_info.isFile():
            fname = src_info.fileName()
            if not QFile.copy(src, os.path.join(tgt, fname)):
                return False

        return True
def _apply_base_theme(app):
    """ Apply base theme to the application.

        Args:
            app (QApplication): QApplication instance.
    """

    if QT_VERSION < (5,):
        app.setStyle('plastique')
    else:
        app.setStyle('Fusion')

    f = QFile(':/style.qss')
    f.open(QIODevice.ReadOnly | QIODevice.Text)
    text = QTextStream(f)
    text.setCodec('UTF-8')
    app.setStyleSheet(text.readAll())
    f.close()
Esempio n. 27
0
def main():
    app = QApplication(sys.argv)

    app.setWindowIcon(QIcon(':/icons/app.svg'))

    fontDB = QFontDatabase()
    fontDB.addApplicationFont(':/fonts/Roboto-Regular.ttf')
    app.setFont(QFont('Roboto'))

    f = QFile(':/style.qss')
    f.open(QFile.ReadOnly | QFile.Text)
    app.setStyleSheet(QTextStream(f).readAll())
    f.close()

    translator = QTranslator()
    translator.load(':/translations/' + QLocale.system().name() + '.qm')
    app.installTranslator(translator)

    mw = MainWindow()
    mw.show()

    sys.exit(app.exec_())
Esempio n. 28
0
def _load_stylesheet(qt_api='', palette=None):
    """
    Load the stylesheet based on QtPy abstraction layer environment variable.

    If the argument is not passed, it uses the current QT_API environment
    variable to make the imports of Qt bindings. If passed, it sets this
    variable then make the imports.

    Args:
        qt_api (str): qt binding name to set QT_API environment variable.
                      Default is ''. Possible values are pyside, pyside2
                      pyqt4, pyqt5. Not case sensitive.
        palette (Palette): Palette class that inherits from Palette.

    Note:
        - Note that the variable QT_API is read when first imported. So,
          pay attention to the import order.
        - If you are using another abstraction layer, i.e PyQtGraph to do
          imports on Qt things you must set both to use the same Qt
          binding (PyQt, PySide).
        - OS, binding and binding version number, and application specific
          patches are applied in this order.

    Returns:
        str: stylesheet string (css).
    """

    if qt_api:
        os.environ['QT_API'] = qt_api

    # Import is made after setting QT_API
    from qtpy.QtCore import QCoreApplication, QFile, QTextStream
    from qtpy.QtGui import QColor, QPalette
    from qtpy import QT_VERSION

    # Then we import resources - binary qrc content
    if palette is None:
        from qdarkstyle.dark import style_rc
        palette = DarkPalette
        _set_global_paths('dark')
    elif palette.ID == 'dark':
        from qdarkstyle.dark import style_rc
        palette = DarkPalette
        _set_global_paths('dark')
    elif palette.ID == 'light':
        from qdarkstyle.light import style_rc
        palette = LightPalette
        _set_global_paths('light')
    else:
        print("Not recognized ID for palette! Exiting!")
        sys.exit(1)

    # Thus, by importing the binary we can access the resources
    package_dir = os.path.basename(PACKAGE_PATH)
    qss_rc_path = ":" + os.path.join(package_dir, palette.ID, QSS_FILE)

    _logger.debug("Reading QSS file in: %s" % qss_rc_path)

    # It gets the qss file from compiled style_rc that was imported,
    # not from the file QSS as we are using resources
    qss_file = QFile(qss_rc_path)

    if qss_file.exists():
        qss_file.open(QFile.ReadOnly | QFile.Text)
        text_stream = QTextStream(qss_file)
        stylesheet = text_stream.readAll()
        _logger.info("QSS file sucessfuly loaded.")
    else:
        stylesheet = ""
        # Todo: check this raise type and add to docs
        raise FileNotFoundError("Unable to find QSS file '{}' "
                                "in resources.".format(qss_rc_path))

    _logger.debug("Checking patches for being applied.")

    # Todo: check execution order for these functions
    # 1. Apply OS specific patches
    stylesheet += _apply_os_patches(palette)

    # 2. Apply binding specific patches
    stylesheet += _apply_binding_patches()

    # 3. Apply binding version specific patches
    stylesheet += _apply_version_patches(QT_VERSION)

    # 4. Apply palette fix. See issue #139
    _apply_application_patches(QCoreApplication, QPalette, QColor, palette)

    return stylesheet
Esempio n. 29
0
 def get_ui_qfile(self, name):
     file = QFile(':/ui/{}'.format(name))
     if not file.exists():
         raise FileNotFoundError('ui file not found: ":/ui/{}"'.format(name))
     file.open(QFile.ReadOnly)
     return file
Esempio n. 30
0
def _load_stylesheet(qt_api='', style=''):
    """
    Load the stylesheet based on QtPy abstraction layer environment variable.

    If the argument is not passed, it uses the current QT_API environment
    variable to make the imports of Qt bindings. If passed, it sets this
    variable then make the imports.

    Args:
        qt_api (str): qt binding name to set QT_API environment variable.
                      Default is ''. Possible values are pyside2,
                      pyqt5. Not case sensitive.

    Note:
        - Note that the variable QT_API is read when first imported. So,
          pay attention to the import order.
        - OS, binding and binding version number, and application specific
          patches are applied in this order.

    Returns:
        str: stylesheet string (css).
    """

    if qt_api:
        os.environ['QT_API'] = qt_api

    # Import is made after setting QT_API
    from qtpy.QtCore import QCoreApplication, QFile, QTextStream
    from qtpy.QtGui import QColor, QPalette
    from qtpy import QT_VERSION

    # Search for style in styles directory
    style_dir = None

    available_styles = getAvailableStyles()
    _logger.debug(f"Available styles: {available_styles}")
    for stl in available_styles:
        if style.lower() == stl.lower():
            style_dir = stl
            break

    if style_dir is None:
        stylesheet = ""
        raise FileNotFoundError("Style " + style + " does not exists")

    # check if any style_rc was loaded before
    if "style_rc" in sys.modules:
        _logger.info("Found already imported style in sys.modules")

        # use qCleanupResources to remove all resource files
        global style_rc  # noqa
        style_rc.qCleanupResources()

        # remove imported modules
        for x in [
                module for module in sys.modules
                if module.startswith("style_rc")
        ]:
            del sys.modules[x]
            del style_rc

        # remove path to previously imported style from sys.path
        for stylepath in [
                path for path in sys.path if any(
                    style for style in getAvailableStyles() if style in path)
        ]:
            sys.path.remove(stylepath)
        _logger.debug("Removed all imported styles")

    try:
        _logger.debug("Loading style from directory: " + style_dir)
        old_working_dir = os.getcwd()
        # set style directory
        package_dir = os.path.join(STYLES_PATH, style_dir)
        os.chdir(package_dir)

        # append directory to sys.path and import style_rc
        sys.path.append(package_dir)
        try:
            import style_rc  # noqa
            # get palette
            palette = style_rc.palette

        except ModuleNotFoundError:
            raise ModuleNotFoundError(
                "Failed to import style_rc from directory: {}".format(
                    package_dir))

        finally:
            os.chdir(old_working_dir)

    except FileExistsError:
        raise FileNotFoundError("Missing style_rc.py file")

    _logger.info("Style resources imported successfully")

    # Thus, by importing the binary we can access the resources
    package_dir = os.path.basename(PACKAGE_PATH)
    qss_rc_path = ":" + os.path.join(package_dir, QSS_FILE)

    _logger.debug("Reading QSS file in: %s", qss_rc_path)

    # It gets the qss file from compiled style_rc that was import
    # not from the file QSS as we are using resources
    qss_file = QFile(qss_rc_path)

    if qss_file.exists():
        qss_file.open(QFile.ReadOnly | QFile.Text)
        text_stream = QTextStream(qss_file)
        stylesheet = text_stream.readAll()
        _logger.info("QSS file sucessfuly loaded.")
    else:
        stylesheet = ""
        # Todo: check this raise type and add to docs
        raise FileNotFoundError("Unable to find QSS file '{}' "
                                "in resources.".format(qss_rc_path))

    _logger.debug("Checking patches for being applied.")

    # Todo: check execution order for these functions
    # 1. Apply OS specific patches
    stylesheet += _apply_os_patches(palette)

    # 2. Apply binding specific patches
    stylesheet += _apply_binding_patches()

    # 3. Apply binding version specific patches
    stylesheet += _apply_version_patches(QT_VERSION)

    # 4. Apply palette fix. See issue #139
    _apply_application_patches(palette, QCoreApplication, QPalette, QColor)

    return stylesheet
    def _update_file_menu(self):
        """
            Set up the File menu and update the menu with recent files
        """
        self.file_menu.clear()

        newAction = QAction("&New Reduction...", self)
        newAction.setShortcut("Ctrl+N")
        newAction.setStatusTip("Start a new reduction")
        newAction.triggered.connect(self._new)

        openAction = QAction("&Open...", self)
        openAction.setShortcut("Ctrl+O")
        openAction.setStatusTip("Open an XML file containing reduction parameters")
        openAction.triggered.connect(self._file_open)

        saveAsAction = QAction("Save as...", self)
        saveAsAction.setStatusTip("Save the reduction parameters to XML")
        saveAsAction.triggered.connect(self._save_as)

        saveAction = QAction("&Save...", self)
        saveAction.setShortcut("Ctrl+S")
        saveAction.setStatusTip("Save the reduction parameters to XML")
        saveAction.triggered.connect(self._save)

        exportAction = QAction("&Export...", self)
        exportAction.setShortcut("Ctrl+E")
        exportAction.setStatusTip("Export to python script for Mantid")
        exportAction.triggered.connect(self._export)

        quitAction = QAction("&Quit", self)
        quitAction.setShortcut("Ctrl+Q")
        quitAction.triggered.connect(self.close)

        self.file_menu.addAction(newAction)
        self.file_menu.addAction(openAction)
        self.file_menu.addAction(saveAction)
        self.file_menu.addAction(saveAsAction)
        self.file_menu.addAction(exportAction)
        self.file_menu.addSeparator()

        if self.general_settings.debug:
            clearAction = QAction("&Clear settings and quit", self)
            clearAction.setStatusTip("Restore initial application settings and close the application")
            clearAction.triggered.connect(self._clear_and_close)
            self.file_menu.addAction(clearAction)

        self.file_menu.addAction(quitAction)

        # TOOLS menu
        instrAction = QAction("Change &instrument...", self)
        instrAction.setShortcut("Ctrl+I")
        instrAction.setStatusTip("Select a new instrument")
        instrAction.triggered.connect(self._change_instrument)

        debug_menu_item_str = "Turn debug mode ON"
        if self.general_settings.debug:
            debug_menu_item_str = "Turn debug mode OFF"
        debugAction = QAction(debug_menu_item_str, self)
        debugAction.setStatusTip(debug_menu_item_str)
        debugAction.triggered.connect(self._debug_mode)

        self.tools_menu.clear()
        self.tools_menu.addAction(instrAction)
        self.tools_menu.addAction(debugAction)

        recent_files = []
        for fname in self._recent_files:
            if fname != self._filename and QFile.exists(fname) and fname not in recent_files:
                recent_files.append(fname)

        if len(recent_files)>0:
            self.file_menu.addSeparator()
            for i, fname in enumerate(recent_files):
                action = QAction("&%d %s" % (i+1, QFileInfo(fname).fileName()), self)
                action.setData(fname)
                action.triggered.connect(self.open_file)
                self.file_menu.addAction(action)