Russian Qt Forum

Qt => Общие вопросы => Тема начата: kadr от Сентябрь 21, 2010, 07:34



Название: Функция копирования папок с их содержимым!
Отправлено: kadr от Сентябрь 21, 2010, 07:34
Привет всем, у меня есть функция  копирования папок с их содержимым, если копировать папку с файлами, то есть без вложенных папок, то копирует нормально, а если в папке есть вложенные подпапки, то происходит непонятные вещи, все содержимое всех папок копируется и как надо и как не надо! Поясню:
1. Все вхождения копируются аж 2 раза, сначало копируется все правильно, как должно, все файлы в нужных папках и папку тоже в нужных папках.
2. Потом почему то содержимое всех вложенных папок копируется в корень основной папки!
Не пойму в чем дело, вот функция:
Код:
bool Linux_Comander::CopyFolder(QString strFrom, QString strTo)//функция копирования папок с их содержимым.
{
  QDir dir;
  //strFrom - имя папки, откуда  копировать
  //strTo - имя папки, куда  копировать

  //убедимся, что имена заканчиваются слэшем, если нет - добавим
  if (strTo.right(1) != "")
     strTo += '/';
  if (strFrom.right(1) != "")
     strFrom += '/';

  //создаем ("копируем") текущую папку
  QDirIterator itr(strFrom,QDirIterator::Subdirectories);
      if (!dir.mkdir(strTo))
        {
          QMessageBox::information(this,"Ошибка создания","Не удалось создать директорию "+strTo);
          return false;
        }

  //будем перебирать все файлы и папки в текущей директории
  while(itr.hasNext())
  {
      QString strFilePath =  itr.next();
      QString strFileTitle = itr.fileName();

     //отсекаем "." и ".."
     if ((itr.fileName() != ".") && (itr.fileName() != "..") && (itr.fileName() != ""))
     {
         begin->setText("Из: "+strFilePath);
         end->setText("В: "+ strTo + strFileTitle);

         if (itr.fileInfo().isDir())
         {   //рекурсивное погружение в найденную папку (strTo + strFileTitle)
           CopyFolder(strFilePath, strTo + strFileTitle);
         }
        else
         {          
           QFile file(strFilePath),f(strTo + strFileTitle);

           file.open(QIODevice::ReadOnly);//открываем его на чтение
           f.open(QIODevice::WriteOnly);//на запись
           qint64 bytes_write = 0;
           qint64 i = 0;
           bar->setMaximum(file.size());

           while (!file.atEnd())//запускаем цикл в котором файл копируется построчно
            {

               bytes_write = f.write(file.readLine());//построчное записывание
               i += bytes_write;
               bar->setValue(i);

            }
            bar_all->setValue(full_size);
            full_size += f.size();

             if (full_size >=1073741824)
                {
                     bar_size->setText("Скопировано: "+ QString::number(full_size/1073741824) + " Gbyte");
                }
             if (full_size >= 1048576)
                {
                     bar_size->setText("Скопировано: "+ QString::number(full_size/1048576) + " Mbyte");
                }
             if (full_size >= 1024)
                {
                     bar_size->setText("Скопировано: "+ QString::number(full_size/1024) + " Kbyte");
                }
             else
                {
                     bar_size->setText("Скопировано: "+ QString::number(full_size) + " Byte");
                }


            }
       }    
  }

   return true;
}


Название: Re: Функция копирования папок с их содержимым!
Отправлено: kramer3d от Сентябрь 21, 2010, 08:32
Код
C++ (Qt)
 QDirIterator itr(strFrom,QDirIterator::Subdirectories);
 
создает итератор по всей иерархии папок на всю глубину вложенности, так что рекурсия здесь не нужна.


Название: Re: Функция копирования папок с их содержимым!
Отправлено: kadr от Сентябрь 22, 2010, 07:31
блин, никак не получается нормально скопировать папку с ее содержимым, все время какая то фигня не дает, я переделал маленько функцию, убрал рекурсию,  а за место неё написал вот так:
Код:
if (itr.fileInfo().isDir())
         {              
              strTo += strFileTitle;
             if (strTo.right(1) != "")
             {
                 strTo += '/';
             }
             if (!dir.mkdir(strTo))
               {
                 QMessageBox::information(this,"Ошибка создания","Не удалось создать временную директорию "+strTo);
                 return false;
               }
             continue;
         }
Впринципе копирует нормально только те папки, в которых одна подпапка, а если больше одной, то он копирует их  друг в друга, то есть папка должна быть в корневой папке, а она оказывается в следущей, я нашел почему так происходит:
Код:
strTo += strFileTitle;
             if (strTo_Vr.right(1) != "")
             {
                 strTo += '/';
             }
надо как то возвращаться назад, после того как в этой папке больше ничего не осталось копировать, вернуться назад, я так понимаю, или может быть как то по другому это нужно делать, скажите в какую сторону думать то? Заранее спасибо!


Название: Re: Функция копирования папок с их содержимым!
Отправлено: Marat(Qt) от Сентябрь 22, 2010, 13:28
Странная функция... никаких там dir.cd, никаках dir.cdUp... Там везде абсолютные пути чтоли используются? Если да, то зачем?
___________________________
Виноват, поспешил. Итак, имеем итератор:
Код:
 QDirIterator it("/etc", QDirIterator::Subdirectories);
 while (it.hasNext()) {
     qDebug() << it.next();

     // /etc/.
     // /etc/..
     // /etc/X11
     // /etc/X11/fs
     // ...
 }
