Example #1
0
def refToLink(ref):
    """Transforms the reference ``ref`` in a link displaying useful infos
    about that reference. For character, character's name. For text item,
    item's name, etc.
    """
    match = re.fullmatch(RegEx, ref)
    if match:
        _type = match.group(1)
        _ref = match.group(2)
        text = ""
        if _type == TextLetter:
            m = mainWindow().mdlOutline
            idx = m.getIndexByID(_ref)
            if idx.isValid():
                item = idx.internalPointer()
                text = item.title()

        elif _type == PersoLetter:
            m = mainWindow().mdlPersos
            text = m.item(int(_ref), Perso.name.value).text()

        elif _type == PlotLetter:
            m = mainWindow().mdlPlots
            text = m.getPlotNameByID(_ref)

        elif _type == WorldLetter:
            m = mainWindow().mdlWorld
            text = m.itemByID(_ref).text()

        if text:
            return "<a href='{ref}'>{text}</a>".format(
                    ref=ref,
                    text=text)
        else:
            return ref
Example #2
0
def open(ref):
    """Identify ``ref`` and open it."""
    match = re.fullmatch(RegEx, ref)
    if not match:
        return

    _type = match.group(1)
    _ref = match.group(2)

    if _type == CharacterLetter:
        mw = mainWindow()
        item = mw.lstCharacters.getItemByID(_ref)

        if item:
            mw.tabMain.setCurrentIndex(mw.TabPersos)
            mw.lstCharacters.setCurrentItem(item)
            return True

        print("Error: Ref {} not found".format(ref))
        return False

    elif _type == TextLetter:
        mw = mainWindow()
        index = mw.mdlOutline.getIndexByID(_ref)

        if index.isValid():
            mw.tabMain.setCurrentIndex(mw.TabRedac)
            mw.mainEditor.setCurrentModelIndex(index, newTab=True)
            return True
        else:
            print("Ref not found")
            return False

    elif _type == PlotLetter:
        mw = mainWindow()
        item = mw.lstPlots.getItemByID(_ref)

        if item:
            mw.tabMain.setCurrentIndex(mw.TabPlots)
            mw.lstPlots.setCurrentItem(item)
            return True

        print("Ref not found")
        return False

    elif _type == WorldLetter:
        mw = mainWindow()
        item = mw.mdlWorld.itemByID(_ref)

        if item:
            mw.tabMain.setCurrentIndex(mw.TabWorld)
            mw.treeWorld.setCurrentIndex(
                    mw.mdlWorld.indexFromItem(item))
            return True

        print("Ref not found")
        return False

    print("Ref not implemented")
    return False
Example #3
0
    def addCharacterInfo(self, ID):
        c = self.getCharacterByID(ID)
        self.beginInsertRows(c.index(), len(c.infos), len(c.infos))
        c.infos.append(CharacterInfo(c, description="Description", value="Value"))
        self.endInsertRows()

        mainWindow().updatePersoInfoView()
Example #4
0
 def output(self, settingsWidget):
     settings = settingsWidget.getSettings()
     try:
         return self.concatenate(mainWindow().mdlOutline.rootItem, settings)
     except re.error as e:
         QMessageBox.warning(mainWindow().dialog, qApp.translate("Export", "Error"),
                             qApp.translate("Export", "Error processing regular expression : \n{}").format(str(e)))
         return ""
Example #5
0
 def setAppFontSize(self, val):
     """
     Set application default font point size.
     """
     f = qApp.font()
     f.setPointSize(val)
     qApp.setFont(f)
     mainWindow().setFont(f)
     sttgs = QSettings(qApp.organizationName(), qApp.applicationName())
     sttgs.setValue("appFontSize", val)
 def choseCharacterColor(self):
     ID = self.currentCharacterID()
     c = self._model.getCharacterByID(ID)
     if c:
         color = iconColor(c.icon)
     else:
         color = Qt.white
     self.colorDialog = QColorDialog(color, mainWindow())
     color = self.colorDialog.getColor(color)
     if color.isValid():
         c.setColor(color)
         mainWindow().updateCharacterColor(ID)
Example #7
0
    def updateAllWidgets(self):

        # Update font and defaultBlockFormat to all textEditView. Drastically.
        for w in mainWindow().findChildren(textEditView, QRegExp(".*")):
            w.loadFontSettings()

        # Update background color in all tabSplitter (tabs)
        for w in mainWindow().findChildren(tabSplitter, QRegExp(".*")):
            w.updateStyleSheet()

        # Update background color in all folder text view:
        for w in mainWindow().findChildren(QWidget, QRegExp("editorWidgetFolderText")):
            w.setStyleSheet("background: {};".format(settings.textEditor["background"]))
Example #8
0
def tooltip(ref):
    """Returns a tooltip in HTML for the reference ``ref``."""
    match = re.fullmatch(RegEx, ref)

    if not match:
        return qApp.translate("references", "Not a reference: {}.").format(ref)

    _type = match.group(1)
    _ref = match.group(2)

    if _type == TextLetter:
        m = mainWindow().mdlOutline
        idx = m.getIndexByID(_ref)

        if not idx.isValid():
            return qApp.translate("references", "Unknown reference: {}.").format(ref)

        item = idx.internalPointer()

        if item.isFolder():
            tt = qApp.translate("references", "Folder: <b>{}</b>").format(item.title())
        else:
            tt = qApp.translate("references", "Text: <b>{}</b>").format(item.title())
        tt += "<br><i>{}</i>".format(item.path())

        return tt

    elif _type == PersoLetter:
        m = mainWindow().mdlPersos
        item = m.item(int(_ref), Perso.name.value)
        if item:
            return qApp.translate("references", "Character: <b>{}</b>").format(item.text())

    elif _type == PlotLetter:
        m = mainWindow().mdlPlots
        name = m.getPlotNameByID(_ref)
        if name:
            return qApp.translate("references", "Plot: <b>{}</b>").format(name)

    elif _type == WorldLetter:
        m = mainWindow().mdlWorld
        item = m.itemByID(_ref)
        if item:
            name = item.text()
            path = m.path(item)
            return qApp.translate("references", "World: <b>{name}</b>{path}").format(
                    name=name,
                    path=" <span style='color:gray;'>({})</span>".format(path) if path else "")

    return qApp.translate("references", "<b>Unknown reference:</b> {}.").format(ref)
Example #9
0
    def convert(self, src, args, outputfile=None):
        args = [self.cmd] + args

        if outputfile:
            args.append("--output={}".format(outputfile))

        for name, col, var in [
            ("Title", 0, "title"),
            ("Subtitle", 1, "subtitle"),
            ("Serie", 2, ""),
            ("Volume", 3, ""),
            ("Genre", 4, ""),
            ("License", 5, ""),
            ("Author", 6, "author"),
            ("Email", 7, ""),
            ]:
            item = mainWindow().mdlFlatData.item(0, col)
            if var and item and item.text().strip():
                args.append("--variable={}:{}".format(var, item.text().strip()))

        # Add title metatadata required for pandoc >= 2.x
        args.append("--metadata=title:{}".format(mainWindow().mdlFlatData.item(0, 0).text().strip()))

        qApp.setOverrideCursor(QCursor(Qt.WaitCursor))

        p = subprocess.Popen(
            args,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE
        )

        if not type(src) == bytes:
            src = src.encode("utf-8")  # assumes utf-8

        stdout, stderr = p.communicate(src)

        qApp.restoreOverrideCursor()

        if stderr or p.returncode != 0:
            err = "ERROR on export" + "\n" \
                + "Return code" + ": %d\n" % (p.returncode) \
                + "Command and parameters" + ":\n%s\n" % (p.args) \
                + "Stderr content" + ":\n" + stderr.decode("utf-8") 
            print(err)
            QMessageBox.critical(mainWindow().dialog, qApp.translate("Export", "Error"), err)
            return None

        return stdout.decode("utf-8")
Example #10
0
    def doCompile(self, filename):
        mw = mainWindow()
        root = mw.mdlOutline.rootItem

        doc = QTextDocument()
        cursor = QTextCursor(doc)

        def appendItem(item):
            if item.isFolder():

                cursor.setPosition(doc.characterCount() - 1)
                title = "<h{l}>{t}</h{l}><br>\n".format(
                        l=str(item.level() + 1),
                        t=item.title())
                cursor.insertHtml(title)

                for c in item.children():
                    appendItem(c)

            else:
                text = self.formatText(item.text(), item.type())
                cursor.setPosition(doc.characterCount() - 1)
                cursor.insertHtml(text)

        for c in root.children():
            appendItem(c)

        dw = QTextDocumentWriter(filename, "odt")
        dw.write(doc)
Example #11
0
    def doCompile(self, path):
        # FIXME: overwrites when items have identical names
        mw = mainWindow()
        root = mw.mdlOutline.rootItem

        def writeItem(item, path):
            if item.isFolder():
                path2 = os.path.join(path, item.title())

                try:
                    os.mkdir(path2)
                except FileExistsError:
                    pass

                for c in item.children():
                    writeItem(c, path2)

            else:
                ext = ".t2t" if item.isT2T() else \
                    ".html" if item.isHTML() else \
                        ".txt"
                path2 = os.path.join(path, item.title() + ext)
                f = open(path2, "w")
                text = self.formatText(item.text(), item.type())
                f.write(text)

        for c in root.children():
            writeItem(c, path)
Example #12
0
def saveProject():
    """
    Saves the whole project. Call this function to save the project in Version 0 format.
    """

    files = []
    mw = mainWindow()

    files.append((saveStandardItemModelXML(mw.mdlFlatData),
                  "flatModel.xml"))
    print("ERROR: file format 0 does not save characters !")
    # files.append((saveStandardItemModelXML(mw.mdlCharacter),
    #               "perso.xml"))
    files.append((saveStandardItemModelXML(mw.mdlWorld),
                  "world.xml"))
    files.append((saveStandardItemModelXML(mw.mdlLabels),
                  "labels.xml"))
    files.append((saveStandardItemModelXML(mw.mdlStatus),
                  "status.xml"))
    files.append((saveStandardItemModelXML(mw.mdlPlots),
                  "plots.xml"))
    files.append((mw.mdlOutline.saveToXML(),
                  "outline.xml"))
    files.append((settings.save(),
                  "settings.pickle"))

    saveFilesToZip(files, mw.currentProject)
