• QTableView: как подсветить текущую строку таблицы?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    void ForecastReport::Delegate::initStyleOption(
            QStyleOptionViewItem * option,
            const QModelIndex & index) const
    {
        Super::initStyleOption(option, index);
        if (index.column() != owner.table->currentIndex().column()
                    && (option->state & QStyle::State_Selected)) {
            fixupStyleOption(option, cache);
        }
    }
    
    // предок ForecastReport::Delegate
    void MyTableDelegate::fixupStyleOption(
            QStyleOptionViewItem * option,
            QBlendCache& cache)
    {
        QBrush& brush = option->backgroundBrush;
        QColor cl = brush.color();
        if (brush.style() == Qt::NoBrush) {
            cl = AdvancedTableModel::BgColor::back();   // это QApplication::palette().base().color();
            brush.setStyle(Qt::SolidPattern);
        }
        brush.setColor(cache(cl, Qt::black, 180));
        option->state &= ~QStyle::State_Selected;
    }
    
    QColor QBlendCache::operator()(const QColor& aFg, const QColor& aBg, int aAlpha)
    {
        if (fg != aFg || bg != aBg || alpha != aAlpha) {
            fg = aFg;
            bg = aBg;
            alpha = aAlpha;
            result = qBlend(aFg, aBg, aAlpha);
        }
        return result;
    }
    
    namespace {
        float fGamma = 2.2f;
        float fInvGamma = 1.0f / 2.2f;
    }
    
    QColor qBlend(const QColor& aFg, const QColor& aBg, int aValue)
    {
        qreal rf, gf, bf, rb, gb, bb, a, ca;
        aFg.getRgbF(&rf, &gf, &bf);
        aBg.getRgbF(&rb, &gb, &bb);
        a = static_cast<qreal>(aValue) / static_cast<qreal>(255);
        ca = static_cast<qreal>(1) - a;
        rf = pow(pow(rf, fGamma) * a + pow(rb, fGamma) * ca, fInvGamma);
        gf = pow(pow(gf, fGamma) * a + pow(gb, fGamma) * ca, fInvGamma);
        bf = pow(pow(bf, fGamma) * a + pow(bb, fGamma) * ca, fInvGamma);
        return QColor::fromRgbF(rf, gf, bf);
    }
    Ответ написан
    Комментировать
  • Почему с мобильного перевернутые изображения?

    @Mercury13
    Программист на «си с крестами» и не только
    Покажите конкретную картинку, я не нашёл.
    Но в целом причина вот в чём. Часто камеры для простоты сохраняют картинку в стандартной ориентации, а реальный поворот аппарата записывают в EXIF. Одни браузеры эти EXIF’ы читают, другие нет.
    Вообще сайт странный и в роли уменьшенных картинок — полноразмерные 1600×1200.
    Ответ написан
    Комментировать
  • Можно ли использовать лицензию Qt Open Source для разработки закрытого приложения с рекламой?

    @Mercury13
    Программист на «си с крестами» и не только
    Можно при двух условиях:
    1. Qt прилинкована динамически.
    2. Выложить минимальный исходник, строящий приложенные библиотеки Qt.
    Так работает лицензия LGPL — версия GPL для библиотек.
    Ответ написан
    2 комментария
  • Почему free() срабатывает только один раз?

    @Mercury13
    Программист на «си с крестами» и не только
    Переполняется longitude, говорите? Ну убедитесь, что он размера SIZE_J. Не этой функции, правда, дело.
    Кроме того, вы массивы latitude[] и longitude[] заполняете случайным мусором, появившимся в результате malloc.
    Ответ написан
  • Что использовать, int, float или double в современном игровом движке?

    @Mercury13
    Программист на «си с крестами» и не только
    Предварительные расчёты (например, координаты моделей) проводить в типе достаточной точности (и, разумеется, на процессоре). Окончательные — в привычном float.
    И, понятное дело, для открытых миров придётся писать свои «велосипеды» по отсечению далёких горизонтов, и Unity в стандартной поставке не уверен, что подойдёт.

    Ещё раз. Координаты участников игры записываются в double. Координаты вершин модели — во float. Мы на процессоре проводим начальные преобразования координат, убеждаемся, что координаты заслуживают того, чтобы их рендерить, преобразуем во float и гоним на видяху.
    Ответ написан
    2 комментария
  • Как найти наиболее вероятные пути прохождения ориентированного графа?

    @Mercury13
    Программист на «си с крестами» и не только
    Замкнуть выход на вход. Каждой вершине придумать вероятности (да хоть 1/n).
    Получаем цепь Маркова, остаётся найти её эргодическое распределение.
    Надо только придумать разглючку на случай, если ЦМ будет периодической — но, возможно, стандартные методы регуляризации СЛАУ с этим справятся.
    Ответ написан
    Комментировать
  • Как написать структура классов платформера?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Перед нами серьёзный проект: есть и сеть, и подкачка, и поиск путей. Если вы будете писать платформер с нуля, вероятно, «лишние» компоненты вы писать не будете.
    2. Это компоненты, а не классы. Структура классов в геймплее будет более густая, а в рендеринге и физике — менее.
    Например, пишем 2D-рендеринг. Я бы делал Renderer, Tileset, TileLayer, Sprite, Particle…

    В зависимости от желания и целей, лучше воспользуйтесь чужим движком или напишите свой простенький. Куча вопросов отпадёт.
    Ответ написан
    Комментировать
  • Как понять решение задачи по нахождению всех анаграмм (рекурсия)?

    @Mercury13
    Программист на «си с крестами» и не только
    По очереди для каждого из элементов.
    1. Поставить его на последнее место.
    2. Вызвать функцию рекурсивно с длиной на 1 меньшей.

    Она, соответственно, будет по очереди ставить на ПРЕДпоследнее место каждый из оставшихся, и т.д.
    Ответ написан
  • Могли бы объяснить что такое квартиль и медианна?

    @Mercury13
    Программист на «си с крестами» и не только
    Это значит:
    Нижние 25% работ — в диапазоне 50…130.
    Следующие 25% — в диапазоне 130…150
    Ещё 25% — в диапазоне 150…170
    И верхние 25% работ — в диапазоне 170…500

    То, что среднее выше медианы, обычно свидетельствует о том, что сверху у распределения «длинный хвост». Что и видно — целых 25% работ попадают в диапазон 170…500.
    Ответ написан
    2 комментария
  • Можно ли обновлять модель в Qt по таймингу?

    @Mercury13
    Программист на «си с крестами» и не только
    Нет, так нельзя. И вообще, эти части модели вызывает элемент управления (например, QTreeView). Тем чаще, чем активнее мы работаем с данными.

    Как я понял, вы столкнулись с ситуацией: доступ к данным медленный. Значит, надо наладить кэш, чтобы rowCount, parent, index и прочие в большинстве случаев исполнялись мгновенно.

    Хорошо, задача номер два: где-то в дебрях второго потока идёт долгое обновление модели, а мы хотим её по частям отображать. Это дело сложное, и универсального ответа нет.

    Начнём с того, что синхронизировать поток и UI удобнее всего через сигналы-слоты-emit с типом соединения Qt::QueuedConnection (BlockedQueuedConnection, думаю, многовато будет). У слота будет один параметр: сколько элементов уже подгрузили.

    Для каждого узла, чьих сыновей мы будет подгружать, указываем дополнительное поле: сколько элементов видно из элемента управления. Все сложные структуры данных закрываем мьютексом. Поскольку дело это сложное, для тех объектов, чья ёмкость ограничена и невелика, лучше этого не делать — например, если у нас группы-альбомы-песни, можно делать это только для корневого элемента: даже у продуктивных групп вроде «битлов» элементов не так много.

    В слоте производим такую фишку: rowsAboutToBeInserted, изменяем наше дополнительное поле, rowsInserted. И так для всех элементов, у кого добавилось потомства.
    Ответ написан
    3 комментария
  • Как на 32-битной платформе в переменную типа intptr_t может влезть максимальный адрес ссылки?

    @Mercury13
    Программист на «си с крестами» и не только
    зачем нужно было вообще вводить intptr_t если есть uintptr_t, в который адрес точно влезет?

    intptr_t — разность двух адресов.

    И, более того, как в ЗНАКОВУЮ переменную типа intptr_t можно поместить 32-битный адрес памяти, если в этом числе 1 бит уходит на знак, а для данных остаётся 31 бит?

    Учите матчасть — как действует дополнительный код, почему машинные целые изображают в виде круга и почему знаковое и беззнаковое сложение выполняется одними и теми же операциями add/sub. В общем, данные записываются во все 32 бита. И в знаковый тоже.

    как может БЕЗЗНАКОВОЕ число равняться числу СО ЗНАКОМ?

    А вот сравнивать их — ошибка, и не зря большинство компиляторов выводит предупреждение. Оба надо перевести либо в unsigned, либо в signed, либо в более крупный знаковый целый тип.
    Ответ написан
    2 комментария
  • Может кто объяснить, что происходит при кликании ярлыка программы на физическом уровне?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Мышь посылает команды «Я нажата» и «Я отпущена». Считаем, что мышь USB’шная — тогда диспетчер шины 125 раз в секунду даёт мыши таймслот, и она за это время посылает 8-байтовый пакет, и в нём есть поля «сдвиг по X, сдвиг по Y, нажатые кнопки». Сама ОС ведёт счёт координатам курсора мыши. Отображение курсора мыши — это отдельная функция графического драйвера (из-за требовательности к скорости).
    2. ОС из этих команд генерирует событие «Двойной щелчок по координатам (X, Y)» и посылает текущей программе (в данном случае — оболочке Windows, explorer.exe, он же Проводник).
    3. Рабочий стол — это сильно модифицированный ListView из comctl32.dll (если я правильно назвал эту библиотеку). Впрочем, событие «двойной щелчок» обрабатывается самим Проводником, и если какой-то элемент выделен, он говорит: запусти файл, библиотека shell32.dll, функция ShellExecute с глаголом «open».
    4. Библиотека оболочки shell32.dll имеет специальную ветвь кода для запуска ярлыков. Она разбирает файл ярлыка и вызывает более низкоуровневую функцию CreateProcess.
    5. Ядро Windows делает всё, что нужно, чтобы создать процесс, завести под него отдельное «пользовательское» адресное пространство, отдельный стек вызовов, потоки ввода-вывода и т.д. Сам EXE-файл и его библиотеки становятся частью системы подкачки Windows, и если какая-то страничка сегмента кода будет выброшена, она подгружается прямо из EXE/DLL. Разрешает динамические адреса, которые становятся известны только при загрузке программы (т.н. relocations). Процесс загрузки программы — дело сложное, с ним я незнаком.
    6. Считаем, что программа GUI’шная. Тогда при загрузке, как ни странно, ничего внешне не происходит (только трещит винт, подкачивая данные в оперативную память). Сама программа говорит WinAPI: мне нужно создать такое-то окно, с такими-то кнопками в заголовке, с отображением на панели задач.
    7. Система сама посылает окну события: «Я изменяю свой размер», «Я показываюсь», «Я перерисовываюсь». Программа может перехватить эти события и сделать по ним что-то своё. Если у окна есть неклиентская часть (заголовок, рамка), показывает их сама Windows.
    8. За перерисовку клиентской части окна (то есть того, что внутри рамки) отвечает одна из нескольких подсистем Windows. Наиболее распространённая — GDI (интерфейс графических устройств), хотя всё чаще используют библиотеки аппаратного ускорения — DirectX/OpenGL/Vulkan.
    9. Как только сработали события перерисовки — внутренние Windows и пользовательские — мы видим на экране окошко!
    Ответ написан
    2 комментария
  • Правильно ли объясняется в тексте почему в 1 кб 1024 байт?

    @Mercury13
    Программист на «си с крестами» и не только
    Дело вот в чём. Возьмём магнитную память. У неё есть проволочки-ряды, проволочки-столбцы и проходящий через все сердечники провод считывания-записи. Чтобы считать ячейку, мы пускаем ток через нужный ряд и нужный столбец (сила тока подбирается так, чтобы две проволочки работали, а одна — нет). Чтобы пустить ток ровно через одну проволочку, используется такой девайс, как дешифратор: двоичный код, например, 010=2 превращает в позиционный код 00100000 (единица на 2-м месте, начиная с ноля).

    Вот у нас есть такой блок памяти. Пришёл адрес — как получить номер строки и столбца? Разделить адрес на кол-во столбцов; частное — № строки, остаток — № столбца. Для удобства столбцов должна быть степень двойки: во-первых, это полностью задействует возможности дешифратора; во-вторых, частное и остаток сводятся к тому, что часть линий адреса отводим на один дешифратор, часть на второй.

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

    С появлением полупроводниковой памяти тяга к степеням двойки даже усилилась: стоимость чипа зависит от его ёмкости постольку, поскольку часть чипов идёт в выбраковку. Есть некий (и довольно узкий) оптимальный диапазон ёмкостей: больше — велика выбраковка; меньше — только для спец. приложений вроде совместимости и энергопотребления.

    Вот и всё.
    Ответ написан
    Комментировать
  • Причина работы данного массива структур?

    @Mercury13
    Программист на «си с крестами» и не только
    Таков смысл «си с крестами» — «вы не платите за то, чем не пользуетесь». В данном случае: не пользуетесь авариями — не платите за них. Кстати, самый эффективный способ обработки аварий на x86 только недавно лишился патента, и я не в курсе, есть ли он в MinGW (на x64 патент обошли и он там давно был). Плюс совместимость с Си.

    Правда, мне пришлось сделать свои массивы Array1d и Fix1d именно для того, чтобы проверять границы: включено в debug и выключено в release.
    Ответ написан
    Комментировать
  • Что такое bulk-запрос?

    @Mercury13
    Программист на «си с крестами» и не только
    Это понятие никак не формализовано. Но в целом это…
    Запрос, позволяющий массово выполнить несколько сходных действий. Например, получить информацию сразу по нескольким контрагентам, со всем, что им подчинено. Залить в БД кучу информации.
    Ответ написан
    Комментировать
  • Программа для работы с тайлсетами?

    @Mercury13
    Программист на «си с крестами» и не только
    Tiled: www.mapeditor.org/. Не самая крутая, но самая известная.
    Вот ещё одна: tide.codeplex.com
    Ответ написан
    Комментировать
  • Как написать картинку кодом?

    @Mercury13
    Программист на «си с крестами» и не только
    Формат JPEG очень сложен, и КРАЙНЕ не рекомендую писать поддержку самому. Лучше пользоваться любой подходящей библиотекой. Вот, например, на Qt:
    #include <QImage>
    #include <QPainter>
    
    int main()
    {
        QImage pix(100, 100, QImage::Format_RGB888);
        pix.fill(Qt::darkBlue);
        QPainter painter(&pix);
        painter.setPen(QPen(Qt::yellow, 2.0));
        painter.drawEllipse(QPoint(50, 50), 40, 30);
        pix.save("test.jpg");
    }

    Приду домой — отыщу код на PHP, призванный уменьшать размер картинок. В общем, для любого современного языка библиотека найдётся.
    Ответ написан
    2 комментария
  • Почему в C++ нужно строить всю программу на ООП (длинный вопрос)?

    @Mercury13
    Программист на «си с крестами» и не только
    Задача ООП: 1) Локализовать изменения состояния объекта (инкапсуляция); 2) связывать разные кирпичики данных через стандартные интерфейсы (полиморфизм).

    Простейший тетрис не слишком велик, чтобы его писать на чистом ООП.
    Но представьте себе, мы начинаем налаживать настраиваемое управление джойстиком или клавиатурой. И тогда у нас появляется такой код.
    enum {
      BT_LEFT = 1,
      BT_RIGHT = 2,
      BT_ROTATE = 4,
      BT_SOFTDROP = 8,
      BT_HARDDROP = 16,
      BT_PAUSE = 32,
      BT_CONNECTED = 32768,   // бит, указывающий, что контроллер подключён
    };
    class Controller {  // интерфейс
    public:
      virtual unsigned poll() const = 0;   // сочетание битов BT_XXX
      virtual ~Controller = default;
    };

    Классы Keyboard и Joystick поддерживают интерфейс Controller, и подмена клавиатуры на джойстик и наоборот ничего не изменит.
    Вот вам полиморфизм.

    Текстовый редактор превращаем в многооконный — берём класс Editor и пристраиваем его не к программе в целом, а к MDI-окошку. Вот вам инкапсуляция — локализованное изменение состояния.

    Я как-то мучил движок Doom. Он написан в самом настоящем объектном стиле на чистом Си! Хотя и там были проблемы: сетевой код был куда хуже по качеству, чем сам движок. Писали разделённый экран, глобальную переменную netgame разделили на две, multiplayer и netgame и долго-долго правили баги, где multiplayer, где netgame (было дело, участник десматча ввёл IDKFA, это сработало и вызвало рассинхронизацию). А код пользовательского интерфейса — вообще медвежуть!
    Ответ написан
    Комментировать
  • Как мне получить нужное значение?

    @Mercury13
    Программист на «си с крестами» и не только
    ($dec >> 8) << 7 теряет нижние 8 бит и сдвигает на один вправо.
    $dec % 128 оставляет нижние 7 бит.
    Таким образом, эта конструкция выкусывает из числа 7-й бит (у младшего номер 0).
    Восстановить однозначно нельзя: надо (($res & ~0x7F) << 1) | ($res & 0x7F) и, возможно, | 0x80.
    Например: ((585 & ~0x7F) << 1) | (585 & 0x7F) | 0x80 = 1225.
    Во всех ваших четырёх примерах установить опущенный 7-й бит нужно. Он что-то значит?
    Ответ написан
    2 комментария
  • Как называется процесс чтения кода браузером?

    @Mercury13
    Программист на «си с крестами» и не только
    Parsing, разбор.
    Ответ написан
    Комментировать