Пример #1
0
  def test_PlusModelCatalogBrowser1(self):

    self.delayDisplay("Starting the test")

    logic = PlusModelCatalogBrowserLogic()
    logic.showBrowser()
    logic.handleClick(qt.QUrl('http://perk-software.cs.queensu.ca/plus/doc/nightly/modelcatalog/'))
    logic.handleClick(qt.QUrl('http://perk-software.cs.queensu.ca/plus/doc/nightly/modelcatalog/printable/CauteryGrabber.STL'))
    logic.hideBrowser()

    self.assertIsNotNone( slicer.util.getNode('CauteryGrabber') )
    self.delayDisplay('Test passed!')
Пример #2
0
    def onURLReceived(self, urlString):
        """Process DICOM view requests. Example:
    slicer://viewer/?studyUID=2.16.840.1.113669.632.20.121711.10000158860
      &access_token=k0zR6WAPpNbVguQ8gGUHp6
      &dicomweb_endpoint=http%3A%2F%2Fdemo.kheops.online%2Fapi
      &dicomweb_uri_endpoint=%20http%3A%2F%2Fdemo.kheops.online%2Fapi%2Fwado
    """

        url = qt.QUrl(urlString)
        if (url.authority().lower() != "viewer"):
            return
        query = qt.QUrlQuery(url)
        queryMap = {}
        for key, value in query.queryItems(qt.QUrl.FullyDecoded):
            queryMap[key] = qt.QUrl.fromPercentEncoding(value)

        if not "dicomweb_endpoint" in queryMap:
            logging.error("Missing dicomweb_endpoint")
            return
        if not "studyUID" in queryMap:
            logging.error("Missing studyUID")
            return

        accessToken = None
        if "access_token" in queryMap:
            accessToken = queryMap["access_token"]

        slicer.util.selectModule("DICOM")
        slicer.app.processEvents()
        from DICOMLib import DICOMUtils
        DICOMUtils.importFromDICOMWeb(
            dicomWebEndpoint=queryMap["dicomweb_endpoint"],
            studyInstanceUID=queryMap["studyUID"],
            accessToken=accessToken)
Пример #3
0
    def printReport(self, currentValuesDict, callback):
        """ Generate a html report file and print it
        :param currentValuesDict: dictionary of GUI values
        """
        if not self.isCurrentReportSaved:
            # Save the report first
            self.saveReport(currentValuesDict)

        # Generate the snapshots of the images
        self.__printSnapshots__()

        self.callback = callback
        # Generate the html code
        html = self.__generateHtml__(currentValuesDict)

        # Write the html to a temp file
        p = os.path.join(self.getCurrentDataFolder(), "report.html")
        with open(p, "w+b") as f:
            f.write(html)

        self.webView = qt.QWebView()
        self.webView.settings().setAttribute(
            qt.QWebSettings.DeveloperExtrasEnabled, True)
        self.webView.connect('loadFinished(bool)',
                             self.__webViewFormLoadedCallback__)
        self.webView.show()
        u = qt.QUrl(p)
        self.webView.setUrl(u)
Пример #4
0
 def notifyChanged(self):
     elem = find_dita_class(traverse_to_element(self.__plugin()), \
         "topic/link", "topic/xref", "map/topicref")
     if not elem:
         return 1
     attr = elem.attrs().getAttribute("href")
     if attr.isNull() or attr.value().isEmpty():
         return 1
     path  = unicode(attr.value())
     pos   = path.find('#')
     idref = ""
     if pos >= 0:
         idref = path[pos+1:]
         path  = path[0:pos]
     if not path:
         return self.goLocal(elem, idref)
     sysurl = qt.QUrl(self.__sysid)
     if qt.QUrl.isRelativeUrl(path):
         tpath = qt.QUrl(sysurl)
         tpath.setFileName("")
         tpath.addPath(path)
         path = unicode(tpath.toString())
     if sysurl == qt.QUrl(path):
         return self.goLocal(elem, idref)
     format = elem.attrs().getAttribute("format")
     if format.isNull() or format.value().isEmpty():
         format = u""
     else:
         format = unicode(format.value())
     if format in (u"xml", u"dita", u"ditamap") or path.endswith(u".xml") or \
        path.endswith(u".dita") or path.endswith(u".ditamap"):
         self.openDocument(path)
         return 0
     if format is None or 0 == len(format):
         path = unicode(qt.QUrl(path).path())
     # Get path extension
         pos = path.rfind('.')
         if pos >= 0:
             format = path[pos+1:]
     ptn = PropertyNode("browser-params")
     ptn.makeDescendant("url").setString(norm_slashes(path))
     ptn.makeDescendant("extension").setString(unicode(format))
     rv = self.__plugin().executeCommandEvent("LaunchBrowser", ptn)
     return 0
