Ejemplo n.º 1
0
 def play(self, url, **kwargs):
     """
 @param  url  str or QUrl
 """
     if not isinstance(url, QUrl):
         url = QUrl(url)
     for k, v in kwargs.iteritems():
         #url.addQueryItem(k, v)
         if not isinstance(v, basestring):
             v = "%s" % v
         url.addEncodedQueryItem(k, QUrl.toPercentEncoding(v))
     self.__d.webView.load(url)
Ejemplo n.º 2
0
    def show(self, qml_file):
        self.app = QApplication([])
        self.view = QDeclarativeView()
        self.view.setResizeMode(QDeclarativeView.SizeRootObjectToView)
        self.view.setSource(QUrl(qml_file))
        self.ctxt = self.view.rootContext()
        self.cmd.ctxt = self.ctxt
        self.ctxt.setContextProperty("cmd", self.cmd)
        self.cmd.finish.connect(self.view.rootObject().finish)
        #self.ctxt.setContextProperty("dist", self.cmd.abort())

        self.view.show()
        self.app.exec_()
Ejemplo n.º 3
0
 def get(self, url, local_path):
     print "url", url
     print "local_path", local_path
     self.url = url
     self.local_path = local_path
     self.mb = DownloadMessageBox(self.parent())
     self.mb.buttonClicked.connect(self.handleCancel)
     self.mb.rejected.connect(self.handleReject)
     mgr = QNetworkAccessManager(self)
     mgr.finished.connect(self.handleFinished)
     self.reply = mgr.get(QNetworkRequest(QUrl(url)))
     self.reply.downloadProgress.connect(self.mb.updateProgress)
     self.mb.exec_()
Ejemplo n.º 4
0
 def downlaod(self, url, timeout=60):
     loop = QEventLoop()
     timer = QTimer()
     timer.setSingleShot(True)
     timer.timeout.connect(loop.quit)
     self.loadFinished.connect(loop.quit)
     self.load(QUrl(url))
     timer.start(timeout * 1000)
     loop.exec_()
     if timer.isActive():
         timer.stop()
         return self.html()
     else:
         print 'Request timed out: ' + url
Ejemplo n.º 5
0
 def show_about(self):
     msg = QMessageBox()
     msg.setIcon(QMessageBox.Question)
     msg.setText("SpyKING CIRCUS v%s" % circus.__version__)
     msg.setWindowTitle("About")
     msg.setInformativeText("Documentation can be found at\n"
                            "http://spyking-circus.rtfd.org\n"
                            "\n"
                            "Open a browser to see the online help?")
     msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
     msg.setDefaultButton(QMessageBox.No)
     answer = msg.exec_()
     if answer == QMessageBox.Yes:
         QDesktopServices.openUrl(QUrl("http://spyking-circus.rtfd.org"))
Ejemplo n.º 6
0
    def __connectHttpServer(self):
        retCode = True
        retCode &= not self.leGraylogIP.text()
        retCode &= not self.leGraylogPort.text()

        if (not retCode):
            self.view.load(
                QUrl("http://" + self.leGraylogIP.text() + ":" +
                     self.leGraylogHttpPort.text() +
                     "/dashboards/59ef8317ac4207031e41f294"))
            self.view.show()
        else:
            QMessageBox.warning(
                self, "Error",
                "Please, fill Graylog IP and Http Port before connect!",
                QMessageBox.Ok)
Ejemplo n.º 7
0
def main():
    app = QApplication([])
    view = QDeclarativeView()
    manager = TodoManager()
    context = view.rootContext()
    context.setContextProperty("manager", manager)

    url = QUrl('main.qml')
    view.setSource(url)

    if "-no-fs" not in sys.argv:
        view.showFullScreen()
    else:
        view.show()

    app.exec_()
Ejemplo n.º 8
0
def main():

    app = QApplication([])

    view = QWebView()
    fac = PluginFactory()
    view.page().setPluginFactory(fac)
    QWebSettings.globalSettings().setAttribute(QWebSettings.PluginsEnabled,
                                               True)

    view.load(QUrl(sys.argv[1]))

    view.resize(840, 600)
    view.show()

    return app.exec_()
