Tag: C++

GitQlient 1.4.0 released

I’m happy to announce the release of GitQlient 1.4.0

Five months after the last big release, I present you a new GitQlient 1.4.0 version. This comes with less features than the previous versions but in exchange I hope it brings better performance.

In this release I’ve focused in the performance of the Git queries and the RAM memory used by GitQlient. I’ve done a deep research on the usage of QString and the allocations that were done to reduce them to the minimum. I’ve also added an internal cache system so now the UI won’t freeze every time the main graph needs to be refreshed. This also includes the separation between the data update of the references and the log history.

During this version I’ve paused the development of GitHub integration although is totally stable and usable, and the integration of Jenkins. This last integration will take a bit longer to refactor so I’ll focus on it in the following releases.

GitQlient 1.4.0 binaries

You can find the binaries for GitQlient 1.4.0 on the release section on the GitHub repo:

New features in GitQlient 1.4.0?

  • Squash merge branches
  • Squash commits: it is now possible to squash the last commits of the current branch. Of course, if the commits where already pushed to remote, they will need to be pushed force.
  • GitQlient now has an internal cache: Local Git operations will be done against the cache and later asynchronously against remote. This allow GitQlient to run faster for local changes that doesn’t need synchronization. This also reduces the UI freeze when refreshing because of changes in the graph.
  • Credentials can be managed by GitQlient with the proper configuration. This can be done through the Config screen.
  • Multi cherry-pick: It is possible now to cherry-pick several commits at once when they’re not part of the current branch.
  • Search tags in the Branches widget: In addition to branches, it is possible to search tags by name.
  • DEB package: GitQlient is now release as well as a DEB package in addition to RPM.

Other features

Technical improvements:

  • Reduced the number of memory allocations (specially with QString)

Known issues:

  • Any MacOS issues are still opened waiting for a system to be tested on.

GitQlient 1.3.0 released

I’m happy to announce the release of GitQlient 1.3.0

Six months after the last big release, I present a new GitQlient 1.3.0 version. This comes with a lot of new stuff that I’m going to talk about in this post.

In this release I’ve continued UX refactor I started in the previous one. This time I harmonized the styles for both the bright and the dark color schemas. Another part I’ve focused in a follow-up of the last release, one of the main focus areas has been the UX in the commit area and in the code editor (adding search).

The second big area has been extending the support of GitQlient for other platforms as Haiku, providing RPMs for CentOS and Fedora and removing submodules to facilitate the release in ArchLinux.

The last area but the most important one is about the new functionality and the improvements that GitQlient 1.3.0 includes. This will need a new section, of course. One of the big changes is the inclusion of new Qt dependencies: WebEngineWidgets and WebChannel.

GitQlient 1.3.0 binaries

You can find the binaries for GitQlient 1.3.0 on the release section on the GitHub repo:

New features in GitQlient 1.3.0?

  • GitHub integration
  • Jenkins integration (preview)
  • Stage chunk
  • Subtrees
  • Deleting submodules
  • Remotes
  • Edit Git/GitQlient configuration in place
  • Translations enabled
  • Pomodoro

Extending GitQlient

One of the new things in this GitQlient 1.3.0 is the extension of the GitHub integration and the addition of Jenkins integration (as preview).

With the GitHub integration it is possible now to create issues and PRs. You can do code reviews of a PR with code extracts, comments, reviews and markdown support as well.

The other big feature, Jenkins, it’s in an early stage. You will be able to review the status of your remote Jenkins server, trigger builds and check the result of the different builds.

Finally, not a big feature but a nice to have one is the Pomodoro. GitQlient is becoming more a workspace manager than a simple GitQlient. So, I thought that having a pomodoro clock in GitQlient would be a nice to have feature.

Minor features

The UX/UI refactor I’ve been doing would be included in the minor features. Unfortunately, it doesn’t bring any really big change, but I hope it simplifies workflows when doing certain Git operations. Among other changes I’ve included:

  • Showing if commits are signed: The History view now shows a green check on the author column if the commit is signed
  • Search functionality in code editor
  • Search functionality for the branches
  • Unified untracked and unstaged lists

The future

For the next release there are some nice features I’ve already planned:

  • Code refactor: Caused by the big growth of GitQlient.
  • Moving commits from UI
  • Squashing commits
  • DEB packages
  • Refactor the GitHub API classes
  • Finish Jenkins integration

As a result of the code growth during the last two releases I’d like to improve the structure and readability of it.

Consequently, I wouldn’t expect too many new additions or changes for next release but a better performance and code split to facilitate fixes and app extension in the future.

You can see the release planning and all the features that every release will contain in the Release Plan. And as always, if you’d like some feature or you’re missing something in GitQlient, check that it’s not yet in the backlog and open an issue on GitHub!

