App.cpp 6.14 KB
Newer Older
1 2 3 4
#include <QMenu>
#include <QQmlComponent>
#include <QQmlContext>
#include <QQuickView>
5
#include <QtDebug>
6

7
#include "../components/camera/Camera.hpp"
8
#include "../components/chat/ChatProxyModel.hpp"
9
#include "../components/contacts/ContactsListProxyModel.hpp"
Ronan Abhamon's avatar
Ronan Abhamon committed
10
#include "../components/core/CoreManager.hpp"
11
#include "../components/notifier/Notifier.hpp"
12 13
#include "../components/settings/AccountSettingsModel.hpp"
#include "../components/timeline/TimelineModel.hpp"
Ronan Abhamon's avatar
Ronan Abhamon committed
14
#include "../components/smart-search-bar/SmartSearchBarModel.hpp"
15

16
#include "App.hpp"
17 18

#define LANGUAGES_PATH ":/languages/"
19
#define WINDOW_ICON_PATH ":/assets/images/linphone.png"
20

21 22 23 24
// The two main windows of Linphone desktop.
#define QML_VIEW_MAIN_WINDOW "qrc:/ui/views/App/MainWindow/MainWindow.qml"
#define QML_VIEW_CALL_WINDOW "qrc:/ui/views/App/Calls/Calls.qml"

25
// =============================================================================
26

Ronan Abhamon's avatar
Ronan Abhamon committed
27 28
App *App::m_instance = nullptr;

29
App::App (int &argc, char **argv) : QApplication(argc, argv) {
30
  if (m_english_translator.load(QLocale(QLocale::English), LANGUAGES_PATH))
31 32 33 34 35
    installTranslator(&m_english_translator);
  else
    qWarning("Unable to install english translator.");

  // Try to use default locale.
36 37 38
  QLocale current_locale = QLocale::system();

  if (m_default_translator.load(current_locale, LANGUAGES_PATH)) {
39
    installTranslator(&m_default_translator);
40 41
    m_locale = current_locale.name();
  } else {
42
    qWarning() << QStringLiteral("Unable to found translations for locale: %1.")
43 44
      .arg(current_locale.name());
  }
45

46 47 48
  // Provide avatars loader.
  m_engine.addImageProvider(AvatarProvider::PROVIDER_ID, &m_avatar_provider);

49 50 51 52 53 54 55 56 57 58
  setWindowIcon(QIcon(WINDOW_ICON_PATH));

  // Provide `+custom` folders for custom components.
  m_file_selector = new QQmlFileSelector(&m_engine);
  m_file_selector->setExtraSelectors(QStringList("custom"));

  // Set modules paths.
  m_engine.addImportPath(":/ui/modules");
  m_engine.addImportPath(":/ui/scripts");
  m_engine.addImportPath(":/ui/views");
Ronan Abhamon's avatar
Ronan Abhamon committed
59
}
60

Ronan Abhamon's avatar
Ronan Abhamon committed
61
// -----------------------------------------------------------------------------
Ronan Abhamon's avatar
Ronan Abhamon committed
62 63

void App::initContentApp () {
64 65
  qInfo() << "Initializing core manager...";

Ronan Abhamon's avatar
Ronan Abhamon committed
66
  // Init core.
Ronan Abhamon's avatar
Ronan Abhamon committed
67 68
  CoreManager::init();

69 70 71 72 73
  // Register types and load context properties.
  registerTypes();
  addContextProperties();

  // Load main view.
74
  qInfo() << "Loading main view...";
75
  m_engine.load(QUrl(QML_VIEW_MAIN_WINDOW));
76 77 78 79 80 81 82 83
  if (m_engine.rootObjects().isEmpty())
    qFatal("Unable to open main window.");

  // Enable TrayIconSystem.
  if (!QSystemTrayIcon::isSystemTrayAvailable())
    qWarning("System tray not found on this system.");
  else
    setTrayIcon();
Ronan Abhamon's avatar
Ronan Abhamon committed
84
}
85 86

