Russian Qt Forum

Qt => Общие вопросы => Тема начата: Serewka от Март 11, 2010, 09:46



Название: Портирование с qt3 на qt4.6. Замешательство с QPtrList
Отправлено: Serewka от Март 11, 2010, 09:46
Добрый день! Помогите разобраться в одном моменте.
у QPtrList ест метод take(). В описании метода написано: Takes the current item out of the list without deleting it.
Какой item является current у метода take() без параметров?

Судя по дальнейшему описанию: The item after the removed item becomes the new current list item if the removed item is not the last item in the list. If the last item is removed, the new last item becomes the current item. The current item is set to 0 if the list becomes empty.
Правильно ли я понял, что это - последний элемент?

Вместо QPtrList я использую QList. Каким методом QList заменить QPtrList::take()? QList::takeLast ()?


Название: Re: Портирование с qt3 на qt4.6. Замешательство с QPtrList
Отправлено: pastor от Март 11, 2010, 10:55
Вместо QPtrList я использую QList. Каким методом QList заменить QPtrList::take()? QList::takeLast ()?

QPtrList::take() указывает именно на текущий элемент, а не на последний. Текущий элемент меняется при помощи методов first(), last(), next() и prev(). Так что QPtrList::take() может указывать на любой жлемент листа. Покажи как можно больше кода, который нужно портировать.


Название: Re: Портирование с qt3 на qt4.6. Замешательство с QPtrList
Отправлено: Serewka от Март 11, 2010, 14:16
над данной коллекцией выполняются в основном однотипные операции: append() и clear(), но есть и функции где организуются итераторы посредством first() и next().

привожу места где используется take()

Код:
SipTransaction *SipCall::newRequest( SipCallMember *member, Sip::Method meth,
                                    const QString &body, const MimeContentType &bodytype, const SipUri &referto,
                                    const QString &proxyauthentication, const QString &authentication,int expiresTime, bool shortTr )
{
  SipTransaction *trans = new SipTransaction( lastseq++, member, this );
  if( trans->sendRequest( meth, body, bodytype, referto, shortTr, proxyauthentication, authentication, expiresTime ) ) {
    if(meth == Sip::PRACK)
    {
      transactions.take(); //take out of queue, do NOT delete
    }
    else
    {
      transactions.clear();
    }
    transactions.append( trans );
    if ( meth == Sip::INVITE )
    {
      member->saveinvite = trans;
    }
    // Audit the call
    auditCall();

    // Return the transaction object for tracking
    return trans;
  }
  else
  {
    delete trans;
    return 0;
  }
}

Код:
SipTransaction *SipCall::newPublish(SipCallMember *callMember,const QString state, const QString sipIfMatch, const SipUri &publishserver, int expiresTime, const QString &authentication, const QString &proxyauthentication, const QString &body)
{
  transactions.clear();
  localuri.setTag( QString::null );
  callMember->setUri(localuri);
  SipTransaction *trans = new SipTransaction( lastseq++, callMember, this );
  transactions.append( trans );
  trans->sendPublish(state,
    sipIfMatch,
    publishserver,
    expiresTime,
    authentication,
    proxyauthentication,
    body
    );
  return trans;
}

далее привожу примеры итераторов по коллекции:

Код:
  SipTransaction *curtrans;

  for ( curtrans = transactions.first(); curtrans != 0; curtrans = transactions.next() )
  {
    if (( incominguri == curtrans->getCallMember()->getUri()) &&
      ( seqnum == curtrans->getSeqNum() ) &&
      ( curtrans->getDirection() == SipTransaction::LocalRequest ) )
    {
      SipCallMember *member = getMember( incominguri );
      if( member == NULL )
      {
        if(KStatics::debugLevel>=2)
          cout << "===SipCall::incomingRequest: member null - do nothing\n";
      } else if( message || message->getStatus().getCode() == 202 )
      {
        // Update the Contact for this member
        if( message->getContactList().getListLength() > 0 )
        {
          member->setContactUri( message->getContactList().getHead() );
        }
        // Update the route
        if( message->getRecordRoute().getListLength() > 0 )
        {
          hasroute = true;
          route = message->getRecordRoute();
          route.reverseList();
          if( !route.getHead().uri().contains( ";lr" ) )
          {
            route.addToEnd( member->getContactUri() );
          }
        }
      }
      if( (message->getStatus().getCode() == 200 ) && (calltype == RegisterCall) )
      {
        QString sr = message->getHeaderData( SipHeader::Service_Route);
        if (sr != "")
        {
          KStatics::serviceRoute = sr;
        }
        else
        {
          KStatics::serviceRoute = "";
        }
      }

      curtrans->incomingResponse( message );
      return;
    }
  }

и тут же встает новый вопрос!

правильна ли замена вышепреведенного участка кода следующим?

Код:
  QList<SipTransaction*>::iterator curtrans;

  for (curtrans = transactions.begin(); curtrans != transactions.end(); ++curtrans)
  {
    if (( incominguri == (*curtrans)->getCallMember()->getUri()) &&
      ( seqnum == (*curtrans)->getSeqNum() ) &&
      ( (*curtrans)->getDirection() == SipTransaction::LocalRequest ) )
    {
      SipCallMember *member = getMember( incominguri );
      if( member == NULL )
      {
        if(KStatics::debugLevel>=2)
          cout << "===SipCall::incomingRequest: member null - do nothing\n";
      } else if( message || message->getStatus().getCode() == 202 )
      {
        // Update the Contact for this member
        if( message->getContactList().getListLength() > 0 )
        {
          member->setContactUri( message->getContactList().getHead() );
        }
        // Update the route
        if( message->getRecordRoute().getListLength() > 0 )
        {
          hasroute = true;
          route = message->getRecordRoute();
          route.reverseList();
          if( !route.getHead().uri().contains( ";lr" ) )
          {
            route.addToEnd( member->getContactUri() );
          }
        }
      }
      if( (message->getStatus().getCode() == 200 ) && (calltype == RegisterCall) )
      {
        QString sr = message->getHeaderData( SipHeader::Service_Route);
        if (sr != "")
        {
          KStatics::serviceRoute = sr;
        }
        else
        {
          KStatics::serviceRoute = "";
        }
      }

      (*curtrans)->incomingResponse( message );
      return;
    }
  }


Название: Re: Портирование с qt3 на qt4.6. Замешательство с QPtrList
Отправлено: Serewka от Март 11, 2010, 14:21
еще 2 итератора и их аналоги (под вопросом)

Код:
  SipTransaction *curtrans;

  if( ( message->getMethod() == Sip::ACK ) || ( message->getMethod() == Sip::CANCEL ) )
  {
    for( curtrans = transactions.first(); curtrans != 0; curtrans = transactions.next() )
    {
      if( ( incominguri == curtrans->getCallMember()->getUri() ) &&
        ( seqnum == curtrans->getSeqNum() ) &&
        ( curtrans->getDirection() == SipTransaction::RemoteRequest ) )
      {
        //Request found
        curtrans->incomingRequest( message, true );
        return 0;
      }
    }
    delete message;
    return 0;
  }

  for( curtrans = transactions.first(); curtrans != 0; curtrans = transactions.next() )
  {
    if( ( incominguri == curtrans->getCallMember()->getUri() ) && ( seqnum == curtrans->getSeqNum() ) &&
      ( seqmethod == curtrans->getSeqMethod() ) &&
      ( curtrans->getDirection() == SipTransaction::RemoteRequest ) )
    {
      curtrans->incomingRequestRetransmission( message );
      return 0;
    }
  }


Аналог

Код:
  QList<SipTransaction*>::iterator curtrans;

  if( ( message->getMethod() == Sip::ACK ) || ( message->getMethod() == Sip::CANCEL ) )
  {
    for (curtrans = transactions.begin(); curtrans != transactions.end(); ++curtrans)
    {
      if( ( incominguri == (*curtrans)->getCallMember()->getUri() ) &&
        ( seqnum == (*curtrans)->getSeqNum() ) &&
        ( (*curtrans)->getDirection() == SipTransaction::RemoteRequest ) )
      {
        //Request found
        (*curtrans)->incomingRequest( message, true );
        return 0;
      }
    }
    delete message;
    return 0;
  }

  for (curtrans = transactions.begin(); curtrans != transactions.end(); ++curtrans)
  {
    if( ( incominguri == (*curtrans)->getCallMember()->getUri() ) && ( seqnum == (*curtrans)->getSeqNum() ) &&
      ( seqmethod == (*curtrans)->getSeqMethod() ) &&
      ( (*curtrans)->getDirection() == SipTransaction::RemoteRequest ) )
    {
      (*curtrans)->incomingRequestRetransmission( message );
      return 0;
    }
  }

В остальных случаях над коллекцией выполняется clear() и append(). В совокупности 13 раз. Если того что я предоставил мало, могу скинуть полный код класса.