Пример #5
0
  def onSwitchToSegmentEditor(self, link):
    if link == '#SwitchToSegmentEditor':
      slicer.util.selectModule('SegmentEditor')
      editorWidget = slicer.modules.segmenteditor.widgetRepresentation().self()
      if editorWidget is not None and self.helper is not None:
        masterNode = self.helper.masterSelector.currentNode()
        editorWidget.parameterSetNode.SetAndObserveMasterVolumeNode(masterNode)

    elif link == '#Feedback':
      qt.QDesktopServices.openUrl(qt.QUrl('http://massmail.spl.harvard.edu/mailman/listinfo/slicer-users'))
Пример #6
0
 def webViewFormTest(self):
     """Just as a demo, load a google search in a web view
     and use the qt api to fill in a search term"""
     self.webView = qt.QWebView()
     self.webView.settings().setAttribute(
         qt.QWebSettings.DeveloperExtrasEnabled, True)
     self.webView.connect('loadFinished(bool)',
                          self.webViewFormLoadedCallback)
     self.webView.show()
     u = qt.QUrl('https://www.google.com')
     self.webView.setUrl(u)
Пример #7
0
    def printPdf(
        self,
        htmlTemplatePath,
        values,
        callbackFunction,
        pdfOutputPath=None,
        imagesFileList=None,
        tempHtmlFolder=None,
    ):
        """
        Print a pdf file with the html stored in htmlPath and the specified values
        :param htmlTemplatePath: path to the html file that contains the template
        :param values: dictionary of values that will be used to build the final html
        :param callbackFunction: function that will be called when the process has finished (it is an asynchronous process)
        :param pdfOutputPath: path to the pdf file that will be created (if none, it will be saved in a temp file)
        :param imagesFileList: list of full paths to images that may be needed to generate the report
        :param tempHtmlFolder: folder where all the intermediate files will be stored. If none, a temporary folder will be used
        """
        if tempHtmlFolder is None:
            tempHtmlFolder = tempfile.mkdtemp()

        self.__pdfOutputPath__ = pdfOutputPath if pdfOutputPath is not None else os.path.join(
            tempHtmlFolder, "report.pdf")
        self.__callbackFunction__ = callbackFunction

        self.webView = qt.QWebView()
        self.webView.settings().setAttribute(
            qt.QWebSettings.DeveloperExtrasEnabled, True)
        self.webView.connect('loadFinished(bool)',
                             self.__webViewFormLoadedCallback__)
        self.webView.show()

        # Generate the Html
        with open(htmlTemplatePath, "r+b") as f:
            html = f.read()
        for key, value in values.iteritems():
            html = html.replace(key, value)

        # Save the file in the temporary folder
        htmlPath = os.path.join(tempHtmlFolder, "temp__.html")
        with open(htmlPath, "w") as f:
            f.write(html)
        logging.debug("Html generated in {}".format(htmlPath))

        # If we need images, copy them to the temporary folder
        if imagesFileList:
            for im in imagesFileList:
                fileName = os.path.basename(im)
                shutil.copy(im, os.path.join(tempHtmlFolder, fileName))

        # Assign the html file to the viewer
        u = qt.QUrl(htmlPath)
        self.webView.setUrl(u)
Пример #8
0
 def __init__(self, files, address, protocol=None, progressCallback=None):
     """protocol: can be DIMSE (default) or DICOMweb
 port: optional (if not specified then address URL should contain it)
 """
     super().__init__()
     self.files = files
     self.destinationUrl = qt.QUrl().fromUserInput(address)
     self.protocol = protocol if protocol is not None else "DIMSE"
     self.progressCallback = progressCallback
     if not self.progressCallback:
         self.progressCallback = self.defaultProgressCallback
     self.send()
