Russian Qt Forum

Qt => Общие вопросы => Тема начата: daimon от Декабрь 06, 2009, 18:11



Название: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 06, 2009, 18:11
Как на момент выполнения трудоемкой задачи заблокировать сигналы от кнопок, закрытие окна.....?


Название: Re: Блокирование интерфейса
Отправлено: lit-uriy от Декабрь 06, 2009, 18:33
чтобы юзер выяснил, где ты живёшь и нанял килера?


Название: Re: Блокирование интерфейса
Отправлено: daimon от Декабрь 06, 2009, 18:55
чтобы юзер выяснил, где ты живёшь и нанял килера?
Закроешь окно, а процесс висит- надо это обработать


Название: Re: Блокирование интерфейса
Отправлено: lit-uriy от Декабрь 06, 2009, 19:03
>>Закроешь окно, а процесс висит
не понял, он что внешний, через QProcess создаётся?


Название: Re: Блокирование интерфейса
Отправлено: daimon от Декабрь 06, 2009, 19:11
>>Закроешь окно, а процесс висит
не понял, он что внешний, через QProcess создаётся?
Нет процесс приложения (всё намного проще).


Название: Re: Блокирование интерфейса
Отправлено: lit-uriy от Декабрь 06, 2009, 19:28
А почему висит?
Закрыл окно, приложение не выгрузилось? Может стоит подумать о связи объектов, организовать её так, чтобы все объекты создавалась в конструкторе окна, а не параллельно с ним.
Либо смотреть в сторону свойства quitOnLastWindowClosed


Название: Re: Блокирование интерфейса
Отправлено: daimon от Декабрь 06, 2009, 19:47
А почему висит?
Закрыл окно, приложение не выгрузилось? Может стоит подумать о связи объектов, организовать её так, чтобы все объекты создавалась в конструкторе окна, а не параллельно с ним.
Либо смотреть в сторону свойства quitOnLastWindowClosed
Задача такая:
поставил на копирование много ячеек таблицы
и закрыл окно - в процессе осталось висеть приложение.
Как обработать операцию (копирование) вывести сообщение про операцию и пердложить продолжить прервать?
Как с другой функции (слота) прервать работу другой функции (которая в процессе)?


Название: Re: Блокирование интерфейса
Отправлено: lit-uriy от Декабрь 06, 2009, 20:03
>>и закрыл окно - в процессе осталось висеть приложение.
имеет смысл свернуть в "системный лоток" (tray)

>>Как обработать операцию (копирование) вывести сообщение про операцию и пердложить продолжить прервать?
когда это сообщение нужно выводить, по какому событию?

>>Как с другой функции (слота) прервать работу другой функции (которая в процессе)?
долгие операции лучше помещать в отдельный поток (смотри QThread), если ты так не сделаешь, то твоё приложение будет мёртвым, пока операция не завершится.
примерно так:
Создаёшь свой объект (наследник QThread), передаёшь в его конструктор параметры для выполнения работы.
Для прекращения работы этого потока вызываешь его слот quit() (слоты можно вызывать как обычные функции) и всё


Название: Re: Блокирование интерфейса
Отправлено: daimon от Декабрь 06, 2009, 20:25
>>и закрыл окно - в процессе осталось висеть приложение.
имеет смысл свернуть в "системный лоток" (tray)

>>Как обработать операцию (копирование) вывести сообщение про операцию и пердложить продолжить прервать?
когда это сообщение нужно выводить, по какому событию?

>>Как с другой функции (слота) прервать работу другой функции (которая в процессе)?
долгие операции лучше помещать в отдельный поток (смотри QThread), если ты так не сделаешь, то твоё приложение будет мёртвым, пока операция не завершится.
примерно так:
Создаёшь свой объект (наследник QThread), передаёшь в его конструктор параметры для выполнения работы.
Для прекращения работы этого потока вызываешь его слот quit() (слоты можно вызывать как обычные функции) и всё

Закрыл окно и должен убратся процесс, поэтому и нужно остановить выполнение текущей задачи.
Как узнать какая задача в текущий момент выполняется?


Название: Re: Блокирование интерфейса
Отправлено: lit-uriy от Декабрь 06, 2009, 20:46
>>Как узнать какая задача в текущий момент выполняется?
ты её запускаешь, ты и знать должен


Название: Re: Блокирование интерфейса
Отправлено: daimon от Декабрь 06, 2009, 20:56
>>Как узнать какая задача в текущий момент выполняется?
ты её запускаешь, ты и знать должен
простой пример:
есть три кнопки a b c
три отдельные слота для кнопок for_a() for_b() for(c) - в каждой выполняется большой цикл (не важно)

пользователь запустил программу и нажимает на кнопку a и выполняется for_a() , потом резко на b и запускается for_b()
Как мне в каждом из слотов проверить какая задача или поток в данный момент выполняется и вывести сообщение о текущей задаче (продолжить или прервать работу предыдущей задачи)?
Может создать указатель на поток и каждый раз его присваивать текущему потоку и проверять указывающий поток на работу
 


Название: Re: Блокирование интерфейса
Отправлено: Igors от Декабрь 06, 2009, 21:04
Закрыл окно и должен убратся процесс, поэтому и нужно остановить выполнение текущей задачи.
Как узнать какая задача в текущий момент выполняется?
Выложите ф-цию, которая заполняет таблицу, я Вам добавлю что Вы хотите - нет уже сил отвечать на Ваши вопросы :)


Название: Re: Проблема трудоемких задач (прервать и продолжить)
Отправлено: daimon от Декабрь 06, 2009, 21:15
Закрыл окно и должен убратся процесс, поэтому и нужно остановить выполнение текущей задачи.
Как узнать какая задача в текущий момент выполняется?
Выложите ф-цию, которая заполняет таблицу, я Вам добавлю что Вы хотите - нет уже сил отвечать на Ваши вопросы :)
дело ведь не в заполнении таблицы, а также в копировании, вставке, вырезать, сортировка- вариант с тремя кнопками обопщение



Название: Re: Проблема трудоемких задач (прервать или продолжить)
Отправлено: lit-uriy от Декабрь 06, 2009, 21:27
самое простое, в слоте блокировать все кнопки, и разблокировать кнопку "прервать" (которую следует добавить), пока не прервёшь, другие процессы запустить будет нельзя.


Название: Re: Проблема трудоемких задач (прервать или продолжить)
Отправлено: lit-uriy от Декабрь 06, 2009, 21:29
собственно твоя задача - рядовая, ежедневная, задача программиста на "подумать и сделать"


Название: Re: Проблема трудоемких задач (прервать и продолжить)
Отправлено: Igors от Декабрь 06, 2009, 21:31
дело ведь не в заполнении таблицы, а также в копировании, вставке, вырезать, сортировка- вариант с тремя кнопками обопщение
Значит во всех этих случаях надо использовать один прием, который я Вам покажу завтра (сейчас мне надо уходить) если буду иметь любую из Ваших долгих ф-ций.


Название: Re: Проблема трудоемких задач (прервать или продолжить)
Отправлено: daimon от Декабрь 06, 2009, 22:04
class for_a:public QThread
{Q_OBJECT
signals: void finished();
public:
   void run()
   {
      int b=0;
      for(int i=0; i<10;i++)
         b++;
      emit finished();
      exec();
   }
};
Как сделать чтобы этот поток разрушался сам после завершения работы функции run()?


Название: Re: Проблема трудоемких задач (прервать или продолжить)
Отправлено: daimon от Декабрь 06, 2009, 23:42
Код:
#ifndef THREAD_H
#define THREAD_H

#include <QWidget>
#include "ui_thread.h"
#include <QThread>
#include <QProgressDialog>

class for_a:public QThread
{
public:
void run()
{
setObjectName("for_a");

int b=0;
for(int i=0; i<1000000000;i++)
{b++;}

}
};

class for_b:public QThread
{

public:
void run()
{

setObjectName("for_b");

int b=0;
for(int i=0; i<1000000000;i++)
{b++;}

}

};

class for_c:public QThread
{
public:
void run()
{
             setObjectName("for_c");

           int b=0;
for(int i=0; i<1000000000;i++)
{b++;}

}
};

using namespace Ui;

class thread : public QWidget, public Form
{
Q_OBJECT

public:
for_a th_a;
for_b th_b;
for_c th_c;
QThread *id;
thread(QWidget *parent = 0);
~thread();
public slots:
void slot_a();
void slot_b();
void slot_c();

};

#endif // THREAD_H




#include "thread.h"

