VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/ui/VBoxSnapshotsWgt.ui.h@ 2671

Last change on this file since 2671 was 2567, checked in by vboxsync, 18 years ago

Main & All Frontends: replaced the IGuestOSType IMachine::OSType property with the wstring IMachine::OSTypeId property (+ converted IGuest and IGuestOSType to VirtualBoxBaseNEXT semantics).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.7 KB
Line 
1/**
2 *
3 * VBox frontends: Qt GUI ("VirtualBox"):
4 * Snapshot details dialog (Qt Designer)
5 */
6
7/*
8 * Copyright (C) 2006 InnoTek Systemberatung GmbH
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * If you received this file as part of a commercial VirtualBox
19 * distribution, then only the terms of your commercial VirtualBox
20 * license agreement apply instead of the previous paragraph.
21 */
22
23/****************************************************************************
24** ui.h extension file, included from the uic-generated form implementation.
25**
26** If you want to add, delete, or rename functions or slots, use
27** Qt Designer to update this file, preserving your code.
28**
29** You should not define a constructor or destructor in this file.
30** Instead, write your code in functions called init() and destroy().
31** These will automatically be called by the form's constructor and
32** destructor.
33*****************************************************************************/
34
35/** QListViewItem subclass for snapshots */
36class VBoxSnapshotsWgt::ListViewItem : public QListViewItem
37{
38public:
39
40 /** Normal snapshot item */
41 ListViewItem (QListView *lv, const CSnapshot &aSnapshot)
42 : QListViewItem (lv)
43 , mBld (false), mItal (false)
44 , mSnapshot (aSnapshot)
45 {
46 recache();
47 }
48
49 /** Normal snapshot item */
50 ListViewItem (QListViewItem *lvi, const CSnapshot &aSnapshot)
51 : QListViewItem (lvi)
52 , mBld (false), mItal (false)
53 , mSnapshot (aSnapshot)
54 {
55 recache();
56 }
57
58 /** Current state item */
59 ListViewItem (QListView *lv, const CMachine &aMachine)
60 : QListViewItem (lv)
61 , mBld (false), mItal (true)
62 , mMachine (aMachine)
63 {
64 recache();
65 updateCurrentState (mMachine.GetState());
66 }
67
68 /** Current state item */
69 ListViewItem (QListViewItem *lvi, const CMachine &aMachine)
70 : QListViewItem (lvi)
71 , mBld (false), mItal (true)
72 , mMachine (aMachine)
73 {
74 recache();
75 updateCurrentState (mMachine.GetState());
76 }
77
78 bool bold() const { return mBld; }
79 void setBold (bool bold)
80 {
81 mBld = bold;
82 repaint();
83 }
84
85 bool italic() const { return mItal; }
86 void setItalic (bool italic)
87 {
88 mItal = italic;
89 repaint();
90 }
91
92 void paintCell (QPainter *p, const QColorGroup &cg, int column, int width, int align)
93 {
94 QFont font = p->font();
95 if (font.bold() != mBld)
96 font.setBold (mBld);
97 if (font.italic() != mItal)
98 font.setItalic (mItal);
99 if (font != p->font())
100 p->setFont (font);
101 QListViewItem::paintCell (p, cg, column, width, align);
102 }
103
104 int width (const QFontMetrics &fm, const QListView *lv, int c) const
105 {
106 QFont font = lv->font();
107 if (font.bold() != mBld)
108 font.setBold (mBld);
109 if (font.italic() != mItal)
110 font.setItalic (mItal);
111 if (font != lv->font())
112 return QListViewItem::width (QFontMetrics (font), lv, c);
113 return QListViewItem::width (fm, lv, c);
114 }
115
116 CSnapshot snapshot() const { return mSnapshot; }
117 QUuid snapshotId() const { return mId; }
118
119 CEnums::MachineState machineState() const { return mMachineState; }
120
121 void recache()
122 {
123 if (!mSnapshot.isNull())
124 {
125 mId = mSnapshot.GetId();
126 setText (0, mSnapshot.GetName());
127 mOnline = mSnapshot.GetOnline();
128 setPixmap (0, vboxGlobal().snapshotIcon (mOnline));
129 mDesc = mSnapshot.GetDescription();
130 mTimestamp.setTime_t (mSnapshot.GetTimeStamp() / 1000);
131 mCurStateModified = false;
132 }
133 else
134 {
135 Assert (!mMachine.isNull());
136 mCurStateModified = mMachine.GetCurrentStateModified();
137 setText (0, mCurStateModified ?
138 VBoxSnapshotsWgt::tr ("Current State (changed)",
139 "Current State (Modified)") :
140 VBoxSnapshotsWgt::tr ("Current State",
141 "Current State (Unmodified)"));
142 mDesc = mCurStateModified ?
143 VBoxSnapshotsWgt::tr ("The current state differs from the state "
144 "stored in the current snapshot") :
145 parent() != 0 ? /* we're not the only item in the view */
146 VBoxSnapshotsWgt::tr ("The current state is identical to the state "
147 "stored in the current snapshot") :
148 QString::null;
149 }
150 }
151
152 void updateCurrentState (CEnums::MachineState aState)
153 {
154 AssertReturn (!mMachine.isNull(), (void) 0);
155 setPixmap (0, vboxGlobal().toIcon (aState));
156 mMachineState = aState;
157 mTimestamp.setTime_t (mMachine.GetLastStateChange() / 1000);
158 }
159
160 QString toolTipText() const
161 {
162 QString name = !mSnapshot.isNull() ?
163 text (0) : text (0);
164
165 bool dateTimeToday = mTimestamp.date() == QDate::currentDate();
166 QString dateTime = dateTimeToday ?
167 mTimestamp.time().toString (Qt::LocalDate) :
168 mTimestamp.toString (Qt::LocalDate);
169
170 QString details;
171 if (!mSnapshot.isNull())
172 {
173 /* the current snapshot is always bold */
174 if (mBld)
175 details = VBoxSnapshotsWgt::tr (" (current, ", "Snapshot details");
176 else
177 details = " (";
178 details += mOnline ? VBoxSnapshotsWgt::tr ("online)", "Snapshot details")
179 : VBoxSnapshotsWgt::tr ("offline)", "Snapshot details");
180
181 if (dateTimeToday)
182 dateTime = VBoxSnapshotsWgt::tr ("Taken at %1", "Snapshot (time)")
183 .arg (dateTime);
184 else
185 dateTime = VBoxSnapshotsWgt::tr ("Taken on %1", "Snapshot (date + time)")
186 .arg (dateTime);
187 }
188 else
189 {
190 dateTime = VBoxSnapshotsWgt::tr ("%1 since %2", "Current State (time or date + time)")
191 .arg (vboxGlobal().toString (mMachineState))
192 .arg (dateTime);
193 }
194
195 QString toolTip = QString ("<nobr><b>%1</b>%2</nobr><br><nobr>%3</nobr>")
196 .arg (name) .arg (details)
197 .arg (dateTime);
198
199 if (!mDesc.isEmpty())
200 toolTip += "<br><hr>" + mDesc;
201
202 return toolTip;
203 }
204
205 void okRename (int aCol)
206 {
207 QListViewItem::okRename (aCol);
208 AssertReturn (aCol == 0 && !mSnapshot.isNull(), (void) 0);
209 mSnapshot.SetName (text (0));
210 }
211
212private:
213
214 bool mBld : 1;
215 bool mItal : 1;
216
217 CSnapshot mSnapshot;
218 CMachine mMachine;
219
220 QUuid mId;
221 bool mOnline;
222 QString mDesc;
223 QDateTime mTimestamp;
224
225 bool mCurStateModified;
226 CEnums::MachineState mMachineState;
227};
228
229////////////////////////////////////////////////////////////////////////////////
230
231/** Tooltips for snapshots */
232class VBoxSnapshotsWgt::ToolTip : public QToolTip
233{
234public:
235
236 ToolTip (QListView *aLV, QWidget *aParent, QToolTipGroup *aTG = 0)
237 : QToolTip (aParent, aTG), mLV (aLV)
238 {}
239
240 virtual ~ToolTip()
241 {
242 remove (parentWidget());
243 }
244
245 void maybeTip (const QPoint &aPnt);
246
247private:
248
249 QListView *mLV;
250};
251
252void VBoxSnapshotsWgt::ToolTip::maybeTip (const QPoint &aPnt)
253{
254 ListViewItem *lvi = static_cast <ListViewItem *> (mLV->itemAt (aPnt));
255 if (!lvi)
256 return;
257
258 if (parentWidget()->topLevelWidget()->inherits ("QMainWindow"))
259 {
260 /*
261 * Ensure the main window doesn't show the text from the previous
262 * tooltip in the status bar.
263 */
264 QToolTipGroup *toolTipGroup =
265 (::qt_cast <QMainWindow *> (parentWidget()->topLevelWidget()))->
266 toolTipGroup();
267 if (toolTipGroup)
268 {
269 int index = toolTipGroup->metaObject()->findSignal("removeTip()", false);
270 toolTipGroup->qt_emit (index, 0);
271 }
272 }
273
274 tip (mLV->itemRect (lvi), lvi->toolTipText());
275}
276
277////////////////////////////////////////////////////////////////////////////////
278
279void VBoxSnapshotsWgt::init()
280{
281 mCurSnapshotItem = 0;
282
283 listView->setItemMargin (2);
284 listView->header()->hide();
285 listView->setRootIsDecorated (true);
286 /* we have our own tooltips */
287 listView->setShowToolTips (false);
288 /* disable sorting */
289 listView->setSorting (-1);
290 /* disable unselecting items by clicking in the unused area of the list */
291 new QIListViewSelectionPreserver (this, listView);
292
293 /* toolbar */
294 VBoxToolBar *toolBar = new VBoxToolBar (0, this, "snapshotToolBar");
295
296 curStateActionGroup->addTo (toolBar);
297 toolBar->addSeparator();
298 snapshotActionGroup->addTo (toolBar);
299 toolBar->addSeparator();
300 showSnapshotDetailsAction->addTo (toolBar);
301
302 toolBar->setUsesTextLabel (false);
303 toolBar->setUsesBigPixmaps (true);
304 toolBar->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed);
305 VBoxSnapshotsWgtLayout->insertWidget (0, toolBar);
306#ifdef Q_WS_MAC
307 toolBar->setMacStyle();
308#endif
309
310 /* context menu */
311 mContextMenu = new QPopupMenu (this);
312 mContextMenuDirty = true;
313
314 /* icons */
315 discardSnapshotAction->setIconSet (VBoxGlobal::iconSetEx (
316 "discard_snapshot_22px.png", "discard_snapshot_16px.png",
317 "discard_snapshot_dis_22px.png", "discard_snapshot_dis_16px.png"));
318 takeSnapshotAction->setIconSet (VBoxGlobal::iconSetEx (
319 "take_snapshot_22px.png", "take_snapshot_16px.png",
320 "take_snapshot_dis_22px.png", "take_snapshot_dis_16px.png"));
321 discardCurStateAction->setIconSet (VBoxGlobal::iconSetEx (
322 "discard_cur_state_22px.png", "discard_cur_state_16px.png",
323 "discard_cur_state_dis_22px.png", "discard_cur_state_dis_16px.png"));
324 discardCurSnapAndStateAction->setIconSet (VBoxGlobal::iconSetEx (
325 "discard_cur_state_snapshot_22px.png", "discard_cur_state_snapshot_16px.png",
326 "discard_cur_state_snapshot_dis_22px.png", "discard_cur_state_snapshot_dis_16px.png"));
327 showSnapshotDetailsAction->setIconSet (VBoxGlobal::iconSetEx (
328 "show_snapshot_details_22px.png", "show_snapshot_details_16px.png",
329 "show_snapshot_details_dis_22px.png", "show_snapshot_details_dis_16px.png"));
330
331 /* tooltip */
332 mToolTip = new ToolTip (listView, listView->viewport());
333}
334
335void VBoxSnapshotsWgt::destroy()
336{
337 delete mToolTip;
338}
339
340void VBoxSnapshotsWgt::setMachine (const CMachine &aMachine)
341{
342 mMachine = aMachine;
343
344 if (aMachine.isNull())
345 {
346 mMachineId = QUuid();
347 mSessionState = CEnums::InvalidSessionState;
348 }
349 else
350 {
351 mMachineId = aMachine.GetId();
352 mSessionState = aMachine.GetSessionState();
353 }
354
355 refreshAll();
356}
357
358VBoxSnapshotsWgt::ListViewItem *VBoxSnapshotsWgt::findItem (const QUuid &aSnapshotId)
359{
360 QListViewItemIterator it (listView);
361 while (it.current())
362 {
363 ListViewItem *lvi = static_cast <ListViewItem *> (it.current());
364 if (lvi->snapshotId() == aSnapshotId)
365 return lvi;
366 ++ it;
367 }
368
369 return 0;
370}
371
372void VBoxSnapshotsWgt::refreshAll (bool aKeepSelected /* = false */)
373{
374 QUuid selected, selectedFirstChild;
375 if (aKeepSelected)
376 {
377 ListViewItem *cur = static_cast <ListViewItem *> (listView->selectedItem());
378 Assert (cur);
379 if (cur)
380 {
381 selected = cur->snapshotId();
382 if (cur->firstChild())
383 selectedFirstChild =
384 static_cast <ListViewItem *> (cur->firstChild())->snapshotId();
385 }
386 }
387
388 listView->clear();
389
390 if (mMachine.isNull())
391 {
392 listView_currentChanged (NULL);
393 return;
394 }
395
396 /* get the first snapshot */
397 if (mMachine.GetSnapshotCount() > 0)
398 {
399 CSnapshot snapshot = mMachine.GetSnapshot (QUuid());
400
401 populateSnapshots (snapshot, 0);
402 Assert (mCurSnapshotItem);
403
404 /* add the "current state" item */
405 new ListViewItem (mCurSnapshotItem, mMachine);
406
407 ListViewItem *cur = 0;
408 if (aKeepSelected)
409 {
410 cur = findItem (selected);
411 if (cur == 0)
412 cur = findItem (selectedFirstChild);
413 }
414 if (cur == 0)
415 cur = curStateItem();
416 listView->setSelected (cur, true);
417 listView->ensureItemVisible (cur);
418 }
419 else
420 {
421 mCurSnapshotItem = NULL;
422
423 /* add the "current state" item */
424 ListViewItem *csi = new ListViewItem (listView, mMachine);
425
426 listView->setSelected (csi, true);
427 /*
428 * stupid Qt doesn't issue this signal when only one item is added
429 * to the empty list -- do it manually
430 */
431 listView_currentChanged (csi);
432 }
433
434 listView->adjustColumn (0);
435}
436
437VBoxSnapshotsWgt::ListViewItem *VBoxSnapshotsWgt::curStateItem()
438{
439 QListViewItem *csi = mCurSnapshotItem ? mCurSnapshotItem->firstChild()
440 : listView->firstChild();
441 Assert (csi);
442 return static_cast <ListViewItem *> (csi);
443}
444
445void VBoxSnapshotsWgt::populateSnapshots (const CSnapshot &snapshot, QListViewItem *item)
446{
447
448 ListViewItem *si = 0;
449 if (item)
450 si = new ListViewItem (item, snapshot);
451 else
452 si = new ListViewItem (listView, snapshot);
453
454 if (mMachine.GetCurrentSnapshot().GetId() == snapshot.GetId())
455 {
456 si->setBold (true);
457 mCurSnapshotItem = si;
458 }
459
460 CSnapshotEnumerator en = snapshot.GetChildren().Enumerate();
461 while (en.HasMore())
462 {
463 CSnapshot sn = en.GetNext();
464 populateSnapshots (sn, si);
465 }
466
467 si->setOpen (true);
468 si->setRenameEnabled (0, true);
469}
470
471void VBoxSnapshotsWgt::listView_currentChanged (QListViewItem *item)
472{
473 if (item)
474 listView->ensureItemVisible (item);
475
476 /* whether another direct session is open or not */
477 bool busy = mSessionState != CEnums::SessionClosed;
478
479 /* enable/disable snapshot actions */
480 snapshotActionGroup->setEnabled (!busy &&
481 item && mCurSnapshotItem && item != mCurSnapshotItem->firstChild());
482
483 /* enable/disable the details action regardles of the session state */
484 showSnapshotDetailsAction->setEnabled (
485 item && mCurSnapshotItem && item != mCurSnapshotItem->firstChild());
486
487 /* enable/disable current state actions */
488 curStateActionGroup->setEnabled (!busy &&
489 item && mCurSnapshotItem && item == mCurSnapshotItem->firstChild());
490
491 /* the Take Snapshot action is always enabled for the current state */
492 takeSnapshotAction->setEnabled (!busy && curStateActionGroup->isEnabled() ||
493 (item && !mCurSnapshotItem));
494
495 mContextMenuDirty = true;
496}
497
498void VBoxSnapshotsWgt::
499listView_contextMenuRequested (QListViewItem *item, const QPoint &pnt,
500 int /* col */)
501{
502 if (!item)
503 return;
504
505 if (mContextMenuDirty)
506 {
507 mContextMenu->clear();
508
509 if (!mCurSnapshotItem)
510 {
511 /* we have only one item -- current state */
512 curStateActionGroup->addTo (mContextMenu);
513 }
514 else
515 {
516 if (item == mCurSnapshotItem->firstChild())
517 {
518 /* current state is selected */
519 curStateActionGroup->addTo (mContextMenu);
520 }
521 else
522 {
523 /* snapshot is selected */
524 snapshotActionGroup->addTo (mContextMenu);
525 mContextMenu->insertSeparator();
526 showSnapshotDetailsAction->addTo (mContextMenu);
527 }
528 }
529
530 mContextMenuDirty = false;
531 }
532
533 mContextMenu->exec (pnt);
534}
535
536void VBoxSnapshotsWgt::discardSnapshot()
537{
538 ListViewItem *item = static_cast <ListViewItem *> (listView->currentItem());
539 AssertReturn (item, (void) 0);
540
541 QUuid snapId = item->snapshotId();
542 AssertReturn (!snapId.isNull(), (void) 0);
543
544 /* open a direct session (this call will handle all errors) */
545 CSession session = vboxGlobal().openSession (mMachineId);
546 if (session.isNull())
547 return;
548
549 CConsole console = session.GetConsole();
550 CProgress progress = console.DiscardSnapshot (snapId);
551 if (console.isOk())
552 {
553 /* show the progress dialog */
554 vboxProblem().showModalProgressDialog (progress, mMachine.GetName(),
555 vboxProblem().mainWindowShown());
556
557 if (progress.GetResultCode() != 0)
558 vboxProblem().cannotDiscardSnapshot (progress, mMachine.GetSnapshot (snapId));
559 }
560 else
561 vboxProblem().cannotDiscardSnapshot (console, mMachine.GetSnapshot (snapId));
562
563 session.Close();
564}
565
566void VBoxSnapshotsWgt::takeSnapshot()
567{
568 ListViewItem *item = static_cast <ListViewItem *> (listView->currentItem());
569 AssertReturn (item, (void) 0);
570
571 VBoxTakeSnapshotDlg dlg (this, "VBoxTakeSnapshotDlg");
572
573 QString typeId = mMachine.GetOSTypeId();
574 dlg.pmIcon->setPixmap (vboxGlobal().vmGuestOSTypeIcon (typeId));
575
576 dlg.leName->setText (tr ("Snapshot %1").arg (mMachine.GetSnapshotCount() + 1));
577
578 if (dlg.exec() == QDialog::Accepted)
579 {
580 /* open a direct session (this call will handle all errors) */
581 CSession session = vboxGlobal().openSession (mMachineId);
582 if (session.isNull())
583 return;
584
585 CConsole console = session.GetConsole();
586 CProgress progress =
587 console.TakeSnapshot (dlg.leName->text().stripWhiteSpace(),
588 dlg.txeDescription->text());
589 if (console.isOk())
590 {
591 /* show the progress dialog */
592 vboxProblem().showModalProgressDialog (progress, mMachine.GetName(),
593 vboxProblem().mainWindowShown());
594
595 if (progress.GetResultCode() != 0)
596 vboxProblem().cannotTakeSnapshot (progress);
597 }
598 else
599 vboxProblem().cannotTakeSnapshot (console);
600
601 session.Close();
602 }
603}
604
605void VBoxSnapshotsWgt::discardCurState()
606{
607 ListViewItem *item = static_cast <ListViewItem *> (listView->currentItem());
608 AssertReturn (item, (void) 0);
609
610 /* open a direct session (this call will handle all errors) */
611 CSession session = vboxGlobal().openSession (mMachineId);
612 if (session.isNull())
613 return;
614
615 CConsole console = session.GetConsole();
616 CProgress progress = console.DiscardCurrentState();
617 if (console.isOk())
618 {
619 /* show the progress dialog */
620 vboxProblem().showModalProgressDialog (progress, mMachine.GetName(),
621 vboxProblem().mainWindowShown());
622
623 if (progress.GetResultCode() != 0)
624 vboxProblem().cannotDiscardCurrentState (progress);
625 }
626 else
627 vboxProblem().cannotDiscardCurrentState (console);
628
629 session.Close();
630}
631
632void VBoxSnapshotsWgt::discardCurSnapAndState()
633{
634 ListViewItem *item = static_cast <ListViewItem *> (listView->currentItem());
635 AssertReturn (item, (void) 0);
636
637 /* open a direct session (this call will handle all errors) */
638 CSession session = vboxGlobal().openSession (mMachineId);
639 if (session.isNull())
640 return;
641
642 CConsole console = session.GetConsole();
643 CProgress progress = console.DiscardCurrentSnapshotAndState();
644 if (console.isOk())
645 {
646 /* show the progress dialog */
647 vboxProblem().showModalProgressDialog (progress, mMachine.GetName(),
648 vboxProblem().mainWindowShown());
649
650 if (progress.GetResultCode() != 0)
651 vboxProblem().cannotDiscardCurrentSnapshotAndState (progress);
652 }
653 else
654 vboxProblem().cannotDiscardCurrentSnapshotAndState (console);
655
656 session.Close();
657}
658
659void VBoxSnapshotsWgt::showSnapshotDetails()
660{
661 ListViewItem *item = static_cast <ListViewItem *> (listView->currentItem());
662 AssertReturn (item, (void) 0);
663
664 CSnapshot snap = item->snapshot();
665 AssertReturn (!snap.isNull(), (void) 0);
666
667 CMachine snapMachine = snap.GetMachine();
668
669 VBoxSnapshotDetailsDlg dlg (this);
670 dlg.getFromSnapshot (snap);
671
672 if (dlg.exec() == QDialog::Accepted)
673 {
674 dlg.putBackToSnapshot();
675 }
676}
677
678void VBoxSnapshotsWgt::machineDataChanged (const VBoxMachineDataChangeEvent &aE)
679{
680 if (aE.id != mMachineId)
681 return; /* not interested in other machines */
682
683 curStateItem()->recache();
684}
685
686void VBoxSnapshotsWgt::machineStateChanged (const VBoxMachineStateChangeEvent &aE)
687{
688 if (aE.id != mMachineId)
689 return; /* not interested in other machines */
690
691 curStateItem()->recache();
692 curStateItem()->updateCurrentState (aE.state);
693}
694
695void VBoxSnapshotsWgt::sessionStateChanged (const VBoxSessionStateChangeEvent &aE)
696{
697 if (aE.id != mMachineId)
698 return; /* not interested in other machines */
699
700 mSessionState = aE.state;
701 listView_currentChanged (listView->currentItem());
702}
703
704void VBoxSnapshotsWgt::snapshotChanged (const VBoxSnapshotEvent &aE)
705{
706 if (aE.machineId != mMachineId)
707 return; /* not interested in other machines */
708
709 switch (aE.what)
710 {
711 case VBoxSnapshotEvent::Taken:
712 case VBoxSnapshotEvent::Discarded:
713 {
714 refreshAll (true);
715 break;
716 }
717 case VBoxSnapshotEvent::Changed:
718 {
719 ListViewItem *lvi = findItem (aE.snapshotId);
720 if (!lvi)
721 refreshAll();
722 else
723 {
724 lvi->recache();
725 lvi->repaint();
726 }
727 break;
728 }
729 }
730}
731
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette