(This is part of The Document Foundation’s Annual Report for 2024 – we’ll post the full version here soon.)
On January 31, LibreOffice 24.2 was officially released after six months of work. Developers at The Document Foundation, Collabora, allotropia, CIB, Red Hat, NISZ and other companies and organisations – along with volunteers – worked on many new features.
For instance, there were many improvements to the tabbed “NotebookBar” user interface, while styles support was added for comments. A new search field was added to the Functions sidebar deck in Calc, while in terms of accessibility, several significant improvements to the handling of mouse positions and the presentation of dialogue boxes via the Accessibility APIs were made, allowing screen readers to present them correctly. And regarding security, the “Sace with Password” dialogue box now has a password strength meter, which uses zxcvbn-c to determine the password strength.
TDF’s marketing and localisation community produced and translated a video (below) which demonstrated many of the new features in LibreOffice 24.2. This was linked to in the announcement, and embedded into various web news websites that covered the release. The video is also available on PeerTube.
Please confirm that you want to play a YouTube video. By accepting, you will be accessing content from YouTube, a service provided by an external third party.
If you accept this notice, your choice will be saved and the page will refresh.
Later in the year, on August 22, TDF released LibreOffice 24.8. Based on the LibreOffice Technology platform for personal productivity on desktop, mobile and cloud, it provided a large number of interoperability improvements with Microsoft’s proprietary file formats.
In terms of features, this release added many improvements to the Navigator in Writer, including ding cross-references by drag-and-drop items, deleting footnotes and endnotes, and indicating images with broken links. In Calc, the functions FILTER, LET, RANDARRAY, SEQUENCE, SORT, SORTBY, UNIQUE, XLOOKUP and XMATCH were added, along with chart types “Pie-of-Pie” and “Bar-of-Pie” which break down a slice of a pie as a pie or bar sub-chart respectively (this also enables import of such charts from OOXML files created with Microsoft Office/365).
Many other features were added as well, and there were a large number of compatibility improvements. As with the previous release, TDF staff worked with the marketing ad localisation communities to make a video (also on PeerTube) to demonstrate some of the new features.
Please confirm that you want to play a YouTube video. By accepting, you will be accessing content from YouTube, a service provided by an external third party.
If you accept this notice, your choice will be saved and the page will refresh.
We also released 14 minor updates with bug and security fixes:
As a LibreOffice user, you have certainly seen the LibreOffice splash screen. It is displayed when you open LibreOffice, it has a progress bar, and when loading the application is finished it goes away. Here we discuss a suggested improvement for this splash screen.
Currently, the splash screen is implemented by creating a custom widget with a custom painting mechanism that draws the splash image and also the progress bar and moves the progress indicator.
This has some drawbacks:
1. The splash screen does not always scale to the same size as the main LibreOffice Window.
2. The style of the progress bar is somehow different from other UI elements, looks mostly like gen interface.
3. It needs and uses a custom paint code.
4. It does not conform to the dark/light theme.
5. It is not easily localize-able. In fact, the only text is from the displayed image, in English. When you build from sources, the image file is instdir/program/intro.png
.
LibreOffice splash screen bitmap
6. It is a separate binary (oosplash
). You may run it with:
$ ./instdir/program/oosplash
LibreOffice dev splash screen
I have previously written about VCL weld mechanism, which is based on creating user interface files (.ui) and loading them inside the application.
The weld mechanism greatly reduces the complexity of creating user interfaces, and also improves other aspects of the user interface, including the consistency.
Most of the code for the current implementation resides in:
desktop/source/splash/splash.cxx.
The SplashScreenWindow
class has an custom paint method, SplashScreenWindow::Paint()
, which draws the bitmap, and also the progress. A new UI file is needed for this purpose, which should use GtkProgressBar, which will be considered a weld::ProgressBar. VCL then uses appropriate progress bar widget in different graphical plugins of VCL.
You may look into some dialogs like tip of the day to get some insight:
It would be interesting to avoid a separate binary, but it is fine to keep things as is, and just change to use .ui file.
The above issue is tdf#166128. If you would like to work on fixing it, you can just follow the Bugzilla link to see more information.
You may also use ideas from a minimal weld application here:
(This is part of The Document Foundation’s Annual Report for 2024 – we’ll post the full version here soon.)
The mission of the Membership Committee is to administer membership applications and renewals following the criteria defined in the Foundation’s Statutes. Members of the MC are directly elected by community members every two years, and serve for a two-year term. The Board of Directors consists of five members and three deputies.
On July 15, Eliane Domingos – chairperson in the Board of Directors at TDF – announced the election for the next MC, and asked for nominations and self-nominations. On August 27, she then announced that the nomination phase had ended, and that voting would run from 3 – 9 September. Around this time there were also three live “town-hall” Q+A meetings with the candidates, so that community members could ask questions and discuss the responses. We made video recordings from the second and third meetings, and here they are (also available on PeerTube here and here):
Please confirm that you want to play a YouTube video. By accepting, you will be accessing content from YouTube, a service provided by an external third party.
If you accept this notice, your choice will be saved and the page will refresh.
Please confirm that you want to play a YouTube video. By accepting, you will be accessing content from YouTube, a service provided by an external third party.
If you accept this notice, your choice will be saved and the page will refresh.
On September 12, Eliane announced the preliminary results, along with a “challenge” phase for people to check their votes and contest the results. And on September 27, TDF announced the final results, with full MC members being Gustavo Buzzatti Pacheco, Stéphane Guillou, Balázs Varga, Pranam Kumarbhai Lashkari and Jona Azizaj; and deputy members being Shinji Enoki, Andreas Mantke and Marco Marinello.
TDF would like to say thank you to all past and new members of the MC for their service to the community, and to all candidates for running. Congratulations to the newly elected MC members and their deputies.
The Document Foundation relies on its Advisory Board Members in order to receive advice and support. The Advisory Board’s primary function is to represent The Document Foundation’s supporters and to provide the Board of Directors with advice, guidance and proposals. Current members are Adfinis, allotropia software GmbH, Collabora, GNOME, CAGE Technologies Inc, City of Munich (Landeshaupstadt München), Open Source Business Alliance (OSBA), Software in the Public Interest (SPI), KDE e.V., and the Free Software Foundation Europe (FSFE).
Throughout the year, TDF had regular calls with representatives of the Advisory Board. Staff and Board members at TDF provided updates on the foundation, LibreOffice software and community, and described plans and activities for the future. Advisory Board members were invited to provide valuable feedback on TDF’s work, and various ideas and proposals were discussed during the calls. TDF would like to express its thanks to all of the members for their help and support.
In summer 2024, we welcomed Jonathan Clark to the TDF team as a new developer. Jonathan is initially working on improving LibreOffice’s writing script support, especially for RTL (right-to-left), CTL (complex text layout) and CJK (Chinese-Japanese-Korean) languages. This will help to make LibreOffice more accessible and usable for hundreds of millions of people around the globe.
When asked why he decided to apply for the position at TDF, Jonathan said:
I want to help people use open source software to work and create in their own language. There are other reasons, too: I’m a long-time user, interested in linguistics, and my background seemed like a good fit for the role. But the most important thing to me that I can believe in the mission.
Throughout the year, TDF supported – and provided information about – various milestones, campaigns and events, via this blog and our social media channels. For instance, in January we announced the ODF Toolkit 0.12.0 release. Big changes included a new ODF 1.3 mimetype “Text master template”, while the API for Text Selection was completely refactored. In addition, there were many fixes to improve reliability and security.
In early March, we announced that the new Board of Directors at TDF had started its term, while later in the month we celebrated Document Freedom Day, a yearly event which raises awareness of how open standards and open document formats provide us with the freedom to read and write as we wish.
Also in March, we wrote on our blog how the European Data Protection Supervisor (EDPS) had found that the European Commission had breached several provisions of Regulation (EU) 2018/1725, the EU data protection law for EU institutions, in its use of Microsoft 365, including those relating to the transfer of personal data outside the EU and the European Economic Area (EEA). The EDPS is imposing corrective measures on the Commission.
On a related topic, in September we supported a campaign to bring back Free Software funding, asking people to give their feedback to the European Commission, following a cut in important funds for FOSS.
Petr Valach from the Czech LibreOffice community tells us about feedback from the LibreOffice booth at this event…
InstallFest is a wellÂ‑established yet relatively small openÂ‑source conference held annually in the Czech Republic, traditionally at the Faculty of Electrical Engineering building at Karlovo námÄ›stà in Prague. Personally, I prefer these more intimate spaces over the larger venues like the Faculty of Information Technology, where the LinuxDays conference takes place. I highly appreciate the somewhat oldÂ‑fashioned and historical atmosphere that fills every corner of the faculty building. It reminds me of English universities and other institutions like museums, where the ambiance of past eras is still preserved. Some may find it irritating, but to me, such a place has far more character than modern buildings devoid of history.
Building E of the Faculty of Electrical Engineering (FEL), or perhaps the shared building of the Faculty of Electrical Engineering and the Faculty of Nuclear Sciences and Physical Engineering (FJFI) on Trojanova Street, which I used to visit as a student – and even more so the main building of FJFI on Břehová Street, or the joint workplace of FJFI and the Faculty of Mathematics and Physics (MFF) of Charles University on Karlova Street – all of these buildings naturally have their own history; and with even older buildings, history seems to radiate from them, evoking a sense of mystery and unattainability.
I’ve had this deep respect for historic landmarks since my school years, when I first encountered the epochal Jaroslav Foglar trilogy set in the mysterious world of StÃnadla (The Mystery of the Puzzle, StÃnadla in Revolt, The Secret of the Great Vont). These books have not lost their charm even after all these years (this year marks the 85th anniversary of The Mystery of the Puzzle), and that’s because you can actually touch the buildings described in them. That’s the true magic of Foglar’s stories – they’re part fiction, part grounded in reality, whether it’s the locations, characters, or structures, and that makes them more believable and realistic.
And even the InstallFest conference has something in common with them. After all, it takes place right in the area where StÃnadla is set, and the building itself stands just a few hundred meters from the birthplace of Jaroslav Foglar. In the conference venue, you can even find a poster for a course titled Planning the Movement of 3D Objects in a Complex Environment, featuring the iconic hedgehog in a cage – hiding the epoch-making invention of fourteen-year-old Jan TleskaÄ�: a flying bicycle! Coincidence? I don’t think so.
And now, on to the actual course of the conference.
Last year, InstallFest was saved by a new team led by Jan Langmaier. Once again, they did an excellent job – everything ran smoothly, without confusion or chaos. They deserve recognition for organizing and executing the conference in such a limited space.
This year saw an increase in the number of booth exhibitors, which naturally raised the question of where to place them all. Unfortunately, the LibreOffice booth drew the short straw and ended up in a separate lecture room designated for booths. As a result, the number of visitors to our booth was significantly lower; throughout the entire conference, we only had a handful of individuals with whom we had actual discussions (not counting those just interested in stickers and the like). Therefore, user feedback this time around was quite limited.
The majority of questions and comments from attendees revolved around four main areas:
LibreOffice provides solid support for OOXML formats, as used by Microsoft Office/365. The use of the plural is appropriate – it should be noted that Microsoft does not use the standardized OOXML Strict format as the default in its suite. This leads to a number of issues, which are described in more detail in this article.
A common question at every conference is how LibreOffice is funded. Although LibreOffice is a communityÂ‑driven project, where volunteers do most of the work in documentation, translations, local marketing and other tasks, the majority of code contributions come from ecosystem companies. These companies offer migration services, employee training, and 24/7 support for organizations using LibreOffice. They can also be commissioned to develop new features, which are then made available to everyone.
But volunteers (like us) are crucial for spreading awareness about LibreOffice, translating the software and manuals, and supporting users. In the Czech Republic, significant translation work has been done under the leadership of ZdenÄ›k Crhonek. Without these efforts, the project wouldn’t function properly, as corporations require localized environments and documentation.
Awareness of the online version of LibreOffice (via Collabora) seems to be increasing. This product deserves more public attention, as it is one of LibreOffice’s strongest assets. It offers a fully autonomous solution that can run on userÂ‑owned cloud infrastructure as well as other platforms.
However, one drawback is that no one offers LibreOffice Online as a fully managed cloud service. Users often complain about the lack of a readyÂ‑toÂ‑use hosted solution, making deployment more challenging. The Document Foundation cannot provide hosting services, but the demand for such a service is significant.
As with every conference, we received feedback about LibreOffice’s user interface. One of the biggest pain points is the icon sets – finding a suitable set for dark mode is nearly impossible. The Elementary icon set is considered the best by many users (including myself), but it is no longer being developed and lacks dark mode support. The Karasa Jaga theme is interesting but also lacks a dark mode version.
Another frequent request is for automatic updates. Windows users now have this feature as of LibreOffice 24.8, but it is still missing for Linux, due to the fragmented nature of the Linux ecosystem.
The most frequent critical feedback was about Impress, LibreOffice’s presentation tool. Some reports and requests included:
Users are welcome to join the project to help to improve these features, or again, fund developers so that all users can benefit.
For the first time, we introduced a small game at InstallFest. QR codes with LibreOfficeÂ‑related questions were placed around the venue, and visitors had to collect them to solve a puzzle. We prepared 200 answer sheets, but only about 30 were used.
Thanks to The Document Foundation (specifically Mike Saunders), we had plenty of giveaways, including T‑shirts, hoodies, and backpacks. Five lucky winners received prizes:
Congratulations to the winners, and thanks to all participants!
A special shoutout to Ondra, a schoolboy who was the only one to complete a nonÂ‑competitive task – writing a LibreOffice improvement suggestion on the back of his form. His request? Better copy/paste formatting options in Calc. Thanks, Ondra! Too bad you didn’t win this time – maybe at LinuxDays in autumn!
Kudos to Ilmari Lauhakangas for helping to elaborate this list.
467 bugs, 63 of which are enhancements, have been reported by 313 people.
488 bugs have been triaged by 72 people.
359 bugs have been set to RESOLVED.
Check the following sections for more information about bugs resolved as FIXED, WORKSFORME and DUPLICATE.
151 bugs have been fixed by 37 people.
List of critical bugs fixed
List of high severity bugs fixed
List of crashes fixed
List of performance issues fixed
List of old bugs ( more than 4 years old ) fixed
For this year’s LibreOffice Conference we had two location proposals: Luxembourg and Budapest. Members of The Document Foundation voted to choose the final location, and we can announce that Budapest is the winner.
Currently, the expected date for the conference is September 1 – 5, but this is still subject to change. We will confirm the final dates soon, then the fun begins: the call for papers, building up the schedule, planning social events and more…
Stay tuned to this blog for further details!
(Photo credit: JStolp on Pixabay)
by Popa Adrian Marius (noreply@blogger.com) at April 08, 2025 09:17 AM
by Popa Adrian Marius (noreply@blogger.com) at April 07, 2025 11:11 AM
Writer has the concept of recording tracked changes or not: if recording, typing into a document or deleting content will create tracked changes of type insertion or deletion. So far this was a per-document setting, but now individual users can enable or disable this as they wish.
This work is primarily for Collabora Online, but the feature is available in desktop Writer as well.
When Alice keeps typing and Bob enables change tracking, then surprisingly the typed characters of Alice will form a tracked insertion, which is surprising, since that was not the case a second ago and Alice didn't do anything other than typing.
Giving users a choice if they enable recording for just this user or for all users fixes this problem.
Here is how the per-user (technically per-view) tracked changes recording looks like:
As you can see, the user on the left has recording turned on and this doesn't influence the user on the right, while this was not possible before.
If you would like to know a bit more about how this works, continue reading... :-)
As usual, the high-level problem was addressed by a series of small changes. Core side:
Online side:
You can get a development edition of Collabora Online 25.04 and try it out yourself right now: try the development edition. Collabora intends to continue supporting and contributing to LibreOffice, the code is merged so we expect all of this work will be available in TDF's next release too (25.8).
On March 26, we celebrated Document Freedom Day. Mike Saunders from The Document Foundation, the non-profit behind LibreOffice, gave an online talk about the importance of open standards and free software:
Please confirm that you want to play a YouTube video. By accepting, you will be accessing content from YouTube, a service provided by an external third party.
If you accept this notice, your choice will be saved and the page will refresh.
Kudos to Ilmari Lauhakangas for helping to elaborate this list.
536 bugs, 69 of which are enhancements, have been reported by 330 people.
465 bugs have been triaged by 60 people.
354 bugs have been set to RESOLVED.
Check the following sections for more information about bugs resolved as FIXED, WORKSFORME and DUPLICATE.
144 bugs have been fixed by 34 people.
List of critical bugs fixed
List of high severity bugs fixed
List of crashes fixed
List of performance issues fixed
List of old bugs ( more than 4 years old ) fixed
51 bugs have been retested by 25 people.
96 bugs have been duplicated by 26 people.
22 bugs have been verified by 12 people.
270 bugs have been categorized with a metabug by 27 people.
37 bugs have been set as regressions by 10 people.
We’ve added a great new Vue.js-3 ZetaJS demo (source)! It showcases word processing and spreadsheets inside a single web app. Calc is being used as a data source for an HTML app, filling letter templates in Writer. You can even upload custom data spreadsheets or document templates! And have you seen the nice Writer toolbar, all done with Vue.js?
We’ve also updated the existing demos, showcasing Chrome PWA support with the Ping Monitor demo – just click the little install button at the top-right of the address bar, to get the Ping Monitor “installedâ€� on your desktop!
Meanwhile, our team was giving some great talks about our work for ZetaOffice and LibreOffice. Why not check out the recordings during your lunch break?
Look, we made some headlines! TheRegister was following up some earlier coverage about the WebAssembly port, after Thorsten gave Liam a demo during FOSDEM. Read up the full article here.
In case you’re around, meet us in two weeks at the FOSSAsia Summit in Bangkok, where Sarper Akdemir will give an update over our work. Dates are March 13-15.
If you’re based in Europe, you might instead enjoy Thorsten’s talk at the Chemnitz Linux Days (Germany) from March 22-23.
Looking forward to meet you there!
Please subscribe to our Newsletter or on Mastodon and let us know how you liked ZetaJS and the demos! If you’re playing with the code leave a star at the ZetaJS repo or if you hit any issues please file a report on GitHub.
Or just leave a comment and let us know directly – thanks for reading!
For the past two months, I’ve been working on adding more templates to LibreOffice Writer as part of my Outreachy project. My goal has been to create functional templates that users need the most.
I created these templates based on what you told us in our survey and your response was incredible!…
by Popa Adrian Marius (noreply@blogger.com) at February 26, 2025 10:57 AM
LibreOffice inherits a gigantic code base from its ancestors, StarOffice and OpenOffice. Here I discuss some notes for the newcomers on how to better understand the existing LibreOffice code, and improve the patches.
As said, LibreOffice is a huge code base, containing ~10 million lines of mostly C++ code. There are different assumptions, conventions and coding styles across ~200 modules that LibreOffice has.
Therefore, it is important to first, study the existing code, through reading and debugging LibreOffice source code, to understand the things that it does, and the way you can implement your ideas, including bug fixes and adding new features.
And although implementing some ideas seem to be straightforward at first sight, it is meaningful to study the details.
First of all, you should understand the thing that you want to implement. No matter if it is a bug, a new feature, or just an EasyHack, you should understand what is requested, what works and what does not work. This requires careful reading of the Bugzilla pages.
Then, you should try to run LibreOffice to understand the exact place in the application where you want to change. LibreOffice user interface has thousands of dialog boxes, so you need to make sure that you understand the thing that you want to do.
And at last, you get into implementing something in the code. Here are some questions that you can ask yourself about the details, when reading the existing code:
git blame
to see the last author of a specific linegit log
to study the details by knowing the commit hashgit log
Or, you may be interested in the code behavior in the big picture:
You can do some small changes, before even getting into implementing your idea:
Then, you can work on the actual implementation. Ask yourself:
After understanding some of the basic details about the way things work, you may go into improving your implementation.
These were the questions to give you some ideas of some of the underlying complexities in the code. You can start from small changes to become familiar with these complexities, and then grow to do more complex stuff in the code.
We have various different EasyHacks in LibreOffice, with different difficulty levels. If you are interested in coding, you can always find something that fits you, and grow gradually.
You can read more in these links:
Kudos to Ilmari Lauhakangas for helping to elaborate this list.
418 bugs, 50 of which are enhancements, have been reported by 246 people.
362 bugs have been triaged by 67 people.
347 bugs have been set to RESOLVED.
Check the following sections for more information about bugs resolved as FIXED, WORKSFORME and DUPLICATE.
157 bugs have been fixed by 29 people.
List of critical bugs fixed
List of high severity bugs fixed
List of crashes fixed
List of performance issues fixed
List of old bugs ( more than 4 years old ) fixed
54 bugs have been retested by 29 people.
66 bugs have been duplicated by 26 people.
22 bugs have been verified by 13 people.
354 bugs have been categorized with a metabug by 28 people.
When you want to interact with users, sometimes simple dialog boxes are sufficient: a simple yes or no, or some info box. But in other cases, you may need more complex message boxes. Here I discuss how to use VCL Weld to create a custom one.
You can create a simple message box, using predefined templates like Info box using a code snippet like this:
std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pParent, VclMessageType::Question, VclButtonsType::YesNo, u"Are you sure?"_ustr)); xInfoBox->run();
And, this is the result, which is very simple, without any title bar:
Yes / No message box
There are other predefined types, which can be used in different scenarios:
enum class VclMessageType { Info, Warning, Question, Error, Other };
But, if you want custom message boxes, you should be using weld mechanism, with its CreateBuilder
function.
Below is the code from the source code sfx2/source/doc/QuerySaveDocument.cxx
, which is inside sfx2
(framework) module. This dialog box is accessible across different modules, including Writer, Calc and Draw/Impress.
Let’s look into the code:
short ExecuteQuerySaveDocument(weld::Widget* _pParent, std::u16string_view _rTitle) { ... std::unique_ptr<weld::Builder> xBuilder( Application::CreateBuilder(_pParent, u"sfx/ui/querysavedialog.ui"_ustr)); std::unique_ptr<weld::MessageDialog> xQBox( xBuilder->weld_message_dialog(u"QuerySaveDialog"_ustr)); xQBox->set_primary_text(xQBox->get_primary_text().replaceFirst("$(DOC)", _rTitle)); return xQBox->run(); }
The code is using a UI file, named sfx/ui/querysavedialog.ui
to create a message dialog, and then change the title of it.
QuerySaveDialog
If you look into the include file, include/vcl/weld.hxx
inside Builder
class, you may see functions like weld_… that are suitable to find various different UI elements from the UI, by mentioning the element ID. For example, to find a label with the ID equal to lable_id
, you do this:
std::unique_ptr<weld::Label> m_pTextLabel label = m_xBuilder->weld_label(u"label_id"_ustr)
This is the result, when you try to close an unsaved document.
QuerySaveDialog running
This is not the only way you can create nice dialog boxes using VCL weld mechanism. There are some predefined message boxes that look nice which use weld mechanism, and are available for use via relevant C++ classes.
An interesting one here, is the QueryDialog
, which is created by a factory method design pattern.
It uses a predefined dialog, using cui/uiconfig/ui/querydialog.ui as the UI file, and it contains a nice stock image! You can test it easily, by modifying a LibreOffice example, minweld.
IMPL_LINK_NOARG(TipOfTheDayDialog, OnNextClick, weld::Button&, void) { VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create(); auto pDlg = pFact->CreateQueryDialog(getDialog(), u"Tips"_ustr, u"Tip of the day"_ustr, u"Are you sure you want to see the next tip of the day?"_ustr, false); sal_Int32 nResult = pDlg->Execute(); pDlg->disposeOnce(); if(nResult == RET_YES) { ++m_nCounter; m_pTextLabel->set_label(u"Here you will see tip of the day #"_ustr + OUString::number(m_nCounter) + "."); } }
Assuming that you have a working build of LibreOffice, you can simply run the minweld workbench by invoking:
./bin/run minweld
The result looks much more interesting:
QueryDialog
The possibilities are endless! It only depends on your ideas and understanding of the user’s needs and requirements. It would be good if you look into what design team does to understand the design process:
by Popa Adrian Marius (noreply@blogger.com) at January 29, 2025 07:11 PM
LibreOffice 25.2 will be released as final at the beginning of February, 2025 ( Check the Release Plan ) being LibreOffice 25.2 Release Candidate 2 (RC2) the forth and last pre-release since the development of version 25.2 started in mid Juny, 2024. Since the previous release, LibreOffice 25.2 RC1, 104 commits have been submitted to the code repository and 55 issues got fixed. Check the release notes to find the new features included in this version of LibreOffice.
LibreOffice 25.2 RC2 can be downloaded for Linux, macOS and Windows, and it will replace the standard installation.
In case you find any problem in this pre-release, please report it in Bugzilla ( You just need a legit email account in order to create a new account ).
For help, you can contact the QA Team directly in the QA IRC channel or via Matrix.
LibreOffice is a volunteer-driven community project, so please help us to test – we appreciate it!
Happy testing!!
Happy new year 2025! I wish a great year for you, and the global LibreOffice community. Now that we are now in 2025, I briefly discuss the year 2024 and outlook for 2024 in the development blog.
LibreOffice Conference 2024, Luxembourg
At The Document Foundation (TDF), our aim is to improve LibreOffice, the leading free/open source office suite that has millions of users around the world. Our work is community-driven, and the software needs your contribution to become better, and work in a way that you like.
My goal here, is to help people understand LibreOffice code easier, and eventually participate in LibreOffice core development to make LibreOffice better for everyone. In 2024, I wrote 22 posts around LibreOffice development in the dev blog (4 of them are unpublished drafts).
Focus of the development blog for 2025 in this blog will be:
I have written about some of these topics in 2024. Therefore, this year I will try to expand the previous writings and provide new articles about them. For example, creating user interfaces using VCL with the help of glade interface designer will be one of important things to discuss.
You can give feedback by writing a comment here, or sending me an email to hossein AT libreoffice DOT org.
We provide mentoring support to those who want to start LibreOffice development. You are welcome to contact me if you need help to build LibreOffice and do some EasyHacks via the above email address. Also, you can always refer to our Getting Involved Wiki page:
Let’s hope a great year for LibreOffice (and the world) in 2025.
by Popa Adrian Marius (noreply@blogger.com) at January 13, 2025 01:15 PM
LibreOffice Writer has long been a trusted tool for users worldwide, offering an open-source solution for documents. But what happens when we take a step back and look at the user experience? How do templates fit into the workflows of users, what makes a great template and where do users want LibreOffice writer to improve?…
Kudos to Ilmari Lauhakangas for helping to elaborate this list.
400 bugs, 60 of which are enhancements, have been reported by 249 people.
365 bugs have been triaged by 69 people.
371 bugs have been set to RESOLVED.
Check the following sections for more information about bugs resolved as FIXED, WORKSFORME and DUPLICATE.
138 bugs have been fixed by 31 people.
List of high severity bugs fixed
List of crashes fixed
List of old bugs ( more than 4 years old ) fixed
44 bugs have been retested by 20 people.
63 bugs have been duplicated by 20 people.
28 bugs have been verified by 14 people.
1175 bugs have been categorized with a metabug by 27 people.
58 bugs have been set as regressions by 16…
Writer has the concept of paragraph margins and page margins, but what happens when you combine the two? It turns out the expectation is that sometimes the top paragraph margin is ignored in this case. We'll see two cases where the behavior of Writer is now improved to better match Word in this regard.
This work is primarily for Collabora Online, but the feature is available in desktop Writer as well.
As described in a previous bugreport, there was a first problem where Word ignored the top paragraph margin of a document, but Writer did not. A recent bugreport then pointed out that the first implementation went too far and now a wanted top margin was ignored. This lead to a set of conditions which now does a decent emulation of Word's rules in this regard.
Here is the old Writer render result for a document where the top margin should be ignored:
And here is the new Writer render result for a document where the top margin is ignored:
Finally, the reference render result, showing the ignored top paragraph margin:
As you can see, now the unwanted top paragraph margin is omitted at page top.
If you would like to know a bit more about how this works, continue reading... :-)
As usual, the high-level problem was addressed by a series of small changes:
You can get a development edition of Collabora Online 24.04 and try it out yourself right now: try the development edition. Collabora intends to continue supporting and contributing to LibreOffice, the code is merged so we expect all of this work will be available in TDF's next release too (25.2).
Since the first implementation of a dark color theme we continuously improved the customization of LibreOffice. In a GSoC projects this year, Sahil Gautam made it possible to not only change the application colors but also what is defined by the operating system respectively the desktop environment.…
Impress shape text doesn't have much support for styles, e.g. the default UI in Writer gives you a paragraph style dropdown, and you don't get the same in Impress. Still, a paragraph style is attached to bullets based on their outline level, and Impress has a View → Outline menu item to give you that styled text you can copy. Pasting that to Writer started to lose styles recently and it's now fixed to work again.
This work is primarily for Collabora Online, but the feature is available in desktop Impress as well.
As described in a previous commit, I had a case where lots of not needed paragraph styles were exported to RTF in case an Impress document had enough master pages. The idea was to only export actually used paragraph styles, to avoid wasting CPU power.
Turns out filtering out paragraph styles has to happen at two locations:
The problem was that unused styles were removed from the style table, but not from the style → index mapping, so as soon as you had both used and unused paragraph styles, the declared and the referred style indexes didn't match anymore.
Here is a sample paste result in Writer, where you can see that the text doesn't have a custom paragraph style:
And here is the same paste, now with paragraph styles restored:
As you can see, now the pasted text has paragraph styles.
If you would like to know a bit more about how this works, continue reading... :-)
The bugfix commit was editeng RTF export: fix broken offsets into the para style table.
The tracking bug was tdf#163883.
You can get a development edition of Collabora Online 24.04 and try it out yourself right now: try the development edition. Collabora intends to continue supporting and contributing to LibreOffice, the code is merged so we expect all of this work will be available in TDF's next release too (25.2).
Let me count the ways, in no particular order and in no way exhaustive:
std::unique_ptr<SalLayout> ImplLayout( const OUString&, sal_Int32 nIndex, sal_Int32 nLen, const Point& rLogicPos = Point(0, 0), tools::Long nLogicWidth = 0, KernArraySpan aKernArray = KernArraySpan(), std::span<const sal_Bool> pKashidaArray = {}, SalLayoutFlags flags = SalLayoutFlags::NONE, vcl::text::TextLayoutCache const* = nullptr, const SalLayoutGlyphs* pGlyphs = nullptr, std::optional<sal_Int32> nDrawOriginCluster = std::nullopt, std::optional<sal_Int32> nDrawMinCharPos = std::nullopt, std::optional<sal_Int32> nDrawEndCharPos = std::nullopt) const;
by Chris Sherlock (noreply@blogger.com) at November 29, 2024 10:58 PM
This post is about recent improvements for ZetaJS, the JavaScript wrapper library for ZetaOffice’s WebAssembly version of LibreOffice:
There is something of a mismatch between the UNO type system and the JavaScript types used by zetajs. For example, JavaScript only has a single number type for both integer and floating point values, while UNO has a whole slew of different numeric types (BYTE
, SHORT
, UNSIGNED SHORT
, LONG
, UNSIGNED LONG
, FLOAT
, DOUBLE
) that all map to that one JavaScript type. Similarly, the different UNO sequence<T>
types all map to JavaScript arrays, where information about the UNO element type T
is lost.
Normally, that’s not an issue. When you call a UNO method that returns a LONG
, you get a number just like when you call a UNO method that returns a DOUBLE
, and your JavaScript code then has a number to work with, and that’s all. Similarly, when you call a UNO method that returns a sequence<LONG>
, you get an array of numbers you can work with, just like when you call a UNO method that returns a sequence<DOUBLE>
. And when you then call a UNO method that takes a seaquence<LONG>
as an argument, you pass in an array of numbers, and the zetajs runtimes figures out how to dress that array up as a UNO sequence<LONG>
, and all is well.
However, one place where UNO’s insistance on more precise typing gets in the way is the UNO ANY
type. It is not just a means to transport any kind of UNO value, it also carries precise type information. A UNO ANY
value that contains a LONG
of value 1 is something different than a UNO ANY
vlaue that contains an UNSIGNED LONG
of value 1. And a UNO ANY
value that contains a reference of type css.uno.XInterface
to some UNO object is something different than a UNO ANY
value that contains a reference of type css.lang.XComponent
to the same UNO object.
Again, most of the time, those precise distinctions are irrelevant to most of the code. When you call a UNO method that returns an ANY
, and you know that that ANY
value must contain a LONG
, you just want to get a JavaScript number out, regardless of what precise numeric UNO type was encoded in that ANY
value. Similarly, when you call a UNO method that returns an ANY
that must contain a css.uno.XInterface
reference, you just want to get some JavaScript object that you can do further UNO method calls on (or null
), regardless of what precise UNO interface type was encoded in that ANY
value. And when you then call a UNO method that takes an ANY
that must contain a LONG
, you want to just pass in a JavaScript number, and the zetajs runtime shall figure out how to dress that up as a UNO ANY
containing a LONG
(or throw an exception, if you passed something that just can’t be dressed up accordingly).
But, sometimes, you need more fine-grained control. There might be a UNO method that takes an ANY
argument and behaves completely differently when you pass it a LONG
of value 1 or an UNSIGNED LONG
of value 1. But when you call that UNO method with the JavaScript number 1, zetajs will always dress that up as a UNO ANY
of type LONG
for you, never as an UNSIGNED LONG
. To solve that issue, the zetajs UNO binding also has the notion of a zetajs.Any
JavaScript type, which records a value along with its precise UNO type. You can thus pass either a new zetajs.Any(zetajs.type.long, 1)
or a new zetajs.Any(zetajs.type.unsigned_long, 1)
when you call that picky UNO method.
Now, when a UNO method returns an ANY
value, the zetajs binding used to be conservative: You might want to know exactly what UNO type it contains (even though, most of the time you don’t actually care), so it always returned those wrapped zetajs.Any
objects that carry the precise contained UNO type. But that lead to awkward code. When you call e.g. x.nextElement()
to get a UNO ANY
that contains a reference to another UNO object, you had to unwrap that first (with zetajs.fromAny
) before you could do any further calls on the obtained UNO object: zetajs.fromAny(x.nextElement()).doSomething()
. But you know that this call to x.nextElement()
will return an ANY
containing an interface reference, and you don’t care about the exact UNO interface type—you just want to do another method call on the obtained object.
So, recently (in Let zetajs return unwrapped ANY representations), the zetajs binding was changed so that it now always returns unwrapped UNO ANY
values: x.nextElement()
no longer returns a zetajs.Any
wrapper (on which you would need to call zetajs.fromAny
first), it directly returns the relevant JavaScript object. And the resulting overall code looks way better: x.nextElement().doSomething()
.
When, in the other direction, you pass something into a UNO method that takes an ANY
argument, you still have the same options you had before: Either, you simply pass the JavaScript number 1, and zetajs figures out for you that that should be dressed up as a UNO ANY
of type LONG
, or you want to be picky and pass in either a new zetajs.Any(zetajs.type.long, 1)
or a new zetajs.Any(zetajs.type.unsigned_long, 1)
.
And when it comes time that you do want to be picky about the ANY
values that you obtain as return values from UNO method calls, there’s now a $precise
way to do that: x.$precise.nextElement()
(and same for any other UNO method call) will always give you back a wrapped zetajs.Any
value. See the updated The zetajs UNO Mapping for all the details.
LibreOffice uses VCL (Visual Class Library) as its internal widget toolkit to create the graphical user interface (GUI) of LibreOffice. Here I discuss how to use UI files designed with Glade interface designer to create LibreOffice user interfaces with a framework called weld, which is part of LibreOffice core source code.
In my previous blog post, you can find out about the structure of a minimal VCL application. Please refer to the below blog post to see how a Window is created in VCL, and how it can be used as a test workbench called minvcl
. You can run it with ./bin/run minvcl
after you build LibreOffice.
Here I discuss how to go further, and create user interface with Glade interface designer, and do most of the things without writing code.
In order to simplify user interface creation in LibreOffice, experienced LibreOffice developer, Caolán, has introduced a mechanism to load UI files created with Glade interface designer, and use them as if they are UI files for each and every GUI framework that LibreOffice supports: from GTK itself to Qt, Windows, macOS and even the so-called gen backend that only requires the X11 library on Linux.
To illustrate how the VCL weld mechanism works, I have added a minimal example, minweld
, as a test workbench. The structure of the code is very similar to the previous example, minvcl
, but there are some changes in the code. In the new code, UI is created from a .ui
file that is designed visually with Glade interface designer. The .ui
file is an XML file which contains placement of widgets that should be displayed on the screen.
The complete code for minweld
is available in the LibreOffice core source code repository, which can also be viewed online:
In minweld
, I have used an existing Glade UI file, tipofthedaydialog.ui
. This is the user interface for displaying a tip of the day in LibreOffice at startup. Heiko, the TDF design mentor, has discussed this dialog box in detail before:
But, you can assume that it is a simple .ui
file, that one can create with Glade. Here, we use it to create our own user interface in C++. You may use any other .ui
file that you have created with almost the same code.
Tip of the day displayed at LibreOffice startup
This UI file is found in cui/uiconfig/ui/tipofthedaydialog.ui
, and minweld
loads it. This is how it looks when you open it in Glade interface designer:
tipofthedaydialog.ui in Glade user interface designer
Let’s look into the specifics of minweld.cxx
.
Headers are almost the same, but here we use vcl/weld.hxx
instead of vcl/wrkwin.hxx
. Therefore, you can see this line in the code:
#include <vcl/weld.hxx>
Then we have the C++ code for the application. The TipOfTheDayDialog
class is defined with:
class TipOfTheDayDialog : public weld::GenericDialogController { public: TipOfTheDayDialog(weld::Window* pParent = nullptr); DECL_LINK(OnNextClick, weld::Button&, void); private: std::unique_ptr<weld::Label> m_pTextLabel; std::unique_ptr<weld::Button> m_pNextButton; sal_Int32 m_nCounter = 0; }; ... }
As you can see, TipOfTheDayDialog
inherits from weld::GenericDialogController
, and not Application
class as before. Also, TipOfTheDayDialog
constructor receives a parent of type weld::Window*
, which is nullptr
now. The reason is that there is no parent window in this example. Using weld::
prefix is also done for other types of widgets that we use in LibreOffice. For example, we use weld::Button
to denote a push button in LibreOffice, or in any application that is created with the vcl::weld
mechanism.
This is the code for the TipOfTheDayDialog
constructor. Here, we initialize two member variables, m_pTextLabel
and m_pNextButton
which point to a label and a button, respectively. We will interact with these two in our code. There are string literals like lbText
and btnNext
, which are the IDs of those widgets in Glade. The IDs should be unique for linking to specific variables in the code.
TipOfTheDayDialog::TipOfTheDayDialog(weld::Window* pParent) : weld::GenericDialogController(pParent, u"cui/ui/tipofthedaydialog.ui"_ustr, u"TipOfTheDayDialog"_ustr) , m_pTextLabel(m_xBuilder->weld_label(u"lbText"_ustr)) , m_pNextButton(m_xBuilder->weld_button(u"btnNext"_ustr)) { m_pNextButton->connect_clicked(LINK(this, TipOfTheDayDialog, OnNextClick)); }
One last step is linking the events with functions in the code. You may do that with the LINK
macro. In the last line, connect_clicked
activates OnNextClick
from the class TipOfTheDayDialog
, whenever m_pNextButton
is clicked.
This is the implementation of the event handler. It should be started with IMPL_LINK macro, in the form of IMPL_LINK_NOARG(Class, Member, ArgType, RetType)
. The code is straightforward: It increases a counter which is initially zero, and displays it alongside a text:
IMPL_LINK_NOARG(TipOfTheDayDialog, OnNextClick, weld::Button&, void) { ++m_nCounter; m_pTextLabel->set_label(u"Here you will see tip of the day #"_ustr + OUString::number(m_nCounter) + "."); }
With a call to set_label
function, m_pTextLabel is updated every time that you click on “Next Tip” button.
You may run the example after you have built LibreOffice from sources. Then, you may simply invoke:
./bin/run minweld
The result is a little bit different from the tipoftheday dialog in LibreOffice, as it does not use a picture. But, it has a nice feature: if you click on “Next Tip”, it will show a text and a counter that goes up whenever you click on it again.
You may look into the original “tip of the day” dialog box in cui/source/dialogs/tipofthedaydlg.cxx
, which is more complex than the one that we created here, as it reads some data from the configuration and uses images. But, the idea is the same. Inherit a class from GenericDialogController
, define and link variables to the widgets with their IDs, add event handlers. Now, the application with VCL graphical user interface is ready to use!
This is somehow similar to the way one creates dialog boxes with Qt and other widget toolkits. On the other hand, the VCL weld mechanism is different in the way that it uses such a toolkit to create UI on the fly. Therefore, if you choose a desired VCL UI plugin, then it will use that specific library for creating user interface. For example, you can run minweld
example with Qt this way:
export SAL_USE_VCLPLUGIN=qt5 ./bin/run minweld
The minweld example in Qt (light theme)
You may also run it with GTK3 UI, this way:
export SAL_USE_VCLPLUGIN=gtk3 export GTK_THEME=Adwaita:light # For light/dark theme ./bin/run minweld
The minweld example in GTK3 (light theme)
I hope that this explanation was helpful for you to understand the basics of GUI design and implementation in LibreOffice. You can try doing small improvements in LibreOffice GUI by looking into the EasyHacks that with the tag “Design“:
TDF Wiki: EasyHacks categorized by “Design” as the required skill
We welcome your code submissions to improve LibreOffice. If you would like to start contributing to LibreOffice, please take a look at our video tutorial:
Hamburg and Bolzano, November 8th, 2024 – During the two-day annual South Tyrol Free Software Conference, allotropia software GmbH today announces beta versions of its new product line “ZetaOffice”.
ZetaOffice is a new set of applications, libraries and services, all powered by the LibreOffice Technology stack. Featured among its products is ZetaJS, an innovative browser-based plugin, with unique programmability & embeddability – the perfect tool for complex office editing, process automation and line-of-business applications in the web.
Additionally, leveraging the unique portability and flexibility of the LibreOffice Technology stack, ZetaOffice will be available in bit-by-bit identical versions (allowing for perfect interoperability and feature parity) also for open-source-based mobile operating systems (Android, and derived OS), as well as for all relevant desktop operating systems (Windows, macOS, Linux – via flatpak and snapcraft).
“We’re very excited being able to offer powerful, data-sovereign Open Source office functionality on even more platforms today”, says Thorsten Behrens, owner and managing director of allotropia software. “In particular our innovative, WASM-based browser version of LibreOffice will be a game-changer for every web developer in need of processing, analysing or integrating with office documents.”
“This could not have come at a better time”, says Michiel Leenaars, director of strategy at philanthropic investor NLnet Foundation. “It is long overdue but certainly in the wake of the recent geo-political developments, we all recognise the urgent need for Europe to regain its technological independence when it comes to core technologies – as boring as these may seem. ZetaOffice shows that Europe has the talent and capacity to break with the past and create new paradigms and use innovation and collaboration to save the day.”
“ZetaOffice is the perfect addition to our portfolio of tools for document and business process automation”, says Uli Brandner, CEO and owner of CIB Group. “With solutions like CIB flow for workflow modeling and CIB coSys for high-quality template management, CIB Group already offers powerful digitalization tools. As demand grows to bring proven applications to the web and stay on the cutting edge of technology, ZetaOffice stands out as an innovative solution precisely tailored to our customers’ needs.”
A detailed blog post, including links to beta versions of the software, is available here.
For the products, please refer to our website at zetaoffice.net.
ZetaOffice and the team at allotropia thanks the European Commission’s Next Generation Internet initiative/NGI Zero for its financial contribution to the development of this software.
About ZetaOffice:
ZetaOffice is a product line based on LibreOffice Technology, comprising of desktop LTS products for classical office productivity requirements; a browser-native version based on WebAssembly for fast, client-side integration and automation of office technology; and an
upcoming mobile app widget, for deep integration in mobile line-of-business applications. ZetaOffice is focused on speed, superb embeddability, excellent inter-product as well as Office compatibility, and geared towards digital-sovereign & data protection needs.
About ZetaJS:
ZetaJS is a JavaScript library, available via the npm package manager, to enable developers to quickly & conveniently embed ZetaOffice WebAssembly in web applications. ZetaJS makes available the entire gamut of the LibreOffice programmability interfaces, providing a web-native component for JavaScript developers to deeply embed an office suite into their web apps. In contrast to classical cloud-office setups, ZetaJS can be used as an integral, client-side part of any web application – permitting users to interact with office documents as part of a larger application framework, with very low latency. That way, e.g. direct integration for editing, suggestions or running calculations in complex spreadsheets can be provided. Similarly, it’s trivially easy to implement direct, client-side rendering and export of office documents into PDF or HTML – all via a self-hostable, digital-sovereign Open Source solution.
About allotropia software GmbH:
The company allotropia software GmbH provides services, consulting and products around LibreOffice and related opensource projects. Founded in 2020 by long-time developers of the project, its stated mission is to make LibreOffice shine – in as many different shapes and forms as necessary to serve modern needs towards office productivity software. allotropia software GmbH is headquartered in Hamburg, Germany at the birthplace of the OpenOffice/LibreOffice project. For more information, visit allotropia.de, or follow fosstodon.org/@allotropia on Mastodon and LinkedIn: www.linkedin.com/company/allotropia-software-gmbh
Today allotropia has launched the ZetaOffice range of products at the SFSCON in South Tyrol. ZetaOffice is a LibreOffice Technology built & designed for professional use in the browser, on the desktop and on mobile.
We are excited to additionally announce a massively improved way for which LibreOffice Technology can be used fully client-side on the web. As an additional building block, we have developed the ZetaJS wrapper, which enables convenient embedding and automating WASM (WebAssembly) builds of ZetaOffice via JavaScript. With that, all of the LibreOffice Technology APIs and features are available to web applications – and by leveraging WASM, which runs ZetaOffice client-side, no server or cloud services are needed. All processing is taking place on the client browser, which minimizes latencies & load (of course, a minimal static delivery of web application code, assets and the WASM binary is still needed, but that’s extremely light-weight).Â
Let’s look at some simple examples to give you an idea, how easy ZetaOffice integration is. All comprise of an HTML and a JavaScript file. A ZetaOffice WASM build will automatically be included from the following URL. To replace it with a custom WASM build see config.sample.js
of each demo.
https://cdn.zetaoffice.net/zetaoffice_latest/
Next you need to upload the zetajs/
folder onto a webserver of your choice, which sets the following HTTP headers (see developer.mozilla.org for further details):
Cross-Origin-Opener-Policy "same-origin"
Cross-Origin-Embedder-Policy "require-corp"
So back to the example code. The HTML files for all examples embed ZetaOffice and some JavaScript loading code. Please check the actual JavaScript file for the code interacting with ZetaOffice.
Lets have a look at the simple.html (see live). ZetaOffice displays its content using an HTML canvas. So in line 14 we initialize this canvas. Currently a list of attributes like is needed for the canvas. But we will migrate those attributes to the ZetaJS wrapper, so they won’t be needed anymore in the HTML code.
<canvas
id="qtcanvas" contenteditable="true"
oncontextmenu="event.preventDefault()" onkeydown="event.preventDefault()"
style="height:100%; width:100%; border:0px none; padding:0;"/>
The Module
variable on line 30 passes the information needed to initialize WASM binaries. First is the canvas. And second is an array of JavaScript files which will be executed in the main Web Worker running the WASM binary. Web Workers are a process like feature of the browsers WASM runtime environment. We pass the ZetaJS wrapper and a file with custom JavaScript code, in this example the simple.js
. You may need to ensure, that the zeta.js
is reachable under the given URL path.
Line 33 to 39 preload the soffice.js
file to ensure, it’s not being blocked by the browsers origin policy when loaded from a foreign origin. Line 42 triggers a website resize event, to make ZetaOffice display nicely inside the canvas. This can be done more precise, as shown in the more complex demos. But for the start the resize event will be triggered after a fixed interval. And finally the soffice.js
document is finally loaded which triggers the start of the WASM binary.
Second is the simple.js file. It’s running inside the same Web Worker as the WASM binary to enable interaction. When running in Chromium / Google Chrome you will find a dropdown list labeled “top” at the upper left of the “Console” tab in the developer tools. There you can select the em-pthread_1
Web Worker to debug code in the simple.js
file.
Inside the simple.js
you will find pretty much the same code as when controlling a LibreOffice running naively on Linux, Windows or any other native OS. It is using LibreOffice’s UNO interface. Most existing examples using UNO via Python or Basic can be easily moved to JavaScript.
The control flow is being passed by the Module.zetajs.then
which gets called as soon as the WASM binary is loaded. It passes the zetajs
object from which we first get the common com.sun.star
object (do not confuse it’s abbreviation css
with HTML CSS). In the lines 11 to 21 we get some control objects via UNO, which allow us to trigger the load of an example office document example.odt
which is embedded in the WASM binary.
Module.zetajs.then(function(zetajs) {
function getTextDocument() {
const css = zetajs.uno.com.sun.star;
const context = zetajs.getUnoComponentContext();
const desktop = css.frame.Desktop.create(context);
let xModel = desktop.getCurrentFrame().getController().getModel();
if (xModel === null
|| !zetajs.fromAny(
xModel.queryInterface(zetajs.type.interface(css.text.XTextDocument))))
{
xModel = desktop.loadComponentFromURL(
'file:///android/default-document/example.odt', '_default', 0, []);
}
const toolkit = css.awt.Toolkit.create(context);
Line 27 is where the actual application logic starts. In this simple example we get a cursor object from the document to insert the text string here!
at the top. In the final section from line 32 to 38 each paragraph of the office document becomes colored in a random color.
const xText = xModel.getText();
const xTextCursor = xText.createTextCursor();
xTextCursor.setString("string here!");
}
{
const xModel = getTextDocument();
const xText = xModel.getText();
const xParaEnumeration = xText.createEnumeration();
for (const next of xParaEnumeration) {
const xParagraph = zetajs.fromAny(next);
const color = Math.floor(Math.random() * 0xFFFFFF);
xParagraph.setPropertyValue("CharColor", color);
}
This other simple-examples/
show you a little more interesting tasks you can do with the same basic techniques as shown here. While the HTML files are all the same, the simple_key_handler.js
(see live) shows you how to register to ZetaOffice event handlers. And finally rainbow_writer.js
(see live) uses this to implement a small tool coloring text as you write it.
The next big step is in the standalone/
(see live) example. It adds a nice loading animation and shows you how to pass messages between the WASM Web Worker and the browsers main thread, handling the HTML page. This is being used to implement some simple controls on the HTML page for formatting text inside ZetaOffice. The demo is build as a npm package and can be run according to the contained README.md
. Don’t forget to pass an URL to the soffice_base_url
variable as explained above!
Additional examples are vuejs3-ping-tool/
(see live) and letter-address-tool/
(see live). The vuejs3-ping-tool/
is again a npm package, and show-cases how to automatically fill spreadsheets documents with values, displaying them in nicely animated Calc charts. The other letter-address-tool/
example gives you an impression how to connect ZetaOffice with external data sources to automatically create letters from templates, and export the result as office document or PDF file.
Please share your feedback as a comment in the blog, or use the GitHub issue tracker for suggestions or bugs in the code!
Writer TextBoxes provide the user with shapes that can have complex geometry and complex content. There is also a feature to capture shapes inside page boundaries: now the two features interact with each other better.
This work is primarily for Collabora Online, but the feature is available in desktop Writer as well.
As described in a previous post, Writer implements the TextBox feature with a pair of objects: a Draw shape (with complex geometry) and a (hidden) Writer TextFrame, providing complex content. To avoid wrapping problems, the underlying TextFrame always has its wrap type set to "through", i.e. text may wrap around the Draw shape, but the hidden TextFrame is always ignored during text wrapping.
In most cases this provides the expected behavior, because the user sees one object, so wrapping around at most one object is not surprising.
However, there is also an other feature, that shapes may be captured inside page frames: if their position would be outside the page frame, Writer corrects this, so they are not off-page. This also makes sense, so it can't happen that your document has a shape that is hard to find, due to a silly position.
The trouble comes when these two are combined: the Draw shape's position gets adjusted to be captured inside the page frame, but the TextFrame's wrap type is "through", and objects with this wrap type are an exception from the capturing mechanism, so the position of the two shapes get out of sync.
The problem is now solved by improving the layout, so in case the TextFrame is actually part of a Draw shape + TextFrame pair (forming a TextBox), then we calculate the effective wrap type of the TextFrame based on the wrap type of its Draw shape, so either both objects are captured or none, which results in consistent render result.
Here is a sample document where all margins are configured to be equal, but capturing corrected the Draw shape (and not the TextFrame):
And here is the same document, with consistent positioning:
As you can see, now the rendered margins actually equal, as wanted.
If you would like to know a bit more about how this works, continue reading... :-)
The bugfix commit was sw textbox: capture fly when its draw object is captured.
The tracking bug was tdf#138711.
You can get a development edition of Collabora Online 24.04 and try it out yourself right now: try the development edition. Collabora intends to continue supporting and contributing to LibreOffice, the code is merged so we expect all of this work will be available in TDF's next release too (25.2).
The SVG export in Impress now supports a per-paragraph setting to handle semi-transparent shape text, while previously this was only possible to control at a per-shape level.
This work is primarily for Collabora Online, but the feature is available in desktop Impress as well.
As described in a previous post, Impress already had the capability to have semi-transparent shape text, but the SVG export of this for the case when not all paragraphs have the same setting was broken.
Transparency in SVG can be described as a property of a group (<g style="opacity: 0.5">...</g>
)
and it can be also a property of the text (<tspan fill-opacity="0.5">...</tspan>
).
The SVG export works with the metafile of the shape, so when looking for meta actions, it tries to
guess if the transparency will be for text: if so, it needs to use the tspan
markup, otherwise
going with the g
markup is OK.
What happened here is that meta action for a normal text started, so the SVG export assumed the text is not semi-transparent, but later the second line was still transparent, so we started a group element, and this resulted in a not even well-formed XML output.
The relevant part of the test document is simple: just 3 paragraphs, the second one is semi-transparent (and also has a bullet, as an extra):
Once this was exported to SVG, this resulted in a non-well-formed XML, so you got this error in a web browser:
Once tweaking the transparency mask writer to check if text started already, we get the correct SVG render:
If you would like to know a bit more about how this works, continue reading... :-)
The bugfix commit was SVG export: fix handling of semi-transparent text inside a list.
The tracking bug was tdf#162782.
You can get a development edition of Collabora Online 24.04 and try it out yourself right now: try the development edition. Collabora intends to continue supporting and contributing to LibreOffice, the code is merged so we expect all of this work will be available in TDF's next release too (25.2).
In my last post on Libreoffice I promised to talk about Writer changes once in a while, but then ... nothing ever happened. However, given that I had an annoying motorcycle accident in the meantime that turned out much more persistently annoying than originally thought, I think I have a bit of an excuse.
So ... what did happen? For one, I fixed quite a few regressions with my name on them, but ... is there much to talk about here? Mostly not: If you look at the fixes, they are often oneliners fixing something that seems rather obvious in retrospect. The more tricky question is: how did these get in in the first place? Its hard for me to say that, as the introducing commits are from even longer ago.
One thing is certain though: Often a unittest would have caught them, so whenever possible, I tried to create a reproducer adding such a test with the fix. To anyone writing bug reports: Creating minimal reproduction test is hugely valuable in this -- not just for finding the issue, but also as a starting point for a regression test. So if a bug bugs you and it is missing a minimal reproduction scenario, adding one is a great way to move this forward. Oh, and maybe verifying a bugfix, if someone provided a fix and the friendly bot say affected users are "encouraged to test the fix and report feedback".
While doing these fixes, I stumbled over Noel suggesting to speed up bookmarks in writer which is of course great, but I noticed that the code could be optimized a bit more as the bookmarks of a document are now sorted by their starting position (which was one of the first changes I made back on OpenOffice.org about more than a decade ago). Thus we can use bisectional search on the bookmarks here, which should be even faster. Now, it would be great if the discussion on this between Noel and me would available for others to learn from, wouldnt it? The cool thing is: it is.
All discussion happened on gerrit in the comments so if you want to learn about bookmark in Writer and how to maybe speed them up for documents that have a lot of them, that is a great starting point! Is there anything to add? Well maybe the following: Currently the bookmarks starting at the same position are currently not sorted. If one would sort them by their end position, the bisectional search could maybe cover even more? This would also remove one extra loop of logic and make the code simpler and easier to read.
The performance improvement is likely irrelevant -- esp. since there will be not that many documents with lots of bookmarks starting at the same position. The simpler code might be worth it though. So why wasnt it done?
It still can be tried in a follow-up, but speaking about regressions earlier: This has some obscure regression risk, because if we change the order of bookmarks starting at the same position from undefined to something ordered by the end position it might impact a lot of code using bookmarks. The function in question might actually be faster, but other functions (e.g. the inserting of new bookmarks) might actually be slower. So ... this is left as an exercise to the reader.
Comments? Feedback? Additions? Most welcome here on the fediverse !