Skip to content

Commit 9bb5f60

Browse files
committed
Support license activation
1 parent c94d9cc commit 9bb5f60

File tree

2 files changed

+215
-3
lines changed

2 files changed

+215
-3
lines changed

examples/official/dcv/README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ Install the Dynamsoft Capture Vision SDK:
5656
pip install dynamsoft-capture-vision-bundle
5757
```
5858

59+
**📝 Note**: The application includes a default trial license. For extended use, get a free 30-day trial license through **Settings****Enter License Key...****Get 30-Day Trial License**.
60+
5961
### Additional Dependencies
6062
```bash
6163
pip install psutil # Optional: for memory monitoring
@@ -136,3 +138,28 @@ python main.py
136138
- **USB Cameras**: Standard UVC-compatible cameras
137139
- **Built-in Cameras**: Laptop/tablet integrated cameras
138140
- **Network Cameras**: IP cameras (with proper drivers)
141+
142+
## 🔧 Configuration
143+
144+
### License Management
145+
The application includes a built-in license management system:
146+
147+
#### Default License
148+
- The application comes with a default trial license
149+
- This license may expire and require renewal
150+
151+
#### Updating License Key
152+
1. Go to **Settings****Enter License Key...**
153+
2. **For new users**: Click **"🌐 Get 30-Day Trial License"** to open the Dynamsoft trial page
154+
3. **For existing users**: Enter your valid Dynamsoft license key
155+
4. Click **"Apply License"** to validate and apply
156+
5. The license is tested before activation
157+
6. Success confirmation will be shown
158+
159+
#### Getting a Trial License
160+
- [**Free 30-Day Trial**](https://www.dynamsoft.com/customer/license/trialLicense/?product=dcv&package=cross-platform): Click the trial license button in the license dialog
161+
- **Automatic Browser**: Opens the Dynamsoft trial page automatically
162+
- **Quick Setup**: Fill out the form and receive license via email
163+
- **Instant Activation**: Copy and paste the license key to activate immediately
164+
165+

examples/official/dcv/main.py

Lines changed: 188 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@
2222
QPushButton, QLabel, QTextEdit, QScrollArea, QFrame, QSplitter, QGroupBox,
2323
QComboBox, QCheckBox, QSpinBox, QProgressBar, QStatusBar, QFileDialog,
2424
QMessageBox, QDialog, QRadioButton, QButtonGroup, QDialogButtonBox,
25-
QTabWidget, QSlider, QLineEdit
25+
QTabWidget, QSlider, QLineEdit, QInputDialog
2626
)
2727
from PySide6.QtCore import (
28-
Qt, QThread, Signal, QTimer, QSize, QRect, QPoint, QMutex, QMutexLocker
28+
Qt, QThread, Signal, QTimer, QSize, QRect, QPoint, QMutex, QMutexLocker, QUrl
2929
)
3030
from PySide6.QtGui import (
3131
QPixmap, QImage, QPainter, QPen, QBrush, QColor, QFont, QAction,
32-
QDragEnterEvent, QDropEvent, QClipboard, QIcon
32+
QDragEnterEvent, QDropEvent, QClipboard, QIcon, QDesktopServices
3333
)
3434
from PySide6.QtMultimedia import QCamera, QMediaDevices
3535
from PySide6.QtMultimediaWidgets import QVideoWidget
@@ -1098,6 +1098,112 @@ def get_selected_format(self):
10981098
"""Get the selected format index."""
10991099
return self.selected_format
11001100

