Released GitQlientPlugin 1.3.0 for QtCreator

I’m happy to announce the release of GitQlientPlugin 1.3.0

Three weeks ago I released a new version of GitQlient and now is the time to update the GitQlient plugin for QtCreator.

The new version of the plugin includes all the features already released in GitQlient. That includes the new tab system, the text editor as well as all the modifications in the UX/UI.

The binaries

You can find the binaries for GitQlientPlugin 1.3.0 on the release section on the GitHub repo. This time the plugin has come just after the release of Qt Creator 4.13, for that reason I’m providing versions for QtCreator 4.12 and 4.13.

Further work

Since GitQlientPlugin is a wrap of GitQlient, you can see the release planning and all the features that every release will contain in the Release Plan for GitQlient.

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

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!

Non closable QDialog

This is quite beginner post but I believe it’s good to share what we learn through experience with the people that are starting. In this entry I’ll show you how to have a UI non closable QDialog but that it can be close from the code.

In GitQlient I’m using this dialog to inform the user that the repository is being loaded. There is some data I’m loading in the cache/background (branches, tags, etc) that can take a bit if the repository is massive. In my case, I’m working with some repos that are quite big (~10 Gb only text files) and old. People usually forget to remove their branches and right know I can see around 2000 branches and close to 500 tags. In that case an async load is needed so the user has to wait.

How to do a non closable QDialog?

We want to prevent the user to close the dialog in all it’s forms:

  • Disabling the window close icon.
  • Disabling the Esc key that in QDialog closes/cancels the dialog.

Acting on the windows title

The way to do that is quite simple. In the first place we hide the close button:

setWindowFlags(windowFlags() & ~Qt::WindowCloseButtonHint);

This will make the close button gone and keep the resize behaviour and dialog title. If you want a dialog only for the text you can do:

setWindowFlags(Qt::FramelessWindowHint);

That will remove the title bar and all it’s components.

Method 1: Acting on the Esc key event

QDialog process the Esc key as close/cancel. Since we don’t want that the user closes our dialog, we need to take care of that behaviour. To do that we need to capture the key press event and avoid processing it:

void WaitingDlg::keyPressEvent(QKeyEvent *e)
{
   if (e->key() == Qt::Key_Escape)
      return;

   QDialog::keyPressEvent(e);
}

The code is quite simple, we check the pressed key and if it’s the one we’re expecting, we don’t process the event.

Additionally, it’s also useful to have full control of another event: the closeEvent. That method plus a custom close method will give us the full behaviour:

void WaitingDlg::closeEvent(QCloseEvent *e)
{
   if (!mPrepareToClose)
      e->ignore();
   else
      QDialog::closeEvent(e);
}

void WaitingDlg::close()
{
   mPrepareToClose = true;

   QDialog::close();
}

In this code I’m using a class member to store when I do want to close the dialog, preventing the dialog to close if it wasn’t me how said it. The result is that this dialog can only be close by calling the close() method.

Method 2: Override reject method

Suggested in the comments by NickD2039 another possibility is to override the reject method, that would prevent the end user from closing the dialog. The code posted has a closeNow method that acts in a similar way to the method 1, it activates a control variable that finall calls accept.

I kind of like a bit more this code, since it’s a bit more elegant and requires you to write less code:

void closeNow()
{
   mPrepareToClose = true;
   accept();
   mPrepareToClose = false;
}

void accept()
{
   if (mPrepareToClose)
      QDialog::accept();
}

void reject()
{
   if (mPrepareToClose)
      QDialog::reject();
}

Where to find the source coude?

You can find the source code for the non closable dialog in my GitHub repository for Qt tips. Please noticed that I name it WaitingDlg since I did the code for GitQlient and that was its purpose.

New GitQlient v1.1.1 (+ Mac)

There is available a patch for the version 1.1 of GitQlient.

The new patch version solves a problem with new repositories. The problem prevented users to work with repositories that have no commits. That applies to both new repositories (via init new repo) and already created repos that don’t have any commits.

I took advantage of this issue to release also a release for OSX. It’s as functional as I would expect to have it in the next 1.2.0. However, I’d like if people can test it before going into the next release.

The binaries

You can find the binaries for GitQlient v1.1.1 on the release section on the GitHub repo:

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.

