def add_link_task(self):
        '''新建普通的链接任务'''
        def do_add_link_task(source_url):
            def on_link_task_added(info, error=None):
                if error or not info:
                    logger.error('CloudPage.do_add_link_task: %s, %s' %
                                 (info, error))
                    self.app.toast(_('Failed to parse download link'))
                    return
                if info.get('error_code', -1) != 0:
                    logger.error('CloudPage.do_add_link_task: %s, %s' %
                                 (info, error))

                if 'task_id' in info or info['error_code'] == 0:
                    self.reload()
                elif info['error_code'] == -19:
                    vcode = info['vcode']
                    vcode_dialog = VCodeDialog(self, self.app, info)
                    response = vcode_dialog.run()
                    vcode_input = vcode_dialog.get_vcode()
                    vcode_dialog.destroy()
                    if response != Gtk.ResponseType.OK:
                        return
                    gutil.async_call(pcs.cloud_add_link_task, self.app.cookie,
                                     self.app.tokens, source_url, save_path,
                                     vcode, vcode_input,
                                     callback=on_link_task_added)
                else:
                    self.app.toast(_('Error: {0}').format(info['error_msg']))
            gutil.async_call(pcs.cloud_add_link_task, self.app.cookie,
                             self.app.tokens, source_url, save_path,
                             callback=on_link_task_added)

        self.check_first()
        dialog = Gtk.Dialog(_('Add new link tasks'), self.app.window,
                            Gtk.DialogFlags.MODAL,
                            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
                            Gtk.STOCK_OK, Gtk.ResponseType.OK))
        dialog.set_border_width(10)
        dialog.set_default_size(480, 300)
        dialog.set_default_response(Gtk.ResponseType.OK)
        box = dialog.get_content_area()
        scrolled_win = Gtk.ScrolledWindow()
        box.pack_start(scrolled_win, True, True, 0)
        links_buf = Gtk.TextBuffer()
        links_tv = Gtk.TextView.new_with_buffer(links_buf)
        links_tv.set_tooltip_text(_('Paste links here, line by line'))
        scrolled_win.add(links_tv)

        infobar = Gtk.InfoBar()
        infobar.set_message_type(Gtk.MessageType.INFO)
        box.pack_start(infobar, False, False, 5)
        info_content = infobar.get_content_area()
        info_label = Gtk.Label.new(
            _('Support http/https/ftp/thunder/qqdl/flashget/eMule/Magnet format'))
        info_content.pack_start(info_label, False, False, 0)

        box.show_all()
        response = dialog.run()
        contents = gutil.text_buffer_get_all_text(links_buf)
        dialog.destroy()
        if response != Gtk.ResponseType.OK or not contents:
            return
        link_tasks = []
        bt_tasks = []
        for source_url in contents.split('\n'):
            source_url = source_url.strip()
            if not source_url:
                continue
            if source_url.startswith('magnet'):
                bt_tasks.append(source_url)
            else:
                priv_url = decoder.decode(source_url)
                if priv_url:
                    link_tasks.append(priv_url)
                else:
                    link_tasks.append(source_url)

        folder_browser = FolderBrowserDialog(self, self.app, _('Save to..'))
        response = folder_browser.run()
        save_path = folder_browser.get_path()
        folder_browser.destroy()
        if response != Gtk.ResponseType.OK or not save_path:
            return
        for source_url in link_tasks:
            do_add_link_task(source_url)
        for source_url in bt_tasks:
            self.add_cloud_bt_task(source_url, save_path)