Ejemplo n.º 9
0
def main():
    app = QApplication([])
    webview = QWebView()
    loop = QEventLoop()
    webview.loadFinished.connect(loop.quit)
    webview.load(QUrl('http://example.webscraping.com/search'))
    loop.exec_()

    webview.show()
    frame = webview.page().mainFrame()
    frame.findFirstElement('#search_term').setAttribute('value', '.')
    frame.findFirstElement('#page_size option:checked').setPlainText('1000')
    frame.findFirstElement('#search').evaluateJavaScript('this.click()')

    elements = None
    while not elements:
        app.processEvents()
Ejemplo n.º 10
0
 def open(self, url, timeout=60):
     """Wait for download to complete and return result"""
     loop = QEventLoop()
     timer = QTimer()
     timer.setSingleShot(True)
     timer.timeout.connect(loop.quit)
     self.loadFinished.connect(loop.quit)
     self.load(QUrl(url))
     timer.start(timeout * 1000)
     loop.exec_()  # delay here until download finished
     if timer.isActive():
         # downloaded successfully
         timer.stop()
         return self.html()
     else:
         # timed out
         print 'Request timed out:', url
Ejemplo n.º 11
0
    def __init__(self, url, title=None, geometry=None, icon=None):
        super(Browser, self).__init__()
        
        self.setGeometry(*geometry)
        self.setWindowTitle(title)
        
        if icon:
            pixmap = QtGui.QPixmap()
            if type(icon) == tuple:  # package, not filepath
                img_data = pkgutil.get_data(*icon)
            else:
                with open(icon) as fh:
                    img_data = fh.read()
            pixmap.loadFromData(QByteArray(img_data))
            self.setWindowIcon(QtGui.QIcon(pixmap))

        self.load(QUrl(url))
Ejemplo n.º 12
0
    def __init__(self,
                 parent,
                 Title='Tutorial_Name',
                 TutorialBlob='Text Here',
                 TutorialVideo='Insert URL Here'):
        QtGui.QDialog.__init__(self)
        self.WindowLabel = Title
        videoView = QtWebKit.QWebView()
        videoURL = TutorialVideo
        videoView.load(QUrl(videoURL))
        videoView.show()

        layout = QtGui.QGridLayout()
        layout.addWidget(videoView, 0, 0)
        #        layout.addWidget(textBlobWindow,1,0)
        self.setWindowTitle(self.WindowLabel)
        self.setLayout(layout)
Ejemplo n.º 13
0
 def get(self, url, path):
     """
 @param  url  unicode or QUrl
 @param  unicode  path
 @return  bool  whether succeeded
 """
     dprint('enter:', url)
     d = self.__d
     d.stop()
     if d.openFile(path):
         if not isinstance(url, QUrl):
             url = QUrl(url)
         d.request = QNetworkRequest(url)
         ok = d.start()
     else:
         ok = False
     dprint('leave: ret = %s' % ok)
     return ok
Ejemplo n.º 14
0
    def testPlugin(self):
        view = QWebView()
        fac = PluginFactory()
        view.page().setPluginFactory(fac)
        QWebSettings.globalSettings().setAttribute(QWebSettings.PluginsEnabled,
                                                   True)

        view.load(
            QUrl(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'qmlplugin', 'index.html')))

        view.resize(840, 600)
        view.show()

        QTimer.singleShot(500, self.app.quit)

        self.app.exec_()
Ejemplo n.º 15
0
def main():
    app = QApplication([])
    webview = QWebView()
    loop = QEventLoop()
    webview.loadFinished.connect(loop.quit)
    webview.load(QUrl('http://example.webscraping.com/places/default/search'))
    loop.exec_()
    webview.show()
    frame = webview.page().mainFrame()
    frame.findFirstElement('#search_term').setAttribute('value', '.')
    frame.findFirstElement('#page_size option').setPlainText('1000') #设置纯文本
    frame.findFirstElement('#search').evaluateJavaScript('this.click()')
    app.exec_()
    elements = None
    while not elements:
        app.processEvents()
        elements = frame.findAllElements('#results a')
        countries = [e.toPlainText().strip() for e in elements]
        print countries
Ejemplo n.º 16
0
def toproxyurl(url):  # QUrl -> QUrl or None
    proxy = _SCHEME_PROXY.get(url.scheme())
    if proxy:
        url = QUrl(url)  # Avoid modifying the original URL
        host = _normalize_host(url.host())
        ip = _PROXY_DOMAINS.get(host) if _MAINLAND else None
        if ip:
            url.setHost(ip)
        else:
            key = _PROXY_SITES.get(host)
            if not key and _MAINLAND:
                key = _DLSITE_PROXY_SITES.get(
                    host) or _TORANOANA_PROXY_SITES.get(host)
            if key:
                url.setHost(config.PROXY_HOST)
                path = proxy + key + url.path()
                url.setPath(path)
        #print url
        return url
