HOME = os.path.expanduser("~")
    PATH = os.path.realpath(os.path.dirname(sys.argv[0]))
    PATH = os.path.join(os.path.realpath(os.path.dirname(__file__)), "..")
EDIS = os.path.join(HOME, ".edis")
CONFIGURACION = os.path.join(EDIS, "edis_config.ini")
LOG = os.path.join(EDIS, "edis_log.log")
PROJECT_DIR = os.path.join(HOME, "EdisProjects") DEBUG = log.debug
class EdisFile(QObject):
    def __init__(self, filename=''):
    def filename(self):
    def is_new(self):
    def read(self):
    def write(self, content, new_filename=''):
    def run_system_watcher(self):
    def stop_system_watcher(self):
    def _on_file_changed(self, filename): class EdisIOError(Exception):
    """ IO Exception""" IS_LINUX = True
    DEFAULT_FONT = "Monospace"
    IS_LINUX = False
    DEFAULT_FONT = "Lucida Console"
COMPILER_FLAGS = "-Wall"
BRACES = {'[': ']', '(': ')'}
QUOTES = ["''", '""']
SETTINGS = {
    'terminal': 'xterm',
    'window/size': QSize(-1, -1),
    'window/position': QPoint(-1, -1),
    'window/show-maximized': True,
    'window/store-size': True,
    'window/style-sheet': 'Edark',
    'general/confirm-exit': True,
    'editor/complete-brace': True,
    'editor/complete-bracket': True,
    'editor/complete-paren': True,
    'editor/complete-single-quote': False,
    'editor/complete-double-quote': False,
    'editor/completion': True,
    'editor/completion-threshold': 2,
    'editor/completion-document': True,
    'editor/completion-keywords': True,
    'editor/completion-cs': False,
    'editor/completion-replace-word': False,
    'editor/completion-single': False,
    'editor/usetabs': False,
    'editor/scheme': 'dark',
    'editor/show-line-number': True,
    'editor/match-brace': True,
    'editor/mark-change': True,
    'editor/eof': False,
    'editor/show-caret-line': True,
    'editor/show-margin': True,
    'editor/width-margin': 79,
    'editor/cursor': 1,  # 0: invisilbe; 1: línea; 2: bloque
    'editor/caret-width': 3,
    'editor/cursor-period': 250,
    'editor/indent': True,
    'editor/width-indent': 4,
    'editor/show-guides': False,
    'editor/show-tabs-spaces': True,
    'editor/wrap-mode': False,
    'editor/font': "",
    'editor/size-font': 12,
    'editor/style-checker': False,
    'editor/minimap': False,
    #'editor/minimap-animation': False,
    'general/language': "",
    'general/show-splash': True,
    'general/show-start-page': True,
    'general/load-files': True,
    'general/check-updates': True
    }
def load_settings():
def get_setting(key):
def set_setting(key, value): REGEX_STRUCT = re.compile("(typedef struct|struct)\s+\w+")
    BRACE = {
        '(': ')',
        '[': ']'
        }
    QUOTE = {
        "'": "'",
        '"': '"'
        }
    MARKER_MODIFIED = 3
    MARKER_SAVED = 4
    WORD_INDICATOR = 0
    WARNING_INDICATOR = 1
