Skip to content

Monday, 20 May 2024

In Plasma, when the user wants to do some significant layout change in the desktop, such as adding, moving or removing panels or add and manage desktop widgets, will go in the so called “edit mode”, by a context menu entry when driven by mouse, or by long-press in the desktop when driven by touchscreen.

Let me introduce you the improved edit mode workflow Plasma 6.1 will have:

An “edit mode” is necessary because since is an operation potentially destructive, we really want to avoid the user to for instance remove their own taskbar or some similar operation by mistake, during day to day use.

“Modes” in UI are a delicate thing: they have advantage as well many possible problems, which come in when it’s not immediately clear in which mode the user is in, and can try to use the UI as it was “in the other mode” (see https://www.nngroup.com/articles/modes/ as a quick introduction on advantages and disadvantages of modes).

This was a bit of a problem of the edit mode in plasma, as the edit mode was not clearly visually separated with the normal UI workflow of the day to day plasma usage.

Another problem present was that the action buttons of the edit mode toolbar were often hidden away by either the panel configuration window or the add widgets sidebar.

This new mode zooms out the desktop with the same visual effect of the window overview effect (yay for consistency), to well differentiate between normal and edit mode. Using the same zoom effect it puts the whole desktop “out of the way” when either the add widget sidebar of the panel configuration window appear, making sure the whole desktop area is always reachable, applets can be dropped anywhere in the desktop and the edit mode toolbar is always completely accessible.

Sorry to annoy you, I would prefer not to deal with politics either, but considering that Mastodon recently lost its status as a nonprofit organisation in Germany without an explanation we cannot ignore that there very much is a direct impact of politics on what we do.

As someone who is collaborating with an international group of nice and smart people every day, it might not come as a surprise that I am opposed to all those parties that keep blaming migration and foreigners for every political failure. Let us try to support the innocent people who are being attacked by terrorist groups or nations. Way too many parties are hostile towards people who try to have a happy, honest life while ignoring or understating the importance of fair taxation and reducing greenhouse gas emissions.

You might say: “But all the parties are corrupt!” – Well, true. In every group there is a share of psychopaths. We even have some in KDE! (Surprisingly few though!) This should not deter you from contributing. Please be the change you want to see in the world and vote for the party that sucks the least! Or don't, it's your life and I am not your mom. Thanks for reading. :^)

A few weeks ago (Time flies!) I attended the KDE Goals Sprint in Berlin. I didn't have concrete plans, but I intended to look into accessibility. Quite some time ago I had improved the accessibility of Kleopatra and at Akademy 2023 in Thessaloniki I gave a talk about it. Back then I had taken the easy route fixing everything directly in Kleopatra and working around several issues in Qt instead of fixing the issues in Qt itself so that all apps could profit. Time to do something about it.

(In-)Accessible icon-only buttons

A common problem for accessibility is icon-only buttons. If a button doesn't have text then screen readers can only tell their user that there's a button. That's not very helpful. Sometimes the developers have at least assigned a tool tip to the button. This can be read out by the screen readers (Qt provides the tool tip as accessible description of the button.), but it's often too verbose. To make a button without text accessible the developer has to set the accessible name property of the widget or, in case of a Qt Quick app, the name property of the Accessible QML Type. Unfortunately, that's often forgotten if the UI isn't designed with accessibility in mind.

At the sprint I discussed several ideas with other participants to help developers remember to set the accessible name:

  • A helper class to instantiate in your app which inspects the app's windows and prints a report at the end with all inaccessible icon-only buttons it has found. A bit like Qt's QAbstractItemModelTester or the different compiler sanitizers. I implemented a prototype of such a class, but didn't pursue this further. The downside of this approach is that the developer needs to open each window of the app to find all inaccessible buttons. If they are already aware of the problem then it's probably easier to search the code.
  • Instead of using a helper class to inspect the widget tree from the inside one could inspect the accessibility tree of the app from the outside. This could be built into our Appium-driven UI test framework so that developers don't have to do anything special. Except that they need to write UI tests that open each and every window of their app. I think it's still worth to look into this.
  • Last but not least, we pondered writing a clazy test. Thinking about the many different ways a text can be set on a button (e.g. with KGuiItem::assign) we doubted that it would be feasible to write such a test.

In the end the easiest approach could be education. If the developers are aware of the problem then there's a good chance that they remember to set an accessible name the next time they add an icon-only button to their app.

Accessible date/time inputs

