Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Spark от Июль 19, 2013, 10:17



Название: Организация произвольного построчного чтения
Отправлено: Spark от Июль 19, 2013, 10:17
Создаю слайдшоу. Имена карточек берутся из списка по порядку, построчно - http://www.prog.org.ru/topic_25276_15.html

Необходимо организовать режим Random (случайное чтение), учитывая, что список может быть большим (тысяч сто). Т.е список надо перемешать и затем выдавать по порядку (что бы не было повторов).
Подскажите как это организовать?
Рад любой помощи.


Название: Re: Организация произвольного построчного чтения
Отправлено: kambala от Июль 19, 2013, 12:01
1) быстрый способ: засунуть строки в хэш или множество и извлекать оттуда, получится такой себе не очень рандомный рандом
2) нормальный способ: генерировать случайный индекс через qrand(), извлекать по нему строку, помещать индекс во множество для проверки уникальности


Название: Re: Организация произвольного построчного чтения
Отправлено: Igors от Июль 19, 2013, 12:58
2) нормальный способ: генерировать случайный индекс через qrand(), извлекать по нему строку, помещать индекс во множество для проверки уникальности
Проще перемешать сами элементы контейнера напр
Код
C++ (Qt)
QStringList lst;
...
for (int i = 0; i < lst.size(); ++i)
lst.swap(qrand() % lst.size(), qrand() % lst.size());
 
А потом брать подряд


Название: Re: Организация произвольного построчного чтения
Отправлено: m_ax от Июль 19, 2013, 13:57
Код
C++ (Qt)
QStringList list;
...
std::random_shuffle(list.begin(), list.end());
 


Название: Re: Организация произвольного построчного чтения
Отправлено: kambala от Июль 19, 2013, 13:59
да уж, надо изучить STL получше


Название: Re: Организация произвольного построчного чтения
Отправлено: Igors от Июль 19, 2013, 14:12
Код
C++ (Qt)
QStringList list;
...
std::random_shuffle(list.begin(), list.end());
 
Это заметно хуже предыдущего варианта (см описание QList::swap)


Название: Re: Организация произвольного построчного чтения
Отправлено: m_ax от Июль 19, 2013, 14:35
Код
C++ (Qt)
QStringList list;
...
std::random_shuffle(list.begin(), list.end());
 
Это заметно хуже предыдущего варианта (см описание QList::swap)

Это Ваше очередное заблуждение..

Давайте посмотрим на тесты:

Код
C++ (Qt)
#include <iostream>
#include <list>
#include <algorithm>
#include <QStringList>
#include <ctime>
#include <chrono>
 
template <unsigned N>
void initList(QStringList & list) {
   for (unsigned i = 0; i < N; ++i) {
       list << QString::number(i);
   }
}
 
int main()
{
 
   using namespace std::chrono;
   const unsigned Num = 1000000;
 
   QStringList list;
 
   initList<Num>(list);
 
   high_resolution_clock::time_point t1 = high_resolution_clock::now();
   std::random_shuffle(list.begin(), list.end());
   high_resolution_clock::time_point t2 = high_resolution_clock::now();
 
   duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
   std::cout << "random_shuffle: " << time_span.count() << " seconds." << std::endl;
 
   t1 = high_resolution_clock::now();
   for (int i = 0; i < list.size(); ++i) {
       list.swap(qrand() % list.size(), qrand() % list.size());
   }
   t2 = high_resolution_clock::now();
 
   time_span = duration_cast<duration<double>>(t2 - t1);
   std::cout << "igors: " << time_span.count() << " seconds." << std::endl;
 
 
   return 0;
}
 

Результаты у меня такие (3 испытания)
Код
Bash
random_shuffle: 0.172468 seconds.
igors: 0.403365 seconds.
 
random_shuffle: 0.1679 seconds.
igors: 0.350107 seconds.
 
random_shuffle: 0.162135 seconds.
igors: 0.362432 seconds.
 

Результаты ясно говорят, что random_shuffle эффективнее более чем в два раза..


Название: Re: Организация произвольного построчного чтения
Отправлено: Old от Июль 19, 2013, 14:53
Результаты ясно говорят, что random_shuffle эффективнее более чем в два раза..
А время на изучение почему ваш тест не выводит, так сказать на поиск и рыскатню? :)


Название: Re: Организация произвольного построчного чтения
Отправлено: m_ax от Июль 19, 2013, 15:03
Результаты ясно говорят, что random_shuffle эффективнее более чем в два раза..
А время на изучение почему ваш тест не выводит, так сказать на поиск и рыскатню? :)

 ;D
Моё лицо упало на пол, потом я долго долго плакал)


Название: Re: Организация произвольного построчного чтения
Отправлено: Igors от Июль 19, 2013, 15:09
Результаты ясно говорят, что random_shuffle эффективнее более чем в два раза..
У меня др результаты (gcc/icc практически одинаковы)
Цитировать
random_shuffle: 298 ms.
igors: 126 ms.
Немного изменил Ваш пример т.к. не имею С++ 11. На всякий случай вот полный текст
Код
C++ (Qt)
#include <iostream>
#include <algorithm>
#include <QtGUI>
 
template <unsigned N>
void initList(QStringList & list) {
   for (unsigned i = 0; i < N; ++i) {
       list << QString::number(i);
   }
}
 
int main()
{
   const unsigned Num = 1000000;
   QStringList list;
   initList<Num>(list);
 
   QTime t1 = QTime::currentTime();
   std::random_shuffle(list.begin(), list.end());
   std::cout << "random_shuffle: " << t1.elapsed() << " ms." << std::endl;
 
   t1 = QTime::currentTime();
   for (int i = 0; i < list.size(); ++i)
list.swap(i, qrand() % list.size());
   std::cout << "igors: " << t1.elapsed() << " ms." << std::endl;
 
   return 0;
}
 
Перемещать данные не есть хорошо/грамотно - нужно перемещать указатели. И здесь еще так-сяк с имплисит шарой


Название: Re: Организация произвольного построчного чтения
Отправлено: m_ax от Июль 19, 2013, 15:16
С Вашим модифицированным вариантом результаты у меня:

Код
Bash
random_shuffle: 163 ms.
igors: 229 ms.
 
random_shuffle: 159 ms.
igors: 229 ms.
 
random_shuffle: 192 ms.
igors: 233 ms.
 

gcc 4.6.3

Architecture:               x86_64
CPU(s):                      1
On-line CPU(s) list:     0
Thread(s) per core:      1
Vendor ID:                  AuthenticAMD
CPU MHz:                  1808.327






Название: Re: Организация произвольного построчного чтения
Отправлено: Igors от Июль 19, 2013, 15:33
С Вашим модифицированным вариантом результаты у меня:
??? Не знаю. Я уже и тесты поменял местами, добавил srand и qsrand - все то же самое gcc/icc 32/64. debug/release. Вот последний вариант (хотя принципиальной разницы никакой)
Код
C++ (Qt)
#include <iostream>
#include <algorithm>
#include <QtGUI>
 
template <unsigned N>
void initList(QStringList & list) {
   for (unsigned i = 0; i < N; ++i) {
       list << QString::number(i);
   }
}
 
int main()
{
   const unsigned Num = 1000000;
   QStringList list;
   initList<Num>(list);
   qsrand(0);
 
   QTime t2 = QTime::currentTime();
   for (int i = 0; i < list.size(); ++i)
list.swap(i, qrand() % list.size());
   std::cout << "igors: " << t2.elapsed() << " ms." << std::endl;
 
   srand(0);
   QTime t1 = QTime::currentTime();
   std::random_shuffle(list.begin(), list.end());
   std::cout << "random_shuffle: " << t1.elapsed() << " ms." << std::endl;
 
   return 0;
}
 


Название: Re: Организация произвольного построчного чтения
Отправлено: Old от Июль 19, 2013, 15:35
А версии и разработчики stl думаю отличаются существенно. У вас даже стандарты разные.


Название: Re: Организация произвольного построчного чтения
Отправлено: Old от Июль 19, 2013, 16:41
Проверил у себя, последний тест:
Код:
igors: 83 ms.
random_shuffle: 59 ms.

g++ (GCC) 4.8.1

Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                4
On-line CPU(s) list:   0-3
Thread(s) per core:    1
Core(s) per socket:    4
Socket(s):             1
NUMA node(s):          1
Vendor ID:             AuthenticAMD
CPU family:            16
Model:                 4
Model name:            AMD Phenom(tm) II X4 945 Processor
Stepping:              2
CPU MHz:               800.000
BogoMIPS:              6030.87
Virtualization:        AMD-V
L1d cache:             64K
L1i cache:             64K
L2 cache:              512K
L3 cache:              6144K
NUMA node0 CPU(s):     0-3


Название: Re: Организация произвольного построчного чтения
Отправлено: Spark от Июль 19, 2013, 17:18
Спасибо за помощь.
Понял пока только  в каком направлении двигаться, остальное не понял :). Но наверное на изучение вопроса придется потратить ночь.
Из того, что понял.
- Надо создать:
Код
C++ (Qt)
QStringList lst;
- Далее каким то образом перетащить в него все пункты с текстового файла.
- Затем перемешать:
Код
C++ (Qt)
for (int i = 0; i < lst.size(); ++i)
lst.swap(qrand() % lst.size(), qrand() % lst.size());

В списке (колонке) 100.000 пунктов. Тормозить не будет?


Название: Re: Организация произвольного построчного чтения
Отправлено: Igors от Июль 19, 2013, 17:41
Проверил у себя, последний тест:
То что великий и могучий std сэкономил мне аж одну(!) строку не компенсирует того что подход неверен в принципе. Возьмем структурку поприличнее, у меня разницв в 20 раз, (не привожу цифры из соображений тактичности  :))

Код
C++ (Qt)
#include <iostream>
#include <algorithm>
#include <QtGUI>
 
struct CData {
CData( void )
{
vec.resize(10);
std::fill(vec.begin(), vec.end(), "test");
}
 
std::vector <std::string> vec;
};
 
