mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2024-11-23 01:06:31 -06:00
8f146ebb4c
Added functionality to open different website link and load the website data to different tab. To achieve this, new customized QTabWidget and QWebView are added to render the data to WebView widget. All the widgets (New Tab, WebViewWinodw, and QToolButton) are added dynamically. QToolButton is used to traverse back and forward to web document opened in WebViewWindow. Introduced the New class called WebViewWindow which is derived from QWebView. Each tab of the QTabWidget contains the instance of WebViewWindow class. WebViewWindow class is useful to display the web document. Introduced New class called TabWindow which is derived from QTabWidget. This class is useful to achieve following functionality: - Customize the close button of tabbar so that it can only be visible other then main pgAdmin 4 window. - Enable/Disable the toolbutton added left side of tabbar depending on the web history traversed by the user in WebViewWindow. - Set the tooltip text of the tabbar depending on the title change event of WebViewWindow class. Modified the Qt project file to support the both the version of python 2 and python 3. Qt5 is recommended to test pgAdmin4 in dektop mode.
178 lines
4.8 KiB
C++
178 lines
4.8 KiB
C++
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// pgAdmin 4 - PostgreSQL Tools
|
|
//
|
|
// Copyright (C) 2013 - 2016, The pgAdmin Development Team
|
|
// This software is released under the PostgreSQL Licence
|
|
//
|
|
// pgAdmin4.cpp - Main application entry point
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "pgAdmin4.h"
|
|
|
|
// Must be before QT
|
|
#include <Python.h>
|
|
|
|
#if QT_VERSION >= 0x050000
|
|
#include <QtWidgets>
|
|
#else
|
|
#include <QApplication>
|
|
#include <QDebug>
|
|
#include <QtNetwork>
|
|
#include <QLineEdit>
|
|
#include <QInputDialog>
|
|
#endif
|
|
|
|
// App headers
|
|
#include "BrowserWindow.h"
|
|
#include "Server.h"
|
|
|
|
int main(int argc, char * argv[])
|
|
{
|
|
// Create the QT application
|
|
QApplication app(argc, argv);
|
|
|
|
// Setup the settings management
|
|
QCoreApplication::setOrganizationName("pgAdmin Development Team");
|
|
QCoreApplication::setOrganizationDomain("pgadmin.org");
|
|
QCoreApplication::setApplicationName(PGA_APP_NAME);
|
|
|
|
quint16 port = 0L;
|
|
|
|
// Find an unused port number. Essentially, we're just reserving one
|
|
// here that Flask will use when we start up the server.
|
|
// In order to use the socket, we need to free this socket ASAP.
|
|
// Hence - putting this code in a code block so the scope of the socket
|
|
// variable vanishes to make that socket available.
|
|
{
|
|
QTcpSocket socket;
|
|
socket.bind(0, QAbstractSocket::DontShareAddress);
|
|
port = socket.localPort();
|
|
}
|
|
|
|
// Fire up the webserver
|
|
Server *server = new Server(port);
|
|
|
|
if (!server->Init())
|
|
{
|
|
qDebug() << server->getError();
|
|
|
|
QString error = QString(QWidget::tr("An error occurred initialising the application server:\n\n%1")).arg(server->getError());
|
|
QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
|
|
|
|
exit(1);
|
|
}
|
|
|
|
server->start();
|
|
|
|
// This is a hack. Wait a second and then check to see if the server thread
|
|
// is still running. If it's not, we probably had a startup error
|
|
QThread::sleep(1);
|
|
|
|
// Any errors?
|
|
if (server->isFinished() || server->getError().length() > 0)
|
|
{
|
|
qDebug() << server->getError();
|
|
|
|
QString error = QString(QWidget::tr("An error occurred initialising the application server:\n\n%1")).arg(server->getError());
|
|
QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
|
|
|
|
// Allow the user to tweak the Python Path if needed
|
|
QSettings settings;
|
|
bool ok;
|
|
|
|
QInputDialog *dlg = new QInputDialog();
|
|
dlg->setInputMode(QInputDialog::TextInput);
|
|
dlg->setWindowTitle(QWidget::tr("Python Path"));
|
|
dlg->setLabelText(QWidget::tr("Set the Python search path (separate entries with a semicolon):"));
|
|
dlg->setTextValue(settings.value("PythonPath").toString());
|
|
dlg->resize(600,100);
|
|
ok = dlg->exec();
|
|
QString path = dlg->textValue();
|
|
|
|
if (ok)
|
|
settings.setValue("PythonPath", path);
|
|
|
|
exit(1);
|
|
}
|
|
|
|
// Generate the app server URL
|
|
QString appServerUrl = QString("http://localhost:%1/").arg(port);
|
|
|
|
// Now the server should be up, we'll attempt to connect and get a response.
|
|
// We'll retry in a loop a few time before aborting if necessary. The browser
|
|
// will also retry - that shouldn't (in theory) be necessary, but it won't
|
|
// hurt.
|
|
int attempt = 0;
|
|
while (attempt++ < 3)
|
|
{
|
|
bool alive = PingServer(QUrl(appServerUrl));
|
|
|
|
if (alive)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (attempt == 10)
|
|
{
|
|
QString error(QWidget::tr("The application server could not be contacted."));
|
|
QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
|
|
|
|
exit(1);
|
|
}
|
|
|
|
QThread::sleep(1);
|
|
}
|
|
|
|
// Create & show the main window
|
|
BrowserWindow browserWindow(appServerUrl);
|
|
browserWindow.show();
|
|
|
|
// Go!
|
|
return app.exec();
|
|
}
|
|
|
|
|
|
// Ping the application server to see if it's alive
|
|
bool PingServer(QUrl url)
|
|
{
|
|
QNetworkAccessManager manager;
|
|
QEventLoop loop;
|
|
QNetworkReply *reply;
|
|
QVariant redirectUrl;
|
|
|
|
url.setPath("/ping");
|
|
|
|
do
|
|
{
|
|
reply = manager.get(QNetworkRequest(url));
|
|
|
|
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
|
|
loop.exec();
|
|
|
|
redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
|
url = redirectUrl.toUrl();
|
|
|
|
if (!redirectUrl.isNull())
|
|
delete reply;
|
|
|
|
} while (!redirectUrl.isNull());
|
|
|
|
if (reply->error() != QNetworkReply::NoError)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
QString response = reply->readAll();
|
|
|
|
if (response != "PING")
|
|
{
|
|
qDebug() << "Failed to connect, server response: " << response;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|