示例#1
1
def update_mru_menu_items(mru_file_list: List[str], mru_menu: QMenu,
                          file_open_action: Callable[[str], None],
                          current_file_name: str,
                          clear_all_actions: Callable[[None], None] = None):

    # look for a separator below the item list
    act_separator = None
    act_clear = None
    for act in mru_menu.actions():
        if act.isSeparator():
            act_separator = act
        elif act.data() == 'clearall':
            act_clear = act
        if act_clear and act_separator:
            break

    if not act_separator:
        act_separator = mru_menu.addSeparator()
    if not act_clear:
        if clear_all_actions:
            act_clear = mru_menu.addAction('Clear all')
            act_clear.setData('clearall')
            act_clear.triggered.connect(clear_all_actions)
            act_clear.setVisible(len(mru_file_list) > 0)
    else:
        act_clear.setVisible(clear_all_actions is not None and len(mru_file_list) > 0)

    action_idx = -1
    home_dir = os.path.expanduser('~')
    for idx, file_name in enumerate(mru_file_list):
        if file_name.find(home_dir) == 0:
            short_file_name = '~' + file_name[len(home_dir):]
        else:
            short_file_name = file_name

        action_idx += 1
        if action_idx < len(mru_menu.actions()) and not mru_menu.actions()[action_idx].isSeparator():
            act = mru_menu.actions()[action_idx]
            act.setText(short_file_name)
        else:
            act = QAction(short_file_name, mru_menu)
            mru_menu.insertAction(act_separator, act)
        act.triggered.disconnect()
        act.triggered.connect(partial(file_open_action, file_name))
        act.setVisible(True)
        act.setCheckable(True)
        if file_name == current_file_name:
            act.setChecked(True)
        else:
            act.setChecked(False)

    # hide all unused actions
    action_idx += 1
    for idx in range(action_idx, len(mru_menu.actions())):
        act = mru_menu.actions()[idx]
        if not (act.isSeparator() or act.data() == 'clearall'):
            act.setVisible(False)

    mru_menu.update()
示例#2
0
    def setup_languages(menu: QMenu, callback: Callable):
        s = settings.Setting_Custom_Language_LANGUAGE

        languages = {
            "English": ("en", _translate("LanguageSelection", "English")),
            "German": ("de", _translate("LanguageSelection", "German")),
            "Italian": ("it", _translate("LanguageSelection", "Italian"))
        }

        menu.clear()

        def on_language_change(loc):
            s.value = loc
            callback()

        for english, _tuple in languages.items():
            action = menu.addAction(_translate("LanguageSelection", english))
            action.setIconVisibleInMenu(True)
            action.setCheckable(True)
            action.setChecked(s.value == _tuple[0])
            action.triggered.connect(lambda a, loc=_tuple[0], f=on_language_change: f(loc))

        # If language is something other than 'en', 'de', 'it'
        if menu.actions() and all(not v.isChecked() for v in menu.actions()):
            s.value = "en"
            callback()
示例#3
0
 def __showContextMenu(self):
     """
     Private slot to show the context menu.
     """
     menu = QMenu()
     act = menu.addAction(self.tr("Object blocked by ClickToFlash"))
     font = act.font()
     font.setBold(True)
     act.setFont(font)
     menu.addAction(
         self.tr("Show information about object"), self.__showInfo)
     menu.addSeparator()
     menu.addAction(self.tr("Load"), self.__load)
     menu.addAction(self.tr("Delete object"), self.__hideAdBlocked)
     menu.addSeparator()
     host = self.__url.host()
     add = menu.addAction(
         self.tr("Add '{0}' to Whitelist").format(host),
         self.__addToWhitelist)
     remove = menu.addAction(
         self.tr("Remove '{0}' from Whitelist").format(host),
         self.__removeFromWhitelist)
     onWhitelist = self.__plugin.onWhitelist(host)
     add.setEnabled(not onWhitelist)
     remove.setEnabled(onWhitelist)
     menu.addSeparator()
     menu.addAction(self.tr("Configure Whitelist"), self.__configure)
     menu.actions()[0].setEnabled(False)
     
     menu.exec_(QCursor.pos())
示例#4
0
    def __showContextMenu(self):
        """
        Private slot to show the context menu.
        """
        menu = QMenu()
        act = menu.addAction(self.tr("Object blocked by ClickToFlash"))
        font = act.font()
        font.setBold(True)
        act.setFont(font)
        menu.addAction(self.tr("Show information about object"),
                       self.__showInfo)
        menu.addSeparator()
        menu.addAction(self.tr("Load"), self.__load)
        menu.addAction(self.tr("Delete object"), self.__hideAdBlocked)
        menu.addSeparator()
        host = self.__url.host()
        add = menu.addAction(
            self.tr("Add '{0}' to Whitelist").format(host),
            self.__addToWhitelist)
        remove = menu.addAction(
            self.tr("Remove '{0}' from Whitelist").format(host),
            self.__removeFromWhitelist)
        onWhitelist = self.__plugin.onWhitelist(host)
        add.setEnabled(not onWhitelist)
        remove.setEnabled(onWhitelist)
        menu.addSeparator()
        menu.addAction(self.tr("Configure Whitelist"), self.__configure)
        menu.actions()[0].setEnabled(False)

        menu.exec_(QCursor.pos())
示例#5
0
文件: MenuView.py 项目: osl2/PhyPiDAQ
class SettingsMenuView(QMenu):
    """This class represents the settings menu of the main menu bar"""
    def __init__(self, parent: QWidget):
        super().__init__(parent)

        self.addAction("", self.__open_global_options)
        self.__settings_window: ConfigView = None
        ManagerModel.init_config()

        self.__language_menu = QMenu("", self)
        self.addMenu(self.__language_menu)

        # Add languages here
        self.__language_menu.addAction(LanguageAction(self, QLocale.German))
        self.__language_menu.addAction(LanguageAction(self, QLocale.English))

        Translator.language_changed.signal.connect(self.__update_text)
        self.__update_text()

    def __update_text(self):
        self.setTitle(Translator.tr("Einstellungen"))
        self.actions()[0].setText(Translator.tr("Globale Einstellungen"))
        self.__language_menu.setTitle(Translator.tr("Sprache"))
        self.__language_menu.actions()[0].setText(Translator.tr("Deutsch"))
        self.__language_menu.actions()[1].setText(Translator.tr("Englisch"))

    def __open_global_options(self):
        self.__settings_window = ConfigView("Globales", ManagerModel.get_settings())
示例#6
0
def show(position, panel, link, cursor):
    """Shows a context menu.

    position: The global position to pop up
    panel: The music view panel, giving access to mainwindow and view widget
    link: a popplerqt5 LinkBrowse instance or None
    cursor: a QTextCursor instance or None

    """
    m = QMenu(panel)

    # selection? -> Copy
    if panel.widget().view.surface().hasSelection():
        if panel.widget().view.surface().selectedText():
            m.addAction(panel.actionCollection.music_copy_text)
        m.addAction(panel.actionCollection.music_copy_image)

    if cursor:
        a = m.addAction(icons.get("document-edit"), _("Edit in Place"))

        @a.triggered.connect
        def edit():
            import editinplace
            editinplace.edit(panel.widget(), cursor, position)
    elif link:
        a = m.addAction(icons.get("window-new"), _("Open Link in &New Window"))

        @a.triggered.connect
        def open_in_browser():
            import helpers
            helpers.openUrl(QUrl(link.url()))

        a = m.addAction(icons.get("edit-copy"), _("Copy &Link"))

        @a.triggered.connect
        def copy_link():
            QApplication.clipboard().setText(link.url())

    # no actions yet? insert Fit Width/Height
    if not m.actions():
        m.addAction(panel.actionCollection.music_fit_width)
        m.addAction(panel.actionCollection.music_fit_height)
        m.addAction(panel.actionCollection.music_zoom_original)
        m.addSeparator()
        m.addAction(panel.actionCollection.music_sync_cursor)

    # help
    m.addSeparator()
    a = m.addAction(icons.get("help-contents"), _("Help"))

    @a.triggered.connect
    def help():
        import userguide
        userguide.show("musicview")

    # show it!
    if m.actions():
        m.exec_(position)
    m.deleteLater()
示例#7
0
def show(position, panel, link, cursor):
    """Shows a context menu.

    position: The global position to pop up
    panel: The music view panel, giving access to mainwindow and view widget
    link: a popplerqt5 LinkBrowse instance or None
    cursor: a QTextCursor instance or None

    """
    m = QMenu(panel)

    # selection? -> Copy
    if panel.widget().view.surface().hasSelection():
        if panel.widget().view.surface().selectedText():
            m.addAction(panel.actionCollection.music_copy_text)
        m.addAction(panel.actionCollection.music_copy_image)

    if cursor:
        a = m.addAction(icons.get("document-edit"), _("Edit in Place"))
        @a.triggered.connect
        def edit():
            import editinplace
            editinplace.edit(panel.widget(), cursor, position)
    elif link:
        a = m.addAction(icons.get("window-new"), _("Open Link in &New Window"))
        @a.triggered.connect
        def open_in_browser():
            import helpers
            helpers.openUrl(QUrl(link.url()))

        a = m.addAction(icons.get("edit-copy"), _("Copy &Link"))
        @a.triggered.connect
        def copy_link():
            QApplication.clipboard().setText(link.url())

    # no actions yet? insert Fit Width/Height
    if not m.actions():
        m.addAction(panel.actionCollection.music_fit_width)
        m.addAction(panel.actionCollection.music_fit_height)
        m.addAction(panel.actionCollection.music_zoom_original)
        m.addSeparator()
        m.addAction(panel.actionCollection.music_sync_cursor)

    # help
    m.addSeparator()
    a = m.addAction(icons.get("help-contents"), _("Help"))
    @a.triggered.connect
    def help():
        import userguide
        userguide.show("musicview")

    # show it!
    if m.actions():
        m.exec_(position)
    m.deleteLater()
示例#8
0
def find_action(menu: QMenu, actionText):
    actions = menu.actions()
    for act in actions:
        currText = act.text()
        if actionText in currText:
            return act
    return None
示例#9
0
    def _show_menu(self, pos):
        item = self.itemAt(pos)
        menu = QMenu()
        self.set_menu_actions(item, menu)

        copy_address = None
        if isinstance(item, MemoryAddressWidget):
            if len(menu.actions()) > 0:
                menu.addSeparator()
            jump_to_address = menu.addAction('Jump to pointer')
            dump = menu.addAction('Dump binary')
            menu.addSeparator()
            copy_address = menu.addAction('Copy address')

        action = menu.exec_(self.mapToGlobal(pos))
        if action:
            if not self.on_menu_action(action.data(), item):
                return
            if isinstance(item, MemoryAddressWidget):
                if action == copy_address:
                    pyperclip.copy(hex(item.get_address()))
                elif action == jump_to_address:
                    self.app.get_memory_panel().read_memory(
                        ptr=item.get_address(),
                        length=item.get_size(),
                        base=item.get_base_address())
                elif action == dump:
                    self.app.get_dwarf().dump_memory(ptr=item.get_address(),
                                                     length=item.get_size())
示例#10
0
    def updatePlotPersoButton(self):
        menu = QMenu(self.mw)

        menus = []
        for i in [self.tr("Main"), self.tr("Secondary"), self.tr("Minor")]:
            m = QMenu(i, menu)
            menus.append(m)
            menu.addMenu(m)

        mpr = QSignalMapper(menu)
        for i in range(self.mw.mdlCharacter.rowCount()):
            a = QAction(self.mw.mdlCharacter.name(i), menu)
            a.setIcon(self.mw.mdlCharacter.icon(i))
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, int(self.mw.mdlCharacter.ID(i)))

            imp = toInt(self.mw.mdlCharacter.importance(i))

            menus[2 - imp].addAction(a)

        # Disabling empty menus
        for m in menus:
            if not m.actions():
                m.setEnabled(False)

        mpr.mapped.connect(self.addPlotPerso)
        self.mw.btnAddPlotPerso.setMenu(menu)
示例#11
0
 def slotShowContextMenu(self, pos):
     hit = self.webview.page().currentFrame().hitTestContent(pos)
     menu = QMenu()
     if hit.linkUrl().isValid():
         a = self.webview.pageAction(QWebPage.CopyLinkToClipboard)
         a.setIcon(icons.get("edit-copy"))
         a.setText(_("Copy &Link"))
         menu.addAction(a)
         menu.addSeparator()
         a = menu.addAction(icons.get("window-new"),
                            _("Open Link in &New Window"))
         a.triggered.connect(
             (lambda url: lambda: self.slotNewWindow(url))(hit.linkUrl()))
     else:
         if hit.isContentSelected():
             a = self.webview.pageAction(QWebPage.Copy)
             a.setIcon(icons.get("edit-copy"))
             a.setText(_("&Copy"))
             menu.addAction(a)
             menu.addSeparator()
         a = menu.addAction(icons.get("window-new"),
                            _("Open Document in &New Window"))
         a.triggered.connect((lambda url: lambda: self.slotNewWindow(url))(
             self.webview.url()))
     if menu.actions():
         menu.exec_(self.webview.mapToGlobal(pos))
示例#12
0
    def customContextMenu(self, position):
        '''show context menu'''

        # group at cursor position
        index = self.indexAt(position)
        if not index.isValid():
            return

        # init context menu
        menu = QMenu()
        if not self.sourceModel.isDefaultGroup(index):
            menu.addAction(self.tr("Create Group"), self.slot_insertRow)
            menu.addAction(self.tr("Create Sub-Group"), self.slot_insertChild)
            menu.addSeparator()
            menu.addAction(self.tr("Empty Group"), self.slot_emptyGroup)
            menu.addAction(self.tr("Remove Group"), self.slot_removeRow)
        else:
            key = index.siblingAtColumn(GroupModel.KEY).data()

            if key == GroupModel.ALLGROUPS:
                menu.addAction(self.tr("Create Group"), self.slot_insertRow)

            if key == GroupModel.TRASH:
                trash = menu.addAction(self.tr("Empty Trash"),
                                       lambda: self.emptyTrash.emit(key))
                # no items in trash
                if '(' not in index.siblingAtColumn(GroupModel.NAME).data():
                    trash.setEnabled(False)

        if menu.actions():
            menu.exec_(self.viewport().mapToGlobal(position))
示例#13
0
    def updatePlotPersoButton(self):
        menu = QMenu(self.mw)

        menus = []
        for i in [self.tr("Main"), self.tr("Secondary"), self.tr("Minor")]:
            m = QMenu(i, menu)
            menus.append(m)
            menu.addMenu(m)

        mpr = QSignalMapper(menu)
        for i in range(self.mw.mdlCharacter.rowCount()):
            a = QAction(self.mw.mdlCharacter.name(i), menu)
            a.setIcon(self.mw.mdlCharacter.icon(i))
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, int(self.mw.mdlCharacter.ID(i)))

            imp = toInt(self.mw.mdlCharacter.importance(i))

            menus[2 - imp].addAction(a)

        # Disabling empty menus
        for m in menus:
            if not m.actions():
                m.setEnabled(False)

        mpr.mapped.connect(self.addPlotPerso)
        self.mw.btnAddPlotPerso.setMenu(menu)