Пример #9
0
  def __init__(self):
    self.catalogMainUrl = qt.QUrl('http://perk-software.cs.queensu.ca/plus/doc/nightly/modelcatalog/')
    self.catalogName = 'Plus toolkit 3D model catalog'

    self.browser = qt.QWebView()
    # Change QWebView such that link clicks are not automatically acted on
    # When links are clicked, run the handleClick() function
    self.browser.page().setLinkDelegationPolicy(qt.QWebPage.DelegateAllLinks)
    self.browser.linkClicked.connect(self.handleClick)

    self.downloadProgressBar = qt.QProgressDialog()
    self.downloadProgressBar.setLabelText('Downloading File')
Пример #10
0
    def onURLReceived(self, urlString):
        """Process DICOM view requests. Example:
        slicer://viewer/?studyUID=2.16.840.1.113669.632.20.121711.10000158860
          &access_token=k0zR6WAPpNbVguQ8gGUHp6
          &dicomweb_endpoint=http%3A%2F%2Fdemo.kheops.online%2Fapi
          &dicomweb_uri_endpoint=%20http%3A%2F%2Fdemo.kheops.online%2Fapi%2Fwado
        """

        url = qt.QUrl(urlString)
        if (url.authority().lower() != "viewer"):
            logging.debug("DICOM module ignores non-viewer URL: " + urlString)
            return
        query = qt.QUrlQuery(url)
        queryMap = {}
        for key, value in query.queryItems(qt.QUrl.FullyDecoded):
            queryMap[key] = qt.QUrl.fromPercentEncoding(value)

        if "dicomweb_endpoint" not in queryMap:
            logging.debug(
                "DICOM module ignores URL without dicomweb_endpoint query parameter: "
                + urlString)
            return
        if "studyUID" not in queryMap:
            logging.debug(
                "DICOM module ignores URL without studyUID query parameter: " +
                urlString)
            return

        logging.info("DICOM module received URL: " + urlString)

        accessToken = None
        if "access_token" in queryMap:
            accessToken = queryMap["access_token"]

        slicer.util.selectModule("DICOM")
        slicer.app.processEvents()
        from DICOMLib import DICOMUtils
        importedSeriesInstanceUIDs = DICOMUtils.importFromDICOMWeb(
            dicomWebEndpoint=queryMap["dicomweb_endpoint"],
            studyInstanceUID=queryMap["studyUID"],
            accessToken=accessToken)

        # Select newly loaded items to make it easier to load them
        self.browserWidget.dicomBrowser.setSelectedItems(
            ctk.ctkDICOMModel.SeriesType, importedSeriesInstanceUIDs)
Пример #11
0
 def onShowRegistrationParametersDatabaseFolder(self):
   qt.QDesktopServices().openUrl(qt.QUrl("file:///" + self.logic.registrationParameterFilesDir, qt.QUrl.TolerantMode));
Пример #12
0
 def onShowTemporaryFilesFolder(self):
   qt.QDesktopServices().openUrl(qt.QUrl("file:///" + self.logic.getTempDirectoryBase(), qt.QUrl.TolerantMode));
Пример #13
0
 def openLocalConnection(self):
     qt.QDesktopServices.openUrl(
         qt.QUrl(f'http://localhost:{self.logic.port}'))