int main()
{
const int Num = 1000 * 1000;
QList <CData> list;
for (int i = 0; i < Num; ++i)
list.push_back(CData());
 
qsrand(0);
QTime t2 = QTime::currentTime();
int limit = list.size();
for (int i = 0; i < limit; ++i)
list.swap(i, qrand() % limit);
std::cout << "igors: " << t2.elapsed() << " ms." << std::endl;
 
srand(0);
QTime t1 = QTime::currentTime();
std::random_shuffle(list.begin(), list.end());
std::cout << "random_shuffle: " << t1.elapsed() << " ms." << std::endl;
 
   return 0;
}
 


Название: Re: Организация произвольного построчного чтения
Отправлено: Igors от Июль 19, 2013, 17:43
В списке (колонке) 100.000 пунктов. Тормозить не будет?
Нет, не забудьте только вызвать qsrand до того, иначе каждвй раз результат перемешивания будет новый


Название: Re: Организация произвольного построчного чтения
Отправлено: m_ax от Июль 19, 2013, 17:51
Проверил у себя, последний тест:
Возьмем структурку поприличнее, у меня разница в 20 раз, (не привожу цифры из соображений тактичности  :))

В 20 раз? У Вас либо какая то сильно кривая stl, либо она на вас держит зуб)

У меня результаты такие:
Код
Bash
igors: 226 ms.
random_shuffle: 736 ms.
 

одного порядка..


Название: Re: Организация произвольного построчного чтения
Отправлено: Old от Июль 19, 2013, 17:59
иначе каждвй раз результат перемешивания будет новый
одинаковый он будет.


Название: Re: Организация произвольного построчного чтения
Отправлено: kambala от Июль 19, 2013, 18:07
компилятор от студии 2012, процессор i7-2600K 3.4 GHz, release сборка:
Цитата: Qt 4.8.5 x86
igors: 14 ms.
random_shuffle: 864 ms.
Цитата: Qt 5.1 x64
igors: 15 ms.
random_shuffle: 741 ms..


Название: Re: Организация произвольного построчного чтения
Отправлено: m_ax от Июль 19, 2013, 18:09
компилятор от студии 2012, процессор i7-2600K 3.4 GHz, release сборка:
Цитата: Qt 4.8.5 x86
igors: 14 ms.
random_shuffle: 864 ms.
Цитата: Qt 5.1 x64
igors: 15 ms.
random_shuffle: 741 ms..

Понятно всё..
В c++11 у std::vector есть move конструктор и move assignment оператор. Этим всё объясняется..


Название: Re: Организация произвольного построчного чтения
Отправлено: Spark от Июль 19, 2013, 18:14
В списке (колонке) 100.000 пунктов. Тормозить не будет?
Нет, не забудьте только вызвать qsrand до того, иначе каждвй раз результат перемешивания будет новый
А остальные пункты верны? Т.е в целом правильно понял и двигаться в этом порядке? Если да, то для меня сейчас важен второй пункт - как перегнать текст в QStringList? Тема для меня относительно новая.
Т.е. надо организовать цикл как в предыдущей теме и добавлять пункты, что то вроде этого?:
Код
C++ (Qt)
           QStringList lst;
           do
           {
               itemStr = fileStream.readLine();
               trimmedStr = itemStr.trimmed();
               lst = +trimmedStr;
           } while( !fileStream.atEnd() );


Название: Re: Организация произвольного построчного чтения
Отправлено: Spark от Июль 19, 2013, 18:33
Или так:
Код
C++ (Qt)
   QStringList lst;
   while(!fileStream.atEnd())
   {
       lst.append(fileStream.readLine());
   }


Название: Re: Организация произвольного построчного чтения
Отправлено: m_ax от Июль 19, 2013, 18:45
Вы и дальше собираетесь всё методом  тыка постигать?


Код
C++ (Qt)
   QFile file("in.txt");
   if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return;
 
    QTextStream in(&file);
    QStringList list = in.readAll().split(QRegExp("[\\s\n]"), QString::SkipEmptyParts);
 




Название: Re: Организация произвольного построчного чтения
Отправлено: kambala от Июль 19, 2013, 19:07
не слишком будет сурово для ста тысяч строк? построчно читать пооптимальнее будет. где-то помню даже была тема, где сравнивались разные подходы к чтению большого текстового файла.


Название: Re: Организация произвольного построчного чтения
Отправлено: m_ax от Июль 19, 2013, 19:17
не слишком будет сурово для ста тысяч строк? построчно читать пооптимальнее будет. где-то помню даже была тема, где сравнивались разные подходы к чтению большого текстового файла.

Думаете сто тысяч это много?

Сейчас проверим..


Название: Re: Организация произвольного построчного чтения
Отправлено: Spark от Июль 19, 2013, 19:31
Спасибо! Вроде как перегнать удалось настроить. 100.000 считывает вроде мгновенно. Теперь организовать разобраться с считыванием с QStringList и можно буде проверить с реальными 100.000 слайдами и вообщее рандомит ли :).
До утра еще время есть у меня. Час 2-3 :).


Название: Re: Организация произвольного построчного чтения
Отправлено: m_ax от Июль 19, 2013, 19:39
не слишком будет сурово для ста тысяч строк? построчно читать пооптимальнее будет. где-то помню даже была тема, где сравнивались разные подходы к чтению большого текстового файла.