thread::thread(QWidget *parent)
: QWidget(parent)
{
setupUi(this);
connect(p_b,SIGNAL(clicked()),SLOT(slot_b()));
connect(p_a,SIGNAL(clicked()),SLOT(slot_a()));
connect(p_c,SIGNAL(clicked()),SLOT(slot_c()));
id=NULL;
}

thread::~thread()
{

}
void thread::slot_a()
{
if(id==NULL)
{
id=&th_a;
th_a.start();

setWindowTitle("ok_a id=NULL");
}
else if(id->isFinished())
{
id=&th_a;
th_a.start();

setWindowTitle("ok_a");

}

else setWindowTitle(id->objectName()+" is working");
}
void thread::slot_b()
{
if(id==NULL)
{
id=&th_b;
th_b.start();

setWindowTitle("ok_b id=NULL");
}
else if(id->isFinished())
{

id=&th_b;
th_b.start();

setWindowTitle("ok_b");
}

else setWindowTitle(id->objectName()+" is working");
}
void thread::slot_c()
{
if(id==NULL)
{

id=&th_c;
th_c.start();

          setWindowTitle("ok_c id=NULL");

}
else if(id->isFinished())
{

id=&th_c;
th_c.start();

setWindowTitle("ok_c");

}

else setWindowTitle(id->objectName()+" is working");
}


#include <QtGui/QApplication>
#include "thread.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
thread w;
w.show();
return a.exec();
}
Можна как нибудь оптимизировать код (условия проверки id, если объединить на первом клике мышкой на кнопке происходит ошибка - id=NULL)


Название: Re: Проблема трудоемких задач (прервать или продолжить)
Отправлено: pastor от Декабрь 06, 2009, 23:51
2 daimon: Зачем ты объявляешь сигнал finished в своих потоках? Этот сингал уже есть:

Цитировать
void QThread::finished ()   [signal]
This signal is emitted when the thread has finished executing.

И ненужно самому его испускать


Название: Re: Проблема трудоемких задач (прервать или продолжить)
Отправлено: daimon от Декабрь 07, 2009, 00:00
2 daimon: Зачем ты объявляешь сигнал finished в своих потоках? Этот сингал уже есть:

Цитировать
void QThread::finished ()   [signal]
This signal is emitted when the thread has finished executing.

И ненужно самому его испускать
Спасибо исправил, а как быть с проверкой id на первом клике мышкой


Название: Re: Проблема трудоемких задач (прервать или продолжить)
Отправлено: pastor от Декабрь 07, 2009, 00:06
Первый клик мышки куда? Чесно сказать непонятно, что ты хочешь


Название: Re: Проблема трудоемких задач (прервать или продолжить)
Отправлено: spectre71 от Декабрь 07, 2009, 00:09
Как сделать чтобы этот поток разрушался сам после завершения работы функции run()?

Цитировать
class MyThread : public QThread {
    Q_OBJECT
  protected:
    MyThread(bool FreeOnComplete = false, QObject * parent = 0);
};

MyThread::MyThread(bool FreeOnComplete, QObject* parent) : QThread(parent) {
  if(FreeOnComplete) {connect(this , SIGNAL(finished()), this , SLOT(deleteLater()));}
}



Название: Re: Проблема трудоемких задач (прервать или продолжить)
Отправлено: daimon от Декабрь 07, 2009, 00:19
Первый клик мышки куда? Чесно сказать непонятно, что ты хочешь
Первый клик на любую из кнопок (и сразу ошибка) - хочу реализовать простой пимер, когда поток начинает работать после того как другой закончил и не иначе.
ошибка
Код:
           if(id==NULL || id->isFinished())
{
id=&th_a;
th_a.start();

setWindowTitle("ok_a");
}
else setWindowTitle(id->objectName()+" is working");
нет ошибки
Код:
     if(id==NULL)
{
id=&th_a;
th_a.start();

setWindowTitle("ok_a id=NULL");
}
else if(id->isFinished())
{
id=&th_a;
th_a.start();

setWindowTitle("ok_a");
}
else setWindowTitle(id->objectName()+" is working");
Последняя реализация кода просто дублируется. Как записать правильно условие?
Проблема id=NULL при запуске и id-isFinished() тогда возвращает ошибку
Может использовать синхронизацию мютексы и семофоры?????
Помогите :-\


Название: Re: Потоки (прервать или продолжить)
Отправлено: daimon от Декабрь 07, 2009, 00:59
Как в потоке отобразить QMessageBox (любой виджет)?


Название: Re: Потоки (прервать или продолжить)
Отправлено: pastor от Декабрь 07, 2009, 01:00
Как в потоке отобразить QMessageBox (любой виджет)?

Никак, это запрещено.


Название: Re: Проблема трудоемких задач (прервать или продолжить)
Отправлено: pastor от Декабрь 07, 2009, 01:02
Первый клик на любую из кнопок (и сразу ошибка)

Какая ошибка?


Название: Re: Проблема трудоемких задач (прервать или продолжить)
Отправлено: daimon от Декабрь 07, 2009, 01:08
Первый клик на любую из кнопок (и сразу ошибка)

Какая ошибка?
Ошибка пропала, пока ошибок нет


Название: Re: Потоки (прервать или продолжить)
Отправлено: daimon от Декабрь 07, 2009, 01:22
Есть функция с виджетами (spreadsheet).
Как узнать работает ли она сейчас и прервать её работу?
Думал потоками - так нельзя виджетов


Название: Re: Потоки (прервать или продолжить)
Отправлено: lit-uriy от Декабрь 07, 2009, 04:22
>>Как сделать чтобы этот поток разрушался сам после завершения работы функции run()?
тут есть момент который нельзя упускать из виду.

посмотри внимательно на функцию main, твоего приложения, как она выполняется. Выходит ли программа из main'а?
если в этой функции вызывается QApplication::exec(), то программа зацикливается внутри него.
Это как раз обработчик событий извне приложения (перетаскивание, щёлканье мышкой по виджетам, ...)
Аналогичная функция есть и у QThread. Если внутри потока ненужно обрабатывать события извне, то можно не вызывать эту функцию. Тем более, что у тебя вся полезная работа выполняется до вызова этой функции.


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 07, 2009, 09:26
А как быть с функциями (слотами) где есть виджеты - их в поток не загонишь (или созжать потоки с синхронизацией с главным потоком)?????


Название: Re: Потоки (прервать или продолжить)
Отправлено: Igors от Декабрь 07, 2009, 10:56
Изначально вопрос был
Как на момент выполнения трудоемкой задачи заблокировать сигналы от кнопок, закрытие окна.....?
Это решается несколькими способами, например очень хорошо смотрится QProgressDialog. Вот старая но хорошая ссылочка http://www.opennet.ru/docs/RUS/qt3_prog/x4064.html (http://www.opennet.ru/docs/RUS/qt3_prog/x4064.html)

daimon, все что Вам нужно это переписать текст из примера (или выложите ф-цию, я добавлю текст). Это займет 5 минут и совершенно незачем вдаваться в нюансы потоков и.т.п. Это не имеет к Вашей задаче никакого отношения.


Название: Re: Потоки (прервать или продолжить)
Отправлено: daimon от Декабрь 07, 2009, 20:47
Изначально вопрос был
Как на момент выполнения трудоемкой задачи заблокировать сигналы от кнопок, закрытие окна.....?
Это решается несколькими способами, например очень хорошо смотрится QProgressDialog. Вот старая но хорошая ссылочка http://www.opennet.ru/docs/RUS/qt3_prog/x4064.html (http://www.opennet.ru/docs/RUS/qt3_prog/x4064.html)

daimon, все что Вам нужно это переписать текст из примера (или выложите ф-цию, я добавлю текст). Это займет 5 минут и совершенно незачем вдаваться в нюансы потоков и.т.п. Это не имеет к Вашей задаче никакого отношения.

