0

So, I made a browser in QtWebEngine, and whenever I make a new tab, and click on a link that takes me to another page, and I click on the back button to go back to the previous one, it doesn't do anything (basically, none of the navigation buttons work). The nav buttons work just fine in the first tab, but when I make a new one, they don't. I tried for hours to make it work, but nothing helped.

I tried changing a lot of stuff, but nothing really worked :/ Here's the code:

import sys
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QMenu, QAction, \
    QDialog, QTableWidget, QTableWidgetItem, QLabel, QTabWidget, QTabBar

from PyQt5.QtWebEngineWidgets import QWebEngineView

class BookmarksHistoryWindow(QDialog):
    def __init__(self, title):
        super().__init__()

        self.setWindowTitle(title)
        self.setGeometry(200, 200, 400, 300)

        self.layout = QVBoxLayout()
        self.setLayout(self.layout)

        self.items_label = QLabel(title)
        self.layout.addWidget(self.items_label)

        self.items_table = QTableWidget()
        self.items_table.setColumnCount(2)
        self.items_table.setHorizontalHeaderLabels(["Title", "URL"])
        self.layout.addWidget(self.items_table)

class BrowserWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Simple Browser")
        self.setGeometry(100, 100, 800, 600)

        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)

        self.layout = QVBoxLayout()
        self.central_widget.setLayout(self.layout)

        # Create navigation buttons layout
        self.nav_layout = QHBoxLayout()
        self.layout.addLayout(self.nav_layout)

        # Back button
        self.back_button = QPushButton("Back")
        self.nav_layout.addWidget(self.back_button)

        # Forward button
        self.forward_button = QPushButton("Forward")
        self.nav_layout.addWidget(self.forward_button)

        # Reload button
        self.reload_button = QPushButton("Reload")
        self.nav_layout.addWidget(self.reload_button)

        # Options button
        self.options_button = QPushButton("Options")
        self.nav_layout.addWidget(self.options_button)

        # Create options menu
        self.options_menu = QMenu(self)
        self.bookmarks_action = QAction("Bookmarks", self)
        self.history_action = QAction("History", self)
        self.bookmark_page_action = QAction("Bookmark Page", self)

        # Add actions to the options menu
        self.options_menu.addAction(self.bookmarks_action)
        self.options_menu.addAction(self.history_action)
        self.options_menu.addAction(self.bookmark_page_action)

        # Connect menu actions
        self.bookmarks_action.triggered.connect(self.show_bookmarks)
        self.history_action.triggered.connect(self.show_history)
        self.bookmark_page_action.triggered.connect(self.save_bookmark)

        # Show menu when options button is clicked
        self.options_button.setMenu(self.options_menu)

        self.tab_widget = QTabWidget()
        self.tab_widget.setTabsClosable(True)  # Allow tabs to be closed
        self.tab_widget.tabBar().setContextMenuPolicy(3)  # Enable right-click context menu on tabs
        self.tab_widget.tabBar().customContextMenuRequested.connect(self.tab_menu_requested)
        self.tab_widget.tabCloseRequested.connect(self.close_tab)
        self.layout.addWidget(self.tab_widget)

        self.browser = QWebEngineView()
        self.tab_widget.addTab(self.browser, "New Tab")

        # Connect buttons to browser actions
        self.back_button.clicked.connect(self.browser.back)
        self.forward_button.clicked.connect(self.browser.forward)
        self.reload_button.clicked.connect(self.browser.reload)

        # Connect signal for page loading finished
        self.browser.page().loadFinished.connect(self.page_loaded)

        self.load_page("https://www.google.com")

        self.bookmarks_window = None
        self.history_window = None
        self.history_pages = []

    

    def load_page(self, url):
        qurl = QUrl(url)
        self.browser.setUrl(qurl)

    def show_bookmarks(self):
        if not self.bookmarks_window:
            self.bookmarks_window = BookmarksHistoryWindow("Bookmarks")
            self.bookmarks_window.items_table.cellDoubleClicked.connect(self.open_bookmark_in_tab)
        self.bookmarks_window.show()

    def show_history(self):
        if not self.history_window:
            self.history_window = BookmarksHistoryWindow("History")
            self.history_window.items_table.cellDoubleClicked.connect(self.open_history_in_tab)
            for title, url in self.history_pages:
                row_position = self.history_window.items_table.rowCount()
                self.history_window.items_table.insertRow(row_position)
                self.history_window.items_table.setItem(row_position, 0, QTableWidgetItem(title))
                self.history_window.items_table.setItem(row_position, 1, QTableWidgetItem(url))
        self.history_window.show()

    def save_bookmark(self):
        title = self.browser.page().title()
        url = self.browser.url().toString()
        if self.bookmarks_window:
            found = False
            for row in range(self.bookmarks_window.items_table.rowCount()):
                if self.bookmarks_window.items_table.item(row, 1).text() == url:
                    found = True
                    break
            if not found:
                row_position = self.bookmarks_window.items_table.rowCount()
                self.bookmarks_window.items_table.insertRow(row_position)
                self.bookmarks_window.items_table.setItem(row_position, 0, QTableWidgetItem(title))
                self.bookmarks_window.items_table.setItem(row_position, 1, QTableWidgetItem(url))

    def page_loaded(self):
        title = self.browser.page().title()
        url = self.browser.url().toString()
        if self.bookmarks_window:
            found = False
            for row in range(self.bookmarks_window.items_table.rowCount()):
                if self.bookmarks_window.items_table.item(row, 1).text() == url:
                    found = True
                    break
            if not found:
                row_position = self.bookmarks_window.items_table.rowCount()
                self.bookmarks_window.items_table.insertRow(row_position)
                self.bookmarks_window.items_table.setItem(row_position, 0, QTableWidgetItem(title))
                self.bookmarks_window.items_table.setItem(row_position, 1, QTableWidgetItem(url))
        # Store page in history
        self.history_pages.append((title, url))
        # Update tab title for the currently active tab
        ''' index = self.tab_widget.currentIndex()
        current_widget = self.tab_widget.widget(index)
        current_index = self.tab_widget.indexOf(current_widget)
        self.tab_widget.setTabText(current_index, title) '''