Ejemplo n.º 17
0
    def __init__(self, *args):
        super(OverlayWidget, self).__init__(*args)

        # Set this widget itself to be transparent
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)

        # We need to set the base colour of the qml widget to be transparent.
        # This is done by setting its palette.
        palette = QtGui.QPalette()
        palette.setColor(QtGui.QPalette.Base, QtCore.Qt.transparent)

        self.setPalette(palette)

        self.qml_view = QDeclarativeView(self)
        self.qml_view.setResizeMode(QDeclarativeView.SizeRootObjectToView)
        self.qml_view.setPalette(palette)

        url = QUrl('drawer_demo.qml')
        self.qml_view.setSource(url)
Ejemplo n.º 18
0
    def testInsert(self):
        myHash = {}
        qdate = QDate.currentDate()
        qdatetime = QDateTime.currentDateTime()
        qtime = QTime.currentTime()
        qurl = QUrl("http://www.pyside.org")
        qpoint = QPoint(12, 42)

        myHash[qdate] = "QDate"
        myHash[qdatetime] = "QDateTime"
        myHash[qtime] = "QTime"
        myHash[qurl] = "QUrl"
        myHash[qpoint] = "QPoint"

        self.assertEqual(myHash[qdate], "QDate")
        self.assertEqual(myHash[qdatetime], "QDateTime")
        self.assertEqual(myHash[qtime], "QTime")
        self.assertEqual(myHash[qurl], "QUrl")
        self.assertEqual(myHash[qpoint], "QPoint")
Ejemplo n.º 19
0
    def downloadFile(self, path, setting):
        self.progress_text = 'Downloading {}'.format(path.replace(self.base_url.format(self.selected_version()),''))

        url = QUrl(path)
        fileInfo = QFileInfo(url.path())
        fileName = setting.save_file_path(self.selected_version())

        archive_exists = QFile.exists(fileName)

        dest_files_exist = True

        for dest_file in setting.dest_files:
            dest_file_path = os.path.join('files', setting.name, dest_file)
            dest_files_exist &= QFile.exists(dest_file_path)

        forced = self.getSetting('force_download').value

        if (archive_exists or dest_files_exist) and not forced:
            self.continueDownloadingOrExtract()
            return #QFile.remove(fileName)

        self.outFile = QFile(fileName)
        if not self.outFile.open(QIODevice.WriteOnly):
            self.show_error('Unable to save the file {}: {}.'.format(fileName, self.outFile.errorString()))
            self.outFile = None
            self.enableUI()
            return

        mode = QHttp.ConnectionModeHttp
        port = url.port()
        if port == -1:
            port = 0
        self.http.setHost(url.host(), mode, port)
        self.httpRequestAborted = False

        path = QUrl.toPercentEncoding(url.path(), "!$&'()*+,;=:@/")
        if path:
            path = str(path)
        else:
            path = '/'

        # Download the file.
        self.httpGetId = self.http.get(path, self.outFile)
Ejemplo n.º 20
0
    def runner(args, index_path, out_dir):
        app = QApplication(sys.argv)

        frame = MainWindow()
        frame.setWindowTitle('hwp5view')
        frame.setMinimumWidth(400)

        url = fspath2url(index_path)
        url = QUrl(url)
        view = QWebView(frame)

        logger.info('Loading...')
        view.load(url)

        @view.loadFinished.connect
        def onLoadFinished():
            frame.show()

        frame.setCentralWidget(view)

        app.exec_()
Ejemplo n.º 21
0
    def open(self,
             address,
             method='get',
             headers={},
             auth=None,
             body=None,
             default_popup_response=None):
        """Opens a web page.

        :param address: The resource URL.
        :param method: The Http method.
        :param headers: An optional dict of extra request hearders.
        :param auth: An optional tuple of HTTP auth (username, password).
        :param body: An optional string containing a payload.
        :param default_popup_response: the default response for any confirm/
        alert/prompt popup from the Javascript (replaces the need for the with
        blocks)
        :return: Page resource, All loaded resources.
        """
        body = body or QByteArray()
        try:
            method = getattr(QNetworkAccessManager,
                             "%sOperation" % method.capitalize())
        except AttributeError:
            raise Error("Invalid http method %s" % method)
        request = QNetworkRequest(QUrl(address))
        request.CacheLoadControl(0)
        for header in headers:
            request.setRawHeader(header, headers[header])
        self._auth = auth
        self._auth_attempt = 0  # Avoids reccursion

        self.main_frame.load(request, method, body)
        self.loaded = False

        if default_popup_response is not None:
            Ghost._prompt_expected = (default_popup_response, None)
            Ghost._confirm_expected = (default_popup_response, None)

        return self.wait_for_page_loaded()
