Exemple #1
0
def web_obj(temp_dir, common_obj, mode, num_files=0):
    """Creates a Web object, in either share mode or receive mode, ready for testing"""
    common_obj.settings = Settings(common_obj)
    mode_settings = ModeSettings(common_obj)
    web = Web(common_obj, False, mode_settings, mode)
    web.running = True

    web.cleanup_tempfiles == []
    web.cleanup_tempdirs == []
    web.app.testing = True

    # Share mode
    if mode == "share":
        # Add files
        files = []
        for _ in range(num_files):
            with tempfile.NamedTemporaryFile(delete=False,
                                             dir=temp_dir.name) as tmp_file:
                tmp_file.write(b"*" * 1024)
                files.append(tmp_file.name)
        web.share_mode.set_file_info(files)
    # Receive mode
    else:
        pass

    return web
Exemple #2
0
    def init(self):
        """
        Custom initialization for ChatMode.
        """
        # Create the Web object
        self.web = Web(self.common, True, self.settings, "chat")

        # Chat image
        self.image_label = QtWidgets.QLabel()
        self.image_label.setPixmap(
            QtGui.QPixmap.fromImage(
                QtGui.QImage(
                    GuiCommon.get_resource_path(
                        "images/{}_mode_chat.png".format(
                            self.common.gui.color_mode)))))
        self.image_label.setFixedSize(300, 300)
        image_layout = QtWidgets.QVBoxLayout()
        image_layout.addStretch()
        image_layout.addWidget(self.image_label)
        image_layout.addStretch()
        self.image = QtWidgets.QWidget()
        self.image.setLayout(image_layout)

        # Server status
        self.server_status.set_mode("chat")
        self.server_status.server_started_finished.connect(
            self.update_primary_action)
        self.server_status.server_stopped.connect(self.update_primary_action)
        self.server_status.server_canceled.connect(self.update_primary_action)
        # Tell server_status about web, then update
        self.server_status.web = self.web
        self.server_status.update()

        # Header
        header_label = QtWidgets.QLabel(strings._("gui_new_tab_chat_button"))
        header_label.setStyleSheet(self.common.gui.css["mode_header_label"])

        # Top bar
        top_bar_layout = QtWidgets.QHBoxLayout()
        top_bar_layout.addStretch()

        # Main layout
        self.main_layout = QtWidgets.QVBoxLayout()
        self.main_layout.addLayout(top_bar_layout)
        self.main_layout.addStretch()
        self.main_layout.addWidget(header_label)
        self.main_layout.addWidget(self.primary_action)
        self.main_layout.addWidget(self.server_status)
        self.main_layout.addStretch()
        self.main_layout.addWidget(MinimumWidthWidget(700))

        # Column layout
        self.column_layout = QtWidgets.QHBoxLayout()
        self.column_layout.addWidget(self.image)
        self.column_layout.addLayout(self.main_layout)

        # Wrapper layout
        self.wrapper_layout = QtWidgets.QVBoxLayout()
        self.wrapper_layout.addLayout(self.column_layout)
        self.setLayout(self.wrapper_layout)
Exemple #3
0
    def init(self):
        """
        Custom initialization for ReceiveMode.
        """
        # Create the Web object
        self.web = Web(self.common, True, self.settings, "website")

        # Settings
        self.disable_csp_checkbox = QtWidgets.QCheckBox()
        self.disable_csp_checkbox.clicked.connect(
            self.disable_csp_checkbox_clicked)
        self.disable_csp_checkbox.setText(
            strings._("mode_settings_website_disable_csp_checkbox"))
        if self.settings.get("website", "disable_csp"):
            self.disable_csp_checkbox.setCheckState(QtCore.Qt.Checked)
        else:
            self.disable_csp_checkbox.setCheckState(QtCore.Qt.Unchecked)

        self.mode_settings_widget.mode_specific_layout.addWidget(
            self.disable_csp_checkbox)

        # File selection
        self.file_selection = FileSelection(
            self.common,
            "images/mode_website.png",
            strings._("gui_new_tab_website_button"),
            self,
        )
        if self.filenames:
            for filename in self.filenames:
                self.file_selection.file_list.add_file(filename)

        # Server status
        self.server_status.set_mode("website", self.file_selection)
        self.server_status.server_started.connect(
            self.file_selection.server_started)
        self.server_status.server_stopped.connect(
            self.file_selection.server_stopped)
        self.server_status.server_stopped.connect(self.update_primary_action)
        self.server_status.server_canceled.connect(
            self.file_selection.server_stopped)
        self.server_status.server_canceled.connect(self.update_primary_action)
        self.file_selection.file_list.files_updated.connect(
            self.server_status.update)
        self.file_selection.file_list.files_updated.connect(
            self.update_primary_action)
        # Tell server_status about web, then update
        self.server_status.web = self.web
        self.server_status.update()

        # Filesize warning
        self.filesize_warning = QtWidgets.QLabel()
        self.filesize_warning.setWordWrap(True)
        self.filesize_warning.setStyleSheet(
            self.common.gui.css["share_filesize_warning"])
        self.filesize_warning.hide()

        # Download history
        self.history = History(
            self.common,
            QtGui.QPixmap.fromImage(
                QtGui.QImage(
                    GuiCommon.get_resource_path(
                        "images/share_icon_transparent.png"))),
            strings._("gui_website_mode_no_files"),
            strings._("gui_all_modes_history"),
            "website",
        )
        self.history.in_progress_label.hide()
        self.history.completed_label.hide()
        self.history.hide()

        # Info label
        self.info_label = QtWidgets.QLabel()
        self.info_label.hide()

        # Delete all files button
        self.remove_all_button = QtWidgets.QPushButton(
            strings._("gui_file_selection_remove_all"))
        self.remove_all_button.setFlat(True)
        self.remove_all_button.setStyleSheet(
            self.common.gui.css["share_delete_all_files_button"])
        self.remove_all_button.clicked.connect(self.delete_all)
        self.remove_all_button.hide()

        # Toggle history
        self.toggle_history = ToggleHistory(
            self.common,
            self,
            self.history,
            QtGui.QIcon(
                GuiCommon.get_resource_path("images/share_icon_toggle.png")),
            QtGui.QIcon(
                GuiCommon.get_resource_path(
                    "images/share_icon_toggle_selected.png")),
        )

        # Top bar
        top_bar_layout = QtWidgets.QHBoxLayout()
        top_bar_layout.addWidget(self.info_label)
        top_bar_layout.addStretch()
        top_bar_layout.addWidget(self.remove_all_button)
        top_bar_layout.addWidget(self.toggle_history)

        # Primary action layout
        self.primary_action_layout.addWidget(self.filesize_warning)
        self.primary_action.hide()
        self.update_primary_action()

        # Main layout
        self.main_layout = QtWidgets.QVBoxLayout()
        self.main_layout.addLayout(top_bar_layout)
        self.main_layout.addLayout(self.file_selection)
        self.main_layout.addWidget(self.primary_action)
        self.main_layout.addWidget(self.server_status)
        self.main_layout.addWidget(MinimumWidthWidget(700))

        # Column layout
        self.column_layout = QtWidgets.QHBoxLayout()
        self.column_layout.addLayout(self.main_layout)
        self.column_layout.addWidget(self.history, stretch=1)

        # Wrapper layout
        self.wrapper_layout = QtWidgets.QVBoxLayout()
        self.wrapper_layout.addLayout(self.column_layout)
        self.setLayout(self.wrapper_layout)

        # Always start with focus on file selection
        self.file_selection.setFocus()
