Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Active file tab in editor gets moved to the right when tab bar is wider than editor pane #5459

Open
Khris777 opened this issue Oct 13, 2017 · 59 comments

Comments

@Khris777
Copy link

Description of your problem

Take the situation when you have lots of files open in the editor so that their tabs don't fit the width of the editor pane and you get those two arrows on the right side next to the tab bar with which you can scroll left or right through your open files.

If you now take any file that is not on the right side and edit it the whole tab bar scrolls horizontally to push the active tab to the right rim of the editor or as far as possible.

Is there a good reason for this? Personally I find this behaviour quite annoying.

What is the expected output?

I don't want to tab bar to scroll on its own only because I'm editing one of the files.

Versions and main components

  • Spyder Version: 3.2.3
  • Python Version: 3.6.3
  • Qt Version: 5.6.2
  • PyQt Version: 5.6
  • Operating system: Windows 10

Dependencies

IPython >=4.0 : 6.2.1 (OK)
cython >=0.21 : 0.26.1 (OK)
jedi >=0.9.0 : 0.10.2 (OK)
nbconvert >=4.0 : 5.3.1 (OK)
numpy >=1.7 : 1.13.1 (OK)
pandas >=0.13.1 : 0.20.3 (OK)
pycodestyle >=2.3: 2.3.1 (OK)
pyflakes >=0.6.0 : 1.5.0 (OK)
pygments >=2.0 : 2.2.0 (OK)
pylint >=0.25 : 1.7.2 (OK)
qtconsole >=4.2.0: 4.3.1 (OK)
rope >=0.9.4 : 0.10.5 (OK)
sphinx >=0.6.6 : 1.6.3 (OK)
sympy >=0.7.3 : 1.1.1 (OK)

@ccordoba12
Copy link
Member

This behavior was asked by several users in the past, so we changed how the Editor tab scrolls to fit it.

@jnsebgosselin
Copy link
Member

@ccordoba12 I think this is a duplicate of Issue #1170, which should have been fixed by @rlaverde in PR #4607. However, I can confirm that I can reproduce the undesired behavior now on the master branch.

tabs_auto_scrolling

@jnsebgosselin
Copy link
Member

jnsebgosselin commented Oct 13, 2017

@ccordoba12 I was wrong. Issue #1170 and PR #4607 seems to relate to the undesired behaviour when selecting tabs, not when editing the corresponding file.

@ccordoba12 ccordoba12 reopened this Oct 13, 2017
@ccordoba12
Copy link
Member

@rlaverde, what do you think about this one?

@rlaverde
Copy link
Member

I can confirm this issue too, is different to #1170 (but It's related)

This is caused because when writing a file,the test of the tab change (file--->file*),and that update cause the scrolling,but I don't know how It could be fixed (#4607 only fixes when selecting the tabs, avoiding the unnecessary update of the tabtext 725c015)

@ccordoba12
Copy link
Member

@rlaverde, any way to fix this one?

@jnsebgosselin
Copy link
Member

@ccordoba12 I've looked a little bit into it and I think this is going to be hard to fix. This is occurring in private methods on the Qt side and I haven't found a way to prevent this undesired behavior. I would say this is a Qt bug per se... but if we wait for this to be fixed on the Qt side, we may wait for a long time.

I'll take a look again in case I've missed something on my first try. It's probably possible to go around it, but this is going to be some kind of a hack.

@rlaverde
Copy link
Member

rlaverde commented Oct 23, 2017

any way to fix this one?

No, I don't know how it could be fixed, sorry 😞, as @jnsebgosselin says It looks like a Qt issue, I fixed the other one (#1170) with a workaround (not updating the tab title) but that workaround is not possible in this case 😕

@ccordoba12
Copy link
Member

Ok, thanks for the info @jnsebgosselin and @rlaverde.

I'm closing this one for now. @jnsebgosselin, please reopen it if you find a workaround.

@bcolsen
Copy link
Member

bcolsen commented Nov 26, 2019

This was irritating me today. It is very difficult to work on two documents with the tabs moving around so I looked up some options.

I seems to happen whenever the title of the tab changes. This is the worst when adding or removing the "*" on changing or saving the document.

Option 1

I thought we could see if changing the text color would force a redraw. Yellow for modified, red for read only

Option 2

Notepadqq changes icons in the tabs and the tabs don't move.

image

Should be smaller. Could be a dot.

https://github.com/notepadqq/notepadqq/blob/c0efb1b275d2a260d18d172a1a739821ce134f80/src/ui/editortabwidget.cpp#L285-L291

@bcolsen bcolsen reopened this Nov 26, 2019
@bcolsen
Copy link
Member

bcolsen commented Nov 26, 2019

Option 3

Let it move and move it back. Can we control the view at all?

@ccordoba12
Copy link
Member

@jnsebgosselin, we could use your input here. What do you think about @bcolsen's ideas?

@jnsebgosselin
Copy link
Member

I agree this is irritating for me too. I will take a look at it again with a fresh eye and see if I can find a solution.

@jnsebgosselin
Copy link
Member

And if I can't find a solution, I think option 2 is the one I prefer.

@goanpeca
Copy link
Member

goanpeca commented Nov 27, 2019

It seems not much to do in that area

https://code.woboq.org/qt5/qtbase/src/widgets/widgets/qtabbar.cpp.html#_ZN14QTabBarPrivate7refreshEv

void QTabBarPrivate::refresh()
--
{
Q_Q(QTabBar);
 
// be safe in case a subclass is also handling move with the tabs
if (pressedIndex != -1
&& movable
&& QGuiApplication::mouseButtons() == Qt::NoButton) {
moveTabFinished(pressedIndex);
if (!validIndex(pressedIndex))
pressedIndex = -1;
}
 
if (!q->isVisible()) {
layoutDirty = true;
} else {
layoutTabs();
makeVisible(currentIndex);
q->update();
q->updateGeometry();
}
}

makeVisible(currentIndex); is always called, and is private.

@goanpeca
Copy link
Member

Let it move and move it back. Can we control the view at all?

I think we can;t... :-\

@jnsebgosselin
Copy link
Member

@bcolsen
Copy link
Member

bcolsen commented Nov 27, 2019

The more I think about it adding the ""s actually the the work around for gui tool kits that don't allow icons on their tabs. I think that a simple small colored dot icon could convey as much meaning as a ""

@jnsebgosselin
Copy link
Member

I thought we could see if changing the text color would force a redraw. Yellow for modified, red for read only

This would work and my vote goes to this option.

It also takes less horizontal space, so this is an additional benefit.

tabs_moving

tabs_moving_color

@goanpeca
Copy link
Member

This is awesome news @jnsebgosselin !

Could you post a version for the dark theme to see how it looks?

@goanpeca goanpeca modified the milestones: important, 4.1.0 Nov 28, 2019
@jnsebgosselin
Copy link
Member

jnsebgosselin commented Nov 6, 2021

Ok, I've looked into this issue (again) and unless I am missing something, we would have to basically rewrite almost the whole QTabBar class in Python in order to paint the tabs ourselves. paintEvent depends on a lot of private methods, which in turn depend on a lot of private attributes that are defined all over the place in QTabBar.

What do you think @ccordoba12? It seems like going that route would be a lot of work and would add a lot of maintenance overhead in order to fix a, relatively speaking, minor UX inconvenience that should, imho, truly be fixed on the Qt side instead.

Maybe this is already or is going to be fixed in Qt6, there seems to be a lot of refactoring going on lately with the QTabBar class.
https://github.com/qt/qtbase/commits/5d4b91ea66666f3c8d3c8640b87a33c13dbd0c2c/src/widgets/widgets/qtabbar.cpp

Even if its not fixed in Qt6, in PyQt6, it seems like initStyleOption has been made virtual. So I think we might be able to easily implement a workaround by extending QTabBar.initStyleOption in order to add an * to the tabs that are modified instead of calling QTabBar.setTabText directly.

For Qt5 and PyQt5 though, I think our best option is to either do nothing or add an option to add an icon like I did in #5459 (comment), even though this makes the tabs wider.

@ccordoba12 ccordoba12 added this to the v6.0alpha3 milestone Jul 11, 2023
@ccordoba12 ccordoba12 modified the milestones: v6.0alphaX, v6.0alpha3 Sep 9, 2023
@ccordoba12 ccordoba12 modified the milestones: v6.0alpha3, v6.0beta1 Nov 17, 2023
@tecbr
Copy link

tecbr commented Nov 19, 2023

Any update on this? This important problem has persisted for 6 years.

@jnsebgosselin
Copy link
Member

jnsebgosselin commented Nov 21, 2023

This bug is more a Qt than a Spyder bug per se and we have not been able to reach consensus to work around this issue in Spyder.

However, I think this annoying behavior was fixed in Qt 6.5.

See :

@tecbr
Copy link

tecbr commented Dec 12, 2023

Changing tab icon/text color when content changes seems to be a good and simple solution.

@jnsebgosselin
Copy link
Member

The option to add an icon makes the tabs substantially larger and was not accepted because of that. The option to simply change the text color was not accepted for accessibility reason I think.

@tecbr
Copy link

tecbr commented Dec 12, 2023

What if you add these features as optional? Then users can choose to activate/deactivate these features.

@jnsebgosselin
Copy link
Member

I know this is not ideal, but you can easily patch this in your Spyder version by changing just a few lines of codes. Something like this:

image

@ccordoba12
Copy link
Member

In PR #21276 I added our own close button for tabs in the editor and IPython console. With that we'll be able to implement the same UI as VSCode, i.e. showing a filled circle instead of an x for unsaved files. I think that will avoid the current behavior until we're able to support Qt 6.

@ccordoba12 ccordoba12 modified the milestones: v6.0alpha4, v6.0beta1 Feb 6, 2024
@ccordoba12 ccordoba12 modified the milestones: v6.0alpha5, v6.0beta1 Mar 12, 2024
@ccordoba12 ccordoba12 modified the milestones: v6.0beta1, v6.0beta2 May 10, 2024
@ccordoba12 ccordoba12 modified the milestones: v6.0beta2, v6.0beta3 Jun 17, 2024
@ptth222
Copy link

ptth222 commented Jul 1, 2024

I know this is not ideal, but you can easily patch this in your Spyder version by changing just a few lines of codes. Something like this:

image

This worked for me. Red and black were not good choices for the dark theme IMO. I went with something closer to orange. Here is the code I used:

from qtpy.QtGui import QColor
self.tabs.tabBar().setTabTextColor(index, QColor('#f5a742') if is_modified else QColor('white'))

It sounds like Qt 6 might finally fix this issue. If not, another good workaround I think would be to add an option on right-click or in the "Options" on the right side of the tab bar to send the tab left. The reposition doesn't happen if the tab bar is all the way on the left. I will often manually move all of my most active tabs to the left to avoid the repositioning. Being able to right-click and "Move Left" would make this less painful. Being able to do it on on the inactive tabs would be great as well, so you wouldn't have to "Move Left" and then scroll back right to move the next one left. Of course, now I think this color thing is going to be fine for me.

@tecbr
Copy link

tecbr commented Jul 1, 2024

Changing the tab text color has been the temporary solution for me as well. I have a bash script that updates Spyder and runs this code at the end:

sed -i -z "s|if tab_text != self\.tabs\.tabText(index):\n self\.tabs\.setTabText(index, tab_text)|#if tab_text != self\.tabs\.tabText(index):\n # self\.tabs\.setTabText(index, tab_text)\n # Fix from spyder-ide\/spyder#5459\n from qtpy\.QtGui import QColor\n self\.tabs\.tabBar()\.setTabTextColor(index, QColor(255, 155, 157) if is_modified else QColor(221, 223, 208))|g" $spyder_path/plugins/editor/widgets/editorstack/editorstack.py

@ccordoba12 ccordoba12 modified the milestones: v6.0beta3, v6.0.1 Jul 7, 2024
@ccordoba12 ccordoba12 modified the milestones: v6.0.1, v6.0.2 Sep 6, 2024
@ccordoba12 ccordoba12 modified the milestones: v6.0.2, v6.x.x Sep 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests