Logo Search packages:      
Sourcecode: dc-qt version File versions  Download package

mainwindow.cpp

#include <QtGui>

#include <iostream>
#include <boost/bind.hpp>

#include "mainwindow.h"
#include "connectdialog.h"
#include "commandhandlers.h"
#include "transferlistitemdelegate.h"
#include "userfiledialog.h"

using namespace std;
using namespace ui_cmd_handlers;

MainWindow::MainWindow()
{
    ui.setupUi(this);
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
      QPushButton* b = new QPushButton(ui.hubTabs);
      QIcon i(":/images/remove.png");
      b->setIcon(i);
      b->setFlat(true);
      b->setToolTip(tr("Disconnect from hub"));
      ui.hubTabs->removeTab(0);
      ui.hubTabs->setCornerWidget(b);
      connect(b,SIGNAL(pressed()),SLOT(onDisconnectPressed())); 
      
      backendRetriesLeft=-1;
      statusBar()->showMessage(tr("Hello"),2000);
      shareStatusLbl = new QLabel(tr("Total shared: 0b"));
      shareStatusLbl->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
      statusBar()->addPermanentWidget(shareStatusLbl);
      
}

MainWindow::~MainWindow()
{}

void MainWindow::closeEvent(QCloseEvent* e)
{
    int i = QMessageBox::question(this,tr("Quit"),tr("Keep backend running?"),tr("&Yes"),tr("&No"),tr("&Cancel"),1,2);
    if(i==1)
    {
        if(backendConnection)
            backendConnection->die();
            QThread::currentThread()->wait(1000);     // TODO dont sleep. make a better way of knowing that the command has completed
        driver->stopSender();
        driver->waitForCompletion();
            e->accept();
    }
      else if(i==0) e->accept();
      else e->ignore();
}

void MainWindow::on_actionConnect_triggered()
{
    if(connectDialog)
        connectDialog->show();
}

void MainWindow::on_actionSettings_triggered( )
{
    if(settingsDialog)
        settingsDialog->show();
}

void MainWindow::on_actionSearch_triggered( )
{
    if(searchManager)
        searchManager->show(this);
}

void MainWindow::userFileListing( const UserFileModelPtr& model )
{
    UserFileDialog* fileDialog = new UserFileDialog( model, backendConnection, userModel );
    fileDialog->show();
}

bool MainWindow::connectToBackend( const char* hostname, int port )
{
    try
    {
        driver = boost::shared_ptr< rpc::RpcClientDriver >(new rpc::RpcClientDriver(hostname, port));
        backendConnection = boost::shared_ptr<BackendConnection>(new BackendConnection(driver));
        userModel = boost::shared_ptr<GlobalUserModel>(new GlobalUserModel(this));
            
            cout << "Creating dialogs and models" << endl;
            
            // Create all dialogs and data models. This code must not make any calls to the backend!
            if(settingsDialog)
                  delete settingsDialog;
            settingsDialog = new SettingsDialog(backendConnection,this);
            if(sessionManager)
                  delete sessionManager;
            sessionManager = new SessionManager(ui.hubTabs,backendConnection,this);
            connect(sessionManager,SIGNAL(currentHubTotalShare(qint64)),SLOT(updateTotalShareStatus(qint64)));
            if(searchManager)
                  delete searchManager;
            searchManager = new SearchManager(backendConnection,this);
            if(queueModel)
                  delete queueModel;
            queueModel = new QueueModel(userModel);
            ui.queueView->setModel(queueModel);
            ui.queueView->addAction(ui.actionCancelDownload);
            ui.queueView->setContextMenuPolicy(Qt::CustomContextMenu);
            connect(ui.queueView,SIGNAL(customContextMenuRequested ( const QPoint&)),SLOT(onQueueContextMenu(const QPoint&)));
            if(finishedModel)
                  delete finishedModel;
            finishedModel = new FinishedModel;
            ui.finishedView->setModel(finishedModel);
            if(transferModel)
                  delete transferModel;
            transferModel = new TransferListModel;
            ui.transfersView->setModel(transferModel);
            ui.transfersView->setItemDelegate( new TransferListItemDelegate );
            ui.transfersView->addAction(ui.actionForceAttempt);
            ui.transfersView->setContextMenuPolicy(Qt::ActionsContextMenu);

            if(connectDialog)
                  delete connectDialog;
            connectDialog = new ConnectDialog(backendConnection, this);
      
            cout << "Done creating" << endl;
            
            // End create dialogs and models.
            
            // Register all command handlers and connect their signals to our dialogs and models.
        registerCommandHandlers();
            
            cout << "connnect!" << endl;
            // Finally, connect to the backend.
            driver->connect();
        
            // -------------------------------------------------------------------------------------------
        // Everything is up and running! That means we can authenticate and request running sessions.
        // -------------------------------------------------------------------------------------------
            backendConnection->authenticate(password);
            QThread::currentThread()->wait(500);
            backendConnection->requestRunningSessions();
            // And get the hub lists
            connectDialog->getLists();
    
      }
    catch( ... )
    {
            logger->error("Exception in connectToBackend()");
        return false;
    }
    return true;
}

