Support running on systems without a system tray. Fixes #3316

This commit is contained in:
Akshay Joshi 2018-07-17 12:10:35 +01:00 committed by Dave Page
parent 0137cfaee3
commit 765a88addf
11 changed files with 567 additions and 212 deletions

View File

@ -18,6 +18,7 @@ Bug fixes
| `Bug #3294 <https://redmine.postgresql.org/issues/3294>`_ - Infrastructure (and changes to the Query Tool) for realtime preference handling.
| `Bug #3309 <https://redmine.postgresql.org/issues/3309>`_ - Fix Directory format support for backups.
| `Bug #3316 <https://redmine.postgresql.org/issues/3316>`_ - Support running on systems without a system tray.
| `Bug #3319 <https://redmine.postgresql.org/issues/3319>`_ - Cleanup and fix handling of Query Tool Cancel button status.
| `Bug #3363 <https://redmine.postgresql.org/issues/3363>`_ - Fix restoring of restore options for sections.
| `Bug #3371 <https://redmine.postgresql.org/issues/3371>`_ - Don't create a session when the /misc/ping test endpoint is called.

13
runtime/.gitignore vendored
View File

@ -1,18 +1,11 @@
.qmake.cache
.qmake.stash
Makefile
moc_predefs.h
moc_BrowserWindow.cpp
moc_ConfigWindow.cpp
moc_LogWindow.cpp
moc_Server.cpp
moc_TabWindow.cpp
moc_WebViewWindow.cpp
moc_*.cpp
moc_*.h
pgAdmin4
pgAdmin4.app/
pgAdmin4.pro.user*
qrc_pgAdmin4.cpp
ui_BrowserWindow.h
ui_ConfigWindow.h
ui_LogWindow.h
ui_*.h
object_script.*

103
runtime/FloatingWindow.cpp Normal file
View File

@ -0,0 +1,103 @@
////////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// FloatingWindow.cpp - For GNOME 3.26 and above floating window will be used.
//
////////////////////////////////////////////////////////////////////////////
#include "FloatingWindow.h"
#include "ui_FloatingWindow.h"
FloatingWindow::FloatingWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::FloatingWindow)
{
m_newAction = NULL;
m_configAction = NULL;
m_logAction = NULL;
m_quitAction = NULL;
m_menuActions = NULL;
m_floatingWindowMenu = NULL;
ui->setupUi(this);
}
FloatingWindow::~FloatingWindow()
{
delete ui;
}
bool FloatingWindow::Init()
{
// Creating Menu
createMenu();
// Setup the icon itself. For convenience, we'll also use it for the dialogue.
#ifdef Q_OS_MAC
QIcon icon(":pgAdmin4-mac.png");
#else
QIcon icon(":pgAdmin4.png");
#endif
setWindowIcon(icon);
setWindowTitle(tr("pgAdmin"));
setFixedSize(300, 230);
setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::WindowMinimizeButtonHint);
return true;
}
// Create the menu
void FloatingWindow::createMenu()
{
createActions();
m_floatingWindowMenu = menuBar()->addMenu(QString(tr("%1")).arg(PGA_APP_NAME));
m_floatingWindowMenu->addAction(m_newAction);
m_floatingWindowMenu->addSeparator();
m_floatingWindowMenu->addAction(m_configAction);
m_floatingWindowMenu->addAction(m_logAction);
m_floatingWindowMenu->addSeparator();
m_floatingWindowMenu->addAction(m_quitAction);
}
// Create the menu actions
void FloatingWindow::createActions()
{
m_newAction = new QAction(QString(tr("&New %1 window...")).arg(PGA_APP_NAME), this);
connect(m_newAction, SIGNAL(triggered()), m_menuActions, SLOT(onNew()));
m_configAction = new QAction(tr("&Configure..."), this);
connect(m_configAction, SIGNAL(triggered()), m_menuActions, SLOT(onConfig()));
m_logAction = new QAction(tr("&View log..."), this);
connect(m_logAction, SIGNAL(triggered()), m_menuActions, SLOT(onLog()));
m_quitAction = new QAction(tr("&Shut down server"), this);
m_quitAction->setEnabled(false);
connect(m_quitAction, SIGNAL(triggered()), m_menuActions, SLOT(onQuit()));
}
void FloatingWindow::enableShutdownMenu()
{
if (m_quitAction != NULL)
{
m_quitAction->setEnabled(true);
}
}
void FloatingWindow::setMenuActions(MenuActions * menuActions)
{
m_menuActions = menuActions;
}
void FloatingWindow::closeEvent(QCloseEvent * event)
{
// Emit the signal to shut down the python server.
emit shutdownSignal(m_menuActions->getAppServerUrl());
event->accept();
exit(0);
}

