OSDN Git Service

通知方法の詳細設定がズームしないのを直す
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / MainForm.cs
index a87ce1d..6404149 100644 (file)
@@ -36,6 +36,7 @@ namespace KancolleSniffer
         private readonly Config _config = new Config();\r
         private readonly ConfigDialog _configDialog;\r
         private readonly ProxyManager _proxyManager;\r
+        private readonly ToolTip _toolTip = new ToolTip {ShowAlways = true};\r
         private int _currentFleet;\r
         private bool _combinedFleet;\r
         private readonly Label[] _labelCheckFleets;\r
@@ -43,12 +44,12 @@ namespace KancolleSniffer
         private readonly ListForm _listForm;\r
         private readonly NotificationManager _notificationManager;\r
         private bool _started;\r
+        private bool _timerEnabled;\r
         private string _debugLogFile;\r
         private IEnumerator<string> _playLog;\r
+        private DateTime _prev, _now;\r
 \r
         private readonly ErrorDialog _errorDialog = new ErrorDialog();\r
-        private bool _missionFinishTimeMode;\r
-        private bool _ndockFinishTimeMode;\r
         private readonly KancolleDb _kancolleDb = new KancolleDb();\r
         private readonly ErrorLog _errorLog;\r
 \r
@@ -75,7 +76,7 @@ namespace KancolleSniffer
             panelRepairList.CreateLabels(panelRepairList_Click);\r
             labelPresetAkashiTimer.BackColor = ShipLabels.ColumnColors[1];\r
             _listForm = new ListForm(_sniffer, _config) {Owner = this};\r
-            _notificationManager = new NotificationManager(Ring);\r
+            _notificationManager = new NotificationManager(Alarm);\r
             try\r
             {\r
                 _config.Load();\r
@@ -86,22 +87,32 @@ namespace KancolleSniffer
             }\r
             _proxyManager = new ProxyManager(_config, this);\r
             _errorLog = new ErrorLog(_sniffer);\r
+            _proxyManager.UpdatePacFile();\r
             PerformZoom();\r
             _shipLabels.AdjustAkashiTimers();\r
             _sniffer.LoadState();\r
-            _sniffer.RepeatingTimerController = new RepeatingTimerController(_notificationManager);\r
+            _sniffer.RepeatingTimerController = new RepeatingTimerController(_notificationManager, _config);\r
         }\r
 \r
         private class RepeatingTimerController : Sniffer.IRepeatingTimerController\r
         {\r
             private readonly NotificationManager _manager;\r
+            private readonly Config _config;\r
 \r
-            public RepeatingTimerController(NotificationManager manager)\r
+            public RepeatingTimerController(NotificationManager manager, Config config)\r
             {\r
                 _manager = manager;\r
+                _config = config;\r
             }\r
 \r
-            public void Stop(string key) => _manager.StopRepeat(key);\r
+            public void Stop(string key)\r
+            {\r
+                _manager.StopRepeat(key,\r
+                    (key == "入渠終了" || key == "遠征終了") &&\r
+                    (_config.Notifications[key].Flags & NotificationType.Cont) != 0);\r
+            }\r
+\r
+            public void Stop(string key, int fleet) => _manager.StopRepeat(key, fleet);\r
 \r
             public void Suspend() => _manager.SuspendRepeat();\r
 \r
@@ -208,6 +219,8 @@ namespace KancolleSniffer
             }\r
             if (!_started)\r
                 return;\r
+            if (_now == DateTime.MinValue)\r
+                _now = DateTime.Now;\r
             if ((update & Sniffer.Update.Item) != 0)\r
                 UpdateItemInfo();\r
             if ((update & Sniffer.Update.Timer) != 0)\r
@@ -325,7 +338,6 @@ namespace KancolleSniffer
                 ApplyConfig();\r
                 StopRepeatingTimer(_configDialog.RepeatSettingsChanged);\r
             }\r