Example #13
0
    def itemContains(self, text, columns, mainWindow=mainWindow(), caseSensitive=False):
        lst = []
        text = text.lower() if not caseSensitive else text
        for c in columns:

            if c == Outline.POV.value and self.POV():
                c = mainWindow.mdlCharacter.getCharacterByID(self.POV())
                if c:
                    searchIn = c.name()
                else:
                    searchIn = ""
                    print("Character POV not found:", self.POV())

            elif c == Outline.status.value:
                searchIn = mainWindow.mdlStatus.item(toInt(self.status()), 0).text()

            elif c == Outline.label.value:
                searchIn = mainWindow.mdlLabels.item(toInt(self.label()), 0).text()

            else:
                searchIn = self.data(c)

            searchIn = searchIn.lower() if not caseSensitive else searchIn

            if text in searchIn:
                if not self.ID() in lst:
                    lst.append(self.ID())

        return lst
Example #14
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.setupUi(self)
        self._updating = False

        self.mw = mainWindow()
        self.tab.tabCloseRequested.connect(self.closeTab)
        self.tab.currentChanged.connect(self.tabChanged)

        # UI
        try:
            self.tab.setTabBarAutoHide(True)
        except AttributeError:
            print("Info: install Qt 5.4 or higher to use tabbar auto-hide in editor.")

        # Connections --------------------------------------------------------

        self.sldCorkSizeFactor.valueChanged.connect(
                self.setCorkSizeFactor, AUC)
        self.btnRedacFolderCork.toggled.connect(
                self.sldCorkSizeFactor.setVisible, AUC)
        self.btnRedacFolderText.clicked.connect(
                lambda v: self.setFolderView("text"), AUC)
        self.btnRedacFolderCork.clicked.connect(
                lambda v: self.setFolderView("cork"), AUC)
        self.btnRedacFolderOutline.clicked.connect(
                lambda v: self.setFolderView("outline"), AUC)

        self.btnRedacFullscreen.clicked.connect(
                self.showFullScreen, AUC)
Example #15
0
 def callMainTreeView(self, functionName):
     """
     The tree view in main window must have same index as the text
     edit that has focus. So we can pass it the call for documents
     edits like: duplicate, move up, etc.
     """
     if self._index and self._column == Outline.text:
         function = getattr(F.mainWindow().treeRedacOutline, functionName)
         function()
Example #16
0
    def updateStatusBar(self):
        # Update progress
        # if self.currentIndex and self.currentIndex.isValid():
        # if self._model:
        mw = mainWindow()
        if not mw:
            return

        mw.mainEditor.updateStats()
Example #17
0
def MW():
    """
    Returns the mainWindow
    """
    from manuskript import functions as F
    MW = F.mainWindow()
    assert MW is not None
    assert MW == F.MW

    return MW
Example #18
0
def test_mainWindow():

    from PyQt5.QtWidgets import QWidget, QLCDNumber

    assert F.mainWindow() is not None
    assert F.MW is not None

    F.statusMessage("Test")
    F.printObjects()
    assert len(F.findWidgetsOfClass(QWidget)) > 0
    assert len(F.findWidgetsOfClass(QLCDNumber)) == 0
Example #19
0
    def findItemsContaining(self, text, columns, mainWindow=mainWindow(), caseSensitive=False, recursive=True):
        """Returns a list if IDs of all subitems
        containing ``text`` in columns ``columns``
        (being a list of int).
        """
        lst = self.itemContains(text, columns, mainWindow, caseSensitive)

        if recursive:
            for c in self.children():
                lst.extend(c.findItemsContaining(text, columns, mainWindow, caseSensitive))

        return lst
Example #20
0
def loadProject(project):

    files = loadFilesFromZip(project)
    mw = mainWindow()

    errors = []

    if "flatModel.xml" in files:
        loadStandardItemModelXML(mw.mdlFlatData,
                                 files["flatModel.xml"], fromString=True)
    else:
        errors.append("flatModel.xml")

    if "perso.xml" in files:
        loadStandardItemModelXMLForCharacters(mw.mdlCharacter, files["perso.xml"])
    else:
        errors.append("perso.xml")

    if "world.xml" in files:
        loadStandardItemModelXML(mw.mdlWorld,
                                 files["world.xml"], fromString=True)
    else:
        errors.append("world.xml")

    if "labels.xml" in files:
        loadStandardItemModelXML(mw.mdlLabels,
                                 files["labels.xml"], fromString=True)
    else:
        errors.append("labels.xml")

    if "status.xml" in files:
        loadStandardItemModelXML(mw.mdlStatus,
                                 files["status.xml"], fromString=True)
    else:
        errors.append("status.xml")

    if "plots.xml" in files:
        loadStandardItemModelXML(mw.mdlPlots,
                                 files["plots.xml"], fromString=True)
    else:
        errors.append("plots.xml")

    if "outline.xml" in files:
        mw.mdlOutline.loadFromXML(files["outline.xml"], fromString=True)
    else:
        errors.append("outline.xml")

    if "settings.pickle" in files:
        settings.load(files["settings.pickle"], fromString=True)
    else:
        errors.append("settings.pickle")

    return errors
Example #21
0
def launch(app, MW = None):
    if MW is None:
        from manuskript.functions import mainWindow
        MW = mainWindow()

    MW.show()

    # Support for IPython Jupyter QT Console as a debugging aid.
    # Last argument must be --console to enable it
    # Code reference : 
    # https://github.com/ipython/ipykernel/blob/master/examples/embedding/ipkernel_qtapp.py
    # https://github.com/ipython/ipykernel/blob/master/examples/embedding/internal_ipkernel.py
    if len(sys.argv) > 1 and sys.argv[-1] == "--console":
        try:
            from IPython.lib.kernel import connect_qtconsole
            from ipykernel.kernelapp import IPKernelApp
            # Only to ensure matplotlib QT mainloop integration is available
            import matplotlib

            # Create IPython kernel within our application
            kernel = IPKernelApp.instance()
            
            # Initialize it and use matplotlib for main event loop integration with QT
            kernel.initialize(['python', '--matplotlib=qt'])

            # Create the console in a new process and connect
            console = connect_qtconsole(kernel.abs_connection_file, profile=kernel.profile)

            # Export MW and app variable to the console's namespace
            kernel.shell.user_ns['MW'] = MW
            kernel.shell.user_ns['app'] = app
            kernel.shell.user_ns['kernel'] = kernel
            kernel.shell.user_ns['console'] = console

            # When we close manuskript, make sure we close the console process and stop the
            # IPython kernel's mainloop, otherwise the app will never finish.
            def console_cleanup():
                app.quit()
                console.kill()
                kernel.io_loop.stop()
            app.lastWindowClosed.connect(console_cleanup)

            # Very important, IPython-specific step: this gets GUI event loop
            # integration going, and it replaces calling app.exec_()
            kernel.start()
        except Exception as e:
            print("Console mode requested but error initializing IPython : %s" % str(e))
            print("To make use of the Interactive IPython QT Console, make sure you install : ")
            print("$ pip3 install ipython qtconsole matplotlib")
            qApp.exec_()
    else:
        qApp.exec_()
    qApp.deleteLater()
Example #22
0
    def setModels(self):
        mw = mainWindow()
        self.outlineModel = mw.mdlOutline
        self.persoModel = mw.mdlPersos
        self.plotModel = mw.mdlPlots
        self.worldModel = mw.mdlWorld

        self.outlineModel.dataChanged.connect(self.populateTimer.start)
        self.persoModel.dataChanged.connect(self.populateTimer.start)
        self.plotModel.dataChanged.connect(self.populateTimer.start)
        self.worldModel.dataChanged.connect(self.populateTimer.start)

        self.populate()
Example #23
0
    def removeCharacterInfo(self, ID):
        c = self.getCharacterByID(ID)

        rm = []
        for idx in mainWindow().tblPersoInfos.selectedIndexes():
            if not idx.row() in rm:
                rm.append(idx.row())

        rm.sort()
        rm.reverse()
        for r in rm:
            self.beginRemoveRows(c.index(), r, r)
            c.infos.pop(r)
            self.endRemoveRows()
Example #24
0
 def __init__(self, parent):
     QWidget.__init__(self, parent)
     self.setupUi(self)
     self.currentIndex = QModelIndex()
     self.currentID = None
     self.txtEdits = []
     self.scroll.setBackgroundRole(QPalette.Base)
     self.toggledSpellcheck.connect(self.txtRedacText.toggleSpellcheck, AUC)
     self.dictChanged.connect(self.txtRedacText.setDict, AUC)
     self.txtRedacText.setHighlighting(True)
     self.currentDict = ""
     self.spellcheck = True
     self.folderView = "cork"
     self.mw = mainWindow()
Example #25
0
def listReferences(ref, title=qApp.translate("references", "Referenced in:")):
    oM = mainWindow().mdlOutline
    listRefs = ""

    lst = findReferencesTo(ref)

    for t in lst:
        idx = oM.getIndexByID(t)
        listRefs += "<li><a href='{link}'>{text}</a></li>".format(
                link=textReference(t),
                text=oM.data(idx, Outline.title))

    return "<h2>{title}</h2><ul>{ref}</ul>".format(
            title=title,
            ref=listRefs) if listRefs else ""
Example #26
0
    def updateListFromData(self):
        data = mainWindow().cheatSheet.data
        self.list.clear()
        for cat in data:
            filtered = [i for i in data[cat] if self.text.text().lower() in i[0].lower()]
            if filtered:
                self.addCategory(cat[0])
                for item in filtered:
                    i = QListWidgetItem(item[0])
                    i.setData(Qt.UserRole, Ref.EmptyRef.format(cat[1], item[1], item[0]))
                    i.setData(Qt.UserRole + 1, item[2])
                    self.list.addItem(i)

        self.list.setCurrentRow(1)
        self.text.setFocus(Qt.PopupFocusReason)
