Beispiel #1
0
 def __init__(self, parent=None):
     super(TabBar, self).__init__(parent)
     
     self.setFocusPolicy(Qt.NoFocus)
     self.setMovable(True)      # TODO: make configurable
     self.setExpanding(False)
     self.setUsesScrollButtons(True)
     self.setElideMode(Qt.ElideNone)
     
     mainwin = self.window()
     self.docs = []
     for doc in app.documents:
         self.addDocument(doc)
         if doc is mainwin.currentDocument():
             self.setCurrentDocument(doc)
     
     app.documentCreated.connect(self.addDocument)
     app.documentClosed.connect(self.removeDocument)
     app.documentUrlChanged.connect(self.setDocumentStatus)
     app.documentModificationChanged.connect(self.setDocumentStatus)
     app.jobStarted.connect(self.setDocumentStatus)
     app.jobFinished.connect(self.setDocumentStatus)
     app.settingsChanged.connect(self.readSettings)
     engrave.engraver(mainwin).stickyChanged.connect(self.setDocumentStatus)
     mainwin.currentDocumentChanged.connect(self.setCurrentDocument)
     self.currentChanged.connect(self.slotCurrentChanged)
     self.tabMoved.connect(self.slotTabMoved)
     self.tabCloseRequested.connect(self.slotTabCloseRequested)
     self.readSettings()
Beispiel #2
0
    def postImport(self, settings, doc):
        """Adaptations of the source after running musicxml2ly
		
		Present settings: 
		Reformat source
        Remove superfluous durations
        Remove duration scaling
        Engrave directly
		
        """
        cursor = QTextCursor(doc)
        if settings[0]:
            import reformat

            reformat.reformat(cursor)
        if settings[1]:
            cursor.select(QTextCursor.Document)
            from rhythm import rhythm

            rhythm.rhythm_implicit_per_line(cursor)
        if settings[2]:
            cursor.select(QTextCursor.Document)
            from rhythm import rhythm

            rhythm.rhythm_remove_fraction_scaling(cursor)
        if settings[3]:
            import engrave

            engrave.engraver(self.mainwindow()).engrave("preview", doc, False)
Beispiel #3
0
    def postImport(self, settings, doc):
        """Adaptations of the source after running musicxml2ly
		
		Present settings: 
		Reformat source
        Remove superfluous durations
        Remove duration scaling
        Engrave directly
		
        """
        cursor = QTextCursor(doc)
        if settings[0]:
            import reformat
            reformat.reformat(cursor)
        if settings[1]:
            cursor.select(QTextCursor.Document)
            from rhythm import rhythm
            rhythm.rhythm_implicit_per_line(cursor)
        if settings[2]:
            cursor.select(QTextCursor.Document)
            from rhythm import rhythm
            rhythm.rhythm_remove_fraction_scaling(cursor)
        if settings[3]:
            import engrave
            engrave.engraver(self.mainwindow()).engrave('preview', doc, False)
Beispiel #4
0
    def __init__(self, parent=None):
        super(TabBar, self).__init__(parent)

        self.setFocusPolicy(Qt.NoFocus)
        self.setTabsClosable(True)  # TODO: make configurable
        self.setMovable(True)  # TODO: make configurable
        self.setExpanding(False)
        self.setUsesScrollButtons(True)
        self.setElideMode(Qt.ElideNone)

        mainwin = self.window()
        self.docs = []
        for doc in app.documents:
            self.addDocument(doc)
            if doc is mainwin.currentDocument():
                self.setCurrentDocument(doc)

        app.documentCreated.connect(self.addDocument)
        app.documentClosed.connect(self.removeDocument)
        app.documentUrlChanged.connect(self.setDocumentStatus)
        app.documentModificationChanged.connect(self.setDocumentStatus)
        app.jobStarted.connect(self.setDocumentStatus)
        app.jobFinished.connect(self.setDocumentStatus)
        engrave.engraver(mainwin).stickyChanged.connect(self.setDocumentStatus)
        mainwin.currentDocumentChanged.connect(self.setCurrentDocument)
        self.currentChanged.connect(self.slotCurrentChanged)
        self.tabMoved.connect(self.slotTabMoved)
        self.tabCloseRequested.connect(self.slotTabCloseRequested)
