From 2fe743cc70a9e7a9a87bba5e4b16c9edf5f76efd Mon Sep 17 00:00:00 2001
From: Marco Biasini <marco.biasini@unibas.ch>
Date: Tue, 5 Mar 2013 11:53:43 +0100
Subject: [PATCH] implement remote loader logic in Python

The code becomes much simpler, cleaner and fixes as weird crash
with Qt 4.8
---
 modules/gui/pymod/CMakeLists.txt              |   7 +-
 modules/gui/pymod/dng/init.py                 |   5 +-
 modules/gui/pymod/dng/menu.py                 |   2 -
 modules/gui/pymod/export_file_loader.cc       |  36 ---
 .../gui/pymod/export_remote_site_loader.cc    |  76 -------
 modules/gui/pymod/init_menubar.py             |  14 --
 modules/gui/pymod/scene/file_loader.py        |   3 +-
 .../gui/pymod/scene/loader_info_handler.py    |  60 -----
 modules/gui/pymod/scene/loader_list_model.py  | 156 -------------
 .../gui/pymod/scene/loader_manager_widget.py  | 199 -----------------
 modules/gui/pymod/scene/remote.py             |  78 +++++++
 modules/gui/pymod/wrap_gui.cc                 |   2 -
 modules/gui/src/CMakeLists.txt                |   7 -
 modules/gui/src/file_loader.cc                |  31 ---
 modules/gui/src/file_loader.hh                |   5 -
 modules/gui/src/loader_manager.cc             | 112 ----------
 modules/gui/src/loader_manager.hh             |  59 -----
 modules/gui/src/remote_loader.cc              | 208 ------------------
 modules/io/pymod/CMakeLists.txt               |   2 +-
 modules/io/pymod/__init__.py                  |  33 +--
 modules/io/pymod/remote.py                    |  93 ++++++++
 21 files changed, 181 insertions(+), 1007 deletions(-)
 delete mode 100644 modules/gui/pymod/export_remote_site_loader.cc
 delete mode 100644 modules/gui/pymod/scene/loader_info_handler.py
 delete mode 100644 modules/gui/pymod/scene/loader_list_model.py
 delete mode 100644 modules/gui/pymod/scene/loader_manager_widget.py
 create mode 100644 modules/gui/pymod/scene/remote.py
 delete mode 100644 modules/gui/src/loader_manager.cc
 delete mode 100644 modules/gui/src/loader_manager.hh
 delete mode 100644 modules/gui/src/remote_loader.cc
 create mode 100644 modules/io/pymod/remote.py

diff --git a/modules/gui/pymod/CMakeLists.txt b/modules/gui/pymod/CMakeLists.txt
index 522f66443..87a9c6337 100644
--- a/modules/gui/pymod/CMakeLists.txt
+++ b/modules/gui/pymod/CMakeLists.txt
@@ -6,7 +6,6 @@ set(OST_GUI_PYMOD_SOURCES
   export_tool.cc
   export_py_shell.cc
   export_gosty.cc
-  export_remote_site_loader.cc
   export_scene_win.cc
   export_sequence_viewer.cc
   export_perspective.cc
@@ -37,6 +36,7 @@ init_inspector.py
 inspector_widget.py
 map_level_widget.py
 preset.py
+remote.py
 preset_editor_list_model.py
 preset_editor_widget.py
 preset_info_handler.py
@@ -54,11 +54,6 @@ trace_widget.py
 tube_widget.py
 uniform_color_widget.py
 visibility_op.py
-file_loader.py
-loader_info_handler.py
-loader_list_model.py
-loader_manager_widget.py
-immutable_loader_info_handler.py
 line_trace_widget.py
 wireframe_widget.py
 query_editor.py
diff --git a/modules/gui/pymod/dng/init.py b/modules/gui/pymod/dng/init.py
index e2338deed..ffe73d8b7 100644
--- a/modules/gui/pymod/dng/init.py
+++ b/modules/gui/pymod/dng/init.py
@@ -23,6 +23,8 @@ from ost.gui.init_context_menu import _InitContextMenu
 from ost.gui.init_splash import _InitSplash
 from ost.gui.dng import termuse
 from ost.gui.dng import superpositiondialog
+from ost.gui.scene.remote import RemoteLoader
+
 import ost.gui.dng.menu
 from PyQt4.QtGui import *
 def _my_exit(code):
@@ -56,7 +58,6 @@ def _InitPanels(app):
   panels = app.perspective.panels
   panels.AddWidgetToPool('ost.gui.FileBrowser', -1)
   panels.AddWidgetToPool('ost.gui.PythonShell', 1)
-  panels.AddWidgetToPool('ost.gui.RemoteLoader', -1)
   panels.AddWidgetToPool('ost.gui.SceneWin', 1)
   panels.AddWidgetToPool('ost.gui.SequenceViewer', 1)
   panels.AddWidgetToPool('ost.gui.MessageWidget', 1)
@@ -64,8 +65,6 @@ def _InitPanels(app):
     panels.AddWidget(gui.PanelPosition.LEFT_PANEL, app.scene_win)
     panels.AddWidgetByName(gui.PanelPosition.LEFT_PANEL, 
                            'ost.gui.FileBrowser', False)    
-    panels.AddWidgetByName(gui.PanelPosition.LEFT_PANEL, 
-                           'ost.gui.RemoteLoader', False)
     panels.AddWidget(gui.PanelPosition.BOTTOM_PANEL, app.seq_viewer)
     panels.AddWidget(gui.PanelPosition.BOTTOM_PANEL, app.py_shell)
     panels.AddWidget(gui.PanelPosition.RIGHT_PANEL, app.message_widget)
diff --git a/modules/gui/pymod/dng/menu.py b/modules/gui/pymod/dng/menu.py
index 75d2ae2ba..800c3f805 100644
--- a/modules/gui/pymod/dng/menu.py
+++ b/modules/gui/pymod/dng/menu.py
@@ -2,7 +2,6 @@ from PyQt4.QtCore import *
 from PyQt4.QtGui import *
 from ost import *
 from ost import gui
-from ost.gui.scene.loader_manager_widget import LoaderManagerWidget
 from ost.gui.init_splash import _InitSplash
 from ost.gui.dng import termuse
 from ost.gui.dng import superpositiondialog
@@ -204,7 +203,6 @@ class WindowMenu(QMenu):
   def __init__(self, parent=None):
     QMenu.__init__(self, parent)
     self.setTitle('Window')
-    self.loader_manager=LoaderManagerWidget()
     gosty=gui.GostyApp.Instance()
     QObject.connect(self, SIGNAL('aboutToShow()'), self._AboutToShow)
     inspector_visible=gosty.GetWidget('InspectorDialog').isVisible()
diff --git a/modules/gui/pymod/export_file_loader.cc b/modules/gui/pymod/export_file_loader.cc
index ab978f09a..b39d6dadd 100644
--- a/modules/gui/pymod/export_file_loader.cc
+++ b/modules/gui/pymod/export_file_loader.cc
@@ -24,7 +24,6 @@ using namespace boost::python;
 #include <QString>
 
 #include <ost/gui/file_loader.hh>
-#include <ost/gui/loader_manager.hh>
 
 using namespace ost;
 using namespace ost::gui;
@@ -41,48 +40,13 @@ void load_object_b(const QString& file_name, const QString& selection)
   FileLoader::LoadObject(file_name, selection);
 }
 