示例#14
0
    def _show_menu(self, pos):
        item = self.itemAt(pos)
        menu = QMenu()
        search = None
        if isinstance(item, MemoryAddressWidget):
            sym = self.app.dwarf.dwarf_api('getSymbolByAddress',
                                           item.get_address())
            if sym is not None:
                if sym['name'] == '' or sym['name'] is None:
                    sym['name'] = sym['address']
                sym_action = menu.addAction('%s (%s)' %
                                            (sym['name'], sym['moduleName']))
                sym_action.setEnabled(False)
                menu.addSeparator()
        else:
            if self.is_search_enabled():
                search = menu.addAction('Search')
                menu.addSeparator()

        self.set_menu_actions(item, menu)

        copy_address = None
        if isinstance(item, MemoryAddressWidget):
            if len(menu.actions()) > 0:
                menu.addSeparator()

            if self.app.dwarf.dwarf_api('isAddressWatched',
                                        item.get_address()):
                watcher = menu.addAction('Remove memory watcher')
            else:
                watcher = menu.addAction('Add memory watcher')
            jump_to_address = menu.addAction('Jump to pointer')
            dump = menu.addAction('Dump binary')
            menu.addSeparator()
            copy_address = menu.addAction('Copy address')

        action = menu.exec_(self.mapToGlobal(pos))
        if action:
            if search is not None and action == search:
                self.search()
            if not self.on_menu_action(action.data(), item):
                return
            if isinstance(item, MemoryAddressWidget):
                if action == copy_address:
                    pyperclip.copy(hex(item.get_address()))
                elif action == watcher:
                    if self.app.dwarf.dwarf_api('isAddressWatched',
                                                item.get_address()):
                        self.app.dwarf.remove_watcher(item.get_address())
                    else:
                        self.app.dwarf.add_watcher(item.get_address())
                elif action == jump_to_address:
                    self.app.memory_panal.read_memory(
                        ptr=item.get_address(),
                        length=item.get_size(),
                        base=item.get_base_address())
                elif action == dump:
                    self.app.dwarf.dump_memory(ptr=item.get_address(),
                                               length=item.get_size())
示例#15
0
class Window(QWidget):
    def __init__(self, *args, **kwargs):
        super(Window, self).__init__(*args, **kwargs)
        layout = QVBoxLayout(self)
        self.labelInfo = QLabel(self)
        self.button = QPushButton('带按钮的菜单', self)
        layout.addWidget(self.labelInfo)
        layout.addWidget(self.button)

        # 添加菜单
        self._initMenu()

    def _initMenu(self):
        # 创建菜单
        self._menu = QMenu(self.button)
        # 替换menu的鼠标释放事件达到选择性不关闭菜单
        self._menu.mouseReleaseEvent = self._menu_mouseReleaseEvent
        self._menu.addAction('菜单1', self._checkAction)
        self._menu.addAction('菜单2', self._checkAction)
        self._menu.addAction(
            QAction('菜单3', self._menu, triggered=self._checkAction))
        action = QAction('菜单4', self._menu, triggered=self._checkAction)
        # 添加自定义的属性,判断该属性可以关闭菜单
        action.setProperty('canHide', True)
        self._menu.addAction(action)
        for action in self._menu.actions():
            # 循环设置可勾选
            action.setCheckable(True)
        self.button.setMenu(self._menu)

    def _menu_mouseReleaseEvent(self, event):
        action = self._menu.actionAt(event.pos())
        if not action:
            # 没有找到action就交给QMenu自己处理
            return QMenu.mouseReleaseEvent(self._menu, event)
        if action.property('canHide'):  # 如果有该属性则给菜单自己处理
            return QMenu.mouseReleaseEvent(self._menu, event)
        # 找到了QAction则只触发Action
        action.activate(action.Trigger)

    def _checkAction(self):
        # 三个action都响应该函数
        self.labelInfo.setText('\n'.join([
            '{}\t选中:{}'.format(action.text(), action.isChecked())
            for action in self._menu.actions()
        ]))
示例#16
0
def _on_menu_about_to_show(log_api: LogApi, menu: QMenu) -> None:
    window = _window_from_menu(menu)
    window.setProperty("focused-widget", window.focusWidget())
    for action in menu.actions():
        if getattr(action, "commands", None):
            enabled = False
            with log_api.exception_guard():
                enabled = all(cmd.is_enabled for cmd in action.commands)
            action.setEnabled(enabled)
示例#17
0
    def customContextMenu(self, position):
        '''show context menu'''

        # menus on items
        menu = QMenu()

        indexes = self.selectionModel().selectedRows(ItemModel.GROUP)

        if indexes:  # actions on index
            # group of current item
            gid = indexes[0].data()

            # tags of current item
            tids = self.selectionModel().selectedRows(ItemModel.TAGS)[0].data()

            if gid != self.groupView.model().UNREFERENCED:
                # open source path
                menu.addAction(self.tr("Open Reference"), self.slot_navigateTo)
                menu.addSeparator()

                # menus on groups
                move = QMenu(self.tr('Move to Group'))
                groups = self.rootGroup()[self.groupView.model().CHILDREN]
                self.setupCascadeGroupMenu(move, groups, gid)

                if move.actions():
                    menu.addMenu(move)
                    menu.addSeparator()

            # menus on tags
            addTag = QMenu(self.tr("Attach Tags"))
            delTag = QMenu(self.tr("Remove Tags"))
            self.setupTagsMenu(menu, addTag, delTag, tids)
            menu.addSeparator()

            # remove items to trash
            trash = self.groupView.model().TRASH
            if gid != trash:
                menu.addAction(self.tr("Move to Trash"),
                               partial(self.slot_moveToGroup, trash))
            else:
                menu.addAction(self.tr("Delete"), self.slot_deleteItems)

        else:
            # create item
            menu.addAction(self.tr("New Item"),
                           partial(self.slot_appendRows, True))
            menu.addAction(self.tr("Import Items"),
                           partial(self.slot_appendRows, False))
            menu.addSeparator()
            menu.addAction(self.tr("Find Duplicated"),
                           self.slot_findDuplicatedItems)
            menu.addAction(self.tr("Find Unreferenced"),
                           self.slot_findUnreferencedItems)

        menu.exec_(self.viewport().mapToGlobal(position))
示例#18
0
def menu_sessions(parent):
    m = QMenu(parent)
    m.setTitle(_('menu title', '&Session'))
    m.triggered.connect(slot_session_action)
    import sessions
    for name in sessions.sessionNames():
        a = m.addAction(name.replace('&', '&&'))
        a.setObjectName(name)
    qutil.addAccelerators(m.actions())
    return m
示例#19
0
    def open_file_menu(self, event):
        menu = QMenu(self.sender())

        if self.process.status not in ('ERROR', 'Aborted', 'Filesize Error'):
            menu.addAction('Open folder', self.open_file)
        if self.url is not None:
            menu.addAction('Copy URL', lambda: to_clipboard(self.url))
        if not menu.actions():
            return
        menu.exec(QCursor.pos())
示例#20
0
def menu_file_open_recent(parent):
    m = QMenu(parent)
    m.setTitle(_("Open &Recent"))
    m.triggered.connect(slot_file_open_recent_action)
    import recentfiles
    for url in recentfiles.urls():
        f = url.toLocalFile()
        dirname, basename = os.path.split(f)
        text = "{0}  ({1})".format(basename, util.homify(dirname))
        m.addAction(text).url = url
    qutil.addAccelerators(m.actions())
    return m
示例#21
0
    def createStandardContextMenu(self):
        popup_menu = QTextEdit.createStandardContextMenu(self)

        if not self.spellcheck:
            return popup_menu

        # Select the word under the cursor.
        # But only if there is no selection (otherwise it's impossible to select more text to copy/cut)
        cursor = self.textCursor()
        if not cursor.hasSelection():
            cursor.select(QTextCursor.WordUnderCursor)
            self.setTextCursor(cursor)

        # Check if the selected word is misspelled and offer spelling
        # suggestions if it is.
        if cursor.hasSelection():
            text = str(cursor.selectedText())
            valid = self._dict.check(text)
            selectedWord = cursor.selectedText()
            if not valid:
                spell_menu = QMenu(self.tr('Spelling Suggestions'), self)
                spell_menu.setIcon(F.themeIcon("spelling"))
                for word in self._dict.suggest(text):
                    action = self.SpellAction(word, spell_menu)
                    action.correct.connect(self.correctWord)
                    spell_menu.addAction(action)
                # Only add the spelling suggests to the menu if there are
                # suggestions.
                if len(spell_menu.actions()) != 0:
                    popup_menu.insertSeparator(popup_menu.actions()[0])
                    # Adds: add to dictionary
                    addAction = QAction(self.tr("&Add to dictionary"),
                                        popup_menu)
                    addAction.setIcon(QIcon.fromTheme("list-add"))
                    addAction.triggered.connect(self.addWordToDict)
                    addAction.setData(selectedWord)
                    popup_menu.insertAction(popup_menu.actions()[0], addAction)
                    # Adds: suggestions
                    popup_menu.insertMenu(popup_menu.actions()[0], spell_menu)
                    # popup_menu.insertSeparator(popup_menu.actions()[0])

            # If word was added to custom dict, give the possibility to remove it
            elif valid and self._dict.is_added(selectedWord):
                popup_menu.insertSeparator(popup_menu.actions()[0])
                # Adds: remove from dictionary
                rmAction = QAction(self.tr("&Remove from custom dictionary"),
                                   popup_menu)
                rmAction.setIcon(QIcon.fromTheme("list-remove"))
                rmAction.triggered.connect(self.rmWordFromDict)
                rmAction.setData(selectedWord)
                popup_menu.insertAction(popup_menu.actions()[0], rmAction)

        return popup_menu
示例#22
0
class QV(QtWidgets.QGraphicsView):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.view_menu = QMenu(self)
        self.create_actions()

    def create_actions(self):
        act = create_action(self.view_menu,
                            "Zoom in",
                            slot=self.on_zoom_in,
                            shortcut=QKeySequence("+"),
                            shortcut_context=Qt.WidgetShortcut)
        self.view_menu.addAction(act)

        act = create_action(self.view_menu,
                            "Zoom out",
                            slot=self.on_zoom_out,
                            shortcut=QKeySequence("-"),
                            shortcut_context=Qt.WidgetShortcut)
        self.view_menu.addAction(act)
        self.addActions(self.view_menu.actions())

    def on_zoom_in(self):
        if not self.scene():
            return

        self.scale(1.5, 1.5)

    def on_zoom_out(self):
        if not self.scene():
            return

        self.scale(1.0 / 1.5, 1.0 / 1.5)

    def drawBackground(self, painter, rect):
        gr = rect.toRect()
        start_x = gr.left() + Settings.WIDTH - (gr.left() % Settings.WIDTH)
        start_y = gr.top() + Settings.HEIGHT - (gr.top() % Settings.HEIGHT)
        painter.save()
        painter.setPen(QtGui.QColor(60, 70, 80).lighter(90))
        painter.setOpacity(0.7)

        for x in range(start_x, gr.right(), Settings.WIDTH):
            painter.drawLine(x, gr.top(), x, gr.bottom())

        for y in range(start_y, gr.bottom(), Settings.HEIGHT):
            painter.drawLine(gr.left(), y, gr.right(), y)

        painter.restore()

        super().drawBackground(painter, rect)
示例#23
0
    def setup_menu_window_title(menu: QMenu, callback: Callable):
        s = settings.Setting_Custom_Appearance_General_WINDOW_TITLE

        def set_window_title(idx_):
            s.value = idx_
            callback()

        group = QActionGroup(menu)
        for idx, action in enumerate(menu.actions()):
            action.setChecked(idx == s.value)
            action.triggered.connect(lambda x, a=idx, f=set_window_title: f(a))

            group.addAction(action)
示例#24
0
    def createStandardContextMenu(self):
        popup_menu = QTextEdit.createStandardContextMenu(self)

        if not self.spellcheck:
            return popup_menu

        # Select the word under the cursor.
        # But only if there is no selection (otherwise it's impossible to select more text to copy/cut)
        cursor = self.textCursor()
        if not cursor.hasSelection():
            cursor.select(QTextCursor.WordUnderCursor)
            self.setTextCursor(cursor)

        # Check if the selected word is misspelled and offer spelling
        # suggestions if it is.
        if self._dict and cursor.hasSelection():
            text = str(cursor.selectedText())
            valid = self._dict.check(text)
            selectedWord = cursor.selectedText()
            if not valid:
                spell_menu = QMenu(self.tr('Spelling Suggestions'), self)
                spell_menu.setIcon(F.themeIcon("spelling"))
                for word in self._dict.suggest(text):
                    action = self.SpellAction(word, spell_menu)
                    action.correct.connect(self.correctWord)
                    spell_menu.addAction(action)
                # Only add the spelling suggests to the menu if there are
                # suggestions.
                if len(spell_menu.actions()) != 0:
                    popup_menu.insertSeparator(popup_menu.actions()[0])
                    # Adds: add to dictionary
                    addAction = QAction(self.tr("&Add to dictionary"), popup_menu)
                    addAction.setIcon(QIcon.fromTheme("list-add"))
                    addAction.triggered.connect(self.addWordToDict)
                    addAction.setData(selectedWord)
                    popup_menu.insertAction(popup_menu.actions()[0], addAction)
                    # Adds: suggestions
                    popup_menu.insertMenu(popup_menu.actions()[0], spell_menu)
                    # popup_menu.insertSeparator(popup_menu.actions()[0])

            # If word was added to custom dict, give the possibility to remove it
            elif valid and self._dict.is_added(selectedWord):
                popup_menu.insertSeparator(popup_menu.actions()[0])
                # Adds: remove from dictionary
                rmAction = QAction(self.tr("&Remove from custom dictionary"), popup_menu)
                rmAction.setIcon(QIcon.fromTheme("list-remove"))
                rmAction.triggered.connect(self.rmWordFromDict)
                rmAction.setData(selectedWord)
                popup_menu.insertAction(popup_menu.actions()[0], rmAction)

        return popup_menu
示例#25
0
def createToolButton(actionNamesList, parent=None):
    try:
        menu = QMenu(parent)
        for an in actionNamesList:
            addAction(menu, an, parent)
            actions = [a for a in menu.actions()]
        tb = QToolButton()
        tb.setDefaultAction(actions[0])
        tb.setMenu(menu)
        tb.setPopupMode(QToolButton.MenuButtonPopup)
        menu.triggered.connect(tb.setDefaultAction)
        return tb
    except Exception as e:
        info(e)
示例#26
0
    def _customContextMenuRequested(self, pos):
        '''
        @param: pos QPoint
        '''
        menu = QMenu()
        menu.addAction(QIcon.fromTheme('document-open'), _('Open File'),
                       self.__openFile)

        menu.addAction(_('Open Folder'), self._openFolder)
        menu.addSeparator()
        menu.addAction(QIcon.fromTheme('edit-copy'), _('Copy Download Link'),
                       self._copyDownloadLink)
        menu.addSeparator()
        menu.addAction(QIcon.fromTheme('process-stop'),
                       _('Cancel downloading'),
                       self._stop).setEnabled(self._downloading)
        menu.addAction(QIcon.fromTheme('list-remove'), _('Remove From List'),
                       self._clear).setEnabled(not self._downloading)

        if self._downloading or self._ui.downloadInfo.text().startswith(_('Cancelled')) or \
                self._ui.downloadInfo.text().startswith(_('Error')):
            menu.actions()[0].setEnabled(False)
        menu.exec_(self.mapToGlobal(pos))