Volker, Carl, David, Harald and me discussed and explored some ideas to make the date and time inputs in Qt Quick apps like Itinerary accessible. In Kleopatra I resorted to allow the user to enter the date in a simple text input instead of trying to make the complex UI of KDE's date picker accessible. Read Volker's blog and David's blog to find out which solutions they found for Qt Quick apps.

A small automation interlude

One advantage of sitting with other people in the same room is that you may overhear them talking about a mistake (e.g. a faulty commit) and you know exactly how to prevent this kind of mistake in the future. In this case the problem was a missing quote character in some YAML file. And the preventive measure was adding a YAML linter CI job. While I was at it I removed some unnecessary code from the CI job and added the job to a second repository.

List views with underlying multi-column model

In several widgets that show or use a simple list of items Qt allows using a model with multiple columns, e.g. QListView, QComboBox, QCompleter. In general this works well except that Qt has a long-standing bug: When navigating through the list screen readers read the entries of the underlying model column by column instead of reading only the entries in the selected model column (QTBUG-33786). In Kleopatra I worked around this bug with a proxy model which pretended that the model only had one column.

During the sprint I finally sat down and prepared a fix for Qt. For better readability I split my changes in five separate commits which resulted in five separate patches for Qt: 556857, 556858, 556859, 556860, 556861. Being used to multi-commit MRs in GitLab I wondered if I had done something wrong when I submitted my changes, but apparently that's Gerrit's way of handling patch reviews. The first two commits are code clean-ups, the third commit changes one aspect of the accessibility test for list views, the fourth commit is the actual fix, and the fifth commit adds a few more unit tests I find useful. The first three commits have been merged, but the actual fix is still waiting for a review.

After that I looked into the problem that QListView emitted an accessibility focus event when the current item changed even if the list view didn't have focus. I found out that this had been fixed recently by a fellow Qt contributor who ran into the same problem independently of me. This meant that I could remove the workaround in Kleopatra for new enough Qt.

Thanks to MBition for hosting us and to Aleix for making sure we don't starve. And many thanks to those donating to KDE which makes these sprints possible.

Sunday, 19 May 2024

This is a brief overview of the project that I will be doing this summer as part of Google Summer of Code.

As the title of this post says, I will create Python bindings for KDE Frameworks. There are more than 70 libraries, so the aim is to add support for three of them: KWidgetsAddons, KCoreAddons and KI18n. As predicting how much time we’ll need for each one is a little bit complex, I might end adding support to other libraries if the time allows.

To create the library we’ll use Shiboken, a tool originally created to generate the Python bindings of Qt (PySide6), but it can also be used with non-Qt code. The plan is to have the library be built automatically by the CI on invent.kde.org. I will also add documentation and examples on how to use it.

I still need to figure out a name for the Python library that we hope to upload to PyPI once it becomes usable.

The project is mentored by Carl Schwan, who also proposed the idea.

Friday, 17 May 2024

MarkNote 1.2 🔗

Carl Schwan CarlSchwan 16:15 +00:00
RSS

The MarkNote team is happy to announce the 1.2 release of MarkNote, KDE’s WYSIWYG note-taking application. Marknote lets you create rich text notes and easily organise them into notebooks. You can personalise your notebooks by choosing an icon and accent color for each one, making it easy to distinguish between them and keep your notes at your fingertips. Your notes are saved as Markdown files in your Documents folder, making it easy to use your notes outside of Marknote as well as inside the app.

Notes management

This releases brings highly wanted features like the ability to choose a custom folder where to store your notes. Mathis Brüchert also added the ability to change the sorting of notes from alphabetically to by date.

Mathis made the sidebar collapsable and added a focus mode where everything but the editing page is displayed.

Finally if you prefer to just use Marknote as a Markdown editor, we made it possible to just open any markdown files directly from the file browser or the console. Additionally Marknote supports markdown files with a so called front matter, which is a common way to inject metadata to markdown in static website generators like Hugo and Jekyll.

Editing

In term of edition support, the subset of markdown supported increased again. Now it is possible to add and edit tables.

 

Additionally we started transforming inline markdown directly to rich text as you type. Support is limited to a few markdown constructs but is likely to grow over time.

You can now customize the font used by editor.

 

Aside from being able to edit text, it’s now possible to also create sketches directly from MarkNote.

 

Mobile Support

Mathis took care of ensuring MarkNote was fully usable when used with Plasma Mobile.

Windows and macOS support

Marknote now provides nightly builds for Windows and macOS. While the Windows builds should be fully usable, the macOS build still has an issue where most icons are not displayed. This should be fixed as soon as we can make use of the new KIconTheme version.

