diff --git a/runtime/BrowserWindow.cpp b/runtime/BrowserWindow.cpp index 023a2647b..89de5871e 100644 --- a/runtime/BrowserWindow.cpp +++ b/runtime/BrowserWindow.cpp @@ -2,7 +2,7 @@ // // pgAdmin 4 - PostgreSQL Tools // -// Copyright (C) 2013, The pgAdmin Development Team +// Copyright (C) 2013 - 2016, The pgAdmin Development Team // This software is released under the PostgreSQL Licence // // BrowserWindow.cpp - Implementation of the main window class @@ -11,9 +11,6 @@ #include "pgAdmin4.h" -// QT headers -#include - #if QT_VERSION >= 0x050000 #include #include @@ -30,20 +27,56 @@ // App headers #include "BrowserWindow.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_appServerUrl = url; // Setup the UI createActions(); createMenus(); - // Create the WebKit control - webView = new QWebView(this); - setCentralWidget(webView); - connect(webView, SIGNAL(loadFinished(bool)), SLOT(finishLoading(bool))); + 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); + + 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) ; + +#ifndef __APPLE__ + m_tabWidget->setStyleSheet("QTabBar::tab{max-height:24px;max-width:250px;}"); +#endif + + 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 ))); + + m_mainWebView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); // Restore the geometry QSettings settings; @@ -53,10 +86,9 @@ BrowserWindow::BrowserWindow(QString url) // Display the app m_initialLoad = true; m_loadAttempt = 1; - webView->setUrl(m_appServerUrl); + m_mainWebView->setUrl(m_appServerUrl); } - // Save the window geometry on close void BrowserWindow::closeEvent(QCloseEvent *event) { @@ -125,16 +157,16 @@ void BrowserWindow::finishLoading(bool ok) if (m_loadAttempt > 1) { qDebug() << "Initial connection failed. Retrying in" << m_loadAttempt << "seconds."; - webView->setHtml(QString(tr("

Failed to connect to the pgAdmin application server. Retrying in %1 seconds, ") + + m_mainWebView->setHtml(QString(tr("

Failed to connect to the pgAdmin application server. Retrying in %1 seconds, ") + tr("or click here to try again now.

")).arg(m_loadAttempt).arg(m_appServerUrl)); } else { - webView->setHtml(QString(tr("

Connecting to the application server...

"))); + m_mainWebView->setHtml(QString(tr("

Connecting to the application server...

"))); } pause(m_loadAttempt); - webView->setUrl(m_appServerUrl); + m_mainWebView->setUrl(m_appServerUrl); m_loadAttempt++; return; @@ -142,7 +174,7 @@ void BrowserWindow::finishLoading(bool ok) else { qDebug() << "Initial connection failed after multiple attempts. Aborting."; - webView->setHtml(QString(tr("

Failed to connect to the pgAdmin application server. ") + + m_mainWebView->setHtml(QString(tr("

Failed to connect to the pgAdmin application server. ") + tr("Click here to try again.

")).arg(m_appServerUrl)); } } @@ -150,6 +182,233 @@ void BrowserWindow::finishLoading(bool ok) 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 widgetList = tab->findChildren(); + foreach( QWidget* widgetPtr, widgetList ) + { + if (widgetPtr != NULL) + { + webviewPtr = dynamic_cast(widgetPtr); + + if (webviewPtr != NULL && !QString::compare(webviewPtr->getFirstLoadURL(),name.url(), Qt::CaseInsensitive)) + { + m_tabWidget->setCurrentIndex(tabCount); + return 1; + } + } + } + } + } + + return 0; +} + +// 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(); + + QObject *senderPtr = QObject::sender(); + if (senderPtr != NULL) + { + btn = dynamic_cast(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 widgetList = tab->findChildren(); + foreach( QWidget* widgetPtr, widgetList ) + { + if (widgetPtr != NULL) + { + webviewPtr = dynamic_cast(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 widgetList = tab->findChildren(); + foreach( QWidget* widgetPtr, widgetList ) + { + if (widgetPtr != NULL) + { + webviewPtr = dynamic_cast(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 widgetList = tab->findChildren(); + foreach( QWidget* widgetPtr, widgetList ) + { + if (widgetPtr != NULL) + { + webviewPtr = dynamic_cast(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(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); + } + } +} + +// Slot: Link is open from pgAdmin mainwindow +void BrowserWindow::urlLinkClicked(const QUrl &name) +{ + // 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); + + m_widget = new QWidget(m_addNewTab); + m_toolBtnBack = new QToolButton(m_widget); + m_toolBtnBack->setFixedHeight(16); + m_toolBtnBack->setFixedWidth(16); + m_toolBtnBack->setText(PGA_BTN_BACK); + m_toolBtnBack->setDisabled(true); + + m_toolBtnForward = new QToolButton(m_widget); + m_toolBtnForward->setFixedHeight(16); + m_toolBtnForward->setFixedWidth(16); + m_toolBtnForward->setText(PGA_BTN_FORWARD); + m_toolBtnForward->setDisabled(true); + + QPushButton *m_btnClose = new QPushButton(m_widget); + m_btnClose->setText(PGA_BTN_CLOSE); + m_btnClose->setFixedHeight(16); + m_btnClose->setFixedWidth(16); + + m_horizontalLayout = new QHBoxLayout(m_widget); + m_horizontalLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); + 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->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.url()); + m_addNewWebView->setTabIndex((m_tabWidget->count() - 1)); + m_addNewWebView->setUrl(name); + } +} // Pause for n seconds, without freezing the UI. void BrowserWindow::pause(int seconds) @@ -160,14 +419,12 @@ void BrowserWindow::pause(int seconds) QCoreApplication::processEvents(QEventLoop::AllEvents, 100); } - // Display the about box void BrowserWindow::about() { - QMessageBox::about(this, tr("About pgAdmin 4"), tr("pgAdmin 4 - PostgreSQL Tools")); + 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() { @@ -175,7 +432,7 @@ void BrowserWindow::openUrl() QString url = QInputDialog::getText(this, tr("Open URL"), tr("Enter a URL"), QLineEdit::Normal, "http://", &ok); if (ok && !url.isEmpty()) - webView->setUrl(url); + m_mainWebView->setUrl(url); } // Open an arbitrary URL @@ -184,7 +441,14 @@ void BrowserWindow::pythonPath() QSettings settings; bool ok; - QString path = QInputDialog::getText(this, tr("Python Path"), tr("Set the Python search path:"), QLineEdit::Normal, settings.value("PythonPath").toString(), &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); diff --git a/runtime/BrowserWindow.h b/runtime/BrowserWindow.h index e580d8b84..f0676012d 100644 --- a/runtime/BrowserWindow.h +++ b/runtime/BrowserWindow.h @@ -2,7 +2,7 @@ // // pgAdmin 4 - PostgreSQL Tools // -// Copyright (C) 2013, The pgAdmin Development Team +// Copyright (C) 2013 - 2016, The pgAdmin Development Team // This software is released under the PostgreSQL Licence // // BrowserWindow.h - Declaration of the main window class @@ -13,8 +13,8 @@ #define BROWSERWINDOW_H #include "pgAdmin4.h" - -#include +#include "TabWindow.h" +#include "WebViewWindow.h" #if QT_VERSION >= 0x050000 #include @@ -41,15 +41,23 @@ protected: protected slots: void finishLoading(bool); + void urlLinkClicked(const QUrl &); + void closetabs(); + void tabTitleChanged(const QString &); private slots: void openUrl(); void pythonPath(); void about(); +public slots: + void tabIndexChanged(int index); + void goBackPage(); + void goForwardPage(); + private: QString m_appServerUrl; - QWebView *webView; + WebViewWindow *m_mainWebView; QMenu *fileMenu; QMenu *helpMenu; QAction *openUrlAction; @@ -57,12 +65,26 @@ private: QAction *exitAction; QAction *aboutAction; + QGridLayout *m_tabGridLayout; + QGridLayout *m_mainGridLayout; + TabWindow *m_tabWidget; + QWidget *m_pgAdminMainTab; + + QWidget *m_addNewTab; + QGridLayout *m_addNewGridLayout; + WebViewWindow *m_addNewWebView; + QHBoxLayout *m_horizontalLayout; + QWidget *m_widget; + QToolButton *m_toolBtnBack; + QToolButton *m_toolBtnForward; + bool m_initialLoad; int m_loadAttempt; void createActions(); void createMenus(); void pause(int seconds = 1); + int findURLTab(const QUrl &name); }; #endif // BROWSERWINDOW_H diff --git a/runtime/Server.cpp b/runtime/Server.cpp index b47ece3ce..a29183b8c 100644 --- a/runtime/Server.cpp +++ b/runtime/Server.cpp @@ -2,7 +2,7 @@ // // pgAdmin 4 - PostgreSQL Tools // -// Copyright (C) 2013, The pgAdmin Development Team +// Copyright (C) 2013 - 2016, The pgAdmin Development Team // This software is released under the PostgreSQL Licence // // Server.cpp - Thread in which the web server will run. @@ -26,9 +26,22 @@ Server::Server(quint16 port) { // Appserver port m_port = port; + m_wcAppName = NULL; // Initialise Python + Py_NoSiteFlag=1; + + // Python3 requires conversion of char * to wchar_t *, so... +#ifdef PYTHON2 Py_SetProgramName(PGA_APP_NAME.toUtf8().data()); +#else + char *appName = PGA_APP_NAME.toUtf8().data(); + const size_t cSize = strlen(appName)+1; + m_wcAppName = new wchar_t[cSize]; + mbstowcs (m_wcAppName, appName, cSize); + Py_SetProgramName(m_wcAppName); +#endif + Py_Initialize(); // Setup the search path @@ -44,13 +57,22 @@ Server::Server(quint16 port) PyObject* sysPath = PySys_GetObject((char*)"path"); // Add new additional path elements - for (int i = 0; i < path_list.size(); ++i) + for (int i = path_list.size() - 1; i >= 0 ; --i) + { +#ifdef PYTHON2 PyList_Append(sysPath, PyString_FromString(path_list.at(i).toUtf8().data())); +#else + PyList_Append(sysPath, PyBytes_FromString(path_list.at(i).toUtf8().data())); +#endif + } } } Server::~Server() { + if (m_wcAppName) + delete m_wcAppName; + // Shutdown Python Py_Finalize(); } diff --git a/runtime/Server.h b/runtime/Server.h index 73c06b7e5..033ac0320 100644 --- a/runtime/Server.h +++ b/runtime/Server.h @@ -2,7 +2,7 @@ // // pgAdmin 4 - PostgreSQL Tools // -// Copyright (C) 2013, The pgAdmin Development Team +// Copyright (C) 2013 - 2016, The pgAdmin Development Team // This software is released under the PostgreSQL Licence // // Server.h - Thread in which the web server will run. @@ -38,7 +38,8 @@ private: QString m_appfile; QString m_error; - quint16 m_port; + quint16 m_port; + wchar_t *m_wcAppName; }; #endif // SERVER_H diff --git a/runtime/TabWindow.cpp b/runtime/TabWindow.cpp new file mode 100644 index 000000000..7252689a2 --- /dev/null +++ b/runtime/TabWindow.cpp @@ -0,0 +1,134 @@ +////////////////////////////////////////////////////////////////////////// +// +// pgAdmin 4 - PostgreSQL Tools +// +// Copyright (C) 2013 - 2016, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +// TabWindow.cpp - Implementation of the custom tab widget +// +////////////////////////////////////////////////////////////////////////// + +#include "pgAdmin4.h" + +// App headers +#include "TabWindow.h" + + +TabWindow::TabWindow(QWidget *parent) : + QTabWidget(parent) +{ + setParent(parent); + setTabsClosable(false); + setElideMode(Qt::ElideRight); +#ifdef __APPLE__ + m_testTabBar = new TabBar(); + setTabBar(m_testTabBar); +#endif + +} + +// Hide the close button of given index displayed on right side of tab +void TabWindow::enableDisableToolButton(const int &index) +{ + QToolButton *toolBtnPtr = NULL; + WebViewWindow *webviewPtr = NULL; + + // Enable/disable the toolbutton based on the history + QWidget *tab1 = this->widget(index); + if (tab1 != NULL) + { + QList widgetList = tab1->findChildren(); + foreach( QWidget* widgetPtr, widgetList ) + { + if (widgetPtr != NULL) + webviewPtr = dynamic_cast(widgetPtr); + } + } + + QWidget *tab = tabBar()->tabButton(index, QTabBar::LeftSide); + if (tab != NULL) + { + QList widgetList = tab->findChildren(); + foreach( QWidget* widgetPtr, widgetList ) + { + if (widgetPtr != NULL) + { + toolBtnPtr = dynamic_cast(widgetPtr); + if (webviewPtr != NULL && toolBtnPtr != NULL) + { + if (!QString::compare(toolBtnPtr->text(), PGA_BTN_BACK, Qt::CaseInsensitive)) + { + if (webviewPtr->page()->history()->canGoBack()) + toolBtnPtr->setDisabled(false); + else + toolBtnPtr->setDisabled(true); + } + + if (!QString::compare(toolBtnPtr->text(), PGA_BTN_FORWARD, Qt::CaseInsensitive)) + { + if (webviewPtr->page()->history()->canGoForward()) + toolBtnPtr->setDisabled(false); + else + toolBtnPtr->setDisabled(true); + } + } + } + } + } +} + +// Get the index of the pushbutton which is requested by user to close the tab +int TabWindow::getButtonIndex(QPushButton *btn) +{ + QPushButton *nextBtnPtr = NULL; + int loopCount = 0; + int totalTabs = this->count(); + + for (loopCount = 1;loopCount < totalTabs;loopCount++) + { + QWidget *tab = tabBar()->tabButton(loopCount, QTabBar::RightSide); + if (tab != NULL) + { + nextBtnPtr = dynamic_cast(tab); + if (nextBtnPtr != NULL && btn != NULL && nextBtnPtr == btn) + return loopCount; + } + } + + return 0; +} + +// Show and Hide the toolbutton once the tab is deselected depending on the option +// option 0: Hide the toolButton +// option 1: Show the toolButton +void TabWindow::showHideToolButton(const int &index, const int &option) +{ + QToolButton *toolBtnPtr = NULL; + + QWidget *tab = tabBar()->tabButton(index, QTabBar::LeftSide); + if (tab != NULL) + { + QList widgetList = tab->findChildren(); + foreach( QWidget* widgetPtr, widgetList ) + { + if (widgetPtr != NULL) + { + toolBtnPtr = dynamic_cast(widgetPtr); + if (toolBtnPtr != NULL) + { + if (!option) + toolBtnPtr->hide(); + else + toolBtnPtr->show(); + } + } + } + } +} + +// Set the tab tool tip text +void TabWindow::setTabToolTipText(const int &index, const QString &toolTipString) +{ + tabBar()->setTabToolTip(index, toolTipString); +} diff --git a/runtime/TabWindow.h b/runtime/TabWindow.h new file mode 100644 index 000000000..9fd10e33d --- /dev/null +++ b/runtime/TabWindow.h @@ -0,0 +1,57 @@ +////////////////////////////////////////////////////////////////////////// +// +// pgAdmin 4 - PostgreSQL Tools +// +// Copyright (C) 2013 - 2016, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +// TabWindow.h - Declaration of the custom tab widget +// +////////////////////////////////////////////////////////////////////////// + +#ifndef TABWINDOW_H +#define TABWINDOW_H + +#include "pgAdmin4.h" +#include "WebViewWindow.h" + +// Define button characters +const QString PGA_BTN_FORWARD = QString("\u2192"); +const QString PGA_BTN_BACK = QString("\u2190"); +const QString PGA_BTN_CLOSE = QString("\u2715"); + +class TabBar : public QTabBar +{ + Q_OBJECT +public: + TabBar(QWidget* parent=0) : QTabBar(parent) + { + } + +protected: + QSize tabSizeHint(int) const + { + return QSize(250, 24); + } +}; + +class TabWindow : public QTabWidget +{ + Q_OBJECT +public: + TabWindow(QWidget *parent = 0); + + int getButtonIndex(QPushButton *btn); + void showHideToolButton(const int &index,const int &option); + void enableDisableToolButton(const int &index); + void setTabToolTipText(const int &index, const QString &toolTipString); + QTabBar *tabBar() const + { + return QTabWidget::tabBar(); + } + +private: + TabBar *m_testTabBar; +}; + +#endif // TABWINDOW_H diff --git a/runtime/WebViewWindow.cpp b/runtime/WebViewWindow.cpp new file mode 100644 index 000000000..2e7cd9e8d --- /dev/null +++ b/runtime/WebViewWindow.cpp @@ -0,0 +1,42 @@ +////////////////////////////////////////////////////////////////////////// +// +// pgAdmin 4 - PostgreSQL Tools +// +// Copyright (C) 2013 - 2016, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +// WebViewWindow.cpp - Implementation of the custom web view widget +// +////////////////////////////////////////////////////////////////////////// + +#include "pgAdmin4.h" + +// App headers +#include "WebViewWindow.h" + +WebViewWindow::WebViewWindow(QWidget *parent) : + QWebView(parent) +{ + m_url = QString(""); + m_tabIndex = 0; +} + +void WebViewWindow::setFirstLoadURL(const QString &url) +{ + m_url = url; +} + +QString WebViewWindow::getFirstLoadURL() const +{ + return m_url; +} + +void WebViewWindow::setTabIndex(const int &tabIndex) +{ + m_tabIndex = tabIndex; +} + +int WebViewWindow::getTabIndex() const +{ + return m_tabIndex; +} diff --git a/runtime/WebViewWindow.h b/runtime/WebViewWindow.h new file mode 100644 index 000000000..4fdddfc8d --- /dev/null +++ b/runtime/WebViewWindow.h @@ -0,0 +1,35 @@ +////////////////////////////////////////////////////////////////////////// +// +// pgAdmin 4 - PostgreSQL Tools +// +// Copyright (C) 2013 - 2016, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +// WebViewWindow.h - Declaration of the custom web view widget +// +////////////////////////////////////////////////////////////////////////// + +#ifndef WEBVIEWWINDOW_H +#define WEBVIEWWINDOW_H + +#include "pgAdmin4.h" + +#include + +class WebViewWindow : public QWebView +{ + Q_OBJECT +public: + WebViewWindow(QWidget *parent = NULL); + void setFirstLoadURL(const QString &url); + QString getFirstLoadURL() const; + void setTabIndex(const int &tabIndex); + int getTabIndex() const; + +private: + QString m_url; + int m_tabIndex; + +}; + +#endif // WEBVIEWWINDOW_H diff --git a/runtime/pgAdmin4.cpp b/runtime/pgAdmin4.cpp index 6546eb29a..5fa6b2d2b 100644 --- a/runtime/pgAdmin4.cpp +++ b/runtime/pgAdmin4.cpp @@ -2,7 +2,7 @@ // // pgAdmin 4 - PostgreSQL Tools // -// Copyright (C) 2013, The pgAdmin Development Team +// Copyright (C) 2013 - 2016, The pgAdmin Development Team // This software is released under the PostgreSQL Licence // // pgAdmin4.cpp - Main application entry point @@ -14,14 +14,14 @@ // Must be before QT #include -// QT headers -#include - #if QT_VERSION >= 0x050000 #include #else #include #include +#include +#include +#include #endif // App headers @@ -38,11 +38,18 @@ int main(int argc, char * argv[]) 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. - QTcpSocket socket; - socket.bind(0, QAbstractSocket::DontShareAddress); - quint16 port = socket.localPort(); + // 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); diff --git a/runtime/pgAdmin4.h b/runtime/pgAdmin4.h index a6b251ff4..48da3b09f 100644 --- a/runtime/pgAdmin4.h +++ b/runtime/pgAdmin4.h @@ -2,7 +2,7 @@ // // pgAdmin 4 - PostgreSQL Tools // -// Copyright (C) 2013, The pgAdmin Development Team +// Copyright (C) 2013 - 2016, The pgAdmin Development Team // This software is released under the PostgreSQL Licence // // pgAdmin4.h - Main application header @@ -23,6 +23,7 @@ #include #else #include +#include #endif // Application name diff --git a/runtime/pgAdmin4.pro b/runtime/pgAdmin4.pro index c9dd8c294..d75b92e01 100644 --- a/runtime/pgAdmin4.pro +++ b/runtime/pgAdmin4.pro @@ -7,20 +7,32 @@ greaterThan(QT_MAJOR_VERSION, 4) { QT += webkit network } +PYTHON_CONFIG=python3-config + # Find and configure Python -!system(which python-config > /dev/null 2>&1) { - error(The python-config executable could not be found. Ensure Python is installed and in the system path.) +!system(which python3-config > /dev/null 2>&1) { + !system(which python-config > /dev/null 2>&1) { + error(The python-config executable could not be found. Ensure Python is installed and in the system path.) + } else { + PYTHON_CONFIG=python-config + DEFINES += PYTHON2 + } } -QMAKE_CXXFLAGS += $$system(python-config --includes) -QMAKE_LFLAGS += $$system(python-config --ldflags) + +QMAKE_CXXFLAGS += $$system($$PYTHON_CONFIG --includes) +QMAKE_LFLAGS += $$system($$PYTHON_CONFIG --ldflags) # Source code HEADERS = BrowserWindow.h \ Server.h \ - pgAdmin4.h + pgAdmin4.h \ + TabWindow.h \ + WebViewWindow.h SOURCES = pgAdmin4.cpp \ BrowserWindow.cpp \ - Server.cpp + Server.cpp \ + TabWindow.cpp \ + WebViewWindow.cpp FORMS = BrowserWindow.ui ICON = pgAdmin4.icns QMAKE_INFO_PLIST = Info.plist