玉兔远程控制 0.1.0-bate5
载入中...
搜索中...
未找到
mainwindow.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include <QFontMetrics>
4#include <QGridLayout>
5#include <QMessageBox>
6#include <QCheckBox>
7#include <QScreen>
8#include <QApplication>
9#include <QDebug>
10#include <QDesktopServices>
11#include <QWidgetAction>
12#include <QMouseEvent>
13#include <QDrag>
14#include <QMimeData>
15#include <QKeySequence>
16#include <QPushButton>
17#include <QDateTime>
18#include <QFileDialog>
19#include <QLoggingCategory>
20#include <QThread>
21
22#include "mainwindow.h"
23#include "ui_mainwindow.h"
24#ifdef HAVE_UPDATE
25 #include "FrmUpdater.h"
26#endif
27#include "RabbitCommonDir.h"
28#include "RabbitCommonTools.h"
29
30#ifdef HAVE_ABOUT
31 #include "DlgAbout.h"
32#endif
33#ifdef BUILD_QUIWidget
34 #include "QUIWidget/QUIWidget.h"
35#endif
36
37#include "Operate.h"
38#include "FrmFullScreenToolBar.h"
39#include "ParameterDlgSettings.h"
40
41#include "ViewTable.h"
42#include "ViewSplitter.h"
43
44#ifdef HAVE_ICE
45 #include "Ice.h"
46#endif
47
48static Q_LOGGING_CATEGORY(log, "App.MainWindow")
49static Q_LOGGING_CATEGORY(logRecord, "App.MainWindow.Record")
50
51MainWindow::MainWindow(QWidget *parent)
52 : QMainWindow(parent)
53 , m_pToolBarMenuAction(nullptr)
54 , m_pMenuActivityGroup(nullptr)
55 , m_ptbMenuActivity(nullptr)
56 , m_pActionOperateMenu(nullptr)
57 , m_pTBOperate(nullptr)
58 , m_pActionTBOperate(nullptr)
59 , m_pDockListRecent(nullptr)
60 , m_pDockActive(nullptr)
61 , m_pFrmActive(nullptr)
62 , m_pSecureLevel(nullptr)
63 , m_pSignalStatus(nullptr)
64 , ui(new Ui::MainWindow)
65 , m_pView(nullptr)
66 , m_pFullScreenToolBar(nullptr)
67 , m_pRecentMenu(nullptr)
68 , m_pDockFavorite(nullptr)
69 , m_pListRecent(nullptr)
70 , m_pFavoriteView(nullptr)
71 , m_StatusBarMessage(this)
72{
73 bool check = false;
74
75 ui->setupUi(this);
76 ui->menubar->show();
77
78#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && !defined(Q_OS_MACOS)
79 // gnome icon isn't support svg
80 setWindowIcon(QIcon(":/images/app"));
81#endif
82
83 m_StatusBarMessage.setSizePolicy(QSizePolicy::Policy::Expanding,
84 QSizePolicy::Policy::Fixed);
85 //m_StatusBarMessage.setWordWrap(true);
86 this->statusBar()->addWidget(&m_StatusBarMessage);
87
88 m_SendRate.setToolTip(tr("Send rate"));
89 m_SendRate.setStatusTip(tr("Send rate"));
90 // m_SendRate.setSizePolicy(QSizePolicy::Policy::Preferred,
91 // QSizePolicy::Policy::Fixed);
92 this->statusBar()->addPermanentWidget(&m_SendRate);
93 m_ReceivesRate.setToolTip(tr("Receives rate"));
94 m_ReceivesRate.setStatusTip(tr("Receives rate"));
95 // m_ReceivesRate.setSizePolicy(QSizePolicy::Policy::Preferred,
96 // QSizePolicy::Policy::Fixed);
97 this->statusBar()->addPermanentWidget(&m_ReceivesRate);
98 m_TotalSends.setToolTip(tr("Total sends"));
99 m_TotalSends.setStatusTip(tr("Total sends"));
100 // m_TotalSends.setSizePolicy(QSizePolicy::Policy::Preferred,
101 // QSizePolicy::Policy::Fixed);
102 this->statusBar()->addPermanentWidget(&m_TotalSends);
103 m_TotalReceives.setToolTip(tr("Total receives"));
104 m_TotalReceives.setStatusTip(tr("Total receives"));
105 // m_TotalReceives.setSizePolicy(QSizePolicy::Policy::Preferred,
106 // QSizePolicy::Policy::Fixed);
107 this->statusBar()->addPermanentWidget(&m_TotalReceives);
108
109 check = connect(&m_Timer, SIGNAL(timeout()), this, SLOT(slotTimeOut()));
110 Q_ASSERT(check);
111
112 m_pSecureLevel = new QLabel(statusBar());
113 // QIcon icon = QIcon::fromTheme("network-wired");
114 // QPixmap pixmap = icon.pixmap(icon.actualSize(QSize(64, 64)));
115 // m_pSecureLevel->setPixmap(pixmap);
116 m_pSecureLevel->hide();
117 statusBar()->addPermanentWidget(m_pSecureLevel);
118
119 //setFocusPolicy(Qt::NoFocus);
120 //addToolBar(Qt::LeftToolBarArea, ui->toolBar);
121 setAcceptDrops(true);
122
123 RabbitCommon::CTools::AddStyleMenu(ui->menuTools);
124 ui->menuTools->addMenu(RabbitCommon::CTools::GetLogMenu(this));
125
126 m_pRecentMenu = new RabbitCommon::CRecentMenu(
127 tr("Recently"), QIcon::fromTheme("document-open-recent"), true, this);
128 check = connect(m_pRecentMenu, SIGNAL(recentFileTriggered(const QString&)),
129 this, SLOT(slotOpenFile(const QString&)));
130 Q_ASSERT(check);
131 check = connect(&m_Parameter, SIGNAL(sigRecentMenuMaxCountChanged(int)),
132 m_pRecentMenu, SLOT(setMaxCount(int)));
133 Q_ASSERT(check);
134 QAction* pRecentAction = ui->menuOperate->insertMenu(
135 ui->actionOpenListRecent, m_pRecentMenu);
136 pRecentAction->setStatusTip(pRecentAction->text());
137 QToolButton* tbRecent = new QToolButton(ui->toolBar);
138 tbRecent->setFocusPolicy(Qt::NoFocus);
139 tbRecent->setPopupMode(QToolButton::InstantPopup);
140 tbRecent->setMenu(m_pRecentMenu);
141 tbRecent->setIcon(pRecentAction->icon());
142 tbRecent->setText(pRecentAction->text());
143 tbRecent->setToolTip(pRecentAction->toolTip());
144 tbRecent->setStatusTip(pRecentAction->statusTip());
145 ui->toolBar->insertWidget(ui->actionOpenListRecent, tbRecent);
146
147#ifdef HAVE_UPDATE
148 CFrmUpdater updater;
149 ui->actionUpdate->setIcon(updater.windowIcon());
150#endif
151
152 QToolButton* tbStart = new QToolButton(ui->toolBar);
153 tbStart->setFocusPolicy(Qt::NoFocus);
154 tbStart->setPopupMode(QToolButton::InstantPopup);
155 //tbStart->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
156 tbStart->setMenu(ui->menuStart);
157 tbStart->setIcon(QIcon::fromTheme("media-playback-start"));
158 tbStart->setText(tr("Start"));
159 tbStart->setToolTip(tr("Start"));
160 tbStart->setStatusTip(tr("Start"));
161 ui->toolBar->insertWidget(ui->actionStop, tbStart);
162
163 m_Parameter.Load();
164
165 check = connect(&m_Parameter, SIGNAL(sigReceiveShortCutChanged()),
166 this, SLOT(slotShortCut()));
167 Q_ASSERT(check);
168 slotSystemTrayIconTypeChanged();
169 check = connect(&m_Parameter, SIGNAL(sigSystemTrayIconTypeChanged()),
170 this,
171 SLOT(slotSystemTrayIconTypeChanged()));
172 Q_ASSERT(check);
173 check = connect(&m_Parameter, SIGNAL(sigEnableSystemTrayIcon()),
174 this, SLOT(slotEnableSystemTrayIcon()));
175 Q_ASSERT(check);
176 check = connect(&m_Parameter, SIGNAL(sigEnableTabToolTipChanged()),
177 this, SLOT(slotUpdateName()));
178 Q_ASSERT(check);
179 check = connect(&m_Parameter, SIGNAL(sigEnableTabIconChanged()),
180 this, SLOT(slotUpdateName()));
181 Q_ASSERT(check);
182
183 auto pTbMenu = new QToolButton(ui->toolBar);
184 pTbMenu->setFocusPolicy(Qt::NoFocus);
185 pTbMenu->setPopupMode(QToolButton::InstantPopup);
186 //m_pTbMenu->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
187 pTbMenu->setText(ui->actionMain_menu_bar_M->text());
188 pTbMenu->setIcon(ui->actionMain_menu_bar_M->icon());
189 pTbMenu->setToolTip(ui->actionMain_menu_bar_M->toolTip());
190 pTbMenu->setStatusTip(ui->actionMain_menu_bar_M->statusTip());
191 QMenu *pMenu = new QMenu(pTbMenu);
192 pMenu->addActions(this->menuBar()->actions());
193 pTbMenu->setMenu(pMenu);
194 m_pToolBarMenuAction = ui->toolBar->insertWidget(ui->actionTabBar_B, pTbMenu);
195#if defined(Q_OS_ANDROID)
196 m_pToolBarMenuAction->setVisible(true);
197#else
198 m_pToolBarMenuAction->setVisible(false);
199#endif
200
201 check = connect(&m_Parameter, SIGNAL(sigStartByTypeChanged()),
202 this, SLOT(slotStartByType()));
203 Q_ASSERT(check);
204
205 m_pDockFavorite = new QDockWidget(this);
206 if(m_pDockFavorite)
207 {
208 m_pFavoriteView = new CFavoriteView(m_pDockFavorite);
209 if(m_pFavoriteView)
210 {
211 m_pDockFavorite->setTitleBarWidget(m_pFavoriteView->m_pDockTitleBar);
212 check = connect(m_pFavoriteView, SIGNAL(sigStart(const QString&, bool)),
213 this, SLOT(slotOpenFile(const QString&, bool)));
214 Q_ASSERT(check);
215 check = connect(m_pFavoriteView, SIGNAL(sigFavorite()),
216 this, SLOT(on_actionAdd_to_favorite_triggered()));
217 Q_ASSERT(check);
218 check = connect(&m_Parameter, SIGNAL(sigFavoriteEditChanged(bool)),
219 m_pFavoriteView, SLOT(slotDoubleEditNode(bool)));
220 Q_ASSERT(check);
221 emit m_Parameter.sigFavoriteEditChanged(m_Parameter.GetFavoriteEdit());
222 m_pDockFavorite->setWidget(m_pFavoriteView);
223 m_pDockFavorite->setWindowTitle(m_pFavoriteView->windowTitle());
224 }
225 // Must set ObjectName then restore it. See: saveState help document
226 m_pDockFavorite->setObjectName("dockFavorite");
227#if defined(Q_OS_ANDROID)
228 m_pDockFavorite->hide();
229#endif
230 ui->menuView->addAction(m_pDockFavorite->toggleViewAction());
231 m_pDockFavorite->toggleViewAction()->setIcon(QIcon::fromTheme("emblem-favorite"));
232 addDockWidget(Qt::DockWidgetArea::LeftDockWidgetArea, m_pDockFavorite);
233 }
234
235 m_pDockListRecent = new QDockWidget(this);
236 if(m_pDockListRecent)
237 {
238 m_pListRecent
239 = new CFrmListRecent(this, &m_Manager, m_Parameter, true,
240 m_pDockListRecent);
241 if(m_pListRecent) {
242 if(m_pListRecent->m_pDockTitleBar)
243 m_pDockListRecent->setTitleBarWidget(
244 m_pListRecent->m_pDockTitleBar);
245 check = connect(m_pListRecent,
246 SIGNAL(sigStart(const QString&, bool)),
247 this, SLOT(slotOpenFile(const QString&, bool)));
248 Q_ASSERT(check);
249 check = connect(m_pListRecent, SIGNAL(sigAddToFavorite(QString,QString,QIcon,QString)),
250 m_pFavoriteView, SLOT(slotAddToFavorite(QString,QString,QIcon,QString)));
251 Q_ASSERT(check);
252 m_pDockListRecent->setWidget(m_pListRecent);
253 m_pDockListRecent->setWindowTitle(
254 m_pListRecent->windowTitle());
255 }
256 // Must set ObjectName then restore it. See: saveState help document
257 m_pDockListRecent->setObjectName("dockListRecent");
258#if defined(Q_OS_ANDROID)
259 m_pDockListRecent->hide();
260#endif
261 ui->menuView->addAction(m_pDockListRecent->toggleViewAction());
262 m_pDockListRecent->toggleViewAction()->setIcon(QIcon::fromTheme("document-open-recent"));
263 tabifyDockWidget(m_pDockFavorite, m_pDockListRecent);
264 }
265
266 m_pDockActive = new QDockWidget(this);
267 if(m_pDockActive)
268 {
269 m_pFrmActive = new CFrmActive(
270 m_Operates, m_Parameter,
271 ui->menuStart, ui->actionStop,
272 m_pRecentMenu, m_pDockActive);
273 if(m_pFrmActive) {
274 m_pDockActive->setWidget(m_pFrmActive);
275 if(m_pFrmActive->m_pDockTitleBar)
276 m_pDockActive->setTitleBarWidget(
277 m_pFrmActive->m_pDockTitleBar);
278 m_pDockActive->setWindowTitle(m_pFrmActive->windowTitle());
279 check = connect(m_pFrmActive, SIGNAL(sigChanged(COperate*)),
280 this, SLOT(slotOperateChanged(COperate*)));
281 Q_ASSERT(check);
282 check = connect(m_pFrmActive, SIGNAL(sigAddToFavorite(QString,QString,QIcon,QString)),
283 m_pFavoriteView, SLOT(slotAddToFavorite(QString,QString,QIcon,QString)));
284 Q_ASSERT(check);
285 }
286 m_pDockActive->setObjectName("dockListActive");
287#if defined(Q_OS_ANDROID)
288 m_pDockActive->hide();
289#endif
290 ui->menuView->addAction(m_pDockActive->toggleViewAction());
291 m_pDockActive->toggleViewAction()->setIcon(QIcon::fromTheme("network-wired"));
292 tabifyDockWidget(m_pDockFavorite, m_pDockActive);
293 }
294
295 QActionGroup* pGBView = new QActionGroup(this);
296 if(pGBView) {
297 pGBView->addAction(ui->actionViewTab);
298 pGBView->addAction(ui->actionViewSplit);
299 }
300 qDebug(log) << "View type:" << m_Parameter.GetViewType();
301 if(CParameterApp::ViewType::Tab == m_Parameter.GetViewType()) {
302 ui->actionViewTab->setChecked(true);
303 on_actionViewTab_triggered();
304 }
305 if(CParameterApp::ViewType::Splitter == m_Parameter.GetViewType()) {
306 ui->actionViewSplit->setChecked(true);
307 on_actionViewSplit_triggered();
308 }
309 check = connect(&m_Parameter, &CParameterApp::sigViewTypeChanged,
310 this, [&](){
311 m_Parameter.Save();
312 });
313 Q_ASSERT(check);
314
315 m_pMenuActivityGroup = new QActionGroup(ui->menuActivity);
316 m_ptbMenuActivity = new QToolButton(ui->toolBar);
317 m_ptbMenuActivity->setFocusPolicy(Qt::NoFocus);
318 m_ptbMenuActivity->setPopupMode(QToolButton::InstantPopup);
319 m_ptbMenuActivity->setMenu(ui->menuActivity);
320 m_ptbMenuActivity->setIcon(ui->menuActivity->icon());
321 m_ptbMenuActivity->setText(ui->menuActivity->title());
322 m_ptbMenuActivity->setToolTip(ui->menuActivity->toolTip());
323 m_ptbMenuActivity->setStatusTip(ui->menuActivity->statusTip());
324 ui->toolBar->insertWidget(ui->actionTabBar_B, m_ptbMenuActivity);
325
326 EnableMenu(false);
327 slotShortCut();
328
329#ifdef HAVE_ICE
330 if(CICE::Instance()->GetSignal())
331 {
332 check = connect(CICE::Instance()->GetSignal().data(),
333 SIGNAL(sigConnected()),
334 this, SLOT(slotSignalConnected()));
335 Q_ASSERT(check);
336 check = connect(CICE::Instance()->GetSignal().data(),
337 SIGNAL(sigDisconnected()),
338 this, SLOT(slotSignalDisconnected()));
339 Q_ASSERT(check);
340 check = connect(CICE::Instance()->GetSignal().data(),
341 SIGNAL(sigError(const int, const QString&)),
342 this, SLOT(slotSignalError(const int, const QString&)));
343 Q_ASSERT(check);
344 }
345 CICE::Instance()->slotStart(statusBar());
346 m_pSignalStatus = new QPushButton();
347 m_pSignalStatus->setToolTip(tr("ICE signal status"));
348 m_pSignalStatus->setStatusTip(m_pSignalStatus->toolTip());
349 m_pSignalStatus->setWhatsThis(m_pSignalStatus->toolTip());
350 slotSignalDisconnected();
351 statusBar()->addPermanentWidget(m_pSignalStatus);
352#endif
353
354 if(m_Parameter.GetSaveMainWindowStatus())
355 {
356 QSettings set(RabbitCommon::CDir::Instance()->GetFileUserConfigure(),
357 QSettings::IniFormat);
358 QByteArray geometry
359 = set.value("MainWindow/Status/Geometry").toByteArray();
360 if(!geometry.isEmpty())
361 restoreGeometry(geometry);
362 // Restores the state of this mainwindow's toolbars and dockwidgets
363 QByteArray state = set.value("MainWindow/Status/State").toByteArray();
364 if(!state.isEmpty())
365 restoreState(state);
366
367 ui->actionTabBar_B->setChecked(m_Parameter.GetTabBar());
368 on_actionTabBar_B_toggled(m_Parameter.GetTabBar());
369 ui->actionStatus_bar_S->setChecked(m_Parameter.GetStatusBar());
370 statusBar()->setVisible(m_Parameter.GetStatusBar());
371 ui->actionMain_menu_bar_M->setChecked(m_Parameter.GetMenuBar());
372 menuBar()->setVisible(m_Parameter.GetMenuBar());
373 ui->actionToolBar_T->setChecked(!ui->toolBar->isHidden());
374 // macOS: Hide 'Main menu bar' on macOS since it's always visible
375 #ifdef Q_OS_MACOS
376 // Hide 'Main menu bar' on View menu
377 ui->actionMain_menu_bar_M->setVisible(false);
378 #else
379 // Show 'Main menu bar' toolbar icon
380 if(!m_Parameter.GetMenuBar()) {
381 m_pToolBarMenuAction->setVisible(true);
382 }
383 #endif
384 }
385}
386
387MainWindow::~MainWindow()
388{
389 qDebug(log) << "MainWindow::~MainWindow()";
390 if(m_pFullScreenToolBar) m_pFullScreenToolBar->close();
391 delete ui;
392}
393
396{
397 qDebug(log) << Q_FUNC_INFO;
398
399 setEnabled(false);
400
401 slotInformation(tr("Load plugins ......"));
402 qApp->processEvents();
403 m_Manager.Initial();
404 m_Manager.EnumPlugins(this);
405
406 if(m_pRecentMenu) {
407 slotInformation(tr("Load recent menu ......"));
408 qApp->processEvents();
409 m_pRecentMenu->slotRestoreState();
410 }
411
412 if(m_pFavoriteView) {
413 slotInformation(tr("Load favorite ......"));
414 qApp->processEvents();
415 m_pFavoriteView->Load();
416 }
417
418 if(m_pListRecent) {
419 slotInformation(tr("Load list recent dock ......"));
420 qApp->processEvents();
421 m_pListRecent->slotLoadFiles();
422 }
423 slotEnableSystemTrayIcon();
424
425 setEnabled(true);
426
427 slotInformation(tr("Load laster operate ......"));
428 qApp->processEvents();
429 LoadOperateLasterClose();
430
431 slotInformation(tr("Ready"));
432
433 return;
434}
435
436void MainWindow::SetView(CView* pView)
437{
438 qDebug(log) << Q_FUNC_INFO;
439 if(!pView)
440 return;
441 if(m_pView)
442 m_pView->disconnect();
443
444 m_pView = pView;
445 setCentralWidget(m_pView);
446
447 bool check = false;
448 //m_pView->setFocusPolicy(Qt::NoFocus);
449 check = connect(m_pView, SIGNAL(sigCloseView(const QWidget*)),
450 this, SLOT(slotCloseView(const QWidget*)));
451 Q_ASSERT(check);
452 check = connect(m_pView, SIGNAL(sigCurrentChanged(const QWidget*)),
453 this, SLOT(slotCurrentViewChanged(const QWidget*)));
454 Q_ASSERT(check);
455 if(m_pFrmActive) {
456 check = connect(m_pView, SIGNAL(sigCurrentChanged(const QWidget*)),
457 m_pFrmActive, SLOT(slotViewChanged(const QWidget*)));
458 Q_ASSERT(check);
459 }
460 check = connect(m_pView, SIGNAL(customContextMenuRequested(const QPoint&)),
461 this, SLOT(slotCustomContextMenuRequested(const QPoint&)));
462 Q_ASSERT(check);
463
464 foreach (auto c, m_Operates) {
465 m_pView->AddView(c->GetViewer());
466 m_pView->SetWidowsTitle(
467 c->GetViewer(), c->Name(), c->Icon(), c->Description());
468 }
469 m_pView->SetVisibleTab(m_Parameter.GetTabBar());
470}
471
472void MainWindow::on_actionViewTab_triggered()
473{
474 qDebug(log) << Q_FUNC_INFO;
475 if(!ui->actionViewTab->isChecked()) return;
476 m_Parameter.SetViewType(CParameterApp::ViewType::Tab);
477 SetView(new CViewTable(&m_Parameter, this));
478}
479
480void MainWindow::on_actionViewSplit_triggered()
481{
482 qDebug(log) << Q_FUNC_INFO;
483 if(!ui->actionViewSplit->isChecked()) return;
484 m_Parameter.SetViewType(CParameterApp::ViewType::Splitter);
485 SetView(new CViewSplitter(&m_Parameter, this));
486}
487
488void MainWindow::on_actionAbout_triggered()
489{
490#ifdef HAVE_ABOUT
491 CDlgAbout *about = new CDlgAbout(this);
492 QIcon icon = QIcon::fromTheme("app");
493 if(!icon.isNull()) {
494 auto sizeList = icon.availableSizes();
495 if(!sizeList.isEmpty()) {
496 QPixmap p = icon.pixmap(*sizeList.begin());
497 about->m_AppIcon = p.toImage();
498 }
499 }
500 about->m_szCopyrightStartTime = "2020";
501 about->m_szVersionRevision = RabbitRemoteControl_REVISION;
502 about->m_szDetails = m_Manager.Details();
503 RC_SHOW_WINDOW(about);
504#endif
505}
506
507void MainWindow::on_actionUpdate_triggered()
508{
509 if(!qEnvironmentVariable("SNAP").isEmpty()) {
510 QDesktopServices::openUrl(QUrl("https://snapcraft.io/rabbitremotecontrol"));
511 } else if(!qEnvironmentVariable("FLATPAK_ID").isEmpty()) {
512 QDesktopServices::openUrl(QUrl("https://flathub.org/apps/io.github.KangLin.RabbitRemoteControl"));
513 } else {
514#ifdef HAVE_UPDATE
515 CFrmUpdater* m_pfrmUpdater = new CFrmUpdater();
516 QIcon icon = QIcon::fromTheme("app");
517 if(!icon.isNull()) {
518 auto sizeList = icon.availableSizes();
519 if(!sizeList.isEmpty()) {
520 QPixmap p = icon.pixmap(*sizeList.begin());
521 m_pfrmUpdater->SetTitle(p.toImage());
522 }
523 }
524 m_pfrmUpdater->SetInstallAutoStartup();
525 RC_SHOW_WINDOW(m_pfrmUpdater);
526#endif
527 }
528}
529
530void MainWindow::on_actionFull_screen_F_triggered()
531{
532 CView* pView = qobject_cast<CView*>(this->centralWidget());
533 if(pView)
534 {
535 pView->SetFullScreen(!isFullScreen());
536 }
537
538 if(isFullScreen())
539 {
540 qDebug(log) << "Exit full screen";
541 ui->actionFull_screen_F->setIcon(QIcon::fromTheme("view-fullscreen"));
542 ui->actionFull_screen_F->setText(tr("Full screen"));
543 ui->actionFull_screen_F->setToolTip(tr("Full screen"));
544 ui->actionFull_screen_F->setStatusTip(tr("Full screen"));
545 ui->actionFull_screen_F->setWhatsThis(tr("Full screen"));
546
547 ui->toolBar->setVisible(m_FullState.toolBar);
548 ui->statusbar->setVisible(m_FullState.statusbar);
549 ui->menubar->setVisible(m_FullState.menubar);
550
551 m_pDockActive->setVisible(m_FullState.dockListActive);
552 m_pDockListRecent->setVisible(m_FullState.dockListRecent);
553 m_pDockFavorite->setVisible(m_FullState.dockFavorite);
554 // TODO: This is hade code. it is in RabbitCommon
555 QDockWidget* pDockDebugLog = findChild<QDockWidget*>("dockDebugLog");
556 if(pDockDebugLog)
557 {
558 pDockDebugLog->setVisible(m_FullState.dockDebugLog);
559 }
560
561 if(m_pFullScreenToolBar)
562 {
563 // Delete it when the widget is close
564 m_pFullScreenToolBar->close();
565 m_pFullScreenToolBar = nullptr;
566 }
567
568 emit sigShowNormal();
569 this->showNormal();
570 this->activateWindow();
571
572 emit sigFullScreen(false);
573 return;
574 }
575
576 qDebug(log) << "Entry full screen";
577
578 //setWindowFlags(Qt::FramelessWindowHint | windowFlags());
579 this->showFullScreen();
580 emit sigFullScreen(true);
581
582 ui->actionFull_screen_F->setIcon(QIcon::fromTheme("view-restore"));
583 ui->actionFull_screen_F->setText(tr("Exit full screen"));
584 ui->actionFull_screen_F->setToolTip(tr("Exit full screen"));
585 ui->actionFull_screen_F->setStatusTip(tr("Exit full screen"));
586 ui->actionFull_screen_F->setWhatsThis(tr("Exit full screen"));
587
588 m_FullState.toolBar = ui->toolBar->isVisible();
589 ui->toolBar->setVisible(false);
590 m_FullState.statusbar = ui->statusbar->isVisible();
591 ui->statusbar->setVisible(false);
592 m_FullState.menubar = ui->menubar->isVisible();
593 ui->menubar->setVisible(false);
594
595 m_FullState.dockListActive = m_pDockActive->isVisible();
596 m_pDockActive->setVisible(false);
597 m_FullState.dockListRecent = m_pDockListRecent->isVisible();
598 m_pDockListRecent->setVisible(false);
599 m_FullState.dockFavorite = m_pDockFavorite->isVisible();
600 m_pDockFavorite->setVisible(false);
601 // This is hade code. it is in RabbitCommon
602 QDockWidget* pDockDebugLog = findChild<QDockWidget*>("dockDebugLog");
603 if(pDockDebugLog)
604 {
605 m_FullState.dockDebugLog = pDockDebugLog->isVisible();
606 pDockDebugLog->setVisible(false);
607 }
608
609 if(m_pFullScreenToolBar) m_pFullScreenToolBar->close();
610 // Delete it when the widget is close
611 m_pFullScreenToolBar = new CFrmFullScreenToolBar(this);
612 QScreen* pScreen = qApp->primaryScreen();
613 if(pScreen) {
614 QPoint pos(pScreen->geometry().left()
615 + (pScreen->geometry().width()
616 - m_pFullScreenToolBar->frameGeometry().width()) / 2,
617 pScreen->geometry().top());
618 qDebug(log) << "Primary screen geometry:" << pScreen->geometry()
619 << "availableGeometry:" << pScreen->availableGeometry()
620 << pos << mapToGlobal(pos);
621 m_pFullScreenToolBar->move(pos);
622 }
623 bool check = connect(m_pFullScreenToolBar, SIGNAL(sigExitFullScreen()),
624 this, SLOT(on_actionFull_screen_F_triggered()));
625 Q_ASSERT(check);
626 check = connect(m_pFullScreenToolBar, SIGNAL(sigExit()),
627 this, SLOT(on_actionExit_E_triggered()));
628 Q_ASSERT(check);
629 Q_ASSERT(check);
630 check = connect(this, SIGNAL(sigOperateMenuChanged(QAction*)),
631 m_pFullScreenToolBar,
632 SLOT(slotOperateMenuChanged(QAction*)));
633 Q_ASSERT(check);
634
635 m_pFullScreenToolBar->show();
636}
637
638void MainWindow::slotViewerFocusIn(QWidget *pView)
639{
640 COperate* c = qobject_cast<COperate*>(sender());
641 qDebug(log) << Q_FUNC_INFO << "Focus:" << c << pView;
642 if(c && m_pView) {
643 m_pView->SetCurrentView(c->GetViewer());
644 }
645}
646
647void MainWindow::slotOperateChanged(COperate *o)
648{
649 if(o && m_pView) {
650 m_pView->SetCurrentView(o->GetViewer());
651 }
652}
653
654void MainWindow::slotCurrentViewChanged(const QWidget* pView)
655{
656 qDebug(log) << Q_FUNC_INFO;
657 if(m_pView && pView)
658 EnableMenu(true);
659 else
660 EnableMenu(false);
661
662 foreach(auto o, m_Operates) {
663 if(o->GetViewer() == pView) {
664 SetSecureLevel(o);
665 SetStatsVisible(o->GetStats());
666 foreach (auto a, ui->menuActivity->actions()) {
667 if(a->data().value<COperate*>() == o)
668 a->setChecked(true);
669 }
670 }
671 }
672}
673
674void MainWindow::EnableMenu(bool bEnable)
675{
676 qDebug(log) << Q_FUNC_INFO << bEnable;
677 ui->actionClone->setEnabled(bEnable);
678 ui->actionAdd_to_favorite->setEnabled(bEnable);
679 ui->actionStop->setEnabled(bEnable);
680 ui->actionTabBar_B->setEnabled(bEnable);
681 ui->menuActivity->setEnabled(bEnable);
682 m_ptbMenuActivity->setEnabled(bEnable);
683 slotLoadOperateMenu();
684}
685
686void MainWindow::slotMenuActivity()
687{
688 QAction* pAction = qobject_cast<QAction*>(sender());
689 Q_ASSERT(pAction);
690 if(!pAction) return;
691 COperate* p = pAction->data().value<COperate*>();
692 if(p)
693 slotOperateChanged(p);
694}
695
696void MainWindow::slotLoadOperateMenu()
697{
698 qDebug(log) << Q_FUNC_INFO;
699
700 if(m_pActionOperateMenu) {
701 ui->menuOperate->removeAction(m_pActionOperateMenu);
702 m_pActionOperateMenu = nullptr;
703 }
704 ui->toolBar->removeAction(m_pActionTBOperate);
705
706 if(!m_pView)
707 return;
708 auto pWin = m_pView->GetCurrentView();
709 if(!pWin) {
710 qDebug(log) << "The current view is empty";
711 return;
712 }
713 foreach(auto op, m_Operates)
714 {
715 if(op->GetViewer() == pWin)
716 {
717 qDebug(log) << "Load plugin menu";
718 auto m = op->GetMenu(ui->menuTools);
719 if(!m) return;
720 // Menu tool bar
721 m_pActionOperateMenu = ui->menuOperate->insertMenu(ui->actionAdd_to_favorite, m);
722 // ToolBar
723 if(!m_pTBOperate)
724 m_pTBOperate = new QToolButton(ui->toolBar);
725 if(m_pTBOperate) {
726 m_pTBOperate->setFocusPolicy(Qt::NoFocus);
727 m_pTBOperate->setPopupMode(QToolButton::InstantPopup);
728 m_pTBOperate->setMenu(m);
729 m_pTBOperate->setIcon(m->icon());
730 m_pTBOperate->setText(m->title());
731 m_pTBOperate->setToolTip(m->toolTip());
732 m_pTBOperate->setStatusTip(m->statusTip());
733 m_pTBOperate->show();
734 m_pActionTBOperate = ui->toolBar->insertWidget(ui->actionAdd_to_favorite, m_pTBOperate);
735 }
736 emit sigOperateMenuChanged(m_pActionOperateMenu);
737 }
738 }
739}
740
748{
749 if(!m_pView)
750 return;
751 auto pWin = m_pView->GetCurrentView();
752 if(!pWin) {
753 qDebug(log) << "The current view is empty";
754 return;
755 }
756 foreach(auto p, m_Operates)
757 {
758 if(p->GetViewer() == pWin)
759 {
760 qDebug(log) << "Load plugin menu";
761 auto m = p->GetMenu(ui->menuTools);
762 if(!m) return;
763 // Note: The view is converted to global coordinates
764 m->exec(pos);
765 }
766 }
767}
768
769void MainWindow::on_actionExit_E_triggered()
770{
771 close();
772}
773
774void MainWindow::keyReleaseEvent(QKeyEvent *event)
775{
776 switch(event->key())
777 {
778 case Qt::Key_Escape:
779 if(isFullScreen())
780 on_actionFull_screen_F_triggered();
781 break;
782 }
783 QMainWindow::keyReleaseEvent(event);
784}
785
786void MainWindow::slotUpdateParameters(COperate *pOperate)
787{
788 m_Manager.SaveOperate(pOperate);
789}
790
791void MainWindow::on_actionClone_triggered()
792{
793 if(!m_pView) return;
794 QWidget* p = m_pView->GetCurrentView();
795 foreach(auto pOperate, m_Operates)
796 {
797 if(pOperate->GetViewer() == p)
798 {
799 QString szFile = pOperate->GetSettingsFile();
800 auto pOperate = m_Manager.LoadOperate(szFile);
801 if(!pOperate) return;
802 Start(pOperate, false, szFile);
803 return;
804 }
805 }
806}
807
808void MainWindow::slotOpenFile(const QString& szFile, bool bOpenSettings)
809{
810 if(szFile.isEmpty()) return;
811 COperate* p = m_Manager.LoadOperate(szFile);
812 if(nullptr == p)
813 {
814 slotStatusMessage(tr("Load file fail: ") + szFile, MessageLevel::Error);
815 return;
816 }
817
818 Start(p, bOpenSettings, szFile);
819}
820
821void MainWindow::on_actionOpenRRCFile_triggered()
822{
823 QString szFile = QFileDialog::getOpenFileName(
824 this,
825 tr("Open rabbit remote control file"),
826 RabbitCommon::CDir::Instance()->GetDirUserData(),
827 tr("Rabbit remote control Files (*.rrc);;All files(*.*)"));
828 if(szFile.isEmpty()) return;
829
830 COperate* p = m_Manager.LoadOperate(szFile);
831 if(nullptr == p)
832 {
833 slotStatusMessage(tr("Load file fail: ") + szFile, MessageLevel::Error);
834 return;
835 }
836
837 Start(p, true);
838}
839
840void MainWindow::slotStart()
841{
842 if(nullptr == m_pView)
843 {
844 Q_ASSERT(false);
845 return;
846 }
847 QAction* pAction = qobject_cast<QAction*>(this->sender());
848 Q_ASSERT(pAction);
849 COperate* p = m_Manager.CreateOperate(pAction->data().toString());
850 if(nullptr == p) return;
851 Start(p, true);
852}
853
864int MainWindow::Start(COperate *pOperate, bool set, QString szFile)
865{
866 qDebug(log) << "MainWindow::Start: set:" << set << "; File:" << szFile;
867 bool bSave = false; //whether is save configure file
868 Q_ASSERT(pOperate);
869 bool check = connect(pOperate, SIGNAL(sigRunning()),
870 this, SLOT(slotRunning()));
871 Q_ASSERT(check);
872 check = connect(pOperate, SIGNAL(sigStop()),
873 this, SLOT(slotStop()));
874 Q_ASSERT(check);
875 check = connect(pOperate, SIGNAL(sigFinished()),
876 this, SLOT(slotFinished()));
877 Q_ASSERT(check);
878 check = connect(pOperate, SIGNAL(sigError(const int, const QString &)),
879 this, SLOT(slotError(const int, const QString&)));
880 Q_ASSERT(check);
881 check = connect(pOperate, SIGNAL(sigShowMessageBox(const QString&, const QString&,
882 const QMessageBox::Icon&)),
883 this, SLOT(slotShowMessageBox(const QString&, const QString&,
884 const QMessageBox::Icon&)));
885 Q_ASSERT(check);
886 check = connect(pOperate, SIGNAL(sigInformation(const QString&)),
887 this, SLOT(slotInformation(const QString&)));
888 Q_ASSERT(check);
889 check = connect(pOperate, SIGNAL(sigUpdateName(const QString&)),
890 this, SLOT(slotUpdateName(const QString&)));
891 Q_ASSERT(check);
892 check = connect(pOperate, SIGNAL(sigUpdateParameters(COperate*)),
893 this, SLOT(slotUpdateParameters(COperate*)));
894 Q_ASSERT(check);
895 check = connect(pOperate, &COperate::sigFullScreen,
896 this, [this, pOperate](bool bFull) {
897 if(m_pView && m_pView->GetCurrentView() == pOperate->GetViewer()) {
898 if((bFull && !isFullScreen()) || (!bFull && isFullScreen()))
899 on_actionFull_screen_F_triggered();
900 }
901 });
902 Q_ASSERT(check);
903 if(set)
904 {
905 int nRet = pOperate->OpenDialogSettings(this);
906 switch(nRet)
907 {
908 case QDialog::Rejected:
909 m_Manager.DeleteOperate(pOperate);
910 return 0;
911 case QDialog::Accepted:
912 bSave = true;
913 break;
914 }
915 }
916
917 if(szFile.isEmpty())
918 szFile = pOperate->GetSettingsFile();
919 else
920 pOperate->SetSettingsFile(szFile);
921
922 int nRet = 0;
923 if(bSave)
924 nRet = m_Manager.SaveOperate(pOperate);
925 if(0 == nRet)
926 m_pRecentMenu->addRecentFile(szFile, pOperate->Name());
927
928 if(!pOperate->Name().isEmpty())
929 slotInformation(tr("Starting: ") + pOperate->Name());
930
931 //* Show view. \see: slotRunning()
932 if(-1 < m_Operates.indexOf(pOperate)) {
933 if(m_pView)
934 m_pView->SetCurrentView(pOperate->GetViewer());
935 return 0;
936 }
937 if(m_pView)
938 {
939 m_pView->AddView(pOperate->GetViewer());
940 m_pView->SetWidowsTitle(pOperate->GetViewer(), pOperate->Name(),
941 pOperate->Icon(), pOperate->Description());
942 //qDebug(log) << "View:" << p->GetViewer();
943 check = connect(pOperate, SIGNAL(sigViewerFocusIn(QWidget*)),
944 this, SLOT(slotViewerFocusIn(QWidget*)));
945 Q_ASSERT(check);
946 }
947 m_Operates.push_back(pOperate);
948 StartTimer();
949
950 m_pFrmActive->slotLoad();
951 m_pFrmActive->slotViewChanged(m_pView->GetCurrentView());
952
953 QVariant vOperate;
954 vOperate.setValue(pOperate);
955 QAction* m_pActionmenuActivity = ui->menuActivity->addAction(
956 pOperate->Icon(), pOperate->Name(), this, SLOT(slotMenuActivity()));
957 m_pActionmenuActivity->setData(vOperate);
958 m_pActionmenuActivity->setCheckable(true);
959 m_pMenuActivityGroup->addAction(m_pActionmenuActivity);
960 m_pActionmenuActivity->setChecked(true);
961 //*/
962
963 nRet = pOperate->Start();
964 if(nRet)
965 pOperate->Stop();
966 return nRet;
967}
968
970
974{
975 COperate* p = qobject_cast<COperate*>(sender());
976 if(!p) return;
977
978 /* If you put it here, when running, the view is not displayed.
979 So put it in the Start() display view.
980 See: Start(COperate *p, bool set, QString szFile)
981 */
982 /*
983 if(-1 == m_Operates.indexOf(p)) {
984 m_Operates.push_back(p);
985 if(m_pView)
986 {
987 m_pView->AddView(p->GetViewer());
988 m_pView->SetWidowsTitle(p->GetViewer(), p->Name(), p->Icon(), p->Description());
989 }
990 } else {
991 m_pView->SetCurrentView(p->GetViewer());
992 }
993 //*/
994
995 SetSecureLevel(p);
996
997 auto m = p->GetMenu();
998 if(m) {
999 m->addSeparator();
1000 m->addAction(ui->actionClone);
1001 }
1002 slotLoadOperateMenu();
1003
1004 slotInformation(tr("Connected to ") + p->Name());
1005 qDebug(log) << Q_FUNC_INFO << p->Name();
1006}
1008
1009void MainWindow::slotCloseView(const QWidget* pView)
1010{
1011 qDebug(log) << "MainWindow::slotCloseView" << pView;
1012 if(!pView) return;
1013 foreach(auto p, m_Operates)
1014 {
1015 if(p->GetViewer() == pView)
1016 {
1017 //TODO: Whether to save the setting
1018 emit p->sigUpdateParameters(p);
1019 p->Stop();
1020 }
1021 }
1022}
1023
1024void MainWindow::on_actionStop_triggered()
1025{
1026 qDebug(log) << Q_FUNC_INFO;
1027 if(!m_pView) return;
1028
1029 QWidget* pView = m_pView->GetCurrentView();
1030 slotCloseView(pView);
1031}
1032
1033void MainWindow::slotStop()
1034{
1035 COperate* pOperate = qobject_cast<COperate*>(sender());
1036 if(!pOperate) return;
1037 qDebug(log) << Q_FUNC_INFO << pOperate->Name();
1038 //TODO: Whether to save the setting
1039 emit pOperate->sigUpdateParameters(pOperate);
1040 pOperate->Stop();
1041}
1042
1043void MainWindow::slotFinished()
1044{
1045 COperate* pOperate = qobject_cast<COperate*>(sender());
1046 if(!pOperate) return;
1047
1048 qDebug(log) << Q_FUNC_INFO << pOperate->Name();
1049 foreach(auto a, ui->menuActivity->actions()) {
1050 COperate* o = a->data().value<COperate*>();
1051 if(o == pOperate) {
1052 ui->menuActivity->removeAction(a);
1053 m_pMenuActivityGroup->removeAction(a);
1054 }
1055 }
1056 foreach(auto p, m_Operates)
1057 {
1058 if(p == pOperate)
1059 {
1060 m_pView->RemoveView(p->GetViewer());
1061 m_Operates.removeAll(p);
1062 m_Manager.DeleteOperate(p);
1063 m_pFrmActive->slotLoad();
1064 m_pFrmActive->slotViewChanged(m_pView->GetCurrentView());
1065 break;
1066 }
1067 }
1068 if(m_Operates.isEmpty())
1069 if(m_pActionOperateMenu) {
1070 ui->menuTools->removeAction(m_pActionOperateMenu);
1071 ui->toolBar->removeAction(m_pActionOperateMenu);
1072 m_pActionOperateMenu = nullptr;
1073 }
1074
1075 StartTimer();
1076}
1077
1078// 该函数将label控件变成一个圆形指示灯,需要指定颜色color以及直径size
1079// size 单位是像素
1080void SetIndicator(QLabel* label, QColor color, int size)
1081{
1082 QString min_width = QString("min-width: %1px;").arg(size); // 最小宽度:size
1083 QString min_height = QString("min-height: %1px;").arg(size); // 最小高度:size
1084 QString max_width = QString("max-width: %1px;").arg(size); // 最小宽度:size
1085 QString max_height = QString("max-height: %1px;").arg(size); // 最小高度:size
1086 // 再设置边界形状及边框
1087 QString border_radius = QString("border-radius: %1px;").arg(size / 2); // 边框是圆角,半径为size/2
1088 QString border = QString("border:1px solid ") + color.name() + ";"; // 边框为1px
1089 // 最后设置背景颜色
1090 QString background = "background-color: ";
1091 background += color.name() + ";";
1092 QString SheetStyle = min_width + min_height + max_width + max_height + border_radius + border + background;
1093 label->setStyleSheet(SheetStyle);
1094}
1095
1096void MainWindow::SetSecureLevel(COperate* o)
1097{
1098 if(!m_pSecureLevel) return;
1099 if(o) {
1100 if(COperate::SecurityLevel::No == o->GetSecurityLevel())
1101 {
1102 m_pSecureLevel->hide();
1103 return;
1104 }
1105 SetIndicator(m_pSecureLevel, o->GetSecurityLevelColor(), statusBar()->height() / 2);
1106 m_pSecureLevel->setToolTip(o->GetSecurityLevelString());
1107 m_pSecureLevel->setStatusTip(o->GetSecurityLevelString());
1108 m_pSecureLevel->show();
1109 } else
1110 m_pSecureLevel->hide();
1111}
1112
1113void MainWindow::slotSignalConnected()
1114{
1115 m_pSignalStatus->setToolTip(tr("ICE signal status: Connected"));
1116 m_pSignalStatus->setStatusTip(m_pSignalStatus->toolTip());
1117 m_pSignalStatus->setWhatsThis(m_pSignalStatus->toolTip());
1118 //m_pSignalStatus->setText(tr("Connected"));
1119 m_pSignalStatus->setIcon(QIcon::fromTheme("network-wired"));
1120}
1121
1122void MainWindow::slotSignalDisconnected()
1123{
1124 m_pSignalStatus->setToolTip(tr("ICE signal status: Disconnected"));
1125 m_pSignalStatus->setStatusTip(m_pSignalStatus->toolTip());
1126 m_pSignalStatus->setWhatsThis(m_pSignalStatus->toolTip());
1127 //m_pSignalStatus->setText(tr("Disconnected"));
1128 m_pSignalStatus->setIcon(QIcon::fromTheme("network-wireless"));
1129}
1130
1131void MainWindow::slotSignalError(const int nError, const QString &szInfo)
1132{
1133 slotSignalDisconnected();
1134 slotError(nError, szInfo);
1135}
1136
1137void MainWindow::slotSignalPushButtonClicked(bool checked)
1138{
1139#ifdef HAVE_ICE
1140 if(checked)
1141 CICE::Instance()->slotStart();
1142 else
1143 CICE::Instance()->slotStop();
1144#endif
1145}
1146
1147void MainWindow::slotError(const int nError, const QString &szInfo)
1148{
1149 Q_UNUSED(nError);
1150 slotStatusMessage(szInfo, MessageLevel::Error);
1151}
1152
1154 const QString &title, const QString &message,
1155 const QMessageBox::Icon &icon)
1156{
1157 slotInformation(message);
1158 if(!m_Parameter.GetMessageBoxDisplayInformation())
1159 return;
1160
1161 QMessageBox msg(icon, title, message, QMessageBox::Ok, this);
1162 QCheckBox* cb = new QCheckBox(
1163 tr("Use message box to display information"), this);
1164 cb->setChecked(true);
1165 msg.setCheckBox(cb);
1166 RC_SHOW_WINDOW(&msg);
1167 if(!cb->isChecked())
1168 {
1169 m_Parameter.SetMessageBoxDisplayInformation(false);
1170 m_Parameter.Save();
1171 }
1172}
1173
1174void MainWindow::slotInformation(const QString& szInfo)
1175{
1176 slotStatusMessage(szInfo, MessageLevel::Normal);
1177}
1178
1179void MainWindow::slotStatusMessage(QString szMessage, MessageLevel level)
1180{
1181 QPalette pe;
1182 switch ((MessageLevel)level) {
1183 case MessageLevel::Error:
1184 pe.setColor(QPalette::WindowText, Qt::red);
1185 break;
1186 case MessageLevel::Warning:
1187 pe.setColor(QPalette::WindowText, Qt::yellow);
1188 break;
1189 default:
1190 break;
1191 }
1192
1193 m_StatusBarMessage.setPalette(pe);
1194 m_StatusBarMessage.setToolTip(szMessage);
1195 QFontMetrics metrics(m_StatusBarMessage.font());
1196
1197 szMessage = metrics.elidedText(szMessage, Qt::ElideRight, m_StatusBarMessage.width());
1198
1199 m_StatusBarMessage.setText(szMessage);
1200}
1201
1202void MainWindow::slotUpdateName()
1203{
1204 foreach (auto p, m_Operates)
1205 {
1206 m_pView->SetWidowsTitle(p->GetViewer(),
1207 p->Name(),
1208 p->Icon(),
1209 p->Description());
1210 }
1211}
1212
1213void MainWindow::slotUpdateName(const QString& szName)
1214{
1215 COperate* p = qobject_cast<COperate*>(sender());
1216 if(!p) return;
1217 m_pView->SetWidowsTitle(p->GetViewer(), szName,
1218 p->Icon(), p->Description());
1219 foreach(auto a, ui->menuActivity->actions()) {
1220 if(a->data().value<COperate*>() == p) {
1221 a->setText(szName);
1222 a->setIcon(p->Icon());
1223 break;
1224 }
1225 }
1226}
1227
1228QAction* MainWindow::GetStartAction(QMenu* pMenu, CPlugin *pPlug)
1229{
1230 QString szTitle;
1231 if(!pPlug->Protocol().isEmpty())
1232 szTitle = pPlug->Protocol() + ": ";
1233 szTitle += pPlug->DisplayName();
1234 QAction* p = pMenu->addAction(szTitle);
1235 p->setToolTip(pPlug->Description());
1236 p->setStatusTip(pPlug->Description());
1237 p->setData(pPlug->Id());
1238 p->setIcon(pPlug->Icon());
1239 return p;
1240}
1241
1242void MainWindow::slotStartByType()
1243{
1244 qDebug(log) << Q_FUNC_INFO;
1245 auto m = ui->menuStart->actions();
1246 foreach(auto a, m) {
1247 a->deleteLater();
1248 }
1249 foreach (auto a, m_MenuStartByType) {
1250 a->deleteLater();
1251 }
1252 ui->menuStart->clear();
1253 m_MenuStartByType.clear();
1254 m_Manager.EnumPlugins(this);
1255}
1256
1257int MainWindow::onProcess(const QString &id, CPlugin *pPlugin)
1258{
1259 Q_UNUSED(id);
1260 QMenu* m = ui->menuStart;
1261 if(m_Parameter.GetStartByType()) {
1262 auto it = m_MenuStartByType.find(pPlugin->Type());
1263 if(it == m_MenuStartByType.end()) {
1264 m = new QMenu(pPlugin->TypeName(pPlugin->Type()), ui->menuStart);
1265 m_MenuStartByType[pPlugin->Type()] = m;
1266 ui->menuStart->addMenu(m);
1267 } else
1268 m = *it;
1269 }
1270 // Start menu and toolbar
1271 QAction* p = GetStartAction(m, pPlugin);
1272 bool check = false;
1273 check = connect(p, SIGNAL(triggered()), this, SLOT(slotStart()));
1274 Q_ASSERT(check);
1275 return 0;
1276}
1277
1278void MainWindow::closeEvent(QCloseEvent *event)
1279{
1280 qDebug(log) << "MainWindow::closeEvent()";
1281
1282 if(m_Parameter.GetSaveMainWindowStatus())
1283 if(isFullScreen())
1284 on_actionFull_screen_F_triggered();
1285
1286 SaveOperateLasterClose();
1287
1288 foreach (auto it, m_Operates)
1289 {
1290 //TODO: Whether to save the setting
1291 emit it->sigUpdateParameters(it);
1292 it->Stop();
1293 }
1294
1295 QSettings set(RabbitCommon::CDir::Instance()->GetFileUserConfigure(),
1296 QSettings::IniFormat);
1297 if(m_Parameter.GetSaveMainWindowStatus())
1298 {
1299 set.setValue("MainWindow/Status/Geometry", saveGeometry());
1300 set.setValue("MainWindow/Status/State", saveState());
1301
1302 m_Parameter.SetTabBar(ui->actionTabBar_B->isChecked());
1303 m_Parameter.SetMenuBar(menuBar()->isVisible());
1304 m_Parameter.SetStatusBar(statusBar()->isVisible());
1305 } else {
1306 set.remove("MainWindow/Status/Geometry");
1307 set.remove("MainWindow/Status/State");
1308 }
1309
1310 m_Manager.SaveSettings();
1311 m_Parameter.Save();
1312
1313 QMainWindow::closeEvent(event);
1314
1315 //TODO: Wait for the background thread to exit
1316 QThread::sleep(1);
1317}
1318
1319int MainWindow::LoadOperateLasterClose()
1320{
1321 if(!m_Parameter.GetOpenLasterClose())
1322 return 0;
1323
1324 QFile f(RabbitCommon::CDir::Instance()->GetDirUserConfig()
1325 + QDir::separator() + "LasterClose.dat");
1326 if(f.open(QFile::ReadOnly))
1327 {
1328 QDataStream d(&f);
1329 while(1){
1330 QString szFile;
1331 d >> szFile;
1332 if(szFile.isEmpty())
1333 break;
1334 slotOpenFile(szFile);
1335 }
1336 f.close();
1337 }
1338 return 0;
1339}
1340
1341int MainWindow::SaveOperateLasterClose()
1342{
1343 QFile f(RabbitCommon::CDir::Instance()->GetDirUserConfig()
1344 + QDir::separator() + "LasterClose.dat");
1345 f.open(QFile::WriteOnly);
1346 if(m_Parameter.GetOpenLasterClose())
1347 {
1348 QDataStream d(&f);
1349 foreach(auto it, m_Operates)
1350 {
1351 d << it->GetSettingsFile();
1352 }
1353 }
1354 f.close();
1355 return 0;
1356}
1357
1358void MainWindow::on_actionTabBar_B_toggled(bool bShow)
1359{
1360 if(m_pView)
1361 {
1362 m_pView->SetVisibleTab(bShow);
1363 m_Parameter.SetTabBar(bShow);
1364 } else {
1365 if(m_pDockActive)
1366 m_pDockActive->setVisible(bShow);
1367 }
1368}
1369
1370void MainWindow::on_actionMain_menu_bar_M_toggled(bool checked)
1371{
1372 qDebug(log) << Q_FUNC_INFO << checked;
1373 if(ui->toolBar->isHidden() && !checked)
1374 {
1375 if( QMessageBox::StandardButton::Yes
1376 == QMessageBox::information(this, tr("Hide menu bar"),
1377 tr("The menu bar will be hidden, the tool bar must be showed."),
1378 QMessageBox::StandardButton::Yes
1379 | QMessageBox::StandardButton::No))
1380 {
1381 ui->actionToolBar_T->setChecked(true);
1382 if(m_pToolBarMenuAction)
1383 m_pToolBarMenuAction->setVisible(true);
1384 } else {
1385 ui->actionMain_menu_bar_M->setChecked(true);
1386#if !defined(Q_OS_ANDROID)
1387 if(m_pToolBarMenuAction)
1388 m_pToolBarMenuAction->setVisible(false);
1389#endif
1390 return;
1391 }
1392 }
1393
1394 menuBar()->setVisible(checked);
1395 m_Parameter.SetMenuBar(checked);
1396#if !defined(Q_OS_ANDROID)
1397 if(m_pToolBarMenuAction)
1398 m_pToolBarMenuAction->setVisible(!checked);
1399#endif
1400}
1401
1402void MainWindow::on_actionToolBar_T_toggled(bool checked)
1403{
1404 qDebug(log) << Q_FUNC_INFO << checked;
1405 if(menuBar()->isHidden() && !checked)
1406 {
1407 if( QMessageBox::StandardButton::Yes
1408 == QMessageBox::information(this, tr("Hide tool bar"),
1409 tr("The tool bar will be hidden, the menu bar must be showed."),
1410 QMessageBox::StandardButton::Yes
1411 | QMessageBox::StandardButton::No))
1412 {
1413 ui->actionMain_menu_bar_M->setChecked(true);
1414 } else {
1415 ui->actionToolBar_T->setChecked(true);
1416 return;
1417 }
1418 }
1419 ui->toolBar->setVisible(checked);
1420}
1421
1422void MainWindow::on_actionStatus_bar_S_toggled(bool checked)
1423{
1424 statusBar()->setVisible(checked);
1425 m_Parameter.SetStatusBar(checked);
1426}
1427
1428// [Get the widget that settings client parameters]
1429void MainWindow::on_actionSettings_triggered()
1430{
1431 CParameterDlgSettings set(&m_Parameter, m_Manager.GetSettingsWidgets(this), this);
1432 if(CParameterDlgSettings::Accepted == RC_SHOW_WINDOW(&set))
1433 {
1434 m_Manager.SaveSettings();
1435 m_Parameter.Save();
1436 }
1437}
1438// [Get the widget that settings client parameters]
1439
1440void MainWindow::slotShortCut()
1441{
1442 if(m_Parameter.GetReceiveShortCut())
1443 {
1444 setFocusPolicy(Qt::WheelFocus);
1445 ui->actionFull_screen_F->setShortcuts(QKeySequence::FullScreen);
1446 } else {
1447 setFocusPolicy(Qt::NoFocus);
1448 ui->actionFull_screen_F->setShortcut(QKeySequence());
1449 }
1450}
1451
1452void MainWindow::on_actionOpenListRecent_triggered()
1453{
1454 CFrmListRecent* p = new CFrmListRecent(this, &m_Manager, m_Parameter, false);
1455 if(!p) return;
1456 bool check = connect(p, SIGNAL(sigStart(const QString&, bool)),
1457 this, SLOT(slotOpenFile(const QString&, bool)));
1458 Q_ASSERT(check);
1459 check = connect(p, SIGNAL(sigAddToFavorite(QString,QString,QIcon,QString)),
1460 m_pFavoriteView, SLOT(slotAddToFavorite(QString,QString,QIcon,QString)));
1461 Q_ASSERT(check);
1462
1463 p->slotLoadFiles();
1464 QDialog d;
1465 d.resize(540, 400);
1466 d.setWindowIcon(windowIcon());
1467 d.setWindowTitle(p->windowTitle());
1468 QGridLayout* pLayout = new QGridLayout(&d);
1469 if(pLayout){
1470 pLayout->addWidget(p);
1471 check = connect(p, SIGNAL(destroyed()), &d, SLOT(reject()));
1472 d.setLayout(pLayout);
1473 }
1474 RC_SHOW_WINDOW(&d);
1475}
1476
1477void MainWindow::on_actionAdd_to_favorite_triggered()
1478{
1479 if(!m_pView || !m_pFavoriteView) return;
1480 QWidget* p = m_pView->GetCurrentView();
1481 foreach(auto c, m_Operates)
1482 {
1483 if(c->GetViewer() == p)
1484 {
1485 m_pFavoriteView->slotAddToFavorite(c->Name(), c->Description(),
1486 c->Icon(), c->GetSettingsFile());
1487 }
1488 }
1489}
1490
1491void MainWindow::dragEnterEvent(QDragEnterEvent *event)
1492{
1493 qDebug(log) << "dragEnterEvent";
1494
1495 if(event->mimeData()->hasUrls())
1496 {
1497 qWarning(log) << event->mimeData()->urls();
1498 event->acceptProposedAction();
1499 }
1500}
1501
1502void MainWindow::dragMoveEvent(QDragMoveEvent *event)
1503{
1504 //qDebug(log) << "dragMoveEvent";
1505}
1506
1507void MainWindow::dropEvent(QDropEvent *event)
1508{
1509 qDebug(log) << "dropEvent";
1510 if(!event->mimeData()->hasUrls())
1511 return;
1512 auto urls = event->mimeData()->urls();
1513 foreach(auto url, urls)
1514 {
1515 if(url.isLocalFile())
1516 slotOpenFile(url.toLocalFile());
1517 }
1518}
1519
1520void MainWindow::slotSystemTrayIconActivated(QSystemTrayIcon::ActivationReason reason)
1521{
1522 //qDebug(log) << "MainWindow::slotSystemTrayIconActivated";
1523
1524 Q_UNUSED(reason)
1525#if defined(Q_OS_ANDROID)
1526 showMaximized();
1527#else
1528 switch(reason)
1529 {
1530 case QSystemTrayIcon::Trigger:
1531 {
1532 showNormal();
1533 activateWindow();
1534 break;
1535 }
1536 default:
1537 break;
1538 }
1539#endif
1540}
1541
1542void MainWindow::slotSystemTrayIconTypeChanged()
1543{
1544 //qDebug(log) << "MainWindow::slotSystemTrayIconTypeChanged:" << m_Parameter.GetEnableSystemTrayIcon();
1545 if(!QSystemTrayIcon::isSystemTrayAvailable())
1546 {
1547 qWarning(log) << "System tray is not available";
1548 return;
1549 }
1550
1551 if(!m_Parameter.GetEnableSystemTrayIcon())
1552 {
1553 qDebug(log) << "Disable system tray icon";
1554 return;
1555 }
1556
1557 if(m_TrayIcon)
1558 m_TrayIcon.reset();
1559
1560 m_TrayIcon = QSharedPointer<QSystemTrayIcon>(new QSystemTrayIcon(this));
1561 if(QSystemTrayIcon::isSystemTrayAvailable())
1562 {
1563 bool check = connect(
1564 m_TrayIcon.data(),
1565 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1566 this,
1567 SLOT(slotSystemTrayIconActivated(QSystemTrayIcon::ActivationReason)));
1568 Q_ASSERT(check);
1569 m_TrayIcon->setIcon(this->windowIcon());
1570 m_TrayIcon->setToolTip(windowTitle());
1571 m_TrayIcon->show();
1572 } else
1573 qWarning(log) << "System tray is not available";
1574
1575 switch (m_Parameter.GetSystemTrayIconMenuType())
1576 {
1577 case CParameterApp::SystemTrayIconMenuType::MenuBar:
1578 {
1579 QMenu* pMenu = new QMenu(this);
1580 pMenu->addMenu(ui->menuOperate);
1581 pMenu->addMenu(ui->menuView);
1582 pMenu->addMenu(ui->menuTools);
1583 m_TrayIcon->setContextMenu(pMenu);
1584 break;
1585 }
1586 case CParameterApp::SystemTrayIconMenuType::Operate:
1587 m_TrayIcon->setContextMenu(ui->menuOperate);
1588 break;
1589 case CParameterApp::SystemTrayIconMenuType::RecentOpen:
1590 m_TrayIcon->setContextMenu(m_pRecentMenu);
1591 break;
1592 case CParameterApp::SystemTrayIconMenuType::View:
1593 m_TrayIcon->setContextMenu(ui->menuView);
1594 break;
1595 case CParameterApp::SystemTrayIconMenuType::Tools:
1596 m_TrayIcon->setContextMenu(ui->menuTools);
1597 break;
1598 case CParameterApp::SystemTrayIconMenuType::No:
1599 m_TrayIcon->setContextMenu(nullptr);
1600 break;
1601 }
1602}
1603
1604void MainWindow::slotEnableSystemTrayIcon()
1605{
1606 //qDebug(log) << "MainWindow::slotEnableSystemTryIcon()";
1607 if(m_TrayIcon)
1608 {
1609 if(!m_Parameter.GetEnableSystemTrayIcon())
1610 m_TrayIcon.reset();
1611 } else
1612 slotSystemTrayIconTypeChanged();
1613}
1614
1615void MainWindow::slotTimeOut()
1616{
1617 auto pWin = m_pView->GetCurrentView();
1618 if(!pWin) {
1619 qDebug(log) << "The current view is empty";
1620 return;
1621 }
1622 foreach(auto p, m_Operates)
1623 {
1624 if(p->GetViewer() == pWin)
1625 {
1626 auto pStats = p->GetStats();
1627 if(!pStats) {
1628 SetStatsVisible(false);
1629 break;
1630 }
1631 SetStatsVisible(true);
1632 pStats->slotCalculating();
1633 m_TotalSends.setText("⇈ " + pStats->TotalSends());
1634 m_TotalReceives.setText("⇊ " + pStats->TotalReceives());
1635 m_SendRate.setText("↑ " + pStats->SendRate());
1636 m_ReceivesRate.setText("↓ " + pStats->ReceiveRate());
1637 break;
1638 }
1639 }
1640}
1641
1642void MainWindow::SetStatsVisible(bool visible)
1643{
1644 if(m_SendRate.isVisible() == visible)
1645 return;
1646 m_SendRate.setVisible(visible);
1647 m_ReceivesRate.setVisible(visible);
1648 m_TotalSends.setVisible(visible);
1649 m_TotalReceives.setVisible(visible);
1650}
1651
1652void MainWindow::StartTimer()
1653{
1654 bool bStart = false;
1655 int nMinInterval = 60;
1656 foreach(auto o, m_Operates) {
1657 if(o && o->GetStats()) {
1658 nMinInterval = qMin(nMinInterval, o->GetStats()->GetInterval());
1659 bStart = true;
1660 }
1661 }
1662 if(bStart)
1663 m_Timer.start(nMinInterval * 1000);
1664 else
1665 m_Timer.stop();
1666}
1667
1668void MainWindow::on_actionUser_manual_triggered()
1669{
1670 QString szUrl = "https://github.com/KangLin/RabbitRemoteControl/wiki/UserManual";
1671 if(RabbitCommon::CTools::GetLanguage() == "zh_CN"
1672 || RabbitCommon::CTools::GetLanguage() == "zh_TW")
1673 szUrl += "_zh_CN";
1674}
1675
1676void MainWindow::on_actionLayoutDefault_triggered()
1677{
1678 qDebug(log) << Q_FUNC_INFO;
1679 if(!m_pDockActive->toggleViewAction()->isChecked())
1680 m_pDockActive->toggleViewAction()->trigger();
1681 if(!m_pDockFavorite->toggleViewAction()->isChecked())
1682 m_pDockFavorite->toggleViewAction()->trigger();
1683 if(!m_pDockListRecent->toggleViewAction()->isChecked())
1684 m_pDockListRecent->toggleViewAction()->trigger();
1685 m_Parameter.SetTabPosition(QTabWidget::North);
1686 if(!ui->actionTabBar_B->isChecked())
1687 ui->actionTabBar_B->trigger();
1688 if(!ui->actionMain_menu_bar_M->isChecked()) {
1689 ui->actionMain_menu_bar_M->trigger();
1690#if !defined(Q_OS_ANDROID)
1691 m_pToolBarMenuAction->setVisible(false);
1692#endif
1693 }
1694 if(!ui->actionToolBar_T->isChecked())
1695 ui->actionToolBar_T->trigger();
1696 addToolBar(Qt::TopToolBarArea, ui->toolBar);
1697 if(!ui->actionStatus_bar_S->isChecked())
1698 ui->actionStatus_bar_S->trigger();
1699}
1700
1701void MainWindow::on_actionLayoutSimple_triggered()
1702{
1703 qDebug(log) << Q_FUNC_INFO;
1704 if(m_pDockActive->toggleViewAction()->isChecked())
1705 m_pDockActive->toggleViewAction()->trigger();
1706 if(m_pDockFavorite->toggleViewAction()->isChecked())
1707 m_pDockFavorite->toggleViewAction()->trigger();
1708 if(m_pDockListRecent->toggleViewAction()->isChecked())
1709 m_pDockListRecent->toggleViewAction()->trigger();
1710 m_Parameter.SetTabPosition(QTabWidget::East);
1711 if(!ui->actionTabBar_B->isChecked())
1712 ui->actionTabBar_B->trigger();
1713 if(!ui->actionMain_menu_bar_M->isChecked()) {
1714 ui->actionMain_menu_bar_M->trigger();
1715#if !defined(Q_OS_ANDROID)
1716 m_pToolBarMenuAction->setVisible(false);
1717#endif
1718 }
1719 if(!ui->actionToolBar_T->isChecked())
1720 ui->actionToolBar_T->trigger();
1721 addToolBar(Qt::LeftToolBarArea, ui->toolBar);
1722 if(!ui->actionStatus_bar_S->isChecked())
1723 ui->actionStatus_bar_S->trigger();
1724}
1725
1726void MainWindow::on_actionLayoutMinimalism_triggered()
1727{
1728 qDebug(log) << Q_FUNC_INFO;
1729 if(m_pDockActive->toggleViewAction()->isChecked())
1730 m_pDockActive->toggleViewAction()->trigger();
1731 if(m_pDockFavorite->toggleViewAction()->isChecked())
1732 m_pDockFavorite->toggleViewAction()->trigger();
1733 if(m_pDockListRecent->toggleViewAction()->isChecked())
1734 m_pDockListRecent->toggleViewAction()->trigger();
1735 m_Parameter.SetTabPosition(QTabWidget::East);
1736 if(ui->actionTabBar_B->isChecked())
1737 ui->actionTabBar_B->trigger();
1738#if !defined(Q_OS_MACOS)
1739 if(ui->actionMain_menu_bar_M->isChecked()) {
1740 ui->actionMain_menu_bar_M->trigger();
1741 m_pToolBarMenuAction->setVisible(true);
1742 }
1743#endif
1744 if(!ui->actionToolBar_T->isChecked())
1745 ui->actionToolBar_T->trigger();
1746#if defined(Q_OS_LINUX)
1747 addToolBar(Qt::RightToolBarArea, ui->toolBar);
1748#else
1749 addToolBar(Qt::LeftToolBarArea, ui->toolBar);
1750#endif
1751 if(ui->actionStatus_bar_S->isChecked())
1752 ui->actionStatus_bar_S->trigger();
1753}
列出存在的连接配置
static CICE * Instance()
Single instance
Definition Ice.cpp:55
virtual QList< QWidget * > GetSettingsWidgets(QWidget *parent)
得到设置参数窗口
Definition Manager.cpp:451
virtual int EnumPlugins(Handle *handle)
Enum plugins
Definition Manager.cpp:482
virtual COperate * CreateOperate(const QString &id)
新建 COperate 指针,所有者是调用者。 当不在使用时,调用者必调用 DeteleOperate() 须释放指针。 调用者必须连接信号 COperate::sigFinished 。 释放指针 (...
Definition Manager.cpp:275
virtual COperate * LoadOperate(const QString &szFile)
从文件中新建 COperate 指针,所有者是调用者。 当不再使用时,调用者必须负责调用 DeleteOperate() 删除此指针。 调用者必须连接信号 COperate::sigFinished 。...
Definition Manager.cpp:336
virtual int DeleteOperate(COperate *p)
Delete COperate
Definition Manager.cpp:303
virtual int SaveOperate(COperate *pOperate)
保存连接参数到文件
Definition Manager.cpp:375
virtual int SaveSettings(const QString szFile=QString())
保存客户端参数到文件
Definition Manager.cpp:437
操作接口。
Definition Operate.h:51
virtual int OpenDialogSettings(QWidget *parent=nullptr)
打开设置对话框
Definition Operate.cpp:87
virtual const QIcon Icon() const
Icon
Definition Operate.cpp:82
virtual int Start()=0
开始
void sigFullScreen(bool bFullScreen)
全屏。由操作触发
virtual QWidget * GetViewer()=0
得到显示视图
virtual const QString Name()
Name
Definition Operate.cpp:41
virtual int Stop()=0
关闭
virtual const QString Description()
Description
Definition Operate.cpp:46
void sigUpdateParameters(COperate *pOperate)
更新参数,通知应用程序保存或显示参数
virtual QMenu * GetMenu(QWidget *parent=nullptr)
Get menu
Definition Operate.cpp:107
virtual int Save(QString szFile=QString(), bool bForce=true)
Save to file
Definition Parameter.cpp:47
插件接口
Definition Plugin.h:15
virtual const QString Id()
标识。默认: Type() + ":" + Protocol() + ":" + Name()
Definition Plugin.cpp:68
virtual const QString DisplayName() const
在界面上显示的名称
Definition Plugin.cpp:73
virtual const QString Protocol() const =0
协议
virtual const QString Description() const =0
描述
int GetInterval()
Get interval.
Definition Stats.cpp:78
The split view class
The CViewTable class
Definition ViewTable.h:16
The CView class
Definition View.h:25
virtual int AddView(QWidget *pView)=0
virtual QWidget * GetCurrentView()=0
virtual int RemoveView(QWidget *pView)=0
The MainWindow class
Definition mainwindow.h:35
int Start(COperate *pOperate, bool set, QString szFile=QString())
Start
virtual int onProcess(const QString &id, CPlugin *pPlugin) override
Process plugins
void slotInitial()
For time-consuming operations
void slotInformation(const QString &szInfo)
显示信息。暂时在状态栏显示。
virtual void slotShowMessageBox(const QString &title, const QString &message, const QMessageBox::Icon &icon)
用消息对话框(QMessageBox)显示信息
void slotRunning()
[MainWindow slotRunning]
void slotCloseView(const QWidget *pView)
[MainWindow slotRunning]
void slotCustomContextMenuRequested(const QPoint &pos)
MainWindow::slotCustomContextMenuRequested