Название: Re: Портирование с qt3 на qt4.6. Замешательство с QPtrList
Отправлено: pastor от Март 11, 2010, 15:07
А в каком контекстве вызывается newRequest?

По поводу агалога итераторов: вроде все верно. Ты также можешь использовать QMutableListIterator \ QListIterator.

ЗЫ: Взгляни на раздел в ассистанте Porting to Qt 4


Название: Re: Портирование с qt3 на qt4.6. Замешательство с QPtrList
Отправлено: Serewka от Март 12, 2010, 01:27
А в каком контекстве вызывается newRequest?

что имеется ввиду под контекстом?


Название: Re: Портирование с qt3 на qt4.6. Замешательство с QPtrList
Отправлено: pastor от Март 12, 2010, 05:21
что имеется ввиду под контекстом?

покажи код как вызывается этот метод


Название: Re: Портирование с qt3 на qt4.6. Замешательство с QPtrList
Отправлено: Serewka от Март 12, 2010, 10:59
Код:
bool SipCallMember::sendRequestInvite( QString username, QString password )
{
  ourUsername=username;
  ourPassword=password;
  if( !username.isEmpty() && !password.isEmpty() &&
    ( authstate == authState_AuthenticationRequired || authstate == authState_AuthenticationRequiredWithNewPassword || SipCallMember::authState_AuthenticationOK ) ) {
      ourUsername=username;
      ourPassword=password;
      proxyauthresponse=QString::null;
      authresponse=QString::null;
      if( authtype == DigestAuthenticationRequired )
      {
        authresponse = Sip::getDigestResponse(
          username, password, "INVITE", getContactUri().theUri(), proxyauthstr,++nonceCounter );
      }
      else if( authtype == ProxyDigestAuthenticationRequired )
      {
        proxyauthresponse = Sip::getDigestResponse(
          username, password, "INVITE", getContactUri().theUri(), proxyauthstr,++nonceCounter );
      } else if( authtype == ProxyBasicAuthenticationRequired )
      {
        proxyauthresponse = Sip::getBasicResponse( username, password );
      }
      local = call->newRequest( this, Sip::INVITE, localsessiondesc, localsessiontype,
        SipUri::null, proxyauthresponse,authresponse, localExpiresTime );
  }
  else
  {
    local = call->newRequest( this, Sip::INVITE, localsessiondesc, localsessiontype,
      SipUri::null, QString::null, QString::null,localExpiresTime );
  }
  if( localExpiresTime > 0 )
  {
    //timer->start( localExpiresTime * 900, TRUE );
    timer->start( localExpiresTime * 900 );
  }
  if( local )
  {
    op = opRequest;
    if( authstate == authState_AuthenticationRequired ||
      authstate == authState_AuthenticationRequiredWithNewPassword )
    {
        authstate = authState_AuthenticationTryingWithPassword;
    } else if( authstate == SipCallMember::authState_AuthenticationOK)
    {
      ;
    }
    else
    {
      authstate = authState_AuthenticationTrying;
    }
    connect( local, SIGNAL( statusUpdated() ), this, SLOT( localStatusUpdated() ) );
  }
  else
  {
    return false;
  }
  return true;
}


Код:
bool  SipCallMember::requestInvite( const QString &body, const MimeContentType &bodytype )
{
  callMemberType = Invite;
  localsessiondesc = body;
  localsessiontype = bodytype;
  state = state_InviteRequested;
  return sendRequestInvite(ourUsername, ourPassword);
}


Название: Re: Портирование с qt3 на qt4.6. Замешательство с QPtrList
Отправлено: pastor от Март 12, 2010, 14:49
Как я понял, при помощи transactions организуется очередь FIFO. И как по мне transactions.take(); удаляет первый элемент очереди. Мой совет: подебаж Qt3 код, посмотри на что указаывает итератор при transactions.take(). Если это всеже очередь по принципу FIFO, и удалется первый элемент замени QPtrList на QQueue


Название: Re: Портирование с qt3 на qt4.6. Замешательство с QPtrList
Отправлено: Serewka от Март 12, 2010, 16:59
Спасибо за наводку! Буду копать!


Название: Re: Портирование с qt3 на qt4.6. Замешательство с QPtrList
Отправлено: Serewka от Март 12, 2010, 17:15
и еще вопрос!
по использованию в QptrList метода setAutoDelete(true);
как быть в случае QList?


Название: Re: Портирование с qt3 на qt4.6. Замешательство с QPtrList
Отправлено: Dendy от Март 12, 2010, 18:18
Самому явно вызывать delete при удалении элемента из списка и/или qDeleteAll() при очистке контейнера.