class DialogOpenArchive(Toplevel):
    def __init__(self,
                 parent,
                 openType,
                 filesource,
                 filenames,
                 title,
                 colHeader,
                 showAltViewButton=False):
        if isinstance(parent, Cntlr):
            cntlr = parent
            parent = parent.parent  # parent is cntlrWinMain
        else:  # parent is a Toplevel dialog
            cntlr = parent.cntlr
        super(DialogOpenArchive, self).__init__(parent)
        self.parent = parent
        self.showAltViewButton = showAltViewButton
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)",
                                  parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))
        self.accepted = False

        self.transient(self.parent)

        frame = Frame(self)

        treeFrame = Frame(frame, width=500)
        vScrollbar = Scrollbar(treeFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(treeFrame, orient=HORIZONTAL)
        self.treeView = Treeview(treeFrame,
                                 xscrollcommand=hScrollbar.set,
                                 yscrollcommand=vScrollbar.set)
        self.treeView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.treeView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E, W))
        vScrollbar["command"] = self.treeView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N, S))
        treeFrame.columnconfigure(0, weight=1)
        treeFrame.rowconfigure(0, weight=1)
        treeFrame.grid(row=0,
                       column=0,
                       columnspan=4,
                       sticky=(N, S, E, W),
                       padx=3,
                       pady=3)
        self.treeView.focus_set()

        if openType not in (PLUGIN, PACKAGE):
            cntlr.showStatus(_("loading archive {0}").format(filesource.url))
        self.filesource = filesource
        self.filenames = filenames
        self.selection = filesource.selection
        self.hasToolTip = False
        selectedNode = None

        if openType == ENTRY_POINTS:
            try:
                metadataFiles = filesource.taxonomyPackageMetadataFiles
                ''' take first for now
                if len(metadataFiles) != 1:
                    raise IOError(_("Taxonomy package contained more than one metadata file: {0}.")
                                  .format(', '.join(metadataFiles)))
                '''
                metadataFile = metadataFiles[0]
                metadata = filesource.url + os.sep + metadataFile
                self.metadataFilePrefix = os.sep.join(
                    os.path.split(metadataFile)[:-1])
                if self.metadataFilePrefix:
                    self.metadataFilePrefix += "/"  # zip contents have /, never \ file seps
                self.taxonomyPkgMetaInf = '{}/META-INF/'.format(
                    os.path.splitext(os.path.basename(filesource.url))[0])

                self.taxonomyPackage = parsePackage(
                    cntlr, filesource, metadata,
                    os.sep.join(os.path.split(metadata)[:-1]) + os.sep)

                if self.taxonomyPackage["entryPoints"]:
                    # may have instance documents too
                    self.packageContainedInstances = []
                    packageContentTypeCounts = {}
                    for suffix in (".xhtml", ".htm", ".html"):
                        for potentialInstance in filesource.dir:
                            if potentialInstance.endswith(".xhtml"):
                                _type = "Inline Instance"
                                self.packageContainedInstances.append(
                                    [potentialInstance, _type])
                                packageContentTypeCounts[
                                    potentialInstance] = packageContentTypeCounts.get(
                                        potentialInstance, 0) + 1
                        if self.packageContainedInstances:
                            break
                    if self.packageContainedInstances:  # add sequences to any duplicated entry types
                        for _type, count in packageContentTypeCounts.items():
                            if count > 1:
                                _dupNo = 0
                                for i in range(
                                        len(self.packageContainedInstances)):
                                    if self.packageContainedInstances[i][
                                            0] == _type:
                                        _dupNo += 1
                                        self.packageContainedInstances[i][
                                            0] = "{} {}".format(_type, _dupNo)

                else:
                    # may be a catalog file with no entry oint names
                    openType = ARCHIVE  # no entry points to show, just archive
                    self.showAltViewButton = False
            except Exception as e:
                self.close()
                err = _(
                    "Failed to parse metadata; the underlying error was: {0}"
                ).format(e)
                messagebox.showerror(_("Malformed taxonomy package"), err)
                cntlr.addToLog(err)
                return

        if openType not in (PLUGIN, PACKAGE):
            cntlr.showStatus(None)

        if openType in (DISCLOSURE_SYSTEM, PLUGIN, PACKAGE):
            y = 3
        else:
            y = 1

        okButton = Button(frame, text=_("OK"), command=self.ok)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        okButton.grid(row=y, column=2, sticky=(S, E, W), pady=3)
        cancelButton.grid(row=y, column=3, sticky=(S, E, W), pady=3, padx=3)

        if self.showAltViewButton:
            self.altViewButton = Button(frame, command=self.showAltView)
            self.altViewButton.grid(row=y,
                                    column=0,
                                    sticky=(S, W),
                                    pady=3,
                                    padx=3)

        self.loadTreeView(openType, colHeader, title)

        self.geometry("+{0}+{1}".format(dialogX + 50, dialogY + 100))
        frame.grid(row=0, column=0, sticky=(N, S, E, W))
        frame.columnconfigure(0, weight=1)
        frame.rowconfigure(0, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        window.rowconfigure(0, weight=1)

        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)

        self.toolTipText = StringVar()
        if self.hasToolTip:
            self.treeView.bind("<Motion>", self.motion, '+')
            self.treeView.bind("<Leave>", self.leave, '+')
            self.toolTipText = StringVar()
            self.toolTip = ToolTip(self.treeView,
                                   textvariable=self.toolTipText,
                                   wraplength=640,
                                   follow_mouse=True,
                                   state="disabled")
            self.toolTipRowId = None

        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()

        self.wait_window(self)

    def loadTreeView(self, openType, title, colHeader):
        self.title(title)
        self.openType = openType
        selectedNode = None

        # clear previous treeview entries
        for previousNode in self.treeView.get_children(""):
            self.treeView.delete(previousNode)

        # set up treeView widget and tabbed pane
        if openType in (ARCHIVE, DISCLOSURE_SYSTEM, PLUGIN, PACKAGE):
            if openType in (PLUGIN, PACKAGE): width = 770
            else: width = 500
            self.treeView.column("#0", width=width, anchor="w")
            self.treeView.heading("#0", text=colHeader)
            self.isRss = getattr(self.filesource, "isRss", False)
            if self.isRss:
                self.treeView.column("#0", width=350, anchor="w")
                self.treeView["columns"] = ("descr", "date", "instDoc")
                self.treeView.column("descr",
                                     width=50,
                                     anchor="center",
                                     stretch=False)
                self.treeView.heading("descr", text="Form")
                self.treeView.column("date",
                                     width=170,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("date", text="Pub Date")
                self.treeView.column("instDoc",
                                     width=200,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("instDoc", text="Instance Document")
            elif openType == PLUGIN:
                self.treeView.column("#0", width=150, anchor="w")
                self.treeView["columns"] = ("name", "vers", "descr", "license")
                self.treeView.column("name",
                                     width=150,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("name", text="Name")
                self.treeView.column("vers",
                                     width=60,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("vers", text="Version")
                self.treeView.column("descr",
                                     width=300,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("descr", text="Description")
                self.treeView.column("license",
                                     width=60,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("license", text="License")
            elif openType == PACKAGE:
                self.treeView.column("#0", width=200, anchor="w")
                self.treeView["columns"] = ("vers", "descr", "license")
                self.treeView.column("vers",
                                     width=100,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("vers", text="Version")
                self.treeView.column("descr",
                                     width=400,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("descr", text="Description")
                self.treeView.column("license",
                                     width=70,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("license", text="License")
            else:
                self.treeView["columns"] = tuple()

            loadedPaths = []
            for i, filename in enumerate(self.filenames):
                if isinstance(filename, tuple):
                    if self.isRss:
                        form, date, instDoc = filename[2:5]
                    elif openType == PLUGIN:
                        name, vers, descr, license = filename[3:7]
                    elif openType == PACKAGE:
                        vers, descr, license = filename[3:6]
                    filename = filename[0]  # ignore tooltip
                    self.hasToolTip = True
                if filename.endswith("/"):
                    filename = filename[:-1]
                path = filename.split("/")
                if not self.isRss and len(
                        path) > 1 and path[:-1] in loadedPaths:
                    parent = "file{0}".format(loadedPaths.index(path[:-1]))
                else:
                    parent = ""
                node = self.treeView.insert(parent,
                                            "end",
                                            "file{0}".format(i),
                                            text=path[-1])
                if self.isRss:
                    self.treeView.set(node, "descr", form)
                    self.treeView.set(node, "date", date)
                    self.treeView.set(node, "instDoc",
                                      os.path.basename(instDoc))
                elif openType == PLUGIN:
                    self.treeView.set(node, "name", name)
                    self.treeView.set(node, "vers", vers)
                    self.treeView.set(node, "descr", descr)
                    self.treeView.set(node, "license", license)
                elif openType == PACKAGE:
                    self.treeView.set(node, "vers", vers)
                    self.treeView.set(node, "descr", descr)
                    self.treeView.set(node, "license", license)
                if self.selection == filename:
                    selectedNode = node
                loadedPaths.append(path)

        elif openType == ENTRY_POINTS:
            self.treeView.column("#0", width=200, anchor="w")
            self.treeView.heading("#0", text="Name")

            self.treeView["columns"] = ("url", )
            self.treeView.column("url", width=300, anchor="w")
            self.treeView.heading("url", text="URL")

            for fileType, fileUrl in getattr(self, "packageContainedInstances",
                                             ()):
                self.treeView.insert("",
                                     "end",
                                     fileUrl,
                                     values=fileType,
                                     text=fileUrl or urls[0][2])
            for name, urls in sorted(
                    self.taxonomyPackage["entryPoints"].items(),
                    key=lambda i: i[0][2]):
                self.treeView.insert("",
                                     "end",
                                     name,
                                     values="\n".join(url[1] for url in urls),
                                     text=name or urls[0][2])

            self.hasToolTip = True
        else:  # unknown openType
            return None
        if selectedNode:
            self.treeView.see(selectedNode)
            self.treeView.selection_set(selectedNode)

        if self.showAltViewButton:
            self.altViewButton.config(text=_("Show Files") if openType ==
                                      ENTRY_POINTS else _("Show Entries"))

    def ok(self, event=None):
        selection = self.treeView.selection()
        if len(selection) > 0:
            if hasattr(self, "taxonomyPackage"):
                # load file source remappings
                self.filesource.mappedPaths = self.taxonomyPackage[
                    "remappings"]
            filename = None
            if self.openType in (ARCHIVE, DISCLOSURE_SYSTEM):
                filename = self.filenames[int(selection[0][4:])]
                if isinstance(filename, tuple):
                    if self.isRss:
                        filename = filename[4]
                    else:
                        filename = filename[0]
            elif self.openType == ENTRY_POINTS:
                epName = selection[0]
                #index 0 is the remapped Url, as opposed to the canonical one used for display
                # Greg Acsone reports [0] does not work for Corep 1.6 pkgs, need [1], old style packages
                filenames = []
                for _url, _type in self.packageContainedInstances:  # check if selection was an inline instance
                    if _type == epName:
                        filenames.append(_url)
                if not filenames:  # else if it's a named taxonomy entry point
                    for url in self.taxonomyPackage["entryPoints"][epName]:
                        filename = url[0]
                        if not filename.endswith("/"):
                            # check if it's an absolute URL rather than a path into the archive
                            if not isHttpUrl(
                                    filename
                            ) and self.metadataFilePrefix != self.taxonomyPkgMetaInf:
                                # assume it's a path inside the archive:
                                filename = self.metadataFilePrefix + filename
                        filenames.append(filename)
                if filenames:
                    self.filesource.select(filenames)
                    self.accepted = True
                    self.close()
                return
            elif self.openType in (PLUGIN, PACKAGE):
                filename = self.filenames[int(selection[0][4:])][2]
            if filename is not None and not filename.endswith("/"):
                if hasattr(self, "taxonomyPackage"):
                    # attempt to unmap the filename to original file
                    # will be mapped again in loading, but this allows schemaLocation to be unmapped
                    for prefix, remapping in self.taxonomyPackage[
                            "remappings"].items():
                        if isHttpUrl(remapping):
                            remapStart = remapping
                        else:
                            remapStart = self.metadataFilePrefix + remapping
                        if filename.startswith(remapStart):
                            # set unmmapped file
                            filename = prefix + filename[len(remapStart):]
                            break
                if self.openType in (PLUGIN, PACKAGE):
                    self.filesource.selection = filename
                else:
                    self.filesource.select(filename)
                self.accepted = True
                self.close()

    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()

    def showAltView(self, event=None):
        if self.openType == ENTRY_POINTS:
            self.loadTreeView(ARCHIVE, _("Select Entry Point"), _("File"))
        else:
            self.loadTreeView(ENTRY_POINTS, _("Select Archive File"),
                              _("File"))

    def leave(self, *args):
        self.toolTipRowId = None

    def motion(self, *args):
        tvRowId = self.treeView.identify_row(args[0].y)
        if tvRowId != self.toolTipRowId:
            text = None
            if self.openType in (ARCHIVE, DISCLOSURE_SYSTEM, PLUGIN, PACKAGE):
                self.toolTipRowId = tvRowId
                if tvRowId and len(tvRowId) > 4:
                    try:
                        text = self.filenames[int(tvRowId[4:])]
                        if isinstance(text, tuple):
                            text = (text[1] or "").replace("\\n", "\n")
                    except (KeyError, ValueError):
                        pass
            elif self.openType == ENTRY_POINTS:
                try:
                    text = "{0}\n{1}".format(
                        tvRowId, "\n".join(
                            url[1] for url in
                            self.taxonomyPackage["entryPoints"][tvRowId]))
                except KeyError:
                    pass
            self.setToolTip(text)

    def setToolTip(self, text):
        self.toolTip._hide()
        if text:
            self.toolTipText.set(text)
            self.toolTip.configure(state="normal")
            self.toolTip._schedule()
        else:
            self.toolTipText.set("")
            self.toolTip.configure(state="disabled")
Exemple #2
0
class DialogOpenArchive(Toplevel):
    def __init__(self, mainWin, openType, filesource, filenames, title, colHeader):
        parent = mainWin.parent
        super().__init__(parent)
        self.parent = parent
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))
        self.accepted = False

        self.transient(self.parent)
        self.title(title)
        
        frame = Frame(self)

        treeFrame = Frame(frame, width=500)
        vScrollbar = Scrollbar(treeFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(treeFrame, orient=HORIZONTAL)
        self.treeView = Treeview(treeFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set)
        self.treeView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.treeView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.treeView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        treeFrame.columnconfigure(0, weight=1)
        treeFrame.rowconfigure(0, weight=1)
        treeFrame.grid(row=0, column=0, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.treeView.focus_set()
        
        # set up treeView widget and tabbed pane
        self.treeView.column("#0", width=500, anchor="w")
        self.treeView.heading("#0", text=colHeader)
        try:
            self.isRss = filesource.isRss
            if self.isRss:
                self.treeView.column("#0", width=350, anchor="w")
                self.treeView["columns"] = ("descr", "date", "instDoc")
                self.treeView.column("descr", width=50, anchor="center", stretch=False)
                self.treeView.heading("descr", text="Form")
                self.treeView.column("date", width=170, anchor="w", stretch=False)
                self.treeView.heading("date", text="Pub Date")
                self.treeView.column("instDoc", width=200, anchor="w", stretch=False)
                self.treeView.heading("instDoc", text="Instance Document")
        except AttributeError:
            self.isRss = False
        
        mainWin.showStatus(_("loading archive {0}").format(filesource.url))
        self.filesource = filesource
        self.filenames = filenames
        selection = filesource.selection
        hasToolTip = False
        loadedPaths = []
        i = 0
        selectedNode = None
        for filename in self.filenames:
            if isinstance(filename,tuple):
                if self.isRss:
                    form, date, instDoc = filename[2:5]
                filename = filename[0] # ignore tooltip
                hasToolTip = True
            if filename.endswith("/"):
                filename = filename[:-1]
            path = filename.split("/")
            if not self.isRss and len(path) > 1 and path[:-1] in loadedPaths:
                parent = "file{0}".format(loadedPaths.index(path[:-1]))
            else:
                parent = "" 
            node = self.treeView.insert(parent, "end", "file{0}".format(i), text=path[-1])
            if self.isRss:
                self.treeView.set(node, "descr", form)
                self.treeView.set(node, "date", date)
                self.treeView.set(node, "instDoc", os.path.basename(instDoc))
            if selection == filename:
                selectedNode = node
            loadedPaths.append(path)
            i += 1
        if selectedNode:
            self.treeView.see(selectedNode)
            self.treeView.selection_set(selectedNode)
        mainWin.showStatus(None)
        
        if openType == DISCLOSURE_SYSTEM:
            y = 3
        else:
            y = 1

        okButton = Button(frame, text=_("OK"), command=self.ok)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        okButton.grid(row=y, column=2, sticky=(S,E,W), pady=3)
        cancelButton.grid(row=y, column=3, sticky=(S,E,W), pady=3, padx=3)
        
        frame.grid(row=0, column=0, sticky=(N,S,E,W))
        frame.columnconfigure(0, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100))
        
        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)
        
        self.toolTipText = StringVar()
        if hasToolTip:
            self.treeView.bind("<Motion>", self.motion, '+')
            self.treeView.bind("<Leave>", self.leave, '+')
            self.toolTipText = StringVar()
            self.toolTip = ToolTip(self.treeView, 
                                   textvariable=self.toolTipText, 
                                   wraplength=640, 
                                   follow_mouse=True,
                                   state="disabled")
            self.toolTipRowId = None

        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        self.wait_window(self)
        
    def ok(self, event=None):
        selection = self.treeView.selection()
        if len(selection) > 0:
            filename = self.filenames[int(selection[0][4:])]
            if isinstance(filename,tuple):
                if self.isRss:
                    filename = filename[4]
                else:
                    filename = filename[0]
            if not filename.endswith("/"):
                self.filesource.select(filename)
                self.accepted = True
                self.close()
        
    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()
        
    def leave(self, *args):
        self.toolTipRowId = None

    def motion(self, *args):
        tvRowId = self.treeView.identify_row(args[0].y)
        if tvRowId != self.toolTipRowId:
            self.toolTipRowId = tvRowId
            newFileIndex = -1
            if tvRowId and len(tvRowId) > 4:
                try:
                    newFileIndex = int(tvRowId[4:])
                except ValueError:
                    pass
            self.setToolTip(newFileIndex)
                
    def setToolTip(self, fileIndex):
        self.toolTip._hide()
        if fileIndex >= 0 and fileIndex < len(self.filenames):
            filenameItem = self.filenames[fileIndex]
            if isinstance(filenameItem, tuple):
                self.toolTipText.set(filenameItem[1].replace("\\n","\n"))
                self.toolTip.configure(state="normal")
                self.toolTip._schedule()
            else:
                self.toolTipText.set("")
                self.toolTip.configure(state="disabled")
        else:
            self.toolTipText.set("")
            self.toolTip.configure(state="disabled")
Exemple #3
0
class ViewTree:
    def __init__(self, modelXbrl, tabWin, tabTitle, hasToolTip=False, lang=None):
        self.tabWin = tabWin
        self.viewFrame = Frame(tabWin)
        self.viewFrame.grid(row=0, column=0, sticky=(N, S, E, W))
        tabWin.add(self.viewFrame,text=tabTitle)
        vScrollbar = Scrollbar(self.viewFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(self.viewFrame, orient=HORIZONTAL)
        self.treeView = Treeview(self.viewFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set)
        self.treeView.grid(row=0, column=0, sticky=(N, S, E, W))
        self.treeView.tag_configure("ELR", background="#E0F0FF")
        self.treeView.tag_configure("even", background="#F0F0F0")
        self.treeView.tag_configure("odd", background="#FFFFFF")
        highlightColor = "#%04x%04x%04x" % self.treeView.winfo_rgb("SystemHighlight")
        self.treeView.tag_configure("selected-ELR", background=highlightColor)
        self.treeView.tag_configure("selected-even", background=highlightColor)
        self.treeView.tag_configure("selected-odd", background=highlightColor)
        self.treeViewSelection = ()
        self.treeView.bind("<<TreeviewSelect>>", self.treeViewSelectionChange, '+')
        hScrollbar["command"] = self.treeView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.treeView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        self.viewFrame.columnconfigure(0, weight=1)
        self.viewFrame.rowconfigure(0, weight=1)
        self.modelXbrl = modelXbrl
        self.hasToolTip = hasToolTip
        self.toolTipText = StringVar()
        if hasToolTip:
            self.treeView.bind("<Motion>", self.motion, '+')
            self.treeView.bind("<Leave>", self.leave, '+')
            self.toolTipText = StringVar()
            self.toolTip = ToolTip(self.treeView, 
                                   textvariable=self.toolTipText, 
                                   wraplength=480, 
                                   follow_mouse=True,
                                   state="disabled")
            self.toolTipColId = None
            self.toolTipRowId = None
        self.modelXbrl = modelXbrl
        self.lang = lang
        self.labelrole = None
        if modelXbrl:
            modelXbrl.views.append(self)
            if not lang: 
                self.lang = modelXbrl.modelManager.defaultLang
                
    def treeViewSelectionChange(self, event=None):
        for node in self.treeViewSelection:
            priorTags = self.treeView.item(node)["tags"]
            if priorTags:
                priorBgTag = priorTags[0]
                if priorBgTag.startswith("selected-"):
                    self.treeView.item(node, tags=(priorBgTag[9:],))
        self.treeViewSelection = self.treeView.selection()
        for node in self.treeViewSelection:
            priorTags = self.treeView.item(node)["tags"]
            if priorTags:
                self.treeView.item(node, tags=("selected-" + priorTags[0],))
            
    def close(self):
        if self.modelXbrl:
            self.tabWin.forget(self.viewFrame)
            self.modelXbrl.views.remove(self)
            self.modelXbrl = None
        
    def leave(self, *args):
        self.toolTipColId = None
        self.toolTipRowId = None

    def motion(self, *args):
        tvColId = self.treeView.identify_column(args[0].x)
        tvRowId = self.treeView.identify_row(args[0].y)
        if tvColId != self.toolTipColId or tvRowId != self.toolTipRowId:
            self.toolTipColId = tvColId
            self.toolTipRowId = tvRowId
            newValue = None
            if tvRowId and len(tvRowId) > 0:
                try:
                    col = int(tvColId[1:])
                    if col == 0:
                        newValue = self.treeView.item(tvRowId,"text")
                    else:
                        values = self.treeView.item(tvRowId,"values")
                        if col <= len(values):
                            newValue = values[col - 1]
                except ValueError:
                    pass
            self.setToolTip(newValue, tvColId)
                
    def setToolTip(self, text, colId="#0"):
        self.toolTip._hide()
        if isinstance(text,str) and len(text) > 0:
            width = self.treeView.column(colId,"width")
            if len(text) * 8 > width or '\n' in text:
                self.toolTipText.set(text)
                self.toolTip.configure(state="normal")
                self.toolTip._schedule()
            else:
                self.toolTipText.set("")
                self.toolTip.configure(state="disabled")
        else:
            self.toolTipText.set("")
            self.toolTip.configure(state="disabled")

    def contextMenu(self):
        try:
            return self.menu
        except AttributeError:
            self.menu = Menu( self.viewFrame, tearoff = 0 )
            self.treeView.bind( self.modelXbrl.modelManager.cntlr.contextMenuClick, self.popUpMenu, '+' )
            return self.menu

    def popUpMenu(self, event):
        self.menuRow = self.treeView.identify_row(event.y)
        self.menuCol = self.treeView.identify_column(event.x)
        self.menu.post( event.x_root, event.y_root )
        
    def expand(self):
        self.setTreeItemOpen(self.menuRow,open=True)
        
    def expandAll(self):
        self.setTreeItemOpen("",open=True)
        
    def collapse(self):
        self.setTreeItemOpen(self.menuRow,open=False)
        
    def collapseAll(self):
        self.setTreeItemOpen("",open=False)
        
    def setTreeItemOpen(self, node, open=True):
        if node:
            self.treeView.item(node, open=open)
        for childNode in self.treeView.get_children(node):
            self.setTreeItemOpen(childNode, open)
            
    def menuAddExpandCollapse(self):
        self.menu.add_cascade(label=_("Expand"), underline=0, command=self.expand)
        self.menu.add_cascade(label=_("Collapse"), underline=0, command=self.collapse)
        self.menu.add_cascade(label=_("Expand All"), underline=0, command=self.expandAll)
        self.menu.add_cascade(label=_("Collapse All"), underline=0, command=self.collapseAll)
        
    def menuAddClipboard(self):
        if self.modelXbrl.modelManager.cntlr.hasClipboard:
            clipboardMenu = Menu(self.viewFrame, tearoff=0)
            clipboardMenu.add_cascade(label=_("Cell"), underline=0, command=self.copyCellToClipboard)
            clipboardMenu.add_cascade(label=_("Row"), underline=0, command=self.copyRowToClipboard)
            clipboardMenu.add_cascade(label=_("Table"), underline=0, command=self.copyTableToClipboard)
            self.menu.add_cascade(label=_("Copy to clipboard"), menu=clipboardMenu, underline=0)
        
    def menuAddLangs(self):
        langsMenu = Menu(self.viewFrame, tearoff=0)
        self.menu.add_cascade(label=_("Language"), menu=langsMenu, underline=0)
        for lang in sorted(self.modelXbrl.langs):
            langsMenu.add_cascade(label=lang, underline=0, command=lambda l=lang: self.setLang(l))

    def menuAddLabelRoles(self, includeConceptName=False, menulabel=None):
        if menulabel is None: menulabel = _("Label Role")
        rolesMenu = Menu(self.viewFrame, tearoff=0)
        self.menu.add_cascade(label=menulabel, menu=rolesMenu, underline=0)
        from arelle.ModelRelationshipSet import labelroles
        for x in labelroles(self.modelXbrl, includeConceptName):
            rolesMenu.add_cascade(label=x[0][1:], underline=0, command=lambda a=x[1]: self.setLabelrole(a))

    def menuAddUnitDisplay(self):
        rolesMenu = Menu(self.viewFrame, tearoff=0)
        self.menu.add_cascade(label=_("Units"), menu=rolesMenu, underline=0)
        rolesMenu.add_cascade(label=_("Unit ID"), underline=0, command=lambda: self.setUnitDisplay(unitDisplayID=True))
        rolesMenu.add_cascade(label=_("Measures"), underline=0, command=lambda: self.setUnitDisplay(unitDisplayID=False))

    def menuAddViews(self):
        viewMenu = Menu(self.viewFrame, tearoff=0)
        self.menu.add_cascade(label=_("View"), menu=viewMenu, underline=0)
        newViewsMenu = Menu(self.viewFrame, tearoff=0)
        viewMenu.add_cascade(label=_("Close"), underline=0, command=self.close)
        viewMenu.add_cascade(label=_("Additional view"), menu=newViewsMenu, underline=0)
        from arelle.ModelRelationshipSet import baseSetArcroles
        for x in baseSetArcroles(self.modelXbrl):
            newViewsMenu.add_cascade(label=x[0][1:], underline=0, command=lambda a=x[1]: self.newView(a))
    
    def newView(self, arcrole):
        from arelle import ViewWinRelationshipSet
        ViewWinRelationshipSet.viewRelationshipSet(self.modelXbrl, self.tabWin, arcrole, lang=self.lang)
            
    def setLang(self, lang):
        self.lang = lang
        self.view()
        
    def setLabelrole(self, labelrole):
        self.labelrole = labelrole
        self.view()
        
    def setUnitDisplay(self, unitDisplayID=False):
        self.unitDisplayID = unitDisplayID
        self.view()
        
    def setColumnsSortable(self, treeColIsInt=False, startUnsorted=False, initialSortCol="#0", initialSortDirForward=True):
        self.lastSortColumn = None if startUnsorted else initialSortCol 
        self.lastSortColumnForward = initialSortDirForward
        self.treeColIsInt = treeColIsInt
        if not hasattr(self, "sortImages"):
            self.sortImages = (PhotoImage(file=os.path.join(self.modelXbrl.modelManager.cntlr.imagesDir, "columnSortUp.gif")),
                               PhotoImage(file=os.path.join(self.modelXbrl.modelManager.cntlr.imagesDir, "columnSortDown.gif")),
                               PhotoImage())
        for col in ("#0",) + self.treeView["columns"]:
            self.treeView.heading(col, command=lambda c=col: self.sortColumn(c))
        if not startUnsorted:
            self.treeView.heading(initialSortCol, image=self.sortImages[not initialSortDirForward])
            
    def colSortVal(self, node, col):
        if col == "#0":
            treeColVal = self.treeView.item(node)["text"]
            if self.treeColIsInt: 
                return int(treeColVal)
        else:
            treeColVal = self.treeView.set(node, col)
            if col == "sequence":
                try:
                    return int(treeColVal)
                except:
                    return 0
        return treeColVal
    
    def sortNestedRows(self, parentNode, col, reverse):
        l = [(self.colSortVal(node, col), node) for node in self.treeView.get_children(parentNode)]
        l.sort(reverse=reverse)
        # rearrange items in sorted positions     
        for i, (cell, node) in enumerate(l):         
            self.treeView.move(node, parentNode, i)
        # reset even/odd tags
        for i, node in enumerate(self.treeView.get_children(parentNode)):
            self.treeView.item(node, tags=('even' if i & 1 else 'odd',))
            self.sortNestedRows(node, col, reverse)
                    
    def sortColumn(self, col):
        if col == self.lastSortColumn:
            reverse = self.lastSortColumnForward
            self.lastSortColumnForward = not reverse
        else:
            if self.lastSortColumn:
                self.treeView.heading(self.lastSortColumn, image=self.sortImages[2])
            reverse = False
            self.lastSortColumnForward = True
            self.lastSortColumn = col
        self.treeView.heading(col, image=self.sortImages[reverse])
        self.sortNestedRows('', col, reverse)
        self.treeViewSelectionChange()  # reselect selected rows
        
    def copyCellToClipboard(self, *ignore):
        self.modelXbrl.modelManager.cntlr.clipboardData(
            text=self.treeView.item(self.menuRow)['text'] if self.menuCol == '#0' else self.treeView.set(self.menuRow,self.menuCol))
        
    def copyRowToClipboard(self, *ignore):
        self.modelXbrl.modelManager.cntlr.clipboardData(
            text='\t'.join([self.treeView.item(self.menuRow)['text']] +
                           [self.treeView.set(self.menuRow,c) for c in self.treeView['columns']]))
        
    def copyTableToClipboard(self, *ignore):
        cols = self.treeView['columns']
        lines = ['\t'.join([self.treeView.heading('#0')['text']] +
                           [self.treeView.heading(h)['text'] for h in cols])]
        self.tabLines('', '', cols, lines)
        self.modelXbrl.modelManager.cntlr.clipboardData(text='\n'.join(lines))

    def tabLines(self, parentNode, indent, cols, lines): 
        for node in self.treeView.get_children(parentNode):
            lines.append('\t'.join([indent + self.treeView.item(node)['text']] +
                                   [self.treeView.set(node,c) for c in cols]))
            self.tabLines(node, indent+'    ', cols, lines)
Exemple #4
0
class DialogOpenArchive(Toplevel):
    def __init__(self, mainWin, openType, filesource, filenames, title, colHeader, showAltViewButton=False):
        parent = mainWin.parent
        super(DialogOpenArchive, self).__init__(parent)
        self.parent = parent
        self.showAltViewButton = showAltViewButton
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))
        self.accepted = False

        self.transient(self.parent)
        
        frame = Frame(self)

        treeFrame = Frame(frame, width=500)
        vScrollbar = Scrollbar(treeFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(treeFrame, orient=HORIZONTAL)
        self.treeView = Treeview(treeFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set)
        self.treeView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.treeView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.treeView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        treeFrame.columnconfigure(0, weight=1)
        treeFrame.rowconfigure(0, weight=1)
        treeFrame.grid(row=0, column=0, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.treeView.focus_set()
        
        mainWin.showStatus(_("loading archive {0}").format(filesource.url))
        self.filesource = filesource
        self.filenames = filenames
        self.selection = filesource.selection
        self.hasToolTip = False
        selectedNode = None

        if openType == ENTRY_POINTS:
            try:
                metadataFiles = filesource.taxonomyPackageMetadataFiles
                if len(metadataFiles) > 1:
                    raise IOError(_("Taxonomy package contained more than one metadata file: {0}.")
                                  .format(', '.join(metadataFiles)))
                metadataFile = metadataFiles[0]
                metadata = filesource.file(filesource.url + os.sep + metadataFile)[0]
                self.metadataFilePrefix = os.sep.join(os.path.split(metadataFile)[:-1])
                if self.metadataFilePrefix:
                    self.metadataFilePrefix += os.sep
        
                self.nameToUrls, self.remappings = parseTxmyPkg(mainWin, metadata)
            except Exception as e:
                self.close()
                err = _("Failed to parse metadata; the underlying error was: {0}").format(e)
                messagebox.showerror(_("Malformed taxonomy package"), err)
                mainWin.addToLog(err)
                return
    
        mainWin.showStatus(None)
        
        if openType == DISCLOSURE_SYSTEM:
            y = 3
        else:
            y = 1

        okButton = Button(frame, text=_("OK"), command=self.ok)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        okButton.grid(row=y, column=2, sticky=(S,E,W), pady=3)
        cancelButton.grid(row=y, column=3, sticky=(S,E,W), pady=3, padx=3)
        
        if showAltViewButton:
            self.altViewButton = Button(frame, command=self.showAltView)
            self.altViewButton.grid(row=y, column=0, sticky=(S,W), pady=3, padx=3)
        
        self.loadTreeView(openType, colHeader, title)

        frame.grid(row=0, column=0, sticky=(N,S,E,W))
        frame.columnconfigure(0, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100))
        
        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)
        
        self.toolTipText = StringVar()
        if self.hasToolTip:
            self.treeView.bind("<Motion>", self.motion, '+')
            self.treeView.bind("<Leave>", self.leave, '+')
            self.toolTipText = StringVar()
            self.toolTip = ToolTip(self.treeView, 
                                   textvariable=self.toolTipText, 
                                   wraplength=640, 
                                   follow_mouse=True,
                                   state="disabled")
            self.toolTipRowId = None

        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        self.wait_window(self)
        
    def loadTreeView(self, openType, title, colHeader):
        self.title(title)
        self.openType = openType
        selectedNode = None

        # clear previous treeview entries
        for previousNode in self.treeView.get_children(""): 
            self.treeView.delete(previousNode)

        # set up treeView widget and tabbed pane
        if openType in (ARCHIVE, DISCLOSURE_SYSTEM):
            self.treeView.column("#0", width=500, anchor="w")
            self.treeView.heading("#0", text=colHeader)
            try:
                self.isRss = self.filesource.isRss
                if self.isRss:
                    self.treeView.column("#0", width=350, anchor="w")
                    self.treeView["columns"] = ("descr", "date", "instDoc")
                    self.treeView.column("descr", width=50, anchor="center", stretch=False)
                    self.treeView.heading("descr", text="Form")
                    self.treeView.column("date", width=170, anchor="w", stretch=False)
                    self.treeView.heading("date", text="Pub Date")
                    self.treeView.column("instDoc", width=200, anchor="w", stretch=False)
                    self.treeView.heading("instDoc", text="Instance Document")
            except AttributeError:
                self.isRss = False
                self.treeView["columns"] = tuple()
        
            loadedPaths = []
            for i, filename in enumerate(self.filenames):
                if isinstance(filename,tuple):
                    if self.isRss:
                        form, date, instDoc = filename[2:5]
                    filename = filename[0] # ignore tooltip
                    self.hasToolTip = True
                if filename.endswith("/"):
                    filename = filename[:-1]
                path = filename.split("/")
                if not self.isRss and len(path) > 1 and path[:-1] in loadedPaths:
                    parent = "file{0}".format(loadedPaths.index(path[:-1]))
                else:
                    parent = "" 
                node = self.treeView.insert(parent, "end", "file{0}".format(i), text=path[-1])
                if self.isRss:
                    self.treeView.set(node, "descr", form)
                    self.treeView.set(node, "date", date)
                    self.treeView.set(node, "instDoc", os.path.basename(instDoc))
                if self.selection == filename:
                    selectedNode = node
                loadedPaths.append(path)

        elif openType == ENTRY_POINTS:
            self.treeView.column("#0", width=150, anchor="w")
            self.treeView.heading("#0", text="Name")
    
            self.treeView["columns"] = ("url",)
            self.treeView.column("url", width=350, anchor="w")
            self.treeView.heading("url", text="URL")
            
            for name, urls in self.nameToUrls.items():
                displayUrl = urls[1] # display the canonical URL
                self.treeView.insert("", "end", name, values=[displayUrl], text=name)
                
            self.hasToolTip = True
        else: # unknown openType
            return None
        if selectedNode:
            self.treeView.see(selectedNode)
            self.treeView.selection_set(selectedNode)

        if self.showAltViewButton:
            self.altViewButton.config(text=_("Show Files") if openType == ENTRY_POINTS else _("Show Entries"))

        
    def ok(self, event=None):
        selection = self.treeView.selection()
        if len(selection) > 0:
            if self.openType in (ARCHIVE, DISCLOSURE_SYSTEM):
                filename = self.filenames[int(selection[0][4:])]
                if isinstance(filename,tuple):
                    if self.isRss:
                        filename = filename[4]
                    else:
                        filename = filename[0]
                if not filename.endswith("/"):
                    self.filesource.select(filename)
                    self.accepted = True
                    self.close()
            elif self.openType == ENTRY_POINTS:
                epName = selection[0]
                #index 0 is the remapped Url, as opposed to the canonical one used for display
                urlOrFile = self.nameToUrls[epName][0]
                
                # load file source remappings
                self.filesource.mappedPaths = \
                    dict((prefix, 
                          remapping if isHttpUrl(remapping)
                          else (self.filesource.baseurl + os.sep + self.metadataFilePrefix +remapping.replace("/", os.sep)))
                          for prefix, remapping in self.remappings.items())
    
                if not urlOrFile.endswith("/"):
                    # check if it's an absolute URL rather than a path into the archive
                    if isHttpUrl(urlOrFile):
                        self.filesource.select(urlOrFile)  # absolute path selection
                    else:
                        # assume it's a path inside the archive:
                        self.filesource.select(self.metadataFilePrefix + urlOrFile)
                    self.accepted = True
                    self.close()
        
    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()
        
    def showAltView(self, event=None):
        if self.openType == ENTRY_POINTS:
            self.loadTreeView(ARCHIVE, _("Select Entry Point"), _("File"))
        else:
            self.loadTreeView(ENTRY_POINTS, _("Select Archive File"), _("File"))
        
    def leave(self, *args):
        self.toolTipRowId = None

    def motion(self, *args):
        tvRowId = self.treeView.identify_row(args[0].y)
        if tvRowId != self.toolTipRowId:
            text = None
            if self.openType in (ARCHIVE, DISCLOSURE_SYSTEM):
                self.toolTipRowId = tvRowId
                if tvRowId and len(tvRowId) > 4:
                    try:
                        text = self.filenames[ int(tvRowId[4:]) ]
                        if isinstance(text, tuple):
                            text = text[1].replace("\\n","\n")
                    except (KeyError, ValueError):
                        pass
            elif self.openType == ENTRY_POINTS:
                try:
                    epUrl = self.nameToUrls[tvRowId][1]
                    text = "{0}\n{1}".format(tvRowId, epUrl)
                except KeyError:
                    pass
            self.setToolTip(text)
                
    def setToolTip(self, text):
        self.toolTip._hide()
        if text:
            self.toolTipText.set(text)
            self.toolTip.configure(state="normal")
            self.toolTip._schedule()
        else:
            self.toolTipText.set("")
            self.toolTip.configure(state="disabled")
Exemple #5
0
class ViewList():
    def __init__(self, modelXbrl, tabWin, tabTitle, hasToolTip=False):
        self.tabWin = tabWin
        self.viewFrame = Frame(tabWin)
        self.viewFrame.grid(row=0, column=0, sticky=(N, S, E, W))
        tabWin.add(self.viewFrame,text=tabTitle)
        xmlScrollbar = Scrollbar(self.viewFrame, orient=VERTICAL)
        self.listBox = Listbox(self.viewFrame, yscrollcommand=xmlScrollbar.set)
        self.listBox.grid(row=0, column=0, sticky=(N, S, E, W))
        #self.listBox.focus_set()
        self.listBox.bind("<Motion>", self.listBoxMotion, '+')
        self.listBox.bind("<Leave>", self.listBoxLeave, '+')
        xmlScrollbar["command"] = self.listBox.yview
        xmlScrollbar.grid(row=0, column=1, sticky=(N,S))
        self.viewFrame.columnconfigure(0, weight=1)
        self.viewFrame.rowconfigure(0, weight=1)
        self.listBoxToolTipText = StringVar()
        if hasToolTip:
            self.listBoxToolTip = ToolTip(self.listBox, textvariable=self.listBoxToolTipText, wraplength=480, follow_mouse=True, state="disabled")
            self.listBoxRow = -9999999
        self.modelXbrl = modelXbrl
        if modelXbrl:
            modelXbrl.views.append(self)
    
    def close(self):
        self.tabWin.forget(self.viewFrame)
        self.modelXbrl.views.remove(self)
        self.modelXbrl = None
        
    def select(self):
        self.tabWin.select(self.viewFrame)
        
    def append(self, line):
        self.listBox.insert(END, line)

    def clear(self):
        self.listBox.delete(0,END)
        
    def listBoxLeave(self, *args):
        self.listBoxRow = -9999999
        
    def lines(self):
        return self.listBox.get(0,END)

    def lineText(self, lineNumber):
        return self.listBox.get(lineNumber)
    
    def selectLine(self, lineNumber):
        self.listBox.selection_clear(0,END)
        self.listBox.selection_set(lineNumber)

    def saveToFile(self, filename):
        with open(filename, "w") as fh:
            fh.writelines([logEntry + '\n' for logEntry in self.listBox.get(0,END)])
            
    def copyToClipboard(self, cntlr=None, *ignore):
        if cntlr is None: cntlr = self.modelXbrl.modelManager.cntlr
        cntlr.clipboardData(text='\n'.join(self.listBox.get(0,END)))
            
    def listBoxMotion(self, *args):
        lbRow = self.listBox.nearest(args[0].y)
        if lbRow != self.listBoxRow:
            self.listBoxRow = lbRow
            text = self.listBox.get(lbRow)
            self.listBoxToolTip._hide()
            if text and len(text) > 0:
                if len(text) * 8 > 200:
                    self.listBoxToolTipText.set(text)
                    self.listBoxToolTip.configure(state="normal")
                    self.listBoxToolTip._schedule()
                else:
                    self.listBoxToolTipText.set("")
                    self.listBoxToolTip.configure(state="disabled")
            else:
                self.listBoxToolTipText.set("")
                self.listBoxToolTip.configure(state="disabled")
    
    def contextMenu(self,contextMenuClick=None):
        try:
            return self.menu
        except AttributeError:
            if contextMenuClick is None: contextMenuClick = self.modelXbrl.modelManager.cntlr.contextMenuClick
            self.menu = Menu( self.viewFrame, tearoff = 0 )
            self.listBox.bind( contextMenuClick, self.popUpMenu )
            return self.menu
    
    def popUpMenu(self, event):
        self.menu.post( event.x_root, event.y_root )

    def menuAddSaveClipboard(self):
        self.menu.add_command(label=_("Save to file"), underline=0, command=self.modelXbrl.modelManager.cntlr.fileSave)
        if self.modelXbrl.modelManager.cntlr.hasClipboard:
            self.menu.add_command(label=_("Copy to clipboard"), underline=0, command=self.copyToClipboard)
Exemple #6
0
class ViewTree:
    def __init__(self,
                 modelXbrl,
                 tabWin,
                 tabTitle,
                 hasToolTip=False,
                 lang=None):
        self.tabWin = tabWin
        self.viewFrame = Frame(tabWin)
        self.viewFrame.view = self
        self.viewFrame.grid(row=0, column=0, sticky=(N, S, E, W))
        tabWin.add(self.viewFrame, text=tabTitle)
        self.tabTitle = tabTitle  # for error messages
        vScrollbar = Scrollbar(self.viewFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(self.viewFrame, orient=HORIZONTAL)
        self.treeView = Treeview(self.viewFrame,
                                 xscrollcommand=hScrollbar.set,
                                 yscrollcommand=vScrollbar.set)
        self.treeView.grid(row=0, column=0, sticky=(N, S, E, W))
        self.treeView.tag_configure("ELR", background="#E0F0FF")
        self.treeView.tag_configure("even", background="#F0F0F0")
        self.treeView.tag_configure("odd", background="#FFFFFF")
        if modelXbrl.modelManager.cntlr.isMac or modelXbrl.modelManager.cntlr.isMSW:
            highlightColor = "#%04x%04x%04x" % self.treeView.winfo_rgb(
                "SystemHighlight")
        else:
            highlightColor = "#33339999ffff"  # using MSW value for Unix/Linux which has no named colors
        self.treeView.tag_configure("selected-ELR", background=highlightColor)
        self.treeView.tag_configure("selected-even", background=highlightColor)
        self.treeView.tag_configure("selected-odd", background=highlightColor)
        self.treeViewSelection = ()
        self.treeView.bind("<<TreeviewSelect>>", self.viewSelectionChange, '+')
        self.treeView.bind("<1>", self.onViewClick, '+')
        hScrollbar["command"] = self.treeView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E, W))
        vScrollbar["command"] = self.treeView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N, S))
        self.viewFrame.columnconfigure(0, weight=1)
        self.viewFrame.rowconfigure(0, weight=1)
        self.modelXbrl = modelXbrl
        self.hasToolTip = hasToolTip
        self.toolTipText = StringVar()
        if hasToolTip:
            self.treeView.bind("<Motion>", self.motion, '+')
            self.treeView.bind("<Leave>", self.leave, '+')
            self.toolTipText = StringVar()
            self.toolTip = ToolTip(self.treeView,
                                   textvariable=self.toolTipText,
                                   wraplength=480,
                                   follow_mouse=True,
                                   state="disabled")
            self.toolTipColId = None
            self.toolTipRowId = None
        self.modelXbrl = modelXbrl
        self.lang = lang
        self.labelrole = None
        self.nameIsPrefixed = False
        if modelXbrl:
            modelXbrl.views.append(self)
            if not lang:
                self.lang = modelXbrl.modelManager.defaultLang

    def clearTreeView(self):
        self.treeViewSelection = ()
        for node in self.treeView.get_children():
            self.treeView.delete(node)

    def viewSelectionChange(self, event=None):
        for node in self.treeViewSelection:
            if self.treeView.exists(node):
                priorTags = self.treeView.item(node)["tags"]
                if priorTags:
                    priorBgTag = priorTags[0]
                    if priorBgTag.startswith("selected-"):
                        self.treeView.item(node, tags=(priorBgTag[9:], ))
        self.treeViewSelection = self.treeView.selection()
        for node in self.treeViewSelection:
            priorTags = self.treeView.item(node)["tags"]
            if priorTags:
                self.treeView.item(node, tags=("selected-" + priorTags[0], ))

    def onViewClick(self, *args):
        self.modelXbrl.modelManager.cntlr.currentView = self

    def close(self):
        del self.viewFrame.view
        if self.modelXbrl:
            self.tabWin.forget(self.viewFrame)
            self.modelXbrl.views.remove(self)
            self.modelXbrl = None
            self.view = None

    def select(self):
        self.tabWin.select(self.viewFrame)

    def leave(self, *args):
        self.toolTipColId = None
        self.toolTipRowId = None

    def motion(self, *args):
        tvColId = self.treeView.identify_column(args[0].x)
        tvRowId = self.treeView.identify_row(args[0].y)
        if tvColId != self.toolTipColId or tvRowId != self.toolTipRowId:
            self.toolTipColId = tvColId
            self.toolTipRowId = tvRowId
            newValue = self.getToolTip(tvRowId, tvColId)
            if newValue is None and tvRowId and len(tvRowId) > 0:
                try:
                    col = int(tvColId[1:])
                    if col == 0:
                        newValue = self.treeView.item(tvRowId, "text")
                    else:
                        values = self.treeView.item(tvRowId, "values")
                        if col <= len(values):
                            newValue = values[col - 1]
                except ValueError:
                    pass
            self.setToolTip(newValue, tvColId)

    def getToolTip(self, rowId, colId):
        return None

    def setToolTip(self, text, colId="#0"):
        self.toolTip._hide()
        if isinstance(text, str) and len(text) > 0:
            width = self.treeView.column(colId, "width")
            if len(text) * 8 > width or '\n' in text:
                self.toolTipText.set(text)
                self.toolTip.configure(state="normal")
                self.toolTip._schedule()
            else:
                self.toolTipText.set("")
                self.toolTip.configure(state="disabled")
        else:
            self.toolTipText.set("")
            self.toolTip.configure(state="disabled")

    def contextMenu(self):
        try:
            return self.menu
        except AttributeError:
            try:
                self.menu = Menu(self.viewFrame, tearoff=0)
                self.treeView.bind(
                    self.modelXbrl.modelManager.cntlr.contextMenuClick,
                    self.popUpMenu, '+')
                return self.menu
            except Exception as ex:  # tkinter menu problem maybe
                self.modelXbrl.info(
                    "arelle:internalException",
                    _("Exception creating context menu in %(title)s: %(error)s"
                      ),
                    modelObject=self.modelXbrl.modelDocument,
                    title=self.tabTitle,
                    error=str(ex))
                self.menu = None
                return None

    def popUpMenu(self, event):
        if self.menu:
            self.menuRow = self.treeView.identify_row(event.y)
            self.menuCol = self.treeView.identify_column(event.x)
            self.menu.post(event.x_root, event.y_root)

    def expand(self):
        self.setTreeItemOpen(self.menuRow, open=True)

    def expandAll(self):
        self.setTreeItemOpen("", open=True)

    def collapse(self):
        self.setTreeItemOpen(self.menuRow, open=False)

    def collapseAll(self):
        self.setTreeItemOpen("", open=False)

    def setTreeItemOpen(self, node, open=True):
        if node:
            self.treeView.item(node, open=open)
        for childNode in self.treeView.get_children(node):
            self.setTreeItemOpen(childNode, open)

    def menuAddExpandCollapse(self):
        if self.menu:
            self.menu.add_command(label=_("Expand"),
                                  underline=0,
                                  command=self.expand)
            self.menu.add_command(label=_("Collapse"),
                                  underline=0,
                                  command=self.collapse)
            self.menu.add_command(label=_("Expand all"),
                                  underline=0,
                                  command=self.expandAll)
            self.menu.add_command(label=_("Collapse all"),
                                  underline=0,
                                  command=self.collapseAll)

    def menuAddClipboard(self):
        if self.menu and self.modelXbrl.modelManager.cntlr.hasClipboard:
            try:
                clipboardMenu = Menu(self.viewFrame, tearoff=0)
                clipboardMenu.add_command(label=_("Cell"),
                                          underline=0,
                                          command=self.copyCellToClipboard)
                clipboardMenu.add_command(label=_("Row"),
                                          underline=0,
                                          command=self.copyRowToClipboard)
                clipboardMenu.add_command(label=_("Table"),
                                          underline=0,
                                          command=self.copyTableToClipboard)
                self.menu.add_cascade(label=_("Copy to clipboard"),
                                      menu=clipboardMenu,
                                      underline=0)
            except Exception as ex:  # tkinter menu problem maybe
                self.modelXbrl.info(
                    "arelle:internalException",
                    _("Exception creating clipboard menu in %(title)s: %(error)s"
                      ),
                    modelObject=self.modelXbrl.modelDocument,
                    title=self.tabTitle,
                    error=str(ex))
                self.menu = None

    def menuAddLangs(self):
        if self.menu:
            try:
                langsMenu = Menu(self.viewFrame, tearoff=0)
                self.menu.add_cascade(label=_("Language"),
                                      menu=langsMenu,
                                      underline=0)
                for lang in sorted(self.modelXbrl.langs):
                    langsMenu.add_command(
                        label=lang,
                        underline=0,
                        command=lambda l=lang: self.setLang(l))
            except Exception as ex:  # tkinter menu problem maybe
                self.modelXbrl.info(
                    "arelle:internalException",
                    _("Exception creating context languages menu in %(title)s: %(error)s"
                      ),
                    modelObject=self.modelXbrl.modelDocument,
                    title=self.tabTitle,
                    error=str(ex))
                self.menu = None

    def menuAddLabelRoles(self, includeConceptName=False, menulabel=None):
        if self.menu:
            try:
                if menulabel is None: menulabel = _("Label role")
                rolesMenu = Menu(self.viewFrame, tearoff=0)
                self.menu.add_cascade(label=menulabel,
                                      menu=rolesMenu,
                                      underline=0)
                from arelle.ModelRelationshipSet import labelroles
                for x in labelroles(self.modelXbrl, includeConceptName):
                    rolesMenu.add_command(
                        label=x[0][1:],
                        underline=0,
                        command=lambda a=x[1]: self.setLabelrole(a))
            except Exception as ex:  # tkinter menu problem maybe
                self.modelXbrl.info(
                    "arelle:internalException",
                    _("Exception creating context label roles menu in %(title)s: %(error)s"
                      ),
                    modelObject=self.modelXbrl.modelDocument,
                    title=self.tabTitle,
                    error=str(ex))
                self.menu = None

    def menuAddNameStyle(self, menulabel=None):
        if self.menu:
            try:
                if menulabel is None: menulabel = _("Name Style")
                nameStyleMenu = Menu(self.viewFrame, tearoff=0)
                self.menu.add_cascade(label=menulabel,
                                      menu=nameStyleMenu,
                                      underline=0)
                from arelle.ModelRelationshipSet import labelroles
                nameStyleMenu.add_command(
                    label=_("Prefixed"),
                    underline=0,
                    command=lambda a=True: self.setNamestyle(a))
                nameStyleMenu.add_command(
                    label=_("No prefix"),
                    underline=0,
                    command=lambda a=False: self.setNamestyle(a))
            except Exception as ex:  # tkinter menu problem maybe
                self.modelXbrl.info(
                    "arelle:internalException",
                    _("Exception creating context name style menu in %(title)s: %(error)s"
                      ),
                    modelObject=self.modelXbrl.modelDocument,
                    title=self.tabTitle,
                    error=str(ex))
                self.menu = None

    def menuAddUnitDisplay(self):
        if self.menu:
            try:
                rolesMenu = Menu(self.viewFrame, tearoff=0)
                self.menu.add_cascade(label=_("Units"),
                                      menu=rolesMenu,
                                      underline=0)
                rolesMenu.add_command(
                    label=_("Unit ID"),
                    underline=0,
                    command=lambda: self.setUnitDisplay(unitDisplayID=True))
                rolesMenu.add_command(
                    label=_("Measures"),
                    underline=0,
                    command=lambda: self.setUnitDisplay(unitDisplayID=False))
            except Exception as ex:  # tkinter menu problem maybe
                self.modelXbrl.info(
                    "arelle:internalException",
                    _("Exception creating context unit menu in %(title)s: %(error)s"
                      ),
                    modelObject=self.modelXbrl.modelDocument,
                    title=self.tabTitle,
                    error=str(ex))
                self.menu = None

    def menuAddViews(self, addClose=True, tabWin=None):
        if self.menu:
            try:
                if tabWin is None: tabWin = self.tabWin
                viewMenu = Menu(self.viewFrame, tearoff=0)
                self.menu.add_cascade(label=_("View"),
                                      menu=viewMenu,
                                      underline=0)
                newViewsMenu = Menu(self.viewFrame, tearoff=0)
                if addClose:
                    viewMenu.add_command(label=_("Close"),
                                         underline=0,
                                         command=self.close)
                viewMenu.add_cascade(label=_("Additional view"),
                                     menu=newViewsMenu,
                                     underline=0)
                newViewsMenu.add_command(
                    label=_("Arcrole group..."),
                    underline=0,
                    command=lambda: self.newArcroleGroupView(tabWin))
                from arelle.ModelRelationshipSet import baseSetArcroles
                for x in baseSetArcroles(self.modelXbrl) + [
                    (" Role Types", "!CustomRoleTypes!"),
                    (" Arcrole Types", "!CustomArcroleTypes!")
                ]:
                    newViewsMenu.add_command(
                        label=x[0][1:],
                        underline=0,
                        command=lambda a=x[1]: self.newView(a, tabWin))
            except Exception as ex:  # tkinter menu problem maybe
                self.modelXbrl.info(
                    "arelle:internalException",
                    _("Exception creating context add-views menu in %(title)s: %(error)s"
                      ),
                    modelObject=self.modelXbrl.modelDocument,
                    title=self.tabTitle,
                    error=str(ex))
                self.menu = None

    def newView(self, arcrole, tabWin):
        if arcrole in ("!CustomRoleTypes!", "!CustomArcroleTypes!"):
            from arelle import ViewWinRoleTypes
            ViewWinRoleTypes.viewRoleTypes(self.modelXbrl,
                                           tabWin,
                                           arcrole == "!CustomArcroleTypes!",
                                           lang=self.lang)
        else:
            from arelle import ViewWinRelationshipSet
            ViewWinRelationshipSet.viewRelationshipSet(self.modelXbrl,
                                                       tabWin,
                                                       arcrole,
                                                       lang=self.lang)

    def newArcroleGroupView(self, tabWin):
        from arelle.DialogArcroleGroup import getArcroleGroup
        from arelle import ViewWinRelationshipSet
        arcroleGroup = getArcroleGroup(self.modelXbrl.modelManager.cntlr,
                                       self.modelXbrl)
        if arcroleGroup:
            ViewWinRelationshipSet.viewRelationshipSet(self.modelXbrl,
                                                       tabWin,
                                                       arcroleGroup,
                                                       lang=self.lang)

    def setLang(self, lang):
        self.lang = lang
        self.view()

    def setLabelrole(self, labelrole):
        self.labelrole = labelrole
        self.view()

    def setNamestyle(self, isPrefixed):
        self.nameIsPrefixed = isPrefixed
        self.view()

    def setUnitDisplay(self, unitDisplayID=False):
        self.unitDisplayID = unitDisplayID
        self.view()

    def setColumnsSortable(self,
                           treeColIsInt=False,
                           startUnsorted=False,
                           initialSortCol="#0",
                           initialSortDirForward=True):
        if hasattr(self, 'lastSortColumn') and self.lastSortColumn:
            self.treeView.heading(self.lastSortColumn,
                                  image=self.sortImages[2])
        self.lastSortColumn = None if startUnsorted else initialSortCol
        self.lastSortColumnForward = initialSortDirForward
        self.treeColIsInt = treeColIsInt
        if not hasattr(self, "sortImages"):
            self.sortImages = (PhotoImage(
                file=os.path.join(self.modelXbrl.modelManager.cntlr.imagesDir,
                                  "columnSortUp.gif")),
                               PhotoImage(file=os.path.join(
                                   self.modelXbrl.modelManager.cntlr.imagesDir,
                                   "columnSortDown.gif")), PhotoImage())
        for col in ("#0", ) + self.treeView["columns"]:
            self.treeView.heading(col,
                                  command=lambda c=col: self.sortColumn(c))
        if not startUnsorted:
            self.treeView.heading(
                initialSortCol,
                image=self.sortImages[not initialSortDirForward])

    def colSortVal(self, node, col):
        if col == "#0":
            treeColVal = self.treeView.item(node)["text"]
            if self.treeColIsInt:
                return int(treeColVal)
        else:
            treeColVal = self.treeView.set(node, col)
            if col == "sequence":
                try:
                    return int(treeColVal)
                except:
                    return 0
        return treeColVal

    def sortNestedRows(self, parentNode, col, reverse):
        l = [(self.colSortVal(node, col), node)
             for node in self.treeView.get_children(parentNode)]
        l.sort(reverse=reverse)
        # rearrange items in sorted positions
        for i, (cell, node) in enumerate(l):
            self.treeView.move(node, parentNode, i)
        # reset even/odd tags
        for i, node in enumerate(self.treeView.get_children(parentNode)):
            self.treeView.item(node, tags=('even' if i & 1 else 'odd', ))
            self.sortNestedRows(node, col, reverse)

    def sortColumn(self, col):
        if col == self.lastSortColumn:
            reverse = self.lastSortColumnForward
            self.lastSortColumnForward = not reverse
        else:
            if self.lastSortColumn:
                self.treeView.heading(self.lastSortColumn,
                                      image=self.sortImages[2])
            reverse = False
            self.lastSortColumnForward = True
            self.lastSortColumn = col
        self.treeView.heading(col, image=self.sortImages[reverse])
        self.sortNestedRows('', col, reverse)
        self.viewSelectionChange()  # reselect selected rows

    def copyCellToClipboard(self, *ignore):
        self.modelXbrl.modelManager.cntlr.clipboardData(
            text=self.treeView.item(self.menuRow)['text'] if self.menuCol ==
            '#0' else self.treeView.set(self.menuRow, self.menuCol))

    def copyRowToClipboard(self, *ignore):
        self.modelXbrl.modelManager.cntlr.clipboardData(
            text='\t'.join([self.treeView.item(self.menuRow)['text']] + [
                self.treeView.set(self.menuRow, c)
                for c in self.treeView['columns']
            ]))

    def copyTableToClipboard(self, *ignore):
        cols = self.treeView['columns']
        lines = [
            '\t'.join([self.treeView.heading('#0')['text']] +
                      [self.treeView.heading(h)['text'] for h in cols])
        ]
        self.tabLines('', '', cols, lines)
        self.modelXbrl.modelManager.cntlr.clipboardData(text='\n'.join(lines))

    def tabLines(self, parentNode, indent, cols, lines):
        for node in self.treeView.get_children(parentNode):
            lines.append('\t'.join(
                '"{}"'.format(c.replace('"', '""')) if (
                    isinstance(c, str) and "\n" in c) else c
                for c in ([indent + self.treeView.item(node)['text']] +
                          [self.treeView.set(node, c) for c in cols])))
            self.tabLines(node, indent + '    ', cols, lines)
Exemple #7
0
class DialogOpenArchive(Toplevel):
    def __init__(self, mainWin, openType, filesource, filenames, title, colHeader, showAltViewButton=False):
        parent = mainWin.parent
        super(DialogOpenArchive, self).__init__(parent)
        self.parent = parent
        self.showAltViewButton = showAltViewButton
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))
        self.accepted = False

        self.transient(self.parent)
        
        frame = Frame(self)

        treeFrame = Frame(frame, width=500)
        vScrollbar = Scrollbar(treeFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(treeFrame, orient=HORIZONTAL)
        self.treeView = Treeview(treeFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set)
        self.treeView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.treeView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.treeView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        treeFrame.columnconfigure(0, weight=1)
        treeFrame.rowconfigure(0, weight=1)
        treeFrame.grid(row=0, column=0, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.treeView.focus_set()
        
        mainWin.showStatus(_("loading archive {0}").format(filesource.url))
        self.filesource = filesource
        self.filenames = filenames
        self.selection = filesource.selection
        self.hasToolTip = False
        selectedNode = None

        if openType == ENTRY_POINTS:
            try:
                metadataFiles = filesource.taxonomyPackageMetadataFiles
                ''' take first for now
                if len(metadataFiles) != 1:
                    raise IOError(_("Taxonomy package contained more than one metadata file: {0}.")
                                  .format(', '.join(metadataFiles)))
                '''
                metadataFile = metadataFiles[0]
                metadata = filesource.url + os.sep + metadataFile
                self.metadataFilePrefix = os.sep.join(os.path.split(metadataFile)[:-1])
                if self.metadataFilePrefix:
                    self.metadataFilePrefix += "/"  # zip contents have /, never \ file seps
                self.taxonomyPkgMetaInf = '{}/META-INF/'.format(
                            os.path.splitext(os.path.basename(filesource.url))[0])

        
                self.taxonomyPackage = parsePackage(mainWin, filesource, metadata,
                                                    os.sep.join(os.path.split(metadata)[:-1]) + os.sep)
                
                # may be a catalog file with no entry oint names
                if not self.taxonomyPackage["nameToUrls"]:
                    openType = ARCHIVE  # no entry points to show, just archive
                    self.showAltViewButton = False
            except Exception as e:
                self.close()
                err = _("Failed to parse metadata; the underlying error was: {0}").format(e)
                messagebox.showerror(_("Malformed taxonomy package"), err)
                mainWin.addToLog(err)
                return
    
        mainWin.showStatus(None)
        
        if openType == DISCLOSURE_SYSTEM:
            y = 3
        else:
            y = 1

        okButton = Button(frame, text=_("OK"), command=self.ok)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        okButton.grid(row=y, column=2, sticky=(S,E,W), pady=3)
        cancelButton.grid(row=y, column=3, sticky=(S,E,W), pady=3, padx=3)
        
        if self.showAltViewButton:
            self.altViewButton = Button(frame, command=self.showAltView)
            self.altViewButton.grid(row=y, column=0, sticky=(S,W), pady=3, padx=3)
        
        self.loadTreeView(openType, colHeader, title)

        self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100))
        frame.grid(row=0, column=0, sticky=(N,S,E,W))
        frame.columnconfigure(0, weight=1)
        frame.rowconfigure(0, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        window.rowconfigure(0, weight=1)
        
        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)
        
        self.toolTipText = StringVar()
        if self.hasToolTip:
            self.treeView.bind("<Motion>", self.motion, '+')
            self.treeView.bind("<Leave>", self.leave, '+')
            self.toolTipText = StringVar()
            self.toolTip = ToolTip(self.treeView, 
                                   textvariable=self.toolTipText, 
                                   wraplength=640, 
                                   follow_mouse=True,
                                   state="disabled")
            self.toolTipRowId = None

        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        self.wait_window(self)
        
    def loadTreeView(self, openType, title, colHeader):
        self.title(title)
        self.openType = openType
        selectedNode = None

        # clear previous treeview entries
        for previousNode in self.treeView.get_children(""): 
            self.treeView.delete(previousNode)

        # set up treeView widget and tabbed pane
        if openType in (ARCHIVE, DISCLOSURE_SYSTEM):
            self.treeView.column("#0", width=500, anchor="w")
            self.treeView.heading("#0", text=colHeader)
            try:
                self.isRss = self.filesource.isRss
                if self.isRss:
                    self.treeView.column("#0", width=350, anchor="w")
                    self.treeView["columns"] = ("descr", "date", "instDoc")
                    self.treeView.column("descr", width=50, anchor="center", stretch=False)
                    self.treeView.heading("descr", text="Form")
                    self.treeView.column("date", width=170, anchor="w", stretch=False)
                    self.treeView.heading("date", text="Pub Date")
                    self.treeView.column("instDoc", width=200, anchor="w", stretch=False)
                    self.treeView.heading("instDoc", text="Instance Document")
            except AttributeError:
                self.isRss = False
                self.treeView["columns"] = tuple()
        
            loadedPaths = []
            for i, filename in enumerate(self.filenames):
                if isinstance(filename,tuple):
                    if self.isRss:
                        form, date, instDoc = filename[2:5]
                    filename = filename[0] # ignore tooltip
                    self.hasToolTip = True
                if filename.endswith("/"):
                    filename = filename[:-1]
                path = filename.split("/")
                if not self.isRss and len(path) > 1 and path[:-1] in loadedPaths:
                    parent = "file{0}".format(loadedPaths.index(path[:-1]))
                else:
                    parent = "" 
                node = self.treeView.insert(parent, "end", "file{0}".format(i), text=path[-1])
                if self.isRss:
                    self.treeView.set(node, "descr", form)
                    self.treeView.set(node, "date", date)
                    self.treeView.set(node, "instDoc", os.path.basename(instDoc))
                if self.selection == filename:
                    selectedNode = node
                loadedPaths.append(path)

        elif openType == ENTRY_POINTS:
            self.treeView.column("#0", width=150, anchor="w")
            self.treeView.heading("#0", text="Name")
    
            self.treeView["columns"] = ("url",)
            self.treeView.column("url", width=350, anchor="w")
            self.treeView.heading("url", text="URL")
            
            for name, urls in self.taxonomyPackage["nameToUrls"].items():
                displayUrl = urls[1] # display the canonical URL
                self.treeView.insert("", "end", name, values=[displayUrl], text=name)
                
            self.hasToolTip = True
        else: # unknown openType
            return None
        if selectedNode:
            self.treeView.see(selectedNode)
            self.treeView.selection_set(selectedNode)

        if self.showAltViewButton:
            self.altViewButton.config(text=_("Show Files") if openType == ENTRY_POINTS else _("Show Entries"))

        
    def ok(self, event=None):
        selection = self.treeView.selection()
        if len(selection) > 0:
            if hasattr(self, "taxonomyPackage"):
                # load file source remappings
                self.filesource.mappedPaths = self.taxonomyPackage["remappings"]
            filename = None
            if self.openType in (ARCHIVE, DISCLOSURE_SYSTEM):
                filename = self.filenames[int(selection[0][4:])]
                if isinstance(filename,tuple):
                    if self.isRss:
                        filename = filename[4]
                    else:
                        filename = filename[0]
            elif self.openType == ENTRY_POINTS:
                epName = selection[0]
                #index 0 is the remapped Url, as opposed to the canonical one used for display
                filename = self.taxonomyPackage["nameToUrls"][epName][0]
                if not filename.endswith("/"):
                    # check if it's an absolute URL rather than a path into the archive
                    if not isHttpUrl(filename) and self.metadataFilePrefix != self.taxonomyPkgMetaInf:
                        # assume it's a path inside the archive:
                        filename = self.metadataFilePrefix + filename
            if filename is not None and not filename.endswith("/"):
                if hasattr(self, "taxonomyPackage"):
                    # attempt to unmap the filename to original file
                    # will be mapped again in loading, but this allows schemaLocation to be unmapped
                    for prefix, remapping in self.taxonomyPackage["remappings"].items():
                        if isHttpUrl(remapping):
                            remapStart = remapping
                        else:
                            remapStart = self.metadataFilePrefix + remapping
                        if filename.startswith(remapStart):
                            # set unmmapped file
                            filename = prefix + filename[len(remapStart):]
                            break
                self.filesource.select(filename)
                self.accepted = True
                self.close()
                        
        
    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()
        
    def showAltView(self, event=None):
        if self.openType == ENTRY_POINTS:
            self.loadTreeView(ARCHIVE, _("Select Entry Point"), _("File"))
        else:
            self.loadTreeView(ENTRY_POINTS, _("Select Archive File"), _("File"))
        
    def leave(self, *args):
        self.toolTipRowId = None

    def motion(self, *args):
        tvRowId = self.treeView.identify_row(args[0].y)
        if tvRowId != self.toolTipRowId:
            text = None
            if self.openType in (ARCHIVE, DISCLOSURE_SYSTEM):
                self.toolTipRowId = tvRowId
                if tvRowId and len(tvRowId) > 4:
                    try:
                        text = self.filenames[ int(tvRowId[4:]) ]
                        if isinstance(text, tuple):
                            text = text[1].replace("\\n","\n")
                    except (KeyError, ValueError):
                        pass
            elif self.openType == ENTRY_POINTS:
                try:
                    epUrl = self.taxonomyPackage["nameToUrls"][tvRowId][1]
                    text = "{0}\n{1}".format(tvRowId, epUrl)
                except KeyError:
                    pass
            self.setToolTip(text)
                
    def setToolTip(self, text):
        self.toolTip._hide()
        if text:
            self.toolTipText.set(text)
            self.toolTip.configure(state="normal")
            self.toolTip._schedule()
        else:
            self.toolTipText.set("")
            self.toolTip.configure(state="disabled")
Exemple #8
0
class ViewGrid:
    def __init__(self, modelXbrl, tabWin, tabTitle, hasToolTip=False, lang=None):
        self.tabWin = tabWin
        #self.viewFrame = Frame(tabWin)
        #self.viewFrame.grid(row=0, column=0, sticky=(N, S, E, W))
        '''
        paneWin = PanedWindow(self.viewFrame, orient=VERTICAL)
        paneWin.grid(row=1, column=0, sticky=(N, S, E, W))
        self.zGrid = scrollgrid(paneWin)
        self.zGrid.grid(row=0, column=0, sticky=(N, S, E, W))
        self.xyGrid = scrollgrid(paneWin)
        self.xyGrid.grid(row=1, column=0, sticky=(N, S, E, W))
        '''
        '''
        self.gridBody = scrollgrid(self.viewFrame)
        self.gridBody.grid(row=0, column=0, sticky=(N, S, E, W))
        '''
        
        self.viewFrame = scrolledHeaderedFrame(tabWin)
        self.gridTblHdr = self.viewFrame.tblHdrInterior
        self.gridColHdr = self.viewFrame.colHdrInterior
        self.gridRowHdr = self.viewFrame.rowHdrInterior
        self.gridBody = self.viewFrame.bodyInterior
        '''
        self.viewFrame = scrolledFrame(tabWin)
        self.gridTblHdr = self.gridRowHdr = self.gridColHdr = self.gridBody = self.viewFrame.interior
        '''
        
        tabWin.add(self.viewFrame,text=tabTitle)
        self.modelXbrl = modelXbrl
        self.hasToolTip = hasToolTip
        self.toolTipText = StringVar()
        if hasToolTip:
            self.gridBody.bind("<Motion>", self.motion, '+')
            self.gridBody.bind("<Leave>", self.leave, '+')
            self.toolTipText = StringVar()
            self.toolTip = ToolTip(self.gridBody, 
                                   textvariable=self.toolTipText, 
                                   wraplength=480, 
                                   follow_mouse=True,
                                   state="disabled")
            self.toolTipColId = None
            self.toolTipRowId = None
        self.modelXbrl = modelXbrl
        self.contextMenuClick = self.modelXbrl.modelManager.cntlr.contextMenuClick
        self.gridTblHdr.contextMenuClick = self.contextMenuClick
        self.gridColHdr.contextMenuClick = self.contextMenuClick
        self.gridRowHdr.contextMenuClick = self.contextMenuClick
        self.gridBody.contextMenuClick = self.contextMenuClick
        self.lang = lang
        if modelXbrl:
            modelXbrl.views.append(self)
            if not lang: 
                self.lang = modelXbrl.modelManager.defaultLang
        
    def close(self):
        self.tabWin.forget(self.viewFrame)
        self.modelXbrl.views.remove(self)
        self.modelXbrl = None
        
    def leave(self, *args):
        self.toolTipColId = None
        self.toolTipRowId = None

    def motion(self, *args):
        '''
        tvColId = self.gridBody.identify_column(args[0].x)
        tvRowId = self.gridBody.identify_row(args[0].y)
        if tvColId != self.toolTipColId or tvRowId != self.toolTipRowId:
            self.toolTipColId = tvColId
            self.toolTipRowId = tvRowId
            newValue = None
            if tvRowId and len(tvRowId) > 0:
                try:
                    col = int(tvColId[1:])
                    if col == 0:
                        newValue = self.gridBody.item(tvRowId,"text")
                    else:
                        values = self.gridBody.item(tvRowId,"values")
                        if col <= len(values):
                            newValue = values[col - 1]
                except ValueError:
                    pass
            self.setToolTip(newValue, tvColId)
        '''
                
    def setToolTip(self, text, colId="#0"):
        self.toolTip._hide()
        if isinstance(text,str) and len(text) > 0:
            width = self.gridBody.column(colId,"width")
            if len(text) * 8 > width or '\n' in text:
                self.toolTipText.set(text)
                self.toolTip.configure(state="normal")
                self.toolTip._schedule()
            else:
                self.toolTipText.set("")
                self.toolTip.configure(state="disabled")
        else:
            self.toolTipText.set("")
            self.toolTip.configure(state="disabled")

    def contextMenu(self):
        try:
            return self.menu
        except AttributeError:
            self.menu = Menu( self.viewFrame, tearoff = 0 )
            self.gridBody.bind( self.contextMenuClick, self.popUpMenu )
            if not self.gridTblHdr.bind(self.contextMenuClick): 
                self.gridTblHdr.bind( self.contextMenuClick, self.popUpMenu )
            if not self.gridColHdr.bind(self.contextMenuClick): 
                self.gridColHdr.bind( self.contextMenuClick, self.popUpMenu )
            if not self.gridRowHdr.bind(self.contextMenuClick): 
                self.gridRowHdr.bind( self.contextMenuClick, self.popUpMenu )
            return self.menu

    def popUpMenu(self, event):
        self.menu.post( event.x_root, event.y_root )
        
    def menuAddLangs(self):
        langsMenu = Menu(self.viewFrame, tearoff=0)
        self.menu.add_cascade(label=_("Language"), menu=langsMenu, underline=0)
        for lang in sorted(self.modelXbrl.langs):
            langsMenu.add_cascade(label=lang, underline=0, command=lambda l=lang: self.setLang(l))
    
    def setLang(self, lang):
        self.lang = lang
        self.view()
Exemple #9
0
class ViewGrid:
    def __init__(self,
                 modelXbrl,
                 tabWin,
                 tabTitle,
                 hasToolTip=False,
                 lang=None):
        self.tabWin = tabWin
        #self.viewFrame = Frame(tabWin)
        #self.viewFrame.grid(row=0, column=0, sticky=(N, S, E, W))
        '''
        paneWin = PanedWindow(self.viewFrame, orient=VERTICAL)
        paneWin.grid(row=1, column=0, sticky=(N, S, E, W))
        self.zGrid = scrollgrid(paneWin)
        self.zGrid.grid(row=0, column=0, sticky=(N, S, E, W))
        self.xyGrid = scrollgrid(paneWin)
        self.xyGrid.grid(row=1, column=0, sticky=(N, S, E, W))
        '''
        '''
        self.gridBody = scrollgrid(self.viewFrame)
        self.gridBody.grid(row=0, column=0, sticky=(N, S, E, W))
        '''

        self.viewFrame = scrolledHeaderedFrame(tabWin)
        self.gridTblHdr = self.viewFrame.tblHdrInterior
        self.gridColHdr = self.viewFrame.colHdrInterior
        self.gridRowHdr = self.viewFrame.rowHdrInterior
        self.gridBody = self.viewFrame.bodyInterior
        '''
        self.viewFrame = scrolledFrame(tabWin)
        self.gridTblHdr = self.gridRowHdr = self.gridColHdr = self.gridBody = self.viewFrame.interior
        '''

        tabWin.add(self.viewFrame, text=tabTitle)
        self.modelXbrl = modelXbrl
        self.hasToolTip = hasToolTip
        self.toolTipText = StringVar()
        if hasToolTip:
            self.gridBody.bind("<Motion>", self.motion, '+')
            self.gridBody.bind("<Leave>", self.leave, '+')
            self.toolTipText = StringVar()
            self.toolTip = ToolTip(self.gridBody,
                                   textvariable=self.toolTipText,
                                   wraplength=480,
                                   follow_mouse=True,
                                   state="disabled")
            self.toolTipColId = None
            self.toolTipRowId = None
        self.modelXbrl = modelXbrl
        self.contextMenuClick = self.modelXbrl.modelManager.cntlr.contextMenuClick
        self.gridTblHdr.contextMenuClick = self.contextMenuClick
        self.gridColHdr.contextMenuClick = self.contextMenuClick
        self.gridRowHdr.contextMenuClick = self.contextMenuClick
        self.gridBody.contextMenuClick = self.contextMenuClick
        self.lang = lang
        if modelXbrl:
            modelXbrl.views.append(self)
            if not lang:
                self.lang = modelXbrl.modelManager.defaultLang

    def close(self):
        self.tabWin.forget(self.viewFrame)
        if self in self.modelXbrl.views:
            self.modelXbrl.views.remove(self)
        self.modelXbrl = None

    def select(self):
        self.tabWin.select(self.viewFrame)

    def leave(self, *args):
        self.toolTipColId = None
        self.toolTipRowId = None

    def motion(self, *args):
        '''
        tvColId = self.gridBody.identify_column(args[0].x)
        tvRowId = self.gridBody.identify_row(args[0].y)
        if tvColId != self.toolTipColId or tvRowId != self.toolTipRowId:
            self.toolTipColId = tvColId
            self.toolTipRowId = tvRowId
            newValue = None
            if tvRowId and len(tvRowId) > 0:
                try:
                    col = int(tvColId[1:])
                    if col == 0:
                        newValue = self.gridBody.item(tvRowId,"text")
                    else:
                        values = self.gridBody.item(tvRowId,"values")
                        if col <= len(values):
                            newValue = values[col - 1]
                except ValueError:
                    pass
            self.setToolTip(newValue, tvColId)
        '''

    def setToolTip(self, text, colId="#0"):
        self.toolTip._hide()
        if isinstance(text, str) and len(text) > 0:
            width = self.gridBody.column(colId, "width")
            if len(text) * 8 > width or '\n' in text:
                self.toolTipText.set(text)
                self.toolTip.configure(state="normal")
                self.toolTip._schedule()
            else:
                self.toolTipText.set("")
                self.toolTip.configure(state="disabled")
        else:
            self.toolTipText.set("")
            self.toolTip.configure(state="disabled")

    def contextMenu(self):
        try:
            return self.menu
        except AttributeError:
            self.menu = Menu(self.viewFrame, tearoff=0)
            self.gridBody.bind(self.contextMenuClick, self.popUpMenu)
            if not self.gridTblHdr.bind(self.contextMenuClick):
                self.gridTblHdr.bind(self.contextMenuClick, self.popUpMenu)
            if not self.gridColHdr.bind(self.contextMenuClick):
                self.gridColHdr.bind(self.contextMenuClick, self.popUpMenu)
            if not self.gridRowHdr.bind(self.contextMenuClick):
                self.gridRowHdr.bind(self.contextMenuClick, self.popUpMenu)
            return self.menu

    def popUpMenu(self, event):
        self.menu.post(event.x_root, event.y_root)

    def menuAddLangs(self):
        langsMenu = Menu(self.viewFrame, tearoff=0)
        self.menu.add_cascade(label=_("Language"), menu=langsMenu, underline=0)
        for lang in sorted(self.modelXbrl.langs):
            langsMenu.add_cascade(label=lang,
                                  underline=0,
                                  command=lambda l=lang: self.setLang(l))

    def setLang(self, lang):
        self.lang = lang
        self.view()
Exemple #10
0
class ViewList():
    def __init__(self, modelXbrl, tabWin, tabTitle, hasToolTip=False):
        self.tabWin = tabWin
        self.viewFrame = Frame(tabWin)
        self.viewFrame.view = self
        self.viewFrame.grid(row=0, column=0, sticky=(N, S, E, W))
        tabWin.add(self.viewFrame, text=tabTitle)
        xmlScrollbar = Scrollbar(self.viewFrame, orient=VERTICAL)
        self.listBox = Listbox(self.viewFrame, yscrollcommand=xmlScrollbar.set)
        self.listBox.grid(row=0, column=0, sticky=(N, S, E, W))
        #self.listBox.focus_set()
        self.listBox.bind("<Motion>", self.listBoxMotion, '+')
        self.listBox.bind("<1>", self.listBoxClick, '+')
        self.listBox.bind("<Leave>", self.listBoxLeave, '+')
        xmlScrollbar["command"] = self.listBox.yview
        xmlScrollbar.grid(row=0, column=1, sticky=(N, S))
        self.viewFrame.columnconfigure(0, weight=1)
        self.viewFrame.rowconfigure(0, weight=1)
        self.listBoxToolTipText = StringVar()
        if hasToolTip:
            self.listBoxToolTip = ToolTip(self.listBox,
                                          textvariable=self.listBoxToolTipText,
                                          wraplength=480,
                                          follow_mouse=True,
                                          state="disabled")
            self.listBoxRow = -9999999
        self.modelXbrl = modelXbrl
        if modelXbrl:
            modelXbrl.views.append(self)

    def close(self):
        del self.viewFrame.view
        self.tabWin.forget(self.viewFrame)
        self.modelXbrl.views.remove(self)
        self.modelXbrl = None

    def select(self):
        self.tabWin.select(self.viewFrame)

    def append(self, line):
        self.listBox.insert(END, line)

    def clear(self):
        self.listBox.delete(0, END)

    def listBoxClick(self, *args):
        if self.modelXbrl:
            self.modelXbrl.modelManager.cntlr.currentView = self

    def listBoxLeave(self, *args):
        self.listBoxRow = -9999999

    def lines(self):
        return self.listBox.get(0, END)

    def lineText(self, lineNumber):
        return self.listBox.get(lineNumber)

    def selectLine(self, lineNumber):
        self.listBox.selection_clear(0, END)
        self.listBox.selection_set(lineNumber)

    def saveToFile(self, filename):
        with open(filename, "w") as fh:
            fh.writelines(
                [logEntry + '\n' for logEntry in self.listBox.get(0, END)])

    def copyToClipboard(self, cntlr=None, *ignore):
        if cntlr is None: cntlr = self.modelXbrl.modelManager.cntlr
        cntlr.clipboardData(text='\n'.join(self.listBox.get(0, END)))

    def listBoxMotion(self, *args):
        lbRow = self.listBox.nearest(args[0].y)
        if lbRow != self.listBoxRow:
            self.listBoxRow = lbRow
            text = self.listBox.get(lbRow)
            self.listBoxToolTip._hide()
            if text and len(text) > 0:
                if len(text) * 8 > 200:
                    self.listBoxToolTipText.set(
                        text[:2048] + "..." if len(text) > 2048 else text)
                    self.listBoxToolTip.configure(state="normal")
                    self.listBoxToolTip._schedule()
                else:
                    self.listBoxToolTipText.set("")
                    self.listBoxToolTip.configure(state="disabled")
            else:
                self.listBoxToolTipText.set("")
                self.listBoxToolTip.configure(state="disabled")

    def contextMenu(self, contextMenuClick=None):
        try:
            return self.menu
        except AttributeError:
            if contextMenuClick is None:
                contextMenuClick = self.modelXbrl.modelManager.cntlr.contextMenuClick
            self.menu = Menu(self.viewFrame, tearoff=0)
            self.listBox.bind(contextMenuClick, self.popUpMenu)
            return self.menu

    def popUpMenu(self, event):
        self.menu.post(event.x_root, event.y_root)

    def menuAddSaveClipboard(self):
        self.menu.add_command(
            label=_("Save to file"),
            underline=0,
            command=self.modelXbrl.modelManager.cntlr.fileSave)
        if self.modelXbrl.modelManager.cntlr.hasClipboard:
            self.menu.add_command(label=_("Copy to clipboard"),
                                  underline=0,
                                  command=self.copyToClipboard)
class DialogOpenTaxonomyPackage(Toplevel):
    def __init__(self, mainWin, openType, filesource, filenames, title):
        parent = mainWin.parent
        super().__init__(parent)
        self.parent = parent
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))
        self.accepted = False
        self.webUrl = None

        self.transient(self.parent)
        self.title(title)

        frame = Frame(self)

        treeFrame = Frame(frame, width=500)
        vScrollbar = Scrollbar(treeFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(treeFrame, orient=HORIZONTAL)
        self.treeView = Treeview(treeFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, columns=2)
        self.treeView.grid(row=0, column=0, sticky=(N, S, E, W))

        hScrollbar["command"] = self.treeView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E, W))
        vScrollbar["command"] = self.treeView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N, S))

        treeFrame.columnconfigure(0, weight=1)

        treeFrame.rowconfigure(0, weight=1)
        treeFrame.grid(row=0, column=0, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)

        self.treeView.focus_set()

        # set up treeView widget and tabbed pane
        self.treeView.column("#0", width=150, anchor="w")
        self.treeView.heading("#0", text="Name")

        self.treeView.column("#1", width=350, anchor="w")
        self.treeView.heading("#1", text="URL")

        mainWin.showStatus(_("loading archive {0}").format(filesource.url))
        self.filesource = filesource
        self.filenames = filenames
        selectedNode = None

        metadata = filesource.file(filesource.url + os.sep + TAXONOMY_PACKAGE_FILE_NAME)[0]

        try:
            self.nameToUrls = parseTxmyPkg(mainWin, metadata)
        except Exception as e:
            self.close()
            err = _("Failed to parse metadata; the underlying error was: {0}").format(e)
            messagebox.showerror(_("Malformed taxonomy package"), err)
            mainWin.addToLog(err)
            return

        for name, urls in self.nameToUrls.items():
            displayUrl = urls[1] # display the canonical URL
            self.treeView.insert("", "end", name, values=[displayUrl], text=name)

        if selectedNode:
            self.treeView.see(selectedNode)
            self.treeView.selection_set(selectedNode)
        mainWin.showStatus(None)

        if openType == DISCLOSURE_SYSTEM:
            y = 3
        else:
            y = 1

        okButton = Button(frame, text=_("OK"), command=self.ok)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        okButton.grid(row=y, column=2, sticky=(S, E, W), pady=3)
        cancelButton.grid(row=y, column=3, sticky=(S, E, W), pady=3, padx=3)

        frame.grid(row=0, column=0, sticky=(N, S, E, W))
        frame.columnconfigure(0, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        self.geometry("+{0}+{1}".format(dialogX + 50, dialogY + 100))

        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)

        self.toolTipText = StringVar()
        self.treeView.bind("<Motion>", self.motion, '+')
        self.treeView.bind("<Leave>", self.leave, '+')
        self.toolTipText = StringVar()
        self.toolTip = ToolTip(self.treeView,
                               textvariable=self.toolTipText,
                               wraplength=640,
                               follow_mouse=True,
                               state="disabled")
        self.toolTipEpName = None

        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        self.wait_window(self)

    def ok(self, event=None):
        selection = self.treeView.selection()
        if len(selection) > 0:
            epName = selection[0]
            #index 0 is the remapped Url, as opposed to the canonical one used for display
            urlOrFile = self.nameToUrls[epName][0]

            if not urlOrFile.endswith("/"):
                # check if it's an absolute URL rather than a path into the archive
                if urlOrFile.startswith("http://") or urlOrFile.startswith("https://"):
                    self.webUrl = urlOrFile
                else:
                    # assume it's a path inside the archive:
                    self.filesource.select(urlOrFile)
                self.accepted = True
                self.close()

    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()

    def leave(self, *args):
        self.toolTipRowId = None

    def motion(self, *args):
        epName = self.treeView.identify_row(args[0].y)
        if epName != self.toolTipEpName:
            self.toolTipEpName = epName
            try:
                epUrl = self.nameToUrls[epName][1]
            except KeyError:
                epUrl = None
            self.toolTip._hide()
            if epName and epUrl:
                self.toolTipText.set("{0}\n{1}".format(epName, epUrl))
                self.toolTip.configure(state="normal")
                self.toolTip._schedule()
            else:
                self.toolTipText.set("")
                self.toolTip.configure(state="disabled")