Код
C++ (Qt)
bool Spreadsheet::sort_data_with_GUI(const QList<QTableWidgetSelectionRange>& range)
{
if(range.isEmpty())
{return false;}
else
{
for(int it=0;it<range.size();it++)
{
if(range[it].leftColumn()<0||range[it].bottomRow()<0||range[it].rightColumn()<0||range[it].topRow()<0)
{process=0;return false;}
qApp->processEvents();
}
QString error="";
 
for(int it=0;it<range.size();it++)
for(int i=0;i<range[it].rowCount();i++)
for(int j=0;j<range[it].columnCount();j++)
{
 
 
 
if(!item(range[it].topRow()+i ,range[it].leftColumn()+j)||item(range[it].topRow()+i ,range[it].leftColumn()+j)->text()=="")
{error+=tr("item: ")+get_header_label(range[it].leftColumn()+j)+QString::number(range[it].topRow()+i+1)+tr(" - not value\n");}
}
 
if(error!="")
{
QMessageBox  *errorMessageDialog = new QMessageBox(this);
 
errorMessageDialog->setWindowTitle(tr(""));
errorMessageDialog->setText(tr("Invalid item(s) ( ? select Item with valid value)."));
errorMessageDialog->setIcon(QMessageBox::Critical);
 
 
  errorMessageDialog->setDetailedText(error);
 
errorMessageDialog->show();
process=0;return false;
}
 
else
{
 
Dialog_properties_datasheet_sort dialog;
 
QStringList interval_names_for_columns;
 
for(int it=0;it<range.size();it++)
for(int i=range[it].leftColumn();i<=range[it].rightColumn();i++)
{
if(interval_names_for_columns.indexOf(list_names_for_columns ()[i])==-1)interval_names_for_columns+=list_names_for_columns ()[i];qApp->processEvents();}
 
dialog.setColumnRange(interval_names_for_columns);
 
if (dialog.exec())
{
if( !sort_data(range,dialog.get_settings_for_compare_from_dialog()))
{
QMessageBox::information(this,tr("Graphbuilder"),tr("Sort nothing has changed"));
return false;
}
}
return true;
}
}
}
 
}
 
 
 
 
bool Spreadsheet::sort_data(const QList<QTableWidgetSelectionRange>& range, const SpreadsheetCompare &compare)
{
 
if(range.isEmpty())
{return false;}
else
{
for(int it=0;it<range.size();it++)
{
if(range[it].leftColumn()<0||range[it].bottomRow()<0||range[it].rightColumn()<0||range[it].topRow()<0)
{return false;}
qApp->processEvents();
}
 
 
 
 
 
 
QList<int> columns;
QList<int> rows_n;
for(int i=0;i<range.size();i++)
{
for(int col=range[i].leftColumn();col<=range[i].rightColumn();col++)
 
{if(columns.indexOf(col) ==-1) columns.push_back(col);qApp->processEvents();}
for(int row=range[i].topRow();row<=range[i].bottomRow();row++)
{if(rows_n.indexOf(row) ==-1) rows_n.push_back(row);qApp->processEvents();}
}
qSort(columns.begin(),columns.end());
 
qSort(rows_n.begin(),rows_n.end());
 
QList<QStringList> rows;
 
 
 
for(int i=0;i<rows_n.size();i++)
 
{
QStringList row;
 
for(int j=0;j<columns.size();j++)
{
 
if(is_item_in_list_selection_range(range, rows_n[i],  columns[j])==true )
{
if(isError_in_cell(rows_n[i],columns[j])==true)
{return false;}
else if(item(rows_n[i],columns[j]))
{
 
row.push_back(formula(rows_n[i],columns[j]));
}
qApp->processEvents();
}
}
if(row.size()==columns.size()&&row.size()>0)
rows.push_back(row);
 
else
{
rows_n.removeOne(rows_n[i]);
i--;
}
row.clear();
}
 
 
QList<QStringList> temp=rows;
qStableSort(rows.begin(), rows.end(),compare);
 
if(rows==temp) {process=0;return false;}
for(int i=0;i<rows.size();i++)
 
{
 
 
for(int j=0;j<rows[i].size();j++)
{
 
setFormula(rows_n[i], columns[j], rows[i][j]);
qApp->processEvents();
 
}
 
 
}
 
 
 
 
 
 
 somethingChanged();
 
 
return true;
}
 
}

Это две самые страшные функции одна вызывает другую (запускаю слот sort_data_with_GUI(const QList<QTableWidgetSelectionRange>& range) (1 из функций) из mainWindow)
Спасибо за ссылку, хорошо для одного цикла в функции, а как быть с разными операциями в функции

Задача изначально была такова- выполняется функция (долгая операция), если пользователь запускает на выполнение другую операцию выводится сообщение: "Прервать или продолжить?", тоже самое и при закрытии окна при выполнении задачи. При подтверждении прерывания желательно было бы откатить то, что сделала функция (не обязательно), а так прервать выполнение функции; продолжить - продолжение выполнение той задачи. Заранее большое спасибо, хочу сделать просто хорошее приложение (обработать все возможные нюансы).


Название: Re: Потоки (прервать или продолжить)
Отправлено: Igors от Декабрь 07, 2009, 21:39
Это две самые страшные функции одна вызывает другую (запускаю слот sort_data_with_GUI(const QList<QTableWidgetSelectionRange>& range) (1 из функций) из mainWindow)
Спасибо за ссылку, хорошо для одного цикла в функции, а как быть с разными операциями в функции

Задача изначально была такова- выполняется функция (долгая операция), если пользователь запускает на выполнение другую операцию выводится сообщение: "Прервать или продолжить?", тоже самое и при закрытии окна при выполнении задачи. При подтверждении прерывания желательно было бы откатить то, что сделала функция (не обязательно), а так прервать выполнение функции; продолжить - продолжение выполнение той задачи. Заранее большое спасибо, хочу сделать просто хорошее приложение (обработать все возможные нюансы).
Объясните ЗАЧЕМ Вы даете пользователю возможность что-то нажимать если текущая операция не закончена? Все гораздо проще, не придумывайте себе проблем. Началась трудоемкая операция - покажите индикатор QProgressDialog. А поскольку он модальный (см. ссылку) то единственное что пользователь может сделать - нажать cancel и Вы легко это можете отловить (см. ту же ссылку). Все остальное будет зажато модальностью индикатора. Надо переспросить пользователя - не проблема, породитесь от QProgressDialog. Надо откатить операцию - у Вас все на руках, одно удовольствие. Не лезьте в асинхронку, потом полжизни на аптеку будете работать  :)


Название: Re: Потоки (прервать или продолжить)
Отправлено: daimon от Декабрь 07, 2009, 21:51
Это две самые страшные функции одна вызывает другую (запускаю слот sort_data_with_GUI(const QList<QTableWidgetSelectionRange>& range) (1 из функций) из mainWindow)
Спасибо за ссылку, хорошо для одного цикла в функции, а как быть с разными операциями в функции

Задача изначально была такова- выполняется функция (долгая операция), если пользователь запускает на выполнение другую операцию выводится сообщение: "Прервать или продолжить?", тоже самое и при закрытии окна при выполнении задачи. При подтверждении прерывания желательно было бы откатить то, что сделала функция (не обязательно), а так прервать выполнение функции; продолжить - продолжение выполнение той задачи. Заранее большое спасибо, хочу сделать просто хорошее приложение (обработать все возможные нюансы).
Объясните ЗАЧЕМ Вы даете пользователю возможность что-то нажимать если текущая операция не закончена? Все гораздо проще, не придумывайте себе проблем. Началась трудоемкая операция - покажите индикатор QProgressDialog. А поскольку он модальный (см. ссылку) то единственное что пользователь может сделать - нажать cancel и Вы легко это можете отловить (см. ту же ссылку). Все остальное будет зажато модальностью индикатора. Надо переспросить пользователя - не проблема, породитесь от QProgressDialog. Надо откатить операцию - у Вас все на руках, одно удовольствие. Не лезьте в асинхронку, потом полжизни на аптеку будете работать  :)
Как распределить показание прогрессдиалога? Может условно поделить свою функции на проценты выполнения


Название: Re: Потоки (прервать или продолжить)
Отправлено: daimon от Декабрь 07, 2009, 21:57
Можна как-то обойтись именно в функции без прогрессдиалога и светить после выполнения части задачи сигналом value
А в функции, которая вызвала этот слот сделать connect с этим сигналом value и соединить с прогрессдиалогом на вывод текущего прогресса. Но тут проблема как прервать работу той страшной функции в слоте с коннектом.


Название: Re: Потоки (прервать или продолжить)
Отправлено: Igors от Декабрь 07, 2009, 22:19
Можна как-то обойтись именно в функции без прогрессдиалога и светить после выполнения части задачи сигналом value
А в функции, которая вызвала этот слот сделать connect с этим сигналом value и соединить с прогрессдиалогом на вывод текущего прогресса. Но тут проблема как прервать работу той страшной функции в слоте с коннектом.
Зачем "обходиться" без вещи которая делает именно то что Вам нужно? QProgressDialog уже "светит", просто давайте ему setProgress (см. ссылку)

