/*************************************************************************** * Copyright (C) 2015-2017 by Savoir-faire Linux * * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>* * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see <http://www.gnu.org/licenses/>. * **************************************************************************/ #include "mainwindow.h" #include "ui_mainwindow.h" #include <QDesktopWidget> #include <QWindow> #include <QScreen> #include "media/text.h" #include "media/textrecording.h" #ifdef Q_OS_WIN #include <windows.h> #include <QWinThumbnailToolBar> #include <QWinThumbnailToolButton> #include "winsparkle.h" #endif #include "aboutdialog.h" #include "settingskey.h" #include "callmodel.h" #include "callwidget.h" #include "utils.h" #include "version.h" MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); for (int i = 0; i < ui->navStack->count(); ++i) { if (auto navWidget = dynamic_cast<NavWidget*>(ui->navStack->widget(i))) { connect(navWidget, &NavWidget::NavigationRequested, [this](ScreenEnum scr) { Utils::setStackWidget(ui->navStack, ui->navStack->widget(scr)); }); } } connect(ui->navStack, SIGNAL(currentChanged(int)), this, SLOT(slotCurrentChanged(int)), Qt::QueuedConnection); QIcon icon(":images/jami.png"); this->setWindowIcon(icon); setWindowTitle(" "); GlobalSystemTray& sysIcon = GlobalSystemTray::instance(); sysIcon.setIcon(icon); QMenu* menu = new QMenu(); auto configAction = new QAction(tr("Settings"), this); connect(configAction, &QAction::triggered, [this]() { Utils::setStackWidget(ui->navStack, ui->settingswidget); setWindowState(Qt::WindowActive); }); menu->addAction(configAction); auto exitAction = new QAction(tr("Exit"), this); connect(exitAction, &QAction::triggered, [this]() { QCoreApplication::exit(); }); menu->addAction(exitAction); sysIcon.setContextMenu(menu); sysIcon.show(); connect(&sysIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason))); #ifdef Q_OS_WIN HMENU sysMenu = ::GetSystemMenu((HWND) winId(), FALSE); if (sysMenu != NULL) { ::AppendMenuA(sysMenu, MF_SEPARATOR, 0, 0); QString aboutTitle = tr("About"); ::AppendMenuW(sysMenu, MF_STRING, IDM_ABOUTBOX, aboutTitle.toStdWString().c_str()); } win_sparkle_set_appcast_url("https://dl.ring.cx/windows/winsparkle-ring.xml"); win_sparkle_set_app_details(L"Savoir-faire Linux", L"Jami", QString(VERSION_STRING).toStdWString().c_str()); win_sparkle_set_shutdown_request_callback([]() { QCoreApplication::exit(); }); win_sparkle_set_did_find_update_callback([]() { MainWindow::instance().showWindow(); }); win_sparkle_init(); if (win_sparkle_get_last_check_time() == -1) { win_sparkle_set_update_check_interval(86400); } QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, [=]() { win_sparkle_cleanup(); }); #endif setContextMenuPolicy(Qt::NoContextMenu); connect(&GlobalSystemTray::instance(), SIGNAL(messageClicked()), this, SLOT(notificationClicked())); connect(&netManager_, &QNetworkConfigurationManager::onlineStateChanged, [=](bool online) { Q_UNUSED(online) AccountModel::instance().slotConnectivityChanged(); }); auto flags_ = windowFlags(); auto accountList = LRCInstance::accountModel().getAccountList(); lastAccountCount_ = accountList.size(); ScreenEnum startScreen; if (accountList.size()) { readSettingsFromRegistry(); startScreen = ScreenEnum::CallScreen; } else { startScreen = ScreenEnum::WizardScreen; } Utils::setStackWidget(ui->navStack, ui->navStack->widget(startScreen)); if (startScreen == ScreenEnum::WizardScreen) { setWindowSize(startScreen); } if (auto navWidget = dynamic_cast<NavWidget*>(ui->navStack->widget(startScreen))) { navWidget->navigated(true); } lastScr_ = startScreen; } MainWindow::~MainWindow() { delete ui; } void MainWindow::slotCurrentChanged(int index) { auto accountList = LRCInstance::accountModel().getAccountList(); auto firstUse = (accountList.size() == 1 && lastScr_ == ScreenEnum::WizardScreen && lastAccountCount_ < accountList.size()) || !accountList.size(); if (lastScr_ == ScreenEnum::WizardScreen && lastAccountCount_ < accountList.size()) { lastAccountCount_ = accountList.size(); } for (int i = 0; i < ui->navStack->count(); ++i) { if (auto navWidget = dynamic_cast<NavWidget*>(ui->navStack->widget(i))) { navWidget->navigated(index == i); } } auto scr = Utils::toEnum<ScreenEnum>(index); if (scr == ScreenEnum::SetttingsScreen) { ui->settingswidget->updateSettings(ui->callwidget->getLeftPanelWidth()); } setWindowSize(scr, firstUse); lastScr_ = scr; } void MainWindow::onRingEvent(const QString& uri) { this->showNormal(); if (not uri.isEmpty()) { auto outCall = CallModel::instance().dialingCall(); outCall->setDialNumber(uri); outCall->performAction(Call::Action::ACCEPT); } } bool MainWindow::nativeEvent(const QByteArray& eventType, void* message, long* result) { Q_UNUSED(eventType) #ifdef Q_OS_WIN MSG* msg = (MSG*) message; if (msg->message == WM_SYSCOMMAND) { if ((msg->wParam & 0xfff0) == IDM_ABOUTBOX) { *result = 0; AboutDialog aboutDialog; aboutDialog.exec(); return true; } } #else Q_UNUSED(message) Q_UNUSED(result) #endif return false; } void MainWindow::trayActivated(QSystemTrayIcon::ActivationReason reason) { if (reason != QSystemTrayIcon::ActivationReason::Context) this->show(); } void MainWindow::showWindow() { if (currentWindowState_ == Qt::WindowMaximized) { showMaximized(); } else { showNormal(); } activateWindow(); raise(); } void MainWindow::notificationClicked() { showWindow(); } void MainWindow::createThumbBar() { #ifdef Q_OS_WIN QWinThumbnailToolBar* thumbbar = new QWinThumbnailToolBar(this); thumbbar->setWindow(this->windowHandle()); QWinThumbnailToolButton* settings = new QWinThumbnailToolButton(thumbbar); settings->setToolTip("Settings"); QIcon icon(":/images/settings.png"); settings->setIcon(icon); settings->setDismissOnClick(true); connect(settings, &QWinThumbnailToolButton::clicked, [this]() { Utils::setStackWidget(ui->navStack, ui->settingswidget); }); thumbbar->addButton(settings); #endif } void MainWindow::changeEvent(QEvent* e) { if (e->type() == QEvent::WindowStateChange) { QWindowStateChangeEvent* event = static_cast<QWindowStateChangeEvent*>(e); if (event->oldState() == Qt::WindowNoState && windowState() == Qt::WindowMaximized) { currentWindowState_ = Qt::WindowMaximized; } else if (event->oldState() == Qt::WindowMaximized && windowState() == Qt::WindowNoState) { currentWindowState_ = Qt::WindowNoState; } } QWidget::changeEvent(e); } void MainWindow::closeEvent(QCloseEvent* event) { Video::PreviewManager::instance().stopPreview(); QSettings settings; if (settings.value(SettingsKey::closeOrMinimized).toBool()) { this->hide(); event->ignore(); } else { settings.setValue(SettingsKey::geometry, saveGeometry()); settings.setValue(SettingsKey::windowState, saveState()); } this->disconnect(screenChangedConnection_); QMainWindow::closeEvent(event); } void MainWindow::readSettingsFromRegistry() { QSettings settings; restoreGeometry(settings.value(SettingsKey::geometry).toByteArray()); restoreState(settings.value(SettingsKey::windowState).toByteArray()); LRCInstance::editableDataTransferModel()->downloadDirectory = settings.value(SettingsKey::downloadPath, QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)).toString().toStdString() + "/"; if (not settings.contains(SettingsKey::enableNotifications)) { settings.setValue(SettingsKey::enableNotifications, true); } } void MainWindow::setWindowSize(ScreenEnum scr, bool firstUse) { auto screenNumber = qApp->desktop()->screenNumber(); auto accountList = LRCInstance::accountModel().getAccountList(); if (scr == ScreenEnum::WizardScreen && !accountList.size()) { hide(); setFixedSize(wizardDialogWidth, wizardDialogHeight); } else { setMinimumSize(mainWindowMinWidth, mainWindowMinHeight); setMaximumSize(QtMaxDimension, QtMaxDimension); } if (firstUse || !accountList.size()) { setGeometry( QStyle::alignedRect( Qt::LeftToRight, Qt::AlignCenter, size(), qApp->desktop()->screenGeometry(screenNumber) ) ); if (scr == ScreenEnum::WizardScreen) { setWindowFlags(Qt::Dialog); setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint)); adjustSize(); } else { setWindowFlags(flags_); } updateGeometry(); update(); show(); } } void MainWindow::show() { QMainWindow::show(); disconnect(screenChangedConnection_); screenChangedConnection_ = connect(windowHandle(), &QWindow::screenChanged, this, &MainWindow::slotScreenChanged); auto screenNumber = qApp->desktop()->screenNumber(); QScreen* screen = qApp->screens().at(screenNumber); currentScalingRatio_ = screen->logicalDotsPerInchX() / 96; qobject_cast<NavWidget*>(ui->navStack->currentWidget())->updateCustomUI(); } void MainWindow::slotScreenChanged(QScreen* screen) { adjustSize(); updateGeometry(); update(); currentScalingRatio_ = screen->logicalDotsPerInchX() / 96; // a little delay won't hurt ;) QTimer::singleShot(100, this, [this] { qobject_cast<NavWidget*>(ui->navStack->currentWidget())->updateCustomUI(); }); } void MainWindow::resizeEvent(QResizeEvent* event) { Q_UNUSED(event); qobject_cast<NavWidget*>(ui->navStack->currentWidget())->updateCustomUI(); } float MainWindow::getCurrentScalingRatio() { return currentScalingRatio_; } void MainWindow::keyReleaseEvent(QKeyEvent* ke) { emit keyReleased(ke); QMainWindow::keyReleaseEvent(ke); }