[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kdevelop-devel
Subject:    Changing the format of displayed value in debugger
From:       Konstantin Karganov <karganov () gmail ! com>
Date:       2010-07-19 17:42:04
Message-ID: AANLkTimCGJ_M_l6azUQefiDa5r6eZuNCKqcdCkeBG5Nd () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


Hi all,

under the wise guidance of Vladimir Prus I've implemented a feature that was
missing in Kdevelop4 compared to Kdevelop3.

Applying the attached patch you'll get context menu in the variable view,
ability to change format of the displayed variable (i.e. decimal, binary,
hex etc) and "copy value to clipboard" command as a free bonus :)

-- 
Best regards,
Konstantin.

[Attachment #5 (text/html)]

Hi all,<br><br>under the wise guidance of Vladimir Prus I&#39;ve implemented a \
feature that was missing in Kdevelop4 compared to Kdevelop3.<br><br>Applying the \
attached patch you&#39;ll get context menu in the variable view, ability to change \
format of the displayed variable (i.e. decimal, binary, hex etc) and &quot;copy value \
to clipboard&quot; command as a free bonus :)<br clear="all"> <br>-- <br>Best \
regards,<br>Konstantin.<br>

--0016367d685635beb0048bc116d4--


["kdevelop.diff" (application/octet-stream)]

commit 5e56e7623aaa0c86dffde1c9cb87816ffdeecf16
Author: Konstantin Karganov <karganov@gmail.com>
Date:   Mon Jul 19 21:17:15 2010 +0400

    Added support for changing format of displayed variables.

diff --git a/debuggers/gdb/gdbvariable.cpp b/debuggers/gdb/gdbvariable.cpp
index adec741..3e1a2c4 100644
--- a/debuggers/gdb/gdbvariable.cpp
+++ b/debuggers/gdb/gdbvariable.cpp
@@ -323,3 +323,47 @@ QString GdbVariable::enquotedExpression() const
     expr = expr.prepend('"').append('"');
     return expr;
 }
+
+
+class SetFormatHandler : public GDBCommandHandler
+{
+public:
+    SetFormatHandler(GdbVariable *var)
+        : m_variable(var)
+    {}
+
+    virtual void handle(const GDBMI::ResultRecord &r)
+    {
+        if(r.hasField("value"))
+            m_variable->setValue(r["value"].literal());
+    }
+private:
+    QPointer<GdbVariable> m_variable;
+};
+
+void GdbVariable::setFormat(format_t format)
+{
+    if(m_format==format)
+        return;
+    
+    if(childCount())
+    {
+        foreach(TreeItem* item, childItems)
+            if( GdbVariable* var=dynamic_cast<GdbVariable*>(item))
+                var->setFormat(format);
+    }
+    else
+    {
+        // FIXME: Eventually, should be a property of variable.
+        IDebugSession* is = ICore::self()->debugController()->currentSession();
+        DebugSession* s = static_cast<DebugSession*>(is);
+        s->addCommand(
+            new GDBCommand(GDBMI::VarSetFormat,
+                           QString(" \"%1\" %2 ").arg(varobj_).arg(format2str(format)),
+                           new SetFormatHandler(this)
+                           )
+                     );
+    }
+    
+    m_format=format;
+}
diff --git a/debuggers/gdb/gdbvariable.h b/debuggers/gdb/gdbvariable.h
index 2a44d8b..b4231fe 100644
--- a/debuggers/gdb/gdbvariable.h
+++ b/debuggers/gdb/gdbvariable.h
@@ -57,6 +57,7 @@ namespace KDevelop
     private: // Variable overrides
         void attachMaybe(QObject *callback, const char *callbackMethod);
         void fetchMoreChildren();
+        void setFormat(format_t format);
 
     private: // Internal
         friend class ::CreateVarobjHandler;

["kdevplatform.diff" (application/octet-stream)]

commit d94ed570973a48677eb7f418dd54c7a4a146ba53
Author: Konstantin Karganov <karganov@gmail.com>
Date:   Mon Jul 19 21:20:37 2010 +0400

    Added context menu for changing the format of displayed variable in debugger.
    Also, some refactoring of VariableWidget code performed.

diff --git a/debugger/variable/variablecollection.cpp b/debugger/variable/variablecollection.cpp
index d4844ed..72095c1 100644
--- a/debugger/variable/variablecollection.cpp
+++ b/debugger/variable/variablecollection.cpp
@@ -30,6 +30,9 @@
 #include <KTextEditor/TextHintInterface>
 #include <KTextEditor/Document>
 #include <KParts/PartManager>
+#include <QClipboard>
+#include <QApplication>
+#include <QMessageBox>
 
 #include "../../interfaces/icore.h"
 #include "../../interfaces/idocumentcontroller.h"
@@ -64,7 +67,7 @@ Variable::Variable(TreeModel* model, TreeItem* parent,
                    const QString& expression,
                    const QString& display)
   : TreeItem(model, parent),
-    inScope_(true), topLevel_(true)
+    inScope_(true), topLevel_(true), m_format(Natural)
 {
     expression_ = expression;
     // FIXME: should not duplicate the data, instead overload 'data'
@@ -117,6 +120,45 @@ void Variable::die()
     deleteLater();
 }
 
+
+Variable::format_t Variable::str2format(const QString& str)
+{
+    if(str=="Binary" || str=="binary")          return Binary;
+    if(str=="Octal" || str=="octal")            return Octal;
+    if(str=="Decimal" || str=="decimal")        return Decimal;
+    if(str=="Hexadecimal" || str=="hexadecimal")return Hexadecimal;
+
+    return Natural; // maybe most reasonable default
+}
+
+QString Variable::format2str(format_t format)
+{
+    switch(format) {
+        case Natural:       return "natural";
+        case Binary:        return "binary";
+        case Octal:         return "octal";
+        case Decimal:       return "decimal";
+        case Hexadecimal:   return "hexadecimal";
+        default:            return "";
+    }
+}
+
+void Variable::slotSetFormat()
+{
+    QObject *obj=sender();
+    if(!obj) return;
+
+    setFormat(str2format(obj->objectName())); // use sender action name to know the format
+}
+
+
+void Variable::slotCopyValueToClipboard()
+{
+    QClipboard *pCb=QApplication::clipboard();
+    QString text=itemData[1].toString();
+    pCb->setText(text);
+}
+
 QVariant Variable::data(int column, int role) const
 {
     if (column == 1 && role == Qt::ForegroundRole
diff --git a/debugger/variable/variablecollection.h b/debugger/variable/variablecollection.h
index 03f7b25..7d9d1e3 100644
--- a/debugger/variable/variablecollection.h
+++ b/debugger/variable/variablecollection.h
@@ -48,6 +48,7 @@ class VariableToolTip;
 
 class KDEVPLATFORMDEBUGGER_EXPORT Variable : public TreeItem
 {
+    Q_OBJECT
     friend class GDBDebugger::GdbTest;
 public:
 protected:
@@ -56,12 +57,16 @@ protected:
              const QString& display = "");
 
 public:
+    enum format_t { Natural, Binary, Octal, Decimal, Hexadecimal };
+    static format_t str2format(const QString& str);
+    static QString format2str(format_t format);
 
     QString expression() const;
     bool inScope() const;
     void setInScope(bool v);
     void setValue(const QString &v);
     void setTopLevel(bool v);
+    
     using TreeItem::setHasMore;
     using TreeItem::setHasMoreInitial;
     using TreeItem::appendChild;
@@ -80,10 +85,17 @@ public:
        The slot should be taking 'bool ok' parameter.  */
     virtual void attachMaybe(QObject *callback = 0, const char *callbackMethod = 0) = 0;
 
+    format_t getFormat() const { return m_format; }
+    virtual void setFormat(format_t format) =0;
+    
     void die();
 
+public slots:
+    void slotSetFormat();
+    void slotCopyValueToClipboard();
+    
 protected:
-    bool topLevel() { return topLevel_; }
+    bool topLevel() const { return topLevel_; }
 
 private: // TreeItem overrides
 
@@ -94,6 +106,9 @@ private:
     QString expression_;
     bool inScope_;
     bool topLevel_;
+    
+protected:
+    format_t m_format;
 };
 
 class KDEVPLATFORMDEBUGGER_EXPORT TooltipRoot : public TreeItem
diff --git a/debugger/variable/variablewidget.cpp b/debugger/variable/variablewidget.cpp
index a4c76ee..289e3b4 100644
--- a/debugger/variable/variablewidget.cpp
+++ b/debugger/variable/variablewidget.cpp
@@ -175,7 +175,7 @@ VariableTree::VariableTree(DebugController *controller,
     QModelIndex index = controller->variableCollection()->indexForItem(
         controller->variableCollection()->watches(), 0);
     setExpanded(index, true);
-
+    
     setupActions();
 }
 
@@ -189,49 +189,105 @@ VariableCollection* VariableTree::collection() const
 
 VariableTree::~VariableTree()
 {
+    delete m_watchDelete;
+    delete m_contextMenuTitle;
 }
 
 void VariableTree::setupActions()
 {
+    // TODO decorate this properly to make nice menu title
+    m_contextMenuTitle = new QAction(this);
+    m_contextMenuTitle->setEnabled(false);
+    
+    // make Format menu action group
+    m_formatMenu = new QMenu(i18n("&Format"), this);
+    QActionGroup *ag= new QActionGroup(m_formatMenu);
+    
+    QAction* act;
+    
+    act = new QAction(i18n("&Natural"), ag);
+    act->setData(Variable::Natural);
+    act->setShortcut(Qt::Key_N);
+    m_formatMenu->addAction(act);
+
+    act = new QAction(i18n("&Binary"), ag);
+    act->setData(Variable::Binary);
+    act->setShortcut(Qt::Key_B);
+    m_formatMenu->addAction(act);
+       
+    act = new QAction(i18n("&Octal"), ag);
+    act->setData(Variable::Octal);
+    act->setShortcut(Qt::Key_O);
+    m_formatMenu->addAction(act);
+    
+    act = new QAction(i18n("&Decimal"), ag);
+    act->setData(Variable::Decimal);
+    act->setShortcut(Qt::Key_D);
+    m_formatMenu->addAction(act);
+    
+    act = new QAction(i18n("&Hexadecimal"), ag);
+    act->setData(Variable::Hexadecimal);
+    act->setShortcut(Qt::Key_H);
+    m_formatMenu->addAction(act);
+    
+    foreach(QAction* act, m_formatMenu->actions())
+    {
+        act->setObjectName( act->text().mid(1) );   // skip first &-sign
+        act->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    }
+    
+    //act=formatMenu->addAction(i18n("&Character"));
+    
     m_watchDelete = new QAction(
-        KIcon("edit-delete"),
-        i18n( "Remove Watch Variable" ),
-        this);
+        KIcon("edit-delete"), i18n( "Remove Watch Variable" ), this);
+        
     m_watchDelete->setShortcut(Qt::Key_Delete);
     m_watchDelete->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-    connect(m_watchDelete, SIGNAL(triggered(bool)), SLOT(deleteWatch()));
-    addAction(m_watchDelete);
 }
 
-
 void VariableTree::contextMenuEvent(QContextMenuEvent* event)
 {
     QModelIndex index = indexAt(event->pos());
     if (!index.isValid())
         return;
     TreeItem* item = collection()->itemForIndex(index);
-    if (!dynamic_cast<Variable*>(item)) return;
-
-    if (dynamic_cast<Watches*>(static_cast<Variable*>(item)->parent())) {
-        QMenu popup;
-        popup.addAction(m_watchDelete);
-        popup.exec(event->globalPos());
+    Variable* var = dynamic_cast<Variable*>(item);
+    if (!var) return;
+
+    // set up menu
+    QMenu contextMenu(this->parentWidget());
+    m_contextMenuTitle->setText(var->expression());
+    contextMenu.addAction(m_contextMenuTitle);
+    contextMenu.addMenu(m_formatMenu);
+
+    // connect all format change actions to currently selected variable
+    // the slotSetFormat slot will know the action by the action object name
+    foreach(QAction* act, m_formatMenu->actions())
+    {
+        act->setCheckable(true);
+        if(act->data().toInt()==var->getFormat())
+            act->setChecked(true);
+        
+        connect(act, SIGNAL(triggered()), var, SLOT(slotSetFormat()));
     }
-}
-
 
-void VariableTree::deleteWatch()
-{
-    QModelIndexList selected = selectionModel()->selectedIndexes();
-    if (!selected.isEmpty()) {
-        TreeItem* item = collection()->itemForIndex(selected.first());
-        if (!dynamic_cast<Variable*>(item)) return;
-        if (!dynamic_cast<Watches*>(static_cast<Variable*>(item)->parent())) return;
-        static_cast<Variable*>(item)->die();
+  
+    if (dynamic_cast<Watches*>(var->parent()))
+    {
+        contextMenu.addAction(m_watchDelete);
+        connect(m_watchDelete, SIGNAL(triggered()), var, SLOT(die()));
     }
+    
+    contextMenu.addSeparator();
+    contextMenu.addAction(i18n("&Copy Value"), var, SLOT(slotCopyValueToClipboard()));
+        
+    contextMenu.exec(event->globalPos());
+    
+    // remove signal connections since the action is reused for all variables
+    foreach(QAction* act, m_formatMenu->actions())
+        disconnect(act, 0, var, 0); 
 }
 
-
 #if 0
 void VariableTree::contextMenuEvent(QContextMenuEvent* event)
 {
diff --git a/debugger/variable/variablewidget.h b/debugger/variable/variablewidget.h
index aa42cac..5fe0f84 100644
--- a/debugger/variable/variablewidget.h
+++ b/debugger/variable/variablewidget.h
@@ -17,6 +17,7 @@
 #define KDEV_VARIABLEWIDGET_H
 
 #include <QTreeView>
+#include <QAction>
 
 #include <KComboBox>
 
@@ -79,9 +80,6 @@ private:
     void setupActions();
     virtual void contextMenuEvent(QContextMenuEvent* event);
 
-private slots:
-    void deleteWatch();
-
 #if 0
 Q_SIGNALS:
     void toggleWatchpoint(const QString &varName);
@@ -102,6 +100,8 @@ private: // helper functions
     QAction* toggleWatch_;
 #endif
 private:
+    QAction *m_contextMenuTitle;
+    QMenu *m_formatMenu;
     QAction *m_watchDelete;
 };
 


-- 
KDevelop-devel mailing list
KDevelop-devel@kdevelop.org
https://barney.cs.uni-potsdam.de/mailman/listinfo/kdevelop-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic