/** \file SystrayIcon.cpp \brief Define the class of the systray icon \author alpha_one_x86 \licence GPL3, see the file COPYING */ #include #include #include #include "SystrayIcon.h" #include "PluginsManager.h" #include "ThemesManager.h" #include "LanguagesManager.h" #include "HelpDialog.h" #include "ProductKey.h" #ifdef Q_OS_MAC //extern void qt_mac_set_dock_menu(QMenu *menu); #endif /// \brief Initiate and show the icon in the systray SystrayIcon::SystrayIcon(QObject * parent) : QSystemTrayIcon(parent) { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start"); //setup the systray icon haveListenerInfo = false; havePluginLoaderInfo = false; systrayMenu = new QMenu(); actionMenuAbout = new QAction(this); #ifdef ULTRACOPIER_DEBUG actionSaveBugReport = new QAction(this); #endif actionMenuQuit = new QAction(this); actionOptions = new QAction(this); actionProductKey = new QAction(this); //actionTransfer = new QAction(this); #ifdef TREEMENU copyMenu = NULL; #endif //to prevent init bug stateListener=Ultracopier::NotListening; statePluginLoader=Ultracopier::Uncaught; setContextMenu(systrayMenu); #ifdef ULTRACOPIER_MODE_SUPERCOPIER setToolTip(QStringLiteral("Supercopier")); #else setToolTip(QStringLiteral("Ultracopier")); #endif #ifdef Q_OS_WIN32 setIcon(QIcon(QStringLiteral(":/systray_Uncaught_Windows.png"))); #else setIcon(QIcon(QStringLiteral(":/systray_Uncaught_Unix.png"))); #endif //connect the action connect(&timerCheckSetTooltip, &QTimer::timeout, this, &SystrayIcon::checkSetTooltip); #ifdef ULTRACOPIER_DEBUG connect(actionSaveBugReport, &QAction::triggered, this, &SystrayIcon::saveBugReport); #endif connect(actionMenuQuit, &QAction::triggered, this, &SystrayIcon::hide); connect(actionMenuQuit, &QAction::triggered, this, &SystrayIcon::quit); connect(actionMenuAbout, &QAction::triggered, this, &SystrayIcon::showHelp); connect(actionOptions, &QAction::triggered, this, &SystrayIcon::showOptions); connect(actionProductKey, &QAction::triggered, this, &SystrayIcon::showProductKey); connect(this, &SystrayIcon::activated, this, &SystrayIcon::CatchAction); #ifdef ULTRACOPIER_INTERNET_SUPPORT connect(this, &QSystemTrayIcon::messageClicked, this, &SystrayIcon::messageClicked); #endif connect(PluginsManager::pluginsManager, &PluginsManager::pluginListingIsfinish, this, &SystrayIcon::reloadEngineList); //display the icon updateCurrentTheme(); //if theme/language change, update graphic part connect(ThemesManager::themesManager, &ThemesManager::theThemeIsReloaded, this, &SystrayIcon::updateCurrentTheme, Qt::QueuedConnection); connect(LanguagesManager::languagesManager, &LanguagesManager::newLanguageLoaded, this, &SystrayIcon::retranslateTheUI, Qt::QueuedConnection); systrayMenu->addAction(actionOptions); systrayMenu->addAction(actionMenuAbout); #ifdef ULTRACOPIER_DEBUG systrayMenu->addAction(actionSaveBugReport); #endif if(!FacilityEngine::facilityEngine.ultimateUrl().empty()) systrayMenu->addAction(actionProductKey); systrayMenu->addAction(actionMenuQuit); #ifndef Q_OS_MAC systrayMenu->insertSeparator(actionOptions); #endif retranslateTheUI(); updateSystrayIcon(); #ifdef ULTRACOPIER_INTERNET_SUPPORT lastVersion=FacilityEngine::version(); #endif timerCheckSetTooltip.setSingleShot(true); timerCheckSetTooltip.start(1000); //impossible with Qt on systray /// \note important for drag and drop, \see dropEvent() systrayMenu->setAcceptDrops(true); #ifdef Q_OS_MAC // qt_mac_set_dock_menu(systrayMenu); #endif show(); } /// \brief Hide and destroy the icon in the systray SystrayIcon::~SystrayIcon() { delete actionMenuQuit; #ifdef ULTRACOPIER_DEBUG delete actionSaveBugReport; #endif delete actionMenuAbout; delete actionOptions; delete actionProductKey; delete systrayMenu; #ifdef TREEMENU if(copyMenu!=NULL) { delete copyMenu; copyMenu=NULL; } #endif } void SystrayIcon::checkSetTooltip() { if(isSystemTrayAvailable()) { #ifdef ULTRACOPIER_MODE_SUPERCOPIER setToolTip(QStringLiteral("Supercopier")); #else setToolTip(QStringLiteral("Ultracopier")); #endif updateSystrayIcon(); } else timerCheckSetTooltip.start(); } void SystrayIcon::listenerReady(const Ultracopier::ListeningState &state,const bool &havePlugin,const bool &someAreInWaitOfReply) { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"state: "+std::to_string((int)state)+", havePlugin: "+std::to_string((int)havePlugin)+", someAreInWaitOfReply: "+std::to_string((int)someAreInWaitOfReply)); Q_UNUSED(someAreInWaitOfReply); stateListener=state; haveListenerInfo=true; haveListener=havePlugin; updateSystrayIcon(); if(!havePlugin) showTryCatchMessageWithNoListener(); } void SystrayIcon::pluginLoaderReady(const Ultracopier::CatchState &state,const bool &havePlugin,const bool &someAreInWaitOfReply) { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"state: "+std::to_string((int)state)+", havePlugin: "+std::to_string((int)havePlugin)+", someAreInWaitOfReply: "+std::to_string((int)someAreInWaitOfReply)); Q_UNUSED(someAreInWaitOfReply); statePluginLoader=state; havePluginLoaderInfo=true; havePluginLoader=havePlugin; updateSystrayIcon(); } void SystrayIcon::showTryCatchMessageWithNoListener() { showSystrayMessage(tr("No copy listener found. Do the copy manually by right click one the system tray icon.").toStdString()); } /// \brief To show a message linked to the systray icon void SystrayIcon::showSystrayMessage(const std::string& text) { showMessage(tr("Information"),QString::fromStdString(text),QSystemTrayIcon::Information,0); } #ifdef ULTRACOPIER_INTERNET_SUPPORT void SystrayIcon::messageClicked() { if(!QDesktopServices::openUrl(QString::fromStdString(HelpDialog::getUpdateUrl()))) ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"start, haveListenerInfo "+std::to_string((int)haveListenerInfo)+", havePluginLoaderInfo: "+std::to_string((int)havePluginLoaderInfo)); } #endif /// \brief To update the systray icon void SystrayIcon::updateSystrayIcon() { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start, haveListenerInfo "+std::to_string((int)haveListenerInfo)+", havePluginLoaderInfo: "+std::to_string((int)havePluginLoaderInfo)); std::string toolTip="???"; std::string icon; if(!haveListenerInfo || !havePluginLoaderInfo) { toolTip=tr("Searching information...").toStdString(); icon="Uncaught"; } else { Ultracopier::ListeningState stateListener=this->stateListener; Ultracopier::CatchState statePluginLoader=this->statePluginLoader; if(!haveListener) stateListener=Ultracopier::NotListening; if((stateListener==Ultracopier::NotListening && statePluginLoader==Ultracopier::Uncaught) || (stateListener==Ultracopier::SemiListening && statePluginLoader==Ultracopier::Semiuncaught) || (stateListener==Ultracopier::FullListening && statePluginLoader==Ultracopier::Caught)) { if(stateListener==Ultracopier::NotListening) { toolTip=tr("Do not replace the explorer copy/move").toStdString(); icon="Uncaught"; } else if(stateListener==Ultracopier::SemiListening) { toolTip=tr("Semi replace the explorer copy/move").toStdString(); icon="Semiuncaught"; } else { toolTip=tr("Replace the explorer copy/move").toStdString(); icon="Caught"; } } else { icon="Semiuncaught"; std::string first_part; std::string second_part; if(stateListener==Ultracopier::NotListening) first_part="No listening"; else if(stateListener==Ultracopier::SemiListening) first_part="Semi listening"; else if(stateListener==Ultracopier::FullListening) first_part="Full listening"; else first_part="Unknow listening"; if(statePluginLoader==Ultracopier::Uncaught) second_part="No replace"; else if(statePluginLoader==Ultracopier::Semiuncaught) second_part="Semi replace"; else if(statePluginLoader==Ultracopier::Caught) second_part="Full replace"; else second_part="Unknow replace"; toolTip=first_part+"/"+second_part; } } QIcon theNewSystrayIcon; #ifdef Q_OS_WIN32 theNewSystrayIcon=ThemesManager::themesManager->loadIcon("SystemTrayIcon/systray_"+icon+"_Windows.png"); #else theNewSystrayIcon=ThemesManager::themesManager->loadIcon("SystemTrayIcon/systray_"+icon+"_Unix.png"); #endif if(theNewSystrayIcon.isNull()) { #ifdef Q_OS_WIN32 ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"use the default systray icon: :/systray_"+icon+"_Windows.png"); theNewSystrayIcon=QIcon(QString::fromStdString(":/systray_"+icon+"_Windows.png")); #else ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"use the default systray icon: :/systray_"+icon+"_Unix.png"); theNewSystrayIcon=QIcon(QString::fromStdString(":/systray_"+icon+"_Unix.png")); #endif } else { #ifdef Q_OS_WIN32 ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"icon: systray_"+icon+"_Windows.png"); #else ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"icon: systray_"+icon+"_Unix.png"); #endif } if(theNewSystrayIcon.isNull()) { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"All the icon include the default icon remain null"); } else setIcon(theNewSystrayIcon); #ifdef ULTRACOPIER_MODE_SUPERCOPIER setToolTip(QString::fromStdString("Supercopier - "+toolTip)); #else setToolTip(QString::fromStdString("Ultracopier - "+toolTip)); #endif } /* drag event processing (impossible with Qt on systray) need setAcceptDrops(true); into the constructor need implementation to accept the drop: void dragEnterEvent(QDragEnterEvent* event); void dragMoveEvent(QDragMoveEvent* event); void dragLeaveEvent(QDragLeaveEvent* event); */ void SystrayIcon::dropEvent(QDropEvent *event) { const QMimeData* mimeData = event->mimeData(); if(mimeData->hasUrls()) { //impossible with Qt on systray ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"mimeData->urls().size()"+std::to_string(mimeData->urls().size())); std::vector urls; unsigned int index=0; while(index<(unsigned int)mimeData->urls().size()) { urls.push_back(mimeData->urls().at(static_cast(index)).toString().toStdString()); index++; } emit urlDropped(urls); event->acceptProposedAction(); } } void SystrayIcon::dragEnterEvent(QDragEnterEvent* event) { // if some actions should not be usable, like move, this code must be adopted event->acceptProposedAction(); } void SystrayIcon::dragMoveEvent(QDragMoveEvent* event) { // if some actions should not be usable, like move, this code must be adopted event->acceptProposedAction(); } void SystrayIcon::dragLeaveEvent(QDragLeaveEvent* event) { event->accept(); } /// \brief To update the current themes void SystrayIcon::updateCurrentTheme() { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"icon: start"); //load the systray menu item QIcon tempIcon; tempIcon=ThemesManager::themesManager->loadIcon("SystemTrayIcon/exit.png"); if(!tempIcon.isNull()) IconQuit=QIcon(tempIcon); else IconQuit=QIcon(""); actionMenuQuit->setIcon(IconQuit); #ifdef ULTRACOPIER_DEBUG actionSaveBugReport->setIcon(QIcon(":/warning.png")); #endif tempIcon=ThemesManager::themesManager->loadIcon("SystemTrayIcon/informations.png"); if(!tempIcon.isNull()) IconInfo=QIcon(tempIcon); else IconInfo=QIcon(""); actionMenuAbout->setIcon(IconInfo); tempIcon=ThemesManager::themesManager->loadIcon("SystemTrayIcon/options.png"); if(!tempIcon.isNull()) IconOptions=QIcon(tempIcon); else IconOptions=QIcon(""); actionOptions->setIcon(IconOptions); actionProductKey->setIcon(IconInfo); tempIcon=ThemesManager::themesManager->loadIcon("SystemTrayIcon/add.png"); if(!tempIcon.isNull()) IconAdd=QIcon(tempIcon); else IconAdd=QIcon(""); //update the systray icon updateSystrayIcon(); reloadEngineList(); } /* \brief For catch an action on the systray icon \param reason Why it activated */ void SystrayIcon::CatchAction(QSystemTrayIcon::ActivationReason reason) { if(reason==QSystemTrayIcon::DoubleClick || reason==QSystemTrayIcon::Trigger) { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"Double click on system tray icon"); if(stateListener!=Ultracopier::NotListening) emit tryUncatchCopy(); else { if(!haveListener) { showTryCatchMessageWithNoListener(); return; } emit tryCatchCopy(); } } else if(reason==QSystemTrayIcon::Context)//do nothing on right click to show as auto the menu {}//ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"The action on the systray icon is unknown: "+std::to_string((int)reason)); else { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"The action on the systray icon is unknown: "+std::to_string((int)reason)); QMessageBox::warning(NULL,tr("Warning"),tr("The action on the systray icon is unknown!")); } } /// \brief To catch copy menu action void SystrayIcon::CatchCopyQuery() { QAction * currentAction=qobject_cast(QObject::sender()); if(currentAction==NULL) { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"action not found"); return; } ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start: "+currentAction->data().toString().toStdString()); emit addWindowCopyMove(Ultracopier::Copy,currentAction->data().toString().toStdString()); } /// \brief To catch move menu action void SystrayIcon::CatchMoveQuery() { QAction * currentAction=qobject_cast(QObject::sender()); if(currentAction==NULL) { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"action not found"); return; } ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start: "+currentAction->data().toString().toStdString()); emit addWindowCopyMove(Ultracopier::Move,currentAction->data().toString().toStdString()); } /// \brief To catch transfer menu action void SystrayIcon::CatchTransferQuery() { QAction * currentAction=qobject_cast(QObject::sender()); if(currentAction==NULL) { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"action not found"); return; } ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start: "+currentAction->data().toString().toStdString()); emit addWindowTransfer(currentAction->data().toString().toStdString()); } /// \brief to retranslate the ui void SystrayIcon::retranslateTheUI() { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"retranslateTheUI"); #ifdef ULTRACOPIER_DEBUG actionMenuAbout ->setText(tr("&About/Debug report")); #else // ULTRACOPIER_DEBUG actionMenuAbout ->setText(tr("&About")); #endif // ULTRACOPIER_DEBUG #ifdef ULTRACOPIER_DEBUG actionSaveBugReport->setText(tr("&Save bug report")); #endif actionMenuQuit ->setText(tr("&Quit")); actionOptions ->setText(tr("&Options")); actionProductKey ->setText(tr("&Register product key")); reloadEngineList(); updateSystrayIcon(); } void SystrayIcon::addCopyEngine(const std::string &name,const bool &canDoOnlyCopy) { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start"); EngineEntry entry; entry.name=name; entry.canDoOnlyCopy=canDoOnlyCopy; engineEntryList.push_back(entry); if(PluginsManager::pluginsManager->allPluginHaveBeenLoaded()) reloadEngineList(); } void SystrayIcon::removeCopyEngine(const std::string &name) { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start"); unsigned int index=0; while(indexsetData(name); #ifdef TREEMENU copyMenu->addAction(copy); #else actions.push_back(copy); systrayMenu->insertAction(actionOptions, copy); #endif } void SystrayIcon::reloadEngineList() { ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start"); #ifdef TREEMENU if(copyMenu!=NULL) { delete copyMenu; copyMenu=NULL; } copyMenu=new QMenu(); copyMenu ->setTitle(tr("A&dd copy/moving")); copyMenu->setIcon(IconAdd); systrayMenu->insertMenu(actionOptions,copyMenu); copyMenu->setEnabled(true); if(engineEntryList.size()==0) { copyMenu->setEnabled(false); return; } #else { for(unsigned int index=0; indexaddMenu(menu); #endif } setContextMenu(systrayMenu); } void SystrayIcon::changeToUltimate() { systrayMenu->removeAction(actionProductKey); }