mainwindow.cpp 11.1 KB
Newer Older
Edric Milaret's avatar
Edric Milaret committed
1
/***************************************************************************
2
 * Copyright (C) 2015-2017 by Savoir-faire Linux                           *
Edric Milaret's avatar
Edric Milaret committed
3
 * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
4
 * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>          *
Edric Milaret's avatar
Edric Milaret committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *                                                                         *
 * 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"

Edric Milaret's avatar
Edric Milaret committed
23
#include <QDesktopWidget>
24 25
#include <QWindow>
#include <QScreen>
26 27 28

#include "media/text.h"
#include "media/textrecording.h"
Edric Milaret's avatar
Edric Milaret committed
29

30
#ifdef Q_OS_WIN
31 32 33 34 35
#include <windows.h>
#include <QWinThumbnailToolBar>
#include <QWinThumbnailToolButton>
#endif

36
#include "aboutdialog.h"
Edric Milaret's avatar
Edric Milaret committed
37
#include "settingskey.h"
38
#include "winsparkle.h"
Edric Milaret's avatar
Edric Milaret committed
39
#include "callmodel.h"
40 41
#include "callwidget.h"
#include "utils.h"
Andreas Traczyk's avatar
Andreas Traczyk committed
42
#include "wizarddialog.h"
43
#include "version.h"
Edric Milaret's avatar
Edric Milaret committed
44

45
MainWindow::MainWindow(QWidget* parent) :
Edric Milaret's avatar
Edric Milaret committed
46
    QMainWindow(parent),
47

48
    ui(new Ui::MainWindow)
Edric Milaret's avatar
Edric Milaret committed
49 50
{
    ui->setupUi(this);
51

52 53 54 55 56 57 58 59 60 61 62 63
    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);
Edric Milaret's avatar
Edric Milaret committed
64

65
    QIcon icon(":images/jami.png");
Edric Milaret's avatar
Edric Milaret committed
66 67

    this->setWindowIcon(icon);
Andreas Traczyk's avatar
Andreas Traczyk committed
68
    setWindowTitle(" ");
Edric Milaret's avatar
Edric Milaret committed
69

70 71 72
    GlobalSystemTray& sysIcon = GlobalSystemTray::instance();
    sysIcon.setIcon(icon);

73
    QMenu* menu = new QMenu();
74

75 76 77
    auto configAction = new QAction(tr("Settings"), this);
    connect(configAction, &QAction::triggered,
        [this]() {
78
            Utils::setStackWidget(ui->navStack, ui->settingswidget);
79 80
            setWindowState(Qt::WindowActive);
        });
81 82
    menu->addAction(configAction);

83
    auto exitAction = new QAction(tr("Exit"), this);
84 85 86 87
    connect(exitAction, &QAction::triggered,
        [this]() {
            QCoreApplication::exit();
        });
88 89
    menu->addAction(exitAction);

90 91 92 93
    sysIcon.setContextMenu(menu);
    sysIcon.show();

    connect(&sysIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
Edric Milaret's avatar
Edric Milaret committed
94 95
            this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));

Edric Milaret's avatar
Edric Milaret committed
96
    connect(&CallModel::instance(), SIGNAL(incomingCall(Call*)),
97 98
            this, SLOT(onIncomingCall(Call*)));

99
#ifdef Q_OS_WIN
100 101 102 103
    HMENU sysMenu = ::GetSystemMenu((HWND) winId(), FALSE);
    if (sysMenu != NULL) {
        ::AppendMenuA(sysMenu, MF_SEPARATOR, 0, 0);
        QString aboutTitle = tr("About");
104
        ::AppendMenuW(sysMenu, MF_STRING, IDM_ABOUTBOX, aboutTitle.toStdWString().c_str());
105 106
    }
#endif
107

108 109
    win_sparkle_set_appcast_url("http://dl.jami.net/windows/winsparkle-ring.xml");
    win_sparkle_set_app_details(L"Savoir-faire Linux", L"Jami", QString(VERSION_STRING).toStdWString().c_str());
110
    win_sparkle_set_shutdown_request_callback([]() {QCoreApplication::exit();});
111
    win_sparkle_set_did_find_update_callback([]() {MainWindow::instance().showNormal();});
112 113 114
    win_sparkle_init();

    if (win_sparkle_get_last_check_time() == -1) {
115
        win_sparkle_set_update_check_interval(86400);
116 117 118 119 120
    }

    QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, [=]() {
        win_sparkle_cleanup();
    });
121 122

    setContextMenuPolicy(Qt::NoContextMenu);
Edric Milaret's avatar
Edric Milaret committed
123 124

    connect(&GlobalSystemTray::instance(), SIGNAL(messageClicked()), this, SLOT(notificationClicked()));
Edric Milaret's avatar
Edric Milaret committed
125 126 127 128 129

    connect(&netManager_, &QNetworkConfigurationManager::onlineStateChanged, [=](bool online) {
        Q_UNUSED(online)
        AccountModel::instance().slotConnectivityChanged();
    });
Andreas Traczyk's avatar
Andreas Traczyk committed
130

131 132
    auto flags_ = windowFlags();

Andreas Traczyk's avatar
Andreas Traczyk committed
133
    auto accountList = LRCInstance::accountModel().getAccountList();
134
    lastAccountCount_ = accountList.size();
135
    ScreenEnum startScreen;
Andreas Traczyk's avatar
Andreas Traczyk committed
136
    if (accountList.size()) {
137 138
        readSettingsFromRegistry();
        startScreen = ScreenEnum::CallScreen;
Andreas Traczyk's avatar
Andreas Traczyk committed
139
    } else {
140 141 142 143 144 145
        startScreen = ScreenEnum::WizardScreen;
    }

    Utils::setStackWidget(ui->navStack, ui->navStack->widget(startScreen));
    if (startScreen == ScreenEnum::WizardScreen) {
        setWindowSize(startScreen);
Andreas Traczyk's avatar
Andreas Traczyk committed
146
    }
147 148 149 150 151
    if (auto navWidget = dynamic_cast<NavWidget*>(ui->navStack->widget(startScreen))) {
        navWidget->navigated(true);
    }

    lastScr_ = startScreen;
Andreas Traczyk's avatar
Andreas Traczyk committed
152 153 154 155 156 157 158 159 160

    connect(windowHandle(), &QWindow::activeChanged,
        [this]() {
            auto screenNumber = qApp->desktop()->screenNumber();
            QScreen* screen = qApp->screens().at(screenNumber);
            windowHandle()->setScreen(nullptr);
            windowHandle()->setScreen(screen);
        });

Edric Milaret's avatar
Edric Milaret committed
161 162 163 164 165 166 167
}

MainWindow::~MainWindow()
{
    delete ui;
}

168 169
void
MainWindow::slotCurrentChanged(int index)
170
{
171 172
    auto accountList = LRCInstance::accountModel().getAccountList();
    auto firstUse =
173 174
        (accountList.size() == 1 && lastScr_ == ScreenEnum::WizardScreen &&
         lastAccountCount_ < accountList.size()) ||
175
        !accountList.size();
176 177 178 179
    if (lastScr_ == ScreenEnum::WizardScreen &&
        lastAccountCount_ < accountList.size()) {
        lastAccountCount_ = accountList.size();
    }
180 181 182 183
    for (int i = 0; i < ui->navStack->count(); ++i) {
        if (auto navWidget = dynamic_cast<NavWidget*>(ui->navStack->widget(i))) {
            navWidget->navigated(index == i);
        }
184 185
    }

186 187 188 189
    auto scr = Utils::toEnum<ScreenEnum>(index);

    if (scr == ScreenEnum::SetttingsScreen) {
        ui->settingswidget->updateSettings(ui->callwidget->getLeftPanelWidth());
190 191
    }

192 193
    setWindowSize(scr, firstUse);
    lastScr_ = scr;
194 195
}

Edric Milaret's avatar
Edric Milaret committed
196
void
197
MainWindow::onRingEvent(const QString& uri)
Edric Milaret's avatar
Edric Milaret committed
198 199 200 201 202 203 204 205 206
{
    this->showNormal();
    if (not uri.isEmpty()) {
        auto outCall = CallModel::instance().dialingCall();
        outCall->setDialNumber(uri);
        outCall->performAction(Call::Action::ACCEPT);
    }
}

207
bool
208
MainWindow::nativeEvent(const QByteArray& eventType, void* message, long* result)
Edric Milaret's avatar
Edric Milaret committed
209
{
210
    Q_UNUSED(eventType)
Edric Milaret's avatar
Edric Milaret committed
211

212 213
#ifdef Q_OS_WIN
    MSG* msg = (MSG*) message;
214 215 216 217 218 219 220 221 222 223

    if (msg->message == WM_SYSCOMMAND) {
        if ((msg->wParam & 0xfff0) == IDM_ABOUTBOX) {
            *result = 0;

            AboutDialog aboutDialog;
            aboutDialog.exec();

            return true;
        }
Edric Milaret's avatar
Edric Milaret committed
224
    }
225 226 227
#else
    Q_UNUSED(message)
    Q_UNUSED(result)
228 229
#endif
    return false;
Edric Milaret's avatar
Edric Milaret committed
230 231 232
}

void
233 234
MainWindow::trayActivated(QSystemTrayIcon::ActivationReason reason)
{
Edric Milaret's avatar
Edric Milaret committed
235 236 237
    if (reason != QSystemTrayIcon::ActivationReason::Context)
        this->show();
}
238

Edric Milaret's avatar
Edric Milaret committed
239 240 241
void
MainWindow::notificationClicked() {
    showNormal();
242 243
    activateWindow();
    raise();
Edric Milaret's avatar
Edric Milaret committed
244 245
}

246
void
247
MainWindow::onIncomingCall(Call* call)
248
{
249 250 251
    Q_UNUSED(call);
    QWidget::showNormal();
}
252 253 254 255

void
MainWindow::createThumbBar()
{
256 257
#ifdef Q_OS_WIN
    QWinThumbnailToolBar* thumbbar = new QWinThumbnailToolBar(this);
258
    thumbbar->setWindow(this->windowHandle());
259
    QWinThumbnailToolButton* settings = new QWinThumbnailToolButton(thumbbar);
260 261 262 263 264
    settings->setToolTip("Settings");
    QIcon icon(":/images/settings.png");
    settings->setIcon(icon);
    settings->setDismissOnClick(true);
    connect(settings, &QWinThumbnailToolButton::clicked, [this]() {
265
        Utils::setStackWidget(ui->navStack, ui->settingswidget);
266 267 268
    });

    thumbbar->addButton(settings);
269
#endif
270
}
271 272 273 274 275 276 277 278 279

void
MainWindow::switchNormalMaximize()
{
    if(isMaximized())
        showNormal();
    else
        showMaximized();
}
Edric Milaret's avatar
Edric Milaret committed
280 281 282 283

void
MainWindow::closeEvent(QCloseEvent* event)
{
Andreas Traczyk's avatar
Andreas Traczyk committed
284
    Video::PreviewManager::instance().stopPreview();
Edric Milaret's avatar
Edric Milaret committed
285 286 287 288
    QSettings settings;
    if (settings.value(SettingsKey::closeOrMinimized).toBool()) {
        this->hide();
        event->ignore();
289
    } else {
290
        settings.setValue(SettingsKey::geometry, saveGeometry());
291
        settings.setValue(SettingsKey::windowState, saveState());
Edric Milaret's avatar
Edric Milaret committed
292
    }
293
    this->disconnect(screenChangedConnection_);
294
    LRCInstance::reset();
295
    QMainWindow::closeEvent(event);
Edric Milaret's avatar
Edric Milaret committed
296
}
297

298 299 300 301 302 303
void
MainWindow::readSettingsFromRegistry()
{
    QSettings settings;
    restoreGeometry(settings.value(SettingsKey::geometry).toByteArray());
    restoreState(settings.value(SettingsKey::windowState).toByteArray());
304 305 306 307

    LRCInstance::editableDataTransferModel()->downloadDirectory = settings.value(SettingsKey::downloadPath,
        QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)).toString().toStdString() + "/";

308 309
    if (not settings.contains(SettingsKey::enableNotifications)) {
        settings.setValue(SettingsKey::enableNotifications, true);
310
    }
311
}
312 313 314 315 316 317 318 319 320

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);
321 322 323
    } else {
        setMinimumSize(mainWindowMinWidth, mainWindowMinHeight);
        setMaximumSize(QtMaxDimension, QtMaxDimension);
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
    }
    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](QScreen* screen) {
Andreas Traczyk's avatar
Andreas Traczyk committed
354
            Q_UNUSED(screen);
355 356 357
            adjustSize();
            updateGeometry();
            update();
Andreas Traczyk's avatar
Andreas Traczyk committed
358 359 360 361 362
            // a little delay won't hurt ;)
            QTimer::singleShot(100, this,
                [this] {
                    qobject_cast<NavWidget*>(ui->navStack->currentWidget())->updateCustomUI();
                });
363 364
        });
}
Andreas Traczyk's avatar
Andreas Traczyk committed
365 366 367 368 369 370 371

void
MainWindow::resizeEvent(QResizeEvent* event)
{
    Q_UNUSED(event);
    qobject_cast<NavWidget*>(ui->navStack->currentWidget())->updateCustomUI();
}