Logo Search packages:      
Sourcecode: kbiff version File versions  Download package

kbiff.cpp

/*
 * kbiff.cpp
 * Copyright (C) 1999-2004 Kurt Granroth <granroth@kde.org>
 *
 * This file contains the implementation of the main KBiff
 * widget
 *
 * $Id: kbiff.cpp,v 1.13 2004/03/26 01:30:43 gran Exp $
 */
#include "kbiff.h"
#include <qmovie.h>
#include <qtooltip.h>

#include <kaudioplayer.h>
#include <kconfig.h>
#include <kglobal.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kpopupmenu.h>
#include <kprocess.h>
#include <krun.h>
#include <kwin.h>

#include "setupdlg.h"
#include "notify.h"
#include "status.h"
#include "led.h"

#include <unistd.h>

#include <dcopclient.h>

KBiff::KBiff(DCOPClient *client, QWidget *parent)
    : QLabel(parent),
      DCOPObjectProxy(client),
      statusTimer(0),
      status(0),
      statusChanged(true),
      mled( new Led("mled") )
{
    setBackgroundMode(X11ParentRelative);

    setAutoResize(true);
    setMargin(0);
    setAlignment(AlignLeft | AlignTop);

    // enable the session management stuff
    connect(kapp, SIGNAL(saveYourself()), this, SLOT(saveYourself()));

    // nuke the list stuff when removed
    monitorList.setAutoDelete(true);
    notifyList.setAutoDelete(true);
    statusList.setAutoDelete(true);

    // register with DCOP
    registerMe(client);

    reset();
}

KBiff::~KBiff()
{
    monitorList.clear();
    notifyList.clear();
    statusList.clear();
    delete mled;

    // we no longer want to be registered
    DCOPClient *client = kapp->dcopClient();
    QCString proxy = QCString("kbiff-") + QCString().setNum(getpid());
    if (client->isApplicationRegistered(proxy) == true)
    {
        QByteArray params;
        QDataStream ds(params, IO_WriteOnly);
        ds << proxy;
        client->send("kbiff", "kbiff", "proxyDeregister(QString)", params);
    }
    client->detach();
}

void KBiff::processSetup(const KBiffSetup* setup, bool run)
{
    // General settings
    isSecure    = setup->getSecure();
    profile     = setup->getProfile();
    mailClient  = setup->getMailClient();
    sessions    = setup->getSessionManagement();
    skipcheck   = setup->getCheckStartup();
    noMailIcon  = setup->getNoMailIcon();
    newMailIcon = setup->getNewMailIcon();
    oldMailIcon = setup->getOldMailIcon();
    noConnIcon  = setup->getNoConnIcon();

    // New mail
    systemBeep     = setup->getSystemBeep();
    runCommand     = setup->getRunCommand();
    runCommandPath = setup->getRunCommandPath();
    runResetCommand     = setup->getRunResetCommand();
    runResetCommandPath = setup->getRunResetCommandPath();
    playSound      = setup->getPlaySound();
    playSoundPath  = setup->getPlaySoundPath();
    notify         = setup->getNotify();
    dostatus       = setup->getStatus();

    // if we aren't going the status route, we should at least
    // provide a tooltip!
    if (dostatus == false)
        QToolTip::add(this, profile);
    else
        QToolTip::remove(this);

    // set all the new mailboxes
    setMailboxList(setup->getMailboxList(), setup->getPoll());

    // change the dock state if necessary
    if (docked != setup->getDock())
        dock();

    if (run && !skipcheck)
        start();
    skipcheck = false;

    // handle session management disabling
    if (sessions == false)
    {
      disconnect(this, SLOT(saveYourself()));
      kapp->disableSessionManagement();
    }

    // if we are going to be doing status, we might as well create
    // one now
    if ( dostatus )
    {
      statusList.clear();
      KBiffMonitor *monitor;
      for (monitor = monitorList.first(); monitor; monitor = monitorList.next())
      {
        statusList.append(new KBiffStatusItem(monitor->getMailboxKey(),
                                              monitor->newMessages(),
                                              monitor->curMessages()));
      }
      if (status)
      {
        status->hide();
        delete status;
        status = 0;
      }
      status = new KBiffStatus(this, profile, statusList);
    }

    delete setup;
}