Example #27
0
    def setModels(self):
        mw = mainWindow()
        self.outlineModel = mw.mdlOutline
        self.characterModel = mw.mdlCharacter
        self.plotModel = mw.mdlPlots
        self.worldModel = mw.mdlWorld

        self.outlineModel.dataChanged.connect(self.populateTimer.start)
        self.characterModel.dataChanged.connect(self.populateTimer.start)
        self.characterModel.rowsInserted.connect(self.populateTimer.start)
        self.characterModel.rowsRemoved.connect(self.populateTimer.start)
        self.plotModel.dataChanged.connect(self.populateTimer.start)
        self.worldModel.dataChanged.connect(self.populateTimer.start)

        self.populate()
Example #28
0
    def restoreOpenIndexes(self, openIndexes):

        try:
            if openIndexes[1]:
                self.split(state=openIndexes[0])

            for i in openIndexes[1]:
                idx = mainWindow().mdlOutline.getIndexByID(i)
                self.mainEditor.setCurrentModelIndex(idx, newTab=True)

            if openIndexes[2]:
                self.focusTab = 2
                self.secondTab.restoreOpenIndexes(openIndexes[2])

        except:
            # Cannot load open indexes. Let's simply open root.
            self.mainEditor.setCurrentModelIndex(QModelIndex(), newTab=True)
Example #29
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.setupUi(self)

        self.template = []

        self.mw = mainWindow()
        self.btnOpen.clicked.connect(self.openFile)
        self.btnCreate.clicked.connect(self.createFile)
        self.chkLoadLastProject.toggled.connect(self.setAutoLoad)
        self.tree.itemClicked.connect(self.changeTemplate)
        self.btnAddLevel.clicked.connect(self.templateAddLevel)
        self.btnAddWC.clicked.connect(self.templateAddWordCount)
        self.btnCreateText = self.btnCreate.text()

        self.populateTemplates()
        self._templates = self.templates()
Example #30
0
def findReferencesTo(ref, parent=None, recursive=True):
    """List of text items containing references ref, and returns IDs.
    Starts from item parent. If None, starts from root."""
    oM = mainWindow().mdlOutline

    if parent == None:
        parent = oM.rootItem

    # Removes everything after the second ':': '{L:ID:random text}' → '{L:ID:'
    ref = ref[:ref.index(":", ref.index(":") + 1)+1]

    # Bare form '{L:ID}'
    ref2 = ref[:-1] + "}"

    # Since it's a simple search (no regex), we search for both.
    lst = parent.findItemsContaining(ref, [Outline.notes], recursive=recursive)
    lst += parent.findItemsContaining(ref2, [Outline.notes], recursive=recursive)

    return lst
Example #31
0
    def setView(self):
        # index = mainWindow().treeRedacOutline.currentIndex()

        # Couting the number of other selected items
        # sel = []
        # for i in mainWindow().treeRedacOutline.selectionModel().selection().indexes():
        # if i.column() != 0: continue
        # if i not in sel: sel.append(i)

        # if len(sel) != 0:
        # item = index.internalPointer()
        # else:
        # index = QModelIndex()
        # item = self.mw.mdlOutline.rootItem

        # self.currentIndex = index

        if self.currentIndex.isValid():
            item = self.currentIndex.internalPointer()
        else:
            item = self.mw.mdlOutline.rootItem

        self.updateTabTitle()

        def addTitle(itm):
            edt = textEditView(self,
                               html="<h{l}>{t}</h{l}>".format(l=min(
                                   itm.level() + 1, 5),
                                                              t=itm.title()),
                               autoResize=True)
            edt.setFrameShape(QFrame.NoFrame)
            self.txtEdits.append(edt)
            l.addWidget(edt)

        def addLine():
            line = QFrame(self.text)
            line.setFrameShape(QFrame.HLine)
            line.setFrameShadow(QFrame.Sunken)
            l.addWidget(line)

        def addText(itm):
            edt = textEditView(self,
                               index=itm.index(),
                               spellcheck=self.spellcheck,
                               dict=settings.dict,
                               highlighting=True,
                               autoResize=True)
            edt.setFrameShape(QFrame.NoFrame)
            edt.setStatusTip("{}".format(itm.path()))
            self.toggledSpellcheck.connect(edt.toggleSpellcheck, AUC)
            self.dictChanged.connect(edt.setDict, AUC)
            # edt.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
            self.txtEdits.append(edt)
            l.addWidget(edt)

        def addChildren(itm):
            for c in range(itm.childCount()):
                child = itm.child(c)

                if child.isFolder():
                    addTitle(child)
                    addChildren(child)

                else:
                    addText(child)
                    addLine()

        def addSpacer():
            l.addItem(
                QSpacerItem(10, 1000, QSizePolicy.Minimum,
                            QSizePolicy.Expanding))

            # Display multiple selected items
            # if len(sel) > 1 and False:  # Buggy and not very useful, skip
            # self.stack.setCurrentIndex(1)
            # w = QWidget()
            # l = QVBoxLayout(w)
            # self.txtEdits = []
            # for idx in sel:
            # sItem = idx.internalPointer()
            # addTitle(sItem)
            # if sItem.isFolder():
            # addChildren(sItem)
            # else:
            # addText(sItem)
            # addLine()
            # addSpacer()
            # self.scroll.setWidget(w)

        if item and item.isFolder() and self.folderView == "text":
            self.stack.setCurrentIndex(1)
            w = QWidget()
            w.setObjectName("editorWidgetFolderText")
            l = QVBoxLayout(w)
            w.setStyleSheet("background: {};".format(
                settings.textEditor["background"]))
            # self.scroll.setWidgetResizable(False)

            self.txtEdits = []

            if item != self.mw.mdlOutline.rootItem:
                addTitle(item)

            addChildren(item)
            addSpacer()
            self.scroll.setWidget(w)

        elif item and item.isFolder() and self.folderView == "cork":
            self.stack.setCurrentIndex(2)
            self.corkView.setModel(self.mw.mdlOutline)
            self.corkView.setRootIndex(self.currentIndex)
            try:
                self.corkView.selectionModel().selectionChanged.connect(
                    mainWindow().redacMetadata.selectionChanged, AUC)
                self.corkView.clicked.connect(
                    mainWindow().redacMetadata.selectionChanged, AUC)
                self.corkView.clicked.connect(
                    mainWindow().mainEditor.updateTargets, AUC)
            except TypeError:
                pass

        elif item and item.isFolder() and self.folderView == "outline":
            self.stack.setCurrentIndex(3)
            self.outlineView.setModelCharacters(mainWindow().mdlCharacter)
            self.outlineView.setModelLabels(mainWindow().mdlLabels)
            self.outlineView.setModelStatus(mainWindow().mdlStatus)
            self.outlineView.setModel(self.mw.mdlOutline)
            self.outlineView.setRootIndex(self.currentIndex)

            try:
                self.outlineView.selectionModel().selectionChanged.connect(
                    mainWindow().redacMetadata.selectionChanged, AUC)
                self.outlineView.clicked.connect(
                    mainWindow().redacMetadata.selectionChanged, AUC)
                self.outlineView.clicked.connect(
                    mainWindow().mainEditor.updateTargets, AUC)
            except TypeError:
                pass

        if item and item.isText():
            self.txtRedacText.setCurrentModelIndex(self.currentIndex)
            self.stack.setCurrentIndex(0)  # Single text item
        else:
            self.txtRedacText.setCurrentModelIndex(QModelIndex())

        try:
            self.mw.mdlOutline.dataChanged.connect(self.modelDataChanged, AUC)
            self.mw.mdlOutline.rowsInserted.connect(self.updateIndexFromID,
                                                    AUC)
            self.mw.mdlOutline.rowsRemoved.connect(self.updateIndexFromID, AUC)
            #self.mw.mdlOutline.rowsAboutToBeRemoved.connect(self.rowsAboutToBeRemoved, AUC)
        except TypeError:
            pass

        self.updateStatusBar()
Example #32
0
    def __init__(self, _format, parent=None):
        QWidget.__init__(self, parent)
        self.setupUi(self)
        self.toolBox.setStyleSheet(S.toolBoxSS())

        self.mw = mainWindow()
        self._format = _format
        self.settings = {}

        #################################################################
        # Content

        self.grpContentFilters.button.setChecked(False)

        h = self.tblContent.horizontalHeader()
        h.setSectionResizeMode(h.ResizeToContents)
        h.setSectionResizeMode(0, h.Stretch)

        self.contentUpdateTable()
        self.chkContentMore.toggled.connect(self.contentTableToggle)
        self.contentTableToggle(False)

        # Labels
        self.lstContentLabels.clear()
        h = QFontMetrics(self.font()).height()
        for i in range(0, self.mw.mdlLabels.rowCount()):
            item = self.mw.mdlLabels.item(i, 0)
            if item:
                item = QListWidgetItem(item.icon(), item.text())
                item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
                item.setCheckState(Qt.Checked)
                item.setSizeHint(QSize(100, h))
                self.lstContentLabels.addItem(item)

        self.chkContentLabels.toggled.connect(self.lstContentLabels.setVisible)
        self.chkContentLabels.toggled.connect(lambda: self.listWidgetAdjustToContent(self.lstContentLabels))
        self.lstContentLabels.setVisible(False)

        # Status
        self.lstContentStatus.clear()
        h = QFontMetrics(self.font()).height()
        for i in range(0, self.mw.mdlStatus.rowCount()):
            item = self.mw.mdlStatus.item(i, 0)
            if item:
                item = QListWidgetItem(item.icon(), item.text())
                item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
                item.setCheckState(Qt.Checked)
                item.setSizeHint(QSize(100, h))
                self.lstContentStatus.addItem(item)

        self.chkContentStatus.toggled.connect(self.lstContentStatus.setVisible)
        self.chkContentStatus.toggled.connect(lambda: self.listWidgetAdjustToContent(self.lstContentStatus))
        self.lstContentStatus.setVisible(False)

        # Root item
        self.cmbContentParent.setModel(self.mw.mdlOutline)
        v = QTreeView()
        self.cmbContentParent.setView(v)
        v.setHeaderHidden(True)
        for i in range(1, self.mw.mdlOutline.columnCount()):
            v.hideColumn(i)
        self.chkContentParent.toggled.connect(self.cmbContentParent.setVisible)
        self.cmbContentParent.hide()

        #################################################################
        # Separations

        for cmb in [self.cmbSepFF, self.cmbSepTT, self.cmbSepFT, self.cmbSepTF]:
            cmb.clear()

            cmb.addItem(self.tr("Empty line"), "empty")
            cmb.addItem(self.tr("Custom"), "custom")
            cmb.currentIndexChanged.connect(self.sepCmbChanged)

        #################################################################
        # Transformations

        h = self.tblReplacements.horizontalHeader()
        h.setSectionResizeMode(h.ResizeToContents)
        h.setSectionResizeMode(1, h.Stretch)
        h.setSectionResizeMode(2, h.Stretch)

        # Cf. https://en.wikipedia.org/wiki/Quotation_mark
        self.cmbTransDoubleQuotes.clear()
        self.cmbTransDoubleQuotes.addItems(["”___“", "“___”", "«___»"])
        self.cmbTransSingleQuote.clear()
        self.cmbTransSingleQuote.addItems(["‘___’", "‹___›"])

        for cmb in [self.cmbTransDoubleQuotes, self.cmbTransSingleQuote]:
            cmb.addItem(self.tr("Custom"), "custom")
            cmb.currentIndexChanged.connect(self.transCmbChanged)
            cmb.currentIndexChanged.emit(0)

        self.btnTransAdd.clicked.connect(lambda: self.transAddTableRow(checked=True))
        self.btnTransRemove.clicked.connect(self.transRemoveTableRow)
        self.tableWidgetAdjustToContent(self.tblReplacements)

        #################################################################
        # Preview

        self.cmbPreviewFont.setCurrentFont(self.font())
        self.spnPreviewSize.setValue(self.font().pointSize())

        #################################################################
        # Final stuff

        self.toolBox.setCurrentIndex(0)