Ejemplo n.º 22
0
def main():
    app = QApplication([])
    app.setApplicationName('Audio Output Test')
    view = QDeclarativeView()

    devices = []
    for info in QAudioDeviceInfo.availableDevices(QAudio.AudioOutput):
        devices.append(info)

    player = TonePlayer(devices, sys.argv[1] if len(sys.argv) > 1 else None)

    context = view.rootContext()
    context.setContextProperty("player", player)
    context.setContextProperty("deviceModel",
                               [x.deviceName() for x in devices])

    url = QUrl('main.qml')
    view.setSource(url)

    view.show()

    app.exec_()
Ejemplo n.º 23
0
 def create_params_file(self, fname):
     msg = QMessageBox()
     msg.setIcon(QMessageBox.Question)
     msg.setText("Parameter file %r not found, do you want SpyKING CIRCUS to "
                 "create it for you?" % fname)
     msg.setWindowTitle("Generate parameter file?")
     msg.setInformativeText("This will create a parameter file from a "
                            "template file and open it in your system's "
                            "standard text editor. Fill properly before "
                            "launching the code. See the documentation "
                            "for details")
     msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
     answer = msg.exec_()
     if answer == QMessageBox.Yes:
         user_path = os.path.join(os.path.expanduser('~'), 'spyking-circus')
         if os.path.exists(user_path + 'config.params'):
             config_file = os.path.abspath(user_path + 'config.params')
         else:
             config_file = os.path.abspath(
                 pkg_resources.resource_filename('circus', 'config.params'))
         shutil.copyfile(config_file, fname)
         QDesktopServices.openUrl(QUrl(fname))
    def __init__(self, *args):
        super(OverlayWidget, self).__init__(*args)

        # We need to set the base colour of the qml widget to be transparent.
        # This is done by setting its palette.
        palette = QtGui.QPalette()
        palette.setColor(QtGui.QPalette.Base, QtCore.Qt.transparent)

        qml_view = QDeclarativeView(self)
        qml_view.setPalette(palette)

        qml_context = qml_view.rootContext()
        qml_context.setContextProperty("slider_handler", self)

        url = QUrl('control_slides.qml')
        qml_view.setSource(url)

        qml_root = qml_view.rootObject()
        self.x_rotation_changed.connect(qml_root.x_rotation_changed)
        self.y_rotation_changed.connect(qml_root.y_rotation_changed)
        self.z_rotation_changed.connect(qml_root.z_rotation_changed)

        return
Ejemplo n.º 25
0
    def testSetAttributes(self):
        #Construct QUrl by set* methods
        url = QUrl()

        url.setScheme('ftp')
        self.assertEqual(url.toString(), 'ftp:')

        url.setHost('www.google.com')
        self.assertEqual(url.toString(), 'ftp://www.google.com')

        url.setPort(8080)
        self.assertEqual(url.toString(), 'ftp://www.google.com:8080')

        url.setPath('mail/view')
        self.assertEqual(url.toString(), 'ftp://www.google.com:8080/mail/view')

        url.setUserName('john')
        self.assertEqual(url.toString(),
                         'ftp://[email protected]:8080/mail/view')

        url.setPassword('abc123')
        self.assertEqual(url.toString(),
                         'ftp://*****:*****@www.google.com:8080/mail/view')