class Editor(base.Base):
    def __init__(self, obj_file):
    def filename(self):
    def is_modified(self):
    def load_font(self, fuente, tam):
    def load_checker(self, activated=True):
    def set_brace_matching(self):
    def update_options(self):
    def update_sidebar(self):
    def show_line_numbers(self):
    def update_margin(self):
    def update_indentation(self):
    def mark_words(self, palabras):
    def active_code_completion(self, enabled=True):
    def _add_marker_modified(self):
    def _show_violations(self):
    def _text_under_cursor(self):
    def mouseReleaseEvent(self, e):
    def mouseMoveEvent(self, event):
    def keyReleaseEvent(self, event):
    def keyPressEvent(self, event):
    def _complete_quote(self, event):
    def _complete_brace(self, event):
    def _complete_key(self, event):
    def resizeEvent(self, e):
    def comment(self):
    def uncomment(self):
    def to_lowercase(self):
    def to_uppercase(self):
    def to_title(self):
    def duplicate_line(self):
    def delete_line(self):
    def indent_more(self):
    def indent_less(self):
    def move_down(self):
    def move_up(self):
    def reemplazar_tabs_por_espacios(self):
    def saved(self):
    def dropEvent(self, event): class Edis(QMainWindow):
    """
    Clase principal:
        Esta clase es la encargada de instalar todos los servicios del IDE,
        las instancias de los componentes que cumplen funciones críticas están
        disponibles desde los atributos de clase.


    """

    __COMPONENTS = {}
    __LATERAL = {}

    def __init__(self):
        QMainWindow.__init__(self)
        # Esto para tener widgets laterales en full height,
        window = QMainWindow(self)
        self.setWindowTitle('{' + ui.__edis__ + '}')
        self.setMinimumSize(750, 500)
        # Se cargan las dimensiones de la ventana
        if settings.get_setting('window/show-maximized'):
            self.setWindowState(Qt.WindowMaximized)
        else:
            size = settings.get_setting('window/size')
            position = settings.get_setting('window/position')
            self.resize(size)
            self.move(position)
        # Toolbars
        self.toolbar = QToolBar(self)
        self.toolbar.setObjectName("toolbar")
        toggle_action = self.toolbar.toggleViewAction()
        toggle_action.setText(self.tr("Toolbar"))
        self.toolbar.setIconSize(QSize(24, 24))
        self.toolbar.setToolButtonStyle(Qt.ToolButtonIconOnly)
        self.addToolBar(Qt.RightToolBarArea, self.toolbar)
        Edis.load_component("toolbar", self.toolbar)
        # Animated property
        self.setDockOptions(QMainWindow.AnimatedDocks)
        # Menú
        menu_bar = self.menuBar()
        self.setup_menu(menu_bar)
        # Barra de estado
        self.status_bar = Edis.get_component("status_bar")
        self.setStatusBar(self.status_bar)
        # Widget central
        central = self._load_ui(window)
        window.setCentralWidget(central)
        window.setWindowFlags(Qt.Widget)
        self.setCentralWidget(window)

        Edis.load_component("edis", self)
        # Comprobar nueva versión
        if settings.get_setting('general/check-updates'):
            self.noti = system_tray.NotificacionActualizacion()
            self.noti.show()

    @classmethod
    def load_component(cls, name, instance):
        """ Carga la instancia de un componente """

        cls.__COMPONENTS[name] = instance

    @classmethod
    def get_component(cls, name):
        """ Devuelve la instancia de un componente """

        return cls.__COMPONENTS.get(name, None)

    @classmethod
    def load_lateral(cls, name, instance):
        """ Carga un componente lateral """

        cls.__LATERAL[name] = instance

    @classmethod
    def get_lateral(cls, name):
        """ Devuelve la instancia de un componente lateral """

        return cls.__LATERAL.get(name, None)

    def setup_menu(self, menu_bar):
        """ Instala la barra de menú (QMenuBar), acciones, shortcuts, toolbars
        y conexiones de cada QAction.
        """

        from src.ui import actions

        menubar_items = [
            self.tr("&Archivo"),
            self.tr("&Editar"),
            self.tr("&Ver"),
            self.tr("&Buscar"),
            self.tr("Có&digo"),
            self.tr("&Construcción"),
            self.tr("A&yuda")
            ]
        menu_items = {}
        toolbar_actions = {}
        editor_container = Edis.get_component("principal")
        #shortcuts = keymap.KEYMAP
        #keymap = keymap.get_keymap
        toolbar_items = TOOLBAR_ITEMS
        for i, m in enumerate(menubar_items):
            menu = menu_bar.addMenu(m)
            menu_items[i] = menu
        for i, _actions in enumerate(actions.ACTIONS):
            for action in _actions:
                obj = editor_container
                menu_name = menu_items[i]
                name = action.get('name', None)
                connection = action.get('connection', None)
                shortcut = action.get('shortcut', None)
                icon_action = action.get('icon', None)
                if icon_action is not None:
                    icon = QIcon(":image/%s" % icon_action)
                else:
                    # FIXME: No depender de shortcut
                    icon = QIcon(":image/%s" % shortcut)
                separator = action.get('separator', False)
                subm = action.get('menu', False)
                if subm:
                    # Archivos recientes
                    submenu = menu_name.addMenu(name)
                    Edis.load_component("menu_recent_file", submenu)
                    continue
                qaction = menu_name.addAction(name)
                qaction.setIcon(icon)
                if shortcut is not None:
                    #qaction.setShortcut(shortcuts[shortcut])
                    qaction.setShortcut(keymap.get_keymap(shortcut))
                if connection.startswith('edis'):
                    obj = self
                    connection = connection.split('.')[-1]
                slot = getattr(obj, connection, None)
                if hasattr(slot, "__call__"):
                    self.connect(qaction, SIGNAL("triggered()"), slot)
                if separator:
                    menu_name.addSeparator()
                if shortcut in toolbar_items:
                    toolbar_actions[shortcut] = qaction
        # Load toolbar
        for item in toolbar_items:
            action = toolbar_actions.get(item, None)
            if action is None:
                self.toolbar.addSeparator()
            else:
                self.toolbar.addAction(action)

    def _load_ui(self, window):
        """ Carga el componente principal (Editor Container), componentes
        laterales y la salida del compilador.
        """

        editor_container = Edis.get_component("principal")
        # Lateral
        tab_container = Edis.get_component("tab_container")
        lateral_widgets = ["symbols", "project", "explorer"]
        for widget in lateral_widgets:
            method = getattr(tab_container, "load_%s_widget" % widget)
            obj = Edis.get_lateral(widget)
            method(obj)
        self.addDockWidget(Qt.LeftDockWidgetArea, tab_container)
        output_widget = Edis.get_component("output")
        output_widget.hide()
        window.addDockWidget(Qt.BottomDockWidgetArea, output_widget)
        if settings.get_setting('general/show-start-page'):
            editor_container.add_start_page()

        # Conexiones
        editor_container.savedFile['QString'].connect(self._show_status)
        editor_container.fileChanged['QString'].connect(self._change_title)
        editor_container.editor_widget.allFilesClosed.connect(self._all_closed)
        output_widget.goToLine[int].connect(editor_container.go_to_line)

        return editor_container

    def _show_status(self, msg):
        self.status_bar.show_message(msg)

    def _all_closed(self):
        """ Limpia el título de la ventana """

        self.setWindowTitle('{' + ui.__edis__ + '}')

    def _change_title(self, title):
        """ Cambia el título de la ventana (filename - {EDIS}) """

        title = os.path.basename(title)
        self.setWindowTitle(title + ' - ' + '{' + ui.__edis__ + '}')

    def report_bug(self):
        """ Se abre la url para reportar un bug """

        webbrowser.open_new(ui.__bug_link__)

    def show_hide_toolbar(self):
        """ Cambia la visibilidad de la barra de herramientas """

        if self.toolbar.isVisible():
            self.toolbar.hide()
        else:
            self.toolbar.show()

    def show_hide_lateral(self):
        """ Cambia la visibilidad del dock lateral """

        lateral_widget = Edis.get_component("tab_container")
        if not lateral_widget.isVisible():
            lateral_widget.show()
        else:
            lateral_widget.hide()

    def show_hide_all(self):
        """ Oculta todo excepto la barra de menú y el editor """

        toolbar = Edis.get_component("toolbar")
        status_bar = Edis.get_component("status_bar")
        output = Edis.get_component("output")
        lateral = Edis.get_component("tab_container")
        widgets = [output, toolbar, status_bar, lateral]
        if (output.isVisible() or toolbar.isVisible() or
           status_bar.isVisible() or lateral.isVisible()):
            for widget in widgets:
                widget.hide()
        else:
            for widget in widgets:
                widget.show()

    def show_full_screen(self):
        """ Cambia a modo FullScreen """

        if self.isFullScreen():
            self.showNormal()
        else:
            self.showFullScreen()

    def show_hide_output(self):
        """ Cambia la visibilidad de la salida del compilador """

        output = Edis.get_component("output")
        if output.isVisible():
            output.hide()
        else:
            output.show()

    def load_files_and_projects(self, files, recents_files, projects):
        """ Carga archivos al editor desde la última sesión y actualiza el menú
        de archivos recientes.
        """

        editor_container = Edis.get_component("principal")
        for _file in files:
            if file_manager.file_exists(_file):
                editor_container.open_file(_file)
        editor_container.update_recents_files(recents_files)
        for project in projects:
            editor_container.open_project(project)

    def about_qt(self):
        """ Muestra el díalogo acerca de Qt """

        QMessageBox.aboutQt(self)

    def about_edis(self):
        from src.ui.dialogs import about
        dialog = about.AcercaDe(self)
        dialog.exec_()

    def closeEvent(self, event):
        """
        Éste médoto es llamado automáticamente por Qt cuando se
        cierra la aplicación, guarda algunas configuraciones como posición y
        tamaño de la ventana, archivos, etc.

        """
        DEBUG("Exiting...")
        editor_container = Edis.get_component("principal")
        if editor_container.check_files_not_saved() and \
                settings.get_setting('general/confirm-exit'):
            files_not_saved = editor_container.files_not_saved()
            dialog = unsaved_files.DialogSaveFiles(
                files_not_saved, editor_container, self)
            dialog.exec_()
            if dialog.ignorado():
                event.ignore()
        if settings.get_setting('window/store-size'):
            if self.isMaximized():
                settings.set_setting('window/show-maximized', True)
            else:
                settings.set_setting('window/show-maximized', False)
                settings.set_setting('window/size', self.size())
                settings.set_setting('window/position', self.pos())
        opened_files = editor_container.opened_files()
        settings.set_setting('general/files', opened_files)
        settings.set_setting('general/recents-files',
                             editor_container.get_recents_files())
        projects = editor_container.get_open_projects()
        settings.set_setting('general/projects', projects) class PopupBusqueda(base_dialog.BaseDialog):
    def __init__(self, weditor):
    def _find(self):
    def _find_next(self):
    def _find_previous(self):
    def word(self): class ReplaceWidget(QDialog):
    def __init__(self):
    def _find(self):
    def _find_next(self):
    def _find_previous(self):
    def _replace(self):
    def _replace_all(self):
    def _state_change(self, value):
    def word(self):
    def word_replace(self):
    def showEvent(self, event): class GoToLineDialog(base_dialog.BaseDialog):
    def __init__(self, editor):
    def _go(self): class FileSelector(QDialog):
    def __init__(self, parent=None):
    def _load_files(self):
    def _update_label(self):
    def _open_file(self, item):
    def showEvent(self, event): class FileProperty(QDialog):
    def __init__(self, editor, parent=None):
    def get_type(self, filename):
    def get_size(self, filename):
    def get_comment_spaces(self, editor):
    def get_modification(self, filename): class NewProjectDialog(QWizard):
