|
3 | 3 | from PyQt5.QtWidgets import *
|
4 | 4 | from PyQt5.QtWebEngineWidgets import *
|
5 | 5 |
|
| 6 | +class BrowserTab(QWebEngineView): |
| 7 | + def __init__(self, parent=None): |
| 8 | + super().__init__(parent) |
| 9 | + self.load(QUrl("https://www.google.com")) # Página inicial padrão para cada nova guia |
| 10 | + |
6 | 11 | class MiniNavegador(QMainWindow):
|
7 | 12 | def __init__(self):
|
8 | 13 | super().__init__()
|
9 | 14 |
|
10 |
| - # Inicializa o navegador |
11 |
| - self.browser = QWebEngineView() |
| 15 | + self.setWindowTitle("Navegador Py-Tech") # Novo título |
| 16 | + self.resize(1200, 800) # Aumenta o tamanho da janela |
| 17 | + |
| 18 | + # Barra de navegação (Toolbar) |
| 19 | + self.toolbar = QToolBar("Navegação") |
| 20 | + self.addToolBar(self.toolbar) |
| 21 | + |
| 22 | + # --- Suporte a Guias --- |
| 23 | + self.tabs = QTabWidget() # Primeiro, inicialize o QTabWidget |
| 24 | + self.tabs.setDocumentMode(True) # Modo de documento (aparência mais moderna) |
| 25 | + self.tabs.tabBarDoubleClicked.connect(self.tab_open_doubleclick) # Abrir nova aba ao clicar duas vezes |
| 26 | + self.tabs.currentChanged.connect(self.current_tab_changed) # Mudar URL na barra quando a aba muda |
| 27 | + |
| 28 | + self.setCentralWidget(self.tabs) |
12 | 29 |
|
13 |
| - # Definindo a página inicial |
14 |
| - self.browser.setUrl(QUrl("http://www.google.com")) |
| 30 | + # Agora que self.tabs existe e tem uma guia, podemos conectar os botões |
| 31 | + # Botões da barra de navegação |
| 32 | + back_btn = QAction("⬅️ Voltar", self) |
| 33 | + back_btn.setStatusTip("Voltar para a página anterior") |
| 34 | + back_btn.triggered.connect(lambda: self.current_browser().back()) |
| 35 | + self.toolbar.addAction(back_btn) |
15 | 36 |
|
16 |
| - # Barra de navegação |
17 |
| - self.url_bar = QLineEdit(self) |
| 37 | + forward_btn = QAction("➡️ Avançar", self) |
| 38 | + forward_btn.setStatusTip("Avançar para a próxima página") |
| 39 | + forward_btn.triggered.connect(lambda: self.current_browser().forward()) |
| 40 | + self.toolbar.addAction(forward_btn) |
| 41 | + |
| 42 | + reload_btn = QAction("🔄 Recarregar", self) |
| 43 | + reload_btn.setStatusTip("Recarregar a página atual") |
| 44 | + reload_btn.triggered.connect(lambda: self.current_browser().reload()) |
| 45 | + self.toolbar.addAction(reload_btn) |
| 46 | + |
| 47 | + home_btn = QAction("🏠 Início", self) |
| 48 | + home_btn.setStatusTip("Ir para a página inicial") |
| 49 | + home_btn.triggered.connect(self.navigate_home) |
| 50 | + self.toolbar.addAction(home_btn) |
| 51 | + |
| 52 | + self.url_bar = QLineEdit() |
18 | 53 | self.url_bar.returnPressed.connect(self.navigate_to_url)
|
| 54 | + self.toolbar.addWidget(self.url_bar) |
19 | 55 |
|
20 |
| - # Botões de navegação |
21 |
| - self.back_button = QPushButton("Voltar", self) |
22 |
| - self.forward_button = QPushButton("Avançar", self) |
23 |
| - self.refresh_button = QPushButton("Atualizar", self) |
| 56 | + # Botão para adicionar nova guia |
| 57 | + new_tab_btn = QAction("➕ Nova Guia", self) |
| 58 | + new_tab_btn.setStatusTip("Abrir uma nova guia") |
| 59 | + new_tab_btn.triggered.connect(lambda: self.add_new_tab()) |
| 60 | + self.toolbar.addAction(new_tab_btn) |
24 | 61 |
|
25 |
| - # Conectar os botões às funções |
26 |
| - self.back_button.clicked.connect(self.go_back) |
27 |
| - self.forward_button.clicked.connect(self.go_forward) |
28 |
| - self.refresh_button.clicked.connect(self.refresh_page) |
29 | 62 |
|
30 |
| - # Layout dos botões |
31 |
| - button_layout = QHBoxLayout() |
32 |
| - button_layout.addWidget(self.back_button) |
33 |
| - button_layout.addWidget(self.forward_button) |
34 |
| - button_layout.addWidget(self.refresh_button) |
| 63 | + self.add_new_tab(QUrl("https://www.google.com"), "Página Inicial") |
| 64 | + self.update_buttons_state() |
35 | 65 |
|
36 |
| - # Layout principal |
37 |
| - layout = QVBoxLayout() |
38 |
| - layout.addLayout(button_layout) |
39 |
| - layout.addWidget(self.url_bar) |
40 |
| - layout.addWidget(self.browser) |
41 | 66 |
|
42 |
| - # Configuração do widget central |
43 |
| - container = QWidget() |
44 |
| - container.setLayout(layout) |
45 |
| - self.setCentralWidget(container) |
| 67 | + self.statusBar().hide() |
46 | 68 |
|
47 |
| - # Ajusta o tamanho da janela |
48 |
| - self.setWindowTitle("Mini Navegador") |
49 |
| - self.resize(1024, 768) |
| 69 | + def current_browser(self): |
| 70 | + """Retorna a instância do navegador da guia atual.""" |
| 71 | + if self.tabs.count() > 0: |
| 72 | + return self.tabs.currentWidget() |
| 73 | + return None |
50 | 74 |
|
51 |
| - # Conectar barra de URL à mudança de página |
52 |
| - self.browser.urlChanged.connect(self.update_url) |
| 75 | + def add_new_tab(self, qurl=None, label="Nova Guia"): |
| 76 | + """Adiciona uma nova guia ao navegador.""" |
| 77 | + if qurl is None or isinstance(qurl, bool): |
| 78 | + qurl = QUrl("https://www.google.com") |
53 | 79 |
|
54 |
| - def navigate_to_url(self): |
55 |
| - url = self.url_bar.text() |
56 |
| - self.browser.setUrl(QUrl(url)) |
| 80 | + browser = BrowserTab() |
| 81 | + browser.setUrl(qurl) |
| 82 | + |
| 83 | + i = self.tabs.addTab(browser, label) |
| 84 | + self.tabs.setCurrentIndex(i) |
| 85 | + |
| 86 | + browser.urlChanged.connect(lambda qurl_obj, browser=browser: self.update_urlbar(qurl_obj, browser)) |
| 87 | + browser.loadStarted.connect(lambda: self.update_buttons_state()) |
| 88 | + browser.loadFinished.connect(lambda success: self.update_buttons_state()) |
| 89 | + |
| 90 | + browser.titleChanged.connect(lambda title, browser=browser: self.tabs.setTabText(self.tabs.indexOf(browser), title)) |
57 | 91 |
|
58 |
| - def update_url(self, q): |
59 |
| - self.url_bar.setText(q.toString()) |
60 | 92 |
|
61 |
| - def go_back(self): |
62 |
| - """Voltar para a página anterior.""" |
63 |
| - if self.browser.canGoBack(): |
64 |
| - self.browser.back() |
| 93 | + def tab_open_doubleclick(self, index): |
| 94 | + """Abre uma nova guia ao dar clique duplo na barra de abas.""" |
| 95 | + if index == -1: |
| 96 | + self.add_new_tab() |
65 | 97 |
|
66 |
| - def go_forward(self): |
67 |
| - """Avançar para a próxima página.""" |
68 |
| - if self.browser.canGoForward(): |
69 |
| - self.browser.forward() |
| 98 | + def current_tab_changed(self, index): |
| 99 | + """Atualiza a barra de URL quando a guia ativa muda.""" |
| 100 | + browser = self.current_browser() |
| 101 | + if browser: |
| 102 | + qurl = browser.url() |
| 103 | + self.update_urlbar(qurl, browser) |
| 104 | + self.update_buttons_state() |
| 105 | + |
| 106 | + def navigate_home(self): |
| 107 | + """Volta para a página inicial.""" |
| 108 | + browser = self.current_browser() |
| 109 | + if browser: |
| 110 | + browser.setUrl(QUrl("https://www.google.com")) |
| 111 | + |
| 112 | + def navigate_to_url(self): |
| 113 | + """ |
| 114 | + Navega para a URL digitada, adiciona HTTPS por padrão |
| 115 | + ou faz uma pesquisa no Google. |
| 116 | + """ |
| 117 | + url = self.url_bar.text() |
| 118 | + browser = self.current_browser() |
| 119 | + if not browser: |
| 120 | + return |
| 121 | + |
| 122 | + if not url.startswith("http://") and not url.startswith("https://"): |
| 123 | + if "." in url and not " " in url: |
| 124 | + url = "https://" + url |
| 125 | + else: |
| 126 | + # --- AQUI ESTÁ A CORREÇÃO --- |
| 127 | + # Codifica o termo de busca para bytes e depois o decodifica para string normal antes de usar |
| 128 | + search_query_bytes = QUrl.toPercentEncoding(url) |
| 129 | + search_query_str = search_query_bytes.data().decode('utf-8') # Converte QByteArray para string UTF-8 |
| 130 | + url = f"https://www.google.com/search?q={search_query_str}" |
| 131 | + # ---------------------------- |
| 132 | + |
| 133 | + browser.setUrl(QUrl(url)) |
| 134 | + self.update_buttons_state() |
| 135 | + |
| 136 | + def update_urlbar(self, q, browser=None): |
| 137 | + """Atualiza a barra de URL com a URL da guia atual.""" |
| 138 | + if browser is None or browser == self.current_browser(): |
| 139 | + self.url_bar.setText(q.toString()) |
| 140 | + self.url_bar.setCursorPosition(0) |
| 141 | + |
| 142 | + def update_buttons_state(self): |
| 143 | + """Atualiza o estado (habilitado/desabilitado) dos botões de navegação.""" |
| 144 | + browser = self.current_browser() |
| 145 | + if browser: |
| 146 | + history = browser.history() |
| 147 | + can_go_back = history.canGoBack() |
| 148 | + can_go_forward = history.canGoForward() |
| 149 | + else: |
| 150 | + can_go_back = False |
| 151 | + can_go_forward = False |
| 152 | + |
| 153 | + for action in self.toolbar.actions(): |
| 154 | + if action.text() == "⬅️ Voltar": |
| 155 | + action.setEnabled(browser is not None and can_go_back and browser.url() != QUrl("https://www.google.com")) |
| 156 | + elif action.text() == "➡️ Avançar": |
| 157 | + action.setEnabled(browser is not None and can_go_forward) |
| 158 | + elif action.text() == "🔄 Recarregar": |
| 159 | + action.setEnabled(browser is not None) |
| 160 | + elif action.text() == "🏠 Início": |
| 161 | + action.setEnabled(browser is not None) |
| 162 | + elif action.text() == "➕ Nova Guia": |
| 163 | + action.setEnabled(True) |
70 | 164 |
|
71 |
| - def refresh_page(self): |
72 |
| - """Atualizar a página atual.""" |
73 |
| - self.browser.reload() |
74 | 165 |
|
75 |
| -# Função principal para rodar o aplicativo |
76 | 166 | if __name__ == "__main__":
|
77 | 167 | app = QApplication(sys.argv)
|
| 168 | + QApplication.setApplicationName("Navegador Py-Tech") |
78 | 169 | navegador = MiniNavegador()
|
79 | 170 | navegador.show()
|
80 | 171 | sys.exit(app.exec_())
|
0 commit comments