Na stránkách Evropské komise, na portálu Podělte se o svůj názor, se lze do 3. února podělit o názor k iniciativě Evropské otevřené digitální ekosystémy řešící přístup EU k otevřenému softwaru.
Společnost Kagi stojící za stejnojmenným placeným vyhledávačem vydala (𝕏) alfa verzi linuxové verze (flatpak) svého proprietárního webového prohlížeče Orion.
Firma Bose se po tlaku uživatelů rozhodla, že otevře API svých chytrých reproduktorů SoundTouch, což umožní pokračovat v jejich používání i po plánovaném ukončení podpory v letošním roce. Pro ovládání také bude stále možné využívat oficiální aplikaci, ale už pouze lokálně bez cloudových služeb. Dokumentace API dostupná zde (soubor PDF).
Jiří Eischmann se v příspěvku na svém blogu rozepsal o open source AdGuard Home jako domácí ochraně nejen před reklamou. Adguard Home není plnohodnotným DNS resolverem, funguje jako DNS forwarder s možností filtrování. To znamená, že když přijme DNS dotaz, sám na něj neodpoví, ale přepošle ho na vybraný DNS server a odpovědi zpracovává a filtruje dle nastavených pravidel a následně posílá zpět klientům. Dá se tedy používat k blokování reklamy a škodlivých stránek a k rodičovské kontrole na úrovni DNS.
AI Claude Code od Anthropicu lépe rozumí frameworku Nette, tj. open source frameworku pro tvorbu webových aplikací v PHP. David Grudl napsal plugin Nette pro Claude Code.
Byla vydána prosincová aktualizace aneb nová verze 1.108 editoru zdrojových kódů Visual Studio Code (Wikipedie). Přehled novinek i s náhledy a videi v poznámkách k vydání. Ve verzi 1.108 vyjde také VSCodium, tj. komunitní sestavení Visual Studia Code bez telemetrie a licenčních podmínek Microsoftu.
Na lasvegaském veletrhu elektroniky CES byl předveden prototyp notebooku chlazeného pomocí plazmových aktuátorů (DBD). Ačkoliv se nejedná o první nápad svého druhu, nepochybně to je první ukázka praktického použití tohoto způsobu chlazení v běžné elektronice. Co činí plazmové chladící akční členy technologickou výzvou je především vysoká produkce jedovatého ozonu, tu se prý podařilo firmě YPlasma zredukovat dielektrickou
… více »Patchouli je open source implementace EMR grafického tabletu (polohovací zařízení). Projekt je hostován na GitLabu.
Český Nejvyšší soud potvrdil, že česká právní úprava plošného uchování dat o elektronické komunikaci porušuje právo Evropské unie. Pravomocným rozsudkem zamítl dovolání ministerstva průmyslu a obchodu. To se teď musí omluvit novináři Českého rozhlasu Janu Cibulkovi za zásah do práv na ochranu soukromí a osobních údajů. Ve sporu jde o povinnost provozovatelů sítí uchovávat údaje, ze kterých lze odvodit, kdo, s kým a odkud komunikoval.
Google bude vydávat zdrojové kódy Androidu pouze dvakrát ročně. Ve 2. a 4. čtvrtletí.
Kterak propojit C++ a Web v praktické aplikaci.
Ve firmě Hobrasoft vyvíjíme distribuovaný CRM systém Deko the CRM. Různých CRM systémů jsou na světě mraky, takže přijít s něčím novým je obtížné. Za výhodu našeho CRM považujeme nezávislost na připojení k internetu. Databáze CouchDB, na které je aplikace postavená, dovolí uživatelům pracovat offline a přitom nejsou nijak omezení ve sdílení dat. Deko je určené jak pro Windows, tak pro Linux.
Jedním z úkolů, před které nás potřeby aplikace postavily, byly tiskové sestavy. Celá aplikace je napsaná v C++ a Qt, takže se nabízela možnost použít C++ i pro tvorbu sestav. Ale tvořit něco v C++ je nepružné i pro nás a představa, že by si mohl uživatel sám vytvořit sdílenou knihovnu se sestavou je čirá utopie. Jak z takové situace ven?
Můj první nápad byl vlastní tabulkový kalkulátor vestavěný v aplikaci. Uživatelé jsou na tabulky zvyklí, nemuselo by jim to činit potíže. Malý průzkum bojem ale ukázal, že potíže by mohl činit tabulkový kalkulátor nám - naprogramovat něco použitelného je pracné.
Druhý nápad bylo použít HTML. Něco vzdáleně podobného už jsme měli hotové:
http://weko.hobrasoft.cz/timesheet/default/288KFTU
Ale to je napsané v PHP a potřebuje to celý ten veliký cirkus spojený s webovými aplikacemi - http server, php interpreter a napojení na databázi (u každého uživatele jiné).
Naštěstí k provádění nějakého programu ve webovém prohlížeči není potřeba PHP, webové prohlížeče už léta dokáží zpracovávat JavaScript a knihoven pro manipulaci HTML stránek je spousta. Spousta je i programátorů - na rozdíl od C++ dnes HTML a Javascript zvládá velké množství lidí.
Takže stačí už jen napsat a připojit k aplikaci webový prohlížeč. V Qt je situace jednoduchá: stačí přilinkovat webkit.
Sestavy obvykle čerpají své podklady z nějaké databáze. Databázi je proto nutné zpřístupnit i do webového prohlížeče. Prohlížeče získávají data dvojím způsobem: pomocí url, například:
nebo přes JavaScript, každý prohlížeč ve speciálním objektu document zpřístupňuje zobrazovanou html stránku:
var html = document.documentElement.outerHTML;
V aplikaci Deko jsme databázi zpřístupnili podobně. Jednak přes speciální url:
deko:///id-dokumentu-v-databazi
nebo přes objekt JavaScriptu:
var dokument = deko.get('id-dokumentu-v-databazi');
Vestavěný webkit se k tomu dá donutit poměrně snadno.
Třída WebView obsahuje webovou stránku, u níž musíme přepsat třídu QNetworkAccessManager, aby rozuměla i našemu schematu deko, zajistí to pár řádků kódu:
QNetworkAccessManager *om = f_view->page()->networkAccessManager(); REPORT_access_manager *nm = new REPORT_access_manager(om, this); f_view->page()->setNetworkAccessManager(nm);
Původní QNetworkAccessManager je nahrazený naším vlastním. Nedělá nic jiného, než že ověří url schema a pokud je schéma deko, vytvoří vlastní odpověď, jinak zavolá standardní proceduru:
class REPORT_access_manager : public QNetworkAccessManager {
Q_OBJECT
public:
REPORT_access_manager(QNetworkAccessManager *, QObject *);
QNetworkReply *createRequest( QNetworkAccessManager::Operation,
const QNetworkRequest&,
QIODevice*);
};
REPORT_access_manager::REPORT_access_manager(
QNetworkAccessManager *manager,
QObject *parent) : QNetworkAccessManager(parent) {
setCache (manager->cache());
setCookieJar (manager->cookieJar());
setProxy (manager->proxy());
setProxyFactory (manager->proxyFactory());
}
QNetworkReply *REPORT_access_manager::createRequest(
QNetworkAccessManager::Operation operation, const QNetworkRequest &request,
QIODevice *device) {
if (request.url().scheme() != "deko") {
return QNetworkAccessManager::createRequest(operation, request, device);
}
if (operation != GetOperation) {
return QNetworkAccessManager::createRequest(operation, request, device);
}
return new REPORT_reply (request.url());
}
Vrácená odpověď je mírně rozšířená třída QNetworkReply
class REPORT_reply : public QNetworkReply {
Q_OBJECT
public:
REPORT_reply(const QUrl&);
void abort() {} ;
qint64 bytesAvailable() const;
bool isSequential() const { return true; }
protected:
qint64 readData(char *data, qint64 maxSize);
private:
QByteArray content;
qint64 offset;
};
REPORT_reply::REPORT_reply(const QUrl& url) {
offset = 0;
open(ReadOnly | Unbuffered);
// REQUEST je naše třída pro přístup do databáze, vrací obvykle JSON řetězec
// Při vaší vlastní implementaci sem doplňte vlastní přístup do databáze
REQUEST rq;
rq.setBinary(true);
rq.get(url.path().toUtf8());
content = rq.data();
setHeader(QNetworkRequest::ContentTypeHeader, rq.contentType().toString());
setHeader(QNetworkRequest::ContentLengthHeader, QVariant(content.size()));
QTimer::singleShot(0, this, SIGNAL(metaDataChanged()));
QTimer::singleShot(0, this, SIGNAL(readyRead()));
QTimer::singleShot(0, this, SIGNAL(finished()));
}
qint64 REPORT_reply::bytesAvailable() const {
qint64 bc = content.size() - offset;
return bc;
}
qint64 REPORT_reply::readData(char *data, qint64 maxSize) {
if (offset < content.size()) {
qint64 number = qMin(maxSize, content.size() - offset);
memcpy(data, content.constData() + offset, number);
offset += number;
return number;
} else {
return -1;
}
}
K webové stránce zobrazené ve webkitu lze snadno připojit libovolný QObject:
QWebFrame *frame = f_view->page()->mainFrame();
frame->addToJavaScriptWindowObject("deko", m_report_script);
Pod jménem deko bude objekt m_report_script přístupný ve webové stránce pomocí JavaScriptu.
U tohoto objektu uvedu pouze deklaraci, samotný kód už není tak důležitý:
class REPORT_SCRIPT : public QObject {
Q_OBJECT
public:
REPORT_SCRIPT(QObject *parent);
Q_INVOKABLE QString id();
Q_INVOKABLE QVariant get(const QString& id);
Q_INVOKABLE QVariant document(const QString& id);
Q_INVOKABLE QVariant linksToMe(const QString& id);
Q_INVOKABLE QVariant linksFromMe(const QString& id);
Q_INVOKABLE QString hash(const QString& text);
Q_INVOKABLE void begin() { emit jobBegin(); }
Q_INVOKABLE void end() { emit jobEnd(); }
Q_INVOKABLE QString userid();
signals:
void jobBegin();
void jobEnd();
};
Makrem Q_INVOKABLE deklaruji metodu jako přístupnou z JavaScriptu. Zajímavé je předávání výsledné hodnoty (podobně lze předávat i parametry). Vrací-li metoda QVariant, použije se v JavaScriptu taková hodnota jako objekt. V C++ vypadá vytvoření takového objektu například takto:
QVariantMap data; data["_id"] = "id-meho-objektu"; data["name"] = "Jmeno objektu"; QVariantList list; list << "abcd" << "1234"; data["list"] = list; return data;
V Javascriptu se interpretuje stejně, jako by se interpretoval tento JSON literár:
{ "_id": "id-meho-objektu", "name": "Jmeno objektu", "list": [ "abcd", "1234"] }
V Javascriptu je použití snadné:
var x = deko.metoda();
var id = x._id;
var name = x.name;
for (var i=0; i<x.list.length; i++) {
// Udělej něco
neco( deko.list[i] );
}
Nakonec několik ukázek: Vestavěná google mapa, hotová sestava a kus zdrojového tvaru sestavy. S webkitem dostanete i luxusní debugger - ten je vidět na posledním obrázku.
Tiskni
Sdílej:
QNetworkAccessManager a ReportAccessManager, nebo ještě lépe Report::NetworkAccessManager.
CamelCase... jdu blejt...
Díky za zápisek. Taky se chystám pustit do jednoho projektu s Qt(WebKitem), tak mě potěšilo, že tam jsou tyhle věci celkem jednoduché.
Ta VELKÁ písmena a podtržítka v názvech tříd se mi taky nelíbí, ale nevím, jaké jsou konvence v okolním kódu, tak to nechci hodnotit.
Mám ale jednu věcnou připomínku k návrhu: jak funguje třída REQUEST („…je naše třída pro přístup do databáze“)? To je nějaký singleton? Kde vezme spojení do databáze nebo jiné zdroje? IMHO by bylo lepší, aby je dostávala jako parametr z toho kontextu, ve kterém je používána, ne že si je někde obstará sama.
...proxy objekt...To mě zajímá. Nevyznám se příliš ve webových technologiích, nevím, co si pod tím představit. Jinak vlastní protokol používám právě proto, že nepředpokládám použití jinde, než v rámci aplikace. Navíc v režimu, kdy předem nevím, jak připojení k databázi vypadá a kdy jednu sestavu může používat více lidí s naprosto odlišným připojením k databázi.
/hello/world namísto http://example.org/hello/world či deko:/hello/world. Pak je můžeš vzít jak jsou a poslat po HTTP do běžného prohlížeče.
No a aby fungovalo připojení k databázi, tak místo deko objektu, který máš teď, tam dáš proxy objekt, což je v Javascriptu implementovaný obyčejný objekt přeposílající volání metod na server a vracející obdržené odpovědi. Na serveru pak bude za nějakým HTTP API schovaný skutečný deko objekt, který udělá všechnu dřinu. Pokud proxy i originál budou mít stejné API, můžeš bezezměn zveřejnit tiskové sestavy na webu i v aplikaci a navíc to bude skoro bez práce (stačí udělat jen ten proxy objekt a aplikaci spustit jako démona bez GUI).
Pointa je v tom, aby jsi si teď nezadělal na problémy v budoucnu, kdy s tím budeš chtít něco dělat a budeš mít spoustu hotových sestav.
QWebView::setUrl("deko:/hello/world/"); by mělo stačit.
QWebView::setHtml( html, QUrl("deko:///hello/world") );
Html se bere z externího editoru