class IntroductionPage(QWizardPage):
class FinishPage(QWizardPage):
    def __init__(self, parent=None):
    def done(self, result):
    def __init__(self):
    def isComplete(self):
    def _update_location(self, button_id):
    def _on_project_name_changed(self, text):
    def __init__(self):
    def template(self): class CodePastingDialog(QDialog):
    def __init__(self, parent=None, code=''):
    def _emit_data(self):
    def _paste_result(self):
    def _set_editor_style(self, editor):
    def resizeEvent(self, event): class EditorWidget(QWidget):
class ComboContainer(QWidget):
    def __init__(self):
    def add_widget(self, widget):
    def add_item_combo(self, text):
    def remove_item_combo(self, index):
    def change_item(self, index):
    def current_widget(self):
    def current_index(self):
    def widget(self, index):
    def count(self):
    def close_file(self):
    def close_file_project(self, widget, index):
    def close_all(self):
    def editor_modified(self, value):
    def _add_to_recent(self, filename):
    def check_files_not_saved(self):
    def files_not_saved(self):
    def opened_files(self):
    def remove_widget(self, widget, index):
    def add_symbols(self, symbols):
    def __init__(self, parent=None):
    def update_cursor_position(self, line, row, lines):
    def _show_dialog_go_to_line(self, event):
    def _load_menu_combo_file(self, point):
    def _go_to_symbol(self, index):
    def _show_icon_checker(self, value):
    def _close_current_file(self):
    def set_modified(self, weditor, index, modified):
    def add_symbols_combo(self, symbols):
    def move_to_symbol(self, line): TEXTS = [
    "Abre un archivo con Ctrl+O",
    "Cambia de Editor con Ctrl+M",
    "Crea un nuevo Proyecto con Ctrl+Shift+N",
    "Busca texto en el código con Ctrl+F",
    "Salta a una línea y/o columna con Ctrl+J",
    "Reemplaza texto con Ctrl+H",
    "Comparte el código con Ctrl+P",
    "Compila el código con Ctrl+B",
    "Compila y Ejecuta con Ctrl+F10",
    "\tEncontraste un problema?\nRepórtalo desde el menú Ayuda",
    "Selecciona un texto y presiona TAB para indentar",
    "Comenta una o más líneas con Ctrl+G",
    "Explora el código desde el Árbol de Símbolos",
    "Oculta todos los widgets con F11"
    ]