BenchmarkTool: time execution tracker

I had the idea of BenchmarkTool when I was trying to figure out why GitQlient was so slow on Windows machines. I had the impression and later on the evidences that in some cases the git client was holding for a long period without any known reason. And that was not happening on Linux.

Before I start hearing about profiling, I must say that I don’t want know how much CPU/RAM my application is using. This can be achieved with profilers, even for this case where the problem is on Windows. When I checked, those values were normal and the problem was in the what.

What process is making GitQlient so slow. Or in other words: what is taking so much execution time.

The idea of tracking time

The idea is not original at all. It’s similar to what Q_BENCHMARK does but for this specific case I wanted to have it in plain C++ so it’s as much portable as possible. This is fine to keep track of the execution of a method but sometimes you are losing the big picture. While doing operations on cascade you find yourself with a lot of tasks that aren’t long. The problem is that when you count them altogether they make a huge difference.

Additionally to the idea of benchmark the time for a single method execution I wanted to have a clear picture of the execution three inside workflow. This will allow me to identify the weak spots of the chain where the application is wasting more time.

Finally, another important thing is that I want to use it in other environments so the license must allow me that. That’s why I release it under BSD license.

How does BenchmarkTook work?

The current state is a singleton class that needs to be initialized with a TimeProvider object. That TimeProvider is optional and the BenchmarkTool creates one if not provided.

To start the benchmark of a method you can choose between two functions: BenchmarkStart or BenchmarkStartMsg. The only difference between these two is that the second one allows you to add a message to the function you want to benchmark.

Let’s say you are calling a method from different places. In this case you could put a message on the caller to differentiate when it’s called from.

Before the function ends, you will need to call BenchmarkEnd so it knows when the execution has finished and it can close that loop. This is important because otherwise the loop will be open and the output will be strange when not directly wrong.

Internally, the tool keeps a tree of calls so it waits until the every starting call ends to close the subtree. The library organizes the calls by thread so there is no danger in having several of them. They will be isolated in the output.

For now, it writes into a file when the execution finishes. But this is an area I’d like to improve before the first release.

Listeners in BenchmarkTool

BenchmarkTool also allows you to add listeners to it. A listener will be notify every time that a function starts and ends the benchmark. This is particularly useful for decentralised architectures where the functionality is better atomized.

As example, you could have a different library that sends the information collected by BenchmarkTool to a server. That tool would use the listener functionality to keep record of that.

Current status and future releases of BenchmarkTool

Right now the current status is officially under development. I wouldn’t use it in a production environment unless the goal is to do QA checks and validation. The main reason is that I still want to add some improvements and extensions on the features it supports.

As for the future, the plan is to release a first stable version before summer. But let’s see how that works. However, if you want to check the code, the GitHub repository is open, and the code is ready to check.

New release of GitQlient 1.2.0

I’m happy to announce the release of GitQlient 1.2.0

Three months after the last minor release I present a new GitQlient 1.2.0 with some fixes, several improvements and a lot of new features. For this release I’ve put the main focus in the UI/UX. That includes both the new features and the improvements of the existing ones.

During this development phase, part of the UI changes have happened in the diff widget by providing multiple views for the changes. I’ve also added a tiny text editor with syntax highlight (for C/C++ for now). Other UI/UX changes are the possibility to minimize the branches widget and to pin repositories. All of this has been marinated with an improvement in the way the settings are stored.

Finally, it is worth to mention the tech preview of GitHub/GitLab integration where you can create issues, pull/merge requests as well as see the status of those in the graph view. This is a new path that I’ll explore in the future where I have other ideas about the integration of third party apps. As a complement, from now on, GitQlient will notify you when a new version is available!

The binaries

You can find the binaries for GitQlient 1.2.0 on the release section on the GitHub repo:

What’s new in GitQlient 1.2.0?

The new version includes a lot of things:

  • Pinned tabs
  • GitHub integration (tech preview)
  • Tiny text editor
  • New diff for the WIP
  • Minimalist branches widget
  • Refactored the diff view
  • Bright colours schema
  • Update notifications
  • Settings per repository
  • More configuration options

New WIP diff view

The new diff view adds the possibility of viewing the file in differnt ways (full view or split) as well as navigate through the changes (in the split mode for now).

When the diff it’s opened from the WIP view, it also adds several extra controls like edit, stage and revert.

New WIP diff view
GitQlient – New WIP diff view

New tiny text editor

The second big feature is the tiny text editor I’ve embedded in GitQlient. It allows you to edit the files that are currently in WIP and pending to be commited.

Some times I’ve missed the ability to edit the files because I forgot something and in QtCreator may be I’ve changed the project or closed the file. I usually work with very large projects and it’s very handy to have an editor just in case.