Beispiel #5
0
 def applySnippet(self, name):
     d = app.openUrl(QUrl())
     self.mainwindow().setCurrentDocument(d)
     super(TemplateMenu, self).applySnippet(name)
     d.setUndoRedoEnabled(False)
     d.setUndoRedoEnabled(True)  # d.clearUndoRedoStacks() only in Qt >= 4.7
     d.setModified(False)
     from . import snippets
     if 'template-run' in snippets.get(name).variables:
         import engrave
         engrave.engraver(self.mainwindow()).engrave('preview', d)
Beispiel #6
0
 def applySnippet(self, name):
     d = app.openUrl(QUrl())
     self.mainwindow().setCurrentDocument(d)
     super(TemplateMenu, self).applySnippet(name)
     d.setUndoRedoEnabled(False)
     d.setUndoRedoEnabled(True) # d.clearUndoRedoStacks() only in Qt >= 4.7
     d.setModified(False)
     from . import snippets
     if 'template-run' in snippets.get(name).variables:
         import engrave
         engrave.engraver(self.mainwindow()).engrave('preview', d)
Beispiel #7
0
 def createDocument(self, filename, contents):
     """Create a new document using the specified filename and contents.
     
     Make it the current document in our mainwindow and run the engraver.
     
     """
     while os.path.exists(filename) or app.findDocument(QUrl.fromLocalFile(filename)):
         filename = util.next_file(filename)
     doc = app.openUrl(QUrl())
     doc.setPlainText(contents)
     doc.setUrl(QUrl.fromLocalFile(filename))
     doc.setModified(True)
     self.mainwindow().setCurrentDocument(doc)
     import engrave
     engrave.engraver(self.mainwindow()).engrave(True, doc, False)
Beispiel #8
0
def slot_file_new_from_template_action(action):
    name = action.objectName()
    d = app.openUrl(QUrl())
    win = mainwindow()
    win.setCurrentDocument(d)
    from snippet import insert, snippets
    view = win.currentView()
    view.setFocus()
    insert.insert(name, view)
    d.setUndoRedoEnabled(False)
    d.setUndoRedoEnabled(True) # d.clearUndoRedoStacks() only in Qt >= 4.7
    d.setModified(False)
    if 'template-run' in snippets.get(name).variables:
        import engrave
        engrave.engraver(win).engrave('preview', d)
Beispiel #9
0
    def createToolBars(self):
        ac = self.actionCollection
        self.toolbar_main = t = self.addToolBar('')
        t.setObjectName('toolbar_main')
        t.addAction(ac.file_new)
        t.addAction(ac.file_open)
        t.addAction(ac.file_save)
        t.addAction(ac.file_save_as)
        t.addAction(ac.file_close)
        t.addSeparator()
        t.addAction(browseriface.get(self).actionCollection.go_back)
        t.addAction(browseriface.get(self).actionCollection.go_forward)
        t.addSeparator()
        t.addAction(ac.edit_undo)
        t.addAction(ac.edit_redo)
        t.addSeparator()
        t.addAction(
            scorewiz.ScoreWizard.instance(self).actionCollection.scorewiz)
        t.addAction(engrave.engraver(self).actionCollection.engrave_runner)

        self.toolbar_music = t = self.addToolBar('')
        t.setObjectName('toolbar_music')
        ma = panelmanager.manager(self).musicview.actionCollection
        t.addAction(ma.music_document_select)
        t.addAction(ma.music_print)
        t.addSeparator()
        t.addAction(ma.music_zoom_in)
        t.addAction(ma.music_zoom_combo)
        t.addAction(ma.music_zoom_out)
        t.addSeparator()
        t.addAction(ma.music_prev_page)
        t.addAction(ma.music_pager)
        t.addAction(ma.music_next_page)
Beispiel #10
0
 def __init__(self, mainwindow):
     super(DocumentActionGroup, self).__init__(mainwindow)
     self._acts = {}
     self._accels = {}
     self.setExclusive(True)
     for d in app.documents:
         self.addDocument(d)
     app.documentCreated.connect(self.addDocument)
     app.documentClosed.connect(self.removeDocument)
     app.documentUrlChanged.connect(self.setDocumentStatus)
     app.documentModificationChanged.connect(self.setDocumentStatus)
     app.jobStarted.connect(self.setDocumentStatus)
     app.jobFinished.connect(self.setDocumentStatus)
     mainwindow.currentDocumentChanged.connect(self.setCurrentDocument)
     engrave.engraver(mainwindow).stickyChanged.connect(self.setDocumentStatus)
     self.triggered.connect(self.slotTriggered)
Beispiel #11
0
 def createToolBars(self):
     ac = self.actionCollection
     self.toolbar_main = t = self.addToolBar('')
     t.setObjectName('toolbar_main')
     t.addAction(ac.file_new)
     t.addAction(ac.file_open)
     t.addAction(ac.file_save)
     t.addAction(ac.file_save_as)
     t.addAction(ac.file_close)
     t.addSeparator()
     t.addAction(browseriface.get(self).actionCollection.go_back)
     t.addAction(browseriface.get(self).actionCollection.go_forward)
     t.addSeparator()
     t.addAction(ac.edit_undo)
     t.addAction(ac.edit_redo)
     t.addSeparator()
     t.addAction(scorewiz.ScoreWizard.instance(self).actionCollection.scorewiz)
     t.addAction(engrave.engraver(self).actionCollection.engrave_runner)
     
     self.toolbar_music = t = self.addToolBar('')
     t.setObjectName('toolbar_music')
     ma = panelmanager.manager(self).musicview.actionCollection
     t.addAction(ma.music_document_select)
     t.addAction(ma.music_print)
     t.addSeparator()
     t.addAction(ma.music_zoom_in)
     t.addAction(ma.music_zoom_combo)
     t.addAction(ma.music_zoom_out)
     t.addSeparator()
     t.addAction(ma.music_prev_page)
     t.addAction(ma.music_pager)
     t.addAction(ma.music_next_page)
Beispiel #12
0
 def __init__(self, mainwindow):
     super(DocumentActionGroup, self).__init__(mainwindow)
     self._acts = {}
     self._accels = {}
     self.setExclusive(True)
     for d in app.documents:
         self.addDocument(d)
     app.documentCreated.connect(self.addDocument)
     app.documentClosed.connect(self.removeDocument)
     app.documentUrlChanged.connect(self.setDocumentStatus)
     app.documentModificationChanged.connect(self.setDocumentStatus)
     app.jobStarted.connect(self.setDocumentStatus)
     app.jobFinished.connect(self.setDocumentStatus)
     mainwindow.currentDocumentChanged.connect(self.setCurrentDocument)
     engrave.engraver(mainwindow).stickyChanged.connect(self.setDocumentStatus)
     self.triggered.connect(self.slotTriggered)
Beispiel #13
0
 def slotUpdatedFiles(self, document, job=None):
     """Called when there are new MIDI files."""
     mainwindow = self.parentWidget().mainwindow()
     import engrave
     if document not in (mainwindow.currentDocument(), engrave.engraver(mainwindow).document()):
         return
     import jobattributes
     if job and jobattributes.get(job).mainwindow != mainwindow:
         return
     self.loadResults(document)
Beispiel #14
0
 def slotUpdatedFiles(self, document, j=None):
     """Called when there are new MIDI files."""
     mainwindow = self.parentWidget().mainwindow()
     import engrave
     if document not in (mainwindow.currentDocument(), engrave.engraver(mainwindow).document()):
         return
     import job
     if j and job.attributes.get(j).mainwindow != mainwindow:
         return
     self.loadResults(document)
Beispiel #15
0
 def slotDocumentUpdated(self, doc, job):
     """Called when a Job, finished on the document, has created new PDFs."""
     # if result files of this document were already displayed, the display
     # is updated. Else the current document is switched if the document was
     # the current document to be engraved (e.g. sticky or master) and the
     # the job was started on this mainwindow
     import engrave
     mainwindow = self.parent().mainwindow()
     if (doc == self._document
             or (jobattributes.get(job).mainwindow == mainwindow
                 and doc == engrave.engraver(mainwindow).document())):
         self.setCurrentDocument(doc)
Beispiel #16
0
 def slotDocumentUpdated(self, doc, job):
     """Called when a Job, finished on the document, has created new PDFs."""
     # if result files of this document were already displayed, the display
     # is updated. Else the current document is switched if the document was
     # the current document to be engraved (e.g. sticky or master) and the
     # the job was started on this mainwindow
     import engrave
     mainwindow = self.parent().mainwindow()
     if (doc == self._document or
         (jobattributes.get(job).mainwindow == mainwindow and
          doc == engrave.engraver(mainwindow).document())):
         self.setCurrentDocument(doc)
Beispiel #17
0
 def __init__(self, tool):
     super(Widget, self).__init__(tool)
     
     layout = QVBoxLayout(spacing=1)
     self.setLayout(layout)
     
     # manual mode UI elements that need special treatment
     self.CBverbose = QCheckBox(clicked=self.optionsChanged)
     self.CBpointandclick = QCheckBox(clicked=self.optionsChanged)
     self.CBcustomfile = QCheckBox(clicked=self.optionsChanged)
     self.LEcustomfile = QLineEdit(enabled=False)
     
     # run Lily button
     self.engraveButton = QToolButton()
     self.engraveButton.setDefaultAction(
         engrave.engraver(tool.mainwindow()).actionCollection.engrave_debug)
     
     # help button
     self.helpButton = QToolButton(clicked=self.helpButtonClicked)
     self.helpButton.setIcon(icons.get('help-contents'))
     
     # add manual widgets
     hbox = QHBoxLayout()
     hbox.setContentsMargins(0, 0, 0, 0)
     hbox.addWidget(self.engraveButton)
     hbox.addWidget(self.helpButton)
     hbox.addStretch(1)
     layout.addLayout(hbox)
     layout.addWidget(self.CBverbose)
     layout.addWidget(self.CBpointandclick)
     
     # automatically processed modes
     self.checkboxes = {}
     for mode in layoutcontrol.modelist():
         self.checkboxes[mode] = cb = QCheckBox(clicked=self.optionsChanged)
         layout.addWidget(cb)
     
     # add manual widgets
     layout.addWidget(self.CBcustomfile)
     layout.addWidget(self.LEcustomfile)
     layout.addStretch(1)
     
     # connect manual widgets
     self.CBcustomfile.toggled.connect(self.LEcustomfile.setEnabled)
     self.LEcustomfile.textEdited.connect(self.optionsChanged)
     
     app.translateUI(self)
     self.loadSettings()
     tool.mainwindow().aboutToClose.connect(self.saveSettings)
Beispiel #18
0
    def __init__(self, tool):
        super(Widget, self).__init__(tool)

        layout = QVBoxLayout(spacing=1)
        self.setLayout(layout)

        # manual mode UI elements that need special treatment
        self.CBverbose = QCheckBox(clicked=self.optionsChanged)
        self.CBpointandclick = QCheckBox(clicked=self.optionsChanged)
        self.CBcustomfile = QCheckBox(clicked=self.optionsChanged)
        self.LEcustomfile = QLineEdit(enabled=False)

        # run Lily button
        self.engraveButton = QToolButton()
        self.engraveButton.setDefaultAction(
            engrave.engraver(tool.mainwindow()).actionCollection.engrave_debug)

        # help button
        self.helpButton = QToolButton(clicked=self.helpButtonClicked)
        self.helpButton.setIcon(icons.get('help-contents'))

        # add manual widgets
        hbox = QHBoxLayout()
        hbox.setContentsMargins(0, 0, 0, 0)
        hbox.addWidget(self.engraveButton)
        hbox.addWidget(self.helpButton)
        hbox.addStretch(1)
        layout.addLayout(hbox)
        layout.addWidget(self.CBverbose)
        layout.addWidget(self.CBpointandclick)

        # automatically processed modes
        self.checkboxes = {}
        for mode in layoutcontrol.modelist():
            self.checkboxes[mode] = cb = QCheckBox(clicked=self.optionsChanged)
            layout.addWidget(cb)

        # add manual widgets
        layout.addWidget(self.CBcustomfile)
        layout.addWidget(self.LEcustomfile)
        layout.addStretch(1)

        # connect manual widgets
        self.CBcustomfile.toggled.connect(self.LEcustomfile.setEnabled)
        self.LEcustomfile.textEdited.connect(self.optionsChanged)

        app.translateUI(self)
        self.loadSettings()
        tool.mainwindow().aboutToClose.connect(self.saveSettings)
Beispiel #19
0
    def queryCloseDocument(self, doc):
        """Returns whether a document can be closed.

        If modified, asks the user. The document is not closed.
        """
        if not doc.isModified():
            allow_close = True
        else:
            self.setCurrentDocument(doc, findOpenView=True)
            res = QMessageBox.warning(self, _("dialog title", "Close Document"),
                _("The document \"{name}\" has been modified.\n"
                "Do you want to save your changes or discard them?").format(name=doc.documentName()),
                QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel)
            if res == QMessageBox.Save:
                allow_close = self.saveDocument(doc)
            else:
                allow_close = res == QMessageBox.Discard
        return allow_close and engrave.engraver(self).queryCloseDocument(doc)
Beispiel #20
0
    def queryCloseDocument(self, doc):
        """Returns whether a document can be closed.

        If modified, asks the user. The document is not closed.
        """
        if not doc.isModified():
            allow_close = True
        else:
            self.setCurrentDocument(doc, findOpenView=True)
            res = QMessageBox.warning(self, _("dialog title", "Close Document"),
                _("The document \"{name}\" has been modified.\n"
                "Do you want to save your changes or discard them?").format(name=doc.documentName()),
                QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel)
            if res == QMessageBox.Save:
                allow_close = self.saveDocument(doc)
            else:
                allow_close = res == QMessageBox.Discard
        return allow_close and engrave.engraver(self).queryCloseDocument(doc)
Beispiel #21
0
        def load_content():
            """
            Load the content to be engraved as sample,
            either from the active editor or from a file.
            """
            nonlocal sample_content, base_dir
            nonlocal cache_persistently
            custom_file = self.custom_sample_url.path()

            # target will be one out of
            # 0: provided sample file
            # 1: custom file
            # 2: active document (unsaved state)
            target = self.sample_button_group.checkedId()
            if target == 1 and not custom_file:
                # Custom file selected but no file provided
                target = 0

            # Provided sample files will be cached persistently
            cache_persistently = target == 0

            if target == 2:
                # Engrave active document
                import engrave
                current_doc = engrave.engraver(app.activeWindow()).document()
                sample_content = current_doc.toPlainText()
                if not current_doc.url().isEmpty():
                    base_dir = os.path.dirname(current_doc.url().toLocalFile())
            else:
                if target == 1:
                    print("Custom file:", custom_file)
                    sample_file = custom_file
                else:
                    # Engrave from a file
                    import fonts
                    template_dir = os.path.join(fonts.__path__[0], 'templates')
                    sample_file = os.path.join(
                        template_dir,
                        'musicfont-' + self.cb_default_sample.currentData())
                    print("Default:", sample_file)
                base_dir = os.path.dirname(sample_file)
                with open(sample_file, 'r') as f:
                    sample_content = f.read()