Example #33
0
def load(string, fromString=False, protocol=None):
    """Load settings from 'string'. 'string' is the filename of the pickle dump.
    If fromString=True, string is the data of the pickle dumps."""
    global allSettings

    if not fromString:
        try:
            f = open(string, "rb")
            allSettings = pickle.load(f)

        except:
            print("{} doesn't exist, cannot load settings.".format(string))
            return
    else:
        if protocol == 0:
            allSettings = json.loads(string)
        else:
            allSettings = pickle.loads(string)

    #pp=pprint.PrettyPrinter(indent=4, compact=False)
    #print("Loading:")
    #pp.pprint(allSettings)

    # FIXME: use dict.update(dict) to update settings in newer versions.

    if "viewSettings" in allSettings:
        global viewSettings
        viewSettings = allSettings["viewSettings"]

        for cat, name, default in [
            ("Tree", "iconSize", 24),  # Added in 0.6.0
        ]:
            if not name in viewSettings[cat]:
                viewSettings[cat][name] = default

    if "fullscreenSettings" in allSettings:
        global fullscreenSettings
        fullscreenSettings = allSettings["fullscreenSettings"]

    if "dict" in allSettings:
        global dict
        dict = allSettings["dict"]

    if "spellcheck" in allSettings:
        global spellcheck
        spellcheck = allSettings["spellcheck"]

    if "corkSizeFactor" in allSettings:
        global corkSizeFactor
        corkSizeFactor = allSettings["corkSizeFactor"]

    if "folderView" in allSettings:
        global folderView
        folderView = allSettings["folderView"]

    if "lastTab" in allSettings:
        global lastTab
        lastTab = allSettings["lastTab"]

    if "openIndexes" in allSettings:
        global openIndexes
        openIndexes = allSettings["openIndexes"]

    if "autoSave" in allSettings:
        global autoSave
        autoSave = allSettings["autoSave"]

    if "autoSaveDelay" in allSettings:
        global autoSaveDelay
        autoSaveDelay = allSettings["autoSaveDelay"]

    if "saveOnQuit" in allSettings:
        global saveOnQuit
        saveOnQuit = allSettings["saveOnQuit"]

    if "autoSaveNoChanges" in allSettings:
        global autoSaveNoChanges
        autoSaveNoChanges = allSettings["autoSaveNoChanges"]

    if "autoSaveNoChangesDelay" in allSettings:
        global autoSaveNoChangesDelay
        autoSaveNoChangesDelay = allSettings["autoSaveNoChangesDelay"]

    if "outlineViewColumns" in allSettings:
        global outlineViewColumns
        outlineViewColumns = allSettings["outlineViewColumns"]

    if "corkBackground" in allSettings:
        global corkBackground
        corkBackground = allSettings["corkBackground"]

    if "corkStyle" in allSettings:
        global corkStyle
        corkStyle = allSettings["corkStyle"]

    if "fullScreenTheme" in allSettings:
        global fullScreenTheme
        fullScreenTheme = allSettings["fullScreenTheme"]

    if "defaultTextType" in allSettings:
        global defaultTextType
        defaultTextType = allSettings["defaultTextType"]

    if "textEditor" in allSettings:
        global textEditor
        textEditor = allSettings["textEditor"]

        added = {
            "textAlignment": 0,  # Added in 0.5.0
            "cursorWidth": 1,
            "cursorNotBlinking": False,  # Added in 0.6.0
            "maxWidth": 600,
            "marginsLR": 0,
            "marginsTB": 20,
            "backgroundTransparent": False,  # Added in 0.6.0
            "alwaysCenter": False,  # Added in 0.7.0
            "focusMode": False,
        }

        for k in added:
            if not k in textEditor: textEditor[k] = added[k]

        if textEditor["cursorNotBlinking"]:
            qApp.setCursorFlashTime(0)
        else:
            from manuskript.functions import mainWindow
            qApp.setCursorFlashTime(mainWindow()._defaultCursorFlashTime)

    if "revisions" in allSettings:
        global revisions
        revisions = allSettings["revisions"]

        # With JSON we had to convert int keys to str, and None to "null", so we roll back.
        r = {}
        for i in revisions["rules"]:
            if i == "null":
                r[None] = revisions["rules"]["null"]

            elif i == None:
                r[None] = revisions["rules"][None]

            else:
                r[int(i)] = revisions["rules"][i]

        revisions["rules"] = r

    if "frequencyAnalyzer" in allSettings:
        global frequencyAnalyzer
        frequencyAnalyzer = allSettings["frequencyAnalyzer"]

    if "viewMode" in allSettings:
        global viewMode
        viewMode = allSettings["viewMode"]

    if "saveToZip" in allSettings:
        global saveToZip
        saveToZip = allSettings["saveToZip"]

    if "dontShowDeleteWarning" in allSettings:
        global dontShowDeleteWarning
        dontShowDeleteWarning = allSettings["dontShowDeleteWarning"]
Example #34
0
 def projectPath(cls):
     return os.path.dirname(os.path.abspath(mainWindow().currentProject))
Example #35
0
def loadProject(project, zip=None):
    """
    Loads a project.
    @param project: the filename of the project to open.
    @param zip: whether the project is a zipped or not.
    @return: an array of errors, empty if None.
    """

    mw = mainWindow()
    errors = []

    ####################################################################################################################
    # Read and store everything in a dict

    log("\nLoading {} ({})".format(project, "ZIP" if zip else "not zip"))
    if zip:
        files = loadFilesFromZip(project)

        # Decode files
        for f in files:
            if f[-4:] not in [".xml", "opml"]:
                files[f] = files[f].decode("utf-8")

    else:
        # Project path
        dir = os.path.dirname(project)

        # Folder containing file: name of the project file (without .msk extension)
        folder = os.path.splitext(os.path.basename(project))[0]

        # The full path towards the folder containing files
        path = os.path.join(dir, folder, "")

        files = {}
        for dirpath, dirnames, filenames in os.walk(path):
            p = dirpath.replace(path, "")
            # Skip directories that begin with a period
            if p[:1] == ".":
                continue
            for f in filenames:
                # Skip filenames that begin with a period
                if f[:1] == ".":
                    continue
                # mode = "r" + ("b" if f[-4:] in [".xml", "opml"] else "")
                if f[-4:] in [".xml", "opml"]:
                    with open(os.path.join(dirpath, f), "rb") as fo:
                        files[os.path.join(p, f)] = fo.read()
                else:
                    with open(os.path.join(dirpath, f), "r",
                              encoding="utf8") as fo:
                        files[os.path.join(p, f)] = fo.read()

        # Saves to cache (only if we loaded from disk and not zip)
        global cache
        cache = files

        # FIXME: watch directory for changes

    # Sort files by keys
    files = OrderedDict(sorted(files.items()))

    ####################################################################################################################
    # Settings

    if "settings.txt" in files:
        settings.load(files["settings.txt"], fromString=True, protocol=0)
    else:
        errors.append("settings.txt")

    # Just to be sure
    settings.saveToZip = zip
    settings.defaultTextType = "md"

    ####################################################################################################################
    # Labels

    mdl = mw.mdlLabels
    mdl.appendRow(QStandardItem(""))  # Empty = No labels
    if "labels.txt" in files:
        log("\nReading labels:")
        for s in files["labels.txt"].split("\n"):
            if not s:
                continue

            m = re.search(r"^(.*?):\s*(.*)$", s)
            txt = m.group(1)
            col = m.group(2)
            log("* Add status: {} ({})".format(txt, col))
            icon = iconFromColorString(col)
            mdl.appendRow(QStandardItem(icon, txt))

    else:
        errors.append("labels.txt")

    ####################################################################################################################
    # Status

    mdl = mw.mdlStatus
    mdl.appendRow(QStandardItem(""))  # Empty = No status
    if "status.txt" in files:
        log("\nReading Status:")
        for s in files["status.txt"].split("\n"):
            if not s:
                continue
            log("* Add status:", s)
            mdl.appendRow(QStandardItem(s))
    else:
        errors.append("status.txt")

    ####################################################################################################################
    # Infos

    mdl = mw.mdlFlatData
    if "infos.txt" in files:
        md, body = parseMMDFile(files["infos.txt"], asDict=True)

        row = []
        for name in [
                "Title", "Subtitle", "Serie", "Volume", "Genre", "License",
                "Author", "Email"
        ]:
            row.append(QStandardItem(md.get(name, "")))

        mdl.appendRow(row)

    else:
        errors.append("infos.txt")

    ####################################################################################################################
    # Summary

    mdl = mw.mdlFlatData
    if "summary.txt" in files:
        md, body = parseMMDFile(files["summary.txt"], asDict=True)

        row = []
        for name in ["Situation", "Sentence", "Paragraph", "Page", "Full"]:
            row.append(QStandardItem(md.get(name, "")))

        mdl.appendRow(row)

    else:
        errors.append("summary.txt")

    ####################################################################################################################
    # Plots

    mdl = mw.mdlPlots
    if "plots.xml" in files:
        log("\nReading plots:")
        # xml = bytearray(files["plots.xml"], "utf-8")
        root = ET.fromstring(files["plots.xml"])

        for plot in root:
            # Create row
            row = getStandardItemRowFromXMLEnum(plot, Plot)

            # Log
            log("* Add plot: ", row[0].text())

            # Characters
            if row[Plot.characters].text():
                IDs = row[Plot.characters].text().split(",")
                item = QStandardItem()
                for ID in IDs:
                    item.appendRow(QStandardItem(ID.strip()))
                row[Plot.characters] = item

            # Subplots
            for step in plot:
                row[Plot.steps].appendRow(
                    getStandardItemRowFromXMLEnum(step, PlotStep))

            # Add row to the model
            mdl.appendRow(row)

    else:
        errors.append("plots.xml")

    ####################################################################################################################
    # World

    mdl = mw.mdlWorld
    if "world.opml" in files:
        log("\nReading World:")
        # xml = bytearray(files["plots.xml"], "utf-8")
        root = ET.fromstring(files["world.opml"])
        body = root.find("body")

        for outline in body:
            row = getOutlineItem(outline, World)
            mdl.appendRow(row)

    else:
        errors.append("world.opml")

    ####################################################################################################################
    # Characters

    mdl = mw.mdlCharacter
    log("\nReading Characters:")
    for f in [f for f in files if "characters" in f]:
        md, body = parseMMDFile(files[f])
        c = mdl.addCharacter()
        c.lastPath = f

        color = False
        for desc, val in md:

            # Base infos
            if desc in characterMap.values():
                key = [
                    key for key, value in characterMap.items() if value == desc
                ][0]
                index = c.index(key.value)
                mdl.setData(index, val)

            # Character color
            elif desc == "Color" and not color:
                c.setColor(QColor(val))
                # We remember the first time we found "Color": it is the icon color.
                # If "Color" comes a second time, it is a Character's info.
                color = True

            # Character's infos
            else:
                c.infos.append(CharacterInfo(c, desc, val))

        log("* Adds {} ({})".format(c.name(), c.ID()))

    ####################################################################################################################
    # Texts
    # We read outline form the outline folder. If revisions are saved, then there's also a revisions.xml which contains
    # everything, but the outline folder takes precedence (in cases it's been edited outside of manuskript.

    mdl = mw.mdlOutline
    log("\nReading outline:")
    paths = [f for f in files if "outline" in f]
    outline = OrderedDict()

    # We create a structure of imbricated OrderedDict to store the whole tree.
    for f in paths:
        split = f.split(os.path.sep)[1:]
        # log("* ", split)

        last = ""
        parent = outline
        parentLastPath = "outline"
        for i in split:
            if last:
                parent = parent[last]
                parentLastPath = os.path.join(parentLastPath, last)
            last = i

            if not i in parent:
                # If not last item, then it is a folder
                if i != split[-1]:
                    parent[i] = OrderedDict()

                # If file, we store it
                else:
                    parent[i] = files[f]

                # We store f to add it later as lastPath
                parent[i + ":lastPath"] = os.path.join(parentLastPath, i)

    # We now just have to recursively add items.
    addTextItems(mdl, outline)

    # Adds revisions
    if "revisions.xml" in files:
        root = ET.fromstring(files["revisions.xml"])
        appendRevisions(mdl, root)

    # Check IDS
    mdl.rootItem.checkIDs()

    return errors
Example #36
0
 def tabOpenIndexes(self):
     sel = []
     for i in range(self.tab.count()):
         sel.append(mainWindow().mdlOutline.ID(self.tab.widget(i).currentIndex))
     return sel
Example #37
0
 def openView(self, searchResult):
     mainWindow().tabMain.setCurrentIndex(mainWindow().TabSummary)
Example #38
0
    def __init__(self, parent):
        QStandardItemModel.__init__(self, 0, 3, parent)
        self.setHorizontalHeaderLabels([i.name for i in Plot])
        self.mw = mainWindow()

        self.updatePlotPersoButton()
Example #39
0
def shortInfos(ref):
    """Returns infos about reference ``ref``.
    Returns -1 if ``ref`` is not a valid reference, and None if it is valid but unknown."""
    match = re.fullmatch(RegEx, ref)

    if not match:
        return -1

    _type = match.group(1)
    _ref = match.group(2)

    infos = {}
    infos["ID"] = _ref

    if _type == TextLetter:

        infos["type"] = TextLetter

        m = mainWindow().mdlOutline
        idx = m.getIndexByID(_ref)

        if not idx.isValid():
            return None

        item = idx.internalPointer()

        if item.isFolder():
            infos["text_type"] = "folder"
        else:
            infos["text_type"] = "text"

        infos["title"] = item.title()
        infos["path"] = item.path()
        return infos

    elif _type == CharacterLetter:

        infos["type"] = CharacterLetter

        m = mainWindow().mdlCharacter
        c = m.getCharacterByID(_ref)

        if c:
            infos["title"] = c.name()
            infos["name"] = c.name()
            return infos

    elif _type == PlotLetter:

        infos["type"] = PlotLetter

        m = mainWindow().mdlPlots
        name = m.getPlotNameByID(_ref)
        if name:
            infos["title"] = name
            return infos

    elif _type == WorldLetter:

        infos["type"] = WorldLetter

        m = mainWindow().mdlWorld
        item = m.itemByID(_ref)
        if item:
            name = item.text()
            path = m.path(item)
            infos["title"] = name
            infos["path"] = path
            return infos

    return None
