openvfs-rb 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e4e0c990813542ab1b0b2aee640ffe25e13b865ec89300f22e796a37251f37f
4
- data.tar.gz: 618bec06ee55f463316af80cb2cfad9e02b21a66748629d070d087c6dc2a645f
3
+ metadata.gz: 47b056c85a99f2ed491a6291f7298d23e02d4ab34c56820b2f0b00b8534d896e
4
+ data.tar.gz: fda56bd491099b36f454fdf2e6842e3bb74505715d0146c8252b72e18394b120
5
5
  SHA512:
6
- metadata.gz: 11ec8556f9b9e44533591404eee4ffc900b2a615918972f9d8be968741ec13123a8de10d2cf49509ed98cf35b82cb8beda73c675867926666e6076401537e803
7
- data.tar.gz: 9988ae322baa3fbd3a71edabe1db176f025172fb2ff4477714df88bff8942e4e6f2bc4bf1cbae14cf4ba25c686208482fc312346b753d632ec1af3fd557f1bb3
6
+ metadata.gz: bd63d9c279decfeb6f6a1d97924fbd5ecb51e766f45b7a04529ce8e7d8058d71fe532d34abfa4b4a84f02331e3509bf587bb08d8ad5013054fa480fe34382a34
7
+ data.tar.gz: ae047f5301ee535a2664aaf2c76bb60a447274a889320aa4d196fb4e4a26d23cb76386224c1a8711bac72ed1cb8aadbbc911222409cb569374438a3cdc90c750
@@ -1,15 +1,18 @@
1
1
  // Rice bindings for OpenCloud Desktop.
2
2
  //
3
- // Only two classes are wrapped: OCC::Account and OCC::CredentialManager, plus the types
4
- // their methods take and return, and OCC::init - the desktop's own entry point, with the
5
- // UI patched out. Nothing here adds behaviour that libsync does not already have.
3
+ // What is wrapped: OCC::Account and OCC::CredentialManager, OCC::ProgressDispatcher and the
4
+ // Folder, SyncFileItem, ProgressInfo and Estimates its signals carry, plus the types all of
5
+ // their methods take and return, and OCC::init - the desktop's own entry point, with the UI
6
+ // patched out. Nothing here adds behaviour that libsync does not already have.
6
7
  //
7
8
  // is_convertible returns a double score, matching Rice 4.12.0's own converters in
8
9
  // stl.hpp; Rice's published docs still describe an older enum form.
9
10
 
10
11
  // Qt comes before Ruby, and the order is load-bearing on Windows: ruby.h defines truncate and access as macros onto its own win32 replacements, and Qt's headers stop with an #error rather than be parsed after that.
12
+ #include <gui/folder.h>
11
13
  #include <libsync/account.h>
12
14
  #include <libsync/creds/credentialmanager.h>
15
+ #include <libsync/progressdispatcher.h>
13
16
 
14
17
  #include <qt6keychain/keychain.h>
15
18
 
@@ -450,6 +453,58 @@ QVariant credential_get(OCC::CredentialManager &manager, const QString &key)
450
453
 
451
454
  return job->data();
452
455
  }
456
+
457
+ // ProgressDispatcher's whole interface is four Qt signals, and the Ruby side of each one is
458
+ // a block. Rice always turns a block into a proc and passes it as a trailing VALUE parameter
459
+ // marked Arg(...).setValue(); Object(proc).call("call", ...) then invokes it with the
460
+ // arguments converted by To_Ruby. Both halves are the documented
461
+ // square_with_proc/invokeFunction pattern, only with a Qt connection in between.
462
+ //
463
+ // The proc has to outlive the subscribing call, so each lambda captures a Rice::Pin, whose
464
+ // documented use is exactly "callback adapters that capture a Ruby proc". Pin's copy
465
+ // semantics share one GC anchor, so every copy Qt takes of the lambda keeps the same proc
466
+ // alive. Nothing disconnects: the dispatcher is a singleton and Rice does not free callback
467
+ // wrappers either, for the same reason - C++ may call back at any time.
468
+
469
+ void on_progress_info(OCC::ProgressDispatcher &self, VALUE callback)
470
+ {
471
+ Rice::Pin pin(callback);
472
+ QObject::connect(&self, &OCC::ProgressDispatcher::progressInfo,
473
+ [pin](OCC::Folder *folder, const OCC::ProgressInfo &progress) {
474
+ Object(pin.value()).call("call", folder, progress);
475
+ });
476
+ }
477
+
478
+ void on_item_completed(OCC::ProgressDispatcher &self, VALUE callback)
479
+ {
480
+ Rice::Pin pin(callback);
481
+ QObject::connect(&self, &OCC::ProgressDispatcher::itemCompleted,
482
+ [pin](OCC::Folder *folder, const OCC::SyncFileItemPtr &item) {
483
+ // By value, not by reference: a reference would wrap the signal's own
484
+ // QSharedPointer, which is gone once the emission returns. A copy is what Ruby
485
+ // frees, and copying a QSharedPointer is what holds the SyncFileItem open for as
486
+ // long as the block keeps it.
487
+ Object(pin.value()).call("call", folder, OCC::SyncFileItemPtr(item));
488
+ });
489
+ }
490
+
491
+ void on_sync_error(OCC::ProgressDispatcher &self, VALUE callback)
492
+ {
493
+ Rice::Pin pin(callback);
494
+ QObject::connect(&self, &OCC::ProgressDispatcher::syncError,
495
+ [pin](OCC::Folder *folder, const QString &message, OCC::ErrorCategory category) {
496
+ Object(pin.value()).call("call", folder, message, category);
497
+ });
498
+ }
499
+
500
+ void on_folder_conflicts(OCC::ProgressDispatcher &self, VALUE callback)
501
+ {
502
+ Rice::Pin pin(callback);
503
+ QObject::connect(&self, &OCC::ProgressDispatcher::folderConflicts,
504
+ [pin](OCC::Folder *folder, const QStringList &conflictPaths) {
505
+ Object(pin.value()).call("call", folder, conflictPaths);
506
+ });
507
+ }
453
508
  }
454
509
 
455
510
  extern "C" void Init_occ()
@@ -498,5 +553,147 @@ extern "C" void Init_occ()
498
553
  .define_method("url=", [](OCC::AccountPtr &self, const QUrl &url) { self->setUrl(url); }, Arg("url"))
499
554
  .define_method("credential_manager", [](const OCC::AccountPtr &self) { return self->credentialManager(); },
500
555
  Return().keepAlive());
556
+
557
+ // -----------------------------------------------------------------------------------------
558
+ // OCC::Folder - the sync folder a progress signal is about. Wrapped for its name and
559
+ // path only; the dispatcher hands out Folder pointers and Ruby needs to tell them apart.
560
+ //
561
+ // No define_constructor: folders are created by the desktop's FolderMan, never by Ruby,
562
+ // and a wrapped class without a constructor is simply one Ruby cannot instantiate.
563
+ // -----------------------------------------------------------------------------------------
564
+
565
+ Data_Type<OCC::Folder> rb_cFolder =
566
+ define_class_under<OCC::Folder>(rb_mOpenVFS, "Folder")
567
+ .define_method("display_name", &OCC::Folder::displayName)
568
+ .define_method("path", &OCC::Folder::path)
569
+ .define_method("clean_path", &OCC::Folder::cleanPath)
570
+ .define_method("short_gui_local_path", &OCC::Folder::shortGuiLocalPath)
571
+ .define_method("sync_running?", &OCC::Folder::isSyncRunning);
572
+
573
+ // -----------------------------------------------------------------------------------------
574
+ // OCC::SyncFileItem - one file in a sync run.
575
+ //
576
+ // As with Account, what gets wrapped is the QSharedPointer rather than what it points at,
577
+ // so the reference count keeps the item alive while Ruby holds it. The methods therefore
578
+ // take the pointer and dereference it.
579
+ // -----------------------------------------------------------------------------------------
580
+
581
+ Data_Type<OCC::SyncFileItemPtr> rb_cSyncFileItem =
582
+ define_class_under<OCC::SyncFileItemPtr>(rb_mOpenVFS, "SyncFileItem")
583
+ .define_method("local_name", [](const OCC::SyncFileItemPtr &self) { return self->localName(); })
584
+ .define_method("destination", [](const OCC::SyncFileItemPtr &self) { return self->destination(); })
585
+ .define_method("rename_target", [](const OCC::SyncFileItemPtr &self) { return self->_renameTarget; })
586
+ .define_method("original_file", [](const OCC::SyncFileItemPtr &self) { return self->_originalFile; })
587
+ .define_method("status", [](const OCC::SyncFileItemPtr &self) { return self->_status; })
588
+ .define_method("direction", [](const OCC::SyncFileItemPtr &self) { return self->_direction; })
589
+ .define_method("error_string", [](const OCC::SyncFileItemPtr &self) { return self->_errorString; })
590
+ .define_method("message_string", [](const OCC::SyncFileItemPtr &self) { return self->_messageString; })
591
+ .define_method("http_error_code", [](const OCC::SyncFileItemPtr &self) { return self->_httpErrorCode; })
592
+ .define_method("affected_items", [](const OCC::SyncFileItemPtr &self) { return self->_affectedItems; })
593
+ .define_method("size", [](const OCC::SyncFileItemPtr &self) { return self->_size; })
594
+ .define_method("modtime", [](const OCC::SyncFileItemPtr &self) { return self->_modtime; })
595
+ .define_method("etag", [](const OCC::SyncFileItemPtr &self) { return self->_etag; })
596
+ .define_method("empty?", [](const OCC::SyncFileItemPtr &self) { return self->isEmpty(); })
597
+ .define_method("directory?", [](const OCC::SyncFileItemPtr &self) { return self->isDirectory(); })
598
+ .define_method("error_status?", [](const OCC::SyncFileItemPtr &self) { return self->hasErrorStatus(); })
599
+ // OCC::Progress's two free functions turn an item into the line the desktop's own
600
+ // UI would show for it.
601
+ .define_method("action_string", [](const OCC::SyncFileItemPtr &self) { return OCC::Progress::asActionString(*self); })
602
+ .define_method("result_string", [](const OCC::SyncFileItemPtr &self) { return OCC::Progress::asResultString(*self); })
603
+ .define_method("warning_kind?", [](const OCC::SyncFileItemPtr &self) { return OCC::Progress::isWarningKind(self->_status); })
604
+ .define_method("ignored_kind?", [](const OCC::SyncFileItemPtr &self) { return OCC::Progress::isIgnoredKind(self->_status); });
605
+
606
+ Enum<OCC::SyncFileItem::Status> rb_eSyncFileItemStatus =
607
+ define_enum_under<OCC::SyncFileItem::Status>("Status", rb_cSyncFileItem)
608
+ .define_value("NoStatus", OCC::SyncFileItem::NoStatus)
609
+ .define_value("FatalError", OCC::SyncFileItem::FatalError)
610
+ .define_value("NormalError", OCC::SyncFileItem::NormalError)
611
+ .define_value("SoftError", OCC::SyncFileItem::SoftError)
612
+ .define_value("Success", OCC::SyncFileItem::Success)
613
+ .define_value("Conflict", OCC::SyncFileItem::Conflict)
614
+ .define_value("FileIgnored", OCC::SyncFileItem::FileIgnored)
615
+ .define_value("Restoration", OCC::SyncFileItem::Restoration)
616
+ .define_value("DetailError", OCC::SyncFileItem::DetailError)
617
+ .define_value("BlacklistedError", OCC::SyncFileItem::BlacklistedError)
618
+ .define_value("Excluded", OCC::SyncFileItem::Excluded)
619
+ .define_value("Message", OCC::SyncFileItem::Message)
620
+ .define_value("FilenameReserved", OCC::SyncFileItem::FilenameReserved);
621
+
622
+ Enum<OCC::SyncFileItem::Direction> rb_eSyncFileItemDirection =
623
+ define_enum_under<OCC::SyncFileItem::Direction>("Direction", rb_cSyncFileItem)
624
+ .define_value("None", OCC::SyncFileItem::None)
625
+ .define_value("Up", OCC::SyncFileItem::Up)
626
+ .define_value("Down", OCC::SyncFileItem::Down);
627
+
628
+ // -----------------------------------------------------------------------------------------
629
+ // OCC::ProgressInfo - the payload of the progressInfo signal.
630
+ // -----------------------------------------------------------------------------------------
631
+
632
+ // Estimates is a plain struct of two public members, which is what define_attr is for.
633
+ // Read-only: it is a snapshot the dispatcher computed, so writing to it means nothing.
634
+ Data_Type<OCC::ProgressInfo::Estimates> rb_cEstimates =
635
+ define_class_under<OCC::ProgressInfo::Estimates>(rb_mOpenVFS, "Estimates")
636
+ .define_attr("estimated_bandwidth", &OCC::ProgressInfo::Estimates::estimatedBandwidth, Rice::AttrAccess::Read)
637
+ .define_attr("estimated_eta", &OCC::ProgressInfo::Estimates::estimatedEta, Rice::AttrAccess::Read);
638
+
639
+ Data_Type<OCC::ProgressInfo> rb_cProgressInfo =
640
+ define_class_under<OCC::ProgressInfo>(rb_mOpenVFS, "ProgressInfo")
641
+ .define_method("status", &OCC::ProgressInfo::status)
642
+ .define_method("updating_estimates?", &OCC::ProgressInfo::isUpdatingEstimates)
643
+ .define_method("total_files", &OCC::ProgressInfo::totalFiles)
644
+ .define_method("completed_files", &OCC::ProgressInfo::completedFiles)
645
+ .define_method("total_size", &OCC::ProgressInfo::totalSize)
646
+ .define_method("completed_size", &OCC::ProgressInfo::completedSize)
647
+ .define_method("current_file", &OCC::ProgressInfo::currentFile)
648
+ // Estimates comes back by value, so Rice copy-constructs it and Ruby frees the copy.
649
+ .define_method("total_progress", &OCC::ProgressInfo::totalProgress)
650
+ .define_method("optimistic_eta", &OCC::ProgressInfo::optimisticEta)
651
+ .define_method("trust_eta?", &OCC::ProgressInfo::trustEta)
652
+ .define_method("file_progress", [](const OCC::ProgressInfo &self, const OCC::SyncFileItemPtr &item) {
653
+ return self.fileProgress(*item);
654
+ }, Arg("item"))
655
+ .define_method("current_discovered_remote_folder", [](const OCC::ProgressInfo &self) {
656
+ return self._currentDiscoveredRemoteFolder;
657
+ })
658
+ .define_method("current_discovered_local_folder", [](const OCC::ProgressInfo &self) {
659
+ return self._currentDiscoveredLocalFolder;
660
+ })
661
+ // _lastCompletedItem is a SyncFileItem value, and SyncFileItem is wrapped through
662
+ // its QSharedPointer, so hand back a copy in one rather than a reference into a
663
+ // ProgressInfo that only lives for the duration of the signal.
664
+ .define_method("last_completed_item", [](const OCC::ProgressInfo &self) {
665
+ return OCC::SyncFileItemPtr::create(self._lastCompletedItem);
666
+ });
667
+
668
+ Enum<OCC::ProgressInfo::Status> rb_eProgressInfoStatus =
669
+ define_enum_under<OCC::ProgressInfo::Status>("Status", rb_cProgressInfo)
670
+ .define_value("None", OCC::ProgressInfo::None)
671
+ .define_value("Discovery", OCC::ProgressInfo::Discovery)
672
+ .define_value("Reconcile", OCC::ProgressInfo::Reconcile)
673
+ .define_value("Propagation", OCC::ProgressInfo::Propagation)
674
+ .define_value("Done", OCC::ProgressInfo::Done);
675
+
676
+ Enum<OCC::ErrorCategory> rb_eErrorCategory =
677
+ define_enum_under<OCC::ErrorCategory>("ErrorCategory", rb_mOpenVFS)
678
+ .define_value("Normal", OCC::ErrorCategory::Normal)
679
+ .define_value("InsufficientRemoteStorage", OCC::ErrorCategory::InsufficientRemoteStorage);
680
+
681
+ // -----------------------------------------------------------------------------------------
682
+ // OCC::ProgressDispatcher - the singleton every sync progress signal comes through.
683
+ //
684
+ // instance() is a static member function, so define_singleton_function. It returns a
685
+ // pointer and Rice's default is that C++ keeps ownership, which is what a singleton
686
+ // wants - no Return().takeOwnership() here, or Ruby would free the one instance.
687
+ //
688
+ // Each on_* method subscribes a block; see the helpers above for how.
689
+ // -----------------------------------------------------------------------------------------
690
+
691
+ Data_Type<OCC::ProgressDispatcher> rb_cProgressDispatcher =
692
+ define_class_under<OCC::ProgressDispatcher>(rb_mOpenVFS, "ProgressDispatcher")
693
+ .define_singleton_function("instance", &OCC::ProgressDispatcher::instance)
694
+ .define_method("on_progress_info", &on_progress_info, Arg("callback").setValue())
695
+ .define_method("on_item_completed", &on_item_completed, Arg("callback").setValue())
696
+ .define_method("on_sync_error", &on_sync_error, Arg("callback").setValue())
697
+ .define_method("on_folder_conflicts", &on_folder_conflicts, Arg("callback").setValue());
501
698
  });
502
699
  }
@@ -5,6 +5,6 @@
5
5
 
6
6
  module OpenVFS
7
7
  module Rb
8
- VERSION = "1.0.0"
8
+ VERSION = "1.1.0"
9
9
  end
10
10
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openvfs-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Kidd
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 1980-01-01 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: gem_kit