void MainWindow::connectToBackend( )
{
    QSettings settings("dc-qt.sf.net","dcqt");
    SettingsDialog::BackendConnectionType backendConnectionType =
        (SettingsDialog::BackendConnectionType)settings.value("bctype",(int)SettingsDialog::USE_LOCAL_BACKEND).toInt();
    QString backendConnectionURL = settings.value("bcurl","localhost").toString();
    int localPort = settings.value("bclocalport",6161).toInt();
    int remotePort = settings.value("bcremoteport",6161).toInt();
      password = settings.value("bcpassword",QString::number(rand() % 100000 + 100000)).toString();
      
    if( backendConnectionType == SettingsDialog::USE_LOCAL_BACKEND)
    {
        if(!connectToBackend("localhost",localPort))
        {
            // Ok, connection failed, try to start a backend
            // Figure out the path of the executable
            if( backendRetriesLeft > 0 )
            {
                backendRetriesLeft--;
                QTimer::singleShot( 3000, this, SLOT(connectToBackend()));

            }
            else if(backendRetriesLeft==0)
            {
                QMessageBox::critical(this, "Error", "Backend started but could not connect.");
            }
            else
            {
                QString dir = QCoreApplication::applicationDirPath();
                QString path;
                if(QFile::exists(dir+"/backend"))
                {
                    path = dir+"/backend";
                }
                else if(QFile::exists(dir+"/../backend/backend"))
                {
                    path = dir+"/../backend/backend";
                }
                else if(QFile::exists(dir+"/../Resources/backend"))
                        {
                              path = dir+"/../Resources/backend";
                        }
                        else
                    QMessageBox::critical(this,"Error","Could not find backend executable (installation problem?).");

                if(!path.isEmpty())
                {
                    QStringList args;
                    args+="--port";
                    args+=QString::number(localPort);
                              args+="--password";
                              args+=password;
                    logger->info(QString("Trying to start backend at %1").arg(path));
                    if( !QProcess::startDetached(path,args) )
                    {
                        logger->error("Error starting backend");
                        QMessageBox::critical(this,"Error","Could not start the backend.");
                    }
                    else
                    {
                        // Ok, the backend is starting at this point. We need to give it some time to initialize.
                        // This will take different amount of time on different machines.
                        QTimer::singleShot( 2000, this, SLOT(connectToBackend()));
                        backendRetriesLeft=5;
                    }
                }
            }
        }
    }
    else
    {
        if(!connectToBackend( backendConnectionURL.toAscii(), remotePort ))
        {
            QMessageBox::critical(this, "Error", QString("Error connecting to backend at %1:%2").arg(backendConnectionURL).arg(remotePort));
        }
    }

}