GitQlient tiny text editor
GitQlient – Tiny text editor

The future

For the next release there are some nice features already planned:

  • Add subtree Git feature support
  • Git LFS
  • RPM and DEB packages
  • Prepare GitQlient for translations

As I said, you can see the release planning and all the features that every release will contain in the Release Plan.

As always, if you’d like some feature or you’re missing something in GitQlient, check that it’s not yet in the backlog and open an issue on GitHub!

How to pin tabs in QTabWidget

Pin tabs in QTabWidget

When I was doing GitQlient I wanted to have a QTabWidget where I could pin some tabs. I did some research but I found that I had to tweak/hack how QTabWidget and specially the QTabBar inside they behave. At that time it was not an option since I wanted to have the work done ASAP. But now, I have had a little bit more time and I could manage to pin tabs in a QTabWidget.

I thought it was going to be easier than I expected and I’m aware that I don’t probably cover all cases. However, I think I’ve managed to created a class that inherits from QTabWidget where the tabs can actually be pinned.

Pin tabs in QTabWidget
Pin tabs in QTabWidget

In the image above I show how I pinned the first three tabs. The widget puts the pinned tabs in the beginning whereas the unpinned remain after them. Once a tab is unpinned, the widget will remove it from the left part and put the tab as the first one in the right part.

To pin/unpin (and to close a tab) you can do it through the UI using the context menu. This menu appears when you left-click in a tab and it acts over that clicked tab:

QPinTabWidget context menu
Context menu for QPinnableTabWidget

In the other hand, if you need to modify that behaviour programmatically, there are two methods you can use for that:

int addPinnedTab(QWidget *page, const QString &label);
int addPinnedTab(QWidget *page, const QIcon &icon, const QString &label);

Both methods perform the same action that they do in QTabWidget but with the addition that they move the pinned tab to the beginning of the QTabBar.

Explaining the code

You can find the code in GitHub. In the next sections I’ll do an introduction to the code I wrote and why some things look like they are.

The code can be easily understood by a mid-level Qt developer. But even in that case I had to do some tweaks in order to bypass the normal functionality of the QTabBar.

QPinnableTabWidget

The first thing I needed, of course, was to create a class that inherits from QTabWidget. In that class I’ve created two addPinnedTab methods that add the functionality to pin tabs. The main reason is that I need to keep track of what tabs are pinned and to move them to the right place when pinned.

I also had to overwrite the mousePressEvent and mouseReleaseEvent since I want to create a context menu to pin/unpin tabs. The reason for this is that I’m processing the signal tabBarClicked from the QTabWidget. This signal tells me what tab has been clicked and after getting it I need to filter the left click.

Hidding the close button

By default, the QPinnableTabWidget has the close button visible for all the tabs. This is to allow the user to close easily a tab. However this adds an extra layer of complexity since I need to remove that close button for the pinned tabs. In addition, that same button needs to come back if the user decides to unpin the tab.

I dig into the Qt code and I saw that the QTabBar is adding an overloaded QAbstractButton so I did the same thing. I’ve created two different buttons one that adds the close button, and another that doesn’t show anything. I’ve extracted the code for the real close button from the implementation of the QTabBar. The fake one is just a dummy impl, necessary so it doesn’t crash.

Custom QTabBar

Another tweak I had to do is to overload the QTabBar that QTabWidget has by default since I needed to disable the moving of the pinned tabs. I’ve created a class that overloads the mousePressEvent, mouseMoveEvent and mouseReleaseEvent. Here I check what tab index the user wants to move and I filter to only accept the unpinned ones.

Conclusions and code

I’d like to notice that most of the things I needed to do, can be done in Qt official widgets in an easier and more elegant way. Actually, my code seems more complicated than it is. Basically, because I had to fight the default implementation.

I’ve uploaded the code for QPinnableTabWidget as a library in my GitHub space. Please feel free to open bugs or add comments if you liked it.

New GitQlient release v1.1.0

I’m happy to announce the release of GitQlient 1.1.0

After two and a half months from the first release here I present a new release with some fixes, several improvements and new features. The main focus on this release was to improve the stability of GitQlient, making it faster on Windows (there is room for improvement still) and adding some big features that didn’t go into the first release for time reasons.

During this development phase, some non-development tasks where done as well. One thing I wanted was to improve the documentation and the guides and for that reason I’ve shipped the GitQlient User Manual. Another thing I’ve added is Doxygen documentation to the headers (although it’s not yet finished). It will speed up the future documentation for developers who want to collaborate with the project. Related with that, I’ve also set up a Wiki to show the release plan and I’m currently working with GitHub kanban boards.