Цитировать
next ()
Advances the iterator to the next entry, and returns the file path of this new entry
Как я понял, речь идет о полном пути, но есть функция QDirIterator::path() которая в данном примере должна вернуть что-то вроде "/etc", прибавим к этому "/" и вырежем "/etc/" из next, получим относительный путь, который можно и в mkdir кинуть. Ну а для QFile вроде не сложно тут полный путь состряпать, что-то вроде dir.absolutePath()+temp, где temp - относительное имя файла. Ну, может быть перед temp еще надо "/" поставить... в итоге обычный цикл вроде получается.


Название: Re: Функция копирования папок с их содержимым!
Отправлено: kadr от Сентябрь 23, 2010, 10:17
Спасибки, это действительно помогло!


Название: Re: Функция копирования папок с их содержимым!
Отправлено: kadr от Сентябрь 23, 2010, 11:01
У меня есть вот еще вопросик. При копировании файла или папки, вызывается функция в корой создается виджет с прогресс барами:
Код:
void Linux_Comander::progress_bar()//функция отображения хода копирования
{
    QVBoxLayout *laytbar = new QVBoxLayout;
    QVBoxLayout *layt_b = new QVBoxLayout;
    QVBoxLayout *layt_e = new QVBoxLayout;
    QVBoxLayout *layt_size = new QVBoxLayout;
    QHBoxLayout *layt_button = new QHBoxLayout;
    QHBoxLayout *layt_speed = new QHBoxLayout;
    QPushButton *close_but = new QPushButton;
    QPushButton *cancel_but = new QPushButton;



    begin = new QLabel;
    end = new QLabel;
    bar_size = new QLabel;
    block_copy = new QLabel;
    speed = new QLabel;
    prog_dialog = new QWidget;
    bar = new QProgressBar;
    bar_all = new QProgressBar;


    begin->setWordWrap(true);
    end->setWordWrap(true);


    bar_size->setAlignment(Qt::AlignHCenter);
    block_copy->setAlignment(Qt::AlignHCenter);
    speed->setAlignment(Qt::AlignHCenter);

    layt_b->addWidget(begin);
    layt_e->addWidget(end);

    layt_speed->addWidget(block_copy);
    layt_speed->addWidget(speed);
    layt_speed->setAlignment(layt_speed,Qt::AlignHCenter);

    layt_size->addWidget(bar_size);
    layt_size->addLayout(layt_speed);


    layt_button->addWidget(close_but);
    layt_button->addWidget(cancel_but);
    layt_button->setContentsMargins(100,1,100,1);

    laytbar->addLayout(layt_b);
    laytbar->addLayout(layt_e);

    laytbar->addWidget(bar);
    laytbar->addWidget(bar_all);

    laytbar->addLayout(layt_size);
    laytbar->addLayout(layt_button);

    prog_dialog->setLayout(laytbar);
    prog_dialog->setWindowModality(Qt::WindowModal);
    prog_dialog->setGeometry((x/2)-(450/2),(y/2)-(140/2),450,140);//устанавливаем диалог в центре экрана
    prog_dialog->setStyleSheet("background-color: #CCCCCF");//цвет диалога
    prog_dialog->setWindowTitle("Копирование");//заголовок   
    prog_dialog->setFont(QFont("",14,71));


    bar_all->setMaximum(max_bar_all);
    bar->setAlignment(Qt::AlignHCenter);
    bar_all->setAlignment(Qt::AlignHCenter);

    close_but->setText("Закрыть");
    cancel_but->setText("Отменить");

    prog_dialog->show();
   
    connect(cancel_but,SIGNAL(clicked()),prog_dialog,SLOT(deleteLater()));
    connect(close_but,SIGNAL(clicked()),prog_dialog,SLOT(close()));

}
вызываю я ее в самом начале функции
Код:
bool Linux_Comander::CopyFolder(QString strFrom, QString strTo)
{
   progress_bar();
....
....
....
}
Но вот проблема, окно открывается и компаненты на нем появляются по мере использования, то есть, когда появляется сигнал заполнять прогресс бар, он появляется и начинает заполняться, два лабла в которых указаны пути откуда и куда копировать появляются только после тога как скопируется первый файл, и если он большой, то это напрягает, а кнопки вообще появляются в самом конце, когда все скопируется! В чем дело не пойму!


Название: Re: Функция копирования папок с их содержимым!
Отправлено: crossly от Сентябрь 23, 2010, 11:41
processEvents()


Название: Re: Функция копирования папок с их содержимым!
Отправлено: kadr от Сентябрь 23, 2010, 12:57
processEvents()
Не пойму!


Название: Re: Функция копирования папок с их содержимым!
Отправлено: crossly от Сентябрь 23, 2010, 13:45
дык в асистенте написано...


Название: Re: Функция копирования папок с их содержимым!
Отправлено: Marat(Qt) от Сентябрь 24, 2010, 02:36
вызывай эту функцию, скажем, на каждой пятой итерации, ну или меньше, или больше... не знаю, самому не приходилось с ней работать. Идея такая: ты вызвал функцию copyFolder, пока она не выполнится, другие функции выполнятся не будут, обработчики событий, слоты, привязанные к сигналам, все они мирно ждут и бездействуют, пока не выполнится copyFolder, или пока их не вызовут явным образом. А если вызвать processEvents, то он быстренько выполнит обработку событий, выполнит слоты какие надо и вернется к копированию..