void App::registerTypes () {
87 88
  qInfo() << "Registering types...";

Ronan Abhamon's avatar
Ronan Abhamon committed
89 90 91 92 93 94
  qmlRegisterUncreatableType<ContactModel>(
    "Linphone", 1, 0, "ContactModel", "ContactModel is uncreatable"
  );
  qmlRegisterUncreatableType<VcardModel>(
    "Linphone", 1, 0, "VcardModel", "VcardModel is uncreatable"
  );
95 96 97
  qmlRegisterUncreatableType<Presence>(
    "Linphone", 1, 0, "Presence", "Presence is uncreatable"
  );
Ronan Abhamon's avatar
Ronan Abhamon committed
98

99 100 101 102 103 104 105 106 107 108 109 110 111 112
  qmlRegisterSingletonType<App>(
    "Linphone", 1, 0, "App",
    [](QQmlEngine *, QJSEngine *) -> QObject *{
      return App::getInstance();
    }
  );

  qmlRegisterSingletonType<CoreManager>(
    "Linphone", 1, 0, "CoreManager",
    [](QQmlEngine *, QJSEngine *) -> QObject *{
      return CoreManager::getInstance();
    }
  );

113 114
  qmlRegisterSingletonType<ContactsListModel>(
    "Linphone", 1, 0, "ContactsListModel",
115
    [](QQmlEngine *, QJSEngine *) -> QObject *{
Ronan Abhamon's avatar
Ronan Abhamon committed
116
      return CoreManager::getInstance()->getContactsListModel();
117 118
    }
  );
119

Ronan Abhamon's avatar
Ronan Abhamon committed
120 121 122
  qmlRegisterSingletonType<SipAddressesModel>(
    "Linphone", 1, 0, "SipAddressesModel",
    [](QQmlEngine *, QJSEngine *) -> QObject *{
Ronan Abhamon's avatar
Ronan Abhamon committed
123
      return CoreManager::getInstance()->getSipAddressesModel();
Ronan Abhamon's avatar
Ronan Abhamon committed
124 125 126
    }
  );

127 128 129 130 131 132 133 134 135 136
  qmlRegisterSingletonType<AccountSettingsModel>(
    "Linphone", 1, 0, "AccountSettingsModel",
    [](QQmlEngine *, QJSEngine *) -> QObject *{
      return new AccountSettingsModel();
    }
  );

  qmlRegisterSingletonType<TimelineModel>(
    "Linphone", 1, 0, "TimelineModel",
    [](QQmlEngine *, QJSEngine *) -> QObject *{
Ronan Abhamon's avatar
Ronan Abhamon committed
137
      return new TimelineModel();
138 139
    }
  );
Ronan Abhamon's avatar
Ronan Abhamon committed
140 141 142 143 144

  qmlRegisterType<Camera>("Linphone", 1, 0, "Camera");
  qmlRegisterType<ContactsListProxyModel>("Linphone", 1, 0, "ContactsListProxyModel");
  qmlRegisterType<ChatModel>("Linphone", 1, 0, "ChatModel");
  qmlRegisterType<ChatProxyModel>("Linphone", 1, 0, "ChatProxyModel");
Ronan Abhamon's avatar
Ronan Abhamon committed
145
  qmlRegisterType<SmartSearchBarModel>("Linphone", 1, 0, "SmartSearchBarModel");
Ronan Abhamon's avatar
Ronan Abhamon committed
146 147

  qRegisterMetaType<ChatModel::EntryType>("ChatModel::EntryType");
148 149 150
}

void App::addContextProperties () {
151
  qInfo() << "Adding context properties...";
152 153
  QQmlContext *context = m_engine.rootContext();

Ronan Abhamon's avatar
Ronan Abhamon committed
154
  // TODO: Avoid context properties. Use qmlRegister...
155 156
  QQmlComponent component(&m_engine, QUrl(QML_VIEW_CALL_WINDOW));
  if (component.isError()) {
157
    qWarning() << component.errors();
158 159 160 161
    abort();
  }

  context->setContextProperty("CallsWindow", component.create());
162

163 164
  m_notifier = new Notifier();
  context->setContextProperty("Notifier", m_notifier);
165 166 167 168 169
}

void App::setTrayIcon () {
  QQuickWindow *root = qobject_cast<QQuickWindow *>(m_engine.rootObjects().at(0));
  QMenu *menu = new QMenu();
Ronan Abhamon's avatar
Ronan Abhamon committed
170 171

  m_system_tray_icon = new QSystemTrayIcon(root);
172 173 174 175 176 177 178 179 180

  // trayIcon: Right click actions.
  QAction *quit_action = new QAction("Quit", root);
  root->connect(quit_action, &QAction::triggered, qApp, &QCoreApplication::quit);

  QAction *restore_action = new QAction("Restore", root);
  root->connect(restore_action, &QAction::triggered, root, &QQuickWindow::showNormal);

  // trayIcon: Left click actions.
181 182
  root->connect(
    m_system_tray_icon, &QSystemTrayIcon::activated, [root](
Ronan Abhamon's avatar
Ronan Abhamon committed
183 184
      QSystemTrayIcon::ActivationReason reason
    ) {
185 186 187 188 189 190
      if (reason == QSystemTrayIcon::Trigger) {
        if (root->visibility() == QWindow::Hidden)
          root->showNormal();
        else
          root->hide();
      }
191
    }
192
  );
193 194 195 196 197 198

  // Build trayIcon menu.
  menu->addAction(restore_action);
  menu->addSeparator();
  menu->addAction(quit_action);

Ronan Abhamon's avatar
Ronan Abhamon committed
199 200 201 202 203
  m_system_tray_icon->setContextMenu(menu);
  m_system_tray_icon->setIcon(QIcon(WINDOW_ICON_PATH));
  m_system_tray_icon->setToolTip("Linphone");
  m_system_tray_icon->show();
}