56
runtime/FloatingWindow.h Normal file
View File

@ -0,0 +1,56 @@
////////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// FloatingWindow.h - For GNOME 3.26 and above floating window will be used.
//
////////////////////////////////////////////////////////////////////////////
#ifndef FLOATINGWINDOW_H
#define FLOATINGWINDOW_H
#include "pgAdmin4.h"
#include "MenuActions.h"
#include <QMainWindow>
namespace Ui {
class FloatingWindow;
}
class FloatingWindow : public QMainWindow
{
Q_OBJECT
public:
explicit FloatingWindow(QWidget *parent = 0);
~FloatingWindow();
bool Init();
void enableShutdownMenu();
void setMenuActions(MenuActions * menuActions);
private:
Ui::FloatingWindow *ui;
void createMenu();
void createActions();
void closeEvent(QCloseEvent * event);
QAction *m_newAction;
QAction *m_configAction;
QAction *m_logAction;
QAction *m_quitAction;
QMenu *m_floatingWindowMenu;
MenuActions *m_menuActions;
signals:
void shutdownSignal(QUrl);
};
#endif // FLOATINGWINDOW_H

155
runtime/FloatingWindow.ui Normal file
View File

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FloatingWindow</class>
<widget class="QMainWindow" name="FloatingWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>300</width>
<height>230</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>281</width>
<height>201</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">border-image:url(&quot;:pgAdmin4.png&quot;);</string>
</property>
<property name="text">
<string/>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Note: Installing a system tray plugin will prevent this window being shown.</string>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</widget>
<resources/>
<connections/>
</ui>

129
runtime/MenuActions.cpp Normal file
View File

@ -0,0 +1,129 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// MenuActions.cpp - Common file for menu actions.
//
//////////////////////////////////////////////////////////////////////////
#include "MenuActions.h"
// QT headers
#include <QMessageBox>
MenuActions::MenuActions()
{
m_logWindow = NULL;
m_logFile = "";
m_appServerUrl = "";
}
MenuActions::~MenuActions()
{
}
void MenuActions::setAppServerUrl(QString appServerUrl)
{
m_appServerUrl = appServerUrl;
}
void MenuActions::setLogFile(QString logFile)
{
m_logFile = logFile;
}
// Create a new application browser window on user request
void MenuActions::onNew()
{
QSettings settings;
QString cmd = settings.value("BrowserCommand").toString();
if (!cmd.isEmpty())
{
cmd.replace("%URL%", m_appServerUrl);
QProcess::startDetached(cmd);
}
else
{
if (!QDesktopServices::openUrl(m_appServerUrl))
{
QString error(QWidget::tr("Failed to open the system default web browser. Is one installed?."));
QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
exit(1);
}
}
}
// Show the config dialogue
void MenuActions::onConfig()
{
QSettings settings;
bool ok;
ConfigWindow *dlg = new ConfigWindow();
dlg->setWindowTitle(QString(tr("%1 Configuration")).arg(PGA_APP_NAME));
dlg->setBrowserCommand(settings.value("BrowserCommand").toString());
dlg->setPythonPath(settings.value("PythonPath").toString());
dlg->setApplicationPath(settings.value("ApplicationPath").toString());
dlg->setModal(true);
ok = dlg->exec();
QString browsercommand = dlg->getBrowserCommand();
QString pythonpath = dlg->getPythonPath();
QString applicationpath = dlg->getApplicationPath();
if (ok)
{
bool needRestart = (settings.value("PythonPath").toString() != pythonpath ||
settings.value("ApplicationPath").toString() != applicationpath);
settings.setValue("BrowserCommand", browsercommand);
settings.setValue("PythonPath", pythonpath);
settings.setValue("ApplicationPath", applicationpath);
if (needRestart)
{
if (QMessageBox::Yes == QMessageBox::question(NULL, tr("Shut down server?"), QString(tr("The %1 server must be restarted for changes to take effect. Do you want to shut down the server now?")).arg(PGA_APP_NAME), QMessageBox::Yes | QMessageBox::No))
{
exit(0);
}
}
}
}
// Show the log window
void MenuActions::onLog()
{
QSettings settings;
if (!m_logWindow)
{
m_logWindow = new LogWindow(NULL, m_logFile);
m_logWindow->setWindowTitle(QString(tr("%1 Log")).arg(PGA_APP_NAME));
}
m_logWindow->show();
m_logWindow->raise();
m_logWindow->activateWindow();
QCoreApplication::processEvents( QEventLoop::AllEvents, 100 );
m_logWindow->ReadLog();
}
// Exit
void MenuActions::onQuit()
{
if (QMessageBox::Yes == QMessageBox::question(NULL, tr("Shut down server?"), QString(tr("Are you sure you want to shut down the %1 server?")).arg(PGA_APP_NAME), QMessageBox::Yes | QMessageBox::No))
{
// Emit the signal to shut down the python server.
emit shutdownSignal(m_appServerUrl);
exit(0);
}
}