-\r
         }\r
 \r
         private void StopRepeatingTimer(IEnumerable<string> names)\r
@@ -342,7 +354,8 @@ namespace KancolleSniffer
             foreach (var control in new Control[]\r
             {\r
                 this, _listForm, labelLogin, linkLabelGuide,\r
-                _configDialog, contextMenuStripMain, _errorDialog\r
+                _configDialog, _configDialog.NotificationConfigDialog,\r
+                contextMenuStripMain, _errorDialog\r
             })\r
             {\r
                 control.Font = new Font(control.Font.FontFamily, control.Font.Size * _config.Zoom / 100);\r
@@ -398,17 +411,20 @@ namespace KancolleSniffer
         {\r
             var rect = new Rectangle(\r
                 new Point(location.X + SystemInformation.IconSize.Width + SystemInformation.HorizontalFocusThickness,\r
-                    location.Y + SystemInformation.CaptionHeight) , new Size(60, 1));\r
+                    location.Y + SystemInformation.CaptionHeight), new Size(60, 1));\r
             return Screen.AllScreens.Any(screen => screen.WorkingArea.Contains(rect));\r
         }\r
 \r
         private void timerMain_Tick(object sender, EventArgs e)\r
         {\r
-            if (_started)\r
+            if (_timerEnabled)\r
             {\r
                 try\r
                 {\r
+                    _now = DateTime.Now;\r
                     UpdateTimers();\r
+                    NotifyTimers();\r
+                    _prev = _now;\r
                 }\r
                 catch (Exception ex)\r
                 {\r
@@ -463,6 +479,7 @@ namespace KancolleSniffer
         {\r
             UpdateNumOfShips();\r
             UpdateNumOfEquips();\r
+            _notificationManager.Flash();\r
             labelNumOfBuckets.Text = _sniffer.Material.MaterialHistory[(int)Material.Bucket].Now.ToString("D");\r
             UpdateBucketHistory();\r
             var ac = _sniffer.Achievement.Value;\r
@@ -482,11 +499,11 @@ namespace KancolleSniffer
             var item = _sniffer.Item;\r
             labelNumOfShips.Text = $"{item.NowShips:D}/{item.MaxShips:D}";\r
             labelNumOfShips.ForeColor = item.TooManyShips ? CUDColor.Red : Color.Black;\r
-            if (item.RingShips)\r
+            if (item.AlarmShips)\r
             {\r
                 var message = $"残り{_sniffer.Item.MaxShips - _sniffer.Item.NowShips:D}隻";\r
                 _notificationManager.Enqueue("艦娘数超過", message);\r
-                item.RingShips = false;\r
+                item.AlarmShips = false;\r
             }\r
         }\r
 \r
@@ -495,11 +512,11 @@ namespace KancolleSniffer
             var item = _sniffer.Item;\r
             labelNumOfEquips.Text = $"{item.NowEquips:D}/{item.MaxEquips:D}";\r
             labelNumOfEquips.ForeColor = item.TooManyEquips ? CUDColor.Red : Color.Black;\r
-            if (item.RingEquips)\r
+            if (item.AlarmEquips)\r
             {\r
                 var message = $"残り{_sniffer.Item.MaxEquips - _sniffer.Item.NowEquips:D}個";\r
                 _notificationManager.Enqueue("装備数超過", message);\r
-                item.RingEquips = false;\r
+                item.AlarmEquips = false;\r
             }\r
         }\r
 \r
@@ -563,37 +580,10 @@ namespace KancolleSniffer
 \r
         private void NotifyDamagedShip()\r
         {\r
-            if (_sniffer.BadlyDamagedShips.Any())\r
-                _notificationManager.Enqueue("大破警告", string.Join(" ", _sniffer.BadlyDamagedShips));\r
-        }\r
-\r
-        private void NotifyAkashiTimer()\r
-        {\r
-            var akashi = _sniffer.AkashiTimer;\r
-            var msgs = akashi.GetNotice();\r
-            if (msgs.Length == 0)\r
-            {\r
-                _notificationManager.StopRepeat("泊地修理");\r
-                return;\r
-            }\r
-            if (!akashi.CheckReparing() && !(akashi.CheckPresetReparing() && _config.UsePresetAkashi))\r
-            {\r
-                _notificationManager.StopRepeat("泊地修理");\r
+            if (!_sniffer.BadlyDamagedShips.Any())\r
                 return;\r
-            }\r
-            if (msgs[0].Proceeded == "20分経過しました。")\r
-            {\r
-                SetNotification("泊地修理20分経過", msgs[0].Proceeded);\r
-                msgs[0].Proceeded = "";\r
-                // 修理完了がいるかもしれないので続ける\r
-            }\r
-            for (var i = 0; i < ShipInfo.FleetCount; i++)\r
-            {\r
-                if (msgs[i].Proceeded != "")\r
-                    SetNotification("泊地修理進行", i, msgs[i].Proceeded);\r
-                if (msgs[i].Completed != "")\r
-                    SetNotification("泊地修理完了", i, msgs[i].Completed);\r
-            }\r
+            _notificationManager.Enqueue("大破警告", string.Join(" ", _sniffer.BadlyDamagedShips));\r
+            _notificationManager.Flash();\r
         }\r
 \r
         public void UpdateFighterPower(bool combined)\r
@@ -628,13 +618,14 @@ namespace KancolleSniffer
         private void UpdateBattleInfo()\r
         {\r
             ResetBattleInfo();\r
+            _listForm.UpdateBattleResult();\r
             if (_sniffer.Battle.BattleState == BattleState.None)\r
                 return;\r
             panelBattleInfo.BringToFront();\r
             var battle = _sniffer.Battle;\r
-            labelFormation.Text = battle.Formation;\r
+            labelFormation.Text = new[] {"同航戦", "反航戦", "T字有利", "T字不利"}[battle.Formation[2] - 1];\r
             UpdateBattleFighterPower();\r
-            if (_config.AlwaysShowResultRank)\r
+            if ((_config.Spoilers & Spoiler.ResultRank) != 0)\r
                 ShowResultRank();\r
             if (_sniffer.Battle.BattleState == BattleState.Day)\r
                 _listForm.UpdateAirBattleResult();\r
@@ -698,7 +689,7 @@ namespace KancolleSniffer
 \r
         private void labelNDock_Click(object sender, EventArgs e)\r
         {\r
-            _ndockFinishTimeMode = !_ndockFinishTimeMode;\r
+            _config.ShowEndTime ^= TimerKind.NDock;\r
             UpdateTimers();\r
         }\r
 \r
@@ -712,54 +703,75 @@ namespace KancolleSniffer
 \r
         private void labelMission_Click(object sender, EventArgs e)\r
         {\r
-            _missionFinishTimeMode = !_missionFinishTimeMode;\r
+            _config.ShowEndTime ^= TimerKind.Mission;\r
             UpdateTimers();\r
         }\r
 \r
         private void UpdateTimers()\r
         {\r
-            foreach (var entry in\r
-                new[] {labelMission1, labelMission2, labelMission3}.Zip(_sniffer.Missions,\r
-                    (label, mission) => new {label, mission.Name, mission.Timer}))\r
-            {\r
-                entry.Timer.Update();\r
-                SetTimerColor(entry.label, entry.Timer);\r
-                entry.label.Text = entry.Timer.ToString(_missionFinishTimeMode);\r
-                if (!entry.Timer.NeedRing)\r
-                    continue;\r
-                SetNotification("遠征終了", entry.Name);\r
-                entry.Timer.NeedRing = false;\r
+            var mission = new[] {labelMission1, labelMission2, labelMission3};\r
+            for (var i = 0; i < mission.Length; i++)\r
+            {\r
+                var entry = _sniffer.Missions[i];\r
+                SetTimerColor(mission[i], entry.Timer, _now);\r
+                mission[i].Text = entry.Timer.ToString(_now, (_config.ShowEndTime & TimerKind.Mission) != 0);\r
             }\r
             for (var i = 0; i < _sniffer.NDock.Length; i++)\r
             {\r
                 var entry = _sniffer.NDock[i];\r
-                entry.Timer.Update();\r
-                _shipLabels.SetNDockTimer(i, entry.Timer, _ndockFinishTimeMode);\r
-                if (!entry.Timer.NeedRing)\r
-                    continue;\r
-                SetNotification("入渠終了", entry.Name);\r
-                entry.Timer.NeedRing = false;\r
+                _shipLabels.SetNDockTimer(i, entry.Timer, _now, (_config.ShowEndTime & TimerKind.NDock) != 0);\r
             }\r
             var kdock = new[] {labelConstruct1, labelConstruct2, labelConstruct3, labelConstruct4};\r
             for (var i = 0; i < kdock.Length; i++)\r
             {\r
                 var timer = _sniffer.KDock[i];\r
-                timer.Update();\r
-                SetTimerColor(kdock[i], timer);\r
-\r
-                kdock[i].Text = timer.ToString();\r
-                if (!timer.NeedRing)\r
-                    continue;\r
-                SetNotification("建造完了", $"第{i + 1:D}ドック");\r
-                timer.NeedRing = false;\r
+                SetTimerColor(kdock[i], timer, _now);\r
+                kdock[i].Text = timer.ToString(_now);\r
             }\r
             UpdateCondTimers();\r
             UpdateAkashiTimer();\r
+            _timerEnabled = true;\r
         }\r
 \r
-        private void SetTimerColor(Label label, RingTimer timer)\r
+        private void NotifyTimers()\r
         {\r
-            label.ForeColor = timer.IsFinished ? CUDColor.Red : Color.Black;\r
+            for (var i = 0; i < _sniffer.Missions.Length; i++)\r
+            {\r
+                var entry = _sniffer.Missions[i];\r
+                CheckAlarm("遠征終了", entry.Timer, i + 1, entry.Name);\r
+            }\r
+            for (var i = 0; i < _sniffer.NDock.Length; i++)\r
+            {\r
+                var entry = _sniffer.NDock[i];\r
+                CheckAlarm("入渠終了", entry.Timer, i, entry.Name);\r
+            }\r
+            for (var i = 0; i < _sniffer.KDock.Length; i++)\r
+            {\r
+                var timer = _sniffer.KDock[i];\r
+                CheckAlarm("建造完了", timer, 0, $"第{i + 1:D}ドック");\r
+            }\r
+            NotifyCondTimers();\r
+            NotifyAkashiTimer();\r
+            _notificationManager.Flash();\r
+        }\r
+\r
+        private void CheckAlarm(string key, AlarmTimer timer, int fleet, string subject)\r
+        {\r
+            if (timer.CheckAlarm(_prev, _now))\r
+            {\r
+                SetNotification(key, fleet, subject);\r
+                return;\r
+            }\r
+            var pre = TimeSpan.FromSeconds(_config.Notifications[key].PreliminaryPeriod);\r
+            if (pre == TimeSpan.Zero)\r
+                return;\r
+            if (timer.CheckAlarm(_prev + pre, _now + pre))\r
+                SetPreNotification(key, fleet, subject);\r
+        }\r
+\r
+        private void SetTimerColor(Label label, AlarmTimer timer, DateTime now)\r
+        {\r
+            label.ForeColor = timer.IsFinished(now) ? CUDColor.Red : Color.Black;\r
         }\r
 \r
         private void UpdateCondTimers()\r
@@ -775,14 +787,13 @@ namespace KancolleSniffer
             {\r
                 timer = _sniffer.GetConditionTimer(_currentFleet);\r
             }\r
-            var now = DateTime.Now;\r
             if (timer == DateTime.MinValue)\r
             {\r
                 labelCondTimerTitle.Text = "";\r
                 labelCondTimer.Text = "";\r
                 return;\r
             }\r
-            var span = TimeSpan.FromSeconds(Ceiling((timer - now).TotalSeconds));\r
+            var span = TimeSpan.FromSeconds(Ceiling((timer - _now).TotalSeconds));\r
             if (span >= TimeSpan.FromMinutes(9))\r
             {\r
                 labelCondTimerTitle.Text = "cond40まで";\r
@@ -795,27 +806,26 @@ namespace KancolleSniffer
                 labelCondTimer.Text = (span >= TimeSpan.Zero ? span : TimeSpan.Zero).ToString(@"mm\:ss");\r
                 labelCondTimer.ForeColor = span <= TimeSpan.Zero ? CUDColor.Red : DefaultForeColor;\r
             }\r
-            var notice = _sniffer.GetConditionNotice();\r
-            if (notice == null)\r
-                return;\r
-            for (var i = 0; i < ShipInfo.FleetCount; i++)\r
-            {\r
-                if (!_config.NotifyConditions.Contains(notice[i]))\r
-                    return;\r
-                SetNotification("疲労回復" + notice[i], i, "cond" + notice[i]);\r
-            }\r
-        }\r
-\r
-        private void SetNotification(string key, string subject)\r
-        {\r
-            SetNotification(key, 0, subject);\r
         }\r
 \r
-        private void SetNotification(string key, int fleet, string subject)\r
+        private void NotifyCondTimers()\r
         {\r
-            var spec = _config.Notifications[_notificationManager.KeyToName(key)];\r
-            _notificationManager.Enqueue(key, fleet, subject,\r
-                (spec.Flags & NotificationType.Repeat) == 0 ? 0 : spec.RepeatInterval);\r
+            var notice = _sniffer.GetConditionNotice(_prev, _now);\r
+            var pre = TimeSpan.FromSeconds(_config.Notifications["疲労回復"].PreliminaryPeriod);\r
+            var preNotice = pre == TimeSpan.Zero\r
+                ? new int[ShipInfo.FleetCount]\r
+                : _sniffer.GetConditionNotice(_prev + pre, _now + pre);\r
+            for (var i = 0; i < ShipInfo.FleetCount; i++)\r
+            {\r
+                if (_config.NotifyConditions.Contains(notice[i]))\r
+                {\r
+                    SetNotification("疲労回復" + notice[i], i, "cond" + notice[i]);\r
+                }\r
+                else if (_config.NotifyConditions.Contains(preNotice[i]))\r
+                {\r
+                    SetPreNotification("疲労回復" + preNotice[i], i, "cond" + notice[i]);\r
+                }\r
+            }\r
         }\r
 \r
         private void UpdateAkashiTimer()\r
@@ -825,18 +835,17 @@ namespace KancolleSniffer
             var statuses = _sniffer.GetShipStatuses(_currentFleet);\r
             _shipLabels.SetAkashiTimer(statuses,\r
                 _sniffer.AkashiTimer.GetTimers(_currentFleet));\r
-            NotifyAkashiTimer();\r
         }\r
 \r
         private void UpdatePresetAkashiTimer()\r
         {\r
             var akashi = _sniffer.AkashiTimer;\r
             var span = akashi.PresetDeckTimer;\r
-            var color = span == TimeSpan.Zero && akashi.CheckPresetReparing() ? CUDColor.Red : DefaultForeColor;\r
+            var color = span == TimeSpan.Zero && akashi.CheckPresetRepairing() ? CUDColor.Red : DefaultForeColor;\r
             var text = span == TimeSpan.MinValue ? "" : span.ToString(@"mm\:ss");\r
             labelAkashiRepairTimer.ForeColor = color;\r
             labelAkashiRepairTimer.Text = text;\r
-            if (akashi.CheckPresetReparing() && !akashi.CheckReparing(_currentFleet))\r
+            if (akashi.CheckPresetRepairing() && !akashi.CheckRepairing(_currentFleet))\r
             {\r
                 labelPresetAkashiTimer.ForeColor = color;\r
                 labelPresetAkashiTimer.Text = text;\r
@@ -848,6 +857,61 @@ namespace KancolleSniffer
             }\r
         }\r
 \r
+        private void NotifyAkashiTimer()\r
+        {\r
+            var akashi = _sniffer.AkashiTimer;\r
+            var msgs = akashi.GetNotice(_prev, _now);\r
+            if (msgs.Length == 0)\r
+            {\r
+                _notificationManager.StopRepeat("泊地修理");\r
+                return;\r
+            }\r
+            if (!akashi.CheckRepairing() && !(akashi.CheckPresetRepairing() && _config.UsePresetAkashi))\r
+            {\r
+                _notificationManager.StopRepeat("泊地修理");\r
+                return;\r
+            }\r
+            var skipPreliminary = false;\r
+            if (msgs[0].Proceeded == "20分経過しました。")\r
+            {\r
+                SetNotification("泊地修理20分経過", msgs[0].Proceeded);\r
+                msgs[0].Proceeded = "";\r
+                skipPreliminary = true;\r
+                // 修理完了がいるかもしれないので続ける\r
+            }\r
+            for (var i = 0; i < ShipInfo.FleetCount; i++)\r
+            {\r
+                if (msgs[i].Proceeded != "")\r
+                    SetNotification("泊地修理進行", i, msgs[i].Proceeded);\r
+                if (msgs[i].Completed != "")\r
+                    SetNotification("泊地修理完了", i, msgs[i].Completed);\r
+            }\r
+            var pre = TimeSpan.FromSeconds(_config.Notifications["泊地修理20分経過"].PreliminaryPeriod);\r
+            if (skipPreliminary || pre == TimeSpan.Zero)\r
+                return;\r
+            if ((msgs = akashi.GetNotice(_prev + pre, _now + pre))[0].Proceeded == "20分経過しました。")\r
+                SetPreNotification("泊地修理20分経過", 0, msgs[0].Proceeded);\r
+        }\r
+\r
+        private void SetNotification(string key, string subject)\r
+        {\r
+            SetNotification(key, 0, subject);\r
+        }\r
+\r
+        private void SetNotification(string key, int fleet, string subject)\r
+        {\r
+            var spec = _config.Notifications[_notificationManager.KeyToName(key)];\r
+            _notificationManager.Enqueue(key, fleet, subject,\r
+                (spec.Flags & _config.NotificationFlags & NotificationType.Repeat) == 0 ? 0 : spec.RepeatInterval);\r
+        }\r
+\r
+        private void SetPreNotification(string key, int fleet, string subject)\r
+        {\r
+            var spec = _config.Notifications[_notificationManager.KeyToName(key)];\r
+            if ((spec.Flags & NotificationType.Preliminary) != 0)\r
+                _notificationManager.Enqueue(key, fleet, subject, 0, true);\r
+        }\r
+\r
         private void UpdateRepairList()\r
         {\r
             panelRepairList.SetRepairList(_sniffer.RepairList);\r
@@ -861,6 +925,11 @@ namespace KancolleSniffer
                 labelQuestColor6\r
             };\r
             var name = new[] {labelQuest1, labelQuest2, labelQuest3, labelQuest4, labelQuest5, labelQuest6};\r
+            var count = new[]\r
+            {\r
+                labelQuestCount1, labelQuestCount2, labelQuestCount3, labelQuestCount4, labelQuestCount5,\r
+                labelQuestCount6\r
+            };\r
             var progress = new[]\r
                 {labelProgress1, labelProgress2, labelProgress3, labelProgress4, labelProgress5, labelProgress6};\r
             var quests = _sniffer.Quests;\r
@@ -871,26 +940,51 @@ namespace KancolleSniffer
                     category[i].BackColor = quests[i].Color;\r
                     name[i].Text = quests[i].Name;\r
                     progress[i].Text = $"{quests[i].Progress:D}%";\r
+                    var c = quests[i].Count;\r
+                    if (c.Id == 0)\r
+                    {\r
+                        count[i].Text = "";\r
+                        count[i].ForeColor = Color.Black;\r
+                        _toolTip.SetToolTip(count[i], "");\r
+                        continue;\r
+                    }\r
+                    count[i].Text = " " + c;\r
+                    count[i].ForeColor = c.Cleared ? CUDColor.Green : Color.Black;\r
+                    _toolTip.SetToolTip(count[i], c.ToToolTip());\r
                 }\r
                 else\r
                 {\r
                     category[i].BackColor = DefaultBackColor;\r
-                    name[i].Text = progress[i].Text = "";\r
+                    name[i].Text = count[i].Text = progress[i].Text = "";\r
+                    _toolTip.SetToolTip(count[i], "");\r
                 }\r
             }\r
         }\r
 \r
-        private void Ring(string balloonTitle, string balloonMessage, string name)\r
+        private void Alarm(string balloonTitle, string balloonMessage, string name)\r
         {\r
-            if (_config.FlashWindow && (_config.Notifications[name].Flags & NotificationType.FlashWindow) != 0)\r
+            var flags = _config.Notifications[name].Flags;\r
+            var effective = _config.NotificationFlags & _config.Notifications[name].Flags;\r
+            if ((effective & NotificationType.FlashWindow) != 0)\r
                 Win32API.FlashWindow(Handle);\r
-            if (_config.ShowBaloonTip && (_config.Notifications[name].Flags & NotificationType.ShowBaloonTip) != 0)\r
+            if ((effective & NotificationType.ShowBaloonTip) != 0)\r
                 notifyIconMain.ShowBalloonTip(20000, balloonTitle, balloonMessage, ToolTipIcon.Info);\r
-            if (_config.PlaySound && (_config.Notifications[name].Flags & NotificationType.PlaySound) != 0)\r
+            if ((effective & NotificationType.PlaySound) != 0)\r
                 PlaySound(_config.Sounds[name], _config.Sounds.Volume);\r
-            if (_config.Pushbullet.On && (_config.Notifications[name].Flags & NotificationType.Pushbullet) != 0)\r
+            if (_config.Pushbullet.On && (flags & NotificationType.Push) != 0)\r
             {\r
-                Task.Run(() => { PushBullet.PushNote(_config.Pushbullet.Token, balloonTitle, balloonMessage); });\r
+                Task.Run(() =>\r
+                {\r
+                    PushNotification.PushToPushbullet(_config.Pushbullet.Token, balloonTitle, balloonMessage);\r
+                });\r
+            }\r
+            if (_config.Pushover.On && (flags & NotificationType.Push) != 0)\r
+            {\r
+                Task.Run(() =>\r
+                {\r
+                    PushNotification.PushToPushover(_config.Pushover.ApiKey, _config.Pushover.UserKey,\r
+                        balloonTitle, balloonMessage);\r
+                });\r
             }\r
         }\r
 \r
@@ -1056,6 +1150,12 @@ namespace KancolleSniffer
             Process.Start("http://localhost:" + _config.Proxy.Listen + "/");\r
         }\r
 \r
+        private void labelClearQuest_Click(object sender, EventArgs e)\r
+        {\r
+            _sniffer.ClearQuests();\r
+            UpdateQuestList();\r
+        }\r
+\r
         private void CaptureToolStripMenuItem_Click(object sender, EventArgs e)\r
         {\r
             try\r