Думаете сто тысяч это много?

Сейчас проверим..

Вобщем создал файлик 100000 строк.. Размер порядка 1 метра. Короче, на таких объёмах можно пока не беспокоиться)  


Название: Re: Организация произвольного построчного чтения
Отправлено: Spark от Июль 19, 2013, 20:21
Спасибо! Разобрался. Проверил два варианта:
Код
C++ (Qt)
           if ( file.open( QFile::ReadOnly | QIODevice::Text ) )
           {
 
               QTextStream fileStr( & file );
 
               QStringList list = fileStr.readAll().split(QRegExp("[\\s\n]"), QString::SkipEmptyParts);
 
               for (int i = 0; i < list.size(); ++i)
                list.swap(qrand() % list.size(), qrand() % list.size());
 
               foreach (QString itm, list)
               {
                   if(slideShowPopupAction->isChecked())winPopup->slideTranslationFor( itm );
 
                   QEventLoop loop2;
                   QTimer::singleShot(cfg.preferences.slideShowTimer, &loop2, SLOT(quit()));
                   loop2.exec();
               }
               file.close();
           }


Код
C++ (Qt)
           if ( file.open( QFile::ReadOnly | QIODevice::Text ) )
           {
 
               QTextStream fileStr( & file );
               QStringList list;
 
               while(!fileStr.atEnd())
               {
                   list.append(fileStr.readLine());
               }
 
               for (int i = 0; i < list.size(); ++i)
                list.swap(qrand() % list.size(), qrand() % list.size());
 
 
               foreach (QString itm, list)
               {
                   if(slideShowPopupAction->isChecked())winPopup->slideTranslationFor( itm );
 
                   QEventLoop loop2;
                   QTimer::singleShot(cfg.preferences.slideShowTimer, &loop2, SLOT(quit()));
                   loop2.exec();
               }
               file.close();
           }
Тормоза не обнаружены. 100,000 реальных слайдов заводятся мгновенно. Какой вариант предпочтительней? Учитывая, что список вполне может быть и на 200,000 и на 300,000.


Название: Re: Организация произвольного построчного чтения
Отправлено: Spark от Июль 19, 2013, 20:26
Осталось решить маленький баг. Если ставить таймер показа большим (допустим час), а после ставить маленький (допустим 5 сек), то придется ждать час. Причина ясна. Как избавиться, не прерывая последовательность обработки спика? Или все таки придется пересмотреть механизм показа слайд?
Так полагаю таймер можно зациклить с коротким дискретным значением. Но как от этого пострадает точность? И грамотная ли это реализация? Может прервать цикл можно иным более правильным способом?


Название: Re: Организация произвольного построчного чтения
Отправлено: Igors от Июль 20, 2013, 09:24
2m_aх Не могу объяснить противоположные результаты. Может qrand заметно медленнее std::rand? Если нетрудно - проверьте (с QStringList)


Название: Re: Организация произвольного построчного чтения
Отправлено: m_ax от Июль 20, 2013, 10:32
2m_aх Не могу объяснить противоположные результаты. Может qrand заметно медленнее std::rand? Если нетрудно - проверьте (с QStringList)

Если использовать Мерсен Твистер, то результаты практически совпадают.
Код
C++ (Qt)
using namespace std::chrono;
   const unsigned Num = 1000000;
 
   QStringList list;
 
   initList<Num>(list);
 
   std::mt19937 gen;
 
   high_resolution_clock::time_point t1 = high_resolution_clock::now();
   std::random_shuffle(list.begin(), list.end(), std::bind(std::uniform_int_distribution<int>(0, Num-1), gen));
   high_resolution_clock::time_point t2 = high_resolution_clock::now();
 
   duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
   std::cout << "random_shuffle: " << time_span.count() << " seconds." << std::endl;
 
 
   t1 = high_resolution_clock::now();
   for (int i = 0; i < list.size(); ++i) {
       list.swap(i, qrand() % list.size());
   }
   t2 = high_resolution_clock::now();
 
   time_span = duration_cast<duration<double>>(t2 - t1);
   std::cout << "igors: " << time_span.count() << " seconds." << std::endl;
 

Код
Bash
random_shuffle: 0.237838 seconds.
igors: 0.27764 seconds.
 


Название: Re: Организация произвольного построчного чтения
Отправлено: m_ax от Июль 20, 2013, 11:09
Если в обоих алгоритмах использовать один и тот же генератор, то результаты также практически совпадают..  

Скорее всего дело в реализации swap  в c++11.


Название: Re: Организация произвольного построчного чтения
Отправлено: Old от Июль 20, 2013, 11:13
Если в обоих алгоритмах использовать один и тот же генератор, то результаты также практически совпадают..  

В c++11 у std::vector есть move конструктор и move assignment оператор. Этим всё объясняется..

В c++11 и std::swap из-за этого эффективней и отпадает необходимость использовать встроенный из списка QList.


Название: Re: Организация произвольного построчного чтения
Отправлено: m_ax от Июль 20, 2013, 11:21
Если в обоих алгоритмах использовать один и тот же генератор, то результаты также практически совпадают..  

