/** \file CopyListener.h
\brief Define the copy listener
\author alpha_one_x86
\licence GPL3, see the file COPYING */
#include "CopyListener.h"
#include "LanguagesManager.h"
#include "cpp11addition.h"
#ifdef ULTRACOPIER_PLUGIN_ALL_IN_ONE_DIRECT
#include "plugins/Listener/catchcopy-v0002/listener.h"
#endif
#include <QRegularExpression>
#include <QMessageBox>
CopyListener::CopyListener(OptionDialog *optionDialog)
{
nextOrderId=1;
stopIt=false;
this->optionDialog=optionDialog;
pluginLoader=new PluginLoaderCore(optionDialog);
//load the options
tryListen=false;
PluginsManager::pluginsManager->lockPluginListEdition();
std::vector<PluginsAvailable> list=PluginsManager::pluginsManager->getPluginsByCategory(PluginType_Listener);
connect(this,&CopyListener::previouslyPluginAdded, this,&CopyListener::onePluginAdded,Qt::QueuedConnection);
connect(PluginsManager::pluginsManager,&PluginsManager::onePluginAdded, this,&CopyListener::onePluginAdded,Qt::QueuedConnection);
#ifndef ULTRACOPIER_PLUGIN_ALL_IN_ONE
connect(PluginsManager::pluginsManager,&PluginsManager::onePluginWillBeRemoved, this,&CopyListener::onePluginWillBeRemoved,Qt::DirectConnection);
#endif
connect(PluginsManager::pluginsManager,&PluginsManager::pluginListingIsfinish, this,&CopyListener::allPluginIsloaded,Qt::QueuedConnection);
connect(pluginLoader,&PluginLoaderCore::pluginLoaderReady, this,&CopyListener::pluginLoaderReady);
foreach(PluginsAvailable currentPlugin,list)
emit previouslyPluginAdded(currentPlugin);
PluginsManager::pluginsManager->unlockPluginListEdition();
last_state=Ultracopier::NotListening;
last_have_plugin=false;
last_inWaitOfReply=false;
stripSeparatorRegex=std::regex("[\\\\/]+$");
}
CopyListener::~CopyListener()
{
stopIt=true;
if(pluginLoader!=NULL)
{
delete pluginLoader;
pluginLoader=NULL;
}
}
void CopyListener::resendState()
{
if(PluginsManager::pluginsManager->allPluginHaveBeenLoaded())
{
sendState(true);
if(pluginLoader!=NULL)
pluginLoader->resendState();
}
}
void CopyListener::onePluginAdded(const PluginsAvailable &plugin)
{
if(plugin.category!=PluginType_Listener)
return;
PluginListener newPluginListener;
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"try load: "+plugin.path+PluginsManager::getResolvedPluginName("listener"));
//setFileName
#ifdef ULTRACOPIER_PLUGIN_ALL_IN_ONE
PluginInterface_Listener *listen;
#ifndef ULTRACOPIER_PLUGIN_ALL_IN_ONE_DIRECT
QObjectList objectList=QPluginLoader::staticInstances();
int index=0;
QObject *pluginObject;
while(index<objectList.size())
{
pluginObject=objectList.at(index);
listen = qobject_cast<PluginInterface_Listener *>(pluginObject);
if(listen!=NULL)
break;
index++;
}
if(index==objectList.size())
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"static listener not found");
return;
}
#else
listen=new Listener();
#endif
#ifndef ULTRACOPIER_PLUGIN_ALL_IN_ONE_DIRECT
newPluginListener.pluginLoader=NULL;
#endif
#else
QPluginLoader *pluginOfPluginLoader=new QPluginLoader(QString::fromStdString(plugin.path+PluginsManager::getResolvedPluginName("listener")));
QObject *pluginInstance = pluginOfPluginLoader->instance();
if(!pluginInstance)
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"unable to load the plugin: "+pluginOfPluginLoader->errorString().toStdString());
return;
}
PluginInterface_Listener *listen = qobject_cast<PluginInterface_Listener *>(pluginInstance);
if(!listen)
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"unable to load the plugin: "+pluginOfPluginLoader->errorString().toStdString());
return;
}
//check if found
unsigned int index=0;
while(index<pluginList.size())
{
if(pluginList.at(index).listenInterface==listen)
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"Plugin already found "+pluginList.at(index).path+" for "+plugin.path);
pluginOfPluginLoader->unload();
return;
}
index++;
}
newPluginListener.pluginLoader = pluginOfPluginLoader;
#endif
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"Plugin correctly loaded");
#ifdef ULTRACOPIER_DEBUG
connect(listen,&PluginInterface_Listener::debugInformation,this,&CopyListener::debugInformation,Qt::DirectConnection);
#endif // ULTRACOPIER_DEBUG
connect(listen,&PluginInterface_Listener::error, this,&CopyListener::error,Qt::DirectConnection);
connect(listen,&PluginInterface_Listener::newCopyWithoutDestination, this,&CopyListener::newPluginCopyWithoutDestination,Qt::DirectConnection);
connect(listen,&PluginInterface_Listener::newCopy, this,&CopyListener::newPluginCopy,Qt::DirectConnection);
connect(listen,&PluginInterface_Listener::newMoveWithoutDestination, this,&CopyListener::newPluginMoveWithoutDestination,Qt::DirectConnection);
connect(listen,&PluginInterface_Listener::newMove, this,&CopyListener::newPluginMove,Qt::DirectConnection);
connect(listen,&PluginInterface_Listener::newClientList, this,&CopyListener::reloadClientList,Qt::DirectConnection);
newPluginListener.listenInterface = listen;
newPluginListener.path = plugin.path+PluginsManager::getResolvedPluginName("listener");
newPluginListener.state = Ultracopier::NotListening;
newPluginListener.inWaitOfReply = false;
newPluginListener.options=new LocalPluginOptions("Listener-"+plugin.name);
newPluginListener.listenInterface->setResources(newPluginListener.options,plugin.writablePath,plugin.path,ULTRACOPIER_VERSION_PORTABLE_BOOL);
optionDialog->addPluginOptionWidget(PluginType_Listener,plugin.name,newPluginListener.listenInterface->options());
connect(LanguagesManager::languagesManager,&LanguagesManager::newLanguageLoaded,newPluginListener.listenInterface,&PluginInterface_Listener::newLanguageLoaded,Qt::DirectConnection);
pluginList.push_back(newPluginListener);
connect(pluginList.back().listenInterface,&PluginInterface_Listener::newState,this,&CopyListener::newState,Qt::DirectConnection);
if(tryListen)
{
pluginList.back().inWaitOfReply=true;
listen->listen();
}
}
#ifdef ULTRACOPIER_DEBUG
void CopyListener::debugInformation(const Ultracopier::DebugLevel &level, const std::string& fonction, const std::string& text, const std::string& file, const int& ligne)
{
DebugEngine::addDebugInformationStatic(level,fonction,text,file,ligne,"Listener plugin");
}
#endif // ULTRACOPIER_DEBUG
void CopyListener::error(const std::string &error)
{
QMessageBox::critical(NULL,tr("Error"),tr("Error during the reception of the copy/move list\n%1").arg(QString::fromStdString(error)));
}
bool CopyListener::oneListenerIsLoaded()
{
return (pluginList.size()>0);
}
#ifndef ULTRACOPIER_PLUGIN_ALL_IN_ONE
void CopyListener::onePluginWillBeRemoved(const PluginsAvailable &plugin)
{
if(plugin.category!=PluginType_Listener)
return;
unsigned int indexPlugin=0;
while(indexPlugin<pluginList.size())
{
if((plugin.path+PluginsManager::getResolvedPluginName("listener"))==pluginList.at(indexPlugin).path)
{
unsigned int index=0;
while(index<copyRunningList.size())
{
if(copyRunningList.at(index).listenInterface==pluginList.at(indexPlugin).listenInterface)
copyRunningList[index].listenInterface=NULL;
index++;
}
if(pluginList.at(indexPlugin).listenInterface!=NULL)
{
pluginList.at(indexPlugin).listenInterface->close();
delete pluginList.at(indexPlugin).listenInterface;
}
if(pluginList.at(indexPlugin).pluginLoader!=NULL)
{
pluginList.at(indexPlugin).pluginLoader->unload();
delete pluginList.at(indexPlugin).options;
}
pluginList.erase(pluginList.cbegin()+indexPlugin);
sendState();
return;
}
indexPlugin++;
}
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"not found");
}
#endif
void CopyListener::newState(const Ultracopier::ListeningState &state)
{
if(stopIt)
return;
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
PluginInterface_Listener *temp=qobject_cast<PluginInterface_Listener *>(QObject::sender());
if(temp==NULL)
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"listener not located!");
return;
}
unsigned int index=0;
while(index<pluginList.size())
{
if(temp==pluginList.at(index).listenInterface)
{
pluginList[index].state=state;
pluginList[index].inWaitOfReply=false;
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"new state for the plugin "+std::to_string(index)+": "+std::to_string((int)state));
sendState(true);
return;
}
index++;
}
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"listener not found!");
}
void CopyListener::listen()
{
tryListen=true;
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
unsigned int index=0;
while(index<pluginList.size())
{
pluginList[index].inWaitOfReply=true;
pluginList.at(index).listenInterface->listen();
index++;
}
if(pluginLoader!=NULL)
pluginLoader->load();
}
void CopyListener::close()
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
tryListen=false;
if(pluginLoader!=NULL)
pluginLoader->unload();
unsigned int index=0;
while(index<pluginList.size())
{
pluginList[index].inWaitOfReply=true;
pluginList.at(index).listenInterface->close();
index++;
}
copyRunningList.clear();
}
std::vector<std::string> CopyListener::stripSeparator(std::vector<std::string> sources)
{
unsigned int index=0;
while(index<sources.size())
{
std::regex_replace(sources[index],stripSeparatorRegex,"");
index++;
}
return sources;
}
/** new copy without destination have been pased by the CLI */
void CopyListener::copyWithoutDestination(std::vector<std::string> sources)
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
std::vector<std::string> list;
list.push_back("file");
emit newCopyWithoutDestination(incrementOrderId(),list,stripSeparator(sources));
}
/** new copy with destination have been pased by the CLI */
void CopyListener::copy(std::vector<std::string> sources,std::string destination)
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
std::vector<std::string> list;
list.push_back("file");
emit newCopy(incrementOrderId(),list,stripSeparator(sources),"file",destination);
}
/** new move without destination have been pased by the CLI */
void CopyListener::moveWithoutDestination(std::vector<std::string> sources)
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
std::vector<std::string> list;
list.push_back("file");
emit newMoveWithoutDestination(incrementOrderId(),list,stripSeparator(sources));
}
/** new move with destination have been pased by the CLI */
void CopyListener::move(std::vector<std::string> sources,std::string destination)
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
std::vector<std::string> list;
list.push_back("file");
emit newMove(incrementOrderId(),list,stripSeparator(sources),"file",destination);
}
void CopyListener::copyFinished(const quint32 & orderId,const bool &withError)
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
unsigned int index=0;
while(index<copyRunningList.size())
{
if(orderId==copyRunningList.at(index).orderId)
{
vectorRemoveAll(orderList,orderId);
if(copyRunningList.at(index).listenInterface!=NULL)
copyRunningList.at(index).listenInterface->transferFinished(copyRunningList.at(index).pluginOrderId,withError);
copyRunningList.erase(copyRunningList.cbegin()+index);
return;
}
index++;
}
}
void CopyListener::copyCanceled(const uint32_t & orderId)
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
unsigned int index=0;
while(index<copyRunningList.size())
{
if(orderId==copyRunningList.at(index).orderId)
{
vectorRemoveAll(orderList,orderId);
if(copyRunningList.at(index).listenInterface!=NULL)
copyRunningList.at(index).listenInterface->transferCanceled(copyRunningList.at(index).pluginOrderId);
copyRunningList.erase(copyRunningList.cbegin()+index);
return;
}
index++;
}
}
void CopyListener::newPluginCopyWithoutDestination(const uint32_t &orderId,const std::vector<std::string> &sources)
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"sources: "+stringimplode(sources,";"));
PluginInterface_Listener *plugin = qobject_cast<PluginInterface_Listener *>(sender());
CopyRunning newCopyInformation;
newCopyInformation.listenInterface = plugin;
newCopyInformation.pluginOrderId = orderId;
newCopyInformation.orderId = incrementOrderId();
copyRunningList.push_back(newCopyInformation);
std::vector<std::string> stringList;stringList.push_back("file");
emit newCopyWithoutDestination(orderId,stringList,stripSeparator(sources));
}
void CopyListener::newPluginCopy(const quint32 &orderId,const std::vector<std::string> &sources,const std::string &destination)
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"sources: "+stringimplode(sources,";")+", destination: "+destination);
PluginInterface_Listener *plugin = qobject_cast<PluginInterface_Listener *>(sender());
CopyRunning newCopyInformation;
newCopyInformation.listenInterface = plugin;
newCopyInformation.pluginOrderId = orderId;
newCopyInformation.orderId = incrementOrderId();
copyRunningList.push_back(newCopyInformation);
std::vector<std::string> stringList;stringList.push_back("file");
emit newCopy(orderId,stringList,stripSeparator(sources),"file",destination);
}
void CopyListener::newPluginMoveWithoutDestination(const uint32_t &orderId,const std::vector<std::string> &sources)
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"sources: "+stringimplode(sources,";"));
PluginInterface_Listener *plugin = qobject_cast<PluginInterface_Listener *>(sender());
CopyRunning newCopyInformation;
newCopyInformation.listenInterface = plugin;
newCopyInformation.pluginOrderId = orderId;
newCopyInformation.orderId = incrementOrderId();
copyRunningList.push_back(newCopyInformation);
std::vector<std::string> stringList;stringList.push_back("file");
emit newMoveWithoutDestination(orderId,stringList,stripSeparator(sources));
}
void CopyListener::newPluginMove(const quint32 &orderId,const std::vector<std::string> &sources,const std::string &destination)
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"sources: "+stringimplode(sources,";")+", destination: "+destination);
PluginInterface_Listener *plugin = qobject_cast<PluginInterface_Listener *>(sender());
CopyRunning newCopyInformation;
newCopyInformation.listenInterface = plugin;
newCopyInformation.pluginOrderId = orderId;
newCopyInformation.orderId = incrementOrderId();
copyRunningList.push_back(newCopyInformation);
std::vector<std::string> stringList;stringList.push_back("file");
emit newMove(orderId,stringList,stripSeparator(sources),"file",destination);
}
uint32_t CopyListener::incrementOrderId()
{
do
{
nextOrderId++;
if(nextOrderId>2000000)
nextOrderId=0;
} while(vectorcontainsAtLeastOne(orderList,nextOrderId));
return nextOrderId;
}
void CopyListener::allPluginIsloaded()
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"with value: "+std::to_string(pluginList.size()>0));
sendState(true);
reloadClientList();
}
void CopyListener::reloadClientList()
{
if(!PluginsManager::pluginsManager->allPluginHaveBeenLoaded())
return;
std::vector<std::string> clients;
unsigned int indexPlugin=0;
while(indexPlugin<pluginList.size())
{
if(pluginList.at(indexPlugin).listenInterface!=NULL)
{
const PluginListener &pluginListener=pluginList.at(indexPlugin);
const std::vector<std::string> &clientsList=pluginListener.listenInterface->clientsList();
clients.insert(clients.cbegin(),clientsList.cbegin(),clientsList.cend());
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"ask client to: "+pluginList.at(indexPlugin).path);
}
indexPlugin++;
}
emit newClientList(clients);
}
void CopyListener::sendState(bool force)
{
if(stopIt)
return;
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start, pluginList.size(): "+std::to_string(pluginList.size())+", force: "+std::to_string(force));
Ultracopier::ListeningState current_state=Ultracopier::NotListening;
bool found_not_listen=false,found_listen=false,found_inWaitOfReply=false;
unsigned int index=0;
while(index<pluginList.size())
{
if(current_state==Ultracopier::NotListening)
{
if(pluginList.at(index).state==Ultracopier::SemiListening)
current_state=Ultracopier::SemiListening;
else if(pluginList.at(index).state==Ultracopier::NotListening)
found_not_listen=true;
else if(pluginList.at(index).state==Ultracopier::FullListening)
found_listen=true;
}
if(pluginList.at(index).inWaitOfReply)
found_inWaitOfReply=true;
index++;
}
if(current_state==Ultracopier::NotListening)
{
if(found_not_listen && found_listen)
current_state=Ultracopier::SemiListening;
else if(found_not_listen)
current_state=Ultracopier::NotListening;
else if(!found_not_listen && found_listen)
current_state=Ultracopier::FullListening;
else
current_state=Ultracopier::SemiListening;
}
bool have_plugin=pluginList.size()>0;
if(force || current_state!=last_state || have_plugin!=last_have_plugin || found_inWaitOfReply!=last_inWaitOfReply)
{
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"send listenerReady("+std::to_string(current_state)+","+std::to_string(have_plugin)+","+std::to_string(found_inWaitOfReply)+")");
emit listenerReady(current_state,have_plugin,found_inWaitOfReply);
}
else
ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"Skip the signal sending");
last_state=current_state;
last_have_plugin=have_plugin;
last_inWaitOfReply=found_inWaitOfReply;
}