示例#27
0
        def table_Strat_context_menu(event_star):
            root_menu = QMenu(table_Equip)
            this_item = table_Strat.itemAt(event_star.pos())
            dis_gear = this_item.__dict__[STR_TW_GEAR]
            eq_row = None
            for rew in range(0, table_Equip.rowCount()):
                if dis_gear is table_Equip.item(rew, 0).__dict__[STR_TW_GEAR]:
                    eq_row = table_Equip.item(rew, 0)

            give_menu_downgrade(root_menu, event_star, eq_row)
            for akshon in root_menu.actions():
                akshon.triggered.connect(lambda: frmObj.cmdStrat_go.click())

            root_menu.exec_(event_star.globalPos())
示例#28
0
def insert_new_action(menu: QMenu, text: str, index: int):
    actionsList = menu.actions()
    if index >= len(actionsList):
        if text:
            return menu.addAction(text)
        return menu.addSeparator()
    indexAction = actionsList[index]
    if text:
        newAction = QAction(text, menu)
        menu.insertAction(indexAction, newAction)
    else:
        newAction = QAction(menu)
        newAction.setSeparator(True)
        menu.insertAction(indexAction, newAction)
    return newAction
示例#29
0
class PopupWidget(QPushButton):
    def __init__(self, label, elements, checklist, parent=None):
        super(PopupWidget, self).__init__(parent)
        self.parent = parent
        self.setText(label)
        self.menu = QMenu(self)
        self.checklist = checklist
        for i in range(0, len(elements)):
            Action = QAction(elements[i], self.menu)
            Action.triggered.connect(lambda chk, item=i: self.open_spectral(item))
            self.menu.addAction(Action)

    def mouseReleaseEvent(self, event):
        self.menu.exec_(event.globalPos())

    def open_spectral(self, index):
        self.parent.open_spectral(index)

    def getChecklist(self):
        mlen = len(self.menu.actions())
        checklist = np.zeros(mlen)
        for i in range(0, mlen):
            checklist[i] = self.menu.actions()[i].isChecked()
        return checklist
示例#30
0
 def check_index_widget_menu(self, index: QModelIndex, menu: QMenu):
     item = self.itemFromIndex(index)
     if item is not None:
         gw = self.itemWidget(item, self.get_header_index(HEADER_NAME))
         if isinstance(gw, GearWidget):
             if len(menu.actions()) > 0:
                 menu.addSeparator()
             action_downgrade = QAction('Downgrade', menu)
             action_downgrade.triggered.connect(
                 lambda: self.frmMain.downgrade(gw))
             menu.addAction(action_downgrade)
             action_upgrade = QAction('Upgrade', menu)
             action_upgrade.triggered.connect(
                 lambda: self.frmMain.simulate_success_gear(
                     gw.gear, this_item=gw.parent_widget))
             menu.addAction(action_upgrade)
示例#31
0
def translate_text_widget_menu(menu: QtW.QMenu):
    """Translates the text of each action from the given text widget’s context menu."""
    keys = [
        'menu_common.undo_item',
        'menu_common.redo_item',
        'menu_common.cut_item',
        'menu_common.copy_item',
        'menu_common.paste_item',
        'menu_common.delete_item',
        'menu_common.select_all_item',
    ]
    i = 0
    for action in menu.actions():
        if not action.isSeparator():
            shortcut = action.text().split('\t')[1] if '\t' in action.text() else ''
            action.setText(_t(keys[i]) + '\t' + shortcut)
            i += 1
示例#32
0
 def createToolButton(self, actionNamesList, parent=None):
     try:
         if len(actionNamesList) == 0: return
         if actionNamesList[0].lower() == 'combo:':
             del actionNamesList[0]
             return GtoToolCombo(self.gtomain, actionNamesList, None)
         menu = QMenu(parent)
         for an in actionNamesList:
             self.addAction(menu, an, parent)
             actions = [a for a in menu.actions()]
         tb = QToolButton()
         tb.setDefaultAction(actions[0])
         tb.setMenu(menu)
         tb.setPopupMode(QToolButton.MenuButtonPopup)
         menu.triggered.connect(tb.setDefaultAction)
         return tb
     except Exception as e:
         self.info.err(e)
示例#33
0
    def _show_menu(self, pos):
        item = self.itemAt(pos)
        menu = QMenu()
        self.set_menu_actions(item, menu)

        copy_address = None
        if isinstance(item, MemoryAddressWidget):
            if len(menu.actions()) > 0:
                menu.addSeparator()
            copy_address = menu.addAction('Copy address')

        action = menu.exec_(self.mapToGlobal(pos))
        if action:
            if not self.on_menu_action(action.data(), item):
                return
            if isinstance(item, MemoryAddressWidget):
                if action == copy_address:
                    pyperclip.copy(hex(item.get_address()))
示例#34
0
def menu_file_new_from_template(parent):
    m = QMenu(parent)
    m.setTitle(_("New from &Template"))
    m.triggered.connect(slot_file_new_from_template_action)
    from snippet import model, actions, snippets
    groups = {}
    for name in sorted(model.model().names()):
        variables = snippets.get(name).variables
        group = variables.get('template')
        if group:
            action = actions.action(name, m)
            if action:
                groups.setdefault(group, []).append(action)
    for group in sorted(groups):
        for action in groups[group]:
            m.addAction(action)
        m.addSeparator()
    qutil.addAccelerators(m.actions())
    return m
示例#35
0
 def __init__(self):
     # We need this to load the GUI
     super(mapEditorWindow, self).__init__()
     uic.loadUi(os.path.join(GUI_FOLDER, 'mapEditor.ui'), self)
     # Defining radio buttons
     self.brushRadio.setText('Brush')
     self.rectangleRadio.setText('Rectangle')
     # A button for filling the whole map with a tile
     self.fillButton.setText('Fill Map')
     # Let's also define labels
     self.columnLabel.setText('Columns: -')
     self.rowLabel.setText('Rows: -')
     # This should take the brush as the default 
     self.brushRadio.setChecked(True)
     # I will instance this here because I f****d up
     self.triggerEditorInstance = triggerEditorWindow()
     # A Tool Button for loading tilemaps and stuff
     self.toolButton.setPopupMode(2)
     # Since I don't know how to load this stuff properly, I'll improvise.
     menu = QMenu()
     actions = ['Load Tilemap', 'Load map', 'Triggers', 'Save Map',
               'Load Old Map']
     for i in actions:
         menu.addAction(i)
     del(actions)
     menuActions = menu.actions()
     self.loadTmAction = menuActions[0]
     self.loadMapAction = menuActions[1]
     self.triggersAction = menuActions[2]
     self.saveMap = menuActions[3]
     self.pickOldMapAction = menuActions[4]
     self.toolButton.setMenu(menu)
     self.toolButton.setArrowType(Qt.DownArrow)
     self.tileMapFlag = False
     self.mapFileFlag = False
     # Signals
     self.loadTmAction.triggered.connect(self.pickTilemap)
     self.loadMapAction.triggered.connect(self.pickMap)
     self.triggersAction.triggered.connect(self.triggerEditor)
     self.saveMap.triggered.connect(self.saveMapFile)
     self.pickOldMapAction.triggered.connect(self.pickOldMap)
     self.mapFileViewer.itemSelectionChanged.connect(self.paint)
示例#36
0
 def slotShowContextMenu(self, pos):
     hit = self.webview.page().currentFrame().hitTestContent(pos)
     menu = QMenu()
     if hit.linkUrl().isValid():
         a = self.webview.pageAction(QWebPage.CopyLinkToClipboard)
         a.setIcon(icons.get("edit-copy"))
         a.setText(_("Copy &Link"))
         menu.addAction(a)
         menu.addSeparator()
         a = menu.addAction(icons.get("window-new"), _("Open Link in &New Window"))
         a.triggered.connect((lambda url: lambda: self.slotNewWindow(url))(hit.linkUrl()))
     else:
         if hit.isContentSelected():
             a = self.webview.pageAction(QWebPage.Copy)
             a.setIcon(icons.get("edit-copy"))
             a.setText(_("&Copy"))
             menu.addAction(a)
             menu.addSeparator()
         a = menu.addAction(icons.get("window-new"), _("Open Document in &New Window"))
         a.triggered.connect((lambda url: lambda: self.slotNewWindow(url))(self.webview.url()))
     if menu.actions():
         menu.exec_(self.webview.mapToGlobal(pos))
示例#37
0
文件: textedit.py 项目: hovo1990/GROM
    def contextMenuEvent(self, event):
        popup_menu = self.createStandardContextMenu()
        # color: rgb(154, 190, 154);
        menu_style = "QMenu { background-color: rgb(38,38,38);selection-color: black; selection-background-color: grey;}"
        popup_menu.setStyleSheet(menu_style)

        # Select the word under the cursor.
        cursor = self.textCursor()
        cursor.select(QTextCursor.WordUnderCursor)
        self.setTextCursor(cursor)

        # Check if the selected word is misspelled and offer spelling
        # suggestions if it is.
        if enchant and self.dict:
            if self.textCursor().hasSelection():
                text = str(self.textCursor().selectedText())
                if self.dict.check(text):
                    self.gotoHelp = QAction('Goto in Help', self)
                    self.gotoHelp.triggered.connect(self.showInHelpFile)
                    popup_menu.insertAction(popup_menu.actions()[0], self.gotoHelp)
                    popup_menu.insertSeparator(popup_menu.actions()[1])
                if not self.dict.check(text):
                    spell_menu = QMenu(QCoreApplication.translate('app', 'Spelling Suggestions'), self)
                    spell_menu.setStyleSheet(menu_style)
                    for word in self.dict.suggest(text):
                        # print('word is ',word)
                        action = SpellAction(word, spell_menu)
                        action.correct.connect(self.correctWord)
                        spell_menu.addAction(action)
                    # Only add the spelling suggests to the menu if there are
                    # suggestions.
                    if len(spell_menu.actions()) != 0:
                        popup_menu.insertSeparator(popup_menu.actions()[0])
                        popup_menu.insertMenu(popup_menu.actions()[0], spell_menu)

        # FIXME: add change dict and disable spellcheck options

        popup_menu.exec_(event.globalPos())
示例#38
0
class Navigation(QWidget):
    """
    Navigation class definition.
    
    Provide a combobox to switch on each opened directories and display it into
    a tree view
    
    Provide 2 useful function (to use in alter module):
      - add_action(name, shortcut, callback)
         - callback take 2 arguments : file_info and parent
      - add_separator()
    
    """
    
    SETTINGS_DIRECTORIES = 'navigation_dirs'
    SETTINGS_CURRENT_DIR = 'navigation_current_dir'
    
    onFileItemActivated = pyqtSignal(QFileInfo, name="onFileItemActivated")
    onDirItemActivated = pyqtSignal(QFileInfo, name="onDirItemActivated")
    
    def __init__(self, parent=None):
        super(Navigation, self).__init__(parent)
        self.setObjectName("Navigation")
        
        self.layout = QVBoxLayout(self)
        self.layout.setSpacing(0)
        self.layout.setContentsMargins(0,0,0,0)
        
        self.menu_button = QPushButton('Select directory', self)
        self.menu_button.setFlat(True)
#        self.menu_button.clicked.connect(self.on_menu_button_clicked)
        self.menu = QMenu(self)
        self.menu_button.setMenu(self.menu)
        self.menu_directories = QMenu(self)
        self.menu_directories.setTitle('Directories')
        self.menu_add_action(
            'Open directory', self.open_directory, None, QKeySequence.Open)
        self.menu_add_separator()
        self.menu_add_action('Refresh', self.reset, None, QKeySequence.Refresh)
        # @TODO invoke_all
        self.menu_add_separator()
        self.menu.addMenu(self.menu_directories)
        
        self.tree = QTreeView(self)
        self.model = FileSystemModel(self)
        self.tree.setModel(self.model)
        self.tree.setColumnHidden(1, True)
        self.tree.setColumnHidden(2, True)
        self.tree.setColumnHidden(3, True)
        self.tree.setHeaderHidden(True)
        # only to expand directory or activated with one click
        self.tree.clicked.connect(self.on_item_clicked)
        # else, for file use activated signal
        self.tree.activated.connect(self.on_item_activated)
        self.tree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree.customContextMenuRequested.connect(self.on_context_menu)
        
        self.widgets = collections.OrderedDict()
        self.widgets['menu_button'] = self.menu_button
        self.widgets['tree'] = self.tree
        
        # @ToDo: Alter.invoke_all('add_widget', self.widgets)
        
        for name, widget in self.widgets.items():
            if name == 'menu_button':
                self.layout.addWidget(widget, 0, Qt.AlignLeft)
            else:
                self.layout.addWidget(widget)
        
        self.context_menu = QMenu(self)
        self.add_action('New file', QKeySequence.New, 
                        FileSystemHelper.new_file)
        self.add_action('New Directory', '', 
                        FileSystemHelper.new_directory)
        self.add_separator()
        self.add_action('Rename', '', FileSystemHelper.rename)
        self.add_action('Copy', QKeySequence.Copy, FileSystemHelper.copy)
        self.add_action('Cut', QKeySequence.Cut, FileSystemHelper.cut)
        self.add_action('Paste', QKeySequence.Paste, FileSystemHelper.paste)
        self.add_separator()
        self.add_action('Delete', QKeySequence.Delete, 
                        FileSystemHelper.delete)
        
        # @ToDo Alter.invoke_all('navigation_add_action', self)
        
        #restore previous session and data
        dirs = ModuleManager.core['settings'].Settings.value(
            self.SETTINGS_DIRECTORIES, None, True)
        for directory_path in dirs:
            name = os.path.basename(directory_path)
            self.menu_add_directory(name, directory_path)
        current_dir = ModuleManager.core['settings'].Settings.value(
            self.SETTINGS_CURRENT_DIR, '')
        if current_dir:
            for action in self.menu_directories.actions():
                if action.data() == current_dir:
                    action.trigger()
        
        self.menu_button.setFocusPolicy(Qt.NoFocus)
        self.menu_button.setFocusProxy(self.tree)
    
    def reset(self, file_info):
        self.model.beginResetModel()
        current_dir = ModuleManager.core['settings'].Settings.value(
            self.SETTINGS_CURRENT_DIR, '')
        if current_dir:
            for action in self.menu_directories.actions():
                if action.data() == current_dir:
                    action.trigger()
    
    def on_menu_button_clicked(self):
        pos = self.mapToGlobal(self.menu_button.pos())
        menu_width = self.menu.sizeHint().width()
        pos.setY(pos.y() + self.menu_button.height())