В c++11 у std::vector есть move конструктор и move assignment оператор. Этим всё объясняется..

В c++11 и std::swap из-за этого эффективней и отпадает необходимость использовать встроенный из списка QList.


Да, если у того, кто хранится в списке есть move конструктор)


Название: Re: Организация произвольного построчного чтения
Отправлено: Spark от Июль 20, 2013, 17:51
В принципе доделал организацию слайдшоу. Функционирует как задумал. Спасибо за помощь.
Оцените критическим взглядом и если не в тягость посоветуйте, как оптимизировать. Как организация таймера? Достаточно ли будет точен?...
Связи:
Код
C++ (Qt)
 // Slide
 slideShowButton = new QToolButton ( navToolbarBefore );
 slideShowButton->setIcon( QIcon (":/icons/show.png") );
 slideShowButton->setToolTip( tr( "Slideshow Play/Pause" ) );
 slideShowButton->setCheckable(true);
 slideShowButton->setChecked(false);
 slideShowButton->setContextMenuPolicy( Qt::CustomContextMenu );
 navToolbarBefore->addWidget( slideShowButton );
 
 zeroActionSlideShow = navToolbarBefore->addWidget( slideShowButton );
 zeroActionSlideShow->setVisible( cfg.preferences.slideshowButtonVisible );
 
 slideShowTimerAction = new QAction( tr( "Set Timer" ), this );
 
 slideShowRandomAction = new QAction( tr( "Random" ), this );
 slideShowRandomAction->setCheckable(true);
 slideShowRandomAction->setChecked(cfg.preferences.slideShowRandom);
 
 slideShowPopupAction = new QAction( tr( "Popup Window" ), this );
 slideShowPopupAction->setCheckable(true);
 slideShowPopupAction->setChecked(cfg.preferences.slideShowPopup);
 
 slideShowPopupOnTopAction = new QAction( tr( "Popup Window On Top" ), this );
 slideShowPopupOnTopAction->setCheckable(true);
 slideShowPopupOnTopAction->setChecked(cfg.preferences.alwaysOnTopPopup);
 
 slideShowGrandAction = new QAction( tr( "Grand Window" ), this );
 slideShowGrandAction->setCheckable(true);
 slideShowGrandAction->setChecked(cfg.preferences.slideShowGrand);
 
 sendToTranslateLineAction = new QAction( tr( "Send To Translate Line" ), this );
 sendToTranslateLineAction->setCheckable(true);
 sendToTranslateLineAction->setChecked(cfg.preferences.sendToTranslateLine);
 
 slideShowGrandOnTopAction = new QAction( tr( "Grand Window On Top" ), this );
 slideShowGrandOnTopAction->setCheckable(true);
 slideShowGrandOnTopAction->setChecked(cfg.preferences.alwaysOnTop);
 
 slideShowOpenAction = new QAction( tr( "Open" ), this );
 
 slideShowQuitAction = new QAction( tr( "Stop" ), this );
 
 slideShowPlay = false;
 slideShowPause = true;
 slideShowStop = false;
 
 connect( slideShowButton, SIGNAL( toggled( bool ) ),
          this, SLOT( slideShowOn( bool ) ) );
 
 connect( slideShowButton, SIGNAL( customContextMenuRequested( const QPoint & ) ),
          this, SLOT( contextToolbarSlideShowButton( const QPoint & ) ) );
 
 connect( slideShowTimerAction, SIGNAL( triggered() ),
          this, SLOT(slideShowTimer()));
 
 connect( slideShowRandomAction, SIGNAL( triggered( bool ) ),
          this, SLOT( slideShowRandomTriggered( bool ) ) );
 
 connect( slideShowPopupAction, SIGNAL( triggered( bool ) ),
          this, SLOT( slideShowPopupTriggered( bool ) ) );
 
 connect( slideShowPopupOnTopAction, SIGNAL( triggered( bool ) ),
          this, SLOT( slideShowOnTopTriggered( bool ) ) );
 
 connect( slideShowGrandAction, SIGNAL( triggered( bool ) ),
          this, SLOT( slideShowGrandTriggered( bool ) ) );
 
 connect( sendToTranslateLineAction, SIGNAL( triggered( bool ) ),
          this, SLOT( sendToTranslateLineTriggered( bool ) ) );
 
 connect( slideShowGrandOnTopAction, SIGNAL( triggered( bool ) ),
          this, SLOT( on_alwaysOnTop_triggered( bool ) ) );
 
 connect( slideShowOpenAction, SIGNAL( triggered() ),
          this, SLOT( openNewSlideShow() ) );
 
 connect( slideShowQuitAction, SIGNAL( triggered() ),
          this, SLOT( slideShowQuit() ) );

Функционал:
Код
C++ (Qt)
void MainWindow::slideShowOn(bool on)
{
   if(!on)
   {
       slideShowPause = true;
       return;
   }
   else if(slideShowPlay && slideShowPause)
   {
       slideShowPause = false;
       return;
   }
   else
   {
       if(!cfg.preferences.slideShowPopup && !cfg.preferences.slideShowGrand)
       {
           slideShowPopupAction->setChecked(true);
           cfg.preferences.slideShowPopup = true;
       }
 
       slideShowStop = false;
       slideShowPlay = true;
       slideShowPause = false;
 
       QString importPath;
       if( cfg.contentExportPath.isEmpty() )
           importPath = QDir::homePath();
       else
       {
           importPath = QDir::fromNativeSeparators( cfg.contentExportPath );
           if( !QDir( importPath ).exists() )
               importPath = QDir::homePath();
       }
 
       QString fileName = QFileDialog::getOpenFileName( this, tr( "Slideshow content from file" ),
                                                        importPath,
                                                        tr( "Text files (*.txt);;All files (*.*)" ) );
       if( fileName.size() == 0)
       {
           slideShowButton->setChecked(false);
           return;
       }
 
       QFileInfo fileInfo( fileName );
       QString contentName = fileInfo.baseName();
       QFile file( fileName );
       slideShowOnTopTriggered( cfg.preferences.alwaysOnTopPopup );
       int n(0);
 
       for(;;)
       {
           // Count
           n=0;
           if ( file.open( QFile::ReadOnly ) )
           {
 
               char buf[1024];
               qint64 lineLength;
               forever
               {
                   lineLength = file.readLine(buf, sizeof(buf));
                   if (lineLength > 0)
                   {
                       ++n;
                   }
                   else if (lineLength == -1)
                   {
                       break;
                   }
               }
               file.close();
           }
 
           slideShowName.setNum(n);
           slideShowName = contentName + "/" + slideShowName;
 
           if(slideShowRandomAction->isChecked())
           {
 
               if ( file.open( QFile::ReadOnly | QIODevice::Text ) )
               {
 
                   QTextStream fileStr( & file );
                   QStringList list;
 
                   if(slideShowGrandAction->isChecked())setWindowTitle( slideShowName + "/Random" );
                   if(slideShowPopupAction->isChecked())winPopup->setWindowTitle( slideShowName + "/Random" );
 
                   while(!fileStr.atEnd())
                   {
                       list.append(fileStr.readLine());
                   }
 
                   for (int i = 0; i < list.size(); ++i)
                    list.swap(qrand() % list.size(), qrand() % list.size());
 
                   foreach (QString itm, list)
                   {
                       do
                       {
                           QEventLoop loop;
                           QTimer::singleShot(0, &loop, SLOT(quit()));
                           loop.exec();
 
                           // Нормально стопим паузу для экстренного выхода программы
                           if(slideShowStop)break;
                       } while(slideShowPause);
 
                       if(slideShowGrandAction->isChecked())showTranslationFor( itm );
                       if(sendToTranslateLineAction->isChecked())translateLine->setText( itm );
                       if(slideShowPopupAction->isChecked())winPopup->slideTranslationFor( itm );
 
                       for(int i=1; i<=cfg.preferences.slideShowTimer/1000; ++i)
                       {
                           QEventLoop loop3;
                           QTimer::singleShot(1000, &loop3, SLOT(quit()));
                           loop3.exec();
                       }
 
                       if(!cfg.preferences.slideShowRandom)break;
                       if(slideShowStop)break;
                   }
                   file.close();
               }
           }
           if(!slideShowStop)
           {
               if ( file.open( QFile::ReadOnly | QIODevice::Text ) )
 
               {
 
               QTextStream fileStream( & file );
               QString itemStr;
 
               if(slideShowGrandAction->isChecked())setWindowTitle( slideShowName );
               if(slideShowPopupAction->isChecked())winPopup->setWindowTitle( slideShowName );
 
               do
               {
 
                   do
                   {
                       QEventLoop loop;
                       QTimer::singleShot(0, &loop, SLOT(quit()));
                       loop.exec();
 
                       if(slideShowStop)break;
                   } while(slideShowPause);
 
 
                   itemStr = fileStream.readLine();
                   if( fileStream.status() >= QTextStream::ReadCorruptData )
                       break;
 
                   trimmedStr = itemStr.trimmed();
                   if( trimmedStr.isEmpty() )
                       continue;
 
                   if(slideShowGrandAction->isChecked())showTranslationFor( trimmedStr );
                   if(sendToTranslateLineAction->isChecked())translateLine->setText( trimmedStr );
                   if(slideShowPopupAction->isChecked())winPopup->slideTranslationFor( trimmedStr );
 
                   for(int i=1; i<=cfg.preferences.slideShowTimer/1000; i++)
                   {
                       QEventLoop loop3;
                       QTimer::singleShot(1000, &loop3, SLOT(quit()));
                       loop3.exec();
                   }
                   if(cfg.preferences.slideShowRandom)break;
                   if(slideShowStop)break;
 
             } while( !fileStream.atEnd() );
 
             }
               file.close();
           }
           if(slideShowStop)break;
       }
 
   }
}
 
void MainWindow::quitApp()
{
   slideShowStop = true;
   qApp->quit();
}
 
void MainWindow::openNewSlideShow()
{
   slideShowStop = true;
   slideShowOn(true);
 
}
 
void MainWindow::slideShowTimer()
{
   TimerDialog *dialog = new TimerDialog( cfg );
   dialog->setWindowFlags(Qt::WindowStaysOnTopHint);
   dialog->show();
}
 
void MainWindow::slideShowRandomTriggered( bool checked )
{
   cfg.preferences.slideShowRandom = checked;
}
 
void MainWindow::slideShowPopupTriggered( bool checked )
{
   cfg.preferences.slideShowPopup = checked;
   if(cfg.preferences.slideShowRandom)
   {
       winPopup->setWindowTitle( slideShowName + "/Random");
   }
   else
   {
       winPopup->setWindowTitle( slideShowName);
   }
}
 
void MainWindow::slideShowGrandTriggered( bool checked )
{
   cfg.preferences.slideShowGrand = checked;
   if(cfg.preferences.slideShowRandom)
   {
       setWindowTitle( slideShowName + "/Random");
   }
   else
   {
       setWindowTitle( slideShowName);
   }
}
 
void MainWindow::sendToTranslateLineTriggered( bool checked )
{
   cfg.preferences.sendToTranslateLine = checked;
}
 
void MainWindow::slideShowQuit()
{
   slideShowButton->setChecked(false);
   slideShowPlay = false;
   slideShowPause = true;
   slideShowStop = true;
}
 
void MainWindow::contextToolbarSlideShowButton( const QPoint &pos)
{
   QMenu * slideMenu = new QMenu( this );
   slideMenu->addAction( slideShowTimerAction );
   slideMenu->addAction( slideShowRandomAction );
   slideMenu->addSeparator();
   slideMenu->addAction( slideShowPopupAction );
   slideMenu->addAction( slideShowPopupOnTopAction );
   slideMenu->addSeparator();
   slideMenu->addAction( slideShowGrandAction );
   slideMenu->addAction( sendToTranslateLineAction );
   slideMenu->addAction( slideShowGrandOnTopAction );
   slideMenu->addSeparator();
   slideMenu->addAction( slideShowOpenAction );
   slideMenu->addAction( slideShowQuitAction );
   slideMenu->exec( slideShowButton->mapToGlobal( pos ) );
}

Виджет Таймер:
Код
C++ (Qt)
#include <QtGui>
 
#include "timerslide.hh"
 
TimerDialog::TimerDialog( Config::Class &cfg_, QWidget *parent ) :
   QDialog( parent ),
   cfg(cfg_)
 
{
   setWindowTitle(tr("Timer"));
   setMinimumWidth(210);
 
   setHoursLabel = new QLabel(tr("Hours:"));
   setHoursSpinBox = new QSpinBox();
   setHoursSpinBox->setValue(cfg.preferences.slideShowTimer/3600000);
   setHoursSpinBox->setMinimum(0);
   setHoursSpinBox->setMaximum(12);
 
   setMinutesLabel = new QLabel(tr("Minutes:"));
   setMinutesSpinBox = new QSpinBox();
   setMinutesSpinBox->setValue(cfg.preferences.slideShowTimer%3600000/60000);
   setMinutesSpinBox->setMinimum(0);
   setMinutesSpinBox->setMaximum(60);
 
   setSecondsLabel = new QLabel(tr("Seconds:"));
   setSecondsSpinBox = new QSpinBox();
   setSecondsSpinBox->setValue(cfg.preferences.slideShowTimer%3600000%60000/1000);
   setSecondsSpinBox->setMinimum(1);
   setSecondsSpinBox->setMaximum(60);
   setSecondsSpinBox->setFocus();
 
   setOkButton = new QPushButton(tr("Ok"));
   setOkButton->setToolTip( tr( "Set Timer" ) );
 
   QGridLayout *timerLayout = new QGridLayout;
   timerLayout->addWidget(setHoursLabel, 0, 0);
   timerLayout->addWidget(setHoursSpinBox, 0, 1);
   timerLayout->addWidget(setMinutesLabel, 1, 0);
   timerLayout->addWidget(setMinutesSpinBox, 1, 1);
   timerLayout->addWidget(setSecondsLabel, 2, 0);
   timerLayout->addWidget(setSecondsSpinBox, 2, 1);
   timerLayout->addWidget(setOkButton, 3, 0, 1, 2);
 
   QHBoxLayout *mainLayout = new QHBoxLayout;
   mainLayout->addLayout(timerLayout);
   setLayout(mainLayout);
 
   connect(setOkButton, SIGNAL(clicked()),
           this, SLOT(setOkButtonClicked()));
}
 
void TimerDialog::setOkButtonClicked()
{
   int valtHours = setHoursSpinBox->value();
   int valMinutes = setMinutesSpinBox->value();
   int valSeconds = setSecondsSpinBox->value();
   cfg.preferences.slideShowTimer = valtHours*60*60*1000+valMinutes*60*1000+valSeconds*1000;
   close();
}


Название: Re: Организация произвольного построчного чтения
Отправлено: gil9red от Июль 20, 2013, 19:11
Проще было бы заценить, если бы скинули исходный код :)


Название: Re: Организация произвольного построчного чтения
Отправлено: Spark от Июль 20, 2013, 19:31
Проще было бы заценить, если бы скинули исходный код :)
Однако, здесь весь исходный код самой организации слайдшоу. И качество этой части меня интересует в первую очередь. С остальным все в порядке.


