Esempio n. 1
0
inline bool KNMusicTagM4a::getBox(QDataStream &musicDataStream,
                                  KNMusicTagM4a::M4ABox &box,
                                  bool ignoreContent)
{
    //Clear the box data.
    clearBox(box);
    //Set the box properties to independet box.
    box.independence=true;
    //Get the size of the box, reduce the 8 bytes size of itself and the name.
    musicDataStream>>box.size;
    box.size-=8;
    //Generate the name field.
    char nameField[5]={0};
    //Get the name of the box.
    if(musicDataStream.readRawData(nameField, 4)==-1)
    {
        //If you cannot read the data, then it's failed to read the box.
        return false;
    }
    //Save the box name.
    box.name=nameField;
    //Get the content, or else we will simply get back.
    if(ignoreContent)
    {
        box.independence=false;
        //Skip the box size data.
        return musicDataStream.skipRawData(box.size);
    }
    //Allocate memory to store the box data.
    box.data=new char[box.size];
    //Read the new data.
    return musicDataStream.readRawData(box.data, box.size);
}
Esempio n. 2
0
  QWidget *MosaicAreaTool::getToolBarWidget() {
    m_latLineEdit = new QLineEdit();
    m_latLineEdit->setValidator(new QDoubleValidator(-90.0, 90.0, 99, this));

    m_lonLineEdit = new QLineEdit();
    m_lonLineEdit->setValidator(new QDoubleValidator(this));

    m_areaLineEdit = new QLineEdit();
    m_areaLineEdit->setValidator(new QDoubleValidator(this));
    m_areaLineEdit->setText("10000");

    QLabel *latLabel = new QLabel("Latitude");
    QLabel *lonLabel = new QLabel("Longitude");
    QLabel *areaLabel = new QLabel("Size (meters)");
    areaLabel->setToolTip("This is the width and the height of the box");

    // Create the action buttons
    QPushButton *okButton = new QPushButton("Update Box");
    connect(okButton, SIGNAL(clicked()), this, SLOT(userChangedBox()));

    QPushButton *clearButton = new QPushButton("Clear Box");
    connect(clearButton, SIGNAL(clicked()), this, SLOT(clearBox()));

    // Put the buttons in a horizontal orientation
    QHBoxLayout *actionLayout = new QHBoxLayout();
    actionLayout->addWidget(latLabel);
    actionLayout->addWidget(m_latLineEdit);
    actionLayout->addWidget(lonLabel);
    actionLayout->addWidget(m_lonLineEdit);
    actionLayout->addWidget(areaLabel);
    actionLayout->addWidget(m_areaLineEdit);
    actionLayout->addWidget(okButton);
    actionLayout->addWidget(clearButton);
    actionLayout->addStretch(1);
    actionLayout->setMargin(0);

    QWidget *toolBarWidget = new QWidget;
    toolBarWidget->setLayout(actionLayout);

    return toolBarWidget;
  }
Esempio n. 3
0
  void MosaicAreaTool::mouseButtonRelease(QPointF mouseLoc, Qt::MouseButton s) {
    if(!isActive())
      return;

    if(s == Qt::LeftButton) {
      TProjection *tproj = (TProjection *) getWidget()->getProjection();

      if(tproj && getWidget()->getView()->sceneRect().contains(mouseLoc)) {
        if(tproj->SetCoordinate(mouseLoc.x(), -1 * mouseLoc.y())) {
          if(m_drawBox != NULL) {
            clearBox();
          }

          m_latLineEdit->setText(QString::number(tproj->Latitude(), 'g', 10));
          m_lonLineEdit->setText(QString::number(tproj->Longitude(), 'g', 10));

          userChangedBox();
        }
      }
    }
  }