46
runtime/MenuActions.h Normal file
View File

@ -0,0 +1,46 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// MenuActions.h - Common file for menu actions.
//
//////////////////////////////////////////////////////////////////////////
#ifndef MENUACTIONS_H
#define MENUACTIONS_H
#include "pgAdmin4.h"
// App headers
#include "LogWindow.h"
#include "ConfigWindow.h"
class MenuActions: public QObject
{
Q_OBJECT
public:
MenuActions();
~MenuActions();
void setAppServerUrl(QString appServerUrl);
void setLogFile(QString logFile);
QString getAppServerUrl() { return m_appServerUrl; }
private:
QString m_appServerUrl, m_logFile;
LogWindow *m_logWindow;
protected slots:
void onNew();
void onConfig();
void onLog();
void onQuit();
signals:
void shutdownSignal(QUrl);
};
#endif // MENUACTIONS_H

View File

@ -9,22 +9,11 @@
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin4.h"
// QT headers
#include <QMessageBox>
// App headers
#include "ConfigWindow.h"
#include "LogWindow.h"
#include "TrayIcon.h"
TrayIcon::TrayIcon(QString logFile) :
m_logFile(logFile)
TrayIcon::TrayIcon()
{
m_logWindow = NULL;
m_trayIcon = NULL;
m_trayIconMenu = NULL;
@ -32,74 +21,22 @@ TrayIcon::TrayIcon(QString logFile) :
m_configAction = NULL;
m_logAction = NULL;
m_quitAction = NULL;
m_menuActions = NULL;
}
TrayIcon::~TrayIcon()
{
}
bool TrayIcon::Init()
void TrayIcon::Init()
{
if (! isSystemTrayAvailable())
return false;
createTrayIcon();
if (m_trayIcon)
m_trayIcon->show();
return true;
}
void TrayIcon::setAppServerUrl(QString appServerUrl)
{
m_appServerUrl = appServerUrl;
}
// Check whether system tray exists
bool TrayIcon::isSystemTrayAvailable()
{
int timeout = 10; // 30 sec * 10 = 5 minutes, thus we timeout after 5 minutes
int iteration = 0;
bool trayFound = false;
while (iteration < timeout)
{
// Check we can find the system tray.
if (!QSystemTrayIcon::isSystemTrayAvailable())
{
// Wait for 30 seconds.
wait(3000);
trayFound = false;
}
else
{
trayFound = true;
break;
}
iteration++;
}
return trayFound;
}
// Make application wait for msec milliseconds
void TrayIcon::wait(int msec)
{
QMutex mutex;
QWaitCondition wc;
mutex.lock();
wc.wait(&mutex, msec);
mutex.unlock();
}
// Create the tray icon
void TrayIcon::createTrayIcon()
{
@ -135,116 +72,21 @@ void TrayIcon::createTrayIcon()
setWindowIcon(icon);
}
// Create the menu actions
void TrayIcon::createActions()
{
m_newAction = new QAction(QString(tr("&New %1 window...")).arg(PGA_APP_NAME), this);
connect(m_newAction, SIGNAL(triggered()), this, SLOT(onNew()));
connect(m_newAction, SIGNAL(triggered()), m_menuActions, SLOT(onNew()));
m_configAction = new QAction(tr("&Configure..."), this);
connect(m_configAction, SIGNAL(triggered()), this, SLOT(onConfig()));
connect(m_configAction, SIGNAL(triggered()), m_menuActions, SLOT(onConfig()));
m_logAction = new QAction(tr("&View log..."), this);
connect(m_logAction, SIGNAL(triggered()), this, SLOT(onLog()));
connect(m_logAction, SIGNAL(triggered()), m_menuActions, SLOT(onLog()));
m_quitAction = new QAction(tr("&Shut down server"), this);
m_quitAction->setEnabled(false);
connect(m_quitAction, SIGNAL(triggered()), this, SLOT(onQuit()));
}
// Create a new application browser window on user request
void TrayIcon::onNew()
{
QSettings settings;
QString cmd = settings.value("BrowserCommand").toString();
if (!cmd.isEmpty())
{
cmd.replace("%URL%", m_appServerUrl);
QProcess::startDetached(cmd);
}
else
{
if (!QDesktopServices::openUrl(m_appServerUrl))
{
QString error(QWidget::tr("Failed to open the system default web browser. Is one installed?."));
QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
exit(1);
}
}
}
// Show the config dialogue
void TrayIcon::onConfig()
{
QSettings settings;
bool ok;
ConfigWindow *dlg = new ConfigWindow();
dlg->setWindowTitle(QString(tr("%1 Configuration")).arg(PGA_APP_NAME));
dlg->setBrowserCommand(settings.value("BrowserCommand").toString());
dlg->setPythonPath(settings.value("PythonPath").toString());
dlg->setApplicationPath(settings.value("ApplicationPath").toString());
dlg->setModal(true);
ok = dlg->exec();
QString browsercommand = dlg->getBrowserCommand();
QString pythonpath = dlg->getPythonPath();
QString applicationpath = dlg->getApplicationPath();
if (ok)
{
bool needRestart = (settings.value("PythonPath").toString() != pythonpath ||
settings.value("ApplicationPath").toString() != applicationpath);
settings.setValue("BrowserCommand", browsercommand);
settings.setValue("PythonPath", pythonpath);
settings.setValue("ApplicationPath", applicationpath);
if (needRestart)
{
if (QMessageBox::Yes == QMessageBox::question(this, tr("Shut down server?"), QString(tr("The %1 server must be restarted for changes to take effect. Do you want to shut down the server now?")).arg(PGA_APP_NAME), QMessageBox::Yes | QMessageBox::No))
{
exit(0);
}
}
}
}
// Show the log window
void TrayIcon::onLog()
{
QSettings settings;
if (!m_logWindow)
{
m_logWindow = new LogWindow(NULL, m_logFile);
m_logWindow->setWindowTitle(QString(tr("%1 Log")).arg(PGA_APP_NAME));
}
m_logWindow->show();
m_logWindow->raise();
m_logWindow->activateWindow();
QCoreApplication::processEvents( QEventLoop::AllEvents, 100 );
m_logWindow->ReadLog();
}
// Exit
void TrayIcon::onQuit()
{
if (QMessageBox::Yes == QMessageBox::question(this, tr("Shut down server?"), QString(tr("Are you sure you want to shut down the %1 server?")).arg(PGA_APP_NAME), QMessageBox::Yes | QMessageBox::No))
{
// Emit the signal to shut down the python server.
emit shutdownSignal(m_appServerUrl);
exit(0);
}
connect(m_quitAction, SIGNAL(triggered()), m_menuActions, SLOT(onQuit()));
}
void TrayIcon::enableShutdownMenu()
@ -254,3 +96,8 @@ void TrayIcon::enableShutdownMenu()
m_quitAction->setEnabled(true);
}
}
void TrayIcon::setMenuActions(MenuActions * menuActions)
{
m_menuActions = menuActions;
}