Как распределить показание прогрессдиалога? Может условно поделить свою функции на проценты выполнения
Объявите в начале ф-ции QProgressDialog progress. К каждому processEvents в Ваших ф-циях добавьте:
Код:
 progress.setProgress(it);
..
 qApp->processEvents();
 if (progress.wasCanceled()) {
      return false;
 }
Сделайте это, потом задавайте очередные вопросы (если они возникнут).


Название: Re: Потоки (прервать или продолжить)
Отправлено: daimon от Декабрь 08, 2009, 01:55
Можна как-то обойтись именно в функции без прогрессдиалога и светить после выполнения части задачи сигналом value
А в функции, которая вызвала этот слот сделать connect с этим сигналом value и соединить с прогрессдиалогом на вывод текущего прогресса. Но тут проблема как прервать работу той страшной функции в слоте с коннектом.
Зачем "обходиться" без вещи которая делает именно то что Вам нужно? QProgressDialog уже "светит", просто давайте ему setProgress (см. ссылку)

Как распределить показание прогрессдиалога? Может условно поделить свою функции на проценты выполнения
Объявите в начале ф-ции QProgressDialog progress. К каждому processEvents в Ваших ф-циях добавьте:
Код:
 progress.setProgress(it);
..
 qApp->processEvents();
 if (progress.wasCanceled()) {
      return false;
 }
Сделайте это, потом задавайте очередные вопросы (если они возникнут).

Разбил функцию условно на 6 частей и через часть вывожу по +17%
Я не знаю в каком моменте -строке функции пользователь нажмёт cancel. Как мне обработать cancel? Можна через соединение сигнал-слот, но как я прерву работу функции через другой слот?
Код
C++ (Qt)
bool Spreadsheet::sort_data(const QList<QTableWidgetSelectionRange>& range, const SpreadsheetCompare &compare)
{
 
if(range.isEmpty())
{return false;}
else
{
QProgressDialog *p_d=new QProgressDialog(this);
 
connect(p_d, SIGNAL(canceled()),  this,SLOT(?????return 0));/////////////////////////////////
p_d->setMinimumDuration(1);
 
for(int it=0;it<range.size();it++)
{
if(range[it].leftColumn()<0||range[it].bottomRow()<0||range[it].rightColumn()<0||range[it].topRow()<0)
{return false;}
qApp->processEvents();
}
 
p_d->setValue(17);/////////////////////////////////////////////////////////////////////
 
 
 
 
QList<int> columns;
QList<int> rows_n;
for(int i=0;i<range.size();i++)
{
for(int col=range[i].leftColumn();col<=range[i].rightColumn();col++)
 
{if(columns.indexOf(col) ==-1) columns.push_back(col);qApp->processEvents();}
for(int row=range[i].topRow();row<=range[i].bottomRow();row++)
{if(rows_n.indexOf(row) ==-1) rows_n.push_back(row);qApp->processEvents();}
}
p_d->setValue(34);///////////////////////////////////////////////////////////////////////////////////////
qSort(columns.begin(),columns.end());
p_d->setValue(51);////////////////////////////////////////////////////////////////////////////////////
qSort(rows_n.begin(),rows_n.end());
 
QList<QStringList> rows;
 
 
 
for(int i=0;i<rows_n.size();i++)
 
{
QStringList row;
 
for(int j=0;j<columns.size();j++)
{
 
if(is_item_in_list_selection_range(range, rows_n[i],  columns[j])==true )
{
if(isError_in_cell(rows_n[i],columns[j])==true)
{process=0;return false;}
else if(item(rows_n[i],columns[j]))
{
 
row.push_back(text(rows_n[i],columns[j]));
}
qApp->processEvents();
}
}
if(row.size()==columns.size()&&row.size()>0)
rows.push_back(row);
 
else
{
rows_n.removeOne(rows_n[i]);
i--;
}
row.clear();
}
 
p_d->setValue(68);//////////////////////////////////////////////////////////////
QList<QStringList> temp=rows;
qStableSort(rows.begin(), rows.end(),compare);
p_d->setValue(85);/////////////////////////////////////////////////////////////
if(rows==temp) {return false;}
for(int i=0;i<rows.size();i++)
 
{
 
 
for(int j=0;j<rows[i].size();j++)
{
 
setItem(rows_n[i], columns[j], rows[i][j]);
qApp->processEvents();
 
}
 
p_d->setValue((i*10)/rows.size()+85);//////////////////////////////////////
}
 
 
 
 
 
p_d->setValue(95);/////////////////////////////////////////////////
 //  clearSelection();
somethingChanged();
p_d->setValue(100);/////////////////////////////////////////
 
return true;
}
 
}


Название: Re: Потоки (прервать или продолжить)
Отправлено: Igors от Декабрь 08, 2009, 15:04
Can you read or only write? :)

Вам говорили что диалог должен быть модальным? Просто слушайте и понимайте - и массы вопросов не возникнет. Не надо ничего разбивать, просто заряжайте индикатор для каждой операции, например

Код:
#define UPDATE_STEP	100

bool UpdateProgress( QProgressDialog & progress, int row )
{
if ((row + 1) % UPDATE_STEP) return true; // update once per UPDATE_STEP
progress.setValue(row); // calls processEvents for modal dialog
return progress.wasCanceled();
}

bool Spreadsheet::sort_data( const QList<QTableWidgetSelectionRange> & range, const SpreadsheetCompare & compare )
{
if(range.isEmpty()) return false;

QProgressDialog progress(this);
progess.setModal(true); // should be modal

// check range
progress.setLabelText(tr("Checking range"));
progress.setMaximum(range.size());
for (int it = 0; it < range.size(); it++) {
if (range[it].leftColumn() < 0) return false;
if (range[it].bottomRow() < 0) return false;
if (range[it].rightColumn() < 0) return false;
if (range[it].topRow() < 0) return false;
if (!UpdateProgress(progress, it)) return false;
}

// fill columns
QList<int> columns;
QList<int> rows_n;

progress.setLabelText(tr("Adding rows & columns"));
progress.setMaximum(range.size());
progress.setValue(0);
for(int i = 0; i < range.size(); i++) {
for (int col = range[i].leftColumn(); col <= range[i].rightColumn(); col++)
  if (columns.indexOf(col) == -1) columns.push_back(col);

for(int row = range[i].topRow(); row <= range[i].bottomRow(); row++)
if (rows_n.indexOf(row) == -1) rows_n.push_back(row);

if (!UpdateProgress(progress, i)) return false;
}

// sort
progress.setLabelText(tr("Sorting"));
progress.setMaximum(2);
progress.setValue(0);
qSort(columns.begin(), columns.end());
qSort(rows_n.begin(), rows_n.end());

// add
progress.setLabelText(tr("Adding rows & columns"));
progress.setMaximum(rows_n.size());
progress.setValue(0);
QList<QStringList> rows;
for(int i = 0; i < rows_n.size(); i++) {
if (!UpdateProgress(progress, i)) return false;
QStringList row;
for (int j = 0; j < columns.size(); j++) {
  if (is_item_in_list_selection_range(range, rows_n[i], columns[j])) {
if (isError_in_cell(rows_n[i], columns[j]))
return false;
if (item(rows_n[i], columns[j]))
  row.push_back(text(rows_n[i], columns[j]));
}
}

if (row.size() == columns.size() && row.size() > 0)
rows.push_back(row);
else {
rows_n.removeOne(rows_n[i]);
i--;
}
row.clear();
}

QList<QStringList> temp = rows;
qStableSort(rows.begin(), rows.end(), compare);
if (rows == temp) return false;

// set items
progress.setLabelText(tr("Setting Items"));
progress.setMaximum(rows.size());
progress.setValue(0);
for (int i = 0; i < rows.size(); i++) {
if (!UpdateProgress(progress, i)) return false;
for(int j = 0; j < rows[i].size(); j++)
setItem(rows_n[i], columns[j], rows[i][j]);
}
 
return true;
}


Название: Re: Потоки (прервать или продолжить)
Отправлено: daimon от Декабрь 08, 2009, 23:33
Огромное спасибо буду пробовать ;D


Название: Re: Потоки (прервать или продолжить)
Отправлено: daimon от Декабрь 09, 2009, 22:45
Can you read or only write? :)

Вам говорили что диалог должен быть модальным? Просто слушайте и понимайте - и массы вопросов не возникнет. Не надо ничего разбивать, просто заряжайте индикатор для каждой операции, например

Код:
#define UPDATE_STEP	100