void KBiff::setMailboxList(const QList<KBiffMailbox>& mailbox_list, unsigned int poll)
{
    QList<KBiffMailbox> tmp_list = mailbox_list;

    myMUTEX = true;
    if (isRunning())
        stop();
    monitorList.clear();
    
    KBiffMailbox *mbox;
    for (mbox = tmp_list.first(); mbox != 0; mbox = tmp_list.next())
    {
        KBiffURL *url = &(mbox->url);
        KBiffMonitor *monitor = new KBiffMonitor();
        monitor->setMailbox(*url);
        monitor->setPollInterval(poll);
        monitor->setMailboxKey(mbox->key);
        connect(monitor, SIGNAL(signal_newMail(const int, const QString&)),
                this, SLOT(haveNewMail(const int, const QString&)));
        connect(monitor, SIGNAL(signal_currentStatus(const int, const QString&, const KBiffMailState)),
                this, SLOT(currentStatus(const int, const QString&, const KBiffMailState)));
        connect(monitor, SIGNAL(signal_noMail()), this, SLOT(displayPixmap()));
        connect(monitor, SIGNAL(signal_noMail()),
                this, SLOT(haveNoNewMail()));
        connect(monitor, SIGNAL(signal_oldMail()), this, SLOT(displayPixmap()));
        connect(monitor, SIGNAL(signal_oldMail()),
                this, SLOT(haveNoNewMail()));
        connect(monitor, SIGNAL(signal_noConn()), this, SLOT(displayPixmap()));
        connect(monitor, SIGNAL(signal_noConn()),
                this, SLOT(haveNoNewMail()));
        connect(monitor, SIGNAL(signal_invalidLogin(const QString&)),
                this, SLOT(invalidLogin(const QString&)));
        connect(monitor, SIGNAL(signal_fetchMail(const QString&)),
                this, SLOT(slotLaunchFetchClient(const QString&)));
        monitorList.append(monitor);
    }
    myMUTEX = false;
}

const bool KBiff::isDocked() const
{
    return docked;
}

void KBiff::readSessionConfig()
{
    KConfig *config = kapp->sessionConfig();

    config->setGroup("KBiff");

    profile = config->readEntry("Profile", "Inbox");
    docked = config->readBoolEntry("IsDocked", false);
    bool run = config->readBoolEntry("IsRunning", true);

    KBiffSetup *setup_dlg = new KBiffSetup(profile);
    processSetup(setup_dlg, run);
}

///////////////////////////////////////////////////////////////////////////
// Protected Virtuals
///////////////////////////////////////////////////////////////////////////
void KBiff::mousePressEvent(QMouseEvent *event)
{
    // regardless of which button, get rid of the status box
    if (status)
        status->hide();

    // also, ditch the timer
    if (statusTimer)
    {
        statusTimer->stop();
        delete statusTimer;
        statusTimer = 0;
    }

    // check if this is a right click
    if(event->button() == RightButton)
    {
        // popup the context menu
        popupMenu();
    }
    else
    {
        // execute the command
        slotLaunchMailClient();

        readPop3MailNow();
    }
}

void KBiff::enterEvent(QEvent *e)
{
    QLabel::enterEvent(e);

    // return now if the user doesn't want this feature.
    // *sniff*.. the ingrate.. I worked so hard on this, too... *sob*
    if (dostatus == false)
        return;

    // don't do anything if we already have a timer
    if (statusTimer)
        return;

    // popup the status in one second
    statusTimer = new QTimer(this);
    connect(statusTimer, SIGNAL(timeout()), this, SLOT(popupStatus()));

    statusTimer->start(1000, true);
}

void KBiff::leaveEvent(QEvent *e)
{
    QLabel::leaveEvent(e);

    // stop the timer if it is going
    if (statusTimer)
    {
        statusTimer->stop();
        delete statusTimer;
        statusTimer = 0;
    }

    // get rid of the status box if it is activated
    if (status)
        status->hide();
}

void KBiff::popupStatus()
{
    // if we don't get rid of the timer, then the very next
    // time we float over the icon, the status box will
    // *not* be activated!
    if (statusTimer)
    {
        statusTimer->stop();
        delete statusTimer;
        statusTimer = 0;
    }

    if (statusChanged)
    {
        statusList.clear();
        KBiffMonitor *monitor;
        for(monitor = monitorList.first(); monitor; monitor = monitorList.next())
        {
            statusList.append(new KBiffStatusItem(monitor->getMailboxKey(), monitor->newMessages(), monitor->curMessages()));
        }
        statusChanged = false;
    }

    status->updateListView(statusList);
    status->popup(QCursor::pos());
}