1101+
class LicenseDialog(QDialog):
1102+
"""Custom dialog for license key entry with trial license option."""
1103+
1104+
def __init__(self, current_license_key, parent=None):
1105+
super().__init__(parent)
1106+
self.setWindowTitle("License Management")
1107+
self.setFixedSize(500, 300)
1108+
self.license_key = ""
1109+
self.result_type = None # 'license', 'trial', or None
1110+
1111+
layout = QVBoxLayout()
1112+
1113+
# Title
1114+
title = QLabel("🔑 Dynamsoft License Management")
1115+
title.setFont(QFont("Arial", 14, QFont.Weight.Bold))
1116+
title.setAlignment(Qt.AlignmentFlag.AlignCenter)
1117+
layout.addWidget(title)
1118+
1119+
# Current license info
1120+
current_key_display = current_license_key[:20] + "..." if len(current_license_key) > 20 else current_license_key
1121+
current_info = QLabel(f"Current license: {current_key_display}")
1122+
current_info.setStyleSheet("color: gray; font-size: 10px; padding: 10px;")
1123+
layout.addWidget(current_info)
1124+
1125+
# License key input
1126+
input_group = QGroupBox("Enter New License Key")
1127+
input_layout = QVBoxLayout(input_group)
1128+
1129+
self.license_input = QLineEdit()
1130+
self.license_input.setPlaceholderText("Paste your Dynamsoft license key here...")
1131+
input_layout.addWidget(self.license_input)
1132+
1133+
layout.addWidget(input_group)
1134+
1135+
# Trial license section
1136+
trial_group = QGroupBox("Need a License?")
1137+
trial_layout = QVBoxLayout(trial_group)
1138+
1139+
trial_info = QLabel("Get a 30-day free trial license from Dynamsoft:")
1140+
trial_layout.addWidget(trial_info)
1141+
1142+
self.trial_button = QPushButton("🌐 Get 30-Day Trial License")
1143+
self.trial_button.setStyleSheet("""
1144+
QPushButton {
1145+
background-color: #007acc;
1146+
color: white;
1147+
padding: 10px;
1148+
border: none;
1149+
border-radius: 5px;
1150+
font-weight: bold;
1151+
}
1152+
QPushButton:hover {
1153+
background-color: #005a9e;
1154+
}
1155+
""")
1156+
self.trial_button.clicked.connect(self.open_trial_page)
1157+
trial_layout.addWidget(self.trial_button)
1158+
1159+
layout.addWidget(trial_group)
1160+
1161+
# Buttons
1162+
button_layout = QHBoxLayout()
1163+
1164+
self.apply_button = QPushButton("Apply License")
1165+
self.apply_button.setDefault(True)
1166+
self.apply_button.clicked.connect(self.apply_license)
1167+
1168+
cancel_button = QPushButton("Cancel")
1169+
cancel_button.clicked.connect(self.reject)
1170+
1171+
button_layout.addWidget(cancel_button)
1172+
button_layout.addWidget(self.apply_button)
1173+
1174+
layout.addLayout(button_layout)
1175+
self.setLayout(layout)
1176+
1177+
def open_trial_page(self):
1178+
"""Open the trial license page in the default browser."""
1179+
trial_url = "https://www.dynamsoft.com/customer/license/trialLicense/?product=dcv&package=cross-platform"
1180+
QDesktopServices.openUrl(QUrl(trial_url))
1181+
1182+
# Show info message
1183+
QMessageBox.information(
1184+
self,
1185+
"Trial License",
1186+
"🌐 The trial license page has been opened in your browser.\n\n"
1187+
"Steps to get your trial license:\n"
1188+
"1. Fill out the form on the opened page\n"
1189+
"2. Submit to receive your license key via email\n"
1190+
"3. Copy the license key and paste it here\n"
1191+
"4. Click 'Apply License' to activate"
1192+
)
1193+
1194+
def apply_license(self):
1195+
"""Apply the entered license key."""
1196+
self.license_key = self.license_input.text().strip()
1197+
if self.license_key:
1198+
self.result_type = 'license'
1199+
self.accept()
1200+
else:
1201+
QMessageBox.warning(self, "Missing License", "Please enter a license key.")
1202+
1203+
def get_license_key(self):
1204+
"""Get the entered license key."""
1205+
return self.license_key
1206+
11011207
class BarcodeReaderMainWindow(QMainWindow):
11021208
"""Main window for the PySide6 barcode reader application with camera support."""
11031209