Example #40
0
def saveProject(zip=None):
    """
    Saves the project. If zip is False, the project is saved as a multitude of plain-text files for the most parts
    and some XML or zip? for settings and stuff.
    If zip is True, everything is saved as a single zipped file. Easier to carry around, but does not allow
    collaborative work, versioning, or third-party editing.
    @param zip: if True, saves as a single file. If False, saves as plain-text. If None, tries to determine based on
    settings.
    @return: True if successful, False otherwise.
    """
    if zip is None:
        zip = settings.saveToZip

    log("\n\nSaving to:", "zip" if zip else "folder")

    # List of files to be written
    files = []
    # List of files to be removed
    removes = []
    # List of files to be moved
    moves = []

    # MainWindow interaction things.
    mw = mainWindow()
    project = mw.currentProject

    # Sanity check (see PR-583): make sure we actually have a current project.
    if project is None:
        print(
            "Error: cannot save project because there is no current project in the UI."
        )
        return False

    # File format version
    files.append(("MANUSKRIPT", "1"))

    # General infos (book and author)
    # Saved in plain text, in infos.txt

    path = "infos.txt"
    content = ""
    for name, col in [
        ("Title", 0),
        ("Subtitle", 1),
        ("Serie", 2),
        ("Volume", 3),
        ("Genre", 4),
        ("License", 5),
        ("Author", 6),
        ("Email", 7),
    ]:
        item = mw.mdlFlatData.item(0, col)
        if item:
            val = item.text().strip()
        else:
            val = ""

        if val:
            content += "{name}:{spaces}{value}\n".format(name=name,
                                                         spaces=" " *
                                                         (15 - len(name)),
                                                         value=val)
    files.append((path, content))

    ####################################################################################################################
    # Summary
    # In plain text, in summary.txt

    path = "summary.txt"
    content = ""
    for name, col in [
        ("Situation", 0),
        ("Sentence", 1),
        ("Paragraph", 2),
        ("Page", 3),
        ("Full", 4),
    ]:
        item = mw.mdlFlatData.item(1, col)
        if item:
            val = item.text().strip()
        else:
            val = ""

        if val:
            content += formatMetaData(name, val, 12)

    files.append((path, content))

    ####################################################################################################################
    # Label & Status
    # In plain text

    for mdl, path in [(mw.mdlStatus, "status.txt"),
                      (mw.mdlLabels, "labels.txt")]:

        content = ""

        # We skip the first row, which is empty and transparent
        for i in range(1, mdl.rowCount()):
            color = ""
            if mdl.data(mdl.index(i, 0), Qt.DecorationRole) is not None:
                color = iconColor(mdl.data(mdl.index(
                    i, 0), Qt.DecorationRole)).name(QColor.HexRgb)
                color = color if color != "#ff000000" else "#00000000"

            text = mdl.data(mdl.index(i, 0))

            if text:
                content += "{name}{color}\n".format(
                    name=text,
                    color="" if color == "" else ":" + " " * (20 - len(text)) +
                    color)

        files.append((path, content))

    ####################################################################################################################
    # Characters
    # In a character folder

    path = os.path.join("characters", "{name}.txt")
    mdl = mw.mdlCharacter

    # Review characters
    for c in mdl.characters:

        # Generates file's content
        content = ""
        for m in characterMap:
            val = mdl.data(c.index(m.value)).strip()
            if val:
                content += formatMetaData(characterMap[m], val, 20)

        # Character's color:
        content += formatMetaData("Color", c.color().name(QColor.HexRgb), 20)

        # Character's infos
        for info in c.infos:
            content += formatMetaData(info.description, info.value, 20)

        # generate file's path
        cpath = path.format(name="{ID}-{slugName}".format(
            ID=c.ID(), slugName=slugify(c.name())))

        # Has the character been renamed?
        if c.lastPath and cpath != c.lastPath:
            moves.append((c.lastPath, cpath))

        # Update character's path
        c.lastPath = cpath

        files.append((cpath, content))

    ####################################################################################################################
    # Texts
    # In an outline folder

    mdl = mw.mdlOutline

    # Go through the tree
    f, m, r = exportOutlineItem(mdl.rootItem)
    files += f
    moves += m
    removes += r

    # Writes revisions (if asked for)
    if settings.revisions["keep"]:
        files.append(("revisions.xml", mdl.saveToXML()))

    ####################################################################################################################
    # World
    # Either in an XML file, or in lots of plain texts?
    # More probably text, since there might be writing done in third-party.

    path = "world.opml"
    mdl = mw.mdlWorld

    root = ET.Element("opml")
    root.attrib["version"] = "1.0"
    body = ET.SubElement(root, "body")
    addWorldItem(body, mdl)
    content = ET.tostring(root,
                          encoding="UTF-8",
                          xml_declaration=True,
                          pretty_print=True)
    files.append((path, content))

    ####################################################################################################################
    # Plots (mw.mdlPlots)
    # Either in XML or lots of plain texts?
    # More probably XML since there is not really a lot if writing to do (third-party)

    path = "plots.xml"
    mdl = mw.mdlPlots

    root = ET.Element("root")
    addPlotItem(root, mdl)
    content = ET.tostring(root,
                          encoding="UTF-8",
                          xml_declaration=True,
                          pretty_print=True)
    files.append((path, content))

    ####################################################################################################################
    # Settings
    # Saved in readable text (json) for easier versioning. But they mustn't be shared, it seems.
    # Maybe include them only if zipped?
    # Well, for now, we keep them here...

    files.append(("settings.txt", settings.save(protocol=0)))

    # We check if the file exist and we have write access. If the file does
    # not exist, we check the parent folder, because it might be a new project.
    if os.path.exists(project) and not os.access(project, os.W_OK) or \
       not os.path.exists(project) and not os.access(os.path.dirname(project), os.W_OK):
        print("Error: you don't have write access to save this project there.")
        return False

    ####################################################################################################################
    # Save to zip

    if zip:
        # project = os.path.join(
        #     os.path.dirname(project),
        #     "_" + os.path.basename(project)
        # )

        zf = zipfile.ZipFile(project, mode="w")

        for filename, content in files:
            zf.writestr(filename, content, compress_type=compression)

        zf.close()
        return True

    ####################################################################################################################
    # Save to plain text

    else:

        global cache

        # Project path
        dir = os.path.dirname(project)

        # Folder containing file: name of the project file (without .msk extension)
        folder = os.path.splitext(os.path.basename(project))[0]

        # Debug
        log("\nSaving to folder", folder)

        # If cache is empty (meaning we haven't loaded from disk), we wipe folder, just to be sure.
        if not cache:
            if os.path.exists(os.path.join(dir, folder)):
                shutil.rmtree(os.path.join(dir, folder))

        # Moving files that have been renamed
        for old, new in moves:

            # Get full path
            oldPath = os.path.join(dir, folder, old)
            newPath = os.path.join(dir, folder, new)

            # Move the old file to the new place
            try:
                os.replace(oldPath, newPath)
                log("* Renaming/moving {} to {}".format(old, new))
            except FileNotFoundError:
                # Maybe parent folder has been renamed
                pass

            # Update cache
            cache2 = {}
            for f in cache:
                f2 = f.replace(old, new)
                if f2 != f:
                    log("  * Updating cache:", f, f2)
                cache2[f2] = cache[f]
            cache = cache2

        # Writing files
        for path, content in files:
            filename = os.path.join(dir, folder, path)
            os.makedirs(os.path.dirname(filename), exist_ok=True)

            # Check if content is in cache, and write if necessary
            if path not in cache or cache[path] != content:
                log("* Writing file {} ({})".format(
                    path,
                    "not in cache" if path not in cache else "different"))
                # mode = "w" + ("b" if type(content) == bytes else "")
                if type(content) == bytes:
                    with open(filename, "wb") as f:
                        f.write(content)
                else:
                    with open(filename, "w", encoding='utf8') as f:
                        f.write(content)

                cache[path] = content

        # Removing phantoms
        for path in [p for p in cache if p not in [p for p, c in files]]:
            filename = os.path.join(dir, folder, path)
            log("* Removing", path)

            if os.path.isdir(filename):
                shutil.rmtree(filename)

            else:  # elif os.path.exists(filename)
                os.remove(filename)

            # Clear cache
            cache.pop(path, 0)

        # Removing empty directories
        for root, dirs, files in os.walk(os.path.join(dir, folder, "outline")):
            for dir in dirs:
                newDir = os.path.join(root, dir)
                try:
                    os.removedirs(newDir)
                    log("* Removing empty directory:", newDir)
                except:
                    # Directory not empty, we don't remove.
                    pass

        # Write the project file's content
        with open(project, "w", encoding='utf8') as f:
            f.write("1")  # Format number

        return True
Example #41
0
    def paint(self, p, option, index):
        # QStyledItemDelegate.paint(self, p, option, index)
        if not index.isValid():
            return

        item = index.internalPointer()
        self.updateRects(option, index)
        colors = outlineItemColors(item)

        style = qApp.style()

        def _rotate(angle):
            p.translate(self.mainRect.center())
            p.rotate(angle)
            p.translate(-self.mainRect.center())

        # Draw background
        cg = QPalette.ColorGroup(QPalette.Normal if option.state
                                 & QStyle.State_Enabled else QPalette.Disabled)
        if cg == QPalette.Normal and not option.state & QStyle.State_Active:
            cg = QPalette.Inactive

            # Selection
        if option.state & QStyle.State_Selected:
            p.save()
            p.setBrush(option.palette.brush(cg, QPalette.Highlight))
            p.setPen(Qt.NoPen)
            p.drawRoundedRect(option.rect, 12, 12)
            p.restore()

            # Stack
        if item.isFolder() and item.childCount() > 0:
            p.save()
            p.setBrush(Qt.white)
            for i in reversed(range(3)):
                p.drawRoundedRect(
                    self.itemRect.adjusted(2 * i, 2 * i, -2 * i, 2 * i), 10,
                    10)

            p.restore()

            # Background
        itemRect = self.itemRect
        p.save()
        if settings.viewSettings["Cork"]["Background"] != "Nothing":
            c = colors[settings.viewSettings["Cork"]["Background"]]
            col = mixColors(c, QColor(Qt.white), .2)
            p.setBrush(col)
        else:
            p.setBrush(Qt.white)
        pen = p.pen()
        pen.setWidth(2)
        p.setPen(pen)
        p.drawRoundedRect(itemRect, 10, 10)
        p.restore()

        # Title bar
        topRect = self.topRect
        p.save()
        if item.isFolder():
            color = QColor(Qt.darkGreen)
        else:
            color = QColor(Qt.blue).lighter(175)
        p.setPen(Qt.NoPen)
        p.setBrush(color)
        p.setClipRegion(QRegion(topRect))
        p.drawRoundedRect(itemRect, 10, 10)
        # p.drawRect(topRect)
        p.restore()

        # Label color
        if settings.viewSettings["Cork"]["Corner"] != "Nothing":
            p.save()
            color = colors[settings.viewSettings["Cork"]["Corner"]]
            p.setPen(Qt.NoPen)
            p.setBrush(color)
            p.setClipRegion(QRegion(self.labelRect))
            p.drawRoundedRect(itemRect, 10, 10)
            # p.drawRect(topRect)
            p.restore()
            p.drawLine(self.labelRect.topLeft(), self.labelRect.bottomLeft())

            # One line summary background
        lineSummary = item.data(Outline.summarySentence.value)
        fullSummary = item.data(Outline.summaryFull.value)
        if lineSummary or not fullSummary:
            m = self.margin
            r = self.mainLineRect.adjusted(-m, -m, m, m / 2)
            p.save()
            p.setPen(Qt.NoPen)
            p.setBrush(QColor("#EEE"))
            p.drawRect(r)
            p.restore()

            # Border
        p.save()
        p.setBrush(Qt.NoBrush)
        pen = p.pen()
        pen.setWidth(2)
        if settings.viewSettings["Cork"]["Border"] != "Nothing":
            col = colors[settings.viewSettings["Cork"]["Border"]]
            if col == Qt.transparent:
                col = Qt.black
            pen.setColor(col)
        p.setPen(pen)
        p.drawRoundedRect(itemRect, 10, 10)
        p.restore()

        # Draw the icon
        iconRect = self.iconRect
        mode = QIcon.Normal
        if not option.state & style.State_Enabled:
            mode = QIcon.Disabled
        elif option.state & style.State_Selected:
            mode = QIcon.Selected
        # index.data(Qt.DecorationRole).paint(p, iconRect, option.decorationAlignment, mode)
        icon = index.data(Qt.DecorationRole).pixmap(iconRect.size())
        if settings.viewSettings["Cork"]["Icon"] != "Nothing":
            color = colors[settings.viewSettings["Cork"]["Icon"]]
            colorifyPixmap(icon, color)
        QIcon(icon).paint(p, iconRect, option.decorationAlignment, mode)

        # Draw title
        p.save()
        text = index.data()
        titleRect = self.titleRect
        if text:
            if settings.viewSettings["Cork"]["Text"] != "Nothing":
                col = colors[settings.viewSettings["Cork"]["Text"]]
                if col == Qt.transparent:
                    col = Qt.black
                p.setPen(col)
            f = QFont(option.font)
            # f.setPointSize(f.pointSize() + 1)
            f.setBold(True)
            p.setFont(f)
            fm = QFontMetrics(f)
            elidedText = fm.elidedText(text, Qt.ElideRight, titleRect.width())
            p.drawText(titleRect, Qt.AlignCenter, elidedText)
        p.restore()

        # Draw the line
        bottomRect = self.bottomRect
        p.save()
        # p.drawLine(itemRect.x(), iconRect.bottom() + margin,
        # itemRect.right(), iconRect.bottom() + margin)
        p.drawLine(bottomRect.topLeft(), bottomRect.topRight())
        p.restore()

        # Lines
        if True:
            p.save()
            p.setPen(QColor("#EEE"))
            fm = QFontMetrics(option.font)
            h = fm.lineSpacing()
            l = self.mainTextRect.topLeft() + QPoint(0, h)
            while self.mainTextRect.contains(l):
                p.drawLine(l, QPoint(self.mainTextRect.right(), l.y()))
                l.setY(l.y() + h)
            p.restore()

        # Draw status
        mainRect = self.mainRect
        status = item.data(Outline.status.value)
        if status:
            it = mainWindow().mdlStatus.item(int(status), 0)
            if it != None:
                p.save()
                p.setClipRegion(QRegion(mainRect))
                f = p.font()
                f.setPointSize(f.pointSize() + 12)
                f.setBold(True)
                p.setFont(f)
                p.setPen(QColor(Qt.red).lighter(175))
                _rotate(-35)
                p.drawText(mainRect, Qt.AlignCenter, it.text())
                p.restore()

                # Draw Summary
                # One line
        if lineSummary:
            p.save()
            f = QFont(option.font)
            f.setItalic(True)
            p.setFont(f)
            fm = QFontMetrics(f)
            elidedText = fm.elidedText(lineSummary, Qt.ElideRight,
                                       self.mainLineRect.width())
            p.drawText(self.mainLineRect, Qt.AlignCenter, elidedText)
            p.restore()

            # Full summary
        if fullSummary:
            p.setFont(option.font)
            p.drawText(self.mainTextRect, Qt.TextWordWrap, fullSummary)
Example #42
0
 def output(self, settingsWidget):
     settings = settingsWidget.getSettings()
     return self.concatenate(mainWindow().mdlOutline.rootItem, settings)
Example #43
0
def infos(ref):
    """Returns a full paragraph in HTML format 
    containing detailed infos about the reference ``ref``.
    """
    match = re.fullmatch(RegEx, ref)
    if not match:
        return qApp.translate("references", "Not a reference: {}.").format(ref)

    _type = match.group(1)
    _ref = match.group(2)

    # A text or outine item
    if _type == TextLetter:
        m = mainWindow().mdlOutline
        idx = m.getIndexByID(_ref)

        if not idx.isValid():
            return qApp.translate("references",
                                  "Unknown reference: {}.").format(ref)

        item = idx.internalPointer()

        # Titles
        pathTitle = qApp.translate("references", "Path:")
        statsTitle = qApp.translate("references", "Stats:")
        POVTitle = qApp.translate("references", "POV:")
        statusTitle = qApp.translate("references", "Status:")
        labelTitle = qApp.translate("references", "Label:")
        ssTitle = qApp.translate("references", "Short summary:")
        lsTitle = qApp.translate("references", "Long summary:")
        notesTitle = qApp.translate("references", "Notes:")

        # The POV of the scene
        POV = ""
        if item.POV():
            POV = "<a href='{ref}'>{text}</a>".format(
                ref=characterReference(item.POV()),
                text=mainWindow().mdlCharacter.getCharacterByID(
                    item.POV()).name())

        # The status of the scene
        status = item.status()
        if status:
            status = mainWindow().mdlStatus.item(int(status), 0).text()
        else:
            status = ""

        # The label of the scene
        label = item.label()
        if label:
            label = mainWindow().mdlLabels.item(int(label), 0).text()
        else:
            label = ""

        # The path of the scene
        path = item.pathID()
        pathStr = []
        for _id, title in path:
            pathStr.append("<a href='{ref}'>{text}</a>".format(
                ref=textReference(_id), text=title))
        path = " > ".join(pathStr)

        # Summaries and notes
        ss = item.data(Outline.summarySentence.value)
        ls = item.data(Outline.summaryFull.value)
        notes = item.data(Outline.notes.value)

        text = """<h1>{title}</h1>
        <p><b>{pathTitle}</b> {path}</p>
        <p><b>{statsTitle}</b> {stats}<br>
            {POV}
            {status}
            {label}</p>
        {ss}
        {ls}
        {notes}
        {references}
        """.format(
            title=item.title(),
            pathTitle=pathTitle,
            path=path,
            statsTitle=statsTitle,
            stats=item.stats(),
            POV="<b>{POVTitle}</b> {POV}<br>".format(POVTitle=POVTitle,
                                                     POV=POV) if POV else "",
            status="<b>{statusTitle}</b> {status}<br>".format(
                statusTitle=statusTitle, status=status) if status else "",
            label="<b>{labelTitle}</b> {label}</p>".format(
                labelTitle=labelTitle, label=label) if label else "",
            ss="<p><b>{ssTitle}</b> {ss}</p>".format(
                ssTitle=ssTitle, ss=ss.replace("\n", "<br>"))
            if ss.strip() else "",
            ls="<p><b>{lsTitle}</b><br>{ls}</p>".format(
                lsTitle=lsTitle, ls=ls.replace("\n", "<br>"))
            if ls.strip() else "",
            notes="<p><b>{notesTitle}</b><br>{notes}</p>".format(
                notesTitle=notesTitle, notes=linkifyAllRefs(notes))
            if notes.strip() else "",
            references=listReferences(ref))

        return text

    # A character
    elif _type == CharacterLetter:
        m = mainWindow().mdlCharacter
        c = m.getCharacterByID(int(_ref))
        index = c.index()

        name = c.name()

        # Titles
        basicTitle = qApp.translate("references", "Basic infos")
        detailedTitle = qApp.translate("references", "Detailed infos")
        POVof = qApp.translate("references", "POV of:")

        # Goto (link)
        goto = qApp.translate("references", "Go to {}.")
        goto = goto.format(refToLink(ref))

        # basic infos
        basic = []
        for i in [
            (Character.motivation, qApp.translate("references",
                                                  "Motivation"), False),
            (Character.goal, qApp.translate("references", "Goal"), False),
            (Character.conflict, qApp.translate("references",
                                                "Conflict"), False),
            (Character.epiphany, qApp.translate("references",
                                                "Epiphany"), False),
            (Character.summarySentence,
             qApp.translate("references", "Short summary"), True),
            (Character.summaryPara,
             qApp.translate("references", "Longer summary"), True),
        ]:

            val = m.data(index.sibling(index.row(), i[0].value))

            if val:
                basic.append("<b>{title}:</b>{n}{val}".format(
                    title=i[1], n="\n" if i[2] else " ", val=val))
        basic = "<br>".join(basic)

        # detailed infos
        detailed = []
        for _name, _val in c.listInfos():
            detailed.append("<b>{}:</b> {}".format(_name, _val))
        detailed = "<br>".join(detailed)

        # list scenes of which it is POV
        oM = mainWindow().mdlOutline
        lst = oM.findItemsByPOV(_ref)

        listPOV = ""
        for t in lst:
            idx = oM.getIndexByID(t)
            listPOV += "<li><a href='{link}'>{text}</a></li>".format(
                link=textReference(t), text=oM.data(idx, Outline.title.value))

        text = """<h1>{name}</h1>
        {goto}
        {basicInfos}
        {detailedInfos}
        {POV}
        {references}
        """.format(name=name,
                   goto=goto,
                   basicInfos="<h2>{basicTitle}</h2>{basic}".format(
                       basicTitle=basicTitle, basic=basic) if basic else "",
                   detailedInfos="<h2>{detailedTitle}</h2>{detailed}".format(
                       detailedTitle=detailedTitle, detailed=detailed)
                   if detailed else "",
                   POV="<h2>{POVof}</h2><ul>{listPOV}</ul>".format(
                       POVof=POVof, listPOV=listPOV) if listPOV else "",
                   references=listReferences(ref))
        return text

    # A plot
    elif _type == PlotLetter:
        m = mainWindow().mdlPlots
        index = m.getIndexFromID(_ref)
        name = m.getPlotNameByID(_ref)

        # Titles
        descriptionTitle = qApp.translate("references", "Description")
        resultTitle = qApp.translate("references", "Result")
        charactersTitle = qApp.translate("references", "Characters")
        stepsTitle = qApp.translate("references", "Resolution steps")

        # Goto (link)
        goto = qApp.translate("references", "Go to {}.")
        goto = goto.format(refToLink(ref))

        # Description
        description = m.data(index.sibling(index.row(),
                                           Plot.description.value))

        # Result
        result = m.data(index.sibling(index.row(), Plot.result.value))

        # Characters
        pM = mainWindow().mdlCharacter
        item = m.item(index.row(), Plot.characters.value)
        characters = ""
        if item:
            for r in range(item.rowCount()):
                ID = item.child(r, 0).text()
                characters += "<li><a href='{link}'>{text}</a>".format(
                    link=characterReference(ID),
                    text=pM.getCharacterByID(ID).name())

        # Resolution steps
        steps = ""
        item = m.item(index.row(), Plot.steps.value)
        if item:
            for r in range(item.rowCount()):
                title = item.child(r, PlotStep.name.value).text()
                summary = item.child(r, PlotStep.summary.value).text()
                meta = item.child(r, PlotStep.meta.value).text()
                if meta:
                    meta = " <span style='color:gray;'>({})</span>".format(
                        meta)
                steps += "<li><b>{title}</b>{summary}{meta}</li>".format(
                    title=title,
                    summary=": {}".format(summary) if summary else "",
                    meta=meta if meta else "")

        text = """<h1>{name}</h1>
        {goto}
        {characters}
        {description}
        {result}
        {steps}
        {references}
        """.format(
            name=name,
            goto=goto,
            description="<h2>{title}</h2>{text}".format(title=descriptionTitle,
                                                        text=description)
            if description else "",
            result="<h2>{title}</h2>{text}".format(
                title=resultTitle, text=result) if result else "",
            characters="<h2>{title}</h2><ul>{lst}</ul>".format(
                title=charactersTitle, lst=characters) if characters else "",
            steps="<h2>{title}</h2><ul>{steps}</ul>".format(
                title=stepsTitle, steps=steps) if steps else "",
            references=listReferences(ref))
        return text

    # A World item
    elif _type == WorldLetter:
        m = mainWindow().mdlWorld
        index = m.indexByID(_ref)
        name = m.name(index)

        # Titles
        descriptionTitle = qApp.translate("references", "Description")
        passionTitle = qApp.translate("references", "Passion")
        conflictTitle = qApp.translate("references", "Conflict")

        # Goto (link)
        goto = qApp.translate("references", "Go to {}.")
        goto = goto.format(refToLink(ref))

        # Description
        description = basicFormat(m.description(index))

        # Passion
        passion = basicFormat(m.passion(index))

        # Conflict
        conflict = basicFormat(m.conflict(index))

        text = """<h1>{name}</h1>
        {goto}
        {description}
        {passion}
        {conflict}
        {references}
        """.format(name=name,
                   goto=goto,
                   description="<h2>{title}</h2>{text}".format(
                       title=descriptionTitle, text=description)
                   if description else "",
                   passion="<h2>{title}</h2>{text}".format(
                       title=passionTitle, text=passion) if passion else "",
                   conflict="<h2>{title}</h2><ul>{lst}</ul>".format(
                       title=conflictTitle, lst=conflict) if conflict else "",
                   references=listReferences(ref))
        return text

    else:
        return qApp.translate("references",
                              "Unknown reference: {}.").format(ref)