bool KBiff::isGIF8x(const QString& file_name)
{

    /* The first test checks if we can open the file */
    QFile gif8x(file_name);
    if (gif8x.open(IO_ReadOnly) == false)
        return false;

    /**
     * The GIF89 format specifies that the first five bytes of
     * the file shall have the characters 'G' 'I' 'F' '8' '9'.
     * The GIF87a format specifies that the first six bytes
     * shall read 'G' 'I' 'F' '8' '7' 'a'.  Knowing that, we
     * shall read in the first six bytes and test away.
     */
    char header[6];
    int bytes_read = gif8x.readBlock(header, 6);

    /* Close the file just to be nice */
    gif8x.close();

    /* If we read less than 6 bytes, then its definitely not GIF8x */
    if (bytes_read < 6)
        return false;

    /* Now test for the magical GIF8(9|7a) */
    if (header[0] == 'G' &&
         header[1] == 'I' &&
         header[2] == 'F' &&
         header[3] == '8' &&
         header[4] == '9' ||
        (header[4] == '7' && header[5] == 'a'))
    {
        /* Success! */
        return true;
    }

    /* Apparently not GIF8(9|7a) */
    return false;
}

///////////////////////////////////////////////////////////////////////////
// Protected Slots
///////////////////////////////////////////////////////////////////////////
void KBiff::saveYourself()
{
    if (sessions)
    {
        KConfig *config = kapp->sessionConfig();
        config->setGroup("KBiff");

        config->writeEntry("Profile", profile);
        config->writeEntry("IsDocked", docked);
        config->writeEntry("IsRunning", isRunning());

        config->sync();

    }
}

void KBiff::invokeHelp()
{
    kapp->invokeHelp();
}

void KBiff::displayPixmap()
{
    if (myMUTEX)
        return;

    // we will try to deduce the pixmap (or gif) name now.  it will
    // vary depending on the dock and mail state
    QString pixmap_name;
    bool has_new = false, has_old = false, has_no = true, has_noconn = false;
    KBiffMonitor *monitor;
    for (monitor = monitorList.first();
         monitor != 0 && has_new == false;
          monitor = monitorList.next())
    {
        switch (monitor->getMailState())
        {
            case NoMail:
                has_no = true;
                break;
            case NewMail:
                has_new = true;
                break;
            case OldMail:
                has_old = true;
                break;
            case NoConn:
                has_noconn = true;
                break;
            default:
                has_no = true;
                break;
        }
    }

    if (has_new)
    {
        pixmap_name = newMailIcon;
        // turn on led for new mail, otherwise turn off
        mled->On();
    }
    else if (has_old)
    {
        pixmap_name = oldMailIcon;
        mled->Off();
    }
    else if (has_noconn)
    {
        pixmap_name = noConnIcon;
        mled->Off();
    }
    else
    {
        pixmap_name = noMailIcon;
        mled->Off();
    }

    if (docked)
    {
        // we need to check if this has path info encoded into it
        QFileInfo info(pixmap_name);

        // if info.fileName() returns pixmap_name, then we no there
        // isn't any paths attached and we can just prepend our 'mini'
        if (info.fileName() == pixmap_name)
            pixmap_name.prepend("mini-");
        else
        {
            // so we have some path junk on it.  we get the filename
            // by itself, prepend our 'mini' and tack it onto the end
            // of the original dirpath.  simple
            QString filename(info.fileName());
            filename.prepend("mini-");

            // we aren't guaranteed that the dirpath will end in a /
            // so we add one (an extra one won't hurt, in any case
            pixmap_name = info.dirPath() + "/" + filename;
        }
    }
    QString filename = KGlobal::iconLoader()->iconPath( pixmap_name, KIcon::User );
    QFileInfo file(filename);

    // at this point, we have the file to display.  so display it
    if (isGIF8x(file.absFilePath()))
        setMovie(QMovie(file.absFilePath()));
    else
        setPixmap(QPixmap(file.absFilePath()));
    adjustSize();
}