-void load_from_site_a(const QString& id)
-{
-  FileLoader::LoadFrom(id);
-}
-
-void load_from_site_b(const QString& id, const QString& site)
-{
-  FileLoader::LoadFrom(id,site);
-}
-
-void load_from_site_c(const QString& id, const QString& site, const QString& selection)
-{
-  FileLoader::LoadFrom(id,site,selection);
-}
-
-void add_remote_site_loader(LoaderManager* loader_manager, const QString& site, RemoteSiteLoader* site_loader){
-  loader_manager->AddRemoteSiteLoader(site,site_loader);
-}
-
 }
 
 void export_FileLoader()
 {
-  class_<LoaderManager, LoaderManagerPtr, boost::noncopyable>("LoaderManager", no_init)
-    .def("GetSiteLoaderIdents", &LoaderManager::GetSiteLoaderIdents)
-    .def("AddRemoteSiteLoader", &add_remote_site_loader)
-    .def("RemoveRemoteSiteLoader", &LoaderManager::RemoveRemoteSiteLoader)
-    .def("SetDefaultRemoteSiteIdent", &LoaderManager::SetDefaultRemoteSiteIdent)
-    .def("GetDefaultRemoteSiteIdent", &LoaderManager::GetDefaultRemoteSiteIdent)
-  ;
-
   class_<FileLoader, boost::noncopyable>("FileLoader", no_init)
     .def("LoadObject", &load_object_a)
     .def("LoadObject", &load_object_b)
     .staticmethod("LoadObject")
-    .def("LoadFrom", &load_from_site_a)
-    .def("LoadFrom", &load_from_site_b)
-    .def("LoadFrom", &load_from_site_c)
-    .staticmethod("LoadFrom")
-    .def("GetSiteLoaderIdents", &FileLoader::GetSiteLoaderIdents)
-    .staticmethod("GetSiteLoaderIdents")
-    .def("GetLoaderManager", &FileLoader::GetLoaderManager)
-    .staticmethod("GetLoaderManager")
   ;
 }
diff --git a/modules/gui/pymod/export_remote_site_loader.cc b/modules/gui/pymod/export_remote_site_loader.cc
deleted file mode 100644
index 80ad57049..000000000
--- a/modules/gui/pymod/export_remote_site_loader.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-
-#include <boost/python.hpp>
-#include <string>
-
-
-#include <ost/gui/remote_site_loader.hh>
-#include <boost/python/register_ptr_to_python.hpp>
-#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
-
-#include "sip_handler.hh"
-
-using namespace ost;
-using namespace ost::gui;
-using namespace boost::python;
-
-struct WrappedRemoteSiteLoader : public RemoteSiteLoader
-{
-    WrappedRemoteSiteLoader(PyObject *p):
-        RemoteSiteLoader(), self(p)
-    { }
-
-    virtual void LoadById(const QString& id, const QString& selection=QString()){
-       return call_method<void, std::string>(self, "LoadById", id.toStdString(), selection.toStdString());
-    }
-
-    virtual QString GetRemoteSiteName(){
-      return call_method<QString>(self, "GetRemoteSiteName");
-    }
-
-    virtual bool IsImg() const{
-      return call_method<bool>(self, "IsImg");
-    }
-
-    virtual QNetworkReply* ById(const QString& id, const QString& selection=QString()){
-      object obj = call_method<object, std::string, std::string>(self, "ById", id.toStdString(), selection.toStdString());
-      QNetworkReply* network_reply= get_cpp_qobject<QNetworkReply>(obj);
-      if(network_reply){
-        return network_reply;
-      }
-      return NULL;
-    }
-
- private:
-    PyObject* self;
-};
-
-void export_RemoteSiteLoader()
-{
-  class_<RemoteSiteLoader, WrappedRemoteSiteLoader, boost::noncopyable>("RemoteSiteLoader")
-    .def("LoadById",&WrappedRemoteSiteLoader::LoadById)
-    .def("GetRemoteSiteName", &WrappedRemoteSiteLoader::GetRemoteSiteName)
-    .def("IsImg", &WrappedRemoteSiteLoader::IsImg)
-  ;
-
-}
-
-
-
diff --git a/modules/gui/pymod/init_menubar.py b/modules/gui/pymod/init_menubar.py
index cc8dd3b61..761e483bb 100644
--- a/modules/gui/pymod/init_menubar.py
+++ b/modules/gui/pymod/init_menubar.py
@@ -25,8 +25,6 @@ import ost
 
 from PyQt4 import QtCore, QtGui
 from ost.gui import FileLoader
-from ost.gui.scene.file_loader import GenericLoader
-from ost.gui.scene.loader_manager_widget import LoaderManagerWidget
 from ost.gui.init_splash import _InitSplash
 from ost.gui.dng import termuse
 class InitMenuBar(QtCore.QObject):
@@ -74,15 +72,6 @@ class InitMenuBar(QtCore.QObject):
     self.connect(reset, QtCore.SIGNAL('triggered()'), self.ResetView)
     window.addAction(reset)
     
-    #Options
-    #Add file loader to menu
-    loader_manager = QtGui.QAction('File &Loader', self)
-    loader_manager.setStatusTip('Loader Manager')
-    self.connect(loader_manager, QtCore.SIGNAL('triggered()'), self.LoaderManager)
-    options.addAction(loader_manager)
-    
-    self.loader_manager = LoaderManagerWidget()
-    
   def Exit(self):
     reply = QtGui.QMessageBox()
     reply.addButton(QtGui.QMessageBox.Yes)
@@ -93,9 +82,6 @@ class InitMenuBar(QtCore.QObject):
     if(QtCore.QFileInfo(filename).isFile()):
       FileLoader.LoadObject(str(filename))
 
-  def LoaderManager(self):
-    self.loader_manager.exec_()
-  
   def OpenDocs(self):
     QtGui.QDesktopServices.openUrl(QtCore.QUrl("http://www.openstructure.org/docs/"))
     
diff --git a/modules/gui/pymod/scene/file_loader.py b/modules/gui/pymod/scene/file_loader.py
index ba7efb375..a0acf4140 100644
--- a/modules/gui/pymod/scene/file_loader.py
+++ b/modules/gui/pymod/scene/file_loader.py
@@ -26,7 +26,7 @@ import re
 from PyQt4 import QtCore, QtGui, QtNetwork
 from ost.gui import FileLoader
 
