6.8. Network Transparency

If you want a program to be able to have the KDE sticker, it needs to be network transparent. Fortunately, this isn't all that difficult! The importance of such a functionality cannot be understated; more information on network transparency is also presented in Chapter 7, "Further KDE Compliance."

Generally, the only two classes that need to be worried about are KIO::Job and KIO::NetAccess. KIO is a namespace.

Remember that KDE would rather deal with URLs than with filenames. Both can be stored in a QString, but you should prefer a KURL, because it can do all the parsing for you.

In the following example (Listing 6.8), the user has clicked the Open toolbar or menu item. The Open File window appears, and then the selected file opens.

You'll have to include kfiledialog.h, netaccess.h, and knotifyclient.h.


Example 6.8. Opening a File, Network Transparently

   1 
   2  1: // In this class, we have declared a QString file, which is the filename
   3  2: // of the local copy of our file. We also have a KURL url which contains
   4  3: // the local/remote location of the file that is opened
   5  4:
   6  5: // TODO: Test if there is already a file open, or, if the current file
   7  6: // has been edited
   8  7:
   9  8: url=KFileDialog::getOpenURL(0,
  10  9:     "*.txt|Text Files (*.txt)\n*.cpp|C++ Source Files (*.cpp)",this);
  11 10:
  12 11: if (!KIO::NetAccess::download(url, file))
  13 12:     KNotifyClient::event("cannotopenfile"), return;
  14 13:
  15 14: // That's it! Now, we get to open the string "local" the standard way
  16 15:
  17 16: QFile f(file);
  18 17: // TODO: read and open the file….
  19 

When the user clicks Save, you want to store the file to the server, if necessary:


   1 
   2 // file and url have been declared, remember?
   3 QFile f(file);
   4 // […] store data to file
   5 f.close();
   6 
   7 if (!KIO::NetAccess::upload(file, url))
   8     KNotifyClient::event("cannotopenfile"), return;
   9 

Not that bad at all, is it?

What if the user has not selected a filename for this file yet? Listing 6.9 shows what to do in such a situation:


Example 6.9. More Network Transparency Checks

   1 
   2  1: if (url.isEmpty())
   3  2: {
   4  3:   url=KFileDialog::getSaveUrl(0,
   5  4:   "*.txt|Text Files (*.txt)\n*.cpp|C++ Source (*.cpp)", this)
   6  5:   // URL now contains where we want to save this to
   7  6:     file=url.path();
   8  7:   // This won't be useful if it's not a local file, but if it is a local  file
   9  8:   // we get to save directly into this!
  10  9:   if (!file.isLocalPath())
  11 10:   // We must come up with a temporary file to save to (more info on this  shortly)
  12 11:
  13 12: […]
  14 

Your application should have two menu items: Save and Save As.

Save As asks you to save a file in another filename and format. Save just saves it under the currently selected filename; if that filename has not been selected, Save acts as Save As.

Listing 6.10 is the full and complete code of those two methods; you should often be able to just plug this in with minimal changes. Just remember that KURL url and QString file have been declared.


Example 6.10. Complete Network Transparency Example

   1 
   2  1: #include <ktempfile.h>
   3  2:
   4  3: void MainWindow::slotSaveAs()
   5  4: {
   6  5:   url=KFileDialog::getSaveUrl(0,
   7  6:   "*.txt|Text Files (*.txt)\n*.cpp|C++ Source (*.cpp)",
   8  7:     this)
   9  8:   file=url.path();
  10  9:
  11 10:   if (!file.isLocalPath())
  12 11:   {
  13 12:     KTempFile temp;
  14 13:     file=temp.name(); // Get somewhere local to write to
  15 14:
  16 15:     slotSave(); // write to that
  17 16:     temp.unlink();
  18 17:     return;
  19 18:   }
  20 19:   // As of here, the url will always be local, which means
  21 20:   // that file contains the local path of the file to save!
  22 21:   // So lets just save it!
  23 22:   slotSave();
  24 23: }
  25 24:
  26 25: void MainWindow::slotSave()
  27 26: {
  28 27:   // Looks like there isn't a selected file yet!
  29 28:   if (url.isEmpty() || file.isEmpty())
  30 29:     slotSaveAs(), return;
  31 30:
  32 31:   // Lets save the file.
  33 32:   QFile f(file);
  34 33:
  35 34:   // IO_Truncate purges the file so we start with a
  36 35:   // clean slate
  37 36:   if (!f.open(IO_WriteOnly | IO_Truncate))
  38 37:     KNotifyClient::event("cannotopenfile"), return;
  39 38:
  40 39:   QTextStream t( &f );
  41 40:   // QDataStream may be more appropriate for some
  42 41:   // purposes, check the QT documentation for all your
  43 42:   // file-storing needs.
  44 43:   t << "The filename that was stored is " << file << '\n';
  45 44:
  46 45:   f.close();
  47 46:
  48 47:   // TODO: Set a flag, telling you that this file is
  49 48:   // currently saved.
  50 49: }
  51 50:
  52 51: void MainWindow::slotOpen()
  53 52: {
  54 53:   if ( /* TODO: test if the currently opened file needs to be saved */ )
  55 54:   { // User already has a file open! What does this
  56 55:     // person want to do with this file?
  57 56:     int result=KMessageBox::questionYesNo(this,
  58 57:        i18n("You already have a file open! Would you"
  59 58:             "like to save the currently "
  60 59:             "opened file and open another?"),
  61 60:        i18n("Continue?"));
  62 61:
  63 62:    if (result==KMessageBox::Yes)
  64 63:      slotSave();
  65 64:    else
  66 65:      return;
  67 66:   }
  68 67:
  69 68:   url=KFileDialog::getOpenURL(0,
  70 69:     "*.txt|Text Files (*.txt)\n*.cpp|C++ Source(*.cpp)",
  71 70:     this);
  72 71:
  73 72:   if (!KIO::NetAccess::download(url, file))
  74 73:     KNotifyClient::event("cannotopenfile"), return;
  75 74:
  76 75:   QFile f(file);
  77 76:   if (!f.open(IO_ReadOnly))
  78 77:     KNotifyClient::event("cannotopenfile"), return;
  79 78:
  80 79:   QTextStream t( &f );
  81 80:   QString dataFromFile;
  82 81:   t>>dataFromFile;
  83 82:   // TODO: Do something with the data!
  84 83:
  85 84:   f.close();
  86 85: }
  87