Beispiel #22
0
 def setDocumentStatus(self, doc):
     # create accels
     accels = [self._accels[d] for d in self._accels if d is not doc]
     name = doc.documentName().replace('&', '&&')
     for index, char in enumerate(name):
         if char.isalnum() and char.lower() not in accels:
             name = name[:index] + '&' + name[index:]
             self._accels[doc] = char.lower()
             break
     else:
         self._accels[doc] = ''
     # add [sticky] mark if necessary
     if doc == engrave.engraver(self.mainwindow()).stickyDocument():
         # L10N: 'always engraved': the document is marked as 'Always Engrave' in the LilyPond menu
         name += " " + _("[always engraved]")
     self._acts[doc].setText(name)
     icon = documenticon.icon(doc, self.mainwindow())
     if icon.name() == "text-plain":
         icon = QIcon()
     self._acts[doc].setIcon(icon)
Beispiel #23
0
 def setDocumentStatus(self, doc):
     # create accels
     accels = [self._accels[d] for d in self._accels if d is not doc]
     name = doc.documentName().replace('&', '&&')
     for index, char in enumerate(name):
         if char.isalnum() and char.lower() not in accels:
             name = name[:index] + '&' + name[index:]
             self._accels[doc] = char.lower()
             break
     else:
         self._accels[doc] = ''
     # add [sticky] mark if necessary
     if doc == engrave.engraver(self.mainwindow()).stickyDocument():
         # L10N: 'always engraved': the document is marked as 'Always Engrave' in the LilyPond menu
         name += " " + _("[always engraved]")
     self._acts[doc].setText(name)
     icon = documenticon.icon(doc, self.mainwindow())
     if icon.name() == "text-plain":
         icon = QIcon()
     self._acts[doc].setIcon(icon)
Beispiel #24
0
        def load_content():
            """
            Load the content to be engraved as sample,
            either from the active editor or from a file.
            """
            nonlocal sample_content, base_dir
            nonlocal cache_persistently, target
            custom_file = self.custom_sample_url.path()

            if target == "<CUSTOM>" and not custom_file:
                target = self.cb_samples.itemData(0)

            # Provided sample files will be cached persistently
            cache_persistently = target not in ("<CUSTOM>", "<CURRENT>")

            if target == "<CURRENT>":
                # Engrave active document
                import engrave
                current_doc = engrave.engraver(app.activeWindow()).document()
                sample_content = current_doc.toPlainText()
                if not current_doc.url().isEmpty():
                    base_dir = os.path.dirname(current_doc.url().toLocalFile())
            else:
                if target == "<CUSTOM>":
                    print("Custom file:", custom_file)
                    sample_file = custom_file
                else:
                    # Engrave from a file
                    import fonts
                    template_dir = os.path.join(fonts.__path__[0], 'templates')
                    sample_file = os.path.join(template_dir,
                                               'musicfont-' + target)
                    print("Default:", sample_file)
                base_dir = os.path.dirname(sample_file)
                with open(sample_file, 'r') as f:
                    sample_content = f.read()