-
+"""
 class BaseRemoteLoader(gui.RemoteSiteLoader):
   def __init__(self):
     gui.RemoteSiteLoader.__init__(self)
@@ -195,3 +195,4 @@ class GenericLoader(BaseRemoteLoader):
       default = bool(int(group.GetAttribute(GenericLoader.DEFAULT_ATTRIBUTE_NAME)))
 
     return GenericLoader(name, url, up_case, file_type, tmp_url, img, default)
+"""
diff --git a/modules/gui/pymod/scene/loader_info_handler.py b/modules/gui/pymod/scene/loader_info_handler.py
deleted file mode 100644
index 079620ecc..000000000
--- a/modules/gui/pymod/scene/loader_info_handler.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#------------------------------------------------------------------------------
-# This file is part of the OpenStructure project <www.openstructure.org>
-#
-# Copyright (C) 2008-2011 by the OpenStructure authors
-#
-# This library is free software; you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation; either version 3.0 of the License, or (at your option)
-# any later version.
-# This library is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this library; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-#------------------------------------------------------------------------------
-# -*- coding: utf-8 -*-
-
-from ost import gui
-from ost import gfx
-from ost import info
-from PyQt4 import QtCore, QtGui
-from immutable_loader_info_handler import ImmutableLoaderInfoHandler
-
-#Generic Loader Info Handler
-class LoaderInfoHandler(ImmutableLoaderInfoHandler):
-  
-  def __init__(self, file_name):    
-    ImmutableLoaderInfoHandler.__init__(self, file_name)
-  
-  def StoreLoader(self,name, loader):
-    group = self.loaders_.CreateGroup(ImmutableLoaderInfoHandler.LOADER_GROUP_NAME)
-    group.SetAttribute(ImmutableLoaderInfoHandler.NAME_ATTRIBUTE_NAME, str(name))    
-    loader.ToInfo(group)
-    self.handle_.Export(self.file_name_)
-    
-  def RemoveLoader(self, name):
-    group_list = self.loaders_.GetGroups(ImmutableLoaderInfoHandler.LOADER_GROUP_NAME)
-    group_to_del = None
-    for group in group_list:
-      if group.HasAttribute(ImmutableLoaderInfoHandler.NAME_ATTRIBUTE_NAME):
-        groupname = group.GetAttribute(ImmutableLoaderInfoHandler.NAME_ATTRIBUTE_NAME)
-        if name == groupname:
-          group_to_del = group
-          break
-    
-    if group_to_del != None:
-      self.loaders_.Remove(group_to_del)      
-      self.handle_.Export(self.file_name_)
-      
-  def RenameLoader(self, old, new):
-    group_list = self.loaders_.GetGroups(ImmutableLoaderInfoHandler.LOADER_GROUP_NAME)
-    for group in group_list:
-      if group.HasAttribute(ImmutableLoaderInfoHandler.NAME_ATTRIBUTE_NAME):
-        groupname = group.GetAttribute(ImmutableLoaderInfoHandler.NAME_ATTRIBUTE_NAME)
-        if old == groupname:
-          group.SetAttribute(ImmutableLoaderInfoHandler.NAME_ATTRIBUTE_NAME, new)
-          self.handle_.Export(self.file_name_)
\ No newline at end of file
diff --git a/modules/gui/pymod/scene/loader_list_model.py b/modules/gui/pymod/scene/loader_list_model.py
deleted file mode 100644
index c033df038..000000000
--- a/modules/gui/pymod/scene/loader_list_model.py
+++ /dev/null
@@ -1,156 +0,0 @@
-from ost import gui
-from ost import gfx
-import os
-import ost
-from PyQt4 import QtCore, QtGui
-from immutable_loader_info_handler import ImmutableLoaderInfoHandler
-from loader_info_handler import LoaderInfoHandler
-from ost.gui import LoaderManager
-
-class LoaderListModel(QtCore.QAbstractListModel):
-  
-  IMMUTABLE_LOADERS_PATH = os.path.join(ost.GetSharedDataPath(),"scene", 
-                                          "loaders.xml")
-  MUTABLE_LOADERS_PATH = "user_loaders.xml"
-  
-  def __init__(self, parent=None, *args): 
-    QtCore.QAbstractListModel.__init__(self, parent, *args)
-    
-    self.data_ = list()
-    
-    #Info Handler
-    self.immutable_infoh_ = ImmutableLoaderInfoHandler(LoaderListModel.IMMUTABLE_LOADERS_PATH)
-    self.infoh_ = LoaderInfoHandler(LoaderListModel.MUTABLE_LOADERS_PATH)
-    self.LoadLoaderFromInfo()
-    
-    self.loader_manager_ = gui.FileLoader.GetLoaderManager()
-    
-  def AddItem(self, name, loader, row, editable, save):
-    if self.NameIsValid(name):
-      self.insertRow(row, QtCore.QModelIndex())
-      self.data_[row] = [name, loader, editable]
-      model_index = self.createIndex(row,0)
-      index = self.index(row)
-      end_index = self.createIndex(self.rowCount(),0)
-      if save:
-        self.AddLoaderToInfo(name, loader)
-      self.emit(QtCore.SIGNAL("dataChanged"),model_index, end_index)
-      gui.FileLoader.GetLoaderManager().AddRemoteSiteLoader(name, loader)
-      if(loader.IsDefault()):
-        gui.FileLoader.GetLoaderManager().SetDefaultRemoteSiteIdent(name)
-      return True
-    return False
-  
-  def IsEditable(self, row):
-    return self.data_[row][2]
-  
-  def RemoveItem(self, row):
-    if self.IsEditable(row):
-      name = self.data_[row][0]
-      self.removeRow(row, QtCore.QModelIndex())
-      model_index = self.createIndex(row,0)
-      self.infoh_.RemoveLoader(name)
-      self.emit(QtCore.SIGNAL("dataChanged"),model_index, model_index)
-      self.loader_manager_.RemoveRemoteSiteLoader(name)
-      return True
-    return False
-
-  def AddLoaderToInfo(self, name, loader):
-    self.infoh_.StoreLoader(name, loader)
-  
-  def RemoveLoaderFromInfo(self, name):
-    self.infoh_.RemoveLoader(name)
-  
-  def SetItem(self, model_index, loader):
-    row = model_index.row()
-    name = self.data_[row][0]
-    self.data_[row][1] = loader
-    model_index = self.createIndex(row,0)
-    index = self.index(row)
-    end_index = self.createIndex(self.rowCount(),0)
-    self.RemoveLoaderFromInfo(self.data_[row][0])
-    self.AddLoaderToInfo(self.data_[row][0], loader)
-    self.emit(QtCore.SIGNAL("dataChanged"),model_index, end_index)
-    self.loader_manager_.RemoveRemoteSiteLoader(name)
-    self.loader_manager_.AddRemoteSiteLoader(name, loader)
-    return True
-    
-  def LoadLoaderFromInfo(self):
-    if self.immutable_infoh_:
-      loaders = self.immutable_infoh_.GetLoaders()
-      for k, v in loaders.iteritems():
-        self.AddItem(k, v, self.GetLastRow(), False, False)
-    
-    loaders = self.infoh_.GetLoaders()
-    for k, v in loaders.iteritems():
-      self.AddItem(k, v, self.GetLastRow(), True, False)
-
-  def GetLoader(self, model_index):
-    if model_index.isValid():
-      return self.data_[model_index.row()][1]
-  
-  def GetLastRow(self):
-    return self.rowCount()
-  
-  #Helper
-  def NameIsValid(self, string):
-    if len(string)==0:
-      return False
-    for values in self.data_:
-      if string == values[0]:
-        return False
-    return True
-  
-  #Overwritten Methods  
-  def rowCount(self, parent=QtCore.QModelIndex()): 
-    return len(self.data_) 
- 
-  def data(self, index, role):
-    if index.isValid() and index.row()< self.rowCount():
-      data = self.data_[index.row()]
-      if role == QtCore.Qt.DisplayRole:
-        return QtCore.QVariant(data[0])
-    return QtCore.QVariant()
-
-  def setData(self, index, value, role):
-    if index.isValid():
-      row = index.row()
-      if not self.data_[row]:
-        self.data_[row] = list()
-      if role == QtCore.Qt.EditRole and self.NameIsValid(value.toString()):
-        old_name = str(self.data_[row][0])
-        new_name = value.toString()
-        self.data_[row][0] = new_name
-        self.infoh_.RenameLoader(old_name,str(new_name))
-        self.emit(QtCore.SIGNAL("dataChanged"),index, index)
-        self.loader_manager_.RemoveRemoteSiteLoader(old_name)
-        self.loader_manager_.AddRemoteSiteLoader(str(new_name), self.data_[row][1])
-        return True
-      elif role == QtCore.Qt.DisplayRole:
-        self.data_[row][0] = value.toString()
-    return False
-
-  def flags(self, index):
-    if index.isValid():
-      flags = QtCore.QAbstractItemModel.flags(self,index)
-      if self.IsEditable(index.row()):
-        return flags | QtCore.Qt.ItemIsEditable
-      else:
-        return flags
-    return QtCore.Qt.ItemIsEnabled
-  
-  def insertRow(self, position, index):
-    self.beginInsertRows(index, position, position)
-    self.data_.insert(position,list())
-    self.endInsertRows()
-    return True
-  
-  def removeRow(self, position, index):
-    self.beginRemoveRows(index, position, position)
-    del self.data_[position]
-    self.endRemoveRows()
-    return True
-
-  
-  
-  
diff --git a/modules/gui/pymod/scene/loader_manager_widget.py b/modules/gui/pymod/scene/loader_manager_widget.py
deleted file mode 100644
index d1fd7795d..000000000
--- a/modules/gui/pymod/scene/loader_manager_widget.py
+++ /dev/null
@@ -1,199 +0,0 @@
-#------------------------------------------------------------------------------
-# This file is part of the OpenStructure project <www.openstructure.org>
-#
-# Copyright (C) 2008-2011 by the OpenStructure authors
-#
-# This library is free software; you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation; either version 3.0 of the License, or (at your option)
-# any later version.
-# This library is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this library; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-#------------------------------------------------------------------------------
-# -*- coding: utf-8 -*-
-
-import os
-import ost
-from ost import gui
-from ost import gfx
-from datetime import datetime
-from PyQt4 import QtCore, QtGui
-
-from loader_list_model import LoaderListModel
-from file_loader import GenericLoader
-
-#Gradient Preset Widget
-class LoaderManagerWidget(QtGui.QDialog):
-  ICONS_DIR = os.path.join(ost.GetSharedDataPath(), "gui", "icons/")
-  def __init__(self, parent=None):
-    QtGui.QDialog.__init__(self, parent)
-    
-    #Title
-    self.text_ = "Loader Manager"
-        
-    #Create Ui elements
-    self.list_view_ = QtGui.QListView()
-    
-    #Create Model
-    self.list_model_ = LoaderListModel(self)
-    self.list_view_.setModel(self.list_model_)
-    self.list_view_.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
-        
-    loader_label = QtGui.QLabel(self.text_)
-    font = loader_label.font()
-    font.setBold(True)
-    
-    self.add_action = QtGui.QAction("+",self)
-    self.add_action.setIcon(QtGui.QIcon(LoaderManagerWidget.ICONS_DIR+"add_icon.png"))
-    
-    QtCore.QObject.connect(self.add_action, QtCore.SIGNAL("triggered()"), self.Add)
-    
-    self.add_button_ = QtGui.QToolButton(self)
-    self.add_button_.setIconSize(QtCore.QSize(20,20))
-    self.add_button_.setDefaultAction(self.add_action)
-        
-    grid = QtGui.QGridLayout()
-    grid.setContentsMargins(0,5,0,0)
-    grid.addWidget(loader_label, 0, 0, 1, 1)
-    qhbox = QtGui.QHBoxLayout()
-    grid.addWidget(self.list_view_,1,0,3,3)
-    grid.addWidget(self.add_button_,4,0,1,1)
-    self.setLayout(grid)
-    
-    self.list_view_.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
-    QtCore.QObject.connect(self.list_view_, QtCore.SIGNAL("customContextMenuRequested(const QPoint)"), self.contextMenuEvent)
-    self.CreateContextMenu()
-
-    QtCore.QObject.connect(self.list_view_, QtCore.SIGNAL("doubleClicked(const QModelIndex)"), self.Edit)
-
-  def CreateContextMenu(self):
-    self.contextMenu_ = QtGui.QMenu("Context menu", self)
-    self.remove_ = QtGui.QAction("Remove", self.list_view_)
-    self.rename_ = QtGui.QAction("Rename", self.list_view_)
-    self.edit_ = QtGui.QAction("Edit", self.list_view_)
-    self.contextMenu_.addAction(self.remove_)
-    self.contextMenu_.addAction(self.rename_)
-    self.contextMenu_.addAction(self.edit_)
-    #Connect Signals with Slots  
-    QtCore.QObject.connect(self.remove_, QtCore.SIGNAL("triggered()"), self.Remove)
-    QtCore.QObject.connect(self.rename_, QtCore.SIGNAL("triggered()"), self.Rename)
-    QtCore.QObject.connect(self.edit_, QtCore.SIGNAL("triggered()"), self.Edit)
-  
-  def contextMenuEvent(self, pos):
-    #ContextMenu
-    index = self.list_view_.indexAt(pos)
-    if index.isValid(): 
-      if self.list_model_.IsEditable(index.row()):
-        self.contextMenu_.popup(QtGui.QCursor.pos())
-  
-  def Add(self):
-    row = self.list_model_.GetLastRow()
-    edit_widget = LoaderEditWidget()
-    
-    if edit_widget.exec_() and self.list_model_.AddItem(datetime.now().isoformat(' '), edit_widget.GetLoader(), row, True, True):
-      index = self.list_model_.index(row)
-      self.list_view_.setCurrentIndex(index)
-      self.Rename()
-    
-  def Edit(self):
-    current_index = self.list_view_.currentIndex()
-    loader = self.list_model_.GetLoader(current_index)
-    edit_widget = LoaderEditWidget()
-    edit_widget.SetLoader(loader)
-    if edit_widget.exec_():
-      self.list_model_.SetItem(current_index, edit_widget.GetLoader())
-    
-      
-  def Remove(self):
-    if(self.list_view_.currentIndex().isValid()):
-      ret = QtGui.QMessageBox.warning(self, "Delete File Loader",
-                   "Delete File Loader?",
-                   QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
-      if ret == QtGui.QMessageBox.Yes:
-        self.list_model_.RemoveItem(self.list_view_.currentIndex().row())
-
-  def Rename(self):
-    if(self.list_view_.currentIndex().isValid()):
-      self.list_view_.edit(self.list_view_.currentIndex())
-      
-  def GetText(self):
-    return self.text_
-      
-
-
-
-class LoaderEditWidget(QtGui.QDialog):
-  def __init__(self, parent=None):
-    QtGui.QDialog.__init__(self, parent)
-    name_ext_label = QtGui.QLabel("Name Extension")
-    self.name_ext_edit_ = QtGui.QLineEdit()
-    
-    url_label = QtGui.QLabel("Url")
-    self.url_edit_ = QtGui.QLineEdit()
-    self.add_id_button_ = QtGui.QToolButton(self)
-    self.add_id_button_.setDefaultAction(QtGui.QAction("ID",self))
-     
-    file_ext_label = QtGui.QLabel("File Type")
-    self.file_ext_auto_ = QtGui.QCheckBox("Auto")    
-    self.file_ext_edit_ = QtGui.QLineEdit()
-    
-    self.hbox_ = QtGui.QHBoxLayout()
-    self.ok_button_ = QtGui.QPushButton("OK")
-    self.cancel_button_ = QtGui.QPushButton("Cancel")
-    self.hbox_.addWidget(self.ok_button_)
-    self.hbox_.addStretch()
-    self.hbox_.addWidget(self.cancel_button_)
-    
-    grid = QtGui.QGridLayout()
-    grid.setContentsMargins(0,5,0,0)
-    grid.addWidget(name_ext_label, 0, 0, 1, 1)
-    grid.addWidget(self.name_ext_edit_, 0, 1, 1, 4)
-    grid.addWidget(url_label, 1, 0, 1, 1)
-    grid.addWidget(self.url_edit_, 1, 1, 1, 3)
-    grid.addWidget(self.add_id_button_, 1, 4, 1, 1)
-    grid.addWidget(file_ext_label, 2, 0, 1, 1)
-    grid.addWidget(self.file_ext_auto_, 2, 1, 1, 1)
-    grid.addWidget(self.file_ext_edit_, 2, 2, 1, 3)
-    grid.addLayout(self.hbox_,3,0,1,2)
-    grid.setRowStretch(2, 1)
-    self.setLayout(grid)
-    
-    QtCore.QObject.connect(self.add_id_button_, QtCore.SIGNAL("clicked()"), self.AppendId)
-    QtCore.QObject.connect(self.file_ext_auto_, QtCore.SIGNAL("stateChanged(int)"), self.CbStateChanged)
-    QtCore.QObject.connect(self.ok_button_, QtCore.SIGNAL("clicked()"), self.Ok)
-    QtCore.QObject.connect(self.cancel_button_, QtCore.SIGNAL("clicked()"), self.Cancel)
-        
-  def GetLoader(self):
-    name_ext = str(self.name_ext_edit_.text())
-    url = str(self.url_edit_.text())
-    file_ext = None
-    if not self.file_ext_auto_.isChecked():
-      file_ext = str(self.file_ext_edit_.text())
-    
-    return GenericLoader(name_ext, url, False, file_ext)
-
-  def SetLoader(self, loader):
-    self.name_ext_edit_.setText(loader.name_)
-    self.url_edit_.setText(loader.url_)
-    if loader.file_type_ is not None:
-      self.file_ext_edit_.setText(loader.file_type_)
-      self.file_ext_auto_.setChecked(False)
-    else:
-      self.file_ext_auto_.setChecked(True)
-  def AppendId(self):
-    self.url_edit_.setText(self.url_edit_.text()+"${ID}")
-
-  def CbStateChanged(self, state):
-      self.file_ext_edit_.setEnabled(not self.file_ext_auto_.isChecked())
-      
-  def Ok(self):
-    self.accept()
-    
-  def Cancel(self):
-    self.reject()
diff --git a/modules/gui/pymod/scene/remote.py b/modules/gui/pymod/scene/remote.py
new file mode 100644
index 000000000..46a7553b4
--- /dev/null
+++ b/modules/gui/pymod/scene/remote.py
@@ -0,0 +1,78 @@
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+import threading
+from ost import LogError
+from ost import gui, gfx
+from ost.io.remote import RemoteLoad, REMOTE_REPOSITORIES
+import re
+
+class RemoteLoader(QWidget):
+  def __init__(self):
+    QWidget.__init__(self)
+    self._line = QLineEdit(self)
+    self._load = QToolButton(self)
+    self._load.setAttribute(Qt.WA_MacSmallSize)
+    QObject.connect(self._line, SIGNAL('returnPressed()'),
+                    self._DoLoad)
+    QObject.connect(self._load, SIGNAL('clicked()'),
+                    self._DoLoad)
+    hbox = QHBoxLayout(self)
+    hbox.addWidget(self._line,1)
+    hbox.addWidget(self._load,0)
+    self.setLayout(hbox)
+    hbox.setMargin(3)
+    hbox.setSpacing(3)
+    self._menu = self._RemoteMenu()
+    self._load.setMenu(self._menu)
+    self._current_repo = 'pdb'
+    self._UpdateLoadButton(self._current_repo)
+    self.setFixedHeight(self._load.height())
+    self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+
+  def _RemoteMenu(self):
+    menu = QMenu()
+    action_group = QActionGroup(menu)
+    for k,v in REMOTE_REPOSITORIES.iteritems():
+      action = menu.addAction(v.name)
+      action.setCheckable(True)
+      if k == 'pdb':
+        action.setChecked(True)
+      action.setData(QVariant(k))
+      action_group.addAction(action)
+    QObject.connect(menu, SIGNAL('triggered(QAction*)'),
+                    self._ToggleRepo)
+    return menu
+  def _UpdateLoadButton(self, current):
+    name = REMOTE_REPOSITORIES[current].name
+    self._load.setText('load from %s  ' % name)
+
+  def _ToggleRepo(self, action):
+    self._current_repo = str(action.data().toString())
+    self._UpdateLoadButton(self._current_repo)
+
+
+  def _DoLoad(self):
+    split_ids = []
+    for p in str(self._line.text()).split(','):
+      for k in p.split():
+        if len(k.strip()):
+          split_ids.append(k.strip())
+    self._line.setText('')
+    for split_id in split_ids:
+      try:
+        ent = RemoteLoad(split_id, from_repo=self._current_repo)
+      except Exception, e:
+        LogError(str(e))
+        continue
+      g = gfx.Entity(split_id, ent)
+      try:
+        gfx.Scene().Add(g)
+      except Exception, e:
+        LogError(str(e))
+
+remote_loader=RemoteLoader()
+remote_loader_for_panel=gui.Widget(remote_loader)
+remote_loader_for_panel.qobject.setSizePolicy(QSizePolicy.Expanding, 
+                                              QSizePolicy.Fixed)
+panels=gui.GostyApp.Instance().perspective.panels
+panels.AddWidgetToPool("Remote Loader",remote_loader_for_panel)
diff --git a/modules/gui/pymod/wrap_gui.cc b/modules/gui/pymod/wrap_gui.cc
index 81b6ff788..a4474a6f8 100644
--- a/modules/gui/pymod/wrap_gui.cc
+++ b/modules/gui/pymod/wrap_gui.cc
@@ -38,7 +38,6 @@ void export_SipHandler();
 void export_SceneSelection();
 void export_MainArea();
 void export_MenuBar();
-void export_RemoteSiteLoader();
 void export_FileLoader();
 void export_FileViewer();
 void export_Widget();
@@ -118,7 +117,6 @@ BOOST_PYTHON_MODULE(_ost_gui)
   export_SceneWin();
   export_SceneSelection();
   export_SequenceViewer();
-  export_RemoteSiteLoader();
   export_FileLoader();
   export_FileViewer();
   export_Widget();
diff --git a/modules/gui/src/CMakeLists.txt b/modules/gui/src/CMakeLists.txt
index 190cb6f66..cdeb7d273 100644
--- a/modules/gui/src/CMakeLists.txt
+++ b/modules/gui/src/CMakeLists.txt
@@ -166,7 +166,6 @@ set(OST_GUI_HEADERS
 file_browser.hh
 file_type_dialog.hh
 file_viewer.hh
-remote_loader.hh
 gl_canvas.hh
 gl_win.hh
 scene_menu.hh
@@ -176,7 +175,6 @@ module_config.hh
 main.hh
 main_area.hh
 perspective.hh
-remote_site_loader.hh
 scene_selection.hh
 main_window.hh
 dock_widget.hh
@@ -188,7 +186,6 @@ widget_pool.hh
 widget_registry.hh
 widget_state_saver.hh
 file_loader.hh
-loader_manager.hh
 )
 
 set(OST_GUI_SOURCES
@@ -198,7 +195,6 @@ widget_registry.cc
 file_browser.cc
 file_type_dialog.cc
 file_viewer.cc
-remote_loader.cc
 main.cc
 gl_canvas.cc
 dock_widget.cc
@@ -208,7 +204,6 @@ scene_menu.cc
 widget.cc
 admin.cc
 widget_pool.cc
-remote_site_loader.cc
 messages/message_widget.cc
 messages/message_box_widget.cc
 messages/log_reader.cc
@@ -237,7 +232,6 @@ widget_state_saver.cc
 scene_selection.cc
 widget_geom_handler.cc
 file_loader.cc
-loader_manager.cc
 panels/button_bar.cc
 panels/drop_box.cc
 panels/panel_bar.cc
@@ -305,7 +299,6 @@ set(HEADERS_TO_BE_MOCCED
 file_browser.hh
 file_type_dialog.hh
 file_viewer.hh
-remote_loader.hh
 gl_canvas.hh
 gl_win.hh
 scene_menu.hh
diff --git a/modules/gui/src/file_loader.cc b/modules/gui/src/file_loader.cc
index d31c2f0b8..bc69ba7b8 100644
--- a/modules/gui/src/file_loader.cc
+++ b/modules/gui/src/file_loader.cc
@@ -59,7 +59,6 @@
 #include <QMenuBar>
 namespace ost { namespace gui {
 
-LoaderManagerPtr FileLoader::loader_manager_ = LoaderManagerPtr();
 
 #if OST_IMG_ENABLED
   QList<img::ImageHandle> FileLoader::loaded_images_;
@@ -161,36 +160,6 @@ gfx::GfxObjP FileLoader::NoHandlerFound(const QString& filename)
   return gfx::GfxObjP();
 }
 
-void FileLoader::LoadFrom(const QString& id, const QString& site, const QString& selection)
-{
-  if(!loader_manager_)
-    loader_manager_ = LoaderManagerPtr(new LoaderManager());
-  RemoteSiteLoader* remote_site = loader_manager_->GetRemoteSiteLoader(site);
-  if(remote_site){
-    remote_site->LoadById(id,selection);
-  }
-  else{
-    remote_site = loader_manager_->GetCurrentSiteLoader();
-    if(remote_site){
-      remote_site->LoadById(id,selection);
-    }
-  }
-}
-
-LoaderManagerPtr FileLoader::GetLoaderManager()
-{
-  if(!loader_manager_)
-    loader_manager_ = LoaderManagerPtr(new LoaderManager());
-  return loader_manager_;
-}
-
-std::vector<String> FileLoader::GetSiteLoaderIdents()
-{
-  if(!loader_manager_)
-    loader_manager_ = LoaderManagerPtr(new LoaderManager());
-  return loader_manager_->GetSiteLoaderIdents();
-}
-
 void FileLoader::HandleError(const Error& e, ErrorType type, const QString& filename, gfx::GfxObjP obj)
 {
   if(type==GFX_ADD || type==GFX_MULTIPLE_ADD){
diff --git a/modules/gui/src/file_loader.hh b/modules/gui/src/file_loader.hh
index 32a4ba18e..23419b613 100644
--- a/modules/gui/src/file_loader.hh
+++ b/modules/gui/src/file_loader.hh
@@ -24,8 +24,6 @@
 #include <ost/gfx/gfx_object.hh>
 
 #include <ost/gui/module_config.hh>
-#include <ost/gui/remote_site_loader.hh>
-#include <ost/gui/loader_manager.hh>
 
 #include <ost/io/io_exception.hh>
 #include <ost/io/entity_io_handler.hh>
@@ -64,7 +62,6 @@ private:
   static gfx::GfxObjP NoHandlerFound(const QString& filename);
   virtual ~FileLoader();
 
-  static LoaderManagerPtr loader_manager_;
 
 #if OST_IMG_ENABLED
   static QList<img::ImageHandle> loaded_images_;
@@ -72,9 +69,7 @@ private:
 
 public:
   static void LoadObject(const QString& filename, const QString& selection=QString());
-  static void LoadFrom(const QString& id, const QString& site=QString(), const QString& selection=QString());
   static std::vector<String> GetSiteLoaderIdents();
-  static LoaderManagerPtr GetLoaderManager();
 };
 
 } }
diff --git a/modules/gui/src/loader_manager.cc b/modules/gui/src/loader_manager.cc
deleted file mode 100644
index bfe2853dc..000000000
--- a/modules/gui/src/loader_manager.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-#include <ost/gui/gosty_app.hh>
-#include "loader_manager.hh"
-
-#include <ost/gui/perspective.hh>
-#include <QDir>
-#include <QAction>
-#include <QMenu>
-#include <QFileInfo>
-#include <QMessageBox>
-#include <QMenuBar>
-
-
-namespace ost { namespace gui {
-
-LoaderManager::LoaderManager():
-  site_loaders_(),
-  site_actions_(new QActionGroup(GostyApp::Instance()->GetPerspective()->GetMenuBar())),
-  default_site_()
-
-{
-  site_actions_->setExclusive(true);
-}
-
-void LoaderManager::AddRemoteSiteLoader(const QString& ident, RemoteSiteLoader* site_loader)
-{
-  site_loaders_.insert(ident,site_loader);
-
-  QAction* action = new QAction(ident,site_actions_);
-  action->setCheckable(true);
-  site_actions_->addAction(action);
-  if(site_actions_->checkedAction()==NULL){
-    action->setChecked(true);
-  }
-}
-
-void LoaderManager::RemoveRemoteSiteLoader(const QString& ident)
-{
-  site_loaders_.remove(ident);
-
-  QList<QAction*> actions = site_actions_->actions();
-  QAction* action = NULL;
-  for (int i=0; i<actions.size(); i++){
-    if(actions[i]->text()==ident){
-      action = actions[i];
-      break;
-    }
-  }
-  if(action){
-    site_actions_->removeAction(action);
-  }
-}
-
-
-RemoteSiteLoader* LoaderManager::GetRemoteSiteLoader(const QString& ident)
-{
-  if(site_loaders_.contains(ident)){
-    return site_loaders_[ident];
-  }
-  return NULL;
-}
-
-RemoteSiteLoader* LoaderManager::GetCurrentSiteLoader()
-{
-  if(site_actions_->checkedAction()!=NULL)
-    return site_loaders_[site_actions_->checkedAction()->text()];
-  return NULL;
-}
-
-std::vector<String> LoaderManager::GetSiteLoaderIdents()
-{
-  QList<QString> keys = site_loaders_.keys();
-  std::vector<String> sites;
-  for(int i=0;i<keys.size();i++){
-    sites.push_back(keys.at(i).toStdString());
-  }
-  return sites;
-}
-
-RemoteSiteLoader* LoaderManager::GetDefaultRemoteSiteLoader()
-{
- return GetRemoteSiteLoader(GetDefaultRemoteSiteIdent());
-}
-
-QString LoaderManager::GetDefaultRemoteSiteIdent(){
-  return default_site_;
-}
-
-void LoaderManager::SetDefaultRemoteSiteIdent(const QString& ident){
-  default_site_ = ident;
-}
-
-LoaderManager::~LoaderManager(){}
-
-} }
diff --git a/modules/gui/src/loader_manager.hh b/modules/gui/src/loader_manager.hh
deleted file mode 100644
index f969b289c..000000000
--- a/modules/gui/src/loader_manager.hh
+++ /dev/null
@@ -1,59 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-#ifndef OST_GUI_LOADER_MANAGER_HH
-#define OST_GUI_LOADER_MANAGER_HH
-#include <vector>
-
-#include <boost/shared_ptr.hpp>
-
-#include <QString>
-#include <QMap>
-
-#include <ost/gui/remote_site_loader.hh>
-
-namespace ost { namespace gui {
-
-class DLLEXPORT_OST_GUI LoaderManager {
-
-public:
-  LoaderManager();
-  virtual ~LoaderManager();
-  std::vector<String> GetSiteLoaderIdents();
-  void AddRemoteSiteLoader(const QString& ident, RemoteSiteLoader* site_loader);
-  void RemoveRemoteSiteLoader(const QString& ident);
-  RemoteSiteLoader* GetRemoteSiteLoader(const QString& ident);
-  RemoteSiteLoader* GetCurrentSiteLoader();
-  RemoteSiteLoader* GetDefaultRemoteSiteLoader();
-  QString GetDefaultRemoteSiteIdent();
-  void SetDefaultRemoteSiteIdent(const QString& ident);
-  QMenu* GetSiteMenu();
-
-private:
-  QMap<QString,RemoteSiteLoader*> site_loaders_;
-  QActionGroup* site_actions_;
-  QString default_site_;
-
-
-};
-
-typedef boost::shared_ptr<LoaderManager> LoaderManagerPtr;
-
-} }
-
-#endif /* OST_GUI_LOADER_MANAGER_HH */
diff --git a/modules/gui/src/remote_loader.cc b/modules/gui/src/remote_loader.cc
deleted file mode 100644
index a75a0b4a1..000000000
--- a/modules/gui/src/remote_loader.cc
+++ /dev/null
@@ -1,208 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-#include <vector>
-
-#include <ost/platform.hh>
-
-#include <ost/gui/file_loader.hh>
-#include <ost/gui/loader_manager.hh>
-
-#include "widget_registry.hh"
-#include "remote_loader.hh"
-
-#include <QString>
-#include <QSettings>
-#include <QNetworkReply>
-#include <QHBoxLayout>
-#include <QDir>
-namespace ost { namespace gui {
-
-RemoteLoader::RemoteLoader(QWidget* parent):
- Widget(NULL, parent)
-{
-  img_support_=OST_IMG_ENABLED;
-  line_edit_ = new QLineEdit(this);
-  button_ = new QToolButton(this);
-  button_->setAttribute(Qt::WA_MacSmallSize);
-  progress_bar_ = new QProgressBar(this);
-  progress_bar_->setAttribute(Qt::WA_MacSmallSize);
-  progress_bar_->setVisible(false);
-  progress_bar_->setRange(0,0);
-
-  QHBoxLayout* l=new QHBoxLayout(this);
-  l->addWidget(line_edit_);
-  l->addWidget(button_);
-  l->addWidget(progress_bar_);
-  l->setMargin(3);
-  l->setSpacing(2);
-
-  connect(button_, SIGNAL(clicked()), this,
-          SLOT(Clicked()));
-
-  QDir icon_path(GetSharedDataPath().c_str());
-  icon_path.cd("gui");
-  icon_path.cd("icons");
-  site_loader_menu_ = new QMenu(this);
-  site_actions_ = new QActionGroup(site_loader_menu_);
-
-  site_loader_menu_ = new QMenu(this);
-  site_actions_ = new QActionGroup(site_loader_menu_);
-
-  QAction* select_url_action = new QAction(this);
-  select_url_action->setText("URL");
-  select_url_action->setToolTip("Select remote URL");
-  select_url_action->setIcon(QIcon(icon_path.absolutePath()+QDir::separator()+
-                                   QString("site_icon.png")));
-  action_list_.append(select_url_action);
-  connect(select_url_action, SIGNAL(triggered(bool)), this, SLOT(UrlClick()));
-  this->BuildMenu();
-  this->RenameButton();
-  this->setFixedHeight(button_->height());
-  this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);  
-}
-
-void RemoteLoader::UrlClick()
-{
-  this->BuildMenu();
-  site_loader_menu_->exec(QCursor::pos());
-}
-
-void RemoteLoader::BuildMenu(String active_loader)
-{
-  if(!active_loader.empty()){
-    selected_site_loader_ = active_loader;
-  }
-  else if(site_actions_->checkedAction()!=NULL){
-    selected_site_loader_=site_actions_->checkedAction()->text().toStdString();
-  }
-  site_loader_menu_->clear();
-  QList<QAction*> actions = site_actions_->actions();
-  for(int i=0;i<actions.size();i++){
-    site_actions_->removeAction(actions[i]);
-  }
-  std::vector<String> site_loaders = FileLoader::GetSiteLoaderIdents();
-  for(unsigned int i=0; i<site_loaders.size(); i++){
-    QString loader_ident(site_loaders[i].c_str());
-    RemoteSiteLoader* loader = FileLoader::GetLoaderManager()->GetRemoteSiteLoader(loader_ident);
-    if(loader && ((loader->IsImg() && img_support_) || !loader->IsImg())){
-      QAction* action = new QAction(loader_ident,site_loader_menu_);
-      connect(action, SIGNAL(triggered()), this, SLOT(RenameButton()));
-      action->setCheckable(true);
-      site_actions_->addAction(action);
-      if((site_actions_->checkedAction()==NULL && loader_ident == FileLoader::GetLoaderManager()->GetDefaultRemoteSiteIdent()) ||selected_site_loader_==loader_ident.toStdString() ){
-        action->setChecked(true);
-      }
-      site_loader_menu_->addAction(action);
-    }
-  }
-}
-
-ActionList RemoteLoader::GetActions()
-{
-  return action_list_;
-}
-
-bool RemoteLoader::Save(const QString& prefix)
-{
-  this->BuildMenu();
-  QSettings settings;
-  settings.beginGroup(prefix);
-  settings.setValue("loader", site_actions_->checkedAction()->text());
-  settings.endGroup();
-  return true;
-}
-
-bool RemoteLoader::Restore(const QString& prefix)
-{
-  QSettings settings;
-  settings.beginGroup(prefix);
-  if (settings.contains("loader")) {
-    this->BuildMenu(settings.value("loader").toString().toStdString());
-  }
-  else{
-    this->BuildMenu();
-  }
-  this->RenameButton();
-  return true;
-}
-
-void RemoteLoader::Clicked()
-{
-  this->BuildMenu();
-  if(!line_edit_->text().isEmpty() && site_actions_->checkedAction()){
-    RemoteSiteLoader* loader = FileLoader::GetLoaderManager()->GetRemoteSiteLoader(site_actions_->checkedAction()->text());
-
-    QString text = line_edit_->text().simplified();
-    QString id = text;
-    QString selection = "";
-    int pos = text.indexOf('[');
-    if(pos >= 0){
-      id = text.left(pos);
-      selection = text.right(text.size()-(pos+1));
-      pos = selection.lastIndexOf(']');
-      if(pos>=0){
-        selection = selection.left(pos);
-      }
-    }
-    QNetworkReply* network_reply = loader->ById(id,selection);
-    if(network_reply){
-      progress_bar_->reset();
-      connect(network_reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(UpdateProgress(qint64,qint64)));
-      connect(network_reply, SIGNAL(finished()), this, SLOT(DownloadFinished()));
-      this->ShowProgressBar(true);
-    }
-    line_edit_->setText("");
-    line_edit_->setFocus();
-  }
-}
-
-void RemoteLoader::keyPressEvent(QKeyEvent* event){
-  if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
-    this->Clicked();
-  }
-}
-
-void RemoteLoader::ShowProgressBar(bool visibility){
-  button_->setVisible(!visibility);
-  line_edit_->setVisible(!visibility);
-  progress_bar_->setVisible(visibility);
-}
-
-void RemoteLoader::UpdateProgress(qint64 read, qint64 total){
-  progress_bar_->setMaximum(total);
-  progress_bar_->setValue(read);
-
-}
-
-void RemoteLoader::DownloadFinished(){
-  this->ShowProgressBar(false);
-}
-
-
-void RemoteLoader::RenameButton(){
-  if(site_actions_->checkedAction()){
-    QString text = "Load (" + site_actions_->checkedAction()->text() + ")";
-    button_->setText(text);
-  }
-}
-
-OST_REGISTER_WIDGET_WITH_DEFAULT_FACTORY(ost::gui, RemoteLoader, "Remote Loader");
-
-}}
-
diff --git a/modules/io/pymod/CMakeLists.txt b/modules/io/pymod/CMakeLists.txt
index 007569fff..6763a0189 100644
--- a/modules/io/pymod/CMakeLists.txt
+++ b/modules/io/pymod/CMakeLists.txt
@@ -10,7 +10,7 @@ endif()
 
 set(OST_IO_PYMOD_MODULES
   __init__.py
-  hhsearch.py
+  remote.py
   repository.py
 )
 
diff --git a/modules/io/pymod/__init__.py b/modules/io/pymod/__init__.py
index abe1dcfdb..661d6bbcd 100644
--- a/modules/io/pymod/__init__.py
+++ b/modules/io/pymod/__init__.py
@@ -60,30 +60,6 @@ def _override(val1, val2):
   else:
     return val1
 
-def __GetModelFromPDB(model_id, output_dir, file_pattern='pdb%s.ent.gz'):
-  file_name = file_pattern % model_id
-  file_path = os.path.join(output_dir,file_name)
-  try:
-    server="ftp.wwpdb.org"
-    ftp=ftplib.FTP(server,"anonymous","user@")
-    ftp.cwd("pub/pdb/data/structures/all/pdb")
-    ftp_retrfile=open(file_path,"wb")
-    ftp.retrbinary("RETR "+file_name,ftp_retrfile.write)
-    ftp_retrfile.close()
-  except:
-    conn=httplib.HTTPConnection('www.pdb.org')
-    conn.request('GET', '/pdb/files/%s.pdb.gz' % model_id )
-    response=conn.getresponse()
-    if response.status==200:
-      data=response.read()
-      f=open(os.path.join(output_dir, file_pattern % model_id), 'w+')
-      f.write(data)
-      f.close()
-    else:
-      conn.close()
-      return False
-  return os.path.getsize(file_path) > 0
-
 def LoadPDB(filename, restrict_chains="", no_hetatms=None,
             fault_tolerant=None, load_multi=False, quack_mode=None,
             join_spread_atom_records=None, calpha_only=None,
@@ -156,12 +132,11 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=None,
   prof.join_spread_atom_records=_override(prof.join_spread_atom_records,
                                           join_spread_atom_records)
 
+  tmp_file = None # avoid getting out of scope
   if remote:
-    output_dir = tempfile.gettempdir()
-    if __GetModelFromPDB(filename, output_dir):
-      filename = os.path.join(output_dir, 'pdb%s.ent.gz' % filename)
-    else:
-      raise IOError('Can not load PDB %s from www.pdb.org'%filename) 
+    from ost.io.remote import RemoteGet
+    tmp_file =RemoteGet(filename)
+    filename = tmp_file.name
   
   conop_inst=conop.Conopology.Instance()
   builder=conop_inst.GetBuilder("DEFAULT")
diff --git a/modules/io/pymod/remote.py b/modules/io/pymod/remote.py
new file mode 100644
index 000000000..102cf6807
--- /dev/null
+++ b/modules/io/pymod/remote.py
@@ -0,0 +1,93 @@
+#------------------------------------------------------------------------------
+# This file is part of the OpenStructure project <www.openstructure.org>
+#
+# Copyright (C) 2008-2011 by the OpenStructure authors
+#
+# This library is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation; either version 3.0 of the License, or (at your option)
+# any later version.
+# This library is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#------------------------------------------------------------------------------
+
+import urllib2
+import tempfile
+
+from ost.io import LoadPDB, LoadMMCIF
+
+class RemoteRepository:
+  """
+  A remote repository represents a structural database accessible through the 
+  internet, e.g. the PDB or SWISS-MODEL template library.
+  """
+  def __init__(self, name, url_pattern, type, id_transform='upper'):
+    self.name = name
+    self.url_pattern = url_pattern
+    self.type = type
+    if type not in ('cif', 'pdb'):
+      raise ValueError('only cif and pdb types are supported')
+    self.id_transform = id_transform
+
+  def URLForID(self, id):
+    if self.id_transform == 'upper':
+      id = id.upper()
+    if self.id_transform == 'lower':
+      id = id.lower()
+    return self.url_pattern.replace('$ID', id)
+
+  def Get(self, id):
+    remote_url = self.URLForID(id)
+    tmp_file_suffix = '.%s' % self.type
+    if remote_url.endswith('.gz'):
+      tmp_file_suffix+='.gz'
+
+    try:
+      connection = urllib2.urlopen(remote_url)
+      status = connection.getcode()
+    except urllib2.HTTPError, e:
+      status = e.code
+    msg = 'Could not load %s from %s (status code %d)'
+    if status!=200:
+      raise IOError(msg % (id , self.name ,status))
+    tmp_file = tempfile.NamedTemporaryFile(suffix=tmp_file_suffix)
+    contents = ''.join(connection)
+    tmp_file.write(contents)
+    tmp_file.flush()
+    return tmp_file
+
+  def Load(self, id):
+    tmp_file = self.Get(id)
+    if self.type == 'pdb':
+      return LoadPDB(tmp_file.name)
+    if self.type == 'cif':
+      return LoadMMCIF(tmp_file.name)
+
+REMOTE_REPOSITORIES = {
+    'pdb' : RemoteRepository('pdb.org (PDB)', 'http://www.pdb.org/pdb/files/$ID.ent.gz',
+                   type='pdb', id_transform='upper'),
+    'smtl' : RemoteRepository('SMTL', 'http://beta.swissmodel.expasy.org/templates/$ID.pdb',
+                   type='pdb', id_transform='lower'),
+    'cif' : RemoteRepository('pdb.org (mmCIF)', 'http://www.pdb.org/pdb/files/$ID.cif.gz',
+                   type='cif', id_transform='lower'),
+    'pdb_redo' : RemoteRepository('pdbredo', 'http://www.cmbi.ru.nl/pdb_redo/$ID/$ID_besttls.pdb',
+                   type='pdb'),
+}
+
+def RemoteGet(id, from_repo='pdb'):
+  remote_repo = REMOTE_REPOSITORIES.get(from_repo, None) 
+  if not remote_repo:
+    raise ValueError('%s is not a valid repository' % from_repo)
+  return remote_repo.Get(id)
+
+def RemoteLoad(id ,from_repo='pdb'):
+  remote_repo = REMOTE_REPOSITORIES.get(from_repo, None) 
+  if not remote_repo:
+    raise ValueError('%s is not a valid repository' % from_repo)
+  return remote_repo.Load(id)
-- 
GitLab