#        pos.setX(pos.x() + self.menu_button.width() - menu_width)
        if len(self.menu.actions()) > 0:
            self.menu.exec(pos)
    
    def menu_add_action(self, name, callback, data=None, shortcut=None, icon=None):
        action = QAction(name, self)
        if icon:
            action.setIcon(icon)
        if shortcut:
            action.setShortcut(shortcut)
            action.setShortcutContext(Qt.WidgetWithChildrenShortcut)
        if data:
            action.setData(data)
        action.triggered.connect(callback)
        self.addAction(action)
        self.menu.addAction(action)
    
    def menu_add_directory(self, name, data):
        action = QAction(name, self)
        action.setData(data)
        action.triggered.connect(self.on_menu_action_triggered)
        self.menu_directories.addAction(action)
        return action
    
    def menu_add_separator(self):
        self.menu.addSeparator()
    
    def add_action(self, name, shortcut, callback, icon = None):
        """
        Ajoute une action au context menu et au widget navigation lui même.
        Créer une fonction à la volé pour fournir des arguments aux fonctions
        associé aux actions.
        """
        action = QAction(name, self)
        if icon:
            action.setIcon(icon)
        action.setShortcut(shortcut)
        action.setShortcutContext(Qt.WidgetWithChildrenShortcut)
        action.triggered.connect(self.__wrapper(callback))
        self.addAction(action)
        self.context_menu.addAction(action)
    
    def add_separator(self):
        """Simple abstraction of self.context_menu.addSeparator()"""
        self.context_menu.addSeparator()
    
    def __wrapper(self, callback):
        def __new_function():
            """
            __new_function représente la forme de tous les callbacks connecté
            à une action pour pouvoir utiliser les raccourcis en même temps que
            le menu contextuel.
            """
            action = self.sender()
            file_info = action.data()
            if not file_info:
                indexes = self.tree.selectedIndexes()
                if indexes:
                    model_index = indexes[0]
                    file_info = self.model.fileInfo(model_index)
                    callback(file_info, self)
                elif action.shortcut() == QKeySequence.New:
                    file_info = self.model.fileInfo(self.tree.rootIndex())
                    callback(file_info, self)
            else:
                callback(file_info, self)
                action.setData(None)
        return __new_function
    
    def question(self, text, informative_text = None):
        message_box = QMessageBox(self)
        message_box.setText(text)
        if informative_text:
            message_box.setInformativeText(informative_text)
        message_box.setStandardButtons(
            QMessageBox.No | QMessageBox.Yes)
        message_box.setDefaultButton(QMessageBox.No)
        return message_box.exec()
    
    def on_context_menu(self, point):
        model_index = self.tree.indexAt(point)
        file_info = self.model.fileInfo(model_index)
        # pour chaque action on met a jour les data (file_info)
        # puis on altère les actions (ex enabled)
        for action in self.context_menu.actions():
            if not action.isSeparator():
                action.setData(file_info)
                action.setEnabled(model_index.isValid())
                if action.shortcut() == QKeySequence.New:
                    action.setEnabled(True)
                    if not model_index.isValid():
                        file_info = self.model.fileInfo(self.tree.rootIndex())
                        action.setData(file_info)
                if action.shortcut() == QKeySequence.Paste:
                    enable = FileSystemHelper.ready() and model_index.isValid()
                    action.setEnabled(enable)
                if action.shortcut() == QKeySequence.Delete:
                    # remove directory only if is an empty directory
                    if model_index.isValid() and file_info.isDir():
                        path = file_info.absoluteFilePath()
                        # QDir(path).count() always contains '.' and '..'
                        action.setEnabled(QDir(path).count() == 2)
                # @ToDo 
                #Alter.invoke_all(
                #    'navigation_on_menu_action', 
                #    model_index, file_info, action, self)
        if len(self.context_menu.actions()) > 0:
            self.context_menu.exec(self.tree.mapToGlobal(point))
        # reset action data, sinon y a des problèmes dans _new_function
        for action in self.context_menu.actions():
            action.setData(None)
    
    def on_item_activated(self, index):
        qFileInfo = self.model.fileInfo(index)
        if qFileInfo.isDir():
            self.onDirItemActivated.emit(qFileInfo)
        else:
            self.onFileItemActivated.emit(qFileInfo)
    
    def on_item_clicked(self, index):
        qFileInfo = self.model.fileInfo(index)
        if qFileInfo.isDir():
            self.onDirItemActivated.emit(qFileInfo)
            self.tree.setExpanded(index, not self.tree.isExpanded(index))
        else:
            self.onFileItemActivated.emit(qFileInfo)
    
    def open_directory(self):
        project = ModuleManager.core['settings'].Settings.value(
            self.SETTINGS_CURRENT_DIR, '')
        path = QFileDialog.getExistingDirectory(self, "Open Directory", project)
        if path:
            name = os.path.basename(path)
            action = self.menu_add_directory(name, path)
            self.save_directories_path()
            action.trigger()
    
    def on_menu_action_triggered(self):
        action = self.sender()
        path = action.data()
        if path:
            self.model.setRootPath(path)
            self.tree.setRootIndex(self.model.index(path))
            self.menu_button.setText(os.path.basename(path))
            self.save_current_dir(path)
    
    def save_directories_path(self):
        ModuleManager.core['settings'].Settings.set_value(
            self.SETTINGS_DIRECTORIES,
            [action.data() for action in self.menu_directories.actions()]    
        )
    
    def save_current_dir(self, path):
        ModuleManager.core['settings'].Settings.set_value(
            self.SETTINGS_CURRENT_DIR,
            path
        )
示例#39
0
class EditorWidget(QWidget):
    
    def __init__(self, file_info, parent=None):
        super(EditorWidget, self).__init__(parent)
        self.parent = parent
        
        self.file_info = file_info
        
        self.v_box = QVBoxLayout(self)
        self.v_box.setSpacing(0)
        self.v_box.setContentsMargins(0, 0, 0, 0)
        
        self.status_bar = StatusBar(self)
        
        self.editor = Editor(self.file_info, self)
        self.editor.modificationChanged[bool].connect(
            self.on_modification_changed)
        self.editor.cursorPositionChanged.connect(self.on_cursor_changed)
        
        self.v_box.addWidget(self.editor)
        self.v_box.addWidget(self.status_bar)
        
        self.setLayout(self.v_box)
        
        self.status_bar.menu_button.clicked.connect(
            self.on_menu_button_clicked)
        
        self.menu = QMenu(self)
        self.add_action(self.tr('Save'), 'ctrl+s', self.editor.save)
        self.add_separator()
        self.add_action(
            self.tr('Zoom in'), 
            QKeySequence.ZoomIn, 
            self.editor.zoomIn,
            wrapped=False
        )
        self.add_action(
            self.tr('Zoom out'), 
            QKeySequence.ZoomOut, 
            self.editor.zoomOut,
            wrapped=False
        )
        self.add_action(
            self.tr('Zoom reset'), 
            'ctrl+0',
            self.editor.zoom_reset
        )
        self.add_action(
            self.tr('Indent current line'), 
            'ctrl+i',
            self.editor.indent_current_line
        )
        self.add_action(
            self.tr('Unindent current line'),
            'ctrl+shift+i',
            self.editor.unindent_current_line
        )
        self.add_separator()
        self.add_action(
            self.tr('Auto close brackets and quotes'),
            'ctrl+alt+a',
            EditorHelper.auto_close_brackets_quotes,
            checkable=True,
            checked=ModuleManager.core['settings'].Settings.value(
                EditorHelper.SETTINGS_AUTO_CLOSE_BRACKETS,
                'true'
            )
        )
        self.add_action(
            self.tr('Use tabs to indent/unindent'),
            'ctrl+shift+alt+&',
            EditorHelper.use_tabs_to_indent,
            checkable=True,
            checked=ModuleManager.core['settings'].Settings.value(
                EditorHelper.SETTINGS_USE_TABS_TO_INDENT,
                'true'
            )
        )
        self.add_action(
            self.tr('Comment/Uncomment line(s)'),
            'ctrl+e',
            self.editor.comment_lines
        )
        
        self.setFocusPolicy(Qt.NoFocus)
        self.setFocusProxy(self.editor)
        
        Alter.invoke_all('editor_widget_init', self)
    
    def on_modification_changed(self, modified):
        if self.parent:
            self.parent.on_current_modified(modified)
    
    def on_cursor_changed(self, line, index):
        self.status_bar.showMessage(
            self.tr("Line {0}, column {1}".format(line + 1, index))
        )
    
    def on_menu_button_clicked(self):
        pos = self.status_bar.mapToGlobal(self.status_bar.menu_button.pos())
        menu_size = self.menu.sizeHint()
        menu_height = menu_size.height()
        menu_width = menu_size.width()
        pos.setY(pos.y() - menu_height)
        pos.setX(pos.x() - menu_width + self.status_bar.menu_button.width())
        if len(self.menu.actions()) > 0:
            self.menu.exec(pos)
    
    def add_action(self, name, shortcut, callback, **kwargs):
        """
        Ajoute une action au context menu et au widget navigation lui même.
        Créer une fonction à la volé pour fournir des arguments aux fonctions
        associé aux actions.
        """
        action = QAction(name, self)
        if 'icon' in kwargs:
            action.setIcon(kwargs['icon'])
        if 'checkable' in kwargs and kwargs['checkable']:
            action.setCheckable(True)
            if 'checked' in kwargs:
                checked = True if kwargs['checked'] == 'true' else False
                action.setChecked(
                    checked
                )
        
        action.setShortcut(shortcut)
        action.setShortcutContext(Qt.WidgetWithChildrenShortcut)
        
        if 'wrapped' in kwargs and kwargs['wrapped'] is False:
            action.triggered.connect(callback)
        else:
            action.triggered.connect(self.__wrapper(callback))
        
        self.addAction(action)
        self.menu.addAction(action)
        
    def add_separator(self):
        """Simple abstraction of self.context_menu.addSeparator()"""
        self.menu.addSeparator()

    def __wrapper(self, callback):
        def __new_function():
            """
            __new_function représente la forme de tous les callbacks connecté
            à une action pour pouvoir utiliser les raccourcis en même temps que
            le menu contextuel.
            """
            action = self.sender()
            callback(self, action)
        return __new_function
示例#40
0
class AbstractViewerContextMenu(QObject):
    """Base class for viewers' context menus.
    It provides the template method pattern to generate the menu.
    Subclasses can override individual parts of the menu this way."""

    def __init__(self, panel):
        self._panel = panel
        self._actionCollection = panel.actionCollection
        self._surface = None
        self._menu = QMenu(self._panel)

    def surface(self):
        """Return the (cached) surface"""
        result = self._surface or self._panel.widget().view.surface()
        return result

    def addSeparator(self):
        """Add a separator to the menu."""
        self._menu.addSeparator()

    def addCopyImageAction(self):
        """Add action to copy image if available"""
        if self.surface().hasSelection():
            self._menu.addAction(self._actionCollection.viewer_copy_image)

    def addEditInPlaceAction(self, cursor, position):
        """Add action to edit snippet if on a textedit link"""
        a = self._menu.addAction(icons.get("document-edit"), _("Edit in Place"))
        @a.triggered.connect
        def edit():
            import editinplace
            editinplace.edit(self._panel.widget(), cursor, position)

    def addLinkAction(self, link):
        """Add action if on an arbitrary link"""
        m = self._menu
        a = m.addAction(icons.get("window-new"), _("Open Link in &New Window"))
        @a.triggered.connect
        def open_in_browser():
            import helpers
            helpers.openUrl(QUrl(link.url()))

        a = m.addAction(icons.get("edit-copy"), _("Copy &Link"))
        @a.triggered.connect
        def copy_link():
            QApplication.clipboard().setText(link.url())

    def addCursorLinkActions(self):
        """Add actions if on a textedit or arbitrary link"""
        if self._cursor:
            self.addEditInPlaceAction(self._cursor, self._position)
        elif self._link:
            self.addLinkAction(self._link)

    def addShowActions(self):
        """Adds a submenu giving access to the (other)
        opened viewer documents"""
        mds = self._actionCollection.viewer_document_select
        docs = mds.viewdocs()
        document_actions = {}
        multi_docs = len(docs) > 1
        if self._panel.widget().currentViewdoc():
            current_doc_filename = self._panel.widget().currentViewdoc().filename()

        m = self._menu
        sm = QMenu(m)
        sm.setTitle(_("Show..."))
        sm.setEnabled(multi_docs)
        ag = QActionGroup(m)
        ag.triggered.connect(self._panel.slotShowViewdoc)

        for d in docs:
            action = QAction(sm)
            action.setText(d.name())
            action._document_filename = d.filename()
            # TODO: Tooltips aren't shown by Qt (it seems)
            action.setToolTip(d.filename())
            action.setCheckable(True)
            action.setChecked(d.filename() == current_doc_filename)

            ag.addAction(action)
            sm.addAction(action)

        m.addSeparator()
        m.addMenu(sm)

    def addOpenCloseActions(self):
        """Add actions to close documents.
        This is not implemented in the base class"""
        m = self._menu
        ac = self._actionCollection
        m.addAction(ac.viewer_open)
        docs = self._actionCollection.viewer_document_select.viewdocs()
        if docs:
            sm = QMenu(m)
            sm.setTitle(_("Close..."))
            m.addMenu(sm)
            sm.addAction(ac.viewer_close)
            multi_docs = len(docs) > 1
            ac.viewer_close_other.setEnabled(multi_docs)
            ac.viewer_close_all.setEnabled(multi_docs)
            sm.addAction(ac.viewer_close_other)
            sm.addAction(ac.viewer_close_all)

    def addReloadAction(self):
        """Add action to reload document."""
        current_document = self._panel.widget().currentViewdoc()
        if current_document:
            m = self._menu
            ac = self._actionCollection
            m.addAction(ac.viewer_reload)

    def addZoomActions(self):
        """Add actions to zoom the viewer"""
        m = self._menu
        m.addSeparator()
        sm = QMenu(m)
        sm.setTitle(_("Zoom"))
        m.addMenu(sm)
        ac = self._actionCollection
        sm.addAction(ac.viewer_fit_width)
        sm.addAction(ac.viewer_fit_height)
        sm.addAction(ac.viewer_fit_both)
        sm.addSeparator()
        sm.addAction(ac.viewer_zoom_in)
        sm.addAction(ac.viewer_zoom_out)
        sm.addAction(ac.viewer_zoom_original)

    def addSynchronizeAction(self):
        """Add an action telling the viewer to
        always try syncing with the input editor."""
        m = self._menu
        ac = self._actionCollection
        m.addAction(ac.viewer_sync_cursor)

    def addShowToolbarAction(self):
        """Add action to toggle the visibility of
        the viewer's toolbar"""
        m = self._menu
        ac = self._actionCollection
        m.addAction(ac.viewer_show_toolbar)

    def addHelpAction(self):
        """Add help menu item"""
        m = self._menu
        ac = self._actionCollection
        m.addSeparator()
        m.addAction(ac.viewer_help)

    def show(self, position, link, cursor, methods = None):
        """Build the panel's context menu dynamically.
        Implements the template method pattern to allow
        subclasses to override each step.
        If methods passes a list of methods these will be
        called instead to construct the menu, making it
        possible to change order or add methods not
        available in the base class."""

        self._position = position
        self._link = link
        self._cursor = cursor

        self._menu.clear()

        if not methods:
            # Actions affecting the current link(selection)
            self.addCopyImageAction()
            self.addCursorLinkActions()
            # Actions affecting the currently opened documents
            self.addShowActions()
            self.addOpenCloseActions()
            self.addReloadAction()
            # Actions affecting the viewer's state
            self.addZoomActions()
            self.addSynchronizeAction()
            self.addShowToolbarAction()
        else:
            for m in methods:
                m()
        # The help action is added always
        self.addHelpAction()

        # show it!
        if self._menu.actions():
            self._menu.exec_(position)
示例#41
0
class FontWindow(BaseMainWindow):

    def __init__(self, font, parent=None):
        super().__init__(parent)
        self._font = None

        self._settingsWindow = None
        self._infoWindow = None
        self._featuresWindow = None
        self._metricsWindow = None
        self._groupsWindow = None

        menuBar = self.menuBar()
        fileMenu = QMenu(self.tr("&File"), self)
        fileMenu.addAction(self.tr("&New…"), self.newFile, QKeySequence.New)
        fileMenu.addAction(
            self.tr("&Open…"), self.openFile, QKeySequence.Open)
        # recent files
        self.recentFilesMenu = QMenu(self.tr("Open &Recent"), self)
        for i in range(MAX_RECENT_FILES):
            action = QAction(self.recentFilesMenu)
            action.setVisible(False)
            action.triggered.connect(self.openRecentFile)
            self.recentFilesMenu.addAction(action)
        self.updateRecentFiles()
        fileMenu.addMenu(self.recentFilesMenu)
        fileMenu.addAction(self.tr("&Import…"), self.importFile)
        fileMenu.addSeparator()
        fileMenu.addAction(self.tr("&Save"), self.saveFile, QKeySequence.Save)
        fileMenu.addAction(
            self.tr("Save &As…"), self.saveFileAs, QKeySequence.SaveAs)
        fileMenu.addAction(self.tr("&Export…"), self.exportFile)
        fileMenu.addAction(self.tr("&Reload From Disk"), self.reloadFile)
        fileMenu.addAction(self.tr("E&xit"), self.close, QKeySequence.Quit)
        menuBar.addMenu(fileMenu)

        editMenu = QMenu(self.tr("&Edit"), self)
        self._undoAction = editMenu.addAction(
            self.tr("&Undo"), self.undo, QKeySequence.Undo)
        self._redoAction = editMenu.addAction(
            self.tr("&Redo"), self.redo, QKeySequence.Redo)
        editMenu.addSeparator()
        self.markColorMenu = QMenu(self.tr("&Flag Color"), self)
        self.updateMarkColors()
        editMenu.addMenu(self.markColorMenu)
        cut = editMenu.addAction(self.tr("C&ut"), self.cut, QKeySequence.Cut)
        copy = editMenu.addAction(
            self.tr("&Copy"), self.copy, QKeySequence.Copy)
        copyComponent = editMenu.addAction(
            self.tr("Copy &As Component"), self.copyAsComponent, "Ctrl+Alt+C")
        paste = editMenu.addAction(
            self.tr("&Paste"), self.paste, QKeySequence.Paste)
        self._clipboardActions = (cut, copy, copyComponent, paste)
        editMenu.addSeparator()
        editMenu.addAction(self.tr("&Settings…"), self.settings)
        menuBar.addMenu(editMenu)

        fontMenu = QMenu(self.tr("&Font"), self)
        fontMenu.addAction(
            self.tr("&Add Glyphs…"), self.addGlyphs, "Ctrl+G")
        fontMenu.addAction(
            self.tr("Font &Info"), self.fontInfo, "Ctrl+Alt+I")
        fontMenu.addAction(
            self.tr("Font &Features"), self.fontFeatures, "Ctrl+Alt+F")
        fontMenu.addSeparator()
        fontMenu.addAction(self.tr("&Sort…"), self.sortGlyphs)
        menuBar.addMenu(fontMenu)

        pythonMenu = QMenu(self.tr("&Python"), self)
        pythonMenu.addAction(
            self.tr("&Scripting Window"), self.scripting, "Ctrl+Alt+R")
        pythonMenu.addAction(
            self.tr("&Output Window"), self.outputWindow, "Ctrl+Alt+O")
        menuBar.addMenu(pythonMenu)

        windowMenu = QMenu(self.tr("&Windows"), self)
        action = windowMenu.addAction(
            self.tr("&Inspector"), self.inspector, "Ctrl+I")
        # XXX: we're getting duplicate shortcut when we spawn a new window...
        action.setShortcutContext(Qt.ApplicationShortcut)
        windowMenu.addAction(
            self.tr("&Metrics Window"), self.metrics, "Ctrl+Alt+S")
        windowMenu.addAction(
            self.tr("&Groups Window"), self.groups, "Ctrl+Alt+G")
        menuBar.addMenu(windowMenu)

        helpMenu = QMenu(self.tr("&Help"), self)
        helpMenu.addAction(self.tr("&About"), self.about)
        helpMenu.addAction(
            self.tr("About &Qt"), QApplication.instance().aboutQt)
        menuBar.addMenu(helpMenu)

        cellSize = 56
        self.glyphCellView = GlyphCellView(self)
        self.glyphCellView.glyphActivated.connect(self._glyphActivated)
        self.glyphCellView.glyphsDropped.connect(self._orderChanged)
        self.glyphCellView.selectionChanged.connect(self._selectionChanged)
        self.glyphCellView.setAcceptDrops(True)
        self.glyphCellView.setCellRepresentationName("TruFont.GlyphCell")
        self.glyphCellView.setCellSize(cellSize)
        self.glyphCellView.setFocus()

        self.cellSizeSlider = QSlider(Qt.Horizontal, self)
        self.cellSizeSlider.setMinimum(32)
        self.cellSizeSlider.setMaximum(116)
        self.cellSizeSlider.setFixedWidth(.9 * self.cellSizeSlider.width())
        self.cellSizeSlider.setValue(cellSize)
        self.cellSizeSlider.valueChanged.connect(self._sliderCellSizeChanged)
        self.selectionLabel = QLabel(self)
        statusBar = self.statusBar()
        statusBar.addPermanentWidget(self.cellSizeSlider)
        statusBar.addWidget(self.selectionLabel)

        self.setFont_(font)
        if font is not None:
            self.setCurrentFile(font.path)

        app = QApplication.instance()
        app.dispatcher.addObserver(
            self, "_preferencesChanged", "preferencesChanged")
        app.dispatcher.addObserver(self, "_fontSaved", "fontSaved")
        self._updateGlyphActions()

        self.setCentralWidget(self.glyphCellView)
        self.setWindowTitle()
        self.resize(605, 430)

    # --------------
    # Custom methods
    # --------------

    def font_(self):
        return self._font

    def setFont_(self, font):
        if self._font is not None:
            self._font.removeObserver(self, "Font.Changed")
            self._font.removeObserver(self, "Font.GlyphOrderChanged")
            self._font.removeObserver(self, "Font.SortDescriptorChanged")
        self._font = font
        if font is None:
            return
        self._updateGlyphsFromGlyphOrder()
        font.addObserver(self, "_fontChanged", "Font.Changed")
        font.addObserver(
            self, "_glyphOrderChanged", "Font.GlyphOrderChanged")
        font.addObserver(
            self, "_sortDescriptorChanged", "Font.SortDescriptorChanged")

    def maybeSaveBeforeExit(self):
        if self._font.dirty:
            currentFont = self.windowTitle()[3:]
            body = self.tr("Do you want to save the changes you made "
                           "to “{}”?").format(currentFont)
            closeDialog = QMessageBox(
                QMessageBox.Question, None, body,
                QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel,
                self)
            closeDialog.setInformativeText(
                self.tr("Your changes will be lost if you don’t save them."))
            closeDialog.setModal(True)
            ret = closeDialog.exec_()
            if ret == QMessageBox.Save:
                self.saveFile()
                return True
            elif ret == QMessageBox.Discard:
                return True
            return False
        return True

    # -------------
    # Notifications
    # -------------

    # app

    def _fontSaved(self, notification):
        if notification.data["font"] != self._font:
            return
        path = notification.data["path"]
        self.setCurrentFile(path)
        self.setWindowModified(False)

    def _preferencesChanged(self, notification):
        self.updateMarkColors()

    # widgets

    def _sliderCellSizeChanged(self):
        cellSize = self.cellSizeSlider.value()
        self.glyphCellView.setCellSize(cellSize)
        QToolTip.showText(QCursor.pos(), str(cellSize), self)

    def _glyphActivated(self, glyph):
        glyphWindow = GlyphWindow(glyph, self)
        glyphWindow.show()

    def _orderChanged(self):
        # TODO: reimplement when we start showing glyph subsets
        glyphs = self.glyphCellView.glyphs()
        self._font.glyphOrder = [glyph.name for glyph in glyphs]

    def _selectionChanged(self):
        # currentGlyph
        lastSelectedGlyph = self.glyphCellView.lastSelectedGlyph()
        app = QApplication.instance()
        app.setCurrentGlyph(lastSelectedGlyph)
        # selection text
        # TODO: this should probably be internal to the label
        selection = self.glyphCellView.selection()
        if selection is not None:
            count = len(selection)
            if count == 1:
                glyph = self.glyphCellView.glyphsForIndexes(selection)[0]
                text = "%s " % glyph.name
            else:
                text = ""
            if count:
                text = self.tr("{0}(%n selected)".format(text), n=count)
        else:
            text = ""
        self.selectionLabel.setText(text)
        # actions
        self._updateGlyphActions()

    # defcon

    def _fontChanged(self, notification):
        font = notification.object
        self.setWindowModified(font.dirty)

    def _glyphOrderChanged(self, notification):
        self._updateGlyphsFromGlyphOrder()

    def _updateGlyphsFromGlyphOrder(self):
        font = self._font
        glyphOrder = font.glyphOrder
        if glyphOrder:
            glyphs = []
            for glyphName in glyphOrder:
                if glyphName in font:
                    glyphs.append(font[glyphName])
            if len(glyphs) < len(font):
                # if some glyphs in the font are not present in the glyph
                # order, loop again to add them at the end
                for glyph in font:
                    if glyph not in glyphs:
                        glyphs.append(glyph)
                font.disableNotifications(observer=self)
                font.glyphOrder = [glyph.name for glyph in glyphs]
                font.enableNotifications(observer=self)
        else:
            glyphs = list(font)
            font.disableNotifications(observer=self)
            font.glyphOrder = [glyph.name for glyph in glyphs]
            font.enableNotifications(observer=self)
        self.glyphCellView.setGlyphs(glyphs)

    def _sortDescriptorChanged(self, notification):
        font = notification.object
        descriptors = notification.data["newValue"]
        if descriptors[0]["type"] == "glyphSet":
            glyphNames = descriptors[0]["glyphs"]
        else:
            glyphNames = font.unicodeData.sortGlyphNames(
                font.keys(), descriptors)
        font.glyphOrder = glyphNames

    # ------------
    # Menu methods
    # ------------

    # File

    def newFile(self):
        QApplication.instance().newFile()

    def openFile(self):
        path, _ = QFileDialog.getOpenFileName(
            self, self.tr("Open File"), '',
            platformSpecific.fileFormat
        )
        if path:
            QApplication.instance().openFile(path)

    def openRecentFile(self):
        fontPath = self.sender().toolTip()
        QApplication.instance().openFile(fontPath)

    def saveFile(self, path=None, ufoFormatVersion=3):
        if path is None and self._font.path is None:
            self.saveFileAs()
        else:
            if path is None:
                path = self._font.path
            self._font.save(path, ufoFormatVersion)

    def saveFileAs(self):
        fileFormats = OrderedDict([
            (self.tr("UFO Font version 3 {}").format("(*.ufo)"), 3),
            (self.tr("UFO Font version 2 {}").format("(*.ufo)"), 2),
        ])
        # TODO: switch to directory on platforms that need it
        dialog = QFileDialog(
            self, self.tr("Save File"), None, ";;".join(fileFormats.keys()))
        dialog.setAcceptMode(QFileDialog.AcceptSave)
        ok = dialog.exec_()
        if ok:
            nameFilter = dialog.selectedNameFilter()
            path = dialog.selectedFiles()[0]
            self.saveFile(path, fileFormats[nameFilter])
            self.setWindowTitle()
        # return ok

    def importFile(self):
        # TODO: systematize this
        fileFormats = (
            self.tr("OpenType Font file {}").format("(*.otf *.ttf)"),
            self.tr("Type1 Font file {}").format("(*.pfa *.pfb)"),
            self.tr("ttx Font file {}").format("(*.ttx)"),
            self.tr("WOFF Font file {}").format("(*.woff)"),
            self.tr("All supported files {}").format(
                "(*.otf *.pfa *.pfb *.ttf *.ttx *.woff)"),
            self.tr("All files {}").format("(*.*)"),
        )

        path, _ = QFileDialog.getOpenFileName(
            self, self.tr("Import File"), None,
            ";;".join(fileFormats), fileFormats[-2])

        if path:
            font = TFont()
            try:
                font.extract(path)
            except Exception as e:
                errorReports.showCriticalException(e)
                return
            window = FontWindow(font)
            window.show()

    def exportFile(self):
        path, _ = QFileDialog.getSaveFileName(
            self, self.tr("Export File"), None,
            self.tr("OpenType PS font {}").format("(*.otf)"))
        if path:
            try:
                self._font.export(path)
            except Exception as e:
                errorReports.showCriticalException(e)

    def reloadFile(self):
        font = self._font
        if font.path is None:
            return
        font.reloadInfo()
        font.reloadKerning()
        font.reloadGroups()
        font.reloadFeatures()
        font.reloadLib()
        font.reloadGlyphs(font.keys())
        self.setWindowModified(False)

    # Edit

    def undo(self):
        glyph = self.glyphCellView.lastSelectedGlyph()
        glyph.undo()

    def redo(self):
        glyph = self.glyphCellView.lastSelectedGlyph()
        glyph.redo()

    def markColor(self):
        color = self.sender().data()
        if color is not None:
            color = color.getRgbF()
        glyphs = self.glyphCellView.glyphs()
        for index in self.glyphCellView.selection():
            glyph = glyphs[index]
            glyph.markColor = color

    def cut(self):
        self.copy()
        glyphs = self.glyphCellView.glyphs()
        for index in self.glyphCellView.selection():
            glyph = glyphs[index]
            glyph.clear()

    def copy(self):
        glyphs = self.glyphCellView.glyphs()
        pickled = []
        for index in sorted(self.glyphCellView.selection()):
            pickled.append(glyphs[index].serialize(
                blacklist=("name", "unicode")
            ))
        clipboard = QApplication.clipboard()
        mimeData = QMimeData()
        mimeData.setData("application/x-trufont-glyph-data",
                         pickle.dumps(pickled))
        clipboard.setMimeData(mimeData)

    def copyAsComponent(self):
        glyphs = self.glyphCellView.glyphs()
        pickled = []
        for index in self.glyphCellView.selection():
            glyph = glyphs[index]
            componentGlyph = glyph.__class__()
            componentGlyph.width = glyph.width
            component = componentGlyph.instantiateComponent()
            component.baseGlyph = glyph.name
            pickled.append(componentGlyph.serialize())
        clipboard = QApplication.clipboard()
        mimeData = QMimeData()
        mimeData.setData("application/x-trufont-glyph-data",
                         pickle.dumps(pickled))
        clipboard.setMimeData(mimeData)

    def paste(self):
        clipboard = QApplication.clipboard()
        mimeData = clipboard.mimeData()
        if mimeData.hasFormat("application/x-trufont-glyph-data"):
            data = pickle.loads(mimeData.data(
                "application/x-trufont-glyph-data"))
            selection = self.glyphCellView.selection()
            glyphs = self.glyphCellView.glyphsForIndexes(selection)
            if len(data) == len(glyphs):
                for pickled, glyph in zip(data, glyphs):
                    # XXX: prune
                    glyph.prepareUndo()
                    glyph.deserialize(pickled)

    def settings(self):
        if self._settingsWindow is not None and \
                self._settingsWindow.isVisible():
            self._settingsWindow.raise_()
        else:
            self._settingsWindow = SettingsWindow(self)
            self._settingsWindow.show()

    # Font

    def fontInfo(self):
        # If a window is already opened, bring it to the front, else spawn one.
        # TODO: see about using widget.setAttribute(Qt.WA_DeleteOnClose)
        # otherwise it seems we're just leaking memory after each close...
        # (both raise_ and show allocate memory instead of using the hidden
        # widget it seems)
        if self._infoWindow is not None and self._infoWindow.isVisible():
            self._infoWindow.raise_()
        else:
            self._infoWindow = FontInfoWindow(self._font, self)
            self._infoWindow.show()

    def fontFeatures(self):
        # TODO: see up here
        if self._featuresWindow is not None and self._featuresWindow.isVisible(
                ):
            self._featuresWindow.raise_()
        else:
            self._featuresWindow = FontFeaturesWindow(self._font, self)
            self._featuresWindow.show()

    def addGlyphs(self):
        glyphs = self.glyphCellView.glyphs()
        newGlyphNames, params, ok = AddGlyphsDialog.getNewGlyphNames(
            self, glyphs)
        if ok:
            sortFont = params.pop("sortFont")
            for name in newGlyphNames:
                glyph = self._font.newStandardGlyph(name, **params)
                if glyph is not None:
                    glyphs.append(glyph)
            self.glyphCellView.setGlyphs(glyphs)
            if sortFont:
                # TODO: when the user add chars from a glyphSet and no others,
                # should we try to sort according to that glyphSet?
                # The above would probably warrant some rearchitecturing.
                # kick-in the sort mechanism
                self._font.sortDescriptor = self._font.sortDescriptor

    def sortGlyphs(self):
        sortDescriptor, ok = SortDialog.getDescriptor(
            self, self._font.sortDescriptor)
        if ok:
            self._font.sortDescriptor = sortDescriptor

    # Python

    def scripting(self):
        app = QApplication.instance()
        if not hasattr(app, 'scriptingWindow'):
            app.scriptingWindow = ScriptingWindow()
            app.scriptingWindow.show()
        elif app.scriptingWindow.isVisible():
            app.scriptingWindow.raise_()
        else:
            app.scriptingWindow.show()

    def outputWindow(self):
        app = QApplication.instance()
        if app.outputWindow.isVisible():
            app.outputWindow.raise_()
        else:
            app.outputWindow.show()

    # Windows

    def inspector(self):
        app = QApplication.instance()
        if not hasattr(app, 'inspectorWindow'):
            app.inspectorWindow = InspectorWindow()
            app.inspectorWindow.show()
        elif app.inspectorWindow.isVisible():
            # TODO: do this only if the widget is user-visible, otherwise the
            # key press feels as if it did nothing
            # toggle
            app.inspectorWindow.close()
        else:
            app.inspectorWindow.show()

    def metrics(self):
        # TODO: see up here
        if self._metricsWindow is not None and self._metricsWindow.isVisible():
            self._metricsWindow.raise_()
        else:
            self._metricsWindow = MetricsWindow(self._font, parent=self)
            self._metricsWindow.show()
        # TODO: default string kicks-in on the window before this. Figure out
        # how to make a clean interface
        selection = self.glyphCellView.selection()
        if selection:
            glyphs = self.glyphCellView.glyphsForIndexes(selection)
            self._metricsWindow.setGlyphs(glyphs)

    def groups(self):
        # TODO: see up here
        if self._groupsWindow is not None and self._groupsWindow.isVisible():
            self._groupsWindow.raise_()
        else:
            self._groupsWindow = GroupsWindow(self._font, self)
            self._groupsWindow.show()

    # About

    def about(self):
        name = QApplication.applicationName()
        domain = QApplication.organizationDomain()
        text = self.tr(
            "<h3>About {n}</h3>"
            "<p>{n} is a cross-platform, modular typeface design "
            "application.</p><p>{n} is built on top of "
            "<a href='http://ts-defcon.readthedocs.org/en/ufo3/'>defcon</a> "
            "and includes scripting support "
            "with a <a href='http://robofab.com/'>robofab</a>-like API.</p>"
            "<p>Version {} {} – Python {}.").format(
            __version__, gitShortHash, platform.python_version(), n=name)
        if domain:
            text += self.tr("<br>See <a href='http://{d}'>{d}</a> for more "
                            "information.</p>").format(d=domain)
        else:
            text += "</p>"
        QMessageBox.about(self, self.tr("About {}").format(name), text)

    # update methods

    def setCurrentFile(self, path):
        if path is None:
            return
        recentFiles = settings.recentFiles()
        if path in recentFiles:
            recentFiles.remove(path)
        recentFiles.insert(0, path)
        while len(recentFiles) > MAX_RECENT_FILES:
            del recentFiles[-1]
        settings.setRecentFiles(recentFiles)
        for window in QApplication.topLevelWidgets():
            if isinstance(window, FontWindow):
                window.updateRecentFiles()

    def updateRecentFiles(self):
        recentFiles = settings.recentFiles()
        count = min(len(recentFiles), MAX_RECENT_FILES)
        actions = self.recentFilesMenu.actions()
        for index, recentFile in enumerate(recentFiles[:count]):
            action = actions[index]
            shortName = os.path.basename(recentFile.rstrip(os.sep))

            action.setText(shortName)
            action.setToolTip(recentFile)
            action.setVisible(True)
        for index in range(count, MAX_RECENT_FILES):
            actions[index].setVisible(False)

        self.recentFilesMenu.setEnabled(len(recentFiles))

    def updateMarkColors(self):
        entries = settings.readMarkColors()
        self.markColorMenu.clear()
        pixmap = QPixmap(24, 24)
        none = self.markColorMenu.addAction("None", self.markColor)
        none.setData(None)
        for name, color in entries.items():
            action = self.markColorMenu.addAction(name, self.markColor)
            pixmap.fill(color)
            action.setIcon(QIcon(pixmap))
            action.setData(color)

    def _updateGlyphActions(self):
        currentGlyph = self.glyphCellView.lastSelectedGlyph()
        # disconnect eventual signal of previous glyph
        self._undoAction.disconnect()
        self._undoAction.triggered.connect(self.undo)
        self._redoAction.disconnect()
        self._redoAction.triggered.connect(self.redo)
        # now update status
        if currentGlyph is None:
            self._undoAction.setEnabled(False)
            self._redoAction.setEnabled(False)
        else:
            undoManager = currentGlyph.undoManager
            self._undoAction.setEnabled(currentGlyph.canUndo())
            undoManager.canUndoChanged.connect(self._undoAction.setEnabled)
            self._redoAction.setEnabled(currentGlyph.canRedo())
            undoManager.canRedoChanged.connect(self._redoAction.setEnabled)
        # and other actions
        for action in self._clipboardActions:
            action.setEnabled(currentGlyph is not None)
        self.markColorMenu.setEnabled(currentGlyph is not None)

    # ----------
    # Qt methods
    # ----------

    def showEvent(self, event):
        app = QApplication.instance()
        data = dict(
            font=self._font,
            window=self,
        )
        app.postNotification("fontWindowWillOpen", data)
        super().showEvent(event)
        app.postNotification("fontWindowOpened", data)

    def closeEvent(self, event):
        ok = self.maybeSaveBeforeExit()
        if ok:
            app = QApplication.instance()
            data = dict(
                font=self._font,
                window=self,
            )
            app.postNotification("fontWindowWillClose", data)
            self._font.removeObserver(self, "Font.Changed")
            app = QApplication.instance()
            app.dispatcher.removeObserver(self, "preferencesChanged")
            app.dispatcher.removeObserver(self, "fontSaved")
            event.accept()
        else:
            event.ignore()

    def event(self, event):
        if event.type() == QEvent.WindowActivate:
            app = QApplication.instance()
            app.setCurrentMainWindow(self)
            lastSelectedGlyph = self.glyphCellView.lastSelectedGlyph()
            if lastSelectedGlyph is not None:
                app.setCurrentGlyph(lastSelectedGlyph)
        return super().event(event)

    def setWindowTitle(self, title=None):
        if title is None:
            if self._font.path is not None:
                title = os.path.basename(self._font.path.rstrip(os.sep))
            else:
                title = self.tr("Untitled.ufo")
        super().setWindowTitle("[*]{}".format(title))
示例#42
0
class AceEditor(QWidget):
    """ Embbeded Ace javascript web editor """
    
    
    def __init__(self, file_info, parent=None):
        super(AceEditor, self).__init__(parent)
        self.parent = parent
        self.file_info = file_info
        self.editor_actions = {}
        self.language = EditorHelper.lang_from_file_info(file_info)
        
        self.editor = Ace(self.file_info, self)
        
        self.status_bar = StatusBar(self)
        
        self.editor.modificationChanged.connect(
            self.modification_changed)
        self.editor.cursorPositionChanged.connect(self.on_cursor_changed)
        
        self.v_box = QVBoxLayout(self)
        self.v_box.setSpacing(0)
        self.v_box.setContentsMargins(0, 0, 0, 0)
        
        self.v_box.addWidget(self.editor, 1)
        self.v_box.addWidget(self.status_bar, 0)
        
        self.setLayout(self.v_box)
        
        self.status_bar.menu_button.clicked.connect(
            self.on_menu_button_clicked)
        
        self.menu = QMenu(self)
        self.add_action('Save', 'ctrl+s', self.editor.save)
        self.add_separator()
        self.add_action(
            'Show hidden', 'ctrl+i', self.editor.toggle_hidden,checkable=True
        )
        self.add_action(
            'Use soft tabs', 'ctrl+shift+alt+s', self.editor.toggle_soft_tabs,
            checkable=True
        )
        self.setFocusPolicy(Qt.NoFocus)
        self.setFocusProxy(self.editor)
        
        Alter.invoke_all('editor_widget_init', self)
    
    @pyqtSlot(bool, name='modificationChanged')
    def modification_changed(self, b):
        if self.parent:
            self.parent.on_current_modified(b)
    
    @pyqtSlot(int, int, name='cursorPositionChanged')
    def on_cursor_changed(self, line, index):
        self.status_bar.showMessage(
            self.tr("Line {0}, column {1}".format(line + 1, index))
        )
    
    def on_menu_button_clicked(self):
        pos = self.status_bar.mapToGlobal(self.status_bar.menu_button.pos())
        menu_size = self.menu.sizeHint()
        menu_height = menu_size.height()
        menu_width = menu_size.width()
        pos.setY(pos.y() - menu_height)
        pos.setX(pos.x() - menu_width + self.status_bar.menu_button.width())
        if len(self.menu.actions()) > 0:
            self.menu.exec(pos)
    
    def add_action(self, name, shortcut, callback, **kwargs):
        """
        Ajoute une action au context menu et au widget navigation lui même.
        Créer une fonction à la volé pour fournir des arguments aux fonctions
        associé aux actions.
        """
        action = QAction(self.tr(name), self)
        if 'icon' in kwargs:
            action.setIcon(kwargs['icon'])
        if 'checkable' in kwargs and kwargs['checkable']:
            action.setCheckable(True)
            if 'checked' in kwargs:
                checked = True if kwargs['checked'] == 'true' else False
                action.setChecked(
                    checked
                )
        
        action.setShortcut(shortcut)
        action.setShortcutContext(Qt.WidgetWithChildrenShortcut)
        
        if 'wrapped' in kwargs and kwargs['wrapped'] is False:
            action.triggered.connect(callback)
        else:
            action.triggered.connect(self.__wrapper(callback))
        
        self.addAction(action)
        self.menu.addAction(action)
        self.editor_actions[name] = action
        
    def add_separator(self):
        """Simple abstraction of self.context_menu.addSeparator()"""
        self.menu.addSeparator()

    def __wrapper(self, callback):
        def __new_function():
            """
            __new_function représente la forme de tous les callbacks connecté
            à une action pour pouvoir utiliser les raccourcis en même temps que
            le menu contextuel.
            """
            action = self.sender()
            callback(self, action)
        return __new_function
示例#43
0
class MainWindow(QMainWindow, Ui_MainWindow, WindowState):

    ROLE = 'main'

    def __init__(self, engine, use_qt_notifications):
        super(MainWindow, self).__init__()
        self.setupUi(self)
        if hasattr(self, 'setUnifiedTitleAndToolBarOnMac'):
            self.setUnifiedTitleAndToolBarOnMac(True)
        self._engine = engine
        self._active_dialogs = {}
        self._dialog_class = {
            'about'             : AboutDialog,
            'configuration'     : ConfigWindow,
        }
        all_actions = find_menu_actions(self.menubar)
        # Dictionaries.
        self.dictionaries = self.scroll_area.widget()
        self.dictionaries.add_translation.connect(self._add_translation)
        self.dictionaries.setFocus()
        edit_menu = all_actions['menu_Edit'].menu()
        edit_menu.addAction(self.dictionaries.action_Undo)
        edit_menu.addSeparator()
        edit_menu.addMenu(self.dictionaries.menu_AddDictionaries)
        edit_menu.addAction(self.dictionaries.action_EditDictionaries)
        edit_menu.addAction(self.dictionaries.action_RemoveDictionaries)
        edit_menu.addSeparator()
        edit_menu.addAction(self.dictionaries.action_MoveDictionariesUp)
        edit_menu.addAction(self.dictionaries.action_MoveDictionariesDown)
        # Tray icon.
        self._trayicon = TrayIcon()
        self._trayicon.enable()
        self._trayicon.clicked.connect(self._engine.toggle_output)
        if use_qt_notifications:
            handler = NotificationHandler()
            handler.emitSignal.connect(self._trayicon.log)
            log.add_handler(handler)
        popup_menu = QMenu()
        for action_name in (
            'action_ToggleOutput',
            'action_Reconnect',
            '',
            'menu_Tools',
            '',
            'action_Configure',
            '',
            'menu_Help',
            '',
            'action_Show',
            'action_Quit',
        ):
            if action_name:
                popup_menu.addAction(all_actions[action_name])
            else:
                popup_menu.addSeparator()
        self._trayicon.set_menu(popup_menu)
        engine.signal_connect('machine_state_changed', self._trayicon.update_machine_state)
        engine.signal_connect('quit', self.on_quit)
        self.action_Quit.triggered.connect(engine.quit)
        # Populate tools bar/menu.
        tools_menu = all_actions['menu_Tools'].menu()
        # Toolbar popup menu for selecting which tools are shown.
        self.toolbar_menu = QMenu()
        self.toolbar.setContextMenuPolicy(Qt.CustomContextMenu)
        self.toolbar.customContextMenuRequested.connect(
            lambda: self.toolbar_menu.popup(QCursor.pos())
        )
        for tool_plugin in registry.list_plugins('gui.qt.tool'):
            tool = tool_plugin.obj
            action_parameters = []
            if tool.ICON is not None:
                icon = tool.ICON
                # Internal QT resources start with a `:`.
                if not icon.startswith(':'):
                    icon = resource_filename(icon)
                action_parameters.append(QIcon(icon))
            action_parameters.append(tool.TITLE)
            toolbar_action = None
            for parent in (tools_menu, self.toolbar, self.toolbar_menu):
                action = parent.addAction(*action_parameters)
                action.setObjectName(tool_plugin.name)
                if tool.__doc__ is not None:
                    action.setToolTip(tool.__doc__)
                if tool.SHORTCUT is not None:
                    action.setShortcut(QKeySequence.fromString(tool.SHORTCUT))
                if parent == self.toolbar_menu:
                    action.setCheckable(True)
                    action.setChecked(True)
                    assert toolbar_action is not None
                    action.toggled.connect(toolbar_action.setVisible)
                else:
                    if parent == self.toolbar:
                        toolbar_action = action
                    action.triggered.connect(partial(self._activate_dialog,
                                                     tool_plugin.name,
                                                     args=()))
            self._dialog_class[tool_plugin.name] = tool
        engine.signal_connect('output_changed', self.on_output_changed)
        # Machine.
        self.machine_type.addItems(
            _(plugin.name)
            for plugin in registry.list_plugins('machine')
        )
        engine.signal_connect('config_changed', self.on_config_changed)
        engine.signal_connect('machine_state_changed',
            lambda machine, state:
            self.machine_state.setText(_(state.capitalize()))
        )
        self.restore_state()
        # Commands.
        engine.signal_connect('add_translation', partial(self._add_translation, manage_windows=True))
        engine.signal_connect('focus', self._focus)
        engine.signal_connect('configure', partial(self._configure, manage_windows=True))
        engine.signal_connect('lookup', partial(self._activate_dialog, 'lookup',
                                                manage_windows=True))
        # Load the configuration (but do not start the engine yet).
        if not engine.load_config():
            self.on_configure()
        # Apply configuration settings.
        config = self._engine.config
        self.machine_type.setCurrentText(config['machine_type'])
        self._configured = False
        self.dictionaries.on_config_changed(config)
        self.set_visible(not config['start_minimized'])
        # Start the engine.
        engine.start()

    def set_visible(self, visible):
        if visible:
            self.show()
        else:
            if self._trayicon.is_enabled():
                self.hide()
            else:
                self.showMinimized()

    def _activate_dialog(self, name, args=(), manage_windows=False):
        if manage_windows:
            previous_window = wmctrl.GetForegroundWindow()
        dialog = self._active_dialogs.get(name)
        if dialog is None:
            dialog_class = self._dialog_class[name]
            dialog = self._active_dialogs[name] = dialog_class(self._engine, *args)
            dialog.setWindowIcon(self.windowIcon())
            def on_finished():
                del self._active_dialogs[name]
                dialog.deleteLater()
                if manage_windows:
                    wmctrl.SetForegroundWindow(previous_window)
            dialog.finished.connect(on_finished)
        dialog.show()
        dialog.activateWindow()
        dialog.raise_()

    def _add_translation(self, dictionary=None, manage_windows=False):
        if not dictionary:
            dictionary = None
        self._activate_dialog('add_translation', args=(dictionary,),
                              manage_windows=manage_windows)

    def _focus(self):
        self.set_visible(True)
        self.activateWindow()
        self.raise_()

    def _configure(self, manage_windows=False):
        self._activate_dialog('configuration', manage_windows=manage_windows)

    def _lookup(self, manage_windows=False):
        self._activate_dialog('lookup', manage_windows=manage_windows)

    def _restore_state(self, settings):
        if settings.contains('hidden_toolbar_tools'):
            hidden_toolbar_tools = json.loads(settings.value('hidden_toolbar_tools'))
            for action in self.toolbar_menu.actions():
                if action.objectName() in hidden_toolbar_tools:
                    action.setChecked(False)

    def _save_state(self, settings):
        hidden_toolbar_tools = set()
        for action in self.toolbar_menu.actions():
            if not action.isChecked():
                hidden_toolbar_tools.add(action.objectName())
        settings.setValue('hidden_toolbar_tools', json.dumps(list(sorted(hidden_toolbar_tools))))

    def on_config_changed(self, config_update):
        if 'machine_type' in config_update:
            self.machine_type.setCurrentText(config_update['machine_type'])
        if not self._configured:
            self._configured = True
            if config_update.get('show_suggestions_display', False):
                self._activate_dialog('suggestions')
            if config_update.get('show_stroke_display', False):
                self._activate_dialog('paper_tape')

    def on_machine_changed(self, machine_type):
        self._engine.config = { 'machine_type': machine_type }

    def on_output_changed(self, enabled):
        self._trayicon.update_output(enabled)
        self.output_enable.setChecked(enabled)
        self.output_disable.setChecked(not enabled)
        self.action_ToggleOutput.setChecked(enabled)

    def on_toggle_output(self, enabled):
        self._engine.output = enabled

    def on_enable_output(self):
        self.on_toggle_output(True)

    def on_disable_output(self):
        self.on_toggle_output(False)

    def on_configure(self):
        self._configure()

    def on_reconnect(self):
        self._engine.reset_machine()

    def on_manage_dictionaries(self):
        self._activate_dialog('dictionary_manager')

    def on_about(self):
        self._activate_dialog('about')

    def on_quit(self):
        for dialog in list(self._active_dialogs.values()):
            dialog.close()
        self.save_state()
        self._trayicon.disable()
        self.hide()
        QCoreApplication.quit()

    def on_show(self):
        self._focus()

    def closeEvent(self, event):
        self.hide()
        if not self._trayicon.is_enabled():
            self._engine.quit()
        event.ignore()
示例#44
0
    def __init__(self, activateCallback, parent=None):
        if app.devicePixelRatio() == 2:
            icon = QtGui.QIcon(basedir+'Assets/aether-black-tray.svg')
            iconActive = QtGui.QIcon(basedir+'Assets/aether-white-tray.svg')
        else:
            icon = QtGui.QIcon(basedir+'Assets/aether-black-tray.png')
            iconActive = QtGui.QIcon(basedir+'Assets/aether-white-tray.png')
        QSystemTrayIcon.__init__(self, icon, parent)
        menu = QMenu(parent)
        if globals.appIsPaused:
            menu.addAction('Aether is paused.').setDisabled(True)
        else:
            menu.addAction('Aether is connected.').setDisabled(True)
        globalStatusMenuItem = menu.actions()[0]

        menu.addSeparator() # 1
        if globals.appIsPaused:
            menu.addAction('Resume')
        else:
            menu.addAction('Pause')
        togglePauseMenuItem = menu.actions()[2]
        def togglePause():
            if globals.appIsPaused:
                globals.appIsPaused = False
                togglePauseMenuItem.setText('Pause')
                globalStatusMenuItem.setText('Aether is connected.')
            else:
                globals.appIsPaused = True
                togglePauseMenuItem.setText('Resume')
                globalStatusMenuItem.setText('Aether is paused.')
        togglePauseMenuItem.triggered.connect(togglePause)

        if not globals.appStartedAtBoot:
            menu.addAction('Show Aether')
        else:
            menu.addAction('Hide Aether')
        global toggleVisibilityMenuItem
        toggleVisibilityMenuItem = menu.actions()[3]
        def toggleVisibility():
            if parent.isHidden():
                parent.show()
                toggleVisibilityMenuItem.setText('Hide Aether')

            else:
                parent.close()
                toggleVisibilityMenuItem.setText('Show Aether')
        toggleVisibilityMenuItem.triggered.connect(toggleVisibility)

        menu.addAction('Email the developer')
        emailDevMenuItem = menu.actions()[4]
        def emailDev():
            mailInitialiser = \
                QUrl('mailto:[email protected]'
                     '?subject=Feedback for Aether'
                     '&body=<i><br><br>Hello there! Thanks for taking time to give feedback, I really appreciate it. '
                     'If you are having problems, please right click on Aether.app on your Applications folder, '
                     'click Show Package Contents, go to Contents/MacOS/Logs and attach the network.log file there to '
                     'this email. <br><br>'
                     'You can delete this text before sending.'
                     '<br><br>You can find my PGP key here:</i> '
                     'http://pgp.mit.edu:11371/pks/lookup?search=Burak+Nehbit')
            QtGui.QDesktopServices.openUrl(mailInitialiser)
        emailDevMenuItem.triggered.connect(emailDev)

        menu.addSeparator() # 5

        menu.addAction('Quit')
        quitAppMenuItem = menu.actions()[6]
        # This is below reactor.run to allow access from other places outside main.
        def quitApp():
            # This is buggy...
            if parent.reactor.threadpool is not None:
                parent.reactor.threadpool.stop()
            parent.close()
            parent.reactor.stop()
            app.quit()
            sys.exit()
        quitAppMenuItem.triggered.connect(quitApp)

        self.setContextMenu(menu)
        self.setIcon(icon)
        self.activated.connect(lambda r: activateCallback(self, r))
        def changeIconToActiveState():
            self.setIcon(iconActive)
        def changeIconToPassiveState():
            self.setIcon(icon)
        menu.aboutToShow.connect(changeIconToActiveState)
        menu.aboutToHide.connect(changeIconToPassiveState)
示例#45
0
class TabWidget(QTabWidget):
    """
    TabWidget class definition
    """
    
    currentChangedFileInfo = pyqtSignal(QFileInfo)
    
    def __init__(self, parent=None):
        super(TabWidget, self).__init__(parent)
        self.tabBar().installEventFilter(self)
        self.setTabsClosable(True)
        self.setMovable(True)
        self.setFocusPolicy(Qt.NoFocus)
        
        self.icon_modified = QIcon('images/is-modified.png')
        self.icon_not_modified = QIcon('images/is-not-modified.png')
        
        self.tabCloseRequested.connect(self.on_tab_closed)
        
        nav_icon = QIcon('images/navigation-menu.png')
        self.menu_button = QPushButton('', self)
        self.menu_button.setIcon(nav_icon)
        self.menu_button.setFlat(True)
        self.menu_button.clicked.connect(self.on_menu_button_clicked)
        self.menu_button.setObjectName('TabWidgetMenuButton')
        self.menu_button.setToolTip('Menu with useful actions')
        self.setCornerWidget(self.menu_button, Qt.TopRightCorner)
        self.menu = QMenu(self)
        self.add_action('Remove current tab', 'ctrl+w', TabWidgetHelper.remove)
        self.add_action(
            'Remove all tab', 'ctrl+shift+w', TabWidgetHelper.remove_all)
        self.add_separator()
        self.add_action('Next Tab', QKeySequence.NextChild, 
                        TabWidgetHelper.next_tab)
        self.add_action('Previous Tab', QKeySequence.PreviousChild, 
                        TabWidgetHelper.previous_tab)
        self.add_separator()
        self.add_action('Open file', QKeySequence.Open,
                        TabWidgetHelper.open_file)
        Alter.invoke_all('tab_widget_add_action', self)
        self.currentChanged[int].connect(self.on_current_changed)
    
    def eventFilter(self, o, event):
        if o == self.tabBar() and event.type() == QEvent.MouseButtonPress:
            if event.button() == Qt.MidButton:
                index = self.tabBar().tabAt(event.pos())
                if index != -1:
                    self.on_tab_closed(index)
                    return True
        return super(TabWidget, self).eventFilter(o, event)
    
    def on_current_changed(self, index):
        if index != -1:
            widget = self.widget(index)
            self.setFocusProxy(widget)
            self.setFocus(Qt.TabFocusReason)
            self.currentChangedFileInfo.emit(widget.file_info)
    
    # the function name must be equal to signal name.
    # decorator because reduce the amount of memory used and is slightly faster
    @pyqtSlot(QFileInfo)
    def onFileItemActivated(self, file_info):
        Alter.invoke_all('tab_widget_add_tab', self, file_info)
    
    def add_tab(self, cls, file_info, force_open=False):
        #if file is already open
        index, i = -1, 0
        while not force_open and i < self.count() and index == -1:
            if self.widget(i).file_info == file_info:
                index = i
            i += 1
        if index == -1:
            index = self.addTab(
                cls(file_info, self),
                self.icon_not_modified,
                file_info.fileName()
            )
        self.setCurrentIndex(index)
        self.setFocus(True)
    
    def on_menu_button_clicked(self):
        pos = self.mapToGlobal(self.menu_button.pos())
        menu_width = self.menu.sizeHint().width()
        pos.setY(pos.y() + self.menu_button.height())
        pos.setX(pos.x() + self.menu_button.width() - menu_width)
        if len(self.menu.actions()) > 0:
            self.menu.exec(pos)
    
    def on_tab_closed(self, index):
        widget = self.widget(index)
        self.removeTab(index)
        # remove the widget for real
        widget.deleteLater()
        del widget
    
    def add_action(self, name, shortcut, callback, icon = None):
        """
        Ajoute une action au context menu et au widget lui même.
        Créer une fonction à la volé pour fournir des arguments aux fonctions
        associé aux actions.
        """
        action = QAction(name, self)
        if icon:
            action.setIcon(icon)
        action.setShortcut(shortcut)
        action.setShortcutContext(Qt.WidgetWithChildrenShortcut)
        action.triggered.connect(self.__wrapper(callback))
        self.addAction(action)
        self.menu.addAction(action)

    def add_separator(self):
        """Simple abstraction of self.context_menu.addSeparator()"""
        self.menu.addSeparator()
    
    def __wrapper(self, callback):
        def __new_function():
            """
            __new_function représente la forme de tous les callbacks connecté
            à une action pour pouvoir utiliser les raccourcis en même temps que
            le menu contextuel.
            """
            callback(self)
        return __new_function
    
    def on_current_modified(self, modified):
        icon = self.icon_modified if modified else self.icon_not_modified
        index = self.currentIndex()
        self.tabBar().setTabIcon(index, icon)
示例#46
0
class SystemTrayIcon(QSystemTrayIcon):
    def __init__(self, basedir, app, parent=None):
        self.basedir = basedir
        if globals.PLATFORM == 'OSX':
            if app.devicePixelRatio() == 2:
                self.icon = QtGui.QIcon(basedir+'Assets/aether-black-tray.svg')
                self.iconActive = QtGui.QIcon(basedir+'Assets/aether-white-tray.svg')
                self.iconHighlight =  QtGui.QIcon(self.basedir+'Assets/aether-blue-tray.svg')
            else:
                self.icon = QtGui.QIcon(basedir+'Assets/aether-black-tray.png')
                self.iconActive = QtGui.QIcon(basedir+'Assets/aether-white-tray.png')
                self.iconHighlight =  QtGui.QIcon(self.basedir+'Assets/aether-blue-tray.png')
        elif globals.PLATFORM == 'LNX':
            self.icon = QtGui.QIcon(basedir+'Assets/aether-white-tray.png')
            self.iconActive = self.icon
            self.iconHighlight = self.icon
        elif globals.PLATFORM == 'WIN':
            self.icon = QtGui.QIcon(basedir+'Assets/aether-black-tray-win.svg')
            self.iconActive = self.icon
            self.iconHighlight = self.icon
        else:
            pass

        QSystemTrayIcon.__init__(self, self.icon, parent)

        self.menu = QMenu(parent)
        if globals.appIsPaused:
            self.menu.addAction('Aether is paused.').setDisabled(True)
        else:
            self.menu.addAction('Aether is connected.').setDisabled(True)
        globalStatusMenuItem = self.menu.actions()[0]

        self.menu.addSeparator() # 1
        self.menu.addAction('You have no replies.').setDisabled(True)
        self.messagesMenuItem = self.menu.actions()[2]
        def goToMessages():
            self.messagesMenuItem.setText('You have no replies.')
            self.messagesMenuItem.setDisabled(True)
            if parent.isHidden():
                parent.show()
                parent.raise_()
            jsString = \
            ("firstFrameScope = angular.element(document.getElementById('first-frame-contents')).scope();"
             "firstFrameScope.repliesButtonClick();"
             "firstFrameScope.$apply();"
            )
            self.webView.JSContext(jsString)
            # reach out to jscontext and
            # Here, I need to call qtwebkit and tell it to open messages.
        self.messagesMenuItem.triggered.connect(goToMessages)
        self.menu.addSeparator() # 3
        if globals.appIsPaused:
            self.menu.addAction('Resume')
        else:
            self.menu.addAction('Pause')
        self.togglePauseMenuItem = self.menu.actions()[4]
        def togglePause():
            if globals.appIsPaused:
                globals.appIsPaused = False
                self.togglePauseMenuItem.setText('Pause')
                globalStatusMenuItem.setText('Aether is connected.')
            else:
                globals.appIsPaused = True
                self.togglePauseMenuItem.setText('Resume')
                self.globalStatusMenuItem.setText('Aether is paused.')
        self.togglePauseMenuItem.triggered.connect(togglePause)

        if not globals.appStartedAtBoot:
            self.menu.addAction('Show Aether')
        else:
            self.menu.addAction('Hide Aether')
        self.toggleVisibilityMenuItem = self.menu.actions()[5]
        def toggleVisibility():
            if parent.isHidden():
                parent.show()
                parent.raise_()
                # if globals.PLATFORM == 'OSX':
                #     globals.raiseAndFocusApp() #FIXME BEFORE RELEASE
                self.toggleVisibilityMenuItem.setText('Hide Aether')

            else:
                parent.hide()
                parent.lower()
                self.toggleVisibilityMenuItem.setText('Show Aether')
        self.toggleVisibilityMenuItem.triggered.connect(toggleVisibility)

        self.menu.addAction('Email the developer')
        self.emailDevMenuItem = self.menu.actions()[6]
        def emailDev():
            mailInitialiser = \
                QUrl('mailto:[email protected]'
                     '?subject=Feedback for Aether'
                     '&body=<i><br><br>Hello there! Thanks for taking time to give feedback, I really appreciate it. '
                     'If you are having problems, please right click on Aether.app on your Applications folder, '
                     'click Show Package Contents, go to Contents/MacOS/Logs and attach the network.log file there to '
                     'this email. <br><br>'
                     'You can delete this text before sending.'
                     '<br><br>You can find my PGP key here:</i> '
                     'http://pgp.mit.edu:11371/pks/lookup?search=Burak+Nehbit')
            QtGui.QDesktopServices.openUrl(mailInitialiser)
        self.emailDevMenuItem.triggered.connect(emailDev)

        self.menu.addSeparator() # 5

        self.menu.addAction('Quit')
        self.quitAppMenuItem = self.menu.actions()[8]
        # This is below reactor.run to allow access from other places outside main.
        def quitApp():
            # This is buggy...
            # if parent.reactor.threadpool is not None:
            #     parent.reactor.threadpool.stop()
            # parent.close()
            print('firing kill app on prot instance')
            self.protInstance.killApp()
            # def finishExit():
            #     parent.reactor.stop()
            #     app.quit()
            #     sys.exit()
            # d.addCallback(finishExit)
        self.quitAppMenuItem.triggered.connect(quitApp)

        self.setContextMenu(self.menu)
        self.setIcon(self.icon)

        def changeIconToActiveState():
            self.setIcon(self.iconActive)
        def changeIconToPassiveState():
            self.setIcon(self.icon)
        self.menu.aboutToShow.connect(changeIconToActiveState)
        self.menu.aboutToHide.connect(changeIconToPassiveState)
        if globals.PLATFORM == 'WIN':
            def showOnLeftClick(reason):
                if reason == self.Trigger:
                    toggleVisibility() # I hate that Python doesn't have anonymous functions.
            self.activated.connect(showOnLeftClick)

    def lightUpIcon(self):
        self.setIcon(self.iconHighlight)
        self.messagesMenuItem.setText('New replies available.')
        self.messagesMenuItem.setDisabled(False)
        self.toggleVisibilityMenuItem.setText('Hide Aether')

    def makeIconGoDark(self):
        self.setIcon(self.icon)
        self.messagesMenuItem.setText('You have no replies.')
        self.messagesMenuItem.setDisabled(True)
示例#47
0
    def contextMenuEvent(self, event):
        """ Creates two context menus:
            1. no modifier -> spellchecker & clear emnu
            2. ctrl modifier -> Text change & Insert symbol
        """
        contextMenu = self.createStandardContextMenu()
        spellMenu = True

        if (QApplication.keyboardModifiers() & Qt.ControlModifier):
            spellMenu = False

        self.clearAction = QAction(self.tr("Clear"), contextMenu)
        contextMenu.addSeparator()
        contextMenu.addAction(self.clearAction)
        if not len(self.toPlainText()):
            self.clearAction.setEnabled(False)
        self.clearAction.triggered.connect(self.clear)
        if not spellMenu:
            textOpsMenu = QMenu(self.tr("Text change..."))

            removeEOLAction = QAction(self.tr("Join lines"),
                                            textOpsMenu, )
            textOpsMenu.addAction(removeEOLAction)
            removeEOLAction.triggered.connect(self.removeEOL)
            textOpsMenu.addSeparator()

            toUppercaseAction = QAction(self.tr("to UPPERCASE"),
                                              textOpsMenu)
            textOpsMenu.addAction(toUppercaseAction)
            toUppercaseAction.triggered.connect(self.toUppercase)

            toLowercaseAction = QAction(self.tr("to lowercase"),
                                              textOpsMenu)
            textOpsMenu.addAction(toLowercaseAction)
            toLowercaseAction.triggered.connect(self.toLowercase)

            toTitleAction = QAction(self.tr("to Title"), textOpsMenu)
            textOpsMenu.addAction(toTitleAction)
            toTitleAction.triggered.connect(self.toTitlecase)

            toCapsAction = QAction(self.tr("to Capitalize"), textOpsMenu)
            textOpsMenu.addAction(toCapsAction)
            toCapsAction.triggered.connect(self.toCaps)

            contextMenu.insertSeparator(contextMenu.actions()[0])
            contextMenu.insertMenu(contextMenu.actions()[0], textOpsMenu)

            insertSymbolMenu = QMenu(self.tr("Insert symbol..."))
            settings_symbols = settings.get('editor:symbols')
            if settings_symbols:
                self.symbols = settings_symbols.split('\n')
            for symbol in self.symbols:
                action = SpellAction(symbol, insertSymbolMenu)
                action.correct.connect( self.insertSymbol)
                insertSymbolMenu.addAction(action)

            contextMenu.insertMenu(contextMenu.actions()[0], insertSymbolMenu)

        if not self.textCursor().hasSelection() and spellMenu:
            # Select the word under the cursor for spellchecker
            cursor = self.textCursor()
            cursor.select(QTextCursor.WordUnderCursor)

            self.setTextCursor(cursor)
            text = self.textCursor().selectedText()

            #TODO: put to configuration list of ignored starting/ending chars
            # remove u"„" from selection
            if text.startswith(u"„") or text.startswith(u"“"):
                text = text[1:]
                selectionEnd = cursor.selectionEnd()
                cursor.setPosition(cursor.position() - len(text))
                cursor.setPosition(selectionEnd, QTextCursor.KeepAnchor)
                self.setTextCursor(cursor)
            # remove u"”" from selection
            if text.endswith(u"”") or text.startswith(u"“"):
                selectionEnd = cursor.selectionEnd()
                cursor.setPosition(cursor.position() - len(text))
                cursor.setPosition(selectionEnd - 1, QTextCursor.KeepAnchor)
                text = text[:-1]
                self.setTextCursor(cursor)

            # Check if the selected word is misspelled and offer spelling
            # suggestions if it is.
            if self.textCursor().hasSelection():
                if not self.dict.check(text):
                    spell_menu = QMenu(self.tr("Spelling Suggestions"))
                    addWordAcction = QAction(self.tr('Add word...'),
                                             spell_menu)
                    addWordAcction.triggered.connect(self.addWord)
                    spell_menu.addAction(addWordAcction)
                    for word in self.dict.suggest(text):
                        action = SpellAction(word, spell_menu)
                        action.correct.connect(self.changeText)
                        spell_menu.addAction(action)
                    contextMenu.insertSeparator(contextMenu.actions()[1])
                    contextMenu.insertMenu(contextMenu.actions()[0],
                                            spell_menu)
                    # Only add the spelling suggests to the menu if there are
                    # suggestions.
                    if len(spell_menu.actions()) != 1:
                        spell_menu.insertSeparator(spell_menu.actions()[1])


        contextMenu.exec_(event.globalPos())
        event.accept()
示例#48
0
class SystemTrayIcon(QSystemTrayIcon):
    def __init__(self, basedir, app, parent=None):
        if PLATFORM == 'OSX':
            if app.devicePixelRatio() == 2:
                self.icon = QtGui.QIcon(BASEDIR+'Assets/aether-black-tray.svg')
                self.iconActive = QtGui.QIcon(BASEDIR+'Assets/aether-white-tray.svg')
                self.iconHighlight =  QtGui.QIcon(BASEDIR+'Assets/aether-blue-tray.svg')
            else:
                self.icon = QtGui.QIcon(BASEDIR+'Assets/aether-black-tray.png')
                self.iconActive = QtGui.QIcon(BASEDIR+'Assets/aether-white-tray.png')
                self.iconHighlight =  QtGui.QIcon(BASEDIR+'Assets/aether-blue-tray.png')
        elif PLATFORM == 'WIN':
            self.icon = QtGui.QIcon(BASEDIR+'Assets/aether-white-tray-win.svg')
            self.iconActive = self.icon
            self.iconHighlight = QtGui.QIcon(BASEDIR+'Assets/aether-green-tray-win.svg')
        else:
            pass

        QSystemTrayIcon.__init__(self, self.icon, parent)

        self.menu = QMenu(parent)
        if globals.appIsPaused:
            self.menu.addAction('Paused').setDisabled(True)
        else:
            self.menu.addAction('Online').setDisabled(True)
        self.globalStatusMenuItem = self.menu.actions()[0]

        self.menu.addSeparator() # 1
        self.menu.addAction('You have no replies.').setDisabled(True)
        self.messagesMenuItem = self.menu.actions()[2]
        def goToMessages():
            self.messagesMenuItem.setText('You have no replies.')
            self.messagesMenuItem.setDisabled(True)
            parent.show()
            parent.raise_()
            jsString = \
            ("firstFrameScope = angular.element(document.getElementById('first-frame-contents')).scope();"
             "firstFrameScope.repliesButtonClick();"
             "firstFrameScope.$apply();"
            )
            self.webView.JSContext(jsString)
            # reach out to jscontext and
            # Here, I need to call qtwebkit and tell it to open messages.
        self.messagesMenuItem.triggered.connect(goToMessages)
        self.menu.addSeparator() # 3
        if globals.appIsPaused:
            self.menu.addAction('Resume')
        else:
            self.menu.addAction('Pause')
        self.togglePauseMenuItem = self.menu.actions()[4]
        def togglePause():
            if globals.appIsPaused:
                globals.appIsPaused = False
                self.togglePauseMenuItem.setText('Pause')
                self.globalStatusMenuItem.setText('Online')
            else:
                globals.appIsPaused = True
                self.togglePauseMenuItem.setText('Resume')
                self.globalStatusMenuItem.setText('Paused')
        self.togglePauseMenuItem.triggered.connect(togglePause)
        self.menu.addAction('Show Aether')
        self.toggleVisibilityMenuItem = self.menu.actions()[5]
        def makeVisible():
            parent.show()
            parent.raise_()
            if PLATFORM == 'OSX':
                globals.raiseAndFocusApp()

        self.toggleVisibilityMenuItem.triggered.connect(makeVisible)

        self.menu.addAction('Email the developer')
        self.emailDevMenuItem = self.menu.actions()[6]
        def emailDev():
            mailInitialiser = \
                QUrl('mailto:[email protected]'
                     '?subject=Feedback for Aether'
                     '&body=Hello there! Thanks for taking time to give feedback, I really appreciate it. '
                     'If you are having problems, please follow the directions at www.getaether.net/sending_logs, '
                     'and send me the produced logs. Thanks! You can delete this text before sending. '
                     'You can find my PGP key here: pgp.mit.edu:11371/pks/lookup?search=Burak+Nehbit')
            QtGui.QDesktopServices.openUrl(mailInitialiser)
        self.emailDevMenuItem.triggered.connect(emailDev)

        self.menu.addSeparator() # 5

        self.menu.addAction('Settings')
        self.settingsMenuItem = self.menu.actions()[8]
        def goToSettings():
            self.settingsMenuItem.setText('Settings')
            self.settingsMenuItem.setDisabled(False)
            if parent.isHidden():
                parent.show()
                parent.raise_()
            jsString = \
            ("firstFrameScope = angular.element(document.getElementById('first-frame-contents')).scope();"
             "firstFrameScope.settingsButtonClick();"
             "firstFrameScope.$apply();"
            )
            self.webView.JSContext(jsString)
        self.settingsMenuItem.triggered.connect(goToSettings)

        self.menu.addSeparator() # 6

        self.menu.addAction('Quit Aether')
        self.quitAppMenuItem = self.menu.actions()[10]
        # This is below reactor.run to allow access from other places outside main.
        def quitApp():
            # This is buggy...
            if parent.reactor.threadpool is not None:
                parent.reactor.threadpool.stop()
            parent.close()
            parent.reactor.stop()
            app.quit()
            sys.exit()

            # self.protInstance.killApp()
            # def finishExit():
            #     parent.reactor.stop()
            #     app.quit()
            #     sys.exit()
            # d.addCallback(finishExit)
        self.quitAppMenuItem.triggered.connect(quitApp)



        self.setContextMenu(self.menu)
        self.setIcon(self.icon)

        def changeIconToActiveState():
            self.setIcon(self.iconActive)
        def changeIconToPassiveState():
            self.setIcon(self.icon)
        self.menu.aboutToShow.connect(changeIconToActiveState)
        self.menu.aboutToHide.connect(changeIconToPassiveState)
        if PLATFORM == 'WIN':
            def showOnLeftClick(reason):
                if reason == self.Trigger:
                    makeVisible() # I hate that Python doesn't have anonymous functions.
            self.activated.connect(showOnLeftClick)

    def lightUpIcon(self):
        self.setIcon(self.iconHighlight)
        self.messagesMenuItem.setText('New replies available.')
        self.messagesMenuItem.setDisabled(False)

    def makeIconGoDark(self):
        self.setIcon(self.icon)
        self.messagesMenuItem.setText('You have no replies.')
        self.messagesMenuItem.setDisabled(True)