Ejemplo n.º 26
0
def main():
    '''
    首先设置搜索参数和模拟动作事件,获取在此参数和动作下搜索后得到的网页
    然后在这网页下,获取数据
    '''
    app = QApplication([])
    webview = QWebView()
    loop = QEventLoop()
    webview.loadFinished.connect(loop.quit)
    webview.load(QUrl('http://example.webscraping.com/places/default/search'))
    loop.exec_()

    webview.show()  ## 显示渲染窗口,,可以直接在这个窗口里面输入参数,执行动作,方便调试
    frame = webview.page().mainFrame()
    ## 设置搜索参数
    # frame.findAllElements('#search_term') ##寻找所有的search_term框,返回的是列表
    # frame.findAllElements('#page_size option:checked')
    # ## 表单使用evaluateJavaScript()方法进行提交,模拟点击事件
    # frame.findAllElements('#search')

    frame.findFirstElement('#search_term').setAttribute('value',
                                                        '.')  ##第一个search_term框
    frame.findFirstElement('#page_size option:checked').setPlainText(
        '1000')  ##第一个page_size框
    ## 表单使用evaluateJavaScript()方法进行提交,模拟点击事件
    frame.findFirstElement('#search').evaluateJavaScript(
        'this.click()')  ##第一个点击框

    ## 轮询网页,等待特定内容出现
    ## 下面不断循环,直到国家链接出现在results这个div元素中,每次循环都会调用app.processEvents()
    ##用于给QT事件执行任务的时间,比如响应事件和更新GUI
    elements = None
    while not elements:
        app.processEvents()
        elements = frame.findAllElements('#results a')  ##查找下载网页内的所有a标签
    countries = [e.toPlainText().strip() for e in elements]  ##取出所有a标签内的文本内容
    print countries
Ejemplo n.º 27
0
        def __init__(self,window, layout = None, imageform = None, backto = None, title = None):
                super (ImageListView, self).__init__()
                
                #导入这个页面的视图
                self.father_layout = layout
                self.setStyleSheet("QToolBar {background-color:#b60400; border-bottom:2px solid #b60400} QLabel{color:white; font-size:19px}")
                self.window = window

                self.backto = backto

                self.setContentsMargins(0,0,0,0)
                self.Layout = QVBoxLayout()
                self.Layout.setSpacing(0)
                self.Layout.setContentsMargins(0,0,0,0)

                self.Bar = QToolBar("ToolBar")
                self.Bar.setFloatable(False)
                self.Bar.setMovable(False)
                self.Bar.setIconSize(QSize(44,44))

                self.return_action = QAction(QIcon.fromTheme("new", QIcon(":/icons/return.png")), u"返回",
                self)

                self.return_btn = QToolButton()
                self.return_btn.setDefaultAction(self.return_action)
                self.return_btn.setToolButtonStyle(Qt.ToolButtonIconOnly)
                self.return_btn.triggered.connect(self.back)

                
                
                self.clear_bar_left = QToolBar("Fix")
                
                self.Bar.addWidget(self.clear_bar_left)
                self.clear_bar_left.addWidget(self.return_btn)

                self.label = QLabel(title)
                self.Bar.addWidget(self.label)
                
                self.clear_bar_right = QToolBar("Fix")
                self.clear_bar_right.setSizePolicy(QSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding))
                self.Bar.addWidget(self.clear_bar_right)
                self.Bar.setIconSize(QSize(44,44))




                self.setLayout(self.Layout)


                self.view = QtDeclarative.QDeclarativeView()
                self.view.setResizeMode(QtDeclarative.QDeclarativeView.SizeRootObjectToView)

                self.rc = self.view.rootContext()
                self.controller = ImageListController(window,layout,imageform)
                self.rc.setContextProperty('controller', self.controller)
                self.rc.setContextProperty('bili', self.window.bili)
                self.rc.setContextProperty('imagenum', self.window.imagenum)
                
                self.view.setSource(QUrl('qrc:/UI/imagelist.qml'))

                self.Layout.addWidget(self.Bar)
                self.Layout.addWidget(self.view)
Ejemplo n.º 28
0
if __name__ == '__main__':
    import sys
    QtGui.QApplication.setGraphicsSystem("raster")
    app = QtGui.QApplication(sys.argv)

    username, ok = QtGui.QInputDialog.getText(None, "Username", "Username:"******"Must provide a username")
        sys.exit(1)

    password, ok = QtGui.QInputDialog.getText(None, "Password", "Password:"******"Must provide a password")
        sys.exit(1)

    data = Picasa(username, password)

    view = QtDeclarative.QDeclarativeView()
    engine = view.engine()
    engine.quit.connect(app.quit)
    albums = data.getAlbumListModel()
    view.rootContext().setContextProperty("albumModel", albums)
    context = view.rootContext()
    view.setSource(QUrl('photoviewer.qml'))
    view.show()

    sys.exit(app.exec_())