// temporary place
void MainWindow::registerCommandHandlers()
{
      // SettingsInfo
    ui_cmd_handlers::settingsInfoHandler* p =new ui_cmd_handlers::settingsInfoHandler( boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2) );
    rpc::RpcCommandHandlerPtr settingsInfo( p );
    driver->registerCommand( settingsInfo );


    connect(p,SIGNAL(settingsInfo(const QList<QString>&,const QList<QVariant>&)),
            settingsDialog,SLOT(settingsInfo(const QList<QString>&,const QList<QVariant>&)));

      // SessionCreated
    ui_cmd_handlers::GuiCommandHandlerBase* ptr = new ui_cmd_handlers::SessionCreatedHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpc::RpcCommandHandlerPtr rpccptr( ptr );
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(sessionCreated(int)),sessionManager,SLOT(createSession(int)));

    // HubConnected
    ptr = new ui_cmd_handlers::HubConnectedHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(hubConnected(int)),sessionManager,SLOT(createSession(int)));

    // HubUpdated
    ptr = new ui_cmd_handlers::HubUpdatedHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(hubUpdated(int,const QString&)),sessionManager,SLOT(hubUpdated(int,const QString&)));

      // HubUpdated
      ptr = new ui_cmd_handlers::HubStatsHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
      rpccptr = rpc::RpcCommandHandlerPtr(ptr);
      driver->registerCommand( rpccptr );
      connect(ptr,SIGNAL(hubStats(int,qint64)),sessionManager,SLOT(onHubStats(int,qint64)));
      
    // ConnectionFailed
    ptr = new ui_cmd_handlers::ConnectionFailedHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(connectionFailed(int,const QString&)),sessionManager,SLOT(connectionFailed(int,const QString&)));

    // PrivateChat
    ptr = new ui_cmd_handlers::PrivateChatHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(privateChat(int,const QString&,const QString&)),sessionManager,SLOT(privateChat(int,const QString&,const QString&)));

    // UsersUpdated
    ptr = new ui_cmd_handlers::UsersUpdatedHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(usersUpdated(int,QList<User*>)),sessionManager,SLOT(usersUpdated(int,QList<User*>)));
    connect(ptr,SIGNAL(usersUpdated(int,QList<User*>)),userModel.get(),SLOT(usersUpdated(int,QList<User*>)));

      // UserRemoved
      ptr = new ui_cmd_handlers::UserRemovedHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
      rpccptr = rpc::RpcCommandHandlerPtr(ptr);
      driver->registerCommand( rpccptr );
      connect(ptr,SIGNAL(userRemoved(int,int)),sessionManager,SLOT(userRemoved(int,int)));
      connect(ptr,SIGNAL(userRemoved(int,int)),userModel.get(),SLOT(userRemoved(int,int)));
      
    // ChatMessage
    ptr = new ui_cmd_handlers::ChatMessageHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(chatMessage(int,const QString&)),sessionManager,SLOT(chatMessage(int,const QString&)));

    // RunningSessions
    ptr = new ui_cmd_handlers::RunningSessionsHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(sessionInfo(int,const QString&,const QString&,const QList<User*>)),
                  sessionManager,SLOT(sessionInfo(int,const QString&,const QString,const QList<User*>)));
      connect(ptr,SIGNAL(sessionInfo(int,const QString&,const QString&,const QList<User*>)),
                  userModel.get(),SLOT(sessionInfo(int,const QString&,const QString,const QList<User*>)));
    connect(ptr,SIGNAL(queueList(const QList<QueueItem>&)), queueModel, SLOT(onItemsAdded(const QList<QueueItem>&)));

    // SharedDirs
    ptr = new ui_cmd_handlers::SharedDirsHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(sharedDirs(const QList<ShareItem>)),settingsDialog,SLOT(sharedDirs(const QList<ShareItem>)));

    // SearchResults
    ptr = new ui_cmd_handlers::SearchResultsHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(searchResults(int,QList<SearchEntry>&)),searchManager,SLOT(searchResults(int,QList<SearchEntry>&)));
      
    // NewHubList
    ptr = new ui_cmd_handlers::PublicHubListHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(hubList(const QList<rpc_types::HubEntry>&)),connectDialog,SLOT(publicHubList(const QList<rpc_types::HubEntry>&)));
      
    // FavouriteHubList
    ptr = new ui_cmd_handlers::FavouriteHubListHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(hubList(const QList<rpc_types::FavouriteHub>&)),connectDialog,SLOT(favouriteHubList(const QList<rpc_types::FavouriteHub>&)));
      
    // FavouriteHubList
    ptr = new ui_cmd_handlers::FavouriteHubAddedHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(favHubAdded(const rpc_types::FavouriteHub&)),connectDialog,SLOT(favouriteHubAdded(const rpc_types::FavouriteHub&)));
      
    // FavouriteHubList
    ptr = new ui_cmd_handlers::FavouriteHubRemovedHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(favHubRemoved(const string&)),connectDialog,SLOT(favouriteHubRemoved(const string&)));

    // QueueEvent
    ptr = new ui_cmd_handlers::QueueEventHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(queueItemAdded(const QueueItem&)),queueModel,SLOT(onItemAdded(const QueueItem&)));
    connect(ptr,SIGNAL(queueItemRemoved(int)),queueModel,SLOT(onItemRemoved(int)));
    connect(ptr,SIGNAL(queueItemFinshed(int)),queueModel,SLOT(onFinished(int)));
    connect(ptr,SIGNAL(sourcesUpdated(int, QList<int>)),queueModel,SLOT(onSourcesUpdated(int,QList<int>)));
    connect(ptr,SIGNAL(statusUpdated(int, int, int, int)),queueModel,SLOT(onStatusUpdated(int,int,int,int)));

    // FinishedEvent
    ptr = new ui_cmd_handlers::FinishedEventHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(itemAdded(const FinishedItem&)),finishedModel,SLOT(onItemAdded(const FinishedItem&)));
    connect(ptr,SIGNAL(itemRemoved(int)),finishedModel,SLOT(onItemRemoved(int)));
    connect(ptr,SIGNAL(allRemoved(int)),finishedModel,SLOT(onAllRemoved(int)));

    // TransferEvent
    ptr = new ui_cmd_handlers::TransferEventHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL( transferStarting(const FileTransfer&)), transferModel, SLOT(onTransferStart(const FileTransfer&)));
    connect(ptr,SIGNAL( transferTick(const QList<FileTransfer>&)), transferModel, SLOT(onTransferTick(const QList<FileTransfer>&)));
    connect(ptr,SIGNAL( transferComplete(const FileTransfer&)), transferModel, SLOT(onTransferComplete(const FileTransfer&)));
    connect(ptr,SIGNAL( transferFailed(const FileTransfer&,const QString&)), transferModel, SLOT(onTransferFailed(const FileTransfer&,const QString&)));

    // UerFileList
    ptr = new ui_cmd_handlers::UserFileListHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
    rpccptr = rpc::RpcCommandHandlerPtr(ptr);
    driver->registerCommand( rpccptr );
    connect(ptr,SIGNAL(fileListing(const UserFileModelPtr& )),
            this,SLOT(userFileListing(const UserFileModelPtr& )));
      
      // Hashinfo
      ptr = new ui_cmd_handlers::HashInfoHandler(boost::bind(&rpc::RpcDriver::queueCommand, driver.get(),_1,_2));
      rpccptr = rpc::RpcCommandHandlerPtr(ptr);
      driver->registerCommand( rpccptr );
}