bool UpdateProgress( QProgressDialog & progress, int row )
{
if ((row + 1) % UPDATE_STEP) return true; // update once per UPDATE_STEP
progress.setValue(row); // calls processEvents for modal dialog
return progress.wasCanceled();
}

bool Spreadsheet::sort_data( const QList<QTableWidgetSelectionRange> & range, const SpreadsheetCompare & compare )
{
if(range.isEmpty()) return false;

QProgressDialog progress(this);
progess.setModal(true); // should be modal

// check range
progress.setLabelText(tr("Checking range"));
progress.setMaximum(range.size());
for (int it = 0; it < range.size(); it++) {
if (range[it].leftColumn() < 0) return false;
if (range[it].bottomRow() < 0) return false;
if (range[it].rightColumn() < 0) return false;
if (range[it].topRow() < 0) return false;
if (!UpdateProgress(progress, it)) return false;
}

// fill columns
QList<int> columns;
QList<int> rows_n;

progress.setLabelText(tr("Adding rows & columns"));
progress.setMaximum(range.size());
progress.setValue(0);
for(int i = 0; i < range.size(); i++) {
for (int col = range[i].leftColumn(); col <= range[i].rightColumn(); col++)
  if (columns.indexOf(col) == -1) columns.push_back(col);

for(int row = range[i].topRow(); row <= range[i].bottomRow(); row++)
if (rows_n.indexOf(row) == -1) rows_n.push_back(row);

if (!UpdateProgress(progress, i)) return false;
}

// sort
progress.setLabelText(tr("Sorting"));
progress.setMaximum(2);
progress.setValue(0);
qSort(columns.begin(), columns.end());
qSort(rows_n.begin(), rows_n.end());

// add
progress.setLabelText(tr("Adding rows & columns"));
progress.setMaximum(rows_n.size());
progress.setValue(0);
QList<QStringList> rows;
for(int i = 0; i < rows_n.size(); i++) {
if (!UpdateProgress(progress, i)) return false;
QStringList row;
for (int j = 0; j < columns.size(); j++) {
  if (is_item_in_list_selection_range(range, rows_n[i], columns[j])) {
if (isError_in_cell(rows_n[i], columns[j]))
return false;
if (item(rows_n[i], columns[j]))
  row.push_back(text(rows_n[i], columns[j]));
}
}

if (row.size() == columns.size() && row.size() > 0)
rows.push_back(row);
else {
rows_n.removeOne(rows_n[i]);
i--;
}
row.clear();
}

QList<QStringList> temp = rows;
qStableSort(rows.begin(), rows.end(), compare);
if (rows == temp) return false;

// set items
progress.setLabelText(tr("Setting Items"));
progress.setMaximum(rows.size());
progress.setValue(0);
for (int i = 0; i < rows.size(); i++) {
if (!UpdateProgress(progress, i)) return false;
for(int j = 0; j < rows[i].size(); j++)
setItem(rows_n[i], columns[j], rows[i][j]);
}
 
return true;
}
Как по мне надо сделать маленькие изменения
Код
C++ (Qt)
if ((row+1 ) % UPDATE_STEP) return false;
if (UpdateProgress(progress, it)) return false; каждую проверку заменить


Название: Re: Потоки (прервать или продолжить)
Отправлено: Igors от Декабрь 09, 2009, 23:00
Как по мне надо сделать маленькие изменения
Код
C++ (Qt)
if ((row+1 ) % UPDATE_STEP) return false;
if (UpdateProgress(progress, it)) return false; каждую проверку заменить
Почему нет? Но тогда измените название - не UpdateProgress, а, например, UserCancel.

И еще: не прессуйте текст типа (row+1) - это выглядит как зажатый зародыш в утробе матери :) Что Вам, пробелов жалко? Пишите со вкусом, покажите всем что Вы хотели сказать, не жмитесь к стенке :)


Название: Re: Потоки (прервать или продолжить)
Отправлено: daimon от Декабрь 10, 2009, 00:37
У меня в конце той страшной функции вызывается функция  somethingChanged(), которая тоже долго вычисляется. Как тогда быть в таком случае с прогресс диалогом (проверкой на отмену)? Ну например ещё qSort...
UpdateProgress(progress, i)


Название: Re: Потоки (прервать или продолжить)
Отправлено: Igors от Декабрь 10, 2009, 01:13
У меня в конце той страшной функции вызывается функция  somethingChanged(), которая тоже долго вычисляется. Как тогда быть в таком случае с прогресс диалогом (проверкой на отмену)? Ну например ещё qSort...
UpdateProgress(progress, i)
Ну и подайте ей progress (QProgressDialog) как аргумент, напр. опишите ее так
Код:
bool somethingChanged( QProgressDialog & progress );

// вызов
if (!somethingChanged(progress)) return false;

А внутри ф-ции работайте в том же стиле, заряжайте индикатор и все дела. Насчет сортировки - да, это не обновит индикатор, ну так что с того - не все операции могут быть прерваны, это нормально. И вообще, что это за философия такая "страшная ф-ция" и.т.п? Это они должны Вас бояться а не Вы их :)


Название: Re: Потоки (прервать или продолжить)
Отправлено: daimon от Декабрь 10, 2009, 01:26
У меня в конце той страшной функции вызывается функция  somethingChanged(), которая тоже долго вычисляется. Как тогда быть в таком случае с прогресс диалогом (проверкой на отмену)? Ну например ещё qSort...
UpdateProgress(progress, i)
Ну и подайте ей progress (QProgressDialog) как аргумент, напр. опишите ее так
Код:
bool somethingChanged( QProgressDialog & progress );

// вызов
if (!somethingChanged(progress)) return false;
А внутри ф-ции работайте в том же стиле, заряжайте индикатор и все дела. Насчет сортировки - да, это не обновит индикатор, ну так что с того - не все операции могут быть прерваны, это нормально. И вообще, что это за философия такая "страшная ф-ция" и.т.п? Это они должны Вас бояться а не Вы их :)