Beispiel #25
0
 def setDocumentStatus(self, doc):
     # create accels
     accels = [self._accels[d] for d in self._accels if d is not doc]
     name = doc.documentName().replace('&', '&&')
     for index, char in enumerate(name):
         if char.isalnum() and char.lower() not in accels:
             name = name[:index] + '&' + name[index:]
             self._accels[doc] = char.lower()
             break
     else:
         self._accels[doc] = ''
     # add [sticky] mark if necessary
     if doc == engrave.engraver(self.mainwindow()).stickyDocument():
         # L10N: 'always engraved': the document is marked as 'Always Engrave' in the LilyPond menu
         name += " " + _("[always engraved]")
     self._acts[doc].setText(name)
     # set the icon
     if jobmanager.is_running(doc):
         icon = icons.get('lilypond-run')
     elif doc.isModified():
         icon = icons.get('document-save')
     else:
         icon = QIcon()
     self._acts[doc].setIcon(icon)
Beispiel #26
0
 def setDocumentStatus(self, doc):
     # create accels
     accels = [self._accels[d] for d in self._accels if d is not doc]
     name = doc.documentName().replace('&', '&&')
     for index, char in enumerate(name):
         if char.isalnum() and char.lower() not in accels:
             name = name[:index] + '&' + name[index:]
             self._accels[doc] = char.lower()
             break
     else:
         self._accels[doc] = ''
     # add [sticky] mark if necessary
     if doc == engrave.engraver(self.mainwindow()).stickyDocument():
         # L10N: 'always engraved': the document is marked as 'Always Engrave' in the LilyPond menu
         name += " " + _("[always engraved]")
     self._acts[doc].setText(name)
     # set the icon
     if jobmanager.is_running(doc):
         icon = icons.get('lilypond-run')
     elif doc.isModified():
         icon = icons.get('document-save')
     else:
         icon = QIcon()
     self._acts[doc].setIcon(icon)
Beispiel #27
0
    def __init__(self, parent=None):
        super(TabBar, self).__init__(parent)

        self.setFocusPolicy(Qt.NoFocus)
        self.setMovable(True)  # TODO: make configurable
        self.setExpanding(False)
        self.setUsesScrollButtons(True)
        self.setElideMode(Qt.ElideNone)

        mainwin = self.window()
        self.docs = []
        for doc in app.documents:
            self.addDocument(doc)
            if doc is mainwin.currentDocument():
                self.setCurrentDocument(doc)

        app.documentCreated.connect(self.addDocument)
        app.documentClosed.connect(self.removeDocument)
        app.documentUrlChanged.connect(self.setDocumentStatus)
        app.documentModificationChanged.connect(self.setDocumentStatus)
        app.jobStarted.connect(self.setDocumentStatus)
        app.jobFinished.connect(self.setDocumentStatus)
        app.settingsChanged.connect(self.readSettings)
        engrave.engraver(mainwin).stickyChanged.connect(self.setDocumentStatus)
        mainwin.currentDocumentChanged.connect(self.setCurrentDocument)
        self.currentChanged.connect(self.slotCurrentChanged)
        self.tabMoved.connect(self.slotTabMoved)
        self.tabCloseRequested.connect(self.slotTabCloseRequested)
        self.readSettings()

        style = """
QTabBar::tab {
    background: white;
    border-style: solid;
    border-width: 1px 0px;
    border-color: #ACACAC;
    min-width: 8ex;
    padding: 2px 4px 2px 2px;
}

QTabBar::tab:selected:active {
    border-color: #045FFF;
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                stop: 0 #69B1FA, stop: 1 #0C80FF);
    color: white;
}

QTabBar::tab:selected:!active {
    background: #E5E5E5;
}

QTabBar::tab:first,
QTabBar::tab:only-one {
    border-left-width: 1px;
    border-top-left-radius: 4px;
    border-bottom-left-radius: 4px;
}

QTabBar::tab:!first:!selected:!previous-selected {
    border-left-color: #E5E5E5;
    border-left-width: 1px;
}

QTabBar::tab:last,
QTabBar::tab:only-one {
    border-right-width: 1px;
    border-top-right-radius: 4px;
    border-bottom-right-radius: 4px;
}
"""
        if sys.platform.startswith('darwin'):
            self.setStyleSheet(style)