Exemplo n.º 1
0
class FileSwitcher(QDialog):
    """A Sublime-like file switcher."""
    sig_goto_file = Signal(int)
    sig_close_file = Signal(int)

    # Constants that define the mode in which the list widget is working
    # FILE_MODE is for a list of files, SYMBOL_MODE if for a list of symbols
    # in a given file when using the '@' symbol.
    FILE_MODE, SYMBOL_MODE = [1, 2]

    def __init__(self, parent, tabs, data):
        QDialog.__init__(self, parent)

        # Variables
        self.tabs = tabs  # Editor stack tabs
        self.data = data  # Editor data
        self.mode = self.FILE_MODE  # By default start in this mode
        self.initial_cursors = None  # {fullpath: QCursor}
        self.initial_path = None  # Fullpath of initial active editor
        self.initial_editor = None  # Initial active editor
        self.line_number = None  # Selected line number in filer

        help_text = _("Press <b>Enter</b> to switch files or <b>Esc</b> to "
                      "cancel.<br><br>Type to filter filenames.<br><br>"
                      "Use <b>:number</b> to go to a line, e.g. "
                      "<b><code>main:42</code></b><br>"
                      "Use <b>@symbol_text</b> to go to a symbol, e.g. "
                      "<b><code>@init</code></b>"
                      "<br><br> Press <b>Ctrl+W</b> to close current tab.<br>")

        # Either allow searching for a line number or a symbol but not both
        regex = QRegExp("([A-Za-z0-9_]{0,100}@[A-Za-z0-9_]{0,100})|" +
                        "([A-Za-z]{0,100}:{0,1}[0-9]{0,100})")

        # Widgets
        self.edit = QLineEdit(self)
        self.help = HelperToolButton()
        self.list = QListWidget(self)
        self.filter = KeyPressFilter()
        regex_validator = QRegExpValidator(regex, self.edit)

        # Widgets setup
        self.setWindowFlags(Qt.Popup | Qt.FramelessWindowHint)
        self.setWindowOpacity(0.95)
        self.edit.installEventFilter(self.filter)
        self.edit.setValidator(regex_validator)
        self.help.setToolTip(help_text)
        self.list.setItemDelegate(HTMLDelegate(self))

        # Layout
        edit_layout = QHBoxLayout()
        edit_layout.addWidget(self.edit)
        edit_layout.addWidget(self.help)
        layout = QVBoxLayout()
        layout.addLayout(edit_layout)
        layout.addWidget(self.list)
        self.setLayout(layout)

        # Signals
        self.rejected.connect(self.restore_initial_state)
        self.filter.sig_up_key_pressed.connect(self.previous_row)
        self.filter.sig_down_key_pressed.connect(self.next_row)
        self.edit.returnPressed.connect(self.accept)
        self.edit.textChanged.connect(self.setup)
        self.list.itemSelectionChanged.connect(self.item_selection_changed)
        self.list.clicked.connect(self.edit.setFocus)

        # Setup
        self.save_initial_state()
        self.set_dialog_position()
        self.setup()

    # --- Properties
    @property
    def editors(self):
        return [self.tabs.widget(index) for index in range(self.tabs.count())]

    @property
    def line_count(self):
        return [editor.get_line_count() for editor in self.editors]

    @property
    def save_status(self):
        return [getattr(td, 'newly_created', False) for td in self.data]

    @property
    def paths(self):
        return [getattr(td, 'filename', None) for td in self.data]

    @property
    def filenames(self):
        return [self.tabs.tabText(index) for index in range(self.tabs.count())]

    @property
    def current_path(self):
        return self.paths_by_editor[self.get_editor()]

    @property
    def paths_by_editor(self):
        return dict(zip(self.editors, self.paths))

    @property
    def editors_by_path(self):
        return dict(zip(self.paths, self.editors))

    @property
    def filter_text(self):
        """Get the normalized (lowecase) content of the filter text."""
        return to_text_string(self.edit.text()).lower()

    def save_initial_state(self):
        """Saves initial cursors and initial active editor."""
        paths = self.paths
        self.initial_editor = self.get_editor()
        self.initial_cursors = {}

        for i, editor in enumerate(self.editors):
            if editor is self.initial_editor:
                self.initial_path = paths[i]
            self.initial_cursors[paths[i]] = editor.textCursor()

    def accept(self):
        QDialog.accept(self)
        self.list.clear()

    def restore_initial_state(self):
        """Restores initial cursors and initial active editor."""
        self.list.clear()
        editors = self.editors_by_path

        for path in self.initial_cursors:
            cursor = self.initial_cursors[path]
            if path in editors:
                self.set_editor_cursor(editors[path], cursor)

        if self.initial_editor in self.paths_by_editor:
            index = self.paths.index(self.initial_path)
            self.sig_goto_file.emit(index)

    def set_dialog_position(self):
        """Positions the file switcher dialog in the center of the editor."""
        parent = self.parent()
        geo = parent.geometry()
        width = self.list.width()  # This has been set in setup

        left = parent.geometry().width() / 2 - width / 2
        top = 0
        while parent:
            geo = parent.geometry()
            top += geo.top()
            left += geo.left()
            parent = parent.parent()

        # Note: the +1 pixel on the top makes it look better
        self.move(left, top + self.tabs.tabBar().geometry().height() + 1)

    def fix_size(self, content, extra=50):
        """Adjusts the width of the file switcher, based on the content."""
        # Update size of dialog based on longest shortened path
        strings = []
        if content:
            for rich_text in content:
                label = QLabel(rich_text)
                label.setTextFormat(Qt.PlainText)
                strings.append(label.text())
                fm = label.fontMetrics()
            max_width = max([fm.width(s) * 1.3 for s in strings])
            self.list.setMinimumWidth(max_width + extra)
            self.set_dialog_position()

    # --- Helper methods: List widget
    def count(self):
        """Gets the item count in the list widget."""
        return self.list.count()

    def current_row(self):
        """Returns the current selected row in the list widget."""
        return self.list.currentRow()

    def set_current_row(self, row):
        """Sets the current selected row in the list widget."""
        return self.list.setCurrentRow(row)

    def select_row(self, steps):
        """Select row in list widget based on a number of steps with direction.

        Steps can be positive (next rows) or negative (previous rows).
        """
        row = self.current_row() + steps
        if 0 <= row < self.count():
            self.set_current_row(row)

    def previous_row(self):
        """Select previous row in list widget."""
        self.select_row(-1)

    def next_row(self):
        """Select next row in list widget."""
        self.select_row(+1)

    # --- Helper methods: Editor
    def get_editor(self, index=None, path=None):
        """Get editor by index or path.
        
        If no path or index specified the current active editor is returned
        """
        if index:
            return self.tabs.widget(index)
        elif path:
            return self.tabs.widget(index)
        else:
            return self.parent().get_current_editor()

    def set_editor_cursor(self, editor, cursor):
        """Set the cursor of an editor."""
        pos = cursor.position()
        anchor = cursor.anchor()

        new_cursor = QTextCursor()
        if pos == anchor:
            new_cursor.movePosition(pos)
        else:
            new_cursor.movePosition(anchor)
            new_cursor.movePosition(pos, QTextCursor.KeepAnchor)
        editor.setTextCursor(cursor)

    def goto_line(self, line_number):
        """Go to specified line number in current active editor."""
        if line_number:
            line_number = int(line_number)
            editor = self.get_editor()
            editor.go_to_line(min(line_number, editor.get_line_count()))

    # --- Helper methods: Outline explorer
    def get_symbol_list(self):
        """Get the object explorer data."""
        return self.get_editor().highlighter.get_outlineexplorer_data()

    # --- Handlers
    def item_selection_changed(self):
        """List widget item selection change handler."""
        row = self.current_row()
        if self.count() and row >= 0:
            if self.mode == self.FILE_MODE:
                try:
                    stack_index = self.paths.index(self.filtered_path[row])
                    self.sig_goto_file.emit(stack_index)
                    self.goto_line(self.line_number)
                    self.edit.setFocus()
                except ValueError:
                    pass
            else:
                line_number = self.filtered_symbol_lines[row]
                self.goto_line(line_number)

    def setup_file_list(self, filter_text, current_path):
        """Setup list widget content for file list display."""
        short_paths = shorten_paths(self.paths, self.save_status)
        paths = self.paths
        results = []
        trying_for_line_number = ':' in filter_text

        # Get optional line number
        if trying_for_line_number:
            filter_text, line_number = filter_text.split(':')
        else:
            line_number = None

        # Get all available filenames and get the scores for "fuzzy" matching
        scores = get_search_scores(filter_text,
                                   self.filenames,
                                   template="<b>{0}</b>")

        # Build the text that will appear on the list widget
        for index, score in enumerate(scores):
            text, rich_text, score_value = score
            if score_value != -1:
                text_item = '<big>' + rich_text + '</big>'
                if trying_for_line_number:
                    text_item += " [{0:} {1:}]".format(self.line_count[index],
                                                       _("lines"))
                text_item += "<br><i>{0:}</i>".format(short_paths[index])

                results.append((score_value, index, text_item))

        # Sort the obtained scores and populate the list widget
        self.filtered_path = []
        for result in sorted(results):
            index = result[1]
            text = result[-1]
            path = paths[index]
            item = QListWidgetItem(self.tabs.tabIcon(index), text)
            item.setToolTip(path)
            item.setSizeHint(QSize(0, 25))
            self.list.addItem(item)
            self.filtered_path.append(path)

        # Move selected item in list accordingly and update list size
        if current_path in self.filtered_path:
            self.set_current_row(self.filtered_path.index(current_path))
        elif self.filtered_path:
            self.set_current_row(0)
        self.fix_size(short_paths)

        # If a line number is searched look for it
        self.line_number = line_number
        self.goto_line(line_number)

    def setup_symbol_list(self, filter_text, current_path):
        """Setup list widget content for symbol list display."""
        # Get optional symbol name
        filter_text, symbol_text = filter_text.split('@')

        # Fetch the Outline explorer data, get the icons and values
        oedata = self.get_symbol_list()
        icons = get_python_symbol_icons(oedata)

        symbol_list = process_python_symbol_data(oedata)
        line_fold_token = [(item[0], item[2], item[3]) for item in symbol_list]
        choices = [item[1] for item in symbol_list]
        scores = get_search_scores(symbol_text, choices, template="<b>{0}</b>")

        # Build the text that will appear on the list widget
        results = []
        lines = []
        self.filtered_symbol_lines = []
        for index, score in enumerate(scores):
            text, rich_text, score_value = score
            line, fold_level, token = line_fold_token[index]
            lines.append(text)
            if score_value != -1:
                results.append((score_value, line, text, rich_text, fold_level,
                                icons[index], token))

        template_1 = '<code>{0}<big>{1} {2}</big></code>'
        template_2 = '<br><code>{0}</code><i>[Line {1}]</i>'

        for (score, line, text, rich_text, fold_level, icon,
             token) in sorted(results):
            fold_space = '&nbsp;' * (fold_level)
            line_number = line + 1
            self.filtered_symbol_lines.append(line_number)
            textline = template_1.format(fold_space, token, rich_text)
            textline += template_2.format(fold_space, line_number)
            item = QListWidgetItem(icon, textline)
            item.setSizeHint(QSize(0, 16))
            self.list.addItem(item)

        # Move selected item in list accordingly
        # NOTE: Doing this is causing two problems:
        # 1. It makes the cursor to auto-jump to the last selected
        #    symbol after opening or closing a different file
        # 2. It moves the cursor to the first symbol by default,
        #    which is very distracting.
        # That's why this line is commented!
        # self.set_current_row(0)

        # Update list size
        self.fix_size(lines, extra=125)

    def setup(self):
        """Setup list widget content."""
        if not self.tabs.count():
            self.close()
            return

        self.list.clear()
        current_path = self.current_path
        filter_text = self.filter_text

        # Get optional line or symbol to define mode and method handler
        trying_for_symbol = ('@' in self.filter_text)

        if trying_for_symbol:
            self.mode = self.SYMBOL_MODE
            self.setup_symbol_list(filter_text, current_path)
        else:
            self.mode = self.FILE_MODE
            self.setup_file_list(filter_text, current_path)
