Russian Qt Forum
Ноябрь 23, 2024, 07:11 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 [3] 4   Вниз
  Печать  
Автор Тема: Итераторы в последовательных контейнерах  (Прочитано 25490 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #30 : Июль 24, 2014, 08:23 »

Вот мы взяли нулевой элемент вектора data. По индексу взяли виджет, я так понимаю, из ui и спросили его тип - пусть это будет "Текстовая строка".
А дальше мы пытаемся из этой текстовой строки вытащить/установить данные в формате, заданном в элементе структуры CData?
Да

А если виджет QLineEdit, а элемент TYPE_RGB, то нам нужно попробовать из строки виджета получить/установить цвет?
Нет, совместимость UI и опиcаний проверяется 1 раз на старте

И огласите сразу все возможные типы виджетов.
TYPE_SFLOAT   EditText
TYPE_UFLOAT   EditText
TYPE_SLONG    EditText
TYPE_ULONG    EditText
TYPE_BOOLEAN CheckBox
TYPE_OPTION   Popup
TYPE_RGB       ColorBox (no alpha)
TYPE_ARGB     ColorBox (with alpha)
TYPE_CUSTOM  "complex control" напр график

P.S. И последний вопрос: этот код эту вермишель выше вы писали?  Строит глазки
Нет. Несмотря на всю свою уродливость этот код работает минимум 15 лет и делает все что требуется. Поэтому и живет

Для конкретного числового идентификатора типа виджета и конкретного числового идентификатора элемента данных что-то делается....

Что? Не понятно.. Не понятно почему именно так делается.
Смысл - запуск UI без написания какого-либо кода юзером. Он его готовит интерактивно рисуя контролы и создавая "дескриптор параметра" (CData) для каждого контрола. Отсюда ясно что делается

AcceptData - вызывается когда UI запущено, данные изменены и нажата кнопка Ok. Если данные невалидны нужно дать отлуп с объяснением причины (показать min, max, default). Иначе вылить данные (в char *)

SetupData - все наоборот, зарядить данные в UI

DefailtData - зарядить данные используя default в дескрипторах

И.т.д.
« Последнее редактирование: Июль 24, 2014, 08:28 от Igors » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #31 : Июль 24, 2014, 09:56 »

Нет, совместимость UI и опиcаний проверяется 1 раз на старте
Если тип однозначно ассоциируется с виджетом, то лучше идти по типам данных, проверять тип виджета и если он подходящий устанавливать/читать данные.

Код
C++ (Qt)
bool AcceptData( std::vector <CData> & data  )
{
   for( size_t i = 0; i  < data.size(); ++i )
   {
       QWidget * w = GetWidget(i);     // берем UI элемент
       int type = GetWidgetType(w);    
       switch( data[ i ].rmp_Type )
       {
       case TYPE_SFLOAT:
           assert( type == edit_Text );    // Тип виджета должен быть однозначно QLineEdit
            if (data[i].rmp_Flag & FLAG_BIT_LIMITED) {
               // проверка диапазона
            }
            // запись в выходную структуру
            break;
 
       }
   }
}
 

А если перейти с C на C++, то можно легко избавится от этого большого свитча + можно будет легко добавлять другие типы без переделки всей системы.
« Последнее редактирование: Июль 24, 2014, 10:25 от Old » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #32 : Июль 24, 2014, 14:08 »

Если тип однозначно ассоциируется с виджетом, то лучше идти по типам данных, проверять тип виджета и если он подходящий устанавливать/читать данные.
Такая "перестановка сомножителей" на принципиальное решение не тянет

А если перейти с C на C++, то можно легко избавится от этого большого свитча + можно будет легко добавлять другие типы без переделки всей системы.
Так давайте переходить - это и было предложено для обсуждения  Улыбающийся

Да, на всякий случай: вход/выход (данные что устанавливаются в UI и запоминаются из него) = просто поток. Напр в QDataStream в терминах Qt. Этот (сохраненный) поток подается на вход расчетной части которая знает ту же форматку. До первого сохранения поток создается из дефаултов форматки 
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #33 : Июль 24, 2014, 14:45 »

Такая "перестановка сомножителей" на принципиальное решение не тянет
Зато она избавляет от бесполезных внутренних свитчей по типам для каждого виджета - код уменьшится раза в два.

Так давайте переходить - это и было предложено для обсуждения  Улыбающийся
Так давайте. Улыбающийся
Такие задачки задают школьникам после прочтения им глав о наследовании и виртуальных функциях, кроме этого ничего из C++ не надо.
Или ждете готового решения?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #34 : Июль 24, 2014, 15:38 »

Зато она избавляет от бесполезных внутренних свитчей по типам для каждого виджета - код уменьшится раза в два.
Да нисколько, напр связка type_EdtText + TYPE_SFLOAT как была так и осталась. Ведь пишутся только нужные ветки case, напр для type_Popup будет только TYPE_OPTION

Такие задачки задают школьникам после прочтения им глав о наследовании и виртуальных функциях, кроме этого ничего из C++ не надо.
Ну и что этим достигается? Кусочки свитча переносятся в методы классов, но экономии-то никакой. "Зато" надо наделать кучу сомнительных мелких классов + как-то отконвертить исходную структуру которая не виртуальна. Говоря "более официально" попытка наследования/обобщения для слабосвязных классов явно неудачна.

Или ждете готового решения?
Спесь поубавьте - опять вылезла  Улыбающийся
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #35 : Июль 24, 2014, 15:48 »

Да нисколько, напр связка type_EdtText + TYPE_SFLOAT как была так и осталась.
Посмотрите на мой кусок кода и на ваш. В моем внутреннего свитча нет вообще, как совершенно бесполезного.

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

Говоря "более официально" попытка наследования/обобщения для слабосвязных классов явно неудачна.
Они не слабосвязанные, а прямо таки дети родные - это все поля данных (можно их так назвать).

Спесь поубавьте - опять вылезла  Улыбающийся
Тогда предлагая, что то обсудить показывайте сразу ваши мысли, тогда будет понятно, что вы хотите разобраться, а не выхватить решение на халяву.
« Последнее редактирование: Июль 24, 2014, 16:24 от Old » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #36 : Июль 25, 2014, 10:35 »

Тогда предлагая, что то обсудить показывайте сразу ваши мысли, тогда будет понятно, что вы хотите разобраться, а не выхватить решение на халяву.
Ну что Вы такой "примитивно-жадный" Улыбающийся У меня и в мыслях не было задействовать Вас в корыстных целях. Даже если (предположим) я получу идеальный ответ - вряд ли я буду что-то переделывать, по принципу "работает - не лезь". Но вот если в след раз возникнет аналогичная ситуация (что вполне вероятно) - буду делать "по уму", а не свитчеваться. А Вы вцепились в несущественные детали, типа как улучшить свитч - это не заслуживает обсуждения.

Рассмотрим небольшую подзадачу: контроль диапазона. Проверяем лежит ли введенное юзером значение в заданном диапазоне, если нет то предъявляем диалог где указаны min/max/default. Все данные для этого есть. Хотелось бы написать так
Код
C++ (Qt)
for (size_t i = 0; i < data.size(); ++i) {
...
if (!ValidRange(data[i], currentValue)) return false;
 
Тогда что делать в ValidRange ?
Код
C++ (Qt)
template <class T>
bool ValidRange( const CData & param, T & value )
{
if (!param.rmp_Flag & FLAG_BIT_LIMITED) return true;  // нет ограничений на диапазон
switch (param.rmp_Type) {
  case TYPE_SFLOAT:
  case TYPE_UFLOAT:
    if (value >= param.valReal.rmp_Minimum && value <= param.valReal.rmp_Maximum) return true;
    return DoModalDialog(value, param.valReal.rmp_Minimum, param.valReal.rmp_Maximum, param.valReal.rmp_Value> MODE_REAL);
 
  case TYPE_SLONG:
  case TYPE_ULONG:
    if (value >= param.valLong.rmp_Minimum && value <= param.valLong.rmp_Maximum) return true;
    return DoModalDialog(value, param.valLong.rmp_Minimum, param.valLong.rmp_Maximum, param.valLong.rmp_Value, MODE_LONG);
 
  default: return true;
}
}
И с общностью по-прежнему хреновато. Сам по себе диалог обобщается прекрасно - но там надо показывать или целые числа или с точкой. И опять вылазит свитч. Выделив ValidRange мы ничего особенного не достигли - ну двигаем свитчи туда-сюда. Возможно стоит сделать template выдачи min/max/default

А как хороши темплейты на простых примерах! Впрочем и этот не выглядит слишком сложным. Да, и где же юный энтузиаст шаблонной магии? Как всегда, занят с собачкой...
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #37 : Июль 25, 2014, 10:49 »

И с общностью по-прежнему хреновато. Сам по себе диалог обобщается прекрасно - но там надо показывать или целые числа или с точкой. И опять вылазит свитч.
Так вы ничего не обобщаете.
Сделайте классы на каждый тип данных (для примера это для long знаковых и беззнаковых):
Код
C++ (Qt)
typedef quint64         FlagType;
 
class Field
{
public:
       explicit Field( const QString &name, FlagType flags ) : m_name( name ), m_flags( flags ) {}
 
       virtual void            setData( QWidget *w ) = 0;
       virtual void            getData( QWidget *w ) = 0;
 
private:
       QString         m_name;
       FlagType        m_flags;
};
 
class LongField : public Field
{
public:
       explicit Field( const QString &name, FlagType flags, long value, long min, long max, bool sign ) :
               Field( name, flags ), m_value( value ), m_min( min ), m_max( max ), m_sign( sign ) {}
 
       virtual void            setData( QWidget *w )
       {
 
       }
 
       virtual void            getData( QWidget *w )
       {
             // Проверили, что ввел пользователь и выдали диалог
       }
 
private:
       long            m_value;
       long            m_min;
       long            m_max;
       bool            m_sign;
};
 
   

А как хороши темплейты на простых примерах!
А как хорошо говнокодиться с свитчем... Ну вы в курсе. Улыбающийся

Да, и где же юный энтузиаст шаблонной магии? Как всегда, занят с собачкой...
Тема настолько детская, что найдётся мало желающих пережовывать элементарщину.
« Последнее редактирование: Июль 25, 2014, 11:35 от Old » Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #38 : Июль 25, 2014, 12:01 »

Цитировать
Код
C++ (Qt)
for (size_t i = 0; i < data.size(); ++i) {
...
if (!ValidRange(data[i], currentValue)) return false;
 

Код
C++ (Qt)
template <class T>
bool ValidRange( const CData & param, T & value )
{
if (!param.rmp_Flag & FLAG_BIT_LIMITED) return true;  // нет ограничений на диапазон
switch (param.rmp_Type) {
  case TYPE_SFLOAT:
  case TYPE_UFLOAT:
    if (value >= param.valReal.rmp_Minimum && value <= param.valReal.rmp_Maximum) return true;
    return DoModalDialog(value, param.valReal.rmp_Minimum, param.valReal.rmp_Maximum, param.valReal.rmp_Value> MODE_REAL);
 
  case TYPE_SLONG:
  case TYPE_ULONG:
    if (value >= param.valLong.rmp_Minimum && value <= param.valLong.rmp_Maximum) return true;
    return DoModalDialog(value, param.valLong.rmp_Minimum, param.valLong.rmp_Maximum, param.valLong.rmp_Value, MODE_LONG);
 
  default: return true;
}
}
 

Я бы сделал проще, через специализацию шаблонов (как альтернатива наследованию) например так

Код
C++ (Qt)
typedef long TYPE_SLONG;
typedef unsigned long TYPE_ULONG;
typedef float TYPE_FLOAT;
 
template<class T, class Container>
class RangeValidator
{};
 
template <class Container>
class RangeValidator<TYPE_ULONG, Container>
{
public:
   RangeValidator(const Container & container) : _container(container) {}
 
   template <class T>
   bool isValid(const T & value) const
   {
       typedef typename Container::value_type value_type;
       auto it = std::find_if(_container.begin(), _container.end(), [&](const value_type & param) -> bool
       {
           return (value >= param.valLong.rmp_Minimum && value <= param.valLong.rmp_Maximum);
       }
       );
 
       if (it != _container.end())
       {
           // Сообщаем о проблемах.. и выходим..
       }
 
       return true;
   }
 
private:
   const Container & _container;
};
 

И если понадобится вдруг какой ещё тип данных, то нужно лишь реализовать для него свою специализацию RangeValidator..   
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #39 : Июль 26, 2014, 11:48 »

Сделайте классы на каждый тип данных (для примера это для long знаковых и беззнаковых):
Ага, а для типов с точкой будет еще точно такой же класс? И только потому что там long а здесь double. И чего Вы льете туда же и все подробности UI? Где же пресловутое разделение бызнес-логики? Да и флажок signed выглядит как "попытка уползти"  Улыбающийся, никакой идейностью не пахнет 

Тема настолько детская, что найдётся мало желающих пережовывать элементарщину.
Это справедливо только по отношению к предложенному Вами решению Улыбающийся Наверное Вы и сами осознали его минусы - много каких-то классов, дубляж кода налицо, создание нового класса при первой же необходимости...

Я бы сделал проще, через специализацию шаблонов (как альтернатива наследованию) например так
TYPE_SLONG и др - это числовые константы используемые внешним редактором, менять ее нельзя. И не понял что Вы обобщаете если юзается valLong? Или имеется ввиду это надо повторить для др типов? Это как-то не привлекает, и тогда причем здесь find_if, этим должен заниматься вызывающий.

А вообще специализация шаблонов напрашивается. Может не связываться с самой форматкой, а подавать ее как аргумент в темплейтщину, напр
Код
C++ (Qt)
СParam <double> param(CData[i]);
А CParam уже как-то обобщать. Но это просто "мысли вслух"
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #40 : Июль 26, 2014, 12:37 »

Я так и не понял тз.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #41 : Июль 26, 2014, 12:47 »

Ага, а для типов с точкой будет еще точно такой же класс? И только потому что там long а здесь double.
Секундочку, это вы нас убеждаете, что вам нужно для целых и плавающих чисел показывать разные диалоги... А так все числа (знаковые/беззнаковые/целые/плавающие) можно положить в один шаблонный класс и не мучатся.

И чего Вы льете туда же и все подробности UI?
А вы не лейте туда UI, а посылайте сигнал (любым удобным для вас способом), в обработчике которого и показывайте диалоги. Думайте.

Где же пресловутое разделение бызнес-логики?
Так вы не делайте влоб, что за привычка. Я вам идею показываю, а вы на нее смотрите как на готовое решение и сокрушаетесь что вам не очень подходит. Подумайте, доработайте.

Это справедливо только по отношению к предложенному Вами решению Улыбающийся
Повторюсь, это идея, которую нужно понять и развить. /* Но боюсь дальше решения в лоб со свитчами (эталон детской некомпетентности) вам не уползти. */

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

дубляж кода налицо
В каком месте? Покажите.

создание нового класса при первой же необходимости...
Вот! Это главная идея объектно-ориентированных языков программирования, которую вы никак не хотите понять. Улыбающийся
« Последнее редактирование: Июль 26, 2014, 13:47 от Old » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #42 : Июль 26, 2014, 13:53 »

Я так и не понял тз.
В данном случае это практически не реально. Улыбающийся
Никакого ТЗ нет, даже требований никаких нет и по ходу обсуждения будут придумываться новые условия и требования.
Просто вбрасывайте как поняли и будем развлекаться дальше. Улыбающийся
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #43 : Июль 26, 2014, 14:13 »

Никакого ТЗ нет, даже требований никаких нет и по ходу обсуждения будут придумываться новые условия и требования.
Просто вбрасывайте как поняли и будем развлекаться дальше. Улыбающийся

Вообще никак не понял.

В частности: есть кнопочки (гуй), есть логика (обработка каких то данных по нажатию на кнопку).
Мне не понятно, какое отношение одно имеет к другому?

Ведь.
Логике не нужен гуй, что бы обработать свои данные.
А кнопкам пофигу, какая реакция может быть при нажатии на ту, или иную кнопку.

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

Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #44 : Июль 26, 2014, 14:25 »

Вообще никак не понял.
Все это для того, что бы дать пользователю возможность создавать UI без написания кода и соответственно перекомпиляции всей системы.
Например, пользователь написал скрипт, которому для работы нужно задать три параметра (два числа и цвет). Пользователь рисует в том же дизайнере диалог, состоящий из двух QLineEdit и ColorSelector и создает коллекцию структур, в которых указаны начальные значения для чисел, диапазоны, начальный цвет и т.д.
Эту коллекцию и UI-файл с диалогом передается движку, который создает диалог, устанавливает все параметры и показывает его пользователю, тот задает нужные параметры и жмет Ok, движок сохраняет их обратно в коллекцию и завершается. Скрипт берет заданные пользователем данные и выполняется.
Записан
Страниц: 1 2 [3] 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.582 секунд. Запросов: 23.