Finally, in the part of new features, the major addition is The Merge View, that will show the files that are in conflict and will allow you to resolve the conflict. The edition of the files, though, is done in a external editor that you can now configure. The future will be a live editor in GitQlient.

The binaries

You can find the binaries for GitQlient 1.1.0 on the release section on the GitHub repo:

What’s new in GitQlient 1.1.0?

The new version includes a lot of things:

  • New merge view
  • Basic Git config UI
  • Quick access to the recent projects in the init screen
  • Improved display of branches distance
  • Improved UX when pushing a local branch
  • Improved UX when checkout a branch
  • Improved UX for the graph view
  • Ability to open an external editor to edit files
  • Improved performance on Windows
  • Added Doxygen
  • Added User Manual
  • Added Planning

The Merge View

The merge view it’s special since it isn’t accessible as a regular view. It’s only triggered when GitQlient detects that a merge, pull or cherry-pick has conflicts.

GitQlient – The Merge View

As you can see, once this view is activated a red banner will appear under the quick access buttons. It will remain there until the merge is done. It doesn’t mean you cannot do other Git actions. But you won’t be able to push anything until solved. Of course, you can still navigate between all the other views.

The future

As I said, you can see the release planning and all the features that every release will contain in the Release Plan.

As always, if you’d like some feature or you’re missing something in GitQlient, check that it’s not yet in the backlog and open an issue on GitHub!

GitQlient: Multi-platform Git client written with Qt

I’m happy to announce the release of GitQlient 1.0.0

Almost 5 months ago I started this project with the idea of taking an old app and re-factor it. The main focus was to change the the look & feel and creating a Qt Creator plugin based on it. But the most important thing was to have a client I’d feel comfortable to work with.

During the first two months I focused in the separation of the UI and the logic to set a nicer MVC pattern so I could start from there. After that, I started to add new features and removed all the old widgets and functionality that I didn’t need.

For the version 1.0.0 I’ve implemented all the features that were part of GitQlientPlugin with some fixes and improvements. A way more that I initially thought. I’ve been using GitQlient for the last two weeks in my day-to-day work and I feel it’s ready for this first version!

The binaries

You can find the binaries for GitQlient 1.0.0 on the release section on the GitHub repo:

What’s new in GitQlient 1.0.0?

You can find everything that is in the plugin, specially this major ones:

  • Multi-repository support
  • Submodules
  • Tags and stashes
  • Blame & History
  • QLogger as log system
  • New graphic tree representation
  • Improved Diff view
GitQlient showing its main window
GitQlient showing its main window
GitQlient showing the new diff window
GitQlient showing the new diff window
GitQlient Blame&History view
GitQlient Blame&History view

Future

After this release, I’ll start working on the version 2.0.0 and the plan is to have it in 3-6 months. After that I’ll plan how often I want to release major versions: whether 3, 6 or 12 months period.

For the next version the plan is to include the following features:

  • Merge: Full merge support
  • Configuration: Provide UI for Git config file per project
  • Commit additions:
    • Stage changes by hunk and by line
    • Squash commits
  • Diff features:
    • Provide UI for file vs file diff
    • Browse file diff and full commit diff
  • UI: Stylesheet for bright colours
  • More platforms: GitQlient for MacOSX (planned for 2.0.0 if requested)

As always, if you’d like some feature or you’re missing something in GitQlient, check that it’s not yet in the backlog and open an issue on GitHub!

Orthodox canonical class form

This post is more about the basics of C++ and the last things C++11 brings to the orthodox canonical class form (OCCF). Some times the basics of a programming language are assumed by everybody but there is always a the time when someone asks why. Implement the complete OCCF is something that not always is required. In fact when you work with Qt framework and specially with widgets or inheritance from QObject is something you usually don’t care. And that’s an error.

(more…)

Bicing Barcelona with Qt

When I was living in Barcelona I saw that there is a OpenData service to get the information of the Bicing (bike public service). They provide the data in several formats such as CSV, XML and JSON. I wanted to write an app for Windows and Linux that retrieves the information from the stations and shows their current status. And for that, I chose JSON since I think the format is easier to read than XML.

After thinking a while I realised that it could be useful not just have every Bicing station data on demand but also a historic. To achieve that I split the app in two separated parts: “backend” that works as a deamon or service, and “frontend” that is the actual GUI app.

(more…)

Customization of a QCompleter

Time ago I had the task to create a QComboBox and a QLineEdit that open a completer so the user can select between all the suggested options. So far it seems a quite easy task by using the QCompleter that Qt provides.

The interesting part starts when I had to add customized styles for both the QComboBox and the QLineEdit, and make them match with the styles that I also had to add to the QCompleter. In addition I had a language constraint that initially I didn’t take into account but it impacted the performance of the widget. That’s the default filter implemented in QCompleter.

(more…)