As part of the work to improve the macOS support, Marknote also gained global menu support for Linux.

Others

  • The command bar will show translated shortcuts. (Laurent Montel)
  • Unify spelling of MarkNote and fix typos in the README.md (Jonah Brüchert)

Get Involved

Mathis created a Matrix channel for MarkNote: #marknote:kde.org. There is also still a lot of small improvements that can be done everywhere and which don’t require a lot of programming experience. Take a look at these two tasks !31 and !27 for some inspiration on what you could work on.

Let’s go for my web review for the week 2024-20.


Password cracking: past, present, future

Tags: tech, security

Ever wondered about the state of the art in password cracking? This is not an easy read but a good reference.

https://www.openwall.com/presentations/OffensiveCon2024-Password-Cracking/


Beyond public key encryption – A Few Thoughts on Cryptographic Engineering

Tags: tech, cryptography

There are other cryptography schemes out there with interesting properties. Too bad they’re not very much used.

https://blog.cryptographyengineering.com/2017/07/02/beyond-public-key-encryption/


SSD death, tricky read-only filesystems, and systemd magic?

Tags: tech, system, hardware, failure

Strange things do happen when the hardware fails… indeed the systemd open question at the end is mysterious.

https://rachelbythebay.com/w/2024/05/15/ro/


The new APT 3.0 solver | Blog of Julian Andres Klode

Tags: tech, debian, packaging

Interesting work. This is nice to see improvements and experiments in dependency solvers for package managers.

https://blog.jak-linux.org/2024/05/14/solver3/


Extensions for GNU Make

Tags: tech, tools, make

Looks like nice extensions to use GNU Make to run simple tasks.

https://github.com/mitjafelicijan/makext


Which filepath-join behavior is implemented for relative and absolute paths as arguments?

Tags: tech, system, filesystem

You expect joining file paths to be a simple operation? Think again, it’s definitely error prone and can change between stacks.

https://lukas-prokop.at/articles/2024-05-03-filepath-join-behavior


What even is a pidfd anyway?

Tags: tech, processes, system, linux

Definitely a recent and lesser known to interact with other processes. Could be useful in some cases.

https://www.corsix.org/content/what-is-a-pidfd


An informal comparison of the three major implementations of std::string - The Old New Thing

Tags: tech, c++, performance, memory

Interesting quick comparison, this shows the design tradeoffs quite well.

https://devblogs.microsoft.com/oldnewthing/20240510-00/?p=109742


GPUs Go Brrr · Hazy Research

Tags: tech, gpu, hardware, ai, machine-learning, neural-networks, performance

Interesting how much extra performance you can shave off the GPU by going back to how the hardware works.

https://hazyresearch.stanford.edu/blog/2024-05-12-tk


Sir, there’s a cat in your mirror dimension

Tags: tech, graphics, mathematics, funny

Funny experiment playing with the frequency domain and the spatial domain of an image. This gives unintuitive results for sure.

https://lcamtuf.substack.com/p/sir-theres-a-cat-in-your-mirror-dimension


Snapshot Testing For the Masses

Tags: tech, tests, snapshots

This is a technique which is definitely underestimated. There are plenty of libraries out there allowing to use them.

https://tigerbeetle.com/blog/2024-05-14-snapshot-testing-for-the-masses


Laurence Tratt: What Factors Explain the Nature of Software?

Tags: tech, programming, software, craftsmanship, engineering

Good food for thought. Explains quite well the factors which impact software development.

https://tratt.net/laurie/blog/2024/what_factors_explain_the_nature_of_software.html



Bye for now!

强制类型转换

C++提供了四个强制类型转换的关键字:

  • static_cast
  • const_cast
  • reinterpret_cast
  • ``dynamic_cast`

static_cast

1
static_cast<目标类型>(表达式)
1
2
int num = 2;
double result =static_cast<double>(num);

该运算符将表达式转换为目标类型。但没有进行运行时类型检查来保证转换的安全性

主要用法

  1. 用于类层次结构中父类和子类之间指针或引用的转换.进行上行转换是安全的(即将子类的指针或引用转换成父类是正确的);进行下行转换的时候,由于没有动态类型检查,所以是不安全的。继承必须为public
  2. 用于基本类型之间的转换,如intchar安全性也需要程序员来保证
  3. 把空指针转换为目标类型的空指针
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Person
{
public:
void print()
{
cout << "Person " << endl;
}
};

class Son : public Person
{
public:
void print()
{
cout << "Son " << endl;
}
};

void print1(Person *p)
{
p->print();
}

int main()
{
Son s;
print1(static_cast<Person *>(&s));
return 0;
}

const_cast

const_cast是c++中专用于处理与const相关的强制类型转换的关键字

其功能为:为一个变量重新设定其const描述.

即:const_cast可以为一个变量强行增加或删除其const限定.

需要明确的是,即使用户通过const_cast强行去除了const属性,也不代表当前变量从不可变变为了可变。const_cast只是使得用户接管了编译器对于const限定的管理权,故用户必须遵守“不修改变量”的承诺。如果违反此承诺,编译器也不会因此而引发编译时错误,但可能引发运行时错误。

  1. const_cast可用于更改const成员函数内的非const类成员。
  2. const_cast可用于将const数据传递给不接收const的函数。
  3. const_cast<>里边的内容必须是引用或者指针。
  4. const_cast也可以用来抛弃volatile__unaligned属性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Student
{
private:
int roll;
public:
Student(int r) :roll(r) {}
void fun() const
{
(const_cast<Student*> (this))->roll = 5;
}
int getRoll() { return roll; }
};

int main() {
Student student(3);
std::cout << "Old roll number: " << student.getRoll() << std::endl;
student.fun();
std::cout << "New roll number: " << student.getRoll() << std::endl;

// const_cast只能调节类型限定符,不能更改基础类型
int a1 = 40;
//const int* b1 = &a1;
//char* c1 = const_cast <char*> (b1); // 编译程序时出错

const volatile int* d1 = &a1;
std::cout << "typeid of d1 " << typeid(d1).name() << '\n'; // int const volatile *
int* e1 = const_cast <int*> (d1);
std::cout << "typeid of e1 " << typeid(e1).name() << '\n'; // int *

return 0;
}

在const成员函数fun()中,编译器将“this”视为“ const student const this”,即“this”是指向常量对象的常量指针,因此编译器不允许通过以下方式更改数据成员“这个”指针。const_cast将“this”指针的类型更改为“student const this”

const_cast比简单类型转换更安全。从某种意义上讲,如果强制类型与原始对象不相同,则强制转换不会发生,这是比较安全的。

1
2
3
int a=20;
const int *p=&a;
char *c1=const_cast<char*> (p);//编译时程序出错

reinterpret_cast

reinterpret,即重新解释.

该强制类型转换的作用是提供某个变量在底层数据上的重新解释.

当我们对一个变量使用reinterpret_cast后,编译器将无视任何不合理行为,强行将被转换变量的内存数据重解释为某个新的类型。用于进行各种不同类型的指针之间、不同类型的引用之间以及指针和能容纳指针的整数类型之间的转换。转换时,执行的是逐个比特复制的操作。 它不检查指针类型和指针所指向的数据是否相同。

需要注意的是,reinterpret_cast要求转换的两个数据所占用的内存大小一致,否则会引发编译时错误.

1
data_type *var_name = reinterpret_cast <data_type *>(pointer_variable);

使用 reinterpret_cast 的目的:

  1. reinterpret_cast是一种非常特殊且危险的类型转换操作符。并且建议使用适当的数据类型使用它,即(指针数据类型应与原始数据类型相同)。
  2. 它可以将任何指针类型转换为任何其他数据类型。
  3. 当我们要使用位时使用它。
  4. 它仅用于将任何指针转换为原始类型。
  5. 布尔值将转换为整数值,即0表示false,1表示true。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class A {
public:
int a;
A(int i) :a(i) {}
void fun_a()
{
std::cout << "In class A\n";
}
};

class B {
public:
int b;
B(int i) :b(i) {}
void fun_b()
{
std::cout << "In class B\n";
}
};

void testReinterpretCast() {
B *x = new B(5);
A* y = reinterpret_cast<A*>(x);
y->fun_a(); // In class A
std::cout << y->a << std::endl; // 5
}

dynamic_cast

dynamic用于在运行时实现向下类型转换。

1
dynamic_cast <type-id> (expression)

expression转换为type-id类型,type-id必须是类的指针,类的引用或者是void,

如果type-id是一个指针,那么expression也是一个指针,是引用的话同为引用

特点如下:

  1. 它是在运行是进行处理的,其余三个都是在编译时完成. 运行时进行类型检查
  2. 不能用于内置的基本数据类型之间的强制转换
  3. dynamic_cast 要求 <> 内所描述的目标类型必须为指针或引用。dynamic_cast 转换如果成功的话返回的是指向类的指针或引用,转换失败的话则会返回 nullptr
  4. 在类的转换时,在类层次上进行向上转换(子类指针指向父类指针),与static_cast的效果是一样的。在进行父类指针向子类指针的转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
  5. 向下转换的成功与否还与将要转换的类型有关,即要转换的指针指向的对象的实际类型与转换以后的对象类型一定要相同,否则转换失败。在C++中,编译期的类型转换有可能会在运行时出现错误,特别是涉及到类对象的指针或引用操作时,更容易产生错误。dynamic_cast操作符则可以在运行期对可能产生问题的类型转换进行测试。
  6. 使用 dynamic_cast 进行转换的,基类中一定要有虚函数,否则编译不通过(类中存在虚函数,就说明它有想要让基类指针或引用指向派生类对象的情况,此时转换才有意义)。这是由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表中,只有定义了虚函数的类才有虚函数表。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class AA {
public:
virtual void print() {
cout << "in class AA" << endl;
};
};

class BB :public AA {
public:
void print() {
cout << "in class BB" << endl;
};
};

void testDynamicCast() {
AA* a1 = new BB; // a1是A类型的指针指向一个B类型的对象
AA* a2 = new AA; // a2是A类型的指针指向一个A类型的对象

BB* b1, * b2, * b3, * b4;

b1 = dynamic_cast<BB*>(a1);// not null,向下转换成功,a1 之前指向的就是 B 类型的对象,所以可以转换成 B 类型的指针。
if (b1 == nullptr)
cout << "b1 is null" << endl;
else
cout << "b1 is not null" << endl;

b2 = dynamic_cast<BB*>(a2);// null,向下转换失败
if (b2 == nullptr)
cout << "b2 is null" << endl;
else
cout << "b2 is not null" << endl;

// 用 static_cast,Resharper C++ 会提示修改为 dynamic_cast
b3 = static_cast<BB*>(a1);// not null
if (b3 == nullptr)
cout << "b3 is null" << endl;
else
cout << "b3 is not null" << endl;

b4 = static_cast<BB*>(a2);// not null
if (b4 == nullptr)
cout << "b4 is null" << endl;
else
cout << "b4 is not null" << endl;

a1->print();// in class BB
a2->print();// in class AA

b1->print();// in class BB
//b2->print(); // null 引发异常
b3->print();// in class BB
b4->print();// in class AA
}

详细

Wednesday, 15 May 2024

So, recently, I shifted some of my workload to kde. And I started my KDE journey with KDE Neon. Even with a 2 year old base and packages, snaps and ppas saved me. Now, one of the important part of my work was to clone the repo using ssh. And here comes the problem.

In gnome, the gnome-keyring and the seahorse would automatically manage my ssh and gpg key passphrases. But, in KDE, that didn’t happen. On the starting I was getting frustrated with the ssh always asking me the passphrase. Then after a lot of reading manuals and internet searching, I found out about ksshaskpass. This can be used to write my passphrase and there I can set it to remember my passphrase, which it would essentially save in kwallet. So, How did I set this up?

Monday, 13 May 2024

A few weeks ago I attended the KDE Goals April 2024 sprint

I was there as part of the Automation & Systematization sprint given my involvement in the release process, the "not very automatized" weekly emails about the status of CI about KDE Gear and KDE Frameworks, etc. but I think that maybe I was there more as "person that has been around a long time, ask me if you have questions about things that are documented through oral tradition"

I didn't end up doing lots of work on sprint topics themselves (though I participated in various discussions, did a bit of pair-programming with Aleix on QML accessibility issues, inspired DavidR to do the QML-text-missing-i18n check that he describes in his blog); instead I cheated a bit and used the sprint to focus on some of the KDE stuff I had a bit on my backlog, creating the KDE Gear release/24.05 branches and lots of MR reviewing and more!

Group photo

Thanks KDE e.V. for sponsoring the trip, if you would like such events to continue please we need your continued donations

And remember Akademy talk submission period ends in 10 days, send your talk now!

A new revision of digiKam Recipes is available for your reading pleasure. The new version covers the auto tagging feature introduced in digiKam 8.3 and explains how to run digiKam in a container.

If you bought the book through Gumroad, you’ll find the new revision in the Library section. The book purchased through Google Play should be updated automatically to the latest version. If you have problems getting the latest revision of the book, contact the author at dmpop@cameracode.coffee