Exemple #12
0
class DialogOpenArchive(Toplevel):
    def __init__(self, parent, openType, filesource, filenames, title, colHeader, showAltViewButton=False):
        if isinstance(parent, Cntlr):
            cntlr = parent
            parent = parent.parent # parent is cntlrWinMain
        else: # parent is a Toplevel dialog
            cntlr = parent.cntlr
        super(DialogOpenArchive, self).__init__(parent)
        self.parent = parent
        self.showAltViewButton = showAltViewButton
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))
        self.accepted = False

        self.transient(self.parent)
        
        frame = Frame(self)

        treeFrame = Frame(frame, width=500)
        vScrollbar = Scrollbar(treeFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(treeFrame, orient=HORIZONTAL)
        self.treeView = Treeview(treeFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set)
        self.treeView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.treeView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.treeView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        treeFrame.columnconfigure(0, weight=1)
        treeFrame.rowconfigure(0, weight=1)
        treeFrame.grid(row=0, column=0, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.treeView.focus_set()
        
        if openType not in (PLUGIN, PACKAGE):
            cntlr.showStatus(_("loading archive {0}").format(filesource.url))
        self.filesource = filesource
        self.filenames = filenames
        self.selection = filesource.selection
        self.hasToolTip = False
        selectedNode = None

        if openType == ENTRY_POINTS:
            try:
                metadataFiles = filesource.taxonomyPackageMetadataFiles
                ''' take first for now
                if len(metadataFiles) != 1:
                    raise IOError(_("Taxonomy package contained more than one metadata file: {0}.")
                                  .format(', '.join(metadataFiles)))
                '''
                metadataFile = metadataFiles[0]
                metadata = filesource.url + os.sep + metadataFile
                self.metadataFilePrefix = os.sep.join(os.path.split(metadataFile)[:-1])
                if self.metadataFilePrefix:
                    self.metadataFilePrefix += "/"  # zip contents have /, never \ file seps
                self.taxonomyPkgMetaInf = '{}/META-INF/'.format(
                            os.path.splitext(os.path.basename(filesource.url))[0])

        
                self.taxonomyPackage = parsePackage(cntlr, filesource, metadata,
                                                    os.sep.join(os.path.split(metadata)[:-1]) + os.sep)
                
                
                if self.taxonomyPackage["entryPoints"]:
                    # may have instance documents too
                    self.packageContainedInstances = []
                    packageContentTypeCounts = {}
                    for suffix in (".xhtml", ".htm", ".html"):
                        for potentialInstance in filesource.dir:
                            if potentialInstance.endswith(".xhtml"):
                                _type = "Inline Instance"
                                self.packageContainedInstances.append([potentialInstance, _type])
                                packageContentTypeCounts[potentialInstance] = packageContentTypeCounts.get(potentialInstance, 0) + 1
                        if self.packageContainedInstances:
                            break 
                    if self.packageContainedInstances: # add sequences to any duplicated entry types
                        for _type, count in packageContentTypeCounts.items():
                            if count > 1:
                                _dupNo = 0
                                for i in range(len(self.packageContainedInstances)):
                                    if self.packageContainedInstances[i][0] == _type:
                                        _dupNo += 1
                                        self.packageContainedInstances[i][0] = "{} {}".format(_type, _dupNo)
                                    
                else:
                    # may be a catalog file with no entry oint names
                    openType = ARCHIVE  # no entry points to show, just archive
                    self.showAltViewButton = False
            except Exception as e:
                self.close()
                err = _("Failed to parse metadata; the underlying error was: {0}").format(e)
                messagebox.showerror(_("Malformed taxonomy package"), err)
                cntlr.addToLog(err)
                return
    
        if openType not in (PLUGIN, PACKAGE):
            cntlr.showStatus(None)
        
        if openType in (DISCLOSURE_SYSTEM, PLUGIN, PACKAGE):
            y = 3
        else:
            y = 1

        okButton = Button(frame, text=_("OK"), command=self.ok)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        okButton.grid(row=y, column=2, sticky=(S,E,W), pady=3)
        cancelButton.grid(row=y, column=3, sticky=(S,E,W), pady=3, padx=3)
        
        if self.showAltViewButton:
            self.altViewButton = Button(frame, command=self.showAltView)
            self.altViewButton.grid(row=y, column=0, sticky=(S,W), pady=3, padx=3)
        
        self.loadTreeView(openType, colHeader, title)

        self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100))
        frame.grid(row=0, column=0, sticky=(N,S,E,W))
        frame.columnconfigure(0, weight=1)
        frame.rowconfigure(0, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        window.rowconfigure(0, weight=1)
        
        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)
        
        self.toolTipText = StringVar()
        if self.hasToolTip:
            self.treeView.bind("<Motion>", self.motion, '+')
            self.treeView.bind("<Leave>", self.leave, '+')
            self.toolTipText = StringVar()
            self.toolTip = ToolTip(self.treeView, 
                                   textvariable=self.toolTipText, 
                                   wraplength=640, 
                                   follow_mouse=True,
                                   state="disabled")
            self.toolTipRowId = None

        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        
        self.wait_window(self)

    
        
        
    def loadTreeView(self, openType, title, colHeader):
        self.title(title)
        self.openType = openType
        selectedNode = None

        # clear previous treeview entries
        for previousNode in self.treeView.get_children(""): 
            self.treeView.delete(previousNode)

        # set up treeView widget and tabbed pane
        if openType in (ARCHIVE, DISCLOSURE_SYSTEM, PLUGIN, PACKAGE):
            if openType in (PLUGIN, PACKAGE): width = 770
            else: width = 500
            self.treeView.column("#0", width=width, anchor="w")
            self.treeView.heading("#0", text=colHeader)
            self.isRss = getattr(self.filesource, "isRss", False)
            if self.isRss:
                self.treeView.column("#0", width=350, anchor="w")
                self.treeView["columns"] = ("descr", "date", "instDoc")
                self.treeView.column("descr", width=50, anchor="center", stretch=False)
                self.treeView.heading("descr", text="Form")
                self.treeView.column("date", width=170, anchor="w", stretch=False)
                self.treeView.heading("date", text="Pub Date")
                self.treeView.column("instDoc", width=200, anchor="w", stretch=False)
                self.treeView.heading("instDoc", text="Instance Document")
            elif openType == PLUGIN:
                self.treeView.column("#0", width=150, anchor="w")
                self.treeView["columns"] = ("name", "vers", "descr", "license")
                self.treeView.column("name", width=150, anchor="w", stretch=False)
                self.treeView.heading("name", text="Name")
                self.treeView.column("vers", width=60, anchor="w", stretch=False)
                self.treeView.heading("vers", text="Version")
                self.treeView.column("descr", width=300, anchor="w", stretch=False)
                self.treeView.heading("descr", text="Description")
                self.treeView.column("license", width=60, anchor="w", stretch=False)
                self.treeView.heading("license", text="License")
            elif openType == PACKAGE:
                self.treeView.column("#0", width=200, anchor="w")
                self.treeView["columns"] = ("vers", "descr", "license")
                self.treeView.column("vers", width=100, anchor="w", stretch=False)
                self.treeView.heading("vers", text="Version")
                self.treeView.column("descr", width=400, anchor="w", stretch=False)
                self.treeView.heading("descr", text="Description")
                self.treeView.column("license", width=70, anchor="w", stretch=False)
                self.treeView.heading("license", text="License")
            else:
                self.treeView["columns"] = tuple()
        
            loadedPaths = []
            for i, filename in enumerate(self.filenames):
                if isinstance(filename,tuple):
                    if self.isRss:
                        form, date, instDoc = filename[2:5]
                    elif openType == PLUGIN:
                        name, vers, descr, license = filename[3:7]
                    elif openType == PACKAGE:
                        vers, descr, license = filename[3:6]
                    filename = filename[0] # ignore tooltip
                    self.hasToolTip = True
                if filename.endswith("/"):
                    filename = filename[:-1]
                path = filename.split("/")
                if not self.isRss and len(path) > 1 and path[:-1] in loadedPaths:
                    parent = "file{0}".format(loadedPaths.index(path[:-1]))
                else:
                    parent = "" 
                node = self.treeView.insert(parent, "end", "file{0}".format(i), text=path[-1])
                if self.isRss:
                    self.treeView.set(node, "descr", form)
                    self.treeView.set(node, "date", date)
                    self.treeView.set(node, "instDoc", os.path.basename(instDoc))
                elif openType == PLUGIN:
                    self.treeView.set(node, "name", name)
                    self.treeView.set(node, "vers", vers)
                    self.treeView.set(node, "descr", descr)
                    self.treeView.set(node, "license", license)
                elif openType == PACKAGE:
                    self.treeView.set(node, "vers", vers)
                    self.treeView.set(node, "descr", descr)
                    self.treeView.set(node, "license", license)
                if self.selection == filename:
                    selectedNode = node
                loadedPaths.append(path)

        elif openType == ENTRY_POINTS:
            self.treeView.column("#0", width=200, anchor="w")
            self.treeView.heading("#0", text="Name")
    
            self.treeView["columns"] = ("url",)
            self.treeView.column("url", width=300, anchor="w")
            self.treeView.heading("url", text="URL")
            
            for fileType, fileUrl in getattr(self, "packageContainedInstances", ()):
                self.treeView.insert("", "end", fileUrl, 
                                     values=fileType, 
                                     text=fileUrl or urls[0][2])
            for name, urls in sorted(self.taxonomyPackage["entryPoints"].items(), key=lambda i:i[0][2]):
                self.treeView.insert("", "end", name, 
                                     values="\n".join(url[1] for url in urls), 
                                     text=name or urls[0][2])
                
            self.hasToolTip = True
        else: # unknown openType
            return None
        if selectedNode:
            self.treeView.see(selectedNode)
            self.treeView.selection_set(selectedNode)

        if self.showAltViewButton:
            self.altViewButton.config(text=_("Show Files") if openType == ENTRY_POINTS else _("Show Entries"))

        
    def ok(self, event=None):
        selection = self.treeView.selection()
        if len(selection) > 0:
            if hasattr(self, "taxonomyPackage"):
                # load file source remappings
                self.filesource.mappedPaths = self.taxonomyPackage["remappings"]
            filename = None
            if self.openType in (ARCHIVE, DISCLOSURE_SYSTEM):
                filename = self.filenames[int(selection[0][4:])]
                if isinstance(filename,tuple):
                    if self.isRss:
                        filename = filename[4]
                    else:
                        filename = filename[0]
            elif self.openType == ENTRY_POINTS:
                epName = selection[0]
                #index 0 is the remapped Url, as opposed to the canonical one used for display
                # Greg Acsone reports [0] does not work for Corep 1.6 pkgs, need [1], old style packages
                filenames = []
                for _url, _type in self.packageContainedInstances: # check if selection was an inline instance
                    if _type == epName:
                        filenames.append(_url)
                if not filenames: # else if it's a named taxonomy entry point
                    for url in self.taxonomyPackage["entryPoints"][epName]:
                        filename = url[0]
                        if not filename.endswith("/"):
                            # check if it's an absolute URL rather than a path into the archive
                            if not isHttpUrl(filename) and self.metadataFilePrefix != self.taxonomyPkgMetaInf:
                                # assume it's a path inside the archive:
                                filename = self.metadataFilePrefix + filename
                        filenames.append(filename)
                if filenames:
                    self.filesource.select(filenames)
                    self.accepted = True
                    self.close()
                return
            elif self.openType in (PLUGIN, PACKAGE):
                filename = self.filenames[int(selection[0][4:])][2]
            if filename is not None and not filename.endswith("/"):
                if hasattr(self, "taxonomyPackage"):
                    # attempt to unmap the filename to original file
                    # will be mapped again in loading, but this allows schemaLocation to be unmapped
                    for prefix, remapping in self.taxonomyPackage["remappings"].items():
                        if isHttpUrl(remapping):
                            remapStart = remapping
                        else:
                            remapStart = self.metadataFilePrefix + remapping
                        if filename.startswith(remapStart):
                            # set unmmapped file
                            filename = prefix + filename[len(remapStart):]
                            break
                if self.openType in (PLUGIN, PACKAGE):
                    self.filesource.selection = filename
                else:
                    self.filesource.select(filename)
                self.accepted = True
                self.close()
                        
        
    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()
        
    def showAltView(self, event=None):
        if self.openType == ENTRY_POINTS:
            self.loadTreeView(ARCHIVE, _("Select Entry Point"), _("File"))
        else:
            self.loadTreeView(ENTRY_POINTS, _("Select Archive File"), _("File"))
        
    def leave(self, *args):
        self.toolTipRowId = None

    def motion(self, *args):
        tvRowId = self.treeView.identify_row(args[0].y)
        if tvRowId != self.toolTipRowId:
            text = None
            if self.openType in (ARCHIVE, DISCLOSURE_SYSTEM, PLUGIN, PACKAGE):
                self.toolTipRowId = tvRowId
                if tvRowId and len(tvRowId) > 4:
                    try:
                        text = self.filenames[ int(tvRowId[4:]) ]
                        if isinstance(text, tuple):
                            text = (text[1] or "").replace("\\n","\n")
                    except (KeyError, ValueError):
                        pass
            elif self.openType == ENTRY_POINTS:
                try:
                    text = "{0}\n{1}".format(tvRowId, 
                             "\n".join(url[1] for url in self.taxonomyPackage["entryPoints"][tvRowId]))
                except KeyError:
                    pass
            self.setToolTip(text)
                
    def setToolTip(self, text):
        self.toolTip._hide()
        if text:
            self.toolTipText.set(text)
            self.toolTip.configure(state="normal")
            self.toolTip._schedule()
        else:
            self.toolTipText.set("")
            self.toolTip.configure(state="disabled")