void MainWindow::on_actionForceAttempt_triggered( )
{
    QModelIndex mi = ui.transfersView->selectionModel()->currentIndex();
    if(mi.isValid())
    {
        FileTransfer ft = transferModel->data(mi.row());
        backendConnection->forceConnectionAttempt(ft.userid);
    }
}

void MainWindow::on_actionCancelDownload_triggered( )
{
    QModelIndex mi = ui.queueView->selectionModel()->currentIndex();
    if(mi.isValid())
    {
        QueueItem* qi = queueModel->getItem(mi.row());
        if(qi)
            backendConnection->removeQueueItem(qi->id);
    }
}

void MainWindow::onDisconnectPressed( )
{
      if(sessionManager) sessionManager->closeCurrentSession();
}

void MainWindow::updateTotalShareStatus( qint64 s)
{
      shareStatusLbl->setText( tr("Total shared: ") + Util::bytesToStr(s));
}

void MainWindow::onQueueContextMenu( const QPoint &p )
{
      if( ui.queueView->indexAt(p).isValid() ) {
            // Build context menu
            QMenu *contextMenu = new QMenu(tr("Queue Menu"),this);
            QueueItem* item = queueModel->getItem( ui.queueView->indexAt(p).row() );
            contextMenu->addAction(ui.actionCancelDownload);
            QMenu *srcMenu = contextMenu->addMenu(tr("Remove source"));
            QList< QPair<QAction*,int> > al;
            for(int i = 0;i < item->sources.size();i++) {
                  User* u = userModel->getUser(item->sources[i]);
                  if(u!=NULL) {
                        QString username = u->nick;
                        QAction *a = new QAction(username,srcMenu);
                        al+= QPair<QAction*,int>(a,item->sources[i]);
                        srcMenu->addAction(a);
                  }
            }
            
            QAction *a = contextMenu->exec(QCursor::pos());
            
            if( a == ui.actionCancelDownload ) {
                  logger->debug("cancel dl");
            } else {
                  // Find the action in the array
                  logger->debug("array action");
                  for(int i=0;i < al.size();i++) {
                        if( al[i].first == a ) {
                              logger->debug("remove source " + QString::number(al[i].second));
                              backendConnection->removeSource( item->id, al[i].second );
                        }
                  }
            }
            
            delete contextMenu;
      }
}

Generated by  Doxygen 1.6.0   Back to index