View File

@ -16,30 +16,24 @@
// QT headers
#include <QWidget>
#include <QMessageBox>
// App headers
#include "LogWindow.h"
#include "MenuActions.h"
class TrayIcon : public QWidget
{
Q_OBJECT
public:
TrayIcon(QString logFile);
TrayIcon();
~TrayIcon();
bool Init();
void setAppServerUrl(QString appServerUrl);
void Init();
void enableShutdownMenu();
void setMenuActions(MenuActions * menuActions);
private:
void createTrayIcon();
bool isSystemTrayAvailable();
void createActions();
void wait(int msec);
QAction *m_newAction;
QAction *m_configAction;
QAction *m_logAction;
@ -48,18 +42,7 @@ private:
QSystemTrayIcon *m_trayIcon;
QMenu *m_trayIconMenu;
QString m_appServerUrl, m_logFile;
LogWindow *m_logWindow;
private slots:
void onNew();
void onConfig();
void onLog();
void onQuit();
signals:
void shutdownSignal(QUrl);
MenuActions *m_menuActions;
};
#endif // TRAYICON_H

View File

@ -34,6 +34,8 @@
#include "ConfigWindow.h"
#include "Server.h"
#include "TrayIcon.h"
#include "MenuActions.h"
#include "FloatingWindow.h"
#include <QTime>
@ -172,6 +174,7 @@ int main(int argc, char * argv[])
// Display the spash screen
QSplashScreen *splash = new QSplashScreen();
splash->setPixmap(QPixmap(":/splash.png"));
splash->setWindowFlags(splash->windowFlags() | Qt::WindowStaysOnTopHint);
splash->show();
app.processEvents(QEventLoop::AllEvents);
@ -205,15 +208,43 @@ int main(int argc, char * argv[])
// Generate the filename for the log
logFileName = homeDir + (QString("/.%1.%2.log").arg(PGA_APP_NAME).arg(exeHash)).remove(" ");
// Start the tray service
TrayIcon *trayicon = new TrayIcon(logFileName);
// Create Menu Actions
MenuActions *menuActions = new MenuActions();
if(menuActions != NULL)
menuActions->setLogFile(logFileName);
if (!trayicon->Init())
splash->showMessage(QString(QWidget::tr("Checking for system tray...")), Qt::AlignBottom | Qt::AlignCenter);
// Check system tray is available or not. If not then create one floating window.
FloatingWindow *floatingWindow = NULL;
TrayIcon *trayicon = NULL;
if (QSystemTrayIcon::isSystemTrayAvailable())
{
QString error = QString(QWidget::tr("An error occurred initialising the tray icon"));
QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
// Start the tray service
trayicon = new TrayIcon();
exit(1);
// Set the MenuActions object to connect to slot
if (trayicon != NULL)
trayicon->setMenuActions(menuActions);
trayicon->Init();
}
else
{
splash->showMessage(QString(QWidget::tr("System tray not found, creating floating window...")), Qt::AlignBottom | Qt::AlignCenter);
// Unable to find tray icon, so creating floting window
floatingWindow = new FloatingWindow();
if (floatingWindow == NULL)
{
QString error = QString(QWidget::tr("Unable to initialize either a tray icon or control window."));
QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
exit(1);
}
// Set the MenuActions object to connect to slot
floatingWindow->setMenuActions(menuActions);
floatingWindow->Init();
}
// Fire up the webserver
@ -221,6 +252,7 @@ int main(int argc, char * argv[])
bool done = false;
splash->showMessage(QString(QWidget::tr("Starting pgAdmin4 server...")), Qt::AlignBottom | Qt::AlignCenter);
while (done != true)
{
server = new Server(port, key, logFileName);
@ -335,9 +367,13 @@ int main(int argc, char * argv[])
}
// Go!
trayicon->setAppServerUrl(appServerUrl);
menuActions->setAppServerUrl(appServerUrl);
// Enable the shutdown server menu as server started successfully.
trayicon->enableShutdownMenu();
if (trayicon != NULL)
trayicon->enableShutdownMenu();
if (floatingWindow != NULL)
floatingWindow->enableShutdownMenu();
QString cmd = settings.value("BrowserCommand").toString();
@ -357,10 +393,12 @@ int main(int argc, char * argv[])
}
}
QObject::connect(trayicon, SIGNAL(shutdownSignal(QUrl)), server, SLOT(shutdown(QUrl)));
QObject::connect(menuActions, SIGNAL(shutdownSignal(QUrl)), server, SLOT(shutdown(QUrl)));
splash->finish(NULL);
if (floatingWindow != NULL)
floatingWindow->show();
return app.exec();
}

View File

@ -87,19 +87,23 @@ else {
}
# Source code
HEADERS = \
Server.h \
HEADERS = Server.h \
pgAdmin4.h \
ConfigWindow.h \
TrayIcon.h \
LogWindow.h
LogWindow.h \
MenuActions.h \
FloatingWindow.h
SOURCES = pgAdmin4.cpp \
Server.cpp \
ConfigWindow.cpp \
TrayIcon.cpp \
LogWindow.cpp
LogWindow.cpp \
MenuActions.cpp \
FloatingWindow.cpp
FORMS = ConfigWindow.ui \
LogWindow.ui
LogWindow.ui \
FloatingWindow.ui
ICON = pgAdmin4.icns
QMAKE_INFO_PLIST = Info.plist