Released GitQlientPlugin 1.2.0 for QtCreator

I’m happy to announce the release of GitQlientPlugin 1.2.0

A month ago I released the version 1.1.0 of GitQlient. With that I shipped some improvements, a few fixes and a big new functionality I was missing: the Merge view.

I still have to add some features and add OSX support in GitQlient, but for now the code is fully compatible with the three big ones (Linux, Mac and Windows).

What was missing is some fixes at plugin level, even that I’ve tried to be on track with it, I prefer to focus on GitQlient as app. However, after a month I think I have a stable version of the plugin that can be ship or at least published as version.

I’ve generated two binaries: one for Linux, compiled with GCC 5.3.1 and another with MSVC2017 32bits. The main reason is because those are the compilers that QtCreator uses and then I make sure that the dependencies, that are shipped as dynamic libraries work well. As you can see, Mac is still the pending task.

The binaries

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

Further work

Since GitQlientPlugin is a wrap of GitQlient, you can see the release planning and all the features that every release will contain in the Release Plan for GitQlient.

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

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!

New UI Git plugin for QtCreator: GitQlient

Today I’m really happy to announce that the first version of the Git plugin for QtCreator has been released!

In the last post I advanced some of the final work that will be part of the first version of GitQlient. But what I didn’t explain so far is that that refactor, the re-work and addition of new functionality and the new redesign of the UI had one purpose: provide a Git plugin UI-based for QtCreator!

How to install the Git plugin

You can find the plugin in the release section of GitHub, but I give you the link as well:

Once you have downloaded the plugin, copy it into the QtCreator folder where Qt is installed (Qt/Tools/QtCreator/lib/qtcreator/plugins) or in the following folders:

  • Linux:
    • ~/.local/share/data/QtProject/qtcreator/plugin/<version>
  • Windows
    • %LOCALAPPDATA%\QtProject\qtcreator\plugins\<version>
  • OSX
    • ~/Library/Application Support/QtProject/Qt Creator/plugins/<version>

You need to replace <version> with the QtCreator version (e.g. 4.10.2).

The plugin is activated by default once you have copied it, so you just will need to reboot QtCreator.

How to use the Git plugin for QtCreator

As said before, the plugin will be active by default. That will add a new tab in the left panel with the name of GitQlient (the shourtcut is managed by QtCreator and is Ctrl+4):

New tab option for GitQlient
New tab option for GitQlient

If you go in that tab you will find the main window of GitQlient as it is in the app. I’ve disabled the logs in the plugin but apart from that is the same version.

As you can see, I’ve even added the support for multiple repositories in the view:

Support for multi-repo view - GitQlientPlugin - Git plugin for QtCreator
Support for multi-repo view – GitQlientPlugin – Git plugin for QtCreator

In the top of the window you will find the main controls. You will find all the available options in context menu inside every view. The Blame&History view is also available:

Blame&History view - GiQlientPlugin - Git plugin for QtCreator
Blame&History view – GiQlientPlugin – Git plugin for QtCreator

How to report an error, bug or request a new feature

If you find an error or a bug, please contact me as soon as possible so I can fix it. I’m using GitHub issues to help me on that task.

Since the 99% of the code belongs to GitQlient, please open an issue in that repo on GitHub and I’ll manage from there 🙂

In the Project area, you can see all the new features that are planned for the version 2.0.0. If you want something that is not there, don’t hesitate to add a new issue as Feature or Improvement in the issues page as you did for bug/errors.

Further work

The plan is to release a version of the plugin every time that QtCreator updates.

In addition and not to loose all the new features, I’ll release a new version of the plugin every time that GitQlient updates.

How to set up TravisCI for Qt apps

When I started GitQlient and GitQlientPlugin one of the first things I wanted was to setup TravisCI for Qt apps. The main reason is, of course, to have a system that checks a clean build of both projects.

The other reason, however, is that I think its a quite nice environment to deploy your build in GitHub. Locally, your system can be messed up with versions and old objects that are not cleared, etc. By doing it in this way, one is allowed to have a clean build in a really controlled environment. In addition, you can run as much versions and they are deploy independently.

This is post is more a remind me in the future rather than a how to, although I hope people find it useful.

(more…)