diff -r 8cbdfbbce3a9 CMakeLists.txt
--- a/CMakeLists.txt	Mon Jul 30 00:41:53 2012 +0100
+++ b/CMakeLists.txt	Sat Aug 18 15:45:54 2012 +0100
@@ -15,7 +15,7 @@
 
 set(CNOID_MAJOR_VERSION 1) 
 set(CNOID_MINOR_VERSION 3)
-set(CNOID_PATCH_VERSION 0)
+set(CNOID_PATCH_VERSION 1)
 set(CNOID_VERSION ${CNOID_MAJOR_VERSION}.${CNOID_MINOR_VERSION})
 set(CNOID_FULL_VERSION ${CNOID_MAJOR_VERSION}.${CNOID_MINOR_VERSION}.${CNOID_PATCH_VERSION})
 
diff -r 8cbdfbbce3a9 src/Base/ItemManager.cpp
--- a/src/Base/ItemManager.cpp	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/Base/ItemManager.cpp	Sat Aug 18 15:45:54 2012 +0100
@@ -886,6 +886,7 @@
     QFileDialog dialog(MainWindow::instance());
     dialog.setWindowTitle(str(fmt(_("Save %1% as")) % itemLabel).c_str());
     dialog.setFileMode(QFileDialog::AnyFile);
+    dialog.setAcceptMode(QFileDialog::AcceptSave);
     dialog.setViewMode(QFileDialog::List);
     dialog.setLabelText(QFileDialog::Accept, _("Save"));
     dialog.setLabelText(QFileDialog::Reject, _("Cancel"));
@@ -1070,28 +1071,39 @@
 
 void ItemManagerImpl::onReloadSelectedItemsActivated()
 {
-    ItemList<Item> selectedItems = ItemTreeView::mainInstance()->selectedItems<Item>();
-    for(size_t i=0; i < selectedItems.size(); ++i){
+    ItemList<Item> selected = ItemTreeView::mainInstance()->selectedItems<Item>();
+    ItemManager::reloadItems(selected);
+}
 
-        ItemPtr item = selectedItems[i];
 
-        if(!item->lastAccessedFilePath_.empty() && !item->lastAccessedFileFormatId_.empty()){
+void ItemManager::reloadItems(ItemList<Item>& items)
+{
+    for(size_t i=0; i < items.size(); ++i){
+
+        ItemPtr item = items[i];
+
+        if(item->parentItem() && !item->isSubItem() &&
+           !item->lastAccessedFilePath().empty() && !item->lastAccessedFileFormatId().empty()){
 
             ItemPtr reloaded = item->duplicate();
             if(reloaded){
-                if(reloaded->load(item->lastAccessedFilePath_, item->lastAccessedFileFormatId_)){
+                if(reloaded->load(item->lastAccessedFilePath(), item->parentItem(), item->lastAccessedFileFormatId())){
 
                     item->parentItem()->insertChildItem(reloaded, item);
                     
-                    // move childrent to the reload item
+                    // move children to the reload item
                     ItemPtr child = item->childItem();
                     while(child){
                         ItemPtr nextChild = child->nextItem();
-                        reloaded->addChildItem(child);
+                        if(!child->isSubItem()){
+                            child->detachFromParentItem();
+                            reloaded->addChildItem(child);
+                        }
                         child = nextChild;
                     }
+                    reloaded->assign(item.get());
+                    messageView->putln(format(_("\"%1%\" has been reloaded.")) % reloaded->name());
                     
-                    reloaded->assign(item.get());
                     item->detachFromParentItem();
                 }
             }
diff -r 8cbdfbbce3a9 src/Base/ItemManager.h
--- a/src/Base/ItemManager.h	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/Base/ItemManager.h	Sat Aug 18 15:45:54 2012 +0100
@@ -186,6 +186,8 @@
 
         void addMenuItemToImport(const std::string& caption, boost::function<void()> slot);
 
+        static void reloadItems(ItemList<Item>& items);
+
       private:
         
         // The following static functions are called from functions in the Item class
diff -r 8cbdfbbce3a9 src/Base/ItemPropertyView.cpp
--- a/src/Base/ItemPropertyView.cpp	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/Base/ItemPropertyView.cpp	Sat Aug 18 15:45:54 2012 +0100
@@ -107,7 +107,7 @@
         CustomizedTableWidget(QWidget* parent) : QTableWidget(parent) { }
         
         PropertyItem* itemFromIndex(const QModelIndex& index) const {
-            return static_cast<PropertyItem*>(QTableWidget::itemFromIndex(index));
+            return dynamic_cast<PropertyItem*>(QTableWidget::itemFromIndex(index));
         }
     };
 
@@ -122,23 +122,26 @@
             : tableWidget(tableWidget) { decimals = 2; }
         
         virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const {
+
             QWidget* editor = QStyledItemDelegate::createEditor(parent, option, index);
-
-            if(QSpinBox* spinBox = dynamic_cast<QSpinBox*>(editor)){
-                ValueVariant& value = tableWidget->itemFromIndex(index)->value;
-                if(value.which() == TYPE_INT){
-                    Int& v = get<Int>(value);
-                    spinBox->setRange(v.min, v.max);
-                }
-            } else if(QDoubleSpinBox* doubleSpinBox = dynamic_cast<QDoubleSpinBox*>(editor)){
-                ValueVariant& value = tableWidget->itemFromIndex(index)->value;
-                if(value.which() == TYPE_DOUBLE){
-                    Double& v = get<Double>(value);
-                    if(v.decimals >= 0){
-                        doubleSpinBox->setDecimals(v.decimals);
-                        doubleSpinBox->setSingleStep(pow(10.0, -v.decimals));
+            PropertyItem* item = tableWidget->itemFromIndex(index);
+            if(item){
+                if(QSpinBox* spinBox = dynamic_cast<QSpinBox*>(editor)){
+                    ValueVariant& value = item->value;
+                    if(value.which() == TYPE_INT){
+                        Int& v = get<Int>(value);
+                        spinBox->setRange(v.min, v.max);
                     }
-                    doubleSpinBox->setRange(v.min, v.max);
+                } else if(QDoubleSpinBox* doubleSpinBox = dynamic_cast<QDoubleSpinBox*>(editor)){
+                    ValueVariant& value = item->value;
+                    if(value.which() == TYPE_DOUBLE){
+                        Double& v = get<Double>(value);
+                        if(v.decimals >= 0){
+                            doubleSpinBox->setDecimals(v.decimals);
+                            doubleSpinBox->setSingleStep(pow(10.0, -v.decimals));
+                        }
+                        doubleSpinBox->setRange(v.min, v.max);
+                    }
                 }
             }
             return editor;
@@ -154,7 +157,7 @@
         void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const {
             
             PropertyItem* item = tableWidget->itemFromIndex(index);
-            if(item->value.which() == TYPE_DOUBLE){
+            if(item && item->value.which() == TYPE_DOUBLE){
                 int& d = const_cast<int&>(decimals);
                 d = get<Double>(item->value).decimals;
             }
@@ -162,7 +165,6 @@
         }
 
     };
-    
 }
 
 
diff -r 8cbdfbbce3a9 src/Base/ItemTreeView.cpp
--- a/src/Base/ItemTreeView.cpp	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/Base/ItemTreeView.cpp	Sat Aug 18 15:45:54 2012 +0100
@@ -6,6 +6,7 @@
 #include "Item.h"
 #include "RootItem.h"
 #include "ExtensionManager.h"
+#include "ItemManager.h"
 #include "MenuManager.h"
 #include "Archive.h"
 #include "TreeWidget.h"
@@ -79,6 +80,8 @@
         bool isDropping;
 
         virtual void mousePressEvent(QMouseEvent* event);
+        virtual void keyPressEvent(QKeyEvent* event);
+        
         ItvItem* getItvItem(Item* item);
         ItvItem* getOrCreateItvItem(Item* item);
         void onSubTreeAdded(Item* item);
@@ -307,6 +310,28 @@
 }
 
 
+void ItemTreeViewImpl::keyPressEvent(QKeyEvent* event)
+{
+    bool processed = false;
+    
+    if(event->modifiers() & Qt::ControlModifier){
+        processed = true;
+        switch(event->key()){
+        case Qt::Key_R:
+            ItemManager::reloadItems(selectedItemList);
+            break;
+        defaut:
+            processed = false;
+            break;
+        }
+    }
+
+    if(!processed){
+        TreeWidget::keyPressEvent(event);
+    }
+}
+
+
 ItvItem* ItemTreeViewImpl::getItvItem(Item* item)
 {
     ItvItem* itvItem = 0;
diff -r 8cbdfbbce3a9 src/Base/MainWindow.cpp
--- a/src/Base/MainWindow.cpp	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/Base/MainWindow.cpp	Sat Aug 18 15:45:54 2012 +0100
@@ -948,6 +948,7 @@
     QFileDialog dialog(self);
     dialog.setWindowTitle(_("Save a layout"));
     dialog.setFileMode(QFileDialog::AnyFile);
+    dialog.setAcceptMode(QFileDialog::AcceptSave);
     dialog.setViewMode(QFileDialog::List);
     dialog.setLabelText(QFileDialog::Accept, _("Save"));
     dialog.setLabelText(QFileDialog::Reject, _("Cancel"));
diff -r 8cbdfbbce3a9 src/Base/PluginManager.cpp
--- a/src/Base/PluginManager.cpp	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/Base/PluginManager.cpp	Sat Aug 18 15:45:54 2012 +0100
@@ -226,10 +226,24 @@
     if(filesystem::exists(pluginPath)){
        if(filesystem::is_directory(pluginPath)){
            if(!isRecursive){
+
+               static const bool doSorting = false;
                filesystem::directory_iterator end;
-               for(filesystem::directory_iterator it(pluginPath); it != end; ++it){
-                   const filesystem::path& filepath = *it;
-                   scanPluginFiles(getNativePathString(filepath), true);
+               if(doSorting){
+                   list<string> paths;
+                   for(filesystem::directory_iterator it(pluginPath); it != end; ++it){
+                       const filesystem::path& filepath = *it;
+                       paths.push_back(getNativePathString(*it));
+                   }
+                   paths.sort();
+                   for(list<string>::iterator p = paths.begin(); p != paths.end(); ++p){
+                       scanPluginFiles(*p, true);
+                   }
+               } else {
+                   for(filesystem::directory_iterator it(pluginPath); it != end; ++it){
+                       const filesystem::path& filepath = *it;
+                       scanPluginFiles(getNativePathString(filepath), true);
+                   }
                }
            }
        } else {
@@ -394,7 +408,16 @@
                 }
             }
 
-            if(requisitesActive){
+            if(!requisitesActive){
+
+                /*
+                if(info->dll.unload()){
+                    info->status = PluginManager::NOT_LOADED;
+                    info->requisites.clear();
+                    mv->putln(fmt(_("Plugin file \"%1%\" is unloaded.")) % info->pathString);                }
+                */
+
+            } else {
 
                 info->areAllRequisitiesResolved = true;
                 
diff -r 8cbdfbbce3a9 src/Base/ProjectManager.cpp
--- a/src/Base/ProjectManager.cpp	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/Base/ProjectManager.cpp	Sat Aug 18 15:45:54 2012 +0100
@@ -421,6 +421,7 @@
     QFileDialog dialog(MainWindow::instance());
     dialog.setWindowTitle(_("Save a choreonoid project file"));
     dialog.setFileMode(QFileDialog::AnyFile);
+    dialog.setAcceptMode(QFileDialog::AcceptSave);
     dialog.setViewMode(QFileDialog::List);
     dialog.setLabelText(QFileDialog::Accept, _("Save"));
     dialog.setLabelText(QFileDialog::Reject, _("Cancel"));
diff -r 8cbdfbbce3a9 src/Base/SceneView.cpp
--- a/src/Base/SceneView.cpp	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/Base/SceneView.cpp	Sat Aug 18 15:45:54 2012 +0100
@@ -1870,6 +1870,7 @@
     QFileDialog dialog(MainWindow::instance());
     dialog.setWindowTitle(_("Save an image of the scene view"));
     dialog.setFileMode(QFileDialog::AnyFile);
+    dialog.setAcceptMode(QFileDialog::AcceptSave);
     dialog.setViewMode(QFileDialog::List);
     dialog.setLabelText(QFileDialog::Accept, _("Save"));
     dialog.setLabelText(QFileDialog::Reject, _("Cancel"));
diff -r 8cbdfbbce3a9 src/Body/Body.cpp
--- a/src/Body/Body.cpp	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/Body/Body.cpp	Sat Aug 18 15:45:54 2012 +0100
@@ -247,8 +247,7 @@
     for(size_t i=0; i < jointIdToLinkArray.size(); ++i){
         if(!jointIdToLinkArray[i]){
             jointIdToLinkArray[i] = createEmptyJoint(i);
-            std::cerr << "Warning: Model " << modelName_ <<
-                " has empty joint ID in the valid IDs." << std::endl;
+            // throw an exeption?
         }
     }
 
@@ -391,9 +390,7 @@
         }
         sensor = sensors[id];
         if(sensor){
-            std::cerr << "duplicated sensor Id is specified(id = "
-                      << id << ", name = " << name << ")" << std::endl;
-                
+            // Warning: duplicated sensor Id is specified. Is it better to throw an exeption?
             nameToSensorMap.erase(sensor->name);
         } else {
             sensor = Sensor::create(sensorType);
@@ -410,25 +407,6 @@
     return sensor;
 }
 
-void Body::addSensor(Sensor* sensor, int sensorType, int id ){
-    if(sensorType < Sensor::NUM_SENSOR_TYPES && id >= 0){
-        SensorArray& sensors = allSensors[sensorType];
-        int n = sensors.size();
-        if(id >= n){
-            sensors.resize(id + 1, 0);
-        }
-        Sensor* sameId = sensors[id];
-        if(sameId){
-            std::cerr << "duplicated sensor Id is specified(id = "
-                      << id << ", name = " << sensor->name << ")" << std::endl;
-                
-            nameToSensorMap.erase(sameId->name);
-        }
-        sensors[id] = sensor;
-        nameToSensorMap[sensor->name] = sensor;
-    }
-}
-
 
 void Body::clearSensorValues()
 {
diff -r 8cbdfbbce3a9 src/Body/Body.h
--- a/src/Body/Body.h	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/Body/Body.h	Sat Aug 18 15:45:54 2012 +0100
@@ -147,8 +147,6 @@
         // sensor access methods
         Sensor* createSensor(Link* link, int sensorType, int id, const std::string& name);
 
-        void addSensor(Sensor* sensor, int sensorType, int id );
-
         inline Sensor* sensor(int sensorType, int sensorId) const {
             return allSensors[sensorType][sensorId];
         }
diff -r 8cbdfbbce3a9 src/Body/BodyLoader.cpp
--- a/src/Body/BodyLoader.cpp	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/Body/BodyLoader.cpp	Sat Aug 18 15:45:54 2012 +0100
@@ -17,6 +17,7 @@
 #include <boost/bind.hpp>
 #include <boost/function.hpp>
 #include <boost/format.hpp>
+#include <boost/dynamic_bitset.hpp>
 
 using namespace std;
 using namespace boost;
@@ -42,6 +43,8 @@
         bool createColdetModel;
         string errorMessage;
         MappingPtr info;
+        dynamic_bitset<> validJointIdSet;
+        int numValidJointIds;
 
         boost::signal<void(const std::string& message)> sigMessage;
 
@@ -229,6 +232,8 @@
 {
     body = 0;
     info = 0;
+    validJointIdSet.clear();
+    numValidJointIds = 0;
     errorMessage.clear();
     
     filesystem::path orgpath(filename);
@@ -307,6 +312,16 @@
     
 	Matrix3 Rs = Matrix3::Identity();
 	Link* rootLink = createLink(rootJointNodeSet, Rs);
+
+        // Warn empty joint ids
+        if(numValidJointIds < validJointIdSet.size()){
+            for(int i=0; i < validJointIdSet.size(); ++i){
+                if(!validJointIdSet[i]){
+                    sigMessage(str(format("Warning: Joint ID %1% is not specified.\n") % i));
+                }
+            }
+        }
+        
 	body->setRootLink(rootLink);
 
 	VRMLProtoFieldMap& f = rootJointNodeSet->jointNode->fields;
@@ -369,6 +384,17 @@
     VRMLProtoFieldMap& jf = jointNode->fields;
 
     copyVRMLfield(jf["jointId"], link->jointId);
+    if(link->jointId >= 0){
+        if(link->jointId >= validJointIdSet.size()){
+            validJointIdSet.resize(link->jointId + 1);
+        }
+        if(!validJointIdSet[link->jointId]){
+            ++numValidJointIds;
+            validJointIdSet.set(link->jointId);
+        } else {
+            sigMessage(str(format("Warning: Joint ID %1% is duplicated.\n") % link->jointId));
+        }
+    }
 
     Vector3 b;
     copyVRMLfield(jf["translation"], b);
@@ -538,6 +564,12 @@
 
             } else {
 		sensorType = p->second;
+
+                if(id < body->numSensors(sensorType) && body->sensor(sensorType, id)){
+                    sigMessage(str(format("Warning: Same sensor ID %1% is specified for %2% and %3%.")
+                                   % id % body->sensor(sensorType, id)->name % name));
+                }
+
                 Sensor* sensor = body->createSensor(link, sensorType, id, name);
                 if(sensor){
                     Vector3 p;
diff -r 8cbdfbbce3a9 src/Body/Link.h
--- a/src/Body/Link.h	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/Body/Link.h	Sat Aug 18 15:45:54 2012 +0100
@@ -44,7 +44,7 @@
         inline bool isRoot() { return !parent; }
 
         inline void setAttitude(const Matrix3& R) { this->R = R * Rs.transpose(); }
-        inline Matrix3 attitude() { return this->R * Rs; }
+        inline Matrix3 attitude() const { return this->R * Rs; }
         inline Matrix3 calcRfromAttitude(const Matrix3& R) { return R * Rs.transpose(); }
 
         /**
@@ -61,7 +61,7 @@
         /**
            @deprecated use attitude().
         */
-        inline Matrix3 segmentAttitude() { return this->R * Rs; }
+        inline Matrix3 segmentAttitude() const { return this->R * Rs; }
 
         void updateColdetModelPosition() {
             coldetModel->setPosition(R, p);
diff -r 8cbdfbbce3a9 src/BodyPlugin/po/ja.po
--- a/src/BodyPlugin/po/ja.po	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/BodyPlugin/po/ja.po	Sat Aug 18 15:45:54 2012 +0100
@@ -725,11 +725,11 @@
 
 #: SimulationBar.cpp:38
 msgid "Store body positions to the initial world state"
-msgstr ""
+msgstr "現在の状態をワールド初期状態に設定"
 
 #: SimulationBar.cpp:42
 msgid "Restore body positions from the initial world state"
-msgstr ""
+msgstr "ワールド初期状態の呼び出し"
 
 #: SimulationBar.cpp:47
 msgid "Start simulation from the beginning"
diff -r 8cbdfbbce3a9 src/PoseSeqPlugin/PoseSeqViewBase.cpp
--- a/src/PoseSeqPlugin/PoseSeqViewBase.cpp	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/PoseSeqPlugin/PoseSeqViewBase.cpp	Sat Aug 18 15:45:54 2012 +0100
@@ -861,8 +861,10 @@
     body = 0;
     selectedPoseIters.clear();
 
-    if(poseSeqItem){
+    if(!poseSeqItem){
+        linkTreeWidget->setBodyItem(0);
 
+    } else {
         poseSeqConnections.add(
             poseSeqItem->sigNameChanged().connect(
                 bind(&PoseSeqViewBase::setCurrentItemName, this, poseSeqItem)));
diff -r 8cbdfbbce3a9 src/Util/Array2D.h
--- a/src/Util/Array2D.h	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/Util/Array2D.h	Sat Aug 18 15:45:54 2012 +0100
@@ -21,6 +21,7 @@
         typedef typename std::vector<ElementType, Allocator> Container;
         typedef typename Container::iterator iterator;
 
+        //! \todo make const version of this class
         class Row
         {
             typename Container::iterator top;
@@ -44,7 +45,7 @@
                 top = rhs.top;
                 end_ = rhs.end_;
                 size_ = rhs.size_;
-				return *this;
+                return *this;
             }
             
             int size() const {
@@ -68,6 +69,7 @@
             }
         };
 
+        //! \todo make const version of this class
         class Column
         {
         public:
@@ -108,8 +110,8 @@
 
         public:
 
-            Column(Array2D<ElementType, Allocator>& owner, int part) {
-                top = owner.container.begin() + part;
+            Column(const Array2D<ElementType, Allocator>& owner, int part) {
+                top = (const_cast<Array2D<ElementType, Allocator>&>(owner)).container.begin() + part;
                 this->part = part;
                 colSize = owner.colSize_;
                 size_ = owner.rowSize_;
@@ -214,10 +216,18 @@
             return Row(*this, rowIndex);
         }
 
+        const Row row(int rowIndex) const {
+            return Row(*this, rowIndex);
+        }
+
         Column column(int colIndex) {
             return Column(*this, colIndex);
         }
 
+        const Column column(int colIndex) const {
+            return Column(*this, colIndex);
+        }
+
         iterator begin() {
             return container.begin();
         }
diff -r 8cbdfbbce3a9 src/Util/ExecutablePath.cpp
--- a/src/Util/ExecutablePath.cpp	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/Util/ExecutablePath.cpp	Sat Aug 18 15:45:54 2012 +0100
@@ -79,8 +79,14 @@
         if(_NSGetExecutablePath(buf, &n) == 0){
             executablePath_ = buf;
         }
+        
+        filesystem::path path;
+        // remove dot from a path like bin/./choreonoid
+        makePathCompact(filesystem::path(executablePath_), path);
+        //filesystem::path path = filesystem::canonical(filesystem::path(executablePath_));
+#else
+        filesystem::path path(executablePath_);
 #endif
-        filesystem::path path(executablePath_);
 
         filesystem::path topPath = path.parent_path().parent_path();
         executableTopDirectory_ = topPath.string();
diff -r 8cbdfbbce3a9 src/Util/MultiSeq.h
--- a/src/Util/MultiSeq.h	Mon Jul 30 00:41:53 2012 +0100
+++ b/src/Util/MultiSeq.h	Sat Aug 18 15:45:54 2012 +0100
@@ -104,13 +104,6 @@
             return Array2DType::colSize();
         }
 
-        /**
-           @if jp
-           シーケンスの時間長を返す。
-           @note この時間 *未満* の時間については有効なデータが存在する。
-           この時間のデータは存在しないので、そのようなアクセスしてはいけない。
-           @endif
-        */
         inline double timeLength() const {
             return numFrames() / frameRate();
         }
@@ -122,7 +115,11 @@
         inline double timeOfFrame(int frame) const {
             return (frame / frameRate_);
         }
-            
+
+        inline const Part part(int index) const {
+            return Array2DType::column(index);
+        }
+
         inline Part part(int index) {
             return Array2DType::column(index);
         }
@@ -131,6 +128,10 @@
             return Array2DType::row(index);
         }
 
+        inline const Frame frame(int index) const {
+            return Array2DType::row(index);
+        }
+
     protected:
 
         double frameRate_;
