summaryrefslogtreecommitdiffstats
path: root/src/part/remoteLister.cpp
blob: 834e9cdbbcb8733e5725d56d1f53c301829802f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//Author:    Max Howell <[email protected]>, (C) 2003-4
//Copyright: See COPYING file that comes with this distribution

#include <debug.h>
#include "fileTree.h"
#include <tqapplication.h>
#include <tqtimer.h>
#include <tqvaluelist.h>
#include "remoteLister.h"
#include "scan.h"

namespace Filelight
{
   //you need to use a single DirLister
   //one per directory breaks KIO (seemingly) and also uses un-godly amounts of memory!

   //TODO delete all this stuff!

   struct Store {

      typedef TQValueList<Store*> List;

      /// location of the directory
      const KURL url;
      /// the directory on which we are operating
      Directory *directory;
      /// so we can reference the parent store
      Store *parent;
      /// directories in this directory that need to be scanned before we can propagate()
      List stores;

      Store()
         : directory( 0 ), parent( 0 ) {}
      Store( const KURL &u, const TQString &name, Store *s )
         : url( u ), directory( new Directory( name.local8Bit() + '/' ) ), parent( s ) {}


      Store*
      propagate()
      {
         /// returns the next store available for scanning

         debug() << "propagate: " << url << endl;

         if( parent ) {
            parent->directory->append( directory );
            if( parent->stores.isEmpty() ) {
               return parent->propagate();
            }
            else
               return parent;
         }

         //we reached the root, let's get our next directory scanned
         return this;
      }

   private:
      Store( Store& );
      Store &operator=( const Store& );
   };


   RemoteLister::RemoteLister( const KURL &url, TQWidget *parent )
      : KDirLister( true /*don't fetch mimetypes*/ )
      , m_root( new Store( url, url.url(), 0 ) )
      , m_store( m_root )
   {
      setAutoUpdate( false ); //don't use KDirWatchers
      setShowingDotFiles( true ); //stupid KDirLister API function names
      setMainWindow( parent );

      //use TQT_SIGNAL(result(TDEIO::Job*)) instead and then use Job::error()
      connect( this, TQT_SIGNAL(completed()), TQT_SLOT(completed()) );
      connect( this, TQT_SIGNAL(canceled()), TQT_SLOT(canceled()) );

      //we do this non-recursively - it is the only way!
      openURL( url );
   }

   RemoteLister::~RemoteLister()
   {
      Directory *tree = isFinished() ? m_store->directory : 0;

      TQCustomEvent *e = new TQCustomEvent( 1000 );
      e->setData( tree );
      TQApplication::postEvent( parent(), e );

      delete m_root;
   }

   void
   RemoteLister::completed()
   {
      debug() << "completed: " << url().prettyURL() << endl;

      //as usual KDE documentation didn't suggest I needed to do this at all
      //I had to figure it out myself
      // -- avoid crash
      TQTimer::singleShot( 0, this, TQT_SLOT(_completed()) );
   }

   void
   RemoteLister::canceled()
   {
      debug() << "canceled: " << url().prettyURL() << endl;

      TQTimer::singleShot( 0, this, TQT_SLOT(_completed()) );
   }

   void
   RemoteLister::_completed()
   {
      //m_directory is set to the directory we should operate on

      KFileItemList items = KDirLister::items();
      for( KFileItemList::ConstIterator it = items.begin(), end = items.end(); it != end; ++it )
      {
         if( (*it)->isDir() )
            m_store->stores += new Store( (*it)->url(), (*it)->name(), m_store );
         else
            m_store->directory->append( (*it)->name().local8Bit(), (*it)->size() / 1024 );

         ScanManager::s_files++;
      }


      if( m_store->stores.isEmpty() )
         //no directories to scan, so we need to append ourselves to the parent directory
         //propagate() will return the next ancestor that has stores left to be scanned, or root if we are done
         m_store = m_store->propagate();

      if( !m_store->stores.isEmpty() )
      {
         Store::List::Iterator first = m_store->stores.begin();
         const KURL url( (*first)->url );
         Store *currentStore = m_store;

         //we should operate with this store next time this function is called
         m_store = *first;

         //we don't want to handle this store again
         currentStore->stores.remove( first );

         //this returns _immediately_
         debug() << "scanning: " << url << endl;
         openURL( url );
      }
      else {

         debug() << "I think we're done\n";

         Q_ASSERT( m_root == m_store );

         delete this;
      }
   }
}

#include "remoteLister.moc"