void KBiff::currentStatus(const int num, const QString& the_mailbox, const KBiffMailState the_state)
{
  statusChanged = true;
  // iterate through all saved notify dialogs to see if "our" one is
  // currently being displayed
  KBiffNotify *notify;
  for (notify = notifyList.first();
       notify != 0;
       notify = notifyList.next())
  {
    // if this one is not visible, delete it from the list.  the only
    // way it will again become visible is if the haveNewMail slot
    // gets triggered
    if (notify->isVisible() == false)
    {
      notifyList.remove();
    }
    else
    {
      // if this box is visible (active), we see if it is the one
      // we are looking for
      if (notify->getMailbox() == the_mailbox)
      {
        // yep.  now, if there is new mail, we set the new number in
        // the dialog.  if it is any other state, we remove this
        // dialog from the list
        switch (the_state)
        {
          case NewMail:
            notify->setNew(num);
            break;
          case OldMail:
          case NoMail:
          case NoConn:
          default:
            notifyList.remove();
            break;
        }
      }
    }
  }
}

void KBiff::haveNewMail(const int num, const QString& the_mailbox)
{
    displayPixmap();

    // beep if we are allowed to
    if (systemBeep)
    {
        kapp->beep();
    }

    // run a command if we have to
    if (runCommand)
    {
        // make sure the command exists
        if (!runCommandPath.isEmpty())
        {
            executeCommand(replaceCommandArgs(runCommandPath));
        }
    }

    // play a sound if we have to
    if (playSound)
        slotPlaySound(playSoundPath);

    // notify if we must
    if (notify)
    {
        KBiffNotify *notify_dlg = new KBiffNotify(this, num, the_mailbox);
        connect(notify_dlg, SIGNAL(signalLaunchMailClient()),
                this, SLOT(slotLaunchMailClient()));
        notifyList.append(notify_dlg);
        notify_dlg->show();

        // half-hearted attempt to center this
        int x = (KApplication::desktop()->width() - notify_dlg->width()) / 2;
        int y = (KApplication::desktop()->height() - notify_dlg->height()) / 2;
        notify_dlg->move(x, y);
    }
}

void KBiff::haveNoNewMail()
{
    displayPixmap();

    // run a command if we have to
    if (runResetCommand)
    {
        // make sure the command exists
        if (!runResetCommandPath.isEmpty())
        {
            executeCommand(runResetCommandPath);
        }
    }
}

QString KBiff::getURLWithNewMail()
{
    KBiffMonitor *monitor;
    for (monitor = monitorList.first();
            monitor != 0;
            monitor = monitorList.next())
    {
        if(monitor->getMailState() == NewMail)
            return monitor->getMailbox();
    }

    return monitorList.first()->getMailbox();
}

QString KBiff::getMailBoxWithNewMail()
{
    QString url(getURLWithNewMail());
    
    int slashPos = url.find('/');
    if(slashPos == -1)
      return url.mid(slashPos + 1);
    else
      return url.mid(url.find(':') + 1);
}

QString KBiff::replaceCommandArgs(QString cmdStr)
{
    bool expand = false;
    for(unsigned int i = 0; i < cmdStr.length(); i++)
    {
        if(expand)
        {
            expand = false;
            if(cmdStr[i] == 'm')
                cmdStr.replace(i - 1, 2, getMailBoxWithNewMail());
            else if(cmdStr[i] == 'u')
                cmdStr.replace(i - 1, 2, getURLWithNewMail());
            else if(cmdStr[i] == '%')
                cmdStr.replace(i - 1, 2, "%");

            continue;
        }

        if(cmdStr[i] == '%')
            expand = true;
    }

    return cmdStr;
}

void KBiff::dock()
{
    // destroy the old window
    if (this->isVisible())
    {
        this->hide();
        this->destroy(true, true);
        this->create(0, true, false);
        kapp->setMainWidget(this);

        // we don't want a "real" top widget if we are _going_ to
        // be docked.
        if (docked)
            kapp->setTopWidget(this);
        else
            kapp->setTopWidget(new QWidget);
    }

    if (docked == false)
    {
        docked = true;

        // enable docking
        KWin::setSystemTrayWindowFor(this->winId(), 0);
    }
    else
        docked = false;

    // (un)dock it!
    this->show();
    QTimer::singleShot(1000, this, SLOT(displayPixmap()));
}