WELCOME = "Bienvenido a Edis!"
class StartPage(QWidget):
    def __init__(self):
    def _show_welcome_text(self):
    def _show_text(self): FORMAT = "%(asctime)s %(name)10s:%(funcName)s:%(lineno)s " \
              "%(levelname)10s %(message)10s"
FORMAT_TIME = "%y-%m-%d %H:%M:%S"
FILE = paths.LOG
class Logger(object):
    def __init__(self):
    def get_logger(self, name):
def get_logger(name):
import os
import json
from PyQt4.QtGui import (
    QWidget,
    QVBoxLayout,
    QFileDialog,
    QMessageBox,
    QStackedWidget
    )
from PyQt4.QtCore import (
    SIGNAL,
    QFileInfo,
    pyqtSignal
    )
from src.core import (
    paths,
    object_file
    )
from src.core.exceptions import EdisIOError
from src.core import settings
from src.ui.editor import editor
from src.ui.main import Edis
from src.ui.widgets import (
    find_popup,
    replace_widget,
    goto_line_widget,
    file_selector
    )
from src.ui.dialogs import (
    file_properties,
    new_project,
    code_pasting_dialog
    )
from src.ui.containers import editor_widget
from src.ui import start_page
from src.core import logger
        from src.ui.widgets.pyborita import pyborita_widget
        self.editor_widget.editor_modified(value)

    def _file_saved(self, filename):
        self.editor_widget.editor_modified(False)
        self.emit(SIGNAL("updateSymbols(QString)"), filename)

    def change_widget(self, index):
        weditor = self.get_active_editor()
        self.editor_widget.combo.combo_file.setCurrentIndex(index)
        if weditor is not None and not weditor.obj_file.is_new:
            self.emit(SIGNAL("updateSymbols(QString)"), weditor.filename)
            self.emit(SIGNAL("fileChanged(QString)"), weditor.filename)
            weditor.setFocus()

    def create_editor(self, obj_file=None, filename=""):
        if obj_file is None:
            obj_file = object_file.EdisFile(filename)
        self.stack.addWidget(self.editor_widget)
        # Quito la página de inicio, si está
        _start_page = self.stack.widget(0)
        if isinstance(_start_page, start_page.StartPage):
            self.remove_widget(_start_page)
            # Detengo el tiimer
            _start_page.timer.stop()
        weditor = editor.Editor(obj_file)
        self.editor_widget.add_widget(weditor)
        self.editor_widget.add_item_combo(obj_file.filename)
        lateral = Edis.get_component("tab_container")
        if not lateral.isVisible():
            lateral.show()

        # Conexiones
        self.connect(obj_file, SIGNAL("fileChanged(PyQt_PyObject)"),
                     self._file_changed)
        self.connect(weditor, SIGNAL("cursorPositionChanged(int, int)"),
                     self.update_cursor)
        self.connect(weditor, SIGNAL("modificationChanged(bool)"),
                     self._file_modified)
        self.connect(weditor, SIGNAL("fileSaved(QString)"),
                     self._file_saved)
        self.connect(weditor, SIGNAL("linesChanged(int)"),
                     self.editor_widget.combo.move_to_symbol)
        self.connect(weditor, SIGNAL("dropEvent(PyQt_PyObject)"),
                     self._drop_editor)
        self.emit(SIGNAL("fileChanged(QString)"), obj_file.filename)

        weditor.setFocus()

        return weditor

    def _file_changed(self, obj_file):
        filename = obj_file.filename
        flags = QMessageBox.Yes
        flags |= QMessageBox.No
        result = QMessageBox.information(self, self.tr("Monitoreo de Archivo"),
                                         self.tr("El archivo <b>{0}</b> fué "
                                         "modificado fuera de Edis. "
                                         "<br><br> Quieres recar"
                                         "garlo?".format(filename)), flags)
        if result == QMessageBox.No:
            return
        self.reload_file(obj_file)

    def reload_file(self, obj_file=None):
        weditor = self.get_active_editor()
        if weditor is None:
            return
        if obj_file is None:
            obj_file = weditor.obj_file
        content = obj_file.read()
        if weditor.is_modified:
            result = QMessageBox.information(self, self.tr(
                "Archivo no guardado!"),
                self.tr("Seguro que quieres recargar el archivo <b>{0}</b>?"
                        "<br><br>"
                        "Se perderán los cambios no guardados.").format(
                            obj_file.filename),
                QMessageBox.Cancel | QMessageBox.Yes)
            if result == QMessageBox.Cancel:
                return
        weditor.setText(content)
        weditor.markerDeleteAll()
        weditor.setModified(False)

    def open_file(self, filename="", cursor_position=None):
        filter_files = "Archivos C(*.cpp *.c);;ASM(*.s);;HEADERS(*.h);;(*.*)"
        if not filename:
            working_directory = os.path.expanduser("~")
            weditor = self.get_active_editor()
            if weditor and weditor.filename:
                working_directory = self._last_folder(weditor.filename)
            filenames = QFileDialog.getOpenFileNames(self,
                                                     self.tr("Abrir Archivo"),
                                                     working_directory,
                                                     filter_files)
        else:
            filenames = [filename]
        try:
            for _file in filenames:
                if not self._is_open(_file):
                    #self.editor_widget.not_open = False
                    # Creo el objeto Edis File
                    obj_file = object_file.EdisFile(_file)
                    content = obj_file.read()
                    weditor = self.create_editor(obj_file, _file)
                    weditor.setText(content)
                    # Cuando se setea el contenido en el editor
                    # se emite la señal textChanged() por lo tanto se agrega
                    # el marker, entonces se procede a borrarlo
                    weditor.markerDelete(0, 3)
                    # FIXME: Cursor position not found
                    #if cursor_position is not None:
                        #line, row = cursor_position
                        #weditor.setCursorPosition(line, row)
                    weditor.setModified(False)
                    obj_file.run_system_watcher()
                else:
                    # Se cambia el índice del stacked
                    # para mostrar el archivo que ya fué abierto
                    for index in range(self.editor_widget.count()):

                        editor = self.editor_widget.widget(index)