Пример #14
0
    def test_WebEngine1(self):
        """ Testing WebEngine
    """

        self.delayDisplay("Starting the test")

        webWidget = slicer.qSlicerWebWidget()
        webWidget.size = qt.QSize(1024, 512)
        webWidget.webView().url = qt.QUrl("")
        webWidget.show()
        self.delayDisplay('Showing widget')

        webWidget.evalJS("""
        const paragraph = document.createElement('p');
        paragraph.innerText = 'Hello from Slicer!';
        document.body.appendChild(paragraph);
    """)
        self.delayDisplay('Slicer should be saying hello!')

        #
        # Test javascript evaluation + use of "evalResult()" signal
        #
        webWidget.connect("evalResult(QString,QString)", self.onEvalResult)

        self.delayDisplay('Slicer setting a javascript value')

        webWidget.evalJS("const valueFromSlicer = 42;")
        webWidget.evalJS("valueFromSlicer;")

        iteration = 0
        while not self.gotResponse and iteration < 3:
            # Specify an explicit delay to ensure async execution by the
            # webengine has completed.
            self.delayDisplay('Waiting for response...', msec=500)
            iteration += 1
        webWidget.disconnect("evalResult(QString,QString)", self.onEvalResult)

        if not self.gotResponse:
            raise RuntimeError("Never got response from evalJS")

        if not self.gotCorrectResponse:
            raise AssertionError("Did not get back expected result!")

        #
        # Test python evaluation from javascript
        #
        self.delayDisplay('Call a python method')

        slicer.app.settings().setValue("WebEngine/AllowPythonExecution",
                                       ctk.ctkMessageBox.AcceptRole)

        webWidget.evalJS(r"""
        let pythonCode = "dialog = qt.QInputDialog(slicer.util.mainWindow())\n";
        pythonCode += "dialog.setLabelText('hello')\n";
        pythonCode += "dialog.open()\n";
        pythonCode += "qt.QTimer.singleShot(1000, dialog.close)\n";

        window.slicerPython.evalPython(pythonCode);
    """)

        self.delayDisplay('Test access to python via js', msec=500)

        if hasattr(slicer.modules, 'slicerPythonValueFromJS'):
            del slicer.modules.slicerPythonValueFromJS

        webWidget.evalJS("""
        window.slicerPython.evalPython("slicer.modules.slicerPythonValueFromJS = 42");
    """)

        iteration = 0
        while iteration < 3 and not hasattr(slicer.modules,
                                            'slicerPythonValueFromJS'):
            # Specify an explicit delay to ensure async execution by the
            # webengine has completed.
            self.delayDisplay('Waiting for python value from JS...', msec=500)
            iteration += 1

        if iteration >= 3:
            raise RuntimeError("Couldn't get python value back from JS")

        self.delayDisplay('Value of %d received via javascipt' %
                          slicer.modules.slicerPythonValueFromJS)

        del slicer.modules.slicerPythonValueFromJS

        self.delayDisplay('Test passed!')
Пример #15
0
 def onEditSource(self):
     filePath = slicer.util.modulePath(self.moduleName)
     qt.QDesktopServices.openUrl(
         qt.QUrl("file:///" + filePath, qt.QUrl.TolerantMode))
Пример #16
0
    def send(self):
        self.progressCallback("Starting send to %s using self.protocol" %
                              self.destinationUrl.toString())

        if self.protocol == "DICOMweb":
            # DICOMweb
            # Ensure that correct version of dicomweb-client Python package is installed
            needRestart = False
            needInstall = False
            minimumDicomwebClientVersion = "0.51"
            try:
                import dicomweb_client
                from packaging import version
                if version.parse(dicomweb_client.__version__) < version.parse(
                        minimumDicomwebClientVersion):
                    if not slicer.util.confirmOkCancelDisplay(
                            f"DICOMweb sending requires installation of dicomweb-client (version {minimumDicomwebClientVersion} or later).\nClick OK to upgrade dicomweb-client and restart the application."
                    ):
                        self.showBrowserOnEnter = False
                        return
                    needRestart = True
                    needInstall = True
            except ModuleNotFoundError:
                needInstall = True

            if needInstall:
                # pythonweb-client 0.50 was broken (https://github.com/MGHComputationalPathology/dicomweb-client/issues/41)
                progressDialog = slicer.util.createProgressDialog(
                    labelText=
                    'Upgrading dicomweb-client. This may take a minute...',
                    maximum=0)
                slicer.app.processEvents()
                slicer.util.pip_install(
                    f'dicomweb-client>={minimumDicomwebClientVersion}')
                import dicomweb_client
                progressDialog.close()
            if needRestart:
                slicer.util.restart()

            # Establish connection
            import dicomweb_client.log
            dicomweb_client.log.configure_logging(2)
            from dicomweb_client.api import DICOMwebClient
            effectiveServerUrl = self.destinationUrl.toString()
            session = None
            headers = {}
            # Setting up of the DICOMweb client from various server parameters can be done
            # in plugins in the future, but for now just hardcode special initialization
            # steps for a few server types.
            if "kheops" in effectiveServerUrl:
                # Kheops DICOMweb API endpoint from browser view URL
                url = qt.QUrl(effectiveServerUrl)
                if url.path().startswith('/view/'):
                    # This is a Kheops viewer URL.
                    # Retrieve the token from the viewer URL and use the Kheops API URL to connect to the server.
                    token = url.path().replace('/view/', '')
                    effectiveServerUrl = "https://demo.kheops.online/api"
                    from requests.auth import HTTPBasicAuth
                    from dicomweb_client.session_utils import create_session_from_auth
                    auth = HTTPBasicAuth('token', token)
                    session = create_session_from_auth(auth)

            client = DICOMwebClient(url=effectiveServerUrl,
                                    session=session,
                                    headers=headers)

            for file in self.files:
                if not self.progressCallback(
                        f"Sending {file} to {self.destinationUrl.toString()} using {self.protocol}"
                ):
                    raise UserWarning(
                        "Sending was cancelled, upload is incomplete.")
                import pydicom
                dataset = pydicom.dcmread(file)
                client.store_instances(datasets=[dataset])
        else:
            # DIMSE (traditional DICOM networking)
            for file in self.files:
                self.start(file)
                if not self.progressCallback(
                        f"Sent {file} to {self.destinationUrl.host()}:{self.destinationUrl.port()}"
                ):
                    raise UserWarning(
                        "Sending was cancelled, upload is incomplete.")