Exemplo n.º 2
0
class PathManager(QDialog):
    def __init__(self, parent=None, pathlist=None, ro_pathlist=None, sync=True):
        QDialog.__init__(self, parent)
        
        # Destroying the C++ object right after closing the dialog box,
        # otherwise it may be garbage-collected in another QThread
        # (e.g. the editor's analysis thread in Spyder), thus leading to
        # a segmentation fault on UNIX or an application crash on Windows
        self.setAttribute(Qt.WA_DeleteOnClose)
        
        assert isinstance(pathlist, list)
        self.pathlist = pathlist
        if ro_pathlist is None:
            ro_pathlist = []
        self.ro_pathlist = ro_pathlist
        
        self.last_path = getcwd()
        
        self.setWindowTitle(_("PYTHONPATH manager"))
        self.setWindowIcon(get_icon('pythonpath.png'))
        self.resize(500, 300)
        
        self.selection_widgets = []
        
        layout = QVBoxLayout()
        self.setLayout(layout)
        
        top_layout = QHBoxLayout()
        layout.addLayout(top_layout)
        self.toolbar_widgets1 = self.setup_top_toolbar(top_layout)

        self.listwidget = QListWidget(self)
        self.connect(self.listwidget, SIGNAL("currentRowChanged(int)"),
                     self.refresh)
        layout.addWidget(self.listwidget)

        bottom_layout = QHBoxLayout()
        layout.addLayout(bottom_layout)
        self.sync_button = None
        self.toolbar_widgets2 = self.setup_bottom_toolbar(bottom_layout, sync)        
        
        # Buttons configuration
        bbox = QDialogButtonBox(QDialogButtonBox.Close)
        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
        bottom_layout.addWidget(bbox)
        
        self.update_list()
        self.refresh()
        
    def _add_widgets_to_layout(self, layout, widgets):
        layout.setAlignment(Qt.AlignLeft)
        for widget in widgets:
            layout.addWidget(widget)
        
    def setup_top_toolbar(self, layout):
        toolbar = []
        movetop_button = create_toolbutton(self,
                                    text=_("Move to top"),
                                    icon=get_icon('2uparrow.png'),
                                    triggered=lambda: self.move_to(absolute=0),
                                    text_beside_icon=True)
        toolbar.append(movetop_button)
        moveup_button = create_toolbutton(self,
                                    text=_("Move up"),
                                    icon=get_icon('1uparrow.png'),
                                    triggered=lambda: self.move_to(relative=-1),
                                    text_beside_icon=True)
        toolbar.append(moveup_button)
        movedown_button = create_toolbutton(self,
                                    text=_("Move down"),
                                    icon=get_icon('1downarrow.png'),
                                    triggered=lambda: self.move_to(relative=1),
                                    text_beside_icon=True)
        toolbar.append(movedown_button)
        movebottom_button = create_toolbutton(self,
                                    text=_("Move to bottom"),
                                    icon=get_icon('2downarrow.png'),
                                    triggered=lambda: self.move_to(absolute=1),
                                    text_beside_icon=True)
        toolbar.append(movebottom_button)
        self.selection_widgets.extend(toolbar)
        self._add_widgets_to_layout(layout, toolbar)
        return toolbar
    
    def setup_bottom_toolbar(self, layout, sync=True):
        toolbar = []
        add_button = create_toolbutton(self, text=_("Add path"),
                                       icon=get_icon('edit_add.png'),
                                       triggered=self.add_path,
                                       text_beside_icon=True)
        toolbar.append(add_button)
        remove_button = create_toolbutton(self, text=_("Remove path"),
                                          icon=get_icon('edit_remove.png'),
                                          triggered=self.remove_path,
                                          text_beside_icon=True)
        toolbar.append(remove_button)
        self.selection_widgets.append(remove_button)
        self._add_widgets_to_layout(layout, toolbar)
        layout.addStretch(1)
        if os.name == 'nt' and sync:
            self.sync_button = create_toolbutton(self,
                  text=_("Synchronize..."),
                  icon=get_icon('synchronize.png'), triggered=self.synchronize,
                  tip=_("Synchronize Spyder's path list with PYTHONPATH "
                              "environment variable"),
                  text_beside_icon=True)
            layout.addWidget(self.sync_button)
        return toolbar
    
    def synchronize(self):
        """
        Synchronize Spyder's path list with PYTHONPATH environment variable
        Only apply to: current user, on Windows platforms
        """
        answer = QMessageBox.question(self, _("Synchronize"),
            _("This will synchronize Spyder's path list with "
                    "<b>PYTHONPATH</b> environment variable for current user, "
                    "allowing you to run your Python modules outside Spyder "
                    "without having to configure sys.path. "
                    "<br>Do you want to clear contents of PYTHONPATH before "
                    "adding Spyder's path list?"),
            QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
        if answer == QMessageBox.Cancel:
            return
        elif answer == QMessageBox.Yes:
            remove = True
        else:
            remove = False
        from spyderlib.utils.environ import (get_user_env, set_user_env,
                                             listdict2envdict)
        env = get_user_env()
        if remove:
            ppath = self.pathlist+self.ro_pathlist
        else:
            ppath = env.get('PYTHONPATH', [])
            if not isinstance(ppath, list):
                ppath = [ppath]
            ppath = [path for path in ppath
                     if path not in (self.pathlist+self.ro_pathlist)]
            ppath.extend(self.pathlist+self.ro_pathlist)
        env['PYTHONPATH'] = ppath
        set_user_env( listdict2envdict(env), parent=self )
        
    def get_path_list(self):
        """Return path list (does not include the read-only path list)"""
        return self.pathlist
        
    def update_list(self):
        """Update path list"""
        self.listwidget.clear()
        for name in self.pathlist+self.ro_pathlist:
            item = QListWidgetItem(name)
            item.setIcon(get_std_icon('DirClosedIcon'))
            if name in self.ro_pathlist:
                item.setFlags(Qt.NoItemFlags)
            self.listwidget.addItem(item)
        self.refresh()
        
    def refresh(self, row=None):
        """Refresh widget"""
        for widget in self.selection_widgets:
            widget.setEnabled(self.listwidget.currentItem() is not None)
        not_empty = self.listwidget.count() > 0
        if self.sync_button is not None:
            self.sync_button.setEnabled(not_empty)
    
    def move_to(self, absolute=None, relative=None):
        index = self.listwidget.currentRow()
        if absolute is not None:
            if absolute:
                new_index = len(self.pathlist)-1
            else:
                new_index = 0
        else:
            new_index = index + relative        
        new_index = max(0, min(len(self.pathlist)-1, new_index))
        path = self.pathlist.pop(index)
        self.pathlist.insert(new_index, path)
        self.update_list()
        self.listwidget.setCurrentRow(new_index)
        
    def remove_path(self):
        answer = QMessageBox.warning(self, _("Remove path"),
            _("Do you really want to remove selected path?"),
            QMessageBox.Yes | QMessageBox.No)
        if answer == QMessageBox.Yes:
            self.pathlist.pop(self.listwidget.currentRow())
            self.update_list()
    
    def add_path(self):
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        directory = getexistingdirectory(self, _("Select directory"),
                                         self.last_path)
        self.emit(SIGNAL('redirect_stdio(bool)'), True)
        if directory:
            directory = osp.abspath(directory)
            self.last_path = directory
            if directory in self.pathlist:
                answer = QMessageBox.question(self, _("Add path"),
                    _("This directory is already included in Spyder path "
                            "list.<br>Do you want to move it to the top of "
                            "the list?"),
                    QMessageBox.Yes | QMessageBox.No)
                if answer == QMessageBox.Yes:
                    self.pathlist.remove(directory)
                else:
                    return
            self.pathlist.insert(0, directory)
            self.update_list()
Exemplo n.º 3
0
class FileSwitcher(QDialog):
    """A Sublime-like file switcher."""
    sig_goto_file = Signal(int)
    sig_close_file = Signal(int)

    # Constants that define the mode in which the list widget is working
    # FILE_MODE is for a list of files, SYMBOL_MODE if for a list of symbols
    # in a given file when using the '@' symbol.
    FILE_MODE, SYMBOL_MODE = [1, 2]

    def __init__(self, parent, tabs, data):
        QDialog.__init__(self, parent)

        # Variables
        self.tabs = tabs                  # Editor stack tabs
        self.data = data                  # Editor data
        self.mode = self.FILE_MODE        # By default start in this mode
        self.initial_cursors = None       # {fullpath: QCursor}
        self.initial_path = None          # Fullpath of initial active editor
        self.initial_editor = None        # Initial active editor
        self.line_number = None           # Selected line number in filer

        help_text = _("Press <b>Enter</b> to switch files or <b>Esc</b> to "
                      "cancel.<br><br>Type to filter filenames.<br><br>"
                      "Use <b>:number</b> to go to a line, e.g. "
                      "<b><code>main:42</code></b><br>"
                      "Use <b>@symbol_text</b> to go to a symbol, e.g. "
                      "<b><code>@init</code></b>"
                      "<br><br> Press <b>Ctrl+W</b> to close current tab.<br>")

        # Either allow searching for a line number or a symbol but not both
        regex = QRegExp("([A-Za-z0-9_]{0,100}@[A-Za-z0-9_]{0,100})|" +
                        "([A-Za-z]{0,100}:{0,1}[0-9]{0,100})")

        # Widgets
        self.edit = QLineEdit(self)
        self.help = HelperToolButton()
        self.list = QListWidget(self)
        self.filter = KeyPressFilter()
        regex_validator = QRegExpValidator(regex, self.edit)

        # Widgets setup
        self.setWindowFlags(Qt.Popup | Qt.FramelessWindowHint)
        self.setWindowOpacity(0.95)
        self.edit.installEventFilter(self.filter)
        self.edit.setValidator(regex_validator)
        self.help.setToolTip(help_text)
        self.list.setItemDelegate(HTMLDelegate(self))

        # Layout
        edit_layout = QHBoxLayout()
        edit_layout.addWidget(self.edit)
        edit_layout.addWidget(self.help)
        layout = QVBoxLayout()
        layout.addLayout(edit_layout)
        layout.addWidget(self.list)
        self.setLayout(layout)

        # Signals
        self.rejected.connect(self.restore_initial_state)
        self.filter.sig_up_key_pressed.connect(self.previous_row)
        self.filter.sig_down_key_pressed.connect(self.next_row)
        self.edit.returnPressed.connect(self.accept)
        self.edit.textChanged.connect(self.setup)
        self.list.itemSelectionChanged.connect(self.item_selection_changed)
        self.list.clicked.connect(self.edit.setFocus)

        # Setup
        self.save_initial_state()
        self.set_dialog_position()
        self.setup()

    # --- Properties
    @property
    def editors(self):
        return [self.tabs.widget(index) for index in range(self.tabs.count())]

    @property
    def line_count(self):
        return [editor.get_line_count() for editor in self.editors]

    @property
    def save_status(self):
        return [getattr(td, 'newly_created', False) for td in self.data]

    @property
    def paths(self):
        return [getattr(td, 'filename', None) for td in self.data]

    @property
    def filenames(self):
        return [self.tabs.tabText(index) for index in range(self.tabs.count())]

    @property
    def current_path(self):
        return self.paths_by_editor[self.get_editor()]

    @property
    def paths_by_editor(self):
        return dict(zip(self.editors, self.paths))

    @property
    def editors_by_path(self):
        return dict(zip(self.paths, self.editors))

    @property
    def filter_text(self):
        """Get the normalized (lowecase) content of the filter text."""
        return to_text_string(self.edit.text()).lower()

    def save_initial_state(self):
        """Saves initial cursors and initial active editor."""
        paths = self.paths
        self.initial_editor = self.get_editor()
        self.initial_cursors = {}

        for i, editor in enumerate(self.editors):
            if editor is self.initial_editor:
                self.initial_path = paths[i]
            self.initial_cursors[paths[i]] = editor.textCursor()

    def restore_initial_state(self):
        """Restores initial cursors and initial active editor."""
        editors = self.editors_by_path

        for path in self.initial_cursors:
            cursor = self.initial_cursors[path]
            if path in editors:
                self.set_editor_cursor(editors[path], cursor)

        if self.initial_editor in self.paths_by_editor:
            index = self.paths.index(self.initial_path)
            self.sig_goto_file.emit(index)

    def set_dialog_position(self):
        """Positions the file switcher dialog in the center of the editor."""
        parent = self.parent()
        geo = parent.geometry()
        width = self.list.width()  # This has been set in setup

        left = parent.geometry().width()/2 - width/2
        top = 0
        while parent:
            geo = parent.geometry()
            top += geo.top()
            left += geo.left()
            parent = parent.parent()

        # Note: the +1 pixel on the top makes it look better
        self.move(left, top + self.tabs.tabBar().geometry().height() + 1)

    def fix_size(self, content, extra=50):
        """Adjusts the width of the file switcher, based on the content."""
        # Update size of dialog based on longest shortened path
        strings = []
        if content:
            for rich_text in content:
                label = QLabel(rich_text)
                label.setTextFormat(Qt.PlainText)
                strings.append(label.text())
                fm = label.fontMetrics()
            max_width = max([fm.width(s)*1.3 for s in strings])
            self.list.setMinimumWidth(max_width + extra)
            self.set_dialog_position()

    # --- Helper methods: List widget
    def count(self):
        """Gets the item count in the list widget."""
        return self.list.count()

    def current_row(self):
        """Returns the current selected row in the list widget."""
        return self.list.currentRow()

    def set_current_row(self, row):
        """Sets the current selected row in the list widget."""
        return self.list.setCurrentRow(row)

    def select_row(self, steps):
        """Select row in list widget based on a number of steps with direction.

        Steps can be positive (next rows) or negative (previous rows).
        """
        row = self.current_row() + steps
        if 0 <= row < self.count():
            self.set_current_row(row)

    def previous_row(self):
        """Select previous row in list widget."""
        self.select_row(-1)

    def next_row(self):
        """Select next row in list widget."""
        self.select_row(+1)

    # --- Helper methods: Editor
    def get_editor(self, index=None, path=None):
        """Get editor by index or path.
        
        If no path or index specified the current active editor is returned
        """
        if index:
            return self.tabs.widget(index)
        elif path:
            return self.tabs.widget(index)
        else:
            return self.parent().get_current_editor()

    def set_editor_cursor(self, editor, cursor):
        """Set the cursor of an editor."""
        pos = cursor.position()
        anchor = cursor.anchor()

        new_cursor = QTextCursor()
        if pos == anchor:
            new_cursor.movePosition(pos)
        else:
            new_cursor.movePosition(anchor)
            new_cursor.movePosition(pos, QTextCursor.KeepAnchor)
        editor.setTextCursor(cursor)

    def goto_line(self, line_number):
        """Go to specified line number in current active editor."""
        if line_number:
            line_number = int(line_number)
            editor = self.get_editor()
            editor.go_to_line(min(line_number, editor.get_line_count()))

    # --- Helper methods: Outline explorer
    def get_symbol_list(self):
        """Get the object explorer data."""
        return self.get_editor().highlighter.get_outlineexplorer_data()

    # --- Handlers
    def item_selection_changed(self):
        """List widget item selection change handler."""
        row = self.current_row()
        if self.count() and row >= 0:
            if self.mode == self.FILE_MODE:
                try:
                    stack_index = self.paths.index(self.filtered_path[row])
                    self.sig_goto_file.emit(stack_index)
                    self.goto_line(self.line_number)
                    self.edit.setFocus()
                except ValueError:
                    pass
            else:
                line_number = self.filtered_symbol_lines[row]
                self.goto_line(line_number)

    def setup_file_list(self, filter_text, current_path):
        """Setup list widget content for file list display."""
        short_paths = shorten_paths(self.paths, self.save_status)
        paths = self.paths
        results = []
        trying_for_line_number = ':' in filter_text

        # Get optional line number
        if trying_for_line_number:
            filter_text, line_number = filter_text.split(':')
        else:
            line_number = None

        # Get all available filenames and get the scores for "fuzzy" matching
        scores = get_search_scores(filter_text, self.filenames,
                                   template="<b>{0}</b>")

        # Build the text that will appear on the list widget
        for index, score in enumerate(scores):
            text, rich_text, score_value = score
            if score_value != -1:
                text_item = '<big>' + rich_text + '</big>'
                if trying_for_line_number:
                    text_item += " [{0:} {1:}]".format(self.line_count[index],
                                                       _("lines"))
                text_item += "<br><i>{0:}</i>".format(
                    short_paths[index])

                results.append((score_value, index, text_item))

        # Sort the obtained scores and populate the list widget
        self.filtered_path = []
        for result in sorted(results):
            index = result[1]
            text = result[-1]
            path = paths[index]
            item = QListWidgetItem(self.tabs.tabIcon(index), text)
            item.setToolTip(path)
            item.setSizeHint(QSize(0, 25))
            self.list.addItem(item)
            self.filtered_path.append(path)

        # Move selected item in list accordingly and update list size
        if current_path in self.filtered_path:
            self.set_current_row(self.filtered_path.index(current_path))
        elif self.filtered_path:
            self.set_current_row(0)
        self.fix_size(short_paths)

        # If a line number is searched look for it
        self.line_number = line_number
        self.goto_line(line_number)

    def setup_symbol_list(self, filter_text, current_path):
        """Setup list widget content for symbol list display."""
        # Get optional symbol name
        filter_text, symbol_text = filter_text.split('@')

        # Fetch the Outline explorer data, get the icons and values
        oedata = self.get_symbol_list()
        icons = get_python_symbol_icons(oedata)

        symbol_list = process_python_symbol_data(oedata)
        line_fold_token = [(item[0], item[2], item[3]) for item in symbol_list]
        choices = [item[1] for item in symbol_list]
        scores = get_search_scores(symbol_text, choices, template="<b>{0}</b>")

        # Build the text that will appear on the list widget
        results = []
        lines = []
        self.filtered_symbol_lines = []
        for index, score in enumerate(scores):
            text, rich_text, score_value = score
            line, fold_level, token = line_fold_token[index]
            lines.append(text)
            if score_value != -1:
                results.append((score_value, line, text, rich_text,
                                fold_level, icons[index], token))

        template_1 = '<code>{0}<big>{1} {2}</big></code>'
        template_2 = '<br><code>{0}</code><i>[Line {1}]</i>'

        for (score, line, text, rich_text, fold_level, icon,
             token) in sorted(results):
            fold_space = '&nbsp;'*(fold_level)
            line_number = line + 1
            self.filtered_symbol_lines.append(line_number)
            textline = template_1.format(fold_space, token, rich_text)
            textline += template_2.format(fold_space, line_number)
            item = QListWidgetItem(icon, textline)
            item.setSizeHint(QSize(0, 16))
            self.list.addItem(item)

        # Move selected item in list accordingly and update list size
        self.set_current_row(0)
        self.fix_size(lines, extra=125)

    def setup(self):
        """Setup list widget content."""
        if not self.tabs.count():
            self.close()
            return

        self.list.clear()
        current_path = self.current_path
        filter_text = self.filter_text

        # Get optional line or symbol to define mode and method handler
        trying_for_symbol = ('@' in self.filter_text)

        if trying_for_symbol:
            self.mode = self.SYMBOL_MODE
            self.setup_symbol_list(filter_text, current_path)
        else:
            self.mode = self.FILE_MODE
            self.setup_file_list(filter_text, current_path)
Exemplo n.º 4
0
class RateLawWidget(QWidget):
    """
    Rate Law widget
    """
    
    def __init__(self, parent, max_entries=100):
        """ Creates a very basic window with some text """
        """
        RATE_LAW_MESSAGE = \
            "The Plugins for Spyder consists out of three main classes: \n\n" \
            "1. HelloWorld\n\n" \
            "\tThe HelloWorld class inherits all its methods from\n" \
            "\tSpyderPluginMixin and the HelloWorldWidget and performs all\n" \
            "\tthe processing required by the GU. \n\n" \
            "2. HelloWorldConfigPage\n\n" \
            "\tThe HelloWorldConfig class inherits all its methods from\n" \
            "\tPluginConfigPage to create a configuration page that can be\n" \
            "\tfound under Tools -> Preferences\n\n" \
            "3. HelloWorldWidget\n\n" \
            "\tThe HelloWorldWidget class inherits all its methods from\n" \
            "\tQWidget to create the actual plugin GUI interface that \n" \
            "\tdisplays this message on screen\n\n"
        """
        #Testing access editor on plugin initialization
        
        
        RATE_LAW_MESSAGE = ""
        displaynamelist = []
        #displaylist = []
        infixlist = []
        desclist = []
        parameterstringlist = []
        xmldoc = minidom.parse('\\.spyder2\\ratelaw2_0_3.xml')
        #xmldoc = minidom.parse('%\\Downloads\\ratelaw2_0_3.xml')
        
        lawlistxml = xmldoc.getElementsByTagName('law')
        #i is the number of laws currently in the xml file
        i = 0
        for s in lawlistxml:
            #RATE_LAW_MESSAGE += s.getAttribute('displayName') + "\n"
            RATE_LAW_MESSAGE += s.getAttribute('display') + "\n"
            #displaynamelist[i] = s.getAttribute('displayName')
            #displaylist[i] = s.getAttribute('display')
            displaynamelist.append(s.getAttribute('displayName'))
            #displaylist.append(s.getAttribute('display'))
            infixlist.append(s.getAttribute('infixExpression'))
            desclist.append(s.getAttribute('description'))
            parameterlist = s.getElementsByTagName('listOfParameters')[0]
            #for p in parameterlist    
            parameters = parameterlist.getElementsByTagName('parameter')
            parameterstring = ""
            for param in parameters:
                parametername = param.attributes['name'].value
                parameterdesc = param.attributes['description'].value
                parameterstring = parameterstring + '\t' + parametername + ":" + '\t' + "  " + parameterdesc + "\n"
                #print('\t' + parametername + ":" + '\t' + parameterdesc)
            parameterstringlist.append(parameterstring)    
            i = i + 1
            
        
        QWidget.__init__(self, parent)
        
        self.setWindowTitle("Rate Law Library")
        
        self.output = None
        self.error_output = None
        
        self._last_wdir = None
        self._last_args = None
        self._last_pythonpath = None
        
        self.textlabel = QLabel(RATE_LAW_MESSAGE)        

        self.lawlist = QListWidget()
        self.lawpage = QStackedWidget()
        #Adding displayName items to lawlist
        for j in range(i):
            item = QListWidgetItem(displaynamelist[j])
            self.lawlist.addItem(item)
            self.lawdetailpage = QWidget()
            # Page layout will become its own function
            setup_group = QGroupBox(displaynamelist[j])
            infixmod = infixlist[j].replace("___"," ")
            setup_label = QLabel(infixmod)
            setup_label.setWordWrap(True)
            
            desc_group = QGroupBox("Description")
            desc_label = QLabel(desclist[j])
            desc_label.setWordWrap(True)
            param_label = QLabel(parameterstringlist[j])
            param_label.setWordWrap(True)

        # Warning: do not try to regroup the following QLabel contents with 
        # widgets above -- this string was isolated here in a single QLabel
        # on purpose: to fix Issue 863
            setup_layout = QVBoxLayout()
            setup_layout.addWidget(setup_label)
            setup_group.setLayout(setup_layout)
            
            desc_layout = QVBoxLayout()
            desc_layout.addWidget(desc_label)
            desc_layout.addWidget(param_label)
            desc_group.setLayout(desc_layout)

            vlayout = QVBoxLayout()
            vlayout.addWidget(setup_group)
            vlayout.addWidget(desc_group)
            vlayout.addStretch(1)
            self.lawdetailpage.setLayout(vlayout)
            
            self.lawpage.addWidget(self.lawdetailpage)
        
        #self.connect(self.lawlist, SIGNAL(self.lawlist.currentRowChanged(int)),self.lawpage,SLOT(self.lawpage.setCurrentIndex(int)))
        self.lawlist.currentRowChanged.connect(self.lawpage.setCurrentIndex)            
        '''
        self.lawpage = QWidget()
        '''
        self.lawlist.setCurrentRow(0)
        
        hsplitter = QSplitter()
        hsplitter.addWidget(self.lawlist)
        
        
        
        
        hlayout1 = QHBoxLayout()
        hlayout1.addWidget(self.textlabel)
        hlayout1.addStretch()
        self.lawpage.setLayout(hlayout1)
        
        hsplitter.addWidget(self.lawpage)
        
        layout = QVBoxLayout()
        layout.addWidget(hsplitter)
        self.setLayout(layout)
Exemplo n.º 5
0
class PathManager(QDialog):
    redirect_stdio = Signal(bool)
    
    def __init__(self, parent=None, pathlist=None, ro_pathlist=None, sync=True):
        QDialog.__init__(self, parent)
        
        # Destroying the C++ object right after closing the dialog box,
        # otherwise it may be garbage-collected in another QThread
        # (e.g. the editor's analysis thread in Spyder), thus leading to
        # a segmentation fault on UNIX or an application crash on Windows
        self.setAttribute(Qt.WA_DeleteOnClose)
        
        assert isinstance(pathlist, list)
        self.pathlist = pathlist
        if ro_pathlist is None:
            ro_pathlist = []
        self.ro_pathlist = ro_pathlist
        
        self.last_path = getcwd()
        
        self.setWindowTitle(_("PYTHONPATH manager"))
        self.setWindowIcon(get_icon('pythonpath.png'))
        self.resize(500, 300)
        
        self.selection_widgets = []
        
        layout = QVBoxLayout()
        self.setLayout(layout)
        
        top_layout = QHBoxLayout()
        layout.addLayout(top_layout)
        self.toolbar_widgets1 = self.setup_top_toolbar(top_layout)

        self.listwidget = QListWidget(self)
        self.listwidget.currentRowChanged.connect(self.refresh)
        layout.addWidget(self.listwidget)

        bottom_layout = QHBoxLayout()
        layout.addLayout(bottom_layout)
        self.sync_button = None
        self.toolbar_widgets2 = self.setup_bottom_toolbar(bottom_layout, sync)        
        
        # Buttons configuration
        bbox = QDialogButtonBox(QDialogButtonBox.Close)
        bbox.rejected.connect(self.reject)
        bottom_layout.addWidget(bbox)
        
        self.update_list()
        self.refresh()
        
    def _add_widgets_to_layout(self, layout, widgets):
        layout.setAlignment(Qt.AlignLeft)
        for widget in widgets:
            layout.addWidget(widget)
        
    def setup_top_toolbar(self, layout):
        toolbar = []
        movetop_button = create_toolbutton(self,
                                    text=_("Move to top"),
                                    icon=get_icon('2uparrow.png'),
                                    triggered=lambda: self.move_to(absolute=0),
                                    text_beside_icon=True)
        toolbar.append(movetop_button)
        moveup_button = create_toolbutton(self,
                                    text=_("Move up"),
                                    icon=get_icon('1uparrow.png'),
                                    triggered=lambda: self.move_to(relative=-1),
                                    text_beside_icon=True)
        toolbar.append(moveup_button)
        movedown_button = create_toolbutton(self,
                                    text=_("Move down"),
                                    icon=get_icon('1downarrow.png'),
                                    triggered=lambda: self.move_to(relative=1),
                                    text_beside_icon=True)
        toolbar.append(movedown_button)
        movebottom_button = create_toolbutton(self,
                                    text=_("Move to bottom"),
                                    icon=get_icon('2downarrow.png'),
                                    triggered=lambda: self.move_to(absolute=1),
                                    text_beside_icon=True)
        toolbar.append(movebottom_button)
        self.selection_widgets.extend(toolbar)
        self._add_widgets_to_layout(layout, toolbar)
        return toolbar
    
    def setup_bottom_toolbar(self, layout, sync=True):
        toolbar = []
        add_button = create_toolbutton(self, text=_("Add path"),
                                       icon=get_icon('edit_add.png'),
                                       triggered=self.add_path,
                                       text_beside_icon=True)
        toolbar.append(add_button)
        remove_button = create_toolbutton(self, text=_("Remove path"),
                                          icon=get_icon('edit_remove.png'),
                                          triggered=self.remove_path,
                                          text_beside_icon=True)
        toolbar.append(remove_button)
        self.selection_widgets.append(remove_button)
        self._add_widgets_to_layout(layout, toolbar)
        layout.addStretch(1)
        if os.name == 'nt' and sync:
            self.sync_button = create_toolbutton(self,
                  text=_("Synchronize..."),
                  icon=get_icon('synchronize.png'), triggered=self.synchronize,
                  tip=_("Synchronize Spyder's path list with PYTHONPATH "
                              "environment variable"),
                  text_beside_icon=True)
            layout.addWidget(self.sync_button)
        return toolbar

    @Slot()
    def synchronize(self):
        """
        Synchronize Spyder's path list with PYTHONPATH environment variable
        Only apply to: current user, on Windows platforms
        """
        answer = QMessageBox.question(self, _("Synchronize"),
            _("This will synchronize Spyder's path list with "
                    "<b>PYTHONPATH</b> environment variable for current user, "
                    "allowing you to run your Python modules outside Spyder "
                    "without having to configure sys.path. "
                    "<br>Do you want to clear contents of PYTHONPATH before "
                    "adding Spyder's path list?"),
            QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
        if answer == QMessageBox.Cancel:
            return
        elif answer == QMessageBox.Yes:
            remove = True
        else:
            remove = False
        from spyderlib.utils.environ import (get_user_env, set_user_env,
                                             listdict2envdict)
        env = get_user_env()
        if remove:
            ppath = self.pathlist+self.ro_pathlist
        else:
            ppath = env.get('PYTHONPATH', [])
            if not isinstance(ppath, list):
                ppath = [ppath]
            ppath = [path for path in ppath
                     if path not in (self.pathlist+self.ro_pathlist)]
            ppath.extend(self.pathlist+self.ro_pathlist)
        env['PYTHONPATH'] = ppath
        set_user_env( listdict2envdict(env), parent=self )
        
    def get_path_list(self):
        """Return path list (does not include the read-only path list)"""
        return self.pathlist
        
    def update_list(self):
        """Update path list"""
        self.listwidget.clear()
        for name in self.pathlist+self.ro_pathlist:
            item = QListWidgetItem(name)
            item.setIcon(get_std_icon('DirClosedIcon'))
            if name in self.ro_pathlist:
                item.setFlags(Qt.NoItemFlags)
            self.listwidget.addItem(item)
        self.refresh()
        
    def refresh(self, row=None):
        """Refresh widget"""
        for widget in self.selection_widgets:
            widget.setEnabled(self.listwidget.currentItem() is not None)
        not_empty = self.listwidget.count() > 0
        if self.sync_button is not None:
            self.sync_button.setEnabled(not_empty)
    
    def move_to(self, absolute=None, relative=None):
        index = self.listwidget.currentRow()
        if absolute is not None:
            if absolute:
                new_index = len(self.pathlist)-1
            else:
                new_index = 0
        else:
            new_index = index + relative        
        new_index = max(0, min(len(self.pathlist)-1, new_index))
        path = self.pathlist.pop(index)
        self.pathlist.insert(new_index, path)
        self.update_list()
        self.listwidget.setCurrentRow(new_index)

    @Slot()
    def remove_path(self):
        answer = QMessageBox.warning(self, _("Remove path"),
            _("Do you really want to remove selected path?"),
            QMessageBox.Yes | QMessageBox.No)
        if answer == QMessageBox.Yes:
            self.pathlist.pop(self.listwidget.currentRow())
            self.update_list()

    @Slot()
    def add_path(self):
        self.redirect_stdio.emit(False)
        directory = getexistingdirectory(self, _("Select directory"),
                                         self.last_path)
        self.redirect_stdio.emit(True)
        if directory:
            directory = osp.abspath(directory)
            self.last_path = directory
            if directory in self.pathlist:
                answer = QMessageBox.question(self, _("Add path"),
                    _("This directory is already included in Spyder path "
                            "list.<br>Do you want to move it to the top of "
                            "the list?"),
                    QMessageBox.Yes | QMessageBox.No)
                if answer == QMessageBox.Yes:
                    self.pathlist.remove(directory)
                else:
                    return
            self.pathlist.insert(0, directory)
            self.update_list()
Exemplo n.º 6
0
class RateLawWidget(QWidget):
    """
    Rate Law widget
    """
    
    def __init__(self, parent, max_entries=100):
        """ Creates a very basic window with some text """
        """
        RATE_LAW_MESSAGE = \
            "The Plugins for Spyder consists out of three main classes: \n\n" \
            "1. HelloWorld\n\n" \
            "\tThe HelloWorld class inherits all its methods from\n" \
            "\tSpyderPluginMixin and the HelloWorldWidget and performs all\n" \
            "\tthe processing required by the GU. \n\n" \
            "2. HelloWorldConfigPage\n\n" \
            "\tThe HelloWorldConfig class inherits all its methods from\n" \
            "\tPluginConfigPage to create a configuration page that can be\n" \
            "\tfound under Tools -> Preferences\n\n" \
            "3. HelloWorldWidget\n\n" \
            "\tThe HelloWorldWidget class inherits all its methods from\n" \
            "\tQWidget to create the actual plugin GUI interface that \n" \
            "\tdisplays this message on screen\n\n"
        """
        #Testing access editor on plugin initialization
        
        
        RATE_LAW_MESSAGE = ""
        displaynamelist = []
        #displaylist = []
        infixlist = []
        desclist = []
        parameterstringlist = []
        xmldoc = minidom.parse('\\.spyder2\\ratelaw2_0_3.xml')
        #xmldoc = minidom.parse('%\\Downloads\\ratelaw2_0_3.xml')
        
        lawlistxml = xmldoc.getElementsByTagName('law')
        #i is the number of laws currently in the xml file
        i = 0
        
        """
        Parsing xml: Acquiring rate law name, description, and list of parameter information
        """
        for s in lawlistxml:
            #RATE_LAW_MESSAGE += s.getAttribute('displayName') + "\n"
            RATE_LAW_MESSAGE += s.getAttribute('display') + "\n"
            #displaynamelist[i] = s.getAttribute('displayName')
            #displaylist[i] = s.getAttribute('display')
            displaynamelist.append(s.getAttribute('displayName'))
            #displaylist.append(s.getAttribute('display'))
            infixlist.append(s.getAttribute('infixExpression'))
            desclist.append(s.getAttribute('description'))
            parameterlist = s.getElementsByTagName('listOfParameters')[0]
            #for p in parameterlist    
            parameters = parameterlist.getElementsByTagName('parameter')
            parameterstring = ""
            for param in parameters:
                parametername = param.attributes['name'].value
                parameterdesc = param.attributes['description'].value
                parameterstring = parameterstring + '\t' + parametername + ":" + '\t' + "  " + parameterdesc + "\n"
                """Creates "description" string"""
                #print('\t' + parametername + ":" + '\t' + parameterdesc)
            parameterstringlist.append(parameterstring)    
            i = i + 1
            
        
        QWidget.__init__(self, parent)
        
        self.setWindowTitle("Rate Law Library")
        
        self.output = None
        self.error_output = None
        
        self._last_wdir = None
        self._last_args = None
        self._last_pythonpath = None
        
        self.textlabel = QLabel(RATE_LAW_MESSAGE)        

        self.lawlist = QListWidget()
        self.lawpage = QStackedWidget()
        #Adding displayName items to lawlist
        for j in range(i):
            item = QListWidgetItem(displaynamelist[j])      """Creates list entry for each rate law"""
            self.lawlist.addItem(item)                      """Adds rate law to list"""
            self.lawdetailpage = QWidget()                  """Creates page for each rate law"""
            # Page layout will become its own function
            setup_group = QGroupBox(displaynamelist[j])     """Creates box with rate law name as title"""
            infixmod = infixlist[j].replace("___"," ")      
            setup_label = QLabel(infixmod)
            setup_label.setWordWrap(True)                   """types rate law expression, removing underscores"""
            
            desc_group = QGroupBox("Description")           """creates box for description"""
            desc_label = QLabel(desclist[j])
            desc_label.setWordWrap(True)
            param_label = QLabel(parameterstringlist[j])
            param_label.setWordWrap(True)

        # Warning: do not try to regroup the following QLabel contents with 
        # widgets above -- this string was isolated here in a single QLabel
        # on purpose: to fix Issue 863
            setup_layout = QVBoxLayout()
            setup_layout.addWidget(setup_label)
            setup_group.setLayout(setup_layout)
            
            desc_layout = QVBoxLayout()
            desc_layout.addWidget(desc_label)
            desc_layout.addWidget(param_label)
            desc_group.setLayout(desc_layout)

            vlayout = QVBoxLayout()
            vlayout.addWidget(setup_group)
            vlayout.addWidget(desc_group)
            vlayout.addStretch(1)
            self.lawdetailpage.setLayout(vlayout)
            
            self.lawpage.addWidget(self.lawdetailpage)      """Formats the page shown when a rate law is selected"""
        
        #self.connect(self.lawlist, SIGNAL(self.lawlist.currentRowChanged(int)),self.lawpage,SLOT(self.lawpage.setCurrentIndex(int)))
        self.lawlist.currentRowChanged.connect(self.lawpage.setCurrentIndex)     """When a rate law in the list is clicked, its corresponding page is shown"""       
        '''
        self.lawpage = QWidget()
        '''
        self.lawlist.setCurrentRow(0)
        
        hsplitter = QSplitter()
        hsplitter.addWidget(self.lawlist)                   "Adds list to left side of window"
        
        
        
        
        hlayout1 = QHBoxLayout()
        hlayout1.addWidget(self.textlabel)
        hlayout1.addStretch()
        self.lawpage.setLayout(hlayout1)
        
        hsplitter.addWidget(self.lawpage)                   """Adds law page to left side of window"""
        
        layout = QVBoxLayout()
        layout.addWidget(hsplitter)
        self.setLayout(layout)
Exemplo n.º 7
0
class RateLawWidget(QWidget):
    """
    Rate Law widget
    """
    
    def __init__(self, parent, max_entries=100):
        
        "Initialize Various list objects before assignment"
        displaylist = []
        displaynamelist = []
        infixmod = []
        infixlist = []
        desclist = []
        
        parameternamelist = []
        parameterdesclist = []
        parameterstringlist = []
        paramcountlist = []
        
        
        
        buttonlist  = []
        xmldoc = minidom.parse('C:\\Users\\Jayit\\.spyder2\\ratelaw2_0_3.xml')
        #xmldoc = minidom.parse('%\\Downloads\\ratelaw2_0_3.xml')
        
        lawlistxml = xmldoc.getElementsByTagName('law')
        
        o = 0
        for s in lawlistxml:
            o = o + 1
        
        parameternamelistlist = [0 for x in range(o)]
        parameterdesclistlist = [0 for x in range(o)]
        
        """i is the number of laws currently in the xml file"""
        i = 0
        
        """
        Parsing xml: Acquiring rate law name, description, and list of parameter information
        """
        for s in lawlistxml:
            #RATE_LAW_MESSAGE += s.getAttribute('displayName') + "\n"
            """Gets Latec Expression"""
            displaylist.append(s.getAttribute('display'))
            
            """Gets Rate-Law Name"""
            displaynamelist.append(s.getAttribute('displayName'))
            
            """"Gets Raw Rate-Law expression"""
            infixlist.append(s.getAttribute('infixExpression'))
            
            """Gets description statement"""
            desclist.append(s.getAttribute('description'))
            
            """Gets listOfParameters Object"""
            parameterlist = s.getElementsByTagName('listOfParameters')[0]
            
            """Gets a list of parameters within ListOfParameters object"""    
            parameters = parameterlist.getElementsByTagName('parameter')
            
            for param in parameters:
                parameternamelist.append(param.attributes['name'].value)
                #print(param.attributes['name'].value)
                parameterdesclist.append(param.attributes['description'].value)  
            
            parameternamelistlist[i] = parameternamelist
            #print("break")
            parameterdesclistlist[i] = parameterdesclist
            
            parameternamelist = []
            parameterdesclist = []
            i = i + 1
        
        SLElistlist = [ 0 for x in range(i)]
        PLElistlist = [ 0 for x in range(i)]
        ILElistlist = [ 0 for x in range(i)]
        paramLElistlist = [ 0 for x in range(i)]
        numlistlist = [ 0 for x in range(i)]
        
        QWidget.__init__(self, parent)
        
        self.setWindowTitle("Rate Law Library")
        
        self.output = None
        self.error_output = None
        self._last_wdir = None
        self._last_args = None
        self._last_pythonpath = None
        
        #self.textlabel = QLabel(RATE_LAW_MESSAGE)
        
        self.lawlist = QListWidget()
        self.lawpage = QStackedWidget()
        index = 0
        for j in range(i):            
            item = QListWidgetItem(displaynamelist[j])
            self.lawlist.addItem(item)
            self.lawdetailpage = QWidget()
            setup_group = QGroupBox(displaynamelist[j])
            infixmod.append(infixlist[j].replace("___"," "))      
            setup_label = QLabel(infixmod[j])
            setup_label.setWordWrap(True)
            
            desc_group = QGroupBox("Description")
            desc_label = QLabel(desclist[j])
            desc_label.setWordWrap(True)
                        
            param_label = QGridLayout()
            nm = QLabel("Name:")
            des = QLabel("Description:")
            repl = QLabel("Replace with:")
            param_label.addWidget(nm,0,0)
            param_label.addWidget(des,0,1)
            param_label.addWidget(repl,0,2)
            """g is the total number of alterable values"""
            g = 0
            """t is the total number of alterable non-parameters"""
            t = 1
            
            snum = 0
            pnum = 0
            inum = 0
            
            """range of N is the max number of possible substrates OR products"""
            N = 5
            for n in range(N):
                nl = n+1
                if (infixmod[j].find('S%s' % nl) > -1):
                    z = QLabel('S%s is present' % nl)
                    param_label.addWidget(z,t,0)
                    snum = snum + 1
                    t = t + 1
            
            for n in range(N):
                nl = n+1    
                if (infixmod[j].find('P%s' % nl) > -1):
                    z = QLabel('P%s is present' % nl)
                    param_label.addWidget(z,t,0)
                    pnum = pnum + 1
                    t = t + 1
                    
            for n in range(N):
                nl = n+1
                if (infixmod[j].find('I%s' % nl) > -1):
                    z = QLabel('I%s is present' % nl)
                    param_label.addWidget(z,t,0)
                    inum = inum + 1
                    t = t + 1
            
            """Initialize lists of list of parameter lineedit"""    
            length = len(parameternamelistlist[j])
            for b in range(length):
                p = QLabel("%s :" % parameternamelistlist[j][b])
                param_label.addWidget(p,b+t,0)
                d = QLabel("'%s'" % parameterdesclistlist[j][b])
                param_label.addWidget(d,b+t,1)
            
            g = t + length
            
            Slineeditlist = [0 for x in range(snum)]
            Plineeditlist = [0 for x in range(pnum)]
            Ilineeditlist = [0 for x in range(inum)]
            paramlineeditlist = [0 for x in range(length)]
            
            editcount = 1
            
            """Place lineedit widgets for parameters"""
            for s in range(snum):
                Slineeditlist[s] = QLineEdit()
                param_label.addWidget(Slineeditlist[s],editcount,2)
                editcount = editcount + 1
            
            SLElistlist[j] = Slineeditlist
            
            for s in range(pnum):
                Plineeditlist[s] = QLineEdit()
                param_label.addWidget(Plineeditlist[s],editcount,2)
                editcount = editcount + 1
            
            PLElistlist[j] = Plineeditlist
            
            for s in range(inum):
                Ilineeditlist[s] = QLineEdit()
                param_label.addWidget(Ilineeditlist[s],editcount,2)
                editcount = editcount + 1
               
            ILElistlist[j] = Ilineeditlist   
            
            for s in range(length):
                paramlineeditlist[s] = QLineEdit()
                param_label.addWidget(paramlineeditlist[s],editcount,2)
                editcount = editcount + 1
            
            paramLElistlist[j] = paramlineeditlist
            
            """Necessary lists for editable parameters. Housekeeping essentially."""
            stuff = paramlineeditlist[0].text()            
            numlistlist[j] = [snum, pnum, inum, length]
            charlist = ["S","P","I"]
            
            
            
            buttonlist.append(QPushButton(self))
            buttonlist[j].setText("Insert Rate Law: %s" % displaynamelist[j])
            
            
        # Warning: do not try to regroup the following QLabel contents with 
        # widgets above -- this string was isolated here in a single QLabel
        # on purpose: to fix Issue 863
            """Page formatting"""
            setup_layout = QVBoxLayout()
            setup_layout.addWidget(setup_label)
            setup_group.setLayout(setup_layout)
           
            desc_group.setLayout(param_label)
            
            vlayout = QVBoxLayout()
            vlayout.addWidget(setup_group)
            vlayout.addWidget(desc_group)
            vlayout.addWidget(buttonlist[j])
            vlayout.addStretch(1)
            self.lawdetailpage.setLayout(vlayout)
            self.lawpage.addWidget(self.lawdetailpage)
        
        """Set up button functionality"""
        for k in range(47):
            buttonlist[k].clicked.connect(pressbutton(self, infixmod[k], SLElistlist[k], PLElistlist[k],ILElistlist[k], paramLElistlist[k], parameternamelistlist[k], numlistlist[k], charlist,k))
            
        self.lawlist.currentRowChanged.connect(self.lawpage.setCurrentIndex)
        self.lawlist.setCurrentRow(0)
        
        
        """Set up high-level widget formatting."""
        hsplitter = QSplitter()
        hsplitter.addWidget(self.lawlist)
        hsplitter.addWidget(self.lawpage)
        
        layout = QVBoxLayout()
        layout.addWidget(hsplitter)
        self.setLayout(layout)
Exemplo n.º 8
0
class RateLawWidget(QWidget):
    """
    Rate Law widget
    """
    def __init__(self, parent, max_entries=100):

        "Initialize Various list objects before assignment"
        displaylist = []
        displaynamelist = []
        infixmod = []
        infixlist = []
        desclist = []

        parameternamelist = []
        parameterdesclist = []
        parameterstringlist = []
        paramcountlist = []

        buttonlist = []
        xmldoc = minidom.parse('C:\\Users\\Jayit\\.spyder2\\ratelaw2_0_3.xml')
        #xmldoc = minidom.parse('%\\Downloads\\ratelaw2_0_3.xml')

        lawlistxml = xmldoc.getElementsByTagName('law')

        o = 0
        for s in lawlistxml:
            o = o + 1

        parameternamelistlist = [0 for x in range(o)]
        parameterdesclistlist = [0 for x in range(o)]
        """i is the number of laws currently in the xml file"""
        i = 0
        """
        Parsing xml: Acquiring rate law name, description, and list of parameter information
        """
        for s in lawlistxml:
            #RATE_LAW_MESSAGE += s.getAttribute('displayName') + "\n"
            """Gets Latec Expression"""
            displaylist.append(s.getAttribute('display'))
            """Gets Rate-Law Name"""
            displaynamelist.append(s.getAttribute('displayName'))
            """"Gets Raw Rate-Law expression"""
            infixlist.append(s.getAttribute('infixExpression'))
            """Gets description statement"""
            desclist.append(s.getAttribute('description'))
            """Gets listOfParameters Object"""
            parameterlist = s.getElementsByTagName('listOfParameters')[0]
            """Gets a list of parameters within ListOfParameters object"""
            parameters = parameterlist.getElementsByTagName('parameter')

            for param in parameters:
                parameternamelist.append(param.attributes['name'].value)
                #print(param.attributes['name'].value)
                parameterdesclist.append(param.attributes['description'].value)

            parameternamelistlist[i] = parameternamelist
            #print("break")
            parameterdesclistlist[i] = parameterdesclist

            parameternamelist = []
            parameterdesclist = []
            i = i + 1

        SLElistlist = [0 for x in range(i)]
        PLElistlist = [0 for x in range(i)]
        ILElistlist = [0 for x in range(i)]
        paramLElistlist = [0 for x in range(i)]
        numlistlist = [0 for x in range(i)]

        QWidget.__init__(self, parent)

        self.setWindowTitle("Rate Law Library")

        self.output = None
        self.error_output = None
        self._last_wdir = None
        self._last_args = None
        self._last_pythonpath = None

        #self.textlabel = QLabel(RATE_LAW_MESSAGE)

        self.lawlist = QListWidget()
        self.lawpage = QStackedWidget()
        index = 0
        for j in range(i):
            item = QListWidgetItem(displaynamelist[j])
            self.lawlist.addItem(item)
            self.lawdetailpage = QWidget()
            setup_group = QGroupBox(displaynamelist[j])
            infixmod.append(infixlist[j].replace("___", " "))
            setup_label = QLabel(infixmod[j])
            setup_label.setWordWrap(True)

            desc_group = QGroupBox("Description")
            desc_label = QLabel(desclist[j])
            desc_label.setWordWrap(True)

            param_label = QGridLayout()
            nm = QLabel("Name:")
            des = QLabel("Description:")
            repl = QLabel("Replace with:")
            param_label.addWidget(nm, 0, 0)
            param_label.addWidget(des, 0, 1)
            param_label.addWidget(repl, 0, 2)
            """g is the total number of alterable values"""
            g = 0
            """t is the total number of alterable non-parameters"""
            t = 1

            snum = 0
            pnum = 0
            inum = 0
            """range of N is the max number of possible substrates OR products"""
            N = 5
            for n in range(N):
                nl = n + 1
                if (infixmod[j].find('S%s' % nl) > -1):
                    z = QLabel('S%s is present' % nl)
                    param_label.addWidget(z, t, 0)
                    snum = snum + 1
                    t = t + 1

            for n in range(N):
                nl = n + 1
                if (infixmod[j].find('P%s' % nl) > -1):
                    z = QLabel('P%s is present' % nl)
                    param_label.addWidget(z, t, 0)
                    pnum = pnum + 1
                    t = t + 1

            for n in range(N):
                nl = n + 1
                if (infixmod[j].find('I%s' % nl) > -1):
                    z = QLabel('I%s is present' % nl)
                    param_label.addWidget(z, t, 0)
                    inum = inum + 1
                    t = t + 1
            """Initialize lists of list of parameter lineedit"""
            length = len(parameternamelistlist[j])
            for b in range(length):
                p = QLabel("%s :" % parameternamelistlist[j][b])
                param_label.addWidget(p, b + t, 0)
                d = QLabel("'%s'" % parameterdesclistlist[j][b])
                param_label.addWidget(d, b + t, 1)

            g = t + length

            Slineeditlist = [0 for x in range(snum)]
            Plineeditlist = [0 for x in range(pnum)]
            Ilineeditlist = [0 for x in range(inum)]
            paramlineeditlist = [0 for x in range(length)]

            editcount = 1
            """Place lineedit widgets for parameters"""
            for s in range(snum):
                Slineeditlist[s] = QLineEdit()
                param_label.addWidget(Slineeditlist[s], editcount, 2)
                editcount = editcount + 1

            SLElistlist[j] = Slineeditlist

            for s in range(pnum):
                Plineeditlist[s] = QLineEdit()
                param_label.addWidget(Plineeditlist[s], editcount, 2)
                editcount = editcount + 1

            PLElistlist[j] = Plineeditlist

            for s in range(inum):
                Ilineeditlist[s] = QLineEdit()
                param_label.addWidget(Ilineeditlist[s], editcount, 2)
                editcount = editcount + 1

            ILElistlist[j] = Ilineeditlist

            for s in range(length):
                paramlineeditlist[s] = QLineEdit()
                param_label.addWidget(paramlineeditlist[s], editcount, 2)
                editcount = editcount + 1

            paramLElistlist[j] = paramlineeditlist
            """Necessary lists for editable parameters. Housekeeping essentially."""
            stuff = paramlineeditlist[0].text()
            numlistlist[j] = [snum, pnum, inum, length]
            charlist = ["S", "P", "I"]

            buttonlist.append(QPushButton(self))
            buttonlist[j].setText("Insert Rate Law: %s" % displaynamelist[j])

            # Warning: do not try to regroup the following QLabel contents with
            # widgets above -- this string was isolated here in a single QLabel
            # on purpose: to fix Issue 863
            """Page formatting"""
            setup_layout = QVBoxLayout()
            setup_layout.addWidget(setup_label)
            setup_group.setLayout(setup_layout)

            desc_group.setLayout(param_label)

            vlayout = QVBoxLayout()
            vlayout.addWidget(setup_group)
            vlayout.addWidget(desc_group)
            vlayout.addWidget(buttonlist[j])
            vlayout.addStretch(1)
            self.lawdetailpage.setLayout(vlayout)
            self.lawpage.addWidget(self.lawdetailpage)
        """Set up button functionality"""
        for k in range(47):
            buttonlist[k].clicked.connect(
                pressbutton(self, infixmod[k], SLElistlist[k], PLElistlist[k],
                            ILElistlist[k], paramLElistlist[k],
                            parameternamelistlist[k], numlistlist[k], charlist,
                            k))

        self.lawlist.currentRowChanged.connect(self.lawpage.setCurrentIndex)
        self.lawlist.setCurrentRow(0)
        """Set up high-level widget formatting."""
        hsplitter = QSplitter()
        hsplitter.addWidget(self.lawlist)
        hsplitter.addWidget(self.lawpage)

        layout = QVBoxLayout()
        layout.addWidget(hsplitter)
        self.setLayout(layout)