void KBiff::setup()
{
    KBiffSetup* setup_dlg = new KBiffSetup(profile);

    if (setup_dlg->exec())
        processSetup(setup_dlg, true);
    else
        delete setup_dlg;
}

void KBiff::checkMailNow()
{
    KBiffMonitor *monitor;
    for (monitor = monitorList.first();
         monitor != 0;
          monitor = monitorList.next())
    {
        monitor->checkMailNow();
    }
}

void KBiff::readMailNow()
{
    KBiffMonitor *monitor;
    for (monitor = monitorList.first();
         monitor != 0;
          monitor = monitorList.next())
    {
        monitor->setMailboxIsRead();
    }
}

void KBiff::readPop3MailNow()
{
    KBiffMonitor *monitor;
    for (monitor = monitorList.first();
         monitor != 0;
          monitor = monitorList.next())
    {
        if (monitor->getProtocol() == "pop3")
            monitor->setMailboxIsRead();
    }
}

void KBiff::stop()
{
    KBiffMonitor *monitor;
    for (monitor = monitorList.first();
         monitor != 0;
          monitor = monitorList.next())
    {
        monitor->stop();
    }
}

void KBiff::start()
{
    myMUTEX = true;
    KBiffMonitor *monitor;
    for (unsigned int i = 0; i < monitorList.count(); i++)
    {
        monitor = monitorList.at(i);
        monitor->start();
    }
    myMUTEX = false;
    displayPixmap();
}

///////////////////////////////////////////////////////////////////////////
// Protected Functions
///////////////////////////////////////////////////////////////////////////
void KBiff::popupMenu()
{
    KPopupMenu *popup = new KPopupMenu(0, "popup");
    popup->insertTitle(kapp->miniIcon(), profile);

    // if secure, disable everything but exit
    if (isSecure == false)
    {
        if (docked)
            popup->insertItem(i18n("&UnDock"), this, SLOT(dock()));
        else
            popup->insertItem(i18n("&Dock"), this, SLOT(dock()));
        popup->insertItem(i18n("&Setup..."), this, SLOT(setup()));
        popup->insertSeparator();
        popup->insertItem(i18n("&Help..."), this, SLOT(invokeHelp()));
        popup->insertSeparator();

        int check_id;
        check_id = popup->insertItem(i18n("&Check Mail Now"), this, SLOT(checkMailNow()));
        int read_id;
        read_id = popup->insertItem(i18n("&Read Mail Now"), this, SLOT(readMailNow()));

        if (isRunning())
        {
            popup->setItemEnabled(check_id, true);
            popup->setItemEnabled(read_id, true);
            popup->insertItem(i18n("&Stop"), this, SLOT(stop()));
        }
        else
        {
            popup->setItemEnabled(check_id, false);
            popup->setItemEnabled(read_id, false);
            popup->insertItem(i18n("&Start"), this, SLOT(start()));
        }
        popup->insertSeparator();
    }

    popup->insertItem(i18n("E&xit"), kapp, SLOT(quit()));

    popup->popup(QCursor::pos());
}

void KBiff::reset()
{
    // reset all the member variables
    systemBeep     = true;
    runCommand     = false;
    runCommandPath = "";
    playSound      = false;
    playSoundPath  = "";
    notify         = true;
    dostatus       = true;

    noMailIcon  = "nomail";
    newMailIcon = "newmail";
    oldMailIcon = "oldmail";
    noConnIcon  = "noconn";

    docked    = false;
    isSecure  = false;

    mailClient  = "xmutt -f +%m";

    myMUTEX = false;
}

bool KBiff::isRunning()
{
    bool is_running = false;
    KBiffMonitor *monitor;
    for (monitor = monitorList.first();
         monitor != 0;
          monitor = monitorList.next())
    {
        if (monitor->isRunning())
        {
            is_running = true;
            break;
        }
    }
    return is_running;
}

void KBiff::executeCommand(const QString& command)
{
    KRun::runCommand(command);
}

void KBiff::slotLaunchFetchClient(const QString& fetchClient)
{
    if (!fetchClient.isEmpty())
        executeCommand(fetchClient);
}

void KBiff::slotLaunchMailClient()
{
    if (!mailClient.isEmpty())
        executeCommand(replaceCommandArgs(mailClient));
}

void KBiff::slotPlaySound(const QString& play_sound)
{
    // make sure something is specified
    if (!play_sound.isNull())
        KAudioPlayer::play(play_sound);
}

