1 #include "NotificationPage.hpp"
2 
3 #include "Application.hpp"
4 #include "controllers/notifications/NotificationController.hpp"
5 #include "controllers/notifications/NotificationModel.hpp"
6 #include "singletons/Settings.hpp"
7 #include "singletons/Toasts.hpp"
8 #include "util/LayoutCreator.hpp"
9 #include "widgets/helper/EditableModelView.hpp"
10 
11 #include <QCheckBox>
12 #include <QFileDialog>
13 #include <QGroupBox>
14 #include <QHeaderView>
15 #include <QLabel>
16 #include <QListView>
17 #include <QPushButton>
18 #include <QTableView>
19 #include <QTimer>
20 
21 namespace chatterino {
22 
NotificationPage()23 NotificationPage::NotificationPage()
24 {
25     LayoutCreator<NotificationPage> layoutCreator(this);
26     auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
27     {
28         auto tabs = layout.emplace<QTabWidget>();
29         {
30             auto settings = tabs.appendTab(new QVBoxLayout, "Options");
31             {
32                 settings.emplace<QLabel>(
33                     "You can be informed when certain channels go live. You "
34                     "can be informed in multiple ways:");
35 
36                 settings.append(this->createCheckBox(
37                     "Flash taskbar", getSettings()->notificationFlashTaskbar));
38                 settings.append(
39                     this->createCheckBox("Play sound for selected channels",
40                                          getSettings()->notificationPlaySound));
41                 settings.append(this->createCheckBox(
42                     "Play sound for any channel going live",
43                     getSettings()->notificationOnAnyChannel));
44 #ifdef Q_OS_WIN
45                 settings.append(this->createCheckBox(
46                     "Show notification", getSettings()->notificationToast));
47                 auto openIn = settings.emplace<QHBoxLayout>().withoutMargin();
48                 {
49                     openIn
50                         .emplace<QLabel>(
51                             "Action when clicking on a notification:  ")
52                         ->setSizePolicy(QSizePolicy::Maximum,
53                                         QSizePolicy::Preferred);
54 
55                     // implementation of custom combobox done
56                     // because addComboBox only can handle strings-settings
57                     // int setting for the ToastReaction is desired
58                     openIn
59                         .append(this->createToastReactionComboBox(
60                             this->managedConnections_))
61                         ->setSizePolicy(QSizePolicy::Maximum,
62                                         QSizePolicy::Preferred);
63                 }
64                 openIn->setContentsMargins(40, 0, 0, 0);
65                 openIn->setSizeConstraint(QLayout::SetMaximumSize);
66 #endif
67                 auto customSound =
68                     layout.emplace<QHBoxLayout>().withoutMargin();
69                 {
70                     customSound.append(this->createCheckBox(
71                         "Custom sound",
72                         getSettings()->notificationCustomSound));
73                     auto selectFile = customSound.emplace<QPushButton>(
74                         "Select custom sound file");
75                     QObject::connect(
76                         selectFile.getElement(), &QPushButton::clicked, this,
77                         [this] {
78                             auto fileName = QFileDialog::getOpenFileName(
79                                 this, tr("Open Sound"), "",
80                                 tr("Audio Files (*.mp3 *.wav)"));
81                             getSettings()->notificationPathSound = fileName;
82                         });
83                 }
84 
85                 settings->addStretch(1);
86             }
87             auto twitchChannels =
88                 tabs.appendTab(new QVBoxLayout, "Selected Channels");
89             {
90                 twitchChannels.emplace<QLabel>(
91                     "These are the channels for which you will be informed "
92                     "when they go live:");
93 
94                 EditableModelView *view =
95                     twitchChannels
96                         .emplace<EditableModelView>(
97                             getApp()->notifications->createModel(
98                                 nullptr, Platform::Twitch))
99                         .getElement();
100                 view->setTitles({"Twitch channels"});
101 
102                 view->getTableView()->horizontalHeader()->setSectionResizeMode(
103                     QHeaderView::Fixed);
104                 view->getTableView()->horizontalHeader()->setSectionResizeMode(
105                     0, QHeaderView::Stretch);
106 
107                 QTimer::singleShot(1, [view] {
108                     view->getTableView()->resizeColumnsToContents();
109                     view->getTableView()->setColumnWidth(0, 200);
110                 });
111 
112                 view->addButtonPressed.connect([] {
113                     getApp()
114                         ->notifications->channelMap[Platform::Twitch]
115                         .append("channel");
116                 });
117             }
118         }
119     }
120 }
createToastReactionComboBox(std::vector<pajlada::Signals::ScopedConnection> managedConnections)121 QComboBox *NotificationPage::createToastReactionComboBox(
122     std::vector<pajlada::Signals::ScopedConnection> managedConnections)
123 {
124     QComboBox *toastReactionOptions = new QComboBox();
125 
126     for (int i = 0; i <= static_cast<int>(ToastReaction::DontOpen); i++)
127     {
128         toastReactionOptions->insertItem(
129             i, Toasts::findStringFromReaction(static_cast<ToastReaction>(i)));
130     }
131 
132     // update when setting changes
133     pajlada::Settings::Setting<int> setting = getSettings()->openFromToast;
134     setting.connect(
135         [toastReactionOptions](const int &index, auto) {
136             toastReactionOptions->setCurrentIndex(index);
137         },
138         managedConnections);
139 
140     QObject::connect(toastReactionOptions,
141                      QOverload<int>::of(&QComboBox::currentIndexChanged),
142                      [](const int &newValue) {
143                          getSettings()->openFromToast.setValue(newValue);
144                      });
145 
146     return toastReactionOptions;
147 }
148 }  // namespace chatterino
149