Exemple #4
0
    def init(self):
        """
        Custom initialization for ReceiveMode.
        """
        # Create the Web object
        self.web = Web(self.common, True, self.settings, "receive")

        # Receive image
        self.image_label = QtWidgets.QLabel()
        self.image_label.setPixmap(
            QtGui.QPixmap.fromImage(
                QtGui.QImage(
                    GuiCommon.get_resource_path(
                        "images/{}_mode_receive.png".format(
                            self.common.gui.color_mode)))))
        self.image_label.setFixedSize(250, 250)
        image_layout = QtWidgets.QVBoxLayout()
        image_layout.addWidget(self.image_label)
        self.image = QtWidgets.QWidget()
        self.image.setLayout(image_layout)

        # Settings
        data_dir_label = QtWidgets.QLabel(
            strings._("mode_settings_receive_data_dir_label"))
        self.data_dir_lineedit = QtWidgets.QLineEdit()
        self.data_dir_lineedit.setReadOnly(True)
        self.data_dir_lineedit.setText(self.settings.get(
            "receive", "data_dir"))
        data_dir_button = QtWidgets.QPushButton(
            strings._("mode_settings_receive_data_dir_browse_button"))
        data_dir_button.clicked.connect(self.data_dir_button_clicked)
        data_dir_layout = QtWidgets.QHBoxLayout()
        data_dir_layout.addWidget(data_dir_label)
        data_dir_layout.addWidget(self.data_dir_lineedit)
        data_dir_layout.addWidget(data_dir_button)

        self.mode_settings_widget.mode_specific_layout.addLayout(
            data_dir_layout)

        # Server status
        self.server_status.set_mode("receive")
        self.server_status.server_started_finished.connect(
            self.update_primary_action)
        self.server_status.server_stopped.connect(self.update_primary_action)
        self.server_status.server_canceled.connect(self.update_primary_action)

        # Tell server_status about web, then update
        self.server_status.web = self.web
        self.server_status.update()

        # Upload history
        self.history = History(
            self.common,
            QtGui.QPixmap.fromImage(
                QtGui.QImage(
                    GuiCommon.get_resource_path(
                        "images/receive_icon_transparent.png"))),
            strings._("gui_receive_mode_no_files"),
            strings._("gui_all_modes_history"),
        )
        self.history.hide()

        # Toggle history
        self.toggle_history = ToggleHistory(
            self.common,
            self,
            self.history,
            QtGui.QIcon(
                GuiCommon.get_resource_path("images/receive_icon_toggle.png")),
            QtGui.QIcon(
                GuiCommon.get_resource_path(
                    "images/receive_icon_toggle_selected.png")),
        )

        # Header
        header_label = QtWidgets.QLabel(
            strings._("gui_new_tab_receive_button"))
        header_label.setStyleSheet(self.common.gui.css["mode_header_label"])

        # Receive mode warning
        receive_warning = QtWidgets.QLabel(
            strings._("gui_receive_mode_warning"))
        receive_warning.setMinimumHeight(80)
        receive_warning.setWordWrap(True)

        # Top bar
        top_bar_layout = QtWidgets.QHBoxLayout()
        top_bar_layout.addStretch()
        top_bar_layout.addWidget(self.toggle_history)

        # Main layout
        self.main_layout = QtWidgets.QVBoxLayout()
        self.main_layout.addWidget(header_label)
        self.main_layout.addWidget(receive_warning)
        self.main_layout.addWidget(self.primary_action)
        self.main_layout.addWidget(MinimumWidthWidget(525))

        # Row layout
        content_row = QtWidgets.QHBoxLayout()
        content_row.addLayout(self.main_layout)
        content_row.addWidget(self.image)
        row_layout = QtWidgets.QVBoxLayout()
        row_layout.addLayout(top_bar_layout)
        row_layout.addStretch()
        row_layout.addLayout(content_row)
        row_layout.addWidget(self.server_status)
        row_layout.addStretch()

        # Column layout
        self.column_layout = QtWidgets.QHBoxLayout()
        self.column_layout.addLayout(row_layout)
        self.column_layout.addWidget(self.history, stretch=1)

        # Wrapper layout
        self.wrapper_layout = QtWidgets.QVBoxLayout()
        self.wrapper_layout.addLayout(self.column_layout)
        self.setLayout(self.wrapper_layout)
    def init(self):
        """
        Custom initialization for ReceiveMode.
        """
        # Create the Web object
        self.web = Web(self.common, True, self.settings, "website")

        # Settings
        # Disable CSP option
        self.disable_csp_checkbox = QtWidgets.QCheckBox()
        self.disable_csp_checkbox.clicked.connect(self.disable_csp_checkbox_clicked)
        self.disable_csp_checkbox.setText(
            strings._("mode_settings_website_disable_csp_checkbox")
        )
        if self.settings.get("website", "disable_csp"):
            self.disable_csp_checkbox.setCheckState(QtCore.Qt.Checked)
        else:
            self.disable_csp_checkbox.setCheckState(QtCore.Qt.Unchecked)

        self.mode_settings_widget.mode_specific_layout.addWidget(
            self.disable_csp_checkbox
        )

        # Custom CSP option
        self.custom_csp_checkbox = QtWidgets.QCheckBox()
        self.custom_csp_checkbox.clicked.connect(self.custom_csp_checkbox_clicked)
        self.custom_csp_checkbox.setText(strings._("mode_settings_website_custom_csp_checkbox"))
        if self.settings.get("website", "custom_csp") and not self.settings.get("website", "disable_csp"):
            self.custom_csp_checkbox.setCheckState(QtCore.Qt.Checked)
        else:
            self.custom_csp_checkbox.setCheckState(QtCore.Qt.Unchecked)
        self.custom_csp = QtWidgets.QLineEdit()
        self.custom_csp.setPlaceholderText(
            "default-src 'self'; frame-ancestors 'none'; form-action 'self'; base-uri 'self'; img-src 'self' data:;"
        )
        self.custom_csp.editingFinished.connect(self.custom_csp_editing_finished)

        custom_csp_layout = QtWidgets.QHBoxLayout()
        custom_csp_layout.setContentsMargins(0, 0, 0, 0)
        custom_csp_layout.addWidget(self.custom_csp_checkbox)
        custom_csp_layout.addWidget(self.custom_csp)
        self.mode_settings_widget.mode_specific_layout.addLayout(custom_csp_layout)

        # File selection
        self.file_selection = FileSelection(
            self.common,
            "images/{}_mode_website.png".format(self.common.gui.color_mode),
            strings._("gui_new_tab_website_button"),
            self,
        )
        if self.filenames:
            for filename in self.filenames:
                self.file_selection.file_list.add_file(filename)

        # Set title placeholder
        self.mode_settings_widget.title_lineedit.setPlaceholderText(
            strings._("gui_tab_name_website")
        )

        # Server status
        self.server_status.set_mode("website", self.file_selection)
        self.server_status.server_started.connect(self.file_selection.server_started)
        self.server_status.server_stopped.connect(self.file_selection.server_stopped)
        self.server_status.server_stopped.connect(self.update_primary_action)
        self.server_status.server_canceled.connect(self.file_selection.server_stopped)
        self.server_status.server_canceled.connect(self.update_primary_action)
        self.file_selection.file_list.files_updated.connect(self.server_status.update)
        self.file_selection.file_list.files_updated.connect(self.update_primary_action)
        # Tell server_status about web, then update
        self.server_status.web = self.web
        self.server_status.update()

        # Filesize warning
        self.filesize_warning = QtWidgets.QLabel()
        self.filesize_warning.setWordWrap(True)
        self.filesize_warning.setStyleSheet(
            self.common.gui.css["share_filesize_warning"]
        )
        self.filesize_warning.hide()

        # Download history
        self.history = History(
            self.common,
            QtGui.QPixmap.fromImage(
                QtGui.QImage(
                    GuiCommon.get_resource_path("images/share_icon_transparent.png")
                )
            ),
            strings._("gui_website_mode_no_files"),
            strings._("gui_all_modes_history"),
            "website",
        )
        self.history.in_progress_label.hide()
        self.history.completed_label.hide()
        self.history.hide()

        # Info label
        self.info_label = QtWidgets.QLabel()
        self.info_label.hide()

        # Delete all files button
        self.remove_all_button = QtWidgets.QPushButton(
            strings._("gui_file_selection_remove_all")
        )
        self.remove_all_button.setFlat(True)
        self.remove_all_button.setStyleSheet(
            self.common.gui.css["share_delete_all_files_button"]
        )
        self.remove_all_button.clicked.connect(self.delete_all)
        self.remove_all_button.hide()

        # Toggle history
        self.toggle_history = ToggleHistory(
            self.common,
            self,
            self.history,
            QtGui.QIcon(GuiCommon.get_resource_path("images/share_icon_toggle.png")),
            QtGui.QIcon(
                GuiCommon.get_resource_path("images/share_icon_toggle_selected.png")
            ),
        )

        # Top bar
        top_bar_layout = QtWidgets.QHBoxLayout()
        top_bar_layout.addWidget(self.info_label)
        top_bar_layout.addStretch()
        top_bar_layout.addWidget(self.remove_all_button)
        top_bar_layout.addWidget(self.toggle_history)

        # Primary action layout
        self.primary_action_layout.addWidget(self.filesize_warning)
        self.primary_action.hide()
        self.update_primary_action()

        # Main layout
        self.main_layout = QtWidgets.QVBoxLayout()
        self.main_layout.addLayout(top_bar_layout)
        self.main_layout.addLayout(self.file_selection)
        self.main_layout.addWidget(self.primary_action, stretch=1)
        self.main_layout.addWidget(self.server_status)
        self.main_layout.addWidget(MinimumSizeWidget(700, 0))

        # Column layout
        self.column_layout = QtWidgets.QHBoxLayout()
        self.column_layout.addLayout(self.main_layout)
        self.column_layout.addWidget(self.history, stretch=1)

        # Content layout
        self.content_layout.addLayout(self.column_layout)

        # Always start with focus on file selection
        self.file_selection.setFocus()
Exemple #6
0
    def init(self):
        """
        Custom initialization for ReceiveMode.
        """
        # Create the Web object
        self.web = Web(self.common, True, self.settings, "receive")

        # Receive image
        self.image_label = QtWidgets.QLabel()
        self.image_label.setPixmap(
            QtGui.QPixmap.fromImage(
                QtGui.QImage(
                    GuiCommon.get_resource_path(
                        "images/{}_mode_receive.png".format(self.common.gui.color_mode)
                    )
                )
            )
        )
        self.image_label.setFixedSize(250, 250)
        image_layout = QtWidgets.QVBoxLayout()
        image_layout.addWidget(self.image_label)
        self.image = QtWidgets.QWidget()
        self.image.setLayout(image_layout)

        # Settings

        # Data dir
        data_dir_label = QtWidgets.QLabel(
            strings._("mode_settings_receive_data_dir_label")
        )
        self.data_dir_lineedit = QtWidgets.QLineEdit()
        self.data_dir_lineedit.setReadOnly(True)
        self.data_dir_lineedit.setText(self.settings.get("receive", "data_dir"))
        data_dir_button = QtWidgets.QPushButton(
            strings._("mode_settings_receive_data_dir_browse_button")
        )
        data_dir_button.clicked.connect(self.data_dir_button_clicked)
        data_dir_layout = QtWidgets.QHBoxLayout()
        data_dir_layout.addWidget(data_dir_label)
        data_dir_layout.addWidget(self.data_dir_lineedit)
        data_dir_layout.addWidget(data_dir_button)
        self.mode_settings_widget.mode_specific_layout.addLayout(data_dir_layout)

        # Disable text or files
        self.disable_text_checkbox = self.settings.get("receive", "disable_files")
        self.disable_text_checkbox = QtWidgets.QCheckBox()
        self.disable_text_checkbox.clicked.connect(self.disable_text_checkbox_clicked)
        self.disable_text_checkbox.setText(
            strings._("mode_settings_receive_disable_text_checkbox")
        )
        self.disable_files_checkbox = self.settings.get("receive", "disable_files")
        self.disable_files_checkbox = QtWidgets.QCheckBox()
        self.disable_files_checkbox.clicked.connect(self.disable_files_checkbox_clicked)
        self.disable_files_checkbox.setText(
            strings._("mode_settings_receive_disable_files_checkbox")
        )
        disable_layout = QtWidgets.QHBoxLayout()
        disable_layout.addWidget(self.disable_text_checkbox)
        disable_layout.addWidget(self.disable_files_checkbox)
        disable_layout.addStretch()
        self.mode_settings_widget.mode_specific_layout.addLayout(disable_layout)

        # Webhook URL
        webhook_url = self.settings.get("receive", "webhook_url")
        self.webhook_url_checkbox = QtWidgets.QCheckBox()
        self.webhook_url_checkbox.clicked.connect(self.webhook_url_checkbox_clicked)
        self.webhook_url_checkbox.setText(
            strings._("mode_settings_receive_webhook_url_checkbox")
        )
        self.webhook_url_lineedit = QtWidgets.QLineEdit()
        self.webhook_url_lineedit.editingFinished.connect(
            self.webhook_url_editing_finished
        )
        self.webhook_url_lineedit.setPlaceholderText(
            "https://example.com/post-when-file-uploaded"
        )
        webhook_url_layout = QtWidgets.QHBoxLayout()
        webhook_url_layout.addWidget(self.webhook_url_checkbox)
        webhook_url_layout.addWidget(self.webhook_url_lineedit)
        if webhook_url is not None and webhook_url != "":
            self.webhook_url_checkbox.setCheckState(QtCore.Qt.Checked)
            self.webhook_url_lineedit.setText(
                self.settings.get("receive", "webhook_url")
            )
            self.show_webhook_url()
        else:
            self.webhook_url_checkbox.setCheckState(QtCore.Qt.Unchecked)
            self.hide_webhook_url()
        self.mode_settings_widget.mode_specific_layout.addLayout(webhook_url_layout)

        # Set title placeholder
        self.mode_settings_widget.title_lineedit.setPlaceholderText(
            strings._("gui_tab_name_receive")
        )

        # Server status
        self.server_status.set_mode("receive")
        self.server_status.server_started_finished.connect(self.update_primary_action)
        self.server_status.server_stopped.connect(self.update_primary_action)
        self.server_status.server_canceled.connect(self.update_primary_action)

        # Tell server_status about web, then update
        self.server_status.web = self.web
        self.server_status.update()

        # Upload history
        self.history = History(
            self.common,
            QtGui.QPixmap.fromImage(
                QtGui.QImage(
                    GuiCommon.get_resource_path("images/receive_icon_transparent.png")
                )
            ),
            strings._("gui_receive_mode_no_files"),
            strings._("gui_all_modes_history"),
        )
        self.history.hide()

        # Toggle history
        self.toggle_history = ToggleHistory(
            self.common,
            self,
            self.history,
            QtGui.QIcon(GuiCommon.get_resource_path("images/receive_icon_toggle.png")),
            QtGui.QIcon(
                GuiCommon.get_resource_path("images/receive_icon_toggle_selected.png")
            ),
        )

        # Header
        header_label = QtWidgets.QLabel(strings._("gui_new_tab_receive_button"))
        header_label.setStyleSheet(self.common.gui.css["mode_header_label"])

        # Receive mode warning
        receive_warning = QtWidgets.QLabel(strings._("gui_receive_mode_warning"))
        receive_warning.setMinimumHeight(80)
        receive_warning.setWordWrap(True)

        # Top bar
        top_bar_layout = QtWidgets.QHBoxLayout()
        top_bar_layout.addStretch()
        top_bar_layout.addWidget(self.toggle_history)

        # Main layout
        self.main_layout = QtWidgets.QVBoxLayout()
        self.main_layout.addWidget(header_label)
        self.main_layout.addWidget(receive_warning)
        self.main_layout.addWidget(self.primary_action, stretch=1)
        self.main_layout.addWidget(MinimumSizeWidget(525, 0))

        # Row layout
        content_row = QtWidgets.QHBoxLayout()
        content_row.addLayout(self.main_layout)
        content_row.addWidget(self.image)
        row_layout = QtWidgets.QVBoxLayout()
        row_layout.addLayout(top_bar_layout)
        row_layout.addLayout(content_row, stretch=1)
        row_layout.addWidget(self.server_status)

        # Column layout
        self.column_layout = QtWidgets.QHBoxLayout()
        self.column_layout.addLayout(row_layout)
        self.column_layout.addWidget(self.history, stretch=1)

        # Wrapper layout
        self.wrapper_layout = QtWidgets.QVBoxLayout()
        self.wrapper_layout.addLayout(self.column_layout)
        self.setLayout(self.wrapper_layout)
Exemple #7
0
    def init(self):
        """
        Custom initialization for ChatMode.
        """
        # Create the Web object
        self.web = Web(self.common, True, self.settings, "chat")

        # Chat image
        self.image_label = QtWidgets.QLabel()
        self.image_label.setPixmap(
            QtGui.QPixmap.fromImage(
                QtGui.QImage(
                    GuiCommon.get_resource_path(
                        "images/{}_mode_chat.png".format(
                            self.common.gui.color_mode)))))
        self.image_label.setFixedSize(300, 300)
        image_layout = QtWidgets.QVBoxLayout()
        image_layout.addStretch()
        image_layout.addWidget(self.image_label)
        image_layout.addStretch()
        self.image = QtWidgets.QWidget()
        self.image.setLayout(image_layout)

        # Set title placeholder
        self.mode_settings_widget.title_lineedit.setPlaceholderText(
            strings._("gui_tab_name_chat"))

        # Server status
        self.server_status.set_mode("chat")
        self.server_status.server_started_finished.connect(
            self.update_primary_action)
        self.server_status.server_stopped.connect(self.update_primary_action)
        self.server_status.server_canceled.connect(self.update_primary_action)
        # Tell server_status about web, then update
        self.server_status.web = self.web
        self.server_status.update()

        # Header
        header_label = QtWidgets.QLabel(strings._("gui_new_tab_chat_button"))
        header_label.setStyleSheet(self.common.gui.css["mode_header_label"])

        # Top bar
        top_bar_layout = QtWidgets.QHBoxLayout()
        # Add space at the top, same height as the toggle history bar in other modes
        top_bar_layout.addWidget(MinimumSizeWidget(0, 30))

        # Main layout
        self.main_layout = QtWidgets.QVBoxLayout()
        self.main_layout.addLayout(top_bar_layout)
        self.main_layout.addWidget(header_label)
        self.main_layout.addWidget(self.primary_action, stretch=1)
        self.main_layout.addWidget(self.server_status)
        self.main_layout.addWidget(MinimumSizeWidget(700, 0))

        # Column layout
        self.column_layout = QtWidgets.QHBoxLayout()
        self.column_layout.addWidget(self.image)
        self.column_layout.addLayout(self.main_layout)

        # Content layout
        self.content_layout.addLayout(self.column_layout)