Пример #17
0
 def onShowCreatedOutputFile(self):
     if not self.createdOutputFile:
         return
     qt.QDesktopServices().openUrl(
         qt.QUrl("file:///" + self.createdOutputFile, qt.QUrl.TolerantMode))
Пример #18
0
 def openURL(self, URL):
     qt.QDesktopServices().openUrl(qt.QUrl(URL))
     QDesktopServices
Пример #19
0
    def printPdf(
        self,
        htmlTemplatePath,
        values,
        callbackFunction,
        pdfOutputPath=None,
        imagesFileList=None,
        tempHtmlFolder=None,
    ):
        """
        Print a pdf file with the html stored in htmlPath and the specified values
        :param htmlTemplatePath: path to the html file that contains the template
        :param values: dictionary of values that will be used to build the final html
        :param callbackFunction: function that will be called when the process has finished (it is an asynchronous process)
        :param pdfOutputPath: path to the pdf file that will be created (if none, it will be saved in a temp file)
        :param imagesFileList: list of full paths to images that may be needed to generate the report
        :param tempHtmlFolder: folder where all the intermediate files will be stored. If none, a temporary folder will be used
        """
        if tempHtmlFolder is None:
            tempHtmlFolder = tempfile.mkdtemp()

        self.__pdfOutputPath__ = pdfOutputPath if pdfOutputPath is not None else os.path.join(
            tempHtmlFolder, "report.pdf")
        self.__callbackFunction__ = callbackFunction

        # Generate the Html
        with open(htmlTemplatePath, "r") as f:
            html = f.read()
        for key, value in values.items():
            html = html.replace(key, value)

        # If we need images, copy them to the temporary folder
        if imagesFileList:
            for im in imagesFileList:
                fileName = os.path.basename(im)
                shutil.copy(im, os.path.join(tempHtmlFolder, fileName))

        if hasattr(qt, 'QWebView'):
            # Save the file in the temporary folder
            htmlPath = os.path.join(tempHtmlFolder, "temp__.html")
            with open(htmlPath, "w") as f:
                f.write(html)
            logging.debug("Html generated in {}".format(htmlPath))
            # Create a web browser for rendering html
            self.webView = qt.QWebView()
            self.webView.settings().setAttribute(
                qt.QWebSettings.DeveloperExtrasEnabled, True)
            self.webView.connect('loadFinished(bool)',
                                 self.__webViewFormLoadedCallback__)
            u = qt.QUrl(htmlPath)
            self.webView.setUrl(u)
            self.webView.show()
        else:
            printer = qt.QPrinter(qt.QPrinter.PrinterResolution)
            printer.setOutputFormat(qt.QPrinter.PdfFormat)
            printer.setPaperSize(qt.QPrinter.A4)
            printer.setOutputFileName(self.__pdfOutputPath__)

            doc = qt.QTextDocument()
            doc.setHtml(html)
            doc.baseUrl = qt.QUrl.fromLocalFile(tempHtmlFolder + "/")
            doc.setPageSize(qt.QSizeF(
                printer.pageRect().size()))  # hide the page number
            doc.print(printer)

            # Call the callback
            self.__callbackFunction__(self.__pdfOutputPath__)
            self.__callbackFunction__ = None
Пример #20
0
 def onHelpBrowserPressed(self):
     qt.QDesktopServices.openUrl(qt.QUrl("https://fastslice.github.io/"))