понедельник, 8 августа 2016 г.

Книга по БД

http://www.arbinada.com/node/1372
Надо будет купить, почитать.

воскресенье, 29 мая 2016 г.

VmWare и расшаренные каталоги

Чтобы организовать расшаренные папки в OpenSuse, пришлось воспользоваться советом
https://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2016514

четверг, 29 октября 2015 г.

ZEOS DB

Посмотрел (глянул мельком) компоненты доступа ZEOS
Жаль, что нет специального управления транзакциями.

четверг, 2 июля 2015 г.

За что я люблю  Delphi -  можно довольно легко поменять среду кое в чём.
Надо было увеличить ширину, чтобы не лазить по двум строкам вкладок, и видеть все строки VersionInfo.
Restorator 2007 помог мне в том:

четверг, 21 мая 2015 г.

Демонстрация мобильного приложения

Искал чем можно показать экран мобильного приложения, чтобы можно было вывести на большой экран проектора, и нашел сервис http://www.mobizen.com

Для моего Samsung Galaxy Core 2 Dual прекрасно подошёл.

среда, 20 мая 2015 г.

Таймауты

 Черт побери, почему именно 5 секунд на вызов обратной функции, Карл?!

procedure TDSClientCallbackChannelManager.Invoke(const Id: string;
  Data: TJSONValue; out Response: TJSONValue);
var
  Item: TDSCallbackItem;
  Callback: TDBXCallback;
  ExecThread: TDSExecuteThread;
begin
  TMonitor.Enter(FLocalCallbackRepo);
  try
    if FLocalCallbackRepo.TryGetValue(Id, Item) then
    begin
      Callback := Item.Callback;
      try
        TMonitor.Enter(Callback);
        ExecThread := TDSExecuteThread.Create(Callback, Data);

        if not TMonitor.Wait(Callback, 5000) then
          ExecThread.Terminate;

        Response := ExecThread.Response;

среда, 13 мая 2015 г.

Потихоньку ваяю клиент-серверное приложение, применяя Datasnap Callback.
На время ожидания обработки запроса сервером буду показывать popup-форму ожидания, закрывающуюся по обработчику OnTerminate потока.
Естественно, это уже не анонимный поток, а специфический.

Ещё появилась необходимость передавать вызов процедуры с большим количеством параметров с сервера на клиент.
Пока что сделал регистрацию клиентской функции и ручками разворачиваю JSON в набор параметров.
Не хватает автоматической генерации обвязки как у серверных методов.

Есть мысль попробовать сделать Datasnap-сервер на клиенте и подключаться к нему...

вторник, 18 ноября 2014 г.

Программист должен быть "отцом". Иначе - вайп.

понедельник, 3 ноября 2014 г.

XE7 - Дизайнер форм

Одна из непривычных вещей, которую я обнаружил в XE7 - это измененный дизайнер.
Более никаких точных по размерам форм - только резиновый слой.
6 форм-факторов под Андроид с примерными размерами.

правда, мой 5" Galaxy S4 определялся как 4"-ый телефон, но это не существенно - контролы отображались примерно так же как и на макете.


Непростая часть - расположить контролы на макете так, чтобы они перемещались самостоятельно на основе правил.
Тут помогают слои (TLayout) с новыми видами выравнивания, например Align = HorzCenter

вторник, 2 сентября 2014 г.

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

воскресенье, 17 ноября 2013 г.

Пример использования DataSnap Callback: запрос данных во время вызова серверного метода

Что это и для чего надо:
Работа с Datasnap  заключается в запросе от сервера данных и вызове серверных методов, например:
 - Запросить список товаров с сервера (dataset )
 - Создать новый документ
 - Добавить в него позиции
 - Закрыть документ

Иногда при добавлении позиции необходимо сделать дополнительный выбор, например выбрать партию товара или разрез.

    Это можно сделать через возврат кода ошибки (что-то вроде Prepare/Execute), чтобы клиент запросил пользователя, а затем попробовал снова выполнить операцию.
    Или же дать серверу возможность запросить клиента непосредственно во время операции все необходимые ему данные.

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

Вызов:
procedure TForm2.btnRegisterWareClick(Sender: TObject);
begin
  TThread.CreateAnonymousThread(
    procedure()
    begin
      clmClient.ServerMethods1Client.RegisterWare(seWareID.Value, clmClient.DSClientCallbackChannelManager1.ManagerId)
    end).Start;
end;

Сама функция обратного вызова:
  TmyCallback = class(TDBXCallback)
  protected
    FSelectedString: Integer;
    procedure SelectString(const Arg: TJSONValue);
  public
    function Execute(const Arg: TJSONValue): TJSONValue; override;
  end;

{ TmyCallback }