bool KBiff::process(const QCString&, const QCString& function,
                    const QByteArray& data, QCString& replyType,
                    QByteArray &replyData)
{
    QDataStream args(data, IO_ReadOnly);
    QDataStream reply(replyData, IO_WriteOnly);
    QString proxy;
    if (function == "proxyRegister(QString)")
    {
        args >> proxy;
        proxyList.append(proxy);
        replyType = "void";
        return true;
    }

    else if (function == "proxyDeregister(QString)")
    {
        args >> proxy;
        proxyList.remove(proxy);
        replyType = "void";
        return true;
    }

    else if (function == "hasMailbox(QString)")
    {
        QString mailbox;
        args >> mailbox;

        reply << (bool) findMailbox(mailbox, proxy);
        replyType = "bool";
        return true;
    }

    else if (function == "mailCount(QString)")
    {
        reply << -1;
        replyType = "int";
        return true;
    }

    else if (function == "newMailCount(QString)")
    {
        QString mailbox;
        args >> mailbox;

        reply << newMailCount(mailbox);
        replyType = "int";
        return true;
    }


    return false;
}

int KBiff::newMailCount(const QString& url)
{
    int newmail = -1;

    QString proxy;
    if (findMailbox(url, proxy) == true)
    {
        if (proxy != QString::null)
        {
            QByteArray data;
            QDataStream ds(data, IO_WriteOnly);
            ds << url;

            QByteArray reply_data;
            QCString reply_type;
            QDataStream reply(reply_data, IO_ReadOnly);

            DCOPClient *dcc = kapp->dcopClient();
            if (dcc->call(proxy.ascii(), "kbiff",
                          "newMailCount(QString)", data, reply_type,
                          reply_data) == true)
            {
                reply >> newmail;
            }
        }
        else
        {
            KBiffMonitor *monitor;
            for(monitor = monitorList.first(); monitor;
                monitor = monitorList.next())
            {
                if (monitor->getMailbox() == url)
                {
                    newmail = monitor->newMessages();
                    break;
                }
            }
        }
    }

    return newmail;
}

bool KBiff::findMailbox(const QString& url, QString& proxy)
{
    bool has_mailbox = false;
    KBiffMonitor *monitor;
    for(monitor = monitorList.first(); monitor; monitor = monitorList.next())
    {
        if (monitor->getMailbox() == url)
        {
            has_mailbox = true;
            break;
        }
    }
    if (has_mailbox == false)
    {
        QByteArray data, replyData;
        QCString replyType;
        QDataStream ds(data, IO_WriteOnly);
        ds << url;
        // okay, now try to iterate through our proxies
        QStringList::Iterator it = proxyList.begin();
        for ( ; it != proxyList.end(); it++)
        {
            DCOPClient *dcc = kapp->dcopClient();
            if (dcc->call(QCString((*it).ascii()), "kbiff",
                        "hasMailbox(QString)", data, replyType,
                        replyData) == true)
            {
                has_mailbox = true;
                proxy = *it;
                break;
            }
        }
    }

    return has_mailbox;
}

void KBiff::registerMe(DCOPClient *client)
{
    // we need to attach our client before doing anything
    client->attach();

    // if we aren't registered yet, then we will do so.. and be
    // responsible for all *other* kbiff requests, too!
    if (client->isApplicationRegistered("kbiff") == false)
        client->registerAs("kbiff");
    else
    {
        // okay, there is a running kbiff already.  we will let it
        // know that we are active and let it feed us requests
        QCString proxy = QCString("kbiff-") + QCString().setNum(getpid());
        QByteArray params, reply;
        QCString reply_type;
        QDataStream ds(params, IO_WriteOnly);
        ds << proxy;
        client->send("kbiff", "kbiff", "proxyRegister(QString)", params);
        client->registerAs(QCString(proxy));
    }
}

void KBiff::invalidLogin(const QString& mailbox)
{
  QString title(i18n("Invalid Login to %1").arg(mailbox));
  KMessageBox::sorry(0,
    i18n("I was not able to login to the remote server.\n"
         "This means that either the server is down or you have "
         "entered an incorrect username or password.\n"
         "Please make sure that you have entered the correct settings."),
    title);
}

Generated by  Doxygen 1.6.0   Back to index