mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-09 18:31:04 +00:00
* Some more clever elide mode for the LyX buffer tabs. In trunk
currently the whole path is (possibly with some unmotivated ... in the middle) used which is usually far too long. The algorithm implemented here will start with absolute paths. From left to right path segments are added to the display string if they help to make the display strings more unique. Otherwise nothing is added, or if some middle path segments are omitted otherwise, three dots ... are used. The result is that we get just the base filename without extension if they are unique in the tabbar. The patch is open for discussion. If there is demand we can create yet another preference option to get back the old behaviour. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@24555 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
2090c47bfa
commit
48999ee671
@ -1313,13 +1313,15 @@ GuiWorkArea * TabWorkArea::addWorkArea(Buffer & buffer, GuiView & view)
|
||||
showBar(count() > 0);
|
||||
addTab(wa, wa->windowTitle());
|
||||
QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
|
||||
this, SLOT(updateTabText(GuiWorkArea *)));
|
||||
this, SLOT(updateTabTexts()));
|
||||
if (currentWorkArea() && currentWorkArea()->isFullScreen())
|
||||
setFullScreen(true);
|
||||
else
|
||||
// Hide tabbar if there's only one tab.
|
||||
showBar(count() > 1);
|
||||
|
||||
updateTabTexts();
|
||||
|
||||
return wa;
|
||||
}
|
||||
|
||||
@ -1347,6 +1349,8 @@ bool TabWorkArea::removeWorkArea(GuiWorkArea * work_area)
|
||||
lastWorkAreaRemoved();
|
||||
}
|
||||
|
||||
updateTabTexts();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1392,13 +1396,216 @@ void TabWorkArea::closeCurrentTab()
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
class DisplayPath {
|
||||
public:
|
||||
/// make vector happy
|
||||
DisplayPath() {}
|
||||
///
|
||||
DisplayPath(int tab, FileName const & filename)
|
||||
: tab_(tab)
|
||||
{
|
||||
filename_ = toqstr(filename.onlyFileNameWithoutExt());
|
||||
postfix_ = toqstr(filename.absoluteFilePath()).split("/", QString::SkipEmptyParts);
|
||||
postfix_.pop_back();
|
||||
abs_ = toqstr(filename.absoluteFilePath());
|
||||
dottedPrefix_ = false;
|
||||
}
|
||||
|
||||
/// Absolute path for debugging.
|
||||
QString abs() const
|
||||
{
|
||||
return abs_;
|
||||
}
|
||||
/// Add the first segment from the postfix or three dots to the prefix.
|
||||
/// Merge multiple dot tripples. In fact dots are added lazily, i.e. only
|
||||
/// when really needed.
|
||||
void shiftPathSegment(bool dotted)
|
||||
{
|
||||
if (postfix_.count() > 0) {
|
||||
if (!dotted) {
|
||||
if (dottedPrefix_ && !prefix_.isEmpty())
|
||||
prefix_ += ".../";
|
||||
prefix_ += postfix_.front() + "/";
|
||||
}
|
||||
dottedPrefix_ = dotted && !prefix_.isEmpty();
|
||||
postfix_.pop_front();
|
||||
}
|
||||
}
|
||||
///
|
||||
QString displayString() const
|
||||
{
|
||||
if (prefix_.isEmpty())
|
||||
return filename_;
|
||||
else {
|
||||
bool dots = dottedPrefix_ || !postfix_.isEmpty();
|
||||
return prefix_
|
||||
+ (dots ? ".../" : "")
|
||||
+ filename_;
|
||||
}
|
||||
}
|
||||
///
|
||||
QString forecastDisplayString() const
|
||||
{
|
||||
if (postfix_.count() == 0)
|
||||
return displayString();
|
||||
|
||||
bool postfixLeft = postfix_.count() > 1;
|
||||
return prefix_
|
||||
+ (dottedPrefix_ ? ".../" : "")
|
||||
+ postfix_.front() + "/"
|
||||
+ (postfixLeft ? ".../" : "")
|
||||
+ filename_;
|
||||
}
|
||||
///
|
||||
bool final() const
|
||||
{
|
||||
return postfix_.empty();
|
||||
}
|
||||
///
|
||||
int tab() const
|
||||
{
|
||||
return tab_;
|
||||
}
|
||||
|
||||
private:
|
||||
///
|
||||
QString prefix_;
|
||||
///
|
||||
QStringList postfix_;
|
||||
///
|
||||
QString filename_;
|
||||
///
|
||||
QString abs_;
|
||||
///
|
||||
int tab_;
|
||||
///
|
||||
bool dottedPrefix_;
|
||||
};
|
||||
|
||||
void TabWorkArea::updateTabText(GuiWorkArea * wa)
|
||||
|
||||
///
|
||||
bool operator<(DisplayPath const & a, DisplayPath const & b)
|
||||
{
|
||||
int const i = indexOf(wa);
|
||||
if (i < 0)
|
||||
return a.displayString() < b.displayString();
|
||||
}
|
||||
|
||||
///
|
||||
bool operator==(DisplayPath const & a, DisplayPath const & b)
|
||||
{
|
||||
return a.displayString() == b.displayString();
|
||||
}
|
||||
|
||||
|
||||
void TabWorkArea::updateTabTexts()
|
||||
{
|
||||
size_t n = count();
|
||||
if (n == 0)
|
||||
return;
|
||||
setTabText(i, wa->windowTitle());
|
||||
std::list<DisplayPath> paths;
|
||||
typedef std::list<DisplayPath>::iterator It;
|
||||
|
||||
// collect full names first: path into postfix, empty prefix and
|
||||
// filename without extension
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
GuiWorkArea * i_wa = dynamic_cast<GuiWorkArea *>(widget(i));
|
||||
FileName const fn = i_wa->bufferView().buffer().fileName();
|
||||
paths.push_back(DisplayPath(i, fn));
|
||||
}
|
||||
|
||||
// go through path segments and see if it helps to make the path more unique
|
||||
bool somethingChanged = true;
|
||||
bool allFinal = false;
|
||||
while (somethingChanged && !allFinal) {
|
||||
// adding path segments changes order
|
||||
paths.sort();
|
||||
|
||||
LYXERR(Debug::GUI, "updateTabTexts() iteration start");
|
||||
somethingChanged = false;
|
||||
allFinal = true;
|
||||
|
||||
// find segments which are not unique (i.e. non-atomic)
|
||||
It it = paths.begin();
|
||||
It segStart = it;
|
||||
QString segString = it->displayString();
|
||||
for (; it != paths.end(); ++it) {
|
||||
// look to the next item
|
||||
It next = it;
|
||||
++next;
|
||||
|
||||
// final?
|
||||
allFinal = allFinal && it->final();
|
||||
|
||||
LYXERR(Debug::GUI, "it = " << fromqstr(it->abs())
|
||||
<< " => " << fromqstr(it->displayString()));
|
||||
|
||||
// still the same segment?
|
||||
QString nextString;
|
||||
if ((next != paths.end()
|
||||
&& (nextString = next->displayString()) == segString))
|
||||
continue;
|
||||
LYXERR(Debug::GUI, "segment ended");
|
||||
|
||||
// only a trivial one with one element?
|
||||
if (it == segStart) {
|
||||
// start new segment
|
||||
segStart = next;
|
||||
segString = nextString;
|
||||
continue;
|
||||
}
|
||||
|
||||
// we found a non-atomic segment segStart <= sit <= it < next.
|
||||
// Shift path segments and hope for the best
|
||||
// that it makes the path more unique.
|
||||
somethingChanged = true;
|
||||
It sit = segStart;
|
||||
QString dspString = sit->forecastDisplayString();
|
||||
LYXERR(Debug::GUI, "first forecast found for "
|
||||
<< fromqstr(sit->abs())
|
||||
<< " => " << fromqstr(dspString));
|
||||
++sit;
|
||||
bool moreUnique = false;
|
||||
for (; sit != next; ++sit) {
|
||||
if (sit->forecastDisplayString() != dspString) {
|
||||
LYXERR(Debug::GUI, "different forecast found for "
|
||||
<< fromqstr(sit->abs())
|
||||
<< " => "
|
||||
<< fromqstr(sit->forecastDisplayString()));
|
||||
moreUnique = true;
|
||||
break;
|
||||
} else {
|
||||
LYXERR(Debug::GUI, "same forecast found for "
|
||||
<< fromqstr(sit->abs())
|
||||
<< " => "
|
||||
<< fromqstr(sit->forecastDisplayString()));
|
||||
}
|
||||
}
|
||||
|
||||
// if the path segment helped, add it. Otherwise add dots
|
||||
bool dots = !moreUnique;
|
||||
LYXERR(Debug::GUI, "using dots = " << dots);
|
||||
for (sit = segStart; sit != next; ++sit) {
|
||||
sit->shiftPathSegment(dots);
|
||||
LYXERR(Debug::GUI, "shifting " << fromqstr(sit->abs())
|
||||
<< " => "
|
||||
<< fromqstr(sit->displayString()));
|
||||
}
|
||||
|
||||
// start new segment
|
||||
segStart = next;
|
||||
segString = nextString;
|
||||
}
|
||||
}
|
||||
|
||||
// set new tab titles
|
||||
for (It it = paths.begin(); it != paths.end(); ++it) {
|
||||
GuiWorkArea * i_wa = dynamic_cast<GuiWorkArea *>(widget(it->tab()));
|
||||
Buffer & buf = i_wa->bufferView().buffer();
|
||||
if (!buf.fileName().empty() && !buf.isClean())
|
||||
setTabText(it->tab(), it->displayString() + "*");
|
||||
else
|
||||
setTabText(it->tab(), it->displayString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -270,7 +270,7 @@ public Q_SLOTS:
|
||||
/// close current tab, or the one given by \c clicked_tab_
|
||||
void closeCurrentTab();
|
||||
///
|
||||
void updateTabText(GuiWorkArea *);
|
||||
void updateTabTexts();
|
||||
|
||||
private Q_SLOTS:
|
||||
///
|
||||
|
@ -265,6 +265,12 @@ string FileName::onlyFileName() const
|
||||
}
|
||||
|
||||
|
||||
string FileName::onlyFileNameWithoutExt() const
|
||||
{
|
||||
return fromqstr(d->fi.baseName());
|
||||
}
|
||||
|
||||
|
||||
FileName FileName::onlyPath() const
|
||||
{
|
||||
FileName path;
|
||||
|
@ -162,6 +162,8 @@ public:
|
||||
|
||||
/// filename without path
|
||||
std::string onlyFileName() const;
|
||||
/// filename without path and without extension
|
||||
std::string onlyFileNameWithoutExt() const;
|
||||
/// path without file name
|
||||
FileName onlyPath() const;
|
||||
/// used for display in the Gui
|
||||
|
Loading…
Reference in New Issue
Block a user