Edison Design Group po více než 30 letech zveřejnil zdrojový kód svého EDG C/C++ front-endu. Ten proslul širokou podporou standardů C++ a kompatibilitou s dialekty kompilátorů od Microsoftu, GNU, Clangu, Sunu a dokonce i s prehistorickým cfrontem. EDG byl použit například v kompilátoru Intel C++ Classic, kompilátoru NVCC od firmy NVIDIA pro platformu CUDA nebo v našeptávači kódu IntelliSense v produktech společnosti Microsoft. Projekt nyní spravuje organizace The C++ Alliance a kód je dostupný pod licencí Apache 2.0, doplněnou o výjimky projektu LLVM.
Pocket Tank je malé kapesní virtuální akvárium postavené na vývojové desce ESP32-S3-Touch-AMOLED-1.8. Na dvoujádrovém mikrokontroléru ESP32-S3 s 8 MB PSRAM a 16 MB flash paměti běží jak simulace akvária, tak i malý jazykový model určující chování rybiček. Lokální model o velikosti 7,56 MB se 14 miliony parametrů vznikl destilací modelu Gemma 4 26B, tedy učitele s 26 miliardami parametrů. Kromě firmwaru pro skutečný modul s AMOLED
… více »Open-source nástroj Jevstiller vytváří (destiluje) malý lokální model, který se průběžně učí z odpovědí komerční služby Jev. Běžné dotazy vyřizuje přímo na vlastním hardware, čímž může řádově zkrátit čas odezvy a snížit provozní náklady díky menšímu využívání zpoplatněného API. Nejisté požadavky Jevstiller posílá do Jevu, rovněž průběžně kontroluje náhodná dvě procenta dotazů Jevem. Pokud se lokální model začne s Jevem rozcházet,
… více »Konference LinuxDays 2026 proběhne již tento víkend 3. a 4. října v Praze v areálu ČVUT v Dejvicích na FIT. Konference LinuxDays 2026 znamená desítky přednášek a workshopů, zástup zajímavých osobností, místo pro setkání, spoustu nových nápadů a informací a stánky řady různých projektů: Fedora, openSUSE, vpsFree.cz, Mozilla, MacGyver - bastlíři SH, OpenAlt a mnoho dalších. Vstup je volný.
Microsoft oznámil, že WSL kontejnery (WSLC) aneb linuxové kontejnery ve Windows Subsystem for Linux (WSL) jsou již obecně dostupné. Současně popsal jejich architekturu.
openSUSE Leap 16.1 vstoupil do RC fáze. Nově lze instalovat jako standardní systém (Standard) nebo jako neměnný systém s atomickými aktualizacemi (Immutable). Samostatná neměnná distribuce openSUSE Leap Micro končí.
Byl vydán Mozilla Firefox 157.0. S nejvýraznější vizuální proměnou za poslední roky. Přehled novinek v poznámkách k vydání a poznámkách k vydání pro vývojáře. Řešeny jsou rovněž bezpečnostní chyby. Nový Firefox 157 bude brzy k dispozici také na Flathubu a Snapcraftu.
Rodina produktů Raspberry Pi se rozšířila o Raspberry Pi Smart Display Module. Deska pro Raspberry Pi Compute Module 5 se zasouvá přímo do displejů dle specifikace Intel SDM. Cena desky je 30 dolarů.
Byla vydána nová verze 2.56.0 distribuovaného systému správy verzí Git. Přispělo 104 vývojářů, z toho 39 nových. Přehled novinek v příspěvku na blogu GitHubu a v poznámkách k vydání.
Hackerská skupina ShinyHunters oznámila průnik do informačních systémů FBI, prostřednictvím zero-day zranitelnosti v platformě Oracle PeopleSoft, kterou úřad využívá mimo jiné pro náborový portál FBIJobs.gov. Útočníci tvrdí, že získali až 3 TB dat o současných i bývalých zaměstnancích a uchazečích o práci. Jako důkaz zveřejnili vzorek přibližně 5 000 záznamů obsahující jména, adresy, telefonní čísla, data narození, čísla
… více »Plasmoidy, to nejsou jen applety na plochu, ale zahrnují i tzv. runnery. Runner je knihovna, kterou využívá KRunner. Když píšete název nějaké aplikace, KRunner postupně volá hlavní funkce všech dostupných runnerů a předává jim zadaný řetězec (tzv. Context). Každý runner vrací seznam relativních položek (Plasma::QueryMatch). Při kliknutí na vybraný QueryMatch KRunner zavolá funkci run příslušného Runneru, který zařídí, aby se vykonala příslušná událost.
Jako příklad pro dnešní článek použijeme jeden můj starší runner, který umožňuje prohledávat kontakty z Kopete. Kliknutím na kontakt se rovnou otevře chatovací okno Kopete. Celá komunikace probíha přes rozhraní DBus. Podobný, ale ještě o něco propracovanější runner najdete v KDE SC 4.4.

Runner je třída odvozená od Plasma::AbstractRunner a musí implementovat tři metody:
Konstruktor, ve kterém se nastavují výchozí vlastnosti Runneru.
match(Plasma::RunnerContext &context), která se volá vždy, když se změní text v KRunneru. Ten získáme pomocí metody Plasma::RunnerContext.query(). Plasma::RunnerContext má ještě jednu další šikovnou vlastnost, kterou zjistíme pomocí metody isValid(). Ta vrací true, pokud je RunnerContext stále platný, a false, pokud se RunnerContext mezitím změnil (např. uživatel napsal další znak) – v takovém případě runner zpravidla skončí, protože už běží jeho nová instance s novým kontextem a ten stavající je zneplatněn (jeho výstup nebude zobrazen).
Třetí metodou, kterou musí runnery implementovat, je run(Plasma::RunnerContext &context, Plasma::QueryMatch &match), která se volá, když uživatel klikne na položku v seznamu výsledků. Jako parametr přijímá ukazatel na příslušný QueryMatch. V QueryMatch lze, kromě zobrazovaných hodnot, uložit ještě hodnotu skrytou, která obsahuje například URL, která se má otevřít a podobně. Context obsahuje aktuální kontext, pro který je daný QueryMatch platný.
A teď od teorie k praxi.
kopetecontacts.h
#ifndef KOPETECONTACTS_H
#define KOPETECONTACTS_H
#include <Plasma/AbstractRunner>
#include <KIcon>
class KopeteContactsRunner : public Plasma::AbstractRunner
{
Q_OBJECT
public:
KopeteContactsRunner(QObject *parent, const QVariantList& args );
~KopeteContactsRunner() { }
void match(Plasma::RunnerContext &context);
void run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match);
private:
KIcon m_icon;
};
// Makro pro registraci runneru
K_EXPORT_PLASMA_RUNNER(kopetecontacts, KopeteContactsRunner)
#endif // KOPETECONTACTS_H
#endif
Důležité je nezapomenout na makro pro registraci runneru do KDE. První parametr je název pluginu, pod kterým ho systém bude znát. Musí odpovídat hodnotě X-KDE-PluginInfo-Name v souboru .desktop. Druhým parametrem je název třídy runneru.
kopetecontacts.cpp
#include "kopetecontactsrunner.h"
// Vloží podporu QtDbus
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusReply>
#include <KIcon>
KopeteContactsRunner::KopeteContactsRunner(QObject *parent, const QVariantList& args)
: Plasma::AbstractRunner(parent, args)
{
// Umlčí překladač
Q_UNUSED(args);
// Název runneru
setObjectName("KopeteContacts");
// Použije ikonku Kopete
m_icon = KIcon("kopete");
// Bude ignorovat všechny generické typy kontextu
setIgnoredTypes(Plasma::RunnerContext::Directory |
Plasma::RunnerContext::File |
Plasma::RunnerContext::NetworkLocation |
Plasma::RunnerContext::Executable |
Plasma::RunnerContext::ShellCommand);
// Přiklad syntaxe
addSyntax(Plasma::RunnerSyntax(":q:", "Zahaji chat s :q:"));
// DBus protocol je pomalý…
setSpeed(AbstractRunner::SlowSpeed);
}
void KopeteContactsRunner::match(Plasma::RunnerContext &context)
{
// Vyhledávání nebude case-sensitive
QString searchedName = context.query().toLower();
// Nebude se vyhledávat pro kontexty kratší než 3 znaky
if (searchedName.length() < 3) {
return;
}
// Pokusí se navázat DBus spojení s Kopete
QDBusInterface kopeteDBusTest("org.kde.kopete", "/Kopete", "org.freedesktop.DBus.Introspectable");
QDBusReply<QString>kopeteReply = kopeteDBusTest.call("Introspect");
if (!kopeteReply.isValid()) {
return;
}
// Vytvoří seznam výsledků
QList<Plasma::QueryMatch> matches;
// Načte seznam všech kontaktu
QDBusInterface kopeteDBus("org.kde.kopete","/Kopete","org.kde.Kopete");
QDBusReply<QStringList> kopeteContacts = kopeteDBus.call("contacts");
QString contactName;
// Projde všechny kontakty
for (int i = 0; i < kopeteContacts.value().size(); i++) {
// Nemá smysl pokračovat, pokud aktuální kontext už neni platný
if (!context.isValid()) {
return;
}
// Načte informace o kontaktu
QDBusReply<QVariantMap>contactData = kopeteDBus.call("contactProperties",kopeteContacts.value().at(i));
// Uloží jméno kontaktu
contactName = contactData.value().value("display_name").toString();
// Zjistí, jestli kontext odpovídá kontaktu
bool matched = contactName.contains(searchedName, Qt::CaseInsensitive);
// Pokud ano, tak přidáme výsledek do QueryMatch
if (matched) {
// Vytvoří nový QueryMatch
Plasma::QueryMatch matchItem(this);
// Nastaví mu ikonu
matchItem.setIcon(m_icon);
// Jako hlavní název QueryMatch nastaví název kontaktu
matchItem.setText(contactName);
// Načte status kontaktu
QString statusMessage = contactData.value().value("status_message").toString();
if (not statusMessage.isEmpty()) {
statusMessage.prepend(": ");
}
// Jako popis QueryMatch nastaví název a popis statusu
matchItem.setSubtext(contactData.value().value("status").toString().append(statusMessage));
// Jako data (skrytá, nezobrazují se) nastaví UID
matchItem.setData(kopeteContacts.value().at(i));
// Pokud kontakt přesně odpovídá kontextu, nastavíme ExactMatch
if (contactName == searchedName) {
matchItem.setType(Plasma::QueryMatch::ExactMatch);
} else {
matchItem.setType(Plasma::QueryMatch::PossibleMatch);
}
// Přidá tento QueryMatch do seznamu
matches.append(matchItem);
}
}
// Uloží do kontextu seznam QueryMatchů
context.addMatches(searchedName,matches);
}
void KopeteContactsRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match)
{
// Umlčí překladač
Q_UNUSED(context);
QString uid = match.data().toString();
// Pokusí se navázat DBus spojení s Kopete
QDBusInterface kopeteDBusTest("org.kde.kopete", "/Kopete", "org.freedesktop.DBus.Introspectable");
QDBusReply<QString>kopeteReply = kopeteDBusTest.call("Introspect");
if (!kopeteReply.isValid()) {
return;
}
QDBusInterface kopeteDBus("org.kde.kopete","/Kopete","org.kde.Kopete");
kopeteDBus.call("openChat",uid);
}
#include "kopetecontactsrunner.moc"
V konstruktoru se podíváme podrobněji na metody setSpeed a addSyntax. Metoda setSpeed nastavuje rychlost Plasmoidů. Výchozí hodnota je rychlá, ale pokud runner pužívá internetové připojení nebo DBus, měla by se rychlost nastavit na AbstractRunner::Slow – KRunner pak počítá s tím, že na takový runner musí čekat o něco déle. Metoda addSyntax přijímá objekt Plasma::RunnerSyntax. Plasma::RunnerSyntax v konstruktoru přijímá dva parametry – syntaxi vstupu, kde :q: je symbol pro vyhledávaný výraz a popis vstupu. Pokud například chcete, aby vstup vypadal „kontakt jméno_kontaktu“, vložili byste do addSyntax objekt Plasma::RunnerSyntax("kontakt :q:","Vyhledá kontakt :q:")).
V metodě match je na konci volána metoda context.addMatches, která jako parametr přijímá seznam všech nalezených položek, které se mají zobrazit.
Stejně jako applet, i runner musí mít svůj soubor .desktop, podle kterého ho KDE může najít.
plasma-runner-idossearchrunner.desktop
[Desktop Entry] Name=Kopete Contacts Comment=Start chat with your Kopete contacts ServiceTypes=Plasma/Runner Type=Service Icon=kopete X-KDE-Library=krunner_kopetecontacts X-KDE-PluginInfo-Author=Dan Vratil X-KDE-PluginInfo-Email=vratil@progdansoft.com X-KDE-PluginInfo-Name=kopetecontacts X-KDE-PluginInfo-Version=0.1 X-KDE-PluginInfo-License=GPL X-KDE-PluginInfo-EnabledByDefault=true
Důležité je, aby X-KDE-PluginInfo-Name odpovídalo hodnotě v makru v hlavičkovém souboru.
CMakeLists.txt
# Název projektu
project(kopetecontactsrunner)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
# Najde požadované komponenty
find_package(KDE4 REQUIRED)
find_package(Qt4 REQUIRED)
find_package(KDE4Workspace REQUIRED)
find_package(Kopete REQUIRED)
include (KDE4Defaults)
# Nastaví definice
add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
# Nastaví adresáře s hlavičkovými soubory
include_directories (${KDE4_INCLUDES}
${KDE4WORKSPACE_INCLUDE_DIR}
${QT_INCLUDE_DIR}
${QT_QTDBUS_INCLUDE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/libs)
set(krunner_kopetecontacts_SRCS
kopetecontactsrunner.cpp
)
# Přidá plugin do KDE
kde4_add_plugin(krunner_kopetecontacts ${krunner_kopetecontacts_SRCS})
# Slinkuje knihovnu
target_link_libraries(krunner_kopetecontacts ${KDE4_PLASMA_LIBS})
# Nainstaluje soubory
install(TARGETS krunner_kopetecontacts DESTINATION ${PLUGIN_INSTALL_DIR} )
install(FILES plasma-runner-kopetecontacts.desktop DESTINATION ${SERVICES_INSTALL_DIR})
Nyní je potřeba restartovat KRunner:
kquitap krunner kstart krunner
Nyní můžete runner otestovat – když začnete psát název některého ze svých kontaktů v Kopete, budou se relevantní kontakty zobrazovat v KRunneru.
Možností, jak rozšířit KRunner, je mnoho. Runnery mohou, stejně jako applety, také používat DataEnginy a mít dialog pro konfiguraci. Jedinou nevýhodou je, že není možná interakce s uživatelem (kromě úvodního vstupu). Nakonec ještě přikládám tarball se zdrojovými kódy.
Nástroje: Tisk bez diskuse
Tiskni
Sdílej:
Hodilo by se udělat něco podobného pro psi, jenže tam by se nejdříve musely doimplementovat potřebné DBUS metody.
$qdbus org.psi-im.Psi /Main method void org.psi_im.Psi.Main.openURI(QString uri) method void org.psi_im.Psi.Main.raise() method void org.psi_im.Psi.Main.setStatus(QString status, QString message) method void org.psi_im.Psi.Main.sleep() method void org.psi_im.Psi.Main.wake() method QDBusVariant org.freedesktop.DBus.Properties.Get(QString interface_name, QString property_name) method QVariantMap org.freedesktop.DBus.Properties.GetAll(QString interface_name) method void org.freedesktop.DBus.Properties.Set(QString interface_name, QString property_name, QDBusVariant value) method QString org.freedesktop.DBus.Introspectable.Introspect()
Co se rychlost tyce, ja sem si treba musel v KDE 4.4 vypnout Nepomuk Desktop Search runner protoze KRunner zabijelo cekani na odpoved z Virtuosa...kazdopadne mam moznost srovnat (sic jen subjektivne, ale preci) rychlost KRunneru v KDE 4.3 a v 4.4 a ten vyvoj je tam znatelny. Za hodne muze i optimalizace, kterou si prosla vetsina Runneru. Ale ne vzdy to plati (viz Virtuoso).
Nejakou cache bych samozrejme uvital, otazkou je jak zajistovat jeji aktualizaci, zejmena u veci, ktere se casto meni (statusy kontaktu napriklad).