Название: Re: Организация произвольного построчного чтения
Отправлено: Spark от Июль 20, 2013, 21:01
Маленький косячок остался. В момент показав слайда, курсор мыши меняется. Подскажите, что за это отвечает?


Название: Re: Организация произвольного построчного чтения
Отправлено: thechicho от Июль 20, 2013, 21:43
Код
C++ (Qt)
QStringList list = in.readAll().split(QRegExp("[\\s\n]"), QString::SkipEmptyParts);
для чего \\s?
если в строке будет пробел, будет ошибка.
с флагом QIODevice::Text достаточно
Код
C++ (Qt)
split("\n", QString::SkipEmptyParts)


Название: Re: Организация произвольного построчного чтения
Отправлено: m_ax от Июль 20, 2013, 21:57
Код
C++ (Qt)
QStringList list = in.readAll().split(QRegExp("[\\s\n]"), QString::SkipEmptyParts);
для чего \\s?
если в строке будет пробел, будет ошибка.
с флагом QIODevice::Text достаточно
Код
C++ (Qt)
split("\n", QString::SkipEmptyParts)

Для того чтобы обрезать лишние пробелы в начале и конце строки. (предполагается, что в середине строки пробелов нет).


Название: Re: Организация произвольного построчного чтения
Отправлено: thechicho от Июль 20, 2013, 22:00
функционал убил. это чем надо думать, чтобы такое придумать)
такое чувство, что код писался с целью запутывания кого-то для чего-то.
несколько раз вподряд чтение одного и того же файла :)
самое убойное, что сразу бросилось в глаза ;D
Код:
do
{
    QEventLoop loop;
    QTimer::singleShot(0, &loop, SLOT(quit()));
    loop.exec();
 
    // Нормально стопим паузу для экстренного выхода программы
    if(slideShowStop)break;
} while(slideShowPause);
в более общие моменты не хочу даже вникать, жжешь)


Название: Re: Организация произвольного построчного чтения
Отправлено: thechicho от Июль 20, 2013, 22:05
//Для того чтобы обрезать лишние пробелы в начале и конце строки. (предполагается, что в середине строки пробелов нет).
тогда уж в начале и конце файла. не буду спрашивать, откуда им там взяться)
при
split("\n", QString::SkipEmptyParts)
QString::SkipEmptyParts - убирает пробелы в конце
остаются в начале.
Код
C++ (Qt)
QStringList list = in.readAll().trimmed().split("\n", QString::SkipEmptyParts);


Название: Re: Организация произвольного построчного чтения
Отправлено: Spark от Июль 20, 2013, 22:14
самое убойное, что сразу бросилось в глаза ;D
Однако, с чувством юмора у вас туговато. Кроме того, по этой проблеме вразумительного ответа профи не дали. Так или иначе этот пункт решен.

По остальному - спасибо на добром слове. Замечания учту. Будем набираться опыт.


Название: Re: Организация произвольного построчного чтения
Отправлено: thechicho от Июль 20, 2013, 22:23
//Однако, с чувством юмора у вас туговато
не всем харизма дана как Путину

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

//Кроме того, по этой проблеме вразумительного ответа профи не дали.
какая проблема?
когда мне нужно было как-то сделать паузу, я использовал сигнал-слот
if (slideShowPause) {
QEventLoop loop;
connect(this, SIGNAL(wakeUp()), &loop, SLOT(quit()));
loop.exec();
}
...
connect(play, SIGNAL(clicked()), this, SIGNAL(wakeUp()));


хотя в данном контексте можно просто написать.
connect(play, SIGNAL(clicked()), &loop, SLOT(quit()));

я делал паузу в другом потоке.
это пример, чтобы иметь представление как можно сделать паузу.


Название: Re: Организация произвольного построчного чтения
Отправлено: Spark от Июль 21, 2013, 04:20
я ничего доброго не сказал. код ужасен. это притом что я сам не заморачиваюсь сейчас насчет читаемости своего кода, т.к. мало опыта еще.
Через два года я бы уже начал стесняться говорить. Сомневаюсь, что через пару месяцев вы делали что то серьезное.
А по поводу паузы. Во первых сам по себе ваш ответ говорит подобное. Опыта у вас, действительно, пока еще маловато, для того, что бы с ходу понять, почему пришлось именно так сделать. Вы профи сначала реализуйте свое подобное, когда столкнетесь с проблемами я посмеюсь.
Нравится вам код или нет меня это мало волнует. А вот сами  по себе замечания для меня полезны (просто можно было обойтись без сарказма). Я то воспользуюсь критикой и достаточно быстро оптимизирую, а в следующий раз учту, спасибо вам за это, но вот поумнеете ли вы, это вопрос еще.


Название: Re: Организация произвольного построчного чтения
Отправлено: Igors от Июль 21, 2013, 07:20
2Spark "не кормите тролля"  :)


Название: Re: Организация произвольного построчного чтения
Отправлено: thechicho от Июль 21, 2013, 08:42
да, ты сучонок нагл и упорот. в игнор :)