Ejemplo n.º 29
0
# html = get_results(url, headers=headers)
# parser = etree.XMLParser(recover=True)
# tree = etree.fromstring(html,parser)
# print(tree.cssselect('#result')[0].text)

#初始化一个QApplication对象,
app = QApplication([])
#创建一个QWebView对象,用于web文档的容器
webview = QWebView()
# 创建一个QEventLoop对象,用于创建本地时间循环
loop = QEventLoop()
# loadFinished回调连接了QEventLoop的quit方法,可以在网页加载完成之后停止事件循环
webview.loadFinished.connect(loop.quit)
#将要加载的url传给QWebView,PyQt将该url的字符串封装在QUrl对象中
webview.load(QUrl(url))
# 等待网页加载完成,在事件循环启动时调用loop.exec_
loop.exec_()


# 网页加载完成后退出事件循环
# html = webview.page().mainFrame().toHtml()
# # 对加载的网页产生的HTMl进行数据抽取
# parser = etree.XMLParser(recover=True)
# tree = etree.fromstring(html,parser)
# print(tree.cssselect('#result')[0].text)


webview.show()
frame = webview.page().mainFrame()
#找到id为search_term的标签,设置搜索值为.号(表示搜索全部结果)
    def writeCSVReportForShotSelection(self,
                                       shotSelection=None,
                                       savePath=None):
        """Writes a csv file from a shotSelection, optionally saves tagged shots only. If running"""

        if not shotSelection:
            shotSelection = getSelectedShotsForActiveView()

        if len(shotSelection) <= 0:
            # If we're here we have no shots to work with - bail out.
            return

        sequence = shotSelection[0].parentSequence()
        tagDict = self.buildUniqueTagsDictFromShotSelection(shotSelection)

        if not savePath:
            currentTimeString = datetime.datetime.strftime(
                datetime.datetime.now(), '%Y-%m-%d_%H-%M-%S')
            saveName = "TagReport_%s_%s.csv" % (sequence.name().replace(
                " ", "_"), currentTimeString)
            csvSavePath = os.path.join(os.getenv('HOME'), 'Desktop', saveName)
            savePath = openFileBrowser(caption="Save Tag Report .CSV as...",
                                       initialPath=csvSavePath,
                                       mayNotExist=True,
                                       forSave=True,
                                       pattern="*.csv")
            print "Save path %s" % savePath
            # A list is returned here, we SHOULD only get one file name, but force this to be only one, then check for .csv extension.
            if len(savePath) != 1:
                return
            else:
                savePath = savePath[0]

            if not savePath.lower().endswith(".csv"):
                savePath + ".csv"

        if len(savePath) == 0:
            return

        # The Header row for the CSV will contain some basic info re. the shot...
        sortedTagNames = sorted(tagDict)

        ### THIS HEADER MUST MATCH THE table_data line below ###
        csvHeader = [
            "Shot Name", "Duration", "Source Clip", "Track", "Type", "No. Tags"
        ]

        # Plus Tag names as columns
        if len(sortedTagNames) > 0:
            csvHeader.extend(sortedTagNames)

        # Get a CSV writer object
        csvFile = open(savePath, 'w')
        csvWriter = csv.writer(csvFile,
                               delimiter=',',
                               quotechar='|',
                               quoting=csv.QUOTE_MINIMAL)

        # Write the Header row to the CSV file
        csvWriter.writerow(csvHeader)

        for shot in shotSelection:
            currentTags = shot.tags()
            currentShotTagNames = [tag.name() for tag in currentTags]

            ### THIS LIST MUST MATCH THE csvHeader above ###
            table_data = [
                shot.name(),
                shot.duration(),
                shot.source().name(),
                shot.parentTrack().name(),
                shotMediaType(shot),
                str(len(currentTags))
            ]

            # Then add the remaining columns as TRUE/FALSE values in the tag columns
            for tag in sortedTagNames:
                if tag in currentShotTagNames:
                    table_data += ["TRUE"]
                else:
                    table_data += ["FALSE"]
            csvWriter.writerow(table_data)

        # Be good and close the file
        csvFile.close()
        print 'CSV Tag Report saved to: ' + str(savePath)

        # Conveniently show the CSV file in the native file browser...
        QDesktopServices.openUrl(
            QUrl('file:///%s' % (os.path.dirname(savePath))))