Показ дописів із міткою development. Показати всі дописи
Показ дописів із міткою development. Показати всі дописи

четвер, 29 березня 2012 р.

jQuery: Як клацнути по певному регіоні (jQuery: How to click in certain region)

Уявімо, нам треба клацнути по якомусь елементу, щоб його сховати. Знаходимо цей елемент, додаємо до нього обробку події "click", а також змінюємо CSS стиль відповідним чином.

Якщо ж нам треба клацнути по якомусь регіоні всередині елемента "div"?
Тоді вираховуємо його координати користуючись можливостями jQuery, наприклад, ось так (приклад із сайта на Друпалі):

Drupal.behaviors.samlFirstMsgHide = function(context){
    var scSamlHideFirst = localStorage.getItem("scSamlHideFirst");
    var scSamlFirstVisitMsg = $('div.saml-account-update-message');

    if (scSamlHideFirst){
        scSamlFirstVisitMsg.css("display","none");
    } else {
        scSamlFirstVisitMsg.css("display","block");
        scSamlFirstVisitMsg.click(function(e){
                var minX = 840;
                var minY = 10;
                var maxX = 856;
                var maxY = 24;
                offset = $(this).offset();
                var x = e.pageX - offset.left;
                var y = e.pageY - offset.top;
                if (x < maxX && x > minX && y < maxY && y > minY){
                    $(this).fadeOut();
                    localStorage.setItem("scSamlHideFirst", "true");
                }
        });
    }

};

вівторок, 18 травня 2010 р.

Як зробити блок, що розгортається в QT (fold/unfold block)

Задача: зробити частину вікна діалога такою, що згортається і розгортається по кнопці, схоже до folding в Drupal чи Vim.
Згорнутий блок:


Розгорнутий блок:

Після довгих пошуків я знайшов такий шлях вирішення проблеми:
  1. Всі віджети діалогу мають бути поміщені в QLayout зі встановленим "SetDefaultConstraint" (в даній, 4.6 версії QT - по замовчуванню).
  2. Всі дочірні віджети першого рівня кожного QLayout повинні мати "Vertical Policy" встановлені в "Fixed", інакше вони будуть розтягуватися при зміні конфігурації вікна.
  3. Створити кнопку типу QToolButton, якщо ми хочемо мати кнопку з гарненьким трикутничком, який повертається, як на скріншоті. Я її назвав "advSettingsButton". Трикутник: в дизайнері QT Creator'а встановити властивість arrowType рівною RightArrow.
  4. Для кнопки "advSettingsButton", яка згортає/розгортає блок, слід написати подібний код:
    void OurProxyDialog::on_advSettingsButton_clicked()
    {
        // If advanced settings are hidden, show
        if (m_ui->capabilitiesBox->isHidden()) {
            m_ui->advSettingsButton->setArrowType(Qt::DownArrow);
            m_ui->capabilitiesBox->show();
        } else if (m_ui->capabilitiesBox->isVisible()) {
            // If advanced settings are shown, hide
            m_ui->advSettingsButton->setArrowType(Qt::RightArrow);
            m_ui->capabilitiesBox->hide();
        }
        adjustSize();
    }
    

    Тут "capabilitiesBox" це якраз нижній блок (QGroupBox), який згортається/розгортається.
  5. Для краси в цієї кнопки прибрані границі через встановлення "styleSheet" властивості рівною "border: 0;". Також можна додати градієнт там же.
  6. Для конструктора діалогу встановити таку обробку, щоб блок був схований при створенні вікна:
    OurProxyDialog::OurProxyDialog(QWidget *parent) :
        QDialog(parent),
        m_ui(new Ui::OurProxyDialog)
    {
        m_ui->setupUi(this);
    
        // Hide advanced settings
        m_ui->capabilitiesBox->hide();
        setMaximumHeight(0);
        adjustSize();
    }
    

Ніби все.

    PS. Кінцевий варіант коду мені допомогло написати ось це джерело (щодо зміни розміру вікна після видалення певного віджету): http://lists.trolltech.com/qt-interest/2006-10/thread00212-0.html

    четвер, 13 травня 2010 р.

    Універсальний тип даних для вказівника (C/C++ pointer)

    Вирішував нещодавно цікаву задачу: як правильно здійснити приведення типу для вказівника типу (void *)? Якщо на 32-бітних системах розмір вказівника рівний розміру типу даних int, то в 64-бітних системах усе залежить від реалізації. Наприклад, тип int може бути як 32-бітним (Microsoft Win64, більшість UNIX-подібних систем), так і 64-бітним (якщо система використовує модель даних ILP64 або SILP64). Аналогічна ситуація і з типом long: він 64-бітний на більшості систем, проте є системи, де його розмірність рівна 32 біт. Детальніше про це можна прочитати тут:
    http://en.wikipedia.org/wiki/64-bit#Specific_C-language_data_models.

    Отже, задача звелася до того, що слід мати універсальний тип даних, розмірність якого завжди відповідає розмірності вказівника. Як виявилося, в UNIX-подібних системах існують спеціальні типи даних, спроектовані для операцій з вказівниками, такі як ptrdiff_t, intptr_t, uintptr_t.
    Тип ptrdiff_t призначений зберігання результатів віднімання вказівників і є знаковим.
    Тип intptr_t є його синонімом.
    Тип uintptr_t є беззнаковим цілочисельним типом і здатен безпечно зберігати у собі вказівник незалежно від розрядності платформи.

    Отже, для моєї задачі потрібен був тип uintptr_t. Слід було лише виявити, для якої платформи який заголовний файл (header) слід включити, щоб використати цей тип.
    Ось список заголовних файлів відповідно для системи:
    GNU/Linux - stdint.h;
    Solaris - inttypes.h;
    AIX - inttypes.h;
    IRIX - додадковий заголовний файл не потрібен;
    HP-UX - sys/wsio.h.

    Відповідно, універсальний код для включення типу uintptr_t:

    #if defined(__hpux)
    #include <sys/wsio.h>
    #else
    # if defined(__sun) || defined(_AIX)
    #include <inttypes.h>
    # else
    # ifndef __sgi
    #include <stdint.h>
    # endif
    # endif
    #endif

    середа, 14 квітня 2010 р.

    Проблеми з повторними генераціями сигналу finished для QNetworkReply

    Вчора зіткнувся з досить неочевидною проблемою при тестуванні QT-аплікації. Після відсилання мережевого запиту обробка відповіді відбувається у функції, прив'язаній до сигналу finished.
    Робота з мережевими запитами в QT описана ось тут Creating_an_HTTP_network_request_in_Qt

    Ось, власне, прив'язка у моєму випадку:
    connect(_networkManager, SIGNAL(finished(QNetworkReply*)), this,
        SLOT(replyFinished(QNetworkReply*)));
    

    Виявилося, що цей сигнал генерується декілька разів: QNetworkReply завершив роботу, перед знищенням об'єкта QNetworkReply або під час його закриття функціями close() чи abort(). При цьому лише у першому випадку з нього можна щось прочитати, у решті - ні, що призводить до помилок при парсінгу даних і зупинки обробки наступних запитів (у моєму випадку відбувається перевірка статусу попереднього запиту перед відправкою наступного).

    Правильним рішенням було відключити всі слоти від сигналів QNetworkReply, щоб не отримувати їх після завершення обробки даних. Ось як це реалізовано:
    void MyClass::replyFinished(QNetworkReply* reply) {
        // --------------------------------------
        // Тут насправді міститься обробка даних
        // --------------------------------------
    
        // Close and clean up.
        m_networkManager->disconnect();
        reply->close();
        reply->deleteLater();
    }
    

    неділя, 20 грудня 2009 р.

    Деякі проблеми лінкування динамічних бібліотек на AIX

    На жаль, не зміг опублікувати це по свіжих слідах, тому спробую зробити це по пам'яті і старих записках.

    Якось я майже два тижні витратив на вирішення проблеми, пов'язаної з лінкуванням динамічних бібліотек на IBM AIX 5.1.

    Проблема полягала в тому, що створена динамічна бібліотека викликала падіння аплікації при спробі використати будь-яку функцію з бібліотеки, що означало, що бібліотека зібрана не так, як слід. Дослідження показало, що проблема була в тому, що на AIX слід явно експортувати всі необхідні символи, причому як від бібліотеки до програми, так і в зворотньому напрямку.

    Граючись із різними опціями та читаючи документацію, я виявив, що зараз (починаючи з IBM AIX 5.1) замість цілого ряду опцій для включення створення динамічної бібліотеки, дозволу run-time лінкування, та ін., можна використати всього лише опцію -G, яка вкаже лінкеру на необхідність створення shared object з можливістю run-time лінкування. Також слід вказати опцію -bE:exportlist де "exportlist" -- назва файлу зі списком символів (класів та функцій) з бібліотеки, які мають бути викликані з головної аплікації.
    Якщо ми використовуємо run-time лінкування, головна аплікація має бути зібрана з опцією -brtl. Для самої аплікації також слід вказати -bE:exportlist_app, де "exportlist_app" -- назва файлу з символами, які експортуються з аплікації, щоб бути видимими у бібліотеці.

    У моєму випадку "exportlist" бібліотеки містив її функції та клас "theApplication" з іншої бібліотеки. Файл "exportlist_app" для аплікації містив лише клас "theApplication", інакше у бібліотеці символ "theApplication" з аплікації був недоступний. В результаті це символ у програмі був оголошений двічі -- один раз явно проініціалізований у головній аплікації, а інший -- із конструктором по замовчуванню в моїй бібліотеці, що приводило до падіння аплікації (хоча явного виклику конструктора чи створення об'єкта класу і не було, через недоступність об'єкта класу з аплікації, лінкер створював новий об'єкт у бібліотеці).

    Узагальнюючи, ось процес створення динамічної бібліотеки на IBM AIX:
    1. Скомпілювати кожен вихідний файл в об'єктний файл, без лінкування. Наприклад:
      xlc -c foo.c -o foo.o
    2. Створити експортний файл, у якому перераховуються глобальні символи, які мають бути експортовані. Автоматичний спосіб генерує багато зайвого, тому я створював вручну, щось типу такого:
      function_one
      function_two
      ....
      class_one
      ....
    3. Використати опцію -G для створення динамічної бібліотеки зі згенерованих об'єктних файлів, щоб мати символи, які лінкуються до аплікації під час завантаження, і опцію лінкера -bE для вказання імені експортного файлу. (Також можна використати опцію -qmkshrobj для вказання пріоритету для C++ shared object; див. Initializing static objects in libraries (C++).) Наприклад:
      xlc -G -o libfoo.so foo1.o foo2.o -bE:exportlist
    4. Злінкувати бібліотеку з головною аплікацією, якщо бібліотека використовує run-time лінкування, додати опцію -brtl (а також -bE за потребою):
      xlc  -bE:main.exp -brtl -o myprogram main.c -Ldirectory -lfoo