Страшная функция - не оптимизирована страшно, краткая характеристика. Думаю как упрастить.
Что можна заменить на более быстродействующее?
Смысл работы: передаю список выделений итемов, составляю список выделенных колонок и строк; по этому списку формирую список итемов для сортировки, сортирую полученный список и устанавливаю эти итемы в выделенные колонки/строки. Списков много, как уменьшить. Преимущество такой сортировки ячеек для таблицы - могу сортировать разные колонки, находящиеся не рядом (поэтому и список выделений selectionRange) и могу выделять ячейки с помощью Ctrl , недостатки для колонки 10000 итемов сортирует долго
Кто чем может помогите? :(


Название: Re: Потоки (прервать или продолжить)
Отправлено: Igors от Декабрь 10, 2009, 11:45
Страшная функция - не оптимизирована страшно, краткая характеристика. Думаю как упрастить.
Что можна заменить на более быстродействующее?
Смысл работы: передаю список выделений итемов, составляю список выделенных колонок и строк; по этому списку формирую список итемов для сортировки, сортирую полученный список и устанавливаю эти итемы в выделенные колонки/строки. Списков много, как уменьшить. Преимущество такой сортировки ячеек для таблицы - могу сортировать разные колонки, находящиеся не рядом (поэтому и список выделений selectionRange) и могу выделять ячейки с помощью Ctrl , недостатки для колонки 10000 итемов сортирует долго
Кто чем может помогите? :(
10 тысяч итемов - для сортировки не объем, если Вы сортируете грамотно это должно выполняться за доли секунды. Для начала проверьте что все списки/контейнеры подаются по ссылке. Не поможет - выкладывайте Вашу "страшную ф-цию", будем смотреть.


Название: Re: Потоки (прервать или продолжить)
Отправлено: daimon от Декабрь 10, 2009, 21:28
Страшная функция - не оптимизирована страшно, краткая характеристика. Думаю как упрастить.
Что можна заменить на более быстродействующее?
Смысл работы: передаю список выделений итемов, составляю список выделенных колонок и строк; по этому списку формирую список итемов для сортировки, сортирую полученный список и устанавливаю эти итемы в выделенные колонки/строки. Списков много, как уменьшить. Преимущество такой сортировки ячеек для таблицы - могу сортировать разные колонки, находящиеся не рядом (поэтому и список выделений selectionRange) и могу выделять ячейки с помощью Ctrl , недостатки для колонки 10000 итемов сортирует долго
Кто чем может помогите? :(
10 тысяч итемов - для сортировки не объем, если Вы сортируете грамотно это должно выполняться за доли секунды. Для начала проверьте что все списки/контейнеры подаются по ссылке. Не поможет - выкладывайте Вашу "страшную ф-цию", будем смотреть.
Проблема даже не в сортировке, а в обновлении всех значений таблицы после сортировки somethingChanged(), если таблица 10000*10000 обновляется минуты 2 (обновляю потому, что после сортировки некоторые ячейки изменились - нужно изменить зависящие от этих ячеек другие ячейки). Сама функция
Код
C++ (Qt)
#define UPDATE_STEP 100
 
bool UpdateProgress( QProgressDialog & progress, int row )
{
int k=1% 100;
if ((row+1 ) % UPDATE_STEP) return false; // update once per UPDATE_STEP
progress.setValue(row); // calls processEvents for modal dialog
return progress.wasCanceled();
}
 
bool Spreadsheet::sort_data(const QList<QTableWidgetSelectionRange>& range, const SpreadsheetCompare &compare)
{
 
if(range.isEmpty())
{return false;}
else
{
QProgressDialog progress(this);
progress.setModal(true);
progress.setWindowFlags(Qt::Dialog|Qt::CustomizeWindowHint|Qt::WindowTitleHint);
 
progress.setMinimumDuration(1);
progress.setLabelText(tr("Checking range 1/5"));
progress.setMaximum(range.size());
for(int it=0;it<range.size();it++)
{
if(range[it].leftColumn()<0||range[it].bottomRow()<0||range[it].rightColumn()<0||range[it].topRow()<0)
{return false;}
qApp->processEvents();
if (UpdateProgress(progress, it)) return false;
}
progress.setLabelText(tr("Adding rows & columns 2/5"));
progress.setMaximum(range.size());
progress.setValue(0);
 
 
 
 
QList<int> columns;
QList<int> rows;
for(int i=0;i<range.size();i++)
{
for(int col=range[i].leftColumn();col<=range[i].rightColumn();col++)
 
{if(columns.indexOf(col) ==-1) columns.push_back(col);qApp->processEvents();}
for(int row=range[i].topRow();row<=range[i].bottomRow();row++)
{if(rows.indexOf(row) ==-1) rows.push_back(row);qApp->processEvents();}
if (UpdateProgress(progress, i)) return false;
}
progress.setLabelText(tr("Sorting 3/5"));
progress.setMaximum(2);
progress.setValue(0);
qSort(columns.begin(),columns.end());
 
qSort(rows.begin(),rows.end());
 
QList<QList<QTableWidgetItem*>> data_for_sort;
progress.setLabelText(tr("Adding rows & columns 4/5"));
progress.setMaximum(rows.size());
progress.setValue(0);
 
 
for(int i=0;i<rows.size();i++)
 
{
if (UpdateProgress(progress, i)) return false;
QList<QTableWidgetItem*> row;
 
for(int j=0;j<columns.size();j++)
{
 
if(is_item_in_list_selection_range(range, rows[i],  columns[j])==true )
{
if(isError_in_cell(rows[i],columns[j])==true)
{return false;}
else if(item(rows[i],columns[j]))
{
 
row.push_back(takeItem(rows[i],columns[j]));
}
qApp->processEvents();
}
}
if(row.size()==columns.size()&&row.size()>0)
data_for_sort.push_back(row);
 
else
{
rows.removeOne(rows[i]);
i--;
}
row.clear();
}
 
 
QList<QList<QTableWidgetItem*>> temp=data_for_sort;
qStableSort(data_for_sort.begin(), data_for_sort.end(),compare);
 
if(data_for_sort==temp) {return false;}
 
set_calculate_function(true);
progress.setLabelText(tr("Setting Items 5/5"));
progress.setMaximum(rows.size());
progress.setValue(0);
for(int i=0;i<data_for_sort.size();i++)
 
{
 
 
for(int j=0;j<data_for_sort[i].size();j++)
{
if (UpdateProgress(progress, i)) return false;
//setFormula(rows[i], columns[j], data_for_sort[i][j]->data(Qt::EditRole).toString());
setItem(rows[i],columns[j],data_for_sort[i][j]);
qApp->processEvents();
 
 
}
 
// progress.setValue(((i)*10)/rows.size()+85);
}
 
set_calculate_function(false);
 
 
 
//progress.setValue(95);
 //  clearSelection();
 
progress.setValue(100);
if(! somethingChanged(progress,true)) return false;
//progress.setValue(100);
progress.cancel();
return true;
}
 
}
 
 
bool Spreadsheet::somethingChanged(QProgressDialog &progress,bool update)
{
if (autoRecalc&&!bool_calculate_function||update)
if(!recalculate(progress)) return false;
  if(!bool_calculate_function||update)
emit modified();
return true;
 
}
 
 
bool Spreadsheet::recalculate(QProgressDialog &progress) //мое работает
{
 
progress.setRange(0,RowCount);
for (int row = 0; row < RowCount; ++row) {
 
for (int column = 0; column < ColumnCount; ++column)
{
if (UpdateProgress(progress, row)) return false;
if( item(row, column))
if(item(row,column)->text()!="")
cell(row, column)->setDirty();
qApp->processEvents();
 
}
}
  viewport()-> update();
  return true;
 
}
 
class SpreadsheetCompare
{
public:
   bool operator()(const QList<QTableWidgetItem*> &row1,
                   const QList<QTableWidgetItem*> &row2) const
{
 
        int column = keys;
       if (column != -1) {
           if (row1[column] != row2[column])
{
parser p;
 
 
               if (ascending)
return row1[column]->text().toDouble()< row2[column]->text().toDouble();//*///p.calculation(row1[column].toStdString().c_str()) < p.calculation(row2[column].toStdString().c_str());
                else
                   return row1[column]->text().toDouble()> row2[column]->text().toDouble();//*///p.calculation(row1[column].toStdString().c_str()) > p.calculation(row2[column].toStdString().c_str());
 
           }
 
   }
   return false;
}
 
 
 
   int keys;
   bool ascending;
};
compare - ключ для сортировки


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 12, 2009, 00:02
Кто может помогите?


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: Igors от Декабрь 12, 2009, 01:20
Кто может помогите?
Я не "придираюсь" но с таким текстом как у Вас желание помочь быстро пропадает. Отрихтуйте, почистите

Код:
if (UpdateProgress(progress, i)) return false;	
Неудачное название если ф-ция возвращает false

- processEvents ест время ничего не делает (поскольку UpdateProgess это решает)

 "== true" выглядит не очень естественно
 
- текст должен выглядеть ровно (а не как бык поссал)
 
- возможно что тормоза в is_item_in_list_selection_range, покажите ее тоже

Вот когда все подправите - тогда и поговорим.


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 12, 2009, 02:36
Кто может помогите?
Я не "придираюсь" но с таким текстом как у Вас желание помочь быстро пропадает. Отрихтуйте, почистите

-  
Код:
if (UpdateProgress(progress, i)) return false;	
Неудачное название если ф-ция возвращает false

- processEvents ест время ничего не делает (поскольку UpdateProgess это решает)

 "== true" выглядит не очень естественно
 
- текст должен выглядеть ровно (а не как бык поссал)
 
- возможно что тормоза в is_item_in_list_selection_range, покажите ее тоже

Вот когда все подправите - тогда и поговорим.
- processEvents ест время ничего не делает (поскольку UpdateProgess это решает) объясните строку не понятно


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 12, 2009, 03:11
Вроде функцию подогнал под читабельность. Кто может как улучшить код? :(

Код
C++ (Qt)
bool Spreadsheet::is_item_in_list_selection_range(const QList<QTableWidgetSelectionRange>& range, int row_, int column)
{
if(range.isEmpty())
return false;
else
{
for(int it=0;it<range.size();it++)
{
if(range[it].leftColumn()<0||range[it].bottomRow()<0||range[it].rightColumn()<0||range[it].topRow()<0) return false;
qApp->processEvents();
}
for(int i=0;i<range.size();i++)
{
for(int col=range[i].leftColumn();col<=range[i].rightColumn();col++)
{
for(int row=range[i].topRow();row<=range[i].bottomRow();row++)
{
if(col==column&&row==row_) return true;
qApp->processEvents();
}
}
}
return false;
}
}
bool Spreadsheet::sort_data_with_GUI(const QList<QTableWidgetSelectionRange>& range)
{
if(range.isEmpty()) return false;
else
{
for(int it=0;it<range.size();it++)
{
if(range[it].leftColumn()<0||range[it].bottomRow()<0||range[it].rightColumn()<0||range[it].topRow()<0) return false;
qApp->processEvents();
}
QString error="";
 
for(int it=0;it<range.size();it++)
for(int i=0;i<range[it].rowCount();i++)
for(int j=0;j<range[it].columnCount();j++)
{
if(!item(range[it].topRow()+i ,range[it].leftColumn()+j)||item(range[it].topRow()+i ,range[it].leftColumn()+j)->text()=="")
{
error+=tr("item: ")+get_header_label(range[it].leftColumn()+j)+QString::number(range[it].topRow()+i+1)+tr(" - not value\n");}
}
if(error!="")
{
QMessageBox  *errorMessageDialog = new QMessageBox(this);
errorMessageDialog->setWindowTitle(tr(""));
errorMessageDialog->setText(tr("Invalid item(s) ( ? select Item with valid value)."));
errorMessageDialog->setIcon(QMessageBox::Critical);
  errorMessageDialog->setDetailedText(error);
errorMessageDialog->show();
return false;
}
else
{
Dialog_properties_datasheet_sort dialog;
QStringList interval_names_for_columns;
for(int it=0;it<range.size();it++)
for(int i=range[it].leftColumn();i<=range[it].rightColumn();i++)
{
if(interval_names_for_columns.indexOf(list_names_for_columns ()[i])==-1)interval_names_for_columns+=list_names_for_columns ()[i];
qApp->processEvents();
}
    dialog.setColumnRange(interval_names_for_columns);
if (dialog.exec())
{
if( !sort_data(range,dialog.get_settings_for_compare_from_dialog()))
{
QMessageBox::information(this,tr("Graphbuilder"),tr("Sort nothing has changed or cancel"));
return false;
}
}
return true;
}
}
}
#define UPDATE_STEP 100
 
bool UpdateProgress( QProgressDialog & progress, int row )
{
int k=1% 100;
if ((row+1 ) % UPDATE_STEP) return true; // update once per UPDATE_STEP
progress.setValue(row); // calls processEvents for modal dialog
return !progress.wasCanceled();
}
 
bool Spreadsheet::sort_data(const QList<QTableWidgetSelectionRange>& range, const SpreadsheetCompare &compare)
{
if(range.isEmpty())
return false;
else
{
QProgressDialog progress(this);
progress.setModal(true);
progress.setWindowFlags(Qt::Dialog|Qt::CustomizeWindowHint|Qt::WindowTitleHint);
progress.setMinimumDuration(1);
progress.setLabelText(tr("Checking range 1/5"));
progress.setMaximum(range.size());
for(int it=0;it<range.size();it++)
{
if(range[it].leftColumn()<0||range[it].bottomRow()<0||range[it].rightColumn()<0||range[it].topRow()<0) return false;
//qApp->processEvents();
if (!UpdateProgress(progress, it)) return false;
}
progress.setLabelText(tr("Adding rows & columns 2/5"));
progress.setMaximum(range.size());
progress.setValue(0);
QList<int> columns;
QList<int> rows;
for(int i=0;i<range.size();i++)
{
for(int col=range[i].leftColumn();col<=range[i].rightColumn();col++)
{if(columns.indexOf(col) ==-1) columns.push_back(col);qApp->processEvents();}
for(int row=range[i].topRow();row<=range[i].bottomRow();row++)
{if(rows.indexOf(row) ==-1) rows.push_back(row);qApp->processEvents();}
if (!UpdateProgress(progress, i)) return false;
}
progress.setLabelText(tr("Sorting 3/5"));
progress.setMaximum(2);
progress.setValue(0);
qSort(columns.begin(),columns.end());
qSort(rows.begin(),rows.end());
QList<QList<QTableWidgetItem*>> data_for_sort;
progress.setLabelText(tr("Adding data to sort 4/5"));
progress.setMaximum(rows.size());
progress.setValue(0);
 
for(int i=0;i<rows.size();i++)
{
if (!UpdateProgress(progress, i)) return false;
QList<QTableWidgetItem*> row;
 
for(int j=0;j<columns.size();j++)
{
if(is_item_in_list_selection_range(range, rows[i],  columns[j])==true )
{
if(isError_in_cell(rows[i],columns[j])==true)
return false;
else if(item(rows[i],columns[j]))
row.push_back(takeItem(rows[i],columns[j]));
 
// qApp->processEvents();
}
}
if(row.size()==columns.size()&&row.size()>0)
data_for_sort.push_back(row);
else
{
rows.removeOne(rows[i]);
i--;
}
row.clear();
}
 
QList<QList<QTableWidgetItem*>> temp=data_for_sort;
qStableSort(data_for_sort.begin(), data_for_sort.end(),compare);
 
if(data_for_sort==temp) return false;
 
set_calculate_function(true);
progress.setLabelText(tr("Setting Items 5/5"));
progress.setMaximum(rows.size());
progress.setValue(0);
for(int i=0;i<data_for_sort.size();i++)
{
for(int j=0;j<data_for_sort[i].size();j++)
{
if (!UpdateProgress(progress, i)) return false;
//setFormula(rows[i], columns[j], data_for_sort[i][j]->data(Qt::EditRole).toString());
setItem(rows[i],columns[j],data_for_sort[i][j]);
//qApp->processEvents();
}
}
 
set_calculate_function(false);/////разрешает обновлять ячейки таблицы (true - запрещает).
progress.setValue(100);
if(! somethingChanged(progress,true)) return false;
//progress.setValue(100);
return true;
}
}
 
bool Spreadsheet::somethingChanged(QProgressDialog &progress,bool update)
{
if (autoRecalc&&!bool_calculate_function||update)
if(!recalculate(progress)) return false;
if(!bool_calculate_function||update)
emit modified();
return true;
}
 
bool Spreadsheet::recalculate(QProgressDialog &progress) //мое работает
{
progress.setRange(0,RowCount);
for (int row = 0; row < RowCount; ++row)
{
for (int column = 0; column < ColumnCount; ++column)
{
if (!UpdateProgress(progress, row)) return false;
if( item(row, column))
if(item(row,column)->text()!="")
cell(row, column)->setDirty();
qApp->processEvents();
}
}
  viewport()-> update();
  return true;
}
 
class SpreadsheetCompare
{
public:
int keys;
   bool ascending;
   bool operator()(const QList<QTableWidgetItem*> &row1, const QList<QTableWidgetItem*> &row2) const
{
int column = keys;
       if (column != -1)
{
           if (row1[column] != row2[column])
{
       if (ascending)
return row1[column]->text().toDouble()< row2[column]->text().toDouble();
                else
                   return row1[column]->text().toDouble()> row2[column]->text().toDouble();
           }
}
return false;
}
};


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 12, 2009, 12:10
Медленней всего работают операции серии "Adding data to sort 4/5". Как можно улучшить?


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: Igors от Декабрь 12, 2009, 14:23
Вроде функцию подогнал под читабельность. Кто может как улучшить код? :(
1) Уберите ВСЕ вызовы processEvents - везде. Посмотрите и подумайте зачем нужен UPDATE_STEP

2) Не создавайте избыточного кода методом copy/paste. Попробуйте так
Код
C++ (Qt)
bool Spreadsheet::is_item_in_list_selection_range(const QList<QTableWidgetSelectionRange>& range, int row_, int column)
{
for(int i = 0 ; i < range.size(); i++) {
if (row_ < range[i].topRow()) continue;
if (row_ > range[i].bottomRow()) continue;
if (column < range[i].leftColumn()) continue;
if (column > range[i].rightColumn()) continue;
return true;
}
return false;
}


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 12, 2009, 19:23
Вроде функцию подогнал под читабельность. Кто может как улучшить код? :(
1) Уберите ВСЕ вызовы processEvents - везде. Посмотрите и подумайте зачем нужен UPDATE_STEP

2) Не создавайте избыточного кода методом copy/paste. Попробуйте так
Код
C++ (Qt)
bool Spreadsheet::is_item_in_list_selection_range(const QList<QTableWidgetSelectionRange>& range, int row_, int column)
{
for(int i = 0 ; i < range.size(); i++) {
if (row_ < range[i].topRow()) continue;
if (row_ > range[i].bottomRow()) continue;
if (column < range[i].leftColumn()) continue;
if (column > range[i].rightColumn()) continue;
return true;
}
return false;
}

Очень умное решение :o


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 12, 2009, 19:33
Код
C++ (Qt)
void Spreadsheet::setRowCount(int count_,QProgressDialog &dialog) //мое работает
{
dialog.setLabelText(tr("set Row"));
dialog.setRange(0,0);
dialog.setValue(0);
dialog.setMinimumDuration(1);
QTableWidget::setRowCount(count_);
RowCount=count_;
 
}
При установке большого числа строк возникает зависание приложения на 3 сек. Как в эти 3 сек выводить QProgressDialog со свойствами: setRange(0,0), setValue(0)? Заранее спасибо


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: Igors от Декабрь 12, 2009, 19:57
Код
C++ (Qt)
void Spreadsheet::setRowCount(int count_,QProgressDialog &dialog) //мое работает
{
dialog.setLabelText(tr("set Row"));
dialog.setRange(0,0);
dialog.setValue(0);
dialog.setMinimumDuration(1);
QTableWidget::setRowCount(count_);
RowCount=count_;
 
}
При установке большого числа строк возникает зависание приложения на 3 сек. Как в эти 3 сек выводить QProgressDialog со свойствами: setRange(0,0), setValue(0)? Заранее спасибо
Число шагов известно, значит надо использовать setRange(0, count_).
Метод setRowCount позовет метод модели insertRows, вот там и обновляйте QProgressDialog


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 12, 2009, 20:26
Код
C++ (Qt)
void Spreadsheet::setRowCount(int count_,QProgressDialog &dialog) //мое работает
{
dialog.setLabelText(tr("set Row"));
dialog.setRange(0,0);
dialog.setValue(0);
dialog.setMinimumDuration(1);
QTableWidget::setRowCount(count_);
RowCount=count_;
 
}
При установке большого числа строк возникает зависание приложения на 3 сек. Как в эти 3 сек выводить QProgressDialog со свойствами: setRange(0,0), setValue(0)? Заранее спасибо
Число шагов известно, значит надо использовать setRange(0, count_).
Метод setRowCount позовет метод модели insertRows, вот там и обновляйте QProgressDialog
Пока я использую класс QTableWidget и метода insertRows я не видел


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 12, 2009, 21:42
Можете подкинуть пример редактируемой модели таблицы с несколькими ролями для данных QAbstractTableModel(интересует контейнер для данных - какой его вид)


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 13, 2009, 17:27
Как быть с зависанием интерфейса для setRowCount(50000) в QTableWidget? Можна ли сделать, чтоб на время выполнения задачи отображался прогрессдиалог с бегающим уровнем (range-0,0 value - 0)


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: Igors от Декабрь 13, 2009, 17:43
Пока я использую класс QTableWidget и метода insertRows я не видел
Значит плохо смотрели. У любой таблицы есть модель у которой есть метод insertRows.


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 13, 2009, 18:04
Пока я использую класс QTableWidget и метода insertRows я не видел
Значит плохо смотрели. У любой таблицы есть модель у которой есть метод insertRows.
Как тогда вызвать эту функцию?


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 13, 2009, 23:11
Как можно оптимизировать ???

Код
C++ (Qt)
//////////////////////////////////////////основная часть кода  принадлежит bool Spreadsheet::sort_data_with_GUI(const QList<QTableWidgetSelectionRange>& range)//////////////////////////////
QString error="";
for(int it=0;it<range.size();it++)
for(int i=0;i<range[it].rowCount();i++)
for(int j=0;j<range[it].columnCount();j++)
{
if(!item(range[it].topRow()+i ,range[it].leftColumn()+j)||item(range[it].topRow()+i ,range[it].leftColumn()+j)->text()==""||isError_in_cell(range[it].topRow()+i ,range[it].leftColumn()+j))
         {
error+=tr("item: ")+get_header_label(range[it].leftColumn()+j)+QString::number(range[it].topRow()+i+1)+tr(" - is invalid\n");
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool Spreadsheet::isError_in_cell(int row,int column)
{
if(row<0||row>=rowCount()||column<0||column>=columnCount())
{return false;}
if(item(row,column))
{
item(row,column)->data(Qt::DisplayRole).toString().count(";");
if( item(row,column)->data(Qt::DisplayRole).toString().count(";")>0) {return true;}// у меня парсер вычесляет выражение в ячейке, если есть ошибка - идет перечисление через ; ошибок (2* -- 1:Syntax error;)
else {return false;}
}
else {return false;}
}
 
QString Spreadsheet::get_header_label(int column_,bool *ok) //мое работает
{
if(names_for_columns.value(column_)!="")
{
            if(ok)
*ok=true;
return names_for_columns[column_];
}
else
{
         if(ok)
*ok=false;
return "";
}
}
 


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: Alex Custov от Декабрь 13, 2009, 23:22
небольшой совет - в качестве пустых строк используй QString()


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 13, 2009, 23:37

Как можно оптимизировать ???

Код
C++ (Qt)
//////////////////////////////////////////основная часть кода  принадлежит bool Spreadsheet::sort_data_with_GUI(const QList<QTableWidgetSelectionRange>& range)//////////////////////////////
QString error=QString();
for(int it=0;it<range.size();it++)
for(int i=0;i<range[it].rowCount();i++)
for(int j=0;j<range[it].columnCount();j++)
{
if(!item(range[it].topRow()+i ,range[it].leftColumn()+j)||item(range[it].topRow()+i ,range[it].leftColumn()+j)->text()==QString()||isError_in_cell(range[it].topRow()+i ,range[it].leftColumn()+j))
         {
error+=tr("item: ")+get_header_label(range[it].leftColumn()+j)+QString::number(range[it].topRow()+i+1)+tr(" - is invalid\n");
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool Spreadsheet::isError_in_cell(int row,int column)
{
if(row<0||row>=rowCount()||column<0||column>=columnCount())
{return false;}
if(item(row,column))
{
item(row,column)->data(Qt::DisplayRole).toString().count(";");
if( item(row,column)->data(Qt::DisplayRole).toString().count(";")>0) {return true;}// у меня парсер вычесляет выражение в ячейке, если есть ошибка - идет перечисление через ; ошибок (2* -- 1:Syntax error;)
else {return false;}
}
else {return false;}
}
 
QString Spreadsheet::get_header_label(int column_,bool *ok) //мое работает
{
if(names_for_columns.value(column_)!=QString())
{
            if(ok)
*ok=true;
return names_for_columns[column_];
}
else
{
         if(ok)
*ok=false;
return QString();
}
}
 


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: Igors от Декабрь 14, 2009, 00:16
Как можно оптимизировать ???
Код
C++ (Qt)
inline bool ItemOk( QTableWidgetItem * item )
{
if (!item) return false;
if (item->text().isEmpty()) return false;
return  item->data(Qt::DisplayRole).toString().indexOf(";") == -1;
}
//////////////////////////////////////////основная часть кода  принадлежит bool Spreadsheet::sort_data_with_GUI(const QList<QTableWidgetSelectionRange>& range)//////////////////////////////
QString error;
for(int it = 0; it < range.size(); it++) {
int begR = range[it].topRow();
       int endR = range[it].bottomRow();
for (int i = begR; i <= endR; i++) {
int begC = range[it].leftColumn();
int endC = range[it].rightColumn();
for (int j = begC; j <= endC; j++) {
if (!ItemOk(item(i, j))
error += QString("item at column %1, row %2 is invalid\n").arg(get_header_label(j)).arg(i); }
}
}
}
 


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 14, 2009, 00:21
Спасибо


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 14, 2009, 00:48
на большой операции со свойствами прогрессдиалога  range (0,0) setValue(0) интерфейс зависает

Код
C++ (Qt)
bool Spreadsheet::UpdateProgress( QProgressDialog * progress, int row )
{
//if ((row+1 ) % UPDATE_STEP) return true; // update once per UPDATE_STEP
progress->setValue(row);
//progress->show();
// calls processEvents for modal dialog
return !progress->wasCanceled();
}
Эту функцию вызываю в цикле (большая задача)
Как можно исправить это (не хочется вычеслять процент выполнения задачи)?
Помогите


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: Igors от Декабрь 14, 2009, 14:20
Эту функцию вызываю в цикле (большая задача)
Как можно исправить это (не хочется вычеслять процент выполнения задачи)?
Помогите
Раскомментировать первую строку (вы уже 3-й раз о том же спрашиваете  :))


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 14, 2009, 17:48
В  том то и дело что при свойства (все по 0) интерфейс замирает


Название: Re: Трудоемкие задачи (прервать или продолжить). Как прервать?
Отправлено: daimon от Декабрь 15, 2009, 00:49
Зависание (отображается постоянный процент выполнения задачи) прогрессдиалога при перемещении. Как исправить?