mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-10 23:45:58 -06:00
- Compilation error with Qt4 as "QUrlQuery" class was introduced since Qt5. - Client side download code has been removed as now we support server side download. - We should not delete sender object inside slot. If we do so it may crash the application. To avoid this, we used Qt's "deleteLater" which will delete the objects once the processing of all the events have been done.
809 lines
26 KiB
C++
809 lines
26 KiB
C++
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// pgAdmin 4 - PostgreSQL Tools
|
|
//
|
|
// Copyright (C) 2013 - 2016, The pgAdmin Development Team
|
|
// This software is released under the PostgreSQL Licence
|
|
//
|
|
// BrowserWindow.cpp - Implementation of the main window class
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "pgAdmin4.h"
|
|
|
|
#if QT_VERSION >= 0x050000
|
|
#include <QtWidgets>
|
|
#include <QtWebKitWidgets>
|
|
#else
|
|
#include <QtWebKit>
|
|
#include <QAction>
|
|
#include <QMenu>
|
|
#include <QMenuBar>
|
|
#include <QMessageBox>
|
|
#include <QInputDialog>
|
|
#include <QLineEdit>
|
|
#endif
|
|
#include <QNetworkRequest>
|
|
#include <QNetworkReply>
|
|
// App headers
|
|
#include "BrowserWindow.h"
|
|
#include "ConfigWindow.h"
|
|
|
|
// Constructor
|
|
BrowserWindow::BrowserWindow(QString url)
|
|
{
|
|
m_tabGridLayout = NULL;
|
|
m_mainGridLayout = NULL;;
|
|
m_tabWidget = NULL;
|
|
m_pgAdminMainTab = NULL;
|
|
m_addNewTab = NULL;
|
|
m_addNewGridLayout = NULL;
|
|
m_addNewWebView = NULL;
|
|
m_horizontalLayout = NULL;
|
|
m_widget = NULL;
|
|
m_toolBtnBack = NULL;
|
|
m_toolBtnForward = NULL;
|
|
m_downloadStarted = 0;
|
|
m_downloadCancelled = 0;
|
|
m_file = NULL;
|
|
m_downloadFilename = "";
|
|
m_defaultFilename = "";
|
|
m_progressDialog = NULL;
|
|
m_last_open_folder_path = "";
|
|
m_dir = "";
|
|
m_reply = NULL;
|
|
|
|
m_appServerUrl = url;
|
|
|
|
// Setup the shortcuts
|
|
createActions();
|
|
|
|
m_tabWidget = new TabWindow(this);
|
|
m_mainGridLayout = new QGridLayout(m_tabWidget);
|
|
m_mainGridLayout->setContentsMargins(0, 0, 0, 0);
|
|
m_pgAdminMainTab = new QWidget(m_tabWidget);
|
|
m_tabGridLayout = new QGridLayout(m_pgAdminMainTab);
|
|
m_tabGridLayout->setContentsMargins(0, 0, 0, 0);
|
|
m_mainWebView = new WebViewWindow(m_pgAdminMainTab);
|
|
|
|
#ifdef PGADMIN4_DEBUG
|
|
// If pgAdmin4 is run in debug mode, then we should enable the
|
|
// "Inspect" option, when the user right clicks on QWebView widget.
|
|
// This option is useful to debug the pgAdmin4 desktop application and open the developer tools.
|
|
QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
|
|
#endif
|
|
|
|
#ifdef __APPLE__
|
|
m_mainWebView->setStyle(QStyleFactory::create("Fusion"));
|
|
#endif
|
|
|
|
m_tabGridLayout->addWidget(m_mainWebView, 0, 0, 1, 1);
|
|
m_tabWidget->addTab(m_pgAdminMainTab, QString());
|
|
m_tabWidget->setCurrentIndex(0);
|
|
m_tabWidget->setTabText(0, PGA_APP_NAME);
|
|
m_tabWidget->setTabToolTipText(0, PGA_APP_NAME) ;
|
|
|
|
setCentralWidget(m_tabWidget);
|
|
|
|
connect(m_mainWebView, SIGNAL(loadFinished(bool)), SLOT(finishLoading(bool)));
|
|
|
|
// Register the slot when click on the URL link form main menu bar
|
|
connect(m_mainWebView, SIGNAL(linkClicked(const QUrl &)),SLOT(urlLinkClicked(const QUrl &)));
|
|
|
|
// Register the slot on tab index change
|
|
connect(m_tabWidget,SIGNAL(currentChanged(int )),this,SLOT(tabIndexChanged(int )));
|
|
|
|
// Listen for download file request from the web page
|
|
m_mainWebView->page()->setForwardUnsupportedContent(true);
|
|
connect(m_mainWebView->page(), SIGNAL(downloadRequested(const QNetworkRequest &)), this, SLOT(download(const QNetworkRequest &)));
|
|
connect(m_mainWebView->page(), SIGNAL(unsupportedContent(QNetworkReply*)), this, SLOT(unsupportedContent(QNetworkReply*)));
|
|
|
|
m_mainWebView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
|
|
|
|
// Restore the geometry
|
|
QSettings settings;
|
|
restoreGeometry(settings.value("Browser/Geometry").toByteArray());
|
|
restoreState(settings.value("Browser/WindowState").toByteArray());
|
|
|
|
// The last save location
|
|
m_last_open_folder_path = settings.value("Browser/LastSaveLocation", QDir::homePath()).toString();
|
|
|
|
// Display the app
|
|
m_initialLoad = true;
|
|
m_loadAttempt = 1;
|
|
m_mainWebView->setUrl(m_appServerUrl);
|
|
}
|
|
|
|
// Save the window geometry on close
|
|
void BrowserWindow::closeEvent(QCloseEvent *event)
|
|
{
|
|
QSettings settings;
|
|
settings.setValue("Browser/Geometry", saveGeometry());
|
|
settings.setValue("Browser/WindowState", saveState());
|
|
QMainWindow::closeEvent(event);
|
|
}
|
|
|
|
|
|
// Create the actions for the window
|
|
void BrowserWindow::createActions()
|
|
{
|
|
// Open an arbitrary URL
|
|
openUrlShortcut = new QShortcut(QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_U), this);
|
|
openUrlShortcut->setContext(Qt::ApplicationShortcut);
|
|
connect(openUrlShortcut, SIGNAL(activated()), this, SLOT(openUrl()));
|
|
|
|
// Set the Python Path
|
|
preferencesShortcut = new QShortcut(QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_P), this);
|
|
preferencesShortcut->setContext(Qt::ApplicationShortcut);
|
|
connect(preferencesShortcut, SIGNAL(activated()), this, SLOT(preferences()));
|
|
|
|
// Exit the app
|
|
exitShortcut = new QShortcut(QKeySequence::Quit, this);
|
|
exitShortcut->setContext(Qt::ApplicationShortcut);
|
|
connect(exitShortcut, SIGNAL(activated()), this, SLOT(close()));
|
|
|
|
// About box
|
|
aboutShortcut = new QShortcut(QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_A), this);
|
|
aboutShortcut->setContext(Qt::ApplicationShortcut);
|
|
connect(aboutShortcut, SIGNAL(activated()), this, SLOT(about()));
|
|
}
|
|
|
|
|
|
// Process loading finished signals from the web view.
|
|
void BrowserWindow::finishLoading(bool ok)
|
|
{
|
|
if (m_initialLoad && !ok)
|
|
{
|
|
// The load attempt failed. Try again up to 4 times with an
|
|
// incremental backoff.
|
|
if (m_loadAttempt < 5)
|
|
{
|
|
if (m_loadAttempt > 1)
|
|
{
|
|
qDebug() << "Initial connection failed. Retrying in" << m_loadAttempt << "seconds.";
|
|
m_mainWebView->setHtml(QString(tr("<p>Failed to connect to the pgAdmin application server. Retrying in %1 seconds, ") +
|
|
tr("or click <a href=\"%2\">here</a> to try again now.</p>")).arg(m_loadAttempt).arg(m_appServerUrl));
|
|
}
|
|
else
|
|
{
|
|
m_mainWebView->setHtml(QString(tr("<p>Connecting to the application server...</p>")));
|
|
}
|
|
|
|
pause(m_loadAttempt);
|
|
m_mainWebView->setUrl(m_appServerUrl);
|
|
m_loadAttempt++;
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
qDebug() << "Initial connection failed after multiple attempts. Aborting.";
|
|
m_mainWebView->setHtml(QString(tr("<p>Failed to connect to the pgAdmin application server. ") +
|
|
tr("Click <a href=\"%1\">here</a> to try again.</p>")).arg(m_appServerUrl));
|
|
}
|
|
}
|
|
|
|
m_initialLoad = false;
|
|
}
|
|
|
|
// Check if Tab is already open with given URL name
|
|
int BrowserWindow::findURLTab(const QUrl &name)
|
|
{
|
|
int tabCount = 0;
|
|
WebViewWindow *webviewPtr = NULL;
|
|
|
|
for (tabCount = 1;tabCount < m_tabWidget->count();tabCount++)
|
|
{
|
|
QWidget *tab = m_tabWidget->widget(tabCount);
|
|
if (tab != NULL)
|
|
{
|
|
QList<QWidget*> widgetList = tab->findChildren<QWidget*>();
|
|
foreach( QWidget* widgetPtr, widgetList )
|
|
{
|
|
if (widgetPtr != NULL)
|
|
{
|
|
webviewPtr = dynamic_cast<WebViewWindow*>(widgetPtr);
|
|
|
|
if (webviewPtr != NULL && !QString::compare(webviewPtr->getFirstLoadURL(),name.host(), Qt::CaseInsensitive))
|
|
{
|
|
m_tabWidget->setCurrentIndex(tabCount);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Below slot will be called when user right click on download link and select "Save Link..." option from context menu
|
|
void BrowserWindow::download(const QNetworkRequest &request)
|
|
{
|
|
// Check that request contains data for download at client side
|
|
QUrl name;
|
|
|
|
if (m_downloadStarted)
|
|
{
|
|
// Inform user that a download is already started
|
|
QMessageBox::information(this, tr("Download warning"), tr("File download already in progress: %1").arg(m_defaultFilename));
|
|
return;
|
|
}
|
|
|
|
m_defaultFilename = QFileInfo(request.url().toString()).fileName();
|
|
|
|
// Open the dialog to save file
|
|
QFileDialog save_dialog(this);
|
|
save_dialog.setAcceptMode(QFileDialog::AcceptSave);
|
|
save_dialog.setWindowTitle(tr("Save file"));
|
|
save_dialog.setDirectory(m_last_open_folder_path);
|
|
save_dialog.selectFile(m_defaultFilename);
|
|
|
|
// Register the slot for directory travesing when file dialog is opened and save the last open directory
|
|
QObject::connect(&save_dialog, SIGNAL(directoryEntered(const QString &)), this, SLOT(current_dir_path(const QString &)));
|
|
m_dir = m_last_open_folder_path;
|
|
QString fileName = "";
|
|
QString f_name = "";
|
|
|
|
if (save_dialog.exec() == QDialog::Accepted) {
|
|
fileName = save_dialog.selectedFiles().first();
|
|
f_name = fileName.replace(m_dir, "");
|
|
// Remove the first character(/) from fiename
|
|
f_name.remove(0,1);
|
|
m_defaultFilename = f_name;
|
|
}
|
|
else
|
|
return;
|
|
|
|
fileName = m_dir + fileName;
|
|
// Clear the last open directory path
|
|
m_dir.clear();
|
|
|
|
#ifdef __APPLE__
|
|
// Check that user has given valid file name or not - forward slash is not allowed in file name
|
|
// In Mac OSX, forward slash is converted to colon(:) by Qt so we need to check for colon.
|
|
if (f_name.indexOf(":") != -1)
|
|
{
|
|
QMessageBox::information(this, tr("File name error"), tr("Invalid file name"));
|
|
return;
|
|
}
|
|
#else
|
|
// Check that user has given valid file name or not - forward slash is not allowed in file name
|
|
if (f_name.indexOf("/") != -1)
|
|
{
|
|
QMessageBox::information(this, tr("File name error"), tr("Invalid file name"));
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (fileName.isEmpty())
|
|
return;
|
|
else
|
|
{
|
|
m_downloadFilename = fileName;
|
|
|
|
QNetworkRequest newRequest = request;
|
|
newRequest.setAttribute(QNetworkRequest::User, fileName);
|
|
|
|
QObject *obj_web_page = QObject::sender();
|
|
if (obj_web_page != NULL)
|
|
{
|
|
QWebPage *sender_web_page = dynamic_cast<QWebPage*>(obj_web_page);
|
|
if (sender_web_page != NULL)
|
|
{
|
|
QNetworkAccessManager *networkManager = sender_web_page->networkAccessManager();
|
|
QNetworkReply *reply = networkManager->get(newRequest);
|
|
if (reply != NULL)
|
|
{
|
|
m_downloadStarted = 1;
|
|
m_downloadCancelled = 0;
|
|
// Connect the signal for downloadProgress and downloadFinished
|
|
connect( reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadFileProgress(qint64, qint64)) );
|
|
connect( reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Below slot will be called when file download is in progress
|
|
void BrowserWindow::downloadFileProgress(qint64 readData, qint64 totalData)
|
|
{
|
|
QNetworkReply *reply = ((QNetworkReply*)sender());
|
|
QNetworkRequest request = reply->request();
|
|
QVariant v = request.attribute(QNetworkRequest::User);
|
|
|
|
// When download is canceled by user then no need to write data to file
|
|
if (m_downloadCancelled)
|
|
return;
|
|
|
|
if(reply != NULL && reply->error() != QNetworkReply::NoError)
|
|
{
|
|
qDebug() << "Network error occurred whilst downloading: " << m_defaultFilename;
|
|
return;
|
|
}
|
|
|
|
// Download is started so open the file
|
|
if (!m_file)
|
|
{
|
|
m_file = new QFile(m_downloadFilename);
|
|
if (!m_file->open(QIODevice::WriteOnly))
|
|
{
|
|
qDebug() << "Error opening file: " << m_downloadFilename;
|
|
m_downloadFilename.clear();
|
|
m_defaultFilename.clear();
|
|
m_downloadStarted = 0;
|
|
return;
|
|
}
|
|
|
|
// Create progress bar dialog
|
|
m_progressDialog = new QProgressDialog (tr("Downloading file: %1 ").arg(m_defaultFilename), "Cancel", readData, totalData, this);
|
|
m_progressDialog->setWindowModality(Qt::WindowModal);
|
|
m_progressDialog->setWindowTitle(tr("Download progress"));
|
|
m_progressDialog->setMinimumWidth(450);
|
|
m_progressDialog->setMinimumHeight(80);
|
|
m_progressDialog->setWindowFlags(Qt::Window | Qt::CustomizeWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint);
|
|
// Register slot for file download cancel request
|
|
QObject::connect(m_progressDialog, SIGNAL(canceled()), this, SLOT(progressCanceled()));
|
|
m_reply = reply;
|
|
// Show downloading progress bar
|
|
m_progressDialog->show();
|
|
}
|
|
|
|
if (m_file)
|
|
{
|
|
// Write data to file
|
|
m_file->write(reply->read(readData));
|
|
m_progressDialog->setValue(readData);
|
|
|
|
// As read data and totalData difference is zero means downloading is finished.
|
|
if ((totalData - readData) == 0 ||
|
|
(readData != 0 && totalData == -1))
|
|
{
|
|
// As downloading is finished so remove progress bar dialog
|
|
if (m_progressDialog)
|
|
{
|
|
m_progressDialog->deleteLater();
|
|
m_progressDialog = NULL;
|
|
}
|
|
|
|
m_downloadStarted = 0;
|
|
m_downloadFilename.clear();
|
|
m_defaultFilename.clear();
|
|
m_downloadCancelled = 0;
|
|
if (m_file)
|
|
{
|
|
m_file->close();
|
|
delete m_file;
|
|
m_file = NULL;
|
|
}
|
|
|
|
if (m_reply)
|
|
m_reply = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Below slot will be called when user cancel the downloading file which is in progress.
|
|
void BrowserWindow::progressCanceled()
|
|
{
|
|
m_downloadCancelled = 1;
|
|
|
|
if (m_progressDialog)
|
|
{
|
|
m_progressDialog->deleteLater();
|
|
m_progressDialog = NULL;
|
|
}
|
|
|
|
if (m_file)
|
|
{
|
|
m_file->close();
|
|
// Remove the file from file system as downloading is canceled by user
|
|
m_file->remove();
|
|
delete m_file;
|
|
m_file = NULL;
|
|
}
|
|
|
|
if (m_reply)
|
|
{
|
|
m_reply->abort();
|
|
m_reply = NULL;
|
|
}
|
|
|
|
m_downloadFilename.clear();
|
|
m_defaultFilename.clear();
|
|
m_downloadStarted = 0;
|
|
}
|
|
|
|
// Below slot will called when file download is finished
|
|
void BrowserWindow::downloadFinished()
|
|
{
|
|
if (m_progressDialog)
|
|
{
|
|
m_progressDialog->deleteLater();
|
|
m_progressDialog = NULL;
|
|
}
|
|
|
|
m_downloadFilename.clear();
|
|
m_defaultFilename.clear();
|
|
m_downloadStarted = 0;
|
|
m_downloadCancelled = 0;
|
|
if (m_file)
|
|
{
|
|
m_file->close();
|
|
delete m_file;
|
|
m_file = NULL;
|
|
}
|
|
|
|
if (m_reply)
|
|
m_reply = NULL;
|
|
}
|
|
|
|
// Below slot will be called when user directly click on any download link
|
|
void BrowserWindow::unsupportedContent(QNetworkReply * reply)
|
|
{
|
|
#if QT_VERSION >= 0x050000
|
|
// Extract filename and query from encoded URL
|
|
QUrlQuery query_data(reply->url());
|
|
QString file_name = query_data.queryItemValue("filename");
|
|
QString query = query_data.queryItemValue("query");
|
|
#else
|
|
QUrl url(reply->url());
|
|
QString file_name = url.queryItemValue("filename");
|
|
QString query = url.queryItemValue("query");
|
|
#endif
|
|
|
|
if (m_downloadStarted)
|
|
{
|
|
// Inform user that download is already started
|
|
QMessageBox::information(this, tr("Download warning"), tr("File download already in progress: %1").arg(m_defaultFilename));
|
|
return;
|
|
}
|
|
|
|
// If encoded URL contains 'filename' attribute then use that filename in file dialog.
|
|
if (file_name.isEmpty() && query.isEmpty())
|
|
m_defaultFilename = QFileInfo(reply->url().toString()).fileName();
|
|
else
|
|
m_defaultFilename = file_name;
|
|
|
|
QFileDialog save_dialog(this);
|
|
save_dialog.setAcceptMode(QFileDialog::AcceptSave);
|
|
save_dialog.setWindowTitle(tr("Save file"));
|
|
save_dialog.setDirectory(m_last_open_folder_path);
|
|
save_dialog.selectFile(m_defaultFilename);
|
|
|
|
QObject::connect(&save_dialog, SIGNAL(directoryEntered(const QString &)), this, SLOT(current_dir_path(const QString &)));
|
|
m_dir = m_last_open_folder_path;
|
|
QString fileName = "";
|
|
QString f_name = "";
|
|
|
|
if (save_dialog.exec() == QDialog::Accepted) {
|
|
fileName = save_dialog.selectedFiles().first();
|
|
f_name = fileName.replace(m_dir, "");
|
|
// Remove the first character(/) from fiename
|
|
f_name.remove(0,1);
|
|
m_defaultFilename = f_name;
|
|
}
|
|
else
|
|
return;
|
|
|
|
fileName = m_dir + fileName;
|
|
// Clear last open folder path
|
|
m_dir.clear();
|
|
|
|
#ifdef __APPLE__
|
|
// Check that user has given valid file name or not - forward slash is not allowed in file name
|
|
// In Mac OSX, forward slash is converted to colon(:) by Qt so we need to check for colon.
|
|
if (f_name.indexOf(":") != -1)
|
|
{
|
|
QMessageBox::information(this, tr("File name error"), tr("Invalid file name"));
|
|
return;
|
|
}
|
|
#else
|
|
// Check that user has given valid file name or not - forward slash is not allowed in file name
|
|
if (f_name.indexOf("/") != -1)
|
|
{
|
|
QMessageBox::information(this, tr("File name error"), tr("Invalid file name"));
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (fileName.isEmpty())
|
|
return;
|
|
else
|
|
{
|
|
m_downloadFilename = fileName;
|
|
if (reply != NULL)
|
|
{
|
|
m_downloadStarted = 1;
|
|
m_downloadCancelled = 0;
|
|
connect( reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadFileProgress(qint64, qint64)));
|
|
connect( reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Slot: When the tab index change, hide/show the toolbutton displayed on tab
|
|
void BrowserWindow::tabIndexChanged(int index)
|
|
{
|
|
int tabCount = 1;
|
|
for (tabCount = 1;tabCount < m_tabWidget->count();tabCount++)
|
|
{
|
|
if (tabCount != index)
|
|
m_tabWidget->showHideToolButton(tabCount,0);
|
|
else
|
|
m_tabWidget->showHideToolButton(tabCount,1);
|
|
}
|
|
}
|
|
|
|
// Close the tab and remove the memory of the given index tab
|
|
void BrowserWindow::closetabs()
|
|
{
|
|
int loopCount = 0;
|
|
int index = 0;
|
|
QPushButton *btn = NULL;
|
|
int totalTabs = m_tabWidget->count();
|
|
|
|
// If QTabWidget contains only one tab then hide the TabBar window
|
|
if ((totalTabs - 1) < 2)
|
|
m_tabWidget->tabBar()->setVisible(false);
|
|
else
|
|
m_tabWidget->tabBar()->setVisible(true);
|
|
|
|
QObject *senderPtr = QObject::sender();
|
|
if (senderPtr != NULL)
|
|
{
|
|
btn = dynamic_cast<QPushButton*>(senderPtr);
|
|
index = m_tabWidget->getButtonIndex(btn);
|
|
}
|
|
|
|
if (index != 0)
|
|
{
|
|
QWidget *tab = m_tabWidget->widget(index);
|
|
WebViewWindow *webviewPtr = NULL;
|
|
loopCount = 0;
|
|
|
|
// free the allocated memory when the tab is closed
|
|
if (tab != NULL)
|
|
delete tab;
|
|
|
|
// Adjust the tab index value if the tab is closed in between
|
|
for (loopCount = 1;loopCount < totalTabs;loopCount++)
|
|
{
|
|
if (index > loopCount)
|
|
continue;
|
|
|
|
QWidget *tab = m_tabWidget->widget(loopCount);
|
|
if (tab != NULL)
|
|
{
|
|
QList<QWidget*> widgetList = tab->findChildren<QWidget*>();
|
|
foreach( QWidget* widgetPtr, widgetList )
|
|
{
|
|
if (widgetPtr != NULL)
|
|
{
|
|
webviewPtr = dynamic_cast<WebViewWindow*>(widgetPtr);
|
|
if (webviewPtr != NULL)
|
|
webviewPtr->setTabIndex((webviewPtr->getTabIndex() - 1));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Slot: go back to page and enable/disable toolbutton
|
|
void BrowserWindow::goBackPage()
|
|
{
|
|
WebViewWindow *webviewPtr = NULL;
|
|
|
|
QWidget *tab = m_tabWidget->widget(m_tabWidget->currentIndex());
|
|
if (tab != NULL)
|
|
{
|
|
QList<QWidget*> widgetList = tab->findChildren<QWidget*>();
|
|
foreach( QWidget* widgetPtr, widgetList )
|
|
{
|
|
if (widgetPtr != NULL)
|
|
{
|
|
webviewPtr = dynamic_cast<WebViewWindow*>(widgetPtr);
|
|
if (webviewPtr != NULL)
|
|
{
|
|
webviewPtr->back();
|
|
m_tabWidget->enableDisableToolButton(m_tabWidget->currentIndex());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Slot: go forward to page and enable/disable toolbutton
|
|
void BrowserWindow::goForwardPage()
|
|
{
|
|
WebViewWindow *webviewPtr = NULL;
|
|
|
|
QWidget *tab = m_tabWidget->widget(m_tabWidget->currentIndex());
|
|
if (tab != NULL)
|
|
{
|
|
QList<QWidget*> widgetList = tab->findChildren<QWidget*>();
|
|
foreach( QWidget* widgetPtr, widgetList )
|
|
{
|
|
if (widgetPtr != NULL)
|
|
{
|
|
webviewPtr = dynamic_cast<WebViewWindow*>(widgetPtr);
|
|
if (webviewPtr != NULL)
|
|
{
|
|
webviewPtr->forward();
|
|
m_tabWidget->enableDisableToolButton(m_tabWidget->currentIndex());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Slot: set the title of tab when the new tab created or existing tab contents changed
|
|
void BrowserWindow::tabTitleChanged(const QString &str)
|
|
{
|
|
if (!str.isEmpty())
|
|
{
|
|
QObject *senderPtr = QObject::sender();
|
|
WebViewWindow *webViewPtr = NULL;
|
|
if (senderPtr != NULL)
|
|
{
|
|
webViewPtr = dynamic_cast<WebViewWindow*>(senderPtr);
|
|
if (webViewPtr != NULL)
|
|
{
|
|
m_tabWidget->setTabText(webViewPtr->getTabIndex(), str);
|
|
m_tabWidget->setTabToolTipText(webViewPtr->getTabIndex(), str);
|
|
m_tabWidget->enableDisableToolButton(webViewPtr->getTabIndex());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_tabWidget->setTabText(m_tabWidget->currentIndex(), str);
|
|
m_tabWidget->setTabToolTipText(m_tabWidget->currentIndex(), str);
|
|
}
|
|
}
|
|
}
|
|
|
|
void BrowserWindow::current_dir_path(const QString &dir)
|
|
{
|
|
m_dir = dir;
|
|
m_last_open_folder_path = dir;
|
|
|
|
QSettings settings;
|
|
settings.setValue("Browser/LastSaveLocation", m_last_open_folder_path);
|
|
}
|
|
|
|
// Slot: Link is open from pgAdmin mainwindow
|
|
void BrowserWindow::urlLinkClicked(const QUrl &name)
|
|
{
|
|
// Check that request contains the data download at client side
|
|
QNetworkRequest request;
|
|
|
|
// First check is there any tab opened with same URL then open it again.
|
|
int tabFound = findURLTab(name);
|
|
|
|
if (!tabFound)
|
|
{
|
|
m_addNewTab = new QWidget(m_tabWidget);
|
|
m_addNewGridLayout = new QGridLayout(m_addNewTab);
|
|
m_addNewGridLayout->setContentsMargins(0, 0, 0, 0);
|
|
m_addNewWebView = new WebViewWindow(m_addNewTab);
|
|
|
|
// Listen for the download request from the web page
|
|
m_addNewWebView->page()->setForwardUnsupportedContent(true);
|
|
connect(m_addNewWebView->page(), SIGNAL(downloadRequested(const QNetworkRequest &)), this, SLOT(download(const QNetworkRequest &)));
|
|
connect(m_addNewWebView->page(), SIGNAL(unsupportedContent(QNetworkReply*)), this, SLOT(unsupportedContent(QNetworkReply*)));
|
|
|
|
m_widget = new QWidget(m_addNewTab);
|
|
m_toolBtnBack = new QToolButton(m_widget);
|
|
m_toolBtnBack->setFixedHeight(PGA_BTN_SIZE);
|
|
m_toolBtnBack->setFixedWidth(PGA_BTN_SIZE);
|
|
m_toolBtnBack->setIcon(QIcon(":/back.png"));
|
|
m_toolBtnBack->setToolTip(tr("Go back"));
|
|
m_toolBtnBack->setDisabled(true);
|
|
|
|
m_toolBtnForward = new QToolButton(m_widget);
|
|
m_toolBtnForward->setFixedHeight(PGA_BTN_SIZE);
|
|
m_toolBtnForward->setFixedWidth(PGA_BTN_SIZE);
|
|
m_toolBtnForward->setIcon(QIcon(":/forward.png"));
|
|
m_toolBtnForward->setToolTip(tr("Go forward"));
|
|
m_toolBtnForward->setDisabled(true);
|
|
|
|
QPushButton *m_btnClose = new QPushButton(m_widget);
|
|
m_btnClose->setFixedHeight(PGA_BTN_SIZE);
|
|
m_btnClose->setFixedWidth(PGA_BTN_SIZE);
|
|
m_btnClose->setIcon(QIcon(":/close.png"));
|
|
m_btnClose->setToolTip(tr("Close tab"));
|
|
|
|
m_horizontalLayout = new QHBoxLayout(m_widget);
|
|
m_horizontalLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
|
m_horizontalLayout->setSpacing(1);
|
|
m_horizontalLayout->addWidget(m_toolBtnBack);
|
|
m_horizontalLayout->addWidget(m_toolBtnForward);
|
|
|
|
// Register the slot on titleChange so set the tab text accordingly
|
|
connect(m_addNewWebView, SIGNAL(titleChanged(const QString &)), SLOT(tabTitleChanged(const QString &)));
|
|
|
|
// Register the slot on toolbutton to show the previous history of web
|
|
connect(m_toolBtnBack, SIGNAL(clicked()), this, SLOT(goBackPage()));
|
|
|
|
// Register the slot on toolbutton to show the next history of web
|
|
connect(m_toolBtnForward, SIGNAL(clicked()), this, SLOT(goForwardPage()));
|
|
|
|
// Register the slot on close button , added manually
|
|
connect(m_btnClose, SIGNAL(clicked()), SLOT(closetabs()));
|
|
|
|
m_addNewGridLayout->addWidget(m_addNewWebView, 0, 0, 1, 1);
|
|
m_tabWidget->addTab(m_addNewTab, QString());
|
|
m_tabWidget->tabBar()->setVisible(true);
|
|
m_tabWidget->setCurrentIndex((m_tabWidget->count() - 1));
|
|
|
|
// Set the back and forward button on tab
|
|
m_tabWidget->tabBar()->setTabButton((m_tabWidget->count() - 1), QTabBar::LeftSide, m_widget);
|
|
m_tabWidget->tabBar()->setTabButton((m_tabWidget->count() - 1), QTabBar::RightSide, m_btnClose);
|
|
|
|
m_addNewWebView->setFirstLoadURL(name.host());
|
|
m_addNewWebView->setTabIndex((m_tabWidget->count() - 1));
|
|
m_addNewWebView->setUrl(name);
|
|
}
|
|
}
|
|
|
|
// Pause for n seconds, without freezing the UI.
|
|
void BrowserWindow::pause(int seconds)
|
|
{
|
|
QTime dieTime = QTime::currentTime().addSecs(seconds);
|
|
|
|
while (QTime::currentTime() < dieTime)
|
|
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
|
|
}
|
|
|
|
// Display the about box
|
|
void BrowserWindow::about()
|
|
{
|
|
QMessageBox::about(this, tr("About %1").arg(PGA_APP_NAME), tr("%1 - PostgreSQL Tools").arg(PGA_APP_NAME));
|
|
}
|
|
|
|
// Open an arbitrary URL
|
|
void BrowserWindow::openUrl()
|
|
{
|
|
bool ok;
|
|
|
|
QInputDialog *dlg = new QInputDialog();
|
|
dlg->setInputMode(QInputDialog::TextInput);
|
|
dlg->setWindowTitle(QWidget::tr("Open URL"));
|
|
dlg->setLabelText(QWidget::tr("Enter a URL"));
|
|
dlg->setTextValue("http://");
|
|
dlg->resize(600,100);
|
|
|
|
ok = dlg->exec();
|
|
|
|
QString url = dlg->textValue();
|
|
|
|
if (ok && !url.isEmpty())
|
|
urlLinkClicked(QUrl(url));
|
|
}
|
|
|
|
// Edit the app configuration
|
|
void BrowserWindow::preferences()
|
|
{
|
|
QSettings settings;
|
|
bool ok;
|
|
|
|
ConfigWindow *dlg = new ConfigWindow();
|
|
dlg->setWindowTitle(QWidget::tr("Configuration"));
|
|
dlg->setPythonPath(settings.value("PythonPath").toString());
|
|
dlg->setApplicationPath(settings.value("ApplicationPath").toString());
|
|
dlg->setModal(true);
|
|
ok = dlg->exec();
|
|
|
|
QString pythonpath = dlg->getPythonPath();
|
|
QString applicationpath = dlg->getApplicationPath();
|
|
|
|
if (ok)
|
|
{
|
|
settings.setValue("PythonPath", pythonpath);
|
|
settings.setValue("ApplicationPath", applicationpath);
|
|
}
|
|
}
|
|
|