function TmyCallback.Execute(const Arg: TJSONValue): TJSONValue;
begin
  TThread.Synchronize(nil, procedure()  // запрос данных у пользователя - только в основном потоке
    begin
      SelectString(Arg);
    end);
  Result := TJSONNumber.Create(FSelectedString);
end;

procedure TmyCallback.SelectString(const Arg: TJSONValue);
var
  strs: TStringList;
  enum: TJSONPairEnumerator;
  val, str: string;
begin
  enum := TJSONObject(Arg).GetEnumerator;
  if Assigned(enum) then
  begin
    strs := TStringList.Create;
    try
      while enum.MoveNext do
      begin
        Val:= enum.Current.JsonString.Value;
        str := enum.Current.JsonValue.Value;
        strs.AddObject(str, TObject(val.ToInteger()));
      end;
      FSelectedString := TfrmSelectString.SelectString(strs);
    finally
      strs.Free;
    end;
  end;
  enum.Free;
end;

А вот что происходит на сервере:

procedure TServerMethods1.RegisterWare(ID: Integer; ClientID: string);
var
  Params, ParamsServ: TJSONObject;
  ResObj: TJSONValue;
  temp: TJSONValue;
begin
  ResObj := nil;
  Params := TJSONObject.Create;
  Params.AddPair(TJSONPair.Create('1', 'Размер 42'));
  Params.AddPair(TJSONPair.Create('2', 'Размер 43'));
  Params.AddPair(TJSONPair.Create('3', 'Размер 44'));
  ParamsServ := TJSONObject(Params.Clone);  //Делаем копию для себя, ибо ушедшую не вернуть
 ServerContainer1.DSServer1.NotifyCallback(ClientID, 'SelectString', Params, ResObj);
  if Assigned(ResObj) then
    begin
      temp := ParamsServ.GetValue(ResObj.Value);
      if Assigned(temp) then
        Form1.QueueLogMsg(Format('RegisterWare %d с разрезом %s', [ID, temp.ToString]))
      else
        Form1.QueueLogMsg(Format('RegisterWare %d без разреза', [ID]));
      ResObj.Free;
      ParamsServ.Free;
    end
  else
    Form1.QueueLogMsg(Format('RegisterWare %d без разреза', [ID]));
end;

И напоследок напоминание:
 - Локальные переменные процедур - не инициализируются
 - Всё, что вы передаете в функцию - можете попрощаться с ними и не освобождать
 - Всё, что вы получаете из функции - надо освободить (ведь тут ARC не работает (хотя, надо уточнить для мобилок))

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

Код: https://github.com/VladimirSrednikh/datasnap-callback-with-ui

Так как пока с технологией жестко не определился, следующее изучение будет по TRealThinkClient

воскресенье, 10 ноября 2013 г.

Настроил себе точку доступа на D-Link DWA-125 при помощи утилиты Connectify.
Советы с поднятием SoftAP вручную провалились:
 - Динамически адрес подключенному смартфону не выдал => подключения не происходит.
 - при указании статического адреса соединение рвется непонятно почему.

P.S. Нет,  Connectify тоже не спасение. Время от времени смартфон отключался от свистка и переподключался на домашний роутер с Wi-Fi'ем.
Почему?

P.P.S. Запустил на работе - за 40 минут 20 переподключений. Очень плохо.

понедельник, 4 ноября 2013 г.

Пример дизайнера форм FMX

https://drive.google.com/file/d/0B-o0lV3HGn-JcWNUWHhNM3ZYVEk/edit?usp=sharing
Можно кидать на панельку контролы, двигать, изменять размеры.

Есть также дерево объектов, правда пока без редактирования.

суббота, 2 ноября 2013 г.

Oxygene под Андроид

Поставил триалку Оксигена
запустил простое приложение с одной кнопкой
Кнопка выглядит как простой прямоугольник.

четверг, 31 октября 2013 г.

Xamarin

Решил попробовать сделать приложение под Андроид в Xamarin.
Открыл AndroidManifest.xml, поменял Target android Version
и не получается сохранить
Проверил ProcMon'ом - никто не держит файл, никаких отлупов.
Но сохранить не может :-)

Upd. Что-то где-то переключил - увидел ругань на несовпадение переводов строк  (исходно были МАКовские).
Разрешил поменять на виндовые - сохранил :)

вторник, 29 октября 2013 г.

Прототип

Делать прототип я начал с Mobile App под платформу Win32, т.к. по сути на планшет будет то же самое - никаких платформо-зависимых вызовов, только дергать сервер получать/отправлять данные.

Сервер пришлось помучать, чтобы заставить обычное VCL-приложение заработать в неосновном потоке (благо всякие окошки удалось отключить)
Заработало.

Начал собирать под Андроид - пришлось довыпиливать из интерфейсных модулей использование VCL-контролов, а также IBX.
Потом долго пытался бороться с 

[DCC Hint] H2596 C:\Users\Public\Documents\RAD Studio\12.0\PlatformSDKs\android-ndk-r8e\toolchains\arm-linux-androideabi-4.6\prebuilt\windows\bin\arm-linux-androideabi-ld.exe: warning: cannot scan executable section 29 of c:\\program files (x86)\\embarcadero\\rad studio\\12.0\\lib\\Android\\Release/libmidas.a(alchemy.o) for Cortex-A8 erratum because it has no mapping symbols.
пока наконец не понял, что это "всего лишь" Hint а не Error.

Сделал прототип, стал показывать.
Оказалось, что мой wi-fi dongle неустойчиво держит связь,
Т.к. сервер у меня Stateful, помогла смена для серверных объектов LifeCycle на 'Session' (прототип сервера на большее и не допилен).

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

Ну и обратные вызовы я так и не попробовал.

О стиле

FireMonkey - это реализация идеи Model-View-Controller
Контрол  - это Model
Стиль - это View
Поэтому использование FireMonkey требует стилей.
Без них выглядит неважно.
И даже нельзя задать некоторые свойства (например, высоту TEdit, или TabHeight для TabControl'а) если нет стиля. Эти свойства, как правило, влияют на отображение контрола, а не на поведение (ReadOnly, Visible)

воскресенье, 27 октября 2013 г.

Delphi XE5, Android & Datasnap

В последнее время вижу много статей про Datasnap
Это вполне объяснимо ставшей доступной возможностью создавать приложения для Андроида в Дельфи.

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

Что удобно - в таком варианте изменение функционала будет добавляться/меняться прозрачно как для стационарной, так и для мобильной версии, ибо кодовая база едина.

В моем случае, правда, на мобильном клиенте из базы будут использоваться разве что типы данных и константы (посмотрим, что там с новой архитектурой FM)

пятница, 18 октября 2013 г.

Обжалование решения "судьи" Блинова

Смотрю запись трансляции. Суд начал читать какую-то бумагу (?) в 10:30
12:23 трансляции:
"Навальный и его пособник Офицеров в начале 2009 года решили похитить имущество Кировлеса. В начале 2009г Н. и О. изучили деятельность Кировлеса и поставили его в известность о том. что его продукция будет реализовываться через посредника. получив согласие(!) Опалева (директор Кировлеса), О. для создания видимости гражданско-правовых обязательств зарегистрировал ООО, подготовил и подписал договор поставки, не имеющий экономического смысла(!!!)" (13:30)

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

четверг, 17 октября 2013 г.

Как сделать из Wi-FI "Свистка" точку доступа

Купил сегодня D-Link DWA-125. При помощи данного совета настроил себе точку доступа:
http://4pda.ru/forum/index.php?showtopic=175743&st=2120#entry10287735
с правами администратора и выполняем в ней следующую команду:

- netsh wlan set hostednetwork mode=allow ssid="MS Virtual Wi-Fi" key="Pass for virtual wifi" keyUsage=persistent

В данном примере "MS Virtual Wi-Fi" – имя беспроводной сети, "Pass for virtual
wifi
"-пароль для доступа к этой сети. Вы можете задать данные значения по
своему усмотрению.

После выполнения данной команды, система найдет новое оборудование и в
диспетчере устройств появится новый сетевой адаптер,
а точнее виртуальный – Адаптер мини-порта виртуального WiFi Microsoft
(Microsoft Virtual WiFi miniport adapter). Но опять же, данный виртуальный
адаптер появится только в том случаи, если у нас драйвер беспроводного адаптера
имеет поддержку Virtual WiFi.
Перейдя в Панель управления – Центр управления сетями и общим доступом –
изменение параметров адаптера, увидим новое соединение
Wireless Network Connection 2, которое будет показывать статус – нет подключения.
Поэтому следующим этапом будет запуск сети. Для этого необходимо в командной
сроке, запущенной с правами администратора, выполнить команду:
- netsh wlan start hostednetwork.

После этого сеть запустится и заработает программная точка доступа (SoftAP).
В этом можно убедиться перейдя в Панель управления – Центр управления сетями и
общим доступом. Так как у нас используется подключение к интернету по Wi-Fi, мы
обнаружили, что Windows 7 подключена одновременно к нескольким беспроводным
сетям. Теперь другие беспроводные устройства могут подключаться к нашей точке
доступа.

примечание: Сам DWA-125 не очень удобный, так как слишком громоздкий, и соседние порты будут заблокированы его тушкой.
И еще - очень нестабильная связь у меня получилась (проверял на Samsung Galaxy S4)

P.S. кажется победил отваливание доступа - надо убрать с настроек адаптера все лишние протоколы , например TCP/IP v6, Microsoft Network, файлы и принтеры и всякие прочие антивирусы и файерволы.
Правда пока поставил себе Connectify, попробую на работе без неё, будет ли держаться связь.