def open_bookmark_in_tab(self, row, col):
    url = self.bookmarks_window.items_table.item(row, 1).text()
    new_browser = QWebEngineView()  # Create a new instance of QWebEngineView
    self.tab_widget.addTab(new_browser, "New Tab")
    self.tab_widget.setCurrentWidget(new_browser)
    self.load_page(url, new_browser)  # Pass the new_browser instance to load_page

def open_history_in_tab(self, row, col):
    url = self.history_window.items_table.item(row, 1).text()
    new_browser = QWebEngineView()  # Create a new instance of QWebEngineView
    self.tab_widget.addTab(new_browser, "New Tab")
    self.tab_widget.setCurrentWidget(new_browser)
    self.load_page(url, new_browser)  # Pass the new_browser instance to load_page

def load_page(self, url, browser=None):
    if browser is None:
        browser = self.browser  # Use the default browser if None is passed
    qurl = QUrl(url)
    browser.setUrl(qurl)


    def tab_menu_requested(self, pos):
        tab_bar = self.tab_widget.tabBar()
        index = tab_bar.tabAt(pos)
        if index < 0:
            return
        menu = QMenu()
        new_tab_action = QAction("New Tab", self)
        close_tab_action = QAction("Close Tab", self)
        menu.addAction(new_tab_action)
        menu.addAction(close_tab_action)
        new_tab_action.triggered.connect(self.open_new_tab)
        close_tab_action.triggered.connect(lambda: self.close_tab(index))
        menu.exec_(tab_bar.mapToGlobal(pos))

    def open_new_tab(self):
        new_browser = QWebEngineView()
        new_browser.setUrl(QUrl("https://www.google.com"))
        self.tab_widget.addTab(new_browser, "New Tab")
        self.tab_widget.setCurrentWidget(new_browser)
        self.tab_widget.setTabText(self.tab_widget.indexOf(new_browser), "New Tab")  # Set default tab text

    def close_tab(self, index):
        if self.tab_widget.count() > 1:
            self.tab_widget.removeTab(index)

def main():
    app = QApplication(sys.argv)
    window = BrowserWindow()
    window.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

2
  • It does work, but, as you also pointed out, only for the first tab. Even if you're on another tab, clicking on those buttons will have effect on the first tab only. You cannot directly connect those buttons with a QWebEngineView, you must connect to a function that gets the current active view (by checking the tab_widget.currentWidget()) and calls the related functions for that view. Commented Dec 6, 2023 at 19:48
  • There are similar problems with the history and page-load handler, since these also only work with the first tab. (However, you don't actually need to save the history yourself, since each web-page already records its own history). You therefore need to factor out the code for creating a tab, and use that for all new tabs, including the first one. Then you can use the current widget of the tab-widget to access the current web-view. Commented Dec 6, 2023 at 20:14

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.