Example #44
0
    def makePopupMenu(self):
        index = self.currentIndex()
        sel = self.getSelection()
        clipboard = qApp.clipboard()

        menu = QMenu(self)

        # Get index under cursor
        pos = self.viewport().mapFromGlobal(QCursor.pos())
        mouseIndex = self.indexAt(pos)

        # Get index's title
        if mouseIndex.isValid():
            title = mouseIndex.internalPointer().title()

        elif self.rootIndex().parent().isValid():
            # mouseIndex is the background of an item, so we check the parent
            mouseIndex = self.rootIndex().parent()
            title = mouseIndex.internalPointer().title()

        else:
            title = qApp.translate("outlineBasics", "Root")

        if len(title) > 25:
            title = title[:25] + "…"

        # Open Item action
        self.actOpen = QAction(QIcon.fromTheme("go-right"),
                               qApp.translate("outlineBasics", "Open {}".format(title)),
                               menu)
        self.actOpen.triggered.connect(self.openItem)
        menu.addAction(self.actOpen)

        # Open item(s) in new tab
        if mouseIndex in sel and len(sel) > 1:
            actionTitle = qApp.translate("outlineBasics", "Open {} items in new tabs").format(len(sel))
            self._indexesToOpen = sel
        else:
            actionTitle = qApp.translate("outlineBasics", "Open {} in a new tab").format(title)
            self._indexesToOpen = [mouseIndex]

        self.actNewTab = QAction(QIcon.fromTheme("go-right"), actionTitle, menu)
        self.actNewTab.triggered.connect(self.openItemsInNewTabs)
        menu.addAction(self.actNewTab)

        menu.addSeparator()

        # Add text / folder
        self.actAddFolder = QAction(QIcon.fromTheme("folder-new"),
                                    qApp.translate("outlineBasics", "New &Folder"),
                                    menu)
        self.actAddFolder.triggered.connect(self.addFolder)
        menu.addAction(self.actAddFolder)

        self.actAddText = QAction(QIcon.fromTheme("document-new"),
                                  qApp.translate("outlineBasics", "New &Text"),
                                  menu)
        self.actAddText.triggered.connect(self.addText)
        menu.addAction(self.actAddText)

        menu.addSeparator()

        # Copy, cut, paste, duplicate
        self.actCut = QAction(QIcon.fromTheme("edit-cut"),
                              qApp.translate("outlineBasics", "C&ut"), menu)
        self.actCut.triggered.connect(self.cut)
        menu.addAction(self.actCut)

        self.actCopy = QAction(QIcon.fromTheme("edit-copy"),
                               qApp.translate("outlineBasics", "&Copy"), menu)
        self.actCopy.triggered.connect(self.copy)
        menu.addAction(self.actCopy)

        self.actPaste = QAction(QIcon.fromTheme("edit-paste"),
                                qApp.translate("outlineBasics", "&Paste"), menu)
        self.actPaste.triggered.connect(self.paste)
        menu.addAction(self.actPaste)

        # Rename / duplicate / remove items
        self.actDelete = QAction(QIcon.fromTheme("edit-delete"),
                                 qApp.translate("outlineBasics", "&Delete"),
                                 menu)
        self.actDelete.triggered.connect(self.delete)
        menu.addAction(self.actDelete)

        self.actRename = QAction(QIcon.fromTheme("edit-rename"),
                                 qApp.translate("outlineBasics", "&Rename"),
                                 menu)
        self.actRename.triggered.connect(self.rename)
        menu.addAction(self.actRename)

        menu.addSeparator()

        # POV
        self.menuPOV = QMenu(qApp.translate("outlineBasics", "Set POV"), menu)
        mw = mainWindow()
        a = QAction(QIcon.fromTheme("dialog-no"), qApp.translate("outlineBasics", "None"), self.menuPOV)
        a.triggered.connect(lambda: self.setPOV(""))
        self.menuPOV.addAction(a)
        self.menuPOV.addSeparator()

        menus = []
        for i in [qApp.translate("outlineBasics", "Main"),
                  qApp.translate("outlineBasics", "Secondary"),
                  qApp.translate("outlineBasics", "Minor")]:
            m = QMenu(i, self.menuPOV)
            menus.append(m)
            self.menuPOV.addMenu(m)

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

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

            menus[2 - imp].addAction(a)

        mpr.mapped.connect(self.setPOV)
        menu.addMenu(self.menuPOV)

        # Status
        self.menuStatus = QMenu(qApp.translate("outlineBasics", "Set Status"), menu)
        # a = QAction(QIcon.fromTheme("dialog-no"), qApp.translate("outlineBasics", "None"), self.menuStatus)
        # a.triggered.connect(lambda: self.setStatus(""))
        # self.menuStatus.addAction(a)
        # self.menuStatus.addSeparator()

        mpr = QSignalMapper(self.menuStatus)
        for i in range(mw.mdlStatus.rowCount()):
            a = QAction(mw.mdlStatus.item(i, 0).text(), self.menuStatus)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, i)
            self.menuStatus.addAction(a)
        mpr.mapped.connect(self.setStatus)
        menu.addMenu(self.menuStatus)

        # Labels
        self.menuLabel = QMenu(qApp.translate("outlineBasics", "Set Label"), menu)
        mpr = QSignalMapper(self.menuLabel)
        for i in range(mw.mdlLabels.rowCount()):
            a = QAction(mw.mdlLabels.item(i, 0).icon(),
                        mw.mdlLabels.item(i, 0).text(),
                        self.menuLabel)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, i)
            self.menuLabel.addAction(a)
        mpr.mapped.connect(self.setLabel)
        menu.addMenu(self.menuLabel)

        menu.addSeparator()

        # Custom icons
        if self.menuCustomIcons:
            menu.addMenu(self.menuCustomIcons)
        else:
            self.menuCustomIcons = QMenu(qApp.translate("outlineBasics", "Set Custom Icon"), menu)
            a = QAction(qApp.translate("outlineBasics", "Restore to default"), self.menuCustomIcons)
            a.triggered.connect(lambda: self.setCustomIcon(""))
            self.menuCustomIcons.addAction(a)
            self.menuCustomIcons.addSeparator()

            txt = QLineEdit()
            txt.textChanged.connect(self.filterLstIcons)
            txt.setPlaceholderText("Filter icons")
            txt.setStyleSheet("QLineEdit { background: transparent; border: none; }")
            act = QWidgetAction(self.menuCustomIcons)
            act.setDefaultWidget(txt)
            self.menuCustomIcons.addAction(act)

            self.lstIcons = QListWidget()
            for i in customIcons():
                item = QListWidgetItem()
                item.setIcon(QIcon.fromTheme(i))
                item.setData(Qt.UserRole, i)
                item.setToolTip(i)
                self.lstIcons.addItem(item)
            self.lstIcons.itemClicked.connect(self.setCustomIconFromItem)
            self.lstIcons.setViewMode(self.lstIcons.IconMode)
            self.lstIcons.setUniformItemSizes(True)
            self.lstIcons.setResizeMode(self.lstIcons.Adjust)
            self.lstIcons.setMovement(self.lstIcons.Static)
            self.lstIcons.setStyleSheet("background: transparent; background: none;")
            self.filterLstIcons("")
            act = QWidgetAction(self.menuCustomIcons)
            act.setDefaultWidget(self.lstIcons)
            self.menuCustomIcons.addAction(act)

            menu.addMenu(self.menuCustomIcons)

        # Disabling stuff
        if not clipboard.mimeData().hasFormat("application/xml"):
            self.actPaste.setEnabled(False)

        if len(sel) == 0:
            self.actCopy.setEnabled(False)
            self.actCut.setEnabled(False)
            self.actRename.setEnabled(False)
            self.actDelete.setEnabled(False)
            self.menuPOV.setEnabled(False)
            self.menuStatus.setEnabled(False)
            self.menuLabel.setEnabled(False)
            self.menuCustomIcons.setEnabled(False)

        if len(sel) > 1:
            self.actRename.setEnabled(False)

        return menu
Example #45
0
 def __init__(self, parent):
     QStandardItemModel.__init__(self, 0, 3, parent)
     self.mw = mainWindow()
Example #46
0
 def openNewTab(self):
     mainWindow().mainEditor.openIndexes(self._indexesToOpen, newTab=True)
Example #47
0
 def getItem(self, index):
     if index.isValid():
         return index.internalPointer()
     else:
         return mainWindow().mdlOutline.rootItem
Example #48
0
 def findItemsContaining(self, text, columns, caseSensitive=False):
     """Returns a list of IDs of all items containing ``text``
     in columns ``columns`` (being a list of int)."""
     return self.rootItem.findItemsContaining(text, columns, mainWindow(),
                                              caseSensitive)
Example #49
0
 def openView(self, searchResult):
     r = Ref.plotReference(searchResult.id())
     Ref.open(r)
     mainWindow().tabPlot.setEnabled(True)