changeset 523:d869e6a18f63

Make the text labels in the work status area squeezable for small window sizes. Fixes #329
author Chris Cannam
date Tue, 15 Nov 2011 16:02:18 +0000
parents 43ddfa5e9fd0
children 721a8e30822b
files easyhg.pro src/clickablelabel.h src/squeezedlabel.cpp src/squeezedlabel.h src/workstatuswidget.cpp src/workstatuswidget.h
diffstat 6 files changed, 325 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/easyhg.pro	Tue Nov 15 14:47:19 2011 +0000
+++ b/easyhg.pro	Tue Nov 15 16:02:18 2011 +0000
@@ -63,7 +63,8 @@
     src/moreinformationdialog.h \
     src/annotatedialog.h \
     src/hgignoredialog.h \
-    src/versiontester.h
+    src/versiontester.h \
+    src/squeezedlabel.h
 SOURCES = \
     src/main.cpp \
     src/mainwindow.cpp \
@@ -99,7 +100,8 @@
     src/moreinformationdialog.cpp \
     src/annotatedialog.cpp \
     src/hgignoredialog.cpp \
-    src/versiontester.cpp
+    src/versiontester.cpp \
+    src/squeezedlabel.cpp
 
 macx-* {
     SOURCES += src/common_osx.mm
--- a/src/clickablelabel.h	Tue Nov 15 14:47:19 2011 +0000
+++ b/src/clickablelabel.h	Tue Nov 15 16:02:18 2011 +0000
@@ -18,9 +18,11 @@
 #ifndef _CLICKABLE_LABEL_H_
 #define _CLICKABLE_LABEL_H_
 
-#include <QLabel>
+#include "squeezedlabel.h"
 
-class ClickableLabel : public QLabel
+#include <QMouseEvent>
+
+class ClickableLabel : public SqueezedLabel
 {
     Q_OBJECT
 
@@ -28,12 +30,12 @@
 
 public:
     ClickableLabel(const QString &text, QWidget *parent = 0) :
-        QLabel(text, parent),
+        SqueezedLabel(text, parent),
 	m_naturalText(text)
     { }
 
     ClickableLabel(QWidget *parent = 0) :
-	QLabel(parent)
+	SqueezedLabel(parent)
     { }
 
     ~ClickableLabel()
@@ -41,7 +43,7 @@
 
     void setText(const QString &t) {
 	m_naturalText = t;
-	QLabel::setText(t);
+	SqueezedLabel::setText(t);
     }
 
     bool mouseUnderline() const {
@@ -62,18 +64,22 @@
 protected:
     virtual void enterEvent(QEvent *) {
 	if (m_mouseUnderline) {
-	    QLabel::setText(tr("<u>%1</u>").arg(m_naturalText));
+	    SqueezedLabel::setText(tr("<u>%1</u>").arg(m_naturalText));
 	}
     }
 
     virtual void leaveEvent(QEvent *) {
 	if (m_mouseUnderline) {
-	    QLabel::setText(m_naturalText);
+	    SqueezedLabel::setText(m_naturalText);
 	}
     }
 
-    virtual void mousePressEvent(QMouseEvent *) {
-        emit clicked();
+    virtual void mousePressEvent(QMouseEvent *ev) {
+        if (ev->button() == Qt::LeftButton) {
+            emit clicked();
+        } else {
+            SqueezedLabel::mousePressEvent(ev);
+        }
     }
 
 private:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/squeezedlabel.cpp	Tue Nov 15 16:02:18 2011 +0000
@@ -0,0 +1,180 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+    EasyMercurial
+
+    Based on HgExplorer by Jari Korhonen
+    Copyright (c) 2010 Jari Korhonen
+    Copyright (c) 2011 Chris Cannam
+    Copyright (c) 2011 Queen Mary, University of London
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+/*
+    This file adapted from Rosegarden, a sequencer and musical
+    notation editor.  Copyright 2000-2011 the Rosegarden development
+    team.
+
+    Adapted from KDE 4.2.0, this code originally Copyright (c) 2000
+    Ronny Standtke.
+*/
+
+#include "squeezedlabel.h"
+
+#include <iostream>
+
+#include <QContextMenuEvent>
+#include <QAction>
+#include <QMenu>
+#include <QClipboard>
+#include <QApplication>
+#include <QMimeData>
+#include <QDesktopWidget>
+
+
+class SqueezedLabelPrivate
+{
+public:
+};
+
+void SqueezedLabel::_k_copyFullText()
+{
+    QMimeData* data = new QMimeData;
+    data->setText(fullText);
+    QApplication::clipboard()->setMimeData(data);
+}
+
+SqueezedLabel::SqueezedLabel(const QString &text , QWidget *parent)
+        : QLabel (parent)
+{
+    setObjectName("SQUEEZED");
+    setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+    fullText = text;
+    elideMode = Qt::ElideMiddle;
+    squeezeTextToLabel();
+}
+
+SqueezedLabel::SqueezedLabel(QWidget *parent)
+        : QLabel (parent)
+{
+    setObjectName("SQUEEZED");
+    setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+    elideMode = Qt::ElideMiddle;
+}
+
+SqueezedLabel::~SqueezedLabel()
+{
+}
+
+void SqueezedLabel::resizeEvent(QResizeEvent *)
+{
+    squeezeTextToLabel();
+}
+
+QSize SqueezedLabel::minimumSizeHint() const
+{
+    QSize sh = QLabel::minimumSizeHint();
+    sh.setWidth(-1);
+    return sh;
+}
+
+QSize SqueezedLabel::sizeHint() const
+{
+    int dw = QApplication::desktop()->availableGeometry(QPoint(0, 0)).width();
+    int maxWidth = dw * 3 / 4;
+    QFontMetrics fm(fontMetrics());
+    int textWidth = fm.width(fullText);
+    if (textWidth > maxWidth) {
+        textWidth = maxWidth;
+    }
+    return QSize(textWidth, QLabel::sizeHint().height());
+}
+
+void SqueezedLabel::setText(const QString &text)
+{
+    fullText = text;
+    squeezeTextToLabel();
+}
+
+void SqueezedLabel::clear() {
+    fullText.clear();
+    QLabel::clear();
+}
+
+void SqueezedLabel::squeezeTextToLabel() {
+    QFontMetrics fm(fontMetrics());
+    int labelWidth = size().width();
+    QStringList squeezedLines;
+    bool squeezed = false;
+    Q_FOREACH(const QString& line, fullText.split('\n')) {
+        int lineWidth = fm.width(line);
+        if (lineWidth > labelWidth) {
+            squeezed = true;
+            squeezedLines << fm.elidedText(line, elideMode, labelWidth);
+        } else {
+            squeezedLines << line;
+        }
+    }
+
+    if (squeezed) {
+        QLabel::setText(squeezedLines.join("\n"));
+        setToolTip(fullText);
+    } else {
+        QLabel::setText(fullText);
+        setToolTip(QString());
+    }
+}
+
+void SqueezedLabel::setAlignment(Qt::Alignment alignment)
+{
+    // save fullText and restore it
+    QString tmpFull(fullText);
+    QLabel::setAlignment(alignment);
+    fullText = tmpFull;
+}
+
+Qt::TextElideMode SqueezedLabel::textElideMode() const
+{
+    return elideMode;
+}
+
+void SqueezedLabel::setTextElideMode(Qt::TextElideMode mode)
+{
+    elideMode = mode;
+    squeezeTextToLabel();
+}
+
+void SqueezedLabel::contextMenuEvent(QContextMenuEvent* ev)
+{
+    // "We" means the KDE team here.
+    //
+    // We want to reimplement "Copy" to include the elided text.
+    // But this means reimplementing the full popup menu, so no more
+    // copy-link-address or copy-selection support anymore, since we
+    // have no access to the QTextDocument.
+    // Maybe we should have a boolean flag in SqueezedLabel itself for
+    // whether to show the "Copy Full Text" custom popup?
+    // For now I chose to show it when the text is squeezed; when it's not, the
+    // standard popup menu can do the job (select all, copy).
+
+    const bool squeezed = text() != fullText;
+    const bool showCustomPopup = squeezed;
+    if (showCustomPopup) {
+        QMenu menu(this);
+
+        QAction* act = new QAction(tr("&Copy Full Text"), this);
+        connect(act, SIGNAL(triggered()), this, SLOT(_k_copyFullText()));
+        menu.addAction(act);
+
+        ev->accept();
+        menu.exec(ev->globalPos());
+    } else {
+        QLabel::contextMenuEvent(ev);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/squeezedlabel.h	Tue Nov 15 16:02:18 2011 +0000
@@ -0,0 +1,120 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+    EasyMercurial
+
+    Based on HgExplorer by Jari Korhonen
+    Copyright (c) 2010 Jari Korhonen
+    Copyright (c) 2011 Chris Cannam
+    Copyright (c) 2011 Queen Mary, University of London
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+/*
+    This file adapted from Rosegarden, a sequencer and musical
+    notation editor.  Copyright 2000-2011 the Rosegarden development
+    team.
+
+    Adapted from KDE 4.2.0, this code originally Copyright (c) 2000
+    Ronny Standtke.
+*/
+
+#ifndef _SQUEEZED_LABEL_H_
+#define _SQUEEZED_LABEL_H_
+
+#include <QLabel>
+
+class SqueezedLabelPrivate;
+
+/**
+ * @short A replacement for QLabel that squeezes its text
+ *
+ * A label class that squeezes its text into the label
+ *
+ * If the text is too long to fit into the label it is divided into
+ * remaining left and right parts which are separated by three dots.
+ */
+
+class SqueezedLabel : public QLabel
+{
+    Q_OBJECT
+    Q_PROPERTY(Qt::TextElideMode textElideMode READ textElideMode WRITE setTextElideMode)
+
+public:
+    /**
+    * Default constructor.
+    */
+    explicit SqueezedLabel(QWidget *parent = 0);
+    explicit SqueezedLabel(const QString &text, QWidget *parent = 0);
+
+    virtual ~SqueezedLabel();
+
+    virtual QSize minimumSizeHint() const;
+    virtual QSize sizeHint() const;
+    /**
+    * Overridden for internal reasons; the API remains unaffected.
+    */
+    virtual void setAlignment(Qt::Alignment);
+
+    /**
+    *  Returns the text elide mode.
+    */
+    Qt::TextElideMode textElideMode() const;
+
+    /**
+    * Sets the text elide mode.
+    * @param mode The text elide mode.
+    */
+    void setTextElideMode(Qt::TextElideMode mode);
+
+public Q_SLOTS:
+    /**
+    * Sets the text. Note that this is not technically a reimplementation of QLabel::setText(),
+    * which is not virtual (in Qt 4.3). Therefore, you may need to cast the object to
+    * SqueezedLabel in some situations:
+    * \Example
+    * \code
+    * SqueezedLabel* squeezed = new SqueezedLabel("text", parent);
+    * QLabel* label = squeezed;
+    * label->setText("new text");    // this will not work
+    * squeezed->setText("new text");    // works as expected
+    * static_cast<SqueezedLabel*>(label)->setText("new text");    // works as expected
+    * \endcode
+    * @param mode The new text.
+    */
+    void setText(const QString &text);
+    /**
+    * Clears the text. Same remark as above.
+    *
+    */
+    void clear();
+
+protected:
+    /**
+    * Called when widget is resized
+    */
+    void resizeEvent(QResizeEvent *);
+    /**
+    * \reimp
+    */
+    void contextMenuEvent(QContextMenuEvent*);
+    /**
+    * does the dirty work
+    */
+    void squeezeTextToLabel();
+
+private slots:
+    void _k_copyFullText();
+
+private:
+    QString fullText;
+    Qt::TextElideMode elideMode;
+};
+
+
+#endif
--- a/src/workstatuswidget.cpp	Tue Nov 15 14:47:19 2011 +0000
+++ b/src/workstatuswidget.cpp	Tue Nov 15 16:02:18 2011 +0000
@@ -18,6 +18,7 @@
 #include "workstatuswidget.h"
 #include "debug.h"
 #include "clickablelabel.h"
+#include "squeezedlabel.h"
 
 #include <QGridLayout>
 #include <QSpacerItem>
@@ -47,15 +48,13 @@
     f.setBold(true);
     m_openButton->setFont(f);
     m_openButton->setMouseUnderline(true);
-    m_openButton->setWordWrap(true);
     connect(m_openButton, SIGNAL(clicked()), this, SLOT(openButtonClicked()));
-    layout->addWidget(m_openButton, row, 2, 1, 2, Qt::AlignLeft);
+    layout->addWidget(m_openButton, row, 2, 1, 2);
 
     ++row;
     layout->addWidget(new QLabel(tr("Remote:")), row, 1);
-    m_remoteURLLabel = new QLabel;
+    m_remoteURLLabel = new SqueezedLabel;
     m_remoteURLLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
-    m_remoteURLLabel->setWordWrap(true);
     layout->addWidget(m_remoteURLLabel, row, 2, 1, 2);
 
     ++row;
--- a/src/workstatuswidget.h	Tue Nov 15 14:47:19 2011 +0000
+++ b/src/workstatuswidget.h	Tue Nov 15 16:02:18 2011 +0000
@@ -20,6 +20,8 @@
 
 #include <QWidget>
 
+class SqueezedLabel;
+
 class QLabel;
 class QPushButton;
 class QFileInfo;
@@ -51,7 +53,7 @@
     ClickableLabel *m_openButton;
 
     QString m_remoteURL;
-    QLabel *m_remoteURLLabel;
+    SqueezedLabel *m_remoteURLLabel;
 
     QString m_state;
     QLabel *m_stateLabel;