Esempio n. 4
0
void MainWindow::on_dropSpreadAbilites_pressed()
{
    clearBox(ui->comboBoxStrength);
    clearBox(ui->comboBoxDexterity);
    clearBox(ui->comboBoxConstitution);
    clearBox(ui->comboBoxIntelligence);
    clearBox(ui->comboBoxWisdom);
    clearBox(ui->comboBoxCharisma);
    listOfCandidatsToBecomeAbility = trueListOfCandidatsToBecomeAbility;
    setupComboBoxes(ui->comboBoxStrength, &listOfCandidatsToBecomeAbility);
    setupComboBoxes(ui->comboBoxDexterity, &listOfCandidatsToBecomeAbility);
    setupComboBoxes(ui->comboBoxConstitution, &listOfCandidatsToBecomeAbility);
    setupComboBoxes(ui->comboBoxIntelligence, &listOfCandidatsToBecomeAbility);
    setupComboBoxes(ui->comboBoxWisdom, &listOfCandidatsToBecomeAbility);
    setupComboBoxes(ui->comboBoxCharisma, &listOfCandidatsToBecomeAbility);
}
Esempio n. 5
0
  void MosaicAreaTool::userChangedBox() {
    bool latValid = false;
    bool lonValid = false;
    bool areaValid = false;

    if(!m_latLineEdit || !m_lonLineEdit || !m_areaLineEdit) {
      clearBox();
      return;
    }

    QString latitude = m_latLineEdit->text();

    if(latitude != "Null" && latitude != "") {
      int cursorPos = 0;
      QValidator::State validLat =
        m_latLineEdit->validator()->validate(latitude, cursorPos);
      if(validLat != QValidator::Acceptable) {
        QMessageBox::warning(getWidget(), "Error",
                            "Latitude value must be in the range -90 to 90",
                            QMessageBox::Ok, QMessageBox::NoButton,
                            QMessageBox::NoButton);
      }
      else {
        latValid = true;
      }
    }

    //Validate longitude value
    QString longitude = m_lonLineEdit->text();
    if(longitude != "Null" && longitude != "" && latValid) {
      int cursorPos = 0;
      QValidator::State validLon =
        m_lonLineEdit->validator()->validate(longitude, cursorPos);
      if(validLon != QValidator::Acceptable) {
        QMessageBox::warning(getWidget(), "Error",
                            "Longitude value invalid",
                            QMessageBox::Ok, QMessageBox::NoButton,
                            QMessageBox::NoButton);
      }
      else {
        lonValid = true;
      }
    }

    QString areaString = m_areaLineEdit->text();
    if(areaString != "Null" && areaString != "" && latValid && lonValid) {
      int cursorPos = 0;
      QValidator::State validArea =
        m_areaLineEdit->validator()->validate(areaString, cursorPos);
      if(validArea != QValidator::Acceptable) {
        QMessageBox::warning(getWidget(), "Error",
                            "Area value invalid",
                            QMessageBox::Ok, QMessageBox::NoButton,
                            QMessageBox::NoButton);
      }
      else {
        areaValid = true;
      }
    }


    if(latValid && lonValid && areaValid) {
      double lat = IString(latitude.toStdString()).ToDouble();
      double lon = IString(longitude.toStdString()).ToDouble();
      double area = IString(areaString.toStdString()).ToDouble();

      Projection *projection = getWidget()->getProjection();
      Projection::ProjectionType ptype = projection->projectionType();

      if (projection && ptype == Projection::Triaxial) {
        TProjection * tproj = (TProjection *) projection;
        if (tproj->SetGround(lat, lon)) {
          QPointF scenePos(projection->XCoord(), -1 * projection->YCoord());
          QRectF sceneRect(getWidget()->getView()->sceneRect());

          if(sceneRect.contains(scenePos)) {
            if(m_box != NULL) {
              clearBox();
            }

            Distance distance(area, Distance::Meters);

            QPolygonF boxPoly;
            QRectF latLonRange = calcLatLonRange(QPointF(lon, lat), distance);

            double xStep = latLonRange.width() / 100.0;
            double yStep = latLonRange.height() / 100.0;

            bool hasPole = (latLonRange.top() == -90 ||
                            latLonRange.bottom() == 90);

            double yPos = latLonRange.top();
            if (yPos != -90) {
              for(double xPos = latLonRange.left();
                xPos <= latLonRange.right();
                xPos += xStep) {
                if (tproj->SetGround(yPos, xPos)) {
                  QPointF pos(tproj->XCoord(), -1 * tproj->YCoord());
                  boxPoly << pos;
                }
              }
            }

            double xPos = latLonRange.right();
            for (double yPos = latLonRange.top();
                !hasPole && yPos <= latLonRange.bottom();
                yPos += yStep) {
              if (tproj->SetGround(yPos, xPos)) {
                QPointF pos(tproj->XCoord(), -1 * tproj->YCoord());
                boxPoly << pos;
              }
            }

            yPos = latLonRange.bottom();
            if (yPos != 90) {
              for (double xPos = latLonRange.right();
                xPos >= latLonRange.left();
                xPos -= xStep) {
                if (tproj->SetGround(yPos, xPos)) {
                  QPointF pos(tproj->XCoord(), -1 * tproj->YCoord());
                  boxPoly << pos;
                }
              }
            }

            xPos = latLonRange.left();
            for (double yPos = latLonRange.bottom();
              !hasPole && yPos >= latLonRange.top();
              yPos -= yStep) {
              if (tproj->SetGround(yPos, xPos)) {
                QPointF pos(tproj->XCoord(), -1 * tproj->YCoord());
                boxPoly << pos;
              }
            }

            if (boxPoly.size() > 0) {
              boxPoly << boxPoly[0];

              m_box = new QGraphicsPolygonItem(boxPoly);
              m_box->setZValue(DBL_MAX);

              getWidget()->getScene()->addItem(m_box);
              getWidget()->getView()->centerOn(scenePos);
            }
          }
          else {
          QString message = "Lat/Lon not within this view.";
          QMessageBox::information(getWidget(), "Cannot Calculate Box",
                                  message, QMessageBox::Ok);
          }
        }
      }
    }
  }
Esempio n. 6
0
bool KNMusicTagM4a::parseTag(QFile &musicFile,
                             QDataStream &musicDataStream,
                             KNMusicAnalysisItem &analysisItem)
{
    Q_UNUSED(musicFile)
    //Some comments is from:
    //      http://atomicparsley.sourceforge.net/mpeg-4files.html
    //The m4a file is made of a number of atoms, now they are called 'boxes'.
    //   A box always begins with 4 bytes length and follows 4 bytes name.
    //And first we need to check the header box of the file. Its name is 'ftyp'
    //Check out the data.
    M4ABox ftypBox;
    if(!getBox(musicDataStream, ftypBox, true) ||
            ftypBox.name!="ftyp")
    {
        //This cannot be a m4a file.
        return false;
    }
    //Metadata to be used with iTunes comes in the ilst box inside the moov box.
    //The structure of the ilst is:
    /* moov         <-
     * |-udta
     * | |-meta
     * | | |-ilst
     */
    //We have to keep reading until we find out the moov box.
    M4ABox moovBox;
    while(moovBox.name!="moov")
    {
        //If we cannot find a box, means there's no "moov" box, return false.
        if(!getBox(musicDataStream, moovBox))
        {
            return true;
        }
    }
    //When we comes to here, we should find the "moov" box, expand the box to
    //find out the "udta" box.
    /* moov
     * |-udta       <-
     * | |-meta
     * | | |-ilst
     */
    QList<M4ABox> expandList;
    extractBox(moovBox, expandList);
    //Check the expand list.
    if(expandList.isEmpty())
    {
        return true;
    }
    //Generate a empty box for "udta" box.
    M4ABox udtaBox;
    //Find all the box of the expand list of the "moov" box.
    for(auto i : expandList)
    {
        //Check the name of each box.
        if(i.name=="udta")
        {
            //Save the udta box.
            udtaBox=i;
            //Make the udta box to independent box.
            independent(udtaBox);
            //Clear the moov box.
            clearBox(moovBox);
            break;
        }
    }
    //Check out the data.
    if(udtaBox.name.isEmpty())
    {
        //If the name of the udta box is still empty, means there's no udta box
        //in the moov box, then we are faild to parse.
        return true;
    }
    //Expand the "udta" box, and find "meta" box.
    /* moov
     * |-udta
     * | |-meta     <-
     * | | |-ilst
     */
    expandList.clear();
    extractBox(udtaBox, expandList);
    //Check the expand list.
    if(expandList.isEmpty())
    {
        return true;
    }
    //Generate a empty box for "meta" box.
    M4ABox metaBox;
    //Find all the box of the expand list of the "meta" box.
    for(auto i : expandList)
    {
        //Check the name of each box.
        if(i.name=="meta")
        {
            //Save the udta box.
            metaBox=i;
            //Make the meta box to independent box.
            independent(metaBox);
            //Clear the udta box.
            clearBox(udtaBox);
            break;
        }
    }
    //Check out the box.
    if(metaBox.name.isEmpty())
    {
        //If the name of the meta box is still empty, means we cannot find meta
        //box in the meta box, then we are finished to parse.
        return true;
    }
    //Okay, now we can parse the meta box.
    /* moov
     * |-udta
     * | |-meta
     * | | |-ilst   <-
     */
    //Generate a box for ilst.
    M4ABox ilstBox;
    //Extract the meta box.
    if(!findIlstBox(metaBox, ilstBox))
    {
        //Finished to parse the tag if we cannot file the ilst box.
        return true;
    }
    //Clear the meta box to recover the memory.
    clearBox(metaBox);
    //Okay we are now find out the ilst box. Extract the ilst box and we can now
    //fill our data to the detail info.
    expandList.clear();
    extractBox(ilstBox, expandList);
    //Check out the expand list.
    if(expandList.isEmpty())
    {
        //If there's no data inside the expand list, then our mission is
        //finished.
        return true;
    }
    //Write the expand list to the detail info.
    //Get the detail info.
    KNMusicDetailInfo &detailInfo=analysisItem.detailInfo;
    //Check all box inside the list.
    for(auto i : expandList)
    {
        //Check the name of the box.
        //If it's "covr", means we find out the album art box.
        if(i.name=="covr")
        {
            analysisItem.imageData["M4A"].append(QByteArray(i.data, i.size));
            //Continue to next box.
            continue;
        }
        //Check the index of the box inside the map.
        int atomIndex=m_atomIndexMap.value(i.name, -1);
        //If the atom index is -1, then we have to continue to the next box.
        if(atomIndex==-1)
        {
            continue;
        }
        //Check the data size.
        if(i.size<16)
        {
            continue;
        }
        //Get the data position.
        //Actually there's another box inside the box of the i.
        //We can just skip it to read the data.
        char *dataPosition=i.data+16;
        int dataSize=i.size-16;
        //Output box data to detail info.
        switch(atomIndex)
        {
        case TrackNumber:
            //Ensure the data is enough to set the track number and track count.
            if(dataSize>6)
            {
                //Pick up the third byte data of the position as the track
                //number.
                detailInfo.textLists[TrackNumber]=
                        QString::number(dataPosition[3]);
                //Pick up the fifth byte data of the position as the track
                //count.
                detailInfo.textLists[TrackCount]=
                        QString::number(dataPosition[5]);
            }
            break;
        case DiscNumber:
            //Ensure the data is enough to set the disc number and disc count.
            if(dataSize>6)
            {
                //Pick up the third byte data of the position as the disc
                //number.
                detailInfo.textLists[DiscNumber]=
                        QString::number(dataPosition[3]);
                //Pick up the fifth byte data of the position as the disc
                //count.
                detailInfo.textLists[DiscCount]=
                        QString::number(dataPosition[5]);
            }
            break;
        case Rating:
            if(dataSize>0)
            {
                //Turn the first byte into the rating data.
                detailInfo.textLists[Rating]=
                        QString::number((quint8)dataPosition[0]);
            }
            break;
        default:
            //Check out the data size first.
            if(dataSize>0)
            {
                //Set the whole data as the text data.
                setTextData(detailInfo.textLists[atomIndex],
                            QByteArray(dataPosition, dataSize));
            }
            break;
        }
    }
    return true;
}
Esempio n. 7
0
bool KNMusicTagM4a::writeTag(const KNMusicAnalysisItem &analysisItem)
{
    //Get the detail info.
    const KNMusicDetailInfo &detailInfo=analysisItem.detailInfo;
    //Prepare and get the music file.
    QFile musicFile(detailInfo.filePath);
    //Open the file as read only mode.
    if(!musicFile.open(QIODevice::ReadOnly))
    {
        //Failed to open the source.
        return false;
    }
    //Generate a temporary file, write the new data to the temporary file.
    QTemporaryFile updatedTagFile;
    //Open the temporary file, if we cannot open the temporary file it will be
    //failed to write the tag.
    if(!updatedTagFile.open())
    {
        //Close the opened music file.
        musicFile.close();
        return false;
    }
    //Generate a data stream for music file.
    QDataStream musicDataStream(&musicFile);
    //Read and copy the fytp box. If the first box isn't fytp box, then ignore
    //the file.
    M4ABox ftypBox;
    if(!getBox(musicDataStream, ftypBox) || ftypBox.name!="ftyp")
    {
        //Close both file.
        musicFile.close();
        updatedTagFile.close();
        //Failed to find a m4a file, return false.
        return false;
    }
    //Write ftyp data to the temporary file.
    writeBox(ftypBox, updatedTagFile);
    //We have to keep reading until we find out the moov box.
    //Output all the other data to updated tag file.
    M4ABox moovBox;
    for(;;)
    {
        //If we can get a new box.
        if(getBox(musicDataStream, moovBox))
        {
            //Check out the name.
            if(moovBox.name=="moov")
            {
                break;
            }
            else
            {
                //Copy the data.
                writeBox(moovBox, updatedTagFile);
            }
        }
        else
        {
            //If we cannot find a box, means there's no "moov" box, failed to
            //write data.
            //Close both file.
            musicFile.close();
            updatedTagFile.close();
            //Failed to find a m4a file, return false.
            return false;
        }
    }
    //When we comes to here, we should find the "moov" box, expand the box to
    //find out the "udta" box.
    QList<M4ABox> moovExpandList;
    extractBox(moovBox, moovExpandList);
    //Generate a empty box for "udta" box.
    M4ABox udtaBox;
    //Check the expand list.
    if(moovExpandList.isEmpty() ||
            !findBox("udta", udtaBox, moovExpandList))
    {
        //If the name of the udta box is still empty, means there's no udta box
        //in the moov box, then we are faild to parse.
        //Close both file.
        musicFile.close();
        updatedTagFile.close();
        //Failed to find a m4a file, return false.
        return false;
    }
    //Expand the "udta" box, and find "meta" box.
    QList<M4ABox> udtaExpandList;
    extractBox(udtaBox, udtaExpandList);
    //Generate a empty box for "meta" box.
    M4ABox metaBox;
    //Check the expand list and find box.
    if(udtaExpandList.isEmpty() ||
            !findBox("meta", metaBox, udtaExpandList))
    {
        //If the name of the meta box is still empty, means we cannot find meta
        //box in the meta box, then we are finished to parse.
        //Close both file.
        musicFile.close();
        updatedTagFile.close();
        //Failed to find a m4a file, return false.
        return false;
    }
    //Okay, now we can parse the meta box.
    //Generate a box for ilst.
    M4ABox ilstBox;
    QList<M4ABox> metaExpandList;
    //Extract the meta box.
    extractMetaBox(metaBox, metaExpandList);
    //Find all box of the expand list.
    if(metaExpandList.isEmpty() ||
            !findBox("ilst", ilstBox, metaExpandList))
    {
        //We cannot find ilst box in the meta box.
        //Close both file.
        musicFile.close();
        updatedTagFile.close();
        //Failed to find a m4a file, return false.
        return false;
    }
    //Prepare the ilst expand list.
    QList<M4ABox> ilstExpandList;
    //Expand the ilst box.
    extractBox(ilstBox, ilstExpandList);

    //Now we have to write data to ilst expand list.
    for(int i=0; i<MusicDataCount; ++i)
    {
        //Get the atom name of current data.
        QString atomName=m_indexAtomMap.value(i, QString());
        //Check if the atom name is empty, then go to the next.
        if(atomName.isEmpty())
        {
            continue;
        }
        //Remove the exist data inside the ilst expand list.
        for(int j=ilstExpandList.size()-1; j>-1; --j)
        {
            //Check the name of the item.
            if(ilstExpandList.at(j).name==atomName)
            {
                //Remove it.
                ilstExpandList.removeAt(j);
            }
        }
        //Generate the raw data.
        QByteArray rawData;
        //Write the data to raw data.
        switch(i)
        {
        case TrackNumber:
            //Append three 0x00 first.
            rawData.append((char)0x00);
            rawData.append((char)0x00);
            rawData.append((char)0x00);
            //Append the track index.
            rawData.append((char)detailInfo.textLists[TrackNumber].toString()
                           .toInt());
            //Append splitter 0x00.
            rawData.append((char)0x00);
            //Append the track count.
            rawData.append((char)detailInfo.textLists[TrackCount].toString()
                           .toInt());
            //Append two 0x00 after.
            rawData.append((char)0x00);
            rawData.append((char)0x00);
            break;
        case DiscNumber:
            //Append three 0x00 first.
            rawData.append((char)0x00);
            rawData.append((char)0x00);
            rawData.append((char)0x00);
            //Append the disc index.
            rawData.append((char)detailInfo.textLists[DiscNumber].toString()
                           .toInt());
            //Append splitter 0x00.
            rawData.append((char)0x00);
            //Append the disc count.
            rawData.append((char)detailInfo.textLists[DiscCount].toString()
                           .toInt());
            //Append two 0x00 after.
            rawData.append((char)0x00);
            rawData.append((char)0x00);
            break;
        case Rating:
            //Append the rating to bytes.
            rawData.append((char)detailInfo.textLists[Rating].toString()
                           .toInt());
            break;
        default:
            //Translate the text data to UTF-8, without BOM.
            rawData=detailInfo.textLists[i].toString().toUtf8();
        }
        //Generate the box.
        ilstExpandList.append(generateItemBox(i, atomName, rawData));
    }
    //Remove all the album art atom.
    for(int j=ilstExpandList.size()-1; j>-1; --j)
    {
        //Check the name of the item.
        if(ilstExpandList.at(j).name=="covr")
        {
            //Remove it.
            ilstExpandList.removeAt(j);
        }
    }
    //Check album art.
    if(!analysisItem.coverImage.isNull())
    {
        //Generate the raw data for the image.
        //Add the png raw data to image data.
        QByteArray imageData;
        QBuffer imageBuffer(&imageData);
        //Open the image buffer.
        imageBuffer.open(QIODevice::WriteOnly);
        //Save the data to image data.
        analysisItem.coverImage.save(&imageBuffer, "PNG");
        //Close the image buffer.
        imageBuffer.close();
        //Check the image data, if the data is not empty, then insert data.
        if(imageData.isEmpty())
        {
            //Generate the flag data.
            char covrFlag[5];
            covrFlag[0]=0x00;
            covrFlag[1]=0x00;
            covrFlag[2]=0x00;
            covrFlag[3]=14;
            //Generate item box, insert to list.
            ilstExpandList.append(generateItemBox(covrFlag, "covr", imageData));
        }
    }
    //Combine the ilst data together.
    M4ABox updatedIlstBox=zipBox("ilst", ilstExpandList);
    //Clear the list and original ilst box.
    ilstExpandList.clear();
    clearBox(ilstBox);
    //Replace the original ilst box.
    for(int i=metaExpandList.size()-1; i>-1; --i)
    {
        //Check the name.
        if(metaExpandList.at(i).name=="ilst")
        {
            //Replace the item.
            metaExpandList.replace(i, updatedIlstBox);
            //Stop searching.
            break;
        }
    }
    //Combine the meta expand list data.
    QByteArray metaRawData=combineBoxList(metaExpandList);
    //Clear up the meta expand list.
    metaExpandList.clear();
    //Append the first four bytes raw data to the meta box raw data.
    metaRawData.prepend(metaBox.data, 4);
    //Clear up the no use meta box.
    clearBox(metaBox);
    clearBox(updatedIlstBox);
    //Set the data to new meta box.
    metaBox.name="meta";
    metaBox.independence=true;
    metaBox.size=metaRawData.size();
    metaBox.data=new char[metaBox.size];
    memcpy(metaBox.data, metaRawData.data(), metaBox.size);
    //Replace the original meta box.
    for(int i=udtaExpandList.size()-1; i>-1; --i)
    {
        //Check the name.
        if(udtaExpandList.at(i).name=="meta")
        {
            //Replace the item.
            udtaExpandList.replace(i, metaBox);
            //Stop Searching.
            break;
        }
    }
    //Combine the udta data together.
    M4ABox updatedUdtaBox=zipBox("udta", udtaExpandList);
    //Clear the list and original udta box.
    udtaExpandList.clear();
    clearBox(udtaBox);
    //Replace the original udta box.
    for(int i=moovExpandList.size()-1; i>-1; --i)
    {
        //Check the name.
        if(moovExpandList.at(i).name=="udta")
        {
            //Replace the item
            moovExpandList.replace(i, updatedUdtaBox);
            //Stop searching.
            break;
        }
    }
    //Combine the moov data together.
    M4ABox updatedMoovBox=zipBox("moov", moovExpandList);
    //Clear the list and original moov box.
    moovExpandList.clear();
    clearBox(moovBox);
    //Write the new moov box to the updated tag file.
    writeBox(updatedMoovBox, updatedTagFile);
    //Clear up the updated moov box.
    clearBox(updatedMoovBox);
    //Copy the left data to the updated tag file.
    //Generate the music data cache.
    char *turboCache=new char[DataCacheSize];
    //Copy the music data from the original music file, copy the
    //MusicDataCacheSize bytes once, until there's no bytes to copy.
    int bytesRead=musicFile.read(turboCache, DataCacheSize);
    while(bytesRead>0)
    {
        //Write the cache to temporary file.
        updatedTagFile.write(turboCache, bytesRead);
        //Read new data from the original file to cache.
        bytesRead=musicFile.read(turboCache, DataCacheSize);
    }
    //Close the music file.
    musicFile.close();
    //Reset the temporary file.
    updatedTagFile.reset();
    //Reopen the music file as write only mode, write all the udpated tag file
    //data to the music file.
    if(!musicFile.open(QIODevice::WriteOnly))
    {
        //Close the updated tag file.
        updatedTagFile.close();
        //Failed to write data.
        return false;
    }
    //Copy data from temporary file to music file.
    bytesRead=updatedTagFile.read(turboCache, DataCacheSize);
    while(bytesRead>0)
    {
        //Write the cache to music file.
        musicFile.write(turboCache, bytesRead);
        //Read new data from cache to the original file.
        bytesRead=updatedTagFile.read(turboCache, DataCacheSize);
    }
    //Close the music file and temporary file.
    musicFile.close();
    updatedTagFile.close();
    //Clear up the turbo memory.
    delete[] turboCache;
    //The tag rewrite is finished.
    return true;
}