@@ -1600,6 +1706,13 @@ def setup_menu_bar(self):
16001706
exit_action.triggered.connect(self.close)
16011707
file_menu.addAction(exit_action)
16021708

1709+
# Settings menu
1710+
settings_menu = menubar.addMenu("Settings")
1711+
1712+
license_action = QAction("Enter License Key...", self)
1713+
license_action.triggered.connect(self.enter_license_key)
1714+
settings_menu.addAction(license_action)
1715+
16031716
# View menu
16041717
view_menu = menubar.addMenu("View")
16051718

@@ -2923,6 +3036,78 @@ def show_about(self):
29233036
"• Export capabilities (TXT, CSV, JSON)\n"
29243037
"• Professional user interface\n\n"
29253038
"Supports both file-based and live camera scanning.")
3039+
3040+
def enter_license_key(self):
3041+
"""Show dialog to enter a new license key."""
3042+
global LICENSE_KEY, _LICENSE_INITIALIZED
3043+
3044+
# Show custom license dialog
3045+
dialog = LicenseDialog(LICENSE_KEY, self)
3046+
if dialog.exec() == QDialog.DialogCode.Accepted:
3047+
license_key = dialog.get_license_key()
3048+
3049+
if license_key:
3050+
# Show confirmation dialog
3051+
reply = QMessageBox.question(
3052+
self,
3053+
"Update License",
3054+
f"Update license key to:\n{license_key[:20]}...\n\nThe license will be tested and applied.\n\nContinue?",
3055+
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
3056+
QMessageBox.StandardButton.No
3057+
)
3058+
3059+
if reply == QMessageBox.StandardButton.Yes:
3060+
try:
3061+
# Test the new license
3062+
test_error_code, test_error_message = LicenseManager.init_license(license_key)
3063+
3064+
if test_error_code == EnumErrorCode.EC_OK or test_error_code == EnumErrorCode.EC_LICENSE_CACHE_USED:
3065+
# License is valid, update the global LICENSE_KEY
3066+
LICENSE_KEY = license_key
3067+
3068+
# Reinitialize the license system
3069+
_LICENSE_INITIALIZED = False
3070+
3071+
if initialize_license_once():
3072+
# Reinitialize the CVR instance
3073+
if self.cvr_instance:
3074+
self.cvr_instance = None
3075+
3076+
self.cvr_instance = CaptureVisionRouter()
3077+
intermediate_result_manager = self.cvr_instance.get_intermediate_result_manager()
3078+
self.custom_receiver = MyIntermediateResultReceiver(intermediate_result_manager)
3079+
intermediate_result_manager.add_result_receiver(self.custom_receiver)
3080+
3081+
# Update camera widget if it exists
3082+
if hasattr(self, 'camera_widget'):
3083+
self.camera_widget.initialize_dynamsoft_camera(self.cvr_instance)
3084+
3085+
QMessageBox.information(
3086+
self,
3087+
"License Updated",
3088+
"✅ License key updated successfully!\n\nThe new license is now active."
3089+
)
3090+
3091+
self.log_message("✅ License key updated successfully")
3092+
else:
3093+
QMessageBox.critical(
3094+
self,
3095+
"License Error",
3096+
"❌ Failed to reinitialize with new license key.\n\nPlease restart the application."
3097+
)
3098+
else:
3099+
QMessageBox.critical(
3100+
self,
3101+
"Invalid License",
3102+
f"❌ License validation failed:\n\nError Code: {test_error_code}\nError Message: {test_error_message}\n\nPlease check your license key and try again."
3103+
)
3104+
3105+
except Exception as e:
3106+
QMessageBox.critical(
3107+
self,
3108+
"License Error",
3109+
f"❌ Error updating license:\n\n{str(e)}\n\nPlease try again or restart the application."
3110+
)
29263111

29273112
def main():
29283113
"""Main application entry point."""

0 commit comments

Comments
 (0)