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