Exemple #13
0
class ViewTree:
    def __init__(self, modelXbrl, tabWin, tabTitle, hasToolTip=False, lang=None, editableColumns=[], valueChangedCallback=None):
        self.tabWin = tabWin
        self.viewFrame = Frame(tabWin)
        self.viewFrame.view = self
        self.viewFrame.grid(row=0, column=0, sticky=(N, S, E, W))
        tabWin.add(self.viewFrame,text=tabTitle)
        self.tabTitle = tabTitle # for error messages
        vScrollbar = Scrollbar(self.viewFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(self.viewFrame, orient=HORIZONTAL)
        self.isEbaTableIndex = False
        if tabTitle.startswith('Tables'):
            for pluginXbrlMethod in pluginClassMethods("CntlrWinMain.Modeling.LoadFilingIndicators"):
                self.isEbaTableIndex = True
                # for EBA and in case of table index, add a second column with the filing indicator
                # (OK, it is not really sound to base this test on the title)            
                self.treeView = Treeview(self.viewFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, columns="Filing")
                break
        if not self.isEbaTableIndex:
            self.treeView = Treeview(self.viewFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set)
        self.treeView.grid(row=0, column=0, sticky=(N, S, E, W))
        self.treeView.tag_configure("ELR", background="#E0F0FF")
        self.treeView.tag_configure("even", background="#F0F0F0")
        self.treeView.tag_configure("odd", background="#FFFFFF")
        if modelXbrl.modelManager.cntlr.isMac or modelXbrl.modelManager.cntlr.isMSW:
            highlightColor = "#%04x%04x%04x" % self.treeView.winfo_rgb("SystemHighlight")
        else:
            highlightColor = "#33339999ffff"  # using MSW value for Unix/Linux which has no named colors
        self.treeView.tag_configure("selected-ELR", background=highlightColor)
        self.treeView.tag_configure("selected-even", background=highlightColor)
        self.treeView.tag_configure("selected-odd", background=highlightColor)
        self.treeViewSelection = ()
        self.treeView.bind("<<TreeviewSelect>>", self.viewSelectionChange, '+')
        self.treeView.bind("<1>", self.onViewClick, '+')
        self.treeView.bind("<Double-1>", self.onDoubleClick, '+')
        hScrollbar["command"] = self.treeView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.treeView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        self.viewFrame.columnconfigure(0, weight=1)
        self.viewFrame.rowconfigure(0, weight=1)
        self.modelXbrl = modelXbrl
        self.hasToolTip = hasToolTip
        self.toolTipText = StringVar()
        if hasToolTip:
            self.treeView.bind("<Motion>", self.motion, '+')
            self.treeView.bind("<Leave>", self.leave, '+')
            self.toolTipText = StringVar()
            self.toolTip = ToolTip(self.treeView, 
                                   textvariable=self.toolTipText, 
                                   wraplength=480, 
                                   follow_mouse=True,
                                   state="disabled")
            self.toolTipColId = None
            self.toolTipRowId = None
        self.modelXbrl = modelXbrl
        self.lang = lang
        self.labelrole = None
        self.nameIsPrefixed = False
        if modelXbrl:
            modelXbrl.views.append(self)
            if not lang: 
                self.lang = modelXbrl.modelManager.defaultLang
        self.editableColumns = editableColumns
        self.valueChangedCallback = valueChangedCallback
        self.entryPopup = None

    def refreshTitle(self):
        tid = str(self.viewFrame)
        text = "Tables (" + self.modelXbrl.getInstanceFilenameForView() + ")"
        self.tabWin.tab(tid, text=text)
        self.tabTitle = text
            
    def clearTreeView(self):
        self.treeViewSelection = ()
        for node in self.treeView.get_children():
            self.treeView.delete(node)
                
    def viewSelectionChange(self, event=None):
        for node in self.treeViewSelection:
            self.removeSelection(node)
        self.treeViewSelection = self.treeView.selection()
        for node in self.treeViewSelection:
            self.addSelection(node)
            
    def removeSelection(self, node):
        if self.treeView.exists(node):
            priorTags = self.treeView.item(node)["tags"]
            if priorTags:
                newTags = tuple((i[9:] if i.startswith("selected-") else i) for i in priorTags)
                self.treeView.item(node, tags=newTags)


    def addSelection(self, node):
        priorTags = self.treeView.item(node)["tags"]
        if priorTags:
            newTags = tuple(("selected-"+i if i in ['even', 'odd'] else i) for i in priorTags)
            self.treeView.item(node, tags=newTags)

    def onViewClick(self, *args):
        self.modelXbrl.modelManager.cntlr.currentView = self

    def close(self):
        del self.viewFrame.view
        if self.modelXbrl:
            self.tabWin.forget(self.viewFrame)
            self.modelXbrl.views.remove(self)
            self.modelXbrl = None
            self.view = None
                
    def select(self):
        self.tabWin.select(self.viewFrame)
        
    def leave(self, *args):
        self.toolTipColId = None
        self.toolTipRowId = None

    def motion(self, *args):
        tvColId = self.treeView.identify_column(args[0].x)
        tvRowId = self.treeView.identify_row(args[0].y)
        if tvColId != self.toolTipColId or tvRowId != self.toolTipRowId:
            self.toolTipColId = tvColId
            self.toolTipRowId = tvRowId
            newValue = self.getToolTip(tvRowId, tvColId)
            if newValue is None and tvRowId and len(tvRowId) > 0:
                try:
                    col = int(tvColId[1:])
                    if col == 0:
                        newValue = self.treeView.item(tvRowId,"text")
                    else:
                        values = self.treeView.item(tvRowId,"values")
                        if col <= len(values):
                            newValue = values[col - 1]
                except ValueError:
                    pass
            self.setToolTip(newValue, tvColId)
            
    def getToolTip(self, rowId, colId):
        return None
                
    def setToolTip(self, text, colId="#0"):
        self.toolTip._hide()
        if isinstance(text,str) and len(text) > 0:
            width = self.treeView.column(colId,"width")
            if len(text) * 8 > width or '\n' in text:
                self.toolTipText.set(text)
                self.toolTip.configure(state="normal")
                self.toolTip._schedule()
            else:
                self.toolTipText.set("")
                self.toolTip.configure(state="disabled")
        else:
            self.toolTipText.set("")
            self.toolTip.configure(state="disabled")

    def contextMenu(self):
        try:
            return self.menu
        except AttributeError:
            try:
                self.menu = Menu( self.viewFrame, tearoff = 0 )
                self.treeView.bind( self.modelXbrl.modelManager.cntlr.contextMenuClick, self.popUpMenu, '+' )
                return self.menu
            except Exception as ex: # tkinter menu problem maybe
                self.modelXbrl.info("arelle:internalException",
                                    _("Exception creating context menu in %(title)s: %(error)s"),
                                    modelObject=self.modelXbrl.modelDocument, title=self.tabTitle, error=str(ex))
                self.menu = None
                return None

    def popUpMenu(self, event):
        if self.menu:
            self.menuRow = self.treeView.identify_row(event.y)
            self.menuCol = self.treeView.identify_column(event.x)
            self.menu.post( event.x_root, event.y_root )
        
    def expand(self):
        self.setTreeItemOpen(self.menuRow,open=True)
        
    def setFiling(self, filingIndicator):
        # Check if there is a custom method to set filing indicators
        for pluginXbrlMethod in pluginClassMethods("CntlrWinMain.Rendering.SetFilingIndicator"):
            stopPlugin = pluginXbrlMethod(self, self.modelXbrl, filingIndicator)
            if stopPlugin:
                break;
        
    def setFilingTrue(self):
        self.setFiling(True)
        
    def setFilingFalse(self):
        self.setFiling(False)
        
    def resetFiling(self):
        self.setFiling(None)

    def expandAll(self):
        self.setTreeItemOpen("",open=True)
        
    def collapse(self):
        self.setTreeItemOpen(self.menuRow,open=False)
        
    def collapseAll(self):
        self.setTreeItemOpen("",open=False)
        
    def setTreeItemOpen(self, node, open=True):
        if node:
            self.treeView.item(node, open=open)
        for childNode in self.treeView.get_children(node):
            self.setTreeItemOpen(childNode, open)
            
    def menuAddExpandCollapse(self):
        if self.menu:
            self.menu.add_command(label=_("Expand"), underline=0, command=self.expand)
            self.menu.add_command(label=_("Collapse"), underline=0, command=self.collapse)
            self.menu.add_command(label=_("Expand all"), underline=0, command=self.expandAll)
            self.menu.add_command(label=_("Collapse all"), underline=0, command=self.collapseAll)
            
    def menuAddFilingChoice(self):
        if self.menu:
            self.menu.add_command(label=_("Filing: set filed"), underline=0, command=self.setFilingTrue)
            self.menu.add_command(label=_("Filing: set not filed"), underline=0, command=self.setFilingFalse)
            self.menu.add_command(label=_("Filing: clear"), underline=0, command=self.resetFiling)
        
    def menuAddClipboard(self):
        if self.menu and self.modelXbrl.modelManager.cntlr.hasClipboard:
            try:
                clipboardMenu = Menu(self.viewFrame, tearoff=0)
                clipboardMenu.add_command(label=_("Cell"), underline=0, command=self.copyCellToClipboard)
                clipboardMenu.add_command(label=_("Row"), underline=0, command=self.copyRowToClipboard)
                clipboardMenu.add_command(label=_("Table"), underline=0, command=self.copyTableToClipboard)
                self.menu.add_cascade(label=_("Copy to clipboard"), menu=clipboardMenu, underline=0)
            except Exception as ex: # tkinter menu problem maybe
                self.modelXbrl.info("arelle:internalException",
                                    _("Exception creating clipboard menu in %(title)s: %(error)s"),
                                    modelObject=self.modelXbrl.modelDocument, title=self.tabTitle, error=str(ex))
                self.menu = None
        
    def menuAddLangs(self):
        if self.menu:
            try:
                langsMenu = Menu(self.viewFrame, tearoff=0)
                self.menu.add_cascade(label=_("Language"), menu=langsMenu, underline=0)
                for lang in sorted(self.modelXbrl.langs):
                    langsMenu.add_command(label=lang, underline=0, command=lambda l=lang: self.setLang(l))
            except Exception as ex: # tkinter menu problem maybe
                self.modelXbrl.info("arelle:internalException",
                                    _("Exception creating context languages menu in %(title)s: %(error)s"),
                                    modelObject=self.modelXbrl.modelDocument, title=self.tabTitle, error=str(ex))
                self.menu = None

    def menuAddLabelRoles(self, includeConceptName=False, menulabel=None):
        if self.menu:
            try:
                if menulabel is None: menulabel = _("Label role")
                rolesMenu = Menu(self.viewFrame, tearoff=0)
                self.menu.add_cascade(label=menulabel, menu=rolesMenu, underline=0)
                from arelle.ModelRelationshipSet import labelroles
                for x in labelroles(self.modelXbrl, includeConceptName):
                    rolesMenu.add_command(label=x[0][1:], underline=0, command=lambda a=x[1]: self.setLabelrole(a))
            except Exception as ex: # tkinter menu problem maybe
                self.modelXbrl.info("arelle:internalException",
                                    _("Exception creating context label roles menu in %(title)s: %(error)s"),
                                    modelObject=self.modelXbrl.modelDocument, title=self.tabTitle, error=str(ex))
                self.menu = None

    def menuAddNameStyle(self, menulabel=None):
        if self.menu:
            try:
                if menulabel is None: menulabel = _("Name Style")
                nameStyleMenu = Menu(self.viewFrame, tearoff=0)
                self.menu.add_cascade(label=menulabel, menu=nameStyleMenu, underline=0)
                from arelle.ModelRelationshipSet import labelroles
                nameStyleMenu.add_command(label=_("Prefixed"), underline=0, command=lambda a=True: self.setNamestyle(a))
                nameStyleMenu.add_command(label=_("No prefix"), underline=0, command=lambda a=False: self.setNamestyle(a))
            except Exception as ex: # tkinter menu problem maybe
                self.modelXbrl.info("arelle:internalException",
                                    _("Exception creating context name style menu in %(title)s: %(error)s"),
                                    modelObject=self.modelXbrl.modelDocument, title=self.tabTitle, error=str(ex))
                self.menu = None

    def menuAddUnitDisplay(self):
        if self.menu:
            try:
                rolesMenu = Menu(self.viewFrame, tearoff=0)
                self.menu.add_cascade(label=_("Units"), menu=rolesMenu, underline=0)
                rolesMenu.add_command(label=_("Unit ID"), underline=0, command=lambda: self.setUnitDisplay(unitDisplayID=True))
                rolesMenu.add_command(label=_("Measures"), underline=0, command=lambda: self.setUnitDisplay(unitDisplayID=False))
            except Exception as ex: # tkinter menu problem maybe
                self.modelXbrl.info("arelle:internalException",
                                    _("Exception creating context unit menu in %(title)s: %(error)s"),
                                    modelObject=self.modelXbrl.modelDocument, title=self.tabTitle, error=str(ex))
                self.menu = None

    def menuAddViews(self, addClose=True, tabWin=None):
        if self.menu:
            try:
                if tabWin is None: tabWin = self.tabWin
                viewMenu = Menu(self.viewFrame, tearoff=0)
                self.menu.add_cascade(label=_("View"), menu=viewMenu, underline=0)
                newViewsMenu = Menu(self.viewFrame, tearoff=0)
                if addClose:
                    viewMenu.add_command(label=_("Close"), underline=0, command=self.close)
                viewMenu.add_cascade(label=_("Additional view"), menu=newViewsMenu, underline=0)
                newViewsMenu.add_command(label=_("Arcrole group..."), underline=0, command=lambda: self.newArcroleGroupView(tabWin))
                from arelle.ModelRelationshipSet import baseSetArcroles
                for x in baseSetArcroles(self.modelXbrl) + [( " Role Types","!CustomRoleTypes!"), (" Arcrole Types", "!CustomArcroleTypes!")]:
                    newViewsMenu.add_command(label=x[0][1:], underline=0, command=lambda a=x[1]: self.newView(a, tabWin))
            except Exception as ex: # tkinter menu problem maybe
                self.modelXbrl.info("arelle:internalException",
                                    _("Exception creating context add-views menu in %(title)s: %(error)s"),
                                    modelObject=self.modelXbrl.modelDocument, title=self.tabTitle, error=str(ex))
                self.menu = None
    
    def newView(self, arcrole, tabWin):
        if arcrole in ("!CustomRoleTypes!", "!CustomArcroleTypes!"):
            from arelle import ViewWinRoleTypes
            ViewWinRoleTypes.viewRoleTypes(self.modelXbrl, tabWin, arcrole=="!CustomArcroleTypes!", lang=self.lang)
        else:
            from arelle import ViewWinRelationshipSet
            ViewWinRelationshipSet.viewRelationshipSet(self.modelXbrl, tabWin, arcrole, lang=self.lang)
            
    def newArcroleGroupView(self, tabWin):
        from arelle.DialogArcroleGroup import getArcroleGroup
        from arelle import ViewWinRelationshipSet
        arcroleGroup = getArcroleGroup(self.modelXbrl.modelManager.cntlr, self.modelXbrl)
        if arcroleGroup: 
            ViewWinRelationshipSet.viewRelationshipSet(self.modelXbrl, tabWin, arcroleGroup, lang=self.lang)
            
    def setLang(self, lang):
        self.lang = lang
        self.view()
        
    def setLabelrole(self, labelrole):
        self.labelrole = labelrole
        self.view()
        
    def setNamestyle(self, isPrefixed):
        self.nameIsPrefixed = isPrefixed
        self.view()
        
    def setUnitDisplay(self, unitDisplayID=False):
        self.unitDisplayID = unitDisplayID
        self.view()
        
    def setColumnsSortable(self, treeColIsInt=False, startUnsorted=False, initialSortCol="#0", initialSortDirForward=True):
        if hasattr(self, 'lastSortColumn') and self.lastSortColumn:
            self.treeView.heading(self.lastSortColumn, image=self.sortImages[2])
        self.lastSortColumn = None if startUnsorted else initialSortCol 
        self.lastSortColumnForward = initialSortDirForward
        self.treeColIsInt = treeColIsInt
        if not hasattr(self, "sortImages"):
            self.sortImages = (PhotoImage(file=os.path.join(self.modelXbrl.modelManager.cntlr.imagesDir, "columnSortUp.gif")),
                               PhotoImage(file=os.path.join(self.modelXbrl.modelManager.cntlr.imagesDir, "columnSortDown.gif")),
                               PhotoImage())
        for col in ("#0",) + self.treeView["columns"]:
            self.treeView.heading(col, command=lambda c=col: self.sortColumn(c))
        if not startUnsorted:
            self.treeView.heading(initialSortCol, image=self.sortImages[not initialSortDirForward])
            
    def colSortVal(self, node, col):
        if col == "#0":
            treeColVal = self.treeView.item(node)["text"]
            if self.treeColIsInt: 
                return int(treeColVal)
        else:
            treeColVal = self.treeView.set(node, col)
            if col == "sequence":
                try:
                    return int(treeColVal)
                except:
                    return 0
        return treeColVal
    
    def sortNestedRows(self, parentNode, col, reverse):
        l = [(self.colSortVal(node, col), node) for node in self.treeView.get_children(parentNode)]
        l.sort(reverse=reverse)
        # rearrange items in sorted positions     
        for i, (cell, node) in enumerate(l):         
            self.treeView.move(node, parentNode, i)
        # reset even/odd tags
        for i, node in enumerate(self.treeView.get_children(parentNode)):
            self.treeView.item(node, tags=('even' if i & 1 else 'odd',))
            self.sortNestedRows(node, col, reverse)
                    
    def sortColumn(self, col):
        if col == self.lastSortColumn:
            reverse = self.lastSortColumnForward
            self.lastSortColumnForward = not reverse
        else:
            if self.lastSortColumn:
                self.treeView.heading(self.lastSortColumn, image=self.sortImages[2])
            reverse = False
            self.lastSortColumnForward = True
            self.lastSortColumn = col
        self.treeView.heading(col, image=self.sortImages[reverse])
        self.sortNestedRows('', col, reverse)
        self.viewSelectionChange()  # reselect selected rows
        
    def copyCellToClipboard(self, *ignore):
        self.modelXbrl.modelManager.cntlr.clipboardData(
            text=self.treeView.item(self.menuRow)['text'] if self.menuCol == '#0' else self.treeView.set(self.menuRow,self.menuCol))
        
    def copyRowToClipboard(self, *ignore):
        self.modelXbrl.modelManager.cntlr.clipboardData(
            text='\t'.join([self.treeView.item(self.menuRow)['text']] +
                           [self.treeView.set(self.menuRow,c) for c in self.treeView['columns']]))
        
    def copyTableToClipboard(self, *ignore):
        cols = self.treeView['columns']
        lines = ['\t'.join([self.treeView.heading('#0')['text']] +
                           [self.treeView.heading(h)['text'] for h in cols])]
        self.tabLines('', '', cols, lines)
        self.modelXbrl.modelManager.cntlr.clipboardData(text='\n'.join(lines))

    def tabLines(self, parentNode, indent, cols, lines): 
        for node in self.treeView.get_children(parentNode):
            lines.append('\t'.join([indent + self.treeView.item(node)['text']] +
                                   [self.treeView.set(node,c) for c in cols]))
            self.tabLines(node, indent+'    ', cols, lines)

    def onDoubleClick(self, event):
        ''' Executed, when a row is double-clicked. Opens 
        a EntryPopup above the item's column, so it is possible
        to edit the text '''
        # do nothing if no column is editable
        if len(self.editableColumns)<=0:
            return
        
        # delete any open Entry Popup
        if self.entryPopup:
            self.entryPopup.destroy()
            self.entryPopup = None

        # what row and column was clicked on
        rowID = self.treeView.identify_row(event.y)
        column = self.treeView.identify_column(event.x)

        if not (column in self.editableColumns and (self.treeView.tag_has("editable", rowID))):
            return

        # get column position info
        x,y,width,height = self.treeView.bbox(rowID, column)
    
        # y-axis offset
        pady = height // 2
    
        # place Entry popup properly
        data = self.treeView.set(rowID, column=column)
        self.entryPopup = EntryPopup(self.treeView, rowID, column, data, self.valueChanged)
        self.entryPopup.place( x=x, y=y+pady, anchor=W, relwidth=1)
        
    def valueChanged(self, rowID, column, value):
        if self.valueChangedCallback is not None:
            self.valueChangedCallback(rowID, column, value)
Exemple #14
0
class DialogOpenArchive(Toplevel):
    def __init__(self, mainWin, openType, filesource, filenames, title,
                 colHeader):
        parent = mainWin.parent
        super().__init__(parent)
        self.parent = parent
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)",
                                  parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))
        self.accepted = False

        self.transient(self.parent)
        self.title(title)

        frame = Frame(self)

        treeFrame = Frame(frame, width=500)
        vScrollbar = Scrollbar(treeFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(treeFrame, orient=HORIZONTAL)
        self.treeView = Treeview(treeFrame,
                                 xscrollcommand=hScrollbar.set,
                                 yscrollcommand=vScrollbar.set)
        self.treeView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.treeView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E, W))
        vScrollbar["command"] = self.treeView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N, S))
        treeFrame.columnconfigure(0, weight=1)
        treeFrame.rowconfigure(0, weight=1)
        treeFrame.grid(row=0,
                       column=0,
                       columnspan=4,
                       sticky=(N, S, E, W),
                       padx=3,
                       pady=3)
        self.treeView.focus_set()

        # set up treeView widget and tabbed pane
        self.treeView.column("#0", width=500, anchor="w")
        self.treeView.heading("#0", text=colHeader)
        try:
            self.isRss = filesource.isRss
            if self.isRss:
                self.treeView.column("#0", width=350, anchor="w")
                self.treeView["columns"] = ("descr", "date", "instDoc")
                self.treeView.column("descr",
                                     width=50,
                                     anchor="center",
                                     stretch=False)
                self.treeView.heading("descr", text="Form")
                self.treeView.column("date",
                                     width=170,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("date", text="Pub Date")
                self.treeView.column("instDoc",
                                     width=200,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("instDoc", text="Instance Document")
        except AttributeError:
            self.isRss = False

        mainWin.showStatus(_("loading archive {0}").format(filesource.url))
        self.filesource = filesource
        self.filenames = filenames
        selection = filesource.selection
        hasToolTip = False
        loadedPaths = []
        i = 0
        selectedNode = None
        for filename in self.filenames:
            if isinstance(filename, tuple):
                if self.isRss:
                    form, date, instDoc = filename[2:5]
                filename = filename[0]  # ignore tooltip
                hasToolTip = True
            if filename.endswith("/"):
                filename = filename[:-1]
            path = filename.split("/")
            if not self.isRss and len(path) > 1 and path[:-1] in loadedPaths:
                parent = "file{0}".format(loadedPaths.index(path[:-1]))
            else:
                parent = ""
            node = self.treeView.insert(parent,
                                        "end",
                                        "file{0}".format(i),
                                        text=path[-1])
            if self.isRss:
                self.treeView.set(node, "descr", form)
                self.treeView.set(node, "date", date)
                self.treeView.set(node, "instDoc", os.path.basename(instDoc))
            if selection == filename:
                selectedNode = node
            loadedPaths.append(path)
            i += 1
        if selectedNode:
            self.treeView.see(selectedNode)
            self.treeView.selection_set(selectedNode)
        mainWin.showStatus(None)

        if openType == DISCLOSURE_SYSTEM:
            y = 3
        else:
            y = 1

        okButton = Button(frame, text=_("OK"), command=self.ok)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        okButton.grid(row=y, column=2, sticky=(S, E, W), pady=3)
        cancelButton.grid(row=y, column=3, sticky=(S, E, W), pady=3, padx=3)

        frame.grid(row=0, column=0, sticky=(N, S, E, W))
        frame.columnconfigure(0, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        self.geometry("+{0}+{1}".format(dialogX + 50, dialogY + 100))

        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)

        self.toolTipText = StringVar()
        if hasToolTip:
            self.treeView.bind("<Motion>", self.motion, '+')
            self.treeView.bind("<Leave>", self.leave, '+')
            self.toolTipText = StringVar()
            self.toolTip = ToolTip(self.treeView,
                                   textvariable=self.toolTipText,
                                   wraplength=640,
                                   follow_mouse=True,
                                   state="disabled")
            self.toolTipRowId = None

        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        self.wait_window(self)

    def ok(self, event=None):
        selection = self.treeView.selection()
        if len(selection) > 0:
            filename = self.filenames[int(selection[0][4:])]
            if isinstance(filename, tuple):
                if self.isRss:
                    filename = filename[4]
                else:
                    filename = filename[0]
            if not filename.endswith("/"):
                self.filesource.select(filename)
                self.accepted = True
                self.close()

    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()

    def leave(self, *args):
        self.toolTipRowId = None

    def motion(self, *args):
        tvRowId = self.treeView.identify_row(args[0].y)
        if tvRowId != self.toolTipRowId:
            self.toolTipRowId = tvRowId
            newFileIndex = -1
            if tvRowId and len(tvRowId) > 4:
                try:
                    newFileIndex = int(tvRowId[4:])
                except ValueError:
                    pass
            self.setToolTip(newFileIndex)

    def setToolTip(self, fileIndex):
        self.toolTip._hide()
        if fileIndex >= 0 and fileIndex < len(self.filenames):
            filenameItem = self.filenames[fileIndex]
            if isinstance(filenameItem, tuple):
                self.toolTipText.set(filenameItem[1].replace("\\n", "\n"))
                self.toolTip.configure(state="normal")
                self.toolTip._schedule()
            else:
                self.toolTipText.set("")
                self.toolTip.configure(state="disabled")
        else:
